aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/soc/samsung/pm_domains.c
diff options
context:
space:
mode:
authorKrzysztof Kozlowski <k.kozlowski@samsung.com>2016-05-10 09:52:21 -0400
committerKrzysztof Kozlowski <k.kozlowski@samsung.com>2016-05-30 03:12:53 -0400
commitc028e175713698b88694c2075853963d07c81c13 (patch)
tree4755cc690a542a0aa173bbc72d4ce5ce0e03c37f /drivers/soc/samsung/pm_domains.c
parente465007a7a7ca745f018fdcacb0a5a911a5c50d9 (diff)
soc: samsung: pm_domains: Prepare for supporting ARMv8 Exynos
The ARMv8 Exynos family (Exynos5433 and Exynos7420) uses different value (0xf instead of 0x7) for controlling the power domain on/off registers (both for control and for status). Choose the value depending on the compatible. This prepares the driver for supporting ARMv8 SoCs. Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com> Reviewed-by: Javier Martinez Canillas <javier@osg.samsung.com>
Diffstat (limited to 'drivers/soc/samsung/pm_domains.c')
-rw-r--r--drivers/soc/samsung/pm_domains.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/drivers/soc/samsung/pm_domains.c b/drivers/soc/samsung/pm_domains.c
index 875a2bab64f6..f60515eefb66 100644
--- a/drivers/soc/samsung/pm_domains.c
+++ b/drivers/soc/samsung/pm_domains.c
@@ -23,9 +23,13 @@
23#include <linux/of_platform.h> 23#include <linux/of_platform.h>
24#include <linux/sched.h> 24#include <linux/sched.h>
25 25
26#define INT_LOCAL_PWR_EN 0x7
27#define MAX_CLK_PER_DOMAIN 4 26#define MAX_CLK_PER_DOMAIN 4
28 27
28struct exynos_pm_domain_config {
29 /* Value for LOCAL_PWR_CFG and STATUS fields for each domain */
30 u32 local_pwr_cfg;
31};
32
29/* 33/*
30 * Exynos specific wrapper around the generic power domain 34 * Exynos specific wrapper around the generic power domain
31 */ 35 */
@@ -38,6 +42,7 @@ struct exynos_pm_domain {
38 struct clk *clk[MAX_CLK_PER_DOMAIN]; 42 struct clk *clk[MAX_CLK_PER_DOMAIN];
39 struct clk *pclk[MAX_CLK_PER_DOMAIN]; 43 struct clk *pclk[MAX_CLK_PER_DOMAIN];
40 struct clk *asb_clk[MAX_CLK_PER_DOMAIN]; 44 struct clk *asb_clk[MAX_CLK_PER_DOMAIN];
45 u32 local_pwr_cfg;
41}; 46};
42 47
43static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on) 48static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
@@ -69,13 +74,13 @@ static int exynos_pd_power(struct generic_pm_domain *domain, bool power_on)
69 } 74 }
70 } 75 }
71 76
72 pwr = power_on ? INT_LOCAL_PWR_EN : 0; 77 pwr = power_on ? pd->local_pwr_cfg : 0;
73 __raw_writel(pwr, base); 78 __raw_writel(pwr, base);
74 79
75 /* Wait max 1ms */ 80 /* Wait max 1ms */
76 timeout = 10; 81 timeout = 10;
77 82
78 while ((__raw_readl(base + 0x4) & INT_LOCAL_PWR_EN) != pwr) { 83 while ((__raw_readl(base + 0x4) & pd->local_pwr_cfg) != pwr) {
79 if (!timeout) { 84 if (!timeout) {
80 op = (power_on) ? "enable" : "disable"; 85 op = (power_on) ? "enable" : "disable";
81 pr_err("Power domain %s %s failed\n", domain->name, op); 86 pr_err("Power domain %s %s failed\n", domain->name, op);
@@ -119,14 +124,30 @@ static int exynos_pd_power_off(struct generic_pm_domain *domain)
119 return exynos_pd_power(domain, false); 124 return exynos_pd_power(domain, false);
120} 125}
121 126
127static const struct exynos_pm_domain_config exynos4210_cfg __initconst = {
128 .local_pwr_cfg = 0x7,
129};
130
131static const struct of_device_id exynos_pm_domain_of_match[] __initconst = {
132 {
133 .compatible = "samsung,exynos4210-pd",
134 .data = &exynos4210_cfg,
135 },
136 { },
137};
138
122static __init int exynos4_pm_init_power_domain(void) 139static __init int exynos4_pm_init_power_domain(void)
123{ 140{
124 struct device_node *np; 141 struct device_node *np;
142 const struct of_device_id *match;
125 143
126 for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") { 144 for_each_matching_node_and_match(np, exynos_pm_domain_of_match, &match) {
145 const struct exynos_pm_domain_config *pm_domain_cfg;
127 struct exynos_pm_domain *pd; 146 struct exynos_pm_domain *pd;
128 int on, i; 147 int on, i;
129 148
149 pm_domain_cfg = match->data;
150
130 pd = kzalloc(sizeof(*pd), GFP_KERNEL); 151 pd = kzalloc(sizeof(*pd), GFP_KERNEL);
131 if (!pd) { 152 if (!pd) {
132 pr_err("%s: failed to allocate memory for domain\n", 153 pr_err("%s: failed to allocate memory for domain\n",
@@ -153,6 +174,7 @@ static __init int exynos4_pm_init_power_domain(void)
153 174
154 pd->pd.power_off = exynos_pd_power_off; 175 pd->pd.power_off = exynos_pd_power_off;
155 pd->pd.power_on = exynos_pd_power_on; 176 pd->pd.power_on = exynos_pd_power_on;
177 pd->local_pwr_cfg = pm_domain_cfg->local_pwr_cfg;
156 178
157 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) { 179 for (i = 0; i < MAX_CLK_PER_DOMAIN; i++) {
158 char clk_name[8]; 180 char clk_name[8];
@@ -185,14 +207,14 @@ static __init int exynos4_pm_init_power_domain(void)
185 clk_put(pd->oscclk); 207 clk_put(pd->oscclk);
186 208
187no_clk: 209no_clk:
188 on = __raw_readl(pd->base + 0x4) & INT_LOCAL_PWR_EN; 210 on = __raw_readl(pd->base + 0x4) & pd->local_pwr_cfg;
189 211
190 pm_genpd_init(&pd->pd, NULL, !on); 212 pm_genpd_init(&pd->pd, NULL, !on);
191 of_genpd_add_provider_simple(np, &pd->pd); 213 of_genpd_add_provider_simple(np, &pd->pd);
192 } 214 }
193 215
194 /* Assign the child power domains to their parents */ 216 /* Assign the child power domains to their parents */
195 for_each_compatible_node(np, NULL, "samsung,exynos4210-pd") { 217 for_each_matching_node(np, exynos_pm_domain_of_match) {
196 struct generic_pm_domain *child_domain, *parent_domain; 218 struct generic_pm_domain *child_domain, *parent_domain;
197 struct of_phandle_args args; 219 struct of_phandle_args args;
198 220