Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd7bad69 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: mdss: add arm smmu initialization support for mdss"

parents faad5b77 2db2b7a6
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -585,6 +585,10 @@ Subnode properties:
						secure mdp domain.
			"qcom,smmu_rot_sec"	- smmu context bank device for
						secure rotation domain.
			"qcom,smmu_arm_mdp_unsec"	- arm smmu context bank device for
						unsecure mdp domain.
			"qcom,smmu_arm_mdp_sec"	- arm smmu context bank device for
						secure mdp domain.
- gdsc-mmagic-mdss-supply: Phandle for mmagic mdss supply regulator device node.
- clocks:		List of Phandles for clock device nodes
			needed by the device.
+7 −1
Original line number Diff line number Diff line
@@ -176,6 +176,12 @@ enum mdss_qos_settings {
	MDSS_QOS_MAX,
};

enum mdss_smmu_version {
	MDSS_SMMU_V1,
	MDSS_SMMU_V2,
	MDSS_SMMU_ARM
};

struct reg_bus_client {
	char name[MAX_CLIENT_NAME_LEN];
	short usecase_ndx;
@@ -190,6 +196,7 @@ struct mdss_smmu_client {
	struct reg_bus_client *reg_bus_clt;
	bool domain_attached;
	bool handoff_pending;
	enum mdss_smmu_version smmu_type;
};

struct mdss_data_type;
@@ -402,7 +409,6 @@ struct mdss_data_type {

	struct ion_client *iclient;
	int iommu_attached;
	struct mdss_iommu_map_type *iommu_map;

	struct debug_bus *dbg_bus;
	u32 dbg_bus_size;
+85 −6
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/of_platform.h>
#include <linux/msm_dma_iommu_mapping.h>

#include <linux/qcom_iommu.h>
#include <asm/dma-iommu.h>
#include "soc/qcom/secure_buffer.h"

@@ -46,6 +47,21 @@ void mdss_iommu_unlock(void)
	mutex_unlock(&mdp_iommu_lock);
}

static struct mdss_iommu_map_type mdss_iommu_map[MDSS_IOMMU_MAX_DOMAIN] = {
	[MDSS_IOMMU_DOMAIN_UNSECURE] = {
		.client_name = "mdp_ns",
		.ctx_name = "mdp_0",
		.start = SZ_128K,
		.size = SZ_1G - SZ_128K,
	},
	[MDSS_IOMMU_DOMAIN_SECURE] = {
		.client_name = "mdp_secure",
		.ctx_name = "mdp_1",
		.start = SZ_1G,
		.size = SZ_2G,
	},
};

static int mdss_smmu_util_parse_dt_clock(struct platform_device *pdev,
		struct dss_module_power *mp)
{
@@ -123,6 +139,9 @@ static int mdss_smmu_enable_power(struct mdss_smmu_client *mdss_smmu,
	if (!mdss_smmu)
		return -EINVAL;

	if (mdss_smmu->smmu_type == MDSS_SMMU_ARM)
		return 0;

	mp = &mdss_smmu->mp;

	if (enable) {
@@ -170,7 +189,7 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
			continue;

		mdss_smmu = mdss_smmu_get_cb(i);
		if (mdss_smmu->dev) {
		if (mdss_smmu && mdss_smmu->dev) {
			if (!mdss_smmu->handoff_pending) {
				rc = mdss_smmu_enable_power(mdss_smmu, true);
				if (rc) {
@@ -204,7 +223,7 @@ static int mdss_smmu_attach_v2(struct mdss_data_type *mdata)
err:
	for (i--; i >= 0; i--) {
		mdss_smmu = mdss_smmu_get_cb(i);
		if (mdss_smmu->dev) {
		if (mdss_smmu && mdss_smmu->dev) {
			arm_iommu_detach_device(mdss_smmu->dev);
			mdss_smmu_enable_power(mdss_smmu, false);
			mdss_smmu->domain_attached = false;
@@ -229,7 +248,7 @@ static int mdss_smmu_detach_v2(struct mdss_data_type *mdata)
			continue;

		mdss_smmu = mdss_smmu_get_cb(i);
		if (mdss_smmu->dev && !mdss_smmu->handoff_pending)
		if (mdss_smmu && mdss_smmu->dev && !mdss_smmu->handoff_pending)
			mdss_smmu_enable_power(mdss_smmu, false);
	}
	return 0;
@@ -423,14 +442,14 @@ static void mdss_smmu_dsi_unmap_buffer_v2(dma_addr_t dma_addr, int domain,



static void mdss_smmu_deinit_v2(struct mdss_data_type *mata)
static void mdss_smmu_deinit_v2(struct mdss_data_type *mdata)
{
	int i;
	struct mdss_smmu_client *mdss_smmu;

	for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
		mdss_smmu = mdss_smmu_get_cb(i);
		if (mdss_smmu->dev)
		if (mdss_smmu && mdss_smmu->dev)
			arm_iommu_release_mapping(mdss_smmu->mmu_mapping);
	}
}
@@ -496,10 +515,58 @@ static const struct of_device_id mdss_smmu_dt_match[] = {
	{ .compatible = "qcom,smmu_rot_unsec", .data = &mdss_rot_unsec},
	{ .compatible = "qcom,smmu_mdp_sec", .data = &mdss_mdp_sec},
	{ .compatible = "qcom,smmu_rot_sec", .data = &mdss_rot_sec},
	{ .compatible = "qcom,smmu_arm_mdp_sec", .data = &mdss_mdp_sec},
	{ .compatible = "qcom,smmu_arm_mdp_unsec", .data = &mdss_mdp_unsec},
	{}
};
MODULE_DEVICE_TABLE(of, mdss_smmu_dt_match);


/*
 * mdss_smmu_arm_probe()
 * @domain: iommu domain
 *
 * Each arm smmu context acts as a separate device and the context banks are
 * configured with a VA range.
 */
static int mdss_smmu_arm_probe(u32 domain)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
	struct mdss_smmu_client *mdss_smmu;
	struct device *dev;
	struct mdss_iommu_map_type *iomap;
	int rc = 0;

	if ((domain == MDSS_IOMMU_DOMAIN_SECURE) ||
			(domain == MDSS_IOMMU_DOMAIN_UNSECURE)) {
		iomap = &mdss_iommu_map[domain];
		dev = msm_iommu_get_ctx(iomap->ctx_name);
		if (!dev) {
			pr_err("Invalid SMMU ctx for domain:%d\n", domain);
			return -EINVAL;
		}

		mdss_smmu = &mdata->mdss_smmu[domain];
		mdss_smmu->mmu_mapping = arm_iommu_create_mapping(
			msm_iommu_get_bus(dev), iomap->start, iomap->size);
		if (IS_ERR(mdss_smmu->mmu_mapping)) {
			pr_err("iommu create mapping failed for domain[%d]\n",
									domain);
			rc = PTR_ERR(mdss_smmu->mmu_mapping);
			return rc;
		}

		if (mdata->handoff_pending)
			mdss_smmu->handoff_pending = true;
		mdss_smmu->dev = dev;
		mdss_smmu->smmu_type = MDSS_SMMU_ARM;
	} else {
		pr_err("Invalid MDSS domain:%d\n", domain);
		return -EINVAL;
	}
	return rc;
}

/*
 * mdss_smmu_probe()
 * @pdev: platform device
@@ -539,6 +606,16 @@ int mdss_smmu_probe(struct platform_device *pdev)
		return -EINVAL;
	}

	if (of_device_is_compatible(dev->of_node, "qcom,smmu_arm_mdp_sec") ||
			of_device_is_compatible(dev->of_node,
					"qcom,smmu_arm_mdp_unsec")) {
		pr_debug("initializing mdss for arm smmu\n");
		rc  = mdss_smmu_arm_probe(domain);
		if (rc)
			pr_err("arm smmu probe failed\n");
		return rc;
	}

	mdss_smmu = &mdata->mdss_smmu[domain];

	if (domain == MDSS_IOMMU_DOMAIN_UNSECURE ||
@@ -554,6 +631,7 @@ int mdss_smmu_probe(struct platform_device *pdev)
		return -EINVAL;
	}

	mdss_smmu->smmu_type = MDSS_SMMU_V2;
	mp = &mdss_smmu->mp;

	mp->vreg_config = devm_kzalloc(&pdev->dev,
@@ -654,7 +732,8 @@ int mdss_smmu_remove(struct platform_device *pdev)

	for (i = 0; i < MDSS_IOMMU_MAX_DOMAIN; i++) {
		mdss_smmu = mdss_smmu_get_cb(i);
		if (mdss_smmu->dev && mdss_smmu->dev == &pdev->dev)
		if (mdss_smmu && mdss_smmu->dev &&
			(mdss_smmu->dev == &pdev->dev))
			arm_iommu_release_mapping(mdss_smmu->mmu_mapping);
	}
	return 0;
+29 −19
Original line number Diff line number Diff line
@@ -24,9 +24,11 @@

#define MDSS_SMMU_COMPATIBLE "qcom,smmu"

enum mdss_smmu_version {
	MDSS_SMMU_V1,
	MDSS_SMMU_V2
struct mdss_iommu_map_type {
	char *client_name;
	char *ctx_name;
	unsigned long start;
	unsigned long size;
};

void mdss_smmu_register(struct device *dev);
@@ -39,9 +41,29 @@ static inline bool is_mdss_smmu_compatible_device(const char *str)
			strlen(MDSS_SMMU_COMPATIBLE))) ? true : false;
}

/*
 * mdss_smmu_is_valid_domain_type()
 *
 * Used to check if rotator smmu domain is defined or not by checking if
 * vbif base is defined. As those are associated.
 */
static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata,
		int domain_type)
{
	if ((domain_type == MDSS_IOMMU_DOMAIN_ROT_UNSECURE ||
			domain_type == MDSS_IOMMU_DOMAIN_ROT_SECURE) &&
			!mdss_mdp_is_nrt_vbif_base_defined(mdata))
		return false;
	return true;
}

static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();

	if (!mdss_smmu_is_valid_domain_type(mdata, domain))
		return NULL;

	return (domain >= MDSS_IOMMU_MAX_DOMAIN) ? NULL :
			&mdata->mdss_smmu[domain];
}
@@ -58,22 +80,6 @@ static inline int is_mdss_iommu_attached(void)
	return mdata ? mdata->iommu_attached : false;
}

/*
 * mdss_smmu_is_valid_domain_type()
 *
 * Used to check if rotator smmu domain is defined or not by checking if
 * vbif base is defined. As those are associated.
 */
static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata,
		int domain_type)
{
	if ((domain_type == MDSS_IOMMU_DOMAIN_ROT_UNSECURE ||
			domain_type == MDSS_IOMMU_DOMAIN_ROT_SECURE) &&
			!mdss_mdp_is_nrt_vbif_base_defined(mdata))
		return false;
	return true;
}

static inline int mdss_smmu_get_domain_type(u32 flags, bool rotator)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();
@@ -134,6 +140,10 @@ static inline int mdss_smmu_detach(struct mdss_data_type *mdata)
static inline int mdss_smmu_get_domain_id(u32 type)
{
	struct mdss_data_type *mdata = mdss_mdp_get_mdata();

	if (!mdss_smmu_is_valid_domain_type(mdata, type))
		return -ENODEV;

	if (!mdata || !mdata->smmu_ops.smmu_get_domain_id
			|| type >= MDSS_IOMMU_MAX_DOMAIN)
		return -ENODEV;