All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support
@ 2014-08-17  6:04 Mika Westerberg
  2014-08-17  6:04 ` [RFC PATCH 1/9] ACPI: Add support for device specific properties Mika Westerberg
                   ` (6 more replies)
  0 siblings, 7 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

[ Resending with fewer people in CC list. For some reason the series never
  reached attented mailing lists. ]

The recent publication of the ACPI 5.1 specification [1] adds a reserved name
for Device Specific Data (_DSD, Section 6.2.5). This mechanism allows for
passing arbitrary hardware description data to the OS. The exact format of the
_DSD data is specific to the UUID paired with it [2].   

An ACPI Device Properties UUID has been defined [3] to provide a format
compatible with existing device tree schemas. The purpose for this was to allow
for the reuse of the existing schemas and encourage the development of firmware
agnostic device drivers.

This series accomplishes the following (as well as some other dependencies):

 * Add _DSD support to the ACPI core
   This simply reads the UUID and the accompanying Package

 * Add ACPI Device Properties _DSD format support
   This understands the hierarchical key:value pair structure
   defined by the Device Properties UUID

 * Add a unified device properties API with ACPI and OF backends
   This provides for the firmware agnostic device properties
   Interface to be used by drivers

 * Provides 2 example drivers that were previously Device Tree aware that
   can now be used with either Device Tree or ACPI Device Properties. The
   both drivers use an arbitrary _HID.

This has been tested on Minnowboard with relevant parts of the modified
DSDT at the end of this email.

This series does not provide for a means to append to a system DSDT. That
will ultimately be required to make the most effective use of the _DSD
mechanism. Work is underway on that as a separate effort.

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

Aaron Lu (3):
  of: Add property_ops callback for devices with of_node
  gpiolib: add API to get gpio desc and flags
  Input: gpio_keys_polled - Make use of device property API

Max Eliaser (1):
  leds: leds-gpio: Make use of device property API

Mika Westerberg (4):
  ACPI: Add support for device specific properties
  ACPI: Document ACPI device specific properties
  mfd: Add ACPI support
  gpio: sch: Consolidate core and resume banks

Rafael J. Wysocki (1):
  Driver core: Unified device properties interface for platform firmware

 Documentation/acpi/enumeration.txt        |  27 ++
 Documentation/acpi/properties.txt         | 359 ++++++++++++++++++++
 drivers/acpi/Makefile                     |   1 +
 drivers/acpi/glue.c                       |   4 +-
 drivers/acpi/internal.h                   |   6 +
 drivers/acpi/property.c                   | 542 ++++++++++++++++++++++++++++++
 drivers/acpi/scan.c                       |  14 +-
 drivers/base/Makefile                     |   2 +-
 drivers/base/property.c                   |  48 +++
 drivers/gpio/gpio-sch.c                   | 303 ++++++-----------
 drivers/gpio/gpiolib-acpi.c               |  81 +++--
 drivers/gpio/gpiolib.c                    |  18 +
 drivers/gpio/gpiolib.h                    |   8 +
 drivers/input/keyboard/gpio_keys_polled.c | 139 +++++---
 drivers/leds/leds-gpio.c                  | 130 ++++---
 drivers/mfd/mfd-core.c                    |  41 +++
 drivers/of/base.c                         | 194 ++++++++++-
 drivers/of/platform.c                     |   4 +-
 include/acpi/acpi_bus.h                   |   8 +
 include/linux/acpi.h                      |  40 +++
 include/linux/device.h                    |   3 +
 include/linux/gpio/consumer.h             |  11 +
 include/linux/mfd/core.h                  |   3 +
 include/linux/property.h                  |  54 +++
 24 files changed, 1716 insertions(+), 324 deletions(-)
 create mode 100644 Documentation/acpi/properties.txt
 create mode 100644 drivers/acpi/property.c
 create mode 100644 drivers/base/property.c
 create mode 100644 include/linux/property.h

------ DSDT For Minnowboard ------

    Scope (\_SB.PCI0.LPC)
    {
        Device (LEDS)
        {
            Name (_HID, "MNW0001")

            Name (_CRS, ResourceTemplate ()
            {
                GpioIo (Exclusive, PullDown, 0, 0, IoRestrictionOutputOnly,
                        "\\_SB.PCI0.LPC", 0, ResourceConsumer) {10}
                GpioIo (Exclusive, PullDown, 0, 0, IoRestrictionOutputOnly,
                        "\\_SB.PCI0.LPC", 0, ResourceConsumer) {11}
            })

            Device (LEDH)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"label", "Heartbeat"},
                        Package () {"gpios", Package () {^^LEDS, 0, 0, 0}},
                        Package () {"linux,default-trigger", "heartbeat"},
                        Package () {"linux,default-state", "off"},
                        Package () {"linux,retain-state-suspended", 1},
                    }
                })
            }

            Device (LEDM)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"label", "MMC0 Activity"},
                        Package () {"gpios", Package () {^^LEDS, 1, 0, 0}},
                        Package () {"linux,default-trigger", "mmc0"},
                        Package () {"linux,default-state", "on"},
                        Package () {"linux,retain-state-suspended", 1},
                    }
                })
            }
        }
        
        Device (BTNS)
        {
            Name (_HID, "MNW0002")

            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}
                GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                        "\\_SB.PCI0.LPC", 0, ResourceConsumer) {2}
                GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
                        "\\_SB.PCI0.LPC", 0, ResourceConsumer) {3}
            })

            Name (_DSD, Package ()
            {
                ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                Package ()
                {
                    Package () {"poll-interval", 100},
                    Package () {"autorepeat", 1}
                }
            })

            Device (BTN0)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"linux,code", 105},
                        Package () {"linux,input-type", 1},
                        Package () {"gpios", Package () {^^BTNS, 0, 0, 1}},
                    }
                })
            }

            Device (BTN1)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"linux,code", 108},
                        Package () {"linux,input-type", 1},
                        Package () {"gpios", Package (4) {^^BTNS, 1, 0, 1}},
                    }
                })
            }
            
            Device (BTN2)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"linux,code", 103},
                        Package () {"linux,input-type", 1},
                        Package () {"gpios", Package () {^^BTNS, 2, 0, 1}},
                    }
                })
            }
            
            Device (BTN3)
            {
                Name (_HID, "PRP0000")
                Name (_DSD, Package ()
                {
                    ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
                    Package ()
                    {
                        Package () {"linux,code", 106},
                        Package () {"linux,input-type", 1},
                        Package () {"gpios", Package (4) {^^BTNS, 3, 0, 1}},
                    }
                })
            }

        }

    }

-- 
2.1.0.rc1

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

