1 // SPDX-License-Identifier: GPL-2.0-only OR MIT
3 * Apple SoC PMGR device power state driver
5 * Copyright The Asahi Linux Contributors
8 #include <linux/bitops.h>
9 #include <linux/bitfield.h>
10 #include <linux/err.h>
12 #include <linux/of_address.h>
13 #include <linux/platform_device.h>
14 #include <linux/pm_domain.h>
15 #include <linux/regmap.h>
16 #include <linux/mfd/syscon.h>
17 #include <linux/reset-controller.h>
18 #include <linux/module.h>
20 #define APPLE_PMGR_RESET BIT(31)
21 #define APPLE_PMGR_AUTO_ENABLE BIT(28)
22 #define APPLE_PMGR_PS_AUTO GENMASK(27, 24)
23 #define APPLE_PMGR_PS_MIN GENMASK(19, 16)
24 #define APPLE_PMGR_PARENT_OFF BIT(11)
25 #define APPLE_PMGR_DEV_DISABLE BIT(10)
26 #define APPLE_PMGR_WAS_CLKGATED BIT(9)
27 #define APPLE_PMGR_WAS_PWRGATED BIT(8)
28 #define APPLE_PMGR_PS_ACTUAL GENMASK(7, 4)
29 #define APPLE_PMGR_PS_TARGET GENMASK(3, 0)
31 #define APPLE_PMGR_FLAGS (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED)
33 #define APPLE_PMGR_PS_ACTIVE 0xf
34 #define APPLE_PMGR_PS_CLKGATE 0x4
35 #define APPLE_PMGR_PS_PWRGATE 0x0
37 #define APPLE_PMGR_PS_SET_TIMEOUT 100
38 #define APPLE_PMGR_RESET_TIME 1
40 struct apple_pmgr_ps
{
42 struct generic_pm_domain genpd
;
43 struct reset_controller_dev rcdev
;
44 struct regmap
*regmap
;
49 #define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd)
50 #define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev)
52 static int apple_pmgr_ps_set(struct generic_pm_domain
*genpd
, u32 pstate
, bool auto_enable
)
55 struct apple_pmgr_ps
*ps
= genpd_to_apple_pmgr_ps(genpd
);
58 ret
= regmap_read(ps
->regmap
, ps
->offset
, ®
);
62 /* Resets are synchronous, and only work if the device is powered and clocked. */
63 if (reg
& APPLE_PMGR_RESET
&& pstate
!= APPLE_PMGR_PS_ACTIVE
)
64 dev_err(ps
->dev
, "PS %s: powering off with RESET active\n",
67 reg
&= ~(APPLE_PMGR_AUTO_ENABLE
| APPLE_PMGR_FLAGS
| APPLE_PMGR_PS_TARGET
);
68 reg
|= FIELD_PREP(APPLE_PMGR_PS_TARGET
, pstate
);
70 dev_dbg(ps
->dev
, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd
->name
, pstate
, reg
);
72 regmap_write(ps
->regmap
, ps
->offset
, reg
);
74 ret
= regmap_read_poll_timeout_atomic(
75 ps
->regmap
, ps
->offset
, reg
,
76 (FIELD_GET(APPLE_PMGR_PS_ACTUAL
, reg
) == pstate
), 1,
77 APPLE_PMGR_PS_SET_TIMEOUT
);
79 dev_err(ps
->dev
, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n",
80 genpd
->name
, pstate
, reg
);
83 /* Not all devices implement this; this is a no-op where not implemented. */
84 reg
&= ~APPLE_PMGR_FLAGS
;
85 reg
|= APPLE_PMGR_AUTO_ENABLE
;
86 regmap_write(ps
->regmap
, ps
->offset
, reg
);
92 static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps
*ps
)
96 regmap_read(ps
->regmap
, ps
->offset
, ®
);
98 * We consider domains as active if they are actually on, or if they have auto-PM
99 * enabled and the intended target is on.
101 return (FIELD_GET(APPLE_PMGR_PS_ACTUAL
, reg
) == APPLE_PMGR_PS_ACTIVE
||
102 (FIELD_GET(APPLE_PMGR_PS_TARGET
, reg
) == APPLE_PMGR_PS_ACTIVE
&&
103 reg
& APPLE_PMGR_AUTO_ENABLE
));
106 static int apple_pmgr_ps_power_on(struct generic_pm_domain
*genpd
)
108 return apple_pmgr_ps_set(genpd
, APPLE_PMGR_PS_ACTIVE
, true);
111 static int apple_pmgr_ps_power_off(struct generic_pm_domain
*genpd
)
113 return apple_pmgr_ps_set(genpd
, APPLE_PMGR_PS_PWRGATE
, false);
116 static int apple_pmgr_reset_assert(struct reset_controller_dev
*rcdev
, unsigned long id
)
118 struct apple_pmgr_ps
*ps
= rcdev_to_apple_pmgr_ps(rcdev
);
121 spin_lock_irqsave(&ps
->genpd
.slock
, flags
);
123 if (ps
->genpd
.status
== GENPD_STATE_OFF
)
124 dev_err(ps
->dev
, "PS 0x%x: asserting RESET while powered down\n", ps
->offset
);
126 dev_dbg(ps
->dev
, "PS 0x%x: assert reset\n", ps
->offset
);
127 /* Quiesce device before asserting reset */
128 regmap_update_bits(ps
->regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_DEV_DISABLE
,
129 APPLE_PMGR_DEV_DISABLE
);
130 regmap_update_bits(ps
->regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_RESET
,
133 spin_unlock_irqrestore(&ps
->genpd
.slock
, flags
);
138 static int apple_pmgr_reset_deassert(struct reset_controller_dev
*rcdev
, unsigned long id
)
140 struct apple_pmgr_ps
*ps
= rcdev_to_apple_pmgr_ps(rcdev
);
143 spin_lock_irqsave(&ps
->genpd
.slock
, flags
);
145 dev_dbg(ps
->dev
, "PS 0x%x: deassert reset\n", ps
->offset
);
146 regmap_update_bits(ps
->regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_RESET
, 0);
147 regmap_update_bits(ps
->regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_DEV_DISABLE
, 0);
149 if (ps
->genpd
.status
== GENPD_STATE_OFF
)
150 dev_err(ps
->dev
, "PS 0x%x: RESET was deasserted while powered down\n", ps
->offset
);
152 spin_unlock_irqrestore(&ps
->genpd
.slock
, flags
);
157 static int apple_pmgr_reset_reset(struct reset_controller_dev
*rcdev
, unsigned long id
)
161 ret
= apple_pmgr_reset_assert(rcdev
, id
);
165 usleep_range(APPLE_PMGR_RESET_TIME
, 2 * APPLE_PMGR_RESET_TIME
);
167 return apple_pmgr_reset_deassert(rcdev
, id
);
170 static int apple_pmgr_reset_status(struct reset_controller_dev
*rcdev
, unsigned long id
)
172 struct apple_pmgr_ps
*ps
= rcdev_to_apple_pmgr_ps(rcdev
);
175 regmap_read(ps
->regmap
, ps
->offset
, ®
);
177 return !!(reg
& APPLE_PMGR_RESET
);
180 static const struct reset_control_ops apple_pmgr_reset_ops
= {
181 .assert = apple_pmgr_reset_assert
,
182 .deassert
= apple_pmgr_reset_deassert
,
183 .reset
= apple_pmgr_reset_reset
,
184 .status
= apple_pmgr_reset_status
,
187 static int apple_pmgr_reset_xlate(struct reset_controller_dev
*rcdev
,
188 const struct of_phandle_args
*reset_spec
)
193 static int apple_pmgr_ps_probe(struct platform_device
*pdev
)
195 struct device
*dev
= &pdev
->dev
;
196 struct device_node
*node
= dev
->of_node
;
197 struct apple_pmgr_ps
*ps
;
198 struct regmap
*regmap
;
199 struct of_phandle_iterator it
;
204 regmap
= syscon_node_to_regmap(node
->parent
);
206 return PTR_ERR(regmap
);
208 ps
= devm_kzalloc(dev
, sizeof(*ps
), GFP_KERNEL
);
215 ret
= of_property_read_string(node
, "label", &name
);
217 dev_err(dev
, "missing label property\n");
221 ret
= of_property_read_u32(node
, "reg", &ps
->offset
);
223 dev_err(dev
, "missing reg property\n");
227 ps
->genpd
.flags
|= GENPD_FLAG_IRQ_SAFE
;
228 ps
->genpd
.name
= name
;
229 ps
->genpd
.power_on
= apple_pmgr_ps_power_on
;
230 ps
->genpd
.power_off
= apple_pmgr_ps_power_off
;
232 ret
= of_property_read_u32(node
, "apple,min-state", &ps
->min_state
);
233 if (ret
== 0 && ps
->min_state
<= APPLE_PMGR_PS_ACTIVE
)
234 regmap_update_bits(regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_PS_MIN
,
235 FIELD_PREP(APPLE_PMGR_PS_MIN
, ps
->min_state
));
237 active
= apple_pmgr_ps_is_active(ps
);
238 if (of_property_read_bool(node
, "apple,always-on")) {
239 ps
->genpd
.flags
|= GENPD_FLAG_ALWAYS_ON
;
241 dev_warn(dev
, "always-on domain %s is not on at boot\n", name
);
242 /* Turn it on so pm_genpd_init does not fail */
243 active
= apple_pmgr_ps_power_on(&ps
->genpd
) == 0;
247 /* Turn on auto-PM if the domain is already on */
249 regmap_update_bits(regmap
, ps
->offset
, APPLE_PMGR_FLAGS
| APPLE_PMGR_AUTO_ENABLE
,
250 APPLE_PMGR_AUTO_ENABLE
);
252 ret
= pm_genpd_init(&ps
->genpd
, NULL
, !active
);
254 dev_err(dev
, "pm_genpd_init failed\n");
258 ret
= of_genpd_add_provider_simple(node
, &ps
->genpd
);
260 dev_err(dev
, "of_genpd_add_provider_simple failed\n");
264 of_for_each_phandle(&it
, ret
, node
, "power-domains", "#power-domain-cells", -1) {
265 struct of_phandle_args parent
, child
;
268 parent
.args_count
= of_phandle_iterator_args(&it
, parent
.args
, MAX_PHANDLE_ARGS
);
270 child
.args_count
= 0;
271 ret
= of_genpd_add_subdomain(&parent
, &child
);
273 if (ret
== -EPROBE_DEFER
) {
274 of_node_put(parent
.np
);
276 } else if (ret
< 0) {
277 dev_err(dev
, "failed to add to parent domain: %d (%s -> %s)\n",
278 ret
, it
.node
->name
, node
->name
);
279 of_node_put(parent
.np
);
285 * Do not participate in regular PM; parent power domains are handled via the
288 pm_genpd_remove_device(dev
);
290 ps
->rcdev
.owner
= THIS_MODULE
;
291 ps
->rcdev
.nr_resets
= 1;
292 ps
->rcdev
.ops
= &apple_pmgr_reset_ops
;
293 ps
->rcdev
.of_node
= dev
->of_node
;
294 ps
->rcdev
.of_reset_n_cells
= 0;
295 ps
->rcdev
.of_xlate
= apple_pmgr_reset_xlate
;
297 ret
= devm_reset_controller_register(dev
, &ps
->rcdev
);
303 of_genpd_del_provider(node
);
304 pm_genpd_remove(&ps
->genpd
);
308 static const struct of_device_id apple_pmgr_ps_of_match
[] = {
309 { .compatible
= "apple,pmgr-pwrstate" },
313 MODULE_DEVICE_TABLE(of
, apple_pmgr_ps_of_match
);
315 static struct platform_driver apple_pmgr_ps_driver
= {
316 .probe
= apple_pmgr_ps_probe
,
318 .name
= "apple-pmgr-pwrstate",
319 .of_match_table
= apple_pmgr_ps_of_match
,
323 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>");
324 MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs");
326 module_platform_driver(apple_pmgr_ps_driver
);