Skip to content

Commit

Permalink
Merge tag 'gpio-v4.3-2' of git://git.kernel.org/pub/scm/linux/kernel/…
Browse files Browse the repository at this point in the history
…git/linusw/linux-gpio

Pull GPIO fixes from Linus Walleij:
 "This is the first round of GPIO fixes for v4.3.  Quite a lot of
  patches, but the influx of new stuff in the merge window was equally
  big, so I'm not surprised.

   - Return value checks and thus nicer errorpath for two drivers.

   - Make GPIO_RCAR arch neutral.

   - Propagate errors from GPIO chip ->get() vtable call.  It turned out
     these can actually fail sometimes, especially on slowpath
     controllers doing I2C traffic and similar.

   - Update documentation to be in sync with the massive changes in the
     v4.3 merge window, phew.

   - Handle deferred probe properly in the OMAP driver.

   - Get rid of surplus MODULE_ALIAS() from sx150x"

* tag 'gpio-v4.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-gpio:
  gpio: omap: Fix GPIO numbering for deferred probe
  Documentation: gpio: Explain that <function>-gpio is also supported
  gpio: omap: Fix gpiochip_add() handling for deferred probe
  gpio: sx150x: Remove unnecessary MODULE_ALIAS()
  Documentation: gpio: board: describe the con_id parameter
  Documentation: gpio: board: add flags parameter to gpiod_get*() functions
  gpio: Propagate errors from chip->get()
  gpio: rcar: GPIO_RCAR doesn't relate to ARM
  gpio: mxs: need to check return value of irq_alloc_generic_chip
  gpio: mxc: need to check return value of irq_alloc_generic_chip
  • Loading branch information
torvalds committed Sep 16, 2015
2 parents aa57e0b + 46d4f7c commit d1291eb
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 30 deletions.
40 changes: 25 additions & 15 deletions Documentation/gpio/board.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ exact way to do it depends on the GPIO controller providing the GPIOs, see the
device tree bindings for your controller.

GPIOs mappings are defined in the consumer device's node, in a property named
<function>-gpios, where <function> is the function the driver will request
through gpiod_get(). For example:
either <function>-gpios or <function>-gpio, where <function> is the function
the driver will request through gpiod_get(). For example:

foo_device {
compatible = "acme,foo";
Expand All @@ -31,23 +31,32 @@ through gpiod_get(). For example:
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */

power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
power-gpio = <&gpio 1 GPIO_ACTIVE_LOW>;
};

This property will make GPIOs 15, 16 and 17 available to the driver under the
"led" function, and GPIO 1 as the "power" GPIO:

struct gpio_desc *red, *green, *blue, *power;

red = gpiod_get_index(dev, "led", 0);
green = gpiod_get_index(dev, "led", 1);
blue = gpiod_get_index(dev, "led", 2);
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);

power = gpiod_get(dev, "power");
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);

The led GPIOs will be active-high, while the power GPIO will be active-low (i.e.
gpiod_is_active_low(power) will be true).

The second parameter of the gpiod_get() functions, the con_id string, has to be
the <function>-prefix of the GPIO suffixes ("gpios" or "gpio", automatically
looked up by the gpiod functions internally) used in the device tree. With above
"led-gpios" example, use the prefix without the "-" as con_id parameter: "led".

Internally, the GPIO subsystem prefixes the GPIO suffix ("gpios" or "gpio")
with the string passed in con_id to get the resulting string
(snprintf(... "%s-%s", con_id, gpio_suffixes[]).

ACPI
----
ACPI also supports function names for GPIOs in a similar fashion to DT.
Expand Down Expand Up @@ -142,13 +151,14 @@ The driver controlling "foo.0" will then be able to obtain its GPIOs as follows:

struct gpio_desc *red, *green, *blue, *power;

red = gpiod_get_index(dev, "led", 0);
green = gpiod_get_index(dev, "led", 1);
blue = gpiod_get_index(dev, "led", 2);
red = gpiod_get_index(dev, "led", 0, GPIOD_OUT_HIGH);
green = gpiod_get_index(dev, "led", 1, GPIOD_OUT_HIGH);
blue = gpiod_get_index(dev, "led", 2, GPIOD_OUT_HIGH);

power = gpiod_get(dev, "power");
gpiod_direction_output(power, 1);
power = gpiod_get(dev, "power", GPIOD_OUT_HIGH);

Since the "power" GPIO is mapped as active-low, its actual signal will be 0
after this code. Contrary to the legacy integer GPIO interface, the active-low
property is handled during mapping and is thus transparent to GPIO consumers.
Since the "led" GPIOs are mapped as active-high, this example will switch their
signals to 1, i.e. enabling the LEDs. And for the "power" GPIO, which is mapped
as active-low, its actual signal will be 0 after this code. Contrary to the legacy
integer GPIO interface, the active-low property is handled during mapping and is
thus transparent to GPIO consumers.
3 changes: 3 additions & 0 deletions Documentation/gpio/consumer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ device that displays digits), an additional index argument can be specified:
const char *con_id, unsigned int idx,
enum gpiod_flags flags)

