:p
atchew
Login
From: Stefan Raufhake <s.raufhake@beckhoff.com> Hello, We have a device with a simple built-in UPS, which is controlled by GPIOs. For the control of the UPS, we used the “gpio-charger” driver module from the power-supply. For our usecase we want to support enabing and disabling the ups. When the UPS is disabled, the device turns off immediately if the supply power is switched off. When the UPS is enabled, the device has power as long as the UPS has enough energy for the device. Now, we are looking for the best way to implement this function. This patch contains our first proposal. Stefan Raufhake (1): power: supply: gpio-charger: Support to disable charger .../bindings/power/supply/gpio-charger.yaml | 6 +++ drivers/power/supply/gpio-charger.c | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) -- 2.25.1
From: Stefan Raufhake <s.raufhake@beckhoff.de> We want to disable the built-in UPS in our device so that we can switch off the supply power of the device with and without the support of the UPS. This commit will allow us to disable the ups by using the command echo 1 > /sys/class/power_supply/xxx/charge_type (1 = POWER_SUPPLY_CHARGE_TYPE_NONE) and enable the charger by setting it to 4 (POWER_SUPPLY_CHARGE_TYPE_STANDARD). Signed-off-by: Stefan Raufhake <s.raufhake@beckhoff.de> --- .../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 XXXXXXX..XXXXXXX 100644 --- a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml @@ -XXX,XX +XXX,XX @@ properties: maxItems: 32 description: GPIOs used for current limiting + charge-disable-gpios: + maxItems: 1 + description: GPIO to 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 @@ -XXX,XX +XXX,XX @@ anyOf: - charge-status-gpios - required: - charge-current-limit-gpios + - required: + - charge-type-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 XXXXXXX..XXXXXXX 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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 = 0; + break; + case POWER_SUPPLY_CHARGE_TYPE_NONE: + chg_config = 1; + 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) { @@ -XXX,XX +XXX,XX @@ 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_NONE; + else + val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD; + break; + default: return -EINVAL; } @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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: @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ static int gpio_charger_probe(struct platform_device *pdev) num_props++; } + charge_type = devm_gpiod_get_optional(dev, "charge-disable", GPIOD_OUT_LOW); + 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
From: Stefan Raufhake <s.raufhake@beckhoff.de> Hello, We have a device with a simple built-in UPS, which is controlled by GPIOs. For the control of the UPS, we used the “gpio-charger” driver module from the power-supply. For our usecase we want to support enabing and disabling the ups. When the UPS is disabled, the device turns off immediately if the supply power is switched off. When the UPS is enabled, the device has power as long as the UPS has enough energy for the device. Now, we are looking for the best way to implement this function. This patch contains our first proposal. Changes since v1: ================= - Rework of the commit message - Changed the property name from "charge-disable-gpios" to "enable-gpios". - Inverted the logic of charge_type to 0 = disable and 1 = enable for the charger. Stefan Raufhake (1): power: supply: gpio-charger: Support to disable charger .../bindings/power/supply/gpio-charger.yaml | 6 +++ drivers/power/supply/gpio-charger.c | 43 +++++++++++++++++++ 2 files changed, 49 insertions(+) -- 2.25.1
From: Stefan Raufhake <s.raufhake@beckhoff.de> 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@beckhoff.de> --- .../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 XXXXXXX..XXXXXXX 100644 --- a/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml +++ b/Documentation/devicetree/bindings/power/supply/gpio-charger.yaml @@ -XXX,XX +XXX,XX @@ 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 @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX 100644 --- a/drivers/power/supply/gpio-charger.c +++ b/drivers/power/supply/gpio-charger.c @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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) { @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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; } @@ -XXX,XX +XXX,XX @@ 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: @@ -XXX,XX +XXX,XX @@ 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) @@ -XXX,XX +XXX,XX @@ 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; @@ -XXX,XX +XXX,XX @@ 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