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