Message ID | 20170815200502.17339-9-hdegoede@redhat.com (mailing list archive) |
---|---|
State | Deferred, archived |
Headers | show |
* Hans de Goede <hdegoede@redhat.com> [170815 13:06]: > On some devices the USB Type-C port power (USB PD 2.0) negotiation is > done by a separate port-controller IC, while the current limit is > controlled through another (charger) IC. > > It has been decided to model this by modelling the external Type-C > power brick (adapter/charger) as a power-supply class device which > supplies the charger-IC, with its voltage-now and current-max representing > the negotiated voltage and max current draw. > > This commit adds a power_supply_set_input_current_limit_from_supplier > helper function which charger power-supply drivers can call to get > the max-current from their supplier and have this applied > through their set_property call-back to their input-current-limit. Hmm so can this also be used for the USB gadget subsystem to tell charge controller when it's OK to enable 500mA charging after enumeration? FYI, that's controlled by the bq24190 pin named OTG that should be only set high after enumeration. Any ideas how that is wired on your device? Does it connect to the USB PHY or to a GPIO line? Regards, Tony
Hi, On 16-08-17 17:54, Tony Lindgren wrote: > * Hans de Goede <hdegoede@redhat.com> [170815 13:06]: >> On some devices the USB Type-C port power (USB PD 2.0) negotiation is >> done by a separate port-controller IC, while the current limit is >> controlled through another (charger) IC. >> >> It has been decided to model this by modelling the external Type-C >> power brick (adapter/charger) as a power-supply class device which >> supplies the charger-IC, with its voltage-now and current-max representing >> the negotiated voltage and max current draw. >> >> This commit adds a power_supply_set_input_current_limit_from_supplier >> helper function which charger power-supply drivers can call to get >> the max-current from their supplier and have this applied >> through their set_property call-back to their input-current-limit. > > Hmm so can this also be used for the USB gadget subsystem > to tell charge controller when it's OK to enable 500mA > charging after enumeration? I'm not sure that that would be best modeled this way. Perhaps the phy-driver can directly control the gpio you have for that, that seems better then trying to solve this with cross subsystem calls which are always tricky. > FYI, that's controlled by the bq24190 pin named OTG that should > be only set high after enumeration. Any ideas how that is wired > on your device? Does it connect to the USB PHY or to a GPIO > line? I believe it is just hardwired to be logical high all the time on my board. Regards, Hans
* Hans de Goede <hdegoede@redhat.com> [170816 10:38]: > Hi, > > On 16-08-17 17:54, Tony Lindgren wrote: > > * Hans de Goede <hdegoede@redhat.com> [170815 13:06]: > > > On some devices the USB Type-C port power (USB PD 2.0) negotiation is > > > done by a separate port-controller IC, while the current limit is > > > controlled through another (charger) IC. > > > > > > It has been decided to model this by modelling the external Type-C > > > power brick (adapter/charger) as a power-supply class device which > > > supplies the charger-IC, with its voltage-now and current-max representing > > > the negotiated voltage and max current draw. > > > > > > This commit adds a power_supply_set_input_current_limit_from_supplier > > > helper function which charger power-supply drivers can call to get > > > the max-current from their supplier and have this applied > > > through their set_property call-back to their input-current-limit. > > > > Hmm so can this also be used for the USB gadget subsystem > > to tell charge controller when it's OK to enable 500mA > > charging after enumeration? > > I'm not sure that that would be best modeled this way. Perhaps > the phy-driver can directly control the gpio you have for that, > that seems better then trying to solve this with cross subsystem > calls which are always tricky. I don't think the phy driver knows either when the system has enumerated as a gadget.. > > FYI, that's controlled by the bq24190 pin named OTG that should > > be only set high after enumeration. Any ideas how that is wired > > on your device? Does it connect to the USB PHY or to a GPIO > > line? > > I believe it is just hardwired to be logical high all the time > on my board. OK thanks for checking. Tony
Hi, On Tue, Aug 15, 2017 at 10:04:56PM +0200, Hans de Goede wrote: > On some devices the USB Type-C port power (USB PD 2.0) negotiation is > done by a separate port-controller IC, while the current limit is > controlled through another (charger) IC. > > It has been decided to model this by modelling the external Type-C > power brick (adapter/charger) as a power-supply class device which > supplies the charger-IC, with its voltage-now and current-max representing > the negotiated voltage and max current draw. > > This commit adds a power_supply_set_input_current_limit_from_supplier > helper function which charger power-supply drivers can call to get > the max-current from their supplier and have this applied > through their set_property call-back to their input-current-limit. > > Signed-off-by: Hans de Goede <hdegoede@redhat.com> Thanks, queued. -- Sebastian > drivers/power/supply/power_supply_core.c | 41 ++++++++++++++++++++++++++++++++ > include/linux/power_supply.h | 2 ++ > 2 files changed, 43 insertions(+) > > diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c > index 0741fce..3f92574 100644 > --- a/drivers/power/supply/power_supply_core.c > +++ b/drivers/power/supply/power_supply_core.c > @@ -375,6 +375,47 @@ int power_supply_is_system_supplied(void) > } > EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); > > +static int __power_supply_get_supplier_max_current(struct device *dev, > + void *data) > +{ > + union power_supply_propval ret = {0,}; > + struct power_supply *epsy = dev_get_drvdata(dev); > + struct power_supply *psy = data; > + > + if (__power_supply_is_supplied_by(epsy, psy)) > + if (!epsy->desc->get_property(epsy, > + POWER_SUPPLY_PROP_CURRENT_MAX, > + &ret)) > + return ret.intval; > + > + return 0; > +} > + > +int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy) > +{ > + union power_supply_propval val = {0,}; > + int curr; > + > + if (!psy->desc->set_property) > + return -EINVAL; > + > + /* > + * This function is not intended for use with a supply with multiple > + * suppliers, we simply pick the first supply to report a non 0 > + * max-current. > + */ > + curr = class_for_each_device(power_supply_class, NULL, psy, > + __power_supply_get_supplier_max_current); > + if (curr <= 0) > + return (curr == 0) ? -ENODEV : curr; > + > + val.intval = curr; > + > + return psy->desc->set_property(psy, > + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); > +} > +EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier); > + > int power_supply_set_battery_charged(struct power_supply *psy) > { > if (atomic_read(&psy->use_cnt) >= 0 && > diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h > index de89066..79e90b3 100644 > --- a/include/linux/power_supply.h > +++ b/include/linux/power_supply.h > @@ -332,6 +332,8 @@ extern int power_supply_get_battery_info(struct power_supply *psy, > struct power_supply_battery_info *info); > extern void power_supply_changed(struct power_supply *psy); > extern int power_supply_am_i_supplied(struct power_supply *psy); > +extern int power_supply_set_input_current_limit_from_supplier( > + struct power_supply *psy); > extern int power_supply_set_battery_charged(struct power_supply *psy); > > #ifdef CONFIG_POWER_SUPPLY > -- > 2.9.4 >
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c index 0741fce..3f92574 100644 --- a/drivers/power/supply/power_supply_core.c +++ b/drivers/power/supply/power_supply_core.c @@ -375,6 +375,47 @@ int power_supply_is_system_supplied(void) } EXPORT_SYMBOL_GPL(power_supply_is_system_supplied); +static int __power_supply_get_supplier_max_current(struct device *dev, + void *data) +{ + union power_supply_propval ret = {0,}; + struct power_supply *epsy = dev_get_drvdata(dev); + struct power_supply *psy = data; + + if (__power_supply_is_supplied_by(epsy, psy)) + if (!epsy->desc->get_property(epsy, + POWER_SUPPLY_PROP_CURRENT_MAX, + &ret)) + return ret.intval; + + return 0; +} + +int power_supply_set_input_current_limit_from_supplier(struct power_supply *psy) +{ + union power_supply_propval val = {0,}; + int curr; + + if (!psy->desc->set_property) + return -EINVAL; + + /* + * This function is not intended for use with a supply with multiple + * suppliers, we simply pick the first supply to report a non 0 + * max-current. + */ + curr = class_for_each_device(power_supply_class, NULL, psy, + __power_supply_get_supplier_max_current); + if (curr <= 0) + return (curr == 0) ? -ENODEV : curr; + + val.intval = curr; + + return psy->desc->set_property(psy, + POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &val); +} +EXPORT_SYMBOL_GPL(power_supply_set_input_current_limit_from_supplier); + int power_supply_set_battery_charged(struct power_supply *psy) { if (atomic_read(&psy->use_cnt) >= 0 && diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h index de89066..79e90b3 100644 --- a/include/linux/power_supply.h +++ b/include/linux/power_supply.h @@ -332,6 +332,8 @@ extern int power_supply_get_battery_info(struct power_supply *psy, struct power_supply_battery_info *info); extern void power_supply_changed(struct power_supply *psy); extern int power_supply_am_i_supplied(struct power_supply *psy); +extern int power_supply_set_input_current_limit_from_supplier( + struct power_supply *psy); extern int power_supply_set_battery_charged(struct power_supply *psy); #ifdef CONFIG_POWER_SUPPLY
On some devices the USB Type-C port power (USB PD 2.0) negotiation is done by a separate port-controller IC, while the current limit is controlled through another (charger) IC. It has been decided to model this by modelling the external Type-C power brick (adapter/charger) as a power-supply class device which supplies the charger-IC, with its voltage-now and current-max representing the negotiated voltage and max current draw. This commit adds a power_supply_set_input_current_limit_from_supplier helper function which charger power-supply drivers can call to get the max-current from their supplier and have this applied through their set_property call-back to their input-current-limit. Signed-off-by: Hans de Goede <hdegoede@redhat.com> --- drivers/power/supply/power_supply_core.c | 41 ++++++++++++++++++++++++++++++++ include/linux/power_supply.h | 2 ++ 2 files changed, 43 insertions(+)