diff mbox series

[U-Boot,1/8] core: Add uclass_{first,next}_device_compat

Message ID 20180328123832.16401-1-mario.six@gdsys.cc
State Changes Requested
Delegated to: Mario Six
Headers show
Series [U-Boot,1/8] core: Add uclass_{first,next}_device_compat | expand

Commit Message

Mario Six March 28, 2018, 12:38 p.m. UTC
A lot of times one wants to cycle through the devices in a uclass, but
only certain ones, especially ones identified by their compatibility
string, and ignore all others (in the best case this procedure should
not even activate the devices one is not interested in).

Hence, we add a pair of functions similar to uclass_{first,next}_device,
but taking a compatibility string as an additional argument, which cycle
through the devices of a uclass that conform to this compatibility
string.

Signed-off-by: Mario Six <mario.six@gdsys.cc>
---
 drivers/core/uclass.c | 33 +++++++++++++++++++++++++++++++++
 include/dm/uclass.h   | 37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 70 insertions(+)

Comments

Simon Glass March 30, 2018, 8:41 a.m. UTC | #1
Hi Mario,

On 28 March 2018 at 20:38, Mario Six <mario.six@gdsys.cc> wrote:
> A lot of times one wants to cycle through the devices in a uclass, but
> only certain ones, especially ones identified by their compatibility
> string, and ignore all others (in the best case this procedure should
> not even activate the devices one is not interested in).
>
> Hence, we add a pair of functions similar to uclass_{first,next}_device,
> but taking a compatibility string as an additional argument, which cycle
> through the devices of a uclass that conform to this compatibility
> string.

Can we not use a phandle to find the device? Using raw compatible
strings feel bad (and slow to me).

If not, a please add a sandbox test.

>
> Signed-off-by: Mario Six <mario.six@gdsys.cc>
> ---
>  drivers/core/uclass.c | 33 +++++++++++++++++++++++++++++++++
>  include/dm/uclass.h   | 37 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 70 insertions(+)

Regards,
Simon
Mario Six April 11, 2018, 7:15 a.m. UTC | #2
Hi Simon,

On Fri, Mar 30, 2018 at 10:41 AM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 28 March 2018 at 20:38, Mario Six <mario.six@gdsys.cc> wrote:
>> A lot of times one wants to cycle through the devices in a uclass, but
>> only certain ones, especially ones identified by their compatibility
>> string, and ignore all others (in the best case this procedure should
>> not even activate the devices one is not interested in).
>>
>> Hence, we add a pair of functions similar to uclass_{first,next}_device,
>> but taking a compatibility string as an additional argument, which cycle
>> through the devices of a uclass that conform to this compatibility
>> string.
>
> Can we not use a phandle to find the device? Using raw compatible
> strings feel bad (and slow to me).
>
> If not, a please add a sandbox test.
>

A phandle would indeed be the cleaner solution, but it won't work if you have
to get device handles in board files, since there is no device for a board you
could query for a phandle. And the MPC83xx board this series leads up to needs
to gather numerous device handles for configuration and querying purposes.

If there was a underlying device for the board functions there would be no
issue with using a phandle, but as it is, it sadly won't work.

>>
>> Signed-off-by: Mario Six <mario.six@gdsys.cc>
>> ---
>>  drivers/core/uclass.c | 33 +++++++++++++++++++++++++++++++++
>>  include/dm/uclass.h   | 37 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 70 insertions(+)
>
> Regards,
> Simon
>

Best regards,

Mario
Simon Glass April 12, 2018, 4:31 p.m. UTC | #3
Hi Mario,

On 11 April 2018 at 01:15, Mario Six <mario.six@gdsys.cc> wrote:
> Hi Simon,
>
> On Fri, Mar 30, 2018 at 10:41 AM, Simon Glass <sjg@chromium.org> wrote:
>> Hi Mario,
>>
>> On 28 March 2018 at 20:38, Mario Six <mario.six@gdsys.cc> wrote:
>>> A lot of times one wants to cycle through the devices in a uclass, but
>>> only certain ones, especially ones identified by their compatibility
>>> string, and ignore all others (in the best case this procedure should
>>> not even activate the devices one is not interested in).
>>>
>>> Hence, we add a pair of functions similar to uclass_{first,next}_device,
>>> but taking a compatibility string as an additional argument, which cycle
>>> through the devices of a uclass that conform to this compatibility
>>> string.
>>
>> Can we not use a phandle to find the device? Using raw compatible
>> strings feel bad (and slow to me).
>>
>> If not, a please add a sandbox test.
>>
>
> A phandle would indeed be the cleaner solution, but it won't work if you have
> to get device handles in board files, since there is no device for a board you
> could query for a phandle. And the MPC83xx board this series leads up to needs
> to gather numerous device handles for configuration and querying purposes.
>
> If there was a underlying device for the board functions there would be no
> issue with using a phandle, but as it is, it sadly won't work.

Yes, actually this comes up a lot. Perhaps we should support a 'board'
device which can have phandles pointing to things? It would be easy to
implement. I'm not sure how Linux handles this stuff?

Regards,
Simon
Mario Six April 18, 2018, 9:02 a.m. UTC | #4
Hi Simon,

