xref: /linux/arch/arm/mach-omap2/omap-iommu.c (revision 2f14101a1d760db72393910d481fbf7768c44530)
13846a3b9SSuman Anna // SPDX-License-Identifier: GPL-2.0-only
23846a3b9SSuman Anna /*
33846a3b9SSuman Anna  * OMAP IOMMU quirks for various TI SoCs
43846a3b9SSuman Anna  *
53846a3b9SSuman Anna  * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/
63846a3b9SSuman Anna  *      Suman Anna <s-anna@ti.com>
73846a3b9SSuman Anna  */
83846a3b9SSuman Anna 
93846a3b9SSuman Anna #include <linux/platform_device.h>
103846a3b9SSuman Anna #include <linux/err.h>
113846a3b9SSuman Anna 
123846a3b9SSuman Anna #include "omap_hwmod.h"
133846a3b9SSuman Anna #include "omap_device.h"
14*2f14101aSSuman Anna #include "clockdomain.h"
153846a3b9SSuman Anna #include "powerdomain.h"
163846a3b9SSuman Anna 
17*2f14101aSSuman Anna static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev,
18*2f14101aSSuman Anna 					     bool enable)
19*2f14101aSSuman Anna {
20*2f14101aSSuman Anna 	static struct clockdomain *emu_clkdm;
21*2f14101aSSuman Anna 	static DEFINE_SPINLOCK(emu_lock);
22*2f14101aSSuman Anna 	static atomic_t count;
23*2f14101aSSuman Anna 	struct device_node *np = pdev->dev.of_node;
24*2f14101aSSuman Anna 
25*2f14101aSSuman Anna 	if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu"))
26*2f14101aSSuman Anna 		return;
27*2f14101aSSuman Anna 
28*2f14101aSSuman Anna 	if (!emu_clkdm) {
29*2f14101aSSuman Anna 		emu_clkdm = clkdm_lookup("emu_clkdm");
30*2f14101aSSuman Anna 		if (WARN_ON_ONCE(!emu_clkdm))
31*2f14101aSSuman Anna 			return;
32*2f14101aSSuman Anna 	}
33*2f14101aSSuman Anna 
34*2f14101aSSuman Anna 	spin_lock(&emu_lock);
35*2f14101aSSuman Anna 
36*2f14101aSSuman Anna 	if (enable && (atomic_inc_return(&count) == 1))
37*2f14101aSSuman Anna 		clkdm_deny_idle(emu_clkdm);
38*2f14101aSSuman Anna 	else if (!enable && (atomic_dec_return(&count) == 0))
39*2f14101aSSuman Anna 		clkdm_allow_idle(emu_clkdm);
40*2f14101aSSuman Anna 
41*2f14101aSSuman Anna 	spin_unlock(&emu_lock);
42*2f14101aSSuman Anna }
43*2f14101aSSuman Anna 
443846a3b9SSuman Anna int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request,
453846a3b9SSuman Anna 				    u8 *pwrst)
463846a3b9SSuman Anna {
473846a3b9SSuman Anna 	struct powerdomain *pwrdm;
483846a3b9SSuman Anna 	struct omap_device *od;
493846a3b9SSuman Anna 	u8 next_pwrst;
50*2f14101aSSuman Anna 	int ret = 0;
513846a3b9SSuman Anna 
523846a3b9SSuman Anna 	od = to_omap_device(pdev);
533846a3b9SSuman Anna 	if (!od)
543846a3b9SSuman Anna 		return -ENODEV;
553846a3b9SSuman Anna 
563846a3b9SSuman Anna 	if (od->hwmods_cnt != 1)
573846a3b9SSuman Anna 		return -EINVAL;
583846a3b9SSuman Anna 
593846a3b9SSuman Anna 	pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]);
603846a3b9SSuman Anna 	if (!pwrdm)
613846a3b9SSuman Anna 		return -EINVAL;
623846a3b9SSuman Anna 
63*2f14101aSSuman Anna 	if (request) {
643846a3b9SSuman Anna 		*pwrst = pwrdm_read_next_pwrst(pwrdm);
65*2f14101aSSuman Anna 		omap_iommu_dra7_emu_swsup_config(pdev, true);
66*2f14101aSSuman Anna 	}
673846a3b9SSuman Anna 
683846a3b9SSuman Anna 	if (*pwrst > PWRDM_POWER_RET)
69*2f14101aSSuman Anna 		goto out;
703846a3b9SSuman Anna 
713846a3b9SSuman Anna 	next_pwrst = request ? PWRDM_POWER_ON : *pwrst;
723846a3b9SSuman Anna 
73*2f14101aSSuman Anna 	ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst);
74*2f14101aSSuman Anna 
75*2f14101aSSuman Anna out:
76*2f14101aSSuman Anna 	if (!request)
77*2f14101aSSuman Anna 		omap_iommu_dra7_emu_swsup_config(pdev, false);
78*2f14101aSSuman Anna 
79*2f14101aSSuman Anna 	return ret;
803846a3b9SSuman Anna }
81