[COMMON] iommu/exynos: add sysmmu control interface explicitly
authorJanghyuck Kim <janghyuck.kim@samsung.com>
Tue, 17 Oct 2017 10:21:41 +0000 (19:21 +0900)
committerYoungmin Nam <youngmin.nam@samsung.com>
Tue, 3 Jul 2018 07:00:47 +0000 (16:00 +0900)
Change-Id: I0d93fcbbdec3a272bb965306a7ad91a37ade3960
Signed-off-by: Janghyuck Kim <janghyuck.kim@samsung.com>
drivers/iommu/exynos-iommu.c
drivers/iommu/exynos-iommu.h
include/linux/exynos_iovmm.h

index f76b1d1aefe021dd6f7f734586ee0d32a729009e..13acf336240f23f0da222e825b65cd89f65d359f 100644 (file)
@@ -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;
        }
index e0c3e2b510a769b03f216c7a317b261ae445a77f..998aa3411d31b9380493a23b4154d93b9c94e737 100644 (file)
@@ -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)
index 6c69c939c8d7d75cfbfedf60ab828427b87d884e..185e5e7971635e1168919ddab501810217604aa4 100644 (file)
@@ -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() -