lkml.org 
[lkml]   [2014]   [Sep]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 04/15] ACPI: Document ACPI device specific properties
    Date
    From: Mika Westerberg <mika.westerberg@linux.intel.com>

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

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

    diff --git a/Documentation/acpi/properties.txt b/Documentation/acpi/properties.txt
    new file mode 100644
    index 0000000..13a93c5
    --- /dev/null
    +++ b/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.
    --
    1.9.3

    --G44BJl3Aq1QbV/QL--




    \
     
     \ /
      Last update: 2014-10-01 04:41    [W:3.755 / U:0.244 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site