Skip to content

Commit 9d976d6

Browse files
avpatelpalmer-dabbelt
authored andcommitted
cpuidle: Factor-out power domain related code from PSCI domain driver
The generic power domain related code in PSCI domain driver is largely independent of PSCI and can be shared with RISC-V SBI domain driver hence we factor-out this code into dt_idle_genpd.c and dt_idle_genpd.h. Signed-off-by: Anup Patel <anup.patel@wdc.com> Signed-off-by: Anup Patel <apatel@ventanamicro.com> Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org> Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent b820090 commit 9d976d6

8 files changed

Lines changed: 259 additions & 135 deletions

File tree

MAINTAINERS

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5051,6 +5051,13 @@ S: Supported
50515051
F: drivers/cpuidle/cpuidle-psci.h
50525052
F: drivers/cpuidle/cpuidle-psci-domain.c
50535053

5054+
CPUIDLE DRIVER - DT IDLE PM DOMAIN
5055+
M: Ulf Hansson <ulf.hansson@linaro.org>
5056+
L: linux-pm@vger.kernel.org
5057+
S: Supported
5058+
F: drivers/cpuidle/dt_idle_genpd.c
5059+
F: drivers/cpuidle/dt_idle_genpd.h
5060+
50545061
CRAMFS FILESYSTEM
50555062
M: Nicolas Pitre <nico@fluxnic.net>
50565063
S: Maintained

drivers/cpuidle/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ config CPU_IDLE_GOV_HALTPOLL
4747
config DT_IDLE_STATES
4848
bool
4949

50+
config DT_IDLE_GENPD
51+
depends on PM_GENERIC_DOMAINS_OF
52+
bool
53+
5054
menu "ARM CPU Idle Drivers"
5155
depends on ARM || ARM64
5256
source "drivers/cpuidle/Kconfig.arm"

drivers/cpuidle/Kconfig.arm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ config ARM_PSCI_CPUIDLE_DOMAIN
2727
bool "PSCI CPU idle Domain"
2828
depends on ARM_PSCI_CPUIDLE
2929
depends on PM_GENERIC_DOMAINS_OF
30+
select DT_IDLE_GENPD
3031
default y
3132
help
3233
Select this to enable the PSCI based CPUidle driver to use PM domains,

drivers/cpuidle/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
obj-y += cpuidle.o driver.o governor.o sysfs.o governors/
77
obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
88
obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o
9+
obj-$(CONFIG_DT_IDLE_GENPD) += dt_idle_genpd.o
910
obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o
1011
obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o
1112

drivers/cpuidle/cpuidle-psci-domain.c

Lines changed: 5 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -47,96 +47,21 @@ static int psci_pd_power_off(struct generic_pm_domain *pd)
4747
return 0;
4848
}
4949

50-
static int psci_pd_parse_state_nodes(struct genpd_power_state *states,
51-
int state_count)
52-
{
53-
int i, ret;
54-
u32 psci_state, *psci_state_buf;
55-
56-
for (i = 0; i < state_count; i++) {
57-
ret = psci_dt_parse_state_node(to_of_node(states[i].fwnode),
58-
&psci_state);
59-
if (ret)
60-
goto free_state;
61-
62-
psci_state_buf = kmalloc(sizeof(u32), GFP_KERNEL);
63-
if (!psci_state_buf) {
64-
ret = -ENOMEM;
65-
goto free_state;
66-
}
67-
*psci_state_buf = psci_state;
68-
states[i].data = psci_state_buf;
69-
}
70-
71-
return 0;
72-
73-
free_state:
74-
i--;
75-
for (; i >= 0; i--)
76-
kfree(states[i].data);
77-
return ret;
78-
}
79-
80-
static int psci_pd_parse_states(struct device_node *np,
81-
struct genpd_power_state **states, int *state_count)
82-
{
83-
int ret;
84-
85-
/* Parse the domain idle states. */
86-
ret = of_genpd_parse_idle_states(np, states, state_count);
87-
if (ret)
88-
return ret;
89-
90-
/* Fill out the PSCI specifics for each found state. */
91-
ret = psci_pd_parse_state_nodes(*states, *state_count);
92-
if (ret)
93-
kfree(*states);
94-
95-
return ret;
96-
}
97-
98-
static void psci_pd_free_states(struct genpd_power_state *states,
99-
unsigned int state_count)
100-
{
101-
int i;
102-
103-
for (i = 0; i < state_count; i++)
104-
kfree(states[i].data);
105-
kfree(states);
106-
}
107-
10850
static int psci_pd_init(struct device_node *np, bool use_osi)
10951
{
11052
struct generic_pm_domain *pd;
11153
struct psci_pd_provider *pd_provider;
11254
struct dev_power_governor *pd_gov;
113-
struct genpd_power_state *states = NULL;
11455
int ret = -ENOMEM, state_count = 0;
11556

116-
pd = kzalloc(sizeof(*pd), GFP_KERNEL);
57+
pd = dt_idle_pd_alloc(np, psci_dt_parse_state_node);
11758
if (!pd)
11859
goto out;
11960

12061
pd_provider = kzalloc(sizeof(*pd_provider), GFP_KERNEL);
12162
if (!pd_provider)
12263
goto free_pd;
12364

124-
pd->name = kasprintf(GFP_KERNEL, "%pOF", np);
125-
if (!pd->name)
126-
goto free_pd_prov;
127-
128-
/*
129-
* Parse the domain idle states and let genpd manage the state selection
130-
* for those being compatible with "domain-idle-state".
131-
*/
132-
ret = psci_pd_parse_states(np, &states, &state_count);
133-
if (ret)
134-
goto free_name;
135-
136-
pd->free_states = psci_pd_free_states;
137-
pd->name = kbasename(pd->name);
138-
pd->states = states;
139-
pd->state_count = state_count;
14065
pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN;
14166

14267
/* Allow power off when OSI has been successfully enabled. */
@@ -149,10 +74,8 @@ static int psci_pd_init(struct device_node *np, bool use_osi)
14974
pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL;
15075

15176
ret = pm_genpd_init(pd, pd_gov, false);
152-
if (ret) {
153-
psci_pd_free_states(states, state_count);
154-
goto free_name;
155-
}
77+
if (ret)
78+
goto free_pd_prov;
15679

15780
ret = of_genpd_add_provider_simple(np, pd);
15881
if (ret)
@@ -166,12 +89,10 @@ static int psci_pd_init(struct device_node *np, bool use_osi)
16689

16790
remove_pd:
16891
pm_genpd_remove(pd);
169-
free_name:
170-
kfree(pd->name);
17192
free_pd_prov:
17293
kfree(pd_provider);
17394
free_pd:
174-
kfree(pd);
95+
dt_idle_pd_free(pd);
17596
out:
17697
pr_err("failed to init PM domain ret=%d %pOF\n", ret, np);
17798
return ret;
@@ -195,30 +116,6 @@ static void psci_pd_remove(void)
195116
}
196117
}
197118

