diff mbox series

[v2,3/5] power: supply: core: battery-info: fully switch to fwnode

Message ID 20250430-psy-core-convert-to-fwnode-v2-3-f9643b958677@collabora.com
State New
Headers show
Series power: supply: core: convert to fwnode | expand

Commit Message

Sebastian Reichel April 29, 2025, 10:54 p.m. UTC
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.

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

Comments

Hans de Goede June 8, 2025, 7:57 p.m. UTC | #1
Hi Sebastian,
On 30-Apr-25 12:54 AM, Sebastian Reichel wrote:
> 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.
> 
> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>

I have been testing this converting the ug3105 driver to
use power_supply_batinfo_ocv2cap(), replacing the hardcoded
ocv -> capacity table in that driver.

While testing I hit a bug and while looking closer at this
patch it needs more work on top of fixing that bug.

See comments inline, also I've attached 3 fixup patches
which can be squashed into this patch to address the remarks.

> ---
>  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 89947f1fe610d8a75756e1e4e5339b06349f9ab8..a8d1fe66e2486a833ccaa3ed77b861c6e52c5760 100644
> --- a/drivers/power/supply/power_supply_core.c
> +++ b/drivers/power/supply/power_supply_core.c
> @@ -585,32 +585,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;

propname which is also a local-variable for a temporary
malloc-ed buffer uses __free(kfree) instead of explicit
kfree() calls IMHO it would be good to do that here too.

This requires declaring it inside the
"for (index = 0; index < len; index++)" loop like how
this is done for propname, so that it gets freed on
every loop iteration.


>  	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)
> @@ -740,15 +727,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;
> @@ -757,13 +736,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);
> @@ -772,60 +751,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);

As mentioned above I suggest to use the following here instead:

		u32 *propdata __free(kfree) = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);
		

> +		if (!propdata) {
> +			kfree(propname);

propname must NOT be free-ed here since it is marked __free(kfree),
freeing it here will cause a double-free bug.

> +			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);

same as above.

> +			kfree(propdata);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

> +			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);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

>  			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);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

>  	}
>  
> -	list = of_get_property(battery_np, "resistance-temp-table", &len);
> -	if (!list || !len)
> +	proplen = fwnode_property_count_u32(fwnode, "resistance-temp-table");

This will return -EINVAL when the property does not exist, making
power_supply_get_battery_info() always fail when there is no
"resistance-temp-table" in the battery fwnode. See the attached fixup
patch for a suggested fix.

> +	if (proplen < 0 || proplen % 2 != 0) {
> +		power_supply_put_battery_info(psy, info);
> +		err = -ENOMEM;

-ENOMEM is the wrong error code here.

>  		goto out_ret_pointer;

This should be "goto out_put_node" since this is an error path.

> +	} else if (proplen == 0) {
> +		goto out_ret_pointer;
> +	}
>  
> -	info->resist_table_size = len / (2 * sizeof(__be32));
> +	propdata = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);

As mentioned above I suggest to use the following here instead:

		u32 *propdata __free(kfree) = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);

> +	if (!propdata) {
> +		power_supply_put_battery_info(psy, info);
> +		err = -ENOMEM;
> +		goto out_ret_pointer;

This should be "goto out_put_node" since this is an error path.

> +	}
> +
> +	err = fwnode_property_read_u32_array(fwnode, "resistance-temp-table",
> +					     propdata, proplen);
> +	if (err < 0) {
> +		kfree(propdata);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

> +		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);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

>  		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);

with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.

> +
>  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);
> 

Regards,

Hans
Hans de Goede June 8, 2025, 8:16 p.m. UTC | #2
Hi,

