1*e2ad626fSUlf Hansson // SPDX-License-Identifier: GPL-2.0-only OR MIT 2*e2ad626fSUlf Hansson /* 3*e2ad626fSUlf Hansson * Apple SoC PMGR device power state driver 4*e2ad626fSUlf Hansson * 5*e2ad626fSUlf Hansson * Copyright The Asahi Linux Contributors 6*e2ad626fSUlf Hansson */ 7*e2ad626fSUlf Hansson 8*e2ad626fSUlf Hansson #include <linux/bitops.h> 9*e2ad626fSUlf Hansson #include <linux/bitfield.h> 10*e2ad626fSUlf Hansson #include <linux/err.h> 11*e2ad626fSUlf Hansson #include <linux/of.h> 12*e2ad626fSUlf Hansson #include <linux/of_address.h> 13*e2ad626fSUlf Hansson #include <linux/platform_device.h> 14*e2ad626fSUlf Hansson #include <linux/pm_domain.h> 15*e2ad626fSUlf Hansson #include <linux/regmap.h> 16*e2ad626fSUlf Hansson #include <linux/mfd/syscon.h> 17*e2ad626fSUlf Hansson #include <linux/reset-controller.h> 18*e2ad626fSUlf Hansson #include <linux/module.h> 19*e2ad626fSUlf Hansson 20*e2ad626fSUlf Hansson #define APPLE_PMGR_RESET BIT(31) 21*e2ad626fSUlf Hansson #define APPLE_PMGR_AUTO_ENABLE BIT(28) 22*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_AUTO GENMASK(27, 24) 23*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_MIN GENMASK(19, 16) 24*e2ad626fSUlf Hansson #define APPLE_PMGR_PARENT_OFF BIT(11) 25*e2ad626fSUlf Hansson #define APPLE_PMGR_DEV_DISABLE BIT(10) 26*e2ad626fSUlf Hansson #define APPLE_PMGR_WAS_CLKGATED BIT(9) 27*e2ad626fSUlf Hansson #define APPLE_PMGR_WAS_PWRGATED BIT(8) 28*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_ACTUAL GENMASK(7, 4) 29*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_TARGET GENMASK(3, 0) 30*e2ad626fSUlf Hansson 31*e2ad626fSUlf Hansson #define APPLE_PMGR_FLAGS (APPLE_PMGR_WAS_CLKGATED | APPLE_PMGR_WAS_PWRGATED) 32*e2ad626fSUlf Hansson 33*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_ACTIVE 0xf 34*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_CLKGATE 0x4 35*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_PWRGATE 0x0 36*e2ad626fSUlf Hansson 37*e2ad626fSUlf Hansson #define APPLE_PMGR_PS_SET_TIMEOUT 100 38*e2ad626fSUlf Hansson #define APPLE_PMGR_RESET_TIME 1 39*e2ad626fSUlf Hansson 40*e2ad626fSUlf Hansson struct apple_pmgr_ps { 41*e2ad626fSUlf Hansson struct device *dev; 42*e2ad626fSUlf Hansson struct generic_pm_domain genpd; 43*e2ad626fSUlf Hansson struct reset_controller_dev rcdev; 44*e2ad626fSUlf Hansson struct regmap *regmap; 45*e2ad626fSUlf Hansson u32 offset; 46*e2ad626fSUlf Hansson u32 min_state; 47*e2ad626fSUlf Hansson }; 48*e2ad626fSUlf Hansson 49*e2ad626fSUlf Hansson #define genpd_to_apple_pmgr_ps(_genpd) container_of(_genpd, struct apple_pmgr_ps, genpd) 50*e2ad626fSUlf Hansson #define rcdev_to_apple_pmgr_ps(_rcdev) container_of(_rcdev, struct apple_pmgr_ps, rcdev) 51*e2ad626fSUlf Hansson 52*e2ad626fSUlf Hansson static int apple_pmgr_ps_set(struct generic_pm_domain *genpd, u32 pstate, bool auto_enable) 53*e2ad626fSUlf Hansson { 54*e2ad626fSUlf Hansson int ret; 55*e2ad626fSUlf Hansson struct apple_pmgr_ps *ps = genpd_to_apple_pmgr_ps(genpd); 56*e2ad626fSUlf Hansson u32 reg; 57*e2ad626fSUlf Hansson 58*e2ad626fSUlf Hansson ret = regmap_read(ps->regmap, ps->offset, ®); 59*e2ad626fSUlf Hansson if (ret < 0) 60*e2ad626fSUlf Hansson return ret; 61*e2ad626fSUlf Hansson 62*e2ad626fSUlf Hansson /* Resets are synchronous, and only work if the device is powered and clocked. */ 63*e2ad626fSUlf Hansson if (reg & APPLE_PMGR_RESET && pstate != APPLE_PMGR_PS_ACTIVE) 64*e2ad626fSUlf Hansson dev_err(ps->dev, "PS %s: powering off with RESET active\n", 65*e2ad626fSUlf Hansson genpd->name); 66*e2ad626fSUlf Hansson 67*e2ad626fSUlf Hansson reg &= ~(APPLE_PMGR_AUTO_ENABLE | APPLE_PMGR_FLAGS | APPLE_PMGR_PS_TARGET); 68*e2ad626fSUlf Hansson reg |= FIELD_PREP(APPLE_PMGR_PS_TARGET, pstate); 69*e2ad626fSUlf Hansson 70*e2ad626fSUlf Hansson dev_dbg(ps->dev, "PS %s: pwrstate = 0x%x: 0x%x\n", genpd->name, pstate, reg); 71*e2ad626fSUlf Hansson 72*e2ad626fSUlf Hansson regmap_write(ps->regmap, ps->offset, reg); 73*e2ad626fSUlf Hansson 74*e2ad626fSUlf Hansson ret = regmap_read_poll_timeout_atomic( 75*e2ad626fSUlf Hansson ps->regmap, ps->offset, reg, 76*e2ad626fSUlf Hansson (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == pstate), 1, 77*e2ad626fSUlf Hansson APPLE_PMGR_PS_SET_TIMEOUT); 78*e2ad626fSUlf Hansson if (ret < 0) 79*e2ad626fSUlf Hansson dev_err(ps->dev, "PS %s: Failed to reach power state 0x%x (now: 0x%x)\n", 80*e2ad626fSUlf Hansson genpd->name, pstate, reg); 81*e2ad626fSUlf Hansson 82*e2ad626fSUlf Hansson if (auto_enable) { 83*e2ad626fSUlf Hansson /* Not all devices implement this; this is a no-op where not implemented. */ 84*e2ad626fSUlf Hansson reg &= ~APPLE_PMGR_FLAGS; 85*e2ad626fSUlf Hansson reg |= APPLE_PMGR_AUTO_ENABLE; 86*e2ad626fSUlf Hansson regmap_write(ps->regmap, ps->offset, reg); 87*e2ad626fSUlf Hansson } 88*e2ad626fSUlf Hansson 89*e2ad626fSUlf Hansson return ret; 90*e2ad626fSUlf Hansson } 91*e2ad626fSUlf Hansson 92*e2ad626fSUlf Hansson static bool apple_pmgr_ps_is_active(struct apple_pmgr_ps *ps) 93*e2ad626fSUlf Hansson { 94*e2ad626fSUlf Hansson u32 reg = 0; 95*e2ad626fSUlf Hansson 96*e2ad626fSUlf Hansson regmap_read(ps->regmap, ps->offset, ®); 97*e2ad626fSUlf Hansson /* 98*e2ad626fSUlf Hansson * We consider domains as active if they are actually on, or if they have auto-PM 99*e2ad626fSUlf Hansson * enabled and the intended target is on. 100*e2ad626fSUlf Hansson */ 101*e2ad626fSUlf Hansson return (FIELD_GET(APPLE_PMGR_PS_ACTUAL, reg) == APPLE_PMGR_PS_ACTIVE || 102*e2ad626fSUlf Hansson (FIELD_GET(APPLE_PMGR_PS_TARGET, reg) == APPLE_PMGR_PS_ACTIVE && 103*e2ad626fSUlf Hansson reg & APPLE_PMGR_AUTO_ENABLE)); 104*e2ad626fSUlf Hansson } 105*e2ad626fSUlf Hansson 106*e2ad626fSUlf Hansson static int apple_pmgr_ps_power_on(struct generic_pm_domain *genpd) 107*e2ad626fSUlf Hansson { 108*e2ad626fSUlf Hansson return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_ACTIVE, true); 109*e2ad626fSUlf Hansson } 110*e2ad626fSUlf Hansson 111*e2ad626fSUlf Hansson static int apple_pmgr_ps_power_off(struct generic_pm_domain *genpd) 112*e2ad626fSUlf Hansson { 113*e2ad626fSUlf Hansson return apple_pmgr_ps_set(genpd, APPLE_PMGR_PS_PWRGATE, false); 114*e2ad626fSUlf Hansson } 115*e2ad626fSUlf Hansson 116*e2ad626fSUlf Hansson static int apple_pmgr_reset_assert(struct reset_controller_dev *rcdev, unsigned long id) 117*e2ad626fSUlf Hansson { 118*e2ad626fSUlf Hansson struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 119*e2ad626fSUlf Hansson unsigned long flags; 120*e2ad626fSUlf Hansson 121*e2ad626fSUlf Hansson spin_lock_irqsave(&ps->genpd.slock, flags); 122*e2ad626fSUlf Hansson 123*e2ad626fSUlf Hansson if (ps->genpd.status == GENPD_STATE_OFF) 124*e2ad626fSUlf Hansson dev_err(ps->dev, "PS 0x%x: asserting RESET while powered down\n", ps->offset); 125*e2ad626fSUlf Hansson 126*e2ad626fSUlf Hansson dev_dbg(ps->dev, "PS 0x%x: assert reset\n", ps->offset); 127*e2ad626fSUlf Hansson /* Quiesce device before asserting reset */ 128*e2ad626fSUlf Hansson regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 129*e2ad626fSUlf Hansson APPLE_PMGR_DEV_DISABLE); 130*e2ad626fSUlf Hansson regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 131*e2ad626fSUlf Hansson APPLE_PMGR_RESET); 132*e2ad626fSUlf Hansson 133*e2ad626fSUlf Hansson spin_unlock_irqrestore(&ps->genpd.slock, flags); 134*e2ad626fSUlf Hansson 135*e2ad626fSUlf Hansson return 0; 136*e2ad626fSUlf Hansson } 137*e2ad626fSUlf Hansson 138*e2ad626fSUlf Hansson static int apple_pmgr_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) 139*e2ad626fSUlf Hansson { 140*e2ad626fSUlf Hansson struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 141*e2ad626fSUlf Hansson unsigned long flags; 142*e2ad626fSUlf Hansson 143*e2ad626fSUlf Hansson spin_lock_irqsave(&ps->genpd.slock, flags); 144*e2ad626fSUlf Hansson 145*e2ad626fSUlf Hansson dev_dbg(ps->dev, "PS 0x%x: deassert reset\n", ps->offset); 146*e2ad626fSUlf Hansson regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_RESET, 0); 147*e2ad626fSUlf Hansson regmap_update_bits(ps->regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_DEV_DISABLE, 0); 148*e2ad626fSUlf Hansson 149*e2ad626fSUlf Hansson if (ps->genpd.status == GENPD_STATE_OFF) 150*e2ad626fSUlf Hansson dev_err(ps->dev, "PS 0x%x: RESET was deasserted while powered down\n", ps->offset); 151*e2ad626fSUlf Hansson 152*e2ad626fSUlf Hansson spin_unlock_irqrestore(&ps->genpd.slock, flags); 153*e2ad626fSUlf Hansson 154*e2ad626fSUlf Hansson return 0; 155*e2ad626fSUlf Hansson } 156*e2ad626fSUlf Hansson 157*e2ad626fSUlf Hansson static int apple_pmgr_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) 158*e2ad626fSUlf Hansson { 159*e2ad626fSUlf Hansson int ret; 160*e2ad626fSUlf Hansson 161*e2ad626fSUlf Hansson ret = apple_pmgr_reset_assert(rcdev, id); 162*e2ad626fSUlf Hansson if (ret) 163*e2ad626fSUlf Hansson return ret; 164*e2ad626fSUlf Hansson 165*e2ad626fSUlf Hansson usleep_range(APPLE_PMGR_RESET_TIME, 2 * APPLE_PMGR_RESET_TIME); 166*e2ad626fSUlf Hansson 167*e2ad626fSUlf Hansson return apple_pmgr_reset_deassert(rcdev, id); 168*e2ad626fSUlf Hansson } 169*e2ad626fSUlf Hansson 170*e2ad626fSUlf Hansson static int apple_pmgr_reset_status(struct reset_controller_dev *rcdev, unsigned long id) 171*e2ad626fSUlf Hansson { 172*e2ad626fSUlf Hansson struct apple_pmgr_ps *ps = rcdev_to_apple_pmgr_ps(rcdev); 173*e2ad626fSUlf Hansson u32 reg = 0; 174*e2ad626fSUlf Hansson 175*e2ad626fSUlf Hansson regmap_read(ps->regmap, ps->offset, ®); 176*e2ad626fSUlf Hansson 177*e2ad626fSUlf Hansson return !!(reg & APPLE_PMGR_RESET); 178*e2ad626fSUlf Hansson } 179*e2ad626fSUlf Hansson 180*e2ad626fSUlf Hansson const struct reset_control_ops apple_pmgr_reset_ops = { 181*e2ad626fSUlf Hansson .assert = apple_pmgr_reset_assert, 182*e2ad626fSUlf Hansson .deassert = apple_pmgr_reset_deassert, 183*e2ad626fSUlf Hansson .reset = apple_pmgr_reset_reset, 184*e2ad626fSUlf Hansson .status = apple_pmgr_reset_status, 185*e2ad626fSUlf Hansson }; 186*e2ad626fSUlf Hansson 187*e2ad626fSUlf Hansson static int apple_pmgr_reset_xlate(struct reset_controller_dev *rcdev, 188*e2ad626fSUlf Hansson const struct of_phandle_args *reset_spec) 189*e2ad626fSUlf Hansson { 190*e2ad626fSUlf Hansson return 0; 191*e2ad626fSUlf Hansson } 192*e2ad626fSUlf Hansson 193*e2ad626fSUlf Hansson static int apple_pmgr_ps_probe(struct platform_device *pdev) 194*e2ad626fSUlf Hansson { 195*e2ad626fSUlf Hansson struct device *dev = &pdev->dev; 196*e2ad626fSUlf Hansson struct device_node *node = dev->of_node; 197*e2ad626fSUlf Hansson struct apple_pmgr_ps *ps; 198*e2ad626fSUlf Hansson struct regmap *regmap; 199*e2ad626fSUlf Hansson struct of_phandle_iterator it; 200*e2ad626fSUlf Hansson int ret; 201*e2ad626fSUlf Hansson const char *name; 202*e2ad626fSUlf Hansson bool active; 203*e2ad626fSUlf Hansson 204*e2ad626fSUlf Hansson regmap = syscon_node_to_regmap(node->parent); 205*e2ad626fSUlf Hansson if (IS_ERR(regmap)) 206*e2ad626fSUlf Hansson return PTR_ERR(regmap); 207*e2ad626fSUlf Hansson 208*e2ad626fSUlf Hansson ps = devm_kzalloc(dev, sizeof(*ps), GFP_KERNEL); 209*e2ad626fSUlf Hansson if (!ps) 210*e2ad626fSUlf Hansson return -ENOMEM; 211*e2ad626fSUlf Hansson 212*e2ad626fSUlf Hansson ps->dev = dev; 213*e2ad626fSUlf Hansson ps->regmap = regmap; 214*e2ad626fSUlf Hansson 215*e2ad626fSUlf Hansson ret = of_property_read_string(node, "label", &name); 216*e2ad626fSUlf Hansson if (ret < 0) { 217*e2ad626fSUlf Hansson dev_err(dev, "missing label property\n"); 218*e2ad626fSUlf Hansson return ret; 219*e2ad626fSUlf Hansson } 220*e2ad626fSUlf Hansson 221*e2ad626fSUlf Hansson ret = of_property_read_u32(node, "reg", &ps->offset); 222*e2ad626fSUlf Hansson if (ret < 0) { 223*e2ad626fSUlf Hansson dev_err(dev, "missing reg property\n"); 224*e2ad626fSUlf Hansson return ret; 225*e2ad626fSUlf Hansson } 226*e2ad626fSUlf Hansson 227*e2ad626fSUlf Hansson ps->genpd.flags |= GENPD_FLAG_IRQ_SAFE; 228*e2ad626fSUlf Hansson ps->genpd.name = name; 229*e2ad626fSUlf Hansson ps->genpd.power_on = apple_pmgr_ps_power_on; 230*e2ad626fSUlf Hansson ps->genpd.power_off = apple_pmgr_ps_power_off; 231*e2ad626fSUlf Hansson 232*e2ad626fSUlf Hansson ret = of_property_read_u32(node, "apple,min-state", &ps->min_state); 233*e2ad626fSUlf Hansson if (ret == 0 && ps->min_state <= APPLE_PMGR_PS_ACTIVE) 234*e2ad626fSUlf Hansson regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_PS_MIN, 235*e2ad626fSUlf Hansson FIELD_PREP(APPLE_PMGR_PS_MIN, ps->min_state)); 236*e2ad626fSUlf Hansson 237*e2ad626fSUlf Hansson active = apple_pmgr_ps_is_active(ps); 238*e2ad626fSUlf Hansson if (of_property_read_bool(node, "apple,always-on")) { 239*e2ad626fSUlf Hansson ps->genpd.flags |= GENPD_FLAG_ALWAYS_ON; 240*e2ad626fSUlf Hansson if (!active) { 241*e2ad626fSUlf Hansson dev_warn(dev, "always-on domain %s is not on at boot\n", name); 242*e2ad626fSUlf Hansson /* Turn it on so pm_genpd_init does not fail */ 243*e2ad626fSUlf Hansson active = apple_pmgr_ps_power_on(&ps->genpd) == 0; 244*e2ad626fSUlf Hansson } 245*e2ad626fSUlf Hansson } 246*e2ad626fSUlf Hansson 247*e2ad626fSUlf Hansson /* Turn on auto-PM if the domain is already on */ 248*e2ad626fSUlf Hansson if (active) 249*e2ad626fSUlf Hansson regmap_update_bits(regmap, ps->offset, APPLE_PMGR_FLAGS | APPLE_PMGR_AUTO_ENABLE, 250*e2ad626fSUlf Hansson APPLE_PMGR_AUTO_ENABLE); 251*e2ad626fSUlf Hansson 252*e2ad626fSUlf Hansson ret = pm_genpd_init(&ps->genpd, NULL, !active); 253*e2ad626fSUlf Hansson if (ret < 0) { 254*e2ad626fSUlf Hansson dev_err(dev, "pm_genpd_init failed\n"); 255*e2ad626fSUlf Hansson return ret; 256*e2ad626fSUlf Hansson } 257*e2ad626fSUlf Hansson 258*e2ad626fSUlf Hansson ret = of_genpd_add_provider_simple(node, &ps->genpd); 259*e2ad626fSUlf Hansson if (ret < 0) { 260*e2ad626fSUlf Hansson dev_err(dev, "of_genpd_add_provider_simple failed\n"); 261*e2ad626fSUlf Hansson return ret; 262*e2ad626fSUlf Hansson } 263*e2ad626fSUlf Hansson 264*e2ad626fSUlf Hansson of_for_each_phandle(&it, ret, node, "power-domains", "#power-domain-cells", -1) { 265*e2ad626fSUlf Hansson struct of_phandle_args parent, child; 266*e2ad626fSUlf Hansson 267*e2ad626fSUlf Hansson parent.np = it.node; 268*e2ad626fSUlf Hansson parent.args_count = of_phandle_iterator_args(&it, parent.args, MAX_PHANDLE_ARGS); 269*e2ad626fSUlf Hansson child.np = node; 270*e2ad626fSUlf Hansson child.args_count = 0; 271*e2ad626fSUlf Hansson ret = of_genpd_add_subdomain(&parent, &child); 272*e2ad626fSUlf Hansson 273*e2ad626fSUlf Hansson if (ret == -EPROBE_DEFER) { 274*e2ad626fSUlf Hansson of_node_put(parent.np); 275*e2ad626fSUlf Hansson goto err_remove; 276*e2ad626fSUlf Hansson } else if (ret < 0) { 277*e2ad626fSUlf Hansson dev_err(dev, "failed to add to parent domain: %d (%s -> %s)\n", 278*e2ad626fSUlf Hansson ret, it.node->name, node->name); 279*e2ad626fSUlf Hansson of_node_put(parent.np); 280*e2ad626fSUlf Hansson goto err_remove; 281*e2ad626fSUlf Hansson } 282*e2ad626fSUlf Hansson } 283*e2ad626fSUlf Hansson 284*e2ad626fSUlf Hansson /* 285*e2ad626fSUlf Hansson * Do not participate in regular PM; parent power domains are handled via the 286*e2ad626fSUlf Hansson * genpd hierarchy. 287*e2ad626fSUlf Hansson */ 288*e2ad626fSUlf Hansson pm_genpd_remove_device(dev); 289*e2ad626fSUlf Hansson 290*e2ad626fSUlf Hansson ps->rcdev.owner = THIS_MODULE; 291*e2ad626fSUlf Hansson ps->rcdev.nr_resets = 1; 292*e2ad626fSUlf Hansson ps->rcdev.ops = &apple_pmgr_reset_ops; 293*e2ad626fSUlf Hansson ps->rcdev.of_node = dev->of_node; 294*e2ad626fSUlf Hansson ps->rcdev.of_reset_n_cells = 0; 295*e2ad626fSUlf Hansson ps->rcdev.of_xlate = apple_pmgr_reset_xlate; 296*e2ad626fSUlf Hansson 297*e2ad626fSUlf Hansson ret = devm_reset_controller_register(dev, &ps->rcdev); 298*e2ad626fSUlf Hansson if (ret < 0) 299*e2ad626fSUlf Hansson goto err_remove; 300*e2ad626fSUlf Hansson 301*e2ad626fSUlf Hansson return 0; 302*e2ad626fSUlf Hansson err_remove: 303*e2ad626fSUlf Hansson of_genpd_del_provider(node); 304*e2ad626fSUlf Hansson pm_genpd_remove(&ps->genpd); 305*e2ad626fSUlf Hansson return ret; 306*e2ad626fSUlf Hansson } 307*e2ad626fSUlf Hansson 308*e2ad626fSUlf Hansson static const struct of_device_id apple_pmgr_ps_of_match[] = { 309*e2ad626fSUlf Hansson { .compatible = "apple,pmgr-pwrstate" }, 310*e2ad626fSUlf Hansson {} 311*e2ad626fSUlf Hansson }; 312*e2ad626fSUlf Hansson 313*e2ad626fSUlf Hansson MODULE_DEVICE_TABLE(of, apple_pmgr_ps_of_match); 314*e2ad626fSUlf Hansson 315*e2ad626fSUlf Hansson static struct platform_driver apple_pmgr_ps_driver = { 316*e2ad626fSUlf Hansson .probe = apple_pmgr_ps_probe, 317*e2ad626fSUlf Hansson .driver = { 318*e2ad626fSUlf Hansson .name = "apple-pmgr-pwrstate", 319*e2ad626fSUlf Hansson .of_match_table = apple_pmgr_ps_of_match, 320*e2ad626fSUlf Hansson }, 321*e2ad626fSUlf Hansson }; 322*e2ad626fSUlf Hansson 323*e2ad626fSUlf Hansson MODULE_AUTHOR("Hector Martin <marcan@marcan.st>"); 324*e2ad626fSUlf Hansson MODULE_DESCRIPTION("PMGR power state driver for Apple SoCs"); 325*e2ad626fSUlf Hansson 326*e2ad626fSUlf Hansson module_platform_driver(apple_pmgr_ps_driver); 327