linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
@ 2014-10-07  0:10 Rafael J. Wysocki
  2014-10-07  0:12 ` [PATCH 01/13] ACPI: Add support for device specific properties Rafael J. Wysocki
                   ` (16 more replies)
  0 siblings, 17 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:10 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Greg Kroah-Hartman
  Cc: Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Grant Likely, Arnd Bergmann, Darren Hart, Mark Rutland

Hi Everyone,

This is version 4 of the unified device properties interface patchset.

The original cover letter from Mika is here:

http://marc.info/?l=devicetree&m=141087052200600&w=4

My cover letter for version 3 is here:

http://marc.info/?l=linux-acpi&m=141212903816560&w=4

One major change from the previous iteration is that now we will
use the "compatible" property to match drivers to devices having
"PRP0001" as their _HID, so for example the at25 driver doesn't
have to add the extra ACPI match table as part of the conversion
to the unified interface (patch [05/13] in this series).

The second major change is that I've split the driver core patch
in two, where the first one ([02/13]) does not contain any stuff
related to iterating over the child nodes of a given device.
Accordingly, the whole patch series has been rearranged so that
the relatively non-controversial patches [01-09/13], most of which
have been ACKed already, go first and then goes the second driver
core patch ([10/13]) and the other patches related to it.

In patches [10-13/13] I used the Arnd's suggestion to implement
device_for_each_child_node() as a macro which makes the changes
in patches [12-13/13] look more straightforward among other things.

I've retained the Greg's ACKs on patches [02/13] and [10/13], because
the first of them is things ACKed by Greg only and the change in the
second one is just an implementation detail in my opinion (Greg, please
let me know if that's inappropriate).

Thanks!

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 01/13] ACPI: Add support for device specific properties
  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 ` 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
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:12 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.

ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.

In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.

If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:

	Name (_DSD, Package () {
		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
		Package () {
			Package () {"name1", <VALUE1>},
			Package () {"name2", <VALUE2>},
			...
		}
	})

The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].

We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.

The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.

[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Makefile   |    1 
 drivers/acpi/internal.h |    6 
 drivers/acpi/property.c |  364 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c     |    2 
 include/acpi/acpi_bus.h |    7 
 include/linux/acpi.h    |   40 +++++
 6 files changed, 420 insertions(+)
 create mode 100644 drivers/acpi/property.c

Index: linux-pm/drivers/acpi/Makefile
===================================================================
--- linux-pm.orig/drivers/acpi/Makefile
+++ linux-pm/drivers/acpi/Makefile
@@ -46,6 +46,7 @@ acpi-y				+= acpi_pnp.o
 acpi-y				+= power.o
 acpi-y				+= event.o
 acpi-y				+= sysfs.o
+acpi-y				+= property.o
 acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)		+= debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)	+= numa.o
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -181,4 +181,10 @@ struct platform_device *acpi_create_plat
 bool acpi_osi_is_win8(void);
 #endif
 
+/*--------------------------------------------------------------------------
+				Device properties
+  -------------------------------------------------------------------------- */
+void acpi_init_properties(struct acpi_device *adev);
+void acpi_free_properties(struct acpi_device *adev);
+
 #endif /* _ACPI_INTERNAL_H_ */
Index: linux-pm/drivers/acpi/property.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/acpi/property.c
@@ -0,0 +1,364 @@
+/*
+ * ACPI device specific properties support.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Darren Hart <dvhart@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+
+#include "internal.h"
+
+/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
+static const u8 prp_uuid[16] = {
+	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
+	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
+};
+
+static bool acpi_property_value_ok(const union acpi_object *value)
+{
+	int j;
+
+	/*
+	 * The value must be an integer, a string, a reference, or a package
+	 * whose every element must be an integer, a string, or a reference.
+	 */
+	switch (value->type) {
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_LOCAL_REFERENCE:
+		return true;
+
+	case ACPI_TYPE_PACKAGE:
+		for (j = 0; j < value->package.count; j++)
+			switch (value->package.elements[j].type) {
+			case ACPI_TYPE_INTEGER:
+			case ACPI_TYPE_STRING:
+			case ACPI_TYPE_LOCAL_REFERENCE:
+				continue;
+
+			default:
+				return false;
+			}
+
+		return true;
+	}
+	return false;
+}
+
+static bool acpi_properties_format_valid(const union acpi_object *properties)
+{
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		const union acpi_object *property;
+
+		property = &properties->package.elements[i];
+		/*
+		 * Only two elements allowed, the first one must be a string and
+		 * the second one has to satisfy certain conditions.
+		 */
+		if (property->package.count != 2
+		    || property->package.elements[0].type != ACPI_TYPE_STRING
+		    || !acpi_property_value_ok(&property->package.elements[1]))
+			return false;
+	}
+	return true;
+}
+
+void acpi_init_properties(struct acpi_device *adev)
+{
+	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+	const union acpi_object *desc;
+	acpi_status status;
+	int i;
+
+	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return;
+
+	desc = buf.pointer;
+	if (desc->package.count % 2)
+		goto fail;
+
+	/* Look for the device properties UUID. */
+	for (i = 0; i < desc->package.count; i += 2) {
+		const union acpi_object *uuid, *properties;
+
+		uuid = &desc->package.elements[i];
+		properties = &desc->package.elements[i + 1];
+
+		/*
+		 * The first element must be a UUID and the second one must be
+		 * a package.
+		 */
+		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
+		    || properties->type != ACPI_TYPE_PACKAGE)
+			break;
+
+		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
+			continue;
+
+		/*
+		 * We found the matching UUID. Now validate the format of the
+		 * package immediately following it.
+		 */
+		if (!acpi_properties_format_valid(properties))
+			break;
+
+		adev->data.pointer = buf.pointer;
+		adev->data.properties = properties;
+		return;
+	}
+
+ fail:
+	dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
+	ACPI_FREE(buf.pointer);
+}
+
+void acpi_free_properties(struct acpi_device *adev)
+{
+	ACPI_FREE((void *)adev->data.pointer);
+	adev->data.pointer = NULL;
+	adev->data.properties = NULL;
+}
+
+/**
+ * acpi_dev_get_property - return an ACPI property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected property type
+ * @obj: Location to store the property value (if not %NULL)
+ *
+ * Look up a property with @name and store a pointer to the resulting ACPI
+ * object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  These objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if property with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property value type doesn't match @type.
+ */
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+			  acpi_object_type type, const union acpi_object **obj)
+{
+	const union acpi_object *properties;
+	int i;
+
+	if (!adev || !name)
+		return -EINVAL;
+
+	if (!adev->data.pointer || !adev->data.properties)
+		return -ENODATA;
+
+	properties = adev->data.properties;
+	for (i = 0; i < properties->package.count; i++) {
+		const union acpi_object *propname, *propvalue;
+		const union acpi_object *property;
+
+		property = &properties->package.elements[i];
+
+		propname = &property->package.elements[0];
+		propvalue = &property->package.elements[1];
+
+		if (!strcmp(name, propname->string.pointer)) {
+			if (type != ACPI_TYPE_ANY && propvalue->type != type)
+				return -EPROTO;
+			else if (obj)
+				*obj = propvalue;
+
+			return 0;
+		}
+	}
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property);
+
+/**
+ * acpi_dev_get_property_array - return an ACPI array property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected type of array elements
+ * @obj: Location to store a pointer to the property value (if not NULL)
+ *
+ * Look up an array property with @name and store a pointer to the resulting
+ * ACPI object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  Those objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if array property (package) with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property is not a package or the type of its elements
+ *           doesn't match @type.
+ */
+int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
+				acpi_object_type type,
+				const union acpi_object **obj)
+{
+	const union acpi_object *prop;
+	int ret, i;
+
+	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
+	if (ret)
+		return ret;
+
+	if (type != ACPI_TYPE_ANY) {
+		/* Check that all elements are of correct type. */
+		for (i = 0; i < prop->package.count; i++)
+			if (prop->package.elements[i].type != type)
+				return -EPROTO;
+	}
+	if (obj)
+		*obj = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
+
+/**
+ * acpi_dev_get_property_reference - returns handle to the referenced object
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @size_prop: Name of the "size" property in referenced object
+ * @index: Index of the reference to return
+ * @args: Location to store the returned reference with optional arguments
+ *
+ * Find property with @name, verifify that it is a package containing at least
+ * one object reference and if so, store the ACPI device object pointer to the
+ * target object in @args->adev.
+ *
+ * If the reference includes arguments (@size_prop is not %NULL) follow the
+ * reference and check whether or not there is an integer property @size_prop
+ * under the target object and if so, whether or not its value matches the
+ * number of arguments that follow the reference.  If there's more than one
+ * reference in the property value package, @index is used to select the one to
+ * return.
+ *
+ * Return: %0 on success, negative error code on failure.
+ */
+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
+				    const char *size_prop, size_t index,
+				    struct acpi_reference_args *args)
+{
+	const union acpi_object *element, *end;
+	const union acpi_object *obj;
+	struct acpi_device *device;
+	int ret, idx = 0;
+
+	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return ret;
+
+	/*
+	 * The simplest case is when the value is a single reference.  Just
+	 * return that reference then.
+	 */
+	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
+		if (size_prop || index)
+			return -EINVAL;
+
+		ret = acpi_bus_get_device(obj->reference.handle, &device);
+		if (ret)
+			return ret;
+
+		args->adev = device;
+		args->nargs = 0;
+		return 0;
+	}
+
+	/*
+	 * If it is not a single reference, then it is a package of
+	 * references followed by number of ints as follows:
+	 *
+	 *  Package () { REF, INT, REF, INT, INT }
+	 *
+	 * The index argument is then used to determine which reference
+	 * the caller wants (along with the arguments).
+	 */
+	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
+		return -EPROTO;
+
+	element = obj->package.elements;
+	end = element + obj->package.count;
+
+	while (element < end) {
+		u32 nargs, i;
+
+		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+			return -EPROTO;
+
+		ret = acpi_bus_get_device(element->reference.handle, &device);
+		if (ret)
+			return -ENODEV;
+
+		element++;
+		nargs = 0;
+
+		if (size_prop) {
+			const union acpi_object *prop;
+
+			/*
+			 * Find out how many arguments the refenced object
+			 * expects by reading its size_prop property.
+			 */
+			ret = acpi_dev_get_property(device, size_prop,
+						    ACPI_TYPE_INTEGER, &prop);
+			if (ret)
+				return ret;
+
+			nargs = prop->integer.value;
+			if (nargs > MAX_ACPI_REFERENCE_ARGS
+			    || element + nargs > end)
+				return -EPROTO;
+
+			/*
+			 * Skip to the start of the arguments and verify
+			 * that they all are in fact integers.
+			 */
+			for (i = 0; i < nargs; i++)
+				if (element[i].type != ACPI_TYPE_INTEGER)
+					return -EPROTO;
+		} else {
+			/* assume following integer elements are all args */
+			for (i = 0; element + i < end; i++) {
+				int type = element[i].type;
+
+				if (type == ACPI_TYPE_INTEGER)
+					nargs++;
+				else if (type == ACPI_TYPE_LOCAL_REFERENCE)
+					break;
+				else
+					return -EPROTO;
+			}
+		}
+
+		if (idx++ == index) {
+			args->adev = device;
+			args->nargs = nargs;
+			for (i = 0; i < nargs; i++)
+				args->args[i] = element[i].integer.value;
+
+			return 0;
+		}
+
+		element += nargs;
+	}
+
+	return -EPROTO;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -884,6 +884,7 @@ static void acpi_device_release(struct d
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
+	acpi_free_properties(acpi_dev);
 	acpi_free_pnp_ids(&acpi_dev->pnp);
 	acpi_free_power_resources_lists(acpi_dev);
 	kfree(acpi_dev);
@@ -1888,6 +1889,7 @@ void acpi_init_device_object(struct acpi
 	acpi_set_device_status(device, sta);
 	acpi_device_get_busid(device);
 	acpi_set_pnp_ids(handle, &device->pnp, type);
+	acpi_init_properties(device);
 	acpi_bus_get_flags(device);
 	device->flags.match_driver = false;
 	device->flags.initialized = true;
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -337,6 +337,12 @@ struct acpi_device_physical_node {
 	bool put_online:1;
 };
 
+/* ACPI Device Specific Data (_DSD) */
+struct acpi_device_data {
+	const union acpi_object *pointer;
+	const union acpi_object *properties;
+};
+
 /* Device */
 struct acpi_device {
 	int device_type;
@@ -353,6 +359,7 @@ struct acpi_device {
 	struct acpi_device_wakeup wakeup;
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
+	struct acpi_device_data data;
 	struct acpi_scan_handler *handler;
 	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -658,4 +658,44 @@ do {									\
 #endif
 #endif
 
+/* Device properties */
+
+#define MAX_ACPI_REFERENCE_ARGS	8
+struct acpi_reference_args {
+	struct acpi_device *adev;
+	size_t nargs;
+	u64 args[MAX_ACPI_REFERENCE_ARGS];
+};
+
+#ifdef CONFIG_ACPI
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+			  acpi_object_type type, const union acpi_object **obj);
+int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
+				acpi_object_type type,
+				const union acpi_object **obj);
+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
+				    const char *cells_name, size_t index,
+				    struct acpi_reference_args *args);
+#else
+static inline int acpi_dev_get_property(struct acpi_device *adev,
+					const char *name, acpi_object_type type,
+					const union acpi_object **obj)
+{
+	return -ENXIO;
+}
+static inline int acpi_dev_get_property_array(struct acpi_device *adev,
+					      const char *name,
+					      acpi_object_type type,
+					      const union acpi_object **obj)
+{
+	return -ENXIO;
+}
+static inline int acpi_dev_get_property_reference(struct acpi_device *adev,
+				const char *name, const char *cells_name,
+				size_t index, struct acpi_reference_args *args)
+{
+	return -ENXIO;
+}
+#endif
+
 #endif	/*_LINUX_ACPI_H*/


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 02/13] Driver core: Unified device properties interface for platform firmware
  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-07  0:12 ` Rafael J. Wysocki
  2014-10-07  0:13 ` [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:12 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

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

Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type.  The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.

Three general helper functions, device_get_property(),
device_read_property() and device_read_property_array() are provided.
The first one allows the raw value of a given device property to be
accessed.  The remaining two allow the value of a numeric or string
property and multiple numeric or string values of one array
property to be acquired, respectively.  Static inline wrappers are also
provided for the various property data types that can be passed to
device_read_property() or device_read_property_array() for extra type
checking.

The interface covers both ACPI and Device Trees.

This change set includes material from Mika Westerberg and Aaron Lu.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
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/property.c  |  169 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/base/Makefile    |    2 
 drivers/base/property.c  |   97 ++++++++++++++++++++++++++
 drivers/of/base.c        |  171 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/acpi.h     |   31 ++++++++
 include/linux/of.h       |   27 +++++++
 include/linux/property.h |  108 +++++++++++++++++++++++++++++
 7 files changed, 604 insertions(+), 1 deletion(-)
 create mode 100644 drivers/base/property.c
 create mode 100644 include/linux/property.h

Index: linux-pm/drivers/acpi/property.c
===================================================================
--- linux-pm.orig/drivers/acpi/property.c
+++ linux-pm/drivers/acpi/property.c
@@ -362,3 +362,172 @@ int acpi_dev_get_property_reference(stru
 	return -EPROTO;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr)
+{
+	return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
+				     (const union acpi_object **)valptr);
+}
+
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val)
+{
+	const union acpi_object *obj;
+	int ret = -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
+		if (ret)
+			return ret;
+
+		switch (proptype) {
+		case DEV_PROP_U8:
+			if (obj->integer.value > U8_MAX)
+				return -EOVERFLOW;
+			*(u8 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U16:
+			if (obj->integer.value > U16_MAX)
+				return -EOVERFLOW;
+			*(u16 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U32:
+			if (obj->integer.value > U32_MAX)
+				return -EOVERFLOW;
+			*(u32 *)val = obj->integer.value;
+			break;
+		default:
+			*(u64 *)val = obj->integer.value;
+			break;
+		}
+	} else if (proptype == DEV_PROP_STRING) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
+		if (ret)
+			return ret;
+
+		*(char **)val = obj->string.pointer;
+	}
+	return ret;
+}
+
+static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
+				       size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U8_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u16(const union acpi_object *items,
+					u16 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U16_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u32(const union acpi_object *items,
+					u32 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U32_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u64(const union acpi_object *items,
+					u64 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_string(const union acpi_object *items,
+					   char **val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_STRING)
+			return -EPROTO;
+
+		val[i] = items[i].string.pointer;
+	}
+	return 0;
+}
+
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval)
+{
+	const union acpi_object *obj;
+	const union acpi_object *items;
+	int ret;
+
+	ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return ret;
+
+	if (!val)
+		return obj->package.count;
+
+	if (nval > obj->package.count)
+		nval = obj->package.count;
+
+	items = obj->package.elements;
+	switch (proptype) {
+	case DEV_PROP_U8:
+		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
+		break;
+	case DEV_PROP_U16:
+		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
+		break;
+	case DEV_PROP_U32:
+		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
+		break;
+	case DEV_PROP_U64:
+		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
+		break;
+	case DEV_PROP_STRING:
+		ret = acpi_copy_property_array_string(items, (char **)val, nval);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
Index: linux-pm/drivers/base/Makefile
===================================================================
--- linux-pm.orig/drivers/base/Makefile
+++ linux-pm/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o \
-			   topology.o container.o
+			   topology.o container.o property.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
Index: linux-pm/drivers/base/property.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/base/property.c
@@ -0,0 +1,97 @@
+/*
+ * property.c - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/property.h>
+#include <linux/export.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+/**
+ * device_get_property - return a raw property of a device
+ * @dev: Device get the property of
+ * @propname: Name of the property
+ * @valptr: The raw property value is stored here
+ *
+ * Function reads property @propname from the device firmware description 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_property(struct device *dev, const char *propname, void **valptr)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_get(dev->of_node, propname, valptr);
+
+	return acpi_dev_prop_get(ACPI_COMPANION(dev), propname, valptr);
+}
+EXPORT_SYMBOL_GPL(device_get_property);
+
+/**
+ * device_read_property - read a typed property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @proptype: Type of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description 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_property(struct device *dev, const char *propname,
+			 enum dev_prop_type proptype, void *val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read(dev->of_node, propname, proptype, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, proptype, val);
+}
+EXPORT_SYMBOL_GPL(device_read_property);
+
+/**
+ * device_read_property_array - read an array property of a device
+ * @dev: Device 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 device
+ * firmware description 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_property_array(struct device *dev, const char *propname,
+			       enum dev_prop_type proptype, void *val,
+			       size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(dev->of_node, propname, proptype,
+					      val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, proptype,
+					val, nval);
+}
+EXPORT_SYMBOL_GPL(device_read_property_array);
Index: linux-pm/drivers/of/base.c
===================================================================
--- linux-pm.orig/drivers/of/base.c
+++ linux-pm/drivers/of/base.c
@@ -1247,6 +1247,39 @@ int of_property_read_u64(const struct de
 EXPORT_SYMBOL_GPL(of_property_read_u64);
 
 /**
+ * of_property_read_u64_array - Find and read an array of 64 bit integers
+ * from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_values:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 64-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_values is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64_array(const struct device_node *np,
+			       const char *propname, u64 *out_values,
+			       size_t sz)
+{
+	const __be32 *val = of_find_property_value_of_size(np, propname,
+						(sz * sizeof(*out_values)));
+
+	if (IS_ERR(val))
+		return PTR_ERR(val);
+
+	while (sz--) {
+		*out_values++ = of_read_number(val, 2);
+		val += 2;
+	}
+	return 0;
+}
+
+/**
  * of_property_read_string - Find and read a string from a property
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
@@ -1394,6 +1427,49 @@ int of_property_count_strings(struct dev
 }
 EXPORT_SYMBOL_GPL(of_property_count_strings);
 
+/**
+ * of_property_read_string_array - Find and read an array of strings
+ * from a multiple strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_string:	pointer to null terminated return string, modified only if
+ *		return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device tree node and retrieve a list of
+ * terminated string value (pointer to data, not a copy) in that property.
+ * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if
+ * property does not have a value, and -EOVERFLOW if the string is not
+ * null-terminated within the length of the property data.
+ *
+ * The out_string pointer is modified only if a valid string can be decoded.
+ */
+int of_property_read_string_array(struct device_node *np, const char *propname,
+				  char **output, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	int i = 0;
+	size_t l = 0, total = 0;
+	char *p;
+
+	if (!prop)
+		return -EINVAL;
+
+	if (!prop->value)
+		return -ENODATA;
+
+	if (strnlen(prop->value, prop->length) >= prop->length)
+		return -EOVERFLOW;
+
+	p = prop->value;
+
+	for (i = 0; total < prop->length; total += l, p += l) {
+		output[i++] = p;
+		l = strlen(p) + 1;
+	}
+	return 0;
+}
+
 void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
 {
 	int i;
@@ -2183,3 +2259,98 @@ struct device_node *of_graph_get_remote_
 	return of_get_next_parent(np);
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr)
+{
+	struct property *pp = of_find_property(dn, propname, NULL);
+
+	if (!pp)
+		return -ENODATA;
+
+	if (valptr)
+		*valptr = pp->value;
+	return 0;
+}
+
+int of_dev_prop_read(struct device_node *dn, const char *propname,
+		     enum dev_prop_type proptype, void *val)
+{
+	void *value;
+	int ret = of_dev_prop_get(dn, propname, &value);
+
+	if (ret)
+		return ret;
+
+	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+		switch (proptype) {
+		case DEV_PROP_U8: {
+			*(u8 *)val = *(u8 *)value;
+			break;
+		}
+		case DEV_PROP_U16:
+			*(u16 *)val = *(u16 *)value;
+			break;
+		case DEV_PROP_U32:
+			*(u32 *)val = *(u32 *)value;
+			break;
+		default:
+			*(u64 *)val = *(u64 *)value;
+			break;
+		}
+	} else if (proptype == DEV_PROP_STRING) {
+		*(char **)val = value;
+	}
+	return ret;
+
+}
+
+int of_dev_prop_read_array(struct device_node *dn, const char *propname,
+			   enum dev_prop_type proptype, void *val, size_t nval)
+{
+	int ret, elem_size;
+
+	if (!val) {
+		switch (proptype) {
+		case DEV_PROP_U8:
+			elem_size = sizeof(u8);
+			break;
+		case DEV_PROP_U16:
+			elem_size = sizeof(u16);
+			break;
+		case DEV_PROP_U32:
+			elem_size = sizeof(u32);
+			break;
+		case DEV_PROP_U64:
+			elem_size = sizeof(u64);
+			break;
+		case DEV_PROP_STRING:
+			return of_property_count_strings(dn, propname);
+		default:
+			return -EINVAL;
+		}
+		return of_property_count_elems_of_size(dn, propname, elem_size);
+	}
+
+	switch (proptype) {
+	case DEV_PROP_U8:
+		ret = of_property_read_u8_array(dn, propname, (u8 *)val, nval);
+		break;
+	case DEV_PROP_U16:
+		ret = of_property_read_u16_array(dn, propname, (u16 *)val, nval);
+		break;
+	case DEV_PROP_U32:
+		ret = of_property_read_u32_array(dn, propname, (u32 *)val, nval);
+		break;
+	case DEV_PROP_U64:
+		ret = of_property_read_u64_array(dn, propname, (u64 *)val, nval);
+		break;
+	case DEV_PROP_STRING:
+		ret = of_property_read_string_array(dn, propname,
+						    (char **)val, nval);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -28,6 +28,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>	/* for struct resource */
 #include <linux/device.h>
+#include <linux/property.h>
 
 #ifndef _LINUX
 #define _LINUX
@@ -676,6 +677,14 @@ int acpi_dev_get_property_array(struct a
 int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
 				    const char *cells_name, size_t index,
 				    struct acpi_reference_args *args);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr);
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val);
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval);
 #else
 static inline int acpi_dev_get_property(struct acpi_device *adev,
 					const char *name, acpi_object_type type,
@@ -696,6 +705,28 @@ static inline int acpi_dev_get_property_
 {
 	return -ENXIO;
 }
+
+static inline int acpi_dev_prop_get(struct acpi_device *adev,
+				    const char *propname,
+				    void **valptr)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read(struct acpi_device *adev,
+				     const char *propname,
+				     enum dev_prop_type proptype, void *val)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read_array(struct acpi_device *adev,
+					   const char *propname,
+					   enum dev_prop_type proptype,
+					   void *val, size_t nval)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif	/*_LINUX_ACPI_H*/
Index: linux-pm/include/linux/of.h
===================================================================
--- linux-pm.orig/include/linux/of.h
+++ linux-pm/include/linux/of.h
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/topology.h>
 #include <linux/notifier.h>
+#include <linux/property.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -355,6 +356,12 @@ const char *of_prop_next_string(struct p
 
 bool of_console_check(struct device_node *dn, char *name, int index);
 
+int of_dev_prop_get(struct device_node *dn, const char *propname, void **valptr);
+int of_dev_prop_read(struct device_node *dn, const char *propname,
+		     enum dev_prop_type proptype, void *val);
+int of_dev_prop_read_array(struct device_node *dn, const char *propname,
+			   enum dev_prop_type proptype, void *val, size_t nval);
+
 #else /* CONFIG_OF */
 
 static inline const char* of_node_full_name(const struct device_node *np)
@@ -582,6 +589,26 @@ static inline const char *of_prop_next_s
 	return NULL;
 }
 
+static inline int of_dev_prop_get(struct device_node *dn, const char *propname,
+				 void **valptr)
+{
+	return -ENXIO;
+}
+
+static inline int of_dev_prop_read(struct device_node *dn, const char *propname,
+				   enum dev_prop_type proptype, void *val)
+{
+	return -ENXIO;
+}
+
+static inline int of_dev_prop_read_array(struct device_node *dn,
+					 const char *propname,
+					 enum dev_prop_type proptype,
+					 void *val, size_t nval)
+{
+	return -ENXIO;
+}
+
 #define of_match_ptr(_ptr)	NULL
 #define of_match_node(_matches, _node)	NULL
 #endif /* CONFIG_OF */
Index: linux-pm/include/linux/property.h
===================================================================
--- /dev/null
+++ linux-pm/include/linux/property.h
@@ -0,0 +1,108 @@
+/*
+ * property.h - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_PROPERTY_H_
+#define _LINUX_PROPERTY_H_
+
+#include <linux/types.h>
+
+struct device;
+
+enum dev_prop_type {
+	DEV_PROP_U8,
+	DEV_PROP_U16,
+	DEV_PROP_U32,
+	DEV_PROP_U64,
+	DEV_PROP_STRING,
+	DEV_PROP_MAX,
+};
+
+int device_get_property(struct device *dev, const char *propname,
+			void **valptr);
+int device_read_property(struct device *dev, const char *propname,
+			 enum dev_prop_type proptype, void *val);
+int device_read_property_array(struct device *dev, const char *propname,
+			       enum dev_prop_type proptype, void *val,
+			       size_t nval);
+
+static inline int device_property_read_u8(struct device *dev,
+					  const char *propname, u8 *out_value)
+{
+	return device_read_property(dev, propname, DEV_PROP_U8, out_value);
+}
+
+static inline int device_property_read_u16(struct device *dev,
+					  const char *propname, u16 *out_value)
+{
+	return device_read_property(dev, propname, DEV_PROP_U16, out_value);
+}
+
+static inline int device_property_read_u32(struct device *dev,
+					  const char *propname, u32 *out_value)
+{
+	return device_read_property(dev, propname, DEV_PROP_U32, out_value);
+}
+
+static inline int device_property_read_u64(struct device *dev,
+					  const char *propname, u64 *out_value)
+{
+	return device_read_property(dev, propname, DEV_PROP_U64, out_value);
+}
+
+static inline int device_property_read_u8_array(struct device *dev,
+						const char *propname,
+						u8 *val, size_t nval)
+{
+	return device_read_property_array(dev, propname, DEV_PROP_U8, val,
+					  nval);
+}
+
+static inline int device_property_read_u16_array(struct device *dev,
+						 const char *propname,
+						 u16 *val, size_t nval)
+{
+	return device_read_property_array(dev, propname, DEV_PROP_U16, val,
+					  nval);
+}
+
+static inline int device_property_read_u32_array(struct device *dev,
+						 const char *propname,
+						 u32 *val, size_t nval)
+{
+	return device_read_property_array(dev, propname, DEV_PROP_U32, val,
+					  nval);
+}
+
+static inline int device_property_read_u64_array(struct device *dev,
+						 const char *propname,
+						 u64 *val, size_t nval)
+{
+	return device_read_property_array(dev, propname, DEV_PROP_U64, val,
+					  nval);
+}
+
+static inline int device_property_read_string(struct device *dev,
+					      const char *propname,
+					      const char **out_string)
+{
+	return device_read_property(dev, propname, DEV_PROP_STRING, out_string);
+}
+
+static inline int device_property_read_string_array(struct device *dev,
+						    const char *propname,
+						    const char **out_strings,
+						    size_t nstrings)
+{
+	return device_read_property_array(dev, propname, DEV_PROP_STRING,
+					  out_strings, nstrings);
+}
+#endif /* _LINUX_PROPERTY_H_ */


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property
  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-07  0:12 ` [PATCH 02/13] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
@ 2014-10-07  0:13 ` 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
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:13 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead if the driver
is missing .acpi_match_table.

If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/property.c | 34 +++++++++++++++++
 drivers/acpi/scan.c     | 97 +++++++++++++++++++++++++++++++++++++++++++------
 include/acpi/acpi_bus.h |  1 +
 include/linux/acpi.h    |  8 +---
 4 files changed, 123 insertions(+), 17 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 680f7f1..ff53eb8 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -76,6 +76,37 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
 	return true;
 }
 
+static void acpi_init_of_compatible(struct acpi_device *adev)
+{
+	const union acpi_object *of_compatible;
+	struct acpi_hardware_id *hwid;
+	bool acpi_of = false;
+
+	/*
+	 * Check if the special PRP0001 ACPI ID is present and in that
+	 * case we fill in Device Tree compatible properties for this
+	 * device.
+	 */
+	list_for_each_entry(hwid, &adev->pnp.ids, list) {
+		if (!strcmp(hwid->id, "PRP0001")) {
+			acpi_of = true;
+			break;
+		}
+	}
+
+	if (!acpi_of)
+		return;
+
+	if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
+					&of_compatible)) {
+		acpi_handle_warn(adev->handle,
+				 "PRP0001 requires compatible property\n");
+		return;
+	}
+
+	adev->data.of_compatible = of_compatible;
+}
+
 void acpi_init_properties(struct acpi_device *adev)
 {
 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
@@ -119,6 +150,8 @@ void acpi_init_properties(struct acpi_device *adev)
 
 		adev->data.pointer = buf.pointer;
 		adev->data.properties = properties;
+
+		acpi_init_of_compatible(adev);
 		return;
 	}
 
@@ -130,6 +163,7 @@ void acpi_init_properties(struct acpi_device *adev)
 void acpi_free_properties(struct acpi_device *adev)
 {
 	ACPI_FREE((void *)adev->data.pointer);
+	adev->data.of_compatible = NULL;
 	adev->data.pointer = NULL;
 	adev->data.properties = NULL;
 }
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1979ab3..bc999f1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -124,17 +124,51 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
 	if (list_empty(&acpi_dev->pnp.ids))
 		return 0;
 
-	len = snprintf(modalias, size, "acpi:");
-	size -= len;
-
-	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
-		count = snprintf(&modalias[len], size, "%s:", id->id);
-		if (count < 0)
-			return -EINVAL;
-		if (count >= size)
-			return -ENOMEM;
-		len += count;
-		size -= count;
+	/*
+	 * If the device has PRP0001 we expose DT compatible modalias
+	 * instead in form of of:NnameTCcompatible.
+	 */
+	if (acpi_dev->data.of_compatible) {
+		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+		const union acpi_object *of_compatible, *obj;
+		char *c;
+		int i;
+
+		acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
+		/* DT strings are all in lower case */
+		for (c = buf.pointer; *c != '\0'; c++)
+			*c = tolower(*c);
+
+		len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+		ACPI_FREE(buf.pointer);
+
+		of_compatible = acpi_dev->data.of_compatible;
+		for (i = 0; i < of_compatible->package.count; i++) {
+			obj = &of_compatible->package.elements[i];
+
+			count = snprintf(&modalias[len], size, "C%s",
+					 obj->string.pointer);
+			if (count < 0)
+				return -EINVAL;
+			if (count >= size)
+				return -ENOMEM;
+
+			len += count;
+			size -= count;
+		}
+	} else {
+		len = snprintf(modalias, size, "acpi:");
+		size -= len;
+
+		list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+			count = snprintf(&modalias[len], size, "%s:", id->id);
+			if (count < 0)
+				return -EINVAL;
+			if (count >= size)
+				return -ENOMEM;
+			len += count;
+			size -= count;
+		}
 	}
 
 	modalias[len] = '\0';
@@ -864,6 +898,47 @@ int acpi_match_device_ids(struct acpi_device *device,
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
+/* Performs match against special "PRP0001" shoehorn ACPI ID */
+static bool acpi_of_driver_match_device(struct device *dev,
+					const struct device_driver *drv)
+{
+	const union acpi_object *of_compatible;
+	struct acpi_device *adev;
+	int i;
+
+	adev = ACPI_COMPANION(dev);
+	if (!adev)
+		return false;
+
+	of_compatible = adev->data.of_compatible;
+	if (!drv->of_match_table || !of_compatible)
+		return false;
+
+	/* Now we can look for the driver DT compatible strings */
+	for (i = 0; i < of_compatible->package.count; i++) {
+		const struct of_device_id *id;
+		const union acpi_object *obj;
+
+		obj = &of_compatible->package.elements[i];
+
+		for (id = drv->of_match_table; id->compatible[0]; id++)
+			if (!strcasecmp(obj->string.pointer, id->compatible))
+				return true;
+	}
+
+	return false;
+}
+
+bool acpi_driver_match_device(struct device *dev,
+			      const struct device_driver *drv)
+{
+	if (!drv->acpi_match_table)
+		return acpi_of_driver_match_device(dev, drv);
+
+	return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+EXPORT_SYMBOL_GPL(acpi_driver_match_device);
+
 static void acpi_free_power_resources_lists(struct acpi_device *device)
 {
 	int i;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index f9734fa..98cd723 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -341,6 +341,7 @@ struct acpi_device_physical_node {
 struct acpi_device_data {
 	const union acpi_object *pointer;
 	const union acpi_object *properties;
+	const union acpi_object *of_compatible;
 };
 
 /* Device */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 18c1bc3..11aa6b8 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -424,12 +424,8 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
 const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
 					       const struct device *dev);
 
-static inline bool acpi_driver_match_device(struct device *dev,
-					    const struct device_driver *drv)
-{
-	return !!acpi_match_device(drv->acpi_match_table, dev);
-}
-
+extern bool acpi_driver_match_device(struct device *dev,
+				     const struct device_driver *drv);
 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
 int acpi_device_modalias(struct device *, char *, int);
 
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 04/13] ACPI: Document ACPI device specific properties
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (2 preceding siblings ...)
  2014-10-07  0:13 ` [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
@ 2014-10-07  0:14 ` Rafael J. Wysocki
  2014-10-13 12:41   ` Grant Likely
  2014-10-07  0:14 ` [PATCH 05/13] misc: at25: Make use of device property API Rafael J. Wysocki
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:14 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

This document describes the data format and interfaces of ACPI device
specific properties.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 Documentation/acpi/properties.txt |  376 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 376 insertions(+)
 create mode 100644 Documentation/acpi/properties.txt

Index: linux-pm/Documentation/acpi/properties.txt
===================================================================
--- /dev/null
+++ linux-pm/Documentation/acpi/properties.txt
@@ -0,0 +1,376 @@
+ACPI device properties
+======================
+This document describes the format and interfaces of ACPI device
+properties as specified in "Device Properties UUID For _DSD" available
+here:
+
+http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
+
+1. Introduction
+---------------
+In systems that use ACPI and want to take advantage of device specific
+properties, there needs to be a standard way to return and extract
+name-value pairs for a given ACPI device.
+
+An ACPI device that wants to export its properties must implement a
+static name called _DSD that takes no arguments and returns a package of
+packages:
+
+	Name (_DSD, Package () {
+		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+		Package () {
+			Package () {"name1", <VALUE1>},
+			Package () {"name2", <VALUE2>}
+		}
+	})
+
+The UUID identifies contents of the following package. In case of ACPI
+device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301.
+
+In each returned package, the first item is the name and must be a string.
+The corresponding value can be a string, integer, reference, or package. If
+a package it may only contain strings, integers, and references.
+
+An example device where we might need properties is a device that uses
+GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to
+know which GPIO is used for which purpose.
+
+To solve this we add the following ACPI device properties to the device:
+
+	Device (DEV0)
+	{
+		Name (_CRS, ResourceTemplate () {
+			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}
+			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}
+			...
+		})
+
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {"reset-gpio", {^DEV0, 0, 0, 0}},
+				Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}},
+			}
+		})
+	}
+
+Now the device driver can reference the GPIOs using names instead of
+using indexes.
+
+If there is an existing Device Tree binding for a device, it is expected
+that the same bindings are used with ACPI properties, so that the driver
+dealing with the device needs only minor modifications if any.
+
+2. Formal definition of properties
+----------------------------------
+The following chapters define the currently supported properties. For
+these there exists a helper function that can be used to extract the
+property value.
+
+2.1 Integer types
+-----------------
+ACPI integers are always 64-bit. However, for drivers the full range is
+typically not needed so we provide a set of functions which convert the
+64-bit integer to a smaller Linux integer type.
+
+An integer property looks like this:
+
+	Package () {"i2c-sda-hold-time-ns", 300},
+	Package () {"clock-frequency", 400000},
+
+To read a property value, use a unified property accessor as shown
+below:
+
+	u32 val;
+	int ret;
+
+	ret = device_property_read_u32(dev, "clock-frequency", &val);
+	if (ret)
+		/* Handle error */
+
+The function returns 0 if the property is copied to 'val' or negative
+errno if something went wrong (or the property does not exist).
+
+2.2 Integer arrays
+------------------
+An integer array is a package holding only integers. Arrays can be used to
+represent different things like Linux input key codes to GPIO mappings, pin
+control settings, dma request lines, etc.
+
+An integer array looks like this:
+
+	Package () {
+		"max8952,dvs-mode-microvolt",
+		Package () {
+			1250000,
+			1200000,
+			1050000,
+			950000,
+		}
+	}
+
+The above array property can be accessed like:
+
+	u32 voltages[4];
+	int ret;
+
+	ret = device_property_read_u32_array(dev, "max8952,dvs-mode-microvolt",
+					     voltages, ARRAY_SIZE(voltages));
+	if (ret)
+		/* Handle error */
+
+
+All functions copy the resulting values cast to a requested type to the
+caller supplied array. If you pass NULL in the value pointer ('voltages' in
+this case), the function returns number of items in the array. This can be
+useful if caller does not know size of the array beforehand.
+
+2.3 Strings
+-----------
+String properties can be used to describe many things like labels for GPIO
+buttons, compability ids, etc.
+
+A string property looks like this:
+
+	Package () {"name", "value"},
+	Package () {"label", "Status-LED"},
+
+You can use device_property_read_string() to extract strings:
+
+	const char *val;
+	int ret;
+
+	ret = device_property_read_string(dev, "label", &val);
+	if (ret)
+		/* Handle error */
+
+Note that the function does not copy the returned string but instead the
+value is modified to point to the string property itself.
+
+The memory is owned by the associated ACPI device object and released
+when it is removed. The user need not free the associated memory.
+
+2.4 String arrays
+-----------------
+String arrays can be useful in describing a list of labels, names for
+DMA channels, etc.
+
+A string array property looks like this:
+
+	Package () {"dma-names", Package () {"tx", "rx", "rx-tx"}},
+	Package () {"clock-output-names", Package () {"pll", "pll-switched"}},
+
+And these can be read in similar way that the integer arrrays:
+
+	const char *dma_names[3];
+	int ret;
+
+	ret = device_property_read_string_array(dev, "dma-names", dma_names,
+						ARRAY_SIZE(dma_names));
+	if (ret)
+		/* Handle error */
+
+The memory management rules follow what is specified for single strings.
+Specifically the returned pointers should be treated as constant and not to
+be freed. That is done automatically when the correspondig ACPI device
+object is released.
+
+2.5 Object references
+---------------------
+An ACPI object reference is used to refer to some object in the
+namespace. For example, if a device has dependencies with some other
+object, an object reference can be used.
+
+An object reference looks like this:
+
+	Package () {"dev0", \_SB.DEV0},
+
+At the time of writing this, there is no unified device_property_* accessor
+for references so one needs to use the following ACPI helper function:
+
+	int acpi_dev_get_property_reference(struct acpi_device *adev,
+					    const char *name,
+					    const char *size_prop, int index,
+					    struct acpi_reference_args *args);
+
+The referenced ACPI device is returned in args->adev if found.
+
+In addition to simple object references it is also possible to have object
+references with arguments. These are represented in ASL as follows:
+
+	Device (\_SB.PCI0.PWM)
+	{
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {"#pwm-cells", 2}
+			}
+		})
+	}
+
+	Device (\_SB.PCI0.BL)
+	{
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {
+					"pwms",
+					Package () {
+						\_SB.PCI0.PWM, 0, 5000000,
+						\_SB.PCI0.PWM, 1, 4500000,
+					}
+				}
+			}
+		})
+	}
+
+In the above example, the referenced device declares a property that
+returns the number of expected arguments (here it is "#pwm-cells"). If
+no such property is given we assume that all the integers following the
+reference are arguments.
+
+In the above example PWM device expects 2 additional arguments. This
+will be validated by the ACPI property core.
+
+The additional arguments must be integers. Nothing else is supported.
+
+It is possible, as in the above example, to have multiple references
+with varying number of integer arguments. It is up to the referenced
+device to declare how many arguments it expects. The 'index' parameter
+selects which reference is returned.
+
+One can use acpi_dev_get_property_reference() as well to extract the
+information in additional parameters:
+
+	struct acpi_reference_args args;
+	struct acpi_device *adev = /* this will point to the BL device */
+	int ret;
+
+	/* extract the first reference */
+	acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 0, &args);
+
+	BUG_ON(args.nargs != 2);
+	BUG_ON(args.args[0] != 0);
+	BUG_ON(args.args[1] != 5000000);
+
+	/* extract the second reference */
+	acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 1, &args);
+
+	BUG_ON(args.nargs != 2);
+	BUG_ON(args.args[0] != 1);
+	BUG_ON(args.args[1] != 4500000);
+
+In addition to arguments, args.adev now points to the ACPI device that
+corresponds to \_SB.PCI0.PWM.
+
+It is intended that this function is not used directly but instead
+subsystems like pwm implement their ACPI support on top of this function
+in such way that it is hidden from the client drivers, such as via
+pwm_get().
+
+3. Device property hierarchies
+------------------------------
+Devices are organized in a tree within the Linux kernel. It follows that
+the configuration data would also be hierarchical. In order to reach
+equivalence with Device Tree, the ACPI mechanism must also provide some
+sort of tree-like representation. Fortunately, the ACPI namespace is
+already such a structure.
+
+For example, we could have the following device in ACPI namespace. The
+KEYS device is much like gpio_keys_polled.c in that it includes "pseudo"
+devices for each GPIO:
+
+	Device (KEYS)
+	{
+		Name (_CRS, ResourceTemplate () {
+			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}
+			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}
+			...
+		})
+
+		// "pseudo" devices declared under the parent device
+		Device (BTN0) {
+			Name (_DSD, Package () {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package () {"label", "minnow_btn0"}
+					Package () {"gpios", Package () {^KEYS, 0, 0, 1}}
+				}
+			})
+		}
+
+		Device (BTN1) {
+			Name (_DSD, Package () {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package () {"label", "minnow_btn1"}
+					Package () {"gpios", Package () {^KEYS, 1, 0, 1}}
+				}
+			})
+		}
+	}
+
+We can extract the above in gpio_keys_polled.c like:
+
+	static void gpio_keys_polled_probe(struct device *dev)
+	{
+		void *child;
+
+		/* Properties for the KEYS device itself */
+		device_property_read(dev, ...);
+
+		/*
+		 * Iterate over button devices and extract their
+		 * firmware configuration.
+		 */
+		device_for_each_child_node(dev, child) {
+			const char *label = NULL;
+
+			/*
+			 * We need to use device_child_ variant here to access
+			 * properties of the child.
+			 */
+			device_child_property_read_string(dev, child, "label", &label);
+			/* and so on */
+		}
+	}
+
+Note that you still need proper error handling which is omitted in the
+above example.
+
+4. Existing Device Tree enabled drivers
+---------------------------------------
+At the time of writing this, there are ~250 existing DT enabled drivers.
+Allocating _HID/_CID for each would not be feasible. To make sure that
+those drivers can still be used on ACPI systems, we provide an
+alternative way to get these matched.
+
+There is a special _HID "PRP0001" which means that use the DT bindings
+for matching this device to a driver. The driver needs to have
+.of_match_table filled in even when !CONFIG_OF.
+
+An example device would be leds that can be controlled via GPIOs. This
+is represented as "leds-gpio" device and looks like this in the ACPI
+namespace:
+
+	Device (LEDS)
+	{
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {"compatible", Package () {"gpio-leds"}},
+			}
+		})
+		...
+	}
+
+Once ACPI core sees "PRP0001" and that the device has "compatible"
+property it will do the match using .of_match_table instead if the
+driver does not have .acpi_match_table.
+
+It is preferred that new devices get a proper _HID allocated for them
+instead of inventing new DT "compatible" devices.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 05/13] misc: at25: Make use of device property API
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (3 preceding siblings ...)
  2014-10-07  0:14 ` [PATCH 04/13] ACPI: Document ACPI device specific properties Rafael J. Wysocki
@ 2014-10-07  0:14 ` Rafael J. Wysocki
  2014-10-07  9:10   ` Geert Uytterhoeven
  2014-10-07  0:15 ` [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:14 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Make use of device property API in this driver so that both DT and ACPI
based systems can use this driver.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/misc/eeprom/at25.c | 34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

diff --git a/drivers/misc/eeprom/at25.c b/drivers/misc/eeprom/at25.c
index 634f729..58f6cdd 100644
--- a/drivers/misc/eeprom/at25.c
+++ b/drivers/misc/eeprom/at25.c
@@ -18,7 +18,7 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
-#include <linux/of.h>
+#include <linux/property.h>
 
 /*
  * NOTE: this is an *EEPROM* driver.  The vagaries of product naming
@@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
 
 /*-------------------------------------------------------------------------*/
 
-static int at25_np_to_chip(struct device *dev,
-			   struct device_node *np,
-			   struct spi_eeprom *chip)
+static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
 {
 	u32 val;
 
 	memset(chip, 0, sizeof(*chip));
-	strncpy(chip->name, np->name, sizeof(chip->name));
+	strncpy(chip->name, "at25", sizeof(chip->name));
 
-	if (of_property_read_u32(np, "size", &val) == 0 ||
-	    of_property_read_u32(np, "at25,byte-len", &val) == 0) {
+	if (device_property_read_u32(dev, "size", &val) == 0 ||
+	    device_property_read_u32(dev, "at25,byte-len", &val) == 0) {
 		chip->byte_len = val;
 	} else {
 		dev_err(dev, "Error: missing \"size\" property\n");
 		return -ENODEV;
 	}
 
-	if (of_property_read_u32(np, "pagesize", &val) == 0 ||
-	    of_property_read_u32(np, "at25,page-size", &val) == 0) {
+	if (device_property_read_u32(dev, "pagesize", &val) == 0 ||
+	    device_property_read_u32(dev, "at25,page-size", &val) == 0) {
 		chip->page_size = (u16)val;
 	} else {
 		dev_err(dev, "Error: missing \"pagesize\" property\n");
 		return -ENODEV;
 	}
 
-	if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) {
+	if (device_property_read_u32(dev, "at25,addr-mode", &val) == 0) {
 		chip->flags = (u16)val;
 	} else {
-		if (of_property_read_u32(np, "address-width", &val)) {
+		if (device_property_read_u32(dev, "address-width", &val)) {
 			dev_err(dev,
 				"Error: missing \"address-width\" property\n");
 			return -ENODEV;
@@ -350,7 +348,7 @@ static int at25_np_to_chip(struct device *dev,
 				val);
 			return -ENODEV;
 		}
-		if (of_find_property(np, "read-only", NULL))
+		if (!device_get_property(dev, "read-only", NULL))
 			chip->flags |= EE_READONLY;
 	}
 	return 0;
@@ -360,21 +358,15 @@ static int at25_probe(struct spi_device *spi)
 {
 	struct at25_data	*at25 = NULL;
 	struct spi_eeprom	chip;
-	struct device_node	*np = spi->dev.of_node;
 	int			err;
 	int			sr;
 	int			addrlen;
 
 	/* Chip description */
 	if (!spi->dev.platform_data) {
-		if (np) {
-			err = at25_np_to_chip(&spi->dev, np, &chip);
-			if (err)
-				return err;
-		} else {
-			dev_err(&spi->dev, "Error: no chip description\n");
-			return -ENODEV;
-		}
+		err = at25_fw_to_chip(&spi->dev, &chip);
+		if (err)
+			return err;
 	} else
 		chip = *(struct spi_eeprom *)spi->dev.platform_data;
 
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (4 preceding siblings ...)
  2014-10-07  0:14 ` [PATCH 05/13] misc: at25: Make use of device property API Rafael J. Wysocki
@ 2014-10-07  0:15 ` Rafael J. Wysocki
  2014-10-14 13:44   ` Grant Likely
  2014-10-07  0:15 ` [PATCH 07/13] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:15 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
other things as well) returned by _CRS. Previously we were only able to
use integer index to find the corresponding GPIO, which is pretty error
prone if the order changes.

With _DSD we can now query GPIOs using name instead of an integer index,
like the below example shows:

  // Bluetooth device with reset and shutdown GPIOs
  Device (BTH)
  {
      Name (_HID, ...)

      Name (_CRS, ResourceTemplate ()
      {
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) {15}
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
      })

      Name (_DSD, Package ()
      {
          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
          Package ()
	  {
              Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
              Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
          }
      })
  }

The format of the supported GPIO property is:

  Package () { "name", Package () { ref, index, pin, active_low }}

  ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
        typically this is the device itself (BTH in our case).
  index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
  pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
  active_low - If 1 the GPIO is marked as active_low.

Since ACPI GpioIo() resource does not have field saying whether it is
active low or high, the "active_low" argument can be used here. Setting
it to 1 marks the GPIO as active low.

In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.

This patch implements necessary support to gpiolib for extracting GPIOs
using _DSD device properties.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/gpio/gpiolib-acpi.c | 78 +++++++++++++++++++++++++++++++++++++--------
 drivers/gpio/gpiolib.c      | 30 ++++++++++++++---
 drivers/gpio/gpiolib.h      |  7 ++--
 3 files changed, 94 insertions(+), 21 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 687476f..b14c045 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -293,6 +293,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
 struct acpi_gpio_lookup {
 	struct acpi_gpio_info info;
 	int index;
+	int pin_index;
 	struct gpio_desc *desc;
 	int n;
 };
@@ -306,13 +307,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 
 	if (lookup->n++ == lookup->index && !lookup->desc) {
 		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
+		int pin_index = lookup->pin_index;
+
+		if (pin_index >= agpio->pin_table_length)
+			return 1;
 
 		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
-					      agpio->pin_table[0]);
+					      agpio->pin_table[pin_index]);
 		lookup->info.gpioint =
 			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
-		lookup->info.active_low =
-			agpio->polarity == ACPI_ACTIVE_LOW;
+
+		/*
+		 * ActiveLow is only specified for GpioInt resource. If
+		 * GpioIo is used then the only way to set the flag is
+		 * to use _DSD "gpios" property.
+		 */
+		if (lookup->info.gpioint)
+			lookup->info.active_low =
+				agpio->polarity == ACPI_ACTIVE_LOW;
 	}
 
 	return 1;
@@ -320,40 +332,75 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 
 /**
  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
- * @dev: pointer to a device to get GPIO from
+ * @adev: pointer to a ACPI device to get GPIO from
+ * @propname: Property name of the GPIO (optional)
  * @index: index of GpioIo/GpioInt resource (starting from %0)
  * @info: info pointer to fill in (optional)
  *
- * Function goes through ACPI resources for @dev and based on @index looks
+ * Function goes through ACPI resources for @adev and based on @index looks
  * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
  * and returns it. @index matches GpioIo/GpioInt resources only so if there
  * are total %3 GPIO resources, the index goes from %0 to %2.
  *
+ * If @propname is specified the GPIO is looked using device property. In
+ * that case @index is used to select the GPIO entry in the property value
+ * (in case of multiple).
+ *
  * If the GPIO cannot be translated or there is an error an ERR_PTR is
  * returned.
  *
  * Note: if the GPIO resource has multiple entries in the pin list, this
  * function only returns the first.
  */
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+					  const char *propname, int index,
 					  struct acpi_gpio_info *info)
 {
 	struct acpi_gpio_lookup lookup;
 	struct list_head resource_list;
-	struct acpi_device *adev;
-	acpi_handle handle;
+	bool active_low = false;
 	int ret;
 
-	if (!dev)
-		return ERR_PTR(-EINVAL);
-
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev))
+	if (!adev)
 		return ERR_PTR(-ENODEV);
 
 	memset(&lookup, 0, sizeof(lookup));
 	lookup.index = index;
 
+	if (propname) {
+		struct acpi_reference_args args;
+
+		dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
+
+		memset(&args, 0, sizeof(args));
+		ret = acpi_dev_get_property_reference(adev, propname, NULL,
+						      index, &args);
+		if (ret)
+			return ERR_PTR(ret);
+
+		/*
+		 * The property was found and resolved so need to
+		 * lookup the GPIO based on returned args instead.
+		 */
+		adev = args.adev;
+		if (args.nargs >= 2) {
+			lookup.index = args.args[0];
+			lookup.pin_index = args.args[1];
+			/*
+			 * 3rd argument, if present is used to
+			 * specify active_low.
+			 */
+			if (args.nargs >= 3)
+				active_low = !!args.args[2];
+		}
+
+		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
+			dev_name(&adev->dev), args.nargs,
+			args.args[0], args.args[1], args.args[2]);
+	} else {
+		dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
+	}
+
 	INIT_LIST_HEAD(&resource_list);
 	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
 				     &lookup);
@@ -362,8 +409,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 
 	acpi_dev_free_resource_list(&resource_list);
 
-	if (lookup.desc && info)
+	if (lookup.desc && info) {
 		*info = lookup.info;
+		if (active_low)
+			info->active_low = active_low;
+	}
 
 	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
 }
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index c68d037..4c86601 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1487,14 +1487,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
 					unsigned int idx,
 					enum gpio_lookup_flags *flags)
 {
+	static const char * const suffixes[] = { "gpios", "gpio" };
+	struct acpi_device *adev = ACPI_COMPANION(dev);
 	struct acpi_gpio_info info;
 	struct gpio_desc *desc;
+	char propname[32];
+	int i;
 
-	desc = acpi_get_gpiod_by_index(dev, idx, &info);
-	if (IS_ERR(desc))
-		return desc;
+	/* Try first from _DSD */
+	for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+		if (con_id && strcmp(con_id, "gpios")) {
+			snprintf(propname, sizeof(propname), "%s-%s",
+				 con_id, suffixes[i]);
+		} else {
+			snprintf(propname, sizeof(propname), "%s",
+				 suffixes[i]);
+		}
+
+		desc = acpi_get_gpiod_by_index(adev, propname, 0, &info);
+		if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
+			break;
+	}
+
+	/* Then from plain _CRS GPIOs */
+	if (IS_ERR(desc)) {
+		desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
+		if (IS_ERR(desc))
+			return desc;
+	}
 
-	if (info.gpioint && info.active_low)
+	if (info.active_low)
 		*flags |= GPIO_ACTIVE_LOW;
 
 	return desc;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 9db2b6a..e3a5211 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
 void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
 void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
 
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+					  const char *propname, int index,
 					  struct acpi_gpio_info *info);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
@@ -47,8 +48,8 @@ static inline void
 acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
 
 static inline struct gpio_desc *
-acpi_get_gpiod_by_index(struct device *dev, int index,
-			struct acpi_gpio_info *info)
+acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
+			int index, struct acpi_gpio_info *info)
 {
 	return ERR_PTR(-ENOSYS);
 }
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 07/13] gpio: sch: Consolidate core and resume banks
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (5 preceding siblings ...)
  2014-10-07  0:15 ` [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
@ 2014-10-07  0:15 ` Rafael J. Wysocki
  2014-10-07  0:16 ` [PATCH 08/13] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:15 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

This is actually a single device with two sets of identical registers,
which just happen to start from a different offset. Instead of having
separate GPIO chips created we consolidate them to be single GPIO chip.

In addition having a single GPIO chip allows us to handle ACPI GPIO
translation in the core in a more generic way, since the two GPIO chips
share the same parent ACPI device.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/gpio/gpio-sch.c | 293 ++++++++++++++++++------------------------------
 1 file changed, 112 insertions(+), 181 deletions(-)

diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 41e91d7..99720c8 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -29,290 +29,221 @@
 
 #include <linux/gpio.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define CGEN	(0x00)
-#define CGIO	(0x04)
-#define CGLV	(0x08)
-
-#define RGEN	(0x20)
-#define RGIO	(0x24)
-#define RGLV	(0x28)
-
-static unsigned short gpio_ba;
-
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-
-	if (!(curr_dirs & (1 << bit)))
-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+#define GEN	0x00
+#define GIO	0x04
+#define GLV	0x08
+
+struct sch_gpio {
+	struct gpio_chip chip;
+	spinlock_t lock;
+	unsigned short iobase;
+	unsigned short core_base;
+	unsigned short resume_base;
+};
 
-	spin_unlock(&gpio_lock);
-	return 0;
-}
+#define to_sch_gpio(c)	container_of(c, struct sch_gpio, chip)
 
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+				unsigned reg)
 {
-	int res;
-	unsigned short offset, bit;
+	unsigned base = 0;
 
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	if (gpio >= sch->resume_base) {
+		gpio -= sch->resume_base;
+		base += 0x20;
+	}
 
-	res = !!(inb(gpio_ba + offset) & (1 << bit));
-	return res;
+	return base + reg + gpio / 8;
 }
 
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_vals;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_vals = inb(gpio_ba + offset);
-
-	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
-	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-	spin_unlock(&gpio_lock);
+	if (gpio >= sch->resume_base)
+		gpio -= sch->resume_base;
+	return gpio % 8;
 }
 
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_dirs;
 	unsigned short offset, bit;
+	u8 enable;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-	if (curr_dirs & (1 << bit))
-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+	offset = sch_gpio_offset(sch, gpio, GEN);
+	bit = sch_gpio_bit(sch, gpio);
 
-	spin_unlock(&gpio_lock);
+	enable = inb(sch->iobase + offset);
+	if (!(enable & (1 << bit)))
+		outb(enable | (1 << bit), sch->iobase + offset);
 
-	/*
-	 * according to the datasheet, writing to the level register has no
-	 * effect when GPIO is programmed as input.
-	 * Actually the the level register is read-only when configured as input.
-	 * Thus presetting the output level before switching to output is _NOT_ possible.
-	 * Hence we set the level after configuring the GPIO as output.
-	 * But we cannot prevent a short low pulse if direction is set to high
-	 * and an external pull-up is connected.
-	 */
-	sch_gpio_core_set(gc, gpio_num, val);
-	return 0;
+	spin_unlock(&sch->lock);
 }
 
-static struct gpio_chip sch_gpio_core = {
-	.label			= "sch_gpio_core",
-	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_core_direction_in,
-	.get			= sch_gpio_core_get,
-	.direction_output	= sch_gpio_core_direction_out,
-	.set			= sch_gpio_core_set,
-};
-
-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
-					unsigned gpio_num)
+static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_dirs;
 	unsigned short offset, bit;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_dirs = inb(gpio_ba + offset);
+	curr_dirs = inb(sch->iobase + offset);
 
 	if (!(curr_dirs & (1 << bit)))
-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+		outb(curr_dirs | (1 << bit), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 	return 0;
 }
 
-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
+	int res;
 	unsigned short offset, bit;
 
-	offset = RGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GLV);
+	bit = sch_gpio_bit(sch, gpio_num);
+
+	res = !!(inb(sch->iobase + offset) & (1 << bit));
 
-	return !!(inb(gpio_ba + offset) & (1 << bit));
+	return res;
 }
 
-static void sch_gpio_resume_set(struct gpio_chip *gc,
-				unsigned gpio_num, int val)
+static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_vals;
 	unsigned short offset, bit;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = RGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GLV);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_vals = inb(gpio_ba + offset);
+	curr_vals = inb(sch->iobase + offset);
 
 	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
+		outb(curr_vals | (1 << bit), sch->iobase + offset);
 	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+		outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 }
 
-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+				  int val)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_dirs;
 	unsigned short offset, bit;
 
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	spin_lock(&sch->lock);
 
-	spin_lock(&gpio_lock);
+	offset = sch_gpio_offset(sch, gpio_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_dirs = inb(gpio_ba + offset);
+	curr_dirs = inb(sch->iobase + offset);
 	if (curr_dirs & (1 << bit))
-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+		outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 
 	/*
-	* according to the datasheet, writing to the level register has no
-	* effect when GPIO is programmed as input.
-	* Actually the the level register is read-only when configured as input.
-	* Thus presetting the output level before switching to output is _NOT_ possible.
-	* Hence we set the level after configuring the GPIO as output.
-	* But we cannot prevent a short low pulse if direction is set to high
-	* and an external pull-up is connected.
-	*/
-	sch_gpio_resume_set(gc, gpio_num, val);
+	 * according to the datasheet, writing to the level register has no
+	 * effect when GPIO is programmed as input.
+	 * Actually the the level register is read-only when configured as input.
+	 * Thus presetting the output level before switching to output is _NOT_ possible.
+	 * Hence we set the level after configuring the GPIO as output.
+	 * But we cannot prevent a short low pulse if direction is set to high
+	 * and an external pull-up is connected.
+	 */
+	sch_gpio_set(gc, gpio_num, val);
 	return 0;
 }
 
-static struct gpio_chip sch_gpio_resume = {
-	.label			= "sch_gpio_resume",
+static struct gpio_chip sch_gpio_chip = {
+	.label			= "sch_gpio",
 	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_resume_direction_in,
-	.get			= sch_gpio_resume_get,
-	.direction_output	= sch_gpio_resume_direction_out,
-	.set			= sch_gpio_resume_set,
+	.direction_input	= sch_gpio_direction_in,
+	.get			= sch_gpio_get,
+	.direction_output	= sch_gpio_direction_out,
+	.set			= sch_gpio_set,
 };
 
 static int sch_gpio_probe(struct platform_device *pdev)
 {
+	struct sch_gpio *sch;
 	struct resource *res;
-	int err, id;
 
-	id = pdev->id;
-	if (!id)
-		return -ENODEV;
+	sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
+	if (!sch)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!res)
 		return -EBUSY;
 
-	if (!request_region(res->start, resource_size(res), pdev->name))
+	if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
+				 pdev->name))
 		return -EBUSY;
 
-	gpio_ba = res->start;
+	spin_lock_init(&sch->lock);
+	sch->iobase = res->start;
+	sch->chip = sch_gpio_chip;
+	sch->chip.label = dev_name(&pdev->dev);
+	sch->chip.dev = &pdev->dev;
 
-	switch (id) {
+	switch (pdev->id) {
 	case PCI_DEVICE_ID_INTEL_SCH_LPC:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 10;
-		sch_gpio_resume.base = 10;
-		sch_gpio_resume.ngpio = 4;
+		sch->core_base = 0;
+		sch->resume_base = 10;
+		sch->chip.ngpio = 14;
+
 		/*
 		 * GPIO[6:0] enabled by default
 		 * GPIO7 is configured by the CMC as SLPIOVR
 		 * Enable GPIO[9:8] core powered gpios explicitly
 		 */
-		outb(0x3, gpio_ba + CGEN + 1);
+		sch_gpio_enable(sch, 8);
+		sch_gpio_enable(sch, 9);
 		/*
 		 * SUS_GPIO[2:0] enabled by default
 		 * Enable SUS_GPIO3 resume powered gpio explicitly
 		 */
-		outb(0x8, gpio_ba + RGEN);
+		sch_gpio_enable(sch, 13);
 		break;
 
 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 5;
-		sch_gpio_resume.base = 5;
-		sch_gpio_resume.ngpio = 9;
+		sch->core_base = 0;
+		sch->resume_base = 5;
+		sch->chip.ngpio = 14;
 		break;
 
 	case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 21;
-		sch_gpio_resume.base = 21;
-		sch_gpio_resume.ngpio = 9;
+		sch->core_base = 0;
+		sch->resume_base = 21;
+		sch->chip.ngpio = 30;
 		break;
 
 	default:
-		err = -ENODEV;
-		goto err_sch_gpio_core;
+		return -ENODEV;
 	}
 
-	sch_gpio_core.dev = &pdev->dev;
-	sch_gpio_resume.dev = &pdev->dev;
-
-	err = gpiochip_add(&sch_gpio_core);
-	if (err < 0)
-		goto err_sch_gpio_core;
+	platform_set_drvdata(pdev, sch);
 
-	err = gpiochip_add(&sch_gpio_resume);
-	if (err < 0)
-		goto err_sch_gpio_resume;
-
-	return 0;
-
-err_sch_gpio_resume:
-	gpiochip_remove(&sch_gpio_core);
-
-err_sch_gpio_core:
-	release_region(res->start, resource_size(res));
-	gpio_ba = 0;
-
-	return err;
+	return gpiochip_add(&sch->chip);
 }
 
 static int sch_gpio_remove(struct platform_device *pdev)
 {
-	struct resource *res;
-	if (gpio_ba) {
-
-		gpiochip_remove(&sch_gpio_core);
-		gpiochip_remove(&sch_gpio_resume);
-
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-		release_region(res->start, resource_size(res));
-		gpio_ba = 0;
-	}
+	struct sch_gpio *sch = platform_get_drvdata(pdev);
 
+	gpiochip_remove(&sch->chip);
 	return 0;
 }
 
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 08/13] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (6 preceding siblings ...)
  2014-10-07  0:15 ` [PATCH 07/13] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
@ 2014-10-07  0:16 ` Rafael J. Wysocki
  2014-10-07  0:16 ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:16 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/leds/leds-gpio.c | 80 +++++++++++++++++++++++++++---------------------
 include/linux/leds.h     |  1 +
 2 files changed, 46 insertions(+), 35 deletions(-)

diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 57ff20f..c84e913 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/leds.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -24,11 +25,10 @@
 
 struct gpio_led_data {
 	struct led_classdev cdev;
-	unsigned gpio;
+	struct gpio_desc *gpiod;
 	struct work_struct work;
 	u8 new_level;
 	u8 can_sleep;
-	u8 active_low;
 	u8 blinking;
 	int (*platform_gpio_blink_set)(unsigned gpio, int state,
 			unsigned long *delay_on, unsigned long *delay_off);
@@ -40,12 +40,16 @@ static void gpio_led_work(struct work_struct *work)
 		container_of(work, struct gpio_led_data, work);
 
 	if (led_dat->blinking) {
-		led_dat->platform_gpio_blink_set(led_dat->gpio,
-						 led_dat->new_level,
-						 NULL, NULL);
+		int gpio = desc_to_gpio(led_dat->gpiod);
+		int level = led_dat->new_level;
+
+		if (gpiod_is_active_low(led_dat->gpiod))
+			level = !level;
+
+		led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
 		led_dat->blinking = 0;
 	} else
-		gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
+		gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
 }
 
 static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,
 	else
 		level = 1;
 
-	if (led_dat->active_low)
-		level = !level;
-
 	/* Setting GPIOs with I2C/etc requires a task context, and we don't
 	 * seem to have a reliable way to know if we're already in one; so
 	 * let's just assume the worst.
@@ -72,11 +73,16 @@ static void gpio_led_set(struct led_classdev *led_cdev,
 		schedule_work(&led_dat->work);
 	} else {
 		if (led_dat->blinking) {
-			led_dat->platform_gpio_blink_set(led_dat->gpio, level,
-							 NULL, NULL);
+			int gpio = desc_to_gpio(led_dat->gpiod);
+
+			if (gpiod_is_active_low(led_dat->gpiod))
+				level = !level;
+
+			led_dat->platform_gpio_blink_set(gpio, level, NULL,
+							 NULL);
 			led_dat->blinking = 0;
 		} else
-			gpio_set_value(led_dat->gpio, level);
+			gpiod_set_value(led_dat->gpiod, level);
 	}
 }
 
@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev,
 {
 	struct gpio_led_data *led_dat =
 		container_of(led_cdev, struct gpio_led_data, cdev);
+	int gpio = desc_to_gpio(led_dat->gpiod);
 
 	led_dat->blinking = 1;
-	return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
+	return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
 						delay_on, delay_off);
 }
 
@@ -97,24 +104,33 @@ static int create_gpio_led(const struct gpio_led *template,
 {
 	int ret, state;
 
-	led_dat->gpio = -1;
+	if (!template->gpiod) {
+		unsigned long flags = 0;
 
-	/* skip leds that aren't available */
-	if (!gpio_is_valid(template->gpio)) {
-		dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
-				template->gpio, template->name);
-		return 0;
-	}
+		/* skip leds that aren't available */
+		if (!gpio_is_valid(template->gpio)) {
+			dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
+					template->gpio, template->name);
+			return 0;
+		}
 
-	ret = devm_gpio_request(parent, template->gpio, template->name);
-	if (ret < 0)
-		return ret;
+		if (template->active_low)
+			flags |= GPIOF_ACTIVE_LOW;
+
+		ret = devm_gpio_request_one(parent, template->gpio, flags,
+					    template->name);
+		if (ret < 0)
+			return ret;
+
+		led_dat->gpiod = gpio_to_desc(template->gpio);
+		if (IS_ERR(led_dat->gpiod))
+			return PTR_ERR(led_dat->gpiod);
+	}
 
 	led_dat->cdev.name = template->name;
 	led_dat->cdev.default_trigger = template->default_trigger;
-	led_dat->gpio = template->gpio;
-	led_dat->can_sleep = gpio_cansleep(template->gpio);
-	led_dat->active_low = template->active_low;
+	led_dat->gpiod = template->gpiod;
+	led_dat->can_sleep = gpiod_cansleep(template->gpiod);
 	led_dat->blinking = 0;
 	if (blink_set) {
 		led_dat->platform_gpio_blink_set = blink_set;
@@ -122,30 +138,24 @@ static int create_gpio_led(const struct gpio_led *template,
 	}
 	led_dat->cdev.brightness_set = gpio_led_set;
 	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-		state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
+		state = !!gpiod_get_value_cansleep(led_dat->gpiod);
 	else
 		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
 	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
+	ret = gpiod_direction_output(led_dat->gpiod, state);
 	if (ret < 0)
 		return ret;
 
 	INIT_WORK(&led_dat->work, gpio_led_work);
 
-	ret = led_classdev_register(parent, &led_dat->cdev);
-	if (ret < 0)
-		return ret;
-
-	return 0;
+	return led_classdev_register(parent, &led_dat->cdev);
 }
 
 static void delete_gpio_led(struct gpio_led_data *led)
 {
-	if (!gpio_is_valid(led->gpio))
-		return;
 	led_classdev_unregister(&led->cdev);
 	cancel_work_sync(&led->work);
 }
diff --git a/include/linux/leds.h b/include/linux/leds.h
index e436864..879a113 100644
--- a/include/linux/leds.h
+++ b/include/linux/leds.h
@@ -246,6 +246,7 @@ struct led_platform_data {
 struct gpio_led {
 	const char *name;
 	const char *default_trigger;
+	struct gpio_desc *gpiod;
 	unsigned 	gpio;
 	unsigned	active_low : 1;
 	unsigned	retain_state_suspended : 1;
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 09/12] input: gpio_keys_polled - Add support for GPIO descriptors
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (7 preceding siblings ...)
  2014-10-07  0:16 ` [PATCH 08/13] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
@ 2014-10-07  0:16 ` Rafael J. Wysocki
  2014-10-07 17:29   ` Dmitry Torokhov
  2014-10-07  0:17 ` [PATCH 10/13] Driver core: Child node properties for devices Rafael J. Wysocki
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:16 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

From: Aaron Lu <aaron.lu@intel.com>

GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c | 39 +++++++++++++++++++++----------
 include/linux/gpio_keys.h                 |  3 +++
 2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 432d363..b7a514c 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -23,6 +23,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -51,15 +52,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
 	int state;
 
 	if (bdata->can_sleep)
-		state = !!gpio_get_value_cansleep(button->gpio);
+		state = !!gpiod_get_value_cansleep(button->gpiod);
 	else
-		state = !!gpio_get_value(button->gpio);
+		state = !!gpiod_get_value(button->gpiod);
 
 	if (state != bdata->last_state) {
 		unsigned int type = button->type ?: EV_KEY;
 
-		input_event(input, type, button->code,
-			    !!(state ^ button->active_low));
+		input_event(input, type, button->code, state);
 		input_sync(input);
 		bdata->count = 0;
 		bdata->last_state = state;
@@ -259,7 +259,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button *button = &pdata->buttons[i];
 		struct gpio_keys_button_data *bdata = &bdev->data[i];
-		unsigned int gpio = button->gpio;
 		unsigned int type = button->type ?: EV_KEY;
 
 		if (button->wakeup) {
@@ -267,15 +266,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 			return -EINVAL;
 		}
 
-		error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
-					      button->desc ? : DRV_NAME);
-		if (error) {
-			dev_err(dev, "unable to claim gpio %u, err=%d\n",
-				gpio, error);
-			return error;
+		/*
+		 * Legacy GPIO number so request the GPIO here and
+		 * convert it to descriptor.
+		 */
+		if (!button->gpiod && gpio_is_valid(button->gpio)) {
+			unsigned flags = 0;
+
+			if (button->active_low)
+				flags |= GPIOF_ACTIVE_LOW;
+
+			error = devm_gpio_request_one(&pdev->dev, button->gpio,
+					flags, button->desc ? : DRV_NAME);
+			if (error) {
+				dev_err(dev, "unable to claim gpio %u, err=%d\n",
+					button->gpio, error);
+				return error;
+			}
+
+			button->gpiod = gpio_to_desc(button->gpio);
 		}
 
-		bdata->can_sleep = gpio_cansleep(gpio);
+		if (IS_ERR(button->gpiod))
+			return PTR_ERR(button->gpiod);
+
+		bdata->can_sleep = gpiod_cansleep(button->gpiod);
 		bdata->last_state = -1;
 		bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
 						pdata->poll_interval);
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 8b62246..ee2d8c6 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -2,6 +2,7 @@
 #define _GPIO_KEYS_H
 
 struct device;
+struct gpio_desc;
 
 /**
  * struct gpio_keys_button - configuration parameters
@@ -17,6 +18,7 @@ struct device;
  *			disable button via sysfs
  * @value:		axis value for %EV_ABS
  * @irq:		Irq number in case of interrupt keys
+ * @gpiod:		GPIO descriptor
  */
 struct gpio_keys_button {
 	unsigned int code;
@@ -29,6 +31,7 @@ struct gpio_keys_button {
 	bool can_disable;
 	int value;
 	unsigned int irq;
+	struct gpio_desc *gpiod;
 };
 
 /**
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 10/13] Driver core: Child node properties for devices
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (8 preceding siblings ...)
  2014-10-07  0:16 ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-07  0:17 ` Rafael J. Wysocki
  2014-10-07  0:18 ` [PATCH 11/13] gpio: Support for unified device properties interface Rafael J. Wysocki
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:17 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

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
    -------------------------------------------------------------------------- */


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (9 preceding siblings ...)
  2014-10-07  0:17 ` [PATCH 10/13] Driver core: Child node properties for devices Rafael J. Wysocki
@ 2014-10-07  0:18 ` Rafael J. Wysocki
  2014-10-07 10:22   ` Alexandre Courbot
  2014-10-07  0:18 ` [PATCH 12/13] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:18 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Linus Walleij
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Alexandre Courbot, Dmitry Torokhov,
	Bryan Wu, Grant Likely, Arnd Bergmann, Darren Hart, Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.

In order to help device drivers to handle such firmware child nodes we
add dev[m]_get_named_gpiod_from_child() that takes a child firmware
node pointer as its second argument (the first one is the parent device
itself), finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/gpio/devres.c         | 34 ++++++++++++++++++++++++++
 drivers/gpio/gpiolib.c        | 56 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/gpio/consumer.h |  5 ++++
 3 files changed, 95 insertions(+)

diff --git a/drivers/gpio/devres.c b/drivers/gpio/devres.c
index 954b9f6..a1f7e55 100644
--- a/drivers/gpio/devres.c
+++ b/drivers/gpio/devres.c
@@ -109,6 +109,40 @@ struct gpio_desc *__must_check __devm_gpiod_get_index(struct device *dev,
 EXPORT_SYMBOL(__devm_gpiod_get_index);
 
 /**
+ * devm_get_named_gpiod_from_child - managed dev_get_named_gpiod_from_child()
+ * @dev:	GPIO consumer
+ * @child:	firmware node (child of @dev)
+ * @propname:	name of the firmware property
+ * @index:	index of the GPIO in the property value in case of many
+ *
+ * GPIO descriptors returned from this function are automatically disposed on
+ * driver detach.
+ */
+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
+						  const char *propname, int index)
+{
+	struct gpio_desc **dr;
+	struct gpio_desc *desc;
+
+	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
+			  GFP_KERNEL);
+	if (!dr)
+		return ERR_PTR(-ENOMEM);
+
+	desc = dev_get_named_gpiod_from_child(dev, child, propname, index);
+	if (IS_ERR(desc)) {
+		devres_free(dr);
+		return desc;
+	}
+
+	*dr = desc;
+	devres_add(dev, dr);
+
+	return desc;
+}
+EXPORT_SYMBOL(devm_get_named_gpiod_from_child);
+
+/**
  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
  * @dev: GPIO consumer
  * @con_id: function within the GPIO consumer
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 4c86601..344bc12 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -1717,6 +1717,62 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,
 EXPORT_SYMBOL_GPL(__gpiod_get_index);
 
 /**
+ * dev_get_named_gpiod_from_child - obtain a GPIO from firmware node
+ * @dev:	parent device
+ * @child:	firmware node (child of @dev)
+ * @propname:	name of the firmware property
+ * @idx:	index of the GPIO in the property value in case of many
+ *
+ * This function can be used for drivers that get their configuration
+ * from firmware in such a way that some properties are described as child
+ * nodes for the parent device in DT or ACPI.
+ *
+ * Function properly finds the corresponding GPIO using whatever is the
+ * underlying firmware interface and then makes sure that the GPIO
+ * descriptor is requested before it is returned to the caller.
+ *
+ * In case of error an ERR_PTR() is returned.
+ */
+struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
+						 const char *propname, int index)
+{
+	struct gpio_desc *desc = ERR_PTR(-ENODEV);
+	bool active_low = false;
+	int ret;
+
+	if (!child)
+		return ERR_PTR(-EINVAL);
+
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+		enum of_gpio_flags flags;
+
+		desc = of_get_named_gpiod_flags(child, propname, index, &flags);
+		if (!IS_ERR(desc))
+			active_low = flags & OF_GPIO_ACTIVE_LOW;
+	} else if (ACPI_COMPANION(dev)) {
+		struct acpi_gpio_info info;
+
+		desc = acpi_get_gpiod_by_index(child, propname, index, &info);
+		if (!IS_ERR(desc))
+			active_low = info.active_low;
+	}
+
+	if (IS_ERR(desc))
+		return desc;
+
+	ret = gpiod_request(desc, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/* Only value flag can be set from both DT and ACPI is active_low */
+	if (active_low)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	return desc;
+}
+EXPORT_SYMBOL_GPL(dev_get_named_gpiod_from_child);
+
+/**
  * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
  *                            function
  * @dev: GPIO consumer, can be NULL for system-global GPIOs
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 12f146f..033d2fd 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -94,6 +94,11 @@ int gpiod_to_irq(const struct gpio_desc *desc);
 struct gpio_desc *gpio_to_desc(unsigned gpio);
 int desc_to_gpio(const struct gpio_desc *desc);
 
+/* Child properties interface */
+struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
+						 const char *propname, int index);
+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
+						  const char *propname, int index);
 #else /* CONFIG_GPIOLIB */
 
 static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH 12/13] leds: leds-gpio: Make use of device property API
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (10 preceding siblings ...)
  2014-10-07  0:18 ` [PATCH 11/13] gpio: Support for unified device properties interface Rafael J. Wysocki
@ 2014-10-07  0:18 ` Rafael J. Wysocki
  2014-10-08 14:04   ` Rafael J. Wysocki
  2014-10-07  0:19 ` [PATCH 13/13] input: gpio_keys_polled - " Rafael J. Wysocki
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:18 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Bryan Wu
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Grant Likely, Arnd Bergmann, Darren Hart,
	Mark Rutland

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

Make use of device property API in this driver so that both OF and ACPI
based system can use the same driver.

This change contains material from Max Eliaser and Mika Westerberg.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/leds/leds-gpio.c |   67 +++++++++++++++++++++--------------------------
 1 file changed, 30 insertions(+), 37 deletions(-)

Index: linux-pm/drivers/leds/leds-gpio.c
===================================================================
--- linux-pm.orig/drivers/leds/leds-gpio.c
+++ linux-pm/drivers/leds/leds-gpio.c
@@ -15,13 +15,11 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/leds.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/property.h>
 
 struct gpio_led_data {
 	struct led_classdev cdev;
@@ -171,40 +169,41 @@ static inline int sizeof_gpio_leds_priv(
 		(sizeof(struct gpio_led_data) * num_leds);
 }
 
-/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node, *child;
+	struct device *dev = &pdev->dev;
 	struct gpio_leds_priv *priv;
 	int count, ret;
+	void *child;
 
-	/* count LEDs in this device, so we know how much to allocate */
-	count = of_get_available_child_count(np);
+	count = device_get_child_node_count(dev);
 	if (!count)
 		return ERR_PTR(-ENODEV);
 
-	for_each_available_child_of_node(np, child)
-		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
-			return ERR_PTR(-EPROBE_DEFER);
-
-	priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
-			GFP_KERNEL);
+	priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
 	if (!priv)
 		return ERR_PTR(-ENOMEM);
 
-	for_each_available_child_of_node(np, child) {
+	device_for_each_child_node(dev, child) {
 		struct gpio_led led = {};
-		enum of_gpio_flags flags;
-		const char *state;
+		const char *state = NULL;
+
+		led.gpiod = devm_get_named_gpiod_from_child(dev, child,
+							    "gpios", 0);
+		if (IS_ERR(led.gpiod)) {
+			device_put_child_node(dev, child);
+			goto err;
+		}
 
-		led.gpio = of_get_gpio_flags(child, 0, &flags);
-		led.active_low = flags & OF_GPIO_ACTIVE_LOW;
-		led.name = of_get_property(child, "label", NULL) ? : child->name;
-		led.default_trigger =
-			of_get_property(child, "linux,default-trigger", NULL);
-		state = of_get_property(child, "default-state", NULL);
-		if (state) {
+		device_child_property_read_string(dev, child,
+						  "label", &led.name);
+		device_child_property_read_string(dev, child,
+						  "linux,default-trigger",
+						  &led.default_trigger);
+
+		if (!device_child_property_read_string(dev, child,
+						       "linux,default_state",
+						       &state)) {
 			if (!strcmp(state, "keep"))
 				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
 			else if (!strcmp(state, "on"))
@@ -213,13 +212,14 @@ static struct gpio_leds_priv *gpio_leds_
 				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
 		}
 
-		if (of_get_property(child, "retain-state-suspended", NULL))
+		if (!device_get_child_property(dev, child,
+					       "retain-state-suspended", NULL))
 			led.retain_state_suspended = 1;
 
 		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
-				      &pdev->dev, NULL);
+				      dev, NULL);
 		if (ret < 0) {
-			of_node_put(child);
+			device_put_child_node(dev, child);
 			goto err;
 		}
 	}
@@ -238,13 +238,6 @@ static const struct of_device_id of_gpio
 };
 
 MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
-#else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
-{
-	return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_OF_GPIO */
-
 
 static int gpio_led_probe(struct platform_device *pdev)
 {
@@ -273,7 +266,7 @@ static int gpio_led_probe(struct platfor
 			}
 		}
 	} else {
-		priv = gpio_leds_create_of(pdev);
+		priv = gpio_leds_create(pdev);
 		if (IS_ERR(priv))
 			return PTR_ERR(priv);
 	}
@@ -300,7 +293,7 @@ static struct platform_driver gpio_led_d
 	.driver		= {
 		.name	= "leds-gpio",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(of_gpio_leds_match),
+		.of_match_table = of_gpio_leds_match,
 	},
 };
 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH 13/13] input: gpio_keys_polled - Make use of device property API
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (11 preceding siblings ...)
  2014-10-07  0:18 ` [PATCH 12/13] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
@ 2014-10-07  0:19 ` 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
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:19 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Dmitry Torokhov
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot, Bryan Wu,
	Grant Likely, Arnd Bergmann, Darren Hart, Mark Rutland

From: Aaron Lu <aaron.lu@intel.com>

Make use of device property API in this driver so that both OF based
system and ACPI based system can use this driver.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c |   81 +++++++++++-------------------
 1 file changed, 31 insertions(+), 50 deletions(-)

Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
===================================================================
--- linux-pm.orig/drivers/input/keyboard/gpio_keys_polled.c
+++ linux-pm/drivers/input/keyboard/gpio_keys_polled.c
@@ -25,9 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
+#include <linux/property.h>
 
 #define DRV_NAME	"gpio-keys-polled"
 
@@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struc
 		pdata->disable(bdev->dev);
 }
 
-#ifdef CONFIG_OF
 static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
 {
-	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
+	void *child;
 	int error;
 	int nbuttons;
-	int i;
-
-	node = dev->of_node;
-	if (!node)
-		return NULL;
 
-	nbuttons = of_get_child_count(node);
+	nbuttons = device_get_child_node_count(dev);
 	if (nbuttons == 0)
 		return NULL;
 
@@ -126,52 +118,50 @@ static struct gpio_keys_platform_data *g
 		return ERR_PTR(-ENOMEM);
 
 	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-	pdata->nbuttons = nbuttons;
 
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+	pdata->rep = !device_get_property(dev, "autorepeat", NULL);
+	device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
 
-	i = 0;
-	for_each_child_of_node(node, pp) {
-		int gpio;
-		enum of_gpio_flags flags;
-
-		if (!of_find_property(pp, "gpios", NULL)) {
-			pdata->nbuttons--;
-			dev_warn(dev, "Found button without gpios\n");
-			continue;
-		}
+	device_for_each_child_node(dev, child) {
+		struct gpio_desc *desc;
 
-		gpio = of_get_gpio_flags(pp, 0, &flags);
-		if (gpio < 0) {
-			error = gpio;
+		desc = devm_get_named_gpiod_from_child(dev, child, "gpios", 0);
+		if (IS_ERR(desc)) {
+			error = PTR_ERR(desc);
 			if (error != -EPROBE_DEFER)
 				dev_err(dev,
 					"Failed to get gpio flags, error: %d\n",
 					error);
+			device_put_child_node(dev, child);
 			return ERR_PTR(error);
 		}
 
-		button = &pdata->buttons[i++];
-
-		button->gpio = gpio;
-		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+		button = &pdata->buttons[pdata->nbuttons++];
+		button->gpiod = desc;
 
-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: 0x%x\n",
-				button->gpio);
+		if (device_child_property_read_u32(dev, child, "linux,code",
+						   &button->code)) {
+			dev_err(dev, "Button without keycode: %d\n",
+				pdata->nbuttons - 1);
+			device_put_child_node(dev, child);
 			return ERR_PTR(-EINVAL);
 		}
 
-		button->desc = of_get_property(pp, "label", NULL);
+		device_child_property_read_string(dev, child, "label",
+						  &button->desc);
 
-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
+		if (device_child_property_read_u32(dev, child,
+						   "linux,input-type",
+						   &button->type))
 			button->type = EV_KEY;
 
-		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
-
-		if (of_property_read_u32(pp, "debounce-interval",
-					 &button->debounce_interval))
+		button->wakeup = !device_get_child_property(dev, child,
+							    "gpio-key,wakeup",
+							    NULL);
+
+		if (device_child_property_read_u32(dev, child,
+						   "debounce-interval",
+						   &button->debounce_interval))
 			button->debounce_interval = 5;
 	}
 
@@ -187,15 +177,6 @@ static const struct of_device_id gpio_ke
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
 
-#else
-
-static inline struct gpio_keys_platform_data *
-gpio_keys_polled_get_devtree_pdata(struct device *dev)
-{
-	return NULL;
-}
-#endif
-
 static int gpio_keys_polled_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -323,7 +304,7 @@ static struct platform_driver gpio_keys_
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
+		.of_match_table = gpio_keys_polled_of_match,
 	},
 };
 module_platform_driver(gpio_keys_polled_driver);


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (12 preceding siblings ...)
  2014-10-07  0:19 ` [PATCH 13/13] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-07  0:39 ` Rafael J. Wysocki
  2014-10-07  2:28 ` Greg Kroah-Hartman
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-07  0:39 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tuesday, October 07, 2014 02:10:56 AM Rafael J. Wysocki wrote:
> Hi Everyone,
> 
> This is version 4 of the unified device properties interface patchset.
> 
> The original cover letter from Mika is here:
> 
> http://marc.info/?l=devicetree&m=141087052200600&w=4
> 
> My cover letter for version 3 is here:
> 
> http://marc.info/?l=linux-acpi&m=141212903816560&w=4
> 
> One major change from the previous iteration is that now we will
> use the "compatible" property to match drivers to devices having
> "PRP0001" as their _HID, so for example the at25 driver doesn't
> have to add the extra ACPI match table as part of the conversion
> to the unified interface (patch [05/13] in this series).
> 
> The second major change is that I've split the driver core patch
> in two, where the first one ([02/13]) does not contain any stuff
> related to iterating over the child nodes of a given device.
> Accordingly, the whole patch series has been rearranged so that
> the relatively non-controversial patches [01-09/13], most of which
> have been ACKed already, go first and then goes the second driver
> core patch ([10/13]) and the other patches related to it.
> 
> In patches [10-13/13] I used the Arnd's suggestion to implement
> device_for_each_child_node() as a macro which makes the changes
> in patches [12-13/13] look more straightforward among other things.
> 
> I've retained the Greg's ACKs on patches [02/13] and [10/13], because
> the first of them is things ACKed by Greg only and the change in the
> second one is just an implementation detail in my opinion (Greg, please
> let me know if that's inappropriate).

I should have mentioned that the whole series is available in the
device-properties branch of the linux-pm.git tree at kernel.org.

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (13 preceding siblings ...)
  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-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
  16 siblings, 0 replies; 104+ messages in thread
From: Greg Kroah-Hartman @ 2014-10-07  2:28 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Grant Likely,
	Arnd Bergmann, Darren Hart, Mark Rutland

On Tue, Oct 07, 2014 at 02:10:56AM +0200, Rafael J. Wysocki wrote:
> Hi Everyone,
> 
> This is version 4 of the unified device properties interface patchset.
> 
> The original cover letter from Mika is here:
> 
> http://marc.info/?l=devicetree&m=141087052200600&w=4
> 
> My cover letter for version 3 is here:
> 
> http://marc.info/?l=linux-acpi&m=141212903816560&w=4
> 
> One major change from the previous iteration is that now we will
> use the "compatible" property to match drivers to devices having
> "PRP0001" as their _HID, so for example the at25 driver doesn't
> have to add the extra ACPI match table as part of the conversion
> to the unified interface (patch [05/13] in this series).
> 
> The second major change is that I've split the driver core patch
> in two, where the first one ([02/13]) does not contain any stuff
> related to iterating over the child nodes of a given device.
> Accordingly, the whole patch series has been rearranged so that
> the relatively non-controversial patches [01-09/13], most of which
> have been ACKed already, go first and then goes the second driver
> core patch ([10/13]) and the other patches related to it.
> 
> In patches [10-13/13] I used the Arnd's suggestion to implement
> device_for_each_child_node() as a macro which makes the changes
> in patches [12-13/13] look more straightforward among other things.
> 
> I've retained the Greg's ACKs on patches [02/13] and [10/13], because
> the first of them is things ACKed by Greg only and the change in the
> second one is just an implementation detail in my opinion (Greg, please
> let me know if that's inappropriate).

No objection from me, looks good.

greg k-h

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 05/13] misc: at25: Make use of device property API
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Geert Uytterhoeven @ 2014-10-07  9:10 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Grant Likely,
	Arnd Bergmann, Darren Hart, Mark Rutland

On Tue, Oct 7, 2014 at 2:14 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> @@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
>
>  /*-------------------------------------------------------------------------*/
>
> -static int at25_np_to_chip(struct device *dev,
> -                          struct device_node *np,
> -                          struct spi_eeprom *chip)
> +static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
>  {
>         u32 val;
>
>         memset(chip, 0, sizeof(*chip));
> -       strncpy(chip->name, np->name, sizeof(chip->name));
> +       strncpy(chip->name, "at25", sizeof(chip->name));

So this changes chip->name from "eeprom" (or whatever name the DTS
writer used; "eeprom" is the ePAPR-compliant name) to "at25"?

Note:The example in Documentation/devicetree/bindings/misc/at25.txt
uses "at25", not "eeprom".

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 05/13] misc: at25: Make use of device property API
  2014-10-07  9:10   ` Geert Uytterhoeven
@ 2014-10-07  9:32     ` Mika Westerberg
  0 siblings, 0 replies; 104+ messages in thread
From: Mika Westerberg @ 2014-10-07  9:32 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Grant Likely,
	Arnd Bergmann, Darren Hart, Mark Rutland

On Tue, Oct 07, 2014 at 11:10:23AM +0200, Geert Uytterhoeven wrote:
> On Tue, Oct 7, 2014 at 2:14 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > @@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct memory_accessor *mem, const char *buf,
> >
> >  /*-------------------------------------------------------------------------*/
> >
> > -static int at25_np_to_chip(struct device *dev,
> > -                          struct device_node *np,
> > -                          struct spi_eeprom *chip)
> > +static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
> >  {
> >         u32 val;
> >
> >         memset(chip, 0, sizeof(*chip));
> > -       strncpy(chip->name, np->name, sizeof(chip->name));
> > +       strncpy(chip->name, "at25", sizeof(chip->name));
> 
> So this changes chip->name from "eeprom" (or whatever name the DTS
> writer used; "eeprom" is the ePAPR-compliant name) to "at25"?

Yes.

Is there something depending on that name?

> Note:The example in Documentation/devicetree/bindings/misc/at25.txt
> uses "at25", not "eeprom".

Which is the same we use here.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Alexandre Courbot @ 2014-10-07 10:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Linus Walleij, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
>
> Some drivers need to deal with only firmware representation of its
> GPIOs. An example would be a GPIO button array driver where each button
> is described as a separate firmware node in device tree. Typically these
> child nodes do not have physical representation in the Linux device
> model.
>
> In order to help device drivers to handle such firmware child nodes we
> add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> node pointer as its second argument (the first one is the parent device
> itself), finds the GPIO using whatever is the underlying firmware
> method, and requests the GPIO properly.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

...

> +/* Child properties interface */
> +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
> +                                                const char *propname, int index);
> +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
> +                                                 const char *propname, int index);

I see the reason for these functions and am not opposed to them.
However, I wonder if we could not replace propname by a con_id that
would be resolved to one of con_id-gpio for DT and whatever naming
convention ACPI is using?

This would prevent users to name GPIOs outside of the conventions
defined in the bindings and be generally safer. Is there a particular
reason (used by some old code?) for the current direct property
access? If not, maybe we could call a slightly-modified of_find_gpio()
to resolve the GPIO property for DT, and the equivalent function for
ACPI?

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-07 10:22   ` Alexandre Courbot
@ 2014-10-07 10:40     ` Mika Westerberg
  2014-10-07 10:52       ` Alexandre Courbot
  0 siblings, 1 reply; 104+ messages in thread
From: Mika Westerberg @ 2014-10-07 10:40 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Linus Walleij,
	Greg Kroah-Hartman, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 07, 2014 at 07:22:13PM +0900, Alexandre Courbot wrote:
> On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >
> > Some drivers need to deal with only firmware representation of its
> > GPIOs. An example would be a GPIO button array driver where each button
> > is described as a separate firmware node in device tree. Typically these
> > child nodes do not have physical representation in the Linux device
> > model.
> >
> > In order to help device drivers to handle such firmware child nodes we
> > add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> > node pointer as its second argument (the first one is the parent device
> > itself), finds the GPIO using whatever is the underlying firmware
> > method, and requests the GPIO properly.
> >
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> ...
> 
> > +/* Child properties interface */
> > +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
> > +                                                const char *propname, int index);
> > +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
> > +                                                 const char *propname, int index);
> 
> I see the reason for these functions and am not opposed to them.
> However, I wonder if we could not replace propname by a con_id that
> would be resolved to one of con_id-gpio for DT and whatever naming
> convention ACPI is using?

The code in gpio-leds.c and gpio_keys_polled.c refers to "gpios" as the
property name. If we can change that somehow to work with con_id-gpio
instead without breaking things, then why not.

> This would prevent users to name GPIOs outside of the conventions
> defined in the bindings and be generally safer. Is there a particular
> reason (used by some old code?) for the current direct property
> access? If not, maybe we could call a slightly-modified of_find_gpio()
> to resolve the GPIO property for DT, and the equivalent function for
> ACPI?

Only reason I can think of is support for the existing properties that
are used directly. Drivers using gpiod_get() and friends do not need
dev_get_named_gpiod_from_child() anyway.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-07 10:40     ` Mika Westerberg
@ 2014-10-07 10:52       ` Alexandre Courbot
  2014-10-08  0:09         ` Rafael J. Wysocki
  0 siblings, 1 reply; 104+ messages in thread
From: Alexandre Courbot @ 2014-10-07 10:52 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Linus Walleij,
	Greg Kroah-Hartman, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 7, 2014 at 7:40 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Tue, Oct 07, 2014 at 07:22:13PM +0900, Alexandre Courbot wrote:
>> On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
>> >
>> > Some drivers need to deal with only firmware representation of its
>> > GPIOs. An example would be a GPIO button array driver where each button
>> > is described as a separate firmware node in device tree. Typically these
>> > child nodes do not have physical representation in the Linux device
>> > model.
>> >
>> > In order to help device drivers to handle such firmware child nodes we
>> > add dev[m]_get_named_gpiod_from_child() that takes a child firmware
>> > node pointer as its second argument (the first one is the parent device
>> > itself), finds the GPIO using whatever is the underlying firmware
>> > method, and requests the GPIO properly.
>> >
>> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> ...
>>
>> > +/* Child properties interface */
>> > +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
>> > +                                                const char *propname, int index);
>> > +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
>> > +                                                 const char *propname, int index);
>>
>> I see the reason for these functions and am not opposed to them.
>> However, I wonder if we could not replace propname by a con_id that
>> would be resolved to one of con_id-gpio for DT and whatever naming
>> convention ACPI is using?
>
> The code in gpio-leds.c and gpio_keys_polled.c refers to "gpios" as the
> property name. If we can change that somehow to work with con_id-gpio
> instead without breaking things, then why not.
>
>> This would prevent users to name GPIOs outside of the conventions
>> defined in the bindings and be generally safer. Is there a particular
>> reason (used by some old code?) for the current direct property
>> access? If not, maybe we could call a slightly-modified of_find_gpio()
>> to resolve the GPIO property for DT, and the equivalent function for
>> ACPI?
>
> Only reason I can think of is support for the existing properties that
> are used directly. Drivers using gpiod_get() and friends do not need
> dev_get_named_gpiod_from_child() anyway.

Right. Another thing is that the property handling code (active low
only for now) is duplicated again, but that can be addressed
separately.

I will have a look at gpio-leds and gpio_keys_polled to see if we
cannot make this work at a higher level. It's easier to have the
bindings respected if the code itself enforces them.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 09/12] input: gpio_keys_polled - Add support for GPIO descriptors
  2014-10-07  0:16 ` [PATCH 09/12] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-07 17:29   ` Dmitry Torokhov
  0 siblings, 0 replies; 104+ messages in thread
From: Dmitry Torokhov @ 2014-10-07 17:29 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 07, 2014 at 02:16:47AM +0200, Rafael J. Wysocki wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> GPIO descriptors are the preferred way over legacy GPIO numbers
> nowadays. Convert the driver to use GPIO descriptors internally but
> still allow passing legacy GPIO numbers from platform data to support
> existing platforms.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>


Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>


> ---
>  drivers/input/keyboard/gpio_keys_polled.c | 39 +++++++++++++++++++++----------
>  include/linux/gpio_keys.h                 |  3 +++
>  2 files changed, 30 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
> index 432d363..b7a514c 100644
> --- a/drivers/input/keyboard/gpio_keys_polled.c
> +++ b/drivers/input/keyboard/gpio_keys_polled.c
> @@ -23,6 +23,7 @@
>  #include <linux/ioport.h>
>  #include <linux/platform_device.h>
>  #include <linux/gpio.h>
> +#include <linux/gpio/consumer.h>
>  #include <linux/gpio_keys.h>
>  #include <linux/of.h>
>  #include <linux/of_platform.h>
> @@ -51,15 +52,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
>  	int state;
>  
>  	if (bdata->can_sleep)
> -		state = !!gpio_get_value_cansleep(button->gpio);
> +		state = !!gpiod_get_value_cansleep(button->gpiod);
>  	else
> -		state = !!gpio_get_value(button->gpio);
> +		state = !!gpiod_get_value(button->gpiod);
>  
>  	if (state != bdata->last_state) {
>  		unsigned int type = button->type ?: EV_KEY;
>  
> -		input_event(input, type, button->code,
> -			    !!(state ^ button->active_low));
> +		input_event(input, type, button->code, state);
>  		input_sync(input);
>  		bdata->count = 0;
>  		bdata->last_state = state;
> @@ -259,7 +259,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
>  	for (i = 0; i < pdata->nbuttons; i++) {
>  		struct gpio_keys_button *button = &pdata->buttons[i];
>  		struct gpio_keys_button_data *bdata = &bdev->data[i];
> -		unsigned int gpio = button->gpio;
>  		unsigned int type = button->type ?: EV_KEY;
>  
>  		if (button->wakeup) {
> @@ -267,15 +266,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
>  			return -EINVAL;
>  		}
>  
> -		error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
> -					      button->desc ? : DRV_NAME);
> -		if (error) {
> -			dev_err(dev, "unable to claim gpio %u, err=%d\n",
> -				gpio, error);
> -			return error;
> +		/*
> +		 * Legacy GPIO number so request the GPIO here and
> +		 * convert it to descriptor.
> +		 */
> +		if (!button->gpiod && gpio_is_valid(button->gpio)) {
> +			unsigned flags = 0;
> +
> +			if (button->active_low)
> +				flags |= GPIOF_ACTIVE_LOW;
> +
> +			error = devm_gpio_request_one(&pdev->dev, button->gpio,
> +					flags, button->desc ? : DRV_NAME);
> +			if (error) {
> +				dev_err(dev, "unable to claim gpio %u, err=%d\n",
> +					button->gpio, error);
> +				return error;
> +			}
> +
> +			button->gpiod = gpio_to_desc(button->gpio);
>  		}
>  
> -		bdata->can_sleep = gpio_cansleep(gpio);
> +		if (IS_ERR(button->gpiod))
> +			return PTR_ERR(button->gpiod);
> +
> +		bdata->can_sleep = gpiod_cansleep(button->gpiod);
>  		bdata->last_state = -1;
>  		bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
>  						pdata->poll_interval);
> diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
> index 8b62246..ee2d8c6 100644
> --- a/include/linux/gpio_keys.h
> +++ b/include/linux/gpio_keys.h
> @@ -2,6 +2,7 @@
>  #define _GPIO_KEYS_H
>  
>  struct device;
> +struct gpio_desc;
>  
>  /**
>   * struct gpio_keys_button - configuration parameters
> @@ -17,6 +18,7 @@ struct device;
>   *			disable button via sysfs
>   * @value:		axis value for %EV_ABS
>   * @irq:		Irq number in case of interrupt keys
> + * @gpiod:		GPIO descriptor
>   */
>  struct gpio_keys_button {
>  	unsigned int code;
> @@ -29,6 +31,7 @@ struct gpio_keys_button {
>  	bool can_disable;
>  	int value;
>  	unsigned int irq;
> +	struct gpio_desc *gpiod;
>  };
>  
>  /**
> -- 
> 1.9.3
> 
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 13/13] input: gpio_keys_polled - Make use of device property API
  2014-10-07  0:19 ` [PATCH 13/13] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-07 17:30   ` Dmitry Torokhov
  0 siblings, 0 replies; 104+ messages in thread
From: Dmitry Torokhov @ 2014-10-07 17:30 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 07, 2014 at 02:19:20AM +0200, Rafael J. Wysocki wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> Make use of device property API in this driver so that both OF based
> system and ACPI based system can use this driver.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>

> ---
>  drivers/input/keyboard/gpio_keys_polled.c |   81 +++++++++++-------------------
>  1 file changed, 31 insertions(+), 50 deletions(-)
> 
> Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
> ===================================================================
> --- linux-pm.orig/drivers/input/keyboard/gpio_keys_polled.c
> +++ linux-pm/drivers/input/keyboard/gpio_keys_polled.c
> @@ -25,9 +25,7 @@
>  #include <linux/gpio.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/gpio_keys.h>
> -#include <linux/of.h>
> -#include <linux/of_platform.h>
> -#include <linux/of_gpio.h>
> +#include <linux/property.h>
>  
>  #define DRV_NAME	"gpio-keys-polled"
>  
> @@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struc
>  		pdata->disable(bdev->dev);
>  }
>  
> -#ifdef CONFIG_OF
>  static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
>  {
> -	struct device_node *node, *pp;
>  	struct gpio_keys_platform_data *pdata;
>  	struct gpio_keys_button *button;
> +	void *child;
>  	int error;
>  	int nbuttons;
> -	int i;
> -
> -	node = dev->of_node;
> -	if (!node)
> -		return NULL;
>  
> -	nbuttons = of_get_child_count(node);
> +	nbuttons = device_get_child_node_count(dev);
>  	if (nbuttons == 0)
>  		return NULL;
>  
> @@ -126,52 +118,50 @@ static struct gpio_keys_platform_data *g
>  		return ERR_PTR(-ENOMEM);
>  
>  	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
> -	pdata->nbuttons = nbuttons;
>  
> -	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
> -	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
> +	pdata->rep = !device_get_property(dev, "autorepeat", NULL);
> +	device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
>  
> -	i = 0;
> -	for_each_child_of_node(node, pp) {
> -		int gpio;
> -		enum of_gpio_flags flags;
> -
> -		if (!of_find_property(pp, "gpios", NULL)) {
> -			pdata->nbuttons--;
> -			dev_warn(dev, "Found button without gpios\n");
> -			continue;
> -		}
> +	device_for_each_child_node(dev, child) {
> +		struct gpio_desc *desc;
>  
> -		gpio = of_get_gpio_flags(pp, 0, &flags);
> -		if (gpio < 0) {
> -			error = gpio;
> +		desc = devm_get_named_gpiod_from_child(dev, child, "gpios", 0);
> +		if (IS_ERR(desc)) {
> +			error = PTR_ERR(desc);
>  			if (error != -EPROBE_DEFER)
>  				dev_err(dev,
>  					"Failed to get gpio flags, error: %d\n",
>  					error);
> +			device_put_child_node(dev, child);
>  			return ERR_PTR(error);
>  		}
>  
> -		button = &pdata->buttons[i++];
> -
> -		button->gpio = gpio;
> -		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
> +		button = &pdata->buttons[pdata->nbuttons++];
> +		button->gpiod = desc;
>  
> -		if (of_property_read_u32(pp, "linux,code", &button->code)) {
> -			dev_err(dev, "Button without keycode: 0x%x\n",
> -				button->gpio);
> +		if (device_child_property_read_u32(dev, child, "linux,code",
> +						   &button->code)) {
> +			dev_err(dev, "Button without keycode: %d\n",
> +				pdata->nbuttons - 1);
> +			device_put_child_node(dev, child);
>  			return ERR_PTR(-EINVAL);
>  		}
>  
> -		button->desc = of_get_property(pp, "label", NULL);
> +		device_child_property_read_string(dev, child, "label",
> +						  &button->desc);
>  
> -		if (of_property_read_u32(pp, "linux,input-type", &button->type))
> +		if (device_child_property_read_u32(dev, child,
> +						   "linux,input-type",
> +						   &button->type))
>  			button->type = EV_KEY;
>  
> -		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
> -
> -		if (of_property_read_u32(pp, "debounce-interval",
> -					 &button->debounce_interval))
> +		button->wakeup = !device_get_child_property(dev, child,
> +							    "gpio-key,wakeup",
> +							    NULL);
> +
> +		if (device_child_property_read_u32(dev, child,
> +						   "debounce-interval",
> +						   &button->debounce_interval))
>  			button->debounce_interval = 5;
>  	}
>  
> @@ -187,15 +177,6 @@ static const struct of_device_id gpio_ke
>  };
>  MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
>  
> -#else
> -
> -static inline struct gpio_keys_platform_data *
> -gpio_keys_polled_get_devtree_pdata(struct device *dev)
> -{
> -	return NULL;
> -}
> -#endif
> -
>  static int gpio_keys_polled_probe(struct platform_device *pdev)
>  {
>  	struct device *dev = &pdev->dev;
> @@ -323,7 +304,7 @@ static struct platform_driver gpio_keys_
>  	.driver	= {
>  		.name	= DRV_NAME,
>  		.owner	= THIS_MODULE,
> -		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
> +		.of_match_table = gpio_keys_polled_of_match,
>  	},
>  };
>  module_platform_driver(gpio_keys_polled_driver);
> 

-- 
Dmitry

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-07 10:52       ` Alexandre Courbot
@ 2014-10-08  0:09         ` Rafael J. Wysocki
  2014-10-08  2:55           ` Alexandre Courbot
  0 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-08  0:09 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Mika Westerberg, Linux Kernel Mailing List, Linus Walleij,
	Greg Kroah-Hartman, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tuesday, October 07, 2014 07:52:02 PM Alexandre Courbot wrote:
> On Tue, Oct 7, 2014 at 7:40 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Tue, Oct 07, 2014 at 07:22:13PM +0900, Alexandre Courbot wrote:
> >> On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> >> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> >
> >> > Some drivers need to deal with only firmware representation of its
> >> > GPIOs. An example would be a GPIO button array driver where each button
> >> > is described as a separate firmware node in device tree. Typically these
> >> > child nodes do not have physical representation in the Linux device
> >> > model.
> >> >
> >> > In order to help device drivers to handle such firmware child nodes we
> >> > add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> >> > node pointer as its second argument (the first one is the parent device
> >> > itself), finds the GPIO using whatever is the underlying firmware
> >> > method, and requests the GPIO properly.
> >> >
> >> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>
> >> ...
> >>
> >> > +/* Child properties interface */
> >> > +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
> >> > +                                                const char *propname, int index);
> >> > +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
> >> > +                                                 const char *propname, int index);
> >>
> >> I see the reason for these functions and am not opposed to them.
> >> However, I wonder if we could not replace propname by a con_id that
> >> would be resolved to one of con_id-gpio for DT and whatever naming
> >> convention ACPI is using?
> >
> > The code in gpio-leds.c and gpio_keys_polled.c refers to "gpios" as the
> > property name. If we can change that somehow to work with con_id-gpio
> > instead without breaking things, then why not.
> >
> >> This would prevent users to name GPIOs outside of the conventions
> >> defined in the bindings and be generally safer. Is there a particular
> >> reason (used by some old code?) for the current direct property
> >> access? If not, maybe we could call a slightly-modified of_find_gpio()
> >> to resolve the GPIO property for DT, and the equivalent function for
> >> ACPI?
> >
> > Only reason I can think of is support for the existing properties that
> > are used directly. Drivers using gpiod_get() and friends do not need
> > dev_get_named_gpiod_from_child() anyway.
> 
> Right. Another thing is that the property handling code (active low
> only for now) is duplicated again, but that can be addressed
> separately.
> 
> I will have a look at gpio-leds and gpio_keys_polled to see if we
> cannot make this work at a higher level. It's easier to have the
> bindings respected if the code itself enforces them.

I'm wondering if that can be done after merging the current work?

We'll be able to use the drivers in question with our hardware in the
meantime then ...

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-08  0:09         ` Rafael J. Wysocki
@ 2014-10-08  2:55           ` Alexandre Courbot
  2014-10-08 14:01             ` Rafael J. Wysocki
  0 siblings, 1 reply; 104+ messages in thread
From: Alexandre Courbot @ 2014-10-08  2:55 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Mika Westerberg, Linux Kernel Mailing List, Linus Walleij,
	Greg Kroah-Hartman, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Wed, Oct 8, 2014 at 9:09 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Tuesday, October 07, 2014 07:52:02 PM Alexandre Courbot wrote:
>> On Tue, Oct 7, 2014 at 7:40 PM, Mika Westerberg
>> <mika.westerberg@linux.intel.com> wrote:
>> > On Tue, Oct 07, 2014 at 07:22:13PM +0900, Alexandre Courbot wrote:
>> >> On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>> >> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
>> >> >
>> >> > Some drivers need to deal with only firmware representation of its
>> >> > GPIOs. An example would be a GPIO button array driver where each button
>> >> > is described as a separate firmware node in device tree. Typically these
>> >> > child nodes do not have physical representation in the Linux device
>> >> > model.
>> >> >
>> >> > In order to help device drivers to handle such firmware child nodes we
>> >> > add dev[m]_get_named_gpiod_from_child() that takes a child firmware
>> >> > node pointer as its second argument (the first one is the parent device
>> >> > itself), finds the GPIO using whatever is the underlying firmware
>> >> > method, and requests the GPIO properly.
>> >> >
>> >> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> >> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> >>
>> >> ...
>> >>
>> >> > +/* Child properties interface */
>> >> > +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
>> >> > +                                                const char *propname, int index);
>> >> > +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
>> >> > +                                                 const char *propname, int index);
>> >>
>> >> I see the reason for these functions and am not opposed to them.
>> >> However, I wonder if we could not replace propname by a con_id that
>> >> would be resolved to one of con_id-gpio for DT and whatever naming
>> >> convention ACPI is using?
>> >
>> > The code in gpio-leds.c and gpio_keys_polled.c refers to "gpios" as the
>> > property name. If we can change that somehow to work with con_id-gpio
>> > instead without breaking things, then why not.
>> >
>> >> This would prevent users to name GPIOs outside of the conventions
>> >> defined in the bindings and be generally safer. Is there a particular
>> >> reason (used by some old code?) for the current direct property
>> >> access? If not, maybe we could call a slightly-modified of_find_gpio()
>> >> to resolve the GPIO property for DT, and the equivalent function for
>> >> ACPI?
>> >
>> > Only reason I can think of is support for the existing properties that
>> > are used directly. Drivers using gpiod_get() and friends do not need
>> > dev_get_named_gpiod_from_child() anyway.
>>
>> Right. Another thing is that the property handling code (active low
>> only for now) is duplicated again, but that can be addressed
>> separately.
>>
>> I will have a look at gpio-leds and gpio_keys_polled to see if we
>> cannot make this work at a higher level. It's easier to have the
>> bindings respected if the code itself enforces them.
>
> I'm wondering if that can be done after merging the current work?
>
> We'll be able to use the drivers in question with our hardware in the
> meantime then ...

Yeah, that's probably ok. The properties in question already exist so
we will have to support them anyway ; it's just a matter of seeing
whether we can improve the proposed way.

So for now:

Acked-by: Alexandre Courbot <acourbot@nvidia.com>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 11/13] gpio: Support for unified device properties interface
  2014-10-08  2:55           ` Alexandre Courbot
@ 2014-10-08 14:01             ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-08 14:01 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Mika Westerberg, Linux Kernel Mailing List, Linus Walleij,
	Greg Kroah-Hartman, ACPI Devel Maling List, Aaron Lu, devicetree,
	Dmitry Torokhov, Bryan Wu, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Wednesday, October 08, 2014 11:55:08 AM Alexandre Courbot wrote:
> On Wed, Oct 8, 2014 at 9:09 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > On Tuesday, October 07, 2014 07:52:02 PM Alexandre Courbot wrote:
> >> On Tue, Oct 7, 2014 at 7:40 PM, Mika Westerberg
> >> <mika.westerberg@linux.intel.com> wrote:
> >> > On Tue, Oct 07, 2014 at 07:22:13PM +0900, Alexandre Courbot wrote:
> >> >> On Tue, Oct 7, 2014 at 9:18 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> >> >> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> >> >
> >> >> > Some drivers need to deal with only firmware representation of its
> >> >> > GPIOs. An example would be a GPIO button array driver where each button
> >> >> > is described as a separate firmware node in device tree. Typically these
> >> >> > child nodes do not have physical representation in the Linux device
> >> >> > model.
> >> >> >
> >> >> > In order to help device drivers to handle such firmware child nodes we
> >> >> > add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> >> >> > node pointer as its second argument (the first one is the parent device
> >> >> > itself), finds the GPIO using whatever is the underlying firmware
> >> >> > method, and requests the GPIO properly.
> >> >> >
> >> >> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> >> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >> >>
> >> >> ...
> >> >>
> >> >> > +/* Child properties interface */
> >> >> > +struct gpio_desc *dev_get_named_gpiod_from_child(struct device *dev, void *child,
> >> >> > +                                                const char *propname, int index);
> >> >> > +struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev, void *child,
> >> >> > +                                                 const char *propname, int index);
> >> >>
> >> >> I see the reason for these functions and am not opposed to them.
> >> >> However, I wonder if we could not replace propname by a con_id that
> >> >> would be resolved to one of con_id-gpio for DT and whatever naming
> >> >> convention ACPI is using?
> >> >
> >> > The code in gpio-leds.c and gpio_keys_polled.c refers to "gpios" as the
> >> > property name. If we can change that somehow to work with con_id-gpio
> >> > instead without breaking things, then why not.
> >> >
> >> >> This would prevent users to name GPIOs outside of the conventions
> >> >> defined in the bindings and be generally safer. Is there a particular
> >> >> reason (used by some old code?) for the current direct property
> >> >> access? If not, maybe we could call a slightly-modified of_find_gpio()
> >> >> to resolve the GPIO property for DT, and the equivalent function for
> >> >> ACPI?
> >> >
> >> > Only reason I can think of is support for the existing properties that
> >> > are used directly. Drivers using gpiod_get() and friends do not need
> >> > dev_get_named_gpiod_from_child() anyway.
> >>
> >> Right. Another thing is that the property handling code (active low
> >> only for now) is duplicated again, but that can be addressed
> >> separately.
> >>
> >> I will have a look at gpio-leds and gpio_keys_polled to see if we
> >> cannot make this work at a higher level. It's easier to have the
> >> bindings respected if the code itself enforces them.
> >
> > I'm wondering if that can be done after merging the current work?
> >
> > We'll be able to use the drivers in question with our hardware in the
> > meantime then ...
> 
> Yeah, that's probably ok. The properties in question already exist so
> we will have to support them anyway ; it's just a matter of seeing
> whether we can improve the proposed way.
> 
> So for now:
> 
> Acked-by: Alexandre Courbot <acourbot@nvidia.com>

Thanks!

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 12/13] leds: leds-gpio: Make use of device property API
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-08 14:04 UTC (permalink / raw)
  To: Bryan Wu
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tuesday, October 07, 2014 02:18:45 AM Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Make use of device property API in this driver so that both OF and ACPI
> based system can use the same driver.
> 
> This change contains material from Max Eliaser and Mika Westerberg.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Bryan, can you please tell me if you are OK with this patch?

You said you were for one of the previous versions if I remember correctly,
but it's changed quite a bit since then, so can you please check this new
version too?

> ---
>  drivers/leds/leds-gpio.c |   67 +++++++++++++++++++++--------------------------
>  1 file changed, 30 insertions(+), 37 deletions(-)
> 
> Index: linux-pm/drivers/leds/leds-gpio.c
> ===================================================================
> --- linux-pm.orig/drivers/leds/leds-gpio.c
> +++ linux-pm/drivers/leds/leds-gpio.c
> @@ -15,13 +15,11 @@
>  #include <linux/gpio.h>
>  #include <linux/gpio/consumer.h>
>  #include <linux/leds.h>
> -#include <linux/of.h>
> -#include <linux/of_platform.h>
> -#include <linux/of_gpio.h>
>  #include <linux/slab.h>
>  #include <linux/workqueue.h>
>  #include <linux/module.h>
>  #include <linux/err.h>
> +#include <linux/property.h>
>  
>  struct gpio_led_data {
>  	struct led_classdev cdev;
> @@ -171,40 +169,41 @@ static inline int sizeof_gpio_leds_priv(
>  		(sizeof(struct gpio_led_data) * num_leds);
>  }
>  
> -/* Code to create from OpenFirmware platform devices */
> -#ifdef CONFIG_OF_GPIO
> -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
> +static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
>  {
> -	struct device_node *np = pdev->dev.of_node, *child;
> +	struct device *dev = &pdev->dev;
>  	struct gpio_leds_priv *priv;
>  	int count, ret;
> +	void *child;
>  
> -	/* count LEDs in this device, so we know how much to allocate */
> -	count = of_get_available_child_count(np);
> +	count = device_get_child_node_count(dev);
>  	if (!count)
>  		return ERR_PTR(-ENODEV);
>  
> -	for_each_available_child_of_node(np, child)
> -		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
> -			return ERR_PTR(-EPROBE_DEFER);
> -
> -	priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
> -			GFP_KERNEL);
> +	priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
>  	if (!priv)
>  		return ERR_PTR(-ENOMEM);
>  
> -	for_each_available_child_of_node(np, child) {
> +	device_for_each_child_node(dev, child) {
>  		struct gpio_led led = {};
> -		enum of_gpio_flags flags;
> -		const char *state;
> +		const char *state = NULL;
> +
> +		led.gpiod = devm_get_named_gpiod_from_child(dev, child,
> +							    "gpios", 0);
> +		if (IS_ERR(led.gpiod)) {
> +			device_put_child_node(dev, child);
> +			goto err;
> +		}
>  
> -		led.gpio = of_get_gpio_flags(child, 0, &flags);
> -		led.active_low = flags & OF_GPIO_ACTIVE_LOW;
> -		led.name = of_get_property(child, "label", NULL) ? : child->name;
> -		led.default_trigger =
> -			of_get_property(child, "linux,default-trigger", NULL);
> -		state = of_get_property(child, "default-state", NULL);
> -		if (state) {
> +		device_child_property_read_string(dev, child,
> +						  "label", &led.name);
> +		device_child_property_read_string(dev, child,
> +						  "linux,default-trigger",
> +						  &led.default_trigger);
> +
> +		if (!device_child_property_read_string(dev, child,
> +						       "linux,default_state",
> +						       &state)) {
>  			if (!strcmp(state, "keep"))
>  				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
>  			else if (!strcmp(state, "on"))
> @@ -213,13 +212,14 @@ static struct gpio_leds_priv *gpio_leds_
>  				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
>  		}
>  
> -		if (of_get_property(child, "retain-state-suspended", NULL))
> +		if (!device_get_child_property(dev, child,
> +					       "retain-state-suspended", NULL))
>  			led.retain_state_suspended = 1;
>  
>  		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
> -				      &pdev->dev, NULL);
> +				      dev, NULL);
>  		if (ret < 0) {
> -			of_node_put(child);
> +			device_put_child_node(dev, child);
>  			goto err;
>  		}
>  	}
> @@ -238,13 +238,6 @@ static const struct of_device_id of_gpio
>  };
>  
>  MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
> -#else /* CONFIG_OF_GPIO */
> -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
> -{
> -	return ERR_PTR(-ENODEV);
> -}
> -#endif /* CONFIG_OF_GPIO */
> -
>  
>  static int gpio_led_probe(struct platform_device *pdev)
>  {
> @@ -273,7 +266,7 @@ static int gpio_led_probe(struct platfor
>  			}
>  		}
>  	} else {
> -		priv = gpio_leds_create_of(pdev);
> +		priv = gpio_leds_create(pdev);
>  		if (IS_ERR(priv))
>  			return PTR_ERR(priv);
>  	}
> @@ -300,7 +293,7 @@ static struct platform_driver gpio_led_d
>  	.driver		= {
>  		.name	= "leds-gpio",
>  		.owner	= THIS_MODULE,
> -		.of_match_table = of_match_ptr(of_gpio_leds_match),
> +		.of_match_table = of_gpio_leds_match,
>  	},
>  };
>  
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 12/13] leds: leds-gpio: Make use of device property API
  2014-10-08 14:04   ` Rafael J. Wysocki
@ 2014-10-08 17:47     ` Bryan Wu
  2014-10-08 22:02       ` Rafael J. Wysocki
  0 siblings, 1 reply; 104+ messages in thread
From: Bryan Wu @ 2014-10-08 17:47 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Wed, Oct 8, 2014 at 7:04 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Tuesday, October 07, 2014 02:18:45 AM Rafael J. Wysocki wrote:
>> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>>
>> Make use of device property API in this driver so that both OF and ACPI
>> based system can use the same driver.
>>
>> This change contains material from Max Eliaser and Mika Westerberg.
>>
>> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>
> Bryan, can you please tell me if you are OK with this patch?
>
> You said you were for one of the previous versions if I remember correctly,
> but it's changed quite a bit since then, so can you please check this new
> version too?
>

Sure, the new one is even better than before. Please go ahead with my Ack
Acked-by: Bryan Wu <cooloney@gmail.com>

Thanks,
-Bryan

>> ---
>>  drivers/leds/leds-gpio.c |   67 +++++++++++++++++++++--------------------------
>>  1 file changed, 30 insertions(+), 37 deletions(-)
>>
>> Index: linux-pm/drivers/leds/leds-gpio.c
>> ===================================================================
>> --- linux-pm.orig/drivers/leds/leds-gpio.c
>> +++ linux-pm/drivers/leds/leds-gpio.c
>> @@ -15,13 +15,11 @@
>>  #include <linux/gpio.h>
>>  #include <linux/gpio/consumer.h>
>>  #include <linux/leds.h>
>> -#include <linux/of.h>
>> -#include <linux/of_platform.h>
>> -#include <linux/of_gpio.h>
>>  #include <linux/slab.h>
>>  #include <linux/workqueue.h>
>>  #include <linux/module.h>
>>  #include <linux/err.h>
>> +#include <linux/property.h>
>>
>>  struct gpio_led_data {
>>       struct led_classdev cdev;
>> @@ -171,40 +169,41 @@ static inline int sizeof_gpio_leds_priv(
>>               (sizeof(struct gpio_led_data) * num_leds);
>>  }
>>
>> -/* Code to create from OpenFirmware platform devices */
>> -#ifdef CONFIG_OF_GPIO
>> -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
>> +static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
>>  {
>> -     struct device_node *np = pdev->dev.of_node, *child;
>> +     struct device *dev = &pdev->dev;
>>       struct gpio_leds_priv *priv;
>>       int count, ret;
>> +     void *child;
>>
>> -     /* count LEDs in this device, so we know how much to allocate */
>> -     count = of_get_available_child_count(np);
>> +     count = device_get_child_node_count(dev);
>>       if (!count)
>>               return ERR_PTR(-ENODEV);
>>
>> -     for_each_available_child_of_node(np, child)
>> -             if (of_get_gpio(child, 0) == -EPROBE_DEFER)
>> -                     return ERR_PTR(-EPROBE_DEFER);
>> -
>> -     priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
>> -                     GFP_KERNEL);
>> +     priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
>>       if (!priv)
>>               return ERR_PTR(-ENOMEM);
>>
>> -     for_each_available_child_of_node(np, child) {
>> +     device_for_each_child_node(dev, child) {
>>               struct gpio_led led = {};
>> -             enum of_gpio_flags flags;
>> -             const char *state;
>> +             const char *state = NULL;
>> +
>> +             led.gpiod = devm_get_named_gpiod_from_child(dev, child,
>> +                                                         "gpios", 0);
>> +             if (IS_ERR(led.gpiod)) {
>> +                     device_put_child_node(dev, child);
>> +                     goto err;
>> +             }
>>
>> -             led.gpio = of_get_gpio_flags(child, 0, &flags);
>> -             led.active_low = flags & OF_GPIO_ACTIVE_LOW;
>> -             led.name = of_get_property(child, "label", NULL) ? : child->name;
>> -             led.default_trigger =
>> -                     of_get_property(child, "linux,default-trigger", NULL);
>> -             state = of_get_property(child, "default-state", NULL);
>> -             if (state) {
>> +             device_child_property_read_string(dev, child,
>> +                                               "label", &led.name);
>> +             device_child_property_read_string(dev, child,
>> +                                               "linux,default-trigger",
>> +                                               &led.default_trigger);
>> +
>> +             if (!device_child_property_read_string(dev, child,
>> +                                                    "linux,default_state",
>> +                                                    &state)) {
>>                       if (!strcmp(state, "keep"))
>>                               led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
>>                       else if (!strcmp(state, "on"))
>> @@ -213,13 +212,14 @@ static struct gpio_leds_priv *gpio_leds_
>>                               led.default_state = LEDS_GPIO_DEFSTATE_OFF;
>>               }
>>
>> -             if (of_get_property(child, "retain-state-suspended", NULL))
>> +             if (!device_get_child_property(dev, child,
>> +                                            "retain-state-suspended", NULL))
>>                       led.retain_state_suspended = 1;
>>
>>               ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
>> -                                   &pdev->dev, NULL);
>> +                                   dev, NULL);
>>               if (ret < 0) {
>> -                     of_node_put(child);
>> +                     device_put_child_node(dev, child);
>>                       goto err;
>>               }
>>       }
>> @@ -238,13 +238,6 @@ static const struct of_device_id of_gpio
>>  };
>>
>>  MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
>> -#else /* CONFIG_OF_GPIO */
>> -static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
>> -{
>> -     return ERR_PTR(-ENODEV);
>> -}
>> -#endif /* CONFIG_OF_GPIO */
>> -
>>
>>  static int gpio_led_probe(struct platform_device *pdev)
>>  {
>> @@ -273,7 +266,7 @@ static int gpio_led_probe(struct platfor
>>                       }
>>               }
>>       } else {
>> -             priv = gpio_leds_create_of(pdev);
>> +             priv = gpio_leds_create(pdev);
>>               if (IS_ERR(priv))
>>                       return PTR_ERR(priv);
>>       }
>> @@ -300,7 +293,7 @@ static struct platform_driver gpio_led_d
>>       .driver         = {
>>               .name   = "leds-gpio",
>>               .owner  = THIS_MODULE,
>> -             .of_match_table = of_match_ptr(of_gpio_leds_match),
>> +             .of_match_table = of_gpio_leds_match,
>>       },
>>  };
>>
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
> --
> I speak only for myself.
> Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 12/13] leds: leds-gpio: Make use of device property API
  2014-10-08 17:47     ` Bryan Wu
@ 2014-10-08 22:02       ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-08 22:02 UTC (permalink / raw)
  To: Bryan Wu
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Grant Likely, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Wednesday, October 08, 2014 10:47:16 AM Bryan Wu wrote:
> On Wed, Oct 8, 2014 at 7:04 AM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > On Tuesday, October 07, 2014 02:18:45 AM Rafael J. Wysocki wrote:
> >> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >>
> >> Make use of device property API in this driver so that both OF and ACPI
> >> based system can use the same driver.
> >>
> >> This change contains material from Max Eliaser and Mika Westerberg.
> >>
> >> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> >
> > Bryan, can you please tell me if you are OK with this patch?
> >
> > You said you were for one of the previous versions if I remember correctly,
> > but it's changed quite a bit since then, so can you please check this new
> > version too?
> >
> 
> Sure, the new one is even better than before. Please go ahead with my Ack
> Acked-by: Bryan Wu <cooloney@gmail.com>

Thanks!


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 04/13] ACPI: Document ACPI device specific properties
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-13 12:41 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, Darren Hart,
	Mark Rutland

On Tue, 07 Oct 2014 02:14:06 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> This document describes the data format and interfaces of ACPI device
> specific properties.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  Documentation/acpi/properties.txt |  376 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 376 insertions(+)
>  create mode 100644 Documentation/acpi/properties.txt
> 
> Index: linux-pm/Documentation/acpi/properties.txt
> ===================================================================
> --- /dev/null
> +++ linux-pm/Documentation/acpi/properties.txt
> @@ -0,0 +1,376 @@
> +ACPI device properties
> +======================
> +This document describes the format and interfaces of ACPI device
> +properties as specified in "Device Properties UUID For _DSD" available
> +here:
> +
> +http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
> +
> +1. Introduction
> +---------------
> +In systems that use ACPI and want to take advantage of device specific
> +properties, there needs to be a standard way to return and extract
> +name-value pairs for a given ACPI device.
> +
> +An ACPI device that wants to export its properties must implement a
> +static name called _DSD that takes no arguments and returns a package of
> +packages:
> +
> +	Name (_DSD, Package () {
> +		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +		Package () {
> +			Package () {"name1", <VALUE1>},
> +			Package () {"name2", <VALUE2>}
> +		}
> +	})
> +
> +The UUID identifies contents of the following package. In case of ACPI
> +device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301.
> +
> +In each returned package, the first item is the name and must be a string.
> +The corresponding value can be a string, integer, reference, or package. If
> +a package it may only contain strings, integers, and references.
> +
> +An example device where we might need properties is a device that uses
> +GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to
> +know which GPIO is used for which purpose.
> +
> +To solve this we add the following ACPI device properties to the device:
> +
> +	Device (DEV0)
> +	{
> +		Name (_CRS, ResourceTemplate () {
> +			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> +				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}
> +			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> +				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}
> +			...
> +		})
> +
> +		Name (_DSD, Package () {
> +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +			Package () {
> +				Package () {"reset-gpio", {^DEV0, 0, 0, 0}},
> +				Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}},
> +			}
> +		})
> +	}
> +
> +Now the device driver can reference the GPIOs using names instead of
> +using indexes.

Ummm... so this is kind of odd. Why would arguments be needed for the
gpio reference, or a device trying to reference itself (^DEV0) within
it's own device.

It looks like it is trying to shoehorn DT design patterns into the ACPI
tables when ACPI already has a native method for doing the same thing.
That concerns me.

[...]
> +In addition to simple object references it is also possible to have object
> +references with arguments. These are represented in ASL as follows:
> +
> +	Device (\_SB.PCI0.PWM)
> +	{
> +		Name (_DSD, Package () {
> +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +			Package () {
> +				Package () {"#pwm-cells", 2}
> +			}
> +		})
> +	}
> +
> +	Device (\_SB.PCI0.BL)
> +	{
> +		Name (_DSD, Package () {
> +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +			Package () {
> +				Package () {
> +					"pwms",
> +					Package () {
> +						\_SB.PCI0.PWM, 0, 5000000,
> +						\_SB.PCI0.PWM, 1, 4500000,
> +					}
> +				}
> +			}
> +		})
> +	}

This worries me even more. #x-cells is a very devicetree oriented
pattern that looks wrong for ACPI data. I would expect PWM resources in
ACPI to look much like ACPI GPIO resources or Serial bus resources.

g.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 01/13] ACPI: Add support for device specific properties
  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
  0 siblings, 0 replies; 104+ messages in thread
From: Grant Likely @ 2014-10-13 12:47 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, Darren Hart,
	Mark Rutland

On Tue, 07 Oct 2014 02:12:23 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> Device Tree is used in many embedded systems to describe the system
> configuration to the OS. It supports attaching properties or name-value
> pairs to the devices it describe. With these properties one can pass
> additional information to the drivers that would not be available
> otherwise.
> 
> ACPI is another configuration mechanism (among other things) typically
> seen, but not limited to, x86 machines. ACPI allows passing arbitrary
> data from methods but there has not been mechanism equivalent to Device
> Tree until the introduction of _DSD in the recent publication of the
> ACPI 5.1 specification.
> 
> In order to facilitate ACPI usage in systems where Device Tree is
> typically used, it would be beneficial to standardize a way to retrieve
> Device Tree style properties from ACPI devices, which is what we do in
> this patch.
> 
> If a given device described in ACPI namespace wants to export properties it
> must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
> that returns the properties in a package of packages. For example:
> 
> 	Name (_DSD, Package () {
> 		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> 		Package () {
> 			Package () {"name1", <VALUE1>},
> 			Package () {"name2", <VALUE2>},
> 			...
> 		}
> 	})
> 
> The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
> and is documented in the ACPI 5.1 companion document called "_DSD
> Implementation Guide" [1], [2].
> 
> We add several helper functions that can be used to extract these
> properties and convert them to different Linux data types.
> 
> The ultimate goal is that we only have one device property API that
> retrieves the requested properties from Device Tree or from ACPI
> transparent to the caller.
> 
> [1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
> [2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
> 
> Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
> Reviewed-by: Josh Triplett <josh@joshtriplett.org>
> Signed-off-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

This patch seems fine.

Reviewed-by: Grant Likely <grant.likely@linaro.org>

> ---
>  drivers/acpi/Makefile   |    1 
>  drivers/acpi/internal.h |    6 
>  drivers/acpi/property.c |  364 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c     |    2 
>  include/acpi/acpi_bus.h |    7 
>  include/linux/acpi.h    |   40 +++++
>  6 files changed, 420 insertions(+)
>  create mode 100644 drivers/acpi/property.c
> 
> Index: linux-pm/drivers/acpi/Makefile
> ===================================================================
> --- linux-pm.orig/drivers/acpi/Makefile
> +++ linux-pm/drivers/acpi/Makefile
> @@ -46,6 +46,7 @@ acpi-y				+= acpi_pnp.o
>  acpi-y				+= power.o
>  acpi-y				+= event.o
>  acpi-y				+= sysfs.o
> +acpi-y				+= property.o
>  acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
>  acpi-$(CONFIG_DEBUG_FS)		+= debugfs.o
>  acpi-$(CONFIG_ACPI_NUMA)	+= numa.o
> Index: linux-pm/drivers/acpi/internal.h
> ===================================================================
> --- linux-pm.orig/drivers/acpi/internal.h
> +++ linux-pm/drivers/acpi/internal.h
> @@ -181,4 +181,10 @@ struct platform_device *acpi_create_plat
>  bool acpi_osi_is_win8(void);
>  #endif
>  
> +/*--------------------------------------------------------------------------
> +				Device properties
> +  -------------------------------------------------------------------------- */
> +void acpi_init_properties(struct acpi_device *adev);
> +void acpi_free_properties(struct acpi_device *adev);
> +
>  #endif /* _ACPI_INTERNAL_H_ */
> Index: linux-pm/drivers/acpi/property.c
> ===================================================================
> --- /dev/null
> +++ linux-pm/drivers/acpi/property.c
> @@ -0,0 +1,364 @@
> +/*
> + * ACPI device specific properties support.
> + *
> + * Copyright (C) 2014, Intel Corporation
> + * All rights reserved.
> + *
> + * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
> + *          Darren Hart <dvhart@linux.intel.com>
> + *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + */
> +
> +#include <linux/acpi.h>
> +#include <linux/device.h>
> +#include <linux/export.h>
> +
> +#include "internal.h"
> +
> +/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
> +static const u8 prp_uuid[16] = {
> +	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
> +	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
> +};
> +
> +static bool acpi_property_value_ok(const union acpi_object *value)
> +{
> +	int j;
> +
> +	/*
> +	 * The value must be an integer, a string, a reference, or a package
> +	 * whose every element must be an integer, a string, or a reference.
> +	 */
> +	switch (value->type) {
> +	case ACPI_TYPE_INTEGER:
> +	case ACPI_TYPE_STRING:
> +	case ACPI_TYPE_LOCAL_REFERENCE:
> +		return true;
> +
> +	case ACPI_TYPE_PACKAGE:
> +		for (j = 0; j < value->package.count; j++)
> +			switch (value->package.elements[j].type) {
> +			case ACPI_TYPE_INTEGER:
> +			case ACPI_TYPE_STRING:
> +			case ACPI_TYPE_LOCAL_REFERENCE:
> +				continue;
> +
> +			default:
> +				return false;
> +			}
> +
> +		return true;
> +	}
> +	return false;
> +}
> +
> +static bool acpi_properties_format_valid(const union acpi_object *properties)
> +{
> +	int i;
> +
> +	for (i = 0; i < properties->package.count; i++) {
> +		const union acpi_object *property;
> +
> +		property = &properties->package.elements[i];
> +		/*
> +		 * Only two elements allowed, the first one must be a string and
> +		 * the second one has to satisfy certain conditions.
> +		 */
> +		if (property->package.count != 2
> +		    || property->package.elements[0].type != ACPI_TYPE_STRING
> +		    || !acpi_property_value_ok(&property->package.elements[1]))
> +			return false;
> +	}
> +	return true;
> +}
> +
> +void acpi_init_properties(struct acpi_device *adev)
> +{
> +	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> +	const union acpi_object *desc;
> +	acpi_status status;
> +	int i;
> +
> +	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
> +					    ACPI_TYPE_PACKAGE);
> +	if (ACPI_FAILURE(status))
> +		return;
> +
> +	desc = buf.pointer;
> +	if (desc->package.count % 2)
> +		goto fail;
> +
> +	/* Look for the device properties UUID. */
> +	for (i = 0; i < desc->package.count; i += 2) {
> +		const union acpi_object *uuid, *properties;
> +
> +		uuid = &desc->package.elements[i];
> +		properties = &desc->package.elements[i + 1];
> +
> +		/*
> +		 * The first element must be a UUID and the second one must be
> +		 * a package.
> +		 */
> +		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
> +		    || properties->type != ACPI_TYPE_PACKAGE)
> +			break;
> +
> +		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
> +			continue;
> +
> +		/*
> +		 * We found the matching UUID. Now validate the format of the
> +		 * package immediately following it.
> +		 */
> +		if (!acpi_properties_format_valid(properties))
> +			break;
> +
> +		adev->data.pointer = buf.pointer;
> +		adev->data.properties = properties;
> +		return;
> +	}
> +
> + fail:
> +	dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
> +	ACPI_FREE(buf.pointer);
> +}
> +
> +void acpi_free_properties(struct acpi_device *adev)
> +{
> +	ACPI_FREE((void *)adev->data.pointer);
> +	adev->data.pointer = NULL;
> +	adev->data.properties = NULL;
> +}
> +
> +/**
> + * acpi_dev_get_property - return an ACPI property with given name
> + * @adev: ACPI device to get property
> + * @name: Name of the property
> + * @type: Expected property type
> + * @obj: Location to store the property value (if not %NULL)
> + *
> + * Look up a property with @name and store a pointer to the resulting ACPI
> + * object at the location pointed to by @obj if found.
> + *
> + * Callers must not attempt to free the returned objects.  These objects will be
> + * freed by the ACPI core automatically during the removal of @adev.
> + *
> + * Return: %0 if property with @name has been found (success),
> + *         %-EINVAL if the arguments are invalid,
> + *         %-ENODATA if the property doesn't exist,
> + *         %-EPROTO if the property value type doesn't match @type.
> + */
> +int acpi_dev_get_property(struct acpi_device *adev, const char *name,
> +			  acpi_object_type type, const union acpi_object **obj)
> +{
> +	const union acpi_object *properties;
> +	int i;
> +
> +	if (!adev || !name)
> +		return -EINVAL;
> +
> +	if (!adev->data.pointer || !adev->data.properties)
> +		return -ENODATA;
> +
> +	properties = adev->data.properties;
> +	for (i = 0; i < properties->package.count; i++) {
> +		const union acpi_object *propname, *propvalue;
> +		const union acpi_object *property;
> +
> +		property = &properties->package.elements[i];
> +
> +		propname = &property->package.elements[0];
> +		propvalue = &property->package.elements[1];
> +
> +		if (!strcmp(name, propname->string.pointer)) {
> +			if (type != ACPI_TYPE_ANY && propvalue->type != type)
> +				return -EPROTO;
> +			else if (obj)
> +				*obj = propvalue;
> +
> +			return 0;
> +		}
> +	}
> +	return -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(acpi_dev_get_property);
> +
> +/**
> + * acpi_dev_get_property_array - return an ACPI array property with given name
> + * @adev: ACPI device to get property
> + * @name: Name of the property
> + * @type: Expected type of array elements
> + * @obj: Location to store a pointer to the property value (if not NULL)
> + *
> + * Look up an array property with @name and store a pointer to the resulting
> + * ACPI object at the location pointed to by @obj if found.
> + *
> + * Callers must not attempt to free the returned objects.  Those objects will be
> + * freed by the ACPI core automatically during the removal of @adev.
> + *
> + * Return: %0 if array property (package) with @name has been found (success),
> + *         %-EINVAL if the arguments are invalid,
> + *         %-ENODATA if the property doesn't exist,
> + *         %-EPROTO if the property is not a package or the type of its elements
> + *           doesn't match @type.
> + */
> +int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
> +				acpi_object_type type,
> +				const union acpi_object **obj)
> +{
> +	const union acpi_object *prop;
> +	int ret, i;
> +
> +	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
> +	if (ret)
> +		return ret;
> +
> +	if (type != ACPI_TYPE_ANY) {
> +		/* Check that all elements are of correct type. */
> +		for (i = 0; i < prop->package.count; i++)
> +			if (prop->package.elements[i].type != type)
> +				return -EPROTO;
> +	}
> +	if (obj)
> +		*obj = prop;
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
> +
> +/**
> + * acpi_dev_get_property_reference - returns handle to the referenced object
> + * @adev: ACPI device to get property
> + * @name: Name of the property
> + * @size_prop: Name of the "size" property in referenced object
> + * @index: Index of the reference to return
> + * @args: Location to store the returned reference with optional arguments
> + *
> + * Find property with @name, verifify that it is a package containing at least
> + * one object reference and if so, store the ACPI device object pointer to the
> + * target object in @args->adev.
> + *
> + * If the reference includes arguments (@size_prop is not %NULL) follow the
> + * reference and check whether or not there is an integer property @size_prop
> + * under the target object and if so, whether or not its value matches the
> + * number of arguments that follow the reference.  If there's more than one
> + * reference in the property value package, @index is used to select the one to
> + * return.
> + *
> + * Return: %0 on success, negative error code on failure.
> + */
> +int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
> +				    const char *size_prop, size_t index,
> +				    struct acpi_reference_args *args)
> +{
> +	const union acpi_object *element, *end;
> +	const union acpi_object *obj;
> +	struct acpi_device *device;
> +	int ret, idx = 0;
> +
> +	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
> +	if (ret)
> +		return ret;
> +
> +	/*
> +	 * The simplest case is when the value is a single reference.  Just
> +	 * return that reference then.
> +	 */
> +	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
> +		if (size_prop || index)
> +			return -EINVAL;
> +
> +		ret = acpi_bus_get_device(obj->reference.handle, &device);
> +		if (ret)
> +			return ret;
> +
> +		args->adev = device;
> +		args->nargs = 0;
> +		return 0;
> +	}
> +
> +	/*
> +	 * If it is not a single reference, then it is a package of
> +	 * references followed by number of ints as follows:
> +	 *
> +	 *  Package () { REF, INT, REF, INT, INT }
> +	 *
> +	 * The index argument is then used to determine which reference
> +	 * the caller wants (along with the arguments).
> +	 */
> +	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
> +		return -EPROTO;
> +
> +	element = obj->package.elements;
> +	end = element + obj->package.count;
> +
> +	while (element < end) {
> +		u32 nargs, i;
> +
> +		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
> +			return -EPROTO;
> +
> +		ret = acpi_bus_get_device(element->reference.handle, &device);
> +		if (ret)
> +			return -ENODEV;
> +
> +		element++;
> +		nargs = 0;
> +
> +		if (size_prop) {
> +			const union acpi_object *prop;
> +
> +			/*
> +			 * Find out how many arguments the refenced object
> +			 * expects by reading its size_prop property.
> +			 */
> +			ret = acpi_dev_get_property(device, size_prop,
> +						    ACPI_TYPE_INTEGER, &prop);
> +			if (ret)
> +				return ret;
> +
> +			nargs = prop->integer.value;
> +			if (nargs > MAX_ACPI_REFERENCE_ARGS
> +			    || element + nargs > end)
> +				return -EPROTO;
> +
> +			/*
> +			 * Skip to the start of the arguments and verify
> +			 * that they all are in fact integers.
> +			 */
> +			for (i = 0; i < nargs; i++)
> +				if (element[i].type != ACPI_TYPE_INTEGER)
> +					return -EPROTO;
> +		} else {
> +			/* assume following integer elements are all args */
> +			for (i = 0; element + i < end; i++) {
> +				int type = element[i].type;
> +
> +				if (type == ACPI_TYPE_INTEGER)
> +					nargs++;
> +				else if (type == ACPI_TYPE_LOCAL_REFERENCE)
> +					break;
> +				else
> +					return -EPROTO;
> +			}
> +		}
> +
> +		if (idx++ == index) {
> +			args->adev = device;
> +			args->nargs = nargs;
> +			for (i = 0; i < nargs; i++)
> +				args->args[i] = element[i].integer.value;
> +
> +			return 0;
> +		}
> +
> +		element += nargs;
> +	}
> +
> +	return -EPROTO;
> +}
> +EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
> Index: linux-pm/drivers/acpi/scan.c
> ===================================================================
> --- linux-pm.orig/drivers/acpi/scan.c
> +++ linux-pm/drivers/acpi/scan.c
> @@ -884,6 +884,7 @@ static void acpi_device_release(struct d
>  {
>  	struct acpi_device *acpi_dev = to_acpi_device(dev);
>  
> +	acpi_free_properties(acpi_dev);
>  	acpi_free_pnp_ids(&acpi_dev->pnp);
>  	acpi_free_power_resources_lists(acpi_dev);
>  	kfree(acpi_dev);
> @@ -1888,6 +1889,7 @@ void acpi_init_device_object(struct acpi
>  	acpi_set_device_status(device, sta);
>  	acpi_device_get_busid(device);
>  	acpi_set_pnp_ids(handle, &device->pnp, type);
> +	acpi_init_properties(device);
>  	acpi_bus_get_flags(device);
>  	device->flags.match_driver = false;
>  	device->flags.initialized = true;
> Index: linux-pm/include/acpi/acpi_bus.h
> ===================================================================
> --- linux-pm.orig/include/acpi/acpi_bus.h
> +++ linux-pm/include/acpi/acpi_bus.h
> @@ -337,6 +337,12 @@ struct acpi_device_physical_node {
>  	bool put_online:1;
>  };
>  
> +/* ACPI Device Specific Data (_DSD) */
> +struct acpi_device_data {
> +	const union acpi_object *pointer;
> +	const union acpi_object *properties;
> +};
> +
>  /* Device */
>  struct acpi_device {
>  	int device_type;
> @@ -353,6 +359,7 @@ struct acpi_device {
>  	struct acpi_device_wakeup wakeup;
>  	struct acpi_device_perf performance;
>  	struct acpi_device_dir dir;
> +	struct acpi_device_data data;
>  	struct acpi_scan_handler *handler;
>  	struct acpi_hotplug_context *hp;
>  	struct acpi_driver *driver;
> Index: linux-pm/include/linux/acpi.h
> ===================================================================
> --- linux-pm.orig/include/linux/acpi.h
> +++ linux-pm/include/linux/acpi.h
> @@ -658,4 +658,44 @@ do {									\
>  #endif
>  #endif
>  
> +/* Device properties */
> +
> +#define MAX_ACPI_REFERENCE_ARGS	8
> +struct acpi_reference_args {
> +	struct acpi_device *adev;
> +	size_t nargs;
> +	u64 args[MAX_ACPI_REFERENCE_ARGS];
> +};
> +
> +#ifdef CONFIG_ACPI
> +int acpi_dev_get_property(struct acpi_device *adev, const char *name,
> +			  acpi_object_type type, const union acpi_object **obj);
> +int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
> +				acpi_object_type type,
> +				const union acpi_object **obj);
> +int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
> +				    const char *cells_name, size_t index,
> +				    struct acpi_reference_args *args);
> +#else
> +static inline int acpi_dev_get_property(struct acpi_device *adev,
> +					const char *name, acpi_object_type type,
> +					const union acpi_object **obj)
> +{
> +	return -ENXIO;
> +}
> +static inline int acpi_dev_get_property_array(struct acpi_device *adev,
> +					      const char *name,
> +					      acpi_object_type type,
> +					      const union acpi_object **obj)
> +{
> +	return -ENXIO;
> +}
> +static inline int acpi_dev_get_property_reference(struct acpi_device *adev,
> +				const char *name, const char *cells_name,
> +				size_t index, struct acpi_reference_args *args)
> +{
> +	return -ENXIO;
> +}
> +#endif
> +
>  #endif	/*_LINUX_ACPI_H*/
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 04/13] ACPI: Document ACPI device specific properties
  2014-10-13 12:41   ` Grant Likely
@ 2014-10-14  9:42     ` Mika Westerberg
  0 siblings, 0 replies; 104+ messages in thread
From: Mika Westerberg @ 2014-10-14  9:42 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Mon, Oct 13, 2014 at 02:41:32PM +0200, Grant Likely wrote:
> On Tue, 07 Oct 2014 02:14:06 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> > 
> > This document describes the data format and interfaces of ACPI device
> > specific properties.
> > 
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Signed-off-by: Darren Hart <dvhart@linux.intel.com>
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > ---
> >  Documentation/acpi/properties.txt |  376 ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 376 insertions(+)
> >  create mode 100644 Documentation/acpi/properties.txt
> > 
> > Index: linux-pm/Documentation/acpi/properties.txt
> > ===================================================================
> > --- /dev/null
> > +++ linux-pm/Documentation/acpi/properties.txt
> > @@ -0,0 +1,376 @@
> > +ACPI device properties
> > +======================
> > +This document describes the format and interfaces of ACPI device
> > +properties as specified in "Device Properties UUID For _DSD" available
> > +here:
> > +
> > +http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
> > +
> > +1. Introduction
> > +---------------
> > +In systems that use ACPI and want to take advantage of device specific
> > +properties, there needs to be a standard way to return and extract
> > +name-value pairs for a given ACPI device.
> > +
> > +An ACPI device that wants to export its properties must implement a
> > +static name called _DSD that takes no arguments and returns a package of
> > +packages:
> > +
> > +	Name (_DSD, Package () {
> > +		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +		Package () {
> > +			Package () {"name1", <VALUE1>},
> > +			Package () {"name2", <VALUE2>}
> > +		}
> > +	})
> > +
> > +The UUID identifies contents of the following package. In case of ACPI
> > +device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301.
> > +
> > +In each returned package, the first item is the name and must be a string.
> > +The corresponding value can be a string, integer, reference, or package. If
> > +a package it may only contain strings, integers, and references.
> > +
> > +An example device where we might need properties is a device that uses
> > +GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to
> > +know which GPIO is used for which purpose.
> > +
> > +To solve this we add the following ACPI device properties to the device:
> > +
> > +	Device (DEV0)
> > +	{
> > +		Name (_CRS, ResourceTemplate () {
> > +			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> > +				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}
> > +			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> > +				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}
> > +			...
> > +		})
> > +
> > +		Name (_DSD, Package () {
> > +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +			Package () {
> > +				Package () {"reset-gpio", {^DEV0, 0, 0, 0}},
> > +				Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}},
> > +			}
> > +		})
> > +	}
> > +
> > +Now the device driver can reference the GPIOs using names instead of
> > +using indexes.
> 
> Ummm... so this is kind of odd. Why would arguments be needed for the
> gpio reference, or a device trying to reference itself (^DEV0) within
> it's own device.

The reference doesn't need to be the device itself. It can be the parent
device for example.

Also arguments contain information that is not available in ACPI GpioIo
resources:

 - Name of the GPIO
 - Is the GPIO active low

Remember that we can write the above also like:

		Name (_CRS, ResourceTemplate () {
			GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
				"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0, 1}
			...
		})

		Name (_DSD, Package () {
			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
			Package () {
				Package () {"reset-gpio", {^DEV0, 0, 0, 0}},
				Package () {"shutdown-gpio", {^DEV0, 0, 1, 0}},
			}
		})

So the first two integers are used as indexes in _CRS and in the
pinlist.

> It looks like it is trying to shoehorn DT design patterns into the ACPI
> tables when ACPI already has a native method for doing the same thing.
> That concerns me.

There is no native method in ACPI to do what we are doing.

> [...]
> > +In addition to simple object references it is also possible to have object
> > +references with arguments. These are represented in ASL as follows:
> > +
> > +	Device (\_SB.PCI0.PWM)
> > +	{
> > +		Name (_DSD, Package () {
> > +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +			Package () {
> > +				Package () {"#pwm-cells", 2}
> > +			}
> > +		})
> > +	}
> > +
> > +	Device (\_SB.PCI0.BL)
> > +	{
> > +		Name (_DSD, Package () {
> > +			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +			Package () {
> > +				Package () {
> > +					"pwms",
> > +					Package () {
> > +						\_SB.PCI0.PWM, 0, 5000000,
> > +						\_SB.PCI0.PWM, 1, 4500000,
> > +					}
> > +				}
> > +			}
> > +		})
> > +	}
> 
> This worries me even more. #x-cells is a very devicetree oriented
> pattern that looks wrong for ACPI data. I would expect PWM resources in
> ACPI to look much like ACPI GPIO resources or Serial bus resources.

This was already discussed in v3 version of the series and our argument
here is that we should be able to reuse the existing DT schemas as much
as possible as long as ACPI does not have a native method to describe
the thing (and it makes sense in general).

However, nothing prevents us to extend the
acpi_dev_get_property_reference() in future to support a more ACPI style
way of doing things:

http://www.spinics.net/lists/linux-acpi/msg53367.html

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 03/13] ACPI: Allow drivers to match using Device Tree compatible property
  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
  0 siblings, 0 replies; 104+ messages in thread
From: Grant Likely @ 2014-10-14 13:38 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, Darren Hart,
	Mark Rutland

On Tue, 07 Oct 2014 02:13:29 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> We have lots of existing Device Tree enabled drivers and allocating
> separate _HID for each is not feasible. Instead we allocate special _HID
> "PRP0001" that means that the match should be done using Device Tree
> compatible property using driver's .of_match_table instead if the driver
> is missing .acpi_match_table.
> 
> If there is a need to distinguish from where the device is enumerated
> (DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Looks okay to me.

Reviewed-by: Grant Likely <grant.likely@linaro.org>

> ---
>  drivers/acpi/property.c | 34 +++++++++++++++++
>  drivers/acpi/scan.c     | 97 +++++++++++++++++++++++++++++++++++++++++++------
>  include/acpi/acpi_bus.h |  1 +
>  include/linux/acpi.h    |  8 +---
>  4 files changed, 123 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 680f7f1..ff53eb8 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -76,6 +76,37 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
>  	return true;
>  }
>  
> +static void acpi_init_of_compatible(struct acpi_device *adev)
> +{
> +	const union acpi_object *of_compatible;
> +	struct acpi_hardware_id *hwid;
> +	bool acpi_of = false;
> +
> +	/*
> +	 * Check if the special PRP0001 ACPI ID is present and in that
> +	 * case we fill in Device Tree compatible properties for this
> +	 * device.
> +	 */
> +	list_for_each_entry(hwid, &adev->pnp.ids, list) {
> +		if (!strcmp(hwid->id, "PRP0001")) {
> +			acpi_of = true;
> +			break;
> +		}
> +	}
> +
> +	if (!acpi_of)
> +		return;
> +
> +	if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
> +					&of_compatible)) {
> +		acpi_handle_warn(adev->handle,
> +				 "PRP0001 requires compatible property\n");
> +		return;
> +	}
> +
> +	adev->data.of_compatible = of_compatible;
> +}
> +
>  void acpi_init_properties(struct acpi_device *adev)
>  {
>  	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> @@ -119,6 +150,8 @@ void acpi_init_properties(struct acpi_device *adev)
>  
>  		adev->data.pointer = buf.pointer;
>  		adev->data.properties = properties;
> +
> +		acpi_init_of_compatible(adev);
>  		return;
>  	}
>  
> @@ -130,6 +163,7 @@ void acpi_init_properties(struct acpi_device *adev)
>  void acpi_free_properties(struct acpi_device *adev)
>  {
>  	ACPI_FREE((void *)adev->data.pointer);
> +	adev->data.of_compatible = NULL;
>  	adev->data.pointer = NULL;
>  	adev->data.properties = NULL;
>  }
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 1979ab3..bc999f1 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -124,17 +124,51 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
>  	if (list_empty(&acpi_dev->pnp.ids))
>  		return 0;
>  
> -	len = snprintf(modalias, size, "acpi:");
> -	size -= len;
> -
> -	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
> -		count = snprintf(&modalias[len], size, "%s:", id->id);
> -		if (count < 0)
> -			return -EINVAL;
> -		if (count >= size)
> -			return -ENOMEM;
> -		len += count;
> -		size -= count;
> +	/*
> +	 * If the device has PRP0001 we expose DT compatible modalias
> +	 * instead in form of of:NnameTCcompatible.
> +	 */
> +	if (acpi_dev->data.of_compatible) {
> +		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> +		const union acpi_object *of_compatible, *obj;
> +		char *c;
> +		int i;
> +
> +		acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
> +		/* DT strings are all in lower case */
> +		for (c = buf.pointer; *c != '\0'; c++)
> +			*c = tolower(*c);
> +
> +		len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
> +		ACPI_FREE(buf.pointer);
> +
> +		of_compatible = acpi_dev->data.of_compatible;
> +		for (i = 0; i < of_compatible->package.count; i++) {
> +			obj = &of_compatible->package.elements[i];
> +
> +			count = snprintf(&modalias[len], size, "C%s",
> +					 obj->string.pointer);
> +			if (count < 0)
> +				return -EINVAL;
> +			if (count >= size)
> +				return -ENOMEM;
> +
> +			len += count;
> +			size -= count;
> +		}
> +	} else {
> +		len = snprintf(modalias, size, "acpi:");
> +		size -= len;
> +
> +		list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
> +			count = snprintf(&modalias[len], size, "%s:", id->id);
> +			if (count < 0)
> +				return -EINVAL;
> +			if (count >= size)
> +				return -ENOMEM;
> +			len += count;
> +			size -= count;
> +		}
>  	}
>  
>  	modalias[len] = '\0';
> @@ -864,6 +898,47 @@ int acpi_match_device_ids(struct acpi_device *device,
>  }
>  EXPORT_SYMBOL(acpi_match_device_ids);
>  
> +/* Performs match against special "PRP0001" shoehorn ACPI ID */
> +static bool acpi_of_driver_match_device(struct device *dev,
> +					const struct device_driver *drv)
> +{
> +	const union acpi_object *of_compatible;
> +	struct acpi_device *adev;
> +	int i;
> +
> +	adev = ACPI_COMPANION(dev);
> +	if (!adev)
> +		return false;
> +
> +	of_compatible = adev->data.of_compatible;
> +	if (!drv->of_match_table || !of_compatible)
> +		return false;
> +
> +	/* Now we can look for the driver DT compatible strings */
> +	for (i = 0; i < of_compatible->package.count; i++) {
> +		const struct of_device_id *id;
> +		const union acpi_object *obj;
> +
> +		obj = &of_compatible->package.elements[i];
> +
> +		for (id = drv->of_match_table; id->compatible[0]; id++)
> +			if (!strcasecmp(obj->string.pointer, id->compatible))
> +				return true;
> +	}
> +
> +	return false;
> +}
> +
> +bool acpi_driver_match_device(struct device *dev,
> +			      const struct device_driver *drv)
> +{
> +	if (!drv->acpi_match_table)
> +		return acpi_of_driver_match_device(dev, drv);
> +
> +	return !!acpi_match_device(drv->acpi_match_table, dev);
> +}
> +EXPORT_SYMBOL_GPL(acpi_driver_match_device);
> +
>  static void acpi_free_power_resources_lists(struct acpi_device *device)
>  {
>  	int i;
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index f9734fa..98cd723 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -341,6 +341,7 @@ struct acpi_device_physical_node {
>  struct acpi_device_data {
>  	const union acpi_object *pointer;
>  	const union acpi_object *properties;
> +	const union acpi_object *of_compatible;
>  };
>  
>  /* Device */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 18c1bc3..11aa6b8 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -424,12 +424,8 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
>  const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
>  					       const struct device *dev);
>  
> -static inline bool acpi_driver_match_device(struct device *dev,
> -					    const struct device_driver *drv)
> -{
> -	return !!acpi_match_device(drv->acpi_match_table, dev);
> -}
> -
> +extern bool acpi_driver_match_device(struct device *dev,
> +				     const struct device_driver *drv);
>  int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
>  int acpi_device_modalias(struct device *, char *, int);
>  
> -- 
> 1.9.3
> 
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-14 13:44 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, Darren Hart,
	Mark Rutland

On Tue, 07 Oct 2014 02:15:18 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
> other things as well) returned by _CRS. Previously we were only able to
> use integer index to find the corresponding GPIO, which is pretty error
> prone if the order changes.
> 
> With _DSD we can now query GPIOs using name instead of an integer index,
> like the below example shows:
> 
>   // Bluetooth device with reset and shutdown GPIOs
>   Device (BTH)
>   {
>       Name (_HID, ...)
> 
>       Name (_CRS, ResourceTemplate ()
>       {
>           GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
>                   "\\_SB.GPO0", 0, ResourceConsumer) {15}
>           GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
>                   "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
>       })
> 
>       Name (_DSD, Package ()
>       {
>           ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
>           Package ()
> 	  {
>               Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
>               Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
>           }
>       })
>   }
> 
> The format of the supported GPIO property is:
> 
>   Package () { "name", Package () { ref, index, pin, active_low }}
> 
>   ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
>         typically this is the device itself (BTH in our case).
>   index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
>   pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
>   active_low - If 1 the GPIO is marked as active_low.
> 
> Since ACPI GpioIo() resource does not have field saying whether it is
> active low or high, the "active_low" argument can be used here. Setting
> it to 1 marks the GPIO as active low.
> 
> In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
> resource, second pin in that resource with the GPIO number of 31.
> 
> This patch implements necessary support to gpiolib for extracting GPIOs
> using _DSD device properties.

Patch looks good, but please put the above description into
/Documentation until we've got a better place to document extra bindings.

g.

> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Acked-by: Linus Walleij <linus.walleij@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/gpio/gpiolib-acpi.c | 78 +++++++++++++++++++++++++++++++++++++--------
>  drivers/gpio/gpiolib.c      | 30 ++++++++++++++---
>  drivers/gpio/gpiolib.h      |  7 ++--
>  3 files changed, 94 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
> index 687476f..b14c045 100644
> --- a/drivers/gpio/gpiolib-acpi.c
> +++ b/drivers/gpio/gpiolib-acpi.c
> @@ -293,6 +293,7 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
>  struct acpi_gpio_lookup {
>  	struct acpi_gpio_info info;
>  	int index;
> +	int pin_index;
>  	struct gpio_desc *desc;
>  	int n;
>  };
> @@ -306,13 +307,24 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  
>  	if (lookup->n++ == lookup->index && !lookup->desc) {
>  		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
> +		int pin_index = lookup->pin_index;
> +
> +		if (pin_index >= agpio->pin_table_length)
> +			return 1;
>  
>  		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
> -					      agpio->pin_table[0]);
> +					      agpio->pin_table[pin_index]);
>  		lookup->info.gpioint =
>  			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
> -		lookup->info.active_low =
> -			agpio->polarity == ACPI_ACTIVE_LOW;
> +
> +		/*
> +		 * ActiveLow is only specified for GpioInt resource. If
> +		 * GpioIo is used then the only way to set the flag is
> +		 * to use _DSD "gpios" property.
> +		 */
> +		if (lookup->info.gpioint)
> +			lookup->info.active_low =
> +				agpio->polarity == ACPI_ACTIVE_LOW;
>  	}
>  
>  	return 1;
> @@ -320,40 +332,75 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  
>  /**
>   * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
> - * @dev: pointer to a device to get GPIO from
> + * @adev: pointer to a ACPI device to get GPIO from
> + * @propname: Property name of the GPIO (optional)
>   * @index: index of GpioIo/GpioInt resource (starting from %0)
>   * @info: info pointer to fill in (optional)
>   *
> - * Function goes through ACPI resources for @dev and based on @index looks
> + * Function goes through ACPI resources for @adev and based on @index looks
>   * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
>   * and returns it. @index matches GpioIo/GpioInt resources only so if there
>   * are total %3 GPIO resources, the index goes from %0 to %2.
>   *
> + * If @propname is specified the GPIO is looked using device property. In
> + * that case @index is used to select the GPIO entry in the property value
> + * (in case of multiple).
> + *
>   * If the GPIO cannot be translated or there is an error an ERR_PTR is
>   * returned.
>   *
>   * Note: if the GPIO resource has multiple entries in the pin list, this
>   * function only returns the first.
>   */
> -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
> +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
> +					  const char *propname, int index,
>  					  struct acpi_gpio_info *info)
>  {
>  	struct acpi_gpio_lookup lookup;
>  	struct list_head resource_list;
> -	struct acpi_device *adev;
> -	acpi_handle handle;
> +	bool active_low = false;
>  	int ret;
>  
> -	if (!dev)
> -		return ERR_PTR(-EINVAL);
> -
> -	handle = ACPI_HANDLE(dev);
> -	if (!handle || acpi_bus_get_device(handle, &adev))
> +	if (!adev)
>  		return ERR_PTR(-ENODEV);
>  
>  	memset(&lookup, 0, sizeof(lookup));
>  	lookup.index = index;
>  
> +	if (propname) {
> +		struct acpi_reference_args args;
> +
> +		dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
> +
> +		memset(&args, 0, sizeof(args));
> +		ret = acpi_dev_get_property_reference(adev, propname, NULL,
> +						      index, &args);
> +		if (ret)
> +			return ERR_PTR(ret);
> +
> +		/*
> +		 * The property was found and resolved so need to
> +		 * lookup the GPIO based on returned args instead.
> +		 */
> +		adev = args.adev;
> +		if (args.nargs >= 2) {
> +			lookup.index = args.args[0];
> +			lookup.pin_index = args.args[1];
> +			/*
> +			 * 3rd argument, if present is used to
> +			 * specify active_low.
> +			 */
> +			if (args.nargs >= 3)
> +				active_low = !!args.args[2];
> +		}
> +
> +		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
> +			dev_name(&adev->dev), args.nargs,
> +			args.args[0], args.args[1], args.args[2]);
> +	} else {
> +		dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
> +	}
> +
>  	INIT_LIST_HEAD(&resource_list);
>  	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
>  				     &lookup);
> @@ -362,8 +409,11 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
>  
>  	acpi_dev_free_resource_list(&resource_list);
>  
> -	if (lookup.desc && info)
> +	if (lookup.desc && info) {
>  		*info = lookup.info;
> +		if (active_low)
> +			info->active_low = active_low;
> +	}
>  
>  	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
>  }
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index c68d037..4c86601 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -1487,14 +1487,36 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
>  					unsigned int idx,
>  					enum gpio_lookup_flags *flags)
>  {
> +	static const char * const suffixes[] = { "gpios", "gpio" };
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
>  	struct acpi_gpio_info info;
>  	struct gpio_desc *desc;
> +	char propname[32];
> +	int i;
>  
> -	desc = acpi_get_gpiod_by_index(dev, idx, &info);
> -	if (IS_ERR(desc))
> -		return desc;
> +	/* Try first from _DSD */
> +	for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
> +		if (con_id && strcmp(con_id, "gpios")) {
> +			snprintf(propname, sizeof(propname), "%s-%s",
> +				 con_id, suffixes[i]);
> +		} else {
> +			snprintf(propname, sizeof(propname), "%s",
> +				 suffixes[i]);
> +		}
> +
> +		desc = acpi_get_gpiod_by_index(adev, propname, 0, &info);
> +		if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
> +			break;
> +	}
> +
> +	/* Then from plain _CRS GPIOs */
> +	if (IS_ERR(desc)) {
> +		desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
> +		if (IS_ERR(desc))
> +			return desc;
> +	}
>  
> -	if (info.gpioint && info.active_low)
> +	if (info.active_low)
>  		*flags |= GPIO_ACTIVE_LOW;
>  
>  	return desc;
> diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
> index 9db2b6a..e3a5211 100644
> --- a/drivers/gpio/gpiolib.h
> +++ b/drivers/gpio/gpiolib.h
> @@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
>  void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
>  void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
>  
> -struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
> +struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
> +					  const char *propname, int index,
>  					  struct acpi_gpio_info *info);
>  #else
>  static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
> @@ -47,8 +48,8 @@ static inline void
>  acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
>  
>  static inline struct gpio_desc *
> -acpi_get_gpiod_by_index(struct device *dev, int index,
> -			struct acpi_gpio_info *info)
> +acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
> +			int index, struct acpi_gpio_info *info)
>  {
>  	return ERR_PTR(-ENOSYS);
>  }
> -- 
> 1.9.3
> 
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH 06/13] gpio / ACPI: Add support for _DSD device properties
  2014-10-14 13:44   ` Grant Likely
@ 2014-10-15  8:46     ` Mika Westerberg
  0 siblings, 0 replies; 104+ messages in thread
From: Mika Westerberg @ 2014-10-15  8:46 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Arnd Bergmann,
	Darren Hart, Mark Rutland

On Tue, Oct 14, 2014 at 03:44:03PM +0200, Grant Likely wrote:
> On Tue, 07 Oct 2014 02:15:18 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> > 
> > With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
> > other things as well) returned by _CRS. Previously we were only able to
> > use integer index to find the corresponding GPIO, which is pretty error
> > prone if the order changes.
> > 
> > With _DSD we can now query GPIOs using name instead of an integer index,
> > like the below example shows:
> > 
> >   // Bluetooth device with reset and shutdown GPIOs
> >   Device (BTH)
> >   {
> >       Name (_HID, ...)
> > 
> >       Name (_CRS, ResourceTemplate ()
> >       {
> >           GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> >                   "\\_SB.GPO0", 0, ResourceConsumer) {15}
> >           GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
> >                   "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
> >       })
> > 
> >       Name (_DSD, Package ()
> >       {
> >           ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> >           Package ()
> > 	  {
> >               Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
> >               Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
> >           }
> >       })
> >   }
> > 
> > The format of the supported GPIO property is:
> > 
> >   Package () { "name", Package () { ref, index, pin, active_low }}
> > 
> >   ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
> >         typically this is the device itself (BTH in our case).
> >   index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
> >   pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
> >   active_low - If 1 the GPIO is marked as active_low.
> > 
> > Since ACPI GpioIo() resource does not have field saying whether it is
> > active low or high, the "active_low" argument can be used here. Setting
> > it to 1 marks the GPIO as active low.
> > 
> > In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
> > resource, second pin in that resource with the GPIO number of 31.
> > 
> > This patch implements necessary support to gpiolib for extracting GPIOs
> > using _DSD device properties.
> 
> Patch looks good, but please put the above description into
> /Documentation until we've got a better place to document extra bindings.

Thanks for the review.

If you don't mind, I would like to make a separate patch on top of this
series adding this description to Documentation/acpi/properties.txt.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (14 preceding siblings ...)
  2014-10-07  2:28 ` Greg Kroah-Hartman
@ 2014-10-15 13:04 ` David Woodhouse
  2014-10-15 13:15   ` Mark Rutland
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
  16 siblings, 1 reply; 104+ messages in thread
From: David Woodhouse @ 2014-10-15 13:04 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Grant Likely,
	Arnd Bergmann, Darren Hart, Mark Rutland

[-- Attachment #1: Type: text/plain, Size: 5881 bytes --]

Here's a completely untested patch to convert of_serial to be usable via
ACPI properties too. The properties themselves were fairly
straightforward; the interesting part is converting to
platform_get_irq() and platform_get_resource() — in the latter case
first trying IORESOURCE_MEM then IORESOURCE_IO if that fails.

Does this look sane? We'll probably want to think about renaming the
module and the config option too, but that can come after the basic
functionality.

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 26cec64..be95a4c 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1094,14 +1094,14 @@ config SERIAL_NETX_CONSOLE
 	  you can make it the console by answering Y to this option.
 
 config SERIAL_OF_PLATFORM
-	tristate "Serial port on Open Firmware platform bus"
-	depends on OF
+	tristate "Serial port on firmware platform bus"
+	depends on OF || ACPI
 	depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
 	help
-	  If you have a PowerPC based system that has serial ports
-	  on a platform specific bus, you should enable this option.
-	  Currently, only 8250 compatible ports are supported, but
-	  others can easily be added.
+	  If you have a system which advertises its serial ports through
+	  devicetree or ACPI, you should enable this option. Currently
+	  only 8250 compatible and NWP ports and are supported, but others
+	  can easily be added.
 
 config SERIAL_OMAP
 	tristate "OMAP serial port support"
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 68d4455..73ee9af 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -57,13 +57,14 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 			int type, struct uart_port *port,
 			struct of_serial_info *info)
 {
-	struct resource resource;
-	struct device_node *np = ofdev->dev.of_node;
+	struct resource *resource;
 	u32 clk, spd, prop;
+	unsigned char iotype = UPIO_MEM;
+	u32 res_start;
 	int ret;
 
 	memset(port, 0, sizeof *port);
-	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+	if (device_property_read_u32(&ofdev->dev, "clock-frequency", &clk)) {
 
 		/* Get clk rate through clk driver if present */
 		info->clk = clk_get(&ofdev->dev, NULL);
@@ -77,40 +78,52 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 		clk = clk_get_rate(info->clk);
 	}
 	/* If current-speed was set, then try not to change it. */
-	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+	if (device_property_read_u32(&ofdev->dev, "current-speed", &spd) == 0)
 		port->custom_divisor = clk / (16 * spd);
 
-	ret = of_address_to_resource(np, 0, &resource);
-	if (ret) {
+	resource = platform_get_resource(ofdev, IORESOURCE_MEM, 0);
+	if (!resource) {
+		resource = platform_get_resource(ofdev, IORESOURCE_IO, 0);
+		iotype = UPIO_PORT;
+	}
+	if (!resource) {
 		dev_warn(&ofdev->dev, "invalid address\n");
 		goto out;
 	}
 
 	spin_lock_init(&port->lock);
-	port->mapbase = resource.start;
+	res_start = resource->start;
 
 	/* Check for shifted address mapping */
-	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
-		port->mapbase += prop;
+	if (device_property_read_u32(&ofdev->dev, "reg-offset", &prop) == 0)
+		res_start += prop;
+
+	if (iotype == UPIO_PORT)
+		port->iobase = res_start;
+	else
+		port->mapbase = res_start;
 
 	/* Check for registers offset within the devices address range */
-	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
+	if (device_property_read_u32(&ofdev->dev, "reg-shift", &prop) == 0)
 		port->regshift = prop;
 
 	/* Check for fifo size */
-	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+	if (device_property_read_u32(&ofdev->dev, "fifo-size", &prop) == 0)
 		port->fifosize = prop;
 
-	port->irq = irq_of_parse_and_map(np, 0);
-	port->iotype = UPIO_MEM;
-	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
+	port->irq = platform_get_irq(ofdev, 0);
+	port->iotype = iotype;
+	if (device_property_read_u32(&ofdev->dev, "reg-io-width", &prop) == 0) {
 		switch (prop) {
 		case 1:
-			port->iotype = UPIO_MEM;
+			port->iotype = iotype;
 			break;
 		case 4:
-			port->iotype = UPIO_MEM32;
-			break;
+			if (iotype == UPIO_MEM) {
+				port->iotype = UPIO_MEM32;
+				break;
+			}
+			/* Fall through for non-memory */
 		default:
 			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
 				 prop);
@@ -124,7 +137,7 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 
-	if (of_find_property(np, "no-loopback-test", NULL))
+	if (!device_get_property(&ofdev->dev, "no-loopback-test", NULL))
 		port->flags |= UPF_SKIP_TEST;
 
 	port->dev = &ofdev->dev;
@@ -155,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	if (!match)
 		return -EINVAL;
 
-	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
+	if (!device_get_property(&ofdev->dev, "used-by-rtas", NULL))
 		return -EBUSY;
 
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -179,12 +192,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		if (port.fifosize)
 			port8250.capabilities = UART_CAP_FIFO;
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "auto-flow-control"))
+		if (!device_get_property(&ofdev->dev, "auto-flow-control", NULL))
 			port8250.capabilities |= UART_CAP_AFE;
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "has-hw-flow-control"))
+		if (!device_get_property(&ofdev->dev, "has-hw-flow-control", NULL))
 			port8250.port.flags |= UPF_HARD_FLOW;
 
 		ret = serial8250_register_8250_port(&port8250);



-- 
dwmw2


[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5745 bytes --]

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 13:04 ` David Woodhouse
@ 2014-10-15 13:15   ` Mark Rutland
  2014-10-15 13:28     ` David Woodhouse
  2015-01-14 18:42     ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support David Woodhouse
  0 siblings, 2 replies; 104+ messages in thread
From: Mark Rutland @ 2014-10-15 13:15 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, Darren Hart

On Wed, Oct 15, 2014 at 02:04:31PM +0100, David Woodhouse wrote:
> Here's a completely untested patch to convert of_serial to be usable via
> ACPI properties too. The properties themselves were fairly
> straightforward; the interesting part is converting to
> platform_get_irq() and platform_get_resource() — in the latter case
> first trying IORESOURCE_MEM then IORESOURCE_IO if that fails.
> 
> Does this look sane? We'll probably want to think about renaming the
> module and the config option too, but that can come after the basic
> functionality.

The majority of these properties look like they constrained to the
device in question, so make sense for _DSD too.

However...

> @@ -155,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  	if (!match)
>  		return -EINVAL;
>  
> -	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
> +	if (!device_get_property(&ofdev->dev, "used-by-rtas", NULL))
>  		return -EBUSY;

This property should never be present on an ACPI system. RTAS is a
completely different firmware interface on PowerPC.

As a general note, I would hope that we're not going to blindly convert
drivers and subsystems over to a common property interface without
considering each property w.r.t. the particular FW interface. 

Each addition to _DSD, especially if through a common accessor needs
_more_ scrutiny than is applied to DT bindings, and we hardly manage to
review DT bindings.

Mark.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 13:15   ` Mark Rutland
@ 2014-10-15 13:28     ` David Woodhouse
  2014-10-15 13:42       ` Mark Rutland
  2015-01-14 18:42     ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties support David Woodhouse
  1 sibling, 1 reply; 104+ messages in thread
From: David Woodhouse @ 2014-10-15 13:28 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, Darren Hart

[-- Attachment #1: Type: text/plain, Size: 1905 bytes --]

On Wed, 2014-10-15 at 14:15 +0100, Mark Rutland wrote:
> > @@ -155,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
> >  	if (!match)
> >  		return -EINVAL;
> >  
> > -	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
> > +	if (!device_get_property(&ofdev->dev, "used-by-rtas", NULL))
> >  		return -EBUSY;
> 
> This property should never be present on an ACPI system. RTAS is a
> completely different firmware interface on PowerPC.

Yes, I sincerely hope we never see used-by-rtas being set on a non-PPC
system. But this isn't a new consideration; we were already checking for
'used-by-rtas' on *all* platforms. Perhaps we shouldn't be. But that's
almost orthogonal to the issue at hand.

> As a general note, I would hope that we're not going to blindly convert
> drivers and subsystems over to a common property interface without
> considering each property w.r.t. the particular FW interface. 
>
> Each addition to _DSD, especially if through a common accessor needs
> _more_ scrutiny than is applied to DT bindings, and we hardly manage to
> review DT bindings.

The whole point here is to use existing bindings rather than having to
reinvent the wheel. Sure, where the existing binding really makes no
sense for certain subsystems, we should come up with something
different.

But in the general case for 'leaf-node' peripherals we would hope that
we don't really have to change *anything* other than to make sure the
driver is using generic property accessor functions instead of the old
OF-specific ones. The point here is *consistency*. We really don't want
to make a habit of reinventing different bindings to be exposed through
the different firmware types.

-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5745 bytes --]

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 13:28     ` David Woodhouse
@ 2014-10-15 13:42       ` Mark Rutland
  2014-10-15 14:08         ` David Woodhouse
  0 siblings, 1 reply; 104+ messages in thread
From: Mark Rutland @ 2014-10-15 13:42 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, Darren Hart

On Wed, Oct 15, 2014 at 02:28:56PM +0100, David Woodhouse wrote:
> On Wed, 2014-10-15 at 14:15 +0100, Mark Rutland wrote:
> > > @@ -155,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
> > >  	if (!match)
> > >  		return -EINVAL;
> > >  
> > > -	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
> > > +	if (!device_get_property(&ofdev->dev, "used-by-rtas", NULL))
> > >  		return -EBUSY;
> > 
> > This property should never be present on an ACPI system. RTAS is a
> > completely different firmware interface on PowerPC.
> 
> Yes, I sincerely hope we never see used-by-rtas being set on a non-PPC
> system. But this isn't a new consideration; we were already checking for
> 'used-by-rtas' on *all* platforms. Perhaps we shouldn't be. But that's
> almost orthogonal to the issue at hand.

We have been checking for all DT platforms, and that's a bug for DT.
Copying that bug to ACPI is inexcusable given we know it's a bug to do
so.

No-one is using ACPI+RTAS, so there is no reason to enable this property
for ACPI. The only reason anyone would (mis)use this property with ACPI
is because Linux happened to support that combination, which need not be
the case because it doesn't make any sense.

> > As a general note, I would hope that we're not going to blindly convert
> > drivers and subsystems over to a common property interface without
> > considering each property w.r.t. the particular FW interface. 
> >
> > Each addition to _DSD, especially if through a common accessor needs
> > _more_ scrutiny than is applied to DT bindings, and we hardly manage to
> > review DT bindings.
> 
> The whole point here is to use existing bindings rather than having to
> reinvent the wheel. Sure, where the existing binding really makes no
> sense for certain subsystems, we should come up with something
> different.

I understand that. However, where a binding doesn't make sense (as in
this case), it shouldn't be enabled for ACPI as it provides a larger
surface area for misuse, for no benefit.

> But in the general case for 'leaf-node' peripherals we would hope that
> we don't really have to change *anything* other than to make sure the
> driver is using generic property accessor functions instead of the old
> OF-specific ones. The point here is *consistency*. We really don't want
> to make a habit of reinventing different bindings to be exposed through
> the different firmware types.

Where we have a property of a leaf-node that is independent of the
description format, sure. I am not asking us to re-invent bindings, but
we must consider the differences between ACPI and DT systems when trying
to port a DT binding to ACPI.

My concern here is that we don't have the mechanisms in place for
sufficient scrutiny to be applied when bindings are ported over. We
_will_ end up porting over things that don't make sense (as this patch
shows), and some of those are likely to cause unnecessary pain for
everyone. It does not make sense to say that is OK.

Mark.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 13:42       ` Mark Rutland
@ 2014-10-15 14:08         ` David Woodhouse
  2014-10-15 14:46           ` Darren Hart
  0 siblings, 1 reply; 104+ messages in thread
From: David Woodhouse @ 2014-10-15 14:08 UTC (permalink / raw)
  To: Mark Rutland
  Cc: David Woodhouse, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, grant.likely, Arnd Bergmann,
	Darren Hart


> We have been checking for all DT platforms, and that's a bug for DT.
> Copying that bug to ACPI is inexcusable given we know it's a bug to do
> so.

We'll, perhaps it should be named 'used-by-firmware' and actually it's
just as valid under ACPI as it is on RTAS systems. All it does is stop the
OS from using the port.

> I understand that. However, where a binding doesn't make sense (as in
> this case), it shouldn't be enabled for ACPI as it provides a larger
> surface area for misuse, for no benefit.

These are *optional* properties. They were optional precisely *because*
they only make sense in some cases. I don't know that it makes sense to
take them away. The benefit we get is *consistency*. For example if
someone *does* use the property in question as 'used-by-firmware' and
expects the OS not to touch it, we don't want that to change behaviour
between ACPI and fdt boots.

-- 
dwmw2


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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
  0 siblings, 2 replies; 104+ messages in thread
From: Darren Hart @ 2014-10-15 14:46 UTC (permalink / raw)
  To: David Woodhouse, Mark Rutland
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, dvhart



On 10/15/14 16:08, David Woodhouse wrote:
> 
>> We have been checking for all DT platforms, and that's a bug for DT.
>> Copying that bug to ACPI is inexcusable given we know it's a bug to do
>> so.
> 
> We'll, perhaps it should be named 'used-by-firmware' and actually it's
> just as valid under ACPI as it is on RTAS systems. All it does is stop the
> OS from using the port.
> 
>> I understand that. However, where a binding doesn't make sense (as in
>> this case), it shouldn't be enabled for ACPI as it provides a larger
>> surface area for misuse, for no benefit.
> 
> These are *optional* properties. They were optional precisely *because*
> they only make sense in some cases. I don't know that it makes sense to
> take them away. The benefit we get is *consistency*. For example if
> someone *does* use the property in question as 'used-by-firmware' and
> expects the OS not to touch it, we don't want that to change behaviour
> between ACPI and fdt boots.

My comment was going to be along the same lines. It is an optional
parameter, which is what I would expect for a firmware-specific type of
property.

I also don't agree that this is "copying that bug to ACPI". This line of
code has no impact to ACPI. No ACPI implementation should add this,
certainly not if it was actually tested as it would not run if it was
present in the _DSD. So... what's the problem exactly? Or perhaps more
specifically:

Mark, what would you propose we do differently to enable this driver to
be firmware-type agnostic?

-- 
Darren Hart
Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 14:46           ` Darren Hart
@ 2014-10-15 15:11             ` David Woodhouse
  2014-10-15 15:17             ` Mark Rutland
  1 sibling, 0 replies; 104+ messages in thread
From: David Woodhouse @ 2014-10-15 15:11 UTC (permalink / raw)
  To: Darren Hart
  Cc: David Woodhouse, Mark Rutland, Rafael J. Wysocki,
	Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, grant.likely,
	Arnd Bergmann, dvhart


> My comment was going to be along the same lines. It is an optional
> parameter, which is what I would expect for a firmware-specific type of
> property.

Right. Fundamentally, device properties (in DT or ACPI) exist to describe
the hardware in a generic and abstract fashion. It's a slippery slope from
saying "you don't need this property because you know you whether you are
on the *foo* architecture", to saying "you don't this property because you
know whether you're on a Assabet or not." I think it's wrong to go down
that path.

-- 
dwmw2


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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
  1 sibling, 1 reply; 104+ messages in thread
From: Mark Rutland @ 2014-10-15 15:17 UTC (permalink / raw)
  To: Darren Hart
  Cc: David Woodhouse, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, grant.likely, Arnd Bergmann, dvhart

On Wed, Oct 15, 2014 at 03:46:39PM +0100, Darren Hart wrote:
> 
> 
> On 10/15/14 16:08, David Woodhouse wrote:
> > 
> >> We have been checking for all DT platforms, and that's a bug for DT.
> >> Copying that bug to ACPI is inexcusable given we know it's a bug to do
> >> so.
> > 
> > We'll, perhaps it should be named 'used-by-firmware' and actually it's
> > just as valid under ACPI as it is on RTAS systems. All it does is stop the
> > OS from using the port.
> > 
> >> I understand that. However, where a binding doesn't make sense (as in
> >> this case), it shouldn't be enabled for ACPI as it provides a larger
> >> surface area for misuse, for no benefit.
> > 
> > These are *optional* properties. They were optional precisely *because*
> > they only make sense in some cases. I don't know that it makes sense to
> > take them away. The benefit we get is *consistency*. For example if
> > someone *does* use the property in question as 'used-by-firmware' and
> > expects the OS not to touch it, we don't want that to change behaviour
> > between ACPI and fdt boots.
> 
> My comment was going to be along the same lines. It is an optional
> parameter, which is what I would expect for a firmware-specific type of
> property.
> 
> I also don't agree that this is "copying that bug to ACPI". This line of
> code has no impact to ACPI. No ACPI implementation should add this,
> certainly not if it was actually tested as it would not run if it was
> present in the _DSD. So... what's the problem exactly? Or perhaps more
> specifically:
> 
> Mark, what would you propose we do differently to enable this driver to
> be firmware-type agnostic?

For this particular driver, all I'm asking for is that the
"used-by-rtas" property is not moved over from of_find_property to
device_get_property. It is irrelevant for all ACPI systems. Evidently my
comment was unclear; I apologise for that.

We have status = "disabled" as a less specific mechanism for telling the
OS to ignore a node in DT. I was under the impression that ACPI already
had a mechanism for marking devices to be ignored, but perhaps I am
mistaken.

The concerns I mentioned at the end of my original reply were of a more
general nature than this particular device description.

Thanks,
Mark.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 15:17             ` Mark Rutland
@ 2014-10-15 15:43               ` Darren Hart
  2014-10-16 10:05                 ` Rafael J. Wysocki
                                   ` (2 more replies)
  0 siblings, 3 replies; 104+ messages in thread
From: Darren Hart @ 2014-10-15 15:43 UTC (permalink / raw)
  To: Mark Rutland
  Cc: David Woodhouse, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, grant.likely, Arnd Bergmann, dvhart



On 10/15/14 17:17, Mark Rutland wrote:
> On Wed, Oct 15, 2014 at 03:46:39PM +0100, Darren Hart wrote:

>> Mark, what would you propose we do differently to enable this driver to
>> be firmware-type agnostic?
> 
> For this particular driver, all I'm asking for is that the
> "used-by-rtas" property is not moved over from of_find_property to
> device_get_property. It is irrelevant for all ACPI systems. Evidently my
> comment was unclear; I apologise for that.

So my objection here is that by keeping the of_* terms in the driver we
are required to include of, although it does safely convert to returning
NULL if !CONFIG_OF I suppose.

> We have status = "disabled" as a less specific mechanism for telling the
> OS to ignore a node in DT. I was under the impression that ACPI already
> had a mechanism for marking devices to be ignored, but perhaps I am
> mistaken.

That is correct, in ACPI this would be properly implemented with the
_STA reserved named method. In which case it wouldn't enumerate.

> 
> The concerns I mentioned at the end of my original reply were of a more
> general nature than this particular device description.
> 
> Thanks,
> Mark.
> 

-- 
Darren Hart
Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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:35                 ` Grant Likely
  2 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-16 10:05 UTC (permalink / raw)
  To: Darren Hart, Mark Rutland
  Cc: David Woodhouse, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, dvhart

On Wednesday, October 15, 2014 05:43:01 PM Darren Hart wrote:
> 
> On 10/15/14 17:17, Mark Rutland wrote:
> > On Wed, Oct 15, 2014 at 03:46:39PM +0100, Darren Hart wrote:
> 
> >> Mark, what would you propose we do differently to enable this driver to
> >> be firmware-type agnostic?
> > 
> > For this particular driver, all I'm asking for is that the
> > "used-by-rtas" property is not moved over from of_find_property to
> > device_get_property. It is irrelevant for all ACPI systems. Evidently my
> > comment was unclear; I apologise for that.
> 
> So my objection here is that by keeping the of_* terms in the driver we
> are required to include of, although it does safely convert to returning
> NULL if !CONFIG_OF I suppose.

Agreed.

> > We have status = "disabled" as a less specific mechanism for telling the
> > OS to ignore a node in DT. I was under the impression that ACPI already
> > had a mechanism for marking devices to be ignored, but perhaps I am
> > mistaken.
> 
> That is correct, in ACPI this would be properly implemented with the
> _STA reserved named method. In which case it wouldn't enumerate.
> 
> > 
> > The concerns I mentioned at the end of my original reply were of a more
> > general nature than this particular device description.

Moreover, to me, the question really is "Does this driver need to be any
different depending on whether DT or ACPI is used by the platform and if
so, then why?".

In my opinion, there is no technical reason for such differences to be present
in this particular case.  The fact that the "used-by-rtas" property does not
make sense for the ACPI case doesn't imply that the driver should not be allowed
to check it then.

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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
  2 siblings, 2 replies; 104+ messages in thread
From: David Woodhouse @ 2014-10-16 14:55 UTC (permalink / raw)
  To: Darren Hart
  Cc: Mark Rutland, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, grant.likely, Arnd Bergmann, dvhart

[-- Attachment #1: Type: text/plain, Size: 9125 bytes --]

On Wed, 2014-10-15 at 17:43 +0200, Darren Hart wrote:
> 
> So my objection here is that by keeping the of_* terms in the driver we
> are required to include of, although it does safely convert to returning
> NULL if !CONFIG_OF I suppose.

New version removes everything but the of_match_id bits which we need to
match ACPI devices too. Perhaps they ought to be renamed, but I'm not
sure it's worth it.

This also removes the call to platform_get_resource(IORESOURCE_MEM) and
fall back to platform_get_resource(IORESOURCE_IO) as discussed IRL with
Rafael. I'm not sure it's much of an improvement, mind you :)

Still untested. I think it's OK to switch to platform_get_irq() and then
drop the irq_dispose_mapping() call, right? The platform_device takes
care of all of that for us?

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index 26cec64..be95a4c 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1094,14 +1094,14 @@ config SERIAL_NETX_CONSOLE
 	  you can make it the console by answering Y to this option.
 
 config SERIAL_OF_PLATFORM
-	tristate "Serial port on Open Firmware platform bus"
-	depends on OF
+	tristate "Serial port on firmware platform bus"
+	depends on OF || ACPI
 	depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
 	help
-	  If you have a PowerPC based system that has serial ports
-	  on a platform specific bus, you should enable this option.
-	  Currently, only 8250 compatible ports are supported, but
-	  others can easily be added.
+	  If you have a system which advertises its serial ports through
+	  devicetree or ACPI, you should enable this option. Currently
+	  only 8250 compatible and NWP ports and are supported, but others
+	  can easily be added.
 
 config SERIAL_OMAP
 	tristate "OMAP serial port support"
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 68d4455..cc6c99b 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -14,8 +14,7 @@
 #include <linux/delay.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
+#include <linux/property.h>
 #include <linux/of_platform.h>
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
@@ -53,22 +52,22 @@ static inline void tegra_serial_handle_break(struct uart_port *port)
 /*
  * Fill a struct uart_port for a given device node
  */
-static int of_platform_serial_setup(struct platform_device *ofdev,
+static int of_platform_serial_setup(struct platform_device *pdev,
 			int type, struct uart_port *port,
 			struct of_serial_info *info)
 {
-	struct resource resource;
-	struct device_node *np = ofdev->dev.of_node;
 	u32 clk, spd, prop;
-	int ret;
+	int iotype = -1;
+	u32 res_start;
+	int ret, i;
 
 	memset(port, 0, sizeof *port);
-	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+	if (device_property_read_u32(&pdev->dev, "clock-frequency", &clk)) {
 
 		/* Get clk rate through clk driver if present */
-		info->clk = clk_get(&ofdev->dev, NULL);
+		info->clk = clk_get(&pdev->dev, NULL);
 		if (IS_ERR(info->clk)) {
-			dev_warn(&ofdev->dev,
+			dev_warn(&pdev->dev,
 				"clk or clock-frequency not defined\n");
 			return PTR_ERR(info->clk);
 		}
@@ -77,57 +76,63 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 		clk = clk_get_rate(info->clk);
 	}
 	/* If current-speed was set, then try not to change it. */
-	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+	if (device_property_read_u32(&pdev->dev, "current-speed", &spd) == 0)
 		port->custom_divisor = clk / (16 * spd);
 
-	ret = of_address_to_resource(np, 0, &resource);
-	if (ret) {
-		dev_warn(&ofdev->dev, "invalid address\n");
+	/* Check for shifted address mapping */
+	if (device_property_read_u32(&pdev->dev, "reg-offset", &prop) != 0)
+		prop = 0;
+
+	for (i = 0; iotype == -1 && i < pdev->num_resources; i++) {
+		struct resource *resource = &pdev->resource[i];
+		if (resource_type(resource) == IORESOURCE_MEM) {
+			iotype = UPIO_MEM;
+			port->mapbase = res_start + prop;
+		} else if (resource_type(resource) == IORESOURCE_IO) {
+			iotype = UPIO_PORT;
+			port->iobase = res_start + prop;
+		}
+
+		res_start = resource->start;
+	}
+	if (iotype == -1) {
+		dev_warn(&pdev->dev, "invalid address\n");
 		goto out;
 	}
 
 	spin_lock_init(&port->lock);
-	port->mapbase = resource.start;
-
-	/* Check for shifted address mapping */
-	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
-		port->mapbase += prop;
 
 	/* Check for registers offset within the devices address range */
-	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
+	if (device_property_read_u32(&pdev->dev, "reg-shift", &prop) == 0)
 		port->regshift = prop;
 
 	/* Check for fifo size */
-	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+	if (device_property_read_u32(&pdev->dev, "fifo-size", &prop) == 0)
 		port->fifosize = prop;
 
-	port->irq = irq_of_parse_and_map(np, 0);
-	port->iotype = UPIO_MEM;
-	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
-		switch (prop) {
-		case 1:
-			port->iotype = UPIO_MEM;
-			break;
-		case 4:
-			port->iotype = UPIO_MEM32;
-			break;
-		default:
-			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
+	port->irq = platform_get_irq(pdev, 0);
+
+	if (device_property_read_u32(&pdev->dev, "reg-io-width", &prop) == 0) {
+		if (prop == 4 && iotype == UPIO_MEM) {
+			iotype = UPIO_MEM32;
+		} else {
+			dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
 				 prop);
 			ret = -EINVAL;
 			goto out;
 		}
 	}
 
+	port->iotype = iotype;
 	port->type = type;
 	port->uartclk = clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 
-	if (of_find_property(np, "no-loopback-test", NULL))
+	if (!device_get_property(&pdev->dev, "no-loopback-test", NULL))
 		port->flags |= UPF_SKIP_TEST;
 
-	port->dev = &ofdev->dev;
+	port->dev = &pdev->dev;
 
 	if (type == PORT_TEGRA)
 		port->handle_break = tegra_serial_handle_break;
@@ -143,7 +148,7 @@ out:
  * Try to register a serial port
  */
 static struct of_device_id of_platform_serial_table[];
-static int of_platform_serial_probe(struct platform_device *ofdev)
+static int of_platform_serial_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	struct of_serial_info *info;
@@ -151,11 +156,11 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	int port_type;
 	int ret;
 
-	match = of_match_device(of_platform_serial_table, &ofdev->dev);
+	match = of_match_device(of_platform_serial_table, &pdev->dev);
 	if (!match)
 		return -EINVAL;
 
-	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
+	if (!device_get_property(&pdev->dev, "used-by-rtas", NULL))
 		return -EBUSY;
 
 	info = kmalloc(sizeof(*info), GFP_KERNEL);
@@ -163,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		return -ENOMEM;
 
 	port_type = (unsigned long)match->data;
-	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
+	ret = of_platform_serial_setup(pdev, port_type, &port, info);
 	if (ret)
 		goto out;
 
@@ -179,12 +184,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		if (port.fifosize)
 			port8250.capabilities = UART_CAP_FIFO;
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "auto-flow-control"))
+		if (!device_get_property(&pdev->dev, "auto-flow-control", NULL))
 			port8250.capabilities |= UART_CAP_AFE;
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "has-hw-flow-control"))
+		if (!device_get_property(&pdev->dev, "has-hw-flow-control", NULL))
 			port8250.port.flags |= UPF_HARD_FLOW;
 
 		ret = serial8250_register_8250_port(&port8250);
@@ -199,7 +202,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	default:
 		/* need to add code for these */
 	case PORT_UNKNOWN:
-		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
+		dev_info(&pdev->dev, "Unknown serial port found, ignored\n");
 		ret = -ENODEV;
 		break;
 	}
@@ -208,20 +211,19 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 
 	info->type = port_type;
 	info->line = ret;
-	platform_set_drvdata(ofdev, info);
+	platform_set_drvdata(pdev, info);
 	return 0;
 out:
 	kfree(info);
-	irq_dispose_mapping(port.irq);
 	return ret;
 }
 
 /*
  * Release a line
  */
-static int of_platform_serial_remove(struct platform_device *ofdev)
+static int of_platform_serial_remove(struct platform_device *pdev)
 {
-	struct of_serial_info *info = platform_get_drvdata(ofdev);
+	struct of_serial_info *info = platform_get_drvdata(pdev);
 	switch (info->type) {
 #ifdef CONFIG_SERIAL_8250
 	case PORT_8250 ... PORT_MAX_8250:


-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5745 bytes --]

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-07  0:10 [PATCH v4 00/13] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                   ` (15 preceding siblings ...)
  2014-10-15 13:04 ` David Woodhouse
@ 2014-10-17 12:01 ` Rafael J. Wysocki
  2014-10-17 12:03   ` [PATCH v5 01/12] ACPI: Add support for device specific properties Rafael J. Wysocki
                     ` (14 more replies)
  16 siblings, 15 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:01 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Arnd Bergmann
  Cc: Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

Hi Everyone,

Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
now have version 5 taking all feedback into account (hopefully).

Changes have been made to patch [02/12] and to patches [09-12/12], although
in patches [10-12/12] they are fairly minor.  I have retained the Greg's
ACK on patch [02/12], because it is essentially the same that have been
posted aleady and ACKed by him (Greg, please let me know if I shouldn't
do that) and all the ACKs on the remaining patches except for patch [09/12]
which is substantially different.  Still, if reviewers think that their
ACKs don't apply any more, please let me know and I'll remove them.

Patch [02/12] now contains helper functions for all proprerty data types
that can be accessed which call the existing of_ functions, because Grant
preferred that.

Patch [09/12] introduces quite a new concept, which is the struct fwnode_handle
structure containing one field (type) and embedded in struct device_node
(type==FWNODE_OF) and struct acpi_device (type==FWNODE_ACPI).  In short, if
we are passed a struct fwnode_handle pointer, we can get from it to the
appropriate device node pointer (either struct acpi_device or struct device_node)
using container_of() after we've checked the type.  This is needed for the code
that needs to access child nodes of a device in case when they don't have
struct device representations (whatever the reason).  This has been suggested
by Grant and pretty much everyone involved agrees that it's better that the
alternatives presented so far.

For completeness, the previous cover letter is appended below.

Rafael


On Tuesday, October 07, 2014 02:10:56 AM Rafael J. Wysocki wrote:
> Hi Everyone,
> 
> This is version 4 of the unified device properties interface patchset.
> 
> The original cover letter from Mika is here:
> 
> http://marc.info/?l=devicetree&m=141087052200600&w=4
> 
> My cover letter for version 3 is here:
> 
> http://marc.info/?l=linux-acpi&m=141212903816560&w=4
> 
> One major change from the previous iteration is that now we will
> use the "compatible" property to match drivers to devices having
> "PRP0001" as their _HID, so for example the at25 driver doesn't
> have to add the extra ACPI match table as part of the conversion
> to the unified interface (patch [05/13] in this series).
> 
> The second major change is that I've split the driver core patch
> in two, where the first one ([02/13]) does not contain any stuff
> related to iterating over the child nodes of a given device.
> Accordingly, the whole patch series has been rearranged so that
> the relatively non-controversial patches [01-09/13], most of which
> have been ACKed already, go first and then goes the second driver
> core patch ([10/13]) and the other patches related to it.
> 
> In patches [10-13/13] I used the Arnd's suggestion to implement
> device_for_each_child_node() as a macro which makes the changes
> in patches [12-13/13] look more straightforward among other things.
> 
> I've retained the Greg's ACKs on patches [02/13] and [10/13], because
> the first of them is things ACKed by Greg only and the change in the
> second one is just an implementation detail in my opinion (Greg, please
> let me know if that's inappropriate).
> 
> Thanks!
> 
> 

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 01/12] ACPI: Add support for device specific properties
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
@ 2014-10-17 12:03   ` Rafael J. Wysocki
  2014-10-17 12:04   ` [PATCH v5 02/12] Driver core: Unified device properties interface for platform firmware Rafael J. Wysocki
                     ` (13 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:03 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.

ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.

In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.

If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:

	Name (_DSD, Package () {
		ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
		Package () {
			Package () {"name1", <VALUE1>},
			Package () {"name2", <VALUE2>},
			...
		}
	})

The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].

We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.

The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.

[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Reviewed-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/Makefile   |    1 
 drivers/acpi/internal.h |    6 
 drivers/acpi/property.c |  364 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c     |    2 
 include/acpi/acpi_bus.h |    7 
 include/linux/acpi.h    |   40 +++++
 6 files changed, 420 insertions(+)
 create mode 100644 drivers/acpi/property.c

Index: linux-pm/drivers/acpi/Makefile
===================================================================
--- linux-pm.orig/drivers/acpi/Makefile
+++ linux-pm/drivers/acpi/Makefile
@@ -46,6 +46,7 @@ acpi-y				+= acpi_pnp.o
 acpi-y				+= power.o
 acpi-y				+= event.o
 acpi-y				+= sysfs.o
+acpi-y				+= property.o
 acpi-$(CONFIG_X86)		+= acpi_cmos_rtc.o
 acpi-$(CONFIG_DEBUG_FS)		+= debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)	+= numa.o
Index: linux-pm/drivers/acpi/internal.h
===================================================================
--- linux-pm.orig/drivers/acpi/internal.h
+++ linux-pm/drivers/acpi/internal.h
@@ -181,4 +181,10 @@ struct platform_device *acpi_create_plat
 bool acpi_osi_is_win8(void);
 #endif
 
+/*--------------------------------------------------------------------------
+				Device properties
+  -------------------------------------------------------------------------- */
+void acpi_init_properties(struct acpi_device *adev);
+void acpi_free_properties(struct acpi_device *adev);
+
 #endif /* _ACPI_INTERNAL_H_ */
Index: linux-pm/drivers/acpi/property.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/acpi/property.c
@@ -0,0 +1,364 @@
+/*
+ * ACPI device specific properties support.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Darren Hart <dvhart@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <linux/device.h>
+#include <linux/export.h>
+
+#include "internal.h"
+
+/* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
+static const u8 prp_uuid[16] = {
+	0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d,
+	0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01
+};
+
+static bool acpi_property_value_ok(const union acpi_object *value)
+{
+	int j;
+
+	/*
+	 * The value must be an integer, a string, a reference, or a package
+	 * whose every element must be an integer, a string, or a reference.
+	 */
+	switch (value->type) {
+	case ACPI_TYPE_INTEGER:
+	case ACPI_TYPE_STRING:
+	case ACPI_TYPE_LOCAL_REFERENCE:
+		return true;
+
+	case ACPI_TYPE_PACKAGE:
+		for (j = 0; j < value->package.count; j++)
+			switch (value->package.elements[j].type) {
+			case ACPI_TYPE_INTEGER:
+			case ACPI_TYPE_STRING:
+			case ACPI_TYPE_LOCAL_REFERENCE:
+				continue;
+
+			default:
+				return false;
+			}
+
+		return true;
+	}
+	return false;
+}
+
+static bool acpi_properties_format_valid(const union acpi_object *properties)
+{
+	int i;
+
+	for (i = 0; i < properties->package.count; i++) {
+		const union acpi_object *property;
+
+		property = &properties->package.elements[i];
+		/*
+		 * Only two elements allowed, the first one must be a string and
+		 * the second one has to satisfy certain conditions.
+		 */
+		if (property->package.count != 2
+		    || property->package.elements[0].type != ACPI_TYPE_STRING
+		    || !acpi_property_value_ok(&property->package.elements[1]))
+			return false;
+	}
+	return true;
+}
+
+void acpi_init_properties(struct acpi_device *adev)
+{
+	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+	const union acpi_object *desc;
+	acpi_status status;
+	int i;
+
+	status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
+					    ACPI_TYPE_PACKAGE);
+	if (ACPI_FAILURE(status))
+		return;
+
+	desc = buf.pointer;
+	if (desc->package.count % 2)
+		goto fail;
+
+	/* Look for the device properties UUID. */
+	for (i = 0; i < desc->package.count; i += 2) {
+		const union acpi_object *uuid, *properties;
+
+		uuid = &desc->package.elements[i];
+		properties = &desc->package.elements[i + 1];
+
+		/*
+		 * The first element must be a UUID and the second one must be
+		 * a package.
+		 */
+		if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16
+		    || properties->type != ACPI_TYPE_PACKAGE)
+			break;
+
+		if (memcmp(uuid->buffer.pointer, prp_uuid, sizeof(prp_uuid)))
+			continue;
+
+		/*
+		 * We found the matching UUID. Now validate the format of the
+		 * package immediately following it.
+		 */
+		if (!acpi_properties_format_valid(properties))
+			break;
+
+		adev->data.pointer = buf.pointer;
+		adev->data.properties = properties;
+		return;
+	}
+
+ fail:
+	dev_warn(&adev->dev, "Returned _DSD data is not valid, skipping\n");
+	ACPI_FREE(buf.pointer);
+}
+
+void acpi_free_properties(struct acpi_device *adev)
+{
+	ACPI_FREE((void *)adev->data.pointer);
+	adev->data.pointer = NULL;
+	adev->data.properties = NULL;
+}
+
+/**
+ * acpi_dev_get_property - return an ACPI property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected property type
+ * @obj: Location to store the property value (if not %NULL)
+ *
+ * Look up a property with @name and store a pointer to the resulting ACPI
+ * object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  These objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if property with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property value type doesn't match @type.
+ */
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+			  acpi_object_type type, const union acpi_object **obj)
+{
+	const union acpi_object *properties;
+	int i;
+
+	if (!adev || !name)
+		return -EINVAL;
+
+	if (!adev->data.pointer || !adev->data.properties)
+		return -ENODATA;
+
+	properties = adev->data.properties;
+	for (i = 0; i < properties->package.count; i++) {
+		const union acpi_object *propname, *propvalue;
+		const union acpi_object *property;
+
+		property = &properties->package.elements[i];
+
+		propname = &property->package.elements[0];
+		propvalue = &property->package.elements[1];
+
+		if (!strcmp(name, propname->string.pointer)) {
+			if (type != ACPI_TYPE_ANY && propvalue->type != type)
+				return -EPROTO;
+			else if (obj)
+				*obj = propvalue;
+
+			return 0;
+		}
+	}
+	return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property);
+
+/**
+ * acpi_dev_get_property_array - return an ACPI array property with given name
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @type: Expected type of array elements
+ * @obj: Location to store a pointer to the property value (if not NULL)
+ *
+ * Look up an array property with @name and store a pointer to the resulting
+ * ACPI object at the location pointed to by @obj if found.
+ *
+ * Callers must not attempt to free the returned objects.  Those objects will be
+ * freed by the ACPI core automatically during the removal of @adev.
+ *
+ * Return: %0 if array property (package) with @name has been found (success),
+ *         %-EINVAL if the arguments are invalid,
+ *         %-ENODATA if the property doesn't exist,
+ *         %-EPROTO if the property is not a package or the type of its elements
+ *           doesn't match @type.
+ */
+int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
+				acpi_object_type type,
+				const union acpi_object **obj)
+{
+	const union acpi_object *prop;
+	int ret, i;
+
+	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop);
+	if (ret)
+		return ret;
+
+	if (type != ACPI_TYPE_ANY) {
+		/* Check that all elements are of correct type. */
+		for (i = 0; i < prop->package.count; i++)
+			if (prop->package.elements[i].type != type)
+				return -EPROTO;
+	}
+	if (obj)
+		*obj = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);
+
+/**
+ * acpi_dev_get_property_reference - returns handle to the referenced object
+ * @adev: ACPI device to get property
+ * @name: Name of the property
+ * @size_prop: Name of the "size" property in referenced object
+ * @index: Index of the reference to return
+ * @args: Location to store the returned reference with optional arguments
+ *
+ * Find property with @name, verifify that it is a package containing at least
+ * one object reference and if so, store the ACPI device object pointer to the
+ * target object in @args->adev.
+ *
+ * If the reference includes arguments (@size_prop is not %NULL) follow the
+ * reference and check whether or not there is an integer property @size_prop
+ * under the target object and if so, whether or not its value matches the
+ * number of arguments that follow the reference.  If there's more than one
+ * reference in the property value package, @index is used to select the one to
+ * return.
+ *
+ * Return: %0 on success, negative error code on failure.
+ */
+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
+				    const char *size_prop, size_t index,
+				    struct acpi_reference_args *args)
+{
+	const union acpi_object *element, *end;
+	const union acpi_object *obj;
+	struct acpi_device *device;
+	int ret, idx = 0;
+
+	ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return ret;
+
+	/*
+	 * The simplest case is when the value is a single reference.  Just
+	 * return that reference then.
+	 */
+	if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
+		if (size_prop || index)
+			return -EINVAL;
+
+		ret = acpi_bus_get_device(obj->reference.handle, &device);
+		if (ret)
+			return ret;
+
+		args->adev = device;
+		args->nargs = 0;
+		return 0;
+	}
+
+	/*
+	 * If it is not a single reference, then it is a package of
+	 * references followed by number of ints as follows:
+	 *
+	 *  Package () { REF, INT, REF, INT, INT }
+	 *
+	 * The index argument is then used to determine which reference
+	 * the caller wants (along with the arguments).
+	 */
+	if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count)
+		return -EPROTO;
+
+	element = obj->package.elements;
+	end = element + obj->package.count;
+
+	while (element < end) {
+		u32 nargs, i;
+
+		if (element->type != ACPI_TYPE_LOCAL_REFERENCE)
+			return -EPROTO;
+
+		ret = acpi_bus_get_device(element->reference.handle, &device);
+		if (ret)
+			return -ENODEV;
+
+		element++;
+		nargs = 0;
+
+		if (size_prop) {
+			const union acpi_object *prop;
+
+			/*
+			 * Find out how many arguments the refenced object
+			 * expects by reading its size_prop property.
+			 */
+			ret = acpi_dev_get_property(device, size_prop,
+						    ACPI_TYPE_INTEGER, &prop);
+			if (ret)
+				return ret;
+
+			nargs = prop->integer.value;
+			if (nargs > MAX_ACPI_REFERENCE_ARGS
+			    || element + nargs > end)
+				return -EPROTO;
+
+			/*
+			 * Skip to the start of the arguments and verify
+			 * that they all are in fact integers.
+			 */
+			for (i = 0; i < nargs; i++)
+				if (element[i].type != ACPI_TYPE_INTEGER)
+					return -EPROTO;
+		} else {
+			/* assume following integer elements are all args */
+			for (i = 0; element + i < end; i++) {
+				int type = element[i].type;
+
+				if (type == ACPI_TYPE_INTEGER)
+					nargs++;
+				else if (type == ACPI_TYPE_LOCAL_REFERENCE)
+					break;
+				else
+					return -EPROTO;
+			}
+		}
+
+		if (idx++ == index) {
+			args->adev = device;
+			args->nargs = nargs;
+			for (i = 0; i < nargs; i++)
+				args->args[i] = element[i].integer.value;
+
+			return 0;
+		}
+
+		element += nargs;
+	}
+
+	return -EPROTO;
+}
+EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
Index: linux-pm/drivers/acpi/scan.c
===================================================================
--- linux-pm.orig/drivers/acpi/scan.c
+++ linux-pm/drivers/acpi/scan.c
@@ -884,6 +884,7 @@ static void acpi_device_release(struct d
 {
 	struct acpi_device *acpi_dev = to_acpi_device(dev);
 
+	acpi_free_properties(acpi_dev);
 	acpi_free_pnp_ids(&acpi_dev->pnp);
 	acpi_free_power_resources_lists(acpi_dev);
 	kfree(acpi_dev);
@@ -1888,6 +1889,7 @@ void acpi_init_device_object(struct acpi
 	acpi_set_device_status(device, sta);
 	acpi_device_get_busid(device);
 	acpi_set_pnp_ids(handle, &device->pnp, type);
+	acpi_init_properties(device);
 	acpi_bus_get_flags(device);
 	device->flags.match_driver = false;
 	device->flags.initialized = true;
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -337,6 +337,12 @@ struct acpi_device_physical_node {
 	bool put_online:1;
 };
 
+/* ACPI Device Specific Data (_DSD) */
+struct acpi_device_data {
+	const union acpi_object *pointer;
+	const union acpi_object *properties;
+};
+
 /* Device */
 struct acpi_device {
 	int device_type;
@@ -353,6 +359,7 @@ struct acpi_device {
 	struct acpi_device_wakeup wakeup;
 	struct acpi_device_perf performance;
 	struct acpi_device_dir dir;
+	struct acpi_device_data data;
 	struct acpi_scan_handler *handler;
 	struct acpi_hotplug_context *hp;
 	struct acpi_driver *driver;
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -658,4 +658,44 @@ do {									\
 #endif
 #endif
 
+/* Device properties */
+
+#define MAX_ACPI_REFERENCE_ARGS	8
+struct acpi_reference_args {
+	struct acpi_device *adev;
+	size_t nargs;
+	u64 args[MAX_ACPI_REFERENCE_ARGS];
+};
+
+#ifdef CONFIG_ACPI
+int acpi_dev_get_property(struct acpi_device *adev, const char *name,
+			  acpi_object_type type, const union acpi_object **obj);
+int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
+				acpi_object_type type,
+				const union acpi_object **obj);
+int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
+				    const char *cells_name, size_t index,
+				    struct acpi_reference_args *args);
+#else
+static inline int acpi_dev_get_property(struct acpi_device *adev,
+					const char *name, acpi_object_type type,
+					const union acpi_object **obj)
+{
+	return -ENXIO;
+}
+static inline int acpi_dev_get_property_array(struct acpi_device *adev,
+					      const char *name,
+					      acpi_object_type type,
+					      const union acpi_object **obj)
+{
+	return -ENXIO;
+}
+static inline int acpi_dev_get_property_reference(struct acpi_device *adev,
+				const char *name, const char *cells_name,
+				size_t index, struct acpi_reference_args *args)
+{
+	return -ENXIO;
+}
+#endif
+
 #endif	/*_LINUX_ACPI_H*/


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 02/12] Driver core: Unified device properties interface for platform firmware
  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   ` 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
                     ` (12 subsequent siblings)
  14 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:04 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Grant Likely
  Cc: Greg Kroah-Hartman, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

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

Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type.  The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.

The following general helper functions are added:

device_property_present()
device_property_read_u8()
device_property_read_u16()
device_property_read_u32()
device_property_read_u64()
device_property_read_string()
device_property_read_u8_array()
device_property_read_u16_array()
device_property_read_u32_array()
device_property_read_u64_array()
device_property_read_string_array()

The first one allows the caller to check if the given property is
present.  The next 5 of them allow single-valued properties of
various types to be retrieved in a uniform way.  The remaining 5 are
for reading properties with multiple values (arrays of either numbers
or strings).

The interface covers both ACPI and Device Trees.

This change set includes material from Mika Westerberg and Aaron Lu.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
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/property.c  |  169 ++++++++++++++++++++++++++
 drivers/base/Makefile    |    2 
 drivers/base/property.c  |  301 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/base.c        |  106 ++++++++++++++--
 include/linux/acpi.h     |   32 ++++
 include/linux/of.h       |   22 +++
 include/linux/property.h |   47 +++++++
 7 files changed, 662 insertions(+), 17 deletions(-)
 create mode 100644 drivers/base/property.c
 create mode 100644 include/linux/property.h

Index: linux-pm/include/linux/property.h
===================================================================
--- /dev/null
+++ linux-pm/include/linux/property.h
@@ -0,0 +1,47 @@
+/*
+ * property.h - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_PROPERTY_H_
+#define _LINUX_PROPERTY_H_
+
+#include <linux/types.h>
+
+struct device;
+
+enum dev_prop_type {
+	DEV_PROP_U8,
+	DEV_PROP_U16,
+	DEV_PROP_U32,
+	DEV_PROP_U64,
+	DEV_PROP_STRING,
+	DEV_PROP_MAX,
+};
+
+bool device_property_present(struct device *dev, const char *propname);
+int device_property_read_u8(struct device *dev, const char *propname, u8 *val);
+int device_property_read_u16(struct device *dev, const char *propname, u16 *val);
+int device_property_read_u32(struct device *dev, const char *propname, u32 *val);
+int device_property_read_u64(struct device *dev, const char *propname, u64 *val);
+int device_property_read_string(struct device *dev, const char *propname,
+				const char **val);
+int device_property_read_u8_array(struct device *dev, const char *propname,
+				  u8 *val, size_t nval);
+int device_property_read_u16_array(struct device *dev, const char *propname,
+				   u16 *val, size_t nval);
+int device_property_read_u32_array(struct device *dev, const char *propname,
+				   u32 *val, size_t nval);
+int device_property_read_u64_array(struct device *dev, const char *propname,
+				   u64 *val, size_t nval);
+int device_property_read_string_array(struct device *dev, const char *propname,
+				      char **val, size_t nval);
+
+#endif /* _LINUX_PROPERTY_H_ */
Index: linux-pm/include/linux/of.h
===================================================================
--- linux-pm.orig/include/linux/of.h
+++ linux-pm/include/linux/of.h
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/topology.h>
 #include <linux/notifier.h>
+#include <linux/property.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -263,6 +264,10 @@ extern int of_property_read_u32_array(co
 				      size_t sz);
 extern int of_property_read_u64(const struct device_node *np,
 				const char *propname, u64 *out_value);
+extern int of_property_read_u64_array(const struct device_node *np,
+				      const char *propname,
+				      u64 *out_values,
+				      size_t sz);
 
 extern int of_property_read_string(struct device_node *np,
 				   const char *propname,
@@ -275,6 +280,9 @@ extern int of_property_match_string(stru
 				    const char *string);
 extern int of_property_count_strings(struct device_node *np,
 				     const char *propname);
+extern int void of_property_read_string_array(struct device_node *np,
+					      const char *propname,
+					      char **out_strs, size_t sz);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -479,6 +487,13 @@ static inline int of_property_read_u32_a
 	return -ENOSYS;
 }
 
+static inline int of_property_read_u64_array(const struct device_node *np,
+					     const char *propname,
+					     u64 *out_values, size_t sz)
+{
+	return -ENOSYS;
+}
+
 static inline int of_property_read_string(struct device_node *np,
 					  const char *propname,
 					  const char **out_string)
@@ -498,6 +513,13 @@ static inline int of_property_count_stri
 {
 	return -ENOSYS;
 }
+
+static inline int of_property_read_string_array(struct device_node *np,
+						 const char *propname,
+						 char **out_strs, size_t sz)
+{
+	return -ENOSYS;
+}
 
 static inline const void *of_get_property(const struct device_node *node,
 				const char *name,
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -28,6 +28,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>	/* for struct resource */
 #include <linux/device.h>
+#include <linux/property.h>
 
 #ifndef _LINUX
 #define _LINUX
@@ -676,6 +677,14 @@ int acpi_dev_get_property_array(struct a
 int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
 				    const char *cells_name, size_t index,
 				    struct acpi_reference_args *args);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr);
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val);
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval);
 #else
 static inline int acpi_dev_get_property(struct acpi_device *adev,
 					const char *name, acpi_object_type type,
@@ -696,6 +705,29 @@ static inline int acpi_dev_get_property_
 {
 	return -ENXIO;
 }
+
+static inline int acpi_dev_prop_get(struct acpi_device *adev,
+				    const char *propname,
+				    void **valptr)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read(struct acpi_device *adev,
+				     const char *propname,
+				     enum dev_prop_type proptype, void *val)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read_array(struct acpi_device *adev,
+					   const char *propname,
+					   enum dev_prop_type proptype,
+					   void *val, size_t nval)
+{
+	return -ENXIO;
+}
+
 #endif
 
 #endif	/*_LINUX_ACPI_H*/
Index: linux-pm/drivers/base/Makefile
===================================================================
--- linux-pm.orig/drivers/base/Makefile
+++ linux-pm/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o \
-			   topology.o container.o
+			   topology.o container.o property.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
Index: linux-pm/drivers/base/property.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/base/property.c
@@ -0,0 +1,301 @@
+/*
+ * property.c - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/property.h>
+#include <linux/export.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+/**
+ * device_property_present - check if a property of a device is present
+ * @dev: Device whose property is being checked
+ * @propname: Name of the property
+ *
+ * Check if property @propname is present in the device firmware description.
+ */
+bool device_property_present(struct device *dev, const char *propname)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_bool(dev->of_node, propname);
+
+	return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL);
+}
+EXPORT_SYMBOL_GPL(device_property_present);
+
+/**
+ * device_property_read_u8 - return a u8 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u8.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u8,
+ *	   %-EOVERFLOW if the property value is out of bounds of u8.
+ */
+int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_u8(dev->of_node, propname, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
+				  DEV_PROP_U8, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u8);
+
+/**
+ * device_property_read_u16 - return a u16 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u16.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u16,
+ *	   %-EOVERFLOW if the property value is out of bounds of u16.
+ */
+int device_property_read_u16(struct device *dev, const char *propname, u16 *val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_u16(dev->of_node, propname, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
+				  DEV_PROP_U16, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u16);
+
+/**
+ * device_property_read_u32 - return a u32 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u32.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u32,
+ *	   %-EOVERFLOW if the property value is out of bounds of u32.
+ */
+int device_property_read_u32(struct device *dev, const char *propname, u32 *val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_u32(dev->of_node, propname, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
+				  DEV_PROP_U32, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u32);
+
+/**
+ * device_property_read_u64 - return a u64 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u64.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u64,
+ *	   %-EOVERFLOW if the property value is out of bounds of u64.
+ */
+int device_property_read_u64(struct device *dev, const char *propname, u64 *val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_u64(dev->of_node, propname, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
+				  DEV_PROP_U64, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u64);
+
+/**
+ * device_property_read_string - return a string property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be a string.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not a string.
+ */
+int device_property_read_string(struct device *dev, const char *propname,
+				const char **val)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_string(dev->of_node, propname, val);
+
+	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
+				  DEV_PROP_STRING, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string);
+
+#define of_dev_prop_read_array(node, propname, type, val, nval) \
+	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
+	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
+
+/**
+ * device_property_read_u8_array - return a u8 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u8 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u8_array(struct device *dev, const char *propname,
+				  u8 *val, size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(dev->of_node, propname,
+					      u8, val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					DEV_PROP_U8, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u8_array);
+
+/**
+ * device_property_read_u16_array - return a u16 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u16 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u16_array(struct device *dev, const char *propname,
+				   u16 *val, size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(dev->of_node, propname,
+					      u16, val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					DEV_PROP_U16, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u16_array);
+
+/**
+ * device_property_read_u32_array - return a u32 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u32 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u32_array(struct device *dev, const char *propname,
+				   u32 *val, size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(dev->of_node, propname,
+					      u32, val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					DEV_PROP_U32, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u32_array);
+
+/**
+ * device_property_read_u64_array - return a u64 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u64 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u64_array(struct device *dev, const char *propname,
+				   u64 *val, size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_dev_prop_read_array(dev->of_node, propname,
+					      u64, val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					DEV_PROP_U64, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u64_array);
+
+/**
+ * device_property_read_string_array - return a string array property of device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of string properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_string_array(struct device *dev, const char *propname,
+				      char **val, size_t nval)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_string_array(dev->of_node, propname,
+						     val, nval);
+
+	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					DEV_PROP_STRING, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string_array);
Index: linux-pm/drivers/of/base.c
===================================================================
--- linux-pm.orig/drivers/of/base.c
+++ linux-pm/drivers/of/base.c
@@ -1250,6 +1250,39 @@ int of_property_read_u64(const struct de
 EXPORT_SYMBOL_GPL(of_property_read_u64);
 
 /**
+ * of_property_read_u64_array - Find and read an array of 64 bit integers
+ * from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_values:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 64-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_values is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64_array(const struct device_node *np,
+			       const char *propname, u64 *out_values,
+			       size_t sz)
+{
+	const __be32 *val = of_find_property_value_of_size(np, propname,
+						(sz * sizeof(*out_values)));
+
+	if (IS_ERR(val))
+		return PTR_ERR(val);
+
+	while (sz--) {
+		*out_values++ = of_read_number(val, 2);
+		val += 2;
+	};
+	return 0;
+}
+
+/**
  * of_property_read_string - Find and read a string from a property
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
@@ -1362,24 +1395,11 @@ int of_property_match_string(struct devi
 }
 EXPORT_SYMBOL_GPL(of_property_match_string);
 
-/**
- * of_property_count_strings - Find and return the number of strings from a
- * multiple strings property.
- * @np:		device node from which the property value is to be read.
- * @propname:	name of the property to be searched.
- *
- * Search for a property in a device tree node and retrieve the number of null
- * terminated string contain in it. Returns the number of strings on
- * success, -EINVAL if the property does not exist, -ENODATA if property
- * does not have a value, and -EILSEQ if the string is not null-terminated
- * within the length of the property data.
- */
-int of_property_count_strings(struct device_node *np, const char *propname)
+static int property_count_strings(struct property *prop)
 {
-	struct property *prop = of_find_property(np, propname, NULL);
-	int i = 0;
-	size_t l = 0, total = 0;
 	const char *p;
+	size_t l = 0, total = 0;
+	int i = 0;
 
 	if (!prop)
 		return -EINVAL;
@@ -1395,8 +1415,62 @@ int of_property_count_strings(struct dev
 
 	return i;
 }
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+	return property_count_strings(of_find_property(np, propname, NULL));
+}
 EXPORT_SYMBOL_GPL(of_property_count_strings);
 
+/**
+ * of_property_read_string_array - Read an array of strings from a multiple
+ * strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_strs:	output array of string pointers.
+ * @sz:		number of array elements to read.
+ *
+ * Search for a property in a device tree node and retrieve a list of
+ * terminated string values (pointer to data, not a copy) in that property.
+ *
+ * If @out_strs is NULL, the number of strings in the property is returned.
+ */
+int of_property_read_string_array(struct device_node *np, const char *propname,
+				  char **out_strs, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	char *p = prop->value;
+	size_t total = 0;
+	int i;
+
+	i = property_count_strings(prop);
+	if (!out_strs || i < 0)
+		return i;
+
+	if (i < sz)
+		return -EOVERFLOW;
+
+	while (total < prop->length && i < sz) {
+		size_t l = strlen(p) + 1;
+
+		out_strs[i++] = p;
+		total += l;
+		p += l;
+	}
+}
+
 void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
 {
 	int i;
Index: linux-pm/drivers/acpi/property.c
===================================================================
--- linux-pm.orig/drivers/acpi/property.c
+++ linux-pm/drivers/acpi/property.c
@@ -362,3 +362,172 @@ int acpi_dev_get_property_reference(stru
 	return -EPROTO;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr)
+{
+	return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
+				     (const union acpi_object **)valptr);
+}
+
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val)
+{
+	const union acpi_object *obj;
+	int ret = -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
+		if (ret)
+			return ret;
+
+		switch (proptype) {
+		case DEV_PROP_U8:
+			if (obj->integer.value > U8_MAX)
+				return -EOVERFLOW;
+			*(u8 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U16:
+			if (obj->integer.value > U16_MAX)
+				return -EOVERFLOW;
+			*(u16 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U32:
+			if (obj->integer.value > U32_MAX)
+				return -EOVERFLOW;
+			*(u32 *)val = obj->integer.value;
+			break;
+		default:
+			*(u64 *)val = obj->integer.value;
+			break;
+		}
+	} else if (proptype == DEV_PROP_STRING) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
+		if (ret)
+			return ret;
+
+		*(char **)val = obj->string.pointer;
+	}
+	return ret;
+}
+
+static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
+				       size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U8_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u16(const union acpi_object *items,
+					u16 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U16_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u32(const union acpi_object *items,
+					u32 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U32_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u64(const union acpi_object *items,
+					u64 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_string(const union acpi_object *items,
+					   char **val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_STRING)
+			return -EPROTO;
+
+		val[i] = items[i].string.pointer;
+	}
+	return 0;
+}
+
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval)
+{
+	const union acpi_object *obj;
+	const union acpi_object *items;
+	int ret;
+
+	ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return ret;
+
+	if (!val)
+		return obj->package.count;
+
+	if (nval > obj->package.count)
+		return -EOVERFLOW;
+
+	items = obj->package.elements;
+	switch (proptype) {
+	case DEV_PROP_U8:
+		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
+		break;
+	case DEV_PROP_U16:
+		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
+		break;
+	case DEV_PROP_U32:
+		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
+		break;
+	case DEV_PROP_U64:
+		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
+		break;
+	case DEV_PROP_STRING:
+		ret = acpi_copy_property_array_string(items, (char **)val, nval);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property
  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-17 12:05   ` Rafael J. Wysocki
  2014-10-20 14:05     ` Grant Likely
  2014-10-17 12:07   ` [PATCH v5 04/12] misc: at25: Make use of device property API Rafael J. Wysocki
                     ` (11 subsequent siblings)
  14 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:05 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead if the driver
is missing .acpi_match_table.

If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/property.c | 34 +++++++++++++++++
 drivers/acpi/scan.c     | 97 +++++++++++++++++++++++++++++++++++++++++++------
 include/acpi/acpi_bus.h |  1 +
 include/linux/acpi.h    |  8 +---
 4 files changed, 123 insertions(+), 17 deletions(-)

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 680f7f1..ff53eb8 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -76,6 +76,37 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
 	return true;
 }
 
+static void acpi_init_of_compatible(struct acpi_device *adev)
+{
+	const union acpi_object *of_compatible;
+	struct acpi_hardware_id *hwid;
+	bool acpi_of = false;
+
+	/*
+	 * Check if the special PRP0001 ACPI ID is present and in that
+	 * case we fill in Device Tree compatible properties for this
+	 * device.
+	 */
+	list_for_each_entry(hwid, &adev->pnp.ids, list) {
+		if (!strcmp(hwid->id, "PRP0001")) {
+			acpi_of = true;
+			break;
+		}
+	}
+
+	if (!acpi_of)
+		return;
+
+	if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
+					&of_compatible)) {
+		acpi_handle_warn(adev->handle,
+				 "PRP0001 requires compatible property\n");
+		return;
+	}
+
+	adev->data.of_compatible = of_compatible;
+}
+
 void acpi_init_properties(struct acpi_device *adev)
 {
 	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
@@ -119,6 +150,8 @@ void acpi_init_properties(struct acpi_device *adev)
 
 		adev->data.pointer = buf.pointer;
 		adev->data.properties = properties;
+
+		acpi_init_of_compatible(adev);
 		return;
 	}
 
@@ -130,6 +163,7 @@ void acpi_init_properties(struct acpi_device *adev)
 void acpi_free_properties(struct acpi_device *adev)
 {
 	ACPI_FREE((void *)adev->data.pointer);
+	adev->data.of_compatible = NULL;
 	adev->data.pointer = NULL;
 	adev->data.properties = NULL;
 }
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 1979ab3..bc999f1 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -124,17 +124,51 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
 	if (list_empty(&acpi_dev->pnp.ids))
 		return 0;
 
-	len = snprintf(modalias, size, "acpi:");
-	size -= len;
-
-	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
-		count = snprintf(&modalias[len], size, "%s:", id->id);
-		if (count < 0)
-			return -EINVAL;
-		if (count >= size)
-			return -ENOMEM;
-		len += count;
-		size -= count;
+	/*
+	 * If the device has PRP0001 we expose DT compatible modalias
+	 * instead in form of of:NnameTCcompatible.
+	 */
+	if (acpi_dev->data.of_compatible) {
+		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
+		const union acpi_object *of_compatible, *obj;
+		char *c;
+		int i;
+
+		acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
+		/* DT strings are all in lower case */
+		for (c = buf.pointer; *c != '\0'; c++)
+			*c = tolower(*c);
+
+		len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
+		ACPI_FREE(buf.pointer);
+
+		of_compatible = acpi_dev->data.of_compatible;
+		for (i = 0; i < of_compatible->package.count; i++) {
+			obj = &of_compatible->package.elements[i];
+
+			count = snprintf(&modalias[len], size, "C%s",
+					 obj->string.pointer);
+			if (count < 0)
+				return -EINVAL;
+			if (count >= size)
+				return -ENOMEM;
+
+			len += count;
+			size -= count;
+		}
+	} else {
+		len = snprintf(modalias, size, "acpi:");
+		size -= len;
+
+		list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
+			count = snprintf(&modalias[len], size, "%s:", id->id);
+			if (count < 0)
+				return -EINVAL;
+			if (count >= size)
+				return -ENOMEM;
+			len += count;
+			size -= count;
+		}
 	}
 
 	modalias[len] = '\0';
@@ -864,6 +898,47 @@ int acpi_match_device_ids(struct acpi_device *device,
 }
 EXPORT_SYMBOL(acpi_match_device_ids);
 
+/* Performs match against special "PRP0001" shoehorn ACPI ID */
+static bool acpi_of_driver_match_device(struct device *dev,
+					const struct device_driver *drv)
+{
+	const union acpi_object *of_compatible;
+	struct acpi_device *adev;
+	int i;
+
+	adev = ACPI_COMPANION(dev);
+	if (!adev)
+		return false;
+
+	of_compatible = adev->data.of_compatible;
+	if (!drv->of_match_table || !of_compatible)
+		return false;
+
+	/* Now we can look for the driver DT compatible strings */
+	for (i = 0; i < of_compatible->package.count; i++) {
+		const struct of_device_id *id;
+		const union acpi_object *obj;
+
+		obj = &of_compatible->package.elements[i];
+
+		for (id = drv->of_match_table; id->compatible[0]; id++)
+			if (!strcasecmp(obj->string.pointer, id->compatible))
+				return true;
+	}
+
+	return false;
+}
+
+bool acpi_driver_match_device(struct device *dev,
+			      const struct device_driver *drv)
+{
+	if (!drv->acpi_match_table)
+		return acpi_of_driver_match_device(dev, drv);
+
+	return !!acpi_match_device(drv->acpi_match_table, dev);
+}
+EXPORT_SYMBOL_GPL(acpi_driver_match_device);
+
 static void acpi_free_power_resources_lists(struct acpi_device *device)
 {
 	int i;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index f9734fa..98cd723 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -341,6 +341,7 @@ struct acpi_device_physical_node {
 struct acpi_device_data {
 	const union acpi_object *pointer;
 	const union acpi_object *properties;
+	const union acpi_object *of_compatible;
 };
 
 /* Device */
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 18c1bc3..11aa6b8 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -424,12 +424,8 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
 const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
 					       const struct device *dev);
 
-static inline bool acpi_driver_match_device(struct device *dev,
-					    const struct device_driver *drv)
-{
-	return !!acpi_match_device(drv->acpi_match_table, dev);
-}
-
+extern bool acpi_driver_match_device(struct device *dev,
+				     const struct device_driver *drv);
 int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
 int acpi_device_modalias(struct device *, char *, int);
 
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v5 04/12] misc: at25: Make use of device property API
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (2 preceding siblings ...)
  2014-10-17 12:05   ` [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property Rafael J. Wysocki
@ 2014-10-17 12:07   ` Rafael J. Wysocki
  2014-10-17 12:09   ` [PATCH v5 05/12] gpio / ACPI: Add support for _DSD device properties Rafael J. Wysocki
                     ` (10 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:07 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Make use of device property API in this driver so that both DT and ACPI
based systems can use this driver.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/misc/eeprom/at25.c |   34 +++++++++++++---------------------
 1 file changed, 13 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/misc/eeprom/at25.c
===================================================================
--- linux-pm.orig/drivers/misc/eeprom/at25.c
+++ linux-pm/drivers/misc/eeprom/at25.c
@@ -18,7 +18,7 @@
 
 #include <linux/spi/spi.h>
 #include <linux/spi/eeprom.h>
-#include <linux/of.h>
+#include <linux/property.h>
 
 /*
  * NOTE: this is an *EEPROM* driver.  The vagaries of product naming
@@ -301,35 +301,33 @@ static ssize_t at25_mem_write(struct mem
 
 /*-------------------------------------------------------------------------*/
 
-static int at25_np_to_chip(struct device *dev,
-			   struct device_node *np,
-			   struct spi_eeprom *chip)
+static int at25_fw_to_chip(struct device *dev, struct spi_eeprom *chip)
 {
 	u32 val;
 
 	memset(chip, 0, sizeof(*chip));
-	strncpy(chip->name, np->name, sizeof(chip->name));
+	strncpy(chip->name, "at25", sizeof(chip->name));
 
-	if (of_property_read_u32(np, "size", &val) == 0 ||
-	    of_property_read_u32(np, "at25,byte-len", &val) == 0) {
+	if (device_property_read_u32(dev, "size", &val) == 0 ||
+	    device_property_read_u32(dev, "at25,byte-len", &val) == 0) {
 		chip->byte_len = val;
 	} else {
 		dev_err(dev, "Error: missing \"size\" property\n");
 		return -ENODEV;
 	}
 
-	if (of_property_read_u32(np, "pagesize", &val) == 0 ||
-	    of_property_read_u32(np, "at25,page-size", &val) == 0) {
+	if (device_property_read_u32(dev, "pagesize", &val) == 0 ||
+	    device_property_read_u32(dev, "at25,page-size", &val) == 0) {
 		chip->page_size = (u16)val;
 	} else {
 		dev_err(dev, "Error: missing \"pagesize\" property\n");
 		return -ENODEV;
 	}
 
-	if (of_property_read_u32(np, "at25,addr-mode", &val) == 0) {
+	if (device_property_read_u32(dev, "at25,addr-mode", &val) == 0) {
 		chip->flags = (u16)val;
 	} else {
-		if (of_property_read_u32(np, "address-width", &val)) {
+		if (device_property_read_u32(dev, "address-width", &val)) {
 			dev_err(dev,
 				"Error: missing \"address-width\" property\n");
 			return -ENODEV;
@@ -350,7 +348,7 @@ static int at25_np_to_chip(struct device
 				val);
 			return -ENODEV;
 		}
-		if (of_find_property(np, "read-only", NULL))
+		if (device_property_present(dev, "read-only"))
 			chip->flags |= EE_READONLY;
 	}
 	return 0;
@@ -360,21 +358,15 @@ static int at25_probe(struct spi_device
 {
 	struct at25_data	*at25 = NULL;
 	struct spi_eeprom	chip;
-	struct device_node	*np = spi->dev.of_node;
 	int			err;
 	int			sr;
 	int			addrlen;
 
 	/* Chip description */
 	if (!spi->dev.platform_data) {
-		if (np) {
-			err = at25_np_to_chip(&spi->dev, np, &chip);
-			if (err)
-				return err;
-		} else {
-			dev_err(&spi->dev, "Error: no chip description\n");
-			return -ENODEV;
-		}
+		err = at25_fw_to_chip(&spi->dev, &chip);
+		if (err)
+			return err;
 	} else
 		chip = *(struct spi_eeprom *)spi->dev.platform_data;
 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 05/12] gpio / ACPI: Add support for _DSD device properties
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (3 preceding siblings ...)
  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   ` Rafael J. Wysocki
  2014-10-17 12:10   ` [PATCH v5 06/12] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
                     ` (9 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:09 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
other things as well) returned by _CRS. Previously we were only able to
use integer index to find the corresponding GPIO, which is pretty error
prone if the order changes.

With _DSD we can now query GPIOs using name instead of an integer index,
like the below example shows:

  // Bluetooth device with reset and shutdown GPIOs
  Device (BTH)
  {
      Name (_HID, ...)

      Name (_CRS, ResourceTemplate ()
      {
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) {15}
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
      })

      Name (_DSD, Package ()
      {
          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
          Package ()
	  {
              Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
              Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
          }
      })
  }

The format of the supported GPIO property is:

  Package () { "name", Package () { ref, index, pin, active_low }}

  ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
        typically this is the device itself (BTH in our case).
  index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
  pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
  active_low - If 1 the GPIO is marked as active_low.

Since ACPI GpioIo() resource does not have field saying whether it is
active low or high, the "active_low" argument can be used here. Setting
it to 1 marks the GPIO as active low.

In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.

This patch implements necessary support to gpiolib for extracting GPIOs
using _DSD device properties.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 Documentation/acpi/gpio-properties.txt |   52 ++++++++++++++++++++++
 drivers/gpio/gpiolib-acpi.c            |   78 +++++++++++++++++++++++++++------
 drivers/gpio/gpiolib.c                 |   30 +++++++++++-
 drivers/gpio/gpiolib.h                 |    7 +-
 4 files changed, 146 insertions(+), 21 deletions(-)

Index: linux-pm/drivers/gpio/gpiolib-acpi.c
===================================================================
--- linux-pm.orig/drivers/gpio/gpiolib-acpi.c
+++ linux-pm/drivers/gpio/gpiolib-acpi.c
@@ -290,6 +290,7 @@ void acpi_gpiochip_free_interrupts(struc
 struct acpi_gpio_lookup {
 	struct acpi_gpio_info info;
 	int index;
+	int pin_index;
 	struct gpio_desc *desc;
 	int n;
 };
@@ -303,13 +304,24 @@ static int acpi_find_gpio(struct acpi_re
 
 	if (lookup->n++ == lookup->index && !lookup->desc) {
 		const struct acpi_resource_gpio *agpio = &ares->data.gpio;
+		int pin_index = lookup->pin_index;
+
+		if (pin_index >= agpio->pin_table_length)
+			return 1;
 
 		lookup->desc = acpi_get_gpiod(agpio->resource_source.string_ptr,
-					      agpio->pin_table[0]);
+					      agpio->pin_table[pin_index]);
 		lookup->info.gpioint =
 			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
-		lookup->info.active_low =
-			agpio->polarity == ACPI_ACTIVE_LOW;
+
+		/*
+		 * ActiveLow is only specified for GpioInt resource. If
+		 * GpioIo is used then the only way to set the flag is
+		 * to use _DSD "gpios" property.
+		 */
+		if (lookup->info.gpioint)
+			lookup->info.active_low =
+				agpio->polarity == ACPI_ACTIVE_LOW;
 	}
 
 	return 1;
@@ -317,40 +329,75 @@ static int acpi_find_gpio(struct acpi_re
 
 /**
  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
- * @dev: pointer to a device to get GPIO from
+ * @adev: pointer to a ACPI device to get GPIO from
+ * @propname: Property name of the GPIO (optional)
  * @index: index of GpioIo/GpioInt resource (starting from %0)
  * @info: info pointer to fill in (optional)
  *
- * Function goes through ACPI resources for @dev and based on @index looks
+ * Function goes through ACPI resources for @adev and based on @index looks
  * up a GpioIo/GpioInt resource, translates it to the Linux GPIO descriptor,
  * and returns it. @index matches GpioIo/GpioInt resources only so if there
  * are total %3 GPIO resources, the index goes from %0 to %2.
  *
+ * If @propname is specified the GPIO is looked using device property. In
+ * that case @index is used to select the GPIO entry in the property value
+ * (in case of multiple).
+ *
  * If the GPIO cannot be translated or there is an error an ERR_PTR is
  * returned.
  *
  * Note: if the GPIO resource has multiple entries in the pin list, this
  * function only returns the first.
  */
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+					  const char *propname, int index,
 					  struct acpi_gpio_info *info)
 {
 	struct acpi_gpio_lookup lookup;
 	struct list_head resource_list;
-	struct acpi_device *adev;
-	acpi_handle handle;
+	bool active_low = false;
 	int ret;
 
-	if (!dev)
-		return ERR_PTR(-EINVAL);
-
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev))
+	if (!adev)
 		return ERR_PTR(-ENODEV);
 
 	memset(&lookup, 0, sizeof(lookup));
 	lookup.index = index;
 
+	if (propname) {
+		struct acpi_reference_args args;
+
+		dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname);
+
+		memset(&args, 0, sizeof(args));
+		ret = acpi_dev_get_property_reference(adev, propname, NULL,
+						      index, &args);
+		if (ret)
+			return ERR_PTR(ret);
+
+		/*
+		 * The property was found and resolved so need to
+		 * lookup the GPIO based on returned args instead.
+		 */
+		adev = args.adev;
+		if (args.nargs >= 2) {
+			lookup.index = args.args[0];
+			lookup.pin_index = args.args[1];
+			/*
+			 * 3rd argument, if present is used to
+			 * specify active_low.
+			 */
+			if (args.nargs >= 3)
+				active_low = !!args.args[2];
+		}
+
+		dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n",
+			dev_name(&adev->dev), args.nargs,
+			args.args[0], args.args[1], args.args[2]);
+	} else {
+		dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index);
+	}
+
 	INIT_LIST_HEAD(&resource_list);
 	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
 				     &lookup);
@@ -359,8 +406,11 @@ struct gpio_desc *acpi_get_gpiod_by_inde
 
 	acpi_dev_free_resource_list(&resource_list);
 
-	if (lookup.desc && info)
+	if (lookup.desc && info) {
 		*info = lookup.info;
+		if (active_low)
+			info->active_low = active_low;
+	}
 
 	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
 }
Index: linux-pm/drivers/gpio/gpiolib.c
===================================================================
--- linux-pm.orig/drivers/gpio/gpiolib.c
+++ linux-pm/drivers/gpio/gpiolib.c
@@ -1505,14 +1505,36 @@ static struct gpio_desc *acpi_find_gpio(
 					unsigned int idx,
 					enum gpio_lookup_flags *flags)
 {
+	static const char * const suffixes[] = { "gpios", "gpio" };
+	struct acpi_device *adev = ACPI_COMPANION(dev);
 	struct acpi_gpio_info info;
 	struct gpio_desc *desc;
+	char propname[32];
+	int i;
 
-	desc = acpi_get_gpiod_by_index(dev, idx, &info);
-	if (IS_ERR(desc))
-		return desc;
+	/* Try first from _DSD */
+	for (i = 0; i < ARRAY_SIZE(suffixes); i++) {
+		if (con_id && strcmp(con_id, "gpios")) {
+			snprintf(propname, sizeof(propname), "%s-%s",
+				 con_id, suffixes[i]);
+		} else {
+			snprintf(propname, sizeof(propname), "%s",
+				 suffixes[i]);
+		}
 
-	if (info.gpioint && info.active_low)
+		desc = acpi_get_gpiod_by_index(adev, propname, 0, &info);
+		if (!IS_ERR(desc) || (PTR_ERR(desc) == -EPROBE_DEFER))
+			break;
+	}
+
+	/* Then from plain _CRS GPIOs */
+	if (IS_ERR(desc)) {
+		desc = acpi_get_gpiod_by_index(adev, NULL, idx, &info);
+		if (IS_ERR(desc))
+			return desc;
+	}
+
+	if (info.active_low)
 		*flags |= GPIO_ACTIVE_LOW;
 
 	return desc;
Index: linux-pm/drivers/gpio/gpiolib.h
===================================================================
--- linux-pm.orig/drivers/gpio/gpiolib.h
+++ linux-pm/drivers/gpio/gpiolib.h
@@ -34,7 +34,8 @@ void acpi_gpiochip_remove(struct gpio_ch
 void acpi_gpiochip_request_interrupts(struct gpio_chip *chip);
 void acpi_gpiochip_free_interrupts(struct gpio_chip *chip);
 
-struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
+struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev,
+					  const char *propname, int index,
 					  struct acpi_gpio_info *info);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
@@ -47,8 +48,8 @@ static inline void
 acpi_gpiochip_free_interrupts(struct gpio_chip *chip) { }
 
 static inline struct gpio_desc *
-acpi_get_gpiod_by_index(struct device *dev, int index,
-			struct acpi_gpio_info *info)
+acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname,
+			int index, struct acpi_gpio_info *info)
 {
 	return ERR_PTR(-ENOSYS);
 }
Index: linux-pm/Documentation/acpi/gpio-properties.txt
===================================================================
--- /dev/null
+++ linux-pm/Documentation/acpi/gpio-properties.txt
@@ -0,0 +1,52 @@
+_DSD Device Properties Related to GPIO
+--------------------------------------
+
+With the release of ACPI 5.1 and the _DSD configuration objecte names
+can finally be given to GPIOs (and other things as well) returned by
+_CRS.  Previously, we were only able to use an integer index to find
+the corresponding GPIO, which is pretty error prone (it depends on
+the _CRS output ordering, for example).
+
+With _DSD we can now query GPIOs using a name instead of an integer
+index, like the ASL example below shows:
+
+  // Bluetooth device with reset and shutdown GPIOs
+  Device (BTH)
+  {
+      Name (_HID, ...)
+
+      Name (_CRS, ResourceTemplate ()
+      {
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                  "\\_SB.GPO0", 0, ResourceConsumer) {15}
+          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
+                  "\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
+      })
+
+      Name (_DSD, Package ()
+      {
+          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+          Package ()
+	  {
+              Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
+              Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
+          }
+      })
+  }
+
+The format of the supported GPIO property is:
+
+  Package () { "name", Package () { ref, index, pin, active_low }}
+
+  ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
+        typically this is the device itself (BTH in our case).
+  index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
+  pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
+  active_low - If 1 the GPIO is marked as active_low.
+
+Since ACPI GpioIo() resource does not have a field saying whether it is
+active low or high, the "active_low" argument can be used here.  Setting
+it to 1 marks the GPIO as active low.
+
+In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
+resource, second pin in that resource with the GPIO number of 31.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 06/12] gpio: sch: Consolidate core and resume banks
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (4 preceding siblings ...)
  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   ` Rafael J. Wysocki
  2014-10-17 12:11   ` [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
                     ` (8 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:10 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

This is actually a single device with two sets of identical registers,
which just happen to start from a different offset. Instead of having
separate GPIO chips created we consolidate them to be single GPIO chip.

In addition having a single GPIO chip allows us to handle ACPI GPIO
translation in the core in a more generic way, since the two GPIO chips
share the same parent ACPI device.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/gpio/gpio-sch.c | 293 ++++++++++++++++++------------------------------
 1 file changed, 112 insertions(+), 181 deletions(-)

diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index 41e91d7..99720c8 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -29,290 +29,221 @@
 
 #include <linux/gpio.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-
-#define CGEN	(0x00)
-#define CGIO	(0x04)
-#define CGLV	(0x08)
-
-#define RGEN	(0x20)
-#define RGIO	(0x24)
-#define RGLV	(0x28)
-
-static unsigned short gpio_ba;
-
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-
-	if (!(curr_dirs & (1 << bit)))
-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+#define GEN	0x00
+#define GIO	0x04
+#define GLV	0x08
+
+struct sch_gpio {
+	struct gpio_chip chip;
+	spinlock_t lock;
+	unsigned short iobase;
+	unsigned short core_base;
+	unsigned short resume_base;
+};
 
-	spin_unlock(&gpio_lock);
-	return 0;
-}
+#define to_sch_gpio(c)	container_of(c, struct sch_gpio, chip)
 
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+				unsigned reg)
 {
-	int res;
-	unsigned short offset, bit;
+	unsigned base = 0;
 
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	if (gpio >= sch->resume_base) {
+		gpio -= sch->resume_base;
+		base += 0x20;
+	}
 
-	res = !!(inb(gpio_ba + offset) & (1 << bit));
-	return res;
+	return base + reg + gpio / 8;
 }
 
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_vals;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_vals = inb(gpio_ba + offset);
-
-	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
-	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-	spin_unlock(&gpio_lock);
+	if (gpio >= sch->resume_base)
+		gpio -= sch->resume_base;
+	return gpio % 8;
 }
 
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_dirs;
 	unsigned short offset, bit;
+	u8 enable;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	curr_dirs = inb(gpio_ba + offset);
-	if (curr_dirs & (1 << bit))
-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+	offset = sch_gpio_offset(sch, gpio, GEN);
+	bit = sch_gpio_bit(sch, gpio);
 
-	spin_unlock(&gpio_lock);
+	enable = inb(sch->iobase + offset);
+	if (!(enable & (1 << bit)))
+		outb(enable | (1 << bit), sch->iobase + offset);
 
-	/*
-	 * according to the datasheet, writing to the level register has no
-	 * effect when GPIO is programmed as input.
-	 * Actually the the level register is read-only when configured as input.
-	 * Thus presetting the output level before switching to output is _NOT_ possible.
-	 * Hence we set the level after configuring the GPIO as output.
-	 * But we cannot prevent a short low pulse if direction is set to high
-	 * and an external pull-up is connected.
-	 */
-	sch_gpio_core_set(gc, gpio_num, val);
-	return 0;
+	spin_unlock(&sch->lock);
 }
 
-static struct gpio_chip sch_gpio_core = {
-	.label			= "sch_gpio_core",
-	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_core_direction_in,
-	.get			= sch_gpio_core_get,
-	.direction_output	= sch_gpio_core_direction_out,
-	.set			= sch_gpio_core_set,
-};
-
-static int sch_gpio_resume_direction_in(struct gpio_chip *gc,
-					unsigned gpio_num)
+static int sch_gpio_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_dirs;
 	unsigned short offset, bit;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_dirs = inb(gpio_ba + offset);
+	curr_dirs = inb(sch->iobase + offset);
 
 	if (!(curr_dirs & (1 << bit)))
-		outb(curr_dirs | (1 << bit), gpio_ba + offset);
+		outb(curr_dirs | (1 << bit), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 	return 0;
 }
 
-static int sch_gpio_resume_get(struct gpio_chip *gc, unsigned gpio_num)
+static int sch_gpio_get(struct gpio_chip *gc, unsigned gpio_num)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
+	int res;
 	unsigned short offset, bit;
 
-	offset = RGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GLV);
+	bit = sch_gpio_bit(sch, gpio_num);
+
+	res = !!(inb(sch->iobase + offset) & (1 << bit));
 
-	return !!(inb(gpio_ba + offset) & (1 << bit));
+	return res;
 }
 
-static void sch_gpio_resume_set(struct gpio_chip *gc,
-				unsigned gpio_num, int val)
+static void sch_gpio_set(struct gpio_chip *gc, unsigned gpio_num, int val)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_vals;
 	unsigned short offset, bit;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = RGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio_num, GLV);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_vals = inb(gpio_ba + offset);
+	curr_vals = inb(sch->iobase + offset);
 
 	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
+		outb(curr_vals | (1 << bit), sch->iobase + offset);
 	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
+		outb((curr_vals & ~(1 << bit)), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 }
 
-static int sch_gpio_resume_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+static int sch_gpio_direction_out(struct gpio_chip *gc, unsigned gpio_num,
+				  int val)
 {
+	struct sch_gpio *sch = to_sch_gpio(gc);
 	u8 curr_dirs;
 	unsigned short offset, bit;
 
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	spin_lock(&sch->lock);
 
-	spin_lock(&gpio_lock);
+	offset = sch_gpio_offset(sch, gpio_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	curr_dirs = inb(gpio_ba + offset);
+	curr_dirs = inb(sch->iobase + offset);
 	if (curr_dirs & (1 << bit))
-		outb(curr_dirs & ~(1 << bit), gpio_ba + offset);
+		outb(curr_dirs & ~(1 << bit), sch->iobase + offset);
 
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 
 	/*
-	* according to the datasheet, writing to the level register has no
-	* effect when GPIO is programmed as input.
-	* Actually the the level register is read-only when configured as input.
-	* Thus presetting the output level before switching to output is _NOT_ possible.
-	* Hence we set the level after configuring the GPIO as output.
-	* But we cannot prevent a short low pulse if direction is set to high
-	* and an external pull-up is connected.
-	*/
-	sch_gpio_resume_set(gc, gpio_num, val);
+	 * according to the datasheet, writing to the level register has no
+	 * effect when GPIO is programmed as input.
+	 * Actually the the level register is read-only when configured as input.
+	 * Thus presetting the output level before switching to output is _NOT_ possible.
+	 * Hence we set the level after configuring the GPIO as output.
+	 * But we cannot prevent a short low pulse if direction is set to high
+	 * and an external pull-up is connected.
+	 */
+	sch_gpio_set(gc, gpio_num, val);
 	return 0;
 }
 
-static struct gpio_chip sch_gpio_resume = {
-	.label			= "sch_gpio_resume",
+static struct gpio_chip sch_gpio_chip = {
+	.label			= "sch_gpio",
 	.owner			= THIS_MODULE,
-	.direction_input	= sch_gpio_resume_direction_in,
-	.get			= sch_gpio_resume_get,
-	.direction_output	= sch_gpio_resume_direction_out,
-	.set			= sch_gpio_resume_set,
+	.direction_input	= sch_gpio_direction_in,
+	.get			= sch_gpio_get,
+	.direction_output	= sch_gpio_direction_out,
+	.set			= sch_gpio_set,
 };
 
 static int sch_gpio_probe(struct platform_device *pdev)
 {
+	struct sch_gpio *sch;
 	struct resource *res;
-	int err, id;
 
-	id = pdev->id;
-	if (!id)
-		return -ENODEV;
+	sch = devm_kzalloc(&pdev->dev, sizeof(*sch), GFP_KERNEL);
+	if (!sch)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!res)
 		return -EBUSY;
 
-	if (!request_region(res->start, resource_size(res), pdev->name))
+	if (!devm_request_region(&pdev->dev, res->start, resource_size(res),
+				 pdev->name))
 		return -EBUSY;
 
-	gpio_ba = res->start;
+	spin_lock_init(&sch->lock);
+	sch->iobase = res->start;
+	sch->chip = sch_gpio_chip;
+	sch->chip.label = dev_name(&pdev->dev);
+	sch->chip.dev = &pdev->dev;
 
-	switch (id) {
+	switch (pdev->id) {
 	case PCI_DEVICE_ID_INTEL_SCH_LPC:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 10;
-		sch_gpio_resume.base = 10;
-		sch_gpio_resume.ngpio = 4;
+		sch->core_base = 0;
+		sch->resume_base = 10;
+		sch->chip.ngpio = 14;
+
 		/*
 		 * GPIO[6:0] enabled by default
 		 * GPIO7 is configured by the CMC as SLPIOVR
 		 * Enable GPIO[9:8] core powered gpios explicitly
 		 */
-		outb(0x3, gpio_ba + CGEN + 1);
+		sch_gpio_enable(sch, 8);
+		sch_gpio_enable(sch, 9);
 		/*
 		 * SUS_GPIO[2:0] enabled by default
 		 * Enable SUS_GPIO3 resume powered gpio explicitly
 		 */
-		outb(0x8, gpio_ba + RGEN);
+		sch_gpio_enable(sch, 13);
 		break;
 
 	case PCI_DEVICE_ID_INTEL_ITC_LPC:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 5;
-		sch_gpio_resume.base = 5;
-		sch_gpio_resume.ngpio = 9;
+		sch->core_base = 0;
+		sch->resume_base = 5;
+		sch->chip.ngpio = 14;
 		break;
 
 	case PCI_DEVICE_ID_INTEL_CENTERTON_ILB:
-		sch_gpio_core.base = 0;
-		sch_gpio_core.ngpio = 21;
-		sch_gpio_resume.base = 21;
-		sch_gpio_resume.ngpio = 9;
+		sch->core_base = 0;
+		sch->resume_base = 21;
+		sch->chip.ngpio = 30;
 		break;
 
 	default:
-		err = -ENODEV;
-		goto err_sch_gpio_core;
+		return -ENODEV;
 	}
 
-	sch_gpio_core.dev = &pdev->dev;
-	sch_gpio_resume.dev = &pdev->dev;
-
-	err = gpiochip_add(&sch_gpio_core);
-	if (err < 0)
-		goto err_sch_gpio_core;
+	platform_set_drvdata(pdev, sch);
 
-	err = gpiochip_add(&sch_gpio_resume);
-	if (err < 0)
-		goto err_sch_gpio_resume;
-
-	return 0;
-
-err_sch_gpio_resume:
-	gpiochip_remove(&sch_gpio_core);
-
-err_sch_gpio_core:
-	release_region(res->start, resource_size(res));
-	gpio_ba = 0;
-
-	return err;
+	return gpiochip_add(&sch->chip);
 }
 
 static int sch_gpio_remove(struct platform_device *pdev)
 {
-	struct resource *res;
-	if (gpio_ba) {
-
-		gpiochip_remove(&sch_gpio_core);
-		gpiochip_remove(&sch_gpio_resume);
-
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-		release_region(res->start, resource_size(res));
-		gpio_ba = 0;
-	}
+	struct sch_gpio *sch = platform_get_drvdata(pdev);
 
+	gpiochip_remove(&sch->chip);
 	return 0;
 }
 
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (5 preceding siblings ...)
  2014-10-17 12:10   ` [PATCH v5 06/12] gpio: sch: Consolidate core and resume banks Rafael J. Wysocki
@ 2014-10-17 12:11   ` Rafael J. Wysocki
  2014-10-28 15:26     ` Linus Walleij
  2014-10-17 12:12   ` [PATCH v5 08/12] input: gpio_keys_polled - " Rafael J. Wysocki
                     ` (7 subsequent siblings)
  14 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:11 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/leds/leds-gpio.c |   80 ++++++++++++++++++++++++++---------------------
 include/linux/leds.h     |    1 
 2 files changed, 46 insertions(+), 35 deletions(-)

Index: linux-pm/drivers/leds/leds-gpio.c
===================================================================
--- linux-pm.orig/drivers/leds/leds-gpio.c
+++ linux-pm/drivers/leds/leds-gpio.c
@@ -13,6 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/leds.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -24,11 +25,10 @@
 
 struct gpio_led_data {
 	struct led_classdev cdev;
-	unsigned gpio;
+	struct gpio_desc *gpiod;
 	struct work_struct work;
 	u8 new_level;
 	u8 can_sleep;
-	u8 active_low;
 	u8 blinking;
 	int (*platform_gpio_blink_set)(unsigned gpio, int state,
 			unsigned long *delay_on, unsigned long *delay_off);
@@ -40,12 +40,16 @@ static void gpio_led_work(struct work_st
 		container_of(work, struct gpio_led_data, work);
 
 	if (led_dat->blinking) {
-		led_dat->platform_gpio_blink_set(led_dat->gpio,
-						 led_dat->new_level,
-						 NULL, NULL);
+		int gpio = desc_to_gpio(led_dat->gpiod);
+		int level = led_dat->new_level;
+
+		if (gpiod_is_active_low(led_dat->gpiod))
+			level = !level;
+
+		led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
 		led_dat->blinking = 0;
 	} else
-		gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
+		gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
 }
 
 static void gpio_led_set(struct led_classdev *led_cdev,
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_clas
 	else
 		level = 1;
 
-	if (led_dat->active_low)
-		level = !level;
-
 	/* Setting GPIOs with I2C/etc requires a task context, and we don't
 	 * seem to have a reliable way to know if we're already in one; so
 	 * let's just assume the worst.
@@ -72,11 +73,16 @@ static void gpio_led_set(struct led_clas
 		schedule_work(&led_dat->work);
 	} else {
 		if (led_dat->blinking) {
-			led_dat->platform_gpio_blink_set(led_dat->gpio, level,
-							 NULL, NULL);
+			int gpio = desc_to_gpio(led_dat->gpiod);
+
+			if (gpiod_is_active_low(led_dat->gpiod))
+				level = !level;
+
+			led_dat->platform_gpio_blink_set(gpio, level, NULL,
+							 NULL);
 			led_dat->blinking = 0;
 		} else
-			gpio_set_value(led_dat->gpio, level);
+			gpiod_set_value(led_dat->gpiod, level);
 	}
 }
 
@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_cla
 {
 	struct gpio_led_data *led_dat =
 		container_of(led_cdev, struct gpio_led_data, cdev);
+	int gpio = desc_to_gpio(led_dat->gpiod);
 
 	led_dat->blinking = 1;
-	return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
+	return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
 						delay_on, delay_off);
 }
 
@@ -97,24 +104,33 @@ static int create_gpio_led(const struct
 {
 	int ret, state;
 
-	led_dat->gpio = -1;
+	if (!template->gpiod) {
+		unsigned long flags = 0;
 
-	/* skip leds that aren't available */
-	if (!gpio_is_valid(template->gpio)) {
-		dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
-				template->gpio, template->name);
-		return 0;
+		/* skip leds that aren't available */
+		if (!gpio_is_valid(template->gpio)) {
+			dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
+					template->gpio, template->name);
+			return 0;
+		}
+
+		if (template->active_low)
+			flags |= GPIOF_ACTIVE_LOW;
+
+		ret = devm_gpio_request_one(parent, template->gpio, flags,
+					    template->name);
+		if (ret < 0)
+			return ret;
+
+		led_dat->gpiod = gpio_to_desc(template->gpio);
+		if (IS_ERR(led_dat->gpiod))
+			return PTR_ERR(led_dat->gpiod);
 	}
 
-	ret = devm_gpio_request(parent, template->gpio, template->name);
-	if (ret < 0)
-		return ret;
-
 	led_dat->cdev.name = template->name;
 	led_dat->cdev.default_trigger = template->default_trigger;
-	led_dat->gpio = template->gpio;
-	led_dat->can_sleep = gpio_cansleep(template->gpio);
-	led_dat->active_low = template->active_low;
+	led_dat->gpiod = template->gpiod;
+	led_dat->can_sleep = gpiod_cansleep(template->gpiod);
 	led_dat->blinking = 0;
 	if (blink_set) {
 		led_dat->platform_gpio_blink_set = blink_set;
@@ -122,30 +138,24 @@ static int create_gpio_led(const struct
 	}
 	led_dat->cdev.brightness_set = gpio_led_set;
 	if (template->default_state == LEDS_GPIO_DEFSTATE_KEEP)
-		state = !!gpio_get_value_cansleep(led_dat->gpio) ^ led_dat->active_low;
+		state = !!gpiod_get_value_cansleep(led_dat->gpiod);
 	else
 		state = (template->default_state == LEDS_GPIO_DEFSTATE_ON);
 	led_dat->cdev.brightness = state ? LED_FULL : LED_OFF;
 	if (!template->retain_state_suspended)
 		led_dat->cdev.flags |= LED_CORE_SUSPENDRESUME;
 
-	ret = gpio_direction_output(led_dat->gpio, led_dat->active_low ^ state);
+	ret = gpiod_direction_output(led_dat->gpiod, state);
 	if (ret < 0)
 		return ret;
 
 	INIT_WORK(&led_dat->work, gpio_led_work);
 
-	ret = led_classdev_register(parent, &led_dat->cdev);
-	if (ret < 0)
-		return ret;
-
-	return 0;
+	return led_classdev_register(parent, &led_dat->cdev);
 }
 
 static void delete_gpio_led(struct gpio_led_data *led)
 {
-	if (!gpio_is_valid(led->gpio))
-		return;
 	led_classdev_unregister(&led->cdev);
 	cancel_work_sync(&led->work);
 }
Index: linux-pm/include/linux/leds.h
===================================================================
--- linux-pm.orig/include/linux/leds.h
+++ linux-pm/include/linux/leds.h
@@ -251,6 +251,7 @@ struct gpio_led {
 	unsigned	retain_state_suspended : 1;
 	unsigned	default_state : 2;
 	/* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
+	struct gpio_desc *gpiod;
 };
 #define LEDS_GPIO_DEFSTATE_OFF		0
 #define LEDS_GPIO_DEFSTATE_ON		1

^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 08/12] input: gpio_keys_polled - Add support for GPIO descriptors
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (6 preceding siblings ...)
  2014-10-17 12:11   ` [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors Rafael J. Wysocki
@ 2014-10-17 12:12   ` Rafael J. Wysocki
  2014-10-17 12:14   ` [PATCH v5 09/12] Driver core: Unified interface for firmware node properties Rafael J. Wysocki
                     ` (6 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:12 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Aaron Lu <aaron.lu@intel.com>

GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c | 39 +++++++++++++++++++++----------
 include/linux/gpio_keys.h                 |  3 +++
 2 files changed, 30 insertions(+), 12 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 432d363..b7a514c 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -23,6 +23,7 @@
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -51,15 +52,14 @@ static void gpio_keys_polled_check_state(struct input_dev *input,
 	int state;
 
 	if (bdata->can_sleep)
-		state = !!gpio_get_value_cansleep(button->gpio);
+		state = !!gpiod_get_value_cansleep(button->gpiod);
 	else
-		state = !!gpio_get_value(button->gpio);
+		state = !!gpiod_get_value(button->gpiod);
 
 	if (state != bdata->last_state) {
 		unsigned int type = button->type ?: EV_KEY;
 
-		input_event(input, type, button->code,
-			    !!(state ^ button->active_low));
+		input_event(input, type, button->code, state);
 		input_sync(input);
 		bdata->count = 0;
 		bdata->last_state = state;
@@ -259,7 +259,6 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 	for (i = 0; i < pdata->nbuttons; i++) {
 		struct gpio_keys_button *button = &pdata->buttons[i];
 		struct gpio_keys_button_data *bdata = &bdev->data[i];
-		unsigned int gpio = button->gpio;
 		unsigned int type = button->type ?: EV_KEY;
 
 		if (button->wakeup) {
@@ -267,15 +266,31 @@ static int gpio_keys_polled_probe(struct platform_device *pdev)
 			return -EINVAL;
 		}
 
-		error = devm_gpio_request_one(&pdev->dev, gpio, GPIOF_IN,
-					      button->desc ? : DRV_NAME);
-		if (error) {
-			dev_err(dev, "unable to claim gpio %u, err=%d\n",
-				gpio, error);
-			return error;
+		/*
+		 * Legacy GPIO number so request the GPIO here and
+		 * convert it to descriptor.
+		 */
+		if (!button->gpiod && gpio_is_valid(button->gpio)) {
+			unsigned flags = 0;
+
+			if (button->active_low)
+				flags |= GPIOF_ACTIVE_LOW;
+
+			error = devm_gpio_request_one(&pdev->dev, button->gpio,
+					flags, button->desc ? : DRV_NAME);
+			if (error) {
+				dev_err(dev, "unable to claim gpio %u, err=%d\n",
+					button->gpio, error);
+				return error;
+			}
+
+			button->gpiod = gpio_to_desc(button->gpio);
 		}
 
-		bdata->can_sleep = gpio_cansleep(gpio);
+		if (IS_ERR(button->gpiod))
+			return PTR_ERR(button->gpiod);
+
+		bdata->can_sleep = gpiod_cansleep(button->gpiod);
 		bdata->last_state = -1;
 		bdata->threshold = DIV_ROUND_UP(button->debounce_interval,
 						pdata->poll_interval);
diff --git a/include/linux/gpio_keys.h b/include/linux/gpio_keys.h
index 8b62246..ee2d8c6 100644
--- a/include/linux/gpio_keys.h
+++ b/include/linux/gpio_keys.h
@@ -2,6 +2,7 @@
 #define _GPIO_KEYS_H
 
 struct device;
+struct gpio_desc;
 
 /**
  * struct gpio_keys_button - configuration parameters
@@ -17,6 +18,7 @@ struct device;
  *			disable button via sysfs
  * @value:		axis value for %EV_ABS
  * @irq:		Irq number in case of interrupt keys
+ * @gpiod:		GPIO descriptor
  */
 struct gpio_keys_button {
 	unsigned int code;
@@ -29,6 +31,7 @@ struct gpio_keys_button {
 	bool can_disable;
 	int value;
 	unsigned int irq;
+	struct gpio_desc *gpiod;
 };
 
 /**
-- 
1.9.3



^ permalink raw reply related	[flat|nested] 104+ messages in thread

* [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (7 preceding siblings ...)
  2014-10-17 12:12   ` [PATCH v5 08/12] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-17 12:14   ` Rafael J. Wysocki
  2014-10-18  9:35     ` Arnd Bergmann
                       ` (3 more replies)
  2014-10-17 12:16   ` [PATCH v5 10/12] gpio: Support for unified device properties interface Rafael J. Wysocki
                     ` (5 subsequent siblings)
  14 siblings, 4 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:14 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

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

Add new generic routines are provided for retrieving properties from
device description objects in the platform firmware in case there are
no struct device objects for them (either those objects have not been
created yet or they do not exist at all).

The following functions are provided:

fwnode_property_present()
fwnode_property_read_u8()
fwnode_property_read_u16()
fwnode_property_read_u32()
fwnode_property_read_u64()
fwnode_property_read_string()
fwnode_property_read_u8_array()
fwnode_property_read_u16_array()
fwnode_property_read_u32_array()
fwnode_property_read_u64_array()
fwnode_property_read_string_array()

in analogy with the corresponding functions for struct device added
previously.  For all of them, the first argument is a pointer to struct
fwnode_handle (new type) that allows a device description object
(depending on what platform firmware interface is in use) to be
obtained.

Add 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.

Suggested-by: Grant Likely <grant.likely@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/acpi/scan.c      |   21 ++
 drivers/base/property.c  |  373 +++++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h  |   12 +
 include/linux/acpi.h     |   21 ++
 include/linux/of.h       |   22 ++
 include/linux/property.h |   48 ++++++
 6 files changed, 497 insertions(+)

Index: linux-pm/include/linux/property.h
===================================================================
--- linux-pm.orig/include/linux/property.h
+++ linux-pm/include/linux/property.h
@@ -44,4 +44,52 @@ int device_property_read_u64_array(struc
 int device_property_read_string_array(struct device *dev, const char *propname,
 				      char **val, size_t nval);
 
+enum fwnode_type {
+	FWNODE_INVALID = 0,
+	FWNODE_OF,
+	FWNODE_ACPI,
+};
+
+struct fwnode_handle {
+	enum fwnode_type type;
+};
+
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
+int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
+			    u8 *val);
+int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
+			     u16 *val);
+int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
+			     u32 *val);
+int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
+			     u64 *val);
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+				const char *propname, const char **val);
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+				  const char *propname, u8 *val,
+				  size_t nval);
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+				   const char *propname, u16 *val,
+				   size_t nval);
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+				   const char *propname, u32 *val,
+				   size_t nval);
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+				   const char *propname, u64 *val,
+				   size_t nval);
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+				      const char *propname, char **val,
+				      size_t nval);
+
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+						 struct fwnode_handle *child);
+
+#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))
+
+void fwnode_handle_put(struct fwnode_handle *fwnode);
+
+unsigned int device_get_child_node_count(struct device *dev);
+
 #endif /* _LINUX_PROPERTY_H_ */
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -27,6 +27,7 @@
 #define __ACPI_BUS_H__
 
 #include <linux/device.h>
+#include <linux/property.h>
 
 /* TBD: Make dynamic */
 #define ACPI_MAX_HANDLES	10
@@ -348,6 +349,7 @@ struct acpi_device_data {
 struct acpi_device {
 	int device_type;
 	acpi_handle handle;		/* no handle for fixed hardware */
+	struct fwnode_handle fwnode;
 	struct acpi_device *parent;
 	struct list_head children;
 	struct list_head node;
@@ -372,6 +374,16 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_ACPI;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+	return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
+}
+
 static inline void *acpi_driver_data(struct acpi_device *d)
 {
 	return d->driver_data;
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -439,6 +439,18 @@ int acpi_device_modalias(struct device *
 #define ACPI_COMPANION_SET(dev, adev)	do { } while (0)
 #define ACPI_HANDLE(dev)		(NULL)
 
+struct fwnode_handle;
+
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+	return false;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
 static inline const char *acpi_dev_name(struct acpi_device *adev)
 {
 	return NULL;
@@ -681,6 +693,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,
@@ -724,6 +739,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/include/linux/of.h
===================================================================
--- linux-pm.orig/include/linux/of.h
+++ linux-pm/include/linux/of.h
@@ -50,6 +50,7 @@ struct device_node {
 	const char *type;
 	phandle phandle;
 	const char *full_name;
+	struct fwnode_handle fwnode;
 
 	struct	property *properties;
 	struct	property *deadprops;	/* removed properties */
@@ -80,6 +81,7 @@ extern struct kobj_type of_node_ktype;
 static inline void of_node_init(struct device_node *node)
 {
 	kobject_init(&node->kobj, &of_node_ktype);
+	node->fwnode.type = FWNODE_OF;
 }
 
 /* true when node is initialized */
@@ -115,6 +117,16 @@ extern struct device_node *of_aliases;
 extern struct device_node *of_stdout;
 extern raw_spinlock_t devtree_lock;
 
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_OF;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+	return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
+}
+
 static inline bool of_have_populated_dt(void)
 {
 	return of_allnodes != NULL;
@@ -365,6 +377,16 @@ bool of_console_check(struct device_node
 
 #else /* CONFIG_OF */
 
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+	return false;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
 static inline const char* of_node_full_name(const struct device_node *np)
 {
 	return "<no-node>";
Index: linux-pm/drivers/base/property.c
===================================================================
--- linux-pm.orig/drivers/base/property.c
+++ linux-pm/drivers/base/property.c
@@ -156,6 +156,166 @@ int device_property_read_string(struct d
 }
 EXPORT_SYMBOL_GPL(device_property_read_string);
 
+/**
+ * fwnode_property_present - check if a property of a firmware node is present
+ * @fwnode: Firmware node whose property to check
+ * @propname: Name of the property
+ */
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_bool(of_node(fwnode), propname);
+	else if (is_acpi_node(fwnode))
+		return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_present);
+
+/**
+ * fwnode_property_read_u8 - return a u8 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u8.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u8,
+ *	   %-EOVERFLOW if the property value is out of bounds of u8,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
+			    u8 *val)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_u8(of_node(fwnode), propname, val);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read(acpi_node(fwnode), propname,
+					  DEV_PROP_U8, val);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u8);
+
+/**
+ * fwnode_property_read_u16 - return a u16 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u16.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u16,
+ *	   %-EOVERFLOW if the property value is out of bounds of u16,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
+			     u16 *val)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_u16(of_node(fwnode), propname, val);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read(acpi_node(fwnode), propname,
+					  DEV_PROP_U16, val);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u16);
+
+/**
+ * fwnode_property_read_u32 - return a u32 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u32.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u32,
+ *	   %-EOVERFLOW if the property value is out of bounds of u32,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
+			     u32 *val)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_u32(of_node(fwnode), propname, val);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read(acpi_node(fwnode), propname,
+					  DEV_PROP_U32, val);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u32);
+
+/**
+ * fwnode_property_read_u64 - return a u64 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u64.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u64,
+ *	   %-EOVERFLOW if the property value is out of bounds of u64,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
+			     u64 *val)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_u64(of_node(fwnode), propname, val);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read(acpi_node(fwnode), propname,
+					  DEV_PROP_U64, val);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u64);
+
+/**
+ * fwnode_property_read_string - return a string property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be a string.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property is not a string,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+				const char *propname, const char **val)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_string(of_node(fwnode), propname, val);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read(acpi_node(fwnode), propname,
+					  DEV_PROP_STRING, val);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string);
+
 #define of_dev_prop_read_array(node, propname, type, val, nval) \
 	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
 	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
@@ -299,3 +459,216 @@ int device_property_read_string_array(st
 					DEV_PROP_STRING, val, nval);
 }
 EXPORT_SYMBOL_GPL(device_property_read_string_array);
+
+/**
+ * fwnode_property_read_u8_array - return a u8 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u8 properties with @propname from @fwnode and stores them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+				  const char *propname, u8 *val, size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_dev_prop_read_array(of_node(fwnode), propname,
+					      u8, val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_U8, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
+
+/**
+ * fwnode_property_read_u16_array - return a u16 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u16 properties with @propname from @fwnode and store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+				   const char *propname, u16 *val, size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_dev_prop_read_array(of_node(fwnode), propname,
+					      u16, val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_U16, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
+
+/**
+ * fwnode_property_read_u32_array - return a u32 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u32 properties with @propname from @fwnode store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+				   const char *propname, u32 *val, size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_dev_prop_read_array(of_node(fwnode), propname,
+					      u32, val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_U32, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
+
+/**
+ * fwnode_property_read_u64_array - return a u64 array property firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u64 properties with @propname from @fwnode and store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+				   const char *propname, u64 *val, size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_dev_prop_read_array(of_node(fwnode), propname,
+					      u64, val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_U64, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
+
+/**
+ * fwnode_property_read_string_array - return string array property of a node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an string list property @propname from the given firmware node and store
+ * them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of strings,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+				      const char *propname, char **val,
+				      size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_string_array(of_node(fwnode), propname,
+						     val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_STRING, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
+
+
+/**
+ * device_get_next_child_node - Return the next child node handle for a device
+ * @dev: Device to find the next child node for.
+ * @child: Handle to one of the device's child nodes or a null handle.
+ */
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+						 struct fwnode_handle *child)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+		struct device_node *node;
+
+		node = of_get_next_available_child(dev->of_node, of_node(child));
+		if (node)
+			return &node->fwnode;
+	} else if (ACPI_COMPANION(dev)) {
+		struct acpi_device *node;
+
+		node = acpi_get_next_child(dev, acpi_node(child));
+		if (node)
+			return &node->fwnode;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(device_get_next_child_node);
+
+/**
+ * fwnode_handle_put - Drop reference to a device node
+ * @fwnode: Pointer to the device node 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 fwnode_handle_put(struct fwnode_handle *fwnode)
+{
+	if (is_of_node(fwnode))
+		of_node_put(of_node(fwnode));
+}
+EXPORT_SYMBOL_GPL(fwnode_handle_put);
+
+/**
+ * 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)
+{
+	struct fwnode_handle *child;
+	unsigned int count = 0;
+
+	device_for_each_child_node(dev, child)
+		count++;
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(device_get_child_node_count);
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
    -------------------------------------------------------------------------- */
@@ -1961,6 +1981,7 @@ void acpi_init_device_object(struct acpi
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
+	device->fwnode.type = FWNODE_ACPI;
 	acpi_set_device_status(device, sta);
 	acpi_device_get_busid(device);
 	acpi_set_pnp_ids(handle, &device->pnp, type);


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 10/12] gpio: Support for unified device properties interface
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (8 preceding siblings ...)
  2014-10-17 12:14   ` [PATCH v5 09/12] Driver core: Unified interface for firmware node properties Rafael J. Wysocki
@ 2014-10-17 12:16   ` Rafael J. Wysocki
  2014-10-17 18:09     ` Arnd Bergmann
  2014-10-17 12:17   ` [PATCH v5 11/12] leds: leds-gpio: Make use of device property API Rafael J. Wysocki
                     ` (4 subsequent siblings)
  14 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:16 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Mika Westerberg <mika.westerberg@linux.intel.com>

Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.

In order to help device drivers to handle such firmware child nodes we
add dev[m]_get_named_gpiod_from_child() that takes a child firmware
node pointer as its second argument (the first one is the parent device
itself), finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/gpio/devres.c         |   36 +++++++++++++++++++++++++++
 drivers/gpio/gpiolib.c        |   56 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/gpio/consumer.h |    8 ++++++
 3 files changed, 100 insertions(+)

Index: linux-pm/drivers/gpio/devres.c
===================================================================
--- linux-pm.orig/drivers/gpio/devres.c
+++ linux-pm/drivers/gpio/devres.c
@@ -109,6 +109,42 @@ struct gpio_desc *__must_check __devm_gp
 EXPORT_SYMBOL(__devm_gpiod_get_index);
 
 /**
+ * devm_get_named_gpiod_from_child - managed dev_get_named_gpiod_from_child()
+ * @dev:	GPIO consumer
+ * @child:	firmware node (child of @dev)
+ * @propname:	name of the firmware property
+ * @index:	index of the GPIO in the property value in case of many
+ *
+ * GPIO descriptors returned from this function are automatically disposed on
+ * driver detach.
+ */
+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev,
+						  struct fwnode_handle *child,
+						  const char *propname,
+						  int index)
+{
+	struct gpio_desc **dr;
+	struct gpio_desc *desc;
+
+	dr = devres_alloc(devm_gpiod_release, sizeof(struct gpio_desc *),
+			  GFP_KERNEL);
+	if (!dr)
+		return ERR_PTR(-ENOMEM);
+
+	desc = fwnode_get_named_gpiod(child, propname, index);
+	if (IS_ERR(desc)) {
+		devres_free(dr);
+		return desc;
+	}
+
+	*dr = desc;
+	devres_add(dev, dr);
+
+	return desc;
+}
+EXPORT_SYMBOL(devm_get_named_gpiod_from_child);
+
+/**
  * devm_gpiod_get_index_optional - Resource-managed gpiod_get_index_optional()
  * @dev: GPIO consumer
  * @con_id: function within the GPIO consumer
Index: linux-pm/drivers/gpio/gpiolib.c
===================================================================
--- linux-pm.orig/drivers/gpio/gpiolib.c
+++ linux-pm/drivers/gpio/gpiolib.c
@@ -1735,6 +1735,62 @@ struct gpio_desc *__must_check __gpiod_g
 EXPORT_SYMBOL_GPL(__gpiod_get_index);
 
 /**
+ * fwnode_get_named_gpiod - obtain a GPIO from firmware node
+ * @fwnode:	handle of the firmware node
+ * @propname:	name of the firmware property
+ * @idx:	index of the GPIO in the property value in case of many
+ *
+ * This function can be used for drivers that get their configuration
+ * from firmware.
+ *
+ * Function properly finds the corresponding GPIO using whatever is the
+ * underlying firmware interface and then makes sure that the GPIO
+ * descriptor is requested before it is returned to the caller.
+ *
+ * In case of error an ERR_PTR() is returned.
+ */
+struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
+					 const char *propname, int index)
+{
+	struct gpio_desc *desc = ERR_PTR(-ENODEV);
+	bool active_low = false;
+	int ret;
+
+	if (!fwnode)
+		return ERR_PTR(-EINVAL);
+
+	if (is_of_node(fwnode)) {
+		enum of_gpio_flags flags;
+
+		desc = of_get_named_gpiod_flags(of_node(fwnode), propname,
+						index, &flags);
+		if (!IS_ERR(desc))
+			active_low = flags & OF_GPIO_ACTIVE_LOW;
+	} else if (is_acpi_node(fwnode)) {
+		struct acpi_gpio_info info;
+
+		desc = acpi_get_gpiod_by_index(acpi_node(fwnode), propname,
+					       index, &info);
+		if (!IS_ERR(desc))
+			active_low = info.active_low;
+	}
+
+	if (IS_ERR(desc))
+		return desc;
+
+	ret = gpiod_request(desc, NULL);
+	if (ret)
+		return ERR_PTR(ret);
+
+	/* Only value flag can be set from both DT and ACPI is active_low */
+	if (active_low)
+		set_bit(FLAG_ACTIVE_LOW, &desc->flags);
+
+	return desc;
+}
+EXPORT_SYMBOL_GPL(fwnode_get_named_gpiod);
+
+/**
  * gpiod_get_index_optional - obtain an optional GPIO from a multi-index GPIO
  *                            function
  * @dev: GPIO consumer, can be NULL for system-global GPIOs
Index: linux-pm/include/linux/gpio/consumer.h
===================================================================
--- linux-pm.orig/include/linux/gpio/consumer.h
+++ linux-pm/include/linux/gpio/consumer.h
@@ -94,6 +94,14 @@ int gpiod_to_irq(const struct gpio_desc
 struct gpio_desc *gpio_to_desc(unsigned gpio);
 int desc_to_gpio(const struct gpio_desc *desc);
 
+/* Child properties interface */
+struct fwnode_handle;
+
+struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode,
+					 const char *propname, int index);
+struct gpio_desc *devm_get_named_gpiod_from_child(struct device *dev,
+						  struct fwnode_handle *child,
+						  const char *propname, int index);
 #else /* CONFIG_GPIOLIB */
 
 static inline struct gpio_desc *__must_check __gpiod_get(struct device *dev,


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 11/12] leds: leds-gpio: Make use of device property API
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (9 preceding siblings ...)
  2014-10-17 12:16   ` [PATCH v5 10/12] gpio: Support for unified device properties interface Rafael J. Wysocki
@ 2014-10-17 12:17   ` Rafael J. Wysocki
  2014-10-17 12:18   ` [PATCH v5 12/12] input: gpio_keys_polled - " Rafael J. Wysocki
                     ` (3 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:17 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

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

Make use of device property API in this driver so that both OF and ACPI
based system can use the same driver.

This change contains material from Max Eliaser and Mika Westerberg.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Bryan Wu <cooloney@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/leds/leds-gpio.c |   62 ++++++++++++++++++-----------------------------
 1 file changed, 25 insertions(+), 37 deletions(-)

Index: linux-pm/drivers/leds/leds-gpio.c
===================================================================
--- linux-pm.orig/drivers/leds/leds-gpio.c
+++ linux-pm/drivers/leds/leds-gpio.c
@@ -15,13 +15,11 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/leds.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/property.h>
 
 struct gpio_led_data {
 	struct led_classdev cdev;
@@ -171,40 +169,37 @@ static inline int sizeof_gpio_leds_priv(
 		(sizeof(struct gpio_led_data) * num_leds);
 }
 
-/* Code to create from OpenFirmware platform devices */
-#ifdef CONFIG_OF_GPIO
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
+static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
 {
-	struct device_node *np = pdev->dev.of_node, *child;
+	struct device *dev = &pdev->dev;
+	struct fwnode_handle *child;
 	struct gpio_leds_priv *priv;
 	int count, ret;
 
-	/* count LEDs in this device, so we know how much to allocate */
-	count = of_get_available_child_count(np);
+	count = device_get_child_node_count(dev);
 	if (!count)
 		return ERR_PTR(-ENODEV);
 
-	for_each_available_child_of_node(np, child)
-		if (of_get_gpio(child, 0) == -EPROBE_DEFER)
-			return ERR_PTR(-EPROBE_DEFER);
-
-	priv = devm_kzalloc(&pdev->dev, sizeof_gpio_leds_priv(count),
-			GFP_KERNEL);
+	priv = devm_kzalloc(dev, sizeof_gpio_leds_priv(count), GFP_KERNEL);
 	if (!priv)
 		return ERR_PTR(-ENOMEM);
 
-	for_each_available_child_of_node(np, child) {
+	device_for_each_child_node(dev, child) {
 		struct gpio_led led = {};
-		enum of_gpio_flags flags;
-		const char *state;
+		const char *state = NULL;
+
+		led.gpiod = devm_get_named_gpiod_from_child(dev, child, "gpios", 0);
+		if (IS_ERR(led.gpiod)) {
+			fwnode_handle_put(child);
+			goto err;
+		}
+
+		fwnode_property_read_string(child, "label", &led.name);
+		fwnode_property_read_string(child, "linux,default-trigger",
+					    &led.default_trigger);
 
-		led.gpio = of_get_gpio_flags(child, 0, &flags);
-		led.active_low = flags & OF_GPIO_ACTIVE_LOW;
-		led.name = of_get_property(child, "label", NULL) ? : child->name;
-		led.default_trigger =
-			of_get_property(child, "linux,default-trigger", NULL);
-		state = of_get_property(child, "default-state", NULL);
-		if (state) {
+		if (!fwnode_property_read_string(child, "linux,default_state",
+						 &state)) {
 			if (!strcmp(state, "keep"))
 				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
 			else if (!strcmp(state, "on"))
@@ -213,13 +208,13 @@ static struct gpio_leds_priv *gpio_leds_
 				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
 		}
 
-		if (of_get_property(child, "retain-state-suspended", NULL))
+		if (fwnode_property_present(child, "retain-state-suspended"))
 			led.retain_state_suspended = 1;
 
 		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
-				      &pdev->dev, NULL);
+				      dev, NULL);
 		if (ret < 0) {
-			of_node_put(child);
+			fwnode_handle_put(child);
 			goto err;
 		}
 	}
@@ -238,13 +233,6 @@ static const struct of_device_id of_gpio
 };
 
 MODULE_DEVICE_TABLE(of, of_gpio_leds_match);
-#else /* CONFIG_OF_GPIO */
-static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
-{
-	return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_OF_GPIO */
-
 
 static int gpio_led_probe(struct platform_device *pdev)
 {
@@ -273,7 +261,7 @@ static int gpio_led_probe(struct platfor
 			}
 		}
 	} else {
-		priv = gpio_leds_create_of(pdev);
+		priv = gpio_leds_create(pdev);
 		if (IS_ERR(priv))
 			return PTR_ERR(priv);
 	}
@@ -300,7 +288,7 @@ static struct platform_driver gpio_led_d
 	.driver		= {
 		.name	= "leds-gpio",
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(of_gpio_leds_match),
+		.of_match_table = of_gpio_leds_match,
 	},
 };
 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [PATCH v5 12/12] input: gpio_keys_polled - Make use of device property API
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (10 preceding siblings ...)
  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   ` Rafael J. Wysocki
  2014-10-17 12:22   ` [PATCH v5 00/12] Add ACPI _DSD and unified device properties support Rafael J. Wysocki
                     ` (2 subsequent siblings)
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:18 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

From: Aaron Lu <aaron.lu@intel.com>

Make use of device property API in this driver so that both OF based
system and ACPI based system can use this driver.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c |   73 +++++++++---------------------
 1 file changed, 24 insertions(+), 49 deletions(-)

Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
===================================================================
--- linux-pm.orig/drivers/input/keyboard/gpio_keys_polled.c
+++ linux-pm/drivers/input/keyboard/gpio_keys_polled.c
@@ -25,9 +25,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/gpio_keys.h>
-#include <linux/of.h>
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
+#include <linux/property.h>
 
 #define DRV_NAME	"gpio-keys-polled"
 
@@ -102,21 +100,15 @@ static void gpio_keys_polled_close(struc
 		pdata->disable(bdev->dev);
 }
 
-#ifdef CONFIG_OF
 static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct device *dev)
 {
-	struct device_node *node, *pp;
 	struct gpio_keys_platform_data *pdata;
 	struct gpio_keys_button *button;
+	struct fwnode_handle *child;
 	int error;
 	int nbuttons;
-	int i;
-
-	node = dev->of_node;
-	if (!node)
-		return NULL;
 
-	nbuttons = of_get_child_count(node);
+	nbuttons = device_get_child_node_count(dev);
 	if (nbuttons == 0)
 		return NULL;
 
@@ -126,52 +118,44 @@ static struct gpio_keys_platform_data *g
 		return ERR_PTR(-ENOMEM);
 
 	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-	pdata->nbuttons = nbuttons;
 
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+	pdata->rep = device_property_present(dev, "autorepeat");
+	device_property_read_u32(dev, "poll-interval", &pdata->poll_interval);
 
-	i = 0;
-	for_each_child_of_node(node, pp) {
-		int gpio;
-		enum of_gpio_flags flags;
-
-		if (!of_find_property(pp, "gpios", NULL)) {
-			pdata->nbuttons--;
-			dev_warn(dev, "Found button without gpios\n");
-			continue;
-		}
+	device_for_each_child_node(dev, child) {
+		struct gpio_desc *desc;
 
-		gpio = of_get_gpio_flags(pp, 0, &flags);
-		if (gpio < 0) {
-			error = gpio;
+		desc = devm_get_named_gpiod_from_child(dev, child, "gpios", 0);
+		if (IS_ERR(desc)) {
+			error = PTR_ERR(desc);
 			if (error != -EPROBE_DEFER)
 				dev_err(dev,
 					"Failed to get gpio flags, error: %d\n",
 					error);
+			fwnode_handle_put(child);
 			return ERR_PTR(error);
 		}
 
-		button = &pdata->buttons[i++];
-
-		button->gpio = gpio;
-		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+		button = &pdata->buttons[pdata->nbuttons++];
+		button->gpiod = desc;
 
-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: 0x%x\n",
-				button->gpio);
+		if (fwnode_property_read_u32(child, "linux,code", &button->code)) {
+			dev_err(dev, "Button without keycode: %d\n",
+				pdata->nbuttons - 1);
+			fwnode_handle_put(child);
 			return ERR_PTR(-EINVAL);
 		}
 
-		button->desc = of_get_property(pp, "label", NULL);
+		fwnode_property_read_string(child, "label", &button->desc);
 
-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
+		if (fwnode_property_read_u32(child, "linux,input-type",
+					     &button->type))
 			button->type = EV_KEY;
 
-		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+		button->wakeup = fwnode_property_present(child, "gpio-key,wakeup");
 
-		if (of_property_read_u32(pp, "debounce-interval",
-					 &button->debounce_interval))
+		if (fwnode_property_read_u32(child, "debounce-interval",
+					     &button->debounce_interval))
 			button->debounce_interval = 5;
 	}
 
@@ -187,15 +171,6 @@ static const struct of_device_id gpio_ke
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
 
-#else
-
-static inline struct gpio_keys_platform_data *
-gpio_keys_polled_get_devtree_pdata(struct device *dev)
-{
-	return NULL;
-}
-#endif
-
 static int gpio_keys_polled_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
@@ -323,7 +298,7 @@ static struct platform_driver gpio_keys_
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
-		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
+		.of_match_table = gpio_keys_polled_of_match,
 	},
 };
 module_platform_driver(gpio_keys_polled_driver);


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (11 preceding siblings ...)
  2014-10-17 12:18   ` [PATCH v5 12/12] input: gpio_keys_polled - " Rafael J. Wysocki
@ 2014-10-17 12:22   ` Rafael J. Wysocki
  2014-10-17 15:40   ` Greg Kroah-Hartman
  2014-10-17 18:04   ` Arnd Bergmann
  14 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 12:22 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Mika Westerberg
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

On Friday, October 17, 2014 02:01:33 PM Rafael J. Wysocki wrote:
> Hi Everyone,
> 
> Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
> now have version 5 taking all feedback into account (hopefully).
> 
> Changes have been made to patch [02/12] and to patches [09-12/12], although
> in patches [10-12/12] they are fairly minor.  I have retained the Greg's
> ACK on patch [02/12], because it is essentially the same that have been
> posted aleady and ACKed by him (Greg, please let me know if I shouldn't
> do that) and all the ACKs on the remaining patches except for patch [09/12]
> which is substantially different.  Still, if reviewers think that their
> ACKs don't apply any more, please let me know and I'll remove them.
> 
> Patch [02/12] now contains helper functions for all proprerty data types
> that can be accessed which call the existing of_ functions, because Grant
> preferred that.
> 
> Patch [09/12] introduces quite a new concept, which is the struct fwnode_handle
> structure containing one field (type) and embedded in struct device_node
> (type==FWNODE_OF) and struct acpi_device (type==FWNODE_ACPI).  In short, if
> we are passed a struct fwnode_handle pointer, we can get from it to the
> appropriate device node pointer (either struct acpi_device or struct device_node)
> using container_of() after we've checked the type.  This is needed for the code
> that needs to access child nodes of a device in case when they don't have
> struct device representations (whatever the reason).  This has been suggested
> by Grant and pretty much everyone involved agrees that it's better that the
> alternatives presented so far.

While at it, many thanks to Mika for testing the patches on MinnowBoard 1 and
MinnowBoard Max and fixing build problems with them while we've been having
fun at the conferences!  I wouldn't have been able to prepare the patchset
for posting without that work.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (12 preceding siblings ...)
  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-17 18:04   ` Arnd Bergmann
  14 siblings, 2 replies; 104+ messages in thread
From: Greg Kroah-Hartman @ 2014-10-17 15:40 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Fri, Oct 17, 2014 at 02:01:33PM +0200, Rafael J. Wysocki wrote:
> Hi Everyone,
> 
> Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
> now have version 5 taking all feedback into account (hopefully).
> 
> Changes have been made to patch [02/12] and to patches [09-12/12], although
> in patches [10-12/12] they are fairly minor.  I have retained the Greg's
> ACK on patch [02/12], because it is essentially the same that have been
> posted aleady and ACKed by him (Greg, please let me know if I shouldn't
> do that) and all the ACKs on the remaining patches except for patch [09/12]
> which is substantially different.  Still, if reviewers think that their
> ACKs don't apply any more, please let me know and I'll remove them.

No objection from me to keep my ACK on those patches, thanks for asking.

greg k-h

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 12:01 ` [PATCH v5 00/12] " Rafael J. Wysocki
                     ` (13 preceding siblings ...)
  2014-10-17 15:40   ` Greg Kroah-Hartman
@ 2014-10-17 18:04   ` Arnd Bergmann
  2014-10-17 22:50     ` Rafael J. Wysocki
  14 siblings, 1 reply; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-17 18:04 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely
  Cc: Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland



On October 17, 2014 2:01:33 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
>Hi Everyone,
>
>Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC,
>we
>now have version 5 taking all feedback into account (hopefully).

Awesome, that was really fast. I'm currently on my way his me in the train, replying from my phone, but it looks good now. I'll have a more detailed look next week but I'm definitely happy to see this go in (to next and 3.19) now, any details we still find can be fixed on top.

> In
>short, if
>we are passed a struct fwnode_handle pointer, we can get from it to the
>appropriate device node pointer (either struct acpi_device or struct
>device_node)
>using container_of() after we've checked the type.  This is needed for
>the code
>that needs to access child nodes of a device in case when they don't
>have
>struct device representations (whatever the reason).  This has been
>suggested
>by Grant and pretty much everyone involved agrees that it's better that
>the
>alternatives presented so far.

Yes, it's nice enough that I now take back all the objections I had for the child accessory API.

        Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-17 18:09 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland



On October 17, 2014 2:16:00 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
>From: Mika Westerberg <mika.westerberg@linux.intel.com>
>
>Some drivers need to deal with only firmware representation of its
>GPIOs. An example would be a GPIO button array driver where each button
>is described as a separate firmware node in device tree. Typically
>these
>child nodes do not have physical representation in the Linux device
>model.
>
>In order to help device drivers to handle such firmware child nodes we
>add dev[m]_get_named_gpiod_from_child() that takes a child firmware
>node pointer as its second argument (the first one is the parent device
>itself), finds the GPIO using whatever is the underlying firmware
>method, and requests the GPIO properly.

Could we also have a wrapper around this function without a "name" argument, using just the index?

       Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 15:40   ` Greg Kroah-Hartman
@ 2014-10-17 19:23     ` Darren Hart
  2014-10-17 21:49     ` Rafael J. Wysocki
  1 sibling, 0 replies; 104+ messages in thread
From: Darren Hart @ 2014-10-17 19:23 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Mark Rutland



On 10/17/14 17:40, Greg Kroah-Hartman wrote:
> On Fri, Oct 17, 2014 at 02:01:33PM +0200, Rafael J. Wysocki wrote:
>> Hi Everyone,
>>
>> Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
>> now have version 5 taking all feedback into account (hopefully).
>>
>> Changes have been made to patch [02/12] and to patches [09-12/12], although
>> in patches [10-12/12] they are fairly minor.  I have retained the Greg's
>> ACK on patch [02/12], because it is essentially the same that have been
>> posted aleady and ACKed by him (Greg, please let me know if I shouldn't
>> do that) and all the ACKs on the remaining patches except for patch [09/12]
>> which is substantially different.  Still, if reviewers think that their
>> ACKs don't apply any more, please let me know and I'll remove them.
> 
> No objection from me to keep my ACK on those patches, thanks for asking.
> 
> greg k-h
> 

Mine certainly still apply as well.

-- 
Darren Hart
Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  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
  1 sibling, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 21:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Friday, October 17, 2014 05:40:07 PM Greg Kroah-Hartman wrote:
> On Fri, Oct 17, 2014 at 02:01:33PM +0200, Rafael J. Wysocki wrote:
> > Hi Everyone,
> > 
> > Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
> > now have version 5 taking all feedback into account (hopefully).
> > 
> > Changes have been made to patch [02/12] and to patches [09-12/12], although
> > in patches [10-12/12] they are fairly minor.  I have retained the Greg's
> > ACK on patch [02/12], because it is essentially the same that have been
> > posted aleady and ACKed by him (Greg, please let me know if I shouldn't
> > do that) and all the ACKs on the remaining patches except for patch [09/12]
> > which is substantially different.  Still, if reviewers think that their
> > ACKs don't apply any more, please let me know and I'll remove them.
> 
> No objection from me to keep my ACK on those patches, thanks for asking.

Well, that's just fair IMO. :-)

Does [09/12] look good too in particular?

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 18:04   ` Arnd Bergmann
@ 2014-10-17 22:50     ` Rafael J. Wysocki
  2014-10-18  8:49       ` Grant Likely
  0 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-17 22:50 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Friday, October 17, 2014 08:04:52 PM Arnd Bergmann wrote:
> 
> On October 17, 2014 2:01:33 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> >Hi Everyone,
> >
> >Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC,
> >we
> >now have version 5 taking all feedback into account (hopefully).
> 
> Awesome, that was really fast. I'm currently on my way his me in
> the train, replying from my phone, but it looks good now. I'll have a more
> detailed look next week but I'm definitely happy to see this go in (to next
> and 3.19) now, any details we still find can be fixed on top.
> 
> > In
> >short, if
> >we are passed a struct fwnode_handle pointer, we can get from it to the
> >appropriate device node pointer (either struct acpi_device or struct
> >device_node)
> >using container_of() after we've checked the type.  This is needed for
> >the code
> >that needs to access child nodes of a device in case when they don't
> >have
> >struct device representations (whatever the reason).  This has been
> >suggested
> >by Grant and pretty much everyone involved agrees that it's better that
> >the
> >alternatives presented so far.
> 
> Yes, it's nice enough that I now take back all the objections I had for the
> child accessory API.

Cool, thanks!

I've just refreshed the device-properties branch of the linux-pm.git tree
and it contains the current material now (including a couple of build
fixes reported by the autobuild robot in patches [02/12] and [09/12]).

My plan is to merge this into the linux-next branch when 3.18-rc1 is out.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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:35                 ` Grant Likely
  2014-10-21 21:50                   ` [PATCH v4 00/13] Add ACPI _DSD and unified device properties? support Darren Hart
  2 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-18  8:35 UTC (permalink / raw)
  To: Darren Hart, Mark Rutland
  Cc: David Woodhouse, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, dvhart

On Wed, 15 Oct 2014 17:43:01 +0200
, Darren Hart <dvhart@linux.intel.com>
 wrote:
> 
> 
> On 10/15/14 17:17, Mark Rutland wrote:
> > On Wed, Oct 15, 2014 at 03:46:39PM +0100, Darren Hart wrote:
> 
> >> Mark, what would you propose we do differently to enable this driver to
> >> be firmware-type agnostic?
> > 
> > For this particular driver, all I'm asking for is that the
> > "used-by-rtas" property is not moved over from of_find_property to
> > device_get_property. It is irrelevant for all ACPI systems. Evidently my
> > comment was unclear; I apologise for that.
> 
> So my objection here is that by keeping the of_* terms in the driver we
> are required to include of, although it does safely convert to returning
> NULL if !CONFIG_OF I suppose.

This shouldn't be that controversial. There will be things that only make
sense for DT or only ACPI. Allowing the property to be processed when
the other interface is being used may tempt firmware authors to use the
property because it just happens to have a side effect that looks right
to them.

I don't see any problem with factoring out those bits into a function
that is only called (or built) when the associated firmware interface is
used. In these situations, the driver isn't 100% generic, so having
small per-firmware hooks is absolutely okay and not a burden to
maintain.

g.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-16 14:55                 ` David Woodhouse
@ 2014-10-18  8:37                   ` Grant Likely
  2014-10-18  8:39                   ` Grant Likely
  1 sibling, 0 replies; 104+ messages in thread
From: Grant Likely @ 2014-10-18  8:37 UTC (permalink / raw)
  To: David Woodhouse, Darren Hart
  Cc: Mark Rutland, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, dvhart

On Thu, 16 Oct 2014 16:55:56 +0200
, David Woodhouse <dwmw2@infradead.org>
 wrote:
> On Wed, 2014-10-15 at 17:43 +0200, Darren Hart wrote:
> > 
> > So my objection here is that by keeping the of_* terms in the driver we
> > are required to include of, although it does safely convert to returning
> > NULL if !CONFIG_OF I suppose.
> 
> New version removes everything but the of_match_id bits which we need to
> match ACPI devices too. Perhaps they ought to be renamed, but I'm not
> sure it's worth it.
> 
> This also removes the call to platform_get_resource(IORESOURCE_MEM) and
> fall back to platform_get_resource(IORESOURCE_IO) as discussed IRL with
> Rafael. I'm not sure it's much of an improvement, mind you :)
> 
> Still untested. I think it's OK to switch to platform_get_irq() and then
> drop the irq_dispose_mapping() call, right? The platform_device takes
> care of all of that for us?

Well, the irq management code is all messed up, but what you are doing
is indeed okay. Unfortunately for platform devices we can never free an
IRQ once we've claimed it. That's a completely separate problem and you
don't need to worry about it for this patch.

g.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-16 14:55                 ` David Woodhouse
  2014-10-18  8:37                   ` Grant Likely
@ 2014-10-18  8:39                   ` Grant Likely
  1 sibling, 0 replies; 104+ messages in thread
From: Grant Likely @ 2014-10-18  8:39 UTC (permalink / raw)
  To: David Woodhouse, Darren Hart
  Cc: Mark Rutland, Rafael J. Wysocki, Linux Kernel Mailing List,
	Greg Kroah-Hartman, Mika Westerberg, ACPI Devel Maling List,
	Aaron Lu, devicetree, Linus Walleij, Alexandre Courbot,
	Dmitry Torokhov, Bryan Wu, Arnd Bergmann, dvhart

On Thu, 16 Oct 2014 16:55:56 +0200
, David Woodhouse <dwmw2@infradead.org>
 wrote:
> On Wed, 2014-10-15 at 17:43 +0200, Darren Hart wrote:
> > 
> > So my objection here is that by keeping the of_* terms in the driver we
> > are required to include of, although it does safely convert to returning
> > NULL if !CONFIG_OF I suppose.
> 
> New version removes everything but the of_match_id bits which we need to
> match ACPI devices too. Perhaps they ought to be renamed, but I'm not
> sure it's worth it.
> 
> This also removes the call to platform_get_resource(IORESOURCE_MEM) and
> fall back to platform_get_resource(IORESOURCE_IO) as discussed IRL with
> Rafael. I'm not sure it's much of an improvement, mind you :)
> 
> Still untested. I think it's OK to switch to platform_get_irq() and then
> drop the irq_dispose_mapping() call, right? The platform_device takes
> care of all of that for us?
> 
> diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
> index 26cec64..be95a4c 100644
> --- a/drivers/tty/serial/Kconfig
> +++ b/drivers/tty/serial/Kconfig
> @@ -1094,14 +1094,14 @@ config SERIAL_NETX_CONSOLE
>  	  you can make it the console by answering Y to this option.
>  
>  config SERIAL_OF_PLATFORM
> -	tristate "Serial port on Open Firmware platform bus"
> -	depends on OF
> +	tristate "Serial port on firmware platform bus"
> +	depends on OF || ACPI
>  	depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
>  	help
> -	  If you have a PowerPC based system that has serial ports
> -	  on a platform specific bus, you should enable this option.
> -	  Currently, only 8250 compatible ports are supported, but
> -	  others can easily be added.
> +	  If you have a system which advertises its serial ports through
> +	  devicetree or ACPI, you should enable this option. Currently
> +	  only 8250 compatible and NWP ports and are supported, but others
> +	  can easily be added.
>  
>  config SERIAL_OMAP
>  	tristate "OMAP serial port support"
> diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
> index 68d4455..cc6c99b 100644
> --- a/drivers/tty/serial/of_serial.c
> +++ b/drivers/tty/serial/of_serial.c
> @@ -14,8 +14,7 @@
>  #include <linux/delay.h>
>  #include <linux/serial_core.h>
>  #include <linux/serial_reg.h>
> -#include <linux/of_address.h>
> -#include <linux/of_irq.h>
> +#include <linux/property.h>
>  #include <linux/of_platform.h>
>  #include <linux/nwpserial.h>
>  #include <linux/clk.h>
> @@ -53,22 +52,22 @@ static inline void tegra_serial_handle_break(struct uart_port *port)
>  /*
>   * Fill a struct uart_port for a given device node
>   */
> -static int of_platform_serial_setup(struct platform_device *ofdev,
> +static int of_platform_serial_setup(struct platform_device *pdev,
>  			int type, struct uart_port *port,
>  			struct of_serial_info *info)
>  {
> -	struct resource resource;
> -	struct device_node *np = ofdev->dev.of_node;
>  	u32 clk, spd, prop;
> -	int ret;
> +	int iotype = -1;
> +	u32 res_start;
> +	int ret, i;
>  
>  	memset(port, 0, sizeof *port);
> -	if (of_property_read_u32(np, "clock-frequency", &clk)) {
> +	if (device_property_read_u32(&pdev->dev, "clock-frequency", &clk)) {
>  
>  		/* Get clk rate through clk driver if present */
> -		info->clk = clk_get(&ofdev->dev, NULL);
> +		info->clk = clk_get(&pdev->dev, NULL);
>  		if (IS_ERR(info->clk)) {
> -			dev_warn(&ofdev->dev,
> +			dev_warn(&pdev->dev,
>  				"clk or clock-frequency not defined\n");
>  			return PTR_ERR(info->clk);
>  		}
> @@ -77,57 +76,63 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
>  		clk = clk_get_rate(info->clk);
>  	}
>  	/* If current-speed was set, then try not to change it. */
> -	if (of_property_read_u32(np, "current-speed", &spd) == 0)
> +	if (device_property_read_u32(&pdev->dev, "current-speed", &spd) == 0)
>  		port->custom_divisor = clk / (16 * spd);
>  
> -	ret = of_address_to_resource(np, 0, &resource);
> -	if (ret) {
> -		dev_warn(&ofdev->dev, "invalid address\n");
> +	/* Check for shifted address mapping */
> +	if (device_property_read_u32(&pdev->dev, "reg-offset", &prop) != 0)
> +		prop = 0;
> +
> +	for (i = 0; iotype == -1 && i < pdev->num_resources; i++) {
> +		struct resource *resource = &pdev->resource[i];
> +		if (resource_type(resource) == IORESOURCE_MEM) {
> +			iotype = UPIO_MEM;
> +			port->mapbase = res_start + prop;
> +		} else if (resource_type(resource) == IORESOURCE_IO) {
> +			iotype = UPIO_PORT;
> +			port->iobase = res_start + prop;
> +		}
> +
> +		res_start = resource->start;
> +	}
> +	if (iotype == -1) {
> +		dev_warn(&pdev->dev, "invalid address\n");
>  		goto out;
>  	}
>  
>  	spin_lock_init(&port->lock);
> -	port->mapbase = resource.start;
> -
> -	/* Check for shifted address mapping */
> -	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
> -		port->mapbase += prop;
>  
>  	/* Check for registers offset within the devices address range */
> -	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
> +	if (device_property_read_u32(&pdev->dev, "reg-shift", &prop) == 0)
>  		port->regshift = prop;
>  
>  	/* Check for fifo size */
> -	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
> +	if (device_property_read_u32(&pdev->dev, "fifo-size", &prop) == 0)
>  		port->fifosize = prop;
>  
> -	port->irq = irq_of_parse_and_map(np, 0);
> -	port->iotype = UPIO_MEM;
> -	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
> -		switch (prop) {
> -		case 1:
> -			port->iotype = UPIO_MEM;
> -			break;
> -		case 4:
> -			port->iotype = UPIO_MEM32;
> -			break;
> -		default:
> -			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
> +	port->irq = platform_get_irq(pdev, 0);
> +
> +	if (device_property_read_u32(&pdev->dev, "reg-io-width", &prop) == 0) {
> +		if (prop == 4 && iotype == UPIO_MEM) {
> +			iotype = UPIO_MEM32;
> +		} else {
> +			dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
>  				 prop);
>  			ret = -EINVAL;
>  			goto out;
>  		}
>  	}
>  
> +	port->iotype = iotype;
>  	port->type = type;
>  	port->uartclk = clk;
>  	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
>  		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
>  
> -	if (of_find_property(np, "no-loopback-test", NULL))
> +	if (!device_get_property(&pdev->dev, "no-loopback-test", NULL))
>  		port->flags |= UPF_SKIP_TEST;
>  
> -	port->dev = &ofdev->dev;
> +	port->dev = &pdev->dev;
>  
>  	if (type == PORT_TEGRA)
>  		port->handle_break = tegra_serial_handle_break;
> @@ -143,7 +148,7 @@ out:
>   * Try to register a serial port
>   */
>  static struct of_device_id of_platform_serial_table[];
> -static int of_platform_serial_probe(struct platform_device *ofdev)
> +static int of_platform_serial_probe(struct platform_device *pdev)

Nit: Separate patch please. The rename of ofdev to pdev is nothing more
than cleanup. It has no functional impact and just makes the patch
larger.

>  {
>  	const struct of_device_id *match;
>  	struct of_serial_info *info;
> @@ -151,11 +156,11 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  	int port_type;
>  	int ret;
>  
> -	match = of_match_device(of_platform_serial_table, &ofdev->dev);
> +	match = of_match_device(of_platform_serial_table, &pdev->dev);
>  	if (!match)
>  		return -EINVAL;
>  
> -	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
> +	if (!device_get_property(&pdev->dev, "used-by-rtas", NULL))
>  		return -EBUSY;
>  
>  	info = kmalloc(sizeof(*info), GFP_KERNEL);
> @@ -163,7 +168,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  		return -ENOMEM;
>  
>  	port_type = (unsigned long)match->data;
> -	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
> +	ret = of_platform_serial_setup(pdev, port_type, &port, info);
>  	if (ret)
>  		goto out;
>  
> @@ -179,12 +184,10 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  		if (port.fifosize)
>  			port8250.capabilities = UART_CAP_FIFO;
>  
> -		if (of_property_read_bool(ofdev->dev.of_node,
> -					  "auto-flow-control"))
> +		if (!device_get_property(&pdev->dev, "auto-flow-control", NULL))
>  			port8250.capabilities |= UART_CAP_AFE;
>  
> -		if (of_property_read_bool(ofdev->dev.of_node,
> -					  "has-hw-flow-control"))
> +		if (!device_get_property(&pdev->dev, "has-hw-flow-control", NULL))
>  			port8250.port.flags |= UPF_HARD_FLOW;
>  
>  		ret = serial8250_register_8250_port(&port8250);
> @@ -199,7 +202,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  	default:
>  		/* need to add code for these */
>  	case PORT_UNKNOWN:
> -		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
> +		dev_info(&pdev->dev, "Unknown serial port found, ignored\n");
>  		ret = -ENODEV;
>  		break;
>  	}
> @@ -208,20 +211,19 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
>  
>  	info->type = port_type;
>  	info->line = ret;
> -	platform_set_drvdata(ofdev, info);
> +	platform_set_drvdata(pdev, info);
>  	return 0;
>  out:
>  	kfree(info);
> -	irq_dispose_mapping(port.irq);
>  	return ret;
>  }
>  
>  /*
>   * Release a line
>   */
> -static int of_platform_serial_remove(struct platform_device *ofdev)
> +static int of_platform_serial_remove(struct platform_device *pdev)
>  {
> -	struct of_serial_info *info = platform_get_drvdata(ofdev);
> +	struct of_serial_info *info = platform_get_drvdata(pdev);
>  	switch (info->type) {
>  #ifdef CONFIG_SERIAL_8250
>  	case PORT_8250 ... PORT_MAX_8250:
> 
> 
> -- 
> David Woodhouse                            Open Source Technology Centre
> David.Woodhouse@intel.com                              Intel Corporation
Attachment: smime.p7s (application/x-pkcs7-signature)


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 22:50     ` Rafael J. Wysocki
@ 2014-10-18  8:49       ` Grant Likely
  2014-10-19 23:32         ` Rafael J. Wysocki
  0 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-18  8:49 UTC (permalink / raw)
  To: Rafael J. Wysocki, Arnd Bergmann
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

On Sat, 18 Oct 2014 00:50 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> On Friday, October 17, 2014 08:04:52 PM Arnd Bergmann wrote:
> > 
> > On October 17, 2014 2:01:33 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> > >Hi Everyone,
> > >
> > >Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC,
> > >we
> > >now have version 5 taking all feedback into account (hopefully).
> > 
> > Awesome, that was really fast. I'm currently on my way his me in
> > the train, replying from my phone, but it looks good now. I'll have a more
> > detailed look next week but I'm definitely happy to see this go in (to next
> > and 3.19) now, any details we still find can be fixed on top.
> > 
> > > In
> > >short, if
> > >we are passed a struct fwnode_handle pointer, we can get from it to the
> > >appropriate device node pointer (either struct acpi_device or struct
> > >device_node)
> > >using container_of() after we've checked the type.  This is needed for
> > >the code
> > >that needs to access child nodes of a device in case when they don't
> > >have
> > >struct device representations (whatever the reason).  This has been
> > >suggested
> > >by Grant and pretty much everyone involved agrees that it's better that
> > >the
> > >alternatives presented so far.
> > 
> > Yes, it's nice enough that I now take back all the objections I had for the
> > child accessory API.
> 
> Cool, thanks!
> 
> I've just refreshed the device-properties branch of the linux-pm.git tree
> and it contains the current material now (including a couple of build
> fixes reported by the autobuild robot in patches [02/12] and [09/12]).
> 
> My plan is to merge this into the linux-next branch when 3.18-rc1 is out.

Wait for my ack please, but I should be able to review it this weekend
or on Monday. I'm actually reviewing now, but I'm on a plane near the
end of the flight. As soon as I get on the ground SIGFAMILY will
interrupt me for a bit. :-)

g.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  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-18 14:55     ` Grant Likely
                       ` (2 subsequent siblings)
  3 siblings, 1 reply; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-18  9:35 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Friday 17 October 2014 14:14:53 Rafael J. Wysocki wrote:
> +/**
> + * fwnode_property_present - check if a property of a firmware node is present
> + * @fwnode: Firmware node whose property to check
> + * @propname: Name of the property
> + */
> +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
> +{
> +       if (is_of_node(fwnode))
> +               return of_property_read_bool(of_node(fwnode), propname);
> +       else if (is_acpi_node(fwnode))
> +               return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> +
> +       return false;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_present);
> 

Should this be

		return acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);

without the '!'?

I'm also unsure about the '_present' vs '_read_bool' naming. IIRC we had
a long debate about this before we decided on 'read_bool' for DT, and
I don't really want to start a new debate, but being consistent would
be nice.

We could of course have

static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode, const char *propname)
{
	return fwnode_property_present(fwnode, propname);
}

which is completely redundant, but would help for drivers using the
interface to document whether we are checking for bool property that
we expect to be either empty or absent (_get_bool), vs checking for
the presence of a non-empty property (_present).

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  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  6:12         ` Alexandre Courbot
  0 siblings, 2 replies; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-18  9:47 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Friday 17 October 2014 20:09:51 Arnd Bergmann wrote:
> On October 17, 2014 2:16:00 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> >From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >
> >Some drivers need to deal with only firmware representation of its
> >GPIOs. An example would be a GPIO button array driver where each button
> >is described as a separate firmware node in device tree. Typically
> >these
> >child nodes do not have physical representation in the Linux device
> >model.
> >
> >In order to help device drivers to handle such firmware child nodes we
> >add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> >node pointer as its second argument (the first one is the parent device
> >itself), finds the GPIO using whatever is the underlying firmware
> >method, and requests the GPIO properly.
> 
> Could we also have a wrapper around this function without a "name" argument,
> using just the index?

Expanding on this thought: I think we should mandate for new bindings
that they use either a name and no index, or an index but not name,
and I also think that for named gpios, we should try to converge on a
common naming scheme. As discussed, we will probably want to support all
the existing ways to do this even with ACPI and with the unified
interface, but it doesn't have to be the obvious way.

We could do it like this:

// internal implementation, may be called from drivers with legacy bindings 
struct gpio_desc *__fwnode_get_gpiod_from_property(struct fwnode_handle *fwnode,
                                           const char *propname, int index)
{
	... /* your current code */
}

// recommended interface
static inline struct gpio_desc *fwnode_get_gpiod(struct fwnode_handle *fwnode,
						  int index)
{
	return __fwnode_get_gpiod_from_property(fwnode, "gpios", index);
}

// alternative interface
struct gpio_desc *fwnode_get_gpiod(struct fwnode_handle *fwnode, const char *name)
{
	char propname[64];
	int ret;
	
	ret = snprintf(propname, sizeof(propname), "%s-gpios", name);
	if (ret > sizeof(propname))
		return -EINVAL;

	return __fwnode_get_gpiod_from_property(fwnode, propname, 0);
}

The above is just a suggestion, I'm hoping for the GPIO maintainers to
provide more guidance if they have other ideas.

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  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-18 14:55     ` Grant Likely
  2014-10-19 23:46       ` Rafael J. Wysocki
  2014-10-19 22:14     ` Greg Kroah-Hartman
  2014-10-20  0:15     ` [Update][PATCH " Rafael J. Wysocki
  3 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-18 14:55 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

On Fri, 17 Oct 2014 14:14:53 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Add new generic routines are provided for retrieving properties from
> device description objects in the platform firmware in case there are
> no struct device objects for them (either those objects have not been
> created yet or they do not exist at all).
> 
> The following functions are provided:
> 
> fwnode_property_present()
> fwnode_property_read_u8()
> fwnode_property_read_u16()
> fwnode_property_read_u32()
> fwnode_property_read_u64()
> fwnode_property_read_string()
> fwnode_property_read_u8_array()
> fwnode_property_read_u16_array()
> fwnode_property_read_u32_array()
> fwnode_property_read_u64_array()
> fwnode_property_read_string_array()
> 
> in analogy with the corresponding functions for struct device added
> previously.  For all of them, the first argument is a pointer to struct
> fwnode_handle (new type) that allows a device description object
> (depending on what platform firmware interface is in use) to be
> obtained.
> 
> Add 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 is all *so much* better. I'm a lot happier.

I was about to make the comment that the implementation for
device_property_read_*() should merely be wrappers around
fwnode_property_read_*(), but when when I actually looked at it, I saw
this:

In patch 2:
int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
{
	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
		return of_property_read_u8(dev->of_node, propname, val);

	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
				  DEV_PROP_U8, val);
}

And in this patch:
int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
			    u8 *val)
{
	if (is_of_node(fwnode))
		return of_property_read_u8(of_node(fwnode), propname, val);
	else if (is_acpi_node(fwnode))
		return acpi_dev_prop_read(acpi_node(fwnode), propname,
					  DEV_PROP_U8, val);

	return -ENXIO;
}

Making the device_property functions wrappers around fwnode_property_*
wouldn't actually be great since it would need to decode the fwnode
pointer twice.

I do still think the functions above should be macro generated, just in
terms of keeping the line count down, and I would suggest merging patches #2
and #9.

Something like:

#define define_fwnode_accessors(__type, __devprop_type) \
int device_property_read_##__type(struct device *dev, \
				const char *propname, __type *val) \
{ \
	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
		return of_property_read_##__type(dev->of_node, propname, val); \
	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
				  __devprop_type, val); \
} \
int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
				const char *propname, __type *val) \
{ \
	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
		return of_property_read_##__type(of_node(fwnode), propname, val); \
	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
					  __devprop_type, val); \
	return -ENXIO; \
}

define_fwnode_accessors(u8, DEV_PROP_U8);
define_fwnode_accessors(u16, DEV_PROP_U16);
define_fwnode_accessors(u32, DEV_PROP_U32);
define_fwnode_accessors(u64, DEV_PROP_U64);

That significantly reduces the code size for these things.

Also, can the non-array versions be implemented as a wrapper around the
array versions? That also will reduce the sheer number of lines of code
a lot.

Maybe this:

#define define_fwnode_accessors(__type, __devprop_type) \
int device_property_read_##__type##_array(struct device *dev, \
				const char *propname, __type *val, \
				size_t nval) \
{ \
	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
		return of_property_read_##__type##_array(dev->of_node, \
		propname, val, nval); \
	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, \
				  __devprop_type, val, nval); \
} \
static inline int device_property_read_##__type(struct device *dev, \
				const char *propname, __type *val) \
{ \
	return device_property_read_##__type##_array(dev, propname, val, 1) \
} \
int fwnode_property_read_##__type##_array(struct fwnode_handle *fwnode, \
				const char *propname, __type *val, \
				size_t nval) \
{ \
	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
		return of_property_read_##__type(of_node(fwnode), propname, val, nval); \
	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
					  __devprop_type, val, nval); \
	return -ENXIO; \
} \
static inline int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
				const char *propname, __type *val) \
{ \
	return fwnode_property_read_##__type##_array(fwnode, propname, val, 1) \
}
define_fwnode_accessors(u8, DEV_PROP_U8);
define_fwnode_accessors(u16, DEV_PROP_U16);
define_fwnode_accessors(u32, DEV_PROP_U32);
define_fwnode_accessors(u64, DEV_PROP_U64);

g.

> 
> Suggested-by: Grant Likely <grant.likely@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/scan.c      |   21 ++
>  drivers/base/property.c  |  373 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/acpi/acpi_bus.h  |   12 +
>  include/linux/acpi.h     |   21 ++
>  include/linux/of.h       |   22 ++
>  include/linux/property.h |   48 ++++++
>  6 files changed, 497 insertions(+)
> 
> Index: linux-pm/include/linux/property.h
> ===================================================================
> --- linux-pm.orig/include/linux/property.h
> +++ linux-pm/include/linux/property.h
> @@ -44,4 +44,52 @@ int device_property_read_u64_array(struc
>  int device_property_read_string_array(struct device *dev, const char *propname,
>  				      char **val, size_t nval);
>  
> +enum fwnode_type {
> +	FWNODE_INVALID = 0,
> +	FWNODE_OF,
> +	FWNODE_ACPI,
> +};
> +
> +struct fwnode_handle {
> +	enum fwnode_type type;
> +};
> +
> +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
> +int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
> +			    u8 *val);
> +int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
> +			     u16 *val);
> +int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
> +			     u32 *val);
> +int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
> +			     u64 *val);
> +int fwnode_property_read_string(struct fwnode_handle *fwnode,
> +				const char *propname, const char **val);
> +int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
> +				  const char *propname, u8 *val,
> +				  size_t nval);
> +int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u16 *val,
> +				   size_t nval);
> +int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u32 *val,
> +				   size_t nval);
> +int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u64 *val,
> +				   size_t nval);
> +int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
> +				      const char *propname, char **val,
> +				      size_t nval);
> +
> +struct fwnode_handle *device_get_next_child_node(struct device *dev,
> +						 struct fwnode_handle *child);
> +
> +#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))
> +
> +void fwnode_handle_put(struct fwnode_handle *fwnode);
> +
> +unsigned int device_get_child_node_count(struct device *dev);
> +
>  #endif /* _LINUX_PROPERTY_H_ */
> Index: linux-pm/include/acpi/acpi_bus.h
> ===================================================================
> --- linux-pm.orig/include/acpi/acpi_bus.h
> +++ linux-pm/include/acpi/acpi_bus.h
> @@ -27,6 +27,7 @@
>  #define __ACPI_BUS_H__
>  
>  #include <linux/device.h>
> +#include <linux/property.h>
>  
>  /* TBD: Make dynamic */
>  #define ACPI_MAX_HANDLES	10
> @@ -348,6 +349,7 @@ struct acpi_device_data {
>  struct acpi_device {
>  	int device_type;
>  	acpi_handle handle;		/* no handle for fixed hardware */
> +	struct fwnode_handle fwnode;
>  	struct acpi_device *parent;
>  	struct list_head children;
>  	struct list_head node;
> @@ -372,6 +374,16 @@ struct acpi_device {
>  	void (*remove)(struct acpi_device *);
>  };
>  
> +static inline bool is_acpi_node(struct fwnode_handle *fwnode)
> +{
> +	return fwnode && fwnode->type == FWNODE_ACPI;
> +}
> +
> +static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
> +{
> +	return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
> +}
> +
>  static inline void *acpi_driver_data(struct acpi_device *d)
>  {
>  	return d->driver_data;
> Index: linux-pm/include/linux/acpi.h
> ===================================================================
> --- linux-pm.orig/include/linux/acpi.h
> +++ linux-pm/include/linux/acpi.h
> @@ -439,6 +439,18 @@ int acpi_device_modalias(struct device *
>  #define ACPI_COMPANION_SET(dev, adev)	do { } while (0)
>  #define ACPI_HANDLE(dev)		(NULL)
>  
> +struct fwnode_handle;
> +
> +static inline bool is_acpi_node(struct fwnode_handle *fwnode)
> +{
> +	return false;
> +}
> +
> +static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
> +{
> +	return NULL;
> +}
> +
>  static inline const char *acpi_dev_name(struct acpi_device *adev)
>  {
>  	return NULL;
> @@ -681,6 +693,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,
> @@ -724,6 +739,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/include/linux/of.h
> ===================================================================
> --- linux-pm.orig/include/linux/of.h
> +++ linux-pm/include/linux/of.h
> @@ -50,6 +50,7 @@ struct device_node {
>  	const char *type;
>  	phandle phandle;
>  	const char *full_name;
> +	struct fwnode_handle fwnode;
>  
>  	struct	property *properties;
>  	struct	property *deadprops;	/* removed properties */
> @@ -80,6 +81,7 @@ extern struct kobj_type of_node_ktype;
>  static inline void of_node_init(struct device_node *node)
>  {
>  	kobject_init(&node->kobj, &of_node_ktype);
> +	node->fwnode.type = FWNODE_OF;
>  }
>  
>  /* true when node is initialized */
> @@ -115,6 +117,16 @@ extern struct device_node *of_aliases;
>  extern struct device_node *of_stdout;
>  extern raw_spinlock_t devtree_lock;
>  
> +static inline bool is_of_node(struct fwnode_handle *fwnode)
> +{
> +	return fwnode && fwnode->type == FWNODE_OF;
> +}
> +
> +static inline struct device_node *of_node(struct fwnode_handle *fwnode)
> +{
> +	return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
> +}
> +
>  static inline bool of_have_populated_dt(void)
>  {
>  	return of_allnodes != NULL;
> @@ -365,6 +377,16 @@ bool of_console_check(struct device_node
>  
>  #else /* CONFIG_OF */
>  
> +static inline bool is_of_node(struct fwnode_handle *fwnode)
> +{
> +	return false;
> +}
> +
> +static inline struct device_node *of_node(struct fwnode_handle *fwnode)
> +{
> +	return NULL;
> +}
> +
>  static inline const char* of_node_full_name(const struct device_node *np)
>  {
>  	return "<no-node>";
> Index: linux-pm/drivers/base/property.c
> ===================================================================
> --- linux-pm.orig/drivers/base/property.c
> +++ linux-pm/drivers/base/property.c
> @@ -156,6 +156,166 @@ int device_property_read_string(struct d
>  }
>  EXPORT_SYMBOL_GPL(device_property_read_string);
>  
> +/**
> + * fwnode_property_present - check if a property of a firmware node is present
> + * @fwnode: Firmware node whose property to check
> + * @propname: Name of the property
> + */
> +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_bool(of_node(fwnode), propname);
> +	else if (is_acpi_node(fwnode))
> +		return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> +
> +	return false;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_present);
> +
> +/**
> + * fwnode_property_read_u8 - return a u8 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value into
> + * @val if found.  The value is checked to be of type u8.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO or %-EILSEQ if the property type is not u8,
> + *	   %-EOVERFLOW if the property value is out of bounds of u8,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
> +			    u8 *val)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_u8(of_node(fwnode), propname, val);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +					  DEV_PROP_U8, val);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u8);
> +
> +/**
> + * fwnode_property_read_u16 - return a u16 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value into
> + * @val if found.  The value is checked to be of type u16.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO or %-EILSEQ if the property type is not u16,
> + *	   %-EOVERFLOW if the property value is out of bounds of u16,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
> +			     u16 *val)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_u16(of_node(fwnode), propname, val);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +					  DEV_PROP_U16, val);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u16);
> +
> +/**
> + * fwnode_property_read_u32 - return a u32 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value into
> + * @val if found.  The value is checked to be of type u32.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO or %-EILSEQ if the property type is not u32,
> + *	   %-EOVERFLOW if the property value is out of bounds of u32,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
> +			     u32 *val)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_u32(of_node(fwnode), propname, val);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +					  DEV_PROP_U32, val);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u32);
> +
> +/**
> + * fwnode_property_read_u64 - return a u64 property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value into
> + * @val if found.  The value is checked to be of type u64.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO or %-EILSEQ if the property type is not u64,
> + *	   %-EOVERFLOW if the property value is out of bounds of u64,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
> +			     u64 *val)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_u64(of_node(fwnode), propname, val);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +					  DEV_PROP_U64, val);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u64);
> +
> +/**
> + * fwnode_property_read_string - return a string property of a firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The value is stored here
> + *
> + * Read property @propname from the given firmware node and store the value into
> + * @val if found.  The value is checked to be a string.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO or %-EILSEQ if the property is not a string,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_string(struct fwnode_handle *fwnode,
> +				const char *propname, const char **val)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_string(of_node(fwnode), propname, val);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> +					  DEV_PROP_STRING, val);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_string);
> +
>  #define of_dev_prop_read_array(node, propname, type, val, nval) \
>  	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
>  	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
> @@ -299,3 +459,216 @@ int device_property_read_string_array(st
>  					DEV_PROP_STRING, val, nval);
>  }
>  EXPORT_SYMBOL_GPL(device_property_read_string_array);
> +
> +/**
> + * fwnode_property_read_u8_array - return a u8 array property of firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u8 properties with @propname from @fwnode and stores them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO if the property is not an array of numbers,
> + *	   %-EOVERFLOW if the size of the property is not as expected,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
> +				  const char *propname, u8 *val, size_t nval)
> +{
> +	if (is_of_node(fwnode))
> +		return of_dev_prop_read_array(of_node(fwnode), propname,
> +					      u8, val, nval);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +						DEV_PROP_U8, val, nval);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
> +
> +/**
> + * fwnode_property_read_u16_array - return a u16 array property of firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u16 properties with @propname from @fwnode and store them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO if the property is not an array of numbers,
> + *	   %-EOVERFLOW if the size of the property is not as expected,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u16 *val, size_t nval)
> +{
> +	if (is_of_node(fwnode))
> +		return of_dev_prop_read_array(of_node(fwnode), propname,
> +					      u16, val, nval);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +						DEV_PROP_U16, val, nval);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
> +
> +/**
> + * fwnode_property_read_u32_array - return a u32 array property of firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u32 properties with @propname from @fwnode store them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO if the property is not an array of numbers,
> + *	   %-EOVERFLOW if the size of the property is not as expected,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u32 *val, size_t nval)
> +{
> +	if (is_of_node(fwnode))
> +		return of_dev_prop_read_array(of_node(fwnode), propname,
> +					      u32, val, nval);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +						DEV_PROP_U32, val, nval);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
> +
> +/**
> + * fwnode_property_read_u64_array - return a u64 array property firmware node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an array of u64 properties with @propname from @fwnode and store them to
> + * @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO if the property is not an array of numbers,
> + *	   %-EOVERFLOW if the size of the property is not as expected,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
> +				   const char *propname, u64 *val, size_t nval)
> +{
> +	if (is_of_node(fwnode))
> +		return of_dev_prop_read_array(of_node(fwnode), propname,
> +					      u64, val, nval);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +						DEV_PROP_U64, val, nval);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
> +
> +/**
> + * fwnode_property_read_string_array - return string array property of a node
> + * @fwnode: Firmware node to get the property of
> + * @propname: Name of the property
> + * @val: The values are stored here
> + * @nval: Size of the @val array
> + *
> + * Read an string list property @propname from the given firmware node and store
> + * them to @val if found.
> + *
> + * Return: %0 if the property was found (success),
> + *	   %-EINVAL if given arguments are not valid,
> + *	   %-ENODATA if the property does not have a value,
> + *	   %-EPROTO if the property is not an array of strings,
> + *	   %-EOVERFLOW if the size of the property is not as expected,
> + *	   %-ENXIO if no suitable firmware interface is present.
> + */
> +int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
> +				      const char *propname, char **val,
> +				      size_t nval)
> +{
> +	if (is_of_node(fwnode))
> +		return of_property_read_string_array(of_node(fwnode), propname,
> +						     val, nval);
> +	else if (is_acpi_node(fwnode))
> +		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
> +						DEV_PROP_STRING, val, nval);
> +
> +	return -ENXIO;
> +}
> +EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
> +
> +
> +/**
> + * device_get_next_child_node - Return the next child node handle for a device
> + * @dev: Device to find the next child node for.
> + * @child: Handle to one of the device's child nodes or a null handle.
> + */
> +struct fwnode_handle *device_get_next_child_node(struct device *dev,
> +						 struct fwnode_handle *child)
> +{
> +	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
> +		struct device_node *node;
> +
> +		node = of_get_next_available_child(dev->of_node, of_node(child));
> +		if (node)
> +			return &node->fwnode;
> +	} else if (ACPI_COMPANION(dev)) {
> +		struct acpi_device *node;
> +
> +		node = acpi_get_next_child(dev, acpi_node(child));
> +		if (node)
> +			return &node->fwnode;
> +	}
> +	return NULL;
> +}
> +EXPORT_SYMBOL_GPL(device_get_next_child_node);
> +
> +/**
> + * fwnode_handle_put - Drop reference to a device node
> + * @fwnode: Pointer to the device node 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 fwnode_handle_put(struct fwnode_handle *fwnode)
> +{
> +	if (is_of_node(fwnode))
> +		of_node_put(of_node(fwnode));
> +}
> +EXPORT_SYMBOL_GPL(fwnode_handle_put);
> +
> +/**
> + * 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)
> +{
> +	struct fwnode_handle *child;
> +	unsigned int count = 0;
> +
> +	device_for_each_child_node(dev, child)
> +		count++;
> +
> +	return count;
> +}
> +EXPORT_SYMBOL_GPL(device_get_child_node_count);
> 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
>     -------------------------------------------------------------------------- */
> @@ -1961,6 +1981,7 @@ void acpi_init_device_object(struct acpi
>  	device->device_type = type;
>  	device->handle = handle;
>  	device->parent = acpi_bus_get_parent(handle);
> +	device->fwnode.type = FWNODE_ACPI;
>  	acpi_set_device_status(device, sta);
>  	acpi_device_get_busid(device);
>  	acpi_set_pnp_ids(handle, &device->pnp, type);
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-17 21:49     ` Rafael J. Wysocki
@ 2014-10-19 22:14       ` Greg Kroah-Hartman
  0 siblings, 0 replies; 104+ messages in thread
From: Greg Kroah-Hartman @ 2014-10-19 22:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Fri, Oct 17, 2014 at 11:49:45PM +0200, Rafael J. Wysocki wrote:
> On Friday, October 17, 2014 05:40:07 PM Greg Kroah-Hartman wrote:
> > On Fri, Oct 17, 2014 at 02:01:33PM +0200, Rafael J. Wysocki wrote:
> > > Hi Everyone,
> > > 
> > > Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC, we
> > > now have version 5 taking all feedback into account (hopefully).
> > > 
> > > Changes have been made to patch [02/12] and to patches [09-12/12], although
> > > in patches [10-12/12] they are fairly minor.  I have retained the Greg's
> > > ACK on patch [02/12], because it is essentially the same that have been
> > > posted aleady and ACKed by him (Greg, please let me know if I shouldn't
> > > do that) and all the ACKs on the remaining patches except for patch [09/12]
> > > which is substantially different.  Still, if reviewers think that their
> > > ACKs don't apply any more, please let me know and I'll remove them.
> > 
> > No objection from me to keep my ACK on those patches, thanks for asking.
> 
> Well, that's just fair IMO. :-)
> 
> Does [09/12] look good too in particular?

Yes, I have no objections to it.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  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-18 14:55     ` Grant Likely
@ 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
  3 siblings, 1 reply; 104+ messages in thread
From: Greg Kroah-Hartman @ 2014-10-19 22:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Fri, Oct 17, 2014 at 02:14:53PM +0200, Rafael J. Wysocki wrote:
> From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Add new generic routines are provided for retrieving properties from
> device description objects in the platform firmware in case there are
> no struct device objects for them (either those objects have not been
> created yet or they do not exist at all).
> 
> The following functions are provided:
> 
> fwnode_property_present()
> fwnode_property_read_u8()
> fwnode_property_read_u16()
> fwnode_property_read_u32()
> fwnode_property_read_u64()
> fwnode_property_read_string()
> fwnode_property_read_u8_array()
> fwnode_property_read_u16_array()
> fwnode_property_read_u32_array()
> fwnode_property_read_u64_array()
> fwnode_property_read_string_array()
> 
> in analogy with the corresponding functions for struct device added
> previously.  For all of them, the first argument is a pointer to struct
> fwnode_handle (new type) that allows a device description object
> (depending on what platform firmware interface is in use) to be
> obtained.
> 
> Add 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.
> 
> Suggested-by: Grant Likely <grant.likely@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-18  9:35     ` Arnd Bergmann
@ 2014-10-19 23:30       ` Rafael J. Wysocki
  2014-10-20 14:14         ` Arnd Bergmann
  0 siblings, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-19 23:30 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Saturday, October 18, 2014 11:35:21 AM Arnd Bergmann wrote:
> On Friday 17 October 2014 14:14:53 Rafael J. Wysocki wrote:
> > +/**
> > + * fwnode_property_present - check if a property of a firmware node is present
> > + * @fwnode: Firmware node whose property to check
> > + * @propname: Name of the property
> > + */
> > +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
> > +{
> > +       if (is_of_node(fwnode))
> > +               return of_property_read_bool(of_node(fwnode), propname);
> > +       else if (is_acpi_node(fwnode))
> > +               return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> > +
> > +       return false;
> > +}
> > +EXPORT_SYMBOL_GPL(fwnode_property_present);
> > 
> 
> Should this be
> 
> 		return acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> 
> without the '!'?

No, acpi_dev_prop_get() returns 0 on success. :-)

> I'm also unsure about the '_present' vs '_read_bool' naming. IIRC we had
> a long debate about this before we decided on 'read_bool' for DT, and
> I don't really want to start a new debate, but being consistent would
> be nice.
> 
> We could of course have
> 
> static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode, const char *propname)
> {
> 	return fwnode_property_present(fwnode, propname);
> }
> 
> which is completely redundant, but would help for drivers using the
> interface to document whether we are checking for bool property that
> we expect to be either empty or absent (_get_bool), vs checking for
> the presence of a non-empty property (_present).

I'm fine with that, so I'll add fwnode_property_read_bool() (and an analogous
wrapper for device_) to patches [02/12] and [09/12].

I'll be sending updates of them shortly, so please have a look at those.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-19 22:14     ` Greg Kroah-Hartman
@ 2014-10-19 23:31       ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-19 23:31 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Grant Likely, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday, October 20, 2014 06:14:34 AM Greg Kroah-Hartman wrote:
> On Fri, Oct 17, 2014 at 02:14:53PM +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Add new generic routines are provided for retrieving properties from
> > device description objects in the platform firmware in case there are
> > no struct device objects for them (either those objects have not been
> > created yet or they do not exist at all).
> > 
> > The following functions are provided:
> > 
> > fwnode_property_present()
> > fwnode_property_read_u8()
> > fwnode_property_read_u16()
> > fwnode_property_read_u32()
> > fwnode_property_read_u64()
> > fwnode_property_read_string()
> > fwnode_property_read_u8_array()
> > fwnode_property_read_u16_array()
> > fwnode_property_read_u32_array()
> > fwnode_property_read_u64_array()
> > fwnode_property_read_string_array()
> > 
> > in analogy with the corresponding functions for struct device added
> > previously.  For all of them, the first argument is a pointer to struct
> > fwnode_handle (new type) that allows a device description object
> > (depending on what platform firmware interface is in use) to be
> > obtained.
> > 
> > Add 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.
> > 
> > Suggested-by: Grant Likely <grant.likely@linaro.org>
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> 
> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

Thanks!


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 00/12] Add ACPI _DSD and unified device properties support
  2014-10-18  8:49       ` Grant Likely
@ 2014-10-19 23:32         ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-19 23:32 UTC (permalink / raw)
  To: Grant Likely
  Cc: Arnd Bergmann, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Saturday, October 18, 2014 10:49:59 AM Grant Likely wrote:
> On Sat, 18 Oct 2014 00:50 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > On Friday, October 17, 2014 08:04:52 PM Arnd Bergmann wrote:
> > > 
> > > On October 17, 2014 2:01:33 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> > > >Hi Everyone,
> > > >
> > > >Hving had a couple of chats with Grant and Arnd during LinuxCon EU/LPC,
> > > >we
> > > >now have version 5 taking all feedback into account (hopefully).
> > > 
> > > Awesome, that was really fast. I'm currently on my way his me in
> > > the train, replying from my phone, but it looks good now. I'll have a more
> > > detailed look next week but I'm definitely happy to see this go in (to next
> > > and 3.19) now, any details we still find can be fixed on top.
> > > 
> > > > In
> > > >short, if
> > > >we are passed a struct fwnode_handle pointer, we can get from it to the
> > > >appropriate device node pointer (either struct acpi_device or struct
> > > >device_node)
> > > >using container_of() after we've checked the type.  This is needed for
> > > >the code
> > > >that needs to access child nodes of a device in case when they don't
> > > >have
> > > >struct device representations (whatever the reason).  This has been
> > > >suggested
> > > >by Grant and pretty much everyone involved agrees that it's better that
> > > >the
> > > >alternatives presented so far.
> > > 
> > > Yes, it's nice enough that I now take back all the objections I had for the
> > > child accessory API.
> > 
> > Cool, thanks!
> > 
> > I've just refreshed the device-properties branch of the linux-pm.git tree
> > and it contains the current material now (including a couple of build
> > fixes reported by the autobuild robot in patches [02/12] and [09/12]).
> > 
> > My plan is to merge this into the linux-next branch when 3.18-rc1 is out.
> 
> Wait for my ack please, but I should be able to review it this weekend
> or on Monday. I'm actually reviewing now, but I'm on a plane near the
> end of the flight. As soon as I get on the ground SIGFAMILY will
> interrupt me for a bit. :-)

Sure, I won't be trying to push things that you don't like :-)

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  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 14:19         ` Arnd Bergmann
  0 siblings, 2 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-19 23:46 UTC (permalink / raw)
  To: Grant Likely
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Saturday, October 18, 2014 04:55:20 PM Grant Likely wrote:
> On Fri, 17 Oct 2014 14:14:53 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > 
> > Add new generic routines are provided for retrieving properties from
> > device description objects in the platform firmware in case there are
> > no struct device objects for them (either those objects have not been
> > created yet or they do not exist at all).
> > 
> > The following functions are provided:
> > 
> > fwnode_property_present()
> > fwnode_property_read_u8()
> > fwnode_property_read_u16()
> > fwnode_property_read_u32()
> > fwnode_property_read_u64()
> > fwnode_property_read_string()
> > fwnode_property_read_u8_array()
> > fwnode_property_read_u16_array()
> > fwnode_property_read_u32_array()
> > fwnode_property_read_u64_array()
> > fwnode_property_read_string_array()
> > 
> > in analogy with the corresponding functions for struct device added
> > previously.  For all of them, the first argument is a pointer to struct
> > fwnode_handle (new type) that allows a device description object
> > (depending on what platform firmware interface is in use) to be
> > obtained.
> > 
> > Add 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 is all *so much* better. I'm a lot happier.
> 
> I was about to make the comment that the implementation for
> device_property_read_*() should merely be wrappers around
> fwnode_property_read_*(), but when when I actually looked at it, I saw
> this:
> 
> In patch 2:
> int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
> {
> 	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> 		return of_property_read_u8(dev->of_node, propname, val);
> 
> 	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
> 				  DEV_PROP_U8, val);
> }
> 
> And in this patch:
> int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
> 			    u8 *val)
> {
> 	if (is_of_node(fwnode))
> 		return of_property_read_u8(of_node(fwnode), propname, val);
> 	else if (is_acpi_node(fwnode))
> 		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> 					  DEV_PROP_U8, val);
> 
> 	return -ENXIO;
> }
> 
> Making the device_property functions wrappers around fwnode_property_*
> wouldn't actually be great since it would need to decode the fwnode
> pointer twice.

Indeed.

> I do still think the functions above should be macro generated, just in
> terms of keeping the line count down, and I would suggest merging patches #2
> and #9.

Well, the changes in those patches are almost completely independent and patch
#9 is only actually needed for #11 and #12, so I'm not sure if that would be
better.  I certainly prefer splitting longer patches into pieces if that makes
sense and it does make sense to do so in this particular case IMHO.

> Something like:
> 
> #define define_fwnode_accessors(__type, __devprop_type) \
> int device_property_read_##__type(struct device *dev, \
> 				const char *propname, __type *val) \
> { \
> 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> 		return of_property_read_##__type(dev->of_node, propname, val); \
> 	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
> 				  __devprop_type, val); \
> } \
> int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> 				const char *propname, __type *val) \
> { \
> 	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> 		return of_property_read_##__type(of_node(fwnode), propname, val); \
> 	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> 		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> 					  __devprop_type, val); \
> 	return -ENXIO; \
> }
> 
> define_fwnode_accessors(u8, DEV_PROP_U8);
> define_fwnode_accessors(u16, DEV_PROP_U16);
> define_fwnode_accessors(u32, DEV_PROP_U32);
> define_fwnode_accessors(u64, DEV_PROP_U64);
> 
> That significantly reduces the code size for these things.

So I was considering to do that, but eventually decided not to, because (1)
adding kerneldoc comments to such things looks odd and (2) (which IMO is
more important) this breaks LXR (for example, the thing at lxr.free-electrons.com
that some people, including me in particular, occasionally use to check how things
are defined).  And even if you used the old good grep to look for a definition of
fwnode_property_read_u8, say, this wouldn't work exactly as expected I'm afraid. ;-)

I would very much like to retain the headers at least for this reason, if that's
not a big deal.

What I can do, however, is to use macros for generating the bodies of those
functions.

I'm going to send updates of patches #2 and #9 with that modification shortly,
please have a look at them.

> Also, can the non-array versions be implemented as a wrapper around the
> array versions? That also will reduce the sheer number of lines of code
> a lot.
> 
> Maybe this:
> 
> #define define_fwnode_accessors(__type, __devprop_type) \
> int device_property_read_##__type##_array(struct device *dev, \
> 				const char *propname, __type *val, \
> 				size_t nval) \
> { \
> 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> 		return of_property_read_##__type##_array(dev->of_node, \
> 		propname, val, nval); \
> 	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, \
> 				  __devprop_type, val, nval); \
> } \
> static inline int device_property_read_##__type(struct device *dev, \
> 				const char *propname, __type *val) \
> { \
> 	return device_property_read_##__type##_array(dev, propname, val, 1) \
> } \
> int fwnode_property_read_##__type##_array(struct fwnode_handle *fwnode, \
> 				const char *propname, __type *val, \
> 				size_t nval) \
> { \
> 	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> 		return of_property_read_##__type(of_node(fwnode), propname, val, nval); \
> 	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> 		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> 					  __devprop_type, val, nval); \
> 	return -ENXIO; \
> } \
> static inline int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> 				const char *propname, __type *val) \
> { \
> 	return fwnode_property_read_##__type##_array(fwnode, propname, val, 1) \
> }
> define_fwnode_accessors(u8, DEV_PROP_U8);
> define_fwnode_accessors(u16, DEV_PROP_U16);
> define_fwnode_accessors(u32, DEV_PROP_U32);
> define_fwnode_accessors(u64, DEV_PROP_U64);

No, that wouldn't work for ACPI (if I understand your idea correctly), because
acpi_dev_prop_read(adev, propname, DEV_PROP_U8, val) will look for a single-value
int property, whereas acpi_dev_prop_read_array(adev, propname, DEV_PROP_U8, val, 1)
will look for a list (package) property and will attempt to retrieve the first
element of that.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  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
  1 sibling, 1 reply; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-19 23:58 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Saturday, October 18, 2014 11:47:41 AM Arnd Bergmann wrote:
> On Friday 17 October 2014 20:09:51 Arnd Bergmann wrote:
> > On October 17, 2014 2:16:00 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> > >From: Mika Westerberg <mika.westerberg@linux.intel.com>
> > >
> > >Some drivers need to deal with only firmware representation of its
> > >GPIOs. An example would be a GPIO button array driver where each button
> > >is described as a separate firmware node in device tree. Typically
> > >these
> > >child nodes do not have physical representation in the Linux device
> > >model.
> > >
> > >In order to help device drivers to handle such firmware child nodes we
> > >add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> > >node pointer as its second argument (the first one is the parent device
> > >itself), finds the GPIO using whatever is the underlying firmware
> > >method, and requests the GPIO properly.
> > 
> > Could we also have a wrapper around this function without a "name" argument,
> > using just the index?
> 
> Expanding on this thought: I think we should mandate for new bindings
> that they use either a name and no index, or an index but not name,
> and I also think that for named gpios, we should try to converge on a
> common naming scheme. As discussed, we will probably want to support all
> the existing ways to do this even with ACPI and with the unified
> interface, but it doesn't have to be the obvious way.
> 
> We could do it like this:
> 
> // internal implementation, may be called from drivers with legacy bindings 
> struct gpio_desc *__fwnode_get_gpiod_from_property(struct fwnode_handle *fwnode,
>                                            const char *propname, int index)
> {
> 	... /* your current code */
> }
> 
> // recommended interface
> static inline struct gpio_desc *fwnode_get_gpiod(struct fwnode_handle *fwnode,
> 						  int index)
> {
> 	return __fwnode_get_gpiod_from_property(fwnode, "gpios", index);
> }
> 
> // alternative interface
> struct gpio_desc *fwnode_get_gpiod(struct fwnode_handle *fwnode, const char *name)
> {
> 	char propname[64];
> 	int ret;
> 	
> 	ret = snprintf(propname, sizeof(propname), "%s-gpios", name);
> 	if (ret > sizeof(propname))
> 		return -EINVAL;
> 
> 	return __fwnode_get_gpiod_from_property(fwnode, propname, 0);
> }
> 
> The above is just a suggestion, I'm hoping for the GPIO maintainers to
> provide more guidance if they have other ideas.

Actually, since the two last patches in the series, which currently are
the only users of these new functions, both pass "gpios" as the property
name and 0 as the index, I can simplify the functions so that (a)
fwnode_get_gpiod() takes fwnode and name and then simply passes 0 as the
index to either of_get_named_gpiod_flags() or acpi_get_gpiod_by_index()
and (b) devm_get_named_gpiod_from_child() takes only dev and fwnode (child)
and passes "gpios" as the property name to fwnode_get_gpiod().  The name
of devm_get_named_gpiod_from_child() could then be changed to something
like devm_get_gpiod_from_child() even.

If anyone in the future needs anything more general, they can simply
add more complexity to that code, but for now we can go for a simplified
interface just fine.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [Update][PATCH v5 02/12] Driver core: Unified device properties interface for platform firmware
  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     ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-20  0:07 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Grant Likely, Greg Kroah-Hartman, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

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

Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type.  The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.

The following general helper functions are added:

device_property_present()
device_property_read_u8()
device_property_read_u16()
device_property_read_u32()
device_property_read_u64()
device_property_read_string()
device_property_read_u8_array()
device_property_read_u16_array()
device_property_read_u32_array()
device_property_read_u64_array()
device_property_read_string_array()

The first one allows the caller to check if the given property is
present.  The next 5 of them allow single-valued properties of
various types to be retrieved in a uniform way.  The remaining 5 are
for reading properties with multiple values (arrays of either numbers
or strings).

The interface covers both ACPI and Device Trees.

This change set includes material from Mika Westerberg and Aaron Lu.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
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>
---

This adds device_property_read_bool() as a wrapper around device_property_present()
and uses macros to generate the bodies of device_property_read_*(), except for
device_property_read_string_array() that doesn't match the overall scheme exactly.

I believe that the Greg's ACK still applies. :-)

Rafael

---
 drivers/acpi/property.c  |  169 ++++++++++++++++++++++++++++
 drivers/base/Makefile    |    2 
 drivers/base/property.c  |  276 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/base.c        |  106 +++++++++++++++---
 include/linux/acpi.h     |   32 +++++
 include/linux/of.h       |   22 +++
 include/linux/property.h |   53 +++++++++
 7 files changed, 643 insertions(+), 17 deletions(-)
 create mode 100644 drivers/base/property.c
 create mode 100644 include/linux/property.h

Index: linux-pm/include/linux/property.h
===================================================================
--- /dev/null
+++ linux-pm/include/linux/property.h
@@ -0,0 +1,53 @@
+/*
+ * property.h - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _LINUX_PROPERTY_H_
+#define _LINUX_PROPERTY_H_
+
+#include <linux/types.h>
+
+struct device;
+
+enum dev_prop_type {
+	DEV_PROP_U8,
+	DEV_PROP_U16,
+	DEV_PROP_U32,
+	DEV_PROP_U64,
+	DEV_PROP_STRING,
+	DEV_PROP_MAX,
+};
+
+bool device_property_present(struct device *dev, const char *propname);
+int device_property_read_u8(struct device *dev, const char *propname, u8 *val);
+int device_property_read_u16(struct device *dev, const char *propname, u16 *val);
+int device_property_read_u32(struct device *dev, const char *propname, u32 *val);
+int device_property_read_u64(struct device *dev, const char *propname, u64 *val);
+int device_property_read_string(struct device *dev, const char *propname,
+				const char **val);
+int device_property_read_u8_array(struct device *dev, const char *propname,
+				  u8 *val, size_t nval);
+int device_property_read_u16_array(struct device *dev, const char *propname,
+				   u16 *val, size_t nval);
+int device_property_read_u32_array(struct device *dev, const char *propname,
+				   u32 *val, size_t nval);
+int device_property_read_u64_array(struct device *dev, const char *propname,
+				   u64 *val, size_t nval);
+int device_property_read_string_array(struct device *dev, const char *propname,
+				      char **val, size_t nval);
+
+static inline bool device_property_read_bool(struct device *dev,
+					     const char *propname)
+{
+	return device_property_present(dev, propname);
+}
+
+#endif /* _LINUX_PROPERTY_H_ */
Index: linux-pm/include/linux/of.h
===================================================================
--- linux-pm.orig/include/linux/of.h
+++ linux-pm/include/linux/of.h
@@ -23,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/topology.h>
 #include <linux/notifier.h>
+#include <linux/property.h>
 
 #include <asm/byteorder.h>
 #include <asm/errno.h>
@@ -263,6 +264,10 @@ extern int of_property_read_u32_array(co
 				      size_t sz);
 extern int of_property_read_u64(const struct device_node *np,
 				const char *propname, u64 *out_value);
+extern int of_property_read_u64_array(const struct device_node *np,
+				      const char *propname,
+				      u64 *out_values,
+				      size_t sz);
 
 extern int of_property_read_string(struct device_node *np,
 				   const char *propname,
@@ -275,6 +280,9 @@ extern int of_property_match_string(stru
 				    const char *string);
 extern int of_property_count_strings(struct device_node *np,
 				     const char *propname);
+extern int of_property_read_string_array(struct device_node *np,
+					      const char *propname,
+					      char **out_strs, size_t sz);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
 extern int of_device_is_available(const struct device_node *device);
@@ -479,6 +487,13 @@ static inline int of_property_read_u32_a
 	return -ENOSYS;
 }
 
+static inline int of_property_read_u64_array(const struct device_node *np,
+					     const char *propname,
+					     u64 *out_values, size_t sz)
+{
+	return -ENOSYS;
+}
+
 static inline int of_property_read_string(struct device_node *np,
 					  const char *propname,
 					  const char **out_string)
@@ -498,6 +513,13 @@ static inline int of_property_count_stri
 {
 	return -ENOSYS;
 }
+
+static inline int of_property_read_string_array(struct device_node *np,
+						 const char *propname,
+						 char **out_strs, size_t sz)
+{
+	return -ENOSYS;
+}
 
 static inline const void *of_get_property(const struct device_node *node,
 				const char *name,
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -28,6 +28,7 @@
 #include <linux/errno.h>
 #include <linux/ioport.h>	/* for struct resource */
 #include <linux/device.h>
+#include <linux/property.h>
 
 #ifndef _LINUX
 #define _LINUX
@@ -676,6 +677,14 @@ int acpi_dev_get_property_array(struct a
 int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
 				    const char *cells_name, size_t index,
 				    struct acpi_reference_args *args);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr);
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val);
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval);
 #else
 static inline int acpi_dev_get_property(struct acpi_device *adev,
 					const char *name, acpi_object_type type,
@@ -696,6 +705,29 @@ static inline int acpi_dev_get_property_
 {
 	return -ENXIO;
 }
+
+static inline int acpi_dev_prop_get(struct acpi_device *adev,
+				    const char *propname,
+				    void **valptr)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read(struct acpi_device *adev,
+				     const char *propname,
+				     enum dev_prop_type proptype, void *val)
+{
+	return -ENXIO;
+}
+
+static inline int acpi_dev_prop_read_array(struct acpi_device *adev,
+					   const char *propname,
+					   enum dev_prop_type proptype,
+					   void *val, size_t nval)
+{
+	return -ENXIO;
+}
+
 #endif
 
 #endif	/*_LINUX_ACPI_H*/
Index: linux-pm/drivers/base/Makefile
===================================================================
--- linux-pm.orig/drivers/base/Makefile
+++ linux-pm/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o \
-			   topology.o container.o
+			   topology.o container.o property.o
 obj-$(CONFIG_DEVTMPFS)	+= devtmpfs.o
 obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
 obj-y			+= power/
Index: linux-pm/drivers/base/property.c
===================================================================
--- /dev/null
+++ linux-pm/drivers/base/property.c
@@ -0,0 +1,276 @@
+/*
+ * property.c - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *          Mika Westerberg <mika.westerberg@linux.intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/property.h>
+#include <linux/export.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+/**
+ * device_property_present - check if a property of a device is present
+ * @dev: Device whose property is being checked
+ * @propname: Name of the property
+ *
+ * Check if property @propname is present in the device firmware description.
+ */
+bool device_property_present(struct device *dev, const char *propname)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		return of_property_read_bool(dev->of_node, propname);
+
+	return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL);
+}
+EXPORT_SYMBOL_GPL(device_property_present);
+
+#define DEVICE_PROPERTY_READ(_dev_, _propname_, _type_, _proptype_, _val_) \
+	IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \
+		of_property_read_##_type_(_dev_->of_node, _propname_, _val_) : \
+		acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \
+				   _proptype_, _val_)
+
+/**
+ * device_property_read_u8 - return a u8 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u8.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u8,
+ *	   %-EOVERFLOW if the property value is out of bounds of u8.
+ */
+int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
+{
+	return DEVICE_PROPERTY_READ(dev, propname, u8, DEV_PROP_U8, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u8);
+
+/**
+ * device_property_read_u16 - return a u16 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u16.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u16,
+ *	   %-EOVERFLOW if the property value is out of bounds of u16.
+ */
+int device_property_read_u16(struct device *dev, const char *propname, u16 *val)
+{
+	return DEVICE_PROPERTY_READ(dev, propname, u16, DEV_PROP_U16, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u16);
+
+/**
+ * device_property_read_u32 - return a u32 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u32.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u32,
+ *	   %-EOVERFLOW if the property value is out of bounds of u32.
+ */
+int device_property_read_u32(struct device *dev, const char *propname, u32 *val)
+{
+	return DEVICE_PROPERTY_READ(dev, propname, u32, DEV_PROP_U32, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u32);
+
+/**
+ * device_property_read_u64 - return a u64 property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be of type u64.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u64,
+ *	   %-EOVERFLOW if the property value is out of bounds of u64.
+ */
+int device_property_read_u64(struct device *dev, const char *propname, u64 *val)
+{
+	return DEVICE_PROPERTY_READ(dev, propname, u64, DEV_PROP_U64, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u64);
+
+/**
+ * device_property_read_string - return a string property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Function reads property @propname from the device firmware description and
+ * stores the value into @val if found. The value is checked to be a string.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not a string.
+ */
+int device_property_read_string(struct device *dev, const char *propname,
+				const char **val)
+{
+	return DEVICE_PROPERTY_READ(dev, propname, string, DEV_PROP_STRING, val);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string);
+
+#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
+	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
+	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
+
+#define DEVICE_PROPERTY_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \
+	IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \
+		(OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \
+					_val_, _nval_)) : \
+		acpi_dev_prop_read_array(ACPI_COMPANION(_dev_), _propname_, \
+					 _proptype_, _val_, _nval_)
+
+/**
+ * device_property_read_u8_array - return a u8 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u8 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u8_array(struct device *dev, const char *propname,
+				  u8 *val, size_t nval)
+{
+	return DEVICE_PROPERTY_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val,
+					  nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u8_array);
+
+/**
+ * device_property_read_u16_array - return a u16 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u16 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u16_array(struct device *dev, const char *propname,
+				   u16 *val, size_t nval)
+{
+	return DEVICE_PROPERTY_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val,
+					  nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u16_array);
+
+/**
+ * device_property_read_u32_array - return a u32 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u32 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u32_array(struct device *dev, const char *propname,
+				   u32 *val, size_t nval)
+{
+	return DEVICE_PROPERTY_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val,
+					  nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u32_array);
+
+/**
+ * device_property_read_u64_array - return a u64 array property of a device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of u64 properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_u64_array(struct device *dev, const char *propname,
+				   u64 *val, size_t nval)
+{
+	return DEVICE_PROPERTY_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val,
+					  nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_u64_array);
+
+/**
+ * device_property_read_string_array - return a string array property of device
+ * @dev: Device to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Function reads an array of string properties with @propname from the device
+ * firmware description and stores them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property is not an array of strings,
+ *	   %-EOVERFLOW if the size of the property is not as expected.
+ */
+int device_property_read_string_array(struct device *dev, const char *propname,
+				      char **val, size_t nval)
+{
+	return IS_ENABLED(CONFIG_OF) && dev->of_node ?
+		of_property_read_string_array(dev->of_node, propname, val, nval) :
+		acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname,
+					 DEV_PROP_STRING, val, nval);
+}
+EXPORT_SYMBOL_GPL(device_property_read_string_array);
Index: linux-pm/drivers/of/base.c
===================================================================
--- linux-pm.orig/drivers/of/base.c
+++ linux-pm/drivers/of/base.c
@@ -1247,6 +1247,39 @@ int of_property_read_u64(const struct de
 EXPORT_SYMBOL_GPL(of_property_read_u64);
 
 /**
+ * of_property_read_u64_array - Find and read an array of 64 bit integers
+ * from a property.
+ *
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_values:	pointer to return value, modified only if return value is 0.
+ * @sz:		number of array elements to read
+ *
+ * Search for a property in a device node and read 64-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_values is modified only if a valid u64 value can be decoded.
+ */
+int of_property_read_u64_array(const struct device_node *np,
+			       const char *propname, u64 *out_values,
+			       size_t sz)
+{
+	const __be32 *val = of_find_property_value_of_size(np, propname,
+						(sz * sizeof(*out_values)));
+
+	if (IS_ERR(val))
+		return PTR_ERR(val);
+
+	while (sz--) {
+		*out_values++ = of_read_number(val, 2);
+		val += 2;
+	}
+	return 0;
+}
+
+/**
  * of_property_read_string - Find and read a string from a property
  * @np:		device node from which the property value is to be read.
  * @propname:	name of the property to be searched.
@@ -1359,24 +1392,11 @@ int of_property_match_string(struct devi
 }
 EXPORT_SYMBOL_GPL(of_property_match_string);
 
-/**
- * of_property_count_strings - Find and return the number of strings from a
- * multiple strings property.
- * @np:		device node from which the property value is to be read.
- * @propname:	name of the property to be searched.
- *
- * Search for a property in a device tree node and retrieve the number of null
- * terminated string contain in it. Returns the number of strings on
- * success, -EINVAL if the property does not exist, -ENODATA if property
- * does not have a value, and -EILSEQ if the string is not null-terminated
- * within the length of the property data.
- */
-int of_property_count_strings(struct device_node *np, const char *propname)
+static int property_count_strings(struct property *prop)
 {
-	struct property *prop = of_find_property(np, propname, NULL);
-	int i = 0;
-	size_t l = 0, total = 0;
 	const char *p;
+	size_t l = 0, total = 0;
+	int i = 0;
 
 	if (!prop)
 		return -EINVAL;
@@ -1392,8 +1412,62 @@ int of_property_count_strings(struct dev
 
 	return i;
 }
+
+/**
+ * of_property_count_strings - Find and return the number of strings from a
+ * multiple strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ *
+ * Search for a property in a device tree node and retrieve the number of null
+ * terminated string contain in it. Returns the number of strings on
+ * success, -EINVAL if the property does not exist, -ENODATA if property
+ * does not have a value, and -EILSEQ if the string is not null-terminated
+ * within the length of the property data.
+ */
+int of_property_count_strings(struct device_node *np, const char *propname)
+{
+	return property_count_strings(of_find_property(np, propname, NULL));
+}
 EXPORT_SYMBOL_GPL(of_property_count_strings);
 
+/**
+ * of_property_read_string_array - Read an array of strings from a multiple
+ * strings property.
+ * @np:		device node from which the property value is to be read.
+ * @propname:	name of the property to be searched.
+ * @out_strs:	output array of string pointers.
+ * @sz:		number of array elements to read.
+ *
+ * Search for a property in a device tree node and retrieve a list of
+ * terminated string values (pointer to data, not a copy) in that property.
+ *
+ * If @out_strs is NULL, the number of strings in the property is returned.
+ */
+int of_property_read_string_array(struct device_node *np, const char *propname,
+				  char **out_strs, size_t sz)
+{
+	struct property *prop = of_find_property(np, propname, NULL);
+	char *p = prop->value;
+	size_t total = 0;
+	int i;
+
+	i = property_count_strings(prop);
+	if (!out_strs || i < 0)
+		return i;
+
+	if (i < sz)
+		return -EOVERFLOW;
+
+	while (total < prop->length && i < sz) {
+		size_t l = strlen(p) + 1;
+
+		out_strs[i++] = p;
+		total += l;
+		p += l;
+	}
+}
+
 void of_print_phandle_args(const char *msg, const struct of_phandle_args *args)
 {
 	int i;
Index: linux-pm/drivers/acpi/property.c
===================================================================
--- linux-pm.orig/drivers/acpi/property.c
+++ linux-pm/drivers/acpi/property.c
@@ -362,3 +362,172 @@ int acpi_dev_get_property_reference(stru
 	return -EPROTO;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
+
+int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
+		      void **valptr)
+{
+	return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
+				     (const union acpi_object **)valptr);
+}
+
+int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
+		       enum dev_prop_type proptype, void *val)
+{
+	const union acpi_object *obj;
+	int ret = -EINVAL;
+
+	if (!val)
+		return -EINVAL;
+
+	if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
+		if (ret)
+			return ret;
+
+		switch (proptype) {
+		case DEV_PROP_U8:
+			if (obj->integer.value > U8_MAX)
+				return -EOVERFLOW;
+			*(u8 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U16:
+			if (obj->integer.value > U16_MAX)
+				return -EOVERFLOW;
+			*(u16 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U32:
+			if (obj->integer.value > U32_MAX)
+				return -EOVERFLOW;
+			*(u32 *)val = obj->integer.value;
+			break;
+		default:
+			*(u64 *)val = obj->integer.value;
+			break;
+		}
+	} else if (proptype == DEV_PROP_STRING) {
+		ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
+		if (ret)
+			return ret;
+
+		*(char **)val = obj->string.pointer;
+	}
+	return ret;
+}
+
+static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
+				       size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U8_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u16(const union acpi_object *items,
+					u16 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U16_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u32(const union acpi_object *items,
+					u32 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+		if (items[i].integer.value > U32_MAX)
+			return -EOVERFLOW;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_u64(const union acpi_object *items,
+					u64 *val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_INTEGER)
+			return -EPROTO;
+
+		val[i] = items[i].integer.value;
+	}
+	return 0;
+}
+
+static int acpi_copy_property_array_string(const union acpi_object *items,
+					   char **val, size_t nval)
+{
+	int i;
+
+	for (i = 0; i < nval; i++) {
+		if (items[i].type != ACPI_TYPE_STRING)
+			return -EPROTO;
+
+		val[i] = items[i].string.pointer;
+	}
+	return 0;
+}
+
+int acpi_dev_prop_read_array(struct acpi_device *adev, const char *propname,
+			     enum dev_prop_type proptype, void *val,
+			     size_t nval)
+{
+	const union acpi_object *obj;
+	const union acpi_object *items;
+	int ret;
+
+	ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
+	if (ret)
+		return ret;
+
+	if (!val)
+		return obj->package.count;
+
+	if (nval > obj->package.count)
+		return -EOVERFLOW;
+
+	items = obj->package.elements;
+	switch (proptype) {
+	case DEV_PROP_U8:
+		ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
+		break;
+	case DEV_PROP_U16:
+		ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
+		break;
+	case DEV_PROP_U32:
+		ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
+		break;
+	case DEV_PROP_U64:
+		ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
+		break;
+	case DEV_PROP_STRING:
+		ret = acpi_copy_property_array_string(items, (char **)val, nval);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}


^ permalink raw reply	[flat|nested] 104+ messages in thread

* [Update][PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-17 12:14   ` [PATCH v5 09/12] Driver core: Unified interface for firmware node properties Rafael J. Wysocki
                       ` (2 preceding siblings ...)
  2014-10-19 22:14     ` Greg Kroah-Hartman
@ 2014-10-20  0:15     ` Rafael J. Wysocki
  3 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-20  0:15 UTC (permalink / raw)
  To: Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Grant Likely, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

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

Add new generic routines are provided for retrieving properties from
device description objects in the platform firmware in case there are
no struct device objects for them (either those objects have not been
created yet or they do not exist at all).

The following functions are provided:

fwnode_property_present()
fwnode_property_read_u8()
fwnode_property_read_u16()
fwnode_property_read_u32()
fwnode_property_read_u64()
fwnode_property_read_string()
fwnode_property_read_u8_array()
fwnode_property_read_u16_array()
fwnode_property_read_u32_array()
fwnode_property_read_u64_array()
fwnode_property_read_string_array()

in analogy with the corresponding functions for struct device added
previously.  For all of them, the first argument is a pointer to struct
fwnode_handle (new type) that allows a device description object
(depending on what platform firmware interface is in use) to be
obtained.

Add 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.

Suggested-by: Grant Likely <grant.likely@linaro.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
---

This applies on top of https://patchwork.kernel.org/patch/5101721/ .

It adds fwnode_property_read_bool() as a wrapper around fwnode_property_present()
and uses macros to generate the bodies of fwnode_property_read_*(), except for
fwnode_property_read_string_array() whose structure is a bit different from the
other functions.

Also added is the fresh ACK from Greg as the overall picture is still the same
as before.

Rafael

---
 drivers/acpi/scan.c      |   21 ++
 drivers/base/property.c  |  349 +++++++++++++++++++++++++++++++++++++++++++++++
 include/acpi/acpi_bus.h  |   17 ++
 include/linux/acpi.h     |   26 +++
 include/linux/of.h       |   22 ++
 include/linux/property.h |   54 +++++++
 6 files changed, 489 insertions(+)

Index: linux-pm/include/linux/property.h
===================================================================
--- linux-pm.orig/include/linux/property.h
+++ linux-pm/include/linux/property.h
@@ -44,10 +44,64 @@ int device_property_read_u64_array(struc
 int device_property_read_string_array(struct device *dev, const char *propname,
 				      char **val, size_t nval);
 
+enum fwnode_type {
+	FWNODE_INVALID = 0,
+	FWNODE_OF,
+	FWNODE_ACPI,
+};
+
+struct fwnode_handle {
+	enum fwnode_type type;
+};
+
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
+int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
+			    u8 *val);
+int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
+			     u16 *val);
+int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
+			     u32 *val);
+int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
+			     u64 *val);
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+				const char *propname, const char **val);
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+				  const char *propname, u8 *val,
+				  size_t nval);
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+				   const char *propname, u16 *val,
+				   size_t nval);
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+				   const char *propname, u32 *val,
+				   size_t nval);
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+				   const char *propname, u64 *val,
+				   size_t nval);
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+				      const char *propname, char **val,
+				      size_t nval);
+
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+						 struct fwnode_handle *child);
+
+#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))
+
+void fwnode_handle_put(struct fwnode_handle *fwnode);
+
+unsigned int device_get_child_node_count(struct device *dev);
+
 static inline bool device_property_read_bool(struct device *dev,
 					     const char *propname)
 {
 	return device_property_present(dev, propname);
 }
 
+static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode,
+					     const char *propname)
+{
+	return fwnode_property_present(fwnode, propname);
+}
+
 #endif /* _LINUX_PROPERTY_H_ */
Index: linux-pm/include/acpi/acpi_bus.h
===================================================================
--- linux-pm.orig/include/acpi/acpi_bus.h
+++ linux-pm/include/acpi/acpi_bus.h
@@ -27,6 +27,7 @@
 #define __ACPI_BUS_H__
 
 #include <linux/device.h>
+#include <linux/property.h>
 
 /* TBD: Make dynamic */
 #define ACPI_MAX_HANDLES	10
@@ -348,6 +349,7 @@ struct acpi_device_data {
 struct acpi_device {
 	int device_type;
 	acpi_handle handle;		/* no handle for fixed hardware */
+	struct fwnode_handle fwnode;
 	struct acpi_device *parent;
 	struct list_head children;
 	struct list_head node;
@@ -372,6 +374,21 @@ struct acpi_device {
 	void (*remove)(struct acpi_device *);
 };
 
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_ACPI;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+	return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
+}
+
+static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
+{
+	return &adev->fwnode;
+}
+
 static inline void *acpi_driver_data(struct acpi_device *d)
 {
 	return d->driver_data;
Index: linux-pm/include/linux/acpi.h
===================================================================
--- linux-pm.orig/include/linux/acpi.h
+++ linux-pm/include/linux/acpi.h
@@ -439,6 +439,23 @@ int acpi_device_modalias(struct device *
 #define ACPI_COMPANION_SET(dev, adev)	do { } while (0)
 #define ACPI_HANDLE(dev)		(NULL)
 
+struct fwnode_handle;
+
+static inline bool is_acpi_node(struct fwnode_handle *fwnode)
+{
+	return false;
+}
+
+static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
+static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
+{
+	return NULL;
+}
+
 static inline const char *acpi_dev_name(struct acpi_device *adev)
 {
 	return NULL;
@@ -681,6 +698,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,
@@ -724,6 +744,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/include/linux/of.h
===================================================================
--- linux-pm.orig/include/linux/of.h
+++ linux-pm/include/linux/of.h
@@ -50,6 +50,7 @@ struct device_node {
 	const char *type;
 	phandle phandle;
 	const char *full_name;
+	struct fwnode_handle fwnode;
 
 	struct	property *properties;
 	struct	property *deadprops;	/* removed properties */
@@ -80,6 +81,7 @@ extern struct kobj_type of_node_ktype;
 static inline void of_node_init(struct device_node *node)
 {
 	kobject_init(&node->kobj, &of_node_ktype);
+	node->fwnode.type = FWNODE_OF;
 }
 
 /* true when node is initialized */
@@ -115,6 +117,16 @@ extern struct device_node *of_aliases;
 extern struct device_node *of_stdout;
 extern raw_spinlock_t devtree_lock;
 
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+	return fwnode && fwnode->type == FWNODE_OF;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+	return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
+}
+
 static inline bool of_have_populated_dt(void)
 {
 	return of_allnodes != NULL;
@@ -365,6 +377,16 @@ bool of_console_check(struct device_node
 
 #else /* CONFIG_OF */
 
+static inline bool is_of_node(struct fwnode_handle *fwnode)
+{
+	return false;
+}
+
+static inline struct device_node *of_node(struct fwnode_handle *fwnode)
+{
+	return NULL;
+}
+
 static inline const char* of_node_full_name(const struct device_node *np)
 {
 	return "<no-node>";
Index: linux-pm/drivers/base/property.c
===================================================================
--- linux-pm.orig/drivers/base/property.c
+++ linux-pm/drivers/base/property.c
@@ -142,6 +142,151 @@ int device_property_read_string(struct d
 }
 EXPORT_SYMBOL_GPL(device_property_read_string);
 
+/**
+ * fwnode_property_present - check if a property of a firmware node is present
+ * @fwnode: Firmware node whose property to check
+ * @propname: Name of the property
+ */
+bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_bool(of_node(fwnode), propname);
+	else if (is_acpi_node(fwnode))
+		return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_present);
+
+#define FWNODE_PROPERTY_READ(_fwnode_, _propname_, _type_, _proptype_, _val_) \
+({ \
+	int _ret_; \
+	if (is_of_node(_fwnode_)) \
+		_ret_ = of_property_read_##_type_(of_node(_fwnode_), \
+						  _propname_, _val_); \
+	else if (is_acpi_node(_fwnode_)) \
+		_ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
+					   _proptype_, _val_); \
+	else \
+		_ret_ = -ENXIO; \
+	_ret_; \
+})
+
+/**
+ * fwnode_property_read_u8 - return a u8 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u8.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u8,
+ *	   %-EOVERFLOW if the property value is out of bounds of u8,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
+			    u8 *val)
+{
+	return FWNODE_PROPERTY_READ(fwnode, propname, u8, DEV_PROP_U8, val);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u8);
+
+/**
+ * fwnode_property_read_u16 - return a u16 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u16.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u16,
+ *	   %-EOVERFLOW if the property value is out of bounds of u16,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u16(struct fwnode_handle *fwnode, const char *propname,
+			     u16 *val)
+{
+	return FWNODE_PROPERTY_READ(fwnode, propname, u16, DEV_PROP_U16, val);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u16);
+
+/**
+ * fwnode_property_read_u32 - return a u32 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u32.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u32,
+ *	   %-EOVERFLOW if the property value is out of bounds of u32,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u32(struct fwnode_handle *fwnode, const char *propname,
+			     u32 *val)
+{
+	return FWNODE_PROPERTY_READ(fwnode, propname, u32, DEV_PROP_U32, val);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u32);
+
+/**
+ * fwnode_property_read_u64 - return a u64 property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be of type u64.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property type is not u64,
+ *	   %-EOVERFLOW if the property value is out of bounds of u64,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u64(struct fwnode_handle *fwnode, const char *propname,
+			     u64 *val)
+{
+	return FWNODE_PROPERTY_READ(fwnode, propname, u64, DEV_PROP_U64, val);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u64);
+
+/**
+ * fwnode_property_read_string - return a string property of a firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The value is stored here
+ *
+ * Read property @propname from the given firmware node and store the value into
+ * @val if found.  The value is checked to be a string.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO or %-EILSEQ if the property is not a string,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string(struct fwnode_handle *fwnode,
+				const char *propname, const char **val)
+{
+	return FWNODE_PROPERTY_READ(fwnode, propname, string, DEV_PROP_STRING,
+				    val);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string);
+
 #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
 	(val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
 	      : of_property_count_elems_of_size((node), (propname), sizeof(type))
@@ -274,3 +419,207 @@ int device_property_read_string_array(st
 					 DEV_PROP_STRING, val, nval);
 }
 EXPORT_SYMBOL_GPL(device_property_read_string_array);
+
+#define FWNODE_PROPERTY_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
+({ \
+	int _ret_; \
+	if (is_of_node(_fwnode_)) \
+		_ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \
+					       _type_, _val_, _nval_); \
+	else if (is_acpi_node(_fwnode_)) \
+		_ret_ = acpi_dev_prop_read_array(acpi_node(_fwnode_), \
+						 _propname_, _proptype_, \
+						 _val_, _nval_); \
+	else \
+		_ret_ = -ENXIO; \
+	_ret_; \
+})
+
+/**
+ * fwnode_property_read_u8_array - return a u8 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u8 properties with @propname from @fwnode and stores them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
+				  const char *propname, u8 *val, size_t nval)
+{
+	return FWNODE_PROPERTY_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
+					  val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
+
+/**
+ * fwnode_property_read_u16_array - return a u16 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u16 properties with @propname from @fwnode and store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
+				   const char *propname, u16 *val, size_t nval)
+{
+	return FWNODE_PROPERTY_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
+					  val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
+
+/**
+ * fwnode_property_read_u32_array - return a u32 array property of firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u32 properties with @propname from @fwnode store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
+				   const char *propname, u32 *val, size_t nval)
+{
+	return FWNODE_PROPERTY_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
+					  val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
+
+/**
+ * fwnode_property_read_u64_array - return a u64 array property firmware node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an array of u64 properties with @propname from @fwnode and store them to
+ * @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of numbers,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
+				   const char *propname, u64 *val, size_t nval)
+{
+	return FWNODE_PROPERTY_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
+					  val, nval);
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
+
+/**
+ * fwnode_property_read_string_array - return string array property of a node
+ * @fwnode: Firmware node to get the property of
+ * @propname: Name of the property
+ * @val: The values are stored here
+ * @nval: Size of the @val array
+ *
+ * Read an string list property @propname from the given firmware node and store
+ * them to @val if found.
+ *
+ * Return: %0 if the property was found (success),
+ *	   %-EINVAL if given arguments are not valid,
+ *	   %-ENODATA if the property does not have a value,
+ *	   %-EPROTO if the property is not an array of strings,
+ *	   %-EOVERFLOW if the size of the property is not as expected,
+ *	   %-ENXIO if no suitable firmware interface is present.
+ */
+int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
+				      const char *propname, char **val,
+				      size_t nval)
+{
+	if (is_of_node(fwnode))
+		return of_property_read_string_array(of_node(fwnode), propname,
+						     val, nval);
+	else if (is_acpi_node(fwnode))
+		return acpi_dev_prop_read_array(acpi_node(fwnode), propname,
+						DEV_PROP_STRING, val, nval);
+
+	return -ENXIO;
+}
+EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
+
+
+/**
+ * device_get_next_child_node - Return the next child node handle for a device
+ * @dev: Device to find the next child node for.
+ * @child: Handle to one of the device's child nodes or a null handle.
+ */
+struct fwnode_handle *device_get_next_child_node(struct device *dev,
+						 struct fwnode_handle *child)
+{
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
+		struct device_node *node;
+
+		node = of_get_next_available_child(dev->of_node, of_node(child));
+		if (node)
+			return &node->fwnode;
+	} else if (ACPI_COMPANION(dev)) {
+		struct acpi_device *node;
+
+		node = acpi_get_next_child(dev, acpi_node(child));
+		if (node)
+			return acpi_fwnode_handle(node);
+	}
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(device_get_next_child_node);
+
+/**
+ * fwnode_handle_put - Drop reference to a device node
+ * @fwnode: Pointer to the device node 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 fwnode_handle_put(struct fwnode_handle *fwnode)
+{
+	if (is_of_node(fwnode))
+		of_node_put(of_node(fwnode));
+}
+EXPORT_SYMBOL_GPL(fwnode_handle_put);
+
+/**
+ * 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)
+{
+	struct fwnode_handle *child;
+	unsigned int count = 0;
+
+	device_for_each_child_node(dev, child)
+		count++;
+
+	return count;
+}
+EXPORT_SYMBOL_GPL(device_get_child_node_count);
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
    -------------------------------------------------------------------------- */
@@ -1961,6 +1981,7 @@ void acpi_init_device_object(struct acpi
 	device->device_type = type;
 	device->handle = handle;
 	device->parent = acpi_bus_get_parent(handle);
+	device->fwnode.type = FWNODE_ACPI;
 	acpi_set_device_status(device, sta);
 	acpi_device_get_busid(device);
 	acpi_set_pnp_ids(handle, &device->pnp, type);


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  2014-10-18  9:47       ` Arnd Bergmann
  2014-10-19 23:58         ` Rafael J. Wysocki
@ 2014-10-20  6:12         ` Alexandre Courbot
  2014-10-20 14:26           ` Arnd Bergmann
  1 sibling, 1 reply; 104+ messages in thread
From: Alexandre Courbot @ 2014-10-20  6:12 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Mika Westerberg, ACPI Devel Maling List, Aaron Lu,
	devicetree, Linus Walleij, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Sat, Oct 18, 2014 at 6:47 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Friday 17 October 2014 20:09:51 Arnd Bergmann wrote:
>> On October 17, 2014 2:16:00 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
>> >From: Mika Westerberg <mika.westerberg@linux.intel.com>
>> >
>> >Some drivers need to deal with only firmware representation of its
>> >GPIOs. An example would be a GPIO button array driver where each button
>> >is described as a separate firmware node in device tree. Typically
>> >these
>> >child nodes do not have physical representation in the Linux device
>> >model.
>> >
>> >In order to help device drivers to handle such firmware child nodes we
>> >add dev[m]_get_named_gpiod_from_child() that takes a child firmware
>> >node pointer as its second argument (the first one is the parent device
>> >itself), finds the GPIO using whatever is the underlying firmware
>> >method, and requests the GPIO properly.
>>
>> Could we also have a wrapper around this function without a "name" argument,
>> using just the index?
>
> Expanding on this thought: I think we should mandate for new bindings
> that they use either a name and no index, or an index but not name,

I'm afraid this could forbid some useful use-cases, namely the ones
where several GPIOs serve the same function (and are typically set
together). We had a few patch proposals to handle such GPIO groups,
and even though one was in pretty good shape the submitter did not
push it until the end. :/

But my concern is that instead of having this:

enable-gpio = <&gpio 0 GPIO_ACTIVE_HIGH>;
value-gpios = <&gpio 1 GPIO_ACTIVE_HIGH ... &gpio 8 GPIO_ACTIVE_HIGH>;

We would force this:

enable-gpio = <&gpio 0 GPIO_ACTIVE_HIGH>;
value0-gpio = <&gpio 1 GPIO_ACTIVE_HIGH>;
...
value7-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;

Or this:

// First GPIO is enable, other GPIOs are value
gpios = <&gpio 0 GPIO_ACTIVE_HIGH &gpio 1 GPIO_ACTIVE_HIGH ... &gpio 8
GPIO_ACTIVE_HIGH>;

Most bindings don't need that much sophistication, and for these we
should indeed make sure that they stick to using either the names or
index (and in a consistent manner), but closing the possibility to use
both together may bite us in the end.


> and I also think that for named gpios, we should try to converge on a
> common naming scheme. As discussed, we will probably want to support all
> the existing ways to do this even with ACPI and with the unified
> interface, but it doesn't have to be the obvious way.

Personally, I like the idea that each GPIO has a function, so now that
ACPI fully supports this I'd suggest the policy of using names for
each GPIO (e.g. never use the fallback "gpios" or "gpio" property),
and only ressort to indexes if several GPIOs happen to serve the same
function. I know we haven't reached consensus about this so far, but
it would be nice it we could discuss this point again in the light of
the new ACPI capabilities and come with something to write as a
guideline in the GPIO documentation.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-20 14:05 UTC (permalink / raw)
  To: Rafael J. Wysocki, Linux Kernel Mailing List
  Cc: Greg Kroah-Hartman, Arnd Bergmann, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

On Fri, 17 Oct 2014 14:05:59 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> From: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> We have lots of existing Device Tree enabled drivers and allocating
> separate _HID for each is not feasible. Instead we allocate special _HID
> "PRP0001" that means that the match should be done using Device Tree
> compatible property using driver's .of_match_table instead if the driver
> is missing .acpi_match_table.

(Not a critique of this patch, but merely a helpful comment; my previous
ack remains intact) :-)

It would be useful for the code to point at some document that describes
the semantics of the PRP0001 binding.

g.

> 
> If there is a need to distinguish from where the device is enumerated
> (DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Reviewed-by: Grant Likely <grant.likely@linaro.org>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> ---
>  drivers/acpi/property.c | 34 +++++++++++++++++
>  drivers/acpi/scan.c     | 97 +++++++++++++++++++++++++++++++++++++++++++------
>  include/acpi/acpi_bus.h |  1 +
>  include/linux/acpi.h    |  8 +---
>  4 files changed, 123 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 680f7f1..ff53eb8 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -76,6 +76,37 @@ static bool acpi_properties_format_valid(const union acpi_object *properties)
>  	return true;
>  }
>  
> +static void acpi_init_of_compatible(struct acpi_device *adev)
> +{
> +	const union acpi_object *of_compatible;
> +	struct acpi_hardware_id *hwid;
> +	bool acpi_of = false;
> +
> +	/*
> +	 * Check if the special PRP0001 ACPI ID is present and in that
> +	 * case we fill in Device Tree compatible properties for this
> +	 * device.
> +	 */
> +	list_for_each_entry(hwid, &adev->pnp.ids, list) {
> +		if (!strcmp(hwid->id, "PRP0001")) {
> +			acpi_of = true;
> +			break;
> +		}
> +	}
> +
> +	if (!acpi_of)
> +		return;
> +
> +	if (acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING,
> +					&of_compatible)) {
> +		acpi_handle_warn(adev->handle,
> +				 "PRP0001 requires compatible property\n");
> +		return;
> +	}
> +
> +	adev->data.of_compatible = of_compatible;
> +}
> +
>  void acpi_init_properties(struct acpi_device *adev)
>  {
>  	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> @@ -119,6 +150,8 @@ void acpi_init_properties(struct acpi_device *adev)
>  
>  		adev->data.pointer = buf.pointer;
>  		adev->data.properties = properties;
> +
> +		acpi_init_of_compatible(adev);
>  		return;
>  	}
>  
> @@ -130,6 +163,7 @@ void acpi_init_properties(struct acpi_device *adev)
>  void acpi_free_properties(struct acpi_device *adev)
>  {
>  	ACPI_FREE((void *)adev->data.pointer);
> +	adev->data.of_compatible = NULL;
>  	adev->data.pointer = NULL;
>  	adev->data.properties = NULL;
>  }
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index 1979ab3..bc999f1 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -124,17 +124,51 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias,
>  	if (list_empty(&acpi_dev->pnp.ids))
>  		return 0;
>  
> -	len = snprintf(modalias, size, "acpi:");
> -	size -= len;
> -
> -	list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
> -		count = snprintf(&modalias[len], size, "%s:", id->id);
> -		if (count < 0)
> -			return -EINVAL;
> -		if (count >= size)
> -			return -ENOMEM;
> -		len += count;
> -		size -= count;
> +	/*
> +	 * If the device has PRP0001 we expose DT compatible modalias
> +	 * instead in form of of:NnameTCcompatible.
> +	 */
> +	if (acpi_dev->data.of_compatible) {
> +		struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
> +		const union acpi_object *of_compatible, *obj;
> +		char *c;
> +		int i;
> +
> +		acpi_get_name(acpi_dev->handle, ACPI_SINGLE_NAME, &buf);
> +		/* DT strings are all in lower case */
> +		for (c = buf.pointer; *c != '\0'; c++)
> +			*c = tolower(*c);
> +
> +		len = snprintf(modalias, size, "of:N%sT", (char *)buf.pointer);
> +		ACPI_FREE(buf.pointer);
> +
> +		of_compatible = acpi_dev->data.of_compatible;
> +		for (i = 0; i < of_compatible->package.count; i++) {
> +			obj = &of_compatible->package.elements[i];
> +
> +			count = snprintf(&modalias[len], size, "C%s",
> +					 obj->string.pointer);
> +			if (count < 0)
> +				return -EINVAL;
> +			if (count >= size)
> +				return -ENOMEM;
> +
> +			len += count;
> +			size -= count;
> +		}
> +	} else {
> +		len = snprintf(modalias, size, "acpi:");
> +		size -= len;
> +
> +		list_for_each_entry(id, &acpi_dev->pnp.ids, list) {
> +			count = snprintf(&modalias[len], size, "%s:", id->id);
> +			if (count < 0)
> +				return -EINVAL;
> +			if (count >= size)
> +				return -ENOMEM;
> +			len += count;
> +			size -= count;
> +		}
>  	}
>  
>  	modalias[len] = '\0';
> @@ -864,6 +898,47 @@ int acpi_match_device_ids(struct acpi_device *device,
>  }
>  EXPORT_SYMBOL(acpi_match_device_ids);
>  
> +/* Performs match against special "PRP0001" shoehorn ACPI ID */
> +static bool acpi_of_driver_match_device(struct device *dev,
> +					const struct device_driver *drv)
> +{
> +	const union acpi_object *of_compatible;
> +	struct acpi_device *adev;
> +	int i;
> +
> +	adev = ACPI_COMPANION(dev);
> +	if (!adev)
> +		return false;
> +
> +	of_compatible = adev->data.of_compatible;
> +	if (!drv->of_match_table || !of_compatible)
> +		return false;
> +
> +	/* Now we can look for the driver DT compatible strings */
> +	for (i = 0; i < of_compatible->package.count; i++) {
> +		const struct of_device_id *id;
> +		const union acpi_object *obj;
> +
> +		obj = &of_compatible->package.elements[i];
> +
> +		for (id = drv->of_match_table; id->compatible[0]; id++)
> +			if (!strcasecmp(obj->string.pointer, id->compatible))
> +				return true;
> +	}
> +
> +	return false;
> +}
> +
> +bool acpi_driver_match_device(struct device *dev,
> +			      const struct device_driver *drv)
> +{
> +	if (!drv->acpi_match_table)
> +		return acpi_of_driver_match_device(dev, drv);
> +
> +	return !!acpi_match_device(drv->acpi_match_table, dev);
> +}
> +EXPORT_SYMBOL_GPL(acpi_driver_match_device);
> +
>  static void acpi_free_power_resources_lists(struct acpi_device *device)
>  {
>  	int i;
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index f9734fa..98cd723 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -341,6 +341,7 @@ struct acpi_device_physical_node {
>  struct acpi_device_data {
>  	const union acpi_object *pointer;
>  	const union acpi_object *properties;
> +	const union acpi_object *of_compatible;
>  };
>  
>  /* Device */
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 18c1bc3..11aa6b8 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -424,12 +424,8 @@ extern int acpi_nvs_for_each_region(int (*func)(__u64, __u64, void *),
>  const struct acpi_device_id *acpi_match_device(const struct acpi_device_id *ids,
>  					       const struct device *dev);
>  
> -static inline bool acpi_driver_match_device(struct device *dev,
> -					    const struct device_driver *drv)
> -{
> -	return !!acpi_match_device(drv->acpi_match_table, dev);
> -}
> -
> +extern bool acpi_driver_match_device(struct device *dev,
> +				     const struct device_driver *drv);
>  int acpi_device_uevent_modalias(struct device *, struct kobj_uevent_env *);
>  int acpi_device_modalias(struct device *, char *, int);
>  
> -- 
> 1.9.3
> 
> 


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-19 23:30       ` Rafael J. Wysocki
@ 2014-10-20 14:14         ` Arnd Bergmann
  0 siblings, 0 replies; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-20 14:14 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday 20 October 2014 01:30:47 Rafael J. Wysocki wrote:
> On Saturday, October 18, 2014 11:35:21 AM Arnd Bergmann wrote:
> > On Friday 17 October 2014 14:14:53 Rafael J. Wysocki wrote:
> > > +/**
> > > + * fwnode_property_present - check if a property of a firmware node is present
> > > + * @fwnode: Firmware node whose property to check
> > > + * @propname: Name of the property
> > > + */
> > > +bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
> > > +{
> > > +       if (is_of_node(fwnode))
> > > +               return of_property_read_bool(of_node(fwnode), propname);
> > > +       else if (is_acpi_node(fwnode))
> > > +               return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> > > +
> > > +       return false;
> > > +}
> > > +EXPORT_SYMBOL_GPL(fwnode_property_present);
> > > 
> > 
> > Should this be
> > 
> >               return acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
> > 
> > without the '!'?
> 
> No, acpi_dev_prop_get() returns 0 on success. 

Ah, got it now.

> > I'm also unsure about the '_present' vs '_read_bool' naming. IIRC we had
> > a long debate about this before we decided on 'read_bool' for DT, and
> > I don't really want to start a new debate, but being consistent would
> > be nice.
> > 
> > We could of course have
> > 
> > static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode, const char *propname)
> > {
> >       return fwnode_property_present(fwnode, propname);
> > }
> > 
> > which is completely redundant, but would help for drivers using the
> > interface to document whether we are checking for bool property that
> > we expect to be either empty or absent (_get_bool), vs checking for
> > the presence of a non-empty property (_present).
> 
> I'm fine with that, so I'll add fwnode_property_read_bool() (and an analogous
> wrapper for device_) to patches [02/12] and [09/12].
> 
> I'll be sending updates of them shortly, so please have a look at those.

Ok, will do.

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  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
  1 sibling, 1 reply; 104+ messages in thread
From: Grant Likely @ 2014-10-20 14:18 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Mon, 20 Oct 2014 01:46 +0200
, "Rafael J. Wysocki" <rjw@rjwysocki.net>
 wrote:
> On Saturday, October 18, 2014 04:55:20 PM Grant Likely wrote:
> > On Fri, 17 Oct 2014 14:14:53 +0200
> > , "Rafael J. Wysocki" <rjw@rjwysocki.net>
> >  wrote:
> > > From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > > 
> > > Add new generic routines are provided for retrieving properties from
> > > device description objects in the platform firmware in case there are
> > > no struct device objects for them (either those objects have not been
> > > created yet or they do not exist at all).
> > > 
> > > The following functions are provided:
> > > 
> > > fwnode_property_present()
> > > fwnode_property_read_u8()
> > > fwnode_property_read_u16()
> > > fwnode_property_read_u32()
> > > fwnode_property_read_u64()
> > > fwnode_property_read_string()
> > > fwnode_property_read_u8_array()
> > > fwnode_property_read_u16_array()
> > > fwnode_property_read_u32_array()
> > > fwnode_property_read_u64_array()
> > > fwnode_property_read_string_array()
> > > 
> > > in analogy with the corresponding functions for struct device added
> > > previously.  For all of them, the first argument is a pointer to struct
> > > fwnode_handle (new type) that allows a device description object
> > > (depending on what platform firmware interface is in use) to be
> > > obtained.
> > > 
> > > Add 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 is all *so much* better. I'm a lot happier.
> > 
> > I was about to make the comment that the implementation for
> > device_property_read_*() should merely be wrappers around
> > fwnode_property_read_*(), but when when I actually looked at it, I saw
> > this:
> > 
> > In patch 2:
> > int device_property_read_u8(struct device *dev, const char *propname, u8 *val)
> > {
> > 	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> > 		return of_property_read_u8(dev->of_node, propname, val);
> > 
> > 	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
> > 				  DEV_PROP_U8, val);
> > }
> > 
> > And in this patch:
> > int fwnode_property_read_u8(struct fwnode_handle *fwnode, const char *propname,
> > 			    u8 *val)
> > {
> > 	if (is_of_node(fwnode))
> > 		return of_property_read_u8(of_node(fwnode), propname, val);
> > 	else if (is_acpi_node(fwnode))
> > 		return acpi_dev_prop_read(acpi_node(fwnode), propname,
> > 					  DEV_PROP_U8, val);
> > 
> > 	return -ENXIO;
> > }
> > 
> > Making the device_property functions wrappers around fwnode_property_*
> > wouldn't actually be great since it would need to decode the fwnode
> > pointer twice.
> 
> Indeed.
> 
> > I do still think the functions above should be macro generated, just in
> > terms of keeping the line count down, and I would suggest merging patches #2
> > and #9.
> 
> Well, the changes in those patches are almost completely independent and patch
> #9 is only actually needed for #11 and #12, so I'm not sure if that would be
> better.  I certainly prefer splitting longer patches into pieces if that makes
> sense and it does make sense to do so in this particular case IMHO.

I'm not going to make a big deal about. Do what you think is best.

> > Something like:
> > 
> > #define define_fwnode_accessors(__type, __devprop_type) \
> > int device_property_read_##__type(struct device *dev, \
> > 				const char *propname, __type *val) \
> > { \
> > 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> > 		return of_property_read_##__type(dev->of_node, propname, val); \
> > 	return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
> > 				  __devprop_type, val); \
> > } \
> > int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> > 				const char *propname, __type *val) \
> > { \
> > 	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> > 		return of_property_read_##__type(of_node(fwnode), propname, val); \
> > 	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> > 		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> > 					  __devprop_type, val); \
> > 	return -ENXIO; \
> > }
> > 
> > define_fwnode_accessors(u8, DEV_PROP_U8);
> > define_fwnode_accessors(u16, DEV_PROP_U16);
> > define_fwnode_accessors(u32, DEV_PROP_U32);
> > define_fwnode_accessors(u64, DEV_PROP_U64);
> > 
> > That significantly reduces the code size for these things.
> 
> So I was considering to do that, but eventually decided not to, because (1)
> adding kerneldoc comments to such things looks odd and (2) (which IMO is
> more important) this breaks LXR (for example, the thing at lxr.free-electrons.com
> that some people, including me in particular, occasionally use to check how things
> are defined).  And even if you used the old good grep to look for a definition of
> fwnode_property_read_u8, say, this wouldn't work exactly as expected I'm afraid. ;-)
> 
> I would very much like to retain the headers at least for this reason, if that's
> not a big deal.
> 
> What I can do, however, is to use macros for generating the bodies of those
> functions.

I'm fine with that. It's the near-identical blocks of code that I'm
concerned about. It is easy to miss one instance when fixing bugs if
they all have to be open coded. Plus it simply means a lot more lines of
code to wade through and review.

> > Also, can the non-array versions be implemented as a wrapper around the
> > array versions? That also will reduce the sheer number of lines of code
> > a lot.
> > 
> > Maybe this:
> > 
> > #define define_fwnode_accessors(__type, __devprop_type) \
> > int device_property_read_##__type##_array(struct device *dev, \
> > 				const char *propname, __type *val, \
> > 				size_t nval) \
> > { \
> > 	if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> > 		return of_property_read_##__type##_array(dev->of_node, \
> > 		propname, val, nval); \
> > 	return acpi_dev_prop_read_array(ACPI_COMPANION(dev), propname, \
> > 				  __devprop_type, val, nval); \
> > } \
> > static inline int device_property_read_##__type(struct device *dev, \
> > 				const char *propname, __type *val) \
> > { \
> > 	return device_property_read_##__type##_array(dev, propname, val, 1) \
> > } \
> > int fwnode_property_read_##__type##_array(struct fwnode_handle *fwnode, \
> > 				const char *propname, __type *val, \
> > 				size_t nval) \
> > { \
> > 	if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> > 		return of_property_read_##__type(of_node(fwnode), propname, val, nval); \
> > 	else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> > 		return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> > 					  __devprop_type, val, nval); \
> > 	return -ENXIO; \
> > } \
> > static inline int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> > 				const char *propname, __type *val) \
> > { \
> > 	return fwnode_property_read_##__type##_array(fwnode, propname, val, 1) \
> > }
> > define_fwnode_accessors(u8, DEV_PROP_U8);
> > define_fwnode_accessors(u16, DEV_PROP_U16);
> > define_fwnode_accessors(u32, DEV_PROP_U32);
> > define_fwnode_accessors(u64, DEV_PROP_U64);
> 
> No, that wouldn't work for ACPI (if I understand your idea correctly), because
> acpi_dev_prop_read(adev, propname, DEV_PROP_U8, val) will look for a single-value
> int property, whereas acpi_dev_prop_read_array(adev, propname, DEV_PROP_U8, val, 1)
> will look for a list (package) property and will attempt to retrieve the first
> element of that.

That's a problem. There are certainly cases of DT code that use the
non-array version to read something that could also be read as an array
when the code only want the first value. It is a completely valid thing
to do. The ACPI accessors should be completely okay with either a single
value, or the first item(s) in a package when doing either a single read or
an array read.

so, if it is encoded as a singl values, then return that value, and the
largest size of array it will return is 1 element.

If it is encoded as a package, then a single read should return the
first element, and an array read should return up to the number of
values in the package.

g.


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-19 23:46       ` Rafael J. Wysocki
  2014-10-20 14:18         ` Grant Likely
@ 2014-10-20 14:19         ` Arnd Bergmann
  2014-10-20 14:55           ` Grant Likely
  2014-10-20 22:22           ` Rafael J. Wysocki
  1 sibling, 2 replies; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-20 14:19 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Grant Likely, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday 20 October 2014 01:46:00 Rafael J. Wysocki wrote:
> 
> > Something like:
> > 
> > #define define_fwnode_accessors(__type, __devprop_type) \
> > int device_property_read_##__type(struct device *dev, \
> >                               const char *propname, __type *val) \
> > { \
> >       if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> >               return of_property_read_##__type(dev->of_node, propname, val); \
> >       return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
> >                                 __devprop_type, val); \
> > } \
> > int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> >                               const char *propname, __type *val) \
> > { \
> >       if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> >               return of_property_read_##__type(of_node(fwnode), propname, val); \
> >       else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> >               return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> >                                         __devprop_type, val); \
> >       return -ENXIO; \
> > }
> > 
> > define_fwnode_accessors(u8, DEV_PROP_U8);
> > define_fwnode_accessors(u16, DEV_PROP_U16);
> > define_fwnode_accessors(u32, DEV_PROP_U32);
> > define_fwnode_accessors(u64, DEV_PROP_U64);
> > 
> > That significantly reduces the code size for these things.
> 
> So I was considering to do that, but eventually decided not to, because (1)
> adding kerneldoc comments to such things looks odd and (2) (which IMO is
> more important) this breaks LXR (for example, the thing at lxr.free-electrons.com
> that some people, including me in particular, occasionally use to check how things
> are defined).  And even if you used the old good grep to look for a definition of
> fwnode_property_read_u8, say, this wouldn't work exactly as expected I'm afraid. 

Agreed, I'd also prefer your proposed code over Grant's macros.

> I would very much like to retain the headers at least for this reason, if that's
> not a big deal.
> 
> What I can do, however, is to use macros for generating the bodies of those
> functions.

Yes, just don't do any concatenation to generate the names of the called
functions, i.e.

	return fwnode_call(of_property_read_u32, acpi_dev_prop_read, DEV_PROP_U32, node, propname, val);

is better than

	return fwnode_call(u32, DEV_PROP_U32, node, propname, val);

because it's easier to understand the call chain.

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  2014-10-19 23:58         ` Rafael J. Wysocki
@ 2014-10-20 14:22           ` Arnd Bergmann
  0 siblings, 0 replies; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-20 14:22 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday 20 October 2014 01:58:57 Rafael J. Wysocki wrote:
> 
> Actually, since the two last patches in the series, which currently are
> the only users of these new functions, both pass "gpios" as the property
> name and 0 as the index, I can simplify the functions so that (a)
> fwnode_get_gpiod() takes fwnode and name and then simply passes 0 as the
> index to either of_get_named_gpiod_flags() or acpi_get_gpiod_by_index()
> and (b) devm_get_named_gpiod_from_child() takes only dev and fwnode (child)
> and passes "gpios" as the property name to fwnode_get_gpiod().  The name
> of devm_get_named_gpiod_from_child() could then be changed to something
> like devm_get_gpiod_from_child() even.
> 
> If anyone in the future needs anything more general, they can simply
> add more complexity to that code, but for now we can go for a simplified
> interface just fine.
> 

That sounds good, yes.

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 10/12] gpio: Support for unified device properties interface
  2014-10-20  6:12         ` Alexandre Courbot
@ 2014-10-20 14:26           ` Arnd Bergmann
  0 siblings, 0 replies; 104+ messages in thread
From: Arnd Bergmann @ 2014-10-20 14:26 UTC (permalink / raw)
  To: Alexandre Courbot
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Mika Westerberg, ACPI Devel Maling List, Aaron Lu,
	devicetree, Linus Walleij, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday 20 October 2014 15:12:50 Alexandre Courbot wrote:
> On Sat, Oct 18, 2014 at 6:47 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> > On Friday 17 October 2014 20:09:51 Arnd Bergmann wrote:
> >> On October 17, 2014 2:16:00 PM CEST, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> >> >From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >> >
> >> >Some drivers need to deal with only firmware representation of its
> >> >GPIOs. An example would be a GPIO button array driver where each button
> >> >is described as a separate firmware node in device tree. Typically
> >> >these
> >> >child nodes do not have physical representation in the Linux device
> >> >model.
> >> >
> >> >In order to help device drivers to handle such firmware child nodes we
> >> >add dev[m]_get_named_gpiod_from_child() that takes a child firmware
> >> >node pointer as its second argument (the first one is the parent device
> >> >itself), finds the GPIO using whatever is the underlying firmware
> >> >method, and requests the GPIO properly.
> >>
> >> Could we also have a wrapper around this function without a "name" argument,
> >> using just the index?
> >
> > Expanding on this thought: I think we should mandate for new bindings
> > that they use either a name and no index, or an index but not name,
> 
> I'm afraid this could forbid some useful use-cases, namely the ones
> where several GPIOs serve the same function (and are typically set
> together). We had a few patch proposals to handle such GPIO groups,
> and even though one was in pretty good shape the submitter did not
> push it until the end. :/
> 
> But my concern is that instead of having this:
> 
> enable-gpio = <&gpio 0 GPIO_ACTIVE_HIGH>;
> value-gpios = <&gpio 1 GPIO_ACTIVE_HIGH ... &gpio 8 GPIO_ACTIVE_HIGH>;
> 
> We would force this:
> 
> enable-gpio = <&gpio 0 GPIO_ACTIVE_HIGH>;
> value0-gpio = <&gpio 1 GPIO_ACTIVE_HIGH>;
> ...
> value7-gpio = <&gpio 8 GPIO_ACTIVE_HIGH>;
> 
> Or this:
> 
> // First GPIO is enable, other GPIOs are value
> gpios = <&gpio 0 GPIO_ACTIVE_HIGH &gpio 1 GPIO_ACTIVE_HIGH ... &gpio 8
> GPIO_ACTIVE_HIGH>;
> 
> Most bindings don't need that much sophistication, and for these we
> should indeed make sure that they stick to using either the names or
> index (and in a consistent manner), but closing the possibility to use
> both together may bite us in the end.

I would actually prefer the single-property case here, but I see your
point. Could we make it a strong suggestion rather than a mandatory
requirement for new bindings then?

> > and I also think that for named gpios, we should try to converge on a
> > common naming scheme. As discussed, we will probably want to support all
> > the existing ways to do this even with ACPI and with the unified
> > interface, but it doesn't have to be the obvious way.
> 
> Personally, I like the idea that each GPIO has a function, so now that
> ACPI fully supports this I'd suggest the policy of using names for
> each GPIO (e.g. never use the fallback "gpios" or "gpio" property),
> and only ressort to indexes if several GPIOs happen to serve the same
> function. I know we haven't reached consensus about this so far, but
> it would be nice it we could discuss this point again in the light of
> the new ACPI capabilities and come with something to write as a
> guideline in the GPIO documentation.

We have enforced naming things for the dmaengine binding, which has
just led to everyone calling things "rx" and "tx". My fear is that
if we start to enforce giving a name, we'd end up with lots of
drivers that use a "gpio-gpios" property or something silly.

	Arnd

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-20 14:19         ` Arnd Bergmann
@ 2014-10-20 14:55           ` Grant Likely
  2014-10-20 22:22           ` Rafael J. Wysocki
  1 sibling, 0 replies; 104+ messages in thread
From: Grant Likely @ 2014-10-20 14:55 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Mon, Oct 20, 2014 at 4:19 PM, Arnd Bergmann <arnd@arndb.de> wrote:
> On Monday 20 October 2014 01:46:00 Rafael J. Wysocki wrote:
>>
>> > Something like:
>> >
>> > #define define_fwnode_accessors(__type, __devprop_type) \
>> > int device_property_read_##__type(struct device *dev, \
>> >                               const char *propname, __type *val) \
>> > { \
>> >       if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
>> >               return of_property_read_##__type(dev->of_node, propname, val); \
>> >       return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
>> >                                 __devprop_type, val); \
>> > } \
>> > int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
>> >                               const char *propname, __type *val) \
>> > { \
>> >       if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
>> >               return of_property_read_##__type(of_node(fwnode), propname, val); \
>> >       else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
>> >               return acpi_dev_prop_read(acpi_node(fwnode), propname, \
>> >                                         __devprop_type, val); \
>> >       return -ENXIO; \
>> > }
>> >
>> > define_fwnode_accessors(u8, DEV_PROP_U8);
>> > define_fwnode_accessors(u16, DEV_PROP_U16);
>> > define_fwnode_accessors(u32, DEV_PROP_U32);
>> > define_fwnode_accessors(u64, DEV_PROP_U64);
>> >
>> > That significantly reduces the code size for these things.
>>
>> So I was considering to do that, but eventually decided not to, because (1)
>> adding kerneldoc comments to such things looks odd and (2) (which IMO is
>> more important) this breaks LXR (for example, the thing at lxr.free-electrons.com
>> that some people, including me in particular, occasionally use to check how things
>> are defined).  And even if you used the old good grep to look for a definition of
>> fwnode_property_read_u8, say, this wouldn't work exactly as expected I'm afraid.
>
> Agreed, I'd also prefer your proposed code over Grant's macros.
>
>> I would very much like to retain the headers at least for this reason, if that's
>> not a big deal.
>>
>> What I can do, however, is to use macros for generating the bodies of those
>> functions.
>
> Yes, just don't do any concatenation to generate the names of the called
> functions, i.e.
>
>         return fwnode_call(of_property_read_u32, acpi_dev_prop_read, DEV_PROP_U32, node, propname, val);
>
> is better than
>
>         return fwnode_call(u32, DEV_PROP_U32, node, propname, val);
>
> because it's easier to understand the call chain.

Sounds reasonable. I've got no problem with that.

g.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-20 14:18         ` Grant Likely
@ 2014-10-20 22:14           ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-20 22:14 UTC (permalink / raw)
  To: Grant Likely
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday, October 20, 2014 04:18:18 PM Grant Likely wrote:
> On Mon, 20 Oct 2014 01:46 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > On Saturday, October 18, 2014 04:55:20 PM Grant Likely wrote:
> > > On Fri, 17 Oct 2014 14:14:53 +0200

[cut]

> > 
> > No, that wouldn't work for ACPI (if I understand your idea correctly), because
> > acpi_dev_prop_read(adev, propname, DEV_PROP_U8, val) will look for a single-value
> > int property, whereas acpi_dev_prop_read_array(adev, propname, DEV_PROP_U8, val, 1)
> > will look for a list (package) property and will attempt to retrieve the first
> > element of that.
> 
> That's a problem. There are certainly cases of DT code that use the
> non-array version to read something that could also be read as an array
> when the code only want the first value. It is a completely valid thing
> to do. The ACPI accessors should be completely okay with either a single
> value, or the first item(s) in a package when doing either a single read or
> an array read.

Yeah.

So I have a new version of the patchset in which that is implemented as
you are describing.  Fortunately, the differences are limited to patches #2,
#3 (for the "compatible" property to behave this way too) and #9 and are not
too big.

I'd prefer that to pass the Mika's tests before posting it, though, which will
take some time I suppose.

> so, if it is encoded as a singl values, then return that value, and the
> largest size of array it will return is 1 element.
> 
> If it is encoded as a package, then a single read should return the
> first element, and an array read should return up to the number of
> values in the package.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 03/12] ACPI: Allow drivers to match using Device Tree compatible property
  2014-10-20 14:05     ` Grant Likely
@ 2014-10-20 22:19       ` Rafael J. Wysocki
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-20 22:19 UTC (permalink / raw)
  To: Grant Likely
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Arnd Bergmann,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday, October 20, 2014 04:05:01 PM Grant Likely wrote:
> On Fri, 17 Oct 2014 14:05:59 +0200
> , "Rafael J. Wysocki" <rjw@rjwysocki.net>
>  wrote:
> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> > 
> > We have lots of existing Device Tree enabled drivers and allocating
> > separate _HID for each is not feasible. Instead we allocate special _HID
> > "PRP0001" that means that the match should be done using Device Tree
> > compatible property using driver's .of_match_table instead if the driver
> > is missing .acpi_match_table.
> 
> (Not a critique of this patch, but merely a helpful comment; my previous
> ack remains intact) :-)
> 
> It would be useful for the code to point at some document that describes
> the semantics of the PRP0001 binding.

Well, we need to create that document in the first place. :-)

I'd prefer to wait with that until the thing settles, however.

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 09/12] Driver core: Unified interface for firmware node properties
  2014-10-20 14:19         ` Arnd Bergmann
  2014-10-20 14:55           ` Grant Likely
@ 2014-10-20 22:22           ` Rafael J. Wysocki
  1 sibling, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-20 22:22 UTC (permalink / raw)
  To: Arnd Bergmann
  Cc: Grant Likely, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Monday, October 20, 2014 04:19:57 PM Arnd Bergmann wrote:
> On Monday 20 October 2014 01:46:00 Rafael J. Wysocki wrote:
> > 
> > > Something like:
> > > 
> > > #define define_fwnode_accessors(__type, __devprop_type) \
> > > int device_property_read_##__type(struct device *dev, \
> > >                               const char *propname, __type *val) \
> > > { \
> > >       if (IS_ENABLED(CONFIG_OF) && dev->of_node) \
> > >               return of_property_read_##__type(dev->of_node, propname, val); \
> > >       return acpi_dev_prop_read(ACPI_COMPANION(dev), propname, \
> > >                                 __devprop_type, val); \
> > > } \
> > > int fwnode_property_read_##__type(struct fwnode_handle *fwnode, \
> > >                               const char *propname, __type *val) \
> > > { \
> > >       if (IS_ENABLED(CONFIG_OF) && is_of_node(fwnode)) \
> > >               return of_property_read_##__type(of_node(fwnode), propname, val); \
> > >       else if (IS_ENABLED(CONFIG_ACPI) && is_acpi_node(fwnode)) \
> > >               return acpi_dev_prop_read(acpi_node(fwnode), propname, \
> > >                                         __devprop_type, val); \
> > >       return -ENXIO; \
> > > }
> > > 
> > > define_fwnode_accessors(u8, DEV_PROP_U8);
> > > define_fwnode_accessors(u16, DEV_PROP_U16);
> > > define_fwnode_accessors(u32, DEV_PROP_U32);
> > > define_fwnode_accessors(u64, DEV_PROP_U64);
> > > 
> > > That significantly reduces the code size for these things.
> > 
> > So I was considering to do that, but eventually decided not to, because (1)
> > adding kerneldoc comments to such things looks odd and (2) (which IMO is
> > more important) this breaks LXR (for example, the thing at lxr.free-electrons.com
> > that some people, including me in particular, occasionally use to check how things
> > are defined).  And even if you used the old good grep to look for a definition of
> > fwnode_property_read_u8, say, this wouldn't work exactly as expected I'm afraid. 
> 
> Agreed, I'd also prefer your proposed code over Grant's macros.
> 
> > I would very much like to retain the headers at least for this reason, if that's
> > not a big deal.
> > 
> > What I can do, however, is to use macros for generating the bodies of those
> > functions.
> 
> Yes, just don't do any concatenation to generate the names of the called
> functions, i.e.
> 
> 	return fwnode_call(of_property_read_u32, acpi_dev_prop_read, DEV_PROP_U32, node, propname, val);
> 
> is better than
> 
> 	return fwnode_call(u32, DEV_PROP_U32, node, propname, val);
> 
> because it's easier to understand the call chain.

There is one concatenation like that in the code I have today, but it was
already present in the $subject series, in the of_dev_prop_read_array macro
in patch #2 (and it actually makes sense to me).

Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties? support
  2014-10-18  8:35                 ` Grant Likely
@ 2014-10-21 21:50                   ` Darren Hart
  0 siblings, 0 replies; 104+ messages in thread
From: Darren Hart @ 2014-10-21 21:50 UTC (permalink / raw)
  To: Grant Likely
  Cc: Darren Hart, Mark Rutland, David Woodhouse, Rafael J. Wysocki,
	Linux Kernel Mailing List, Greg Kroah-Hartman, Mika Westerberg,
	ACPI Devel Maling List, Aaron Lu, devicetree, Linus Walleij,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Arnd Bergmann

On Sat, Oct 18, 2014 at 10:35:49AM +0200, Grant Likely wrote:
> On Wed, 15 Oct 2014 17:43:01 +0200
> , Darren Hart <dvhart@linux.intel.com>
>  wrote:
> > 
> > 
> > On 10/15/14 17:17, Mark Rutland wrote:
> > > On Wed, Oct 15, 2014 at 03:46:39PM +0100, Darren Hart wrote:
> > 
> > >> Mark, what would you propose we do differently to enable this driver to
> > >> be firmware-type agnostic?
> > > 
> > > For this particular driver, all I'm asking for is that the
> > > "used-by-rtas" property is not moved over from of_find_property to
> > > device_get_property. It is irrelevant for all ACPI systems. Evidently my
> > > comment was unclear; I apologise for that.
> > 
> > So my objection here is that by keeping the of_* terms in the driver we
> > are required to include of, although it does safely convert to returning
> > NULL if !CONFIG_OF I suppose.
> 
> This shouldn't be that controversial. There will be things that only make
> sense for DT or only ACPI. Allowing the property to be processed when
> the other interface is being used may tempt firmware authors to use the
> property because it just happens to have a side effect that looks right
> to them.
> 
> I don't see any problem with factoring out those bits into a function
> that is only called (or built) when the associated firmware interface is
> used. In these situations, the driver isn't 100% generic, so having
> small per-firmware hooks is absolutely okay and not a burden to
> maintain.

Hrm... well, I suppose this isn't a hill I want to die on. I can disagree and
commit here :-)

-- 
Darren Hart
Intel Open Source Technology Center

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  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
  0 siblings, 1 reply; 104+ messages in thread
From: Linus Walleij @ 2014-10-28 15:26 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Arnd Bergmann, Mika Westerberg, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Fri, Oct 17, 2014 at 2:11 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:

> From: Mika Westerberg <mika.westerberg@linux.intel.com>
>
> GPIO descriptors are the preferred way over legacy GPIO numbers
> nowadays. Convert the driver to use GPIO descriptors internally but
> still allow passing legacy GPIO numbers from platform data to support
> existing platforms.
>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> Acked-by: Bryan Wu <cooloney@gmail.com>
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
(...)

>         if (led_dat->blinking) {
> -               led_dat->platform_gpio_blink_set(led_dat->gpio,
> -                                                led_dat->new_level,
> -                                                NULL, NULL);
> +               int gpio = desc_to_gpio(led_dat->gpiod);
> +               int level = led_dat->new_level;

So this desc_to_gpio() is done only to call the legacy callback below?

> +               if (gpiod_is_active_low(led_dat->gpiod))
> +                       level = !level;

And that leads to making it necessary to have this helper variable
to invert the level since that callback does not pass a descriptor
(which would inherently know if it's active low)....

> +
> +               led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);

Is it *really* impossible to change all the users of this callback?

>                 led_dat->blinking = 0;
>         } else
> -               gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
> +               gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);

(...)
>         /* Setting GPIOs with I2C/etc requires a task context, and we don't
>          * seem to have a reliable way to know if we're already in one; so
>          * let's just assume the worst.
> @@ -72,11 +73,16 @@ static void gpio_led_set(struct led_clas
>                 schedule_work(&led_dat->work);
>         } else {
>                 if (led_dat->blinking) {
> -                       led_dat->platform_gpio_blink_set(led_dat->gpio, level,
> -                                                        NULL, NULL);
> +                       int gpio = desc_to_gpio(led_dat->gpiod);
> +
> +                       if (gpiod_is_active_low(led_dat->gpiod))
> +                               level = !level;
> +
> +                       led_dat->platform_gpio_blink_set(gpio, level, NULL,
> +                                                        NULL);

Same comment.

> @@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_cla
>  {
>         struct gpio_led_data *led_dat =
>                 container_of(led_cdev, struct gpio_led_data, cdev);
> +       int gpio = desc_to_gpio(led_dat->gpiod);
>
>         led_dat->blinking = 1;
> -       return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
> +       return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
>                                                 delay_on, delay_off);

Same comment.

> @@ -97,24 +104,33 @@ static int create_gpio_led(const struct
>  {
>         int ret, state;
>
> -       led_dat->gpio = -1;
> +       if (!template->gpiod) {
> +               unsigned long flags = 0;
>
> -       /* skip leds that aren't available */
> -       if (!gpio_is_valid(template->gpio)) {
> -               dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> -                               template->gpio, template->name);
> -               return 0;
> +               /* skip leds that aren't available */
> +               if (!gpio_is_valid(template->gpio)) {
> +                       dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> +                                       template->gpio, template->name);
> +                       return 0;
> +               }
> +
> +               if (template->active_low)
> +                       flags |= GPIOF_ACTIVE_LOW;
> +
> +               ret = devm_gpio_request_one(parent, template->gpio, flags,
> +                                           template->name);
> +               if (ret < 0)
> +                       return ret;
> +
> +               led_dat->gpiod = gpio_to_desc(template->gpio);
> +               if (IS_ERR(led_dat->gpiod))
> +                       return PTR_ERR(led_dat->gpiod);
>         }

OK so this is the legacy codepath: point it out in a big fat
comment that this is the legacy codepath.

> Index: linux-pm/include/linux/leds.h
> ===================================================================
> --- linux-pm.orig/include/linux/leds.h
> +++ linux-pm/include/linux/leds.h
> @@ -251,6 +251,7 @@ struct gpio_led {
>         unsigned        retain_state_suspended : 1;
>         unsigned        default_state : 2;
>         /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
> +       struct gpio_desc *gpiod;

Put the new struct member right below the current "gpio"
member, and add comments saying that either needs to be
specified but "gpio" is deprecated for "gpiod".

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  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:34         ` Linus Walleij
  0 siblings, 2 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2014-10-28 21:56 UTC (permalink / raw)
  To: Linus Walleij, Mika Westerberg
  Cc: Linux Kernel Mailing List, Greg Kroah-Hartman, Grant Likely,
	Arnd Bergmann, ACPI Devel Maling List, Aaron Lu, devicetree,
	Alexandre Courbot, Dmitry Torokhov, Bryan Wu, Darren Hart,
	Mark Rutland

On Tuesday, October 28, 2014 04:26:25 PM Linus Walleij wrote:
> On Fri, Oct 17, 2014 at 2:11 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> 
> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> >
> > GPIO descriptors are the preferred way over legacy GPIO numbers
> > nowadays. Convert the driver to use GPIO descriptors internally but
> > still allow passing legacy GPIO numbers from platform data to support
> > existing platforms.
> >
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> > Acked-by: Bryan Wu <cooloney@gmail.com>
> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> (...)
> 
> >         if (led_dat->blinking) {
> > -               led_dat->platform_gpio_blink_set(led_dat->gpio,
> > -                                                led_dat->new_level,
> > -                                                NULL, NULL);
> > +               int gpio = desc_to_gpio(led_dat->gpiod);
> > +               int level = led_dat->new_level;
> 
> So this desc_to_gpio() is done only to call the legacy callback below?
> 
> > +               if (gpiod_is_active_low(led_dat->gpiod))
> > +                       level = !level;
> 
> And that leads to making it necessary to have this helper variable
> to invert the level since that callback does not pass a descriptor
> (which would inherently know if it's active low)....
> 
> > +
> > +               led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
> 
> Is it *really* impossible to change all the users of this callback?

You said it could be done in a followup patch.  Here:
http://marc.info/?l=linux-acpi&m=141154536921643&w=4

And Mika said he would add that to his TODO list:
http://marc.info/?l=linux-acpi&m=141155173924101&w=4

I suppose that is still valid.

> 
> >                 led_dat->blinking = 0;
> >         } else
> > -               gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
> > +               gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
> 
> (...)
> >         /* Setting GPIOs with I2C/etc requires a task context, and we don't
> >          * seem to have a reliable way to know if we're already in one; so
> >          * let's just assume the worst.
> > @@ -72,11 +73,16 @@ static void gpio_led_set(struct led_clas
> >                 schedule_work(&led_dat->work);
> >         } else {
> >                 if (led_dat->blinking) {
> > -                       led_dat->platform_gpio_blink_set(led_dat->gpio, level,
> > -                                                        NULL, NULL);
> > +                       int gpio = desc_to_gpio(led_dat->gpiod);
> > +
> > +                       if (gpiod_is_active_low(led_dat->gpiod))
> > +                               level = !level;
> > +
> > +                       led_dat->platform_gpio_blink_set(gpio, level, NULL,
> > +                                                        NULL);
> 
> Same comment.
> 
> > @@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_cla
> >  {
> >         struct gpio_led_data *led_dat =
> >                 container_of(led_cdev, struct gpio_led_data, cdev);
> > +       int gpio = desc_to_gpio(led_dat->gpiod);
> >
> >         led_dat->blinking = 1;
> > -       return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
> > +       return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
> >                                                 delay_on, delay_off);
> 
> Same comment.
> 
> > @@ -97,24 +104,33 @@ static int create_gpio_led(const struct
> >  {
> >         int ret, state;
> >
> > -       led_dat->gpio = -1;
> > +       if (!template->gpiod) {
> > +               unsigned long flags = 0;
> >
> > -       /* skip leds that aren't available */
> > -       if (!gpio_is_valid(template->gpio)) {
> > -               dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> > -                               template->gpio, template->name);
> > -               return 0;
> > +               /* skip leds that aren't available */
> > +               if (!gpio_is_valid(template->gpio)) {
> > +                       dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> > +                                       template->gpio, template->name);
> > +                       return 0;
> > +               }
> > +
> > +               if (template->active_low)
> > +                       flags |= GPIOF_ACTIVE_LOW;
> > +
> > +               ret = devm_gpio_request_one(parent, template->gpio, flags,
> > +                                           template->name);
> > +               if (ret < 0)
> > +                       return ret;
> > +
> > +               led_dat->gpiod = gpio_to_desc(template->gpio);
> > +               if (IS_ERR(led_dat->gpiod))
> > +                       return PTR_ERR(led_dat->gpiod);
> >         }
> 
> OK so this is the legacy codepath: point it out in a big fat
> comment that this is the legacy codepath.

That looks like it could be done in a followup patch too.

Since the series is in my linux-next branch at this point, I really wouldn't
like to reshuffle commits in it if that can be avoided.

> > Index: linux-pm/include/linux/leds.h
> > ===================================================================
> > --- linux-pm.orig/include/linux/leds.h
> > +++ linux-pm/include/linux/leds.h
> > @@ -251,6 +251,7 @@ struct gpio_led {
> >         unsigned        retain_state_suspended : 1;
> >         unsigned        default_state : 2;
> >         /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
> > +       struct gpio_desc *gpiod;
> 
> Put the new struct member right below the current "gpio"
> member,

It was done like that in previous versions, but turned out to cause problems
to happen in testing.  Unfortunately, I don't seem to be able to find a pointer
to the original report ATM, but perhaps Mika can.  Mika?

> and add comments saying that either needs to be
> specified but "gpio" is deprecated for "gpiod".

Kind regards,
Rafael


^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  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 15:34         ` Linus Walleij
  1 sibling, 1 reply; 104+ messages in thread
From: Mika Westerberg @ 2014-10-29  8:53 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Linus Walleij, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Tue, Oct 28, 2014 at 10:56:09PM +0100, Rafael J. Wysocki wrote:
> On Tuesday, October 28, 2014 04:26:25 PM Linus Walleij wrote:
> > On Fri, Oct 17, 2014 at 2:11 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> > 
> > > From: Mika Westerberg <mika.westerberg@linux.intel.com>
> > >
> > > GPIO descriptors are the preferred way over legacy GPIO numbers
> > > nowadays. Convert the driver to use GPIO descriptors internally but
> > > still allow passing legacy GPIO numbers from platform data to support
> > > existing platforms.
> > >
> > > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
> > > Acked-by: Bryan Wu <cooloney@gmail.com>
> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> > (...)
> > 
> > >         if (led_dat->blinking) {
> > > -               led_dat->platform_gpio_blink_set(led_dat->gpio,
> > > -                                                led_dat->new_level,
> > > -                                                NULL, NULL);
> > > +               int gpio = desc_to_gpio(led_dat->gpiod);
> > > +               int level = led_dat->new_level;
> > 
> > So this desc_to_gpio() is done only to call the legacy callback below?
> > 
> > > +               if (gpiod_is_active_low(led_dat->gpiod))
> > > +                       level = !level;
> > 
> > And that leads to making it necessary to have this helper variable
> > to invert the level since that callback does not pass a descriptor
> > (which would inherently know if it's active low)....
> > 
> > > +
> > > +               led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
> > 
> > Is it *really* impossible to change all the users of this callback?
> 
> You said it could be done in a followup patch.  Here:
> http://marc.info/?l=linux-acpi&m=141154536921643&w=4
> 
> And Mika said he would add that to his TODO list:
> http://marc.info/?l=linux-acpi&m=141155173924101&w=4
> 
> I suppose that is still valid.

Yes, I'll just let dust to settle before sending out a patch that
converts the existing users of platform_gpio_blink_set() callback to
gpio descriptors.

> 
> > 
> > >                 led_dat->blinking = 0;
> > >         } else
> > > -               gpio_set_value_cansleep(led_dat->gpio, led_dat->new_level);
> > > +               gpiod_set_value_cansleep(led_dat->gpiod, led_dat->new_level);
> > 
> > (...)
> > >         /* Setting GPIOs with I2C/etc requires a task context, and we don't
> > >          * seem to have a reliable way to know if we're already in one; so
> > >          * let's just assume the worst.
> > > @@ -72,11 +73,16 @@ static void gpio_led_set(struct led_clas
> > >                 schedule_work(&led_dat->work);
> > >         } else {
> > >                 if (led_dat->blinking) {
> > > -                       led_dat->platform_gpio_blink_set(led_dat->gpio, level,
> > > -                                                        NULL, NULL);
> > > +                       int gpio = desc_to_gpio(led_dat->gpiod);
> > > +
> > > +                       if (gpiod_is_active_low(led_dat->gpiod))
> > > +                               level = !level;
> > > +
> > > +                       led_dat->platform_gpio_blink_set(gpio, level, NULL,
> > > +                                                        NULL);
> > 
> > Same comment.
> > 
> > > @@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_cla
> > >  {
> > >         struct gpio_led_data *led_dat =
> > >                 container_of(led_cdev, struct gpio_led_data, cdev);
> > > +       int gpio = desc_to_gpio(led_dat->gpiod);
> > >
> > >         led_dat->blinking = 1;
> > > -       return led_dat->platform_gpio_blink_set(led_dat->gpio, GPIO_LED_BLINK,
> > > +       return led_dat->platform_gpio_blink_set(gpio, GPIO_LED_BLINK,
> > >                                                 delay_on, delay_off);
> > 
> > Same comment.
> > 
> > > @@ -97,24 +104,33 @@ static int create_gpio_led(const struct
> > >  {
> > >         int ret, state;
> > >
> > > -       led_dat->gpio = -1;
> > > +       if (!template->gpiod) {
> > > +               unsigned long flags = 0;
> > >
> > > -       /* skip leds that aren't available */
> > > -       if (!gpio_is_valid(template->gpio)) {
> > > -               dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> > > -                               template->gpio, template->name);
> > > -               return 0;
> > > +               /* skip leds that aren't available */
> > > +               if (!gpio_is_valid(template->gpio)) {
> > > +                       dev_info(parent, "Skipping unavailable LED gpio %d (%s)\n",
> > > +                                       template->gpio, template->name);
> > > +                       return 0;
> > > +               }
> > > +
> > > +               if (template->active_low)
> > > +                       flags |= GPIOF_ACTIVE_LOW;
> > > +
> > > +               ret = devm_gpio_request_one(parent, template->gpio, flags,
> > > +                                           template->name);
> > > +               if (ret < 0)
> > > +                       return ret;
> > > +
> > > +               led_dat->gpiod = gpio_to_desc(template->gpio);
> > > +               if (IS_ERR(led_dat->gpiod))
> > > +                       return PTR_ERR(led_dat->gpiod);
> > >         }
> > 
> > OK so this is the legacy codepath: point it out in a big fat
> > comment that this is the legacy codepath.
> 
> That looks like it could be done in a followup patch too.
> 
> Since the series is in my linux-next branch at this point, I really wouldn't
> like to reshuffle commits in it if that can be avoided.
> 
> > > Index: linux-pm/include/linux/leds.h
> > > ===================================================================
> > > --- linux-pm.orig/include/linux/leds.h
> > > +++ linux-pm/include/linux/leds.h
> > > @@ -251,6 +251,7 @@ struct gpio_led {
> > >         unsigned        retain_state_suspended : 1;
> > >         unsigned        default_state : 2;
> > >         /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
> > > +       struct gpio_desc *gpiod;
> > 
> > Put the new struct member right below the current "gpio"
> > member,
> 
> It was done like that in previous versions, but turned out to cause problems
> to happen in testing.  Unfortunately, I don't seem to be able to find a pointer
> to the original report ATM, but perhaps Mika can.  Mika?

It is burried inside this thread:

http://www.spinics.net/lists/arm-kernel/msg369522.html

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-28 21:56       ` Rafael J. Wysocki
  2014-10-29  8:53         ` Mika Westerberg
@ 2014-10-30 15:34         ` Linus Walleij
  1 sibling, 0 replies; 104+ messages in thread
From: Linus Walleij @ 2014-10-30 15:34 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Mika Westerberg, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Tue, Oct 28, 2014 at 10:56 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Tuesday, October 28, 2014 04:26:25 PM Linus Walleij wrote:
>> On Fri, Oct 17, 2014 at 2:11 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>>
>> > From: Mika Westerberg <mika.westerberg@linux.intel.com>
>> >
>> > GPIO descriptors are the preferred way over legacy GPIO numbers
>> > nowadays. Convert the driver to use GPIO descriptors internally but
>> > still allow passing legacy GPIO numbers from platform data to support
>> > existing platforms.
>> >
>> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
>> > Acked-by: Bryan Wu <cooloney@gmail.com>
>> > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> (...)
>>
>> >         if (led_dat->blinking) {
>> > -               led_dat->platform_gpio_blink_set(led_dat->gpio,
>> > -                                                led_dat->new_level,
>> > -                                                NULL, NULL);
>> > +               int gpio = desc_to_gpio(led_dat->gpiod);
>> > +               int level = led_dat->new_level;
>>
>> So this desc_to_gpio() is done only to call the legacy callback below?
>>
>> > +               if (gpiod_is_active_low(led_dat->gpiod))
>> > +                       level = !level;
>>
>> And that leads to making it necessary to have this helper variable
>> to invert the level since that callback does not pass a descriptor
>> (which would inherently know if it's active low)....
>>
>> > +
>> > +               led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
>>
>> Is it *really* impossible to change all the users of this callback?
>
> You said it could be done in a followup patch.  Here:
> http://marc.info/?l=linux-acpi&m=141154536921643&w=4
>
> And Mika said he would add that to his TODO list:
> http://marc.info/?l=linux-acpi&m=141155173924101&w=4
>
> I suppose that is still valid.

Yes, I *can* be done as follow up, and I still *prefer* that it
be fixed now.

Otherwise I wouldn't keep commenting on it.

>> > +               led_dat->gpiod = gpio_to_desc(template->gpio);
>> > +               if (IS_ERR(led_dat->gpiod))
>> > +                       return PTR_ERR(led_dat->gpiod);
>> >         }
>>
>> OK so this is the legacy codepath: point it out in a big fat
>> comment that this is the legacy codepath.
>
> That looks like it could be done in a followup patch too.

That's not so much work that it can't be done now.

The follow-up patch I mean.

> Since the series is in my linux-next branch at this point, I really wouldn't
> like to reshuffle commits in it if that can be avoided.

That's OK if we just get the follow-up stuff now (the comment patch
immediately!), not in 18 months.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-29  8:53         ` Mika Westerberg
@ 2014-10-30 15:40           ` Linus Walleij
  2014-10-30 16:15             ` Mika Westerberg
  0 siblings, 1 reply; 104+ messages in thread
From: Linus Walleij @ 2014-10-30 15:40 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Wed, Oct 29, 2014 at 9:53 AM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Tue, Oct 28, 2014 at 10:56:09PM +0100, Rafael J. Wysocki wrote:
>> On Tuesday, October 28, 2014 04:26:25 PM Linus Walleij wrote:
>> > On Fri, Oct 17, 2014 at 2:11 PM, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
>> > > From: Mika Westerberg <mika.westerberg@linux.intel.com>
>> > >
>> > > GPIO descriptors are the preferred way over legacy GPIO numbers
>> > > nowadays. Convert the driver to use GPIO descriptors internally but
>> > > still allow passing legacy GPIO numbers from platform data to support
>> > > existing platforms.
>> > >
>> > > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> > > Acked-by: Alexandre Courbot <acourbot@nvidia.com>
>> > > Acked-by: Bryan Wu <cooloney@gmail.com>
>> > > Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> > (...)
>> >
>> > >         if (led_dat->blinking) {
>> > > -               led_dat->platform_gpio_blink_set(led_dat->gpio,
>> > > -                                                led_dat->new_level,
>> > > -                                                NULL, NULL);
>> > > +               int gpio = desc_to_gpio(led_dat->gpiod);
>> > > +               int level = led_dat->new_level;
>> >
>> > So this desc_to_gpio() is done only to call the legacy callback below?
>> >
>> > > +               if (gpiod_is_active_low(led_dat->gpiod))
>> > > +                       level = !level;
>> >
>> > And that leads to making it necessary to have this helper variable
>> > to invert the level since that callback does not pass a descriptor
>> > (which would inherently know if it's active low)....
>> >
>> > > +
>> > > +               led_dat->platform_gpio_blink_set(gpio, level, NULL, NULL);
>> >
>> > Is it *really* impossible to change all the users of this callback?
>>
>> You said it could be done in a followup patch.  Here:
>> http://marc.info/?l=linux-acpi&m=141154536921643&w=4
>>
>> And Mika said he would add that to his TODO list:
>> http://marc.info/?l=linux-acpi&m=141155173924101&w=4
>>
>> I suppose that is still valid.
>
> Yes, I'll just let dust to settle before sending out a patch that
> converts the existing users of platform_gpio_blink_set() callback to
> gpio descriptors.

Dust settle = 2 weeks, 18 months, 5 years?

Sorry for nagging but I've been *SO* burnt by people in the past
saying they will "fix things later real soon" and then never get around
to it.

But I guess I'm gonna trust you anyway.

>> > > Index: linux-pm/include/linux/leds.h
>> > > ===================================================================
>> > > --- linux-pm.orig/include/linux/leds.h
>> > > +++ linux-pm/include/linux/leds.h
>> > > @@ -251,6 +251,7 @@ struct gpio_led {
>> > >         unsigned        retain_state_suspended : 1;
>> > >         unsigned        default_state : 2;
>> > >         /* default_state should be one of LEDS_GPIO_DEFSTATE_(ON|OFF|KEEP) */
>> > > +       struct gpio_desc *gpiod;
>> >
>> > Put the new struct member right below the current "gpio"
>> > member,
>>
>> It was done like that in previous versions, but turned out to cause problems
>> to happen in testing.  Unfortunately, I don't seem to be able to find a pointer
>> to the original report ATM, but perhaps Mika can.  Mika?
>
> It is burried inside this thread:
>
> http://www.spinics.net/lists/arm-kernel/msg369522.html

OK people not using C99 initalizers, sigh.

I hope Arnd's complimentary patch gets applied too so we
can move the member back where it should be, kernel structs
as ABI isn't really any fun.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-30 15:40           ` Linus Walleij
@ 2014-10-30 16:15             ` Mika Westerberg
  2014-10-31  9:41               ` Linus Walleij
  0 siblings, 1 reply; 104+ messages in thread
From: Mika Westerberg @ 2014-10-30 16:15 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Thu, Oct 30, 2014 at 04:40:05PM +0100, Linus Walleij wrote:
> > Yes, I'll just let dust to settle before sending out a patch that
> > converts the existing users of platform_gpio_blink_set() callback to
> > gpio descriptors.
> 
> Dust settle = 2 weeks, 18 months, 5 years?

I started to do the conversion already but then noticed that it is not
that trivial after all.

For example we have one user in arch/arm/mach-orion5x/dns323-setup.c:

static struct gpio_led_platform_data dns323ab_led_data = {
	.num_leds       = ARRAY_SIZE(dns323ab_leds),
	.leds           = dns323ab_leds,
	.gpio_blink_set = orion_gpio_led_blink_set,
};

orion_gpio_led_blink_set() is part of orion specific custom GPIO
"driver" defined in arch/arm/plat-orion/gpio.c and as far as I can tell
cannot use GPIO descriptors as it directly programs these numbers to the
hardware.

We can convert the descriptor to a number in the beginning of
orion_gpio_led_blink_set() if that helps.

Other two users: rx1950_led_blink_set() and h1940_led_blink_set() seem
to have similar needs for the numeric value.

> Sorry for nagging but I've been *SO* burnt by people in the past
> saying they will "fix things later real soon" and then never get around
> to it.

Understood.

> But I guess I'm gonna trust you anyway.

Thanks :)

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-30 16:15             ` Mika Westerberg
@ 2014-10-31  9:41               ` Linus Walleij
  2014-10-31  9:55                 ` Mika Westerberg
  0 siblings, 1 reply; 104+ messages in thread
From: Linus Walleij @ 2014-10-31  9:41 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Thu, Oct 30, 2014 at 5:15 PM, Mika Westerberg
<mika.westerberg@linux.intel.com> wrote:
> On Thu, Oct 30, 2014 at 04:40:05PM +0100, Linus Walleij wrote:
>> > Yes, I'll just let dust to settle before sending out a patch that
>> > converts the existing users of platform_gpio_blink_set() callback to
>> > gpio descriptors.
>>
>> Dust settle = 2 weeks, 18 months, 5 years?
>
> I started to do the conversion already but then noticed that it is not
> that trivial after all.

Thanks for looking into this.

> For example we have one user in arch/arm/mach-orion5x/dns323-setup.c:
>
> static struct gpio_led_platform_data dns323ab_led_data = {
>         .num_leds       = ARRAY_SIZE(dns323ab_leds),
>         .leds           = dns323ab_leds,
>         .gpio_blink_set = orion_gpio_led_blink_set,
> };
>
> orion_gpio_led_blink_set() is part of orion specific custom GPIO
> "driver" defined in arch/arm/plat-orion/gpio.c and as far as I can tell
> cannot use GPIO descriptors as it directly programs these numbers to the
> hardware.
>
> We can convert the descriptor to a number in the beginning of
> orion_gpio_led_blink_set() if that helps.
>
> Other two users: rx1950_led_blink_set() and h1940_led_blink_set() seem
> to have similar needs for the numeric value.

Doing the conversion from descriptor to gpio number in the
platforms is *much desired*, because it is a nice divide-and-conquer
approach.

For example mach-orion is going to be deleted and replaced
with mach-mvebu at some time, so then part of the problem
goes away entirely.

Yours,
Linus Walleij

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v5 07/12] leds: leds-gpio: Add support for GPIO descriptors
  2014-10-31  9:41               ` Linus Walleij
@ 2014-10-31  9:55                 ` Mika Westerberg
  0 siblings, 0 replies; 104+ messages in thread
From: Mika Westerberg @ 2014-10-31  9:55 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Grant Likely, Arnd Bergmann, ACPI Devel Maling List, Aaron Lu,
	devicetree, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	Darren Hart, Mark Rutland

On Fri, Oct 31, 2014 at 10:41:38AM +0100, Linus Walleij wrote:
> On Thu, Oct 30, 2014 at 5:15 PM, Mika Westerberg
> <mika.westerberg@linux.intel.com> wrote:
> > On Thu, Oct 30, 2014 at 04:40:05PM +0100, Linus Walleij wrote:
> >> > Yes, I'll just let dust to settle before sending out a patch that
> >> > converts the existing users of platform_gpio_blink_set() callback to
> >> > gpio descriptors.
> >>
> >> Dust settle = 2 weeks, 18 months, 5 years?
> >
> > I started to do the conversion already but then noticed that it is not
> > that trivial after all.
> 
> Thanks for looking into this.
> 
> > For example we have one user in arch/arm/mach-orion5x/dns323-setup.c:
> >
> > static struct gpio_led_platform_data dns323ab_led_data = {
> >         .num_leds       = ARRAY_SIZE(dns323ab_leds),
> >         .leds           = dns323ab_leds,
> >         .gpio_blink_set = orion_gpio_led_blink_set,
> > };
> >
> > orion_gpio_led_blink_set() is part of orion specific custom GPIO
> > "driver" defined in arch/arm/plat-orion/gpio.c and as far as I can tell
> > cannot use GPIO descriptors as it directly programs these numbers to the
> > hardware.
> >
> > We can convert the descriptor to a number in the beginning of
> > orion_gpio_led_blink_set() if that helps.
> >
> > Other two users: rx1950_led_blink_set() and h1940_led_blink_set() seem
> > to have similar needs for the numeric value.
> 
> Doing the conversion from descriptor to gpio number in the
> platforms is *much desired*, because it is a nice divide-and-conquer
> approach.
> 
> For example mach-orion is going to be deleted and replaced
> with mach-mvebu at some time, so then part of the problem
> goes away entirely.

OK, thanks. I'll do the GPIO descriptor -> number conversions in the
platform code then.

^ permalink raw reply	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  2014-10-15 13:15   ` Mark Rutland
  2014-10-15 13:28     ` David Woodhouse
@ 2015-01-14 18:42     ` David Woodhouse
  2015-01-15  9:12       ` Rafael J. Wysocki
  1 sibling, 1 reply; 104+ messages in thread
From: David Woodhouse @ 2015-01-14 18:42 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Rafael J. Wysocki, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, Darren Hart


[-- Attachment #1.1: Type: text/plain, Size: 1803 bytes --]

I'm looking again at updating of_serial to work with ACPI properties. 

Specifically, I want to support a serial port with a non-standard baud
rate, something like this:

    Device(COM1) {
        Name(_HID, EisaId("PNP0501"))
        Name(_CID, EisaId("PRP0001"))
	Name(_DSD, Package() {
	    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
            Package () {
		Package () {"compatible", Package () {"ns16550a"}},
		Package () {"clock-frequency", 2457600},
	    }
	})
        ...
    }

Firstly, the of_serial driver doesn't even get *invoked* unless I do
this:

diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 0d08373..eb1201a 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -2083,6 +2086,8 @@ static int acpi_add_single_object(struct acpi_device **child,
 	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n",
 		dev_name(&device->dev), (char *) buffer.pointer,
 		device->parent ? dev_name(&device->parent->dev) : "(null)"));
+	if (device->data.of_compatible)
+		acpi_create_platform_device(device);
 	kfree(buffer.pointer);
 	*child = device;
 	return 0;

Now it doesn't work because it uses of_match_device() to look the device
up and find the corresponding *data* for that entry in its match table.
And without CONFIG_OF, I don't *have* of_match_device().

We've talked about the fact that the platform bus probe function doesn't
pass you the match ID. Is that something we could potentially fix now
that things are a little more unified?

Or do we expect drivers still to have to use something like
of_match_id() to do the lookup again for themselves... and in that case
should we make of_match_id() available or produce a new
device_match_id() that they are expected to switch to?

-- 
dwmw2


[-- Attachment #1.2: of-serial-dev-properties.patch --]
[-- Type: text/x-patch, Size: 7650 bytes --]

diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig
index c79b43c..65cf850 100644
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1114,14 +1114,14 @@ config SERIAL_NETX_CONSOLE
 	  you can make it the console by answering Y to this option.
 
 config SERIAL_OF_PLATFORM
-	tristate "Serial port on Open Firmware platform bus"
-	depends on OF
+	tristate "Serial port on firmware platform bus"
+	depends on OF || ACPI
 	depends on SERIAL_8250 || SERIAL_OF_PLATFORM_NWPSERIAL
 	help
-	  If you have a PowerPC based system that has serial ports
-	  on a platform specific bus, you should enable this option.
-	  Currently, only 8250 compatible ports are supported, but
-	  others can easily be added.
+	  If you have a system which advertises its serial ports through
+	  devicetree or ACPI, you should enable this option. Currently
+	  only 8250 compatible and NWP ports and are supported, but others
+	  can easily be added.
 
 config SERIAL_OMAP
 	tristate "OMAP serial port support"
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 64f1bab..54110e6 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -15,8 +15,7 @@
 #include <linux/delay.h>
 #include <linux/serial_core.h>
 #include <linux/serial_reg.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
+#include <linux/property.h>
 #include <linux/of_platform.h>
 #include <linux/nwpserial.h>
 #include <linux/clk.h>
@@ -54,22 +53,22 @@ static inline void tegra_serial_handle_break(struct uart_port *port)
 /*
  * Fill a struct uart_port for a given device node
  */
-static int of_platform_serial_setup(struct platform_device *ofdev,
+static int of_platform_serial_setup(struct platform_device *pdev,
 			int type, struct uart_port *port,
 			struct of_serial_info *info)
 {
-	struct resource resource;
-	struct device_node *np = ofdev->dev.of_node;
 	u32 clk, spd, prop;
-	int ret;
+	int iotype = -1;
+	u32 res_start;
+	int ret, i;
 
 	memset(port, 0, sizeof *port);
-	if (of_property_read_u32(np, "clock-frequency", &clk)) {
+	if (device_property_read_u32(&pdev->dev, "clock-frequency", &clk)) {
 
 		/* Get clk rate through clk driver if present */
-		info->clk = clk_get(&ofdev->dev, NULL);
+		info->clk = clk_get(&pdev->dev, NULL);
 		if (IS_ERR(info->clk)) {
-			dev_warn(&ofdev->dev,
+			dev_warn(&pdev->dev,
 				"clk or clock-frequency not defined\n");
 			return PTR_ERR(info->clk);
 		}
@@ -78,57 +77,63 @@ static int of_platform_serial_setup(struct platform_device *ofdev,
 		clk = clk_get_rate(info->clk);
 	}
 	/* If current-speed was set, then try not to change it. */
-	if (of_property_read_u32(np, "current-speed", &spd) == 0)
+	if (device_property_read_u32(&pdev->dev, "current-speed", &spd) == 0)
 		port->custom_divisor = clk / (16 * spd);
 
-	ret = of_address_to_resource(np, 0, &resource);
-	if (ret) {
-		dev_warn(&ofdev->dev, "invalid address\n");
+	/* Check for shifted address mapping */
+	if (device_property_read_u32(&pdev->dev, "reg-offset", &prop) != 0)
+		prop = 0;
+
+	for (i = 0; iotype == -1 && i < pdev->num_resources; i++) {
+		struct resource *resource = &pdev->resource[i];
+		if (resource_type(resource) == IORESOURCE_MEM) {
+			iotype = UPIO_MEM;
+			port->mapbase = res_start + prop;
+		} else if (resource_type(resource) == IORESOURCE_IO) {
+			iotype = UPIO_PORT;
+			port->iobase = res_start + prop;
+		}
+
+		res_start = resource->start;
+	}
+	if (iotype == -1) {
+		dev_warn(&pdev->dev, "invalid address\n");
 		goto out;
 	}
 
 	spin_lock_init(&port->lock);
-	port->mapbase = resource.start;
-
-	/* Check for shifted address mapping */
-	if (of_property_read_u32(np, "reg-offset", &prop) == 0)
-		port->mapbase += prop;
 
 	/* Check for registers offset within the devices address range */
-	if (of_property_read_u32(np, "reg-shift", &prop) == 0)
+	if (device_property_read_u32(&pdev->dev, "reg-shift", &prop) == 0)
 		port->regshift = prop;
 
 	/* Check for fifo size */
-	if (of_property_read_u32(np, "fifo-size", &prop) == 0)
+	if (device_property_read_u32(&pdev->dev, "fifo-size", &prop) == 0)
 		port->fifosize = prop;
 
-	port->irq = irq_of_parse_and_map(np, 0);
-	port->iotype = UPIO_MEM;
-	if (of_property_read_u32(np, "reg-io-width", &prop) == 0) {
-		switch (prop) {
-		case 1:
-			port->iotype = UPIO_MEM;
-			break;
-		case 4:
-			port->iotype = UPIO_MEM32;
-			break;
-		default:
-			dev_warn(&ofdev->dev, "unsupported reg-io-width (%d)\n",
+	port->irq = platform_get_irq(pdev, 0);
+
+	if (device_property_read_u32(&pdev->dev, "reg-io-width", &prop) == 0) {
+		if (prop == 4 && iotype == UPIO_MEM) {
+			iotype = UPIO_MEM32;
+		} else {
+			dev_warn(&pdev->dev, "unsupported reg-io-width (%d)\n",
 				 prop);
 			ret = -EINVAL;
 			goto out;
 		}
 	}
 
+	port->iotype = iotype;
 	port->type = type;
 	port->uartclk = clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
 		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 
-	if (of_find_property(np, "no-loopback-test", NULL))
+	if (device_property_present(&pdev->dev, "no-loopback-test"))
 		port->flags |= UPF_SKIP_TEST;
 
-	port->dev = &ofdev->dev;
+	port->dev = &pdev->dev;
 
 	switch (type) {
 	case PORT_TEGRA:
@@ -151,19 +156,19 @@ out:
  * Try to register a serial port
  */
 static struct of_device_id of_platform_serial_table[];
-static int of_platform_serial_probe(struct platform_device *ofdev)
+static int of_platform_serial_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *match;
 	struct of_serial_info *info;
 	struct uart_port port;
 	int port_type;
 	int ret;
-
-	match = of_match_device(of_platform_serial_table, &ofdev->dev);
+	printk("%s\n", __func__);
+	match = of_match_device(of_platform_serial_table, &pdev->dev);
 	if (!match)
 		return -EINVAL;
 
-	if (of_find_property(ofdev->dev.of_node, "used-by-rtas", NULL))
+	if (device_property_present(&pdev->dev, "used-by-rtas"))
 		return -EBUSY;
 
 	info = kzalloc(sizeof(*info), GFP_KERNEL);
@@ -171,7 +176,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		return -ENOMEM;
 
 	port_type = (unsigned long)match->data;
-	ret = of_platform_serial_setup(ofdev, port_type, &port, info);
+	ret = of_platform_serial_setup(pdev, port_type, &port, info);
 	if (ret)
 		goto out;
 
@@ -187,8 +192,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 		if (port.fifosize)
 			port8250.capabilities = UART_CAP_FIFO;
 
-		if (of_property_read_bool(ofdev->dev.of_node,
-					  "auto-flow-control"))
+		if (device_property_present(&pdev->dev, "auto-flow-control"))
 			port8250.capabilities |= UART_CAP_AFE;
 
 		ret = serial8250_register_8250_port(&port8250);
@@ -203,7 +207,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 	default:
 		/* need to add code for these */
 	case PORT_UNKNOWN:
-		dev_info(&ofdev->dev, "Unknown serial port found, ignored\n");
+		dev_info(&pdev->dev, "Unknown serial port found, ignored\n");
 		ret = -ENODEV;
 		break;
 	}
@@ -212,20 +216,19 @@ static int of_platform_serial_probe(struct platform_device *ofdev)
 
 	info->type = port_type;
 	info->line = ret;
-	platform_set_drvdata(ofdev, info);
+	platform_set_drvdata(pdev, info);
 	return 0;
 out:
 	kfree(info);
-	irq_dispose_mapping(port.irq);
 	return ret;
 }
 
 /*
  * Release a line
  */
-static int of_platform_serial_remove(struct platform_device *ofdev)
+static int of_platform_serial_remove(struct platform_device *pdev)
 {
-	struct of_serial_info *info = platform_get_drvdata(ofdev);
+	struct of_serial_info *info = platform_get_drvdata(pdev);
 	switch (info->type) {
 #ifdef CONFIG_SERIAL_8250
 	case PORT_8250 ... PORT_MAX_8250:

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 5745 bytes --]

^ permalink raw reply related	[flat|nested] 104+ messages in thread

* Re: [PATCH v4 00/13] Add ACPI _DSD and unified device properties support
  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
  0 siblings, 0 replies; 104+ messages in thread
From: Rafael J. Wysocki @ 2015-01-15  9:12 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Mark Rutland, Linux Kernel Mailing List, Greg Kroah-Hartman,
	Mika Westerberg, ACPI Devel Maling List, Aaron Lu, devicetree,
	Linus Walleij, Alexandre Courbot, Dmitry Torokhov, Bryan Wu,
	grant.likely, Arnd Bergmann, Darren Hart

On Wednesday, January 14, 2015 10:42:23 AM David Woodhouse wrote:
> 
> --=-3dIl43yXcWwu/nzOqQWw
> Content-Type: multipart/mixed; boundary="=-ca0AFM5hvqL+pJIndiHh"
> 
> 
> --=-ca0AFM5hvqL+pJIndiHh
> Content-Type: text/plain; charset="UTF-8"
> Content-Transfer-Encoding: quoted-printable
> 
> I'm looking again at updating of_serial to work with ACPI properties.=20
> 
> Specifically, I want to support a serial port with a non-standard baud
> rate, something like this:
> 
>     Device(COM1) {
>         Name(_HID, EisaId("PNP0501"))
>         Name(_CID, EisaId("PRP0001"))
> 	Name(_DSD, Package() {
> 	    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
>             Package () {
> 		Package () {"compatible", Package () {"ns16550a"}},
> 		Package () {"clock-frequency", 2457600},
> 	    }
> 	})
>         ...
>     }
> 
> Firstly, the of_serial driver doesn't even get *invoked* unless I do
> this:
> 
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 0d08373..eb1201a 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -2083,6 +2086,8 @@ static int acpi_add_single_object(struct acpi_device =
> **child,
>  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Added %s [%s] parent %s\n",
>  		dev_name(&device->dev), (char *) buffer.pointer,
>  		device->parent ? dev_name(&device->parent->dev) : "(null)"));
> +	if (device->data.of_compatible)
> +		acpi_create_platform_device(device);
>  	kfree(buffer.pointer);
>  	*child =3D device;
>  	return 0;
> 
> Now it doesn't work because it uses of_match_device() to look the device
> up and find the corresponding *data* for that entry in its match table.
> And without CONFIG_OF, I don't *have* of_match_device().
> 
> We've talked about the fact that the platform bus probe function doesn't
> pass you the match ID. Is that something we could potentially fix now
> that things are a little more unified?

We can do that in my view.

> Or do we expect drivers still to have to use something like
> of_match_id() to do the lookup again for themselves... and in that case
> should we make of_match_id() available or produce a new
> device_match_id() that they are expected to switch to?

So far we've been targeting drivers that already have of_match_id() rather
than ones that want to use the unified interface from the start and not
necessarily with CONFIG_OF set.  That looks like an overlooked use case to me
to be honest.

-- 
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.

^ permalink raw reply	[flat|nested] 104+ messages in thread

end of thread, other threads:[~2015-01-15  8:50 UTC | newest]

Thread overview: 104+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH 10/13] Driver core: Child node properties for devices Rafael J. Wysocki
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).