198-
static int psci_pd_init_topology(struct device_node *np)
199-
{
200-
struct device_node *node;
201-
struct of_phandle_args child, parent;
202-
int ret;
203-
204-
for_each_child_of_node(np, node) {
205-
if (of_parse_phandle_with_args(node, "power-domains",
206-
"#power-domain-cells", 0, &parent))
207-
continue;
208-
209-
child.np = node;
210-
child.args_count = 0;
211-
ret = of_genpd_add_subdomain(&parent, &child);
212-
of_node_put(parent.np);
213-
if (ret) {
214-
of_node_put(node);
215-
return ret;
216-
}
217-
}
218-
219-
return 0;
220-
}
221-
222119
static bool psci_pd_try_set_osi_mode(void)
223120
{
224121
int ret;
@@ -282,7 +179,7 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev)
282179
goto no_pd;
283180

284181
/* Link genpd masters/subdomains to model the CPU topology. */
285-
ret = psci_pd_init_topology(np);
182+
ret = dt_idle_pd_init_topology(np);
286183
if (ret)
287184
goto remove_pd;
288185

@@ -314,28 +211,3 @@ static int __init psci_idle_init_domains(void)
314211
return platform_driver_register(&psci_cpuidle_domain_driver);
315212
}
316213
subsys_initcall(psci_idle_init_domains);
317-
318-
struct device *psci_dt_attach_cpu(int cpu)
319-
{
320-
struct device *dev;
321-
322-
dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci");
323-
if (IS_ERR_OR_NULL(dev))
324-
return dev;
325-
326-
pm_runtime_irq_safe(dev);
327-
if (cpu_online(cpu))
328-
pm_runtime_get_sync(dev);
329-
330-
dev_pm_syscore_device(dev, true);
331-
332-
return dev;
333-
}
334-
335-
void psci_dt_detach_cpu(struct device *dev)
336-
{
337-
if (IS_ERR_OR_NULL(dev))
338-
return;
339-
340-
dev_pm_domain_detach(dev, false);
341-
}

drivers/cpuidle/cpuidle-psci.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,19 @@ void psci_set_domain_state(u32 state);
1010
int psci_dt_parse_state_node(struct device_node *np, u32 *state);
1111

1212
#ifdef CONFIG_ARM_PSCI_CPUIDLE_DOMAIN
13-
struct device *psci_dt_attach_cpu(int cpu);
14-
void psci_dt_detach_cpu(struct device *dev);
13+
14+
#include "dt_idle_genpd.h"
15+
16+
static inline struct device *psci_dt_attach_cpu(int cpu)
17+
{
18+
return dt_idle_attach_cpu(cpu, "psci");
19+
}
20+
21+
static inline void psci_dt_detach_cpu(struct device *dev)
22+
{
23+
dt_idle_detach_cpu(dev);
24+
}
25+
1526
#else
1627
static inline struct device *psci_dt_attach_cpu(int cpu) { return NULL; }
1728
static inline void psci_dt_detach_cpu(struct device *dev) { }

0 commit comments

Comments
 (0)