[PATCH 6/7] power: supply: core: battery-info: fully switch to fwnode

Sebastian Reichel
2025-02-24T23:22:02Z

Also use fwnode based parsing for "ocv-capacity-celsius" and
"resistance-temp-table", so that any DT specific bits are
removed from the power-supply core.

Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
---
drivers/power/supply/power_supply_core.c | 109 ++++++++++++++++++-------------
1 file changed, 63 insertions(+), 46 deletions(-)

diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index c43539ea1318506ada0a6fcbcdbf7ece253f5257..0e5fa16fd8f832414f34fae31086128928fa57cc 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -598,32 +598,19 @@ int power_supply_get_battery_info(struct power_supply *psy,
{
struct power_supply_resistance_temp_table *resist_table;
struct power_supply_battery_info *info;
- struct device_node *battery_np = NULL;
- struct fwnode_reference_args args;
- struct fwnode_handle *fwnode = NULL;
+ struct fwnode_handle *srcnode, *fwnode;
const char *value;
- int err, len, index;
- const __be32 *list;
+ int err, len, index, proplen;
+ u32 *propdata;
u32 min_max[2];

- if (psy->dev.of_node) {
- battery_np = of_parse_phandle(psy->dev.of_node, "monitored-battery", 0);
- if (!battery_np)
- return -ENODEV;
+ srcnode = dev_fwnode(&psy->dev);
+ if (!srcnode && psy->dev.parent)
+ srcnode = dev_fwnode(psy->dev.parent);

- fwnode = fwnode_handle_get(of_fwnode_handle(battery_np));
- } else if (psy->dev.parent) {
- err = fwnode_property_get_reference_args(
- dev_fwnode(psy->dev.parent),
- "monitored-battery", NULL, 0, 0, &args);
- if (err)
- return err;
-
- fwnode = args.fwnode;
- }
-
- if (!fwnode)
- return -ENOENT;
+ fwnode = fwnode_find_reference(srcnode, "monitored-battery", 0);
+ if (IS_ERR(fwnode))
+ return PTR_ERR(fwnode);

err = fwnode_property_read_string(fwnode, "compatible", &value);
if (err)
@@ -753,15 +740,7 @@ int power_supply_get_battery_info(struct power_supply *psy,
info->temp_max = min_max[1];
}

- /*
- * The below code uses raw of-data parsing to parse
- * /schemas/types.yaml#/definitions/uint32-matrix
- * data, so for now this is only support with of.
- */
- if (!battery_np)
- goto out_ret_pointer;
-
- len = of_property_count_u32_elems(battery_np, "ocv-capacity-celsius");
+ len = fwnode_property_count_u32(fwnode, "ocv-capacity-celsius");
if (len < 0 && len != -EINVAL) {
err = len;
goto out_put_node;
@@ -770,13 +749,13 @@ int power_supply_get_battery_info(struct power_supply *psy,
err = -EINVAL;
goto out_put_node;
} else if (len > 0) {
- of_property_read_u32_array(battery_np, "ocv-capacity-celsius",
+ fwnode_property_read_u32_array(fwnode, "ocv-capacity-celsius",
info->ocv_temp, len);
}

for (index = 0; index < len; index++) {
struct power_supply_battery_ocv_table *table;
- int i, tab_len, size;
+ int i, tab_len;

char *propname __free(kfree) = kasprintf(GFP_KERNEL, "ocv-capacity-table-%d",
index);
@@ -785,60 +764,98 @@ int power_supply_get_battery_info(struct power_supply *psy,
err = -ENOMEM;
goto out_put_node;
}
- list = of_get_property(battery_np, propname, &size);
- if (!list || !size) {
+ proplen = fwnode_property_count_u32(fwnode, propname);
+ if (proplen < 0 || proplen % 2 != 0) {
dev_err(&psy->dev, "failed to get %s\n", propname);
power_supply_put_battery_info(psy, info);
err = -EINVAL;
goto out_put_node;
}
+ propdata = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);
+ if (!propdata) {
+ kfree(propname);
+ power_supply_put_battery_info(psy, info);
+ err = -EINVAL;
+ goto out_put_node;
+ }
+ err = fwnode_property_read_u32_array(fwnode, propname, propdata, proplen);
+ if (err < 0) {
+ dev_err(&psy->dev, "failed to get %s\n", propname);
+ kfree(propname);
+ kfree(propdata);
+ power_supply_put_battery_info(psy, info);
+ goto out_put_node;
+ }

- tab_len = size / (2 * sizeof(__be32));
+ tab_len = proplen / 2;
info->ocv_table_size[index] = tab_len;

info->ocv_table[index] = table =
devm_kcalloc(&psy->dev, tab_len, sizeof(*table), GFP_KERNEL);
if (!info->ocv_table[index]) {
+ kfree(propdata);
power_supply_put_battery_info(psy, info);
err = -ENOMEM;
goto out_put_node;
}

for (i = 0; i < tab_len; i++) {
- table[i].ocv = be32_to_cpu(*list);
- list++;
- table[i].capacity = be32_to_cpu(*list);
- list++;
+ table[i].ocv = propdata[i*2];
+ table[i].capacity = propdata[i*2+1];
}
+
+ kfree(propdata);
}

- list = of_get_property(battery_np, "resistance-temp-table", &len);
- if (!list || !len)
+ proplen = fwnode_property_count_u32(fwnode, "resistance-temp-table");
+ if (proplen < 0 || proplen % 2 != 0) {
+ power_supply_put_battery_info(psy, info);
+ err = -ENOMEM;
goto out_ret_pointer;
+ } else if (proplen == 0) {
+ goto out_ret_pointer;
+ }

- info->resist_table_size = len / (2 * sizeof(__be32));
+ propdata = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);
+ if (!propdata) {
+ power_supply_put_battery_info(psy, info);
+ err = -ENOMEM;
+ goto out_ret_pointer;
+ }
+
+ err = fwnode_property_read_u32_array(fwnode, "resistance-temp-table",
+ propdata, proplen);
+ if (err < 0) {
+ kfree(propdata);
+ power_supply_put_battery_info(psy, info);
+ goto out_put_node;
+ }
+
+ info->resist_table_size = proplen / 2;
info->resist_table = resist_table = devm_kcalloc(&psy->dev,
info->resist_table_size,
sizeof(*resist_table),
GFP_KERNEL);
if (!info->resist_table) {
+ kfree(propdata);
power_supply_put_battery_info(psy, info);
err = -ENOMEM;
goto out_put_node;
}

for (index = 0; index < info->resist_table_size; index++) {
- resist_table[index].temp = be32_to_cpu(*list++);
- resist_table[index].resistance = be32_to_cpu(*list++);
+ resist_table[index].temp = propdata[index*2];
+ resist_table[index].resistance = propdata[index*2+1];
}

+ kfree(propdata);
+
out_ret_pointer:
/* Finally return the whole thing */
*info_out = info;

out_put_node:
fwnode_handle_put(fwnode);
- of_node_put(battery_np);
return err;
}
EXPORT_SYMBOL_GPL(power_supply_get_battery_info);

--
2.47.2