1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* 3 * Apple SoC PMGR device power state driver 4 * 5 * Copyright The Asahi Linux Contributors 6 */ 7 8 #include <linux/bitops.h> 9 #include <linux/bitfield.h> 10 #include <linux/err.h> 11 #include <linux/of.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> 19 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) 30 31 #define APPLE_PMGR_FLAGS (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED) 32 33 #define APPLE_PMGR_PS_ACTIVE 0xf 34 #define APPLE_PMGR_PS_CLKGATE 0x4 35 #define APPLE_PMGR_PS_PWRGATE 0x0 36 37 #define APPLE_PMGR_PS_SET_TIMEOUT 100 38 #define APPLE_PMGR_RESET_TIME 1 39 40 struct apple_pmgr_ps { 41 struct device *dev; 42 struct generic_pm_domain genpd; 43 struct reset_controller_dev rcdev; 44 struct regmap *regmap; 45 u32 offset; 46 u32 min_state; 47 }; 48 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) 51 52 static int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable) 53 { 54 int ret; 55 struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd); 56 u32 reg; 57 58 ret = regmap_read(ps->regmap, ps->offset, ®); 59 if (ret < 0) 60 return ret; 61 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", 65 genpd->name); 66 67 reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET); 68 reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate); 69 70 dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg); 71 72 regmap_write(ps->regmap, ps->offset, reg); 73 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); 78 if (ret < 0) 79 dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n", 80 genpd->name, pstate, reg); 81 82 if (auto_enable) { 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); 87 } 88 89 return ret; 90 } 91 92 static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps) 93 { 94 u32 reg = 0; 95 96 regmap_read(ps->regmap, ps->offset, ®); 97 /* 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. 100 */ 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)); 104 } 105 106 static int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd) 107 { 108 return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true); 109 } 110 111 static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd) 112 { 113 return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false); 114 } 115 116 static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 117 { 118 struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 119 unsigned long flags; 120 121 spin_lock_irqsave(&ps->genpd.slock, flags); 122 123 if (ps->genpd.status == GENPD_STATE_OFF) 124 dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset); 125 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, 131 APPLE_PMGR_RESET); 132 133 spin_unlock_irqrestore(&ps->genpd.slock, flags); 134 135 return 0; 136 } 137 138 static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 139 { 140 struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 141 unsigned long flags; 142 143 spin_lock_irqsave(&ps->genpd.slock, flags); 144 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); 148 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); 151 152 spin_unlock_irqrestore(&ps->genpd.slock, flags); 153 154 return 0; 155 } 156 157 static int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) 158 { 159 int ret; 160 161 ret = apple_pmgr_reset_assert(rcdev, id); 162 if (ret) 163 return ret; 164 165 usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME); 166 167 return apple_pmgr_reset_deassert(rcdev, id); 168 } 169 170 static int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id) 171 { 172 struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 173 u32 reg = 0; 174 175 regmap_read(ps->regmap, ps->offset, ®); 176 177 return !!(reg & APPLE_PMGR_RESET); 178 } 179 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, 185 }; 186 187 static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev, 188 const struct of_phandle_args *reset_spec) 189 { 190 return 0; 191 } 192 193 static int apple_pmgr_ps_probe(struct platform_device *pdev) 194 { 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; 200 int ret; 201 const char *name; 202 bool active; 203 204 regmap = syscon_node_to_regmap(node->parent); 205 if (IS_ERR(regmap)) 206 return PTR_ERR(regmap); 207 208 ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL); 209 if (!ps) 210 return -ENOMEM; 211 212 ps->dev = dev; 213 ps->regmap = regmap; 214 215 ret = of_property_read_string(node, "label", &name); 216 if (ret < 0) { 217 dev_err(dev, "missing label property\n"); 218 return ret; 219 } 220 221 ret = of_property_read_u32(node, "reg", &ps->offset); 222 if (ret < 0) { 223 dev_err(dev, "missing reg property\n"); 224 return ret; 225 } 226 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; 231 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)); 236 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; 240 if (!active) { 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; 244 } 245 } 246 247 /* Turn on auto-PM if the domain is already on */ 248 if (active) 249 regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE, 250 APPLE_PMGR_AUTO_ENABLE); 251 252 ret = pm_genpd_init(&ps->genpd, NULL, !active); 253 if (ret < 0) { 254 dev_err(dev, "pm_genpd_init failed\n"); 255 return ret; 256 } 257 258 ret = of_genpd_add_provider_simple(node, &ps->genpd); 259 if (ret < 0) { 260 dev_err(dev, "of_genpd_add_provider_simple failed\n"); 261 return ret; 262 } 263 264 of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) { 265 struct of_phandle_args parent, child; 266 267 parent.np = it.node; 268 parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS); 269 child.np = node; 270 child.args_count = 0; 271 ret = of_genpd_add_subdomain(&parent, &child); 272 273 if (ret == -EPROBE_DEFER) { 274 of_node_put(parent.np); 275 goto err_remove; 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); 280 goto err_remove; 281 } 282 } 283 284 /* 285 * Do not participate in regular PM; parent power domains are handled via the 286 * genpd hierarchy. 287 */ 288 pm_genpd_remove_device(dev); 289 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; 296 297 ret = devm_reset_controller_register(dev, &ps->rcdev); 298 if (ret < 0) 299 goto err_remove; 300 301 return 0; 302 err_remove: 303 of_genpd_del_provider(node); 304 pm_genpd_remove(&ps->genpd); 305 return ret; 306 } 307 308 static const struct of_device_id apple_pmgr_ps_of_match[] = { 309 { .compatible = "apple,pmgr-pwrstate" }, 310 {} 311 }; 312 313 MODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match); 314 315 static struct platform_driver apple_pmgr_ps_driver = { 316 .probe = apple_pmgr_ps_probe, 317 .driver = { 318 .name = "apple-pmgr-pwrstate", 319 .of_match_table = apple_pmgr_ps_of_match, 320 }, 321 }; 322 323 MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 324 MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs"); 325 326 module_platform_driver(apple_pmgr_ps_driver); 327