Loading Documentation/devicetree/bindings/fb/mdss-mdp.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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. Loading drivers/video/msm/mdss/mdss.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading drivers/video/msm/mdss/mdss_smmu.c +85 −6 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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 Loading Loading @@ -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 || Loading @@ -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, Loading Loading @@ -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; Loading drivers/video/msm/mdss/mdss_smmu.h +29 −19 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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]; } Loading @@ -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(); Loading Loading @@ -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; Loading Loading
Documentation/devicetree/bindings/fb/mdss-mdp.txt +4 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
drivers/video/msm/mdss/mdss.h +7 −1 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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; Loading
drivers/video/msm/mdss/mdss_smmu.c +85 −6 Original line number Diff line number Diff line Loading @@ -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" Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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) { Loading Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } } Loading Loading @@ -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 Loading Loading @@ -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 || Loading @@ -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, Loading Loading @@ -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; Loading
drivers/video/msm/mdss/mdss_smmu.h +29 −19 Original line number Diff line number Diff line Loading @@ -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); Loading @@ -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]; } Loading @@ -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(); Loading Loading @@ -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; Loading