On Thu, Apr 12, 2018 at 6:31 PM, Simon Glass <sjg@chromium.org> wrote:
> Hi Mario,
>
> On 11 April 2018 at 01:15, Mario Six <mario.six@gdsys.cc> wrote:
>> Hi Simon,
>>
>> On Fri, Mar 30, 2018 at 10:41 AM, Simon Glass <sjg@chromium.org> wrote:
>>> Hi Mario,
>>>
>>> On 28 March 2018 at 20:38, Mario Six <mario.six@gdsys.cc> wrote:
>>>> A lot of times one wants to cycle through the devices in a uclass, but
>>>> only certain ones, especially ones identified by their compatibility
>>>> string, and ignore all others (in the best case this procedure should
>>>> not even activate the devices one is not interested in).
>>>>
>>>> Hence, we add a pair of functions similar to uclass_{first,next}_device,
>>>> but taking a compatibility string as an additional argument, which cycle
>>>> through the devices of a uclass that conform to this compatibility
>>>> string.
>>>
>>> Can we not use a phandle to find the device? Using raw compatible
>>> strings feel bad (and slow to me).
>>>
>>> If not, a please add a sandbox test.
>>>
>>
>> A phandle would indeed be the cleaner solution, but it won't work if you have
>> to get device handles in board files, since there is no device for a board you
>> could query for a phandle. And the MPC83xx board this series leads up to needs
>> to gather numerous device handles for configuration and querying purposes.
>>
>> If there was a underlying device for the board functions there would be no
>> issue with using a phandle, but as it is, it sadly won't work.
>
> Yes, actually this comes up a lot. Perhaps we should support a 'board'
> device which can have phandles pointing to things? It would be easy to
> implement. I'm not sure how Linux handles this stuff?
>

I'll see what I can do. And, well, the whole concept of a "board" doesn't
really exist in Linux the way it does in U-Boot, but from what I can tell, the
drivers in drivers/platfrom seem to be kind of similar to that.

> Regards,
> Simon
>

Best regards,
Mario
diff mbox series

Patch

diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c
index 1aedaa08f0..19cec1e929 100644
--- a/drivers/core/uclass.c
+++ b/drivers/core/uclass.c
@@ -469,6 +469,23 @@  int uclass_get_device_by_phandle(enum uclass_id id, struct udevice *parent,
 }
 #endif
 
+int uclass_first_device_compat(enum uclass_id id, struct udevice **devp,
+			       const char *compat)
+{
+	struct udevice *dev;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_find_first_device(id, &dev);
+	if (!dev)
+		return 0;
+	if (!device_is_compatible(dev, compat)) {
+		*devp = dev;
+		return uclass_next_device_compat(devp, compat);
+	}
+	return uclass_get_device_tail(dev, ret, devp);
+}
+
 int uclass_first_device(enum uclass_id id, struct udevice **devp)
 {
 	struct udevice *dev;
@@ -494,6 +511,22 @@  int uclass_first_device_err(enum uclass_id id, struct udevice **devp)
 	return 0;
 }
 
+int uclass_next_device_compat(struct udevice **devp, const char *compat)
+{
+	struct udevice *dev = *devp;
+	int ret;
+
+	*devp = NULL;
+	ret = uclass_find_next_device(&dev);
+	if (!dev)
+		return 0;
+	if (!device_is_compatible(dev, compat)) {
+		*devp = dev;
+		return uclass_next_device_compat(devp, compat);
+	}
+	return uclass_get_device_tail(dev, ret, devp);
+}
+
 int uclass_next_device(struct udevice **devp)
 {
 	struct udevice *dev = *devp;
diff --git a/include/dm/uclass.h b/include/dm/uclass.h
index 3a01abc239..0320f1fbee 100644
--- a/include/dm/uclass.h
+++ b/include/dm/uclass.h
@@ -260,6 +260,25 @@  int uclass_get_device_by_driver(enum uclass_id id, const struct driver *drv,
  */
 int uclass_first_device(enum uclass_id id, struct udevice **devp);
 
+/**
+ * uclass_first_device_compat() - Get the first device in a uclass compatible
+ *				  to a given compat string
+ *
+ * The device returned is probed if necessary, and ready for use.
+ *
+ * This function is useful to start iterating through a list of devices which
+ * are functioning correctly, can be probed, and are compatible with a certain
+ * compat string.
+ *
+ * @id: Uclass ID to look up
+ * @devp: Returns pointer to the first device in that uclass if no error
+ * occurred, or NULL if there is no first device, or an error occurred with
+ * that device.
+ * @compat: The compatible string the device has to adhere to
+ * @return 0 if OK (found or not found), other -ve on error
+ */
+int uclass_first_device_compat(enum uclass_id id, struct udevice **devp, const char *compat);
+
 /**
  * uclass_first_device_err() - Get the first device in a uclass
  *
@@ -286,6 +305,24 @@  int uclass_first_device_err(enum uclass_id id, struct udevice **devp);
  */
 int uclass_next_device(struct udevice **devp);
 
+/**
+ * uclass_next_device_compat() - Get the next device in a uclass compatible to
+ *				 a given compat string
+ *
+ * The device returned is probed if necessary, and ready for use
+ *
+ * This function is useful to start iterating through a list of devices which
+ * are functioning correctly, can be probed, and are compatible with a certain
+ * compat string.
+ *
+ * @devp: On entry, pointer to device to lookup. On exit, returns pointer
+ * to the next device in the uclass if no error occurred, or NULL if there is
+ * no next device, or an error occurred with that next device.
+ * @compat: The compatible string the device has to adhere to
+ * @return 0 if OK (found or not found), other -ve on error
+ */
+int uclass_next_device_compat(struct udevice **devp, const char *compat);
+
 /**
  * uclass_first_device() - Get the first device in a uclass
  *