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>
This commit is contained in:
Родитель
1208c93525
Коммит
6f7194a10b
|
@ -51,6 +51,21 @@ it to 1 marks the GPIO as active low.
|
|||
In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
|
||||
resource, second pin in that resource with the GPIO number of 31.
|
||||
|
||||
It is possible to leave holes in the array of GPIOs. This is useful in
|
||||
cases like with SPI host controllers where some chip selects may be
|
||||
implemented as GPIOs and some as native signals. For example a SPI host
|
||||
controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
|
||||
native:
|
||||
|
||||
Package () {
|
||||
"cs-gpios",
|
||||
Package () {
|
||||
^GPIO, 19, 0, 0, // chip select 0: GPIO
|
||||
0, // chip select 1: native signal
|
||||
^GPIO, 20, 0, 0, // chip select 2: GPIO
|
||||
}
|
||||
}
|
||||
|
||||
ACPI GPIO Mappings Provided by Drivers
|
||||
--------------------------------------
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче