Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d1291ebd authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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
parents aa57e0b2 46d4f7c2
Loading
Loading
Loading
Loading
+25 −15
Original line number Diff line number Diff line
@@ -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";
@@ -31,7 +31,7 @@ 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
@@ -39,15 +39,24 @@ This property will make GPIOs 15, 16 and 17 available to the driver under the

	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.
@@ -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 −0
Original line number Diff line number Diff line
@@ -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:

+1 −1
Original line number Diff line number Diff line
@@ -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.
+10 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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:
+11 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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)
@@ -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,
@@ -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;
Loading