msm: mdss: add arm smmu initialization support for mdss

MSM8937 uses arm smmu instead of qsmmu. Add arm smmu
initialization support in MDSS driver.

Change-Id: I0ec701c8bb7ea19a3ce919fd37b014f0bab27367
Signed-off-by: Shivaraj Shetty <shivaraj@codeaurora.org>
Signed-off-by: Kalyan Thota <kalyant@codeaurora.org>
Signed-off-by: Krishna Chaitanya Devarakonda <kdevarak@codeaurora.org>
This commit is contained in:
Shivaraj Shetty 2015-10-21 12:42:45 +05:30 committed by David Keitel
parent d4e9e455d6
commit c529db2342
4 changed files with 128 additions and 29 deletions

View file

@ -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.

View file

@ -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;

View file

@ -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;

View file

@ -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,25 +41,6 @@ static inline bool is_mdss_smmu_compatible_device(const char *str)
strlen(MDSS_SMMU_COMPATIBLE))) ? true : false;
}
static inline struct mdss_smmu_client *mdss_smmu_get_cb(u32 domain)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return (domain >= MDSS_IOMMU_MAX_DOMAIN) ? NULL :
&mdata->mdss_smmu[domain];
}
static inline struct ion_client *mdss_get_ionclient(void)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return mdata ? mdata->iclient : NULL;
}
static inline int is_mdss_iommu_attached(void)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return mdata ? mdata->iommu_attached : false;
}
/*
* mdss_smmu_is_valid_domain_type()
*
@ -74,6 +57,29 @@ static inline bool mdss_smmu_is_valid_domain_type(struct mdss_data_type *mdata,
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];
}
static inline struct ion_client *mdss_get_ionclient(void)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return mdata ? mdata->iclient : NULL;
}
static inline int is_mdss_iommu_attached(void)
{
struct mdss_data_type *mdata = mdss_mdp_get_mdata();
return mdata ? mdata->iommu_attached : false;
}
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;