All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@rjwysocki.net>
To: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	ACPI Devel Maling List <linux-acpi@vger.kernel.org>,
	Aaron Lu <aaron.lu@intel.com>,
	devicetree@vger.kernel.org,
	Linus Walleij <linus.walleij@linaro.org>,
	Alexandre Courbot <gnurou@gmail.com>,
	Dmitry Torokhov <dmitry.torokhov@gmail.com>,
	Bryan Wu <cooloney@gmail.com>,
	Grant Likely <grant.likely@linaro.org>,
	Arnd Bergmann <arnd@arndb.de>,
	Darren Hart <dvhart@linux.intel.com>,
	Mark Rutland <mark.rutland@arm.com>
Subject: [PATCH 10/13] Driver core: Child node properties for devices
Date: Tue, 07 Oct 2014 02:17:17 +0200	[thread overview]
Message-ID: <3208469.WyhU6QFTtE@vostro.rjw.lan> (raw)
In-Reply-To: <2660541.BycO7TFnA2@vostro.rjw.lan>

From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Add new generic routines for retrieving properties from device
description objects in the platform firmware in case a device driver
needs/wants to access properties of a child object of a given device
object.  There are cases in which there is no struct device
representation of such child objects and this additional API is useful
then.  Three functions are provided, device_get_child_property(),
device_read_child_property(), device_read_child_property_array(), in
analogy with device_get_property(), device_read_property() and
device_read_property_array() introduced earlier, respectively, along
with static inline wrappers for all of the propery data types that can
be used.  For all of them, the first argument is a struct device
pointer to the parent device object and the second argument is a
(void *) pointer to the child description provided by the platform
firmware (either ACPI or FDT).

Additionally, provided are a new macro device_for_each_child_node()
for iterating over the children of the device description object
associated with a given device and a new function
device_get_child_node_count() returning the number of a given
device's child nodes.

The interface covers both ACPI and Device Trees.

This change set includes material from Mika Westerberg.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c      |   20 ++++++
 drivers/base/property.c  |  148 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/acpi.h     |    9 ++
 include/linux/property.h |  108 ++++++++++++++++++++++++++++++++++
 4 files changed, 285 insertions(+)

Index: linux-pm/include/linux/property.h
===================================================================
--- linux-pm.orig/include/linux/property.h
+++ linux-pm/include/linux/property.h
@@ -34,6 +34,21 @@ int device_read_property_array(struct de
 			       enum dev_prop_type proptype, void *val,
 			       size_t nval);
 
+int device_get_child_property(struct device *dev, void *child,
+			      const char *propname, void **valptr);
+int device_read_child_property(struct device *dev, void *child,
+			       const char *propname,
+			       enum dev_prop_type proptype, void *val);
+int device_read_child_property_array(struct device *dev, void *child,
+				     const char *propname,
+				     enum dev_prop_type proptype, void *val,
+				     size_t nval);
+
+void *device_get_next_child_node(struct device *dev, void *child);
+void device_put_child_node(struct device *dev, void *child);
+
+unsigned int device_get_child_node_count(struct device *dev);
+
 static inline int device_property_read_u8(struct device *dev,
 					  const char *propname, u8 *out_value)
 {
@@ -105,4 +120,97 @@ static inline int device_property_read_s
 	return device_read_property_array(dev, propname, DEV_PROP_STRING,
 					  out_strings, nstrings);
 }
+
+static inline int device_child_property_read_u8(struct device *dev, void *child,
+						const char *propname,
+						u8 *out_value)
+{
+	return device_read_child_property(dev, child, propname, DEV_PROP_U8,
+					  out_value);
+}
+
+static inline int device_child_property_read_u16(struct device *dev, void *child,
+						 const char *propname,
+						 u16 *out_value)
+{
+	return device_read_child_property(dev, child, propname, DEV_PROP_U16,
+					  out_value);
+}
+
+static inline int device_child_property_read_u32(struct device *dev, void *child,
+						 const char *propname,
+						 u32 *out_value)
+{
+	return device_read_child_property(dev, child, propname, DEV_PROP_U32,
+					  out_value);
+}
+
+static inline int device_child_property_read_u64(struct device *dev, void *child,
+						 const char *propname,
+						 u64 *out_value)
+{
+	return device_read_child_property(dev, child, propname, DEV_PROP_U64,
+					  out_value);
+}
+
+static inline int device_child_property_read_u8_array(struct device *dev,
+						      void *child,
+						      const char *propname,
+						      u8 *val, size_t nval)
+{
+	return device_read_child_property_array(dev, child, propname,
+						DEV_PROP_U8, val, nval);
+}
+
+static inline int device_child_property_read_u16_array(struct device *dev,
+						       void *child,
+						       const char *propname,
+						       u16 *val, size_t nval)
+{
+	return device_read_child_property_array(dev, child, propname,
+						DEV_PROP_U16, val, nval);
+}
+
+static inline int device_child_property_read_u32_array(struct device *dev,
+						       void *child,
+						       const char *propname,
+						       u32 *val, size_t nval)
+{
+	return device_read_child_property_array(dev, child, propname,
+						DEV_PROP_U32, val, nval);
+}
+
+static inline int device_child_property_read_u64_array(struct device *dev,
+						       void *child,
+						       const char *propname,
+						       u64 *val, size_t nval)
+{
+	return device_read_child_property_array(dev, child, propname,
+						DEV_PROP_U64, val, nval);
+}
+
+static inline int device_child_property_read_string(struct device *dev,
+						    void *child,
+						    const char *propname,
+						    const char **out_string)
+{
+	return device_read_child_property(dev, child, propname, DEV_PROP_STRING,
+					  out_string);
+}
+
+static inline int device_child_property_read_string_array(struct device *dev,
+						void *child,
+						const char *propname,
+						const char **out_strings,
+						size_t nstrings)
+{
+	return device_read_child_property_array(dev, child, propname,
+						DEV_PROP_STRING,
+						out_strings, nstrings);
+}
+
+#define device_for_each_child_node(dev, child) \
+	for (child = device_get_next_child_node(dev, NULL); child; \
+	     child = device_get_next_child_node(dev, child))
+
 #endif /* _LINUX_PROPERTY_H_ */
