Hi, On Thu, Aug 20, 2026 at 09:17:58PM +0000, Amit Sunil Dhamne via B4 Relay wrote: > From: Amit Sunil Dhamne > > Some fuel gauges report battery telemetry in energy rather than charge. > Add support for querying native energy properties for Battery Status and > Battery Capabilities AMS, falling back to calculating energy from charge > and average voltage when primary properties are not supported. > > +---------+--------------------+----------------------------------+ > | Sr. No. | Primary | Fallback | > +---------+--------------------+----------------------------------+ > | 1 | ENERGY_NOW | CHARGE_NOW + VOLTAGE_AVG | > | 2 | ENERGY_FULL_DESIGN | CHARGE_FULL_DESIGN + VOLTAGE_AVG | > | 3 | ENERGY_FULL | CHARGE_FULL + VOLTAGE_AVG | > +---------+--------------------+----------------------------------+ > Note: All properties above are to be prefixed with POWER_SUPPLY_PROP_. > > Closes: https://lore.kernel.org/all/amVJ1u67qHENBQ5l@venus/ > Suggested-by: Sebastian Reichel > Assisted-by: Gemini:gemini-3.1-pro > Signed-off-by: Amit Sunil Dhamne > Reviewed-by: Badhri Jagan Sridharan > --- Reviewed-by: Sebastian Reichel Greetings, -- Sebastian > drivers/usb/typec/tcpm/tcpm.c | 57 +++++++++++++++++++++++++++---------------- > 1 file changed, 36 insertions(+), 21 deletions(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index a8cd1959c426..0d7dc0b51c87 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -410,6 +410,9 @@ struct pd_timings { > /* Convert microwatt to watt */ > #define UW_TO_W(pow) (div_u64((pow), 1000000)) > > +/* Convert micro-Watt-hours to USB PD energy (increments of 0.1Wh) */ > +#define UWH_TO_PD_ENERGY(energy) (UW_TO_W((u64)(energy) * 10)) > + > /* > * As per USB PD Spec Rev 3.18 (Sec. 6.5.13.11), the number of fixed batteries > * that a port can be queried is restricted to 4. > @@ -1580,8 +1583,7 @@ static u16 tcpm_charge_to_energy(int charge, int voltage) > { > u64 energy = div_u64((u64)charge * voltage, 1000000); > > - /* Battery telemetry is reported in increments of 0.1Wh */ > - return (u16)UW_TO_W(energy * 10); > + return UWH_TO_PD_ENERGY(energy); > } > > static int tcpm_pd_send_batt_status(struct tcpm_port *port) > @@ -1612,16 +1614,17 @@ static int tcpm_pd_send_batt_status(struct tcpm_port *port) > else > batt_present = val.intval > 0; > > - ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_CHARGE_NOW, > - &val); > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_ENERGY_NOW, &val); > if (!ret) { > - charge_now = val.intval; > - ret = power_supply_get_property(batt, > - POWER_SUPPLY_PROP_VOLTAGE_AVG, > - &val); > - if (!ret) > - present_charge = tcpm_charge_to_energy(charge_now, > - val.intval); > + present_charge = UWH_TO_PD_ENERGY(val.intval); > + } else { > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_CHARGE_NOW, &val); > + if (!ret) { > + charge_now = val.intval; > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_VOLTAGE_AVG, &val); > + if (!ret) > + present_charge = tcpm_charge_to_energy(charge_now, val.intval); > + } > } > > ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_STATUS, &val); > @@ -1678,19 +1681,31 @@ static int tcpm_pd_send_batt_cap(struct tcpm_port *port) > > invalid_ref = false; > batt = port->fixed_batt[batt_id]; > - ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_VOLTAGE_AVG, > - &val); > - if (!ret) { > - vol = val.intval; > - ret = power_supply_get_property(batt, > - POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, > - &val); > + > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, &val); > + if (!ret) > + design_cap = UWH_TO_PD_ENERGY(val.intval); > + > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_ENERGY_FULL, &val); > + if (!ret) > + charge_cap = UWH_TO_PD_ENERGY(val.intval); > + > + if (design_cap != BATTERY_PROPERTY_UNKNOWN && charge_cap != BATTERY_PROPERTY_UNKNOWN) > + goto send_cap; > + > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_VOLTAGE_AVG, &val); > + if (ret) > + goto send_cap; > + > + vol = val.intval; > + if (design_cap == BATTERY_PROPERTY_UNKNOWN) { > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, &val); > if (!ret) > design_cap = tcpm_charge_to_energy(val.intval, vol); > + } > > - ret = power_supply_get_property(batt, > - POWER_SUPPLY_PROP_CHARGE_FULL, > - &val); > + if (charge_cap == BATTERY_PROPERTY_UNKNOWN) { > + ret = power_supply_get_property(batt, POWER_SUPPLY_PROP_CHARGE_FULL, &val); > if (!ret) > charge_cap = tcpm_charge_to_energy(val.intval, vol); > } > > --- > base-commit: e1e6e541c5c9cf548e9fdc35fc26808c82074440 > change-id: 20260820-tcpm-energy-props-upstream-a493353f0054 > > Best regards, > -- > Amit Sunil Dhamne > > >