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@xxxxxxxxxxxxx> --- 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