Index: linux-pm/drivers/base/property.c
===================================================================
--- linux-pm.orig/drivers/base/property.c
+++ linux-pm/drivers/base/property.c
@@ -95,3 +95,151 @@ int device_read_property_array(struct de
 					val, nval);
 }
 EXPORT_SYMBOL_GPL(device_read_property_array);
+
+/**
+ * device_get_child_property - return a raw property of a device's child
+ * @dev: Parent device
+ * @child: Child to get a property of
+ * @propname: Name of the property
+ * @valptr: The raw property value is stored here
+ *
+ * Function reads property @propname from the firmware description of @child and
+ * stores the raw value into @valptr if found.  Otherwise returns a negative
+ * errno as specified below.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not exist.
+ */
+int device_get_child_property(struct device *dev, void *child,
+			      const char *propname, void **valptr)
+{
+	if (!child)
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_get(child, propname, valptr);
+	else if (ACPI_COMPANION(dev))
+		return acpi_dev_prop_get(child, propname, valptr);
+
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_get_child_property);
+
+/**
+ * device_read_child_property - read a typed property of a device's child
+ * @dev: Parent device
+ * @child: Child to read a property of
+ * @propname: Name of the property
+ * @proptype: Type of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the firmware description of @child and
+ * stores the value into @val if found. The value is checked to be of type
+ * @proptype.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not exist,
+ *	   %-EPROTO if the property type does not match @proptype,
+ *	   %-EOVERFLOW if the property value is out of bounds of @proptype.
+ */
+int device_read_child_property(struct device *dev, void *child,
+			       const char *propname, enum dev_prop_type proptype,
+			       void *val)
+{
+	if (!child)
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read(child, propname, proptype, val);
+	else if (ACPI_COMPANION(dev))
+		return acpi_dev_prop_read(child, propname, proptype, val);
+
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_read_child_property);
+
+/**
+ * device_read_child_property_array - read an array property of a device's child
+ * @dev: Parent device
+ * @child: Child to get the property of
+ * @propname: Name of the property
+ * @proptype: Type of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of properties with @propname from the firmware
+ * description of @child and stores them to @val if found. All the values
+ * in the array must be of type @proptype.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not exist,
+ *	   %-EPROTO if the property type does not match @proptype,
+ *	   %-EOVERFLOW if the property value is out of bounds of @proptype.
+ */
+int device_read_child_property_array(struct device *dev, void *child,
+				     const char *propname,
+				     enum dev_prop_type proptype, void *val,
+				     size_t nval)
+{
+	if (!child)
+		return -EINVAL;
+
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(child, propname, proptype,
+					      val, nval);
+	else if (ACPI_COMPANION(dev))
+		return acpi_dev_prop_read_array(child, propname, proptype,
+						val, nval);
+
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_read_child_property_array);
+
+/**
+ * device_get_next_child_node - Return the next child node pointer for a device
+ * @dev: Device to find the next child node for.
+ * @child: Pointer to one of the device's child nodes or NULL.
+ */
+void *device_get_next_child_node(struct device *dev, void *child)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_get_next_available_child(dev->of_node, child);
+
+	return acpi_get_next_child(dev, child);
+}
+EXPORT_SYMBOL_GPL(device_get_next_child_node);
+
+/**
+ * device_put_child_node - Drop reference to a device child node
+ * @dev: Parent device.
+ * @child: Pointer to the child to drop the reference to.
+ *
+ * This has to be used when terminating device_for_each_child_node() iteration
+ * with break or return to prevent stale device node references from being left
+ * behind.
+ */
+void device_put_child_node(struct device *dev, void *child)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		of_node_put(child);
+}
+EXPORT_SYMBOL_GPL(device_put_child_node);
+
+/**
+ * device_get_child_node_count - return the number of child nodes for device
+ * @dev: Device to cound the child nodes for
+ */
+unsigned int device_get_child_node_count(struct device *dev)
+{
+	unsigned int count = 0;
+	void *child = NULL;
+
+	device_for_each_child_node(dev, child)
+		count++;
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(device_get_child_node_count);
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -681,6 +681,9 @@ int acpi_dev_prop_read(struct acpi_devic
 int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
 			     enum dev_prop_type proptype, void *val,
 			     size_t nval);
+
+struct acpi_device *acpi_get_next_child(struct device *dev,
+					struct acpi_device *child);
 #else
 static inline int acpi_dev_get_property(struct acpi_device *adev,
 					const char *name, acpi_object_type type,
@@ -723,6 +726,12 @@ static inline int acpi_dev_prop_read_arr
 {
 	return -ENXIO;
 }
+
+static inline struct acpi_device *acpi_get_next_child(struct device *dev,
+						      struct acpi_device *child)
+{
+	return NULL;
+}
 #endif
 
 #endif	/*_LINUX_ACPI_H*/
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -1342,6 +1342,26 @@ int acpi_device_add(struct acpi_device *
 	return result;
 }
 
+struct acpi_device *acpi_get_next_child(struct device *dev,
+					struct acpi_device *child)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	struct list_head *head, *next;
+
+	if (!adev)
+		return NULL;
+
+	head = &adev->children;
+	if (list_empty(head))
+		return NULL;
+
+	if (!child)
+		return list_first_entry(head, struct acpi_device, node);
+
+	next = child->node.next;
+	return next == head ? NULL : list_entry(next, struct acpi_device, node);
+}
+
 /* --------------------------------------------------------------------------
                                  Driver Management
    -------------------------------------------------------------------------- */

  parent reply	other threads:[~2014-10-07  0:17 UTC|newest]

Thread overview: 109+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-07  0:12 ` [PATCH 01/13] ACPI: Add support for device specific properties Rafael J. Wysocki
2014-10-13 12:47   ` Grant Likely
2014-10-07  0:12 ` [PATCH 02/13] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
2014-10-07  0:13 ` [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
2014-10-14 13:38   ` Grant Likely
2014-10-07  0:14 ` [PATCH 04/13] ACPI: Document ACPI device specific properties Rafael J. Wysocki
2014-10-13 12:41   ` Grant Likely
2014-10-14  9:42     ` Mika Westerberg
2014-10-07  0:14 ` [PATCH 05/13] misc: at25: Make use of device property API Rafael J. Wysocki
2014-10-07  9:10   ` Geert Uytterhoeven
2014-10-07  9:32     ` Mika Westerberg
2014-10-07  0:15 ` [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
2014-10-14 13:44   ` Grant Likely
2014-10-15  8:46     ` Mika Westerberg
2014-10-07  0:15 ` [PATCH 07/13] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
2014-10-07  0:16 ` [PATCH 08/13] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
     [not found] ` <2660541.BycO7TFnA2-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-07  0:16   ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-07  0:16     ` Rafael J. Wysocki
     [not found]     ` <1740633.d3tSWZ2Q0u-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-07 17:29       ` Dmitry Torokhov
2014-10-07 17:29         ` Dmitry Torokhov
2014-10-07  0:17 ` Rafael J. Wysocki [this message]
2014-10-07  0:18 ` [PATCH 11/13] gpio: Support for unified device properties interface Rafael J. Wysocki
2014-10-07 10:22   ` Alexandre Courbot
2014-10-07 10:40     ` Mika Westerberg
2014-10-07 10:52       ` Alexandre Courbot
2014-10-08  0:09         ` Rafael J. Wysocki
2014-10-08  2:55           ` Alexandre Courbot
2014-10-08 14:01             ` Rafael J. Wysocki
2014-10-07  0:18 ` [PATCH 12/13] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
2014-10-08 14:04   ` Rafael J. Wysocki
     [not found]     ` <2960802.kPr8UT7PvT-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-08 17:47       ` Bryan Wu
2014-10-08 17:47         ` Bryan Wu
2014-10-08 22:02         ` Rafael J. Wysocki
2014-10-07  0:19 ` [PATCH 13/13] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-07 17:30   ` Dmitry Torokhov
2014-10-07  0:39 ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-07  2:28 ` Greg Kroah-Hartman
2014-10-15 13:04 ` David Woodhouse
2014-10-15 13:15   ` Mark Rutland
2014-10-15 13:15     ` Mark Rutland
2014-10-15 13:28     ` David Woodhouse
2014-10-15 13:42       ` Mark Rutland
2014-10-15 14:08         ` David Woodhouse
2014-10-15 14:46           ` Darren Hart
2014-10-15 15:11             ` David Woodhouse
2014-10-15 15:17             ` Mark Rutland
2014-10-15 15:43               ` Darren Hart
2014-10-16 10:05                 ` Rafael J. Wysocki
2014-10-16 14:55                 ` David Woodhouse
2014-10-18  8:37                   ` Grant Likely
2014-10-18  8:39                   ` Grant Likely
2014-10-18  8:35                 ` Grant Likely
2014-10-21 21:50                   ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties? support Darren Hart
2015-01-14 18:42     ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support David Woodhouse
2015-01-15  9:12       ` Rafael J. Wysocki
2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
2014-10-17 12:03   ` [PATCH v5 01/12] ACPI: Add support for device specific properties Rafael J. Wysocki
2014-10-17 12:04   ` [PATCH v5 02/12] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
2014-10-20  0:07     ` [Update][PATCH " Rafael J. Wysocki
2014-10-17 12:05   ` [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
2014-10-20 14:05     ` Grant Likely
2014-10-20 22:19       ` Rafael J. Wysocki
2014-10-17 12:07   ` [PATCH v5 04/12] misc: at25: Make use of device property API Rafael J. Wysocki
2014-10-17 12:09   ` [PATCH v5 05/12] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
2014-10-17 12:10   ` [PATCH v5 06/12] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
2014-10-17 12:11   ` [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
2014-10-28 15:26     ` Linus Walleij
2014-10-28 21:56       ` Rafael J. Wysocki
2014-10-29  8:53         ` Mika Westerberg
2014-10-30 15:40           ` Linus Walleij
2014-10-30 16:15             ` Mika Westerberg
2014-10-31  9:41               ` Linus Walleij
2014-10-31  9:55                 ` Mika Westerberg
2014-10-30 15:34         ` Linus Walleij
2014-10-17 12:12   ` [PATCH v5 08/12] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-17 12:14   ` [PATCH v5 09/12] Driver core: Unified interface for firmware node properties Rafael J. Wysocki
2014-10-18  9:35     ` Arnd Bergmann
2014-10-19 23:30       ` Rafael J. Wysocki
2014-10-20 14:14         ` Arnd Bergmann
2014-10-18 14:55     ` Grant Likely
2014-10-19 23:46       ` Rafael J. Wysocki
     [not found]         ` <7821406.D7i8JfDpzX-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-10-20 14:18           ` Grant Likely
2014-10-20 14:18             ` Grant Likely
2014-10-20 22:14             ` Rafael J. Wysocki
2014-10-20 14:19         ` Arnd Bergmann
2014-10-20 14:55           ` Grant Likely
2014-10-20 22:22           ` Rafael J. Wysocki
2014-10-19 22:14     ` Greg Kroah-Hartman
2014-10-19 23:31       ` Rafael J. Wysocki
2014-10-20  0:15     ` [Update][PATCH " Rafael J. Wysocki
2014-10-17 12:16   ` [PATCH v5 10/12] gpio: Support for unified device properties interface Rafael J. Wysocki
2014-10-17 18:09     ` Arnd Bergmann
2014-10-18  9:47       ` Arnd Bergmann
2014-10-19 23:58         ` Rafael J. Wysocki
2014-10-20 14:22           ` Arnd Bergmann
2014-10-20  6:12         ` Alexandre Courbot
2014-10-20 14:26           ` Arnd Bergmann
2014-10-17 12:17   ` [PATCH v5 11/12] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
2014-10-17 12:18   ` [PATCH v5 12/12] input: gpio_keys_polled - " Rafael J. Wysocki
2014-10-17 12:22   ` [PATCH v5 00/12] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
2014-10-17 15:40   ` Greg Kroah-Hartman
2014-10-17 19:23     ` Darren Hart
2014-10-17 21:49     ` Rafael J. Wysocki
2014-10-19 22:14       ` Greg Kroah-Hartman
2014-10-17 18:04   ` Arnd Bergmann
2014-10-17 22:50     ` Rafael J. Wysocki
2014-10-18  8:49       ` Grant Likely
2014-10-19 23:32         ` Rafael J. Wysocki

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3208469.WyhU6QFTtE@vostro.rjw.lan \
    --to=rjw@rjwysocki.net \
    --cc=aaron.lu@intel.com \
    --cc=arnd@arndb.de \
    --cc=cooloney@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dmitry.torokhov@gmail.com \
    --cc=dvhart@linux.intel.com \
    --cc=gnurou@gmail.com \
    --cc=grant.likely@linaro.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mika.westerberg@linux.intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.