From: Stefan Raufhake <s.raufhake@xxxxxxxxxxx> Some GPIO-controlled power supplies can be turned off (charging disabled). Support changing the charging state by setting charge_type to POWER_SUPPLY_CHARGE_TYPE_STANDARD and disabling charging by setting charge_type to POWER_SUPPLY_CHARGE_TYPE_NONE. One potential use case for this is disabling battery backup on a UPS. Signed-off-by: Stefan Raufhake <s.raufhake@xxxxxxxxxxx> --- .../bindings/power/supply/gpio-charger.yaml | 6 +++ drivers/power/supply/gpio-charger.c | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml index 89f8e2bcb2d7..084520bfc040 100644 --- a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml @@ -44,6 +44,10 @@ properties: maxItems: 32 description: GPIOs used for current limiting + enable-gpios: + maxItems: 1 + description: GPIO is used to enable/disable the charger + charge-current-limit-mapping: description: List of tuples with current in uA and a GPIO bitmap (in this order). The tuples must be provided in descending order of the @@ -68,6 +72,8 @@ anyOf: - charge-status-gpios - required: - charge-current-limit-gpios + - required: + - enable-gpios dependencies: charge-current-limit-gpios: [ charge-current-limit-mapping ] diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c index 68212b39785b..461fec34904d 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -32,6 +32,7 @@ struct gpio_charger { struct power_supply_desc charger_desc; struct gpio_desc *gpiod; struct gpio_desc *charge_status; + struct gpio_desc *charge_type; struct gpio_descs *current_limit_gpios; struct gpio_mapping *current_limit_map; @@ -82,6 +83,26 @@ static int set_charge_current_limit(struct gpio_charger *gpio_charger, int val) return 0; } +static int gpio_charger_set_charge_type(struct gpio_desc *gpio_charger, int type) +{ + int chg_config = 0; + + switch (type) { + case POWER_SUPPLY_CHARGE_TYPE_STANDARD: + chg_config = 1; + break; + case POWER_SUPPLY_CHARGE_TYPE_NONE: + chg_config = 0; + break; + default: + return -EINVAL; + } + + gpiod_set_value_cansleep(gpio_charger, chg_config); + + return 0; +} + static int gpio_charger_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val) { @@ -100,6 +121,13 @@ static int gpio_charger_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: val->intval = gpio_charger->charge_current_limit; break; + case POWER_SUPPLY_PROP_CHARGE_TYPE: + if (gpiod_get_value_cansleep(gpio_charger->charge_type)) + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; + else + val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE; + break; + default: return -EINVAL; } @@ -115,6 +143,9 @@ static int gpio_charger_set_property(struct power_supply *psy, switch (psp) { case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: return set_charge_current_limit(gpio_charger, val->intval); + case POWER_SUPPLY_PROP_CHARGE_TYPE: + return gpio_charger_set_charge_type(gpio_charger->charge_type, val->intval); + break; default: return -EINVAL; } @@ -126,6 +157,7 @@ static int gpio_charger_property_is_writeable(struct power_supply *psy, enum power_supply_property psp) { switch (psp) { + case POWER_SUPPLY_PROP_CHARGE_TYPE: case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX: return 1; default: @@ -246,6 +278,7 @@ static enum power_supply_property gpio_charger_properties[] = { POWER_SUPPLY_PROP_ONLINE, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX, + POWER_SUPPLY_PROP_CHARGE_TYPE, }; static int gpio_charger_probe(struct platform_device *pdev) @@ -256,6 +289,7 @@ static int gpio_charger_probe(struct platform_device *pdev) struct gpio_charger *gpio_charger; struct power_supply_desc *charger_desc; struct gpio_desc *charge_status; + struct gpio_desc *charge_type; int charge_status_irq; int ret; int num_props = 0; @@ -304,6 +338,15 @@ static int gpio_charger_probe(struct platform_device *pdev) num_props++; } + charge_type = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH); + if (IS_ERR(charge_type)) + return PTR_ERR(charge_type); + if (charge_type) { + gpio_charger->charge_type = charge_type; + gpio_charger_properties[num_props] = POWER_SUPPLY_PROP_CHARGE_TYPE; + num_props++; + } + charger_desc = &gpio_charger->charger_desc; charger_desc->properties = gpio_charger_properties; charger_desc->num_properties = num_props; -- 2.25.1