Lines Matching +full:power +full:- +full:supply

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * AXP20x PMIC USB power supply status driver
6 * Copyright (C) 2014 Bruno Prémont <bonbons@linux-vserver.org>
11 #include <linux/devm-helpers.h>
27 #define DRVNAME "axp20x-usb-power-supply"
66 struct power_supply *supply; member
77 static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power) in axp20x_usb_vbus_needs_polling() argument
81 * present->absent transition implies an online->offline transition in axp20x_usb_vbus_needs_polling()
84 if (power->axp20x_id >= AXP221_ID && !power->online) in axp20x_usb_vbus_needs_polling()
92 struct axp20x_usb_power *power = devid; in axp20x_usb_power_irq() local
94 power_supply_changed(power->supply); in axp20x_usb_power_irq()
96 mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); in axp20x_usb_power_irq()
103 struct axp20x_usb_power *power = in axp20x_usb_power_poll_vbus() local
108 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val); in axp20x_usb_power_poll_vbus()
113 if (val != power->old_status) in axp20x_usb_power_poll_vbus()
114 power_supply_changed(power->supply); in axp20x_usb_power_poll_vbus()
116 power->old_status = val; in axp20x_usb_power_poll_vbus()
117 power->online = val & AXP20X_PWR_STATUS_VBUS_USED; in axp20x_usb_power_poll_vbus()
120 if (axp20x_usb_vbus_needs_polling(power)) in axp20x_usb_power_poll_vbus()
121 mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); in axp20x_usb_power_poll_vbus()
124 static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val) in axp20x_get_current_max() argument
127 int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp20x_get_current_max()
134 if (power->axp20x_id == AXP221_ID) in axp20x_get_current_max()
135 *val = -1; /* No 100mA limit */ in axp20x_get_current_max()
146 *val = -1; in axp20x_get_current_max()
153 static int axp813_get_current_max(struct axp20x_usb_power *power, int *val) in axp813_get_current_max() argument
156 int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp813_get_current_max()
181 struct axp20x_usb_power *power = power_supply_get_drvdata(psy); in axp20x_usb_power_get_property() local
187 ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp20x_usb_power_get_property()
191 val->intval = AXP20X_VBUS_VHOLD_uV(v); in axp20x_usb_power_get_property()
195 ret = iio_read_channel_processed(power->vbus_v, in axp20x_usb_power_get_property()
196 &val->intval); in axp20x_usb_power_get_property()
201 * IIO framework gives mV but Power Supply framework in axp20x_usb_power_get_property()
204 val->intval *= 1000; in axp20x_usb_power_get_property()
208 ret = axp20x_read_variable_width(power->regmap, in axp20x_usb_power_get_property()
213 val->intval = ret * 1700; /* 1 step = 1.7 mV */ in axp20x_usb_power_get_property()
216 if (power->axp20x_id == AXP813_ID) in axp20x_usb_power_get_property()
217 return axp813_get_current_max(power, &val->intval); in axp20x_usb_power_get_property()
218 return axp20x_get_current_max(power, &val->intval); in axp20x_usb_power_get_property()
221 ret = iio_read_channel_processed(power->vbus_i, in axp20x_usb_power_get_property()
222 &val->intval); in axp20x_usb_power_get_property()
227 * IIO framework gives mA but Power Supply framework in axp20x_usb_power_get_property()
230 val->intval *= 1000; in axp20x_usb_power_get_property()
234 ret = axp20x_read_variable_width(power->regmap, in axp20x_usb_power_get_property()
239 val->intval = ret * 375; /* 1 step = 0.375 mA */ in axp20x_usb_power_get_property()
245 /* All the properties below need the input-status reg value */ in axp20x_usb_power_get_property()
246 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input); in axp20x_usb_power_get_property()
253 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; in axp20x_usb_power_get_property()
257 val->intval = POWER_SUPPLY_HEALTH_GOOD; in axp20x_usb_power_get_property()
259 if (power->axp20x_id == AXP202_ID) { in axp20x_usb_power_get_property()
260 ret = regmap_read(power->regmap, in axp20x_usb_power_get_property()
266 val->intval = in axp20x_usb_power_get_property()
271 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT); in axp20x_usb_power_get_property()
274 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED); in axp20x_usb_power_get_property()
277 return -EINVAL; in axp20x_usb_power_get_property()
283 static int axp813_usb_power_set_online(struct axp20x_usb_power *power, in axp813_usb_power_set_online() argument
288 return regmap_update_bits(power->regmap, in axp813_usb_power_set_online()
293 static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power, in axp20x_usb_power_set_voltage_min() argument
307 val = (intval - 4000000) / 100000; in axp20x_usb_power_set_voltage_min()
308 return regmap_update_bits(power->regmap, in axp20x_usb_power_set_voltage_min()
313 return -EINVAL; in axp20x_usb_power_set_voltage_min()
316 return -EINVAL; in axp20x_usb_power_set_voltage_min()
319 static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power, in axp813_usb_power_set_current_max() argument
326 return regmap_update_bits(power->regmap, in axp813_usb_power_set_current_max()
333 val = (intval - 1000000) / 500000; in axp813_usb_power_set_current_max()
334 return regmap_update_bits(power->regmap, in axp813_usb_power_set_current_max()
338 return -EINVAL; in axp813_usb_power_set_current_max()
341 return -EINVAL; in axp813_usb_power_set_current_max()
344 static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, in axp20x_usb_power_set_current_max() argument
351 if (power->axp20x_id == AXP221_ID) in axp20x_usb_power_set_current_max()
352 return -EINVAL; in axp20x_usb_power_set_current_max()
356 val = (900000 - intval) / 400000; in axp20x_usb_power_set_current_max()
357 return regmap_update_bits(power->regmap, in axp20x_usb_power_set_current_max()
361 return -EINVAL; in axp20x_usb_power_set_current_max()
364 return -EINVAL; in axp20x_usb_power_set_current_max()
371 struct axp20x_usb_power *power = power_supply_get_drvdata(psy); in axp20x_usb_power_set_property() local
375 if (power->axp20x_id != AXP813_ID) in axp20x_usb_power_set_property()
376 return -EINVAL; in axp20x_usb_power_set_property()
377 return axp813_usb_power_set_online(power, val->intval); in axp20x_usb_power_set_property()
380 return axp20x_usb_power_set_voltage_min(power, val->intval); in axp20x_usb_power_set_property()
383 if (power->axp20x_id == AXP813_ID) in axp20x_usb_power_set_property()
384 return axp813_usb_power_set_current_max(power, in axp20x_usb_power_set_property()
385 val->intval); in axp20x_usb_power_set_property()
386 return axp20x_usb_power_set_current_max(power, val->intval); in axp20x_usb_power_set_property()
389 return -EINVAL; in axp20x_usb_power_set_property()
392 return -EINVAL; in axp20x_usb_power_set_property()
398 struct axp20x_usb_power *power = power_supply_get_drvdata(psy); in axp20x_usb_power_prop_writeable() local
402 * - On AXP20x and AXP22x, the flag enables VBUS (ignoring N_VBUSEN). in axp20x_usb_power_prop_writeable()
403 * - On AXP288 and AXP8xx, the flag disables VBUS (ignoring N_VBUSEN). in axp20x_usb_power_prop_writeable()
408 return power->axp20x_id == AXP813_ID; in axp20x_usb_power_prop_writeable()
433 .name = "axp20x-usb",
443 .name = "axp20x-usb",
502 struct axp20x_usb_power *power = dev_get_drvdata(dev); in axp20x_usb_power_suspend() local
511 if (device_may_wakeup(&power->supply->dev)) in axp20x_usb_power_suspend()
512 enable_irq_wake(power->irqs[i++]); in axp20x_usb_power_suspend()
513 while (i < power->num_irqs) in axp20x_usb_power_suspend()
514 disable_irq(power->irqs[i++]); in axp20x_usb_power_suspend()
521 struct axp20x_usb_power *power = dev_get_drvdata(dev); in axp20x_usb_power_resume() local
524 if (device_may_wakeup(&power->supply->dev)) in axp20x_usb_power_resume()
525 disable_irq_wake(power->irqs[i++]); in axp20x_usb_power_resume()
526 while (i < power->num_irqs) in axp20x_usb_power_resume()
527 enable_irq(power->irqs[i++]); in axp20x_usb_power_resume()
529 mod_delayed_work(system_power_efficient_wq, &power->vbus_detect, DEBOUNCE_TIME); in axp20x_usb_power_resume()
539 struct axp20x_usb_power *power) in configure_iio_channels() argument
541 power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v"); in configure_iio_channels()
542 if (IS_ERR(power->vbus_v)) { in configure_iio_channels()
543 if (PTR_ERR(power->vbus_v) == -ENODEV) in configure_iio_channels()
544 return -EPROBE_DEFER; in configure_iio_channels()
545 return PTR_ERR(power->vbus_v); in configure_iio_channels()
548 power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i"); in configure_iio_channels()
549 if (IS_ERR(power->vbus_i)) { in configure_iio_channels()
550 if (PTR_ERR(power->vbus_i) == -ENODEV) in configure_iio_channels()
551 return -EPROBE_DEFER; in configure_iio_channels()
552 return PTR_ERR(power->vbus_i); in configure_iio_channels()
558 static int configure_adc_registers(struct axp20x_usb_power *power) in configure_adc_registers() argument
561 return regmap_update_bits(power->regmap, AXP20X_ADC_EN1, in configure_adc_registers()
570 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); in axp20x_usb_power_probe()
572 struct axp20x_usb_power *power; in axp20x_usb_power_probe() local
576 if (!of_device_is_available(pdev->dev.of_node)) in axp20x_usb_power_probe()
577 return -ENODEV; in axp20x_usb_power_probe()
580 dev_err(&pdev->dev, "Parent drvdata not set\n"); in axp20x_usb_power_probe()
581 return -EINVAL; in axp20x_usb_power_probe()
584 axp_data = of_device_get_match_data(&pdev->dev); in axp20x_usb_power_probe()
586 power = devm_kzalloc(&pdev->dev, in axp20x_usb_power_probe()
587 struct_size(power, irqs, axp_data->num_irq_names), in axp20x_usb_power_probe()
589 if (!power) in axp20x_usb_power_probe()
590 return -ENOMEM; in axp20x_usb_power_probe()
592 platform_set_drvdata(pdev, power); in axp20x_usb_power_probe()
594 power->axp20x_id = axp_data->axp20x_id; in axp20x_usb_power_probe()
595 power->regmap = axp20x->regmap; in axp20x_usb_power_probe()
596 power->num_irqs = axp_data->num_irq_names; in axp20x_usb_power_probe()
598 ret = devm_delayed_work_autocancel(&pdev->dev, &power->vbus_detect, in axp20x_usb_power_probe()
603 if (power->axp20x_id == AXP202_ID) { in axp20x_usb_power_probe()
605 ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, in axp20x_usb_power_probe()
612 ret = configure_iio_channels(pdev, power); in axp20x_usb_power_probe()
614 ret = configure_adc_registers(power); in axp20x_usb_power_probe()
620 if (power->axp20x_id == AXP813_ID) { in axp20x_usb_power_probe()
622 ret = regmap_update_bits(axp20x->regmap, AXP288_BC_GLOBAL, in axp20x_usb_power_probe()
628 psy_cfg.of_node = pdev->dev.of_node; in axp20x_usb_power_probe()
629 psy_cfg.drv_data = power; in axp20x_usb_power_probe()
631 power->supply = devm_power_supply_register(&pdev->dev, in axp20x_usb_power_probe()
632 axp_data->power_desc, in axp20x_usb_power_probe()
634 if (IS_ERR(power->supply)) in axp20x_usb_power_probe()
635 return PTR_ERR(power->supply); in axp20x_usb_power_probe()
638 for (i = 0; i < axp_data->num_irq_names; i++) { in axp20x_usb_power_probe()
639 irq = platform_get_irq_byname(pdev, axp_data->irq_names[i]); in axp20x_usb_power_probe()
643 power->irqs[i] = regmap_irq_get_virq(axp20x->regmap_irqc, irq); in axp20x_usb_power_probe()
644 ret = devm_request_any_context_irq(&pdev->dev, power->irqs[i], in axp20x_usb_power_probe()
646 DRVNAME, power); in axp20x_usb_power_probe()
648 dev_err(&pdev->dev, "Error requesting %s IRQ: %d\n", in axp20x_usb_power_probe()
649 axp_data->irq_names[i], ret); in axp20x_usb_power_probe()
654 if (axp20x_usb_vbus_needs_polling(power)) in axp20x_usb_power_probe()
655 queue_delayed_work(system_power_efficient_wq, &power->vbus_detect, 0); in axp20x_usb_power_probe()
662 .compatible = "x-powers,axp202-usb-power-supply",
665 .compatible = "x-powers,axp221-usb-power-supply",
668 .compatible = "x-powers,axp223-usb-power-supply",
671 .compatible = "x-powers,axp813-usb-power-supply",
689 MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");