Lines Matching +full:power +full:- +full:supply
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AXP20X and AXP22X PMICs' ACIN power supply driver
6 * Quentin Schulz <quentin.schulz@free-electrons.com>
31 #define AXP813_VHOLD_UV_TO_BIT(x) ((((x) / 100000) - 40) << 3)
36 #define AXP813_CURR_LIMIT_UA_TO_BIT(x) (((x) / 500000) - 3)
40 #define DRVNAME "axp20x-ac-power-supply"
44 struct power_supply *supply; member
54 struct axp20x_ac_power *power = devid; in axp20x_ac_power_irq() local
56 power_supply_changed(power->supply); in axp20x_ac_power_irq()
65 struct axp20x_ac_power *power = power_supply_get_drvdata(psy); in axp20x_ac_power_get_property() local
70 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, ®); in axp20x_ac_power_get_property()
75 val->intval = POWER_SUPPLY_HEALTH_GOOD; in axp20x_ac_power_get_property()
79 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; in axp20x_ac_power_get_property()
83 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, ®); in axp20x_ac_power_get_property()
87 val->intval = !!(reg & AXP20X_PWR_STATUS_ACIN_PRESENT); in axp20x_ac_power_get_property()
91 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, ®); in axp20x_ac_power_get_property()
95 val->intval = !!(reg & AXP20X_PWR_STATUS_ACIN_AVAIL); in axp20x_ac_power_get_property()
98 if (val->intval && power->has_acin_path_sel) { in axp20x_ac_power_get_property()
99 ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL, in axp20x_ac_power_get_property()
104 val->intval = !!(reg & AXP813_ACIN_PATH_SEL); in axp20x_ac_power_get_property()
110 ret = iio_read_channel_processed(power->acin_v, &val->intval); in axp20x_ac_power_get_property()
114 /* IIO framework gives mV but Power Supply framework gives uV */ in axp20x_ac_power_get_property()
115 val->intval *= 1000; in axp20x_ac_power_get_property()
120 ret = iio_read_channel_processed(power->acin_i, &val->intval); in axp20x_ac_power_get_property()
124 /* IIO framework gives mA but Power Supply framework gives uA */ in axp20x_ac_power_get_property()
125 val->intval *= 1000; in axp20x_ac_power_get_property()
130 ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL, ®); in axp20x_ac_power_get_property()
134 val->intval = AXP813_VHOLD_REG_TO_UV(reg); in axp20x_ac_power_get_property()
139 ret = regmap_read(power->regmap, AXP813_ACIN_PATH_CTRL, ®); in axp20x_ac_power_get_property()
143 val->intval = AXP813_CURR_LIMIT_REG_TO_UA(reg); in axp20x_ac_power_get_property()
145 if (val->intval > 4000000) in axp20x_ac_power_get_property()
146 val->intval = 4000000; in axp20x_ac_power_get_property()
151 return -EINVAL; in axp20x_ac_power_get_property()
154 return -EINVAL; in axp20x_ac_power_get_property()
161 struct axp20x_ac_power *power = power_supply_get_drvdata(psy); in axp813_ac_power_set_property() local
165 return regmap_update_bits(power->regmap, AXP813_ACIN_PATH_CTRL, in axp813_ac_power_set_property()
167 AXP813_ACIN_PATH_SEL_TO_BIT(val->intval)); in axp813_ac_power_set_property()
170 if (val->intval < 4000000 || val->intval > 4700000) in axp813_ac_power_set_property()
171 return -EINVAL; in axp813_ac_power_set_property()
173 return regmap_update_bits(power->regmap, AXP813_ACIN_PATH_CTRL, in axp813_ac_power_set_property()
175 AXP813_VHOLD_UV_TO_BIT(val->intval)); in axp813_ac_power_set_property()
178 if (val->intval < 1500000 || val->intval > 4000000) in axp813_ac_power_set_property()
179 return -EINVAL; in axp813_ac_power_set_property()
181 return regmap_update_bits(power->regmap, AXP813_ACIN_PATH_CTRL, in axp813_ac_power_set_property()
183 AXP813_CURR_LIMIT_UA_TO_BIT(val->intval)); in axp813_ac_power_set_property()
186 return -EINVAL; in axp813_ac_power_set_property()
189 return -EINVAL; in axp813_ac_power_set_property()
223 .name = "axp20x-ac",
231 .name = "axp22x-ac",
239 .name = "axp813-ac",
288 struct axp20x_ac_power *power = dev_get_drvdata(dev); in axp20x_ac_power_suspend() local
297 if (device_may_wakeup(&power->supply->dev)) in axp20x_ac_power_suspend()
298 enable_irq_wake(power->irqs[i++]); in axp20x_ac_power_suspend()
299 while (i < power->num_irqs) in axp20x_ac_power_suspend()
300 disable_irq(power->irqs[i++]); in axp20x_ac_power_suspend()
307 struct axp20x_ac_power *power = dev_get_drvdata(dev); in axp20x_ac_power_resume() local
310 if (device_may_wakeup(&power->supply->dev)) in axp20x_ac_power_resume()
311 disable_irq_wake(power->irqs[i++]); in axp20x_ac_power_resume()
312 while (i < power->num_irqs) in axp20x_ac_power_resume()
313 enable_irq(power->irqs[i++]); in axp20x_ac_power_resume()
324 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); in axp20x_ac_power_probe()
326 struct axp20x_ac_power *power; in axp20x_ac_power_probe() local
330 if (!of_device_is_available(pdev->dev.of_node)) in axp20x_ac_power_probe()
331 return -ENODEV; in axp20x_ac_power_probe()
334 dev_err(&pdev->dev, "Parent drvdata not set\n"); in axp20x_ac_power_probe()
335 return -EINVAL; in axp20x_ac_power_probe()
338 axp_data = of_device_get_match_data(&pdev->dev); in axp20x_ac_power_probe()
340 power = devm_kzalloc(&pdev->dev, in axp20x_ac_power_probe()
341 struct_size(power, irqs, axp_data->num_irq_names), in axp20x_ac_power_probe()
343 if (!power) in axp20x_ac_power_probe()
344 return -ENOMEM; in axp20x_ac_power_probe()
346 if (axp_data->acin_adc) { in axp20x_ac_power_probe()
347 power->acin_v = devm_iio_channel_get(&pdev->dev, "acin_v"); in axp20x_ac_power_probe()
348 if (IS_ERR(power->acin_v)) { in axp20x_ac_power_probe()
349 if (PTR_ERR(power->acin_v) == -ENODEV) in axp20x_ac_power_probe()
350 return -EPROBE_DEFER; in axp20x_ac_power_probe()
351 return PTR_ERR(power->acin_v); in axp20x_ac_power_probe()
354 power->acin_i = devm_iio_channel_get(&pdev->dev, "acin_i"); in axp20x_ac_power_probe()
355 if (IS_ERR(power->acin_i)) { in axp20x_ac_power_probe()
356 if (PTR_ERR(power->acin_i) == -ENODEV) in axp20x_ac_power_probe()
357 return -EPROBE_DEFER; in axp20x_ac_power_probe()
358 return PTR_ERR(power->acin_i); in axp20x_ac_power_probe()
362 power->regmap = dev_get_regmap(pdev->dev.parent, NULL); in axp20x_ac_power_probe()
363 power->has_acin_path_sel = axp_data->acin_path_sel; in axp20x_ac_power_probe()
364 power->num_irqs = axp_data->num_irq_names; in axp20x_ac_power_probe()
366 platform_set_drvdata(pdev, power); in axp20x_ac_power_probe()
368 psy_cfg.of_node = pdev->dev.of_node; in axp20x_ac_power_probe()
369 psy_cfg.drv_data = power; in axp20x_ac_power_probe()
371 power->supply = devm_power_supply_register(&pdev->dev, in axp20x_ac_power_probe()
372 axp_data->power_desc, in axp20x_ac_power_probe()
374 if (IS_ERR(power->supply)) in axp20x_ac_power_probe()
375 return PTR_ERR(power->supply); in axp20x_ac_power_probe()
378 for (i = 0; i < axp_data->num_irq_names; i++) { in axp20x_ac_power_probe()
379 irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]); in axp20x_ac_power_probe()
383 power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq); in axp20x_ac_power_probe()
384 ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i], in axp20x_ac_power_probe()
386 DRVNAME, power); in axp20x_ac_power_probe()
388 dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n", in axp20x_ac_power_probe()
389 axp_data->irq_names[i], ret); in axp20x_ac_power_probe()
399 .compatible = "x-powers,axp202-ac-power-supply",
402 .compatible = "x-powers,axp221-ac-power-supply",
405 .compatible = "x-powers,axp813-ac-power-supply",
422 MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
423 MODULE_DESCRIPTION("AXP20X and AXP22X PMICs' AC power supply driver");