浏览代码

Merge branch 'iommu-linux-4.19.y' of git://git.ti.com/rpmsg/iommu into rproc-linux-4.19.y

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>
Suman Anna 6 年之前
父节点
当前提交
06fe96b926

+ 1 - 0
arch/arm/mach-omap2/Makefile

@@ -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

+ 80 - 0
arch/arm/mach-omap2/omap-iommu.c

@@ -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;
+}

+ 21 - 3
arch/arm/mach-omap2/pdata-quirks.c

@@ -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",

+ 17 - 0
drivers/iommu/omap-iommu.c

@@ -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);
+		}
+	}
 }
 
 /*

+ 2 - 0
drivers/iommu/omap-iommu.h

@@ -81,6 +81,8 @@ struct omap_iommu {
 
 	struct iommu_device iommu;
 	struct iommu_group *group;
+
+	u8 pwrst;
 };
 
 /**

+ 2 - 0
include/linux/platform_data/iommu-omap.h

@@ -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);
 };