1 // SPDX-License-Identifier: GPL-2.0-only
3 * OMAP IOMMU quirks for various TI SoCs
5 * Copyright (C) 2015-2019 Texas Instruments Incorporated - https://www.ti.com/
6 * Suman Anna <s-anna@ti.com>
9 #include <linux/platform_device.h>
10 #include <linux/err.h>
11 #include <linux/clk.h>
12 #include <linux/list.h>
14 #include "clockdomain.h"
15 #include "powerdomain.h"
19 struct powerdomain
*pwrdm
;
20 struct list_head node
;
23 static DEFINE_SPINLOCK(iommu_lock
);
24 static struct clockdomain
*emu_clkdm
;
25 static atomic_t emu_count
;
27 static void omap_iommu_dra7_emu_swsup_config(struct platform_device
*pdev
,
30 struct device_node
*np
= pdev
->dev
.of_node
;
33 if (!of_device_is_compatible(np
, "ti,dra7-dsp-iommu"))
37 emu_clkdm
= clkdm_lookup("emu_clkdm");
38 if (WARN_ON_ONCE(!emu_clkdm
))
42 spin_lock_irqsave(&iommu_lock
, flags
);
44 if (enable
&& (atomic_inc_return(&emu_count
) == 1))
45 clkdm_deny_idle(emu_clkdm
);
46 else if (!enable
&& (atomic_dec_return(&emu_count
) == 0))
47 clkdm_allow_idle(emu_clkdm
);
49 spin_unlock_irqrestore(&iommu_lock
, flags
);
52 static struct powerdomain
*_get_pwrdm(struct device
*dev
)
55 struct clk_hw_omap
*hwclk
;
56 struct clockdomain
*clkdm
;
57 struct powerdomain
*pwrdm
= NULL
;
58 struct pwrdm_link
*entry
;
60 static LIST_HEAD(cache
);
62 spin_lock_irqsave(&iommu_lock
, flags
);
64 list_for_each_entry(entry
, &cache
, node
) {
65 if (entry
->dev
== dev
) {
71 spin_unlock_irqrestore(&iommu_lock
, flags
);
76 clk
= of_clk_get(dev
->of_node
->parent
, 0);
78 dev_err(dev
, "no fck found\n");
82 hwclk
= to_clk_hw_omap(__clk_get_hw(clk
));
84 if (!hwclk
|| !hwclk
->clkdm_name
) {
85 dev_err(dev
, "no hwclk data\n");
89 clkdm
= clkdm_lookup(hwclk
->clkdm_name
);
91 dev_err(dev
, "clkdm not found: %s\n", hwclk
->clkdm_name
);
95 pwrdm
= clkdm_get_pwrdm(clkdm
);
97 dev_err(dev
, "pwrdm not found: %s\n", clkdm
->name
);
101 entry
= kmalloc(sizeof(*entry
), GFP_KERNEL
);
104 entry
->pwrdm
= pwrdm
;
105 spin_lock_irqsave(&iommu_lock
, flags
);
106 list_add(&entry
->node
, &cache
);
107 spin_unlock_irqrestore(&iommu_lock
, flags
);
113 int omap_iommu_set_pwrdm_constraint(struct platform_device
*pdev
, bool request
,
116 struct powerdomain
*pwrdm
;
120 pwrdm
= _get_pwrdm(&pdev
->dev
);
125 *pwrst
= pwrdm_read_next_pwrst(pwrdm
);
126 omap_iommu_dra7_emu_swsup_config(pdev
, true);
129 if (*pwrst
> PWRDM_POWER_RET
)
132 next_pwrst
= request
? PWRDM_POWER_ON
: *pwrst
;
134 ret
= pwrdm_set_next_pwrst(pwrdm
, next_pwrst
);
138 omap_iommu_dra7_emu_swsup_config(pdev
, false);