GPIO AggregatorÂķ
The GPIO Aggregator provides a mechanism to aggregate GPIOs, and expose them as a new gpio_chip. This supports the following use cases.
Aggregating GPIOs using SysfsÂķ
GPIO controllers are exported to userspace using /dev/gpiochip* character devices. Access control to these devices is provided by standard UNIX file system permissions, on an all-or-nothing basis: either a GPIO controller is accessible for a user, or it is not.
The GPIO Aggregator provides access control for a set of one or more GPIOs, by aggregating them into a new gpio_chip, which can be assigned to a group or user using standard UNIX file ownership and permissions. Furthermore, this simplifies and hardens exporting GPIOs to a virtual machine, as the VM can just grab the full GPIO controller, and no longer needs to care about which GPIOs to grab and which not, reducing the attack surface.
Aggregated GPIO controllers are instantiated and destroyed by writing to write-only attribute files in sysfs.
/sys/bus/platform/drivers/gpio-aggregator/
- ânew_deviceâ ...
Userspace may ask the kernel to instantiate an aggregated GPIO controller by writing a string describing the GPIOs to aggregate to the ânew_deviceâ file, using the format
[<gpioA>] [<gpiochipB> <offsets>] ...Where:
- â<gpioA>â ...
is a GPIO line name,
- â<gpiochipB>â ...
is a GPIO chip label, and
- â<offsets>â ...
is a comma-separated list of GPIO offsets and/or GPIO offset ranges denoted by dashes.
Example: Instantiate a new GPIO aggregator by aggregating GPIO line 19 of âe6052000.gpioâ and GPIO lines 20-21 of âe6050000.gpioâ into a new gpio_chip:
$ echo 'e6052000.gpio 19 e6050000.gpio 20-21' > new_device- âdelete_deviceâ ...
Userspace may ask the kernel to destroy an aggregated GPIO controller after use by writing its device name to the âdelete_deviceâ file.
Example: Destroy the previously-created aggregated GPIO controller, assumed to be âgpio-aggregator.0â:
$ echo gpio-aggregator.0 > delete_device
Aggregating GPIOs using ConfigfsÂķ
Group: /config/gpio-aggregator
This is the root directory of the gpio-aggregator configfs tree.
Group: /config/gpio-aggregator/<example-name>
This directory represents a GPIO aggregator device. You can assign any name to
<example-name>(e.g.agg0), except names starting with_sysfsprefix, which are reserved for auto-generated configfs entries corresponding to devices created via Sysfs.
Attribute: /config/gpio-aggregator/<example-name>/live
The
liveattribute allows to trigger the actual creation of the device once itâs fully configured. Accepted values are:
1,yes,true: enable the virtual device
0,no,false: disable the virtual device
Attribute: /config/gpio-aggregator/<example-name>/dev_name
The read-only
dev_nameattribute exposes the name of the device as it will appear in the system on the platform bus (e.g.gpio-aggregator.0). This is useful for identifying a character device for the newly created aggregator. If itâsgpio-aggregator.0,/sys/devices/platform/gpio-aggregator.0/gpiochipXpath tells you that the GPIO device id isX.
You must create subdirectories for each virtual line you want to
instantiate, named exactly as line0, line1, ..., lineY, when
you want to instantiate Y+1 (Y >= 0) lines. Configure all lines before
activating the device by setting live to 1.
Group: /config/gpio-aggregator/<example-name>/<lineY>/
This directory represents a GPIO line to include in the aggregator.
Attribute: /config/gpio-aggregator/<example-name>/<lineY>/key
Attribute: /config/gpio-aggregator/<example-name>/<lineY>/offset
The default values after creating the
<lineY>directory are:
key: <empty>
offset: -1
keymust always be explicitly configured, whileoffsetdepends. Two configuration patterns exist for each<lineY>:(a). For lookup by GPIO line name:
Set
keyto the line name.Ensure
offsetremains -1 (the default).(b). For lookup by GPIO chip name and the line offset within the chip:
Set
keyto the chip name.Set
offsetto the line offset (0 <=offset< 65535).
Attribute: /config/gpio-aggregator/<example-name>/<lineY>/name
The
nameattribute sets a custom name for lineY. If left unset, the line will remain unnamed.
Once the configuration is done, the 'live' attribute must be set to 1
in order to instantiate the aggregator device. It can be set back to 0 to
destroy the virtual device. The module will synchronously wait for the new
aggregator device to be successfully probed and if this doesnât happen, writing
to 'live' will result in an error. This is a different behaviour from the
case when you create it using sysfs new_device interface.
Note
For aggregators created via Sysfs, the configfs entries are
auto-generated and appear as /config/gpio-aggregator/_sysfs.<N>/. You
cannot add or remove line directories with mkdir(2)/rmdir(2). To modify
lines, you must use the âdelete_deviceâ interface to tear down the
existing device and reconfigure it from scratch. However, you can still
toggle the aggregator with the live attribute and adjust the
key, offset, and name attributes for each line when live
is set to 0 by hand (i.e. itâs not waiting for deferred probe).
Sample configuration commandsÂķ
# Create a directory for an aggregator device
$ mkdir /sys/kernel/config/gpio-aggregator/agg0
# Configure each line
$ mkdir /sys/kernel/config/gpio-aggregator/agg0/line0
$ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line0/key
$ echo 6 > /sys/kernel/config/gpio-aggregator/agg0/line0/offset
$ echo test0 > /sys/kernel/config/gpio-aggregator/agg0/line0/name
$ mkdir /sys/kernel/config/gpio-aggregator/agg0/line1
$ echo gpiochip0 > /sys/kernel/config/gpio-aggregator/agg0/line1/key
$ echo 7 > /sys/kernel/config/gpio-aggregator/agg0/line1/offset
$ echo test1 > /sys/kernel/config/gpio-aggregator/agg0/line1/name
# Activate the aggregator device
$ echo 1 > /sys/kernel/config/gpio-aggregator/agg0/live
Generic GPIO DriverÂķ
The GPIO Aggregator can also be used as a generic driver for a simple GPIO-operated device described in DT, without a dedicated in-kernel driver. This is useful in industrial control, and is not unlike e.g. spidev, which allows the user to communicate with an SPI device from userspace.
Binding a device to the GPIO Aggregator is performed either by modifying the gpio-aggregator driver, or by writing to the âdriver_overrideâ file in Sysfs.
Example: If âdoorâ is a GPIO-operated device described in DT, using its own compatible value:
door {
compatible = "myvendor,mydoor";
gpios = <&gpio2 19 GPIO_ACTIVE_HIGH>,
<&gpio2 20 GPIO_ACTIVE_LOW>;
gpio-line-names = "open", "lock";
};
it can be bound to the GPIO Aggregator by either:
Adding its compatible value to
gpio_aggregator_dt_ids[],Binding manually using âdriver_overrideâ:
$ echo gpio-aggregator > /sys/bus/platform/devices/door/driver_override
$ echo door > /sys/bus/platform/drivers/gpio-aggregator/bind
After that, a new gpiochip âdoorâ has been created:
$ gpioinfo door
gpiochip12 - 2 lines:
line 0: "open" unused input active-high
line 1: "lock" unused input active-high