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