]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - rpmsg/rpmsg.git/commitdiff
Merge branch 'iommu-linux-4.19.y' of git://git.ti.com/rpmsg/iommu into rproc-linux...
authorSuman Anna <s-anna@ti.com>
Mon, 4 Mar 2019 16:09:10 +0000 (10:09 -0600)
committerSuman Anna <s-anna@ti.com>
Mon, 4 Mar 2019 16:09:10 +0000 (10:09 -0600)
Merge in the updated iommu feature branch into remoteproc tree to
pull in the necessary support to fix the DRA7 IPU1 boot issue and
couple of DRA7 DSP idle issues with HW_AUTO setting. The DSP idle
status is achieved across all the DSPs and boards only with the
fix for errata i879.

* 'iommu-linux-4.19.y' of git://git.ti.com/rpmsg/iommu:
  ARM: OMAP2+: Add workaround for DRA7 DSP MStandby errata i879
  ARM: OMAP2+: Extend DRA7 IPU1 MMU pdata quirks to DSP MDMA MMUs
  ARM: OMAP2+: Use separate IOMMU pdata to fix DRA7 IPU1 boot
  iommu/omap: Fix boot issue on remoteprocs with AMMU/Unicache

Signed-off-by: Suman Anna <s-anna@ti.com>
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/omap-iommu.c [new file with mode: 0644]
arch/arm/mach-omap2/pdata-quirks.c
drivers/iommu/omap-iommu.c
drivers/iommu/omap-iommu.h
include/linux/platform_data/iommu-omap.h

index eeb1e8377d824c4c4c0a0ab5456023454354c037..359c9b11d44b3d06e156f26429508e9079fc370f 100644 (file)
@@ -244,6 +244,7 @@ include/generated/ti-pm-asm-offsets.h: arch/arm/mach-omap2/pm-asm-offsets.s FORC
 
 $(obj)/sleep33xx.o $(obj)/sleep43xx.o: include/generated/ti-pm-asm-offsets.h
 
+obj-$(CONFIG_OMAP_IOMMU)               += omap-iommu.o
 ifneq ($(CONFIG_OMAP_REMOTEPROC),)
 obj-y                                  += remoteproc.o
 endif
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
new file mode 100644 (file)
index 0000000..65e7d6e
--- /dev/null
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * OMAP IOMMU quirks for various TI SoCs
+ *
+ * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/
+ *      Suman Anna <s-anna@ti.com>
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+
+#include "omap_hwmod.h"
+#include "omap_device.h"
+#include "clockdomain.h"
+#include "powerdomain.h"
+
+static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev,
+                                            bool enable)
+{
+       static struct clockdomain *emu_clkdm;
+       static DEFINE_SPINLOCK(emu_lock);
+       static atomic_t count;
+       struct device_node *np = pdev->dev.of_node;
+
+       if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
+               return;
+
+       if (!emu_clkdm) {
+               emu_clkdm = clkdm_lookup("emu_clkdm");
+               if (WARN_ON_ONCE(!emu_clkdm))
+                       return;
+       }
+
+       spin_lock(&emu_lock);
+
+       if (enable && (atomic_inc_return(&count) == 1))
+               clkdm_deny_idle(emu_clkdm);
+       else if (!enable && (atomic_dec_return(&count) == 0))
+               clkdm_allow_idle(emu_clkdm);
+
+       spin_unlock(&emu_lock);
+}
+
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+                                   u8 *pwrst)
+{
+       struct powerdomain *pwrdm;
+       struct omap_device *od;
+       u8 next_pwrst;
+       int ret = 0;
+
+       od = to_omap_device(pdev);
+       if (!od)
+               return -ENODEV;
+
+       if (od->hwmods_cnt != 1)
+               return -EINVAL;
+
+       pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]);
+       if (!pwrdm)
+               return -EINVAL;
+
+       if (request) {
+               *pwrst = pwrdm_read_next_pwrst(pwrdm);
+               omap_iommu_dra7_emu_swsup_config(pdev, true);
+       }
+
+       if (*pwrst > PWRDM_POWER_RET)
+               goto out;
+
+       next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
+
+       ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst);
+
+out:
+       if (!request)
+               omap_iommu_dra7_emu_swsup_config(pdev, false);
+
+       return ret;
+}
index 268113a63c8544897dfb9fcd8316ff53332d83c9..2271add0a6619e50648598e5a4e8843921b680ed 100644 (file)
@@ -49,6 +49,17 @@ struct pdata_init {
 static struct of_dev_auxdata omap_auxdata_lookup[];
 static struct twl4030_gpio_platform_data twl_gpio_auxdata;
 
+#if IS_ENABLED(CONFIG_OMAP_IOMMU)
+int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
+                                   u8 *pwrst);
+#else
+static inline int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev,
+                                                 bool request, u8 *pwrst)
+{
+       return 0;
+}
+#endif
+
 #ifdef CONFIG_MACH_NOKIA_N8X0
 static void __init omap2420_n8x0_legacy_init(void)
 {
@@ -451,6 +462,13 @@ static void __init omap5_uevm_legacy_init(void)
 #endif
 
 #ifdef CONFIG_SOC_DRA7XX
+static struct iommu_platform_data dra7_ipu1_dsp_iommu_pdata = {
+       .reset_name = "mmu_cache",
+       .assert_reset = omap_device_assert_hardreset,
+       .deassert_reset = omap_device_deassert_hardreset,
+       .set_pwrdm_constraint = omap_iommu_set_pwrdm_constraint,
+};
+
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc1;
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc2;
 static struct omap_hsmmc_platform_data dra7_hsmmc_data_mmc3;
@@ -623,13 +641,13 @@ static struct of_dev_auxdata omap_auxdata_lookup[] = {
        OF_DEV_AUXDATA("ti,dra7-hsmmc", 0x480ad000, "480ad000.mmc",
                       &dra7_hsmmc_data_mmc3),
        OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x40d01000, "40d01000.mmu",
-                      &omap4_iommu_pdata),
+                      &dra7_ipu1_dsp_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-dsp-iommu", 0x41501000, "41501000.mmu",
-                      &omap4_iommu_pdata),
+                      &dra7_ipu1_dsp_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x55082000, "55082000.mmu",
                       &omap4_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-iommu", 0x58882000, "58882000.mmu",
