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>
25 #define DRVNAME "axp20x-usb-power-supply"
60 struct power_supply *supply; member
70 struct axp20x_usb_power *power = devid; in axp20x_usb_power_irq() local
72 power_supply_changed(power->supply); in axp20x_usb_power_irq()
79 struct axp20x_usb_power *power = in axp20x_usb_power_poll_vbus() local
84 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &val); in axp20x_usb_power_poll_vbus()
89 if (val != power->old_status) in axp20x_usb_power_poll_vbus()
90 power_supply_changed(power->supply); in axp20x_usb_power_poll_vbus()
92 power->old_status = val; in axp20x_usb_power_poll_vbus()
95 mod_delayed_work(system_wq, &power->vbus_detect, DEBOUNCE_TIME); in axp20x_usb_power_poll_vbus()
98 static bool axp20x_usb_vbus_needs_polling(struct axp20x_usb_power *power) in axp20x_usb_vbus_needs_polling() argument
100 if (power->axp20x_id >= AXP221_ID) in axp20x_usb_vbus_needs_polling()
106 static int axp20x_get_current_max(struct axp20x_usb_power *power, int *val) in axp20x_get_current_max() argument
109 int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp20x_get_current_max()
116 if (power->axp20x_id == AXP221_ID) in axp20x_get_current_max()
117 *val = -1; /* No 100mA limit */ in axp20x_get_current_max()
128 *val = -1; in axp20x_get_current_max()
135 static int axp813_get_current_max(struct axp20x_usb_power *power, int *val) in axp813_get_current_max() argument
138 int ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp813_get_current_max()
163 struct axp20x_usb_power *power = power_supply_get_drvdata(psy); in axp20x_usb_power_get_property() local
169 ret = regmap_read(power->regmap, AXP20X_VBUS_IPSOUT_MGMT, &v); in axp20x_usb_power_get_property()
173 val->intval = AXP20X_VBUS_VHOLD_uV(v); in axp20x_usb_power_get_property()
177 ret = iio_read_channel_processed(power->vbus_v, in axp20x_usb_power_get_property()
178 &val->intval); in axp20x_usb_power_get_property()
183 * IIO framework gives mV but Power Supply framework in axp20x_usb_power_get_property()
186 val->intval *= 1000; in axp20x_usb_power_get_property()
190 ret = axp20x_read_variable_width(power->regmap, in axp20x_usb_power_get_property()
195 val->intval = ret * 1700; /* 1 step = 1.7 mV */ in axp20x_usb_power_get_property()
198 if (power->axp20x_id == AXP813_ID) in axp20x_usb_power_get_property()
199 return axp813_get_current_max(power, &val->intval); in axp20x_usb_power_get_property()
200 return axp20x_get_current_max(power, &val->intval); in axp20x_usb_power_get_property()
203 ret = iio_read_channel_processed(power->vbus_i, in axp20x_usb_power_get_property()
204 &val->intval); in axp20x_usb_power_get_property()
209 * IIO framework gives mA but Power Supply framework in axp20x_usb_power_get_property()
212 val->intval *= 1000; in axp20x_usb_power_get_property()
216 ret = axp20x_read_variable_width(power->regmap, in axp20x_usb_power_get_property()
221 val->intval = ret * 375; /* 1 step = 0.375 mA */ in axp20x_usb_power_get_property()
227 /* All the properties below need the input-status reg value */ in axp20x_usb_power_get_property()
228 ret = regmap_read(power->regmap, AXP20X_PWR_INPUT_STATUS, &input); in axp20x_usb_power_get_property()
235 val->intval = POWER_SUPPLY_HEALTH_UNKNOWN; in axp20x_usb_power_get_property()
239 val->intval = POWER_SUPPLY_HEALTH_GOOD; in axp20x_usb_power_get_property()
241 if (power->axp20x_id == AXP202_ID) { in axp20x_usb_power_get_property()
242 ret = regmap_read(power->regmap, in axp20x_usb_power_get_property()
248 val->intval = in axp20x_usb_power_get_property()
253 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_PRESENT); in axp20x_usb_power_get_property()
256 val->intval = !!(input & AXP20X_PWR_STATUS_VBUS_USED); in axp20x_usb_power_get_property()
259 return -EINVAL; in axp20x_usb_power_get_property()
265 static int axp20x_usb_power_set_voltage_min(struct axp20x_usb_power *power, in axp20x_usb_power_set_voltage_min() argument
279 val = (intval - 4000000) / 100000; in axp20x_usb_power_set_voltage_min()
280 return regmap_update_bits(power->regmap, in axp20x_usb_power_set_voltage_min()
285 return -EINVAL; in axp20x_usb_power_set_voltage_min()
288 return -EINVAL; in axp20x_usb_power_set_voltage_min()
291 static int axp813_usb_power_set_current_max(struct axp20x_usb_power *power, in axp813_usb_power_set_current_max() argument
298 return regmap_update_bits(power->regmap, in axp813_usb_power_set_current_max()
305 val = (intval - 1000000) / 500000; in axp813_usb_power_set_current_max()
306 return regmap_update_bits(power->regmap, in axp813_usb_power_set_current_max()
310 return -EINVAL; in axp813_usb_power_set_current_max()
313 return -EINVAL; in axp813_usb_power_set_current_max()
316 static int axp20x_usb_power_set_current_max(struct axp20x_usb_power *power, in axp20x_usb_power_set_current_max() argument
323 if (power->axp20x_id == AXP221_ID) in axp20x_usb_power_set_current_max()
324 return -EINVAL; in axp20x_usb_power_set_current_max()
328 val = (900000 - intval) / 400000; in axp20x_usb_power_set_current_max()
329 return regmap_update_bits(power->regmap, in axp20x_usb_power_set_current_max()
333 return -EINVAL; in axp20x_usb_power_set_current_max()
336 return -EINVAL; in axp20x_usb_power_set_current_max()
343 struct axp20x_usb_power *power = power_supply_get_drvdata(psy); in axp20x_usb_power_set_property() local
347 return axp20x_usb_power_set_voltage_min(power, val->intval); in axp20x_usb_power_set_property()
350 if (power->axp20x_id == AXP813_ID) in axp20x_usb_power_set_property()
351 return axp813_usb_power_set_current_max(power, in axp20x_usb_power_set_property()
352 val->intval); in axp20x_usb_power_set_property()
353 return axp20x_usb_power_set_current_max(power, val->intval); in axp20x_usb_power_set_property()
356 return -EINVAL; in axp20x_usb_power_set_property()
359 return -EINVAL; in axp20x_usb_power_set_property()
388 .name = "axp20x-usb",
398 .name = "axp20x-usb",
408 struct axp20x_usb_power *power) in configure_iio_channels() argument
410 power->vbus_v = devm_iio_channel_get(&pdev->dev, "vbus_v"); in configure_iio_channels()
411 if (IS_ERR(power->vbus_v)) { in configure_iio_channels()
412 if (PTR_ERR(power->vbus_v) == -ENODEV) in configure_iio_channels()
413 return -EPROBE_DEFER; in configure_iio_channels()
414 return PTR_ERR(power->vbus_v); in configure_iio_channels()
417 power->vbus_i = devm_iio_channel_get(&pdev->dev, "vbus_i"); in configure_iio_channels()
418 if (IS_ERR(power->vbus_i)) { in configure_iio_channels()
419 if (PTR_ERR(power->vbus_i) == -ENODEV) in configure_iio_channels()
420 return -EPROBE_DEFER; in configure_iio_channels()
421 return PTR_ERR(power->vbus_i); in configure_iio_channels()
427 static int configure_adc_registers(struct axp20x_usb_power *power) in configure_adc_registers() argument
430 return regmap_update_bits(power->regmap, AXP20X_ADC_EN1, in configure_adc_registers()
439 struct axp20x_dev *axp20x = dev_get_drvdata(pdev->dev.parent); in axp20x_usb_power_probe()
441 struct axp20x_usb_power *power; in axp20x_usb_power_probe() local
450 if (!of_device_is_available(pdev->dev.of_node)) in axp20x_usb_power_probe()
451 return -ENODEV; in axp20x_usb_power_probe()
454 dev_err(&pdev->dev, "Parent drvdata not set\n"); in axp20x_usb_power_probe()
455 return -EINVAL; in axp20x_usb_power_probe()
458 power = devm_kzalloc(&pdev->dev, sizeof(*power), GFP_KERNEL); in axp20x_usb_power_probe()
459 if (!power) in axp20x_usb_power_probe()
460 return -ENOMEM; in axp20x_usb_power_probe()
462 platform_set_drvdata(pdev, power); in axp20x_usb_power_probe()
463 power->axp20x_id = (enum axp20x_variants)of_device_get_match_data( in axp20x_usb_power_probe()
464 &pdev->dev); in axp20x_usb_power_probe()
466 power->np = pdev->dev.of_node; in axp20x_usb_power_probe()
467 power->regmap = axp20x->regmap; in axp20x_usb_power_probe()
469 if (power->axp20x_id == AXP202_ID) { in axp20x_usb_power_probe()
471 ret = regmap_update_bits(power->regmap, AXP20X_VBUS_MON, in axp20x_usb_power_probe()
478 ret = configure_iio_channels(pdev, power); in axp20x_usb_power_probe()
480 ret = configure_adc_registers(power); in axp20x_usb_power_probe()
487 } else if (power->axp20x_id == AXP221_ID || in axp20x_usb_power_probe()
488 power->axp20x_id == AXP223_ID || in axp20x_usb_power_probe()
489 power->axp20x_id == AXP813_ID) { in axp20x_usb_power_probe()
493 dev_err(&pdev->dev, "Unsupported AXP variant: %ld\n", in axp20x_usb_power_probe()
494 axp20x->variant); in axp20x_usb_power_probe()
495 return -EINVAL; in axp20x_usb_power_probe()
498 psy_cfg.of_node = pdev->dev.of_node; in axp20x_usb_power_probe()
499 psy_cfg.drv_data = power; in axp20x_usb_power_probe()
501 power->supply = devm_power_supply_register(&pdev->dev, usb_power_desc, in axp20x_usb_power_probe()
503 if (IS_ERR(power->supply)) in axp20x_usb_power_probe()
504 return PTR_ERR(power->supply); in axp20x_usb_power_probe()
510 dev_warn(&pdev->dev, "No IRQ for %s: %d\n", in axp20x_usb_power_probe()
514 irq = regmap_irq_get_virq(axp20x->regmap_irqc, irq); in axp20x_usb_power_probe()
515 ret = devm_request_any_context_irq(&pdev->dev, irq, in axp20x_usb_power_probe()
516 axp20x_usb_power_irq, 0, DRVNAME, power); in axp20x_usb_power_probe()
518 dev_warn(&pdev->dev, "Error requesting %s IRQ: %d\n", in axp20x_usb_power_probe()
522 INIT_DELAYED_WORK(&power->vbus_detect, axp20x_usb_power_poll_vbus); in axp20x_usb_power_probe()
523 if (axp20x_usb_vbus_needs_polling(power)) in axp20x_usb_power_probe()
524 queue_delayed_work(system_wq, &power->vbus_detect, 0); in axp20x_usb_power_probe()
531 struct axp20x_usb_power *power = platform_get_drvdata(pdev); in axp20x_usb_power_remove() local
533 cancel_delayed_work_sync(&power->vbus_detect); in axp20x_usb_power_remove()
540 .compatible = "x-powers,axp202-usb-power-supply",
543 .compatible = "x-powers,axp221-usb-power-supply",
546 .compatible = "x-powers,axp223-usb-power-supply",
549 .compatible = "x-powers,axp813-usb-power-supply",
567 MODULE_DESCRIPTION("AXP20x PMIC USB power supply status driver");