For a more detailed description of the con_id parameter in the DeviceTree case
see Documentation/gpio/board.txt

The flags parameter is used to optionally specify a direction and initial value
for the GPIO. Values can be:

Expand Down
2 changes: 1 addition & 1 deletion drivers/gpio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ config GPIO_PXA

config GPIO_RCAR
tristate "Renesas R-Car GPIO"
depends on ARM && (ARCH_SHMOBILE || COMPILE_TEST)
depends on ARCH_SHMOBILE || COMPILE_TEST
select GPIOLIB_IRQCHIP
help
Say yes here to support GPIO on Renesas R-Car SoCs.
Expand Down
12 changes: 10 additions & 2 deletions drivers/gpio/gpio-mxc.c
Original file line number Diff line number Diff line change
Expand Up @@ -339,13 +339,15 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
return 0;
}

static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
static int mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;

gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base,
port->base, handle_level_irq);
if (!gc)
return -ENOMEM;
gc->private = port;

ct = gc->chip_types;
Expand All @@ -360,6 +362,8 @@ static void mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)

irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
IRQ_NOREQUEST, 0);

return 0;
}

static void mxc_gpio_get_hw(struct platform_device *pdev)
Expand Down Expand Up @@ -477,12 +481,16 @@ static int mxc_gpio_probe(struct platform_device *pdev)
}

/* gpio-mxc can be a generic irq chip */
mxc_gpio_init_gc(port, irq_base);
err = mxc_gpio_init_gc(port, irq_base);
if (err < 0)
goto out_irqdomain_remove;

list_add_tail(&port->node, &mxc_gpio_ports);

return 0;

out_irqdomain_remove:
irq_domain_remove(port->domain);
out_irqdesc_free:
irq_free_descs(irq_base, 32);
out_gpiochip_remove:
Expand Down
13 changes: 11 additions & 2 deletions drivers/gpio/gpio-mxs.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,13 +196,16 @@ static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
return 0;
}

static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
static int __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)
{
struct irq_chip_generic *gc;
struct irq_chip_type *ct;

gc = irq_alloc_generic_chip("gpio-mxs", 1, irq_base,
port->base, handle_level_irq);
if (!gc)
return -ENOMEM;

gc->private = port;

ct = gc->chip_types;
Expand All @@ -216,6 +219,8 @@ static void __init mxs_gpio_init_gc(struct mxs_gpio_port *port, int irq_base)

irq_setup_generic_chip(gc, IRQ_MSK(32), IRQ_GC_INIT_NESTED_LOCK,
IRQ_NOREQUEST, 0);

return 0;
}

static int mxs_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
Expand Down Expand Up @@ -317,7 +322,9 @@ static int mxs_gpio_probe(struct platform_device *pdev)
}

/* gpio-mxs can be a generic irq chip */
mxs_gpio_init_gc(port, irq_base);
err = mxs_gpio_init_gc(port, irq_base);
if (err < 0)
goto out_irqdomain_remove;

/* setup one handler for each entry */
irq_set_chained_handler_and_data(port->irq, mxs_gpio_irq_handler,
Expand All @@ -343,6 +350,8 @@ static int mxs_gpio_probe(struct platform_device *pdev)

out_bgpio_remove:
bgpio_remove(&port->bgc);
out_irqdomain_remove:
irq_domain_remove(port->domain);
out_irqdesc_free:
irq_free_descs(irq_base, 32);
return err;
Expand Down
9 changes: 7 additions & 2 deletions drivers/gpio/gpio-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,7 +1098,6 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
} else {
bank->chip.label = "gpio";
bank->chip.base = gpio;
gpio += bank->width;
}
bank->chip.ngpio = bank->width;

