2 * rmobile power management support
4 * Copyright (C) 2012 Renesas Solutions Corp.
5 * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 * Copyright (C) 2014 Glider bvba
9 * Copyright (C) 2011 Magnus Damm
11 * This file is subject to the terms and conditions of the GNU General Public
12 * License. See the file "COPYING" in the main directory of this archive
15 #include <linux/console.h>
16 #include <linux/delay.h>
18 #include <linux/of_address.h>
19 #include <linux/of_platform.h>
20 #include <linux/platform_device.h>
22 #include <linux/pm_clock.h>
23 #include <linux/slab.h>
27 #include "pm-rmobile.h"
30 #define SPDCR 0x08 /* SYS Power Down Control Register */
31 #define SWUCR 0x14 /* SYS Wakeup Control Register */
32 #define PSTR 0x80 /* Power Status Register */
34 #define PSTR_RETRIES 100
35 #define PSTR_DELAY_US 10
37 static int rmobile_pd_power_down(struct generic_pm_domain
*genpd
)
39 struct rmobile_pm_domain
*rmobile_pd
= to_rmobile_pd(genpd
);
42 if (rmobile_pd
->bit_shift
== ~0)
45 mask
= 1 << rmobile_pd
->bit_shift
;
46 if (rmobile_pd
->suspend
) {
47 int ret
= rmobile_pd
->suspend();
53 if (__raw_readl(rmobile_pd
->base
+ PSTR
) & mask
) {
54 unsigned int retry_count
;
55 __raw_writel(mask
, rmobile_pd
->base
+ SPDCR
);
57 for (retry_count
= PSTR_RETRIES
; retry_count
; retry_count
--) {
58 if (!(__raw_readl(rmobile_pd
->base
+ SPDCR
) & mask
))
64 if (!rmobile_pd
->no_debug
)
65 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
67 __raw_readl(rmobile_pd
->base
+ PSTR
));
72 static int __rmobile_pd_power_up(struct rmobile_pm_domain
*rmobile_pd
,
76 unsigned int retry_count
;
79 if (rmobile_pd
->bit_shift
== ~0)
82 mask
= 1 << rmobile_pd
->bit_shift
;
83 if (__raw_readl(rmobile_pd
->base
+ PSTR
) & mask
)
86 __raw_writel(mask
, rmobile_pd
->base
+ SWUCR
);
88 for (retry_count
= 2 * PSTR_RETRIES
; retry_count
; retry_count
--) {
89 if (!(__raw_readl(rmobile_pd
->base
+ SWUCR
) & mask
))
91 if (retry_count
> PSTR_RETRIES
)
92 udelay(PSTR_DELAY_US
);
99 if (!rmobile_pd
->no_debug
)
100 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
101 rmobile_pd
->genpd
.name
, mask
,
102 __raw_readl(rmobile_pd
->base
+ PSTR
));
105 if (ret
== 0 && rmobile_pd
->resume
&& do_resume
)
106 rmobile_pd
->resume();
111 static int rmobile_pd_power_up(struct generic_pm_domain
*genpd
)
113 return __rmobile_pd_power_up(to_rmobile_pd(genpd
), true);
116 static bool rmobile_pd_active_wakeup(struct device
*dev
)
121 static int rmobile_pd_attach_dev(struct generic_pm_domain
*domain
,
126 error
= pm_clk_create(dev
);
128 dev_err(dev
, "pm_clk_create failed %d\n", error
);
132 error
= pm_clk_add(dev
, NULL
);
134 dev_err(dev
, "pm_clk_add failed %d\n", error
);
145 static void rmobile_pd_detach_dev(struct generic_pm_domain
*domain
,
151 static void rmobile_init_pm_domain(struct rmobile_pm_domain
*rmobile_pd
)
153 struct generic_pm_domain
*genpd
= &rmobile_pd
->genpd
;
154 struct dev_power_governor
*gov
= rmobile_pd
->gov
;
156 genpd
->flags
= GENPD_FLAG_PM_CLK
;
157 pm_genpd_init(genpd
, gov
? : &simple_qos_governor
, false);
158 genpd
->dev_ops
.active_wakeup
= rmobile_pd_active_wakeup
;
159 genpd
->power_off
= rmobile_pd_power_down
;
160 genpd
->power_on
= rmobile_pd_power_up
;
161 genpd
->attach_dev
= rmobile_pd_attach_dev
;
162 genpd
->detach_dev
= rmobile_pd_detach_dev
;
163 __rmobile_pd_power_up(rmobile_pd
, false);
166 #ifdef CONFIG_ARCH_SHMOBILE_LEGACY
168 void rmobile_init_domains(struct rmobile_pm_domain domains
[], int num
)
172 for (j
= 0; j
< num
; j
++)
173 rmobile_init_pm_domain(&domains
[j
]);
176 void rmobile_add_device_to_domain_td(const char *domain_name
,
177 struct platform_device
*pdev
,
178 struct gpd_timing_data
*td
)
180 struct device
*dev
= &pdev
->dev
;
182 __pm_genpd_name_add_device(domain_name
, dev
, td
);
185 void rmobile_add_devices_to_domains(struct pm_domain_device data
[],
188 struct gpd_timing_data latencies
= {
189 .stop_latency_ns
= DEFAULT_DEV_LATENCY_NS
,
190 .start_latency_ns
= DEFAULT_DEV_LATENCY_NS
,
191 .save_state_latency_ns
= DEFAULT_DEV_LATENCY_NS
,
192 .restore_state_latency_ns
= DEFAULT_DEV_LATENCY_NS
,
196 for (j
= 0; j
< size
; j
++)
197 rmobile_add_device_to_domain_td(data
[j
].domain_name
,
198 data
[j
].pdev
, &latencies
);
201 #else /* !CONFIG_ARCH_SHMOBILE_LEGACY */
203 static int rmobile_pd_suspend_cpu(void)
206 * This domain contains the CPU core and therefore it should
207 * only be turned off if the CPU is not in use.
212 static int rmobile_pd_suspend_console(void)
215 * Serial consoles make use of SCIF hardware located in this domain,
216 * hence keep the power domain on if "no_console_suspend" is set.
218 return console_suspend_enabled
? 0 : -EBUSY
;
221 static int rmobile_pd_suspend_debug(void)
224 * This domain contains the Coresight-ETM hardware block and
225 * therefore it should only be turned off if the debug module is
231 #define MAX_NUM_CPU_PDS 8
233 static unsigned int num_cpu_pds __initdata
;
234 static struct device_node
*cpu_pds
[MAX_NUM_CPU_PDS
] __initdata
;
235 static struct device_node
*console_pd __initdata
;
236 static struct device_node
*debug_pd __initdata
;
238 static void __init
get_special_pds(void)
240 struct device_node
*np
, *pd
;
243 /* PM domains containing CPUs */
244 for_each_node_by_type(np
, "cpu") {
245 pd
= of_parse_phandle(np
, "power-domains", 0);
249 for (i
= 0; i
< num_cpu_pds
; i
++)
250 if (pd
== cpu_pds
[i
])
253 if (i
< num_cpu_pds
) {
258 if (num_cpu_pds
== MAX_NUM_CPU_PDS
) {
259 pr_warn("Too many CPU PM domains\n");
264 cpu_pds
[num_cpu_pds
++] = pd
;
267 /* PM domain containing console */
269 console_pd
= of_parse_phandle(of_stdout
, "power-domains", 0);
271 /* PM domain containing Coresight-ETM */
272 np
= of_find_compatible_node(NULL
, NULL
, "arm,coresight-etm3x");
274 debug_pd
= of_parse_phandle(np
, "power-domains", 0);
279 static void __init
put_special_pds(void)
283 for (i
= 0; i
< num_cpu_pds
; i
++)
284 of_node_put(cpu_pds
[i
]);
285 of_node_put(console_pd
);
286 of_node_put(debug_pd
);
289 static bool __init
pd_contains_cpu(const struct device_node
*pd
)
293 for (i
= 0; i
< num_cpu_pds
; i
++)
294 if (pd
== cpu_pds
[i
])
300 static void __init
rmobile_setup_pm_domain(struct device_node
*np
,
301 struct rmobile_pm_domain
*pd
)
303 const char *name
= pd
->genpd
.name
;
305 if (pd_contains_cpu(np
)) {
306 pr_debug("PM domain %s contains CPU\n", name
);
307 pd
->gov
= &pm_domain_always_on_gov
;
308 pd
->suspend
= rmobile_pd_suspend_cpu
;
309 } else if (np
== console_pd
) {
310 pr_debug("PM domain %s contains serial console\n", name
);
311 pd
->gov
= &pm_domain_always_on_gov
;
312 pd
->suspend
= rmobile_pd_suspend_console
;
313 } else if (np
== debug_pd
) {
314 pr_debug("PM domain %s contains Coresight-ETM\n", name
);
315 pd
->gov
= &pm_domain_always_on_gov
;
316 pd
->suspend
= rmobile_pd_suspend_debug
;
319 rmobile_init_pm_domain(pd
);
322 static int __init
rmobile_add_pm_domains(void __iomem
*base
,
323 struct device_node
*parent
,
324 struct generic_pm_domain
*genpd_parent
)
326 struct device_node
*np
;
328 for_each_child_of_node(parent
, np
) {
329 struct rmobile_pm_domain
*pd
;
332 if (of_property_read_u32(np
, "reg", &idx
)) {
333 /* always-on domain */
336 pd
= kzalloc(sizeof(*pd
), GFP_KERNEL
);
340 pd
->genpd
.name
= np
->name
;
344 rmobile_setup_pm_domain(np
, pd
);
346 pm_genpd_add_subdomain(genpd_parent
, &pd
->genpd
);
347 of_genpd_add_provider_simple(np
, &pd
->genpd
);
349 rmobile_add_pm_domains(base
, np
, &pd
->genpd
);
354 static int __init
rmobile_init_pm_domains(void)
356 struct device_node
*np
, *pmd
;
357 bool scanned
= false;
361 for_each_compatible_node(np
, NULL
, "renesas,sysc-rmobile") {
362 base
= of_iomap(np
, 0);
364 pr_warn("%s cannot map reg 0\n", np
->full_name
);
368 pmd
= of_get_child_by_name(np
, "pm-domains");
370 pr_warn("%s lacks pm-domains node\n", np
->full_name
);
375 /* Find PM domains containing special blocks */
380 ret
= rmobile_add_pm_domains(base
, pmd
, NULL
);
393 core_initcall(rmobile_init_pm_domains
);
395 #endif /* !CONFIG_ARCH_SHMOBILE_LEGACY */