linux-kernel.vger.kernel.org archive mirror
 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:00 UTC|newest]

Thread overview: 104+ 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
2014-10-07  0:16 ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
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
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: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
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 \
    --subject='Re: [PATCH 10/13] Driver core: Child node properties for devices' \
    /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

This is a public inbox, see mirroring instructions
on how to clone and mirror all data and code used for this inbox