On Wed, Mar 12, 2025 at 04:42:02PM -0700, Amit Sunil Dhamne via B4 Relay wrote:Thanks Heikki! I will evaluate between this approach vs OF graph approach (as suggested in previous review) and implement it in v2.
From: Amit Sunil Dhamne <amitsd@xxxxxxxxxx>I don't think this API is necessary. If I've understood what you are
Add a new helper function power_supply_get_by_fwnode_reference_array()
to retrieve a list of power_supplies associated with the fwnode's
property. The property can contain multiple nodes where each node is
associated with a power_supply. The list of power_supply objects will be
stored in an array supplied by the caller and the return value will
indicate the size of the resulting array.
after here, the batteries should simply have the Type-C psy(s) listed
in the supplied_to and/or supplied_from.
So you just need to make sure your battery nodes have the USB Type-C
node(s) listed in the "power-supplies" property in your DT, no?
thanks,
Signed-off-by: Amit Sunil Dhamne <amitsd@xxxxxxxxxx>
---
drivers/power/supply/power_supply_core.c | 60 ++++++++++++++++++++++++++++++++
include/linux/power_supply.h | 5 +++
2 files changed, 65 insertions(+)
diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
index 76c340b38015af0a67a0d91305e6242a8646bf53..df1a52f85125748c4fdcb10687aa7ed2f626ded1 100644
--- a/drivers/power/supply/power_supply_core.c
+++ b/drivers/power/supply/power_supply_core.c
@@ -593,6 +593,66 @@ struct power_supply *devm_power_supply_get_by_phandle(struct device *dev,
EXPORT_SYMBOL_GPL(devm_power_supply_get_by_phandle);
#endif /* CONFIG_OF */
+static int power_supply_match_fwnode(struct device *dev, const void *data)
+{
+ return dev && dev->parent && dev->parent->fwnode == data;
+}
+
+/**
+ * power_supply_get_by_fwnode_reference_array() - Returns an array of power
+ * supply objects associated with each fwnode reference present in the property
+ * @fwnode: Pointer to fwnode to lookup property
+ * @property: Name of property holding references
+ * @psy: Resulting array of power_supply pointers. To be provided by the caller.
+ * @size: size of power_supply pointer array.
+ *
+ * If power supply was found, it increases reference count for the
+ * internal power supply's device. The user should power_supply_put()
+ * after usage.
+ *
+ * Return: On success returns the number of power supply objects filled
+ * in the @psy array.
+ * -EOVERFLOW when size of @psy array is not suffice.
+ * -EINVAL when @psy is NULL or @size is 0.
+ * -ENODATA when fwnode does not contain the given property
+ */
+int power_supply_get_by_fwnode_reference_array(struct fwnode_handle *fwnode,
+ const char *property,
+ struct power_supply **psy,
+ ssize_t size)
+{
+ int ret, index, count = 0;
+ struct fwnode_reference_args args;
+ struct device *dev;
+
+ if (!psy || !size)
+ return -EINVAL;
+
+ for (index = 0; index < size &&
+ !(ret = fwnode_property_get_reference_args(fwnode, property, NULL,
+ 0, index, &args));
+ ++index) {
+ dev = class_find_device(&power_supply_class, NULL, args.fwnode,
+ power_supply_match_fwnode);
+ fwnode_handle_put(args.fwnode);
+ if (!dev)
+ continue;
+
+ if (count > size)
+ return -EOVERFLOW;
+
+ psy[count] = dev_get_drvdata(dev);
+ atomic_inc(&psy[count]->use_cnt);
+ ++count;
+ }
+
+ if (ret != -ENOENT)
+ return ret;
+
+ return index ? count : -ENODATA;
+}
+EXPORT_SYMBOL_GPL(power_supply_get_by_fwnode_reference_array);
+
int power_supply_get_battery_info(struct power_supply *psy,
struct power_supply_battery_info **info_out)
{
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 6ed53b292162469d7b357734d5589bff18a201d0..3f062607e5cd7c7f04384e34128ae0953e25d981 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -820,6 +820,11 @@ devm_power_supply_get_by_phandle(struct device *dev, const char *property)
{ return NULL; }
#endif /* CONFIG_OF */
+extern int
+power_supply_get_by_fwnode_reference_array(struct fwnode_handle *fwnode,
+ const char *property,
+ struct power_supply **psy,
+ ssize_t size);
extern const enum power_supply_property power_supply_battery_info_properties[];
extern const size_t power_supply_battery_info_properties_size;
extern int power_supply_get_battery_info(struct power_supply *psy,
--
2.49.0.rc0.332.g42c0ae87b1-goog