xref: /openbmc/linux/Documentation/admin-guide/gpio/gpio-aggregator.rst (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1*ce7a2f77SGeert Uytterhoeven.. SPDX-License-Identifier: GPL-2.0-only
2*ce7a2f77SGeert Uytterhoeven
3*ce7a2f77SGeert UytterhoevenGPIO Aggregator
4*ce7a2f77SGeert Uytterhoeven===============
5*ce7a2f77SGeert Uytterhoeven
6*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as
7*ce7a2f77SGeert Uytterhoevena new gpio_chip.  This supports the following use cases.
8*ce7a2f77SGeert Uytterhoeven
9*ce7a2f77SGeert Uytterhoeven
10*ce7a2f77SGeert UytterhoevenAggregating GPIOs using Sysfs
11*ce7a2f77SGeert Uytterhoeven-----------------------------
12*ce7a2f77SGeert Uytterhoeven
13*ce7a2f77SGeert UytterhoevenGPIO controllers are exported to userspace using /dev/gpiochip* character
14*ce7a2f77SGeert Uytterhoevendevices.  Access control to these devices is provided by standard UNIX file
15*ce7a2f77SGeert Uytterhoevensystem permissions, on an all-or-nothing basis: either a GPIO controller is
16*ce7a2f77SGeert Uytterhoevenaccessible for a user, or it is not.
17*ce7a2f77SGeert Uytterhoeven
18*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator provides access control for a set of one or more GPIOs, by
19*ce7a2f77SGeert Uytterhoevenaggregating them into a new gpio_chip, which can be assigned to a group or user
20*ce7a2f77SGeert Uytterhoevenusing standard UNIX file ownership and permissions.  Furthermore, this
21*ce7a2f77SGeert Uytterhoevensimplifies and hardens exporting GPIOs to a virtual machine, as the VM can just
22*ce7a2f77SGeert Uytterhoevengrab the full GPIO controller, and no longer needs to care about which GPIOs to
23*ce7a2f77SGeert Uytterhoevengrab and which not, reducing the attack surface.
24*ce7a2f77SGeert Uytterhoeven
25*ce7a2f77SGeert UytterhoevenAggregated GPIO controllers are instantiated and destroyed by writing to
26*ce7a2f77SGeert Uytterhoevenwrite-only attribute files in sysfs.
27*ce7a2f77SGeert Uytterhoeven
28*ce7a2f77SGeert Uytterhoeven    /sys/bus/platform/drivers/gpio-aggregator/
29*ce7a2f77SGeert Uytterhoeven
30*ce7a2f77SGeert Uytterhoeven	"new_device" ...
31*ce7a2f77SGeert Uytterhoeven		Userspace may ask the kernel to instantiate an aggregated GPIO
32*ce7a2f77SGeert Uytterhoeven		controller by writing a string describing the GPIOs to
33*ce7a2f77SGeert Uytterhoeven		aggregate to the "new_device" file, using the format
34*ce7a2f77SGeert Uytterhoeven
35*ce7a2f77SGeert Uytterhoeven		.. code-block:: none
36*ce7a2f77SGeert Uytterhoeven
37*ce7a2f77SGeert Uytterhoeven		    [<gpioA>] [<gpiochipB> <offsets>] ...
38*ce7a2f77SGeert Uytterhoeven
39*ce7a2f77SGeert Uytterhoeven		Where:
40*ce7a2f77SGeert Uytterhoeven
41*ce7a2f77SGeert Uytterhoeven		    "<gpioA>" ...
42*ce7a2f77SGeert Uytterhoeven			    is a GPIO line name,
43*ce7a2f77SGeert Uytterhoeven
44*ce7a2f77SGeert Uytterhoeven		    "<gpiochipB>" ...
45*ce7a2f77SGeert Uytterhoeven			    is a GPIO chip label, and
46*ce7a2f77SGeert Uytterhoeven
47*ce7a2f77SGeert Uytterhoeven		    "<offsets>" ...
48*ce7a2f77SGeert Uytterhoeven			    is a comma-separated list of GPIO offsets and/or
49*ce7a2f77SGeert Uytterhoeven			    GPIO offset ranges denoted by dashes.
50*ce7a2f77SGeert Uytterhoeven
51*ce7a2f77SGeert Uytterhoeven		Example: Instantiate a new GPIO aggregator by aggregating GPIO
52*ce7a2f77SGeert Uytterhoeven		line 19 of "e6052000.gpio" and GPIO lines 20-21 of
53*ce7a2f77SGeert Uytterhoeven		"e6050000.gpio" into a new gpio_chip:
54*ce7a2f77SGeert Uytterhoeven
55*ce7a2f77SGeert Uytterhoeven		.. code-block:: sh
56*ce7a2f77SGeert Uytterhoeven
57*ce7a2f77SGeert Uytterhoeven		    $ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device
58*ce7a2f77SGeert Uytterhoeven
59*ce7a2f77SGeert Uytterhoeven	"delete_device" ...
60*ce7a2f77SGeert Uytterhoeven		Userspace may ask the kernel to destroy an aggregated GPIO
61*ce7a2f77SGeert Uytterhoeven		controller after use by writing its device name to the
62*ce7a2f77SGeert Uytterhoeven		"delete_device" file.
63*ce7a2f77SGeert Uytterhoeven
64*ce7a2f77SGeert Uytterhoeven		Example: Destroy the previously-created aggregated GPIO
65*ce7a2f77SGeert Uytterhoeven		controller, assumed to be "gpio-aggregator.0":
66*ce7a2f77SGeert Uytterhoeven
67*ce7a2f77SGeert Uytterhoeven		.. code-block:: sh
68*ce7a2f77SGeert Uytterhoeven
69*ce7a2f77SGeert Uytterhoeven		    $ echo gpio-aggregator.0 > delete_device
70*ce7a2f77SGeert Uytterhoeven
71*ce7a2f77SGeert Uytterhoeven
72*ce7a2f77SGeert UytterhoevenGeneric GPIO Driver
73*ce7a2f77SGeert Uytterhoeven-------------------
74*ce7a2f77SGeert Uytterhoeven
75*ce7a2f77SGeert UytterhoevenThe GPIO Aggregator can also be used as a generic driver for a simple
76*ce7a2f77SGeert UytterhoevenGPIO-operated device described in DT, without a dedicated in-kernel driver.
77*ce7a2f77SGeert UytterhoevenThis is useful in industrial control, and is not unlike e.g. spidev, which
78*ce7a2f77SGeert Uytterhoevenallows the user to communicate with an SPI device from userspace.
79*ce7a2f77SGeert Uytterhoeven
80*ce7a2f77SGeert UytterhoevenBinding a device to the GPIO Aggregator is performed either by modifying the
81*ce7a2f77SGeert Uytterhoevengpio-aggregator driver, or by writing to the "driver_override" file in Sysfs.
82*ce7a2f77SGeert Uytterhoeven
83*ce7a2f77SGeert UytterhoevenExample: If "door" is a GPIO-operated device described in DT, using its own
84*ce7a2f77SGeert Uytterhoevencompatible value::
85*ce7a2f77SGeert Uytterhoeven
86*ce7a2f77SGeert Uytterhoeven	door {
87*ce7a2f77SGeert Uytterhoeven		compatible = "myvendor,mydoor";
88*ce7a2f77SGeert Uytterhoeven
89*ce7a2f77SGeert Uytterhoeven		gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>,
90*ce7a2f77SGeert Uytterhoeven			<&gpio2 20 GPIO_ACTIVE_LOW>;
91*ce7a2f77SGeert Uytterhoeven		gpio-line-names = "open", "lock";
92*ce7a2f77SGeert Uytterhoeven	};
93*ce7a2f77SGeert Uytterhoeven
94*ce7a2f77SGeert Uytterhoevenit can be bound to the GPIO Aggregator by either:
95*ce7a2f77SGeert Uytterhoeven
96*ce7a2f77SGeert Uytterhoeven1. Adding its compatible value to ``gpio_aggregator_dt_ids[]``,
97*ce7a2f77SGeert Uytterhoeven2. Binding manually using "driver_override":
98*ce7a2f77SGeert Uytterhoeven
99*ce7a2f77SGeert Uytterhoeven.. code-block:: sh
100*ce7a2f77SGeert Uytterhoeven
101*ce7a2f77SGeert Uytterhoeven    $ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override
102*ce7a2f77SGeert Uytterhoeven    $ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind
103*ce7a2f77SGeert Uytterhoeven
104*ce7a2f77SGeert UytterhoevenAfter that, a new gpiochip "door" has been created:
105*ce7a2f77SGeert Uytterhoeven
106*ce7a2f77SGeert Uytterhoeven.. code-block:: sh
107*ce7a2f77SGeert Uytterhoeven
108*ce7a2f77SGeert Uytterhoeven    $ gpioinfo door
109*ce7a2f77SGeert Uytterhoeven    gpiochip12 - 2 lines:
110*ce7a2f77SGeert Uytterhoeven	    line   0:       "open"       unused   input  active-high
111*ce7a2f77SGeert Uytterhoeven	    line   1:       "lock"       unused   input  active-high
112