From: Janghyuck Kim Date: Tue, 17 Oct 2017 10:21:41 +0000 (+0900) Subject: [COMMON] iommu/exynos: add sysmmu control interface explicitly X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=a78600fc902b044b755d1cc019ab691e778b325e;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] iommu/exynos: add sysmmu control interface explicitly Change-Id: I0d93fcbbdec3a272bb965306a7ad91a37ade3960 Signed-off-by: Janghyuck Kim --- diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index f76b1d1aefe0..13acf336240f 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -466,6 +466,9 @@ static int __init sysmmu_parse_dt(struct device *sysmmu, if (of_property_read_bool(sysmmu->of_node, "sysmmu,hold-rpm-on-boot")) drvdata->hold_rpm_on_boot = true; + if (of_property_read_bool(sysmmu->of_node, "sysmmu,no-rpm-control")) + drvdata->no_rpm_control = true; + if (IS_TLB_WAY_TYPE(drvdata)) { ret = sysmmu_parse_tlb_way_dt(sysmmu, drvdata); if (ret) @@ -685,6 +688,28 @@ static int sysmmu_enable_from_master(struct device *master, return ret; } +void exynos_sysmmu_control(struct device *master, bool enable) +{ + unsigned long flags; + struct exynos_iommu_owner *owner = master->archdata.iommu; + struct sysmmu_list_data *list; + struct sysmmu_drvdata *drvdata; + + BUG_ON(!has_sysmmu(master)); + + spin_lock_irqsave(&owner->lock, flags); + list_for_each_entry(list, &owner->sysmmu_list, node) { + drvdata = dev_get_drvdata(list->sysmmu); + if (!drvdata->no_rpm_control) + continue; + if (enable) + __sysmmu_enable_nocount(drvdata); + else + __sysmmu_disable_nocount(drvdata); + } + spin_unlock_irqrestore(&owner->lock, flags); +} + #ifdef CONFIG_PM_SLEEP static int exynos_sysmmu_suspend(struct device *dev) { @@ -708,7 +733,7 @@ static int exynos_sysmmu_resume(struct device *dev) struct sysmmu_drvdata *drvdata = dev_get_drvdata(dev); spin_lock_irqsave(&drvdata->lock, flags); - if (drvdata->is_suspended) { + if (drvdata->is_suspended && !drvdata->no_rpm_control) { __sysmmu_enable_nocount(drvdata); drvdata->is_suspended = false; } diff --git a/drivers/iommu/exynos-iommu.h b/drivers/iommu/exynos-iommu.h index e0c3e2b510a7..998aa3411d31 100644 --- a/drivers/iommu/exynos-iommu.h +++ b/drivers/iommu/exynos-iommu.h @@ -348,6 +348,7 @@ struct sysmmu_drvdata { bool is_suspended; bool hold_rpm_on_boot; struct exynos_iommu_event_log log; + bool no_rpm_control; }; struct exynos_vm_region { @@ -387,18 +388,18 @@ int exynos_iommu_add_fault_handler(struct device *dev, static inline bool get_sysmmu_runtime_active(struct sysmmu_drvdata *data) { - return ++data->runtime_active == 1; + return ++data->runtime_active == 1 && !data->no_rpm_control; } static inline bool put_sysmmu_runtime_active(struct sysmmu_drvdata *data) { BUG_ON(data->runtime_active < 1); - return --data->runtime_active == 0; + return --data->runtime_active == 0 && !data->no_rpm_control; } static inline bool is_sysmmu_runtime_active(struct sysmmu_drvdata *data) { - return data->runtime_active > 0; + return data->runtime_active > 0 && !data->no_rpm_control; } static inline bool set_sysmmu_active(struct sysmmu_drvdata *data) diff --git a/include/linux/exynos_iovmm.h b/include/linux/exynos_iovmm.h index 6c69c939c8d7..185e5e797163 100644 --- a/include/linux/exynos_iovmm.h +++ b/include/linux/exynos_iovmm.h @@ -268,6 +268,7 @@ int sysmmu_set_prefetch_buffer_property(struct device *dev, unsigned int ipoption[], unsigned int opoption[]); void exynos_sysmmu_show_status(struct device *dev); void exynos_sysmmu_dump_pgtable(struct device *dev); +void exynos_sysmmu_control(struct device *master, bool enable); /* * exynos_sysmmu_set/clear/show_ppc_event() -