Re: [PATCH v2 5/5] gpio / ACPI: Add support for ACPI GPIO operation regions

From: Linus Walleij
Date: Thu Mar 13 2014 - 10:32:15 EST


On Mon, Mar 10, 2014 at 1:54 PM, Mika Westerberg
<mika.westerberg@xxxxxxxxxxxxxxx> wrote:

Here:

> +static acpi_status
> +acpi_gpio_adr_space_handler(u32 function, acpi_physical_address address,
> + u32 bits, u64 *value, void *handler_context,
> + void *region_context)
> +{
> + struct acpi_gpio_chip *achip = region_context;
> + struct gpio_chip *chip = achip->chip;
> + struct acpi_resource_gpio *agpio;
> + struct acpi_resource *ares;
> + acpi_status status;
> + bool pull;

Should be named pull_up, right?

> + int i;
> +
> + status = acpi_buffer_to_resource(achip->conn_info.connection,
> + achip->conn_info.length, &ares);
> + if (ACPI_FAILURE(status))
> + return status;
> +
> + if (WARN_ON(ares->type != ACPI_RESOURCE_TYPE_GPIO)) {
> + ACPI_FREE(ares);
> + return AE_BAD_PARAMETER;
> + }
> +
> + agpio = &ares->data.gpio;
> + pull = agpio->pin_config == ACPI_PIN_CONFIG_PULLUP;

So here ACPI tells us that the pin is pulled up.

And I am suspicious since this is strictly speaking pin control business
and not GPIO, and I won't let pin control stuff sneak into the GPIO
subsystem under the radar just because I'm not paying close enough
attention.

I have been told that these things are not dynamic (i.e. we only get
informed that a pin is pulled up/down, we cannot actively change the
config) is this correct?

If any sort of advanced pin control business is going to come into
ACPI a sibling driver in drivers/pinctrl/pinctrl-acpi.c needs to be
created that can select CONFIG_PINCONF properly reflect this
stuff in debugfs etc. (Maybe also give proper names on the pins
since I hear this is coming to ACPI!)

> + if (WARN_ON(agpio->io_restriction == ACPI_IO_RESTRICT_INPUT &&
> + function == ACPI_WRITE)) {
> + ACPI_FREE(ares);
> + return AE_BAD_PARAMETER;
> + }
> +
> + for (i = 0; i < agpio->pin_table_length; i++) {
> + unsigned pin = agpio->pin_table[i];
> + struct acpi_gpio_connection *conn;
> + struct gpio_desc *desc;
> + bool found;
> +
> + desc = gpiochip_get_desc(chip, pin);
> + if (IS_ERR(desc)) {
> + status = AE_ERROR;
> + goto out;
> + }
> +
> + mutex_lock(&achip->conn_lock);
> +
> + found = false;
> + list_for_each_entry(conn, &achip->conns, node) {
> + if (conn->desc == desc) {
> + found = true;
> + break;
> + }
> + }
> + if (!found) {
> + int ret;
> +
> + ret = gpiochip_request_own_desc(desc, "ACPI:OpRegion");
> + if (ret) {
> + status = AE_ERROR;
> + mutex_unlock(&achip->conn_lock);
> + goto out;
> + }
> +
> + switch (agpio->io_restriction) {
> + case ACPI_IO_RESTRICT_INPUT:
> + gpiod_direction_input(desc);
> + break;
> + case ACPI_IO_RESTRICT_OUTPUT:
> + gpiod_direction_output(desc, pull);

Can you explain why the fact that the line is pulled down affects the
default output value like this? I don't get it.

A comment in the code would be needed I think.

This looks more like a typical piece of code for open collector/drain
(which is already handled by gpiolib) not pull up/down.

> + break;
> + default:
> + /*
> + * Assume that the BIOS has configured the
> + * direction and pull accordingly.
> + */
> + break;
> + }
> +
> + conn = kzalloc(sizeof(*conn), GFP_KERNEL);
> + if (!conn) {
> + status = AE_NO_MEMORY;
> + mutex_unlock(&achip->conn_lock);
> + goto out;
> + }
> +
> + conn->desc = desc;
> +
> + list_add_tail(&conn->node, &achip->conns);
> + }
> +
> + mutex_unlock(&achip->conn_lock);
> +
> +
> + if (function == ACPI_WRITE)
> + gpiod_set_raw_value(desc, !!((1 << i) & *value));

What is this? How can the expression !!((1 << i) possibly evaluate to
anything else than "true"? I don't get it. Just (desc, *value) seem more
apropriate.

Yours,
Linus Walleij
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/