David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0-only |
| 2 | /* |
| 3 | * OMAP IOMMU quirks for various TI SoCs |
| 4 | * |
| 5 | * Copyright (C) 2015-2019 Texas Instruments Incorporated - http://www.ti.com/ |
| 6 | * Suman Anna <s-anna@ti.com> |
| 7 | */ |
| 8 | |
| 9 | #include <linux/platform_device.h> |
| 10 | #include <linux/err.h> |
| 11 | |
| 12 | #include "omap_hwmod.h" |
| 13 | #include "omap_device.h" |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 14 | #include "clockdomain.h" |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 15 | #include "powerdomain.h" |
| 16 | |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 17 | static void omap_iommu_dra7_emu_swsup_config(struct platform_device *pdev, |
| 18 | bool enable) |
| 19 | { |
| 20 | static struct clockdomain *emu_clkdm; |
| 21 | static DEFINE_SPINLOCK(emu_lock); |
| 22 | static atomic_t count; |
| 23 | struct device_node *np = pdev->dev.of_node; |
| 24 | |
| 25 | if (!of_device_is_compatible(np, "ti,dra7-dsp-iommu")) |
| 26 | return; |
| 27 | |
| 28 | if (!emu_clkdm) { |
| 29 | emu_clkdm = clkdm_lookup("emu_clkdm"); |
| 30 | if (WARN_ON_ONCE(!emu_clkdm)) |
| 31 | return; |
| 32 | } |
| 33 | |
| 34 | spin_lock(&emu_lock); |
| 35 | |
| 36 | if (enable && (atomic_inc_return(&count) == 1)) |
| 37 | clkdm_deny_idle(emu_clkdm); |
| 38 | else if (!enable && (atomic_dec_return(&count) == 0)) |
| 39 | clkdm_allow_idle(emu_clkdm); |
| 40 | |
| 41 | spin_unlock(&emu_lock); |
| 42 | } |
| 43 | |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 44 | int omap_iommu_set_pwrdm_constraint(struct platform_device *pdev, bool request, |
| 45 | u8 *pwrst) |
| 46 | { |
| 47 | struct powerdomain *pwrdm; |
| 48 | struct omap_device *od; |
| 49 | u8 next_pwrst; |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 50 | int ret = 0; |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 51 | |
| 52 | od = to_omap_device(pdev); |
| 53 | if (!od) |
| 54 | return -ENODEV; |
| 55 | |
| 56 | if (od->hwmods_cnt != 1) |
| 57 | return -EINVAL; |
| 58 | |
| 59 | pwrdm = omap_hwmod_get_pwrdm(od->hwmods[0]); |
| 60 | if (!pwrdm) |
| 61 | return -EINVAL; |
| 62 | |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 63 | if (request) { |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 64 | *pwrst = pwrdm_read_next_pwrst(pwrdm); |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 65 | omap_iommu_dra7_emu_swsup_config(pdev, true); |
| 66 | } |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 67 | |
| 68 | if (*pwrst > PWRDM_POWER_RET) |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 69 | goto out; |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 70 | |
| 71 | next_pwrst = request ? PWRDM_POWER_ON : *pwrst; |
| 72 | |
Olivier Deprez | 0e64123 | 2021-09-23 10:07:05 +0200 | [diff] [blame^] | 73 | ret = pwrdm_set_next_pwrst(pwrdm, next_pwrst); |
| 74 | |
| 75 | out: |
| 76 | if (!request) |
| 77 | omap_iommu_dra7_emu_swsup_config(pdev, false); |
| 78 | |
| 79 | return ret; |
David Brazdil | 0f672f6 | 2019-12-10 10:32:29 +0000 | [diff] [blame] | 80 | } |