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
-------------------------------------------------------------------------- */
next prev 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 \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®