summaryrefslogtreecommitdiff
path: root/drivers/gpio/gpiolib-acpi.c
diff options
context:
space:
mode:
authorMika Westerberg <mika.westerberg@linux.intel.com>2016-10-21 17:21:29 +0300
committerLinus Walleij <linus.walleij@linaro.org>2016-10-24 16:33:11 +0200
commit6f7194a10bdba1588357342c6daaaeef98e0004f (patch)
tree6c68613312a5cd165f8396a48e7e9ac78adea283 /drivers/gpio/gpiolib-acpi.c
parent1208c93525f9385354588f74c3db5413bd7781dc (diff)
downloadlwn-6f7194a10bdba1588357342c6daaaeef98e0004f.tar.gz
lwn-6f7194a10bdba1588357342c6daaaeef98e0004f.zip
ACPI / gpio: Allow holes in list of GPIOs for a device
Make it possible to have an empty GPIOs in a GPIO list for device. For example a SPI master may use both GPIOs and native pins as chip selects and we need to be able to distinguish between the two. This makes it mandatory to have exactly 3 arguments for GPIOs and then converts gpiolib to use of __acpi_node_get_property_reference() instead. In addition we make acpi_gpio_package_count() to handle holes as well (this matches the DT version). Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Diffstat (limited to 'drivers/gpio/gpiolib-acpi.c')
-rw-r--r--drivers/gpio/gpiolib-acpi.c32
1 files changed, 21 insertions, 11 deletions
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c
index 58ece201b8e6..700ea6ad609b 100644
--- a/drivers/gpio/gpiolib-acpi.c
+++ b/drivers/gpio/gpiolib-acpi.c
@@ -468,7 +468,8 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
int ret;
memset(&args, 0, sizeof(args));
- ret = acpi_node_get_property_reference(fwnode, propname, index, &args);
+ ret = __acpi_node_get_property_reference(fwnode, propname, index, 3,
+ &args);
if (ret) {
struct acpi_device *adev = to_acpi_device_node(fwnode);
@@ -483,13 +484,13 @@ static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode,
* on returned args.
*/
lookup->adev = args.adev;
- if (args.nargs >= 2) {
- lookup->index = args.args[0];
- lookup->pin_index = args.args[1];
- /* 3rd argument, if present is used to specify active_low. */
- if (args.nargs >= 3)
- lookup->active_low = !!args.args[2];
- }
+ if (args.nargs != 3)
+ return -EPROTO;
+
+ lookup->index = args.args[0];
+ lookup->pin_index = args.args[1];
+ lookup->active_low = !!args.args[2];
+
return 0;
}
@@ -915,18 +916,27 @@ void acpi_gpiochip_remove(struct gpio_chip *chip)
kfree(acpi_gpio);
}
-static unsigned int acpi_gpio_package_count(const union acpi_object *obj)
+static int acpi_gpio_package_count(const union acpi_object *obj)
{
const union acpi_object *element = obj->package.elements;
const union acpi_object *end = element + obj->package.count;
unsigned int count = 0;
while (element < end) {
- if (element->type == ACPI_TYPE_LOCAL_REFERENCE)
+ switch (element->type) {
+ case ACPI_TYPE_LOCAL_REFERENCE:
+ element += 3;
+ /* Fallthrough */
+ case ACPI_TYPE_INTEGER:
+ element++;
count++;
+ break;
- element++;
+ default:
+ return -EPROTO;
+ }
}
+
return count;
}