1 // SPDX-License-Identifier: GPL-2.0
3 * rmobile power management support
5 * Copyright (C) 2012 Renesas Solutions Corp.
6 * Copyright (C) 2012 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7 * Copyright (C) 2014 Glider bvba
10 * Copyright (C) 2011 Magnus Damm
12 #include <linux/clk/renesas.h>
13 #include <linux/console.h>
14 #include <linux/delay.h>
16 #include <linux/iopoll.h>
18 #include <linux/of_address.h>
20 #include <linux/pm_clock.h>
21 #include <linux/pm_domain.h>
22 #include <linux/slab.h>
25 #define SPDCR 0x08 /* SYS Power Down Control Register */
26 #define SWUCR 0x14 /* SYS Wakeup Control Register */
27 #define PSTR 0x80 /* Power Status Register */
29 #define PSTR_RETRIES 100
30 #define PSTR_DELAY_US 10
32 struct rmobile_pm_domain
{
33 struct generic_pm_domain genpd
;
34 struct dev_power_governor
*gov
;
37 unsigned int bit_shift
;
41 struct rmobile_pm_domain
*to_rmobile_pd(struct generic_pm_domain
*d
)
43 return container_of(d
, struct rmobile_pm_domain
, genpd
);
46 static int rmobile_pd_power_down(struct generic_pm_domain
*genpd
)
48 struct rmobile_pm_domain
*rmobile_pd
= to_rmobile_pd(genpd
);
49 unsigned int mask
= BIT(rmobile_pd
->bit_shift
);
52 if (rmobile_pd
->suspend
) {
53 int ret
= rmobile_pd
->suspend();
59 if (readl(rmobile_pd
->base
+ PSTR
) & mask
) {
60 writel(mask
, rmobile_pd
->base
+ SPDCR
);
62 readl_poll_timeout_atomic(rmobile_pd
->base
+ SPDCR
, val
,
63 !(val
& mask
), 0, PSTR_RETRIES
);
66 pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n", genpd
->name
, mask
,
67 readl(rmobile_pd
->base
+ PSTR
));
72 static int __rmobile_pd_power_up(struct rmobile_pm_domain
*rmobile_pd
)
74 unsigned int val
, mask
= BIT(rmobile_pd
->bit_shift
);
77 if (readl(rmobile_pd
->base
+ PSTR
) & mask
)
80 writel(mask
, rmobile_pd
->base
+ SWUCR
);
82 ret
= readl_poll_timeout_atomic(rmobile_pd
->base
+ SWUCR
, val
,
83 (val
& mask
), PSTR_DELAY_US
,
84 PSTR_RETRIES
* PSTR_DELAY_US
);
86 pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
87 rmobile_pd
->genpd
.name
, mask
,
88 readl(rmobile_pd
->base
+ PSTR
));
93 static int rmobile_pd_power_up(struct generic_pm_domain
*genpd
)
95 return __rmobile_pd_power_up(to_rmobile_pd(genpd
));
98 static void rmobile_init_pm_domain(struct rmobile_pm_domain
*rmobile_pd
)
100 struct generic_pm_domain
*genpd
= &rmobile_pd
->genpd
;
101 struct dev_power_governor
*gov
= rmobile_pd
->gov
;
103 genpd
->flags
|= GENPD_FLAG_PM_CLK
| GENPD_FLAG_ACTIVE_WAKEUP
;
104 genpd
->attach_dev
= cpg_mstp_attach_dev
;
105 genpd
->detach_dev
= cpg_mstp_detach_dev
;
107 if (!(genpd
->flags
& GENPD_FLAG_ALWAYS_ON
)) {
108 genpd
->power_off
= rmobile_pd_power_down
;
109 genpd
->power_on
= rmobile_pd_power_up
;
110 __rmobile_pd_power_up(rmobile_pd
);
113 pm_genpd_init(genpd
, gov
? : &simple_qos_governor
, false);
116 static int rmobile_pd_suspend_console(void)
119 * Serial consoles make use of SCIF hardware located in this domain,
120 * hence keep the power domain on if "no_console_suspend" is set.
122 return console_suspend_enabled
? 0 : -EBUSY
;
133 #define MAX_NUM_SPECIAL_PDS 16
135 static struct special_pd
{
136 struct device_node
*pd
;
138 } special_pds
[MAX_NUM_SPECIAL_PDS
] __initdata
;
140 static unsigned int num_special_pds __initdata
;
142 static const struct of_device_id special_ids
[] __initconst
= {
143 { .compatible
= "arm,coresight-etm3x", .data
= (void *)PD_DEBUG
},
144 { .compatible
= "renesas,dbsc-r8a73a4", .data
= (void *)PD_MEMCTL
, },
145 { .compatible
= "renesas,dbsc3-r8a7740", .data
= (void *)PD_MEMCTL
, },
146 { .compatible
= "renesas,sbsc-sh73a0", .data
= (void *)PD_MEMCTL
, },
150 static void __init
add_special_pd(struct device_node
*np
, enum pd_types type
)
153 struct device_node
*pd
;
155 pd
= of_parse_phandle(np
, "power-domains", 0);
159 for (i
= 0; i
< num_special_pds
; i
++)
160 if (pd
== special_pds
[i
].pd
&& type
== special_pds
[i
].type
) {
165 if (num_special_pds
== ARRAY_SIZE(special_pds
)) {
166 pr_warn("Too many special PM domains\n");
171 pr_debug("Special PM domain %pOFn type %d for %pOF\n", pd
, type
, np
);
173 special_pds
[num_special_pds
].pd
= pd
;
174 special_pds
[num_special_pds
].type
= type
;
178 static void __init
get_special_pds(void)
180 struct device_node
*np
;
181 const struct of_device_id
*id
;
183 /* PM domains containing CPUs */
184 for_each_of_cpu_node(np
)
185 add_special_pd(np
, PD_CPU
);
187 /* PM domain containing console */
189 add_special_pd(of_stdout
, PD_CONSOLE
);
191 /* PM domains containing other special devices */
192 for_each_matching_node_and_match(np
, special_ids
, &id
)
193 add_special_pd(np
, (uintptr_t)id
->data
);
196 static void __init
put_special_pds(void)
200 for (i
= 0; i
< num_special_pds
; i
++)
201 of_node_put(special_pds
[i
].pd
);
204 static enum pd_types __init
pd_type(const struct device_node
*pd
)
208 for (i
= 0; i
< num_special_pds
; i
++)
209 if (pd
== special_pds
[i
].pd
)
210 return special_pds
[i
].type
;
215 static void __init
rmobile_setup_pm_domain(struct device_node
*np
,
216 struct rmobile_pm_domain
*pd
)
218 const char *name
= pd
->genpd
.name
;
220 switch (pd_type(np
)) {
223 * This domain contains the CPU core and therefore it should
224 * only be turned off if the CPU is not in use.
226 pr_debug("PM domain %s contains CPU\n", name
);
227 pd
->genpd
.flags
|= GENPD_FLAG_ALWAYS_ON
;
231 pr_debug("PM domain %s contains serial console\n", name
);
232 pd
->gov
= &pm_domain_always_on_gov
;
233 pd
->suspend
= rmobile_pd_suspend_console
;
238 * This domain contains the Coresight-ETM hardware block and
239 * therefore it should only be turned off if the debug module
242 pr_debug("PM domain %s contains Coresight-ETM\n", name
);
243 pd
->genpd
.flags
|= GENPD_FLAG_ALWAYS_ON
;
248 * This domain contains a memory-controller and therefore it
249 * should only be turned off if memory is not in use.
251 pr_debug("PM domain %s contains MEMCTL\n", name
);
252 pd
->genpd
.flags
|= GENPD_FLAG_ALWAYS_ON
;
256 if (pd
->bit_shift
== ~0) {
257 /* Top-level always-on domain */
258 pr_debug("PM domain %s is always-on domain\n", name
);
259 pd
->genpd
.flags
|= GENPD_FLAG_ALWAYS_ON
;
264 rmobile_init_pm_domain(pd
);
267 static int __init
rmobile_add_pm_domains(void __iomem
*base
,
268 struct device_node
*parent
,
269 struct generic_pm_domain
*genpd_parent
)
271 for_each_child_of_node_scoped(parent
, np
) {
272 struct rmobile_pm_domain
*pd
;
275 if (of_property_read_u32(np
, "reg", &idx
)) {
276 /* always-on domain */
279 pd
= kzalloc(sizeof(*pd
), GFP_KERNEL
);
283 pd
->genpd
.name
= np
->name
;
287 rmobile_setup_pm_domain(np
, pd
);
289 pm_genpd_add_subdomain(genpd_parent
, &pd
->genpd
);
290 of_genpd_add_provider_simple(np
, &pd
->genpd
);
292 rmobile_add_pm_domains(base
, np
, &pd
->genpd
);
297 static int __init
rmobile_init_pm_domains(void)
299 struct device_node
*np
, *pmd
;
300 bool scanned
= false;
304 for_each_compatible_node(np
, NULL
, "renesas,sysc-rmobile") {
305 base
= of_iomap(np
, 0);
307 pr_warn("%pOF cannot map reg 0\n", np
);
311 pmd
= of_get_child_by_name(np
, "pm-domains");
314 pr_warn("%pOF lacks pm-domains node\n", np
);
319 /* Find PM domains containing special blocks */
324 ret
= rmobile_add_pm_domains(base
, pmd
, NULL
);
331 fwnode_dev_initialized(of_fwnode_handle(np
), true);
339 core_initcall(rmobile_init_pm_domains
);