* [RFC PATCH 1/9] ACPI: Add support for device specific properties
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
@ 2014-08-17  6:04 ` Mika Westerberg
  2014-08-18  8:13   ` Hanjun Guo
       [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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

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>
---
 drivers/acpi/Makefile   |   1 +
 drivers/acpi/internal.h |   6 +
 drivers/acpi/property.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/acpi/scan.c     |   2 +
 include/acpi/acpi_bus.h |   7 +
 include/linux/acpi.h    |  40 ++++++
 6 files changed, 421 insertions(+)
 create mode 100644 drivers/acpi/property.c

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index ea55e0179f81..6e8269a111db 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -45,6 +45,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
diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
index 7de5b603f272..35001e2a8769 100644
--- a/drivers/acpi/internal.h
+++ b/drivers/acpi/internal.h
@@ -178,4 +178,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
 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_ */
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
new file mode 100644
index 000000000000..093e834c35db
--- /dev/null
+++ b/drivers/acpi/property.c
@@ -0,0 +1,365 @@
+/*
+ * 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);
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index f775fa0d850f..fc97e6123864 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -880,6 +880,7 @@ static void acpi_device_release(struct device *dev)
 {
 	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);
@@ -1876,6 +1877,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
 	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;
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index b5714580801a..348bd260a6b4 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -331,6 +331,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;
@@ -347,6 +353,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;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 358c01b971db..9181d78eb7c4 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -649,4 +649,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 -ENOSYS;
+}
+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 -ENOSYS;
+}
+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 -ENOSYS;
+}
+#endif
+
 #endif	/*_LINUX_ACPI_H*/
-- 
2.1.0.rc1


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

* [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
@ 2014-08-17  6:04     ` Mika Westerberg
       [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

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

Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Darren Hart <dvhart-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 Documentation/acpi/properties.txt | 359 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 359 insertions(+)
 create mode 100644 Documentation/acpi/properties.txt

diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt
new file mode 100644
index 000000000000..a1e93267c1fa
--- /dev/null
+++ b/Documentation/acpi/properties.txt
@@ -0,0 +1,359 @@
+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 GPIO keys device.
+In addition to the GpioIo/GpioInt resources the driver needs to know how
+to map each GpioIo resource to the corresponding Linux input event.
+
+To solve this we add the following ACPI device properties from the
+gpio-keys schema:
+
+	Device (KEYS) {
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {"poll-interval", 100},
+				Package () {"autorepeat", 1}
+			}
+		})
+
+		Device (BTN0) {
+			Name (_DSD, Package () {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package () {"linux,code", 105},
+					Package () {"linux,input-type", 1},
+					...
+				}
+			})
+		}
+
+		...
+	}
+
+Of course the device driver then needs to iterate over these devices but
+it can be done easily via the ->children field of the companion ACPI
+device. This will be demonstrated later on in the document.
+
+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 () {"poll-interval", 100},
+	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(dev, "poll-interval", DEV_PROP_U32, &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_array(dev, "max8952,dvs-mode-microvolt",
+					 DEV_PROP_U32, 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 () {"pwm-names", "backlight"},
+	Package () {"label", "Status-LED"},
+
+You can also use device_property_read() to extract strings:
+
+	const char *val;
+	int ret;
+
+	ret = device_property_read(dev, "label", DEV_PROP_STRING, &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_array(dev, "dma-names", DEV_PROP_STRING,
+					 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 () {"clock", \_SB.CLK0},
+
+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 }
+			...
+		})
+
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				// Properties for KEYS device
+				Package () {"#gpio-cells", 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:
+
+	void gpio_keys_polled_acpi_probe(struct device *dev)
+	{
+		struct acpi_device *adev = ACPI_COMPANION(dev);
+		struct acpi_device *button;
+
+		/* Properties for the KEYS device itself */
+		device_property_read(dev, ...);
+		/* or acpi_dev_get_property(adev, ...) */
+
+		/*
+		 * Iterate over button devices and extract their
+		 * configuration. Here we need to use ACPI specific
+		 * functions instead because the pseudo devices don't have
+		 * physical device attached to them.
+		 */
+		list_for_each_entry(button, &adev->children, node) {
+			const union acpi_object *label;
+
+			acpi_dev_get_property(button, "label",
+				ACPI_TYPE_STRING, &label);
+			dev_info(dev, "label: %s\n", label->string.pointer);
+		}
+	}
+
+Note that you still need proper error handling which is omitted in the
+above example, and also if possible instead of calling to ACPI specific
+functions, one should add the support to the subsystem in question which
+can then provide this information to the drivers in more generic way.
-- 
2.1.0.rc1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
@ 2014-08-17  6:04     ` Mika Westerberg
  0 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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>
---
 Documentation/acpi/properties.txt | 359 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 359 insertions(+)
 create mode 100644 Documentation/acpi/properties.txt

diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt
new file mode 100644
index 000000000000..a1e93267c1fa
--- /dev/null
+++ b/Documentation/acpi/properties.txt
@@ -0,0 +1,359 @@
+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 GPIO keys device.
+In addition to the GpioIo/GpioInt resources the driver needs to know how
+to map each GpioIo resource to the corresponding Linux input event.
+
+To solve this we add the following ACPI device properties from the
+gpio-keys schema:
+
+	Device (KEYS) {
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				Package () {"poll-interval", 100},
+				Package () {"autorepeat", 1}
+			}
+		})
+
+		Device (BTN0) {
+			Name (_DSD, Package () {
+				ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+				Package () {
+					Package () {"linux,code", 105},
+					Package () {"linux,input-type", 1},
+					...
+				}
+			})
+		}
+
+		...
+	}
+
+Of course the device driver then needs to iterate over these devices but
+it can be done easily via the ->children field of the companion ACPI
+device. This will be demonstrated later on in the document.
+
+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 () {"poll-interval", 100},
+	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(dev, "poll-interval", DEV_PROP_U32, &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_array(dev, "max8952,dvs-mode-microvolt",
+					 DEV_PROP_U32, 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 () {"pwm-names", "backlight"},
+	Package () {"label", "Status-LED"},
+
+You can also use device_property_read() to extract strings:
+
+	const char *val;
+	int ret;
+
+	ret = device_property_read(dev, "label", DEV_PROP_STRING, &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_array(dev, "dma-names", DEV_PROP_STRING,
+					 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 () {"clock", \_SB.CLK0},
+
+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 }
+			...
+		})
+
+		Name (_DSD, Package () {
+			ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
+			Package () {
+				// Properties for KEYS device
+				Package () {"#gpio-cells", 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:
+
+	void gpio_keys_polled_acpi_probe(struct device *dev)
+	{
+		struct acpi_device *adev = ACPI_COMPANION(dev);
+		struct acpi_device *button;
+
+		/* Properties for the KEYS device itself */
+		device_property_read(dev, ...);
+		/* or acpi_dev_get_property(adev, ...) */
+
+		/*
+		 * Iterate over button devices and extract their
+		 * configuration. Here we need to use ACPI specific
+		 * functions instead because the pseudo devices don't have
+		 * physical device attached to them.
+		 */
+		list_for_each_entry(button, &adev->children, node) {
+			const union acpi_object *label;
+
+			acpi_dev_get_property(button, "label",
+				ACPI_TYPE_STRING, &label);
+			dev_info(dev, "label: %s\n", label->string.pointer);
+		}
+	}
+
+Note that you still need proper error handling which is omitted in the
+above example, and also if possible instead of calling to ACPI specific
+functions, one should add the support to the subsystem in question which
+can then provide this information to the drivers in more generic way.
-- 
2.1.0.rc1


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

* [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
  2014-08-17  6:04 ` [RFC PATCH 1/9] ACPI: Add support for device specific properties Mika Westerberg
       [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
@ 2014-08-17  6:04 ` Mika Westerberg
  2014-08-17 12:49     ` Grant Likely
  2014-08-17  6:04 ` [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node Mika Westerberg
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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.

Three general helper functions, device_property_get(),
device_property_read() and device_property_read_array() are provided.
The first one allows the raw value of a given device property to be
accessed by the driver.  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.

The interface is supposed to cover both ACPI and Device Trees,
although the ACPI part is only implemented at this time.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/acpi/glue.c      |   4 +-
 drivers/acpi/property.c  | 179 ++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/acpi/scan.c      |  12 +++-
 drivers/base/Makefile    |   2 +-
 drivers/base/property.c  |  48 +++++++++++++
 include/acpi/acpi_bus.h  |   1 +
 include/linux/device.h   |   3 +
 include/linux/property.h |  50 +++++++++++++
 8 files changed, 293 insertions(+), 6 deletions(-)
 create mode 100644 drivers/base/property.c
 create mode 100644 include/linux/property.h

diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index f774c65ecb8b..1df5223bb98d 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -9,7 +9,7 @@
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/list.h>
-#include <linux/device.h>
+#include <linux/property.h>
 #include <linux/slab.h>
 #include <linux/rwsem.h>
 #include <linux/acpi.h>
@@ -220,6 +220,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
 	list_add(&physical_node->node, physnode_list);
 	acpi_dev->physical_node_count++;
 
+	dev->property_ops = &acpi_property_ops;
 	if (!ACPI_COMPANION(dev))
 		ACPI_COMPANION_SET(dev, acpi_dev);
 
@@ -271,6 +272,7 @@ int acpi_unbind_one(struct device *dev)
 			acpi_physnode_link_name(physnode_name, entry->node_id);
 			sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
 			sysfs_remove_link(&dev->kobj, "firmware_node");
+			dev->property_ops = NULL;
 			ACPI_COMPANION_SET(dev, NULL);
 			/* Drop references taken by acpi_bind_one(). */
 			put_device(dev);
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index 093e834c35db..bdba5f85c919 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -13,8 +13,8 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/property.h>
 #include <linux/acpi.h>
-#include <linux/device.h>
 #include <linux/export.h>
 
 #include "internal.h"
@@ -363,3 +363,180 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
 	return -EPROTO;
 }
 EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
+
+static int acpi_dev_prop_get(struct device *dev, const char *propname,
+			     void **valptr)
+{
+	return acpi_dev_get_property(ACPI_COMPANION(dev), propname,
+				     ACPI_TYPE_ANY,
+				     (const union acpi_object **)valptr);
+}
+
+static int acpi_dev_prop_read(struct device *dev, 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(ACPI_COMPANION(dev), propname,
+					    ACPI_TYPE_INTEGER, &obj);
+		if (ret)
+			return ret;
+
+		switch (proptype) {
+		case DEV_PROP_U8:
+			*(u8 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U16:
+			*(u16 *)val = obj->integer.value;
+			break;
+		case DEV_PROP_U32:
+			*(u32 *)val = obj->integer.value;
+			break;
+		default:
+			*(u64 *)val = obj->integer.value;
+			break;
+		}
+	} else if (proptype == DEV_PROP_STRING) {
+		ret = acpi_dev_get_property(ACPI_COMPANION(dev), 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;
+
+		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;
+
+		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;
+
+		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;
+}
+
+static int acpi_dev_prop_read_array(struct device *dev, 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(ACPI_COMPANION(dev), 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;
+}
+
+static int acpi_dev_get_child_count(struct device *dev)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+
+	if (!adev)
+		return -EINVAL;
+	return adev->child_count;
+}
+
+struct dev_prop_ops acpi_property_ops = {
+	.get = acpi_dev_prop_get,
+	.read = acpi_dev_prop_read,
+	.read_array = acpi_dev_prop_read_array,
+	.child_count = acpi_dev_get_child_count,
+};
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index fc97e6123864..75b1b91e5ab0 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1035,8 +1035,10 @@ struct bus_type acpi_bus_type = {
 static void acpi_device_del(struct acpi_device *device)
 {
 	mutex_lock(&acpi_device_lock);
-	if (device->parent)
+	if (device->parent) {
 		list_del(&device->node);
+		device->parent->child_count--;
+	}
 
 	list_del(&device->wakeup_list);
 	mutex_unlock(&acpi_device_lock);
@@ -1222,8 +1224,10 @@ int acpi_device_add(struct acpi_device *device,
 	}
 	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
 
-	if (device->parent)
+	if (device->parent) {
 		list_add_tail(&device->node, &device->parent->children);
+		device->parent->child_count++;
+	}
 
 	if (device->wakeup.flags.valid)
 		list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
@@ -1248,8 +1252,10 @@ int acpi_device_add(struct acpi_device *device,
 
  err:
 	mutex_lock(&acpi_device_lock);
-	if (device->parent)
+	if (device->parent) {
 		list_del(&device->node);
+		device->parent->child_count--;
+	}
 	list_del(&device->wakeup_list);
 	mutex_unlock(&acpi_device_lock);
 
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 04b314e0fa51..1acd294b6514 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.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/
diff --git a/drivers/base/property.c b/drivers/base/property.c
new file mode 100644
index 000000000000..d770b6edc91a
--- /dev/null
+++ b/drivers/base/property.c
@@ -0,0 +1,48 @@
+/*
+ * property.c - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * All rights reserved.
+ *
+ * Author: 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/property.h>
+#include <linux/export.h>
+
+int device_property_get(struct device *dev, const char *propname, void **valptr)
+{
+	return dev->property_ops && dev->property_ops->get ?
+		dev->property_ops->get(dev, propname, valptr) : -ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_property_get);
+
+int device_property_read(struct device *dev, const char *propname,
+			 enum dev_prop_type proptype, void *val)
+{
+	return dev->property_ops && dev->property_ops->read ?
+		dev->property_ops->read(dev, propname, proptype, val) :
+		-ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_property_read);
+
+int device_property_read_array(struct device *dev, const char *propname,
+			       enum dev_prop_type proptype, void *val,
+			       size_t nval)
+{
+	return dev->property_ops && dev->property_ops->read_array ?
+		dev->property_ops->read_array(dev, propname, proptype, val, nval) :
+		-ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_property_read_array);
+
+int device_property_child_count(struct device *dev)
+{
+	return dev->property_ops && dev->property_ops->child_count ?
+		dev->property_ops->child_count(dev) : -ENODATA;
+}
+EXPORT_SYMBOL_GPL(device_property_child_count);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 348bd260a6b4..312813f60a22 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -340,6 +340,7 @@ struct acpi_device_data {
 /* Device */
 struct acpi_device {
 	int device_type;
+	int child_count;
 	acpi_handle handle;		/* no handle for fixed hardware */
 	struct acpi_device *parent;
 	struct list_head children;
diff --git a/include/linux/device.h b/include/linux/device.h
index af424acd393d..ea4cf31f8b9e 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -38,6 +38,7 @@ struct class;
 struct subsys_private;
 struct bus_type;
 struct device_node;
+struct dev_prop_ops;
 struct iommu_ops;
 struct iommu_group;
 
@@ -701,6 +702,7 @@ struct acpi_dev_node {
  * @archdata:	For arch-specific additions.
  * @of_node:	Associated device tree node.
  * @acpi_node:	Associated ACPI device node.
+ * @property_ops: Firmware interface for device properties
  * @devt:	For creating the sysfs "dev".
  * @id:		device instance
  * @devres_lock: Spinlock to protect the resource of the device.
@@ -777,6 +779,7 @@ struct device {
 
 	struct device_node	*of_node; /* associated device tree node */
 	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
+	struct dev_prop_ops	*property_ops;
 
 	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
 	u32			id;	/* device instance */
diff --git a/include/linux/property.h b/include/linux/property.h
new file mode 100644
index 000000000000..52ea7fe7fe09
--- /dev/null
+++ b/include/linux/property.h
@@ -0,0 +1,50 @@
+/*
+ * property.h - Unified device property interface.
+ *
+ * Copyright (C) 2014, Intel Corporation
+ * Author: 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.
+ */
+
+#ifndef _LINUX_PROPERTY_H_
+#define _LINUX_PROPERTY_H_
+
+#include <linux/device.h>
+#include <linux/acpi.h>
+#include <linux/of.h>
+
+enum dev_prop_type {
+	DEV_PROP_U8,
+	DEV_PROP_U16,
+	DEV_PROP_U32,
+	DEV_PROP_U64,
+	DEV_PROP_STRING,
+	DEV_PROP_MAX,
+};
+
+struct dev_prop_ops {
+	int (*get)(struct device *dev, const char *propname, void **valptr);
+	int (*read)(struct device *dev, const char *propname,
+		    enum dev_prop_type proptype, void *val);
+	int (*read_array)(struct device *dev, const char *propname,
+			  enum dev_prop_type proptype, void *val, size_t nval);
+	int (*child_count)(struct device *dev);
+};
+
+#ifdef CONFIG_ACPI
+extern struct dev_prop_ops acpi_property_ops;
+#endif
+
+int device_property_get(struct device *dev, const char *propname,
+			void **valptr);
+int device_property_read(struct device *dev, const char *propname,
+			 enum dev_prop_type proptype, void *val);
+int device_property_read_array(struct device *dev, const char *propname,
+			       enum dev_prop_type proptype, void *val,
+			       size_t nval);
+int device_property_child_count(struct device *dev);
+
+#endif /* _LINUX_PROPERTY_H_ */
-- 
2.1.0.rc1

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

* [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
                   ` (2 preceding siblings ...)
  2014-08-17  6:04 ` [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware Mika Westerberg
@ 2014-08-17  6:04 ` Mika Westerberg
  2014-08-17 12:54     ` Grant Likely
  2014-08-18  0:44   ` Rob Herring
  2014-08-17  6:04 ` [RFC PATCH 5/9] mfd: Add ACPI support Mika Westerberg
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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

With the unified device properties interface in place, add device tree support.
By adding the dev_prop_ops for of_node devices, drivers can access properties
from ACPI or Device Tree in a generic way.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/of/base.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++-
 drivers/of/platform.c    |   4 +-
 include/linux/property.h |   4 +
 3 files changed, 200 insertions(+), 2 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index b9864806e9b8..527004d01423 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -20,7 +20,7 @@
 #include <linux/ctype.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
-#include <linux/of.h>
+#include <linux/property.h>
 #include <linux/of_graph.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
@@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
 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.
@@ -1490,6 +1523,47 @@ int of_property_count_strings(struct device_node *np, const char *propname)
 }
 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 -EILSEQ 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 -EILSEQ;
+
+	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;
@@ -2376,3 +2450,121 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
 	return of_get_next_parent(np);
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+static int of_dev_prop_get(struct device *dev, const char *propname,
+			   void **valptr)
+{
+	struct property *pp = of_find_property(dev->of_node, propname, NULL);
+
+	if (!pp)
+		return -ENODATA;
+
+	if (valptr)
+		*valptr = pp->value;
+	return 0;
+}
+
+static int of_dev_prop_read(struct device *dev, const char *propname,
+			    enum dev_prop_type proptype, void *val)
+{
+	void *value;
+	int ret = of_dev_prop_get(dev, 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;
+
+}
+
+static int of_dev_prop_read_array(struct device *dev, 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(dev->of_node,
+							 propname);
+		default:
+			return -EINVAL;
+		}
+		return of_property_count_elems_of_size(dev->of_node, propname,
+						       elem_size);
+	}
+
+	switch (proptype) {
+	case DEV_PROP_U8:
+		ret = of_property_read_u8_array(dev->of_node, propname,
+						(u8 *)val, nval);
+		break;
+	case DEV_PROP_U16:
+		ret = of_property_read_u16_array(dev->of_node, propname,
+						 (u16 *)val, nval);
+		break;
+	case DEV_PROP_U32:
+		ret = of_property_read_u32_array(dev->of_node, propname,
+						 (u32 *)val, nval);
+		break;
+	case DEV_PROP_U64:
+		ret = of_property_read_u64_array(dev->of_node, propname,
+						 (u64 *)val, nval);
+		break;
+	case DEV_PROP_STRING:
+		ret = of_property_read_string_array(dev->of_node, propname,
+						    (char **)val, nval);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+static int of_dev_get_child_count(struct device *dev)
+{
+	struct device_node *node = dev->of_node;
+
+	if (!node)
+		return -EINVAL;
+	return of_get_child_count(node);
+}
+
+struct dev_prop_ops of_property_ops = {
+	.get = of_dev_prop_get,
+	.read = of_dev_prop_read,
+	.read_array = of_dev_prop_read_array,
+	.child_count = of_dev_get_child_count,
+};
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 500436f9be7f..3113d3704eff 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -14,7 +14,7 @@
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/amba/bus.h>
-#include <linux/device.h>
+#include <linux/property.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
 #include <linux/of_address.h>
@@ -138,6 +138,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
 	}
 
 	dev->dev.of_node = of_node_get(np);
+	dev->dev.property_ops = &of_property_ops;
 	dev->dev.parent = parent;
 
 	if (bus_id)
@@ -293,6 +294,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
 	/* setup generic device info */
 	dev->dev.coherent_dma_mask = ~0;
 	dev->dev.of_node = of_node_get(node);
+	dev->dev.property_ops = &of_property_ops;
 	dev->dev.parent = parent;
 	dev->dev.platform_data = platform_data;
 	if (bus_id)
diff --git a/include/linux/property.h b/include/linux/property.h
index 52ea7fe7fe09..a840c1784c82 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -38,6 +38,10 @@ struct dev_prop_ops {
 extern struct dev_prop_ops acpi_property_ops;
 #endif
 
+#ifdef CONFIG_OF
+extern struct dev_prop_ops of_property_ops;
+#endif
+
 int device_property_get(struct device *dev, const char *propname,
 			void **valptr);
 int device_property_read(struct device *dev, const char *propname,
-- 
2.1.0.rc1


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

* [RFC PATCH 5/9] mfd: Add ACPI support
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
                   ` (3 preceding siblings ...)
  2014-08-17  6:04 ` [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node Mika Westerberg
@ 2014-08-17  6:04 ` Mika Westerberg
  2014-08-28 11:29     ` Lee Jones
  2014-08-17  6:04 ` [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API Mika Westerberg
  2014-08-17  6:04 ` [RFC PATCH 9/9] leds: leds-gpio: " Mika Westerberg
  6 siblings, 1 reply; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

If an MFD device is backed by ACPI namespace, we should allow subdevice
drivers to access their corresponding ACPI companion devices through normal
means (e.g using ACPI_COMPANION()).

This patch adds such support to the MFD core. If the MFD parent device
doesn't specify any ACPI _HID/_CID for the child device, the child device
will share the parent ACPI companion device. Otherwise the child device
will be assigned with the corresponding ACPI companion, if found in the
namespace below the parent.

Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
---
 Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
 drivers/mfd/mfd-core.c             | 41 ++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/core.h           |  3 +++
 3 files changed, 71 insertions(+)

diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
index e182be5e3c83..74e35c54febf 100644
--- a/Documentation/acpi/enumeration.txt
+++ b/Documentation/acpi/enumeration.txt
@@ -312,3 +312,30 @@ a code like this:
 
 There are also devm_* versions of these functions which release the
 descriptors once the device is released.
+
+MFD devices
+~~~~~~~~~~~
+The MFD devices create platform devices from their children. For the
+child devices there needs to be an ACPI handle that they can use to
+reference parts of the ACPI namespace that relate to them. In the Linux
+MFD subsystem we provide two ways:
+
+	o The children share the parent ACPI handle.
+	o The MFD cell can specify the ACPI id of the device.
+
+For the first case, the MFD drivers do not need to do anything. The
+resulting child platform device will have its ACPI_COMPANION() set to point
+to the parent device.
+
+If the ACPI namespace has a device that we can match using an ACPI id,
+the id should be set like:
+
+	static struct mfd_cell my_subdevice_cell = {
+		.name = "my_subdevice",
+		/* set the resources relative to the parent */
+		.acpi_pnpid = "XYZ0001",
+	};
+
+The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
+the MFD device and if found, that ACPI companion device is bound to the
+resulting child platform device.
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 892d343193ad..bb466b28b3b6 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -78,6 +78,45 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
 	return 0;
 }
 
+#if IS_ENABLED(CONFIG_ACPI)
+static void mfd_acpi_add_device(const struct mfd_cell *cell,
+				struct platform_device *pdev)
+{
+	struct acpi_device *parent_adev;
+	struct acpi_device *adev = NULL;
+
+	parent_adev = ACPI_COMPANION(pdev->dev.parent);
+	if (!parent_adev)
+		return;
+
+	/*
+	 * MFD child device gets its ACPI handle either from the ACPI
+	 * device directly under the parent that matches the acpi_pnpid or
+	 * it will use the parent handle if is no acpi_pnpid is given.
+	 */
+	if (cell->acpi_pnpid) {
+		struct acpi_device_id ids[2] = {};
+		struct acpi_device *child_adev;
+
+		strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
+		list_for_each_entry(child_adev, &parent_adev->children, node)
+			if (acpi_match_device_ids(child_adev, ids)) {
+				adev = child_adev;
+				break;
+			}
+	} else {
+		adev = parent_adev;
+	}
+
+	ACPI_COMPANION_SET(&pdev->dev, adev);
+}
+#else
+static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
+				       struct platform_device *pdev)
+{
+}
+#endif
+
 static int mfd_add_device(struct device *parent, int id,
 			  const struct mfd_cell *cell, atomic_t *usage_count,
 			  struct resource *mem_base,
@@ -118,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id,
 		}
 	}
 
+	mfd_acpi_add_device(cell, pdev);
+
 	if (cell->pdata_size) {
 		ret = platform_device_add_data(pdev,
 					cell->platform_data, cell->pdata_size);
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index f543de91ce19..73e1709d4c09 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -44,6 +44,9 @@ struct mfd_cell {
 	 */
 	const char		*of_compatible;
 
+	/* Matches ACPI PNP id, either _HID or _CID */
+	const char		*acpi_pnpid;
+
 	/*
 	 * These resources can be specified relative to the parent device.
 	 * For accessing hardware you should use resources from the platform dev
-- 
2.1.0.rc1

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

* [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
@ 2014-08-17  6:04     ` Mika Westerberg
       [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

From: Aaron Lu <aaron.lu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

Add a new API to get the GPIO's description pointer and its flags for
both OF based system and ACPI based system. This is useful in drivers
that do not need to care about the underlying firmware interface.

Signed-off-by: Aaron Lu <aaron.lu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Max Eliaser <max.eliaser-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Darren Hart <dvhart-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/gpio/gpiolib-acpi.c   | 81 ++++++++++++++++++++++++++++++++-----------
 drivers/gpio/gpiolib.c        | 18 ++++++++++
 drivers/gpio/gpiolib.h        |  8 +++++
 include/linux/gpio/consumer.h | 11 ++++++
 4 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 4a987917c186..f35e88d29a47 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -293,11 +293,38 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
 		lookup->info.active_low =
 			agpio->polarity == ACPI_ACTIVE_LOW;
+		lookup->info.pin_config = agpio->pin_config;
 	}
 
 	return 1;
 }
 
+static struct gpio_desc *
+__acpi_get_gpiod_by_index(struct acpi_device *adev, int index,
+			  struct acpi_gpio_info *info)
+{
+	struct acpi_gpio_lookup lookup;
+	struct list_head resource_list;
+	int ret;
+
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.index = index;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
+				     &lookup);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (lookup.desc && info)
+		*info = lookup.info;
+
+	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+}
+
+
 /**
  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
  * @dev: pointer to a device to get GPIO from
@@ -318,34 +345,46 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 					  struct acpi_gpio_info *info)
 {
-	struct acpi_gpio_lookup lookup;
-	struct list_head resource_list;
-	struct acpi_device *adev;
-	acpi_handle handle;
-	int ret;
-
-	if (!dev)
+	if (!dev || !ACPI_COMPANION(dev))
 		return ERR_PTR(-EINVAL);
+	return __acpi_get_gpiod_by_index(ACPI_COMPANION(dev), index, info);
+}
 
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev))
-		return ERR_PTR(-ENODEV);
-
-	memset(&lookup, 0, sizeof(lookup));
-	lookup.index = index;
+struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int idx,
+				       enum gpio_lookup_flags *flags)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	struct acpi_reference_args args;
+	struct acpi_gpio_info info;
+	struct gpio_desc *desc;
+	bool active_low;
+	int ret;
 
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
-				     &lookup);
-	if (ret < 0)
+	ret = acpi_dev_get_property_reference(adev, "gpios", NULL, idx, &args);
+	if (ret)
 		return ERR_PTR(ret);
 
-	acpi_dev_free_resource_list(&resource_list);
+	desc = __acpi_get_gpiod_by_index(args.adev, args.args[0], &info);
+	if (IS_ERR(desc))
+		return desc;
 
-	if (lookup.desc && info)
-		*info = lookup.info;
+	/*
+	 * The 3rd argument optionally specifies the pin polarity. We
+	 * use that if it exists, otherwise we resort to the pin config.
+	 * (Note that the first element of the "gpios" package goes into
+	 * arg.adev, not args.args.)
+	 */
+	if (args.nargs >= 3)
+		active_low = !!args.args[2];
+	else if (info.gpioint)
+		active_low = !!info.active_low;
+	else
+		active_low = !!(info.pin_config & ACPI_PIN_CONFIG_PULLUP);
 
-	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+	if (active_low)
+		*flags |= GPIO_ACTIVE_LOW;
+
+	return desc;
 }
 
 static acpi_status
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2ebc9071e354..e6c2413a6fbf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2644,6 +2644,24 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
 	return desc;
 }
 
+struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
+				      enum gpio_lookup_flags *flags)
+{
+	struct gpio_desc *desc = ERR_PTR(-ENOENT);
+
+	if (!dev || !flags)
+		return ERR_PTR(-EINVAL);
+
+	/* Using device tree? */
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		desc = of_find_gpio(dev, NULL, idx, flags);
+	else if (IS_ENABLED(CONFIG_ACPI) && ACPI_COMPANION(dev))
+		desc = acpi_get_gpiod_flags(dev, idx, flags);
+
+	return desc;
+}
+EXPORT_SYMBOL(dev_get_gpiod_flags);
+
 static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
 {
 	const char *dev_id = dev ? dev_name(dev) : NULL;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 1a4103dd38df..a759db968e51 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -25,6 +25,7 @@ enum of_gpio_flags;
 struct acpi_gpio_info {
 	bool gpioint;
 	bool active_low;
+	u8 pin_config;
 };
 
 #ifdef CONFIG_ACPI
@@ -33,6 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
 
 struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 					  struct acpi_gpio_info *info);
+struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
+				       enum gpio_lookup_flags *flags);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
 static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
@@ -43,6 +46,11 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
 {
 	return ERR_PTR(-ENOSYS);
 }
+static struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
+					      enum gpio_lookup_flags *flags)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif
 
 int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 05e53ccb708b..53f422e4f0c9 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -7,6 +7,8 @@
 
 struct device;
 
+enum gpio_lookup_flags;
+
 /**
  * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
  * preferable to the old integer-based handles.
@@ -73,6 +75,9 @@ 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);
 
+struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
+				      enum gpio_lookup_flags *flags);
+
 #else /* CONFIG_GPIOLIB */
 
 static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
@@ -254,6 +259,12 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
 	return -EINVAL;
 }
 
+static inline struct gpio_desc *dev_get_gpiod_flags(struct device *dev,
+			unsigned int idx, enum gpio_lookup_flags *flags)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
 
 #endif /* CONFIG_GPIOLIB */
 
-- 
2.1.0.rc1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
@ 2014-08-17  6:04     ` Mika Westerberg
  0 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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

Add a new API to get the GPIO's description pointer and its flags for
both OF based system and ACPI based system. This is useful in drivers
that do not need to care about the underlying firmware interface.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Max Eliaser <max.eliaser@intel.com>
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>
---
 drivers/gpio/gpiolib-acpi.c   | 81 ++++++++++++++++++++++++++++++++-----------
 drivers/gpio/gpiolib.c        | 18 ++++++++++
 drivers/gpio/gpiolib.h        |  8 +++++
 include/linux/gpio/consumer.h | 11 ++++++
 4 files changed, 97 insertions(+), 21 deletions(-)

diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 4a987917c186..f35e88d29a47 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -293,11 +293,38 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
 		lookup->info.active_low =
 			agpio->polarity == ACPI_ACTIVE_LOW;
+		lookup->info.pin_config = agpio->pin_config;
 	}
 
 	return 1;
 }
 
+static struct gpio_desc *
+__acpi_get_gpiod_by_index(struct acpi_device *adev, int index,
+			  struct acpi_gpio_info *info)
+{
+	struct acpi_gpio_lookup lookup;
+	struct list_head resource_list;
+	int ret;
+
+	memset(&lookup, 0, sizeof(lookup));
+	lookup.index = index;
+
+	INIT_LIST_HEAD(&resource_list);
+	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
+				     &lookup);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	acpi_dev_free_resource_list(&resource_list);
+
+	if (lookup.desc && info)
+		*info = lookup.info;
+
+	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+}
+
+
 /**
  * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
  * @dev: pointer to a device to get GPIO from
@@ -318,34 +345,46 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
 struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 					  struct acpi_gpio_info *info)
 {
-	struct acpi_gpio_lookup lookup;
-	struct list_head resource_list;
-	struct acpi_device *adev;
-	acpi_handle handle;
-	int ret;
-
-	if (!dev)
+	if (!dev || !ACPI_COMPANION(dev))
 		return ERR_PTR(-EINVAL);
+	return __acpi_get_gpiod_by_index(ACPI_COMPANION(dev), index, info);
+}
 
-	handle = ACPI_HANDLE(dev);
-	if (!handle || acpi_bus_get_device(handle, &adev))
-		return ERR_PTR(-ENODEV);
-
-	memset(&lookup, 0, sizeof(lookup));
-	lookup.index = index;
+struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int idx,
+				       enum gpio_lookup_flags *flags)
+{
+	struct acpi_device *adev = ACPI_COMPANION(dev);
+	struct acpi_reference_args args;
+	struct acpi_gpio_info info;
+	struct gpio_desc *desc;
+	bool active_low;
+	int ret;
 
-	INIT_LIST_HEAD(&resource_list);
-	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
-				     &lookup);
-	if (ret < 0)
+	ret = acpi_dev_get_property_reference(adev, "gpios", NULL, idx, &args);
+	if (ret)
 		return ERR_PTR(ret);
 
-	acpi_dev_free_resource_list(&resource_list);
+	desc = __acpi_get_gpiod_by_index(args.adev, args.args[0], &info);
+	if (IS_ERR(desc))
+		return desc;
 
-	if (lookup.desc && info)
-		*info = lookup.info;
+	/*
+	 * The 3rd argument optionally specifies the pin polarity. We
+	 * use that if it exists, otherwise we resort to the pin config.
+	 * (Note that the first element of the "gpios" package goes into
+	 * arg.adev, not args.args.)
+	 */
+	if (args.nargs >= 3)
+		active_low = !!args.args[2];
+	else if (info.gpioint)
+		active_low = !!info.active_low;
+	else
+		active_low = !!(info.pin_config & ACPI_PIN_CONFIG_PULLUP);
 
-	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
+	if (active_low)
+		*flags |= GPIO_ACTIVE_LOW;
+
+	return desc;
 }
 
 static acpi_status
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index 2ebc9071e354..e6c2413a6fbf 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2644,6 +2644,24 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
 	return desc;
 }
 
+struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
+				      enum gpio_lookup_flags *flags)
+{
+	struct gpio_desc *desc = ERR_PTR(-ENOENT);
+
+	if (!dev || !flags)
+		return ERR_PTR(-EINVAL);
+
+	/* Using device tree? */
+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
+		desc = of_find_gpio(dev, NULL, idx, flags);
+	else if (IS_ENABLED(CONFIG_ACPI) && ACPI_COMPANION(dev))
+		desc = acpi_get_gpiod_flags(dev, idx, flags);
+
+	return desc;
+}
+EXPORT_SYMBOL(dev_get_gpiod_flags);
+
 static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
 {
 	const char *dev_id = dev ? dev_name(dev) : NULL;
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
index 1a4103dd38df..a759db968e51 100644
--- a/drivers/gpio/gpiolib.h
+++ b/drivers/gpio/gpiolib.h
@@ -25,6 +25,7 @@ enum of_gpio_flags;
 struct acpi_gpio_info {
 	bool gpioint;
 	bool active_low;
+	u8 pin_config;
 };
 
 #ifdef CONFIG_ACPI
@@ -33,6 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
 
 struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
 					  struct acpi_gpio_info *info);
+struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
+				       enum gpio_lookup_flags *flags);
 #else
 static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
 static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
@@ -43,6 +46,11 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
 {
 	return ERR_PTR(-ENOSYS);
 }
+static struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
+					      enum gpio_lookup_flags *flags)
+{
+	return ERR_PTR(-ENOSYS);
+}
 #endif
 
 int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
index 05e53ccb708b..53f422e4f0c9 100644
--- a/include/linux/gpio/consumer.h
+++ b/include/linux/gpio/consumer.h
@@ -7,6 +7,8 @@
 
 struct device;
 
+enum gpio_lookup_flags;
+
 /**
  * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
  * preferable to the old integer-based handles.
@@ -73,6 +75,9 @@ 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);
 
+struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
+				      enum gpio_lookup_flags *flags);
+
 #else /* CONFIG_GPIOLIB */
 
 static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
@@ -254,6 +259,12 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
 	return -EINVAL;
 }
 
+static inline struct gpio_desc *dev_get_gpiod_flags(struct device *dev,
+			unsigned int idx, enum gpio_lookup_flags *flags)
+{
+	return ERR_PTR(-ENOSYS);
+}
+
 
 #endif /* CONFIG_GPIOLIB */
 
-- 
2.1.0.rc1


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

* [RFC PATCH 7/9] gpio: sch: Consolidate core and resume banks
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
@ 2014-08-17  6:04     ` Mika Westerberg
       [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

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-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Tested-by: Max Eliaser <max.eliaser-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
---
 drivers/gpio/gpio-sch.c | 303 ++++++++++++++++++------------------------------
 1 file changed, 112 insertions(+), 191 deletions(-)

diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index a9b1cd16c848..99720c8bc8ed 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -29,300 +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)
+#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;
+};
 
-static unsigned short gpio_ba;
+#define to_sch_gpio(c)	container_of(c, struct sch_gpio, chip)
 
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+				unsigned reg)
 {
-	u8 curr_dirs;
-	unsigned short offset, bit;
+	unsigned base = 0;
 
-	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);
+	if (gpio >= sch->resume_base) {
+		gpio -= sch->resume_base;
+		base += 0x20;
+	}
 
-	spin_unlock(&gpio_lock);
-	return 0;
+	return base + reg + gpio / 8;
 }
 
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
 {
-	int res;
-	unsigned short offset, bit;
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	res = !!(inb(gpio_ba + offset) & (1 << bit));
-	return res;
+	if (gpio >= sch->resume_base)
+		gpio -= sch->resume_base;
+	return gpio % 8;
 }
 
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_vals;
 	unsigned short offset, bit;
+	u8 enable;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio, GEN);
+	bit = sch_gpio_bit(sch, gpio);
 
-	curr_vals = inb(gpio_ba + offset);
+	enable = inb(sch->iobase + offset);
+	if (!(enable & (1 << bit)))
+		outb(enable | (1 << bit), sch->iobase + offset);
 
-	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
-	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 }
 
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+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);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	spin_lock(&sch->lock);
 
-	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_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	spin_unlock(&gpio_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_core_set(gc, gpio_num, val);
-	return 0;
-}
-
-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)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	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);
 
-	return !!(inb(gpio_ba + offset) & (1 << bit));
+	res = !!(inb(sch->iobase + 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;
-
-	err = gpiochip_add(&sch_gpio_resume);
-	if (err < 0)
-		goto err_sch_gpio_resume;
-
-	return 0;
+	platform_set_drvdata(pdev, sch);
 
-err_sch_gpio_resume:
-	if (gpiochip_remove(&sch_gpio_core))
-		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
-
-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) {
-		int err;
-
-		err  = gpiochip_remove(&sch_gpio_core);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-		err = gpiochip_remove(&sch_gpio_resume);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-		release_region(res->start, resource_size(res));
-		gpio_ba = 0;
-
-		return err;
-	}
+	struct sch_gpio *sch = platform_get_drvdata(pdev);
 
+	gpiochip_remove(&sch->chip);
 	return 0;
 }
 
-- 
2.1.0.rc1

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* [RFC PATCH 7/9] gpio: sch: Consolidate core and resume banks
@ 2014-08-17  6:04     ` Mika Westerberg
  0 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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>
Tested-by: Max Eliaser <max.eliaser@intel.com>
---
 drivers/gpio/gpio-sch.c | 303 ++++++++++++++++++------------------------------
 1 file changed, 112 insertions(+), 191 deletions(-)

diff --git a/drivers/gpio/gpio-sch.c b/drivers/gpio/gpio-sch.c
index a9b1cd16c848..99720c8bc8ed 100644
--- a/drivers/gpio/gpio-sch.c
+++ b/drivers/gpio/gpio-sch.c
@@ -29,300 +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)
+#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;
+};
 
-static unsigned short gpio_ba;
+#define to_sch_gpio(c)	container_of(c, struct sch_gpio, chip)
 
-static int sch_gpio_core_direction_in(struct gpio_chip *gc, unsigned  gpio_num)
+static unsigned sch_gpio_offset(struct sch_gpio *sch, unsigned gpio,
+				unsigned reg)
 {
-	u8 curr_dirs;
-	unsigned short offset, bit;
+	unsigned base = 0;
 
-	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);
+	if (gpio >= sch->resume_base) {
+		gpio -= sch->resume_base;
+		base += 0x20;
+	}
 
-	spin_unlock(&gpio_lock);
-	return 0;
+	return base + reg + gpio / 8;
 }
 
-static int sch_gpio_core_get(struct gpio_chip *gc, unsigned gpio_num)
+static unsigned sch_gpio_bit(struct sch_gpio *sch, unsigned gpio)
 {
-	int res;
-	unsigned short offset, bit;
-
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	res = !!(inb(gpio_ba + offset) & (1 << bit));
-	return res;
+	if (gpio >= sch->resume_base)
+		gpio -= sch->resume_base;
+	return gpio % 8;
 }
 
-static void sch_gpio_core_set(struct gpio_chip *gc, unsigned gpio_num, int val)
+static void sch_gpio_enable(struct sch_gpio *sch, unsigned gpio)
 {
-	u8 curr_vals;
 	unsigned short offset, bit;
+	u8 enable;
 
-	spin_lock(&gpio_lock);
+	spin_lock(&sch->lock);
 
-	offset = CGLV + gpio_num / 8;
-	bit = gpio_num % 8;
+	offset = sch_gpio_offset(sch, gpio, GEN);
+	bit = sch_gpio_bit(sch, gpio);
 
-	curr_vals = inb(gpio_ba + offset);
+	enable = inb(sch->iobase + offset);
+	if (!(enable & (1 << bit)))
+		outb(enable | (1 << bit), sch->iobase + offset);
 
-	if (val)
-		outb(curr_vals | (1 << bit), gpio_ba + offset);
-	else
-		outb((curr_vals & ~(1 << bit)), gpio_ba + offset);
-	spin_unlock(&gpio_lock);
+	spin_unlock(&sch->lock);
 }
 
-static int sch_gpio_core_direction_out(struct gpio_chip *gc,
-					unsigned gpio_num, int val)
+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);
-
-	offset = CGIO + gpio_num / 8;
-	bit = gpio_num % 8;
+	spin_lock(&sch->lock);
 
-	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_num, GIO);
+	bit = sch_gpio_bit(sch, gpio_num);
 
-	spin_unlock(&gpio_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_core_set(gc, gpio_num, val);
-	return 0;
-}
-
-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)
-{
-	u8 curr_dirs;
-	unsigned short offset, bit;
-
-	spin_lock(&gpio_lock);
-
-	offset = RGIO + gpio_num / 8;
-	bit = gpio_num % 8;
-
-	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);
 
-	return !!(inb(gpio_ba + offset) & (1 << bit));
+	res = !!(inb(sch->iobase + 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;
-
-	err = gpiochip_add(&sch_gpio_resume);
-	if (err < 0)
-		goto err_sch_gpio_resume;
-
-	return 0;
+	platform_set_drvdata(pdev, sch);
 
-err_sch_gpio_resume:
-	if (gpiochip_remove(&sch_gpio_core))
-		dev_err(&pdev->dev, "%s gpiochip_remove failed\n", __func__);
-
-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) {
-		int err;
-
-		err  = gpiochip_remove(&sch_gpio_core);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-		err = gpiochip_remove(&sch_gpio_resume);
-		if (err)
-			dev_err(&pdev->dev, "%s failed, %d\n",
-				"gpiochip_remove()", err);
-
-		res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-
-		release_region(res->start, resource_size(res));
-		gpio_ba = 0;
-
-		return err;
-	}
+	struct sch_gpio *sch = platform_get_drvdata(pdev);
 
+	gpiochip_remove(&sch->chip);
 	return 0;
 }
 
-- 
2.1.0.rc1


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

* [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
                   ` (4 preceding siblings ...)
  2014-08-17  6:04 ` [RFC PATCH 5/9] mfd: Add ACPI support Mika Westerberg
@ 2014-08-17  6:04 ` Mika Westerberg
  2014-08-17  6:04 ` [RFC PATCH 9/9] leds: leds-gpio: " Mika Westerberg
  6 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

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.

The driver isn't converted to descriptor based gpio API due to there are
a lot of existing users of struct gpio_keys_button that expects the gpio
integer field. Though this can be solved by adding a new field of type
struct gpio_desc but then there is another problem: the devm_gpiod_get
needs to operate on the button device instead of its parent device that
has the driver binded, so when the driver is unloaded, the resources for
the gpio will not get freed automatically. Alternatively, we can
introduce a new API, something like gpiod_find_index that does almost
the same thing as gpiod_get_index but doesn't do the gpiod_request call
and use it during finding button resources in gpio_keys_polled_get_button
function. But then this may seem too complicated and not desirable. So
in the end, a simple dev_get_gpiod_flags which is introduced in the last
patch gets used and the gpio field of the struct gpio_keys_button can be
got from the desc_to_gpio.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Max Eliaser <max@meliaserlow.dyndns.tv>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c | 139 ++++++++++++++++++------------
 1 file changed, 84 insertions(+), 55 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 432d36395f35..49895d75aaff 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -27,6 +27,7 @@
 #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,78 +103,95 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
 		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;
+#if defined(CONFIG_OF) || defined(CONFIG_ACPI)
+
+struct button_proc_context {
 	struct gpio_keys_platform_data *pdata;
-	struct gpio_keys_button *button;
-	int error;
-	int nbuttons;
 	int i;
+};
 
-	node = dev->of_node;
-	if (!node)
-		return NULL;
+static int gpio_keys_polled_get_button(struct device *dev, void *data)
+{
+	struct button_proc_context *c = data;
+	struct gpio_keys_platform_data *pdata = c->pdata;
+	struct gpio_keys_button *button = &pdata->buttons[c->i];
+	struct gpio_desc *desc;
+	enum gpio_lookup_flags flags;
+	void *val;
+
+	if (device_property_get(dev, "gpios", NULL)) {
+		pdata->nbuttons--;
+		dev_warn(dev, "Found button without gpios\n");
+		return 0;
+	}
 
-	nbuttons = of_get_child_count(node);
-	if (nbuttons == 0)
-		return NULL;
+	desc = dev_get_gpiod_flags(dev, 0, &flags);
+	if (IS_ERR(desc)) {
+		int error = PTR_ERR(desc);
 
-	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
-			     GFP_KERNEL);
-	if (!pdata)
-		return ERR_PTR(-ENOMEM);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get gpio flags, error: %d\n",
+				error);
+		return error;
+	}
 
-	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-	pdata->nbuttons = nbuttons;
+	button->gpio = desc_to_gpio(desc);
+	button->active_low = flags & GPIO_ACTIVE_LOW;
 
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+	if (device_property_read(dev, "linux,code", DEV_PROP_U32,
+				 &button->code)) {
+		dev_err(dev, "Button without keycode: 0x%x\n",
+				button->gpio);
+		return -EINVAL;
+	}
 
-	i = 0;
-	for_each_child_of_node(node, pp) {
-		int gpio;
-		enum of_gpio_flags flags;
+	if (!device_property_get(dev, "label", &val))
+		button->desc = val;
 
-		if (!of_find_property(pp, "gpios", NULL)) {
-			pdata->nbuttons--;
-			dev_warn(dev, "Found button without gpios\n");
-			continue;
-		}
+	if (device_property_read(dev, "linux,input-type", DEV_PROP_U32,
+				 &button->type))
+		button->type = EV_KEY;
 
-		gpio = of_get_gpio_flags(pp, 0, &flags);
-		if (gpio < 0) {
-			error = gpio;
-			if (error != -EPROBE_DEFER)
-				dev_err(dev,
-					"Failed to get gpio flags, error: %d\n",
-					error);
-			return ERR_PTR(error);
-		}
+	button->wakeup = !device_property_get(dev, "gpio-key,wakeup", NULL);
 
-		button = &pdata->buttons[i++];
+	if (device_property_read(dev, "debounce-interval", DEV_PROP_U32,
+				 &button->debounce_interval))
+		button->debounce_interval = 5;
 
-		button->gpio = gpio;
-		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+	c->i++;
+	return 0;
+}
 
-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: 0x%x\n",
-				button->gpio);
-			return ERR_PTR(-EINVAL);
-		}
+static struct gpio_keys_platform_data *
+gpio_keys_polled_get_devtree_pdata(struct device *dev)
+{
+	struct gpio_keys_platform_data *pdata;
+	int size;
+	struct button_proc_context c;
+	int error;
+	int nbuttons;
 
-		button->desc = of_get_property(pp, "label", NULL);
+	nbuttons = device_property_child_count(dev);
+	if (nbuttons <= 0)
+		return NULL;
 
-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
-			button->type = EV_KEY;
+	size = sizeof(*pdata) + nbuttons * sizeof(struct gpio_keys_button);
+	pdata = devm_kzalloc(dev, size, GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
 
-		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+	pdata->nbuttons = nbuttons;
 
-		if (of_property_read_u32(pp, "debounce-interval",
-					 &button->debounce_interval))
-			button->debounce_interval = 5;
-	}
+	pdata->rep = !device_property_get(dev, "autorepeat", NULL);
+	device_property_read(dev, "poll-interval", DEV_PROP_U32,
+			     &pdata->poll_interval);
+
+	c.pdata = pdata;
+	c.i = 0;
+	error = device_for_each_child(dev, &c, gpio_keys_polled_get_button);
+	if (error)
+		return ERR_PTR(error);
 
 	if (pdata->nbuttons == 0)
 		return ERR_PTR(-EINVAL);
@@ -181,11 +199,21 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 	return pdata;
 }
 
+#ifdef CONFIG_OF
 static const struct of_device_id gpio_keys_polled_of_match[] = {
 	{ .compatible = "gpio-keys-polled", },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static struct acpi_device_id gpio_keys_polled_acpi_match[] = {
+	{ "MNW0002" },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match);
+#endif
 
 #else
 
@@ -309,6 +337,7 @@ static struct platform_driver gpio_keys_polled_driver = {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
+		.acpi_match_table = ACPI_PTR(gpio_keys_polled_acpi_match),
 	},
 };
 module_platform_driver(gpio_keys_polled_driver);
-- 
2.1.0.rc1

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

* [RFC PATCH 9/9] leds: leds-gpio: Make use of device property API
  2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
                   ` (5 preceding siblings ...)
  2014-08-17  6:04 ` [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API Mika Westerberg
@ 2014-08-17  6:04 ` Mika Westerberg
  6 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-17  6:04 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

From: Max Eliaser <max.eliaser@intel.com>

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

Signed-off-by: Max Eliaser <max@meliaserlow.dyndns.tv>
Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/leds/leds-gpio.c | 130 +++++++++++++++++++++++++++++------------------
 1 file changed, 80 insertions(+), 50 deletions(-)

diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index 57ff20fecf57..d7334b8a21ae 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/module.h>
 #include <linux/err.h>
+#include <linux/property.h>
 
 struct gpio_led_data {
 	struct led_classdev cdev;
@@ -161,75 +162,102 @@ static inline int sizeof_gpio_leds_priv(int num_leds)
 		(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)
+#if defined(CONFIG_OF) || defined(CONFIG_ACPI)
+
+static int gpio_leds_get_led(struct device *dev, void *data)
+{
+	struct gpio_led led = {};
+	struct gpio_leds_priv *priv = data;
+	const char *state = NULL;
+	struct gpio_desc *desc;
+	enum gpio_lookup_flags flags;
+	void *val;
+
+	if (device_property_get(dev, "gpios", NULL)) {
+		dev_warn(dev, "Found LED without gpios\n");
+		return 0;
+	}
+
+	desc = dev_get_gpiod_flags(dev, 0, &flags);
+	if (IS_ERR(desc)) {
+		int error = PTR_ERR(desc);
+
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get gpio flags for LED, error: %d\n",
+				error);
+		return error;
+	}
+
+	led.gpio = desc_to_gpio(desc);
+	led.active_low = flags & GPIO_ACTIVE_LOW;
+
+	if (!device_property_read(dev, "label", DEV_PROP_STRING, &val))
+		led.name = val;
+
+	if (!device_property_read(dev, "linux,default-trigger",
+				  DEV_PROP_STRING, &val))
+		led.default_trigger = val;
+
+	if (!device_property_read(dev, "linux,default-state", DEV_PROP_STRING,
+				  &val))
+		state = val;
+	if (state) {
+		if (!strcmp(state, "keep"))
+			led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
+		else if (!strcmp(state, "on"))
+			led.default_state = LEDS_GPIO_DEFSTATE_ON;
+		else
+			led.default_state = LEDS_GPIO_DEFSTATE_OFF;
+	}
+
+	if (!device_property_get(dev, "linux,retain-state-suspended", NULL))
+		led.retain_state_suspended = 1;
+
+	return create_gpio_led(&led, &priv->leds[priv->num_leds++], dev, NULL);
+}
+
+static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
 {
-	struct device_node *np = pdev->dev.of_node, *child;
 	struct gpio_leds_priv *priv;
-	int count, ret;
+	int count, error;
 
 	/* count LEDs in this device, so we know how much to allocate */
-	count = of_get_available_child_count(np);
-	if (!count)
+	count = device_property_child_count(dev);
+	if (count <= 0)
 		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),
+	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) {
-		struct gpio_led led = {};
-		enum of_gpio_flags flags;
-		const char *state;
-
-		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 (!strcmp(state, "keep"))
-				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
-			else if (!strcmp(state, "on"))
-				led.default_state = LEDS_GPIO_DEFSTATE_ON;
-			else
-				led.default_state = LEDS_GPIO_DEFSTATE_OFF;
-		}
-
-		if (of_get_property(child, "retain-state-suspended", NULL))
-			led.retain_state_suspended = 1;
-
-		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
-				      &pdev->dev, NULL);
-		if (ret < 0) {
-			of_node_put(child);
-			goto err;
-		}
-	}
-
-	return priv;
+	error = device_for_each_child(dev, priv, gpio_leds_get_led);
+	if (!error)
+		return priv;
 
-err:
 	for (count = priv->num_leds - 2; count >= 0; count--)
 		delete_gpio_led(&priv->leds[count]);
 	return ERR_PTR(-ENODEV);
 }
 
+#ifdef CONFIG_OF
 static const struct of_device_id of_gpio_leds_match[] = {
 	{ .compatible = "gpio-leds", },
 	{},
 };
-
 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)
+#endif
+
+#ifdef CONFIG_ACPI
+static struct acpi_device_id acpi_gpio_leds_match[] = {
+	{ "MNW0001" },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match);
+#endif
+
+#else /* CONFIG_OF || CONFIG_ACPI */
+static struct gpio_leds_priv *gpio_leds_create(struct device *dev)
 {
 	return ERR_PTR(-ENODEV);
 }
@@ -238,7 +266,8 @@ static struct gpio_leds_priv *gpio_leds_create_of(struct platform_device *pdev)
 
 static int gpio_led_probe(struct platform_device *pdev)
 {
-	struct gpio_led_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct device *dev = &pdev->dev;
+	const struct gpio_led_platform_data *pdata = dev_get_platdata(dev);
 	struct gpio_leds_priv *priv;
 	int i, ret = 0;
 
@@ -263,7 +292,7 @@ static int gpio_led_probe(struct platform_device *pdev)
 			}
 		}
 	} else {
-		priv = gpio_leds_create_of(pdev);
+		priv = gpio_leds_create(dev);
 		if (IS_ERR(priv))
 			return PTR_ERR(priv);
 	}
@@ -291,6 +320,7 @@ static struct platform_driver gpio_led_driver = {
 		.name	= "leds-gpio",
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(of_gpio_leds_match),
+		.acpi_match_table = ACPI_PTR(acpi_gpio_leds_match),
 	},
 };
 