-                      &omap4_iommu_pdata),
+                      &dra7_ipu1_dsp_iommu_pdata),
        OF_DEV_AUXDATA("ti,dra7-ipu", 0x55020000, "55020000.ipu",
                       &omap4_ipu_dsp_pdata),
        OF_DEV_AUXDATA("ti,dra7-ipu", 0x58820000, "58820000.ipu",
index a3d0184e24f681dce1c941f6c38f880bacf84fc6..f623f76378a0d2ceab6ef84318211ce878bd7d1f 100644 (file)
@@ -194,6 +194,14 @@ static int iommu_enable(struct omap_iommu *obj)
        struct platform_device *pdev = to_platform_device(obj->dev);
        struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
 
+       if (pdata && pdata->set_pwrdm_constraint) {
+               err = pdata->set_pwrdm_constraint(pdev, true, &obj->pwrst);
+               if (err) {
+                       dev_warn(obj->dev, "pwrdm_constraint failed to be set, status = %d\n",
+                                err);
+               }
+       }
+
        if (pdata && pdata->deassert_reset) {
                err = pdata->deassert_reset(pdev, pdata->reset_name);
                if (err) {
@@ -213,6 +221,7 @@ static void iommu_disable(struct omap_iommu *obj)
 {
        struct platform_device *pdev = to_platform_device(obj->dev);
        struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       int ret;
 
        omap2_iommu_disable(obj);
 
@@ -220,6 +229,14 @@ static void iommu_disable(struct omap_iommu *obj)
 
        if (pdata && pdata->assert_reset)
                pdata->assert_reset(pdev, pdata->reset_name);
+
+       if (pdata && pdata->set_pwrdm_constraint) {
+               ret = pdata->set_pwrdm_constraint(pdev, false, &obj->pwrst);
+               if (ret) {
+                       dev_warn(obj->dev, "pwrdm_constraint failed to be reset, status = %d\n",
+                                ret);
+               }
+       }
 }
 
 /*
index 1703159ef5af390454323b5af427a7ca49f0137c..7766d5a4f3f1f888e9688882079fc1d75ed97906 100644 (file)
@@ -81,6 +81,8 @@ struct omap_iommu {
 
        struct iommu_device iommu;
        struct iommu_group *group;
+
+       u8 pwrst;
 };
 
 /**
index e8b12dbf617024f488f078f746e87ce32eec839a..1a0aa46a5ad6459e0ff31e8ab406fd7aae32f6f2 100644 (file)
@@ -16,4 +16,6 @@ struct iommu_platform_data {
        const char *reset_name;
        int (*assert_reset)(struct platform_device *pdev, const char *name);
        int (*deassert_reset)(struct platform_device *pdev, const char *name);
+       int (*set_pwrdm_constraint)(struct platform_device *pdev, bool request,
+                                   u8 *pwrst);
 };