Loading drivers/iommu/msm_iommu.c +63 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/export.h> #include <linux/iommu.h> #include <linux/qcom_iommu.h> #include <asm/sections.h> static DEFINE_MUTEX(iommu_list_lock); static LIST_HEAD(iommu_list); Loading Loading @@ -68,6 +69,68 @@ int msm_iommu_bus_register(void) } #endif void msm_access_control(void) { int ret; struct device *cb_dev; struct iommu_domain *domain; unsigned long start, kernel_start, kernel_end, end; start = 0; kernel_start = ALIGN(__pa(_stext), SZ_2M); kernel_end = ALIGN(__pa(_etext), SZ_2M); end = 0xFFFFFFFF; /* * If a target doesn't have the access control feature * it won't have CB and that's okay */ cb_dev = msm_iommu_get_ctx("access_control"); domain = iommu_domain_alloc(msm_iommu_non_sec_bus_type); if (!domain) { pr_err("Couldn't get domain for access control\n"); goto err; } /* * Map the region from start to kernel_start */ if (start < kernel_start) { ret = iommu_map(domain, start, start, kernel_start - start, IOMMU_READ | IOMMU_WRITE | IOMMU_DEVICE); if (ret) { pr_err("Mapping failed for region lower than kernel\n"); goto free_dom; } } /* * Map the region from kernel_end to end of DDR */ ret = iommu_map(domain, kernel_end, kernel_end, end - kernel_end + 1, IOMMU_READ | IOMMU_WRITE); if (ret) { pr_err("Mapping failed for region above kernel\n"); goto free_dom; } ret = iommu_attach_device(domain, cb_dev); if (ret) { pr_err("Attach of access_control CB failed\n"); goto free_dom; } return; free_dom: iommu_domain_free(domain); err: BUG(); } /** * Pass the context bank device here. Based on the context bank * device, the bus is chosen and hence the respective IOMMU ops. Loading drivers/iommu/msm_iommu_dev-v1.c +3 −0 Original line number Diff line number Diff line Loading @@ -666,6 +666,9 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev) dev_info(&pdev->dev, "context %s using bank %d\n", ctx_drvdata->name, ctx_drvdata->num); if (strcmp(ctx_drvdata->name, "access_control") == 0) msm_access_control(); } return ret; Loading include/linux/qcom_iommu.h +5 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock); struct device *msm_iommu_get_ctx(const char *ctx_name); struct bus_type *msm_iommu_get_bus(struct device *dev); int msm_iommu_bus_register(void); void msm_access_control(void); #else static inline struct device *msm_iommu_get_ctx(const char *ctx_name) { Loading @@ -348,6 +349,10 @@ static inline struct bus_type *msm_iommu_get_bus(struct device *dev) { return &platform_bus_type; } static inline void msm_access_control(void) { } #endif /* Loading Loading
drivers/iommu/msm_iommu.c +63 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ #include <linux/export.h> #include <linux/iommu.h> #include <linux/qcom_iommu.h> #include <asm/sections.h> static DEFINE_MUTEX(iommu_list_lock); static LIST_HEAD(iommu_list); Loading Loading @@ -68,6 +69,68 @@ int msm_iommu_bus_register(void) } #endif void msm_access_control(void) { int ret; struct device *cb_dev; struct iommu_domain *domain; unsigned long start, kernel_start, kernel_end, end; start = 0; kernel_start = ALIGN(__pa(_stext), SZ_2M); kernel_end = ALIGN(__pa(_etext), SZ_2M); end = 0xFFFFFFFF; /* * If a target doesn't have the access control feature * it won't have CB and that's okay */ cb_dev = msm_iommu_get_ctx("access_control"); domain = iommu_domain_alloc(msm_iommu_non_sec_bus_type); if (!domain) { pr_err("Couldn't get domain for access control\n"); goto err; } /* * Map the region from start to kernel_start */ if (start < kernel_start) { ret = iommu_map(domain, start, start, kernel_start - start, IOMMU_READ | IOMMU_WRITE | IOMMU_DEVICE); if (ret) { pr_err("Mapping failed for region lower than kernel\n"); goto free_dom; } } /* * Map the region from kernel_end to end of DDR */ ret = iommu_map(domain, kernel_end, kernel_end, end - kernel_end + 1, IOMMU_READ | IOMMU_WRITE); if (ret) { pr_err("Mapping failed for region above kernel\n"); goto free_dom; } ret = iommu_attach_device(domain, cb_dev); if (ret) { pr_err("Attach of access_control CB failed\n"); goto free_dom; } return; free_dom: iommu_domain_free(domain); err: BUG(); } /** * Pass the context bank device here. Based on the context bank * device, the bus is chosen and hence the respective IOMMU ops. Loading
drivers/iommu/msm_iommu_dev-v1.c +3 −0 Original line number Diff line number Diff line Loading @@ -666,6 +666,9 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev) dev_info(&pdev->dev, "context %s using bank %d\n", ctx_drvdata->name, ctx_drvdata->num); if (strcmp(ctx_drvdata->name, "access_control") == 0) msm_access_control(); } return ret; Loading
include/linux/qcom_iommu.h +5 −0 Original line number Diff line number Diff line Loading @@ -338,6 +338,7 @@ void msm_iommu_remote_p0_spin_unlock(unsigned int need_lock); struct device *msm_iommu_get_ctx(const char *ctx_name); struct bus_type *msm_iommu_get_bus(struct device *dev); int msm_iommu_bus_register(void); void msm_access_control(void); #else static inline struct device *msm_iommu_get_ctx(const char *ctx_name) { Loading @@ -348,6 +349,10 @@ static inline struct bus_type *msm_iommu_get_bus(struct device *dev) { return &platform_bus_type; } static inline void msm_access_control(void) { } #endif /* Loading