-- 
2.1.0.rc1

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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
  2014-08-17  6:04 ` [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware Mika Westerberg
@ 2014-08-17 12:49     ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 12:49 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel


Hi Mika and Rafael,

Comments below...

On Sun, 17 Aug 2014 09:04:13 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> 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.
> 
> Three general helper functions, device_property_get(),
> device_property_read() and device_property_read_array() are provided.
> The first one allows the raw value of a given device property to be
> accessed by the driver.  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.
> 
> The interface is supposed to cover both ACPI and Device Trees,
> although the ACPI part is only implemented at this time.

Nit:
s/at this time/in this change. The DT component is implemented in a
subsequent patch./

I almost complained that the DT portion must be implemented before this
series can even be considered, but then I found it in patch 4/9.  :-)

> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/acpi/glue.c      |   4 +-
>  drivers/acpi/property.c  | 179 ++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/scan.c      |  12 +++-
>  drivers/base/Makefile    |   2 +-
>  drivers/base/property.c  |  48 +++++++++++++
>  include/acpi/acpi_bus.h  |   1 +
>  include/linux/device.h   |   3 +
>  include/linux/property.h |  50 +++++++++++++
>  8 files changed, 293 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/base/property.c
>  create mode 100644 include/linux/property.h
> 
> diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
> index f774c65ecb8b..1df5223bb98d 100644
> --- a/drivers/acpi/glue.c
> +++ b/drivers/acpi/glue.c
> @@ -9,7 +9,7 @@
>  #include <linux/export.h>
>  #include <linux/init.h>
>  #include <linux/list.h>
> -#include <linux/device.h>
> +#include <linux/property.h>
>  #include <linux/slab.h>
>  #include <linux/rwsem.h>
>  #include <linux/acpi.h>
> @@ -220,6 +220,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
>  	list_add(&physical_node->node, physnode_list);
>  	acpi_dev->physical_node_count++;
>  
> +	dev->property_ops = &acpi_property_ops;
>  	if (!ACPI_COMPANION(dev))
>  		ACPI_COMPANION_SET(dev, acpi_dev);
>  
> @@ -271,6 +272,7 @@ int acpi_unbind_one(struct device *dev)
>  			acpi_physnode_link_name(physnode_name, entry->node_id);
>  			sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
>  			sysfs_remove_link(&dev->kobj, "firmware_node");
> +			dev->property_ops = NULL;
>  			ACPI_COMPANION_SET(dev, NULL);
>  			/* Drop references taken by acpi_bind_one(). */
>  			put_device(dev);
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 093e834c35db..bdba5f85c919 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -13,8 +13,8 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/property.h>
>  #include <linux/acpi.h>
> -#include <linux/device.h>
>  #include <linux/export.h>
>  
>  #include "internal.h"
> @@ -363,3 +363,180 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
>  	return -EPROTO;
>  }
>  EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
> +
> +static int acpi_dev_prop_get(struct device *dev, const char *propname,
> +			     void **valptr)
> +{
> +	return acpi_dev_get_property(ACPI_COMPANION(dev), propname,
> +				     ACPI_TYPE_ANY,
> +				     (const union acpi_object **)valptr);
> +}
> +
> +static int acpi_dev_prop_read(struct device *dev, 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(ACPI_COMPANION(dev), propname,
> +					    ACPI_TYPE_INTEGER, &obj);
> +		if (ret)
> +			return ret;
> +
> +		switch (proptype) {
> +		case DEV_PROP_U8:
> +			*(u8 *)val = obj->integer.value;
> +			break;
> +		case DEV_PROP_U16:
> +			*(u16 *)val = obj->integer.value;
> +			break;
> +		case DEV_PROP_U32:
> +			*(u32 *)val = obj->integer.value;
> +			break;
> +		default:
> +			*(u64 *)val = obj->integer.value;
> +			break;
> +		}
> +	} else if (proptype == DEV_PROP_STRING) {
> +		ret = acpi_dev_get_property(ACPI_COMPANION(dev), 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;
> +
> +		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;
> +
> +		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;
> +
> +		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;
> +}
> +
> +static int acpi_dev_prop_read_array(struct device *dev, 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(ACPI_COMPANION(dev), 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;
> +}
> +
> +static int acpi_dev_get_child_count(struct device *dev)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +
> +	if (!adev)
> +		return -EINVAL;
> +	return adev->child_count;
> +}
> +
> +struct dev_prop_ops acpi_property_ops = {
> +	.get = acpi_dev_prop_get,
> +	.read = acpi_dev_prop_read,
> +	.read_array = acpi_dev_prop_read_array,
> +	.child_count = acpi_dev_get_child_count,
> +};
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index fc97e6123864..75b1b91e5ab0 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1035,8 +1035,10 @@ struct bus_type acpi_bus_type = {
>  static void acpi_device_del(struct acpi_device *device)
>  {
>  	mutex_lock(&acpi_device_lock);
> -	if (device->parent)
> +	if (device->parent) {
>  		list_del(&device->node);
> +		device->parent->child_count--;

I worry about housekeeping like this. It is easy for bugs to slip in.
Unless returning the child count is in a critical path (which it
shouldn't be), I would drop the child_count member and simply count the
number of items in the list when required.

This of course is not my subsystem, so I won't ACK or NACK the patch over this.

> +	}
>  
>  	list_del(&device->wakeup_list);
>  	mutex_unlock(&acpi_device_lock);
> @@ -1222,8 +1224,10 @@ int acpi_device_add(struct acpi_device *device,
>  	}
>  	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
>  
> -	if (device->parent)
> +	if (device->parent) {
>  		list_add_tail(&device->node, &device->parent->children);
> +		device->parent->child_count++;
> +	}
>  
>  	if (device->wakeup.flags.valid)
>  		list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
> @@ -1248,8 +1252,10 @@ int acpi_device_add(struct acpi_device *device,
>  
>   err:
>  	mutex_lock(&acpi_device_lock);
> -	if (device->parent)
> +	if (device->parent) {
>  		list_del(&device->node);
> +		device->parent->child_count--;
> +	}
>  	list_del(&device->wakeup_list);
>  	mutex_unlock(&acpi_device_lock);
>  
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 04b314e0fa51..1acd294b6514 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.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/
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> new file mode 100644
> index 000000000000..d770b6edc91a
> --- /dev/null
> +++ b/drivers/base/property.c
> @@ -0,0 +1,48 @@
> +/*
> + * property.c - Unified device property interface.
> + *
> + * Copyright (C) 2014, Intel Corporation
> + * All rights reserved.
> + *
> + * Author: 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/property.h>
> +#include <linux/export.h>
> +
> +int device_property_get(struct device *dev, const char *propname, void **valptr)
> +{
> +	return dev->property_ops && dev->property_ops->get ?
> +		dev->property_ops->get(dev, propname, valptr) : -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_get);
> +
> +int device_property_read(struct device *dev, const char *propname,
> +			 enum dev_prop_type proptype, void *val)
> +{
> +	return dev->property_ops && dev->property_ops->read ?
> +		dev->property_ops->read(dev, propname, proptype, val) :
> +		-ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_read);
> +
> +int device_property_read_array(struct device *dev, const char *propname,
> +			       enum dev_prop_type proptype, void *val,
> +			       size_t nval)
> +{
> +	return dev->property_ops && dev->property_ops->read_array ?
> +		dev->property_ops->read_array(dev, propname, proptype, val, nval) :
> +		-ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_read_array);
> +
> +int device_property_child_count(struct device *dev)
> +{
> +	return dev->property_ops && dev->property_ops->child_count ?
> +		dev->property_ops->child_count(dev) : -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_child_count);
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 348bd260a6b4..312813f60a22 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -340,6 +340,7 @@ struct acpi_device_data {
>  /* Device */
>  struct acpi_device {
>  	int device_type;
> +	int child_count;
>  	acpi_handle handle;		/* no handle for fixed hardware */
>  	struct acpi_device *parent;
>  	struct list_head children;
> diff --git a/include/linux/device.h b/include/linux/device.h
> index af424acd393d..ea4cf31f8b9e 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -38,6 +38,7 @@ struct class;
>  struct subsys_private;
>  struct bus_type;
>  struct device_node;
> +struct dev_prop_ops;
>  struct iommu_ops;
>  struct iommu_group;
>  
> @@ -701,6 +702,7 @@ struct acpi_dev_node {
>   * @archdata:	For arch-specific additions.
>   * @of_node:	Associated device tree node.
>   * @acpi_node:	Associated ACPI device node.
> + * @property_ops: Firmware interface for device properties
>   * @devt:	For creating the sysfs "dev".
>   * @id:		device instance
>   * @devres_lock: Spinlock to protect the resource of the device.
> @@ -777,6 +779,7 @@ struct device {
>  
>  	struct device_node	*of_node; /* associated device tree node */
>  	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
> +	struct dev_prop_ops	*property_ops;

There are only 2 users of this interface. I don't think adding an ops
pointer to each and every struct device is warrented when the wrapper
function can check if of_node or acpi_node is set and call the
appropriate helper. It is unlikely anything else will use this hook. It
will result in smaller memory footprint. Also smaller code when only one of
CONFIG_OF and CONFIG_ACPI are selected, which is almost always. :-)

It can be refactored later if that ever changes.

>  
>  	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
>  	u32			id;	/* device instance */
> diff --git a/include/linux/property.h b/include/linux/property.h
> new file mode 100644
> index 000000000000..52ea7fe7fe09
> --- /dev/null
> +++ b/include/linux/property.h
> @@ -0,0 +1,50 @@
> +/*
> + * property.h - Unified device property interface.
> + *
> + * Copyright (C) 2014, Intel Corporation
> + * Author: 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.
> + */
> +
> +#ifndef _LINUX_PROPERTY_H_
> +#define _LINUX_PROPERTY_H_
> +
> +#include <linux/device.h>
> +#include <linux/acpi.h>
> +#include <linux/of.h>
> +
> +enum dev_prop_type {
> +	DEV_PROP_U8,
> +	DEV_PROP_U16,
> +	DEV_PROP_U32,
> +	DEV_PROP_U64,
> +	DEV_PROP_STRING,
> +	DEV_PROP_MAX,
> +};
> +
> +struct dev_prop_ops {
> +	int (*get)(struct device *dev, const char *propname, void **valptr);
> +	int (*read)(struct device *dev, const char *propname,
> +		    enum dev_prop_type proptype, void *val);
> +	int (*read_array)(struct device *dev, const char *propname,
> +			  enum dev_prop_type proptype, void *val, size_t nval);

The associated DT functions that implement property reads
(of_property_read_*) were created in part to provide some type safety
when reading properties. This proposed API throws that away by accepting
a void* for the data field, which I don't want to do. This API either
needs to have a separate accessor for each data type, or it needs some
other mechanism (accessor macros?) to ensure the right type is passed
in.

> +	int (*child_count)(struct device *dev);
> +};
> +
> +#ifdef CONFIG_ACPI
> +extern struct dev_prop_ops acpi_property_ops;
> +#endif

Rendered moot by my comment about eliminating the ops structure, but the
above shouldn't appear here. acpi_property_ops shouldn't ever be visible
outside ACPI core code, so it shouldn't be in this header.

> +
> +int device_property_get(struct device *dev, const char *propname,
> +			void **valptr);
> +int device_property_read(struct device *dev, const char *propname,
> +			 enum dev_prop_type proptype, void *val);
> +int device_property_read_array(struct device *dev, const char *propname,
> +			       enum dev_prop_type proptype, void *val,
> +			       size_t nval);
> +int device_property_child_count(struct device *dev);
> +
> +#endif /* _LINUX_PROPERTY_H_ */
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
@ 2014-08-17 12:49     ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 12:49 UTC (permalink / raw)
  To: Mika Westerberg, Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel


Hi Mika and Rafael,

Comments below...

On Sun, 17 Aug 2014 09:04:13 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> 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.
> 
> Three general helper functions, device_property_get(),
> device_property_read() and device_property_read_array() are provided.
> The first one allows the raw value of a given device property to be
> accessed by the driver.  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.
> 
> The interface is supposed to cover both ACPI and Device Trees,
> although the ACPI part is only implemented at this time.

Nit:
s/at this time/in this change. The DT component is implemented in a
subsequent patch./

I almost complained that the DT portion must be implemented before this
series can even be considered, but then I found it in patch 4/9.  :-)

> 
> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/acpi/glue.c      |   4 +-
>  drivers/acpi/property.c  | 179 ++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/acpi/scan.c      |  12 +++-
>  drivers/base/Makefile    |   2 +-
>  drivers/base/property.c  |  48 +++++++++++++
>  include/acpi/acpi_bus.h  |   1 +
>  include/linux/device.h   |   3 +
>  include/linux/property.h |  50 +++++++++++++
>  8 files changed, 293 insertions(+), 6 deletions(-)
>  create mode 100644 drivers/base/property.c
>  create mode 100644 include/linux/property.h
> 
> diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
> index f774c65ecb8b..1df5223bb98d 100644
> --- a/drivers/acpi/glue.c
> +++ b/drivers/acpi/glue.c
> @@ -9,7 +9,7 @@
>  #include <linux/export.h>
>  #include <linux/init.h>
>  #include <linux/list.h>
> -#include <linux/device.h>
> +#include <linux/property.h>
>  #include <linux/slab.h>
>  #include <linux/rwsem.h>
>  #include <linux/acpi.h>
> @@ -220,6 +220,7 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
>  	list_add(&physical_node->node, physnode_list);
>  	acpi_dev->physical_node_count++;
>  
> +	dev->property_ops = &acpi_property_ops;
>  	if (!ACPI_COMPANION(dev))
>  		ACPI_COMPANION_SET(dev, acpi_dev);
>  
> @@ -271,6 +272,7 @@ int acpi_unbind_one(struct device *dev)
>  			acpi_physnode_link_name(physnode_name, entry->node_id);
>  			sysfs_remove_link(&acpi_dev->dev.kobj, physnode_name);
>  			sysfs_remove_link(&dev->kobj, "firmware_node");
> +			dev->property_ops = NULL;
>  			ACPI_COMPANION_SET(dev, NULL);
>  			/* Drop references taken by acpi_bind_one(). */
>  			put_device(dev);
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> index 093e834c35db..bdba5f85c919 100644
> --- a/drivers/acpi/property.c
> +++ b/drivers/acpi/property.c
> @@ -13,8 +13,8 @@
>   * published by the Free Software Foundation.
>   */
>  
> +#include <linux/property.h>
>  #include <linux/acpi.h>
> -#include <linux/device.h>
>  #include <linux/export.h>
>  
>  #include "internal.h"
> @@ -363,3 +363,180 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
>  	return -EPROTO;
>  }
>  EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
> +
> +static int acpi_dev_prop_get(struct device *dev, const char *propname,
> +			     void **valptr)
> +{
> +	return acpi_dev_get_property(ACPI_COMPANION(dev), propname,
> +				     ACPI_TYPE_ANY,
> +				     (const union acpi_object **)valptr);
> +}
> +
> +static int acpi_dev_prop_read(struct device *dev, 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(ACPI_COMPANION(dev), propname,
> +					    ACPI_TYPE_INTEGER, &obj);
> +		if (ret)
> +			return ret;
> +
> +		switch (proptype) {
> +		case DEV_PROP_U8:
> +			*(u8 *)val = obj->integer.value;
> +			break;
> +		case DEV_PROP_U16:
> +			*(u16 *)val = obj->integer.value;
> +			break;
> +		case DEV_PROP_U32:
> +			*(u32 *)val = obj->integer.value;
> +			break;
> +		default:
> +			*(u64 *)val = obj->integer.value;
> +			break;
> +		}
> +	} else if (proptype == DEV_PROP_STRING) {
> +		ret = acpi_dev_get_property(ACPI_COMPANION(dev), 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;
> +
> +		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;
> +
> +		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;
> +
> +		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;
> +}
> +
> +static int acpi_dev_prop_read_array(struct device *dev, 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(ACPI_COMPANION(dev), 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;
> +}
> +
> +static int acpi_dev_get_child_count(struct device *dev)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +
> +	if (!adev)
> +		return -EINVAL;
> +	return adev->child_count;
> +}
> +
> +struct dev_prop_ops acpi_property_ops = {
> +	.get = acpi_dev_prop_get,
> +	.read = acpi_dev_prop_read,
> +	.read_array = acpi_dev_prop_read_array,
> +	.child_count = acpi_dev_get_child_count,
> +};
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index fc97e6123864..75b1b91e5ab0 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1035,8 +1035,10 @@ struct bus_type acpi_bus_type = {
>  static void acpi_device_del(struct acpi_device *device)
>  {
>  	mutex_lock(&acpi_device_lock);
> -	if (device->parent)
> +	if (device->parent) {
>  		list_del(&device->node);
> +		device->parent->child_count--;

I worry about housekeeping like this. It is easy for bugs to slip in.
Unless returning the child count is in a critical path (which it
shouldn't be), I would drop the child_count member and simply count the
number of items in the list when required.

This of course is not my subsystem, so I won't ACK or NACK the patch over this.

> +	}
>  
>  	list_del(&device->wakeup_list);
>  	mutex_unlock(&acpi_device_lock);
> @@ -1222,8 +1224,10 @@ int acpi_device_add(struct acpi_device *device,
>  	}
>  	dev_set_name(&device->dev, "%s:%02x", acpi_device_bus_id->bus_id, acpi_device_bus_id->instance_no);
>  
> -	if (device->parent)
> +	if (device->parent) {
>  		list_add_tail(&device->node, &device->parent->children);
> +		device->parent->child_count++;
> +	}
>  
>  	if (device->wakeup.flags.valid)
>  		list_add_tail(&device->wakeup_list, &acpi_wakeup_device_list);
> @@ -1248,8 +1252,10 @@ int acpi_device_add(struct acpi_device *device,
>  
>   err:
>  	mutex_lock(&acpi_device_lock);
> -	if (device->parent)
> +	if (device->parent) {
>  		list_del(&device->node);
> +		device->parent->child_count--;
> +	}
>  	list_del(&device->wakeup_list);
>  	mutex_unlock(&acpi_device_lock);
>  
> diff --git a/drivers/base/Makefile b/drivers/base/Makefile
> index 04b314e0fa51..1acd294b6514 100644
> --- a/drivers/base/Makefile
> +++ b/drivers/base/Makefile
> @@ -4,7 +4,7 @@ obj-y			:= component.o core.o bus.o dd.o syscore.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/
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> new file mode 100644
> index 000000000000..d770b6edc91a
> --- /dev/null
> +++ b/drivers/base/property.c
> @@ -0,0 +1,48 @@
> +/*
> + * property.c - Unified device property interface.
> + *
> + * Copyright (C) 2014, Intel Corporation
> + * All rights reserved.
> + *
> + * Author: 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/property.h>
> +#include <linux/export.h>
> +
> +int device_property_get(struct device *dev, const char *propname, void **valptr)
> +{
> +	return dev->property_ops && dev->property_ops->get ?
> +		dev->property_ops->get(dev, propname, valptr) : -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_get);
> +
> +int device_property_read(struct device *dev, const char *propname,
> +			 enum dev_prop_type proptype, void *val)
> +{
> +	return dev->property_ops && dev->property_ops->read ?
> +		dev->property_ops->read(dev, propname, proptype, val) :
> +		-ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_read);
> +
> +int device_property_read_array(struct device *dev, const char *propname,
> +			       enum dev_prop_type proptype, void *val,
> +			       size_t nval)
> +{
> +	return dev->property_ops && dev->property_ops->read_array ?
> +		dev->property_ops->read_array(dev, propname, proptype, val, nval) :
> +		-ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_read_array);
> +
> +int device_property_child_count(struct device *dev)
> +{
> +	return dev->property_ops && dev->property_ops->child_count ?
> +		dev->property_ops->child_count(dev) : -ENODATA;
> +}
> +EXPORT_SYMBOL_GPL(device_property_child_count);
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 348bd260a6b4..312813f60a22 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -340,6 +340,7 @@ struct acpi_device_data {
>  /* Device */
>  struct acpi_device {
>  	int device_type;
> +	int child_count;
>  	acpi_handle handle;		/* no handle for fixed hardware */
>  	struct acpi_device *parent;
>  	struct list_head children;
> diff --git a/include/linux/device.h b/include/linux/device.h
> index af424acd393d..ea4cf31f8b9e 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -38,6 +38,7 @@ struct class;
>  struct subsys_private;
>  struct bus_type;
>  struct device_node;
> +struct dev_prop_ops;
>  struct iommu_ops;
>  struct iommu_group;
>  
> @@ -701,6 +702,7 @@ struct acpi_dev_node {
>   * @archdata:	For arch-specific additions.
>   * @of_node:	Associated device tree node.
>   * @acpi_node:	Associated ACPI device node.
> + * @property_ops: Firmware interface for device properties
>   * @devt:	For creating the sysfs "dev".
>   * @id:		device instance
>   * @devres_lock: Spinlock to protect the resource of the device.
> @@ -777,6 +779,7 @@ struct device {
>  
>  	struct device_node	*of_node; /* associated device tree node */
>  	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
> +	struct dev_prop_ops	*property_ops;

There are only 2 users of this interface. I don't think adding an ops
pointer to each and every struct device is warrented when the wrapper
function can check if of_node or acpi_node is set and call the
appropriate helper. It is unlikely anything else will use this hook. It
will result in smaller memory footprint. Also smaller code when only one of
CONFIG_OF and CONFIG_ACPI are selected, which is almost always. :-)

It can be refactored later if that ever changes.

>  
>  	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
>  	u32			id;	/* device instance */
> diff --git a/include/linux/property.h b/include/linux/property.h
> new file mode 100644
> index 000000000000..52ea7fe7fe09
> --- /dev/null
> +++ b/include/linux/property.h
> @@ -0,0 +1,50 @@
> +/*
> + * property.h - Unified device property interface.
> + *
> + * Copyright (C) 2014, Intel Corporation
> + * Author: 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.
> + */
> +
> +#ifndef _LINUX_PROPERTY_H_
> +#define _LINUX_PROPERTY_H_
> +
> +#include <linux/device.h>
> +#include <linux/acpi.h>
> +#include <linux/of.h>
> +
> +enum dev_prop_type {
> +	DEV_PROP_U8,
> +	DEV_PROP_U16,
> +	DEV_PROP_U32,
> +	DEV_PROP_U64,
> +	DEV_PROP_STRING,
> +	DEV_PROP_MAX,
> +};
> +
> +struct dev_prop_ops {
> +	int (*get)(struct device *dev, const char *propname, void **valptr);
> +	int (*read)(struct device *dev, const char *propname,
> +		    enum dev_prop_type proptype, void *val);
> +	int (*read_array)(struct device *dev, const char *propname,
> +			  enum dev_prop_type proptype, void *val, size_t nval);

The associated DT functions that implement property reads
(of_property_read_*) were created in part to provide some type safety
when reading properties. This proposed API throws that away by accepting
a void* for the data field, which I don't want to do. This API either
needs to have a separate accessor for each data type, or it needs some
other mechanism (accessor macros?) to ensure the right type is passed
in.

> +	int (*child_count)(struct device *dev);
> +};
> +
> +#ifdef CONFIG_ACPI
> +extern struct dev_prop_ops acpi_property_ops;
> +#endif

Rendered moot by my comment about eliminating the ops structure, but the
above shouldn't appear here. acpi_property_ops shouldn't ever be visible
outside ACPI core code, so it shouldn't be in this header.

> +
> +int device_property_get(struct device *dev, const char *propname,
> +			void **valptr);
> +int device_property_read(struct device *dev, const char *propname,
> +			 enum dev_prop_type proptype, void *val);
> +int device_property_read_array(struct device *dev, const char *propname,
> +			       enum dev_prop_type proptype, void *val,
> +			       size_t nval);
> +int device_property_child_count(struct device *dev);
> +
> +#endif /* _LINUX_PROPERTY_H_ */
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
  2014-08-17  6:04 ` [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node Mika Westerberg
@ 2014-08-17 12:54     ` Grant Likely
  2014-08-18  0:44   ` Rob Herring
  1 sibling, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 12:54 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

On Sun, 17 Aug 2014 09:04:14 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> With the unified device properties interface in place, add device tree support.
> By adding the dev_prop_ops for of_node devices, drivers can access properties
> from ACPI or Device Tree in a generic way.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Hi Mika,

As commented on patch 3, the new API currently throws away type
information so the compiler won't warn on an error. That needs to be
fixed and this patch reworked accordingly.

g.

---
>  drivers/of/base.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/of/platform.c    |   4 +-
>  include/linux/property.h |   4 +
>  3 files changed, 200 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index b9864806e9b8..527004d01423 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -20,7 +20,7 @@
>  #include <linux/ctype.h>
>  #include <linux/cpu.h>
>  #include <linux/module.h>
> -#include <linux/of.h>
> +#include <linux/property.h>
>  #include <linux/of_graph.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
> @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
>  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;
> +}

Considering we don't even have a user of u64 arrays in all of the DT
drivers, do we even need this type hook in the generic API?