Expand All @@ -1108,6 +1107,9 @@ static int omap_gpio_chip_init(struct gpio_bank *bank, struct irq_chip *irqc)
return ret;
}

if (!bank->is_mpuio)
gpio += bank->width;

#ifdef CONFIG_ARCH_OMAP1
/*
* REVISIT: Once we have OMAP1 supporting SPARSE_IRQ, we can drop
Expand Down Expand Up @@ -1253,8 +1255,11 @@ static int omap_gpio_probe(struct platform_device *pdev)
omap_gpio_mod_init(bank);

ret = omap_gpio_chip_init(bank, irqc);
if (ret)
if (ret) {
pm_runtime_put_sync(bank->dev);
pm_runtime_disable(bank->dev);
return ret;
}

omap_gpio_show_rev(bank);

Expand Down
1 change: 0 additions & 1 deletion drivers/gpio/gpio-sx150x.c
Original file line number Diff line number Diff line change
Expand Up @@ -706,4 +706,3 @@ module_exit(sx150x_exit);
MODULE_AUTHOR("Gregory Bean <[email protected]>");
MODULE_DESCRIPTION("Driver for Semtech SX150X I2C GPIO Expanders");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("i2c:sx150x");
21 changes: 14 additions & 7 deletions drivers/gpio/gpiolib.c
Original file line number Diff line number Diff line change
Expand Up @@ -1174,15 +1174,16 @@ EXPORT_SYMBOL_GPL(gpiod_is_active_low);
* that the GPIO was actually requested.
*/

static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
static int _gpiod_get_raw_value(const struct gpio_desc *desc)
{
struct gpio_chip *chip;
bool value;
int offset;
int value;

chip = desc->chip;
offset = gpio_chip_hwgpio(desc);
value = chip->get ? chip->get(chip, offset) : false;
value = chip->get ? chip->get(chip, offset) : -EIO;
value = value < 0 ? value : !!value;
trace_gpio_value(desc_to_gpio(desc), 1, value);
return value;
}
Expand All @@ -1192,7 +1193,7 @@ static bool _gpiod_get_raw_value(const struct gpio_desc *desc)
* @desc: gpio whose value will be returned
*
* Return the GPIO's raw value, i.e. the value of the physical line disregarding
* its ACTIVE_LOW status.
* its ACTIVE_LOW status, or negative errno on failure.
*
* This function should be called from contexts where we cannot sleep, and will
* complain if the GPIO chip functions potentially sleep.
Expand All @@ -1212,7 +1213,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value);
* @desc: gpio whose value will be returned
*
* Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
* account.
* account, or negative errno on failure.
*
* This function should be called from contexts where we cannot sleep, and will
* complain if the GPIO chip functions potentially sleep.
Expand All @@ -1226,6 +1227,9 @@ int gpiod_get_value(const struct gpio_desc *desc)
WARN_ON(desc->chip->can_sleep);

value = _gpiod_get_raw_value(desc);
if (value < 0)
return value;

if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;

Expand Down Expand Up @@ -1548,7 +1552,7 @@ EXPORT_SYMBOL_GPL(gpiochip_unlock_as_irq);
* @desc: gpio whose value will be returned
*
* Return the GPIO's raw value, i.e. the value of the physical line disregarding
* its ACTIVE_LOW status.
* its ACTIVE_LOW status, or negative errno on failure.
*
* This function is to be called from contexts that can sleep.
*/
Expand All @@ -1566,7 +1570,7 @@ EXPORT_SYMBOL_GPL(gpiod_get_raw_value_cansleep);
* @desc: gpio whose value will be returned
*
* Return the GPIO's logical value, i.e. taking the ACTIVE_LOW status into
* account.
* account, or negative errno on failure.
*
* This function is to be called from contexts that can sleep.
*/
Expand All @@ -1579,6 +1583,9 @@ int gpiod_get_value_cansleep(const struct gpio_desc *desc)
return 0;

value = _gpiod_get_raw_value(desc);
if (value < 0)
return value;

if (test_bit(FLAG_ACTIVE_LOW, &desc->flags))
value = !value;

Expand Down

0 comments on commit d1291eb

Please sign in to comment.