From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 12:28:41
This is a second revision of the patches first submitted here [1].
The recent publication of the ACPI 5.1 specification [2] 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 [3].
An ACPI Device Properties UUID has been defined [4] 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 3 example drivers that were previously Device Tree aware that
can now be used with either Device Tree or ACPI Device Properties. The
drivers use "PRP0001" as their _HID which means that the match should be
done using driver's .of_match_table instead.
The patch series has been tested on Minnoboard and Minnowboard MAX and the
relevant part of DSDTs are at the end of this cover letter.
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.
Most important changes to the previous RFC version:
* Added wrapper functions for most used property types
* Return -EOVERFLOW in case integer would not fit to a type
* Dropped dev_prop_ops
* We now have dev_node_xxx() functions to access firmware node
properties without dev pointer
* The accessor function names try to be close to their corresponding of_*
counterpart
* Tried to have a bit better examples in the documentation patch
* gpiolib got support for _DSD and also it now understand firmware node
properties with dev_node_get_named_gpiod() that requests the GPIO
properly.
* Support for "PRP0001" _HID/_CID. This means that the match should be
done using driver .of_match_table instead.
* Add unified property support for at25 SPI eeprom driver as well.
[1] https://lkml.org/lkml/2014/8/17/10
[2] http://www.uefi.org/sites/default/files/resources/ACPI_5_1release.pdf
[3] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[4] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Aaron Lu (2):
input: gpio_keys_polled - Add support for GPIO descriptors
input: gpio_keys_polled - Make use of device property API
Max Eliaser (2):
leds: leds-gpio: Make use of device property API
leds: leds-gpio: Add ACPI probing support
Mika Westerberg (11):
ACPI: Add support for device specific properties
ACPI: Allow drivers to match using Device Tree compatible property
ACPI: Document ACPI device specific properties
mfd: Add ACPI support
gpio / ACPI: Add support for _DSD device properties
gpio: Add support for unified device properties interface
gpio: sch: Consolidate core and resume banks
leds: leds-gpio: Add support for GPIO descriptors
input: gpio_keys_polled - Add ACPI probing support
misc: at25: Make use of device property API
misc: at25: Add ACPI probing support
Rafael J. Wysocki (1):
Driver core: Unified device properties interface for platform firmware
Documentation/acpi/enumeration.txt | 27 ++
Documentation/acpi/properties.txt | 410 +++++++++++++++++++++
drivers/acpi/Makefile | 1 +
drivers/acpi/internal.h | 6 +
drivers/acpi/property.c | 584 ++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 93 ++++-
drivers/base/Makefile | 2 +-
drivers/base/property.c | 196 ++++++++++
drivers/gpio/devres.c | 35 ++
drivers/gpio/gpio-sch.c | 293 ++++++---------
drivers/gpio/gpiolib-acpi.c | 78 +++-
drivers/gpio/gpiolib.c | 85 ++++-
drivers/gpio/gpiolib.h | 7 +-
drivers/input/keyboard/gpio_keys_polled.c | 169 +++++----
drivers/leds/leds-gpio.c | 188 +++++-----
drivers/mfd/mfd-core.c | 40 ++
drivers/misc/eeprom/at25.c | 41 +--
drivers/of/base.c | 188 ++++++++++
include/acpi/acpi_bus.h | 8 +
include/linux/acpi.h | 90 ++++-
include/linux/gpio/consumer.h | 7 +
include/linux/gpio_keys.h | 3 +
include/linux/leds.h | 1 +
include/linux/mfd/core.h | 3 +
include/linux/of.h | 37 ++
include/linux/property.h | 193 ++++++++++
26 files changed, 2377 insertions(+), 408 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 modifications for Minnowboard (for leds-gpio.c and gpio_keys_polled.c)
---------------------------------------------------------------------------
Scope (\_SB.PCI0.LPC)
{
Device (LEDS)
{
Name (_HID, "PRP0001")
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}
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"gpio-leds"}},
}
})
Device (LEDH)
{
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 (_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", "off"},
Package () {"linux,retain-state-suspended", 1},
}
})
}
}
Device (BTNS)
{
Name (_HID, "PRP0001")
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0, 1, 2, 3}
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"gpio-keys-polled"}},
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},
Package () {"gpios", Package () {^^BTNS, 0, 0, 1}},
}
})
}
Device (BTN1)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"linux,code", 108},
Package () {"linux,input-type", 1},
Package () {"gpios", Package (4) {^^BTNS, 0, 1, 1}},
}
})
}
Device (BTN2)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"linux,code", 103},
Package () {"linux,input-type", 1},
Package () {"gpios", Package () {^^BTNS, 0, 2, 1}},
}
})
}
Device (BTN3)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"linux,code", 106},
Package () {"linux,input-type", 1},
Package () {"gpios", Package (4) {^^BTNS, 0, 3, 1}},
}
})
}
}
}
DSDT modifications for Minnowboard MAX (for at25.c)
---------------------------------------------------
Scope (\_SB.SPI1)
{
Device (AT25)
{
Name (_HID, "PRP0001")
Method (_CRS, 0, Serialized) {
Name (UBUF, ResourceTemplate () {
SpiSerialBus (0x0000, PolarityLow, FourWireMode, 0x08,
ControllerInitiated, 0x007A1200, ClockPolarityLow,
ClockPhaseSecond, "\\_SB.SPI1",
0x00, ResourceConsumer)
})
Return (UBUF)
}
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"atmel,at25"}},
Package () {"size", 1024},
Package () {"pagesize", 32},
Package () {"address-width", 16},
}
})
Method (_STA, 0, NotSerialized)
{
Return (0xF)
}
}
}
--
2.1.0
--
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
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:52:59
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 <redacted>
---
Documentation/acpi/properties.txt | 410 ++++++++++++++++++++++++++++++++++++++
1 file changed, 410 insertions(+)
create mode 100644 Documentation/acpi/properties.txt
@@ -0,0 +1,410 @@+ACPI device properties+======================+This document describes the format and interfaces of ACPI device+properties as specified in "Device Properties UUID For _DSD" available+here:++http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf++1. Introduction+---------------+In systems that use ACPI and want to take advantage of device specific+properties, there needs to be a standard way to return and extract+name-value pairs for a given ACPI device.++An ACPI device that wants to export its properties must implement a+static name called _DSD that takes no arguments and returns a package of+packages:++ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"name1", <VALUE1>},+ Package () {"name2", <VALUE2>}+ }+ })++The UUID identifies contents of the following package. In case of ACPI+device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301.++In each returned package, the first item is the name and must be a string.+The corresponding value can be a string, integer, reference, or package. If+a package it may only contain strings, integers, and references.++An example device where we might need properties is a device that uses+GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to+know which GPIO is used for which purpose.++To solve this we add the following ACPI device properties to the device:++ Device (DEV0)+ {+ Name (_CRS, ResourceTemplate () {+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}+ ...+ })++ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"reset-gpio", {^DEV0, 0, 0, 0}},+ Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}},+ }+ })+ }++Now the device driver can reference the GPIOs using names instead of+using indexes.++If there is an existing Device Tree binding for a device, it is expected+that the same bindings are used with ACPI properties, so that the driver+dealing with the device needs only minor modifications if any.++2. Formal definition of properties+----------------------------------+The following chapters define the currently supported properties. For+these there exists a helper function that can be used to extract the+property value.++2.1 Integer types+-----------------+ACPI integers are always 64-bit. However, for drivers the full range is+typically not needed so we provide a set of functions which convert the+64-bit integer to a smaller Linux integer type.++An integer property looks like this:++ Package () {"i2c-sda-hold-time-ns", 300},+ Package () {"clock-frequency", 400000},++To read a property value, use a unified property accessor as shown+below:++ u32 val;+ int ret;++ ret = device_property_read_u32(dev, "clock-frequency", &val);+ if (ret)+ /* Handle error */++The function returns 0 if the property is copied to 'val' or negative+errno if something went wrong (or the property does not exist).++2.2 Integer arrays+------------------+An integer array is a package holding only integers. Arrays can be used to+represent different things like Linux input key codes to GPIO mappings, pin+control settings, dma request lines, etc.++An integer array looks like this:++ Package () {+ "max8952,dvs-mode-microvolt",+ Package () {+ 1250000,+ 1200000,+ 1050000,+ 950000,+ }+ }++The above array property can be accessed like:++ u32 voltages[4];+ int ret;++ ret = device_property_read_u32_array(dev, "max8952,dvs-mode-microvolt",+ voltages, ARRAY_SIZE(voltages));+ if (ret)+ /* Handle error */+++All functions copy the resulting values cast to a requested type to the+caller supplied array. If you pass NULL in the value pointer ('voltages' in+this case), the function returns number of items in the array. This can be+useful if caller does not know size of the array beforehand.++2.3 Strings+-----------+String properties can be used to describe many things like labels for GPIO+buttons, compability ids, etc.++A string property looks like this:++ Package () {"pwm-names", "backlight"},+ Package () {"label", "Status-LED"},++You can use device_property_read_string() to extract strings:++ const char *val;+ int ret;++ ret = device_property_read_string(dev, "label", &val);+ if (ret)+ /* Handle error */++Note that the function does not copy the returned string but instead the+value is modified to point to the string property itself.++The memory is owned by the associated ACPI device object and released+when it is removed. The user need not free the associated memory.++2.4 String arrays+-----------------+String arrays can be useful in describing a list of labels, names for+DMA channels, etc.++A string array property looks like this:++ Package () {"dma-names", Package () {"tx", "rx", "rx-tx"}},+ Package () {"clock-output-names", Package () {"pll", "pll-switched"}},++And these can be read in similar way that the integer arrrays:++ const char *dma_names[3];+ int ret;++ ret = device_property_read_string_array(dev, "dma-names", dma_names,+ ARRAY_SIZE(dma_names));+ if (ret)+ /* Handle error */++The memory management rules follow what is specified for single strings.+Specifically the returned pointers should be treated as constant and not to+be freed. That is done automatically when the correspondig ACPI device+object is released.++2.5 Object references+---------------------+An ACPI object reference is used to refer to some object in the+namespace. For example, if a device has dependencies with some other+object, an object reference can be used.++An object reference looks like this:++ Package () {"dev0", \_SB.DEV0},++At the time of writing this, there is no unified device_property_* accessor+for references so one needs to use the following ACPI helper function:++ int acpi_dev_get_property_reference(struct acpi_device *adev,+ const char *name,+ const char *size_prop, int index,+ struct acpi_reference_args *args);++The referenced ACPI device is returned in args->adev if found.++In addition to simple object references it is also possible to have object+references with arguments. These are represented in ASL as follows:++ Device (\_SB.PCI0.PWM)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"#pwm-cells", 2}+ }+ })+ }++ Device (\_SB.PCI0.BL)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {+ "pwms",+ Package () {+ \_SB.PCI0.PWM, 0, 5000000,+ \_SB.PCI0.PWM, 1, 4500000,+ }+ }+ }+ })+ }++In the above example, the referenced device declares a property that+returns the number of expected arguments (here it is "#pwm-cells"). If+no such property is given we assume that all the integers following the+reference are arguments.++In the above example PWM device expects 2 additional arguments. This+will be validated by the ACPI property core.++The additional arguments must be integers. Nothing else is supported.++It is possible, as in the above example, to have multiple references+with varying number of integer arguments. It is up to the referenced+device to declare how many arguments it expects. The 'index' parameter+selects which reference is returned.++One can use acpi_dev_get_property_reference() as well to extract the+information in additional parameters:++ struct acpi_reference_args args;+ struct acpi_device *adev = /* this will point to the BL device */+ int ret;++ /* extract the first reference */+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 0, &args);++ BUG_ON(args.nargs != 2);+ BUG_ON(args.args[0] != 0);+ BUG_ON(args.args[1] != 5000000);++ /* extract the second reference */+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 1, &args);++ BUG_ON(args.nargs != 2);+ BUG_ON(args.args[0] != 1);+ BUG_ON(args.args[1] != 4500000);++In addition to arguments, args.adev now points to the ACPI device that+corresponds to \_SB.PCI0.PWM.++It is intended that this function is not used directly but instead+subsystems like pwm implement their ACPI support on top of this function+in such way that it is hidden from the client drivers, such as via+pwm_get().++3. Device property hierarchies+------------------------------+Devices are organized in a tree within the Linux kernel. It follows that+the configuration data would also be hierarchical. In order to reach+equivalence with Device Tree, the ACPI mechanism must also provide some+sort of tree-like representation. Fortunately, the ACPI namespace is+already such a structure.++For example, we could have the following device in ACPI namespace. The+KEYS device is much like gpio_keys_polled.c in that it includes "pseudo"+devices for each GPIO:++ Device (KEYS)+ {+ Name (_CRS, ResourceTemplate () {+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}+ ...+ })++ // "pseudo" devices declared under the parent device+ Device (BTN0) {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"label", "minnow_btn0"}+ Package () {"gpios", Package () {^KEYS, 0, 0, 1}}+ }+ })+ }++ Device (BTN1) {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"label", "minnow_btn1"}+ Package () {"gpios", Package () {^KEYS, 1, 0, 1}}+ }+ })+ }+ }++We can extract the above in gpio_keys_polled.c like:++ static int gpio_keys_polled_create_button(struct fw_dev_node *fdn,+ void *data)+ {+ struct button_data *bdata = data;+ const char *label = NULL;++ /*+ * We need to use dev_node_ variant here to access the+ * firmware properties.+ */+ dev_node_property_read_string(fdn, "label", &label);+ /* and so on */+ }++ static void gpio_keys_polled_probe(struct device *dev)+ {+ /* Properties for the KEYS device itself */+ device_property_read(dev, ...);++ /*+ * Iterate over button devices and extract their+ * firmware configuration.+ */+ ret = device_for_each_child_node(dev, gpio_keys_polled_create_button,+ &bdata);+ if (ret)+ /* Handle error */+ }++Note that you still need proper error handling which is omitted in the+above example.++4. Existing Device Tree enabled drivers+---------------------------------------+At the time of writing this, there are ~250 existing DT enabled drivers.+Allocating _HID/_CID for each would not be feasible. To make sure that+those drivers can still be used on ACPI systems, we provide an+alternative way to get these matched.++There is a special _HID "PRP0001" which means that use the DT bindings+for matching this device to a driver. The driver needs to have+.of_match_table filled in even when !CONFIG_OF.++An example device would be leds that can be controlled via GPIOs. This+is represented as "leds-gpio" device and looks like this in the ACPI+namespace:++ Device (LEDS)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"compatible", Package () {"gpio-leds"}},+ }+ })+ ...+ }++In order to get the existing drivers/leds/leds-gpio.c bound to this+device, we take advantage of "PRP0001":++ /* Following already exists in the driver */+ static const struct of_device_id of_gpio_leds_match[] = {+ { .compatible = "gpio-leds", },+ {},+ };+ MODULE_DEVICE_TABLE(of, of_gpio_leds_match);++ /* This we add to the driver to get it probed */+ static const struct acpi_device_id acpi_gpio_leds_match[] = {+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */+ {},+ };+ MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match);++ static struct platform_driver gpio_led_driver = {+ .driver = {+ /*+ * No of_match_ptr() here because we want this+ * table to be visible even when !CONFIG_OF to+ * match against "compatible" in _DSD.+ */+ .of_match_table = of_gpio_leds_match,+ .acpi_match_table = acpi_gpio_leds_match,+ },+ };++Once ACPI core sees "PRP0001" and that the device has "compatible"+property it will do the match using .of_match_table instead.++It is preferred that new devices get a proper _HID allocated for them+instead of inventing new DT "compatible" devices.
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:01
From: "Rafael J. Wysocki" <redacted>
Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type. The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.
Three general helper functions, device_get_property(),
device_read_property() and device_read_property_array() are provided.
The first one allows the raw value of a given device property to be
accessed 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. Static inline wrappers are also
provided for the various property data types that can be passed to
device_read_property() or device_read_property_array() for extra type
checking.
In addition to that new generic routines are provided for retrieving
properties from device description objects in the platform firmware
in case there are no struct device objects for them (either those
objects have not been created yet or they do not exist at all).
Again, three functions are provided, dev_node_get_property(),
dev_node_read_property(), dev_node_read_property_array(), in analogy
with device_get_property(), device_read_property() and
device_read_property_array() described above, respectively, along
with static inline wrappers for all of the propery data types that
can be used. For all of them, the first argument is a pointer to
struct fw_dev_node (new type) that in turn contains exactly one
valid pointer to a device description object (depending on what
platform firmware interface is in use).
Finally, device_for_each_child_node() is added for iterating over
the children of the device description object associated with the
given device.
The interface covers both ACPI and Device Trees.
This change set includes material from Mika Westerberg and Aaron Lu.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/acpi/property.c | 186 ++++++++++++++++++++++++++++++++++++++++++++
drivers/base/Makefile | 2 +-
drivers/base/property.c | 196 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/of/base.c | 188 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 42 ++++++++++
include/linux/of.h | 37 +++++++++
include/linux/property.h | 193 ++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 843 insertions(+), 1 deletion(-)
create mode 100644 drivers/base/property.c
create mode 100644 include/linux/property.h
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:07
With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
other things as well) returned by _CRS. Previously we were only able to
use integer index to find the corresponding GPIO, which is pretty error
prone if the order changes.
With _DSD we can now query GPIOs using name instead of an integer index,
like the below example shows:
// Bluetooth device with reset and shutdown GPIOs
Device (BTH)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate ()
{
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {15}
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
})
Name (_DSD, Package ()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
}
})
}
The format of the supported GPIO property is:
Package () { "name", Package () { ref, index, pin, active_low }}
ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
typically this is the device itself (BTH in our case).
index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
active_low - If 1 the GPIO is marked as active_low.
Since ACPI GpioIo() resource does not have field saying whether it is
active low or high, the "active_low" argument can be used here. Setting
it to 1 marks the GPIO as active low.
In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.
This patch implements necessary support to gpiolib for extracting GPIOs
using _DSD device properties.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/gpio/gpiolib-acpi.c | 78 +++++++++++++++++++++++++++++++++++++--------
drivers/gpio/gpiolib.c | 30 ++++++++++++++---
drivers/gpio/gpiolib.h | 7 ++--
3 files changed, 94 insertions(+), 21 deletions(-)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:10
From: Aaron Lu <redacted>
Make use of device property API in this driver so that both OF based
system and ACPI based system can use this driver.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/input/keyboard/gpio_keys_polled.c | 125 ++++++++++++++----------------
1 file changed, 59 insertions(+), 66 deletions(-)
@@ -102,21 +105,56 @@ static void gpio_keys_polled_close(struct input_polled_dev *dev)pdata->disable(bdev->dev);}-#ifdef CONFIG_OF+staticintgpio_keys_polled_get_button(structfw_dev_node*fdn,void*data)+{+structgpio_keys_devtree_data*dtdata=data;+structgpio_keys_platform_data*pdata=dtdata->pdata;+structdevice*dev=dtdata->dev;+structgpio_keys_button*button;+structgpio_desc*desc;++desc=devm_node_get_named_gpiod(dev,fdn,"gpios",0);+if(IS_ERR(desc)){+interr=PTR_ERR(desc);++if(err!=-EPROBE_DEFER)+dev_err(dev,"Failed to get gpio flags, error: %d\n",+err);+returnerr;+}++button=&pdata->buttons[pdata->nbuttons++];+button->gpiod=desc;++if(dev_node_property_read_u32(fdn,"linux,code",&button->code)){+dev_err(dev,"Button without keycode: %d\n",+pdata->nbuttons-1);+return-EINVAL;+}++dev_node_property_read_string(fdn,"label",&button->desc);++if(dev_node_property_read_u32(fdn,"linux,input-type",&button->type))+button->type=EV_KEY;++button->wakeup=!dev_node_get_property(fdn,"gpio-key,wakeup",NULL);++if(dev_node_property_read_u32(fdn,"debounce-interval",+&button->debounce_interval))+button->debounce_interval=5;++return0;+}+staticstructgpio_keys_platform_data*gpio_keys_polled_get_devtree_pdata(structdevice*dev){-structdevice_node*node,*pp;+structgpio_keys_devtree_datadtdata;structgpio_keys_platform_data*pdata;structgpio_keys_button*button;interror;intnbuttons;-inti;-node=dev->of_node;-if(!node)-returnNULL;--nbuttons=of_get_child_count(node);+nbuttons=device_get_child_node_count(dev);if(nbuttons==0)returnNULL;
@@ -126,54 +164,18 @@ static struct gpio_keys_platform_data *gpio_keys_polled_get_devtree_pdata(structreturnERR_PTR(-ENOMEM);pdata->buttons=(structgpio_keys_button*)(pdata+1);-pdata->nbuttons=nbuttons;--pdata->rep=!!of_get_property(node,"autorepeat",NULL);-of_property_read_u32(node,"poll-interval",&pdata->poll_interval);--i=0;-for_each_child_of_node(node,pp){-intgpio;-enumof_gpio_flagsflags;--if(!of_find_property(pp,"gpios",NULL)){-pdata->nbuttons--;-dev_warn(dev,"Found button without gpios\n");-continue;-}--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);-returnERR_PTR(error);-}-button=&pdata->buttons[i++];+pdata->rep=!device_get_property(dev,"autorepeat",NULL);+device_property_read_u32(dev,"poll-interval",&pdata->poll_interval);-button->gpio=gpio;-button->active_low=flags&OF_GPIO_ACTIVE_LOW;+memset(&dtdata,0,sizeof(dtdata));+dtdata.pdata=pdata;+dtdata.dev=dev;-if(of_property_read_u32(pp,"linux,code",&button->code)){-dev_err(dev,"Button without keycode: 0x%x\n",-button->gpio);-returnERR_PTR(-EINVAL);-}--button->desc=of_get_property(pp,"label",NULL);--if(of_property_read_u32(pp,"linux,input-type",&button->type))-button->type=EV_KEY;--button->wakeup=!!of_get_property(pp,"gpio-key,wakeup",NULL);--if(of_property_read_u32(pp,"debounce-interval",-&button->debounce_interval))-button->debounce_interval=5;-}+error=device_for_each_child_node(dev,gpio_keys_polled_get_button,+&dtdata);+if(error)+returnERR_PTR(error);if(pdata->nbuttons==0)returnERR_PTR(-EINVAL);
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:15
This is actually a single device with two sets of identical registers,
which just happen to start from a different offset. Instead of having
separate GPIO chips created we consolidate them to be single GPIO chip.
In addition having a single GPIO chip allows us to handle ACPI GPIO
translation in the core in a more generic way, since the two GPIO chips
share the same parent ACPI device.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <redacted>
---
drivers/gpio/gpio-sch.c | 293 ++++++++++++++++++------------------------------
1 file changed, 112 insertions(+), 181 deletions(-)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:31
From: Max Eliaser <redacted>
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 <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/leds/leds-gpio.c | 102 +++++++++++++++++++++--------------------------
1 file changed, 45 insertions(+), 57 deletions(-)
@@ -171,65 +170,61 @@ static inline int sizeof_gpio_leds_priv(int num_leds)(sizeof(structgpio_led_data)*num_leds);}-/* Code to create from OpenFirmware platform devices */-#ifdef CONFIG_OF_GPIO-staticstructgpio_leds_priv*gpio_leds_create_of(structplatform_device*pdev)+staticintgpio_leds_create_led(structfw_dev_node*fdn,void*data)+{+structgpio_leds_priv*priv=data;+structgpio_ledled={};+constchar*state=NULL;++led.gpiod=devm_node_get_named_gpiod(priv->dev,fdn,"gpios",0);+if(IS_ERR(led.gpiod))+returnPTR_ERR(led.gpiod);++dev_node_property_read_string(fdn,"label",&led.name);+dev_node_property_read_string(fdn,"linux,default-trigger",+&led.default_trigger);++dev_node_property_read_string(fdn,"linux,default_state",&state);+if(state){+if(!strcmp(state,"keep"))+led.default_state=LEDS_GPIO_DEFSTATE_KEEP;+elseif(!strcmp(state,"on"))+led.default_state=LEDS_GPIO_DEFSTATE_ON;+else+led.default_state=LEDS_GPIO_DEFSTATE_OFF;+}++if(!dev_node_get_property(fdn,"retain-state-suspended",NULL))+led.retain_state_suspended=1;++returncreate_gpio_led(&led,&priv->leds[priv->num_leds++],priv->dev,+NULL);+}++staticstructgpio_leds_priv*gpio_leds_create(structplatform_device*pdev){-structdevice_node*np=pdev->dev.of_node,*child;structgpio_leds_priv*priv;-intcount,ret;+intret,count;-/* count LEDs in this device, so we know how much to allocate */-count=of_get_available_child_count(np);+count=device_get_child_node_count(&pdev->dev);if(!count)returnERR_PTR(-ENODEV);-for_each_available_child_of_node(np,child)-if(of_get_gpio(child,0)==-EPROBE_DEFER)-returnERR_PTR(-EPROBE_DEFER);-priv=devm_kzalloc(&pdev->dev,sizeof_gpio_leds_priv(count),GFP_KERNEL);if(!priv)returnERR_PTR(-ENOMEM);-for_each_available_child_of_node(np,child){-structgpio_ledled={};-enumof_gpio_flagsflags;-constchar*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;-elseif(!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);-gotoerr;-}+priv->dev=&pdev->dev;+ret=device_for_each_child_node(&pdev->dev,gpio_leds_create_led,+priv);+if(ret){+for(count=priv->num_leds-2;count>=0;count--)+delete_gpio_led(&priv->leds[count]);+returnERR_PTR(ret);}returnpriv;--err:-for(count=priv->num_leds-2;count>=0;count--)-delete_gpio_led(&priv->leds[count]);-returnERR_PTR(-ENODEV);}staticconststructof_device_idof_gpio_leds_match[]={
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:53:49
From: Max Eliaser <redacted>
This allows the driver to probe from ACPI namespace.
Signed-off-by: Max Eliaser <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/leds/leds-gpio.c | 8 ++++++++
1 file changed, 8 insertions(+)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:54:07
Add support for matching using DT compatible string from ACPI _DSD.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/misc/eeprom/at25.c | 7 +++++++
1 file changed, 7 insertions(+)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:54:08
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
does not 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 <redacted>
---
Lee, I tried to get rid of #ifdefs in the below patch but it wasn't
possible because we are using functions that are not available when
!CONFIG_ACPI.
Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
drivers/mfd/mfd-core.c | 40 ++++++++++++++++++++++++++++++++++++++
include/linux/mfd/core.h | 3 +++
3 files changed, 70 insertions(+)
@@ -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 register their children as platform devices. 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.
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:55:34
Make use of device property API in this driver so that both DT and ACPI
based systems can use this driver.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/misc/eeprom/at25.c | 34 +++++++++++++---------------------
1 file changed, 13 insertions(+), 21 deletions(-)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:56:30
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/leds/leds-gpio.c | 80 +++++++++++++++++++++++++++---------------------
include/linux/leds.h | 1 +
2 files changed, 46 insertions(+), 35 deletions(-)
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,elselevel=1;-if(led_dat->active_low)-level=!level;-/* Setting GPIOs with I2C/etc requires a task context, and we don't*seemtohaveareliablewaytoknowifwe'realreadyinone;so*let'sjustassumetheworst.
@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev,{structgpio_led_data*led_dat=container_of(led_cdev,structgpio_led_data,cdev);+intgpio=desc_to_gpio(led_dat->gpiod);led_dat->blinking=1;-returnled_dat->platform_gpio_blink_set(led_dat->gpio,GPIO_LED_BLINK,+returnled_dat->platform_gpio_blink_set(gpio,GPIO_LED_BLINK,delay_on,delay_off);}
@@ -97,24 +104,33 @@ static int create_gpio_led(const struct gpio_led *template,{intret,state;-led_dat->gpio=-1;+if(!template->gpiod){+unsignedlongflags=0;-/* skip leds that aren't available */-if(!gpio_is_valid(template->gpio)){-dev_info(parent,"Skipping unavailable LED gpio %d (%s)\n",-template->gpio,template->name);-return0;-}+/* skip leds that aren't available */+if(!gpio_is_valid(template->gpio)){+dev_info(parent,"Skipping unavailable LED gpio %d (%s)\n",+template->gpio,template->name);+return0;+}-ret=devm_gpio_request(parent,template->gpio,template->name);-if(ret<0)-returnret;+if(template->active_low)+flags|=GPIOF_ACTIVE_LOW;++ret=devm_gpio_request_one(parent,template->gpio,flags,+template->name);+if(ret<0)+returnret;++led_dat->gpiod=gpio_to_desc(template->gpio);+if(IS_ERR(led_dat->gpiod))+returnPTR_ERR(led_dat->gpiod);+}led_dat->cdev.name=template->name;led_dat->cdev.default_trigger=template->default_trigger;-led_dat->gpio=template->gpio;-led_dat->can_sleep=gpio_cansleep(template->gpio);-led_dat->active_low=template->active_low;+led_dat->gpiod=template->gpiod;+led_dat->can_sleep=gpiod_cansleep(template->gpiod);led_dat->blinking=0;if(blink_set){led_dat->platform_gpio_blink_set=blink_set;
@@ -122,30 +138,24 @@ static int create_gpio_led(const struct gpio_led *template,}led_dat->cdev.brightness_set=gpio_led_set;if(template->default_state==LEDS_GPIO_DEFSTATE_KEEP)-state=!!gpio_get_value_cansleep(led_dat->gpio)^led_dat->active_low;+state=!!gpiod_get_value_cansleep(led_dat->gpiod);elsestate=(template->default_state==LEDS_GPIO_DEFSTATE_ON);led_dat->cdev.brightness=state?LED_FULL:LED_OFF;if(!template->retain_state_suspended)led_dat->cdev.flags|=LED_CORE_SUSPENDRESUME;-ret=gpio_direction_output(led_dat->gpio,led_dat->active_low^state);+ret=gpiod_direction_output(led_dat->gpiod,state);if(ret<0)returnret;INIT_WORK(&led_dat->work,gpio_led_work);-ret=led_classdev_register(parent,&led_dat->cdev);-if(ret<0)-returnret;--return0;+returnled_classdev_register(parent,&led_dat->cdev);}staticvoiddelete_gpio_led(structgpio_led_data*led){-if(!gpio_is_valid(led->gpio))-return;led_classdev_unregister(&led->cdev);cancel_work_sync(&led->work);}
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:56:31
From: Aaron Lu <redacted>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/input/keyboard/gpio_keys_polled.c | 39 +++++++++++++++++++++----------
include/linux/gpio_keys.h | 3 +++
2 files changed, 30 insertions(+), 12 deletions(-)
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 11:57:07
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/gpio/devres.c | 35 +++++++++++++++++++++++++++
drivers/gpio/gpiolib.c | 55 +++++++++++++++++++++++++++++++++++++++++++
include/linux/gpio/consumer.h | 7 ++++++
3 files changed, 97 insertions(+)
@@ -1717,6 +1717,61 @@ struct gpio_desc *__must_check __gpiod_get_index(struct device *dev,EXPORT_SYMBOL_GPL(__gpiod_get_index);/**+*dev_node_get_named_gpiod-obtainaGPIOfromfirmwaredevicenode+*@fdn:firmwaredevicenode+*@propname:nameofthefirmwareproperty+*@idx:indexoftheGPIOinthepropertyvalueincaseofmany+*+*Thisfunctioncanbeusedfordriversthatgettheirconfiguration+*fromfirmwareinsuchwaythatthereisnotalwayscorresponding+*physicaldevicepointeravailable.Forexamplesomepropertiesare+*describedasachildnodesfortheparentdeviceinDTorACPI.+*+*FunctionproperlyfindsthecorrespondingGPIOusingwhateveristhe+*underlyingfirmwareinterfaceandthenmakessurethattheGPIO+*descriptorisrequestedbeforeitisreturnedtothecaller.+*+*IncaseoferroranERR_PTR()isreturned.+*/+structgpio_desc*dev_node_get_named_gpiod(structfw_dev_node*fdn,+constchar*propname,intindex)+{+structgpio_desc*desc=ERR_PTR(-ENODEV);+structacpi_device*adev=fdn->acpi_node;+structdevice_node*np=fdn->of_node;+boolactive_low=false;+intret;++if(IS_ENABLED(CONFIG_OF)&&np){+enumof_gpio_flagsflags;++desc=of_get_named_gpiod_flags(np,propname,index,&flags);+if(!IS_ERR(desc))+active_low=flags&OF_GPIO_ACTIVE_LOW;+}elseif(IS_ENABLED(CONFIG_ACPI)&&adev){+structacpi_gpio_infoinfo;++desc=acpi_get_gpiod_by_index(adev,propname,index,&info);+if(!IS_ERR(desc))+active_low=info.active_low;+}++if(IS_ERR(desc))+returndesc;++ret=gpiod_request(desc,NULL);+if(ret)+returnERR_PTR(ret);++/* Only value flag can be set from both DT and ACPI is active_low */+if(active_low)+set_bit(FLAG_ACTIVE_LOW,&desc->flags);++returndesc;+}+EXPORT_SYMBOL_GPL(dev_node_get_named_gpiod);++/***gpiod_get_index_optional-obtainanoptionalGPIOfromamulti-indexGPIO*function*@dev:GPIOconsumer,canbeNULLforsystem-globalGPIOs
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 12:28:55
We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead.
If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/acpi/property.c | 34 ++++++++++++++++++
drivers/acpi/scan.c | 91 +++++++++++++++++++++++++++++++++++++++++++------
include/acpi/acpi_bus.h | 1 +
include/linux/acpi.h | 8 ++---
4 files changed, 118 insertions(+), 16 deletions(-)
@@ -864,6 +890,51 @@ int acpi_match_device_ids(struct acpi_device *device,}EXPORT_SYMBOL(acpi_match_device_ids);+/* Performs match for special "PRP0001" shoehorn ACPI ID */+staticboolacpi_of_driver_match_device(structdevice*dev,+conststructdevice_driver*drv)+{+structacpi_device*adev=ACPI_COMPANION(dev);+constunionacpi_object*of_compatible;+inti;++/*+*IftheACPIdevicedoesnothavecorrespondingcompatible+*propertyorthedriverinquestiondoesnothaveDTmatching+*tableweconsiderthematchsuccesful(matchestheACPIID).+*/+of_compatible=adev->data.of_compatible;+if(!drv->of_match_table||!of_compatible)+returntrue;++/* Now we can look for the driver DT compatible strings */+for(i=0;i<of_compatible->package.count;i++){+conststructof_device_id*id;+constunionacpi_object*obj;++obj=&of_compatible->package.elements[i];++for(id=drv->of_match_table;id->compatible[0];id++)+if(!strcasecmp(obj->string.pointer,id->compatible))+returntrue;+}++returnfalse;+}++boolacpi_driver_match_device(structdevice*dev,+conststructdevice_driver*drv)+{+conststructacpi_device_id*id;++id=acpi_match_device(drv->acpi_match_table,dev);+if(!id)+returnfalse;++returnacpi_of_driver_match_device(dev,drv);+}+EXPORT_SYMBOL_GPL(acpi_driver_match_device);+staticvoidacpi_free_power_resources_lists(structacpi_device*device){inti;
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-16 12:28:57
Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.
ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.
In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.
If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"name1", <VALUE1>},
Package () {"name2", <VALUE2>},
...
}
})
The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].
We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.
The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.
[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Reviewed-by: Hanjun Guo <redacted>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Darren Hart <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
---
drivers/acpi/Makefile | 1 +
drivers/acpi/internal.h | 6 +
drivers/acpi/property.c | 364 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 2 +
include/acpi/acpi_bus.h | 7 +
include/linux/acpi.h | 40 ++++++
6 files changed, 420 insertions(+)
create mode 100644 drivers/acpi/property.c
@@ -0,0 +1,364 @@+/*+*ACPIdevicespecificpropertiessupport.+*+*Copyright(C)2014,IntelCorporation+*Allrightsreserved.+*+*Authors:MikaWesterberg<mika.westerberg@linux.intel.com>+*DarrenHart<dvhart@linux.intel.com>+*RafaelJ.Wysocki<rafael.j.wysocki@intel.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*/++#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 */+staticconstu8prp_uuid[16]={+0x14,0xd8,0xff,0xda,0xba,0x6e,0x8c,0x4d,+0x8a,0x91,0xbc,0x9b,0xbf,0x4a,0xa3,0x01+};++staticboolacpi_property_value_ok(constunionacpi_object*value)+{+intj;++/*+*Thevaluemustbeaninteger,astring,areference,orapackage+*whoseeveryelementmustbeaninteger,astring,orareference.+*/+switch(value->type){+caseACPI_TYPE_INTEGER:+caseACPI_TYPE_STRING:+caseACPI_TYPE_LOCAL_REFERENCE:+returntrue;++caseACPI_TYPE_PACKAGE:+for(j=0;j<value->package.count;j++)+switch(value->package.elements[j].type){+caseACPI_TYPE_INTEGER:+caseACPI_TYPE_STRING:+caseACPI_TYPE_LOCAL_REFERENCE:+continue;++default:+returnfalse;+}++returntrue;+}+returnfalse;+}++staticboolacpi_properties_format_valid(constunionacpi_object*properties)+{+inti;++for(i=0;i<properties->package.count;i++){+constunionacpi_object*property;++property=&properties->package.elements[i];+/*+*Onlytwoelementsallowed,thefirstonemustbeastringand+*thesecondonehastosatisfycertainconditions.+*/+if(property->package.count!=2+||property->package.elements[0].type!=ACPI_TYPE_STRING+||!acpi_property_value_ok(&property->package.elements[1]))+returnfalse;+}+returntrue;+}++voidacpi_init_properties(structacpi_device*adev)+{+structacpi_bufferbuf={ACPI_ALLOCATE_BUFFER};+constunionacpi_object*desc;+acpi_statusstatus;+inti;++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)+gotofail;++/* Look for the device properties UUID. */+for(i=0;i<desc->package.count;i+=2){+constunionacpi_object*uuid,*properties;++uuid=&desc->package.elements[i];+properties=&desc->package.elements[i+1];++/*+*ThefirstelementmustbeaUUIDandthesecondonemustbe+*apackage.+*/+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;++/*+*WefoundthematchingUUID.Nowvalidatetheformatofthe+*packageimmediatelyfollowingit.+*/+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);+}++voidacpi_free_properties(structacpi_device*adev)+{+ACPI_FREE((void*)adev->data.pointer);+adev->data.pointer=NULL;+adev->data.properties=NULL;+}++/**+*acpi_dev_get_property-returnanACPIpropertywithgivenname+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@type:Expectedpropertytype+*@obj:Locationtostorethepropertyvalue(ifnot%NULL)+*+*Lookupapropertywith@nameandstoreapointertotheresultingACPI+*objectatthelocationpointedtoby@objiffound.+*+*Callersmustnotattempttofreethereturnedobjects.Theseobjectswillbe+*freedbytheACPIcoreautomaticallyduringtheremovalof@adev.+*+*Return:%0ifpropertywith@namehasbeenfound(success),+*%-EINVALiftheargumentsareinvalid,+*%-ENODATAifthepropertydoesn'texist,+*%-EPROTOifthepropertyvaluetypedoesn'tmatch@type.+*/+intacpi_dev_get_property(structacpi_device*adev,constchar*name,+acpi_object_typetype,constunionacpi_object**obj)+{+constunionacpi_object*properties;+inti;++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++){+constunionacpi_object*propname,*propvalue;+constunionacpi_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;+elseif(obj)+*obj=propvalue;++return0;+}+}+return-ENODATA;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property);++/**+*acpi_dev_get_property_array-returnanACPIarraypropertywithgivenname+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@type:Expectedtypeofarrayelements+*@obj:Locationtostoreapointertothepropertyvalue(ifnotNULL)+*+*Lookupanarraypropertywith@nameandstoreapointertotheresulting+*ACPIobjectatthelocationpointedtoby@objiffound.+*+*Callersmustnotattempttofreethereturnedobjects.Thoseobjectswillbe+*freedbytheACPIcoreautomaticallyduringtheremovalof@adev.+*+*Return:%0ifarrayproperty(package)with@namehasbeenfound(success),+*%-EINVALiftheargumentsareinvalid,+*%-ENODATAifthepropertydoesn'texist,+*%-EPROTOifthepropertyisnotapackageorthetypeofitselements+*doesn'tmatch@type.+*/+intacpi_dev_get_property_array(structacpi_device*adev,constchar*name,+acpi_object_typetype,+constunionacpi_object**obj)+{+constunionacpi_object*prop;+intret,i;++ret=acpi_dev_get_property(adev,name,ACPI_TYPE_PACKAGE,&prop);+if(ret)+returnret;++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;++return0;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);++/**+*acpi_dev_get_property_reference-returnshandletothereferencedobject+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@size_prop:Nameofthe"size"propertyinreferencedobject+*@index:Indexofthereferencetoreturn+*@args:Locationtostorethereturnedreferencewithoptionalarguments+*+*Findpropertywith@name,verififythatitisapackagecontainingatleast+*oneobjectreferenceandifso,storetheACPIdeviceobjectpointertothe+*targetobjectin@args->adev.+*+*Ifthereferenceincludesarguments(@size_propisnot%NULL)followthe+*referenceandcheckwhetherornotthereisanintegerproperty@size_prop+*underthetargetobjectandifso,whetherornotitsvaluematchesthe+*numberofargumentsthatfollowthereference.Ifthere'smorethanone+*referenceinthepropertyvaluepackage,@indexisusedtoselecttheoneto+*return.+*+*Return:%0onsuccess,negativeerrorcodeonfailure.+*/+intacpi_dev_get_property_reference(structacpi_device*adev,constchar*name,+constchar*size_prop,size_tindex,+structacpi_reference_args*args)+{+constunionacpi_object*element,*end;+constunionacpi_object*obj;+structacpi_device*device;+intret,idx=0;++ret=acpi_dev_get_property(adev,name,ACPI_TYPE_ANY,&obj);+if(ret)+returnret;++/*+*Thesimplestcaseiswhenthevalueisasinglereference.Just+*returnthatreferencethen.+*/+if(obj->type==ACPI_TYPE_LOCAL_REFERENCE){+if(size_prop||index)+return-EINVAL;++ret=acpi_bus_get_device(obj->reference.handle,&device);+if(ret)+returnret;++args->adev=device;+args->nargs=0;+return0;+}++/*+*Ifitisnotasinglereference,thenitisapackageof+*referencesfollowedbynumberofintsasfollows:+*+*Package(){REF,INT,REF,INT,INT}+*+*Theindexargumentisthenusedtodeterminewhichreference+*thecallerwants(alongwiththearguments).+*/+if(obj->type!=ACPI_TYPE_PACKAGE||index>=obj->package.count)+return-EPROTO;++element=obj->package.elements;+end=element+obj->package.count;++while(element<end){+u32nargs,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){+constunionacpi_object*prop;++/*+*Findouthowmanyargumentstherefencedobject+*expectsbyreadingitssize_propproperty.+*/+ret=acpi_dev_get_property(device,size_prop,+ACPI_TYPE_INTEGER,&prop);+if(ret)+returnret;++nargs=prop->integer.value;+if(nargs>MAX_ACPI_REFERENCE_ARGS+||element+nargs>end)+return-EPROTO;++/*+*Skiptothestartoftheargumentsandverify+*thattheyallareinfactintegers.+*/+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++){+inttype=element[i].type;++if(type==ACPI_TYPE_INTEGER)+nargs++;+elseif(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;++return0;+}++element+=nargs;+}++return-EPROTO;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
From: Lee Jones <hidden> Date: 2014-09-16 21:54:51
On Tue, 16 Sep 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
does not 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 <redacted>
---
Lee, I tried to get rid of #ifdefs in the below patch but it wasn't
possible because we are using functions that are not available when
!CONFIG_ACPI.
Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
drivers/mfd/mfd-core.c | 40 ++++++++++++++++++++++++++++++++++++++
include/linux/mfd/core.h | 3 +++
3 files changed, 70 insertions(+)
Acked-by: Lee Jones <redacted>
--
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
On Tue, Sep 16, 2014 at 02:52:33PM +0300, Mika Westerberg wrote:
From: "Rafael J. Wysocki" <redacted>
Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type. The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.
Three general helper functions, device_get_property(),
device_read_property() and device_read_property_array() are provided.
The first one allows the raw value of a given device property to be
accessed 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. Static inline wrappers are also
provided for the various property data types that can be passed to
device_read_property() or device_read_property_array() for extra type
checking.
In addition to that new generic routines are provided for retrieving
properties from device description objects in the platform firmware
in case there are no struct device objects for them (either those
objects have not been created yet or they do not exist at all).
Again, three functions are provided, dev_node_get_property(),
dev_node_read_property(), dev_node_read_property_array(), in analogy
with device_get_property(), device_read_property() and
device_read_property_array() described above, respectively, along
with static inline wrappers for all of the propery data types that
can be used. For all of them, the first argument is a pointer to
struct fw_dev_node (new type) that in turn contains exactly one
valid pointer to a device description object (depending on what
platform firmware interface is in use).
Finally, device_for_each_child_node() is added for iterating over
the children of the device description object associated with the
given device.
The interface covers both ACPI and Device Trees.
This change set includes material from Mika Westerberg and Aaron Lu.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
Looks good to me, feel free to take this through your tree with my:
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
On Tue, Sep 16, 2014 at 8:52 PM, Mika Westerberg
[off-list ref] wrote:
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Obviously a good thing to do.
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
On Tue, Sep 16, 2014 at 8:52 PM, Mika Westerberg
[off-list ref] wrote:
From: Aaron Lu <redacted>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
From: Rafael J. Wysocki <hidden> Date: 2014-09-21 00:06:23
On Tuesday, September 16, 2014 02:52:31 PM Mika Westerberg wrote:
This is a second revision of the patches first submitted here [1].
The recent publication of the ACPI 5.1 specification [2] 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 [3].
An ACPI Device Properties UUID has been defined [4] 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 3 example drivers that were previously Device Tree aware that
can now be used with either Device Tree or ACPI Device Properties. The
drivers use "PRP0001" as their _HID which means that the match should be
done using driver's .of_match_table instead.
The patch series has been tested on Minnoboard and Minnowboard MAX and the
relevant part of DSDTs are at the end of this cover letter.
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.
Most important changes to the previous RFC version:
* Added wrapper functions for most used property types
* Return -EOVERFLOW in case integer would not fit to a type
* Dropped dev_prop_ops
* We now have dev_node_xxx() functions to access firmware node
properties without dev pointer
* The accessor function names try to be close to their corresponding of_*
counterpart
* Tried to have a bit better examples in the documentation patch
* gpiolib got support for _DSD and also it now understand firmware node
properties with dev_node_get_named_gpiod() that requests the GPIO
properly.
* Support for "PRP0001" _HID/_CID. This means that the match should be
done using driver .of_match_table instead.
* Add unified property support for at25 SPI eeprom driver as well.
[1] https://lkml.org/lkml/2014/8/17/10
[2] http://www.uefi.org/sites/default/files/resources/ACPI_5_1release.pdf
[3] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[4] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Aaron Lu (2):
input: gpio_keys_polled - Add support for GPIO descriptors
input: gpio_keys_polled - Make use of device property API
Max Eliaser (2):
leds: leds-gpio: Make use of device property API
leds: leds-gpio: Add ACPI probing support
Mika Westerberg (11):
ACPI: Add support for device specific properties
ACPI: Allow drivers to match using Device Tree compatible property
ACPI: Document ACPI device specific properties
mfd: Add ACPI support
gpio / ACPI: Add support for _DSD device properties
gpio: Add support for unified device properties interface
gpio: sch: Consolidate core and resume banks
leds: leds-gpio: Add support for GPIO descriptors
input: gpio_keys_polled - Add ACPI probing support
misc: at25: Make use of device property API
misc: at25: Add ACPI probing support
Given the ACKs that we've got already (the Greg's one in particular) and
the apparent lack of objections (or indeed any comments at all), I'm about
to queue this up for 3.18 next week.
Rafael
On Tue, Sep 16, 2014 at 4:52 AM, Mika Westerberg
[off-list ref] wrote:
This is a second revision of the patches first submitted here [1].
The recent publication of the ACPI 5.1 specification [2] 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 [3].
An ACPI Device Properties UUID has been defined [4] 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 3 example drivers that were previously Device Tree aware that
can now be used with either Device Tree or ACPI Device Properties. The
drivers use "PRP0001" as their _HID which means that the match should be
done using driver's .of_match_table instead.
The patch series has been tested on Minnoboard and Minnowboard MAX and the
relevant part of DSDTs are at the end of this cover letter.
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.
Most important changes to the previous RFC version:
* Added wrapper functions for most used property types
* Return -EOVERFLOW in case integer would not fit to a type
* Dropped dev_prop_ops
* We now have dev_node_xxx() functions to access firmware node
properties without dev pointer
* The accessor function names try to be close to their corresponding of_*
counterpart
* Tried to have a bit better examples in the documentation patch
* gpiolib got support for _DSD and also it now understand firmware node
properties with dev_node_get_named_gpiod() that requests the GPIO
properly.
* Support for "PRP0001" _HID/_CID. This means that the match should be
done using driver .of_match_table instead.
* Add unified property support for at25 SPI eeprom driver as well.
[1] https://lkml.org/lkml/2014/8/17/10
[2] http://www.uefi.org/sites/default/files/resources/ACPI_5_1release.pdf
[3] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[4] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Aaron Lu (2):
input: gpio_keys_polled - Add support for GPIO descriptors
input: gpio_keys_polled - Make use of device property API
Max Eliaser (2):
leds: leds-gpio: Make use of device property API
leds: leds-gpio: Add ACPI probing support
Mika Westerberg (11):
ACPI: Add support for device specific properties
ACPI: Allow drivers to match using Device Tree compatible property
ACPI: Document ACPI device specific properties
mfd: Add ACPI support
gpio / ACPI: Add support for _DSD device properties
gpio: Add support for unified device properties interface
gpio: sch: Consolidate core and resume banks
leds: leds-gpio: Add support for GPIO descriptors
input: gpio_keys_polled - Add ACPI probing support
misc: at25: Make use of device property API
misc: at25: Add ACPI probing support
Rafael J. Wysocki (1):
Driver core: Unified device properties interface for platform firmware
I'm good with the LEDs change, please go ahead with my Ack
Acked-by: Bryan Wu <redacted>
Thanks,
-Bryan
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
Yours,
Linus Walleij
--
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
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
other things as well) returned by _CRS. Previously we were only able to
use integer index to find the corresponding GPIO, which is pretty error
prone if the order changes.
With _DSD we can now query GPIOs using name instead of an integer index,
like the below example shows:
// Bluetooth device with reset and shutdown GPIOs
Device (BTH)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate ()
{
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {15}
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
})
Name (_DSD, Package ()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
}
})
}
The format of the supported GPIO property is:
Package () { "name", Package () { ref, index, pin, active_low }}
ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
typically this is the device itself (BTH in our case).
index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
active_low - If 1 the GPIO is marked as active_low.
Since ACPI GpioIo() resource does not have field saying whether it is
active low or high, the "active_low" argument can be used here. Setting
it to 1 marks the GPIO as active low.
In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.
This patch implements necessary support to gpiolib for extracting GPIOs
using _DSD device properties.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <redacted>
If Rafael is happy with this approach, and you decide to take it
through the ACPI tree.
Yours,
Linus Walleij
On Tuesday 23 September 2014 17:25:50 Linus Walleij wrote:
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
I just took a brief look at this. My first impression is that the
fw_dev_node structure is weird when all callers just do (in patch 2)
+ struct fw_dev_node fdn = {
+ .of_node = dev->of_node,
+ .acpi_node = ACPI_COMPANION(dev),
+ };
I'd much rather see an interface that passes the 'struct device'
pointer down to dev_get_named_gpiod() and all other exported
functions, and then internally does the conversion at the point
where the access is done.
Arnd
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-23 15:52:47
On Tue, Sep 23, 2014 at 05:45:57PM +0200, Arnd Bergmann wrote:
On Tuesday 23 September 2014 17:25:50 Linus Walleij wrote:
quoted
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
I just took a brief look at this. My first impression is that the
fw_dev_node structure is weird when all callers just do (in patch 2)
+ struct fw_dev_node fdn = {
+ .of_node = dev->of_node,
+ .acpi_node = ACPI_COMPANION(dev),
+ };
I'd much rather see an interface that passes the 'struct device'
pointer down to dev_get_named_gpiod() and all other exported
functions, and then internally does the conversion at the point
where the access is done.
Problem is that if you don't have the dev pointer in the first place.
Please look how leds-gpio.c or gpio_keys_polled.c are using this.
Of course you have the first level device but when you need to iterate
"leds" or "buttons" below where there is no Linux device available we
need something like this.
--
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
From: Rafael J. Wysocki <hidden> Date: 2014-09-23 16:05:17
On Tuesday, September 23, 2014 05:45:57 PM Arnd Bergmann wrote:
On Tuesday 23 September 2014 17:25:50 Linus Walleij wrote:
quoted
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
I just took a brief look at this. My first impression is that the
fw_dev_node structure is weird when all callers just do (in patch 2)
+ struct fw_dev_node fdn = {
+ .of_node = dev->of_node,
+ .acpi_node = ACPI_COMPANION(dev),
+ };
I'd much rather see an interface that passes the 'struct device'
pointer down to dev_get_named_gpiod() and all other exported
functions, and then internally does the conversion at the point
where the access is done.
The problem is iteration over child nodes of a given one where there
may not be struct device objects.
For example (from patch [2/16]):
+int acpi_for_each_child_node(struct acpi_device *adev,
+ int (*fn)(struct fw_dev_node *fdn, void *data),
+ void *data)
+{
+ struct acpi_device *child;
+ int ret = 0;
+
+ list_for_each_entry(child, &adev->children, node) {
+ struct fw_dev_node fdn = { .acpi_node = child, };
+
+ ret = fn(&fdn, data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
and then fn() can be made work for both DTs and ACPI. Without this we'd
need to have two versions of fn(), one for DTs and one for ACPI (and possibly
more for some other FW protocols), which isn't necessary in general (and
duplicates code etc.).
That actually is used by some patches down in the series (eg. [10/16]).
Rafael
--
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
On Tue, Sep 23, 2014 at 06:52:02PM +0300, Mika Westerberg wrote:
On Tue, Sep 23, 2014 at 05:45:57PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday 23 September 2014 17:25:50 Linus Walleij wrote:
quoted
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
I just took a brief look at this. My first impression is that the
fw_dev_node structure is weird when all callers just do (in patch 2)
+ struct fw_dev_node fdn = {
+ .of_node = dev->of_node,
+ .acpi_node = ACPI_COMPANION(dev),
+ };
I'd much rather see an interface that passes the 'struct device'
pointer down to dev_get_named_gpiod() and all other exported
functions, and then internally does the conversion at the point
where the access is done.
Problem is that if you don't have the dev pointer in the first place.
Please look how leds-gpio.c or gpio_keys_polled.c are using this.
Of course you have the first level device but when you need to iterate
"leds" or "buttons" below where there is no Linux device available we
need something like this.
Maybe we should be passing the parent/owner device to the iterator
functions?
Thanks.
--
Dmitry
On Tuesday 23 September 2014 18:25:01 Rafael J. Wysocki wrote:
The problem is iteration over child nodes of a given one where there
may not be struct device objects.
For example (from patch [2/16]):
+int acpi_for_each_child_node(struct acpi_device *adev,
+ int (*fn)(struct fw_dev_node *fdn, void *data),
+ void *data)
+{
+ struct acpi_device *child;
+ int ret = 0;
+
+ list_for_each_entry(child, &adev->children, node) {
+ struct fw_dev_node fdn = { .acpi_node = child, };
+
+ ret = fn(&fdn, data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
and then fn() can be made work for both DTs and ACPI. Without this we'd
need to have two versions of fn(), one for DTs and one for ACPI (and possibly
more for some other FW protocols), which isn't necessary in general (and
duplicates code etc.).
That actually is used by some patches down in the series (eg. [10/16]).
Ok, I understand what you are doing now.
Looking at the example you point to (http://www.spinics.net/lists/devicetree/msg49502.html), I still feel
that this is adding more abstraction than what is good for us, and
I'd be happier with an implementation of gpio_leds_create() that
has a bit more duplication and less abstraction.
The important part should be that the driver-side interface is
sensible, other than that an implementation like
static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
return gpio_leds_create_of(pdev);
else if (IS_ENABLED(CONFIG_ACPI))
return gpio_leds_create_of(acpi);
return ERR_PTR(-ENXIO);
}
would keep either side of it relatively simple, by leaving out the
indirect function calls and new for_each_available_child_of_node()
macro.
How many other users of fw_dev_node do you have at the moment?
Arnd
--
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
From: Rafael J. Wysocki <hidden> Date: 2014-09-23 20:11:42
On Tuesday, September 23, 2014 09:17:24 AM Dmitry Torokhov wrote:
On Tue, Sep 23, 2014 at 06:52:02PM +0300, Mika Westerberg wrote:
quoted
On Tue, Sep 23, 2014 at 05:45:57PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday 23 September 2014 17:25:50 Linus Walleij wrote:
quoted
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_node_get_named_gpiod() that takes a firmware node pointer as
parameter, finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
I have a hard time figuring out if this is what we want for common
accessors between DT and ACPI.
Can I get some input from Grant, Arnd, Mark, Darren...?
I just took a brief look at this. My first impression is that the
fw_dev_node structure is weird when all callers just do (in patch 2)
+ struct fw_dev_node fdn = {
+ .of_node = dev->of_node,
+ .acpi_node = ACPI_COMPANION(dev),
+ };
I'd much rather see an interface that passes the 'struct device'
pointer down to dev_get_named_gpiod() and all other exported
functions, and then internally does the conversion at the point
where the access is done.
Problem is that if you don't have the dev pointer in the first place.
Please look how leds-gpio.c or gpio_keys_polled.c are using this.
Of course you have the first level device but when you need to iterate
"leds" or "buttons" below where there is no Linux device available we
need something like this.
Maybe we should be passing the parent/owner device to the iterator
functions?
Yes, we can do that. That's one alternative for what we have in the current
set.
Rafael
--
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
From: Rafael J. Wysocki <hidden> Date: 2014-09-23 20:27:56
On Tuesday, September 23, 2014 06:26:07 PM Arnd Bergmann wrote:
On Tuesday 23 September 2014 18:25:01 Rafael J. Wysocki wrote:
quoted
The problem is iteration over child nodes of a given one where there
may not be struct device objects.
For example (from patch [2/16]):
+int acpi_for_each_child_node(struct acpi_device *adev,
+ int (*fn)(struct fw_dev_node *fdn, void *data),
+ void *data)
+{
+ struct acpi_device *child;
+ int ret = 0;
+
+ list_for_each_entry(child, &adev->children, node) {
+ struct fw_dev_node fdn = { .acpi_node = child, };
+
+ ret = fn(&fdn, data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
and then fn() can be made work for both DTs and ACPI. Without this we'd
need to have two versions of fn(), one for DTs and one for ACPI (and possibly
more for some other FW protocols), which isn't necessary in general (and
duplicates code etc.).
That actually is used by some patches down in the series (eg. [10/16]).
Ok, I understand what you are doing now.
Looking at the example you point to (http://www.spinics.net/lists/devicetree/msg49502.html), I still feel
that this is adding more abstraction than what is good for us, and
I'd be happier with an implementation of gpio_leds_create() that
has a bit more duplication and less abstraction.
The important part should be that the driver-side interface is
sensible, other than that an implementation like
static struct gpio_leds_priv *gpio_leds_create(struct platform_device *pdev)
{
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
return gpio_leds_create_of(pdev);
else if (IS_ENABLED(CONFIG_ACPI))
return gpio_leds_create_of(acpi);
return ERR_PTR(-ENXIO);
}
would keep either side of it relatively simple, by leaving out the
indirect function calls and new for_each_available_child_of_node()
macro.
Quite frankly, I'm not sure what you're asking for.
It seems to mean "I kind of don't like the current implementation", but
then the last part is quite unclear to me. Are you suggesting to add more
"if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) etc" type of checks to
device drivers? That I'd like to avoid to be honest.
Instead of the current proposal we can introduce something like
int device_get_child_property(struct device *dev, void *child_node,
const char *propname, void **valptr);
(and analogously for device_read_property*) and use that in the drivers that
need to iterate over child nodes of a device. Quite along the lines of what
Dmitry is suggesting.
Then, fn() in acpi_for_each_child_node() (and the of_ counterpart of it)
would become
int (*fn)(struct device *dev, void *child_node, void *data)
and so on.
Would you prefer that?
How many other users of fw_dev_node do you have at the moment?
From: Darren Hart <dvhart@infradead.org> Date: 2014-09-23 21:16:04
On 9/23/14, 9:26, "Arnd Bergmann" [off-list ref] wrote:
On Tuesday 23 September 2014 18:25:01 Rafael J. Wysocki wrote:
quoted
The problem is iteration over child nodes of a given one where there
may not be struct device objects.
For example (from patch [2/16]):
+int acpi_for_each_child_node(struct acpi_device *adev,
+ int (*fn)(struct fw_dev_node *fdn, void
*data),
+ void *data)
+{
+ struct acpi_device *child;
+ int ret = 0;
+
+ list_for_each_entry(child, &adev->children, node) {
+ struct fw_dev_node fdn = { .acpi_node = child, };
+
+ ret = fn(&fdn, data);
+ if (ret)
+ break;
+ }
+ return ret;
+}
and then fn() can be made work for both DTs and ACPI. Without this we'd
need to have two versions of fn(), one for DTs and one for ACPI (and
possibly
more for some other FW protocols), which isn't necessary in general (and
duplicates code etc.).
That actually is used by some patches down in the series (eg. [10/16]).
Ok, I understand what you are doing now.
Looking at the example you point to
(http://www.spinics.net/lists/devicetree/msg49502.html), I still feel
that this is adding more abstraction than what is good for us, and
I'd be happier with an implementation of gpio_leds_create() that
has a bit more duplication and less abstraction.
The important part should be that the driver-side interface is
sensible, other than that an implementation like
static struct gpio_leds_priv *gpio_leds_create(struct platform_device
*pdev)
{
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node)
return gpio_leds_create_of(pdev);
else if (IS_ENABLED(CONFIG_ACPI))
return gpio_leds_create_of(acpi);
Arnd, I think you meant:
Return gpio_leds_create_acpi(pdev) ?
This is what we did early on to prototype this concept, but the problem
with this approach we duplicate all of the creation code, which leads to
maintenance errors, and is inconsistent with the goals of the _DSD which
is to reuse the same schemas for ACPI and FDT. If we have separate pdata
creation functions anyway, we are leaving much of the advantage of the
common schema on the table. Namely the ability to reuse drivers relatively
easily across firmware implementations. We don't want driver authors to
have to care if it's ACPI or FDT.
We would have preferred to have deprecated the of property interface in
favor of the new generic device_property interface, but Grant specifically
requested that we update drivers individually rather than all at once,
which means we can't just kill the OF interface.
We agreed to that, somewhat reluctantly as it adds more work in updating
the drivers over time which will slow adoption, but I understand the
desire not to make large sweeping changes due to the risk of breaking
things inadvertently as we cannot expect to be able to test all of them.
That said, I don't want to forget that the goal is to use the common
interface over time as we convert individual drivers, and using the common
interface means we need a common iterator function and that we not have fw
implementation specific pdata create functions.
--
Darren Hart
Intel Open Source Technology Center
On Tuesday 23 September 2014 22:47:36 Rafael J. Wysocki wrote:
Quite frankly, I'm not sure what you're asking for.
It seems to mean "I kind of don't like the current implementation", but
then the last part is quite unclear to me. Are you suggesting to add more
"if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) etc" type of checks to
device drivers? That I'd like to avoid to be honest.
No, that is not what I want. Device drivers should ideally call interfaces
that just take a 'struct device' or 'struct platform_device' pointer,
and those should be implemented in an appropriate way.
Instead of the current proposal we can introduce something like
int device_get_child_property(struct device *dev, void *child_node,
const char *propname, void **valptr);
(and analogously for device_read_property*) and use that in the drivers that
need to iterate over child nodes of a device. Quite along the lines of what
Dmitry is suggesting.
Then, fn() in acpi_for_each_child_node() (and the of_ counterpart of it)
would become
int (*fn)(struct device *dev, void *child_node, void *data)
and so on.
Would you prefer that?
I must still be missing part of what you are trying to achieve above.
We definitely need an interface to get properties from the device itself,
like
int device_get_property(struct device *dev, const char *propname, void **valptr);
(whatever valptr ends up being, that would be a separate discussion).
As soon as it comes to devices that have child nodes, I don't see a
necessity to have a generic abstraction for them, as this is typically
only done for some of the more obscure bindings, or for child nodes that
are defined in a subsystem-wide binding rather than a device private
binding.
For the former case, I think they are indeed better left in drivers that
actively know the difference between DT and ACPI, and that don't necessarily
use the same binding for both. In the latter case, I'd leave the
implementation up to subsystem code, which again would know what
interface it is using.
Arnd
--
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
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
While this is a nice first step, it must be possible to patch all in-kernel
users of this callback to take a gpiod too...
It's actually just:
$ git grep gpio_blink_set
arch/arm/mach-orion5x/dns323-setup.c: .gpio_blink_set =
orion_gpio_led_blink_set,
arch/arm/mach-orion5x/dns323-setup.c: .gpio_blink_set =
orion_gpio_led_blink_set,
arch/arm/mach-s3c24xx/mach-h1940.c: .gpio_blink_set = h1940_led_blink_set,
arch/arm/mach-s3c24xx/mach-rx1950.c: .gpio_blink_set = rx1950_led_blink_set,
However we can do that as a follow-up patch. (Add to TODO...)
Yours,
Linus Walleij
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
From: Aaron Lu <redacted>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Again <linux/gpio.h> should not be needed anymore.
+ /*
+ * Legacy GPIO number so request the GPIO here and
+ * convert it to descriptor.
+ */
+ if (!button->gpiod && gpio_is_valid(button->gpio)) {
+ unsigned flags = 0;
+
+ if (button->active_low)
+ flags |= GPIOF_ACTIVE_LOW;
+
+ error = devm_gpio_request_one(&pdev->dev, button->gpio,
+ flags, button->desc ? : DRV_NAME);
+ if (error) {
+ dev_err(dev, "unable to claim gpio %u, err=%d\n",
+ button->gpio, error);
+ return error;
+ }
+
+ button->gpiod = gpio_to_desc(button->gpio);
So the field button->gpio is still there, this is a bit disturbing, but when
I grep for it I see there is a multitude of users :-/
OK I guess these users have to be fixed one by one.
Reviewed-by: Linus Walleij <redacted>
Yours,
Linus Walleij
From: Lee Jones <hidden> Date: 2014-09-24 08:34:30
On Sun, 21 Sep 2014, Rafael J. Wysocki wrote:
On Tuesday, September 16, 2014 02:52:31 PM Mika Westerberg wrote:
quoted
This is a second revision of the patches first submitted here [1].
The recent publication of the ACPI 5.1 specification [2] 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 [3].
An ACPI Device Properties UUID has been defined [4] 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 3 example drivers that were previously Device Tree aware that
can now be used with either Device Tree or ACPI Device Properties. The
drivers use "PRP0001" as their _HID which means that the match should be
done using driver's .of_match_table instead.
The patch series has been tested on Minnoboard and Minnowboard MAX and the
relevant part of DSDTs are at the end of this cover letter.
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.
Most important changes to the previous RFC version:
* Added wrapper functions for most used property types
* Return -EOVERFLOW in case integer would not fit to a type
* Dropped dev_prop_ops
* We now have dev_node_xxx() functions to access firmware node
properties without dev pointer
* The accessor function names try to be close to their corresponding of_*
counterpart
* Tried to have a bit better examples in the documentation patch
* gpiolib got support for _DSD and also it now understand firmware node
properties with dev_node_get_named_gpiod() that requests the GPIO
properly.
* Support for "PRP0001" _HID/_CID. This means that the match should be
done using driver .of_match_table instead.
* Add unified property support for at25 SPI eeprom driver as well.
[1] https://lkml.org/lkml/2014/8/17/10
[2] http://www.uefi.org/sites/default/files/resources/ACPI_5_1release.pdf
[3] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[4] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Aaron Lu (2):
input: gpio_keys_polled - Add support for GPIO descriptors
input: gpio_keys_polled - Make use of device property API
Max Eliaser (2):
leds: leds-gpio: Make use of device property API
leds: leds-gpio: Add ACPI probing support
Mika Westerberg (11):
ACPI: Add support for device specific properties
ACPI: Allow drivers to match using Device Tree compatible property
ACPI: Document ACPI device specific properties
mfd: Add ACPI support
gpio / ACPI: Add support for _DSD device properties
gpio: Add support for unified device properties interface
gpio: sch: Consolidate core and resume banks
leds: leds-gpio: Add support for GPIO descriptors
input: gpio_keys_polled - Add ACPI probing support
misc: at25: Make use of device property API
misc: at25: Add ACPI probing support
Given the ACKs that we've got already (the Greg's one in particular) and
the apparent lack of objections (or indeed any comments at all), I'm about
to queue this up for 3.18 next week.
I'd prefer to take the MFD patch through the MFD tree if that's
possible. Are there any technical reasons why this would prove
difficult?
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org │ Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
On Tuesday 23 September 2014 14:15:47 Darren Hart wrote:
Arnd, I think you meant:
Return gpio_leds_create_acpi(pdev) ?
Yes, sorry for the confusion on my part.
This is what we did early on to prototype this concept, but the problem
with this approach we duplicate all of the creation code, which leads to
maintenance errors, and is inconsistent with the goals of the _DSD which
is to reuse the same schemas for ACPI and FDT. If we have separate pdata
creation functions anyway, we are leaving much of the advantage of the
common schema on the table. Namely the ability to reuse drivers relatively
easily across firmware implementations. We don't want driver authors to
have to care if it's ACPI or FDT.
I think we are absolutely in agreement about the basic principle here,
but disagree on how far we'd want to take the abstraction.
I got a little confused by the leds-gpio example, as I initially saw
that as generic infrastructure rather than a specific driver. As I just
wrote in my reply to Rafael, I generally believe we should strive to
have generic driver-side interfaces so drivers don't have to care,
but keep the differences in subsystem specific code.
We would have preferred to have deprecated the of property interface in
favor of the new generic device_property interface, but Grant specifically
requested that we update drivers individually rather than all at once,
which means we can't just kill the OF interface.
I don't actually have a strong opinion on that matter, having only the
device property interface does have some advantages as well, but I also
agree that we are somewhat better off not having to change all the drivers.
We agreed to that, somewhat reluctantly as it adds more work in updating
the drivers over time which will slow adoption, but I understand the
desire not to make large sweeping changes due to the risk of breaking
things inadvertently as we cannot expect to be able to test all of them.
That said, I don't want to forget that the goal is to use the common
interface over time as we convert individual drivers, and using the common
interface means we need a common iterator function and that we not have fw
implementation specific pdata create functions.
I've looked a bit closer at how the LED subsystem handles sub-nodes
in DT at the moment. It seems that there is some duplication between
the drivers already, as they all implement a variation of the sub-node
parsing code.
There are other non-LED drivers with similar loops, but they seem to be
either very specialized, or explicitly for DT abstractions, so I'm still
not convinced we need a generic loop-through-child-nodes-and-parse-properties
interface.
How would you feel about a more general way of probing LED, using
a new helper in the leds-core that iterates over the child nodes
and parses the standard properties but calls into a driver specific
callback to parse the specific properties?
It's probably much more work than your current approach, but it seems
to me that there is more to gain by solving the problem for LED
drivers in particular to cut down the per-driver duplication
at the same time as the per-firmware-interface duplication.
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
but there seems little benefit in abstracting this because there is
only one driver that needs it.
Arnd
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-24 09:38:43
On Wed, Sep 24, 2014 at 11:12:36AM +0200, Arnd Bergmann wrote:
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
but there seems little benefit in abstracting this because there is
only one driver that needs it.
The same interface is used also in gpio_keys_polled.c driver so if we
want to avoid duplicating code this needs to be abstracted away from the
drivers.
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2014-09-24 09:42:18
On Wed, Sep 24, 2014 at 09:55:48AM +0200, Linus Walleij wrote:
On Tue, Sep 16, 2014 at 1:52 PM, Mika Westerberg
[off-list ref] wrote:
quoted
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
While this is a nice first step, it must be possible to patch all in-kernel
users of this callback to take a gpiod too...
It's actually just:
$ git grep gpio_blink_set
arch/arm/mach-orion5x/dns323-setup.c: .gpio_blink_set =
orion_gpio_led_blink_set,
arch/arm/mach-orion5x/dns323-setup.c: .gpio_blink_set =
orion_gpio_led_blink_set,
arch/arm/mach-s3c24xx/mach-h1940.c: .gpio_blink_set = h1940_led_blink_set,
arch/arm/mach-s3c24xx/mach-rx1950.c: .gpio_blink_set = rx1950_led_blink_set,
However we can do that as a follow-up patch. (Add to TODO...)
From: Lee Jones <hidden> Date: 2014-09-24 12:01:06
On Tue, 16 Sep 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
does not 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 <redacted>
---
Lee, I tried to get rid of #ifdefs in the below patch but it wasn't
possible because we are using functions that are not available when
!CONFIG_ACPI.
Documentation/acpi/enumeration.txt | 27 +++++++++++++++++++++++++
drivers/mfd/mfd-core.c | 40 ++++++++++++++++++++++++++++++++++++++
include/linux/mfd/core.h | 3 +++
3 files changed, 70 insertions(+)
Applied, thanks.
--
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
From: Rafael J. Wysocki <hidden> Date: 2014-09-24 13:48:32
On Wednesday, September 24, 2014 09:55:12 AM Arnd Bergmann wrote:
On Tuesday 23 September 2014 22:47:36 Rafael J. Wysocki wrote:
quoted
Quite frankly, I'm not sure what you're asking for.
It seems to mean "I kind of don't like the current implementation", but
then the last part is quite unclear to me. Are you suggesting to add more
"if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) etc" type of checks to
device drivers? That I'd like to avoid to be honest.
No, that is not what I want. Device drivers should ideally call interfaces
that just take a 'struct device' or 'struct platform_device' pointer,
and those should be implemented in an appropriate way.
But then you have drivers that access properties of their child nodes which
have no corresponding struct device(s).
quoted
Instead of the current proposal we can introduce something like
int device_get_child_property(struct device *dev, void *child_node,
const char *propname, void **valptr);
(and analogously for device_read_property*) and use that in the drivers that
need to iterate over child nodes of a device. Quite along the lines of what
Dmitry is suggesting.
Then, fn() in acpi_for_each_child_node() (and the of_ counterpart of it)
would become
int (*fn)(struct device *dev, void *child_node, void *data)
and so on.
Would you prefer that?
I must still be missing part of what you are trying to achieve above.
We definitely need an interface to get properties from the device itself,
like
int device_get_property(struct device *dev, const char *propname, void **valptr);
(whatever valptr ends up being, that would be a separate discussion).
As soon as it comes to devices that have child nodes, I don't see a
necessity to have a generic abstraction for them, as this is typically
only done for some of the more obscure bindings, or for child nodes that
are defined in a subsystem-wide binding rather than a device private
binding.
Well, I don't really agree here.
We can demonstrably reduce code duplication (and therefore complexity too) in
at least two drivers by doing that at a reasonably low cost, which is
simply exposing the API for child nodes and adding helpers for iterating
over them.
We don't have to use struct fw_dev_node (or similar) for that if that's what
bothers you, but in my opinion something like "get me a property of this thing
which may be either a device tree node or an ACPI object" (ie. what the current
dev_node_get_property() does) is more straightforwad than "get me a property
of that child of this device which may be either a device tree node or an ACPI
object" (ie. what device_get_child_property() as described above would do).
For the former case, I think they are indeed better left in drivers that
actively know the difference between DT and ACPI, and that don't necessarily
use the same binding for both. In the latter case, I'd leave the
implementation up to subsystem code, which again would know what
interface it is using.
The case in question is drivers that need not know the difference between DT and
ACPI and do use the same binding for both. It seems quite clear what needs to
be done in the other cases.
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
From: Rafael J. Wysocki <hidden> Date: 2014-09-24 13:51:47
On Wednesday, September 24, 2014 12:38:23 PM Mika Westerberg wrote:
On Wed, Sep 24, 2014 at 11:12:36AM +0200, Arnd Bergmann wrote:
quoted
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
but there seems little benefit in abstracting this because there is
only one driver that needs it.
The same interface is used also in gpio_keys_polled.c driver so if we
want to avoid duplicating code this needs to be abstracted away from the
drivers.
Well, precisely.
Moving it to the leds-core doesn't buy us anything.
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
From: Darren Hart <dvhart@infradead.org> Date: 2014-09-26 03:21:37
On Wed, Sep 24, 2014 at 11:12:36AM +0200, Arnd Bergmann wrote:
On Tuesday 23 September 2014 14:15:47 Darren Hart wrote:
quoted
Arnd, I think you meant:
Return gpio_leds_create_acpi(pdev) ?
Yes, sorry for the confusion on my part.
Hi Arnd,
No problem, just wanted to make sure I knew what you meant.
quoted
This is what we did early on to prototype this concept, but the problem
with this approach we duplicate all of the creation code, which leads to
maintenance errors, and is inconsistent with the goals of the _DSD which
is to reuse the same schemas for ACPI and FDT. If we have separate pdata
creation functions anyway, we are leaving much of the advantage of the
common schema on the table. Namely the ability to reuse drivers relatively
easily across firmware implementations. We don't want driver authors to
have to care if it's ACPI or FDT.
I think we are absolutely in agreement about the basic principle here,
but disagree on how far we'd want to take the abstraction.
I got a little confused by the leds-gpio example, as I initially saw
that as generic infrastructure rather than a specific driver. As I just
wrote in my reply to Rafael, I generally believe we should strive to
have generic driver-side interfaces so drivers don't have to care,
but keep the differences in subsystem specific code.
quoted
We would have preferred to have deprecated the of property interface in
favor of the new generic device_property interface, but Grant specifically
requested that we update drivers individually rather than all at once,
which means we can't just kill the OF interface.
I don't actually have a strong opinion on that matter, having only the
device property interface does have some advantages as well, but I also
agree that we are somewhat better off not having to change all the drivers.
quoted
We agreed to that, somewhat reluctantly as it adds more work in updating
the drivers over time which will slow adoption, but I understand the
desire not to make large sweeping changes due to the risk of breaking
things inadvertently as we cannot expect to be able to test all of them.
That said, I don't want to forget that the goal is to use the common
interface over time as we convert individual drivers, and using the common
interface means we need a common iterator function and that we not have fw
implementation specific pdata create functions.
I've looked a bit closer at how the LED subsystem handles sub-nodes
in DT at the moment. It seems that there is some duplication between
the drivers already, as they all implement a variation of the sub-node
parsing code.
There are other non-LED drivers with similar loops, but they seem to be
either very specialized, or explicitly for DT abstractions, so I'm still
not convinced we need a generic loop-through-child-nodes-and-parse-properties
interface.
How would you feel about a more general way of probing LED, using
a new helper in the leds-core that iterates over the child nodes
and parses the standard properties but calls into a driver specific
callback to parse the specific properties?
It's probably much more work than your current approach, but it seems
to me that there is more to gain by solving the problem for LED
drivers in particular to cut down the per-driver duplication
at the same time as the per-firmware-interface duplication.
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
So as Mika has pointed out, LEDs aren't the only ones affected. Several drivers
will need to walk through non-device child nodes, and it seems to me that having
a firmware-independent mechanism to do so benefits the drivers by both making
them smaller and by increasing the reusability of new drivers and drivers
updated to use the new API across platforms.
I fear we might be entering bike shed territory as we seem to be repeating
points now. Can you restate your concern with the interface and why this level
of abstraction is worse for the kernel? I'm not seeing this point, so I'm not
sure what to address in my response.
Grant, Linus W? Thoughts?
but there seems little benefit in abstracting this because there is
only one driver that needs it.
Arnd
--
Darren Hart
Intel Open Source Technology Center
On Thursday 25 September 2014 20:21:32 Darren Hart wrote:
On Wed, Sep 24, 2014 at 11:12:36AM +0200, Arnd Bergmann wrote:
quoted
How would you feel about a more general way of probing LED, using
a new helper in the leds-core that iterates over the child nodes
and parses the standard properties but calls into a driver specific
callback to parse the specific properties?
It's probably much more work than your current approach, but it seems
to me that there is more to gain by solving the problem for LED
drivers in particular to cut down the per-driver duplication
at the same time as the per-firmware-interface duplication.
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
So as Mika has pointed out, LEDs aren't the only ones affected. Several drivers
will need to walk through non-device child nodes, and it seems to me that having
a firmware-independent mechanism to do so benefits the drivers by both making
them smaller and by increasing the reusability of new drivers and drivers
updated to use the new API across platforms.
I fear we might be entering bike shed territory as we seem to be repeating
points now. Can you restate your concern with the interface and why this level
of abstraction is worse for the kernel? I'm not seeing this point, so I'm not
sure what to address in my response.
I think we should have abstractions for all common interfaces but make
them as simple as possible. In the discussions at the kernel summit,
everyone agreed that we should have common accessors for simple properties
(bool, int, string, ...) based on device pointers, as well as subsystem
specific accessors to handle the high-level abstractions (registers,
interrupts, gpio, regulator, pinctrl, dma, reset, pwm, ...).
Having generalized accessors for the same properties in child nodes of
the device goes beyond that, and I think this is the wrong trade-off
between interface simplicity and generality since only few drivers will
be able to use those. I think we will always have to live with a leaky
abstraction because some drivers need to do things beyond what we can
do with a common API.
Grant, Linus W? Thoughts?
I definitely want to hear other voices on this too. This is really not
a fundamental debate I think, but more a question of how far the abstraction
should go.
Arnd
From: Rafael J. Wysocki <hidden> Date: 2014-09-26 14:22:40
On Friday, September 26, 2014 10:36:06 AM Arnd Bergmann wrote:
On Thursday 25 September 2014 20:21:32 Darren Hart wrote:
quoted
On Wed, Sep 24, 2014 at 11:12:36AM +0200, Arnd Bergmann wrote:
quoted
How would you feel about a more general way of probing LED, using
a new helper in the leds-core that iterates over the child nodes
and parses the standard properties but calls into a driver specific
callback to parse the specific properties?
It's probably much more work than your current approach, but it seems
to me that there is more to gain by solving the problem for LED
drivers in particular to cut down the per-driver duplication
at the same time as the per-firmware-interface duplication.
As a start, we could probably take the proposed device_for_each_child_node
and move that into the leds-core, changing the fw_dev_node argument
for an led_classdev with the addition of the of_node and acpi_object
members. It would still leave it up to the gpio-leds driver to do
if (led_cdev->of_node)
gpiod = devm_of_get_gpiod(led_cdev->of_node, ...);
else
gpiod = devm_acpi_get_gpiod(led_cdev->acpi_object, ...);
So as Mika has pointed out, LEDs aren't the only ones affected. Several drivers
will need to walk through non-device child nodes, and it seems to me that having
a firmware-independent mechanism to do so benefits the drivers by both making
them smaller and by increasing the reusability of new drivers and drivers
updated to use the new API across platforms.
I fear we might be entering bike shed territory as we seem to be repeating
points now. Can you restate your concern with the interface and why this level
of abstraction is worse for the kernel? I'm not seeing this point, so I'm not
sure what to address in my response.
I think we should have abstractions for all common interfaces but make
them as simple as possible. In the discussions at the kernel summit,
everyone agreed that we should have common accessors for simple properties
(bool, int, string, ...) based on device pointers, as well as subsystem
specific accessors to handle the high-level abstractions (registers,
interrupts, gpio, regulator, pinctrl, dma, reset, pwm, ...).
Having generalized accessors for the same properties in child nodes of
the device goes beyond that, and I think this is the wrong trade-off
between interface simplicity and generality since only few drivers will
be able to use those. I think we will always have to live with a leaky
abstraction because some drivers need to do things beyond what we can
do with a common API.
Some drivers do, but then we can avoid adding DT/ACPI knowledge to some
drivers by adding general accessors for properties in child nodes. In my
opinion, drivers should not do things specific to DT/ACPI unless that is
unavoidable.
quoted
Grant, Linus W? Thoughts?
I definitely want to hear other voices on this too. This is really not
a fundamental debate I think, but more a question of how far the abstraction
should go.
Right.
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
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
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:15
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Make use of device property API in this driver so that both DT and ACPI
based systems can use this driver.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/misc/eeprom/at25.c | 34 +++++++++++++---------------------
1 file changed, 13 insertions(+), 21 deletions(-)
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:18
From: Max Eliaser <redacted>
This allows the driver to probe from ACPI namespace.
Signed-off-by: Max Eliaser <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Bryan Wu <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/leds/leds-gpio.c | 8 ++++++++
1 file changed, 8 insertions(+)
Index: linux-pm/drivers/leds/leds-gpio.c
===================================================================
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:23
From: Mika Westerberg <mika.westerberg@linux.intel.com>
This is actually a single device with two sets of identical registers,
which just happen to start from a different offset. Instead of having
separate GPIO chips created we consolidate them to be single GPIO chip.
In addition having a single GPIO chip allows us to handle ACPI GPIO
translation in the core in a more generic way, since the two GPIO chips
share the same parent ACPI device.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/gpio/gpio-sch.c | 293 ++++++++++++++++++------------------------------
1 file changed, 112 insertions(+), 181 deletions(-)
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:26
From: Mika Westerberg <mika.westerberg@linux.intel.com>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Acked-by: Bryan Wu <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/leds/leds-gpio.c | 80 +++++++++++++++++++++++++++---------------------
include/linux/leds.h | 1 +
2 files changed, 46 insertions(+), 35 deletions(-)
@@ -60,9 +64,6 @@ static void gpio_led_set(struct led_classdev *led_cdev,elselevel=1;-if(led_dat->active_low)-level=!level;-/* Setting GPIOs with I2C/etc requires a task context, and we don't*seemtohaveareliablewaytoknowifwe'realreadyinone;so*let'sjustassumetheworst.
@@ -85,9 +91,10 @@ static int gpio_blink_set(struct led_classdev *led_cdev,{structgpio_led_data*led_dat=container_of(led_cdev,structgpio_led_data,cdev);+intgpio=desc_to_gpio(led_dat->gpiod);led_dat->blinking=1;-returnled_dat->platform_gpio_blink_set(led_dat->gpio,GPIO_LED_BLINK,+returnled_dat->platform_gpio_blink_set(gpio,GPIO_LED_BLINK,delay_on,delay_off);}
@@ -97,24 +104,33 @@ static int create_gpio_led(const struct gpio_led *template,{intret,state;-led_dat->gpio=-1;+if(!template->gpiod){+unsignedlongflags=0;-/* skip leds that aren't available */-if(!gpio_is_valid(template->gpio)){-dev_info(parent,"Skipping unavailable LED gpio %d (%s)\n",-template->gpio,template->name);-return0;-}+/* skip leds that aren't available */+if(!gpio_is_valid(template->gpio)){+dev_info(parent,"Skipping unavailable LED gpio %d (%s)\n",+template->gpio,template->name);+return0;+}-ret=devm_gpio_request(parent,template->gpio,template->name);-if(ret<0)-returnret;+if(template->active_low)+flags|=GPIOF_ACTIVE_LOW;++ret=devm_gpio_request_one(parent,template->gpio,flags,+template->name);+if(ret<0)+returnret;++led_dat->gpiod=gpio_to_desc(template->gpio);+if(IS_ERR(led_dat->gpiod))+returnPTR_ERR(led_dat->gpiod);+}led_dat->cdev.name=template->name;led_dat->cdev.default_trigger=template->default_trigger;-led_dat->gpio=template->gpio;-led_dat->can_sleep=gpio_cansleep(template->gpio);-led_dat->active_low=template->active_low;+led_dat->gpiod=template->gpiod;+led_dat->can_sleep=gpiod_cansleep(template->gpiod);led_dat->blinking=0;if(blink_set){led_dat->platform_gpio_blink_set=blink_set;
@@ -122,30 +138,24 @@ static int create_gpio_led(const struct gpio_led *template,}led_dat->cdev.brightness_set=gpio_led_set;if(template->default_state==LEDS_GPIO_DEFSTATE_KEEP)-state=!!gpio_get_value_cansleep(led_dat->gpio)^led_dat->active_low;+state=!!gpiod_get_value_cansleep(led_dat->gpiod);elsestate=(template->default_state==LEDS_GPIO_DEFSTATE_ON);led_dat->cdev.brightness=state?LED_FULL:LED_OFF;if(!template->retain_state_suspended)led_dat->cdev.flags|=LED_CORE_SUSPENDRESUME;-ret=gpio_direction_output(led_dat->gpio,led_dat->active_low^state);+ret=gpiod_direction_output(led_dat->gpiod,state);if(ret<0)returnret;INIT_WORK(&led_dat->work,gpio_led_work);-ret=led_classdev_register(parent,&led_dat->cdev);-if(ret<0)-returnret;--return0;+returnled_classdev_register(parent,&led_dat->cdev);}staticvoiddelete_gpio_led(structgpio_led_data*led){-if(!gpio_is_valid(led->gpio))-return;led_classdev_unregister(&led->cdev);cancel_work_sync(&led->work);}
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:30
Hi Everyone,
Since Dmitry was suggesting that instead of using struct fw_dev_node pointers,
as we did in the previous version, we could pass the parent device along with
the child pointer to iterator functions while walking the children of a given
device node, the following patches do just that. Some things look better this
way, but some look worse. Please tell me what you think.
Mika has tested them on Minnowboard and Minnowboard MAX using the MFD patch
(number 5 previously) that is not included as it has been already applied.
The cover letter below is still applicable mostly, so I'm leaving it as is.
The only patches that changed are [2, 4, 6, 9, 12/15], so I didn't add any
ACKs to them to be prudent.
On Tuesday, September 16, 2014 02:52:31 PM Mika Westerberg wrote:
This is a second revision of the patches first submitted here [1].
The recent publication of the ACPI 5.1 specification [2] 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 [3].
An ACPI Device Properties UUID has been defined [4] 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 3 example drivers that were previously Device Tree aware that
can now be used with either Device Tree or ACPI Device Properties. The
drivers use "PRP0001" as their _HID which means that the match should be
done using driver's .of_match_table instead.
The patch series has been tested on Minnoboard and Minnowboard MAX and the
relevant part of DSDTs are at the end of this cover letter.
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.
Most important changes to the previous RFC version:
* Added wrapper functions for most used property types
* Return -EOVERFLOW in case integer would not fit to a type
* Dropped dev_prop_ops
* We now have dev_node_xxx() functions to access firmware node
properties without dev pointer
* The accessor function names try to be close to their corresponding of_*
counterpart
* Tried to have a bit better examples in the documentation patch
* gpiolib got support for _DSD and also it now understand firmware node
properties with dev_node_get_named_gpiod() that requests the GPIO
properly.
* Support for "PRP0001" _HID/_CID. This means that the match should be
done using driver .of_match_table instead.
* Add unified property support for at25 SPI eeprom driver as well.
[1] https://lkml.org/lkml/2014/8/17/10
[2] http://www.uefi.org/sites/default/files/resources/ACPI_5_1release.pdf
[3] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[4] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Aaron Lu (2):
input: gpio_keys_polled - Add support for GPIO descriptors
input: gpio_keys_polled - Make use of device property API
Max Eliaser (2):
leds: leds-gpio: Make use of device property API
leds: leds-gpio: Add ACPI probing support
Mika Westerberg (11):
ACPI: Add support for device specific properties
ACPI: Allow drivers to match using Device Tree compatible property
ACPI: Document ACPI device specific properties
mfd: Add ACPI support
gpio / ACPI: Add support for _DSD device properties
gpio: Add support for unified device properties interface
gpio: sch: Consolidate core and resume banks
leds: leds-gpio: Add support for GPIO descriptors
input: gpio_keys_polled - Add ACPI probing support
misc: at25: Make use of device property API
misc: at25: Add ACPI probing support
Rafael J. Wysocki (1):
Driver core: Unified device properties interface for platform firmware
Documentation/acpi/enumeration.txt | 27 ++
Documentation/acpi/properties.txt | 410 +++++++++++++++++++++
drivers/acpi/Makefile | 1 +
drivers/acpi/internal.h | 6 +
drivers/acpi/property.c | 584 ++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 93 ++++-
drivers/base/Makefile | 2 +-
drivers/base/property.c | 196 ++++++++++
drivers/gpio/devres.c | 35 ++
drivers/gpio/gpio-sch.c | 293 ++++++---------
drivers/gpio/gpiolib-acpi.c | 78 +++-
drivers/gpio/gpiolib.c | 85 ++++-
drivers/gpio/gpiolib.h | 7 +-
drivers/input/keyboard/gpio_keys_polled.c | 169 +++++----
drivers/leds/leds-gpio.c | 188 +++++-----
drivers/mfd/mfd-core.c | 40 ++
drivers/misc/eeprom/at25.c | 41 +--
drivers/of/base.c | 188 ++++++++++
include/acpi/acpi_bus.h | 8 +
include/linux/acpi.h | 90 ++++-
include/linux/gpio/consumer.h | 7 +
include/linux/gpio_keys.h | 3 +
include/linux/leds.h | 1 +
include/linux/mfd/core.h | 3 +
include/linux/of.h | 37 ++
include/linux/property.h | 193 ++++++++++
26 files changed, 2377 insertions(+), 408 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 modifications for Minnowboard (for leds-gpio.c and gpio_keys_polled.c)
---------------------------------------------------------------------------
Scope (\_SB.PCI0.LPC)
{
Device (LEDS)
{
Name (_HID, "PRP0001")
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}
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"gpio-leds"}},
}
})
Device (LEDH)
{
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 (_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", "off"},
Package () {"linux,retain-state-suspended", 1},
}
})
}
}
Device (BTNS)
{
Name (_HID, "PRP0001")
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.PCI0.LPC", 0, ResourceConsumer) {0, 1, 2, 3}
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"gpio-keys-polled"}},
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},
Package () {"gpios", Package () {^^BTNS, 0, 0, 1}},
}
})
}
Device (BTN1)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"linux,code", 108},
Package () {"linux,input-type", 1},
Package () {"gpios", Package (4) {^^BTNS, 0, 1, 1}},
}
})
}
Device (BTN2)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"linux,code", 103},
Package () {"linux,input-type", 1},
Package () {"gpios", Package () {^^BTNS, 0, 2, 1}},
}
})
}
Device (BTN3)
{
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"linux,code", 106},
Package () {"linux,input-type", 1},
Package () {"gpios", Package (4) {^^BTNS, 0, 3, 1}},
}
})
}
}
}
DSDT modifications for Minnowboard MAX (for at25.c)
---------------------------------------------------
Scope (\_SB.SPI1)
{
Device (AT25)
{
Name (_HID, "PRP0001")
Method (_CRS, 0, Serialized) {
Name (UBUF, ResourceTemplate () {
SpiSerialBus (0x0000, PolarityLow, FourWireMode, 0x08,
ControllerInitiated, 0x007A1200, ClockPolarityLow,
ClockPhaseSecond, "\\_SB.SPI1",
0x00, ResourceConsumer)
})
Return (UBUF)
}
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"compatible", Package () {"atmel,at25"}},
Package () {"size", 1024},
Package () {"pagesize", 32},
Package () {"address-width", 16},
}
})
Method (_STA, 0, NotSerialized)
{
Return (0xF)
}
}
}
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:03:32
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.
ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.
In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.
If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"name1", <VALUE1>},
Package () {"name2", <VALUE2>},
...
}
})
The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].
We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.
The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.
[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Reviewed-by: Hanjun Guo <redacted>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Darren Hart <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/acpi/Makefile | 1
drivers/acpi/internal.h | 6
drivers/acpi/property.c | 364 ++++++++++++++++++++++++++++++++++++++++++++++++
drivers/acpi/scan.c | 2
include/acpi/acpi_bus.h | 7
include/linux/acpi.h | 40 +++++
6 files changed, 420 insertions(+)
create mode 100644 drivers/acpi/property.c
Index: linux-pm/drivers/acpi/Makefile
===================================================================
@@ -0,0 +1,364 @@+/*+*ACPIdevicespecificpropertiessupport.+*+*Copyright(C)2014,IntelCorporation+*Allrightsreserved.+*+*Authors:MikaWesterberg<mika.westerberg@linux.intel.com>+*DarrenHart<dvhart@linux.intel.com>+*RafaelJ.Wysocki<rafael.j.wysocki@intel.com>+*+*Thisprogramisfreesoftware;youcanredistributeitand/ormodify+*itunderthetermsoftheGNUGeneralPublicLicenseversion2as+*publishedbytheFreeSoftwareFoundation.+*/++#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 */+staticconstu8prp_uuid[16]={+0x14,0xd8,0xff,0xda,0xba,0x6e,0x8c,0x4d,+0x8a,0x91,0xbc,0x9b,0xbf,0x4a,0xa3,0x01+};++staticboolacpi_property_value_ok(constunionacpi_object*value)+{+intj;++/*+*Thevaluemustbeaninteger,astring,areference,orapackage+*whoseeveryelementmustbeaninteger,astring,orareference.+*/+switch(value->type){+caseACPI_TYPE_INTEGER:+caseACPI_TYPE_STRING:+caseACPI_TYPE_LOCAL_REFERENCE:+returntrue;++caseACPI_TYPE_PACKAGE:+for(j=0;j<value->package.count;j++)+switch(value->package.elements[j].type){+caseACPI_TYPE_INTEGER:+caseACPI_TYPE_STRING:+caseACPI_TYPE_LOCAL_REFERENCE:+continue;++default:+returnfalse;+}++returntrue;+}+returnfalse;+}++staticboolacpi_properties_format_valid(constunionacpi_object*properties)+{+inti;++for(i=0;i<properties->package.count;i++){+constunionacpi_object*property;++property=&properties->package.elements[i];+/*+*Onlytwoelementsallowed,thefirstonemustbeastringand+*thesecondonehastosatisfycertainconditions.+*/+if(property->package.count!=2+||property->package.elements[0].type!=ACPI_TYPE_STRING+||!acpi_property_value_ok(&property->package.elements[1]))+returnfalse;+}+returntrue;+}++voidacpi_init_properties(structacpi_device*adev)+{+structacpi_bufferbuf={ACPI_ALLOCATE_BUFFER};+constunionacpi_object*desc;+acpi_statusstatus;+inti;++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)+gotofail;++/* Look for the device properties UUID. */+for(i=0;i<desc->package.count;i+=2){+constunionacpi_object*uuid,*properties;++uuid=&desc->package.elements[i];+properties=&desc->package.elements[i+1];++/*+*ThefirstelementmustbeaUUIDandthesecondonemustbe+*apackage.+*/+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;++/*+*WefoundthematchingUUID.Nowvalidatetheformatofthe+*packageimmediatelyfollowingit.+*/+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);+}++voidacpi_free_properties(structacpi_device*adev)+{+ACPI_FREE((void*)adev->data.pointer);+adev->data.pointer=NULL;+adev->data.properties=NULL;+}++/**+*acpi_dev_get_property-returnanACPIpropertywithgivenname+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@type:Expectedpropertytype+*@obj:Locationtostorethepropertyvalue(ifnot%NULL)+*+*Lookupapropertywith@nameandstoreapointertotheresultingACPI+*objectatthelocationpointedtoby@objiffound.+*+*Callersmustnotattempttofreethereturnedobjects.Theseobjectswillbe+*freedbytheACPIcoreautomaticallyduringtheremovalof@adev.+*+*Return:%0ifpropertywith@namehasbeenfound(success),+*%-EINVALiftheargumentsareinvalid,+*%-ENODATAifthepropertydoesn'texist,+*%-EPROTOifthepropertyvaluetypedoesn'tmatch@type.+*/+intacpi_dev_get_property(structacpi_device*adev,constchar*name,+acpi_object_typetype,constunionacpi_object**obj)+{+constunionacpi_object*properties;+inti;++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++){+constunionacpi_object*propname,*propvalue;+constunionacpi_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;+elseif(obj)+*obj=propvalue;++return0;+}+}+return-ENODATA;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property);++/**+*acpi_dev_get_property_array-returnanACPIarraypropertywithgivenname+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@type:Expectedtypeofarrayelements+*@obj:Locationtostoreapointertothepropertyvalue(ifnotNULL)+*+*Lookupanarraypropertywith@nameandstoreapointertotheresulting+*ACPIobjectatthelocationpointedtoby@objiffound.+*+*Callersmustnotattempttofreethereturnedobjects.Thoseobjectswillbe+*freedbytheACPIcoreautomaticallyduringtheremovalof@adev.+*+*Return:%0ifarrayproperty(package)with@namehasbeenfound(success),+*%-EINVALiftheargumentsareinvalid,+*%-ENODATAifthepropertydoesn'texist,+*%-EPROTOifthepropertyisnotapackageorthetypeofitselements+*doesn'tmatch@type.+*/+intacpi_dev_get_property_array(structacpi_device*adev,constchar*name,+acpi_object_typetype,+constunionacpi_object**obj)+{+constunionacpi_object*prop;+intret,i;++ret=acpi_dev_get_property(adev,name,ACPI_TYPE_PACKAGE,&prop);+if(ret)+returnret;++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;++return0;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property_array);++/**+*acpi_dev_get_property_reference-returnshandletothereferencedobject+*@adev:ACPIdevicetogetproperty+*@name:Nameoftheproperty+*@size_prop:Nameofthe"size"propertyinreferencedobject+*@index:Indexofthereferencetoreturn+*@args:Locationtostorethereturnedreferencewithoptionalarguments+*+*Findpropertywith@name,verififythatitisapackagecontainingatleast+*oneobjectreferenceandifso,storetheACPIdeviceobjectpointertothe+*targetobjectin@args->adev.+*+*Ifthereferenceincludesarguments(@size_propisnot%NULL)followthe+*referenceandcheckwhetherornotthereisanintegerproperty@size_prop+*underthetargetobjectandifso,whetherornotitsvaluematchesthe+*numberofargumentsthatfollowthereference.Ifthere'smorethanone+*referenceinthepropertyvaluepackage,@indexisusedtoselecttheoneto+*return.+*+*Return:%0onsuccess,negativeerrorcodeonfailure.+*/+intacpi_dev_get_property_reference(structacpi_device*adev,constchar*name,+constchar*size_prop,size_tindex,+structacpi_reference_args*args)+{+constunionacpi_object*element,*end;+constunionacpi_object*obj;+structacpi_device*device;+intret,idx=0;++ret=acpi_dev_get_property(adev,name,ACPI_TYPE_ANY,&obj);+if(ret)+returnret;++/*+*Thesimplestcaseiswhenthevalueisasinglereference.Just+*returnthatreferencethen.+*/+if(obj->type==ACPI_TYPE_LOCAL_REFERENCE){+if(size_prop||index)+return-EINVAL;++ret=acpi_bus_get_device(obj->reference.handle,&device);+if(ret)+returnret;++args->adev=device;+args->nargs=0;+return0;+}++/*+*Ifitisnotasinglereference,thenitisapackageof+*referencesfollowedbynumberofintsasfollows:+*+*Package(){REF,INT,REF,INT,INT}+*+*Theindexargumentisthenusedtodeterminewhichreference+*thecallerwants(alongwiththearguments).+*/+if(obj->type!=ACPI_TYPE_PACKAGE||index>=obj->package.count)+return-EPROTO;++element=obj->package.elements;+end=element+obj->package.count;++while(element<end){+u32nargs,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){+constunionacpi_object*prop;++/*+*Findouthowmanyargumentstherefencedobject+*expectsbyreadingitssize_propproperty.+*/+ret=acpi_dev_get_property(device,size_prop,+ACPI_TYPE_INTEGER,&prop);+if(ret)+returnret;++nargs=prop->integer.value;+if(nargs>MAX_ACPI_REFERENCE_ARGS+||element+nargs>end)+return-EPROTO;++/*+*Skiptothestartoftheargumentsandverify+*thattheyallareinfactintegers.+*/+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++){+inttype=element[i].type;++if(type==ACPI_TYPE_INTEGER)+nargs++;+elseif(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;++return0;+}++element+=nargs;+}++return-EPROTO;+}+EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:04:05
From: "Rafael J. Wysocki" <redacted>
Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type. The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.
Three general helper functions, device_get_property(),
device_read_property() and device_read_property_array() are provided.
The first one allows the raw value of a given device property to be
accessed. The remaining two allow the value of a numeric or string
property and multiple numeric or string values of one array
property to be acquired, respectively. Static inline wrappers are also
provided for the various property data types that can be passed to
device_read_property() or device_read_property_array() for extra type
checking.
In addition to that, new generic routines are provided for retrieving
properties from device description objects in the platform firmware
in case a device driver needs/wants to access properties of a child
object of a given device object. There are cases in which there is
no struct device representation of such child objects and this
additional API is useful then. Again, three functions are provided,
device_get_child_property(), device_read_child_property(),
device_read_child_property_array(), in analogy with device_get_property(),
device_read_property() and device_read_property_array() described above,
respectively, along with static inline wrappers for all of the propery
data types that can be used. For all of them, the first argument is
a struct device pointer to the parent device object and the second
argument is a (void *) pointer to the child description provided by
the platform firmware (either ACPI or FDT).
Finally, device_for_each_child_node() is added for iterating over
the children of the device description object associated with a
given device.
The interface covers both ACPI and Device Trees.
This change set includes material from Mika Westerberg and Aaron Lu.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
Greg, please let me know if you're fine with this one.
---
drivers/acpi/property.c | 188 +++++++++++++++++++++++++++++++++++++
drivers/base/Makefile | 2
drivers/base/property.c | 235 +++++++++++++++++++++++++++++++++++++++++++++++
drivers/of/base.c | 186 +++++++++++++++++++++++++++++++++++++
include/linux/acpi.h | 42 ++++++++
include/linux/of.h | 37 +++++++
include/linux/property.h | 207 +++++++++++++++++++++++++++++++++++++++++
7 files changed, 896 insertions(+), 1 deletion(-)
create mode 100644 drivers/base/property.c
create mode 100644 include/linux/property.h
Index: linux-pm/drivers/acpi/property.c
===================================================================
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:04:30
From: Mika Westerberg <mika.westerberg@linux.intel.com>
We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead.
If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/acpi/property.c | 34 +++++++++++++++++
drivers/acpi/scan.c | 91 ++++++++++++++++++++++++++++++++++++++++++------
include/acpi/acpi_bus.h | 1
include/linux/acpi.h | 8 +---
4 files changed, 118 insertions(+), 16 deletions(-)
Index: linux-pm/drivers/acpi/property.c
===================================================================
@@ -124,17 +124,43 @@ static int create_modalias(struct acpi_dif(list_empty(&acpi_dev->pnp.ids))return0;-len=snprintf(modalias,size,"acpi:");-size-=len;+/*+*IfthedevicehasPRP0001weexposeDTcompatiblemodalias+*instead.+*/+if(acpi_dev->data.of_compatible){+constunionacpi_object*of_compatible,*obj;+inti;++len=snprintf(modalias,size,"of:Nprp0001Tacpi");++of_compatible=acpi_dev->data.of_compatible;+for(i=0;i<of_compatible->package.count;i++){+obj=&of_compatible->package.elements[i];++count=snprintf(&modalias[len],size,"C%s",+obj->string.pointer);+if(count<0)+return-EINVAL;+if(count>=size)+return-ENOMEM;++len+=count;+size-=count;+}+}else{+len=snprintf(modalias,size,"acpi:");+size-=len;-list_for_each_entry(id,&acpi_dev->pnp.ids,list){-count=snprintf(&modalias[len],size,"%s:",id->id);-if(count<0)-return-EINVAL;-if(count>=size)-return-ENOMEM;-len+=count;-size-=count;+list_for_each_entry(id,&acpi_dev->pnp.ids,list){+count=snprintf(&modalias[len],size,"%s:",id->id);+if(count<0)+return-EINVAL;+if(count>=size)+return-ENOMEM;+len+=count;+size-=count;+}}modalias[len]='\0';
@@ -864,6 +890,51 @@ int acpi_match_device_ids(struct acpi_de}EXPORT_SYMBOL(acpi_match_device_ids);+/* Performs match for special "PRP0001" shoehorn ACPI ID */+staticboolacpi_of_driver_match_device(structdevice*dev,+conststructdevice_driver*drv)+{+structacpi_device*adev=ACPI_COMPANION(dev);+constunionacpi_object*of_compatible;+inti;++/*+*IftheACPIdevicedoesnothavecorrespondingcompatible+*propertyorthedriverinquestiondoesnothaveDTmatching+*tableweconsiderthematchsuccesful(matchestheACPIID).+*/+of_compatible=adev->data.of_compatible;+if(!drv->of_match_table||!of_compatible)+returntrue;++/* Now we can look for the driver DT compatible strings */+for(i=0;i<of_compatible->package.count;i++){+conststructof_device_id*id;+constunionacpi_object*obj;++obj=&of_compatible->package.elements[i];++for(id=drv->of_match_table;id->compatible[0];id++)+if(!strcasecmp(obj->string.pointer,id->compatible))+returntrue;+}++returnfalse;+}++boolacpi_driver_match_device(structdevice*dev,+conststructdevice_driver*drv)+{+conststructacpi_device_id*id;++id=acpi_match_device(drv->acpi_match_table,dev);+if(!id)+returnfalse;++returnacpi_of_driver_match_device(dev,drv);+}+EXPORT_SYMBOL_GPL(acpi_driver_match_device);+staticvoidacpi_free_power_resources_lists(structacpi_device*device){inti;
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:04:52
From: Mika Westerberg <mika.westerberg@linux.intel.com>
This document describes the data format and interfaces of ACPI device
specific properties.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Darren Hart <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
Documentation/acpi/properties.txt | 410 ++++++++++++++++++++++++++++++++++++++
1 file changed, 410 insertions(+)
create mode 100644 Documentation/acpi/properties.txt
@@ -0,0 +1,410 @@+ACPI device properties+======================+This document describes the format and interfaces of ACPI device+properties as specified in "Device Properties UUID For _DSD" available+here:++http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf++1. Introduction+---------------+In systems that use ACPI and want to take advantage of device specific+properties, there needs to be a standard way to return and extract+name-value pairs for a given ACPI device.++An ACPI device that wants to export its properties must implement a+static name called _DSD that takes no arguments and returns a package of+packages:++ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"name1", <VALUE1>},+ Package () {"name2", <VALUE2>}+ }+ })++The UUID identifies contents of the following package. In case of ACPI+device properties it is daffd814-6eba-4d8c-8a91-bc9bbf4aa301.++In each returned package, the first item is the name and must be a string.+The corresponding value can be a string, integer, reference, or package. If+a package it may only contain strings, integers, and references.++An example device where we might need properties is a device that uses+GPIOs. In addition to the GpioIo/GpioInt resources the driver needs to+know which GPIO is used for which purpose.++To solve this we add the following ACPI device properties to the device:++ Device (DEV0)+ {+ Name (_CRS, ResourceTemplate () {+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}+ ...+ })++ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"reset-gpio", {^DEV0, 0, 0, 0}},+ Package () {"shutdown-gpio", {^DEV0, 1, 0, 0}},+ }+ })+ }++Now the device driver can reference the GPIOs using names instead of+using indexes.++If there is an existing Device Tree binding for a device, it is expected+that the same bindings are used with ACPI properties, so that the driver+dealing with the device needs only minor modifications if any.++2. Formal definition of properties+----------------------------------+The following chapters define the currently supported properties. For+these there exists a helper function that can be used to extract the+property value.++2.1 Integer types+-----------------+ACPI integers are always 64-bit. However, for drivers the full range is+typically not needed so we provide a set of functions which convert the+64-bit integer to a smaller Linux integer type.++An integer property looks like this:++ Package () {"i2c-sda-hold-time-ns", 300},+ Package () {"clock-frequency", 400000},++To read a property value, use a unified property accessor as shown+below:++ u32 val;+ int ret;++ ret = device_property_read_u32(dev, "clock-frequency", &val);+ if (ret)+ /* Handle error */++The function returns 0 if the property is copied to 'val' or negative+errno if something went wrong (or the property does not exist).++2.2 Integer arrays+------------------+An integer array is a package holding only integers. Arrays can be used to+represent different things like Linux input key codes to GPIO mappings, pin+control settings, dma request lines, etc.++An integer array looks like this:++ Package () {+ "max8952,dvs-mode-microvolt",+ Package () {+ 1250000,+ 1200000,+ 1050000,+ 950000,+ }+ }++The above array property can be accessed like:++ u32 voltages[4];+ int ret;++ ret = device_property_read_u32_array(dev, "max8952,dvs-mode-microvolt",+ voltages, ARRAY_SIZE(voltages));+ if (ret)+ /* Handle error */+++All functions copy the resulting values cast to a requested type to the+caller supplied array. If you pass NULL in the value pointer ('voltages' in+this case), the function returns number of items in the array. This can be+useful if caller does not know size of the array beforehand.++2.3 Strings+-----------+String properties can be used to describe many things like labels for GPIO+buttons, compability ids, etc.++A string property looks like this:++ Package () {"pwm-names", "backlight"},+ Package () {"label", "Status-LED"},++You can use device_property_read_string() to extract strings:++ const char *val;+ int ret;++ ret = device_property_read_string(dev, "label", &val);+ if (ret)+ /* Handle error */++Note that the function does not copy the returned string but instead the+value is modified to point to the string property itself.++The memory is owned by the associated ACPI device object and released+when it is removed. The user need not free the associated memory.++2.4 String arrays+-----------------+String arrays can be useful in describing a list of labels, names for+DMA channels, etc.++A string array property looks like this:++ Package () {"dma-names", Package () {"tx", "rx", "rx-tx"}},+ Package () {"clock-output-names", Package () {"pll", "pll-switched"}},++And these can be read in similar way that the integer arrrays:++ const char *dma_names[3];+ int ret;++ ret = device_property_read_string_array(dev, "dma-names", dma_names,+ ARRAY_SIZE(dma_names));+ if (ret)+ /* Handle error */++The memory management rules follow what is specified for single strings.+Specifically the returned pointers should be treated as constant and not to+be freed. That is done automatically when the correspondig ACPI device+object is released.++2.5 Object references+---------------------+An ACPI object reference is used to refer to some object in the+namespace. For example, if a device has dependencies with some other+object, an object reference can be used.++An object reference looks like this:++ Package () {"dev0", \_SB.DEV0},++At the time of writing this, there is no unified device_property_* accessor+for references so one needs to use the following ACPI helper function:++ int acpi_dev_get_property_reference(struct acpi_device *adev,+ const char *name,+ const char *size_prop, int index,+ struct acpi_reference_args *args);++The referenced ACPI device is returned in args->adev if found.++In addition to simple object references it is also possible to have object+references with arguments. These are represented in ASL as follows:++ Device (\_SB.PCI0.PWM)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"#pwm-cells", 2}+ }+ })+ }++ Device (\_SB.PCI0.BL)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {+ "pwms",+ Package () {+ \_SB.PCI0.PWM, 0, 5000000,+ \_SB.PCI0.PWM, 1, 4500000,+ }+ }+ }+ })+ }++In the above example, the referenced device declares a property that+returns the number of expected arguments (here it is "#pwm-cells"). If+no such property is given we assume that all the integers following the+reference are arguments.++In the above example PWM device expects 2 additional arguments. This+will be validated by the ACPI property core.++The additional arguments must be integers. Nothing else is supported.++It is possible, as in the above example, to have multiple references+with varying number of integer arguments. It is up to the referenced+device to declare how many arguments it expects. The 'index' parameter+selects which reference is returned.++One can use acpi_dev_get_property_reference() as well to extract the+information in additional parameters:++ struct acpi_reference_args args;+ struct acpi_device *adev = /* this will point to the BL device */+ int ret;++ /* extract the first reference */+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 0, &args);++ BUG_ON(args.nargs != 2);+ BUG_ON(args.args[0] != 0);+ BUG_ON(args.args[1] != 5000000);++ /* extract the second reference */+ acpi_dev_get_property_reference(adev, "pwms", "#pwm-cells", 1, &args);++ BUG_ON(args.nargs != 2);+ BUG_ON(args.args[0] != 1);+ BUG_ON(args.args[1] != 4500000);++In addition to arguments, args.adev now points to the ACPI device that+corresponds to \_SB.PCI0.PWM.++It is intended that this function is not used directly but instead+subsystems like pwm implement their ACPI support on top of this function+in such way that it is hidden from the client drivers, such as via+pwm_get().++3. Device property hierarchies+------------------------------+Devices are organized in a tree within the Linux kernel. It follows that+the configuration data would also be hierarchical. In order to reach+equivalence with Device Tree, the ACPI mechanism must also provide some+sort of tree-like representation. Fortunately, the ACPI namespace is+already such a structure.++For example, we could have the following device in ACPI namespace. The+KEYS device is much like gpio_keys_polled.c in that it includes "pseudo"+devices for each GPIO:++ Device (KEYS)+ {+ Name (_CRS, ResourceTemplate () {+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {0}+ GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,+ "\\_SB.PCI0.LPC", 0, ResourceConsumer) {1}+ ...+ })++ // "pseudo" devices declared under the parent device+ Device (BTN0) {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"label", "minnow_btn0"}+ Package () {"gpios", Package () {^KEYS, 0, 0, 1}}+ }+ })+ }++ Device (BTN1) {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"label", "minnow_btn1"}+ Package () {"gpios", Package () {^KEYS, 1, 0, 1}}+ }+ })+ }+ }++We can extract the above in gpio_keys_polled.c like:++ static int gpio_keys_polled_create_button(struct device *dev, void *child,+ void *data)+ {+ struct button_data *bdata = data;+ const char *label = NULL;++ /*+ * We need to use device_child_ variant here to access+ * properties of the child.+ */+ device_child_property_read_string(dev, child, "label", &label);+ /* and so on */+ }++ static void gpio_keys_polled_probe(struct device *dev)+ {+ /* Properties for the KEYS device itself */+ device_property_read(dev, ...);++ /*+ * Iterate over button devices and extract their+ * firmware configuration.+ */+ ret = device_for_each_child_node(dev, gpio_keys_polled_create_button,+ &bdata);+ if (ret)+ /* Handle error */+ }++Note that you still need proper error handling which is omitted in the+above example.++4. Existing Device Tree enabled drivers+---------------------------------------+At the time of writing this, there are ~250 existing DT enabled drivers.+Allocating _HID/_CID for each would not be feasible. To make sure that+those drivers can still be used on ACPI systems, we provide an+alternative way to get these matched.++There is a special _HID "PRP0001" which means that use the DT bindings+for matching this device to a driver. The driver needs to have+.of_match_table filled in even when !CONFIG_OF.++An example device would be leds that can be controlled via GPIOs. This+is represented as "leds-gpio" device and looks like this in the ACPI+namespace:++ Device (LEDS)+ {+ Name (_DSD, Package () {+ ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),+ Package () {+ Package () {"compatible", Package () {"gpio-leds"}},+ }+ })+ ...+ }++In order to get the existing drivers/leds/leds-gpio.c bound to this+device, we take advantage of "PRP0001":++ /* Following already exists in the driver */+ static const struct of_device_id of_gpio_leds_match[] = {+ { .compatible = "gpio-leds", },+ {},+ };+ MODULE_DEVICE_TABLE(of, of_gpio_leds_match);++ /* This we add to the driver to get it probed */+ static const struct acpi_device_id acpi_gpio_leds_match[] = {+ { "PRP0001" }, /* Device Tree shoehorned into ACPI */+ {},+ };+ MODULE_DEVICE_TABLE(acpi, acpi_gpio_leds_match);++ static struct platform_driver gpio_led_driver = {+ .driver = {+ /*+ * No of_match_ptr() here because we want this+ * table to be visible even when !CONFIG_OF to+ * match against "compatible" in _DSD.+ */+ .of_match_table = of_gpio_leds_match,+ .acpi_match_table = acpi_gpio_leds_match,+ },+ };++Once ACPI core sees "PRP0001" and that the device has "compatible"+property it will do the match using .of_match_table instead.++It is preferred that new devices get a proper _HID allocated for them+instead of inventing new DT "compatible" devices.
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:05:21
From: Mika Westerberg <mika.westerberg@linux.intel.com>
With release of ACPI 5.1 and _DSD method we can finally name GPIOs (and
other things as well) returned by _CRS. Previously we were only able to
use integer index to find the corresponding GPIO, which is pretty error
prone if the order changes.
With _DSD we can now query GPIOs using name instead of an integer index,
like the below example shows:
// Bluetooth device with reset and shutdown GPIOs
Device (BTH)
{
Name (_HID, ...)
Name (_CRS, ResourceTemplate ()
{
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {15}
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionInputOnly,
"\\_SB.GPO0", 0, ResourceConsumer) {27, 31}
})
Name (_DSD, Package ()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package ()
{
Package () {"reset-gpio", Package() {^BTH, 1, 1, 0 }},
Package () {"shutdown-gpio", Package() {^BTH, 0, 0, 0 }},
}
})
}
The format of the supported GPIO property is:
Package () { "name", Package () { ref, index, pin, active_low }}
ref - The device that has _CRS containing GpioIo()/GpioInt() resources,
typically this is the device itself (BTH in our case).
index - Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
pin - Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
active_low - If 1 the GPIO is marked as active_low.
Since ACPI GpioIo() resource does not have field saying whether it is
active low or high, the "active_low" argument can be used here. Setting
it to 1 marks the GPIO as active low.
In our Bluetooth example the "reset-gpio" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.
This patch implements necessary support to gpiolib for extracting GPIOs
using _DSD device properties.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Linus Walleij <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/gpio/gpiolib-acpi.c | 78 ++++++++++++++++++++++++++++++++++++--------
drivers/gpio/gpiolib.c | 30 ++++++++++++++--
drivers/gpio/gpiolib.h | 7 ++-
3 files changed, 94 insertions(+), 21 deletions(-)
Index: linux-pm/drivers/gpio/gpiolib-acpi.c
===================================================================
@@ -306,13 +307,24 @@ static int acpi_find_gpio(struct acpi_reif(lookup->n++==lookup->index&&!lookup->desc){conststructacpi_resource_gpio*agpio=&ares->data.gpio;+intpin_index=lookup->pin_index;++if(pin_index>=agpio->pin_table_length)+return1;lookup->desc=acpi_get_gpiod(agpio->resource_source.string_ptr,-agpio->pin_table[0]);+agpio->pin_table[pin_index]);lookup->info.gpioint=agpio->connection_type==ACPI_RESOURCE_GPIO_TYPE_INT;-lookup->info.active_low=-agpio->polarity==ACPI_ACTIVE_LOW;++/*+*ActiveLowisonlyspecifiedforGpioIntresource.If+*GpioIoisusedthentheonlywaytosettheflagis+*touse_DSD"gpios"property.+*/+if(lookup->info.gpioint)+lookup->info.active_low=+agpio->polarity==ACPI_ACTIVE_LOW;}return1;
@@ -320,40 +332,75 @@ static int acpi_find_gpio(struct acpi_re/***acpi_get_gpiod_by_index()-getaGPIOdescriptorfromdeviceresources-*@dev:pointertoadevicetogetGPIOfrom+*@adev:pointertoaACPIdevicetogetGPIOfrom+*@propname:PropertynameoftheGPIO(optional)*@index:indexofGpioIo/GpioIntresource(startingfrom%0)*@info:infopointertofillin(optional)*-*FunctiongoesthroughACPIresourcesfor@devandbasedon@indexlooks+*FunctiongoesthroughACPIresourcesfor@adevandbasedon@indexlooks*upaGpioIo/GpioIntresource,translatesittotheLinuxGPIOdescriptor,*andreturnsit.@indexmatchesGpioIo/GpioIntresourcesonlysoifthere*aretotal%3GPIOresources,theindexgoesfrom%0to%2.*+*If@propnameisspecifiedtheGPIOislookedusingdeviceproperty.In+*thatcase@indexisusedtoselecttheGPIOentryinthepropertyvalue+*(incaseofmultiple).+**IftheGPIOcannotbetranslatedorthereisanerroranERR_PTRis*returned.**Note:iftheGPIOresourcehasmultipleentriesinthepinlist,this*functiononlyreturnsthefirst.*/-structgpio_desc*acpi_get_gpiod_by_index(structdevice*dev,intindex,+structgpio_desc*acpi_get_gpiod_by_index(structacpi_device*adev,+constchar*propname,intindex,structacpi_gpio_info*info){structacpi_gpio_lookuplookup;structlist_headresource_list;-structacpi_device*adev;-acpi_handlehandle;+boolactive_low=false;intret;-if(!dev)-returnERR_PTR(-EINVAL);--handle=ACPI_HANDLE(dev);-if(!handle||acpi_bus_get_device(handle,&adev))+if(!adev)returnERR_PTR(-ENODEV);memset(&lookup,0,sizeof(lookup));lookup.index=index;+if(propname){+structacpi_reference_argsargs;++dev_dbg(&adev->dev,"GPIO: looking up %s\n",propname);++memset(&args,0,sizeof(args));+ret=acpi_dev_get_property_reference(adev,propname,NULL,+index,&args);+if(ret)+returnERR_PTR(ret);++/*+*Thepropertywasfoundandresolvedsoneedto+*lookuptheGPIObasedonreturnedargsinstead.+*/+adev=args.adev;+if(args.nargs>=2){+lookup.index=args.args[0];+lookup.pin_index=args.args[1];+/*+*3rdargument,ifpresentisusedto+*specifyactive_low.+*/+if(args.nargs>=3)+active_low=!!args.args[2];+}++dev_dbg(&adev->dev,"GPIO: _DSD returned %s %zd %llu %llu %llu\n",+dev_name(&adev->dev),args.nargs,+args.args[0],args.args[1],args.args[2]);+}else{+dev_dbg(&adev->dev,"GPIO: looking up %d in _CRS\n",index);+}+INIT_LIST_HEAD(&resource_list);ret=acpi_dev_get_resources(adev,&resource_list,acpi_find_gpio,&lookup);
@@ -1487,14 +1487,36 @@ static struct gpio_desc *acpi_find_gpio(unsignedintidx,enumgpio_lookup_flags*flags){+staticconstchar*constsuffixes[]={"gpios","gpio"};+structacpi_device*adev=ACPI_COMPANION(dev);structacpi_gpio_infoinfo;structgpio_desc*desc;+charpropname[32];+inti;-desc=acpi_get_gpiod_by_index(dev,idx,&info);-if(IS_ERR(desc))-returndesc;+/* Try first from _DSD */+for(i=0;i<ARRAY_SIZE(suffixes);i++){+if(con_id&&strcmp(con_id,"gpios")){+snprintf(propname,sizeof(propname),"%s-%s",+con_id,suffixes[i]);+}else{+snprintf(propname,sizeof(propname),"%s",+suffixes[i]);+}-if(info.gpioint&&info.active_low)+desc=acpi_get_gpiod_by_index(adev,propname,0,&info);+if(!IS_ERR(desc)||(PTR_ERR(desc)==-EPROBE_DEFER))+break;+}++/* Then from plain _CRS GPIOs */+if(IS_ERR(desc)){+desc=acpi_get_gpiod_by_index(adev,NULL,idx,&info);+if(IS_ERR(desc))+returndesc;+}++if(info.active_low)*flags|=GPIO_ACTIVE_LOW;returndesc;
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:05:45
From: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Some drivers need to deal with only firmware representation of its
GPIOs. An example would be a GPIO button array driver where each button
is described as a separate firmware node in device tree. Typically these
child nodes do not have physical representation in the Linux device
model.
In order to help device drivers to handle such firmware child nodes we
add dev[m]_get_named_gpiod_from_child() that takes a child firmware
node pointer as its second argument (the first one is the parent device
itself), finds the GPIO using whatever is the underlying firmware
method, and requests the GPIO properly.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Rafael J. Wysocki <redacted>
---
Linus, does this look better than the previous one to you?
---
drivers/gpio/devres.c | 34 +++++++++++++++++++++++++
drivers/gpio/gpiolib.c | 56 ++++++++++++++++++++++++++++++++++++++++++
include/linux/gpio/consumer.h | 5 +++
3 files changed, 95 insertions(+)
Index: linux-pm/drivers/gpio/devres.c
===================================================================
@@ -1717,6 +1717,62 @@ struct gpio_desc *__must_check __gpiod_gEXPORT_SYMBOL_GPL(__gpiod_get_index);/**+*dev_get_named_gpiod_from_child-obtainaGPIOfromfirmwarenode+*@dev:parentdevice+*@child:firmwarenode(childof@dev)+*@propname:nameofthefirmwareproperty+*@idx:indexoftheGPIOinthepropertyvalueincaseofmany+*+*Thisfunctioncanbeusedfordriversthatgettheirconfiguration+*fromfirmwareinsuchawaythatsomepropertiesaredescribedaschild+*nodesfortheparentdeviceinDTorACPI.+*+*FunctionproperlyfindsthecorrespondingGPIOusingwhateveristhe+*underlyingfirmwareinterfaceandthenmakessurethattheGPIO+*descriptorisrequestedbeforeitisreturnedtothecaller.+*+*IncaseoferroranERR_PTR()isreturned.+*/+structgpio_desc*dev_get_named_gpiod_from_child(structdevice*dev,void*child,+constchar*propname,intindex)+{+structgpio_desc*desc=ERR_PTR(-ENODEV);+boolactive_low=false;+intret;++if(!child)+returnERR_PTR(-EINVAL);++if(IS_ENABLED(CONFIG_OF)&&dev->of_node){+enumof_gpio_flagsflags;++desc=of_get_named_gpiod_flags(child,propname,index,&flags);+if(!IS_ERR(desc))+active_low=flags&OF_GPIO_ACTIVE_LOW;+}elseif(ACPI_COMPANION(dev)){+structacpi_gpio_infoinfo;++desc=acpi_get_gpiod_by_index(child,propname,index,&info);+if(!IS_ERR(desc))+active_low=info.active_low;+}++if(IS_ERR(desc))+returndesc;++ret=gpiod_request(desc,NULL);+if(ret)+returnERR_PTR(ret);++/* Only value flag can be set from both DT and ACPI is active_low */+if(active_low)+set_bit(FLAG_ACTIVE_LOW,&desc->flags);++returndesc;+}+EXPORT_SYMBOL_GPL(dev_get_named_gpiod_from_child);++/***gpiod_get_index_optional-obtainanoptionalGPIOfromamulti-indexGPIO*function*@dev:GPIOconsumer,canbeNULLforsystem-globalGPIOs
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
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:06:06
From: Max Eliaser <redacted>
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 <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/leds/leds-gpio.c | 99 +++++++++++++++++++----------------------------
1 file changed, 42 insertions(+), 57 deletions(-)
Index: linux-pm/drivers/leds/leds-gpio.c
===================================================================
@@ -171,65 +169,59 @@ static inline int sizeof_gpio_leds_priv((sizeof(structgpio_led_data)*num_leds);}-/* Code to create from OpenFirmware platform devices */-#ifdef CONFIG_OF_GPIO-staticstructgpio_leds_priv*gpio_leds_create_of(structplatform_device*pdev)+staticintgpio_leds_create_led(structdevice*dev,void*child,void*data)+{+structgpio_leds_priv*priv=data;+structgpio_ledled={};+constchar*state=NULL;++led.gpiod=devm_get_named_gpiod_from_child(dev,child,"gpios",0);+if(IS_ERR(led.gpiod))+returnPTR_ERR(led.gpiod);++device_child_property_read_string(dev,child,"label",&led.name);+device_child_property_read_string(dev,child,"linux,default-trigger",+&led.default_trigger);++device_child_property_read_string(dev,child,"linux,default_state",+&state);+if(state){+if(!strcmp(state,"keep"))+led.default_state=LEDS_GPIO_DEFSTATE_KEEP;+elseif(!strcmp(state,"on"))+led.default_state=LEDS_GPIO_DEFSTATE_ON;+else+led.default_state=LEDS_GPIO_DEFSTATE_OFF;+}++if(!device_get_child_property(dev,child,"retain-state-suspended",NULL))+led.retain_state_suspended=1;++returncreate_gpio_led(&led,&priv->leds[priv->num_leds++],dev,NULL);+}++staticstructgpio_leds_priv*gpio_leds_create(structplatform_device*pdev){-structdevice_node*np=pdev->dev.of_node,*child;structgpio_leds_priv*priv;-intcount,ret;+intret,count;-/* count LEDs in this device, so we know how much to allocate */-count=of_get_available_child_count(np);+count=device_get_child_node_count(&pdev->dev);if(!count)returnERR_PTR(-ENODEV);-for_each_available_child_of_node(np,child)-if(of_get_gpio(child,0)==-EPROBE_DEFER)-returnERR_PTR(-EPROBE_DEFER);-priv=devm_kzalloc(&pdev->dev,sizeof_gpio_leds_priv(count),GFP_KERNEL);if(!priv)returnERR_PTR(-ENOMEM);-for_each_available_child_of_node(np,child){-structgpio_ledled={};-enumof_gpio_flagsflags;-constchar*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;-elseif(!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);-gotoerr;-}+ret=device_for_each_child_node(&pdev->dev,gpio_leds_create_led,priv);+if(ret){+for(count=priv->num_leds-2;count>=0;count--)+delete_gpio_led(&priv->leds[count]);+returnERR_PTR(ret);}returnpriv;--err:-for(count=priv->num_leds-2;count>=0;count--)-delete_gpio_led(&priv->leds[count]);-returnERR_PTR(-ENODEV);}staticconststructof_device_idof_gpio_leds_match[]={
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:06:34
From: Aaron Lu <redacted>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Linus Walleij <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/input/keyboard/gpio_keys_polled.c | 39 +++++++++++++++++++++----------
include/linux/gpio_keys.h | 3 +++
2 files changed, 30 insertions(+), 12 deletions(-)
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:06:54
From: Aaron Lu <redacted>
Make use of device property API in this driver so that both OF based
system and ACPI based system can use this driver.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
Dmitry, does this look better than the previous one to you?
---
drivers/input/keyboard/gpio_keys_polled.c | 119 +++++++++++++-----------------
1 file changed, 52 insertions(+), 67 deletions(-)
Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
===================================================================
@@ -102,21 +100,57 @@ static void gpio_keys_polled_close(strucpdata->disable(bdev->dev);}-#ifdef CONFIG_OF+staticintgpio_keys_polled_get_button(structdevice*dev,void*child,+void*data)+{+structgpio_keys_platform_data*pdata=data;+structgpio_keys_button*button;+structgpio_desc*desc;++desc=devm_get_named_gpiod_from_child(dev,child,"gpios",0);+if(IS_ERR(desc)){+interr=PTR_ERR(desc);++if(err!=-EPROBE_DEFER)+dev_err(dev,"Failed to get gpio flags, error: %d\n",+err);+returnerr;+}++button=&pdata->buttons[pdata->nbuttons++];+button->gpiod=desc;++if(device_child_property_read_u32(dev,child,"linux,code",+&button->code)){+dev_err(dev,"Button without keycode: %d\n",+pdata->nbuttons-1);+return-EINVAL;+}++device_child_property_read_string(dev,child,"label",&button->desc);++if(device_child_property_read_u32(dev,child,"linux,input-type",+&button->type))+button->type=EV_KEY;++button->wakeup=!device_get_child_property(dev,child,+"gpio-key,wakeup",NULL);++if(device_child_property_read_u32(dev,child,"debounce-interval",+&button->debounce_interval))+button->debounce_interval=5;++return0;+}+staticstructgpio_keys_platform_data*gpio_keys_polled_get_devtree_pdata(structdevice*dev){-structdevice_node*node,*pp;structgpio_keys_platform_data*pdata;structgpio_keys_button*button;interror;intnbuttons;-inti;--node=dev->of_node;-if(!node)-returnNULL;-nbuttons=of_get_child_count(node);+nbuttons=device_get_child_node_count(dev);if(nbuttons==0)returnNULL;
@@ -126,54 +160,14 @@ static struct gpio_keys_platform_data *greturnERR_PTR(-ENOMEM);pdata->buttons=(structgpio_keys_button*)(pdata+1);-pdata->nbuttons=nbuttons;-pdata->rep=!!of_get_property(node,"autorepeat",NULL);-of_property_read_u32(node,"poll-interval",&pdata->poll_interval);+pdata->rep=!device_get_property(dev,"autorepeat",NULL);+device_property_read_u32(dev,"poll-interval",&pdata->poll_interval);-i=0;-for_each_child_of_node(node,pp){-intgpio;-enumof_gpio_flagsflags;--if(!of_find_property(pp,"gpios",NULL)){-pdata->nbuttons--;-dev_warn(dev,"Found button without gpios\n");-continue;-}--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);-returnERR_PTR(error);-}--button=&pdata->buttons[i++];--button->gpio=gpio;-button->active_low=flags&OF_GPIO_ACTIVE_LOW;--if(of_property_read_u32(pp,"linux,code",&button->code)){-dev_err(dev,"Button without keycode: 0x%x\n",-button->gpio);-returnERR_PTR(-EINVAL);-}--button->desc=of_get_property(pp,"label",NULL);--if(of_property_read_u32(pp,"linux,input-type",&button->type))-button->type=EV_KEY;--button->wakeup=!!of_get_property(pp,"gpio-key,wakeup",NULL);--if(of_property_read_u32(pp,"debounce-interval",-&button->debounce_interval))-button->debounce_interval=5;-}+error=device_for_each_child_node(dev,gpio_keys_polled_get_button,+pdata);+if(error)+returnERR_PTR(error);if(pdata->nbuttons==0)returnERR_PTR(-EINVAL);
From: Rafael J. Wysocki <hidden> Date: 2014-10-01 02:07:38
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Allow the driver to probe from ACPI namespace.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/input/keyboard/gpio_keys_polled.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
===================================================================
On Wednesday 01 October 2014 04:08:56 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Device Tree is used in many embedded systems to describe the system
configuration to the OS. It supports attaching properties or name-value
pairs to the devices it describe. With these properties one can pass
additional information to the drivers that would not be available
otherwise.
ACPI is another configuration mechanism (among other things) typically
seen, but not limited to, x86 machines. ACPI allows passing arbitrary
data from methods but there has not been mechanism equivalent to Device
Tree until the introduction of _DSD in the recent publication of the
ACPI 5.1 specification.
In order to facilitate ACPI usage in systems where Device Tree is
typically used, it would be beneficial to standardize a way to retrieve
Device Tree style properties from ACPI devices, which is what we do in
this patch.
If a given device described in ACPI namespace wants to export properties it
must implement _DSD method (Device Specific Data, introduced with ACPI 5.1)
that returns the properties in a package of packages. For example:
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {"name1", <VALUE1>},
Package () {"name2", <VALUE2>},
...
}
})
The UUID reserved for properties is daffd814-6eba-4d8c-8a91-bc9bbf4aa301
and is documented in the ACPI 5.1 companion document called "_DSD
Implementation Guide" [1], [2].
We add several helper functions that can be used to extract these
properties and convert them to different Linux data types.
The ultimate goal is that we only have one device property API that
retrieves the requested properties from Device Tree or from ACPI
transparent to the caller.
[1] http://www.uefi.org/sites/default/files/resources/_DSD-implementation-guide-toplevel.htm
[2] http://www.uefi.org/sites/default/files/resources/_DSD-device-properties-UUID.pdf
Reviewed-by: Hanjun Guo <redacted>
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Signed-off-by: Darren Hart <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
Looks good to me.
Acked-by: Arnd Bergmann <arnd@arndb.de>
On Wednesday 01 October 2014 04:10:03 Rafael J. Wysocki wrote:
From: "Rafael J. Wysocki" <redacted>
Add a uniform interface by which device drivers can request device
properties from the platform firmware by providing a property name
and the corresponding data type. The purpose of it is to help to
write portable code that won't depend on any particular platform
firmware interface.
Three general helper functions, device_get_property(),
device_read_property() and device_read_property_array() are provided.
The first one allows the raw value of a given device property to be
accessed. The remaining two allow the value of a numeric or string
property and multiple numeric or string values of one array
property to be acquired, respectively. Static inline wrappers are also
provided for the various property data types that can be passed to
device_read_property() or device_read_property_array() for extra type
checking.
These look great!
In addition to that, new generic routines are provided for retrieving
properties from device description objects in the platform firmware
in case a device driver needs/wants to access properties of a child
object of a given device object. There are cases in which there is
no struct device representation of such child objects and this
additional API is useful then. Again, three functions are provided,
device_get_child_property(), device_read_child_property(),
device_read_child_property_array(), in analogy with device_get_property(),
device_read_property() and device_read_property_array() described above,
respectively, along with static inline wrappers for all of the propery
data types that can be used. For all of them, the first argument is
a struct device pointer to the parent device object and the second
argument is a (void *) pointer to the child description provided by
the platform firmware (either ACPI or FDT).
I still have my reservations against the child accessors, and would
like to hear what other people think. Passing a void pointer rather
than struct fw_dev_node has both advantages and disadvantages, and
I won't complain about either one if enough other people on the DT
side would like to see the addition of the child functions.
Finally, device_for_each_child_node() is added for iterating over
the children of the device description object associated with a
given device.
The interface covers both ACPI and Device Trees.
This change set includes material from Mika Westerberg and Aaron Lu.
Regarding device_for_each_child_node(), the syntax is inconsistent
with what we normally use, which can probably be changed. All of the
DT for_each_* helpers are macros that are used like
struct device *dev = ...;
void *child; /* iterator */
device_for_each_child_node(dev, child) {
u32 something;
device_child_property_read_u32(dev, child, "propname", &something);
do_something(dev, something);
}
If we get a consensus on having the child interfaces, I'd rather see
them done this way than with a callback pointer, for consistency
reasons.
Arnd
On Wednesday 01 October 2014 04:10:40 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg@linux.intel.com>
We have lots of existing Device Tree enabled drivers and allocating
separate _HID for each is not feasible. Instead we allocate special _HID
"PRP0001" that means that the match should be done using Device Tree
compatible property using driver's .of_match_table instead.
If there is a need to distinguish from where the device is enumerated
(DT/ACPI) driver can check dev->of_node or ACPI_COMPATION(dev).
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
On Wed, Oct 01, 2014 at 04:20:43AM +0200, Rafael J. Wysocki wrote:
quoted hunk
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Allow the driver to probe from ACPI namespace.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
---
drivers/input/keyboard/gpio_keys_polled.c | 7 +++++++
1 file changed, 7 insertions(+)
Index: linux-pm/drivers/input/keyboard/gpio_keys_polled.c
===================================================================
o
Hmm, why do we need the generic "PRP0001" in every driver? The ACPI device
should have PRP0001 and ACPI bus should know to look into OF matching table
for such devices.
Thanks.
--
Dmitry
On Wednesday 01 October 2014 04:11:20 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg@linux.intel.com>
This document describes the data format and interfaces of ACPI device
specific properties.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Darren Hart <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
Overall looks sane, but I wonder if we should try harder to not duplicate
some of the mistakes we made in the DT bindings. Two points in particular
stick out:
+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"},
The way we name things in DT using separate "foos" and "foo-names" properties
is a bit quirky. Those are always defined on a per-subsystem level, not
a per-device level though, so it should be possible to come up with a
better representation in ACPI.
Since the device driver should never look into the "foo-names" property
itself but just pass down the name into the subsystem, the "foo" subsystem
could instead have a way to add an (optional) name for each reference.
This is something the DT syntax doesn't allow because you can't have
both a phandle and a string in a single property but I think the ACPI
packages can do it, and it wouldn't change the basic structure.
+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}
+ }
+ })
+ }
+
Similarly, the "#foo-cells" syntax is an artifact of the limitations of the
DT syntax, and I'd assume there would be a better way to encode this
in ACPI. Also, a "cell" in Open Firmware is defined as a big-endian
32-bit value, which doesn't directly correspond to something in ACPI,
and the '#' character is an artifact of the use of the Forth language
in Open Firmware, which you also don't have here.
Arnd
The general interface seems fine, but I'd be happier if you didn't
try to support all four of the possible syntaxes we have in DT.
It would be much better to have only "gpios" and not "gpio", and
the "foo-gpios" syntax should be replaced with whatever method you
use to name other subsystem specific links. For most subsystems
we now use something like "gpio-names", but unfortunately the GPIO
binding goes back to the time before we had come to that agreement.
The same applies to regulators.
This is ultimately up to the gpio maintainers though.
Arnd
--
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
On Wednesday 01 October 2014 04:15:41 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Acked-by: Alexandre Courbot <redacted>
Acked-by: Bryan Wu <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
Nice!
Acked-by: Arnd Bergmann <redacted>
--
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
Is this something you'd have to do in every driver you want to support
_PRP based probing? For the ".acpi_match_table =" reference, I think
you could actually provide a generic acpi_device_id table exported from
core code that you refer to, so each driver just does
.acpi_match_table = acpi_match_by_of_compatible,
(or whatever you want to call it).
Regarding the MODULE_DEVICE_TABLE, I suspect the above won't work the
way you are hoping for, because once you get to dozens or hundreds of
drivers doing this, each device will show up with the same string,
so udev will try to load all the modules that list "PRP0001". That
doesn't look right. With the code from patch 3, you can probably drop
the acpi MODULE_DEVICE_TABLE() entirely and get the correct behavior.
Arnd
On Wednesday 01 October 2014 04:17:46 Rafael J. Wysocki wrote:
From: Aaron Lu <redacted>
GPIO descriptors are the preferred way over legacy GPIO numbers
nowadays. Convert the driver to use GPIO descriptors internally but
still allow passing legacy GPIO numbers from platform data to support
existing platforms.
Signed-off-by: Aaron Lu <redacted>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Acked-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Linus Walleij <redacted>
Signed-off-by: Rafael J. Wysocki <redacted>
On Wednesday 01 October 2014 04:21:18 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Make use of device property API in this driver so that both DT and ACPI
based systems can use this driver.
Signed-off-by: Mika Westerberg <mika.westerberg-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Signed-off-by: Rafael J. Wysocki <redacted>
Looks good,
Acked-by: Arnd Bergmann <redacted>
--
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
On Wednesday 01 October 2014 04:22:27 Rafael J. Wysocki wrote:
From: Mika Westerberg <mika.westerberg@linux.intel.com>
Add support for matching using DT compatible string from ACPI _DSD.
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <redacted>
Is this something you'd have to do in every driver you want to support
_PRP based probing? For the ".acpi_match_table =" reference, I think
you could actually provide a generic acpi_device_id table exported from
core code that you refer to, so each driver just does
.acpi_match_table = acpi_match_by_of_compatible,
(or whatever you want to call it).
That's a good idea.
Regarding the MODULE_DEVICE_TABLE, I suspect the above won't work the
way you are hoping for, because once you get to dozens or hundreds of
drivers doing this, each device will show up with the same string,
so udev will try to load all the modules that list "PRP0001". That
doesn't look right. With the code from patch 3, you can probably drop
the acpi MODULE_DEVICE_TABLE() entirely and get the correct behavior.
It actually works like this now:
# cd /sys/bus/platform/devices/PRP0001\:00/
DRIVER=leds-gpio
MODALIAS=of:Nprp0001TacpiCgpio-leds
# cat modalias
of:Nprp0001TacpiCgpio-leds
In other words the modalias changes to be of:Nprp0001Tacpi, e.g
name=prp0001, type=acpi and then list of compatible values.
Udev then loads only module that matches the modalias so it should not
load everything listing PRP0001 in their MODULE_DEVICE_TABLE().