> +
> +/**
>   * 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.
> @@ -1490,6 +1523,47 @@ int of_property_count_strings(struct device_node *np, const char *propname)
>  }
>  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 -EILSEQ 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 -EILSEQ;
> +
> +	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;
> @@ -2376,3 +2450,121 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +static int of_dev_prop_get(struct device *dev, const char *propname,
> +			   void **valptr)
> +{
> +	struct property *pp = of_find_property(dev->of_node, propname, NULL);
> +
> +	if (!pp)
> +		return -ENODATA;
> +
> +	if (valptr)
> +		*valptr = pp->value;
> +	return 0;
> +}
> +
> +static int of_dev_prop_read(struct device *dev, const char *propname,
> +			    enum dev_prop_type proptype, void *val)
> +{
> +	void *value;
> +	int ret = of_dev_prop_get(dev, 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;
> +
> +}
> +
> +static int of_dev_prop_read_array(struct device *dev, 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(dev->of_node,
> +							 propname);
> +		default:
> +			return -EINVAL;
> +		}
> +		return of_property_count_elems_of_size(dev->of_node, propname,
> +						       elem_size);
> +	}
> +
> +	switch (proptype) {
> +	case DEV_PROP_U8:
> +		ret = of_property_read_u8_array(dev->of_node, propname,
> +						(u8 *)val, nval);
> +		break;
> +	case DEV_PROP_U16:
> +		ret = of_property_read_u16_array(dev->of_node, propname,
> +						 (u16 *)val, nval);
> +		break;
> +	case DEV_PROP_U32:
> +		ret = of_property_read_u32_array(dev->of_node, propname,
> +						 (u32 *)val, nval);
> +		break;
> +	case DEV_PROP_U64:
> +		ret = of_property_read_u64_array(dev->of_node, propname,
> +						 (u64 *)val, nval);
> +		break;
> +	case DEV_PROP_STRING:
> +		ret = of_property_read_string_array(dev->of_node, propname,
> +						    (char **)val, nval);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static int of_dev_get_child_count(struct device *dev)
> +{
> +	struct device_node *node = dev->of_node;
> +
> +	if (!node)
> +		return -EINVAL;
> +	return of_get_child_count(node);
> +}
> +
> +struct dev_prop_ops of_property_ops = {
> +	.get = of_dev_prop_get,
> +	.read = of_dev_prop_read,
> +	.read_array = of_dev_prop_read_array,
> +	.child_count = of_dev_get_child_count,
> +};
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 500436f9be7f..3113d3704eff 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -14,7 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/module.h>
>  #include <linux/amba/bus.h>
> -#include <linux/device.h>
> +#include <linux/property.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/slab.h>
>  #include <linux/of_address.h>
> @@ -138,6 +138,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
>  	}
>  
>  	dev->dev.of_node = of_node_get(np);
> +	dev->dev.property_ops = &of_property_ops;
>  	dev->dev.parent = parent;
>  
>  	if (bus_id)
> @@ -293,6 +294,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>  	/* setup generic device info */
>  	dev->dev.coherent_dma_mask = ~0;
>  	dev->dev.of_node = of_node_get(node);
> +	dev->dev.property_ops = &of_property_ops;
>  	dev->dev.parent = parent;
>  	dev->dev.platform_data = platform_data;
>  	if (bus_id)
> diff --git a/include/linux/property.h b/include/linux/property.h
> index 52ea7fe7fe09..a840c1784c82 100644
> --- a/include/linux/property.h
> +++ b/include/linux/property.h
> @@ -38,6 +38,10 @@ struct dev_prop_ops {
>  extern struct dev_prop_ops acpi_property_ops;
>  #endif
>  
> +#ifdef CONFIG_OF
> +extern struct dev_prop_ops of_property_ops;
> +#endif
> +
>  int device_property_get(struct device *dev, const char *propname,
>  			void **valptr);
>  int device_property_read(struct device *dev, const char *propname,
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
@ 2014-08-17 12:54     ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 12:54 UTC (permalink / raw)
  To: Mika Westerberg, Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

On Sun, 17 Aug 2014 09:04:14 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> With the unified device properties interface in place, add device tree support.
> By adding the dev_prop_ops for of_node devices, drivers can access properties
> from ACPI or Device Tree in a generic way.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>

Hi Mika,

As commented on patch 3, the new API currently throws away type
information so the compiler won't warn on an error. That needs to be
fixed and this patch reworked accordingly.

g.

---
>  drivers/of/base.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/of/platform.c    |   4 +-
>  include/linux/property.h |   4 +
>  3 files changed, 200 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index b9864806e9b8..527004d01423 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -20,7 +20,7 @@
>  #include <linux/ctype.h>
>  #include <linux/cpu.h>
>  #include <linux/module.h>
> -#include <linux/of.h>
> +#include <linux/property.h>
>  #include <linux/of_graph.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
> @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
>  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;
> +}

Considering we don't even have a user of u64 arrays in all of the DT
drivers, do we even need this type hook in the generic API?

> +
> +/**
>   * 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.
> @@ -1490,6 +1523,47 @@ int of_property_count_strings(struct device_node *np, const char *propname)
>  }
>  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 -EILSEQ 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 -EILSEQ;
> +
> +	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;
> @@ -2376,3 +2450,121 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +static int of_dev_prop_get(struct device *dev, const char *propname,
> +			   void **valptr)
> +{
> +	struct property *pp = of_find_property(dev->of_node, propname, NULL);
> +
> +	if (!pp)
> +		return -ENODATA;
> +
> +	if (valptr)
> +		*valptr = pp->value;
> +	return 0;
> +}
> +
> +static int of_dev_prop_read(struct device *dev, const char *propname,
> +			    enum dev_prop_type proptype, void *val)
> +{
> +	void *value;
> +	int ret = of_dev_prop_get(dev, 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;
> +
> +}
> +
> +static int of_dev_prop_read_array(struct device *dev, 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(dev->of_node,
> +							 propname);
> +		default:
> +			return -EINVAL;
> +		}
> +		return of_property_count_elems_of_size(dev->of_node, propname,
> +						       elem_size);
> +	}
> +
> +	switch (proptype) {
> +	case DEV_PROP_U8:
> +		ret = of_property_read_u8_array(dev->of_node, propname,
> +						(u8 *)val, nval);
> +		break;
> +	case DEV_PROP_U16:
> +		ret = of_property_read_u16_array(dev->of_node, propname,
> +						 (u16 *)val, nval);
> +		break;
> +	case DEV_PROP_U32:
> +		ret = of_property_read_u32_array(dev->of_node, propname,
> +						 (u32 *)val, nval);
> +		break;
> +	case DEV_PROP_U64:
> +		ret = of_property_read_u64_array(dev->of_node, propname,
> +						 (u64 *)val, nval);
> +		break;
> +	case DEV_PROP_STRING:
> +		ret = of_property_read_string_array(dev->of_node, propname,
> +						    (char **)val, nval);
> +		break;
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +	return ret;
> +}
> +
> +static int of_dev_get_child_count(struct device *dev)
> +{
> +	struct device_node *node = dev->of_node;
> +
> +	if (!node)
> +		return -EINVAL;
> +	return of_get_child_count(node);
> +}
> +
> +struct dev_prop_ops of_property_ops = {
> +	.get = of_dev_prop_get,
> +	.read = of_dev_prop_read,
> +	.read_array = of_dev_prop_read_array,
> +	.child_count = of_dev_get_child_count,
> +};
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 500436f9be7f..3113d3704eff 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -14,7 +14,7 @@
>  #include <linux/errno.h>
>  #include <linux/module.h>
>  #include <linux/amba/bus.h>
> -#include <linux/device.h>
> +#include <linux/property.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/slab.h>
>  #include <linux/of_address.h>
> @@ -138,6 +138,7 @@ struct platform_device *of_device_alloc(struct device_node *np,
>  	}
>  
>  	dev->dev.of_node = of_node_get(np);
> +	dev->dev.property_ops = &of_property_ops;
>  	dev->dev.parent = parent;
>  
>  	if (bus_id)
> @@ -293,6 +294,7 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
>  	/* setup generic device info */
>  	dev->dev.coherent_dma_mask = ~0;
>  	dev->dev.of_node = of_node_get(node);
> +	dev->dev.property_ops = &of_property_ops;
>  	dev->dev.parent = parent;
>  	dev->dev.platform_data = platform_data;
>  	if (bus_id)
> diff --git a/include/linux/property.h b/include/linux/property.h
> index 52ea7fe7fe09..a840c1784c82 100644
> --- a/include/linux/property.h
> +++ b/include/linux/property.h
> @@ -38,6 +38,10 @@ struct dev_prop_ops {
>  extern struct dev_prop_ops acpi_property_ops;
>  #endif
>  
> +#ifdef CONFIG_OF
> +extern struct dev_prop_ops of_property_ops;
> +#endif
> +
>  int device_property_get(struct device *dev, const char *propname,
>  			void **valptr);
>  int device_property_read(struct device *dev, const char *propname,
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-17  6:04     ` Mika Westerberg
@ 2014-08-17 13:00       ` Grant Likely
  -1 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 13:00 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

On Sun, 17 Aug 2014 09:04:16 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> Add a new API to get the GPIO's description pointer and its flags for
> both OF based system and ACPI based system. This is useful in drivers
> that do not need to care about the underlying firmware interface.

Hi Mika,

I've only looked at this one briefly, and noticed one problem below...

g.

> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Max Eliaser <max.eliaser@intel.com>
> 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>
> ---
>  drivers/gpio/gpiolib-acpi.c   | 81 ++++++++++++++++++++++++++++++++-----------
>  drivers/gpio/gpiolib.c        | 18 ++++++++++
>  drivers/gpio/gpiolib.h        |  8 +++++
>  include/linux/gpio/consumer.h | 11 ++++++
>  4 files changed, 97 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
> index 4a987917c186..f35e88d29a47 100644
> --- a/drivers/gpio/gpiolib-acpi.c
> +++ b/drivers/gpio/gpiolib-acpi.c
> @@ -293,11 +293,38 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
>  		lookup->info.active_low =
>  			agpio->polarity == ACPI_ACTIVE_LOW;
> +		lookup->info.pin_config = agpio->pin_config;
>  	}
>  
>  	return 1;
>  }
>  
> +static struct gpio_desc *
> +__acpi_get_gpiod_by_index(struct acpi_device *adev, int index,
> +			  struct acpi_gpio_info *info)
> +{
> +	struct acpi_gpio_lookup lookup;
> +	struct list_head resource_list;
> +	int ret;
> +
> +	memset(&lookup, 0, sizeof(lookup));
> +	lookup.index = index;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
> +				     &lookup);
> +	if (ret < 0)
> +		return ERR_PTR(ret);
> +
> +	acpi_dev_free_resource_list(&resource_list);
> +
> +	if (lookup.desc && info)
> +		*info = lookup.info;
> +
> +	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
> +}
> +
> +
>  /**
>   * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
>   * @dev: pointer to a device to get GPIO from
> @@ -318,34 +345,46 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
>  					  struct acpi_gpio_info *info)
>  {
> -	struct acpi_gpio_lookup lookup;
> -	struct list_head resource_list;
> -	struct acpi_device *adev;
> -	acpi_handle handle;
> -	int ret;
> -
> -	if (!dev)
> +	if (!dev || !ACPI_COMPANION(dev))
>  		return ERR_PTR(-EINVAL);
> +	return __acpi_get_gpiod_by_index(ACPI_COMPANION(dev), index, info);
> +}
>  
> -	handle = ACPI_HANDLE(dev);
> -	if (!handle || acpi_bus_get_device(handle, &adev))
> -		return ERR_PTR(-ENODEV);
> -
> -	memset(&lookup, 0, sizeof(lookup));
> -	lookup.index = index;
> +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int idx,
> +				       enum gpio_lookup_flags *flags)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +	struct acpi_reference_args args;
> +	struct acpi_gpio_info info;
> +	struct gpio_desc *desc;
> +	bool active_low;
> +	int ret;
>  
> -	INIT_LIST_HEAD(&resource_list);
> -	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
> -				     &lookup);
> -	if (ret < 0)
> +	ret = acpi_dev_get_property_reference(adev, "gpios", NULL, idx, &args);
> +	if (ret)
>  		return ERR_PTR(ret);
>  
> -	acpi_dev_free_resource_list(&resource_list);
> +	desc = __acpi_get_gpiod_by_index(args.adev, args.args[0], &info);
> +	if (IS_ERR(desc))
> +		return desc;
>  
> -	if (lookup.desc && info)
> -		*info = lookup.info;
> +	/*
> +	 * The 3rd argument optionally specifies the pin polarity. We
> +	 * use that if it exists, otherwise we resort to the pin config.
> +	 * (Note that the first element of the "gpios" package goes into
> +	 * arg.adev, not args.args.)
> +	 */
> +	if (args.nargs >= 3)
> +		active_low = !!args.args[2];
> +	else if (info.gpioint)
> +		active_low = !!info.active_low;
> +	else
> +		active_low = !!(info.pin_config & ACPI_PIN_CONFIG_PULLUP);
>  
> -	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
> +	if (active_low)
> +		*flags |= GPIO_ACTIVE_LOW;
> +
> +	return desc;
>  }
>  
>  static acpi_status
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index 2ebc9071e354..e6c2413a6fbf 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -2644,6 +2644,24 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
>  	return desc;
>  }
>  
> +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
> +				      enum gpio_lookup_flags *flags)
> +{
> +	struct gpio_desc *desc = ERR_PTR(-ENOENT);
> +
> +	if (!dev || !flags)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* Using device tree? */
> +	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> +		desc = of_find_gpio(dev, NULL, idx, flags);

of_find_gpio() doesn't exist.

> +	else if (IS_ENABLED(CONFIG_ACPI) && ACPI_COMPANION(dev))
> +		desc = acpi_get_gpiod_flags(dev, idx, flags);
> +
> +	return desc;
> +}
> +EXPORT_SYMBOL(dev_get_gpiod_flags);
> +
>  static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
>  {
>  	const char *dev_id = dev ? dev_name(dev) : NULL;
> diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
> index 1a4103dd38df..a759db968e51 100644
> --- a/drivers/gpio/gpiolib.h
> +++ b/drivers/gpio/gpiolib.h
> @@ -25,6 +25,7 @@ enum of_gpio_flags;
>  struct acpi_gpio_info {
>  	bool gpioint;
>  	bool active_low;
> +	u8 pin_config;
>  };
>  
>  #ifdef CONFIG_ACPI
> @@ -33,6 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
>  
>  struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
>  					  struct acpi_gpio_info *info);
> +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
> +				       enum gpio_lookup_flags *flags);
>  #else
>  static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
>  static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
> @@ -43,6 +46,11 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
>  {
>  	return ERR_PTR(-ENOSYS);
>  }
> +static struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
> +					      enum gpio_lookup_flags *flags)
> +{
> +	return ERR_PTR(-ENOSYS);
> +}
>  #endif
>  
>  int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
> diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
> index 05e53ccb708b..53f422e4f0c9 100644
> --- a/include/linux/gpio/consumer.h
> +++ b/include/linux/gpio/consumer.h
> @@ -7,6 +7,8 @@
>  
>  struct device;
>  
> +enum gpio_lookup_flags;
> +
>  /**
>   * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
>   * preferable to the old integer-based handles.
> @@ -73,6 +75,9 @@ 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);
>  
> +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
> +				      enum gpio_lookup_flags *flags);
> +
>  #else /* CONFIG_GPIOLIB */
>  
>  static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
> @@ -254,6 +259,12 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
>  	return -EINVAL;
>  }
>  
> +static inline struct gpio_desc *dev_get_gpiod_flags(struct device *dev,
> +			unsigned int idx, enum gpio_lookup_flags *flags)
> +{
> +	return ERR_PTR(-ENOSYS);
> +}
> +
>  
>  #endif /* CONFIG_GPIOLIB */
>  
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
@ 2014-08-17 13:00       ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-17 13:00 UTC (permalink / raw)
  To: Mika Westerberg, Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, Mika Westerberg, linux-acpi, devicetree,
	linux-kernel

On Sun, 17 Aug 2014 09:04:16 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> Add a new API to get the GPIO's description pointer and its flags for
> both OF based system and ACPI based system. This is useful in drivers
> that do not need to care about the underlying firmware interface.

Hi Mika,

I've only looked at this one briefly, and noticed one problem below...

g.

> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Max Eliaser <max.eliaser@intel.com>
> 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>
> ---
>  drivers/gpio/gpiolib-acpi.c   | 81 ++++++++++++++++++++++++++++++++-----------
>  drivers/gpio/gpiolib.c        | 18 ++++++++++
>  drivers/gpio/gpiolib.h        |  8 +++++
>  include/linux/gpio/consumer.h | 11 ++++++
>  4 files changed, 97 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
> index 4a987917c186..f35e88d29a47 100644
> --- a/drivers/gpio/gpiolib-acpi.c
> +++ b/drivers/gpio/gpiolib-acpi.c
> @@ -293,11 +293,38 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  			agpio->connection_type == ACPI_RESOURCE_GPIO_TYPE_INT;
>  		lookup->info.active_low =
>  			agpio->polarity == ACPI_ACTIVE_LOW;
> +		lookup->info.pin_config = agpio->pin_config;
>  	}
>  
>  	return 1;
>  }
>  
> +static struct gpio_desc *
> +__acpi_get_gpiod_by_index(struct acpi_device *adev, int index,
> +			  struct acpi_gpio_info *info)
> +{
> +	struct acpi_gpio_lookup lookup;
> +	struct list_head resource_list;
> +	int ret;
> +
> +	memset(&lookup, 0, sizeof(lookup));
> +	lookup.index = index;
> +
> +	INIT_LIST_HEAD(&resource_list);
> +	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
> +				     &lookup);
> +	if (ret < 0)
> +		return ERR_PTR(ret);
> +
> +	acpi_dev_free_resource_list(&resource_list);
> +
> +	if (lookup.desc && info)
> +		*info = lookup.info;
> +
> +	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
> +}
> +
> +
>  /**
>   * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources
>   * @dev: pointer to a device to get GPIO from
> @@ -318,34 +345,46 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data)
>  struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
>  					  struct acpi_gpio_info *info)
>  {
> -	struct acpi_gpio_lookup lookup;
> -	struct list_head resource_list;
> -	struct acpi_device *adev;
> -	acpi_handle handle;
> -	int ret;
> -
> -	if (!dev)
> +	if (!dev || !ACPI_COMPANION(dev))
>  		return ERR_PTR(-EINVAL);
> +	return __acpi_get_gpiod_by_index(ACPI_COMPANION(dev), index, info);
> +}
>  
> -	handle = ACPI_HANDLE(dev);
> -	if (!handle || acpi_bus_get_device(handle, &adev))
> -		return ERR_PTR(-ENODEV);
> -
> -	memset(&lookup, 0, sizeof(lookup));
> -	lookup.index = index;
> +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int idx,
> +				       enum gpio_lookup_flags *flags)
> +{
> +	struct acpi_device *adev = ACPI_COMPANION(dev);
> +	struct acpi_reference_args args;
> +	struct acpi_gpio_info info;
> +	struct gpio_desc *desc;
> +	bool active_low;
> +	int ret;
>  
> -	INIT_LIST_HEAD(&resource_list);
> -	ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio,
> -				     &lookup);
> -	if (ret < 0)
> +	ret = acpi_dev_get_property_reference(adev, "gpios", NULL, idx, &args);
> +	if (ret)
>  		return ERR_PTR(ret);
>  
> -	acpi_dev_free_resource_list(&resource_list);
> +	desc = __acpi_get_gpiod_by_index(args.adev, args.args[0], &info);
> +	if (IS_ERR(desc))
> +		return desc;
>  
> -	if (lookup.desc && info)
> -		*info = lookup.info;
> +	/*
> +	 * The 3rd argument optionally specifies the pin polarity. We
> +	 * use that if it exists, otherwise we resort to the pin config.
> +	 * (Note that the first element of the "gpios" package goes into
> +	 * arg.adev, not args.args.)
> +	 */
> +	if (args.nargs >= 3)
> +		active_low = !!args.args[2];
> +	else if (info.gpioint)
> +		active_low = !!info.active_low;
> +	else
> +		active_low = !!(info.pin_config & ACPI_PIN_CONFIG_PULLUP);
>  
> -	return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT);
> +	if (active_low)
> +		*flags |= GPIO_ACTIVE_LOW;
> +
> +	return desc;
>  }
>  
>  static acpi_status
> diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
> index 2ebc9071e354..e6c2413a6fbf 100644
> --- a/drivers/gpio/gpiolib.c
> +++ b/drivers/gpio/gpiolib.c
> @@ -2644,6 +2644,24 @@ static struct gpio_desc *acpi_find_gpio(struct device *dev, const char *con_id,
>  	return desc;
>  }
>  
> +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
> +				      enum gpio_lookup_flags *flags)
> +{
> +	struct gpio_desc *desc = ERR_PTR(-ENOENT);
> +
> +	if (!dev || !flags)
> +		return ERR_PTR(-EINVAL);
> +
> +	/* Using device tree? */
> +	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> +		desc = of_find_gpio(dev, NULL, idx, flags);

of_find_gpio() doesn't exist.

> +	else if (IS_ENABLED(CONFIG_ACPI) && ACPI_COMPANION(dev))
> +		desc = acpi_get_gpiod_flags(dev, idx, flags);
> +
> +	return desc;
> +}
> +EXPORT_SYMBOL(dev_get_gpiod_flags);
> +
>  static struct gpiod_lookup_table *gpiod_find_lookup_table(struct device *dev)
>  {
>  	const char *dev_id = dev ? dev_name(dev) : NULL;
> diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h
> index 1a4103dd38df..a759db968e51 100644
> --- a/drivers/gpio/gpiolib.h
> +++ b/drivers/gpio/gpiolib.h
> @@ -25,6 +25,7 @@ enum of_gpio_flags;
>  struct acpi_gpio_info {
>  	bool gpioint;
>  	bool active_low;
> +	u8 pin_config;
>  };
>  
>  #ifdef CONFIG_ACPI
> @@ -33,6 +34,8 @@ void acpi_gpiochip_remove(struct gpio_chip *chip);
>  
>  struct gpio_desc *acpi_get_gpiod_by_index(struct device *dev, int index,
>  					  struct acpi_gpio_info *info);
> +struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
> +				       enum gpio_lookup_flags *flags);
>  #else
>  static inline void acpi_gpiochip_add(struct gpio_chip *chip) { }
>  static inline void acpi_gpiochip_remove(struct gpio_chip *chip) { }
> @@ -43,6 +46,11 @@ acpi_get_gpiod_by_index(struct device *dev, int index,
>  {
>  	return ERR_PTR(-ENOSYS);
>  }
> +static struct gpio_desc *acpi_get_gpiod_flags(struct device *dev, int index,
> +					      enum gpio_lookup_flags *flags)
> +{
> +	return ERR_PTR(-ENOSYS);
> +}
>  #endif
>  
>  int gpiochip_request_own_desc(struct gpio_desc *desc, const char *label);
> diff --git a/include/linux/gpio/consumer.h b/include/linux/gpio/consumer.h
> index 05e53ccb708b..53f422e4f0c9 100644
> --- a/include/linux/gpio/consumer.h
> +++ b/include/linux/gpio/consumer.h
> @@ -7,6 +7,8 @@
>  
>  struct device;
>  
> +enum gpio_lookup_flags;
> +
>  /**
>   * Opaque descriptor for a GPIO. These are obtained using gpiod_get() and are
>   * preferable to the old integer-based handles.
> @@ -73,6 +75,9 @@ 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);
>  
> +struct gpio_desc *dev_get_gpiod_flags(struct device *dev, unsigned int idx,
> +				      enum gpio_lookup_flags *flags);
> +
>  #else /* CONFIG_GPIOLIB */
>  
>  static inline struct gpio_desc *__must_check gpiod_get(struct device *dev,
> @@ -254,6 +259,12 @@ static inline int desc_to_gpio(const struct gpio_desc *desc)
>  	return -EINVAL;
>  }
>  
> +static inline struct gpio_desc *dev_get_gpiod_flags(struct device *dev,
> +			unsigned int idx, enum gpio_lookup_flags *flags)
> +{
> +	return ERR_PTR(-ENOSYS);
> +}
> +
>  
>  #endif /* CONFIG_GPIOLIB */
>  
> -- 
> 2.1.0.rc1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/


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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
  2014-08-17 12:49     ` Grant Likely
@ 2014-08-17 17:31       ` Darren Hart
  -1 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-17 17:31 UTC (permalink / raw)
  To: Grant Likely, Mika Westerberg, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

On 8/17/14, 5:49, "Grant Likely" <grant.likely@secretlab.ca> wrote:

>
>Hi Mika and Rafael,
>
>Comments below...
>
>On Sun, 17 Aug 2014 09:04:13 +0300, Mika Westerberg
><mika.westerberg@linux.intel.com> wrote:
>> 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.
>> 
>> Three general helper functions, device_property_get(),
>> device_property_read() and device_property_read_array() are provided.
>> The first one allows the raw value of a given device property to be
>> accessed by the driver.  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.
>> 
>> The interface is supposed to cover both ACPI and Device Trees,
>> although the ACPI part is only implemented at this time.
>
>Nit:
>s/at this time/in this change. The DT component is implemented in a
>subsequent patch./
>
>I almost complained that the DT portion must be implemented before this
>series can even be considered, but then I found it in patch 4/9.  :-)
>
>> 
>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
>> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
>> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> ---
>>  drivers/acpi/glue.c      |   4 +-
>>  drivers/acpi/property.c  | 179
>>++++++++++++++++++++++++++++++++++++++++++++++-
>>  drivers/acpi/scan.c      |  12 +++-
>>  drivers/base/Makefile    |   2 +-
>>  drivers/base/property.c  |  48 +++++++++++++
>>  include/acpi/acpi_bus.h  |   1 +
>>  include/linux/device.h   |   3 +
>>  include/linux/property.h |  50 +++++++++++++
>>  8 files changed, 293 insertions(+), 6 deletions(-)
>>  create mode 100644 drivers/base/property.c
>>  create mode 100644 include/linux/property.h
>> 

...

>>
>>  static void acpi_device_del(struct acpi_device *device)
>>  {
>>  	mutex_lock(&acpi_device_lock);
>> -	if (device->parent)
>> +	if (device->parent) {
>>  		list_del(&device->node);
>> +		device->parent->child_count--;
>
>I worry about housekeeping like this. It is easy for bugs to slip in.
>Unless returning the child count is in a critical path (which it
>shouldn't be), I would drop the child_count member and simply count the
>number of items in the list when required.
>
>This of course is not my subsystem, so I won't ACK or NACK the patch over
>this.


This would be consistent with of_get_child_count() and is unlikely to be
called much more than once per device. The maintenance however is limited
to the add/del functions, so it doesn't seem difficult to maintain. I have
no objections to just walking the list though if that is preferable.

...

>> @@ -701,6 +702,7 @@ struct acpi_dev_node {
>>   * @archdata:	For arch-specific additions.
>>   * @of_node:	Associated device tree node.
>>   * @acpi_node:	Associated ACPI device node.
>> + * @property_ops: Firmware interface for device properties
>>   * @devt:	For creating the sysfs "dev".
>>   * @id:		device instance
>>   * @devres_lock: Spinlock to protect the resource of the device.
>> @@ -777,6 +779,7 @@ struct device {
>>  
>>  	struct device_node	*of_node; /* associated device tree node */
>>  	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
>> +	struct dev_prop_ops	*property_ops;
>
>There are only 2 users of this interface. I don't think adding an ops
>pointer to each and every struct device is warrented when the wrapper
>function can check if of_node or acpi_node is set and call the
>appropriate helper. It is unlikely anything else will use this hook. It
>will result in smaller memory footprint. Also smaller code when only one
>of
>CONFIG_OF and CONFIG_ACPI are selected, which is almost always. :-)
>
>It can be refactored later if that ever changes.


Our intent was to eliminate the #ifdefery in every one of the accessors.
It was my understanding the ops structures were preferable in such
situations. For a 64-bit machine with 1000 devices (all of which use
device properties) with one or the other of ACPI/OF enabled, the
additional memory requirement here is what... Something like (8*1000 + 4)
~= 8KB ? That seems worth the arguably more maintainable code to me. Is
there more to it than this, am I missing some more significant impact?

  
>>  	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
>>  	u32			id;	/* device instance */
>> diff --git a/include/linux/property.h b/include/linux/property.h
>> new file mode 100644
>> index 000000000000..52ea7fe7fe09
>> --- /dev/null
>> +++ b/include/linux/property.h
>> @@ -0,0 +1,50 @@
>> +/*
>> + * property.h - Unified device property interface.
>> + *
>> + * Copyright (C) 2014, Intel Corporation
>> + * Author: 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.
>> + */
>> +
>> +#ifndef _LINUX_PROPERTY_H_
>> +#define _LINUX_PROPERTY_H_
>> +
>> +#include <linux/device.h>
>> +#include <linux/acpi.h>
>> +#include <linux/of.h>
>> +
>> +enum dev_prop_type {
>> +	DEV_PROP_U8,
>> +	DEV_PROP_U16,
>> +	DEV_PROP_U32,
>> +	DEV_PROP_U64,
>> +	DEV_PROP_STRING,
>> +	DEV_PROP_MAX,
>> +};
>> +
>> +struct dev_prop_ops {
>> +	int (*get)(struct device *dev, const char *propname, void **valptr);
>> +	int (*read)(struct device *dev, const char *propname,
>> +		    enum dev_prop_type proptype, void *val);
>> +	int (*read_array)(struct device *dev, const char *propname,
>> +			  enum dev_prop_type proptype, void *val, size_t nval);
>
>The associated DT functions that implement property reads
>(of_property_read_*) were created in part to provide some type safety
>when reading properties. This proposed API throws that away by accepting
>a void* for the data field, which I don't want to do. This API either
>needs to have a separate accessor for each data type, or it needs some
>other mechanism (accessor macros?) to ensure the right type is passed
>in.


OK, this would increase the memory impact by 6-fold for 8,16,32,and 64
byte integers, strings, and device references if additional typed function
pointers were added to the dev_prop_ops. The macros could mitigate this I
suppose.

Type checking and validation was something we had discussed as being
important to this mechanism. I believe there was some interest in seeing
this done at the ASL/FDT + Schema level - but that's not justification for
maintaining it in the kernel interface as well.

Could this be addressed by adding an enum dev_prop_type to the get/read
calls similar to that of the read_array call? That would keep the call
count down, maintain the smaller memory footprint, and still allow for
type verification within the device properties API.

-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
@ 2014-08-17 17:31       ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-17 17:31 UTC (permalink / raw)
  To: Grant Likely, Mika Westerberg, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

On 8/17/14, 5:49, "Grant Likely" <grant.likely@secretlab.ca> wrote:

>
>Hi Mika and Rafael,
>
>Comments below...
>
>On Sun, 17 Aug 2014 09:04:13 +0300, Mika Westerberg
><mika.westerberg@linux.intel.com> wrote:
>> 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.
>> 
>> Three general helper functions, device_property_get(),
>> device_property_read() and device_property_read_array() are provided.
>> The first one allows the raw value of a given device property to be
>> accessed by the driver.  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.
>> 
>> The interface is supposed to cover both ACPI and Device Trees,
>> although the ACPI part is only implemented at this time.
>
>Nit:
>s/at this time/in this change. The DT component is implemented in a
>subsequent patch./
>
>I almost complained that the DT portion must be implemented before this
>series can even be considered, but then I found it in patch 4/9.  :-)
>
>> 
>> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
>> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
>> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
>> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> ---
>>  drivers/acpi/glue.c      |   4 +-
>>  drivers/acpi/property.c  | 179
>>++++++++++++++++++++++++++++++++++++++++++++++-
>>  drivers/acpi/scan.c      |  12 +++-
>>  drivers/base/Makefile    |   2 +-
>>  drivers/base/property.c  |  48 +++++++++++++
>>  include/acpi/acpi_bus.h  |   1 +
>>  include/linux/device.h   |   3 +
>>  include/linux/property.h |  50 +++++++++++++
>>  8 files changed, 293 insertions(+), 6 deletions(-)
>>  create mode 100644 drivers/base/property.c
>>  create mode 100644 include/linux/property.h
>> 

...

>>
>>  static void acpi_device_del(struct acpi_device *device)
>>  {
>>  	mutex_lock(&acpi_device_lock);
>> -	if (device->parent)
>> +	if (device->parent) {
>>  		list_del(&device->node);
>> +		device->parent->child_count--;
>
>I worry about housekeeping like this. It is easy for bugs to slip in.
>Unless returning the child count is in a critical path (which it
>shouldn't be), I would drop the child_count member and simply count the
>number of items in the list when required.
>
>This of course is not my subsystem, so I won't ACK or NACK the patch over
>this.


This would be consistent with of_get_child_count() and is unlikely to be
called much more than once per device. The maintenance however is limited
to the add/del functions, so it doesn't seem difficult to maintain. I have
no objections to just walking the list though if that is preferable.

...

>> @@ -701,6 +702,7 @@ struct acpi_dev_node {
>>   * @archdata:	For arch-specific additions.
>>   * @of_node:	Associated device tree node.
>>   * @acpi_node:	Associated ACPI device node.
>> + * @property_ops: Firmware interface for device properties
>>   * @devt:	For creating the sysfs "dev".
>>   * @id:		device instance
>>   * @devres_lock: Spinlock to protect the resource of the device.
>> @@ -777,6 +779,7 @@ struct device {
>>  
>>  	struct device_node	*of_node; /* associated device tree node */
>>  	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
>> +	struct dev_prop_ops	*property_ops;
>
>There are only 2 users of this interface. I don't think adding an ops
>pointer to each and every struct device is warrented when the wrapper
>function can check if of_node or acpi_node is set and call the
>appropriate helper. It is unlikely anything else will use this hook. It
>will result in smaller memory footprint. Also smaller code when only one
>of
>CONFIG_OF and CONFIG_ACPI are selected, which is almost always. :-)
>
>It can be refactored later if that ever changes.


Our intent was to eliminate the #ifdefery in every one of the accessors.
It was my understanding the ops structures were preferable in such
situations. For a 64-bit machine with 1000 devices (all of which use
device properties) with one or the other of ACPI/OF enabled, the
additional memory requirement here is what... Something like (8*1000 + 4)
~= 8KB ? That seems worth the arguably more maintainable code to me. Is
there more to it than this, am I missing some more significant impact?

  
>>  	dev_t			devt;	/* dev_t, creates the sysfs "dev" */
>>  	u32			id;	/* device instance */
>> diff --git a/include/linux/property.h b/include/linux/property.h
>> new file mode 100644
>> index 000000000000..52ea7fe7fe09
>> --- /dev/null
>> +++ b/include/linux/property.h
>> @@ -0,0 +1,50 @@
>> +/*
>> + * property.h - Unified device property interface.
>> + *
>> + * Copyright (C) 2014, Intel Corporation
>> + * Author: 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.
>> + */
>> +
>> +#ifndef _LINUX_PROPERTY_H_
>> +#define _LINUX_PROPERTY_H_
>> +
>> +#include <linux/device.h>
>> +#include <linux/acpi.h>
>> +#include <linux/of.h>
>> +
>> +enum dev_prop_type {
>> +	DEV_PROP_U8,
>> +	DEV_PROP_U16,
>> +	DEV_PROP_U32,
>> +	DEV_PROP_U64,
>> +	DEV_PROP_STRING,
>> +	DEV_PROP_MAX,
>> +};
>> +
>> +struct dev_prop_ops {
>> +	int (*get)(struct device *dev, const char *propname, void **valptr);
>> +	int (*read)(struct device *dev, const char *propname,
>> +		    enum dev_prop_type proptype, void *val);
>> +	int (*read_array)(struct device *dev, const char *propname,
>> +			  enum dev_prop_type proptype, void *val, size_t nval);
>
>The associated DT functions that implement property reads
>(of_property_read_*) were created in part to provide some type safety
>when reading properties. This proposed API throws that away by accepting
>a void* for the data field, which I don't want to do. This API either
>needs to have a separate accessor for each data type, or it needs some
>other mechanism (accessor macros?) to ensure the right type is passed
>in.


OK, this would increase the memory impact by 6-fold for 8,16,32,and 64
byte integers, strings, and device references if additional typed function
pointers were added to the dev_prop_ops. The macros could mitigate this I
suppose.

Type checking and validation was something we had discussed as being
important to this mechanism. I believe there was some interest in seeing
this done at the ASL/FDT + Schema level - but that's not justification for
maintaining it in the kernel interface as well.

Could this be addressed by adding an enum dev_prop_type to the get/read
calls similar to that of the read_array call? That would keep the call
count down, maintain the smaller memory footprint, and still allow for
type verification within the device properties API.

-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-17 13:00       ` Grant Likely
@ 2014-08-17 17:43         ` Darren Hart
  -1 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-17 17:43 UTC (permalink / raw)
  To: Grant Likely, Mika Westerberg, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

On 8/17/14, 6:00, "Grant Likely" <grant.likely@secretlab.ca> wrote:

>>
>>+	/* Using device tree? */
>>+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
>>+		desc = of_find_gpio(dev, NULL, idx, flags);
>
>of_find_gpio() doesn't exist.

Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)

$ git blame -L1455,1456 drivers/gpio/gpiolib.c
bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
gpio_desc *of_find_gpio(struct device *dev, const char *con_id,

Have we removed this in -next or something? (on the plane, will verify
upon landing)



-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation

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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
@ 2014-08-17 17:43         ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-17 17:43 UTC (permalink / raw)
  To: Grant Likely, Mika Westerberg, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

On 8/17/14, 6:00, "Grant Likely" <grant.likely@secretlab.ca> wrote:

>>
>>+	/* Using device tree? */
>>+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
>>+		desc = of_find_gpio(dev, NULL, idx, flags);
>
>of_find_gpio() doesn't exist.

Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)

$ git blame -L1455,1456 drivers/gpio/gpiolib.c
bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
gpio_desc *of_find_gpio(struct device *dev, const char *con_id,

Have we removed this in -next or something? (on the plane, will verify
upon landing)



-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
  2014-08-17  6:04 ` [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node Mika Westerberg
  2014-08-17 12:54     ` Grant Likely
@ 2014-08-18  0:44   ` Rob Herring
  1 sibling, 0 replies; 54+ messages in thread
From: Rob Herring @ 2014-08-18  0:44 UTC (permalink / raw)
  To: Mika Westerberg, Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

On 08/17/2014 01:04 AM, Mika Westerberg wrote:
> From: Aaron Lu <aaron.lu@intel.com>
> 
> With the unified device properties interface in place, add device tree support.
> By adding the dev_prop_ops for of_node devices, drivers can access properties
> from ACPI or Device Tree in a generic way.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/of/base.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++-
>  drivers/of/platform.c    |   4 +-
>  include/linux/property.h |   4 +
>  3 files changed, 200 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index b9864806e9b8..527004d01423 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -20,7 +20,7 @@
>  #include <linux/ctype.h>
>  #include <linux/cpu.h>
>  #include <linux/module.h>
> -#include <linux/of.h>
> +#include <linux/property.h>
>  #include <linux/of_graph.h>
>  #include <linux/spinlock.h>
>  #include <linux/slab.h>
> @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
>  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)

Quite frequently the array functions have turned out to be less useful
as you often don't know how many elements you have upfront. So you end
up parsing the property twice. Using for_each iterators has been a
better fit for most users, so I'd like to see them here. We may need
both, but read_*_array can be a wrapper around for_each.

Rob


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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
  2014-08-17 12:49     ` Grant Likely
  (?)
  (?)
@ 2014-08-18  4:46     ` Rafael J. Wysocki
  -1 siblings, 0 replies; 54+ messages in thread
From: Rafael J. Wysocki @ 2014-08-18  4:46 UTC (permalink / raw)
  To: Grant Likely
  Cc: Mika Westerberg, Darren Hart, Rafael J. Wysocki, Aaron Lu,
	Max Eliaser, linux-acpi, devicetree, linux-kernel

On Sunday, August 17, 2014 01:49:13 PM Grant Likely wrote:
> 
> Hi Mika and Rafael,
> 
> Comments below...

[cut]

> > +enum dev_prop_type {
> > +	DEV_PROP_U8,
> > +	DEV_PROP_U16,
> > +	DEV_PROP_U32,
> > +	DEV_PROP_U64,
> > +	DEV_PROP_STRING,
> > +	DEV_PROP_MAX,
> > +};
> > +
> > +struct dev_prop_ops {
> > +	int (*get)(struct device *dev, const char *propname, void **valptr);
> > +	int (*read)(struct device *dev, const char *propname,
> > +		    enum dev_prop_type proptype, void *val);
> > +	int (*read_array)(struct device *dev, const char *propname,
> > +			  enum dev_prop_type proptype, void *val, size_t nval);
> 
> The associated DT functions that implement property reads
> (of_property_read_*) were created in part to provide some type safety
> when reading properties. This proposed API throws that away by accepting
> a void* for the data field, which I don't want to do. This API either
> needs to have a separate accessor for each data type, or it needs some
> other mechanism (accessor macros?) to ensure the right type is passed
> in.

The intention is to add static inline functions like:

int device_property_read_u64(struct device *dev, const char *propname, u64 *val)
{
	return device_property_read(dev, propname, DEV_PROP_U64, val);
}

and so on for the other property types.  They just have not been implemented in
this version of the patch.

> 
> > +	int (*child_count)(struct device *dev);
> > +};
> > +
> > +#ifdef CONFIG_ACPI
> > +extern struct dev_prop_ops acpi_property_ops;
> > +#endif
> 
> Rendered moot by my comment about eliminating the ops structure, but the
> above shouldn't appear here. acpi_property_ops shouldn't ever be visible
> outside ACPI core code, so it shouldn't be in this header.

It doesn't look like this has to be present here.  At least this particular
patch should compile just fine after removing the 3 lines above.

That seems to be a leftover from one of the previous versions of it.

Rafael


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

* Re: [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware
  2014-08-17 17:31       ` Darren Hart
  (?)
@ 2014-08-18  4:55       ` Rafael J. Wysocki
  -1 siblings, 0 replies; 54+ messages in thread
From: Rafael J. Wysocki @ 2014-08-18  4:55 UTC (permalink / raw)
  To: Darren Hart, Grant Likely
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Sunday, August 17, 2014 12:31:27 PM Darren Hart wrote:
> On 8/17/14, 5:49, "Grant Likely" <grant.likely@secretlab.ca> wrote:
> 
> >
> >Hi Mika and Rafael,
> >
> >Comments below...

[cut]

> ...
> 
> >> @@ -701,6 +702,7 @@ struct acpi_dev_node {
> >>   * @archdata:	For arch-specific additions.
> >>   * @of_node:	Associated device tree node.
> >>   * @acpi_node:	Associated ACPI device node.
> >> + * @property_ops: Firmware interface for device properties
> >>   * @devt:	For creating the sysfs "dev".
> >>   * @id:		device instance
> >>   * @devres_lock: Spinlock to protect the resource of the device.
> >> @@ -777,6 +779,7 @@ struct device {
> >>  
> >>  	struct device_node	*of_node; /* associated device tree node */
> >>  	struct acpi_dev_node	acpi_node; /* associated ACPI device node */
> >> +	struct dev_prop_ops	*property_ops;
> >
> >There are only 2 users of this interface. I don't think adding an ops
> >pointer to each and every struct device is warrented when the wrapper
> >function can check if of_node or acpi_node is set and call the
> >appropriate helper. It is unlikely anything else will use this hook. It
> >will result in smaller memory footprint. Also smaller code when only one
> >of
> >CONFIG_OF and CONFIG_ACPI are selected, which is almost always. :-)
> >
> >It can be refactored later if that ever changes.
> 
> 
> Our intent was to eliminate the #ifdefery in every one of the accessors.
> It was my understanding the ops structures were preferable in such
> situations. For a 64-bit machine with 1000 devices (all of which use
> device properties) with one or the other of ACPI/OF enabled, the
> additional memory requirement here is what... Something like (8*1000 + 4)
> ~= 8KB ? That seems worth the arguably more maintainable code to me. Is
> there more to it than this, am I missing some more significant impact?

Also we wanted to avoid going throug the same sequence of checks every time
a property is accessed for a given device as the result those checks would
lead to every time was already known when the device was registered.

Arguably, if we decide that using DTs and ACPI on the same system at the same
time is a total no-go, then we'll need just one global ops pointer either to
the ACPI or to the DT set of callbacks, but I'm not sure whether or not that
is the way to go.

Rafael


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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-17 17:43         ` Darren Hart
  (?)
@ 2014-08-18  4:57         ` Rafael J. Wysocki
       [not found]           ` <1927766.GeLld99ozq-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
  -1 siblings, 1 reply; 54+ messages in thread
From: Rafael J. Wysocki @ 2014-08-18  4:57 UTC (permalink / raw)
  To: Darren Hart, Grant Likely
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Sunday, August 17, 2014 12:43:38 PM Darren Hart wrote:
> On 8/17/14, 6:00, "Grant Likely" <grant.likely@secretlab.ca> wrote:
> 
> >>
> >>+	/* Using device tree? */
> >>+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> >>+		desc = of_find_gpio(dev, NULL, idx, flags);
> >
> >of_find_gpio() doesn't exist.
> 
> Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)
> 
> $ git blame -L1455,1456 drivers/gpio/gpiolib.c
> bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
> gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> 
> Have we removed this in -next or something? (on the plane, will verify
> upon landing)

In 3.17-rc1:

rafael@vostro:~/src/linux-pm> grep -r of_find_gpio *
drivers/gpio/gpiolib.c:static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
drivers/gpio/gpiolib.c:         desc = of_find_gpio(dev, con_id, idx, &lookupflags);

Rafael


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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-18  4:57         ` Rafael J. Wysocki
@ 2014-08-18  7:16               ` Aaron Lu
  0 siblings, 0 replies; 54+ messages in thread
From: Aaron Lu @ 2014-08-18  7:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Darren Hart, Grant Likely
  Cc: Mika Westerberg, Rafael J. Wysocki, Max Eliaser,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 08/18/2014 12:57 PM, Rafael J. Wysocki wrote:
> On Sunday, August 17, 2014 12:43:38 PM Darren Hart wrote:
>> On 8/17/14, 6:00, "Grant Likely" <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
>>
>>>>
>>>> +	/* Using device tree? */
>>>> +	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
>>>> +		desc = of_find_gpio(dev, NULL, idx, flags);
>>>
>>> of_find_gpio() doesn't exist.
>>
>> Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)
>>
>> $ git blame -L1455,1456 drivers/gpio/gpiolib.c
>> bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
>> gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
>>
>> Have we removed this in -next or something? (on the plane, will verify
>> upon landing)
> 
> In 3.17-rc1:
> 
> rafael@vostro:~/src/linux-pm> grep -r of_find_gpio *
> drivers/gpio/gpiolib.c:static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> drivers/gpio/gpiolib.c:         desc = of_find_gpio(dev, con_id, idx, &lookupflags);

I also verified the following branch:
git://git.secretlab.ca/git/linux devicetree/next
And of_find_gpio is there.

Regards,
Aaron
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
@ 2014-08-18  7:16               ` Aaron Lu
  0 siblings, 0 replies; 54+ messages in thread
From: Aaron Lu @ 2014-08-18  7:16 UTC (permalink / raw)
  To: Rafael J. Wysocki, Darren Hart, Grant Likely
  Cc: Mika Westerberg, Rafael J. Wysocki, Max Eliaser, linux-acpi,
	devicetree, linux-kernel

On 08/18/2014 12:57 PM, Rafael J. Wysocki wrote:
> On Sunday, August 17, 2014 12:43:38 PM Darren Hart wrote:
>> On 8/17/14, 6:00, "Grant Likely" <grant.likely@secretlab.ca> wrote:
>>
>>>>
>>>> +	/* Using device tree? */
>>>> +	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
>>>> +		desc = of_find_gpio(dev, NULL, idx, flags);
>>>
>>> of_find_gpio() doesn't exist.
>>
>> Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)
>>
>> $ git blame -L1455,1456 drivers/gpio/gpiolib.c
>> bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
>> gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
>>
>> Have we removed this in -next or something? (on the plane, will verify
>> upon landing)
> 
> In 3.17-rc1:
> 
> rafael@vostro:~/src/linux-pm> grep -r of_find_gpio *
> drivers/gpio/gpiolib.c:static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> drivers/gpio/gpiolib.c:         desc = of_find_gpio(dev, con_id, idx, &lookupflags);

I also verified the following branch:
git://git.secretlab.ca/git/linux devicetree/next
And of_find_gpio is there.

Regards,
Aaron

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

* Re: [RFC PATCH 1/9] ACPI: Add support for device specific properties
  2014-08-17  6:04 ` [RFC PATCH 1/9] ACPI: Add support for device specific properties Mika Westerberg
@ 2014-08-18  8:13   ` Hanjun Guo
  2014-08-18  8:27     ` Mika Westerberg
  0 siblings, 1 reply; 54+ messages in thread
From: Hanjun Guo @ 2014-08-18  8:13 UTC (permalink / raw)
  To: Mika Westerberg, Darren Hart, Rafael J. Wysocki
  Cc: Aaron Lu, Max Eliaser, linux-acpi, devicetree, linux-kernel

Hi,

Some minor comments below.

On 2014-8-17 14:04, Mika Westerberg wrote:
> 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
> 
> 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>
> ---
>  drivers/acpi/Makefile   |   1 +
>  drivers/acpi/internal.h |   6 +
>  drivers/acpi/property.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++
>  drivers/acpi/scan.c     |   2 +
>  include/acpi/acpi_bus.h |   7 +
>  include/linux/acpi.h    |  40 ++++++
>  6 files changed, 421 insertions(+)
>  create mode 100644 drivers/acpi/property.c
> 
> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> index ea55e0179f81..6e8269a111db 100644
> --- a/drivers/acpi/Makefile
> +++ b/drivers/acpi/Makefile
> @@ -45,6 +45,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
> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> index 7de5b603f272..35001e2a8769 100644
> --- a/drivers/acpi/internal.h
> +++ b/drivers/acpi/internal.h
> @@ -178,4 +178,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
>  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_ */
> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> new file mode 100644
> index 000000000000..093e834c35db
> --- /dev/null
> +++ b/drivers/acpi/property.c
> @@ -0,0 +1,365 @@
> +/*
> + * 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] = {

s/prp_uuid/dsd_uuid ?

> +	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)
> +{
> +

I think the above line is not needed.

With that fixed,

Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks
Hanjun

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

* Re: [RFC PATCH 1/9] ACPI: Add support for device specific properties
  2014-08-18  8:13   ` Hanjun Guo
@ 2014-08-18  8:27     ` Mika Westerberg
  2014-08-18  8:57       ` Hanjun Guo
  2014-08-18 12:37         ` Darren Hart
  0 siblings, 2 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-18  8:27 UTC (permalink / raw)
  To: Hanjun Guo
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Mon, Aug 18, 2014 at 04:13:29PM +0800, Hanjun Guo wrote:
> Hi,
> 
> Some minor comments below.
> 
> On 2014-8-17 14:04, Mika Westerberg wrote:
> > 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
> > 
> > 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>
> > ---
> >  drivers/acpi/Makefile   |   1 +
> >  drivers/acpi/internal.h |   6 +
> >  drivers/acpi/property.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++
> >  drivers/acpi/scan.c     |   2 +
> >  include/acpi/acpi_bus.h |   7 +
> >  include/linux/acpi.h    |  40 ++++++
> >  6 files changed, 421 insertions(+)
> >  create mode 100644 drivers/acpi/property.c
> > 
> > diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
> > index ea55e0179f81..6e8269a111db 100644
> > --- a/drivers/acpi/Makefile
> > +++ b/drivers/acpi/Makefile
> > @@ -45,6 +45,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
> > diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
> > index 7de5b603f272..35001e2a8769 100644
> > --- a/drivers/acpi/internal.h
> > +++ b/drivers/acpi/internal.h
> > @@ -178,4 +178,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
> >  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_ */
> > diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
> > new file mode 100644
> > index 000000000000..093e834c35db
> > --- /dev/null
> > +++ b/drivers/acpi/property.c
> > @@ -0,0 +1,365 @@
> > +/*
> > + * 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] = {
> 
> s/prp_uuid/dsd_uuid ?

Well, it is actually the _DSD UUID that implements ACPI device
properties (hence the prp_) but I have no problems in changing that to
dsd_uuid instead.

> 
> > +	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)
> > +{
> > +
> 
> I think the above line is not needed.

Right, I'll remove it.

> With that fixed,
> 
> Reviewed-by: Hanjun Guo <hanjun.guo@linaro.org>

Thanks!

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

* Re: [RFC PATCH 1/9] ACPI: Add support for device specific properties
  2014-08-18  8:27     ` Mika Westerberg
@ 2014-08-18  8:57       ` Hanjun Guo
  2014-08-18 12:37         ` Darren Hart
  1 sibling, 0 replies; 54+ messages in thread
From: Hanjun Guo @ 2014-08-18  8:57 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On 2014-8-18 16:27, Mika Westerberg wrote:
> On Mon, Aug 18, 2014 at 04:13:29PM +0800, Hanjun Guo wrote:
>> Hi,
>>
>> Some minor comments below.
>>
>> On 2014-8-17 14:04, Mika Westerberg wrote:
>>> 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
>>>
>>> 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>
>>> ---
>>>  drivers/acpi/Makefile   |   1 +
>>>  drivers/acpi/internal.h |   6 +
>>>  drivers/acpi/property.c | 365 ++++++++++++++++++++++++++++++++++++++++++++++++
>>>  drivers/acpi/scan.c     |   2 +
>>>  include/acpi/acpi_bus.h |   7 +
>>>  include/linux/acpi.h    |  40 ++++++
>>>  6 files changed, 421 insertions(+)
>>>  create mode 100644 drivers/acpi/property.c
>>>
>>> diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
>>> index ea55e0179f81..6e8269a111db 100644
>>> --- a/drivers/acpi/Makefile
>>> +++ b/drivers/acpi/Makefile
>>> @@ -45,6 +45,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
>>> diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h
>>> index 7de5b603f272..35001e2a8769 100644
>>> --- a/drivers/acpi/internal.h
>>> +++ b/drivers/acpi/internal.h
>>> @@ -178,4 +178,10 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *adev);
>>>  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_ */
>>> diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
>>> new file mode 100644
>>> index 000000000000..093e834c35db
>>> --- /dev/null
>>> +++ b/drivers/acpi/property.c
>>> @@ -0,0 +1,365 @@
>>> +/*
>>> + * 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] = {
>>
>> s/prp_uuid/dsd_uuid ?
> 
> Well, it is actually the _DSD UUID that implements ACPI device
> properties (hence the prp_) but I have no problems in changing that to
> dsd_uuid instead.

Oh, I missed that part, since this UUID is only for ACPI device
properties, I agree with you that prp_ is better here.

Thanks
Hanjun


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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
  2014-08-17 12:54     ` Grant Likely
  (?)
@ 2014-08-18  9:29     ` Mika Westerberg
       [not found]       ` <20140818092937.GT2462-3PARRvDOhMZrdx17CPfAsdBPR1lH4CV8@public.gmane.org>
  -1 siblings, 1 reply; 54+ messages in thread
From: Mika Westerberg @ 2014-08-18  9:29 UTC (permalink / raw)
  To: Grant Likely
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Sun, Aug 17, 2014 at 01:54:16PM +0100, Grant Likely wrote:
> On Sun, 17 Aug 2014 09:04:14 +0300, Mika Westerberg <mika.westerberg@linux.intel.com> wrote:
> > From: Aaron Lu <aaron.lu@intel.com>
> > 
> > With the unified device properties interface in place, add device tree support.
> > By adding the dev_prop_ops for of_node devices, drivers can access properties
> > from ACPI or Device Tree in a generic way.
> > 
> > Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> > Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> 
> Hi Mika,
> 
> As commented on patch 3, the new API currently throws away type
> information so the compiler won't warn on an error. That needs to be
> fixed and this patch reworked accordingly.

The compiler should warn when we add static inline property accessor
functions for each type.

> 
> g.
> 
> ---
> >  drivers/of/base.c        | 194 ++++++++++++++++++++++++++++++++++++++++++++++-
> >  drivers/of/platform.c    |   4 +-
> >  include/linux/property.h |   4 +
> >  3 files changed, 200 insertions(+), 2 deletions(-)
> > 
> > diff --git a/drivers/of/base.c b/drivers/of/base.c
> > index b9864806e9b8..527004d01423 100644
> > --- a/drivers/of/base.c
> > +++ b/drivers/of/base.c
> > @@ -20,7 +20,7 @@
> >  #include <linux/ctype.h>
> >  #include <linux/cpu.h>
> >  #include <linux/module.h>
> > -#include <linux/of.h>
> > +#include <linux/property.h>
> >  #include <linux/of_graph.h>
> >  #include <linux/spinlock.h>
> >  #include <linux/slab.h>
> > @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
> >  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;
> > +}
> 
> Considering we don't even have a user of u64 arrays in all of the DT
> drivers, do we even need this type hook in the generic API?

Indeed, I think we can remove it for now.

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

* Re: [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
  2014-08-17  6:04     ` Mika Westerberg
  (?)
@ 2014-08-18 10:54     ` Mark Rutland
  2014-08-18 16:05       ` Mika Westerberg
  2014-08-19  5:45         ` Darren Hart
  -1 siblings, 2 replies; 54+ messages in thread
From: Mark Rutland @ 2014-08-18 10:54 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel, grant.likely, rob.herring,
	catalin.marinas, will.deacon

Hi Mika,

While I am very much in favour of having a structured way of describing
device specific data in ACPI I am very concerned by the idea of assuming
(a false) equivalence with DT. More on that below.

On Sun, Aug 17, 2014 at 07:04:12AM +0100, Mika Westerberg wrote:
> 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>
> ---
>  Documentation/acpi/properties.txt | 359 ++++++++++++++++++++++++++++++++++++++
>  1 file changed, 359 insertions(+)
>  create mode 100644 Documentation/acpi/properties.txt
> 
> diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt
> new file mode 100644
> index 000000000000..a1e93267c1fa
> --- /dev/null
> +++ b/Documentation/acpi/properties.txt
> @@ -0,0 +1,359 @@
> +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 GPIO keys device.
> +In addition to the GpioIo/GpioInt resources the driver needs to know how
> +to map each GpioIo resource to the corresponding Linux input event.
> +
> +To solve this we add the following ACPI device properties from the
> +gpio-keys schema:
> +
> +       Device (KEYS) {
> +               Name (_DSD, Package () {
> +                       ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +                       Package () {
> +                               Package () {"poll-interval", 100},
> +                               Package () {"autorepeat", 1}
> +                       }
> +               })
> +
> +               Device (BTN0) {
> +                       Name (_DSD, Package () {
> +                               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> +                               Package () {
> +                                       Package () {"linux,code", 105},
> +                                       Package () {"linux,input-type", 1},

The leakage of Linux implementation details into DTBs is bad enough. I
would really not like to see this kind of thing in ACPI tables.

Leaking this into HW description of any sort completely rids said
description of any OS independence, and it's usually short-sighted,
nonsensical, or ill-defined (what does 'autorepeat' actually mean?).

I am very worried by the prospect of _DSD making it harder rather than
easier for an arbitrary OS to use ACPI data due to assumptions being
made about (a particular revision of) a particular OS.

> +                                       ...
> +                               }
> +                       })
> +               }
> +
> +               ...
> +       }
> +
> +Of course the device driver then needs to iterate over these devices but
> +it can be done easily via the ->children field of the companion ACPI
> +device. This will be demonstrated later on in the document.
> +
> +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.

For simple devices like a UART which just has a "clock-frequency"
property in DT, importing both the concept of the property and the key
name itself is a sensible approach.

However, I do not think this makes sense as a general design rule. ACPI
and DT already have different idioms for describing certain things (e.g.
GPIOs, interrupts) and care needs to be taken to distinguish simple
device-specific properties from class-specific properties or implied
linkages between devices.

The "#clock-cells" and "#pwm-cells" _DSD examples in ACPI 5.1 are
complete nonsense. They import an idiom from DT into ACPI without
considering the surrounding context (cells, lack of typing, phandles,
etc). As an example, I worry that why it may be trivial to map pinctrl
bindings into ACPI _DSD, there is no clear way that they would interact
with ACPI's HW management. This is going to significantly expand our
problem surface area.

There are known deficiencies with many DT bindings that we can't fix for
legacy reasons on the DT side (e.g. the clock detection for ARM
primecell devices). Some of these issues can be trivially fixed for a
legacy-free environment like ACPI _DSD.

We have a lot of stupid (and broken) DT bindings that were either
ill-designed or which newer hardware has exposed weaknesses in. I don't
want us to turn these into even more broken ACPI _DSD bindings. 

For the reasons above I am against having a single API which accesses
both interfaces. I believe at present it is better to separate the two.
For those devices which truly need a small amount of data there will not
be much duplication. For those which need large amounts of data we
clearly need to consider whether those bindings are sensible to pull
across into ACPI at all.

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

Does that always make sense, or should that be left to the driver?

In some cases properties form DT having a max value of 0xffffffff is
simply a result of using the default DT number representation rather
than a conscious decision that 32 bits are enough.

> +An integer property looks like this:
> +
> +       Package () {"poll-interval", 100},
> +       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(dev, "poll-interval", DEV_PROP_U32, &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.

As I mentioned above, I am extremely concerned that it is not sensible
to blindly import the class bindings you mention here.

> +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_array(dev, "max8952,dvs-mode-microvolt",
> +                                        DEV_PROP_U32, 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.

On the DT side we have of_property_count_u{8,16,32,64}_elems. Having
separate functions makes the code easier to read.

> +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 () {"pwm-names", "backlight"},
> +       Package () {"label", "Status-LED"},
> +
> +You can also use device_property_read() to extract strings:
> +
> +       const char *val;
> +       int ret;
> +
> +       ret = device_property_read(dev, "label", DEV_PROP_STRING, &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_array(dev, "dma-names", DEV_PROP_STRING,
> +                                        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 () {"clock", \_SB.CLK0},

For examples I would strongly recommend using something slightly more
abstract so that (for example) it is not assumed that this is the
canonical way to describe a clock using _DSD.

> +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,
> +                                       }

I'm not all that familiar with ASL so perhaps this is not possible, but
IMO it would make far more sense to have the two elements described as
individual packages:

Package {
	"pwms",
	Package () { \ref1, 0, 5235 }
	Package () { \ref2, 1, 42423 } 
}

That way there's no need for #x-cells properties, it's possible to do
better type checking, variadic arguments can be supported, etc.

As it stands this live in the intersection of the limitations of both
ACPI and DT, and I suspect this will only cause pain on both sides.

> +                               }
> +                       }
> +               })
> +       }
> +
> +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.

Is that an ASL limitation or a Linux limitation?

> +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().

If we're expecting device class bindings to use high-level interfaces
(like pwm_get, clk_get, etc) then as far as I can see there is no reason
that the low-level representation in ACPI and DT need to be identical.

Importing DT bindings wholesale into ACPI only optimises for getting
things supported quickly, not getting things supported sanely.

Thanks,
Mark.

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

* Re: [RFC PATCH 1/9] ACPI: Add support for device specific properties
  2014-08-18  8:27     ` Mika Westerberg
@ 2014-08-18 12:37         ` Darren Hart
  2014-08-18 12:37         ` Darren Hart
  1 sibling, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-18 12:37 UTC (permalink / raw)
  To: Mika Westerberg, Hanjun Guo
  Cc: Rafael J. Wysocki, Aaron Lu, Max Eliaser, linux-acpi, devicetree,
	linux-kernel

On 8/18/14, 3:27, "Mika Westerberg" <mika.westerberg@linux.intel.com>
wrote:

>On Mon, Aug 18, 2014 at 04:13:29PM +0800, Hanjun Guo wrote:

Hi Hanjun,

Thanks for reviewing!

>>
>> > +/* ACPI _DSD device properties UUID:
>>daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
>> > +static const u8 prp_uuid[16] = {
>> 
>> s/prp_uuid/dsd_uuid ?
>
>Well, it is actually the _DSD UUID that implements ACPI device
>properties (hence the prp_) but I have no problems in changing that to
>dsd_uuid instead.

The distinction is important. DSD does not define a format, the UUID does,
and there can be many - although we are adding support specifically for
one. The PRP name here also pairs with the PRP0000 HID.

-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 1/9] ACPI: Add support for device specific properties
@ 2014-08-18 12:37         ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-18 12:37 UTC (permalink / raw)
  To: Mika Westerberg, Hanjun Guo
  Cc: Rafael J. Wysocki, Aaron Lu, Max Eliaser, linux-acpi, devicetree,
	linux-kernel

On 8/18/14, 3:27, "Mika Westerberg" <mika.westerberg@linux.intel.com>
wrote:

>On Mon, Aug 18, 2014 at 04:13:29PM +0800, Hanjun Guo wrote:

Hi Hanjun,

Thanks for reviewing!

>>
>> > +/* ACPI _DSD device properties UUID:
>>daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
>> > +static const u8 prp_uuid[16] = {
>> 
>> s/prp_uuid/dsd_uuid ?
>
>Well, it is actually the _DSD UUID that implements ACPI device
>properties (hence the prp_) but I have no problems in changing that to
>dsd_uuid instead.

The distinction is important. DSD does not define a format, the UUID does,
and there can be many - although we are adding support specifically for
one. The PRP name here also pairs with the PRP0000 HID.

-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
  2014-08-18  9:29     ` Mika Westerberg
@ 2014-08-18 12:44           ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-18 12:44 UTC (permalink / raw)
  To: Mika Westerberg, Grant Likely
  Cc: Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 8/18/14, 4:29, "Mika Westerberg" <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
wrote:

>On Sun, Aug 17, 2014 at 01:54:16PM +0100, Grant Likely wrote:
>> On Sun, 17 Aug 2014 09:04:14 +0300, Mika Westerberg
>><mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org> wrote:
>> > From: Aaron Lu <aaron.lu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>> > 
>> > With the unified device properties interface in place, add device
>>tree support.
>> > By adding the dev_prop_ops for of_node devices, drivers can access
>>properties
>> > from ACPI or Device Tree in a generic way.
>> > 
>> > Signed-off-by: Aaron Lu <aaron.lu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
>> > Reviewed-by: Darren Hart <dvhart-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
>> > Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
>> 
>> Hi Mika,
>> 
>> As commented on patch 3, the new API currently throws away type
>> information so the compiler won't warn on an error. That needs to be
>> fixed and this patch reworked accordingly.
>
>The compiler should warn when we add static inline property accessor
>functions for each type.
>
>> 
>> g.
>> 
>> ---
>> >  drivers/of/base.c        | 194
>>++++++++++++++++++++++++++++++++++++++++++++++-
>> >  drivers/of/platform.c    |   4 +-
>> >  include/linux/property.h |   4 +
>> >  3 files changed, 200 insertions(+), 2 deletions(-)
>> > 
>> > diff --git a/drivers/of/base.c b/drivers/of/base.c
>> > index b9864806e9b8..527004d01423 100644
>> > --- a/drivers/of/base.c
>> > +++ b/drivers/of/base.c
>> > @@ -20,7 +20,7 @@
>> >  #include <linux/ctype.h>
>> >  #include <linux/cpu.h>
>> >  #include <linux/module.h>
>> > -#include <linux/of.h>
>> > +#include <linux/property.h>
>> >  #include <linux/of_graph.h>
>> >  #include <linux/spinlock.h>
>> >  #include <linux/slab.h>
>> > @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct
>>device_node *np, const char *propname,
>> >  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;
>> > +}
>> 
>> Considering we don't even have a user of u64 arrays in all of the DT
>> drivers, do we even need this type hook in the generic API?
>
>Indeed, I think we can remove it for now.
>

Keep in mind that existing DT drivers are not the only user of this
interface.

This series enables ACPI systems to make use of such drivers (or lays the
groundwork, each driver does need an update to the new API), but there are
also new drivers being developed today that are ACPI first. While the
DT-space may not need this interface now, I don't see the value in
preventing it from being used in the future by removing it from the
generic interface.

Adding it later, if needed, isn't as trivial as it sounds as we first have
to put developers through the pain of finding the interface doesn't exist
for a valid type, many of whom will decide to work around the limitation
rather than take the discussion to the infamous LKML - resulting in
suboptimal firmware descriptions.

I'd much rather see us enable them to help themselves and then get out of
their way by supporting all the valid types initially.

-- 
Darren Hart					Open Source Technology Center
darren.hart-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org				            Intel Corporation



--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node
@ 2014-08-18 12:44           ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-18 12:44 UTC (permalink / raw)
  To: Mika Westerberg, Grant Likely
  Cc: Rafael J. Wysocki, Aaron Lu, Max Eliaser, linux-acpi, devicetree,
	linux-kernel

On 8/18/14, 4:29, "Mika Westerberg" <mika.westerberg@linux.intel.com>
wrote:

>On Sun, Aug 17, 2014 at 01:54:16PM +0100, Grant Likely wrote:
>> On Sun, 17 Aug 2014 09:04:14 +0300, Mika Westerberg
>><mika.westerberg@linux.intel.com> wrote:
>> > From: Aaron Lu <aaron.lu@intel.com>
>> > 
>> > With the unified device properties interface in place, add device
>>tree support.
>> > By adding the dev_prop_ops for of_node devices, drivers can access
>>properties
>> > from ACPI or Device Tree in a generic way.
>> > 
>> > Signed-off-by: Aaron Lu <aaron.lu@intel.com>
>> > Reviewed-by: Darren Hart <dvhart@linux.intel.com>
>> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
>> 
>> Hi Mika,
>> 
>> As commented on patch 3, the new API currently throws away type
>> information so the compiler won't warn on an error. That needs to be
>> fixed and this patch reworked accordingly.
>
>The compiler should warn when we add static inline property accessor
>functions for each type.
>
>> 
>> g.
>> 
>> ---
>> >  drivers/of/base.c        | 194
>>++++++++++++++++++++++++++++++++++++++++++++++-
>> >  drivers/of/platform.c    |   4 +-
>> >  include/linux/property.h |   4 +
>> >  3 files changed, 200 insertions(+), 2 deletions(-)
>> > 
>> > diff --git a/drivers/of/base.c b/drivers/of/base.c
>> > index b9864806e9b8..527004d01423 100644
>> > --- a/drivers/of/base.c
>> > +++ b/drivers/of/base.c
>> > @@ -20,7 +20,7 @@
>> >  #include <linux/ctype.h>
>> >  #include <linux/cpu.h>
>> >  #include <linux/module.h>
>> > -#include <linux/of.h>
>> > +#include <linux/property.h>
>> >  #include <linux/of_graph.h>
>> >  #include <linux/spinlock.h>
>> >  #include <linux/slab.h>
>> > @@ -1343,6 +1343,39 @@ int of_property_read_u64(const struct
>>device_node *np, const char *propname,
>> >  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;
>> > +}
>> 
>> Considering we don't even have a user of u64 arrays in all of the DT
>> drivers, do we even need this type hook in the generic API?
>
>Indeed, I think we can remove it for now.
>

Keep in mind that existing DT drivers are not the only user of this
interface.

This series enables ACPI systems to make use of such drivers (or lays the
groundwork, each driver does need an update to the new API), but there are
also new drivers being developed today that are ACPI first. While the
DT-space may not need this interface now, I don't see the value in
preventing it from being used in the future by removing it from the
generic interface.

Adding it later, if needed, isn't as trivial as it sounds as we first have
to put developers through the pain of finding the interface doesn't exist
for a valid type, many of whom will decide to work around the limitation
rather than take the discussion to the infamous LKML - resulting in
suboptimal firmware descriptions.

I'd much rather see us enable them to help themselves and then get out of
their way by supporting all the valid types initially.

-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
  2014-08-18 10:54     ` Mark Rutland
@ 2014-08-18 16:05       ` Mika Westerberg
  2014-08-19  5:45         ` Darren Hart
  1 sibling, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-18 16:05 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel, grant.likely, rob.herring,
	catalin.marinas, will.deacon

On Mon, Aug 18, 2014 at 11:54:29AM +0100, Mark Rutland wrote:
> Hi Mika,
> 
> While I am very much in favour of having a structured way of describing
> device specific data in ACPI I am very concerned by the idea of assuming
> (a false) equivalence with DT. More on that below.
> 
> On Sun, Aug 17, 2014 at 07:04:12AM +0100, Mika Westerberg wrote:
> > 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>
> > ---
> >  Documentation/acpi/properties.txt | 359 ++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 359 insertions(+)
> >  create mode 100644 Documentation/acpi/properties.txt
> > 
> > diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt
> > new file mode 100644
> > index 000000000000..a1e93267c1fa
> > --- /dev/null
> > +++ b/Documentation/acpi/properties.txt
> > @@ -0,0 +1,359 @@
> > +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 GPIO keys device.
> > +In addition to the GpioIo/GpioInt resources the driver needs to know how
> > +to map each GpioIo resource to the corresponding Linux input event.
> > +
> > +To solve this we add the following ACPI device properties from the
> > +gpio-keys schema:
> > +
> > +       Device (KEYS) {
> > +               Name (_DSD, Package () {
> > +                       ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                       Package () {
> > +                               Package () {"poll-interval", 100},
> > +                               Package () {"autorepeat", 1}
> > +                       }
> > +               })
> > +
> > +               Device (BTN0) {
> > +                       Name (_DSD, Package () {
> > +                               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                               Package () {
> > +                                       Package () {"linux,code", 105},
> > +                                       Package () {"linux,input-type", 1},
> 
> The leakage of Linux implementation details into DTBs is bad enough. I
> would really not like to see this kind of thing in ACPI tables.
> 
> Leaking this into HW description of any sort completely rids said
> description of any OS independence, and it's usually short-sighted,
> nonsensical, or ill-defined (what does 'autorepeat' actually mean?).
> 
> I am very worried by the prospect of _DSD making it harder rather than
> easier for an arbitrary OS to use ACPI data due to assumptions being
> made about (a particular revision of) a particular OS.

You are right - the above example is bad in that sense. The reason why
we have the above is that we tested the implementation on Minnowboard
and the two devices we converted used these descriptions.

We should pick a better example that describes the HW independent of the
OS.

> 
> > +                                       ...
> > +                               }
> > +                       })
> > +               }
> > +
> > +               ...
> > +       }
> > +
> > +Of course the device driver then needs to iterate over these devices but
> > +it can be done easily via the ->children field of the companion ACPI
> > +device. This will be demonstrated later on in the document.
> > +
> > +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.
> 
> For simple devices like a UART which just has a "clock-frequency"
> property in DT, importing both the concept of the property and the key
> name itself is a sensible approach.
> 
> However, I do not think this makes sense as a general design rule. ACPI
> and DT already have different idioms for describing certain things (e.g.
> GPIOs, interrupts) and care needs to be taken to distinguish simple
> device-specific properties from class-specific properties or implied
> linkages between devices.

For things that ACPI already knows about, like GPIOs, we use them
instead of DT bindings. Some things, like referring a GPIO with name (or
DMA request channel) we rely on DT properties.

Same goes with MMIO addresses, IRQs etc. Those are coming from existing
ACPI descriptions, not from DT.

> 
> The "#clock-cells" and "#pwm-cells" _DSD examples in ACPI 5.1 are
> complete nonsense. They import an idiom from DT into ACPI without
> considering the surrounding context (cells, lack of typing, phandles,
> etc). As an example, I worry that why it may be trivial to map pinctrl
> bindings into ACPI _DSD, there is no clear way that they would interact
> with ACPI's HW management. This is going to significantly expand our
> problem surface area.

One of the driving ideas for this work was that we should be able to
stick DT description inside _DSD with some minor modifications to the
drivers, and it all should just work.

> There are known deficiencies with many DT bindings that we can't fix for
> legacy reasons on the DT side (e.g. the clock detection for ARM
> primecell devices). Some of these issues can be trivially fixed for a
> legacy-free environment like ACPI _DSD.
> 
> We have a lot of stupid (and broken) DT bindings that were either
> ill-designed or which newer hardware has exposed weaknesses in. I don't
> want us to turn these into even more broken ACPI _DSD bindings. 
> 
> For the reasons above I am against having a single API which accesses
> both interfaces. I believe at present it is better to separate the two.
> For those devices which truly need a small amount of data there will not
> be much duplication. For those which need large amounts of data we
> clearly need to consider whether those bindings are sensible to pull
> across into ACPI at all.
> 
> > +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.
> 
> Does that always make sense, or should that be left to the driver?

I think it should be left to the driver. We just provide functions that
help the driver a bit here.

> In some cases properties form DT having a max value of 0xffffffff is
> simply a result of using the default DT number representation rather
> than a conscious decision that 32 bits are enough.

OK

> > +An integer property looks like this:
> > +
> > +       Package () {"poll-interval", 100},
> > +       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(dev, "poll-interval", DEV_PROP_U32, &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.
> 
> As I mentioned above, I am extremely concerned that it is not sensible
> to blindly import the class bindings you mention here.

OK, I'll drop some of those like "Linux input key codes" and possibly
"pin control settings". Or drop the whole example here.

> > +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_array(dev, "max8952,dvs-mode-microvolt",
> > +                                        DEV_PROP_U32, 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.
> 
> On the DT side we have of_property_count_u{8,16,32,64}_elems. Having
> separate functions makes the code easier to read.

We can add static inline wrapper functions that implement the above.

> > +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 () {"pwm-names", "backlight"},
> > +       Package () {"label", "Status-LED"},
> > +
> > +You can also use device_property_read() to extract strings:
> > +
> > +       const char *val;
> > +       int ret;
> > +
> > +       ret = device_property_read(dev, "label", DEV_PROP_STRING, &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_array(dev, "dma-names", DEV_PROP_STRING,
> > +                                        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 () {"clock", \_SB.CLK0},
> 
> For examples I would strongly recommend using something slightly more
> abstract so that (for example) it is not assumed that this is the
> canonical way to describe a clock using _DSD.

Good point. Maybe we can just say something like:

	Package () {"ref", \_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,
> > +                                       }
> 
> I'm not all that familiar with ASL so perhaps this is not possible, but
> IMO it would make far more sense to have the two elements described as
> individual packages:
> 
> Package {
> 	"pwms",
> 	Package () { \ref1, 0, 5235 }
> 	Package () { \ref2, 1, 42423 } 
> }

ASL allows that but the _DSD ACPI device property specification doesn't.

> That way there's no need for #x-cells properties, it's possible to do
> better type checking, variadic arguments can be supported, etc.
> 
> As it stands this live in the intersection of the limitations of both
> ACPI and DT, and I suspect this will only cause pain on both sides.
> 
> > +                               }
> > +                       }
> > +               })
> > +       }
> > +
> > +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.
> 
> Is that an ASL limitation or a Linux limitation?

That is limitation we added on purpose to support DT <&phandle int int>
descriptions. So that we can validate that the returned package at least
contains types we expect.

> > +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().
> 
> If we're expecting device class bindings to use high-level interfaces
> (like pwm_get, clk_get, etc) then as far as I can see there is no reason
> that the low-level representation in ACPI and DT need to be identical.

Well, it is not 100% identical even now. For example ACPI already knows
GPIOs (throuh GpioIo/GpioInt) but there hasn't been any way to refer the
GPIO using name. So we use _CRS returned resources normally but get the
name using _DSD.

Whevever we can use the existing ACPI resources we certainly do, instead
of using DT properties.

> Importing DT bindings wholesale into ACPI only optimises for getting
> things supported quickly, not getting things supported sanely.

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

* Re: [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
  2014-08-18 10:54     ` Mark Rutland
@ 2014-08-19  5:45         ` Darren Hart
  2014-08-19  5:45         ` Darren Hart
  1 sibling, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-19  5:45 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	grant.likely-QSEj5FYQhm4dnm+yROfE0A,
	rob.herring-QSEj5FYQhm4dnm+yROfE0A, catalin.marinas-5wv7dgnIgG8,
	will.deacon-5wv7dgnIgG8

On Mon, Aug 18, 2014 at 11:54:29AM +0100, Mark Rutland wrote:
> Hi Mika,
> 
> While I am very much in favour of having a structured way of describing
> device specific data in ACPI I am very concerned by the idea of assuming
> (a false) equivalence with DT. More on that below.

Hi Mark,

The equivalence is intended in the sense that we should be able to represent any
of the existing schemas with the same properties in ACPI as in DT.

...

> > +An example device where we might need properties is a GPIO keys device.
> > +In addition to the GpioIo/GpioInt resources the driver needs to know how
> > +to map each GpioIo resource to the corresponding Linux input event.
> > +
> > +To solve this we add the following ACPI device properties from the
> > +gpio-keys schema:
> > +
> > +       Device (KEYS) {
> > +               Name (_DSD, Package () {
> > +                       ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                       Package () {
> > +                               Package () {"poll-interval", 100},
> > +                               Package () {"autorepeat", 1}
> > +                       }
> > +               })
> > +
> > +               Device (BTN0) {
> > +                       Name (_DSD, Package () {
> > +                               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                               Package () {
> > +                                       Package () {"linux,code", 105},
> > +                                       Package () {"linux,input-type", 1},
> 
> The leakage of Linux implementation details into DTBs is bad enough. I
> would really not like to see this kind of thing in ACPI tables.
> 
> Leaking this into HW description of any sort completely rids said
> description of any OS independence, and it's usually short-sighted,
> nonsensical, or ill-defined (what does 'autorepeat' actually mean?).
> 
> I am very worried by the prospect of _DSD making it harder rather than
> easier for an arbitrary OS to use ACPI data due to assumptions being
> made about (a particular revision of) a particular OS.

This is perhaps not the best example to include in the documentation. A guiding
principle has been to only represent in the DSD that which is an actual property
of the hardware.

It is also a goal of the mechanism to enable ACPI systems to reuse the 200+
existing OF-aware drivers in the kernel today. If those schemas are
ill-conceived, we should work to improve the schemas.

On the point of OS-independence, while I agree that using something like the USB
keycodes here would be better, the namespacing employed in these properties
makes it possible to use the same DSD for muliple OSes as another OS could add
it's own keycode, for example, without conflict. Again, that is really an issue
with the schemas, not the _DSD mechanism itself.

Perhaps we should use a different example in the documentation as I would agree
this is not a model schema.

> > +Of course the device driver then needs to iterate over these devices but
> > +it can be done easily via the ->children field of the companion ACPI
> > +device. This will be demonstrated later on in the document.
> > +
> > +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.
> 
> For simple devices like a UART which just has a "clock-frequency"
> property in DT, importing both the concept of the property and the key
> name itself is a sensible approach.
> 
> However, I do not think this makes sense as a general design rule. ACPI
> and DT already have different idioms for describing certain things (e.g.
> GPIOs, interrupts) and care needs to be taken to distinguish simple
> device-specific properties from class-specific properties or implied
> linkages between devices.

I believe we have GPIO handled well in this series. In DT terms, ACPI is the
controller, providing a list of GpioIO|GpioInt resources in the CRS of the
referenced object. Arguments are Resource Index, Pin Index, Polarity. The rest
of the properties are handled via the GpioIO|GpioInt resources in the _CRS.

> 
> The "#clock-cells" and "#pwm-cells" _DSD examples in ACPI 5.1 are
> complete nonsense. They import an idiom from DT into ACPI without

Yeah... coming up with good examples for a generic mechanism which are both
descriptive and universally unobjectionable. Good point. We might be able to
improve this via an errata update. What would you recommend?

> considering the surrounding context (cells, lack of typing, phandles,

How are the phandles not covered via the ACPI namespace references?

The point on cells is a good one, and I believe some of this can be mitigated by
providing subsystem specific accessors as we have for GPIO, for example.

> etc). As an example, I worry that why it may be trivial to map pinctrl
> bindings into ACPI _DSD, there is no clear way that they would interact
> with ACPI's HW management. This is going to significantly expand our
> problem surface area.

Pinctrl is an area where I suspect we will need more specific support, but
it is still on my list for a detailed review.

> There are known deficiencies with many DT bindings that we can't fix for
> legacy reasons on the DT side (e.g. the clock detection for ARM
> primecell devices). Some of these issues can be trivially fixed for a
> legacy-free environment like ACPI _DSD.
> 
> We have a lot of stupid (and broken) DT bindings that were either
> ill-designed or which newer hardware has exposed weaknesses in. I don't
> want us to turn these into even more broken ACPI _DSD bindings. 

That's surely the case. Could you provide a concrete example or two I can use to
build context?

> For the reasons above I am against having a single API which accesses
> both interfaces. I believe at present it is better to separate the two.
> For those devices which truly need a small amount of data there will not
> be much duplication. For those which need large amounts of data we
> clearly need to consider whether those bindings are sensible to pull
> across into ACPI at all.

The issue here is there are over 200 drivers in the kernel today that are not
usable by ACPI systems, and many more external to the kernel which are only
usable via board files. The alternative would be to modify every one of these
drivers with an ACPI-specific pdata creation function and to create a new schema
library for ACPI which would differ from DT. Ultimiately it would be preferable
for the hardware vendor to define the properties required to describe the
hardware in a way independent from the firmware implementation.

> > +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.
> 
> Does that always make sense, or should that be left to the driver?
> 

I don't follow - the driver chooses which size integer to request. Josh has
suggested these functions should check for overflow, which I thought made sense.

> In some cases properties form DT having a max value of 0xffffffff is
> simply a result of using the default DT number representation rather
> than a conscious decision that 32 bits are enough.
> 
> > +An integer property looks like this:
> > +
> > +       Package () {"poll-interval", 100},
> > +       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(dev, "poll-interval", DEV_PROP_U32, &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.
> 
> As I mentioned above, I am extremely concerned that it is not sensible
> to blindly import the class bindings you mention here.
> 
> > +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_array(dev, "max8952,dvs-mode-microvolt",
> > +                                        DEV_PROP_U32, 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.
> 
> On the DT side we have of_property_count_u{8,16,32,64}_elems. Having
> separate functions makes the code easier to read.

That makes sense to me, especially as we would be replacing such usage in
existing drivers, it would be nice for it to be as close to a direct mapping as
possible.

...

> > +An object reference looks like this:
> > +
> > +       Package () {"clock", \_SB.CLK0},
> 
> For examples I would strongly recommend using something slightly more
> abstract so that (for example) it is not assumed that this is the
> canonical way to describe a clock using _DSD.
> 

Agreed.

> > +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,
> > +                                       }
> 
> I'm not all that familiar with ASL so perhaps this is not possible, but
> IMO it would make far more sense to have the two elements described as
> individual packages:
> 
> Package {
> 	"pwms",
> 	Package () { \ref1, 0, 5235 }
> 	Package () { \ref2, 1, 42423 } 
> }
> 
> That way there's no need for #x-cells properties, it's possible to do
> better type checking, variadic arguments can be supported, etc.

While the above is valid ASL (minus a comma), the prp_uuid doesn't allow for
multiple "values" in the key value pairs. If wanted to encapsulate each pwm
entry, we would need to give each a unique name, "pwm0", "pwm1" etc. The above
is intended to parallel the DT to make it easiest to reuse drivers.

> 
> As it stands this live in the intersection of the limitations of both
> ACPI and DT, and I suspect this will only cause pain on both sides.
> 
> > +                               }
> > +                       }
> > +               })
> > +       }
> > +
> > +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.
> 
> Is that an ASL limitation or a Linux limitation?

This is a Linux implementation (or our choice of) limitation. Are there other
argument types we should be considering?

> 
> > +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().
> 
> If we're expecting device class bindings to use high-level interfaces
> (like pwm_get, clk_get, etc) then as far as I can see there is no reason
> that the low-level representation in ACPI and DT need to be identical.

There are properties that will not be subsystem specific, or rather that are
simple key:value pairs that are convenient to access with the common mechanism.
Even if we get a number of these abstractions in place, there is still value in
a simple common property API in that it enables drivers to be ignorant of the
underlying firmware-mechanism.

We have an example in this series for gpiolib - is this a good example in your
opinion? Would adding examples/mechanism for pwm_get etc in the series help?

> Importing DT bindings wholesale into ACPI only optimises for getting
> things supported quickly, not getting things supported sanely.
> 
> Thanks,
> Mark.

We're also trying to lower the barriers to enabling and writing new drivers that
work on both DT and ACPI based systems without domain specific knowledge of
each.

Thanks for taking the time to review and comment Mark, very much appreciated.

--
Darren Hart
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
@ 2014-08-19  5:45         ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-19  5:45 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel, grant.likely, rob.herring,
	catalin.marinas, will.deacon

On Mon, Aug 18, 2014 at 11:54:29AM +0100, Mark Rutland wrote:
> Hi Mika,
> 
> While I am very much in favour of having a structured way of describing
> device specific data in ACPI I am very concerned by the idea of assuming
> (a false) equivalence with DT. More on that below.

Hi Mark,

The equivalence is intended in the sense that we should be able to represent any
of the existing schemas with the same properties in ACPI as in DT.

...

> > +An example device where we might need properties is a GPIO keys device.
> > +In addition to the GpioIo/GpioInt resources the driver needs to know how
> > +to map each GpioIo resource to the corresponding Linux input event.
> > +
> > +To solve this we add the following ACPI device properties from the
> > +gpio-keys schema:
> > +
> > +       Device (KEYS) {
> > +               Name (_DSD, Package () {
> > +                       ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                       Package () {
> > +                               Package () {"poll-interval", 100},
> > +                               Package () {"autorepeat", 1}
> > +                       }
> > +               })
> > +
> > +               Device (BTN0) {
> > +                       Name (_DSD, Package () {
> > +                               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > +                               Package () {
> > +                                       Package () {"linux,code", 105},
> > +                                       Package () {"linux,input-type", 1},
> 
> The leakage of Linux implementation details into DTBs is bad enough. I
> would really not like to see this kind of thing in ACPI tables.
> 
> Leaking this into HW description of any sort completely rids said
> description of any OS independence, and it's usually short-sighted,
> nonsensical, or ill-defined (what does 'autorepeat' actually mean?).
> 
> I am very worried by the prospect of _DSD making it harder rather than
> easier for an arbitrary OS to use ACPI data due to assumptions being
> made about (a particular revision of) a particular OS.

This is perhaps not the best example to include in the documentation. A guiding
principle has been to only represent in the DSD that which is an actual property
of the hardware.

It is also a goal of the mechanism to enable ACPI systems to reuse the 200+
existing OF-aware drivers in the kernel today. If those schemas are
ill-conceived, we should work to improve the schemas.

On the point of OS-independence, while I agree that using something like the USB
keycodes here would be better, the namespacing employed in these properties
makes it possible to use the same DSD for muliple OSes as another OS could add
it's own keycode, for example, without conflict. Again, that is really an issue
with the schemas, not the _DSD mechanism itself.

Perhaps we should use a different example in the documentation as I would agree
this is not a model schema.

> > +Of course the device driver then needs to iterate over these devices but
> > +it can be done easily via the ->children field of the companion ACPI
> > +device. This will be demonstrated later on in the document.
> > +
> > +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.
> 
> For simple devices like a UART which just has a "clock-frequency"
> property in DT, importing both the concept of the property and the key
> name itself is a sensible approach.
> 
> However, I do not think this makes sense as a general design rule. ACPI
> and DT already have different idioms for describing certain things (e.g.
> GPIOs, interrupts) and care needs to be taken to distinguish simple
> device-specific properties from class-specific properties or implied
> linkages between devices.

I believe we have GPIO handled well in this series. In DT terms, ACPI is the
controller, providing a list of GpioIO|GpioInt resources in the CRS of the
referenced object. Arguments are Resource Index, Pin Index, Polarity. The rest
of the properties are handled via the GpioIO|GpioInt resources in the _CRS.

> 
> The "#clock-cells" and "#pwm-cells" _DSD examples in ACPI 5.1 are
> complete nonsense. They import an idiom from DT into ACPI without

Yeah... coming up with good examples for a generic mechanism which are both
descriptive and universally unobjectionable. Good point. We might be able to
improve this via an errata update. What would you recommend?

> considering the surrounding context (cells, lack of typing, phandles,

How are the phandles not covered via the ACPI namespace references?

The point on cells is a good one, and I believe some of this can be mitigated by
providing subsystem specific accessors as we have for GPIO, for example.

> etc). As an example, I worry that why it may be trivial to map pinctrl
> bindings into ACPI _DSD, there is no clear way that they would interact
> with ACPI's HW management. This is going to significantly expand our
> problem surface area.

Pinctrl is an area where I suspect we will need more specific support, but
it is still on my list for a detailed review.

> There are known deficiencies with many DT bindings that we can't fix for
> legacy reasons on the DT side (e.g. the clock detection for ARM
> primecell devices). Some of these issues can be trivially fixed for a
> legacy-free environment like ACPI _DSD.
> 
> We have a lot of stupid (and broken) DT bindings that were either
> ill-designed or which newer hardware has exposed weaknesses in. I don't
> want us to turn these into even more broken ACPI _DSD bindings. 

That's surely the case. Could you provide a concrete example or two I can use to
build context?

> For the reasons above I am against having a single API which accesses
> both interfaces. I believe at present it is better to separate the two.
> For those devices which truly need a small amount of data there will not
> be much duplication. For those which need large amounts of data we
> clearly need to consider whether those bindings are sensible to pull
> across into ACPI at all.

The issue here is there are over 200 drivers in the kernel today that are not
usable by ACPI systems, and many more external to the kernel which are only
usable via board files. The alternative would be to modify every one of these
drivers with an ACPI-specific pdata creation function and to create a new schema
library for ACPI which would differ from DT. Ultimiately it would be preferable
for the hardware vendor to define the properties required to describe the
hardware in a way independent from the firmware implementation.

> > +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.
> 
> Does that always make sense, or should that be left to the driver?
> 

I don't follow - the driver chooses which size integer to request. Josh has
suggested these functions should check for overflow, which I thought made sense.

> In some cases properties form DT having a max value of 0xffffffff is
> simply a result of using the default DT number representation rather
> than a conscious decision that 32 bits are enough.
> 
> > +An integer property looks like this:
> > +
> > +       Package () {"poll-interval", 100},
> > +       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(dev, "poll-interval", DEV_PROP_U32, &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.
> 
> As I mentioned above, I am extremely concerned that it is not sensible
> to blindly import the class bindings you mention here.
> 
> > +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_array(dev, "max8952,dvs-mode-microvolt",
> > +                                        DEV_PROP_U32, 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.
> 
> On the DT side we have of_property_count_u{8,16,32,64}_elems. Having
> separate functions makes the code easier to read.

That makes sense to me, especially as we would be replacing such usage in
existing drivers, it would be nice for it to be as close to a direct mapping as
possible.

...

> > +An object reference looks like this:
> > +
> > +       Package () {"clock", \_SB.CLK0},
> 
> For examples I would strongly recommend using something slightly more
> abstract so that (for example) it is not assumed that this is the
> canonical way to describe a clock using _DSD.
> 

Agreed.

> > +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,
> > +                                       }
> 
> I'm not all that familiar with ASL so perhaps this is not possible, but
> IMO it would make far more sense to have the two elements described as
> individual packages:
> 
> Package {
> 	"pwms",
> 	Package () { \ref1, 0, 5235 }
> 	Package () { \ref2, 1, 42423 } 
> }
> 
> That way there's no need for #x-cells properties, it's possible to do
> better type checking, variadic arguments can be supported, etc.

While the above is valid ASL (minus a comma), the prp_uuid doesn't allow for
multiple "values" in the key value pairs. If wanted to encapsulate each pwm
entry, we would need to give each a unique name, "pwm0", "pwm1" etc. The above
is intended to parallel the DT to make it easiest to reuse drivers.

> 
> As it stands this live in the intersection of the limitations of both
> ACPI and DT, and I suspect this will only cause pain on both sides.
> 
> > +                               }
> > +                       }
> > +               })
> > +       }
> > +
> > +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.
> 
> Is that an ASL limitation or a Linux limitation?

This is a Linux implementation (or our choice of) limitation. Are there other
argument types we should be considering?

> 
> > +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().
> 
> If we're expecting device class bindings to use high-level interfaces
> (like pwm_get, clk_get, etc) then as far as I can see there is no reason
> that the low-level representation in ACPI and DT need to be identical.

There are properties that will not be subsystem specific, or rather that are
simple key:value pairs that are convenient to access with the common mechanism.
Even if we get a number of these abstractions in place, there is still value in
a simple common property API in that it enables drivers to be ignorant of the
underlying firmware-mechanism.

We have an example in this series for gpiolib - is this a good example in your
opinion? Would adding examples/mechanism for pwm_get etc in the series help?

> Importing DT bindings wholesale into ACPI only optimises for getting
> things supported quickly, not getting things supported sanely.
> 
> Thanks,
> Mark.

We're also trying to lower the barriers to enabling and writing new drivers that
work on both DT and ACPI based systems without domain specific knowledge of
each.

Thanks for taking the time to review and comment Mark, very much appreciated.

--
Darren Hart

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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
  2014-08-18  4:57         ` Rafael J. Wysocki
@ 2014-08-19 15:58               ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-19 15:58 UTC (permalink / raw)
  To: Rafael J. Wysocki, Darren Hart
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On Mon, 18 Aug 2014 06:57:41 +0200, "Rafael J. Wysocki" <rjw-LthD3rsA81gm4RdzfppkhA@public.gmane.org> wrote:
> On Sunday, August 17, 2014 12:43:38 PM Darren Hart wrote:
> > On 8/17/14, 6:00, "Grant Likely" <grant.likely-s3s/WqlpOiPyB63q8FvJNQ@public.gmane.org> wrote:
> > 
> > >>
> > >>+	/* Using device tree? */
> > >>+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> > >>+		desc = of_find_gpio(dev, NULL, idx, flags);
> > >
> > >of_find_gpio() doesn't exist.
> > 
> > Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)
> > 
> > $ git blame -L1455,1456 drivers/gpio/gpiolib.c
> > bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
> > gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> > 
> > Have we removed this in -next or something? (on the plane, will verify
> > upon landing)
> 
> In 3.17-rc1:
> 
> rafael@vostro:~/src/linux-pm> grep -r of_find_gpio *
> drivers/gpio/gpiolib.c:static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> drivers/gpio/gpiolib.c:         desc = of_find_gpio(dev, con_id, idx, &lookupflags);

Weird, I don't know why I couldn't find it. I must have been on a
different branch. Sorry for the noise.

g.
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags
@ 2014-08-19 15:58               ` Grant Likely
  0 siblings, 0 replies; 54+ messages in thread
From: Grant Likely @ 2014-08-19 15:58 UTC (permalink / raw)
  To: Rafael J. Wysocki, Darren Hart
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Mon, 18 Aug 2014 06:57:41 +0200, "Rafael J. Wysocki" <rjw@rjwysocki.net> wrote:
> On Sunday, August 17, 2014 12:43:38 PM Darren Hart wrote:
> > On 8/17/14, 6:00, "Grant Likely" <grant.likely@secretlab.ca> wrote:
> > 
> > >>
> > >>+	/* Using device tree? */
> > >>+	if (IS_ENABLED(CONFIG_OF) && dev->of_node)
> > >>+		desc = of_find_gpio(dev, NULL, idx, flags);
> > >
> > >of_find_gpio() doesn't exist.
> > 
> > Hrm... As of 3.16.0 (e64df3ebe8262c8203d1fe4f541e0241c3112c01)
> > 
> > $ git blame -L1455,1456 drivers/gpio/gpiolib.c
> > bae48da2 (Alexandre Courbot 2013-10-17 10:21:38 -0700 1455) static struct
> > gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> > 
> > Have we removed this in -next or something? (on the plane, will verify
> > upon landing)
> 
> In 3.17-rc1:
> 
> rafael@vostro:~/src/linux-pm> grep -r of_find_gpio *
> drivers/gpio/gpiolib.c:static struct gpio_desc *of_find_gpio(struct device *dev, const char *con_id,
> drivers/gpio/gpiolib.c:         desc = of_find_gpio(dev, con_id, idx, &lookupflags);

Weird, I don't know why I couldn't find it. I must have been on a
different branch. Sorry for the noise.

g.

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

* Re: [RFC PATCH 2/9] ACPI: Document ACPI device specific properties
  2014-08-19  5:45         ` Darren Hart
  (?)
@ 2014-08-19 16:51         ` Mark Rutland
  -1 siblings, 0 replies; 54+ messages in thread
From: Mark Rutland @ 2014-08-19 16:51 UTC (permalink / raw)
  To: Darren Hart
  Cc: Mika Westerberg, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel, grant.likely, rob.herring,
	Catalin Marinas, Will Deacon

On Tue, Aug 19, 2014 at 06:45:46AM +0100, Darren Hart wrote:
> On Mon, Aug 18, 2014 at 11:54:29AM +0100, Mark Rutland wrote:
> > Hi Mika,
> >
> > While I am very much in favour of having a structured way of describing
> > device specific data in ACPI I am very concerned by the idea of assuming
> > (a false) equivalence with DT. More on that below.
>
> Hi Mark,

Hi Darren,

> The equivalence is intended in the sense that we should be able to represent any
> of the existing schemas with the same properties in ACPI as in DT.
>
> ...
>
> > > +An example device where we might need properties is a GPIO keys device.
> > > +In addition to the GpioIo/GpioInt resources the driver needs to know how
> > > +to map each GpioIo resource to the corresponding Linux input event.
> > > +
> > > +To solve this we add the following ACPI device properties from the
> > > +gpio-keys schema:
> > > +
> > > +       Device (KEYS) {
> > > +               Name (_DSD, Package () {
> > > +                       ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > > +                       Package () {
> > > +                               Package () {"poll-interval", 100},
> > > +                               Package () {"autorepeat", 1}
> > > +                       }
> > > +               })
> > > +
> > > +               Device (BTN0) {
> > > +                       Name (_DSD, Package () {
> > > +                               ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
> > > +                               Package () {
> > > +                                       Package () {"linux,code", 105},
> > > +                                       Package () {"linux,input-type", 1},
> >
> > The leakage of Linux implementation details into DTBs is bad enough. I
> > would really not like to see this kind of thing in ACPI tables.
> >
> > Leaking this into HW description of any sort completely rids said
> > description of any OS independence, and it's usually short-sighted,
> > nonsensical, or ill-defined (what does 'autorepeat' actually mean?).
> >
> > I am very worried by the prospect of _DSD making it harder rather than
> > easier for an arbitrary OS to use ACPI data due to assumptions being
> > made about (a particular revision of) a particular OS.
>
> This is perhaps not the best example to include in the documentation. A guiding
> principle has been to only represent in the DSD that which is an actual property
> of the hardware.

We follow the same principle in DT, but we still have to fight against
bad bindings which do not follow this principle.

Ideally all examples would align with that principle.

> It is also a goal of the mechanism to enable ACPI systems to reuse the 200+
> existing OF-aware drivers in the kernel today. If those schemas are
> ill-conceived, we should work to improve the schemas.
>
> On the point of OS-independence, while I agree that using something like the USB
> keycodes here would be better, the namespacing employed in these properties
> makes it possible to use the same DSD for muliple OSes as another OS could add
> it's own keycode, for example, without conflict. Again, that is really an issue
> with the schemas, not the _DSD mechanism itself.

It's true that the issues are with the individual bindings, and that
_DSD is simply a mechanism for conveying them. We certainly need to fix
up those bindings, but for legacy reasons some bad bindings will have to
stay supported when provided from a DTB. However is no reason for an
ACPI system to pick up any of the linux,* DT properties.

So we must treat ACPI and DTB as different providers of information, and
we need to be careful not to assume a false equivalence.

I'm not a big fan of providing different OSs with different views of the
world. I thought everyone using ACPI hated _OSI and the mess that
usually results in?

> Perhaps we should use a different example in the documentation as I would agree
> this is not a model schema.

Yes please.

> > > +Of course the device driver then needs to iterate over these devices but
> > > +it can be done easily via the ->children field of the companion ACPI
> > > +device. This will be demonstrated later on in the document.
> > > +
> > > +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.
> >
> > For simple devices like a UART which just has a "clock-frequency"
> > property in DT, importing both the concept of the property and the key
> > name itself is a sensible approach.
> >
> > However, I do not think this makes sense as a general design rule. ACPI
> > and DT already have different idioms for describing certain things (e.g.
> > GPIOs, interrupts) and care needs to be taken to distinguish simple
> > device-specific properties from class-specific properties or implied
> > linkages between devices.
>
> I believe we have GPIO handled well in this series. In DT terms, ACPI is the
> controller, providing a list of GpioIO|GpioInt resources in the CRS of the
> referenced object. Arguments are Resource Index, Pin Index, Polarity. The rest
> of the properties are handled via the GpioIO|GpioInt resources in the _CRS.

The description provided in this documentation is extremely vague. The
argument format you mention above is not described.  Was that the format
for a specific controller, or a format you expect all controllers to
follow?

I see an instance of #gpio-cells = <1>, which does not match the format
you mention.

Given that this is only similar to the way GPIOs are described in DT
rather than being identical, I don't see why these GPIOs need be
described through _DSD rather than adding a new standard ACPI resource
type for GPIOs. Either way the same high-level gpio_get* interface can
be used along with similar/identical names or indices; consumers
shouldn't be looking at the underlying representation anyway.

To me it feels like using _DSD to describe the connection of GPIOs is
working around a deficiency in ACPI rather than being the sensible
"native" way of describing GPIO connectivity. Especially so given this
usage is not actually described in the ACPI spec.

As I see it, _DSD makes sense for device-specific properties like
"num-slots" or "broken-cd" which can be handled within an individual
driver. I do not think that _DSD is the correct mechanism for describing
the linkage of devices; certainly not without that linkage description
becoming standardised.

> > The "#clock-cells" and "#pwm-cells" _DSD examples in ACPI 5.1 are
> > complete nonsense. They import an idiom from DT into ACPI without
>
> Yeah... coming up with good examples for a generic mechanism which are both
> descriptive and universally unobjectionable. Good point. We might be able to
> improve this via an errata update. What would you recommend?

It is an unfortunate fact that spec work is a hard and unrewarding task
where only the problems will be commented upon.

Do we expect to describe clocks and PWMs through _DSD rather than
something ACPI "native"? If not, I'd drop examples with #x-cells style
properties and references between nodes.

If we do expect to describe things in that way then I'd recommend that
we get a formal description together in the ACPI spec, and use an
example derived from that.

As I mention elsewhere I am very much not keen on describing device
linkages in _DSD.

> > considering the surrounding context (cells, lack of typing, phandles,
>
> How are the phandles not covered via the ACPI namespace references?

If ACPI namespace references are functionally equivalent, then please
ignore the above. From prior discussions I was under the impression that
they behaved differently, but I guess I am mistaken there?

> The point on cells is a good one, and I believe some of this can be mitigated by
> providing subsystem specific accessors as we have for GPIO, for example.

I'm happy with having common high-level accessors. My disagreement is
with trying to copy across the low-level representation from DT into
ACPI.

> > etc). As an example, I worry that why it may be trivial to map pinctrl
> > bindings into ACPI _DSD, there is no clear way that they would interact
> > with ACPI's HW management. This is going to significantly expand our
> > problem surface area.
>
> Pinctrl is an area where I suspect we will need more specific support, but
> it is still on my list for a detailed review.

Ok. I take it you'll get in touch with Linus W when you get the time to
look into that?

> > There are known deficiencies with many DT bindings that we can't fix for
> > legacy reasons on the DT side (e.g. the clock detection for ARM
> > primecell devices). Some of these issues can be trivially fixed for a
> > legacy-free environment like ACPI _DSD.
> >
> > We have a lot of stupid (and broken) DT bindings that were either
> > ill-designed or which newer hardware has exposed weaknesses in. I don't
> > want us to turn these into even more broken ACPI _DSD bindings.
>
> That's surely the case. Could you provide a concrete example or two I can use to
> build context?

Off the top of my head:

* The primecell class bindings expect clocks in a certain order, the
  primecell code doesn't care about order and acquires by name, and the
  primecell drivers typically acquire by index. This means that
  primecell drivers may pick up the apb_pclk (which drives the bus)
  rather than the clock they intended to.

* The L2x0 cache bindings still require some platform-specific data not
  provided through DT due to the way things were partially transitioned
  from board files to DT. I suspect there are several other drivers for
  which this is true, certainly there are still drivers which acquire
  clocks which aren't described in the DT.

* It's painful to have a GPIO line that's also used for an interrupt,
  because the interrupt flags aren't in the gpio-specifier. So you
  either need a separate interrupts property or separate flags property.
  Neither are fantastic.

* Typo workarounds or other legacy properties which never need to be
  available with ACPI _DSD (e.g. "ti,coordiante-readouts")

* Bindings which represent a software construct (e.g. IIO-HWMON). We
  also have properties like "autorepeat" which are tightly coupled to
  the design on the input subsystem.

* Resources named for the output of the provider, not the input of the
  consumer. I don't have an example to hand for this.

* For some recent additions like IOMMU bindings, devices are currently
  in the process of migrating to the new bindings.

* I don't think we really know how to generically describe interrupt
  line switches like the TI crossbar which aren't quite secondary
  interrupt controllers.

* The few drivers which require an entry in /aliases are likely to be
  problematic.

> > For the reasons above I am against having a single API which accesses
> > both interfaces. I believe at present it is better to separate the two.
> > For those devices which truly need a small amount of data there will not
> > be much duplication. For those which need large amounts of data we
> > clearly need to consider whether those bindings are sensible to pull
> > across into ACPI at all.
>
> The issue here is there are over 200 drivers in the kernel today that are not
> usable by ACPI systems, and many more external to the kernel which are only
> usable via board files. The alternative would be to modify every one of these
> drivers with an ACPI-specific pdata creation function and to create a new schema
> library for ACPI which would differ from DT. Ultimiately it would be preferable
> for the hardware vendor to define the properties required to describe the
> hardware in a way independent from the firmware implementation.

Of those 200 drivers, how many are likely to be useful on an ACPI
system? I would expect that we do not need the vast majority of the
SoC-specific drivers which I believe make up the bulk, but I could be
wrong.

I suspect that modifications will be necessary anyway for the subset of
drivers we actually need/want to enable for use with ACPI. I would like
to see some oversight being applied to these.

I'm not sure hardware vendors will do a better job describing their
hardware, given some bindings I have seen proposed by hardware vendors.
Perhaps if a vendors is actively targeting more than a single OS and
cares about maintaining their driver(s).

> > > +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.
> >
> > Does that always make sense, or should that be left to the driver?
> >
>
> I don't follow - the driver chooses which size integer to request. Josh has
> suggested these functions should check for overflow, which I thought made sense.

Sorry, this was a misunderstanding on my behalf.

> > In some cases properties form DT having a max value of 0xffffffff is
> > simply a result of using the default DT number representation rather
> > than a conscious decision that 32 bits are enough.
> >
> > > +An integer property looks like this:
> > > +
> > > +       Package () {"poll-interval", 100},
> > > +       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(dev, "poll-interval", DEV_PROP_U32, &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.
> >
> > As I mentioned above, I am extremely concerned that it is not sensible
> > to blindly import the class bindings you mention here.
> >
> > > +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_array(dev, "max8952,dvs-mode-microvolt",
> > > +                                        DEV_PROP_U32, 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.
> >
> > On the DT side we have of_property_count_u{8,16,32,64}_elems. Having
> > separate functions makes the code easier to read.
>
> That makes sense to me, especially as we would be replacing such usage in
> existing drivers, it would be nice for it to be as close to a direct mapping as
> possible.
>
> ...
>
> > > +An object reference looks like this:
> > > +
> > > +       Package () {"clock", \_SB.CLK0},
> >
> > For examples I would strongly recommend using something slightly more
> > abstract so that (for example) it is not assumed that this is the
> > canonical way to describe a clock using _DSD.
> >
>
> Agreed.
>
> > > +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,
> > > +                                       }
> >
> > I'm not all that familiar with ASL so perhaps this is not possible, but
> > IMO it would make far more sense to have the two elements described as
> > individual packages:
> >
> > Package {
> >       "pwms",
> >       Package () { \ref1, 0, 5235 }
> >       Package () { \ref2, 1, 42423 }
> > }
> >
> > That way there's no need for #x-cells properties, it's possible to do
> > better type checking, variadic arguments can be supported, etc.
>
> While the above is valid ASL (minus a comma), the prp_uuid doesn't allow for
> multiple "values" in the key value pairs. If wanted to encapsulate each pwm
> entry, we would need to give each a unique name, "pwm0", "pwm1" etc. The above
> is intended to parallel the DT to make it easiest to reuse drivers.

That is unfortunate.

The phandle + args cases are precisely where we only need the high-level
interface to be the same, and I believe using individual packages for
each tuple would have allowed for better sanity checking and error
reporting.

> >
> > As it stands this live in the intersection of the limitations of both
> > ACPI and DT, and I suspect this will only cause pain on both sides.
> >
> > > +                               }
> > > +                       }
> > > +               })
> > > +       }
> > > +
> > > +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.
> >
> > Is that an ASL limitation or a Linux limitation?
>
> This is a Linux implementation (or our choice of) limitation. Are there other
> argument types we should be considering?

Ok. I am not immediately aware of anything else that needs support. It's
just that the phrase "Nothing else is supported" was ambiguous, and I
was curious.

> > > +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().
> >
> > If we're expecting device class bindings to use high-level interfaces
> > (like pwm_get, clk_get, etc) then as far as I can see there is no reason
> > that the low-level representation in ACPI and DT need to be identical.
>
> There are properties that will not be subsystem specific, or rather that are
> simple key:value pairs that are convenient to access with the common mechanism.
> Even if we get a number of these abstractions in place, there is still value in
> a simple common property API in that it enables drivers to be ignorant of the
> underlying firmware-mechanism.

When you say not "subsystem specific" do you mean device-specific
properties or properties which are applicable to more than a particular
device or subsystem?

I can see that there will be common/equivalent properties. I can also
see that there will be cases where only DT or ACPI might have a
particular property (for legacy reasons or because information is not
implicit in ACPI where it is in DT).

I am of the opinion that handling the ACPI and DT cases separately is
preferable. I do not think that it is likely drivers for anything more
than trivial devices will be able to be ignorant of their underlying
firmware, especially if one platform requires the OS to manage clocks
and regulators while another manages this through AML (and we're in for
a world of hurt if another platform expects a mixture).

So far _DSD has been prototyped on reference platforms. I expect that
real implementations will be far more varied now that they have the
option to be.

> We have an example in this series for gpiolib - is this a good example in your
> opinion? Would adding examples/mechanism for pwm_get etc in the series help?
>
> > Importing DT bindings wholesale into ACPI only optimises for getting
> > things supported quickly, not getting things supported sanely.
> >
> > Thanks,
> > Mark.
>
> We're also trying to lower the barriers to enabling and writing new drivers that
> work on both DT and ACPI based systems without domain specific knowledge of
> each.

While that's the ideal case, I don't think it's as simple as mapping DT
bindings on to ACPI types. It will work in prototyping but I don't
believe it's going to stand up very well once we get a range of
differing HW designs trying to target it.

Are we going to get class properties standardized in ACPI, or is Linux
going to end up as the only OS supporting these properties?

> Thanks for taking the time to review and comment Mark, very much appreciated.

...and thanks for taking the time to reply. Let's see where this goes :)

Thanks,
Mark.

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

* Re: [RFC PATCH 5/9] mfd: Add ACPI support
  2014-08-17  6:04 ` [RFC PATCH 5/9] mfd: Add ACPI support Mika Westerberg
@ 2014-08-28 11:29     ` Lee Jones
  0 siblings, 0 replies; 54+ messages in thread
From: Lee Jones @ 2014-08-28 11:29 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Sun, 17 Aug 2014, Mika Westerberg wrote:

> If an MFD device is backed by ACPI namespace, we should allow subdevice
> drivers to access their corresponding ACPI companion devices through normal
> means (e.g using ACPI_COMPANION()).
> 
> This patch adds such support to the MFD core. If the MFD parent device
> doesn't specify any ACPI _HID/_CID for the child device, the child device
> will share the parent ACPI companion device. Otherwise the child device
> will be assigned with the corresponding ACPI companion, if found in the
> namespace below the parent.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> ---
>  Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
>  drivers/mfd/mfd-core.c             | 41 ++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/core.h           |  3 +++
>  3 files changed, 71 insertions(+)
> 
> diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
> index e182be5e3c83..74e35c54febf 100644
> --- a/Documentation/acpi/enumeration.txt
> +++ b/Documentation/acpi/enumeration.txt
> @@ -312,3 +312,30 @@ a code like this:
>  
>  There are also devm_* versions of these functions which release the
>  descriptors once the device is released.
> +
> +MFD devices
> +~~~~~~~~~~~
> +The MFD devices create platform devices from their children. For the
> +child devices there needs to be an ACPI handle that they can use to
> +reference parts of the ACPI namespace that relate to them. In the Linux
> +MFD subsystem we provide two ways:
> +
> +	o The children share the parent ACPI handle.
> +	o The MFD cell can specify the ACPI id of the device.
> +
> +For the first case, the MFD drivers do not need to do anything. The
> +resulting child platform device will have its ACPI_COMPANION() set to point
> +to the parent device.
> +
> +If the ACPI namespace has a device that we can match using an ACPI id,
> +the id should be set like:
> +
> +	static struct mfd_cell my_subdevice_cell = {
> +		.name = "my_subdevice",
> +		/* set the resources relative to the parent */
> +		.acpi_pnpid = "XYZ0001",
> +	};
> +
> +The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
> +the MFD device and if found, that ACPI companion device is bound to the
> +resulting child platform device.
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 892d343193ad..bb466b28b3b6 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -78,6 +78,45 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +#if IS_ENABLED(CONFIG_ACPI)
> +static void mfd_acpi_add_device(const struct mfd_cell *cell,
> +				struct platform_device *pdev)
> +{
> +	struct acpi_device *parent_adev;
> +	struct acpi_device *adev = NULL;
> +
> +	parent_adev = ACPI_COMPANION(pdev->dev.parent);
> +	if (!parent_adev)
> +		return;
> +
> +	/*
> +	 * MFD child device gets its ACPI handle either from the ACPI
> +	 * device directly under the parent that matches the acpi_pnpid or
> +	 * it will use the parent handle if is no acpi_pnpid is given.
> +	 */
> +	if (cell->acpi_pnpid) {
> +		struct acpi_device_id ids[2] = {};
> +		struct acpi_device *child_adev;
> +
> +		strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
> +		list_for_each_entry(child_adev, &parent_adev->children, node)
> +			if (acpi_match_device_ids(child_adev, ids)) {
> +				adev = child_adev;
> +				break;
> +			}

What happens if cell->acpi_pnpid is provided, but not matched?

Surely adev will them be NULL?

In these cases shouldn't you then "adev = parent_adev"?

> +	} else {
> +		adev = parent_adev;
> +	}
> +
> +	ACPI_COMPANION_SET(&pdev->dev, adev);
> +}
> +#else
> +static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
> +				       struct platform_device *pdev)
> +{
> +}
> +#endif
> +
>  static int mfd_add_device(struct device *parent, int id,
>  			  const struct mfd_cell *cell, atomic_t *usage_count,
>  			  struct resource *mem_base,
> @@ -118,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id,
>  		}
>  	}
>  
> +	mfd_acpi_add_device(cell, pdev);
> +
>  	if (cell->pdata_size) {
>  		ret = platform_device_add_data(pdev,
>  					cell->platform_data, cell->pdata_size);
> diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
> index f543de91ce19..73e1709d4c09 100644
> --- a/include/linux/mfd/core.h
> +++ b/include/linux/mfd/core.h
> @@ -44,6 +44,9 @@ struct mfd_cell {
>  	 */
>  	const char		*of_compatible;
>  
> +	/* Matches ACPI PNP id, either _HID or _CID */
> +	const char		*acpi_pnpid;
> +
>  	/*
>  	 * These resources can be specified relative to the parent device.
>  	 * For accessing hardware you should use resources from the platform dev

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
--
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

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

* Re: [RFC PATCH 5/9] mfd: Add ACPI support
@ 2014-08-28 11:29     ` Lee Jones
  0 siblings, 0 replies; 54+ messages in thread
From: Lee Jones @ 2014-08-28 11:29 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Sun, 17 Aug 2014, Mika Westerberg wrote:

> If an MFD device is backed by ACPI namespace, we should allow subdevice
> drivers to access their corresponding ACPI companion devices through normal
> means (e.g using ACPI_COMPANION()).
> 
> This patch adds such support to the MFD core. If the MFD parent device
> doesn't specify any ACPI _HID/_CID for the child device, the child device
> will share the parent ACPI companion device. Otherwise the child device
> will be assigned with the corresponding ACPI companion, if found in the
> namespace below the parent.
> 
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> ---
>  Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
>  drivers/mfd/mfd-core.c             | 41 ++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/core.h           |  3 +++
>  3 files changed, 71 insertions(+)
> 
> diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
> index e182be5e3c83..74e35c54febf 100644
> --- a/Documentation/acpi/enumeration.txt
> +++ b/Documentation/acpi/enumeration.txt
> @@ -312,3 +312,30 @@ a code like this:
>  
>  There are also devm_* versions of these functions which release the
>  descriptors once the device is released.
> +
> +MFD devices
> +~~~~~~~~~~~
> +The MFD devices create platform devices from their children. For the
> +child devices there needs to be an ACPI handle that they can use to
> +reference parts of the ACPI namespace that relate to them. In the Linux
> +MFD subsystem we provide two ways:
> +
> +	o The children share the parent ACPI handle.
> +	o The MFD cell can specify the ACPI id of the device.
> +
> +For the first case, the MFD drivers do not need to do anything. The
> +resulting child platform device will have its ACPI_COMPANION() set to point
> +to the parent device.
> +
> +If the ACPI namespace has a device that we can match using an ACPI id,
> +the id should be set like:
> +
> +	static struct mfd_cell my_subdevice_cell = {
> +		.name = "my_subdevice",
> +		/* set the resources relative to the parent */
> +		.acpi_pnpid = "XYZ0001",
> +	};
> +
> +The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
> +the MFD device and if found, that ACPI companion device is bound to the
> +resulting child platform device.
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 892d343193ad..bb466b28b3b6 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -78,6 +78,45 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
>  	return 0;
>  }
>  
> +#if IS_ENABLED(CONFIG_ACPI)
> +static void mfd_acpi_add_device(const struct mfd_cell *cell,
> +				struct platform_device *pdev)
> +{
> +	struct acpi_device *parent_adev;
> +	struct acpi_device *adev = NULL;
> +
> +	parent_adev = ACPI_COMPANION(pdev->dev.parent);
> +	if (!parent_adev)
> +		return;
> +
> +	/*
> +	 * MFD child device gets its ACPI handle either from the ACPI
> +	 * device directly under the parent that matches the acpi_pnpid or
> +	 * it will use the parent handle if is no acpi_pnpid is given.
> +	 */
> +	if (cell->acpi_pnpid) {
> +		struct acpi_device_id ids[2] = {};
> +		struct acpi_device *child_adev;
> +
> +		strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
> +		list_for_each_entry(child_adev, &parent_adev->children, node)
> +			if (acpi_match_device_ids(child_adev, ids)) {
> +				adev = child_adev;
> +				break;
> +			}

What happens if cell->acpi_pnpid is provided, but not matched?

Surely adev will them be NULL?

In these cases shouldn't you then "adev = parent_adev"?

> +	} else {
> +		adev = parent_adev;
> +	}
> +
> +	ACPI_COMPANION_SET(&pdev->dev, adev);
> +}
> +#else
> +static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
> +				       struct platform_device *pdev)
> +{
> +}
> +#endif
> +
>  static int mfd_add_device(struct device *parent, int id,
>  			  const struct mfd_cell *cell, atomic_t *usage_count,
>  			  struct resource *mem_base,
> @@ -118,6 +157,8 @@ static int mfd_add_device(struct device *parent, int id,
>  		}
>  	}
>  
> +	mfd_acpi_add_device(cell, pdev);
> +
>  	if (cell->pdata_size) {
>  		ret = platform_device_add_data(pdev,
>  					cell->platform_data, cell->pdata_size);
> diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
> index f543de91ce19..73e1709d4c09 100644
> --- a/include/linux/mfd/core.h
> +++ b/include/linux/mfd/core.h
> @@ -44,6 +44,9 @@ struct mfd_cell {
>  	 */
>  	const char		*of_compatible;
>  
> +	/* Matches ACPI PNP id, either _HID or _CID */
> +	const char		*acpi_pnpid;
> +
>  	/*
>  	 * These resources can be specified relative to the parent device.
>  	 * For accessing hardware you should use resources from the platform dev

-- 
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog

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

* Re: [RFC PATCH 5/9] mfd: Add ACPI support
  2014-08-28 11:29     ` Lee Jones
  (?)
@ 2014-08-28 11:45     ` Mika Westerberg
  -1 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-28 11:45 UTC (permalink / raw)
  To: Lee Jones
  Cc: Darren Hart, Rafael J. Wysocki, Aaron Lu, Max Eliaser,
	linux-acpi, devicetree, linux-kernel

On Thu, Aug 28, 2014 at 12:29:00PM +0100, Lee Jones wrote:
> On Sun, 17 Aug 2014, Mika Westerberg wrote:
> 
> > If an MFD device is backed by ACPI namespace, we should allow subdevice
> > drivers to access their corresponding ACPI companion devices through normal
> > means (e.g using ACPI_COMPANION()).
> > 
> > This patch adds such support to the MFD core. If the MFD parent device
> > doesn't specify any ACPI _HID/_CID for the child device, the child device
> > will share the parent ACPI companion device. Otherwise the child device
> > will be assigned with the corresponding ACPI companion, if found in the
> > namespace below the parent.
> > 
> > Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> > Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> > ---
> >  Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
> >  drivers/mfd/mfd-core.c             | 41 ++++++++++++++++++++++++++++++++++++++
> >  include/linux/mfd/core.h           |  3 +++
> >  3 files changed, 71 insertions(+)
> > 
> > diff --git a/Documentation/acpi/enumeration.txt b/Documentation/acpi/enumeration.txt
> > index e182be5e3c83..74e35c54febf 100644
> > --- a/Documentation/acpi/enumeration.txt
> > +++ b/Documentation/acpi/enumeration.txt
> > @@ -312,3 +312,30 @@ a code like this:
> >  
> >  There are also devm_* versions of these functions which release the
> >  descriptors once the device is released.
> > +
> > +MFD devices
> > +~~~~~~~~~~~
> > +The MFD devices create platform devices from their children. For the
> > +child devices there needs to be an ACPI handle that they can use to
> > +reference parts of the ACPI namespace that relate to them. In the Linux
> > +MFD subsystem we provide two ways:
> > +
> > +	o The children share the parent ACPI handle.
> > +	o The MFD cell can specify the ACPI id of the device.
> > +
> > +For the first case, the MFD drivers do not need to do anything. The
> > +resulting child platform device will have its ACPI_COMPANION() set to point
> > +to the parent device.
> > +
> > +If the ACPI namespace has a device that we can match using an ACPI id,
> > +the id should be set like:
> > +
> > +	static struct mfd_cell my_subdevice_cell = {
> > +		.name = "my_subdevice",
> > +		/* set the resources relative to the parent */
> > +		.acpi_pnpid = "XYZ0001",
> > +	};
> > +
> > +The ACPI id "XYZ0001" is then used to lookup an ACPI device directly under
> > +the MFD device and if found, that ACPI companion device is bound to the
> > +resulting child platform device.
> > diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> > index 892d343193ad..bb466b28b3b6 100644
> > --- a/drivers/mfd/mfd-core.c
> > +++ b/drivers/mfd/mfd-core.c
> > @@ -78,6 +78,45 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
> >  	return 0;
> >  }
> >  
> > +#if IS_ENABLED(CONFIG_ACPI)
> > +static void mfd_acpi_add_device(const struct mfd_cell *cell,
> > +				struct platform_device *pdev)
> > +{
> > +	struct acpi_device *parent_adev;
> > +	struct acpi_device *adev = NULL;
> > +
> > +	parent_adev = ACPI_COMPANION(pdev->dev.parent);
> > +	if (!parent_adev)
> > +		return;
> > +
> > +	/*
> > +	 * MFD child device gets its ACPI handle either from the ACPI
> > +	 * device directly under the parent that matches the acpi_pnpid or
> > +	 * it will use the parent handle if is no acpi_pnpid is given.
> > +	 */
> > +	if (cell->acpi_pnpid) {
> > +		struct acpi_device_id ids[2] = {};
> > +		struct acpi_device *child_adev;
> > +
> > +		strlcpy(ids[0].id, cell->acpi_pnpid, sizeof(ids[0].id));
> > +		list_for_each_entry(child_adev, &parent_adev->children, node)
> > +			if (acpi_match_device_ids(child_adev, ids)) {
> > +				adev = child_adev;
> > +				break;
> > +			}
> 
> What happens if cell->acpi_pnpid is provided, but not matched?
> 
> Surely adev will them be NULL?
> 
> In these cases shouldn't you then "adev = parent_adev"?

Good point. I'll fix that in the next version.

> 
> > +	} else {
> > +		adev = parent_adev;
> > +	}
> > +
> > +	ACPI_COMPANION_SET(&pdev->dev, adev);
> > +}
> > +#else
> > +static inline void mfd_acpi_add_device(const struct mfd_cell *cell,
> > +				       struct platform_device *pdev)
> > +{
> > +}
> > +#endif

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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
  2014-08-19  9:27       ` Mika Westerberg
@ 2014-08-19 15:21         ` Darren Hart
  -1 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-19 15:21 UTC (permalink / raw)
  To: Mika Westerberg, Jacob Pan
  Cc: Rafael J. Wysocki, Al Stone, Olof Johansson, Matthew Garrett,
	Matt Fleming, David Woodhouse, H. Peter Anvin, Josh Triplett,
	Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely, Rob Herring, linux-acpi

On 8/19/14, 4:27, "Mika Westerberg" <mika.westerberg@linux.intel.com>
wrote:

>On Mon, Aug 18, 2014 at 10:55:12AM -0700, Jacob Pan wrote:
>> On Sat, 16 Aug 2014 09:53:58 +0300
>> Mika Westerberg <mika.westerberg@linux.intel.com> 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.
>> > 
>> Do we always assume OF and ACPI _DSD will have the same property name
>> strings? i.e. in this patch "gpios"
>> > +	if (device_property_get(dev, "gpios", NULL)) {
>> > -		if (!of_find_property(pp, "gpios", NULL)) {
>> 
>> Maybe i missed something, but I don't think we can make that assumption
>> in BIOS. If not, what is the point of having unified interface?
>
>We recommend that when it makes sense, the property names in _DSD follow
>the corresponding DT names.
>

This is especially try for platform drivers such as this.

We will be creating subsystem types, "gpios", and defining them in the
_DSD Implementors Guide (per our discussion this morning at Kernel Summit).
-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
@ 2014-08-19 15:21         ` Darren Hart
  0 siblings, 0 replies; 54+ messages in thread
From: Darren Hart @ 2014-08-19 15:21 UTC (permalink / raw)
  To: Mika Westerberg, Jacob Pan
  Cc: Rafael J. Wysocki, Al Stone, Olof Johansson, Matthew Garrett,
	Matt Fleming, David Woodhouse, H. Peter Anvin, Josh Triplett,
	Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely, Rob Herring, linux-acpi, devicetree,
	linux-kernel

On 8/19/14, 4:27, "Mika Westerberg" <mika.westerberg@linux.intel.com>
wrote:

>On Mon, Aug 18, 2014 at 10:55:12AM -0700, Jacob Pan wrote:
>> On Sat, 16 Aug 2014 09:53:58 +0300
>> Mika Westerberg <mika.westerberg@linux.intel.com> 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.
>> > 
>> Do we always assume OF and ACPI _DSD will have the same property name
>> strings? i.e. in this patch "gpios"
>> > +	if (device_property_get(dev, "gpios", NULL)) {
>> > -		if (!of_find_property(pp, "gpios", NULL)) {
>> 
>> Maybe i missed something, but I don't think we can make that assumption
>> in BIOS. If not, what is the point of having unified interface?
>
>We recommend that when it makes sense, the property names in _DSD follow
>the corresponding DT names.
>

This is especially try for platform drivers such as this.

We will be creating subsystem types, "gpios", and defining them in the
_DSD Implementors Guide (per our discussion this morning at Kernel Summit).
-- 
Darren Hart					Open Source Technology Center
darren.hart@intel.com				            Intel Corporation




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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
  2014-08-18 17:55     ` Jacob Pan
@ 2014-08-19  9:27       ` Mika Westerberg
  -1 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-19  9:27 UTC (permalink / raw)
  To: Jacob Pan
  Cc: Darren Hart, Rafael J. Wysocki, Al Stone, Olof Johansson,
	Matthew Garrett, Matt Fleming, David Woodhouse, H. Peter Anvin,
	Josh Triplett, Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely

On Mon, Aug 18, 2014 at 10:55:12AM -0700, Jacob Pan wrote:
> On Sat, 16 Aug 2014 09:53:58 +0300
> Mika Westerberg <mika.westerberg@linux.intel.com> 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.
> > 
> Do we always assume OF and ACPI _DSD will have the same property name
> strings? i.e. in this patch "gpios"
> > +	if (device_property_get(dev, "gpios", NULL)) {
> > -		if (!of_find_property(pp, "gpios", NULL)) {
> 
> Maybe i missed something, but I don't think we can make that assumption
> in BIOS. If not, what is the point of having unified interface?

We recommend that when it makes sense, the property names in _DSD follow
the corresponding DT names.

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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
@ 2014-08-19  9:27       ` Mika Westerberg
  0 siblings, 0 replies; 54+ messages in thread
From: Mika Westerberg @ 2014-08-19  9:27 UTC (permalink / raw)
  To: Jacob Pan
  Cc: Darren Hart, Rafael J. Wysocki, Al Stone, Olof Johansson,
	Matthew Garrett, Matt Fleming, David Woodhouse, H. Peter Anvin,
	Josh Triplett, Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely, Rob Herring, linux-acpi, devicetree,
	linux-kernel

On Mon, Aug 18, 2014 at 10:55:12AM -0700, Jacob Pan wrote:
> On Sat, 16 Aug 2014 09:53:58 +0300
> Mika Westerberg <mika.westerberg@linux.intel.com> 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.
> > 
> Do we always assume OF and ACPI _DSD will have the same property name
> strings? i.e. in this patch "gpios"
> > +	if (device_property_get(dev, "gpios", NULL)) {
> > -		if (!of_find_property(pp, "gpios", NULL)) {
> 
> Maybe i missed something, but I don't think we can make that assumption
> in BIOS. If not, what is the point of having unified interface?

We recommend that when it makes sense, the property names in _DSD follow
the corresponding DT names.

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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
  2014-08-16  6:53 ` [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API Mika Westerberg
@ 2014-08-18 17:55     ` Jacob Pan
  0 siblings, 0 replies; 54+ messages in thread
From: Jacob Pan @ 2014-08-18 17:55 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Al Stone, Olof Johansson,
	Matthew Garrett, Matt Fleming, David Woodhouse, H. Peter Anvin,
	Josh Triplett, Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely

On Sat, 16 Aug 2014 09:53:58 +0300
Mika Westerberg <mika.westerberg@linux.intel.com> 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.
> 
Do we always assume OF and ACPI _DSD will have the same property name
strings? i.e. in this patch "gpios"
> +	if (device_property_get(dev, "gpios", NULL)) {
> -		if (!of_find_property(pp, "gpios", NULL)) {

Maybe i missed something, but I don't think we can make that assumption
in BIOS. If not, what is the point of having unified interface?

> The driver isn't converted to descriptor based gpio API due to there
> are a lot of existing users of struct gpio_keys_button that expects
> the gpio integer field. Though this can be solved by adding a new
> field of type struct gpio_desc but then there is another problem: the
> devm_gpiod_get needs to operate on the button device instead of its
> parent device that has the driver binded, so when the driver is
> unloaded, the resources for the gpio will not get freed
> automatically. Alternatively, we can introduce a new API, something
> like gpiod_find_index that does almost the same thing as
> gpiod_get_index but doesn't do the gpiod_request call and use it
> during finding button resources in gpio_keys_polled_get_button
> function. But then this may seem too complicated and not desirable.
> So in the end, a simple dev_get_gpiod_flags which is introduced in
> the last patch gets used and the gpio field of the struct
> gpio_keys_button can be got from the desc_to_gpio.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Max Eliaser <max@meliaserlow.dyndns.tv>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/input/keyboard/gpio_keys_polled.c | 139
> ++++++++++++++++++------------ 1 file changed, 84 insertions(+), 55
> deletions(-)
> 
> diff --git a/drivers/input/keyboard/gpio_keys_polled.c
> b/drivers/input/keyboard/gpio_keys_polled.c index
> 432d36395f35..49895d75aaff 100644 ---
> a/drivers/input/keyboard/gpio_keys_polled.c +++
> b/drivers/input/keyboard/gpio_keys_polled.c @@ -27,6 +27,7 @@
>  #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,78 +103,95 @@ static void gpio_keys_polled_close(struct
> input_polled_dev *dev) 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;
> +#if defined(CONFIG_OF) || defined(CONFIG_ACPI)
> +
> +struct button_proc_context {
>  	struct gpio_keys_platform_data *pdata;
> -	struct gpio_keys_button *button;
> -	int error;
> -	int nbuttons;
>  	int i;
> +};
>  
> -	node = dev->of_node;
> -	if (!node)
> -		return NULL;
> +static int gpio_keys_polled_get_button(struct device *dev, void
> *data) +{
> +	struct button_proc_context *c = data;
> +	struct gpio_keys_platform_data *pdata = c->pdata;
> +	struct gpio_keys_button *button = &pdata->buttons[c->i];
> +	struct gpio_desc *desc;
> +	enum gpio_lookup_flags flags;
> +	void *val;
> +
> +	if (device_property_get(dev, "gpios", NULL)) {
> +		pdata->nbuttons--;
> +		dev_warn(dev, "Found button without gpios\n");
> +		return 0;
> +	}
>  
> -	nbuttons = of_get_child_count(node);
> -	if (nbuttons == 0)
> -		return NULL;
> +	desc = dev_get_gpiod_flags(dev, 0, &flags);
> +	if (IS_ERR(desc)) {
> +		int error = PTR_ERR(desc);
>  
> -	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons *
> sizeof(*button),
> -			     GFP_KERNEL);
> -	if (!pdata)
> -		return ERR_PTR(-ENOMEM);
> +		if (error != -EPROBE_DEFER)
> +			dev_err(dev, "Failed to get gpio flags,
> error: %d\n",
> +				error);
> +		return error;
> +	}
>  
> -	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
> -	pdata->nbuttons = nbuttons;
> +	button->gpio = desc_to_gpio(desc);
> +	button->active_low = flags & GPIO_ACTIVE_LOW;
>  
> -	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
> -	of_property_read_u32(node, "poll-interval",
> &pdata->poll_interval);
> +	if (device_property_read(dev, "linux,code", DEV_PROP_U32,
> +				 &button->code)) {
> +		dev_err(dev, "Button without keycode: 0x%x\n",
> +				button->gpio);
> +		return -EINVAL;
> +	}
>  
> -	i = 0;
> -	for_each_child_of_node(node, pp) {
> -		int gpio;
> -		enum of_gpio_flags flags;
> +	if (!device_property_get(dev, "label", &val))
> +		button->desc = val;
>  
> -		if (!of_find_property(pp, "gpios", NULL)) {
> -			pdata->nbuttons--;
> -			dev_warn(dev, "Found button without
> gpios\n");
> -			continue;
> -		}
> +	if (device_property_read(dev, "linux,input-type",
> DEV_PROP_U32,
> +				 &button->type))
> +		button->type = EV_KEY;
>  
> -		gpio = of_get_gpio_flags(pp, 0, &flags);
> -		if (gpio < 0) {
> -			error = gpio;
> -			if (error != -EPROBE_DEFER)
> -				dev_err(dev,
> -					"Failed to get gpio flags,
> error: %d\n",
> -					error);
> -			return ERR_PTR(error);
> -		}
> +	button->wakeup = !device_property_get(dev,
> "gpio-key,wakeup", NULL); 
> -		button = &pdata->buttons[i++];
> +	if (device_property_read(dev, "debounce-interval",
> DEV_PROP_U32,
> +				 &button->debounce_interval))
> +		button->debounce_interval = 5;
>  
> -		button->gpio = gpio;
> -		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
> +	c->i++;
> +	return 0;
> +}
>  
> -		if (of_property_read_u32(pp, "linux,code",
> &button->code)) {
> -			dev_err(dev, "Button without keycode:
> 0x%x\n",
> -				button->gpio);
> -			return ERR_PTR(-EINVAL);
> -		}
> +static struct gpio_keys_platform_data *
> +gpio_keys_polled_get_devtree_pdata(struct device *dev)
> +{
> +	struct gpio_keys_platform_data *pdata;
> +	int size;
> +	struct button_proc_context c;
> +	int error;
> +	int nbuttons;
>  
> -		button->desc = of_get_property(pp, "label", NULL);
> +	nbuttons = device_property_child_count(dev);
> +	if (nbuttons <= 0)
> +		return NULL;
>  
> -		if (of_property_read_u32(pp, "linux,input-type",
> &button->type))
> -			button->type = EV_KEY;
> +	size = sizeof(*pdata) + nbuttons * sizeof(struct
> gpio_keys_button);
> +	pdata = devm_kzalloc(dev, size, GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
>  
> -		button->wakeup = !!of_get_property(pp,
> "gpio-key,wakeup", NULL);
> +	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
> +	pdata->nbuttons = nbuttons;
>  
> -		if (of_property_read_u32(pp, "debounce-interval",
> -					 &button->debounce_interval))
> -			button->debounce_interval = 5;
> -	}
> +	pdata->rep = !device_property_get(dev, "autorepeat", NULL);
> +	device_property_read(dev, "poll-interval", DEV_PROP_U32,
> +			     &pdata->poll_interval);
> +
> +	c.pdata = pdata;
> +	c.i = 0;
> +	error = device_for_each_child(dev, &c,
> gpio_keys_polled_get_button);
> +	if (error)
> +		return ERR_PTR(error);
>  
>  	if (pdata->nbuttons == 0)
>  		return ERR_PTR(-EINVAL);
> @@ -181,11 +199,21 @@ static struct gpio_keys_platform_data
> *gpio_keys_polled_get_devtree_pdata(struct return pdata;
>  }
>  
> +#ifdef CONFIG_OF
>  static const struct of_device_id gpio_keys_polled_of_match[] = {
>  	{ .compatible = "gpio-keys-polled", },
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static struct acpi_device_id gpio_keys_polled_acpi_match[] = {
> +	{ "MNW0002" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match);
> +#endif
>  
>  #else
>  
> @@ -309,6 +337,7 @@ static struct platform_driver
> gpio_keys_polled_driver = { .name	= DRV_NAME,
>  		.owner	= THIS_MODULE,
>  		.of_match_table =
> of_match_ptr(gpio_keys_polled_of_match),
> +		.acpi_match_table =
> ACPI_PTR(gpio_keys_polled_acpi_match), },
>  };
>  module_platform_driver(gpio_keys_polled_driver);

[Jacob Pan]

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

* Re: [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
@ 2014-08-18 17:55     ` Jacob Pan
  0 siblings, 0 replies; 54+ messages in thread
From: Jacob Pan @ 2014-08-18 17:55 UTC (permalink / raw)
  To: Mika Westerberg
  Cc: Darren Hart, Rafael J. Wysocki, Al Stone, Olof Johansson,
	Matthew Garrett, Matt Fleming, David Woodhouse, H. Peter Anvin,
	Josh Triplett, Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely, Rob Herring, linux-acpi, devicetree,
	linux-kernel

On Sat, 16 Aug 2014 09:53:58 +0300
Mika Westerberg <mika.westerberg@linux.intel.com> 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.
> 
Do we always assume OF and ACPI _DSD will have the same property name
strings? i.e. in this patch "gpios"
> +	if (device_property_get(dev, "gpios", NULL)) {
> -		if (!of_find_property(pp, "gpios", NULL)) {

Maybe i missed something, but I don't think we can make that assumption
in BIOS. If not, what is the point of having unified interface?

> The driver isn't converted to descriptor based gpio API due to there
> are a lot of existing users of struct gpio_keys_button that expects
> the gpio integer field. Though this can be solved by adding a new
> field of type struct gpio_desc but then there is another problem: the
> devm_gpiod_get needs to operate on the button device instead of its
> parent device that has the driver binded, so when the driver is
> unloaded, the resources for the gpio will not get freed
> automatically. Alternatively, we can introduce a new API, something
> like gpiod_find_index that does almost the same thing as
> gpiod_get_index but doesn't do the gpiod_request call and use it
> during finding button resources in gpio_keys_polled_get_button
> function. But then this may seem too complicated and not desirable.
> So in the end, a simple dev_get_gpiod_flags which is introduced in
> the last patch gets used and the gpio field of the struct
> gpio_keys_button can be got from the desc_to_gpio.
> 
> Signed-off-by: Aaron Lu <aaron.lu@intel.com>
> Signed-off-by: Max Eliaser <max@meliaserlow.dyndns.tv>
> Reviewed-by: Darren Hart <dvhart@linux.intel.com>
> Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
> ---
>  drivers/input/keyboard/gpio_keys_polled.c | 139
> ++++++++++++++++++------------ 1 file changed, 84 insertions(+), 55
> deletions(-)
> 
> diff --git a/drivers/input/keyboard/gpio_keys_polled.c
> b/drivers/input/keyboard/gpio_keys_polled.c index
> 432d36395f35..49895d75aaff 100644 ---
> a/drivers/input/keyboard/gpio_keys_polled.c +++
> b/drivers/input/keyboard/gpio_keys_polled.c @@ -27,6 +27,7 @@
>  #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,78 +103,95 @@ static void gpio_keys_polled_close(struct
> input_polled_dev *dev) 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;
> +#if defined(CONFIG_OF) || defined(CONFIG_ACPI)
> +
> +struct button_proc_context {
>  	struct gpio_keys_platform_data *pdata;
> -	struct gpio_keys_button *button;
> -	int error;
> -	int nbuttons;
>  	int i;
> +};
>  
> -	node = dev->of_node;
> -	if (!node)
> -		return NULL;
> +static int gpio_keys_polled_get_button(struct device *dev, void
> *data) +{
> +	struct button_proc_context *c = data;
> +	struct gpio_keys_platform_data *pdata = c->pdata;
> +	struct gpio_keys_button *button = &pdata->buttons[c->i];
> +	struct gpio_desc *desc;
> +	enum gpio_lookup_flags flags;
> +	void *val;
> +
> +	if (device_property_get(dev, "gpios", NULL)) {
> +		pdata->nbuttons--;
> +		dev_warn(dev, "Found button without gpios\n");
> +		return 0;
> +	}
>  
> -	nbuttons = of_get_child_count(node);
> -	if (nbuttons == 0)
> -		return NULL;
> +	desc = dev_get_gpiod_flags(dev, 0, &flags);
> +	if (IS_ERR(desc)) {
> +		int error = PTR_ERR(desc);
>  
> -	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons *
> sizeof(*button),
> -			     GFP_KERNEL);
> -	if (!pdata)
> -		return ERR_PTR(-ENOMEM);
> +		if (error != -EPROBE_DEFER)
> +			dev_err(dev, "Failed to get gpio flags,
> error: %d\n",
> +				error);
> +		return error;
> +	}
>  
> -	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
> -	pdata->nbuttons = nbuttons;
> +	button->gpio = desc_to_gpio(desc);
> +	button->active_low = flags & GPIO_ACTIVE_LOW;
>  
> -	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
> -	of_property_read_u32(node, "poll-interval",
> &pdata->poll_interval);
> +	if (device_property_read(dev, "linux,code", DEV_PROP_U32,
> +				 &button->code)) {
> +		dev_err(dev, "Button without keycode: 0x%x\n",
> +				button->gpio);
> +		return -EINVAL;
> +	}
>  
> -	i = 0;
> -	for_each_child_of_node(node, pp) {
> -		int gpio;
> -		enum of_gpio_flags flags;
> +	if (!device_property_get(dev, "label", &val))
> +		button->desc = val;
>  
> -		if (!of_find_property(pp, "gpios", NULL)) {
> -			pdata->nbuttons--;
> -			dev_warn(dev, "Found button without
> gpios\n");
> -			continue;
> -		}
> +	if (device_property_read(dev, "linux,input-type",
> DEV_PROP_U32,
> +				 &button->type))
> +		button->type = EV_KEY;
>  
> -		gpio = of_get_gpio_flags(pp, 0, &flags);
> -		if (gpio < 0) {
> -			error = gpio;
> -			if (error != -EPROBE_DEFER)
> -				dev_err(dev,
> -					"Failed to get gpio flags,
> error: %d\n",
> -					error);
> -			return ERR_PTR(error);
> -		}
> +	button->wakeup = !device_property_get(dev,
> "gpio-key,wakeup", NULL); 
> -		button = &pdata->buttons[i++];
> +	if (device_property_read(dev, "debounce-interval",
> DEV_PROP_U32,
> +				 &button->debounce_interval))
> +		button->debounce_interval = 5;
>  
> -		button->gpio = gpio;
> -		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
> +	c->i++;
> +	return 0;
> +}
>  
> -		if (of_property_read_u32(pp, "linux,code",
> &button->code)) {
> -			dev_err(dev, "Button without keycode:
> 0x%x\n",
> -				button->gpio);
> -			return ERR_PTR(-EINVAL);
> -		}
> +static struct gpio_keys_platform_data *
> +gpio_keys_polled_get_devtree_pdata(struct device *dev)
> +{
> +	struct gpio_keys_platform_data *pdata;
> +	int size;
> +	struct button_proc_context c;
> +	int error;
> +	int nbuttons;
>  
> -		button->desc = of_get_property(pp, "label", NULL);
> +	nbuttons = device_property_child_count(dev);
> +	if (nbuttons <= 0)
> +		return NULL;
>  
> -		if (of_property_read_u32(pp, "linux,input-type",
> &button->type))
> -			button->type = EV_KEY;
> +	size = sizeof(*pdata) + nbuttons * sizeof(struct
> gpio_keys_button);
> +	pdata = devm_kzalloc(dev, size, GFP_KERNEL);
> +	if (!pdata)
> +		return ERR_PTR(-ENOMEM);
>  
> -		button->wakeup = !!of_get_property(pp,
> "gpio-key,wakeup", NULL);
> +	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
> +	pdata->nbuttons = nbuttons;
>  
> -		if (of_property_read_u32(pp, "debounce-interval",
> -					 &button->debounce_interval))
> -			button->debounce_interval = 5;
> -	}
> +	pdata->rep = !device_property_get(dev, "autorepeat", NULL);
> +	device_property_read(dev, "poll-interval", DEV_PROP_U32,
> +			     &pdata->poll_interval);
> +
> +	c.pdata = pdata;
> +	c.i = 0;
> +	error = device_for_each_child(dev, &c,
> gpio_keys_polled_get_button);
> +	if (error)
> +		return ERR_PTR(error);
>  
>  	if (pdata->nbuttons == 0)
>  		return ERR_PTR(-EINVAL);
> @@ -181,11 +199,21 @@ static struct gpio_keys_platform_data
> *gpio_keys_polled_get_devtree_pdata(struct return pdata;
>  }
>  
> +#ifdef CONFIG_OF
>  static const struct of_device_id gpio_keys_polled_of_match[] = {
>  	{ .compatible = "gpio-keys-polled", },
>  	{ },
>  };
>  MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
> +#endif
> +
> +#ifdef CONFIG_ACPI
> +static struct acpi_device_id gpio_keys_polled_acpi_match[] = {
> +	{ "MNW0002" },
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match);
> +#endif
>  
>  #else
>  
> @@ -309,6 +337,7 @@ static struct platform_driver
> gpio_keys_polled_driver = { .name	= DRV_NAME,
>  		.owner	= THIS_MODULE,
>  		.of_match_table =
> of_match_ptr(gpio_keys_polled_of_match),
> +		.acpi_match_table =
> ACPI_PTR(gpio_keys_polled_acpi_match), },
>  };
>  module_platform_driver(gpio_keys_polled_driver);

[Jacob Pan]

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

* [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API
  2014-08-16  6:53 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
@ 2014-08-16  6:53 ` Mika Westerberg
  2014-08-18 17:55     ` Jacob Pan
  0 siblings, 1 reply; 54+ messages in thread
From: Mika Westerberg @ 2014-08-16  6:53 UTC (permalink / raw)
  To: Darren Hart, Rafael J. Wysocki
  Cc: Al Stone, Olof Johansson, Matthew Garrett, Matt Fleming,
	David Woodhouse, H. Peter Anvin, Jacob Pan, Josh Triplett,
	Aaron Lu, Max Eliaser, Robert Moore, Len Brown,
	Greg Kroah-Hartman, Linus Walleij, Alexandre Courbot, Mark Brown,
	Dmitry Torokhov, Bryan Wu, Richard Purdie, Samuel Ortiz,
	Lee Jones, Grant Likely, Rob Herring, Mika Westerberg,
	linux-acpi, devicetree, linux-kernel

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.

The driver isn't converted to descriptor based gpio API due to there are
a lot of existing users of struct gpio_keys_button that expects the gpio
integer field. Though this can be solved by adding a new field of type
struct gpio_desc but then there is another problem: the devm_gpiod_get
needs to operate on the button device instead of its parent device that
has the driver binded, so when the driver is unloaded, the resources for
the gpio will not get freed automatically. Alternatively, we can
introduce a new API, something like gpiod_find_index that does almost
the same thing as gpiod_get_index but doesn't do the gpiod_request call
and use it during finding button resources in gpio_keys_polled_get_button
function. But then this may seem too complicated and not desirable. So
in the end, a simple dev_get_gpiod_flags which is introduced in the last
patch gets used and the gpio field of the struct gpio_keys_button can be
got from the desc_to_gpio.

Signed-off-by: Aaron Lu <aaron.lu@intel.com>
Signed-off-by: Max Eliaser <max@meliaserlow.dyndns.tv>
Reviewed-by: Darren Hart <dvhart@linux.intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
 drivers/input/keyboard/gpio_keys_polled.c | 139 ++++++++++++++++++------------
 1 file changed, 84 insertions(+), 55 deletions(-)

diff --git a/drivers/input/keyboard/gpio_keys_polled.c b/drivers/input/keyboard/gpio_keys_polled.c
index 432d36395f35..49895d75aaff 100644
--- a/drivers/input/keyboard/gpio_keys_polled.c
+++ b/drivers/input/keyboard/gpio_keys_polled.c
@@ -27,6 +27,7 @@
 #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,78 +103,95 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)
 		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;
+#if defined(CONFIG_OF) || defined(CONFIG_ACPI)
+
+struct button_proc_context {
 	struct gpio_keys_platform_data *pdata;
-	struct gpio_keys_button *button;
-	int error;
-	int nbuttons;
 	int i;
+};
 
-	node = dev->of_node;
-	if (!node)
-		return NULL;
+static int gpio_keys_polled_get_button(struct device *dev, void *data)
+{
+	struct button_proc_context *c = data;
+	struct gpio_keys_platform_data *pdata = c->pdata;
+	struct gpio_keys_button *button = &pdata->buttons[c->i];
+	struct gpio_desc *desc;
+	enum gpio_lookup_flags flags;
+	void *val;
+
+	if (device_property_get(dev, "gpios", NULL)) {
+		pdata->nbuttons--;
+		dev_warn(dev, "Found button without gpios\n");
+		return 0;
+	}
 
-	nbuttons = of_get_child_count(node);
-	if (nbuttons == 0)
-		return NULL;
+	desc = dev_get_gpiod_flags(dev, 0, &flags);
+	if (IS_ERR(desc)) {
+		int error = PTR_ERR(desc);
 
-	pdata = devm_kzalloc(dev, sizeof(*pdata) + nbuttons * sizeof(*button),
-			     GFP_KERNEL);
-	if (!pdata)
-		return ERR_PTR(-ENOMEM);
+		if (error != -EPROBE_DEFER)
+			dev_err(dev, "Failed to get gpio flags, error: %d\n",
+				error);
+		return error;
+	}
 
-	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
-	pdata->nbuttons = nbuttons;
+	button->gpio = desc_to_gpio(desc);
+	button->active_low = flags & GPIO_ACTIVE_LOW;
 
-	pdata->rep = !!of_get_property(node, "autorepeat", NULL);
-	of_property_read_u32(node, "poll-interval", &pdata->poll_interval);
+	if (device_property_read(dev, "linux,code", DEV_PROP_U32,
+				 &button->code)) {
+		dev_err(dev, "Button without keycode: 0x%x\n",
+				button->gpio);
+		return -EINVAL;
+	}
 
-	i = 0;
-	for_each_child_of_node(node, pp) {
-		int gpio;
-		enum of_gpio_flags flags;
+	if (!device_property_get(dev, "label", &val))
+		button->desc = val;
 
-		if (!of_find_property(pp, "gpios", NULL)) {
-			pdata->nbuttons--;
-			dev_warn(dev, "Found button without gpios\n");
-			continue;
-		}
+	if (device_property_read(dev, "linux,input-type", DEV_PROP_U32,
+				 &button->type))
+		button->type = EV_KEY;
 
-		gpio = of_get_gpio_flags(pp, 0, &flags);
-		if (gpio < 0) {
-			error = gpio;
-			if (error != -EPROBE_DEFER)
-				dev_err(dev,
-					"Failed to get gpio flags, error: %d\n",
-					error);
-			return ERR_PTR(error);
-		}
+	button->wakeup = !device_property_get(dev, "gpio-key,wakeup", NULL);
 
-		button = &pdata->buttons[i++];
+	if (device_property_read(dev, "debounce-interval", DEV_PROP_U32,
+				 &button->debounce_interval))
+		button->debounce_interval = 5;
 
-		button->gpio = gpio;
-		button->active_low = flags & OF_GPIO_ACTIVE_LOW;
+	c->i++;
+	return 0;
+}
 
-		if (of_property_read_u32(pp, "linux,code", &button->code)) {
-			dev_err(dev, "Button without keycode: 0x%x\n",
-				button->gpio);
-			return ERR_PTR(-EINVAL);
-		}
+static struct gpio_keys_platform_data *
+gpio_keys_polled_get_devtree_pdata(struct device *dev)
+{
+	struct gpio_keys_platform_data *pdata;
+	int size;
+	struct button_proc_context c;
+	int error;
+	int nbuttons;
 
-		button->desc = of_get_property(pp, "label", NULL);
+	nbuttons = device_property_child_count(dev);
+	if (nbuttons <= 0)
+		return NULL;
 
-		if (of_property_read_u32(pp, "linux,input-type", &button->type))
-			button->type = EV_KEY;
+	size = sizeof(*pdata) + nbuttons * sizeof(struct gpio_keys_button);
+	pdata = devm_kzalloc(dev, size, GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
 
-		button->wakeup = !!of_get_property(pp, "gpio-key,wakeup", NULL);
+	pdata->buttons = (struct gpio_keys_button *)(pdata + 1);
+	pdata->nbuttons = nbuttons;
 
-		if (of_property_read_u32(pp, "debounce-interval",
-					 &button->debounce_interval))
-			button->debounce_interval = 5;
-	}
+	pdata->rep = !device_property_get(dev, "autorepeat", NULL);
+	device_property_read(dev, "poll-interval", DEV_PROP_U32,
+			     &pdata->poll_interval);
+
+	c.pdata = pdata;
+	c.i = 0;
+	error = device_for_each_child(dev, &c, gpio_keys_polled_get_button);
+	if (error)
+		return ERR_PTR(error);
 
 	if (pdata->nbuttons == 0)
 		return ERR_PTR(-EINVAL);
@@ -181,11 +199,21 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(struct
 	return pdata;
 }
 
+#ifdef CONFIG_OF
 static const struct of_device_id gpio_keys_polled_of_match[] = {
 	{ .compatible = "gpio-keys-polled", },
 	{ },
 };
 MODULE_DEVICE_TABLE(of, gpio_keys_polled_of_match);
+#endif
+
+#ifdef CONFIG_ACPI
+static struct acpi_device_id gpio_keys_polled_acpi_match[] = {
+	{ "MNW0002" },
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, gpio_keys_polled_acpi_match);
+#endif
 
 #else
 
@@ -309,6 +337,7 @@ static struct platform_driver gpio_keys_polled_driver = {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
 		.of_match_table = of_match_ptr(gpio_keys_polled_of_match),
+		.acpi_match_table = ACPI_PTR(gpio_keys_polled_acpi_match),
 	},
 };
 module_platform_driver(gpio_keys_polled_driver);
-- 
2.1.0.rc1

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

end of thread, other threads:[~2014-08-28 11:45 UTC | newest]

Thread overview: 54+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-17  6:04 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
2014-08-17  6:04 ` [RFC PATCH 1/9] ACPI: Add support for device specific properties Mika Westerberg
2014-08-18  8:13   ` Hanjun Guo
2014-08-18  8:27     ` Mika Westerberg
2014-08-18  8:57       ` Hanjun Guo
2014-08-18 12:37       ` Darren Hart
2014-08-18 12:37         ` Darren Hart
     [not found] ` <1408255459-17625-1-git-send-email-mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
2014-08-17  6:04   ` [RFC PATCH 2/9] ACPI: Document ACPI " Mika Westerberg
2014-08-17  6:04     ` Mika Westerberg
2014-08-18 10:54     ` Mark Rutland
2014-08-18 16:05       ` Mika Westerberg
2014-08-19  5:45       ` Darren Hart
2014-08-19  5:45         ` Darren Hart
2014-08-19 16:51         ` Mark Rutland
2014-08-17  6:04   ` [RFC PATCH 6/9] gpiolib: add API to get gpio desc and flags Mika Westerberg
2014-08-17  6:04     ` Mika Westerberg
2014-08-17 13:00     ` Grant Likely
2014-08-17 13:00       ` Grant Likely
2014-08-17 17:43       ` Darren Hart
2014-08-17 17:43         ` Darren Hart
2014-08-18  4:57         ` Rafael J. Wysocki
     [not found]           ` <1927766.GeLld99ozq-sKB8Sp2ER+y1GS7QM15AGw@public.gmane.org>
2014-08-18  7:16             ` Aaron Lu
2014-08-18  7:16               ` Aaron Lu
2014-08-19 15:58             ` Grant Likely
2014-08-19 15:58               ` Grant Likely
2014-08-17  6:04   ` [RFC PATCH 7/9] gpio: sch: Consolidate core and resume banks Mika Westerberg
2014-08-17  6:04     ` Mika Westerberg
2014-08-17  6:04 ` [RFC PATCH 3/9] Driver core: Unified device properties interface for platform firmware Mika Westerberg
2014-08-17 12:49   ` Grant Likely
2014-08-17 12:49     ` Grant Likely
2014-08-17 17:31     ` Darren Hart
2014-08-17 17:31       ` Darren Hart
2014-08-18  4:55       ` Rafael J. Wysocki
2014-08-18  4:46     ` Rafael J. Wysocki
2014-08-17  6:04 ` [RFC PATCH 4/9] of: Add property_ops callback for devices with of_node Mika Westerberg
2014-08-17 12:54   ` Grant Likely
2014-08-17 12:54     ` Grant Likely
2014-08-18  9:29     ` Mika Westerberg
     [not found]       ` <20140818092937.GT2462-3PARRvDOhMZrdx17CPfAsdBPR1lH4CV8@public.gmane.org>
2014-08-18 12:44         ` Darren Hart
2014-08-18 12:44           ` Darren Hart
2014-08-18  0:44   ` Rob Herring
2014-08-17  6:04 ` [RFC PATCH 5/9] mfd: Add ACPI support Mika Westerberg
2014-08-28 11:29   ` Lee Jones
2014-08-28 11:29     ` Lee Jones
2014-08-28 11:45     ` Mika Westerberg
2014-08-17  6:04 ` [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API Mika Westerberg
2014-08-17  6:04 ` [RFC PATCH 9/9] leds: leds-gpio: " Mika Westerberg
  -- strict thread matches above, loose matches on Subject: below --
2014-08-16  6:53 [RFC PATCH 0/9] Add ACPI _DSD and unified device properties support Mika Westerberg
2014-08-16  6:53 ` [RFC PATCH 8/9] Input: gpio_keys_polled - Make use of device property API Mika Westerberg
2014-08-18 17:55   ` Jacob Pan
2014-08-18 17:55     ` Jacob Pan
2014-08-19  9:27     ` Mika Westerberg
2014-08-19  9:27       ` Mika Westerberg
2014-08-19 15:21       ` Darren Hart
2014-08-19 15:21         ` Darren Hart

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.