On 8-Jun-25 9:57 PM, Hans de Goede wrote:
> Hi Sebastian,
> On 30-Apr-25 12:54 AM, Sebastian Reichel wrote:
>> 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.
>>
>> Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
>> Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
> 
> I have been testing this converting the ug3105 driver to
> use power_supply_batinfo_ocv2cap(), replacing the hardcoded
> ocv -> capacity table in that driver.
> 
> While testing I hit a bug and while looking closer at this
> patch it needs more work on top of fixing that bug.
> 
> See comments inline, also I've attached 3 fixup patches
> which can be squashed into this patch to address the remarks.
> 
>> ---
>>  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 89947f1fe610d8a75756e1e4e5339b06349f9ab8..a8d1fe66e2486a833ccaa3ed77b861c6e52c5760 100644
>> --- a/drivers/power/supply/power_supply_core.c
>> +++ b/drivers/power/supply/power_supply_core.c
>> @@ -585,32 +585,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;
> 
> propname which is also a local-variable for a temporary
> malloc-ed buffer uses __free(kfree) instead of explicit
> kfree() calls IMHO it would be good to do that here too.
> 
> This requires declaring it inside the
> "for (index = 0; index < len; index++)" loop like how
> this is done for propname, so that it gets freed on
> every loop iteration.
> 
> 
>>  	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)
>> @@ -740,15 +727,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;
>> @@ -757,13 +736,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);
>> @@ -772,60 +751,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);
> 
> As mentioned above I suggest to use the following here instead:
> 
> 		u32 *propdata __free(kfree) = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);
> 		
> 
>> +		if (!propdata) {
>> +			kfree(propname);
> 
> propname must NOT be free-ed here since it is marked __free(kfree),
> freeing it here will cause a double-free bug.
> 
>> +			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);
> 
> same as above.
> 
>> +			kfree(propdata);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>> +			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);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>>  			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);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>>  	}
>>  
>> -	list = of_get_property(battery_np, "resistance-temp-table", &len);
>> -	if (!list || !len)
>> +	proplen = fwnode_property_count_u32(fwnode, "resistance-temp-table");
> 
> This will return -EINVAL when the property does not exist, making
> power_supply_get_battery_info() always fail when there is no
> "resistance-temp-table" in the battery fwnode. See the attached fixup
> patch for a suggested fix.
> 
>> +	if (proplen < 0 || proplen % 2 != 0) {
>> +		power_supply_put_battery_info(psy, info);
>> +		err = -ENOMEM;
> 
> -ENOMEM is the wrong error code here.
> 
>>  		goto out_ret_pointer;
> 
> This should be "goto out_put_node" since this is an error path.
> 
>> +	} else if (proplen == 0) {
>> +		goto out_ret_pointer;
>> +	}
>>  
>> -	info->resist_table_size = len / (2 * sizeof(__be32));
>> +	propdata = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);
> 
> As mentioned above I suggest to use the following here instead:
> 
> 		u32 *propdata __free(kfree) = kcalloc(proplen, sizeof(*propdata), GFP_KERNEL);

Ok, so this does not work, because we jump over this causing
propdata to not get initialized, but the __free(kfree) still
triggers.

Lesson learned: do not use modern C style mixing of declarations
and statements together with __free().

Attached are updated fixup patches which do not make things crash.

Regards,

Hans




> 
>> +	if (!propdata) {
>> +		power_supply_put_battery_info(psy, info);
>> +		err = -ENOMEM;
>> +		goto out_ret_pointer;
> 
> This should be "goto out_put_node" since this is an error path.
> 
>> +	}
>> +
>> +	err = fwnode_property_read_u32_array(fwnode, "resistance-temp-table",
>> +					     propdata, proplen);
>> +	if (err < 0) {
>> +		kfree(propdata);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>> +		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);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>>  		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);
> 
> with the suggested "u32 *propdata __free(kfree)" this can and must be dropped.
> 
>> +
>>  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);
>>
> 
> Regards,
> 
> Hans
> 
>
diff mbox series

Patch

diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 89947f1fe610d8a75756e1e4e5339b06349f9ab8..a8d1fe66e2486a833ccaa3ed77b861c6e52c5760 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -585,32 +585,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)
@@ -740,15 +727,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;
@@ -757,13 +736,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);
@@ -772,60 +751,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);