요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
=============
GPIO Mappings
=============
This document explains how GPIOs can be assigned to given devices and functions.
All platforms can enable the GPIO library, but if the platform strictly
requires GPIO functionality to be present, it needs to select GPIOLIB from its
Kconfig. Then, how GPIOs are mapped depends on what the platform uses to
describe its hardware layout. Currently, mappings can be defined through device
tree, ACPI, and platform data.
Device Tree
-----------
GPIOs can easily be mapped to devices and functions in the device tree. The
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::
foo_device {
compatible = "acme,foo";
...
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};
Properties named <function>-gpio are also considered valid and old bindings use
it but are only supported for compatibility reasons and should not be used for
newer bindings since it has been deprecated.
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, 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_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.
The above DT example can be converted to an equivalent ACPI description
with the help of _DSD (Device Specific Data), introduced in ACPI 5.1::
Device (FOO) {
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 15 } // red
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 16 } // green
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 17 } // blue
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 1 } // power
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {
"led-gpios",
Package () {
^FOO, 0, 0, 1,
^FOO, 1, 0, 1,
^FOO, 2, 0, 1,
}
},
Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } },
}
})
}
For more information about the ACPI GPIO bindings see
Documentation/firmware-guide/acpi/gpio-properties.rst.
Software Nodes
--------------
Software nodes allow board-specific code to construct an in-memory,
device-tree-like structure using struct software_node and struct
property_entry. This structure can then be associated with a platform device,
allowing drivers to use the standard device properties API to query
configuration, just as they would on an ACPI or device tree system.
Software-node-backed GPIOs are described using the ``PROPERTY_ENTRY_GPIO()``
macro, which ties a software node representing the GPIO controller with
consumer device. It allows consumers to use regular gpiolib APIs, such as
gpiod_get(), gpiod_get_optional().
The software node representing a GPIO controller need not be attached to the
GPIO controller device. The only requirement is that the node must be
registered and its name must match the GPIO controller's label.
For example, here is how to describe a single GPIO-connected LED. This is an
alternative to using platform_data on legacy systems.
.. code-block:: c
#include <linux/property.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
/*
* 1. Define a node for the GPIO controller. Its .name must match the
* controller's label.
*/
static const struct software_node gpio_controller_node = {
.name = "gpio-foo",
};
/* 2. Define the properties for the LED device. */
static const struct property_entry led_device_props[] = {
PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
{ }
};
/* 3. Define the software node for the LED device. */
static const struct software_node led_device_swnode = {
.name = "status-led",
.properties = led_device_props,
};
/*
* 4. Register the software nodes and the platform device.
*/
const struct software_node *swnodes[] = {
&gpio_controller_node,
&led_device_swnode,
NULL
};
software_node_register_node_group(swnodes);
// Then register a platform_device for "leds-gpio" and associate
// it with &led_device_swnode via .fwnode.
For a complete guide on converting board files to use software nodes, see
Documentation/driver-api/gpio/legacy-boards.rst.
Platform Data
-------------
Finally, GPIOs can be bound to devices and functions using platform data. Board
files that desire to do so need to include the following header::
#include <linux/gpio/machine.h>
GPIOs are mapped by the means of tables of lookups, containing instances of the
gpiod_lookup structure. Two macros are defined to help declaring such mappings::
GPIO_LOOKUP(key, chip_hwnum, con_id, flags)
GPIO_LOOKUP_IDX(key, chip_hwnum, con_id, idx, flags)
where
- key is either the label of the gpiod_chip instance providing the GPIO, or
the GPIO line name
- chip_hwnum is the hardware number of the GPIO within the chip, or U16_MAX
to indicate that key is a GPIO line name
- con_id is the name of the GPIO function from the device point of view. It
can be NULL, in which case it will match any function.
- idx is the index of the GPIO within the function.
- flags is defined to specify the following properties:
* GPIO_ACTIVE_HIGH - GPIO line is active high
* GPIO_ACTIVE_LOW - GPIO line is active low
* GPIO_OPEN_DRAIN - GPIO line is set up as open drain
* GPIO_OPEN_SOURCE - GPIO line is set up as open source
* GPIO_PERSISTENT - GPIO line is persistent during
suspend/resume and maintains its value
* GPIO_TRANSITORY - GPIO line is transitory and may loose its
electrical state during suspend/resume
In the future, these flags might be extended to support more properties.
Note that:
1. GPIO line names are not guaranteed to be globally unique, so the first
match found will be used.
2. GPIO_LOOKUP() is just a shortcut to GPIO_LOOKUP_IDX() where idx = 0.
A lookup table can then be defined as follows, with an empty entry defining its
end. The 'dev_id' field of the table is the identifier of the device that will
make use of these GPIOs. It can be NULL, in which case it will be matched for
calls to gpiod_get() with a NULL device.
.. code-block:: c
struct gpiod_lookup_table gpios_table = {
.dev_id = "foo.0",
.table = {
GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW),
{ },
},
};
And the table can be added by the board code as follows::
gpiod_add_lookup_table(&gpios_table);
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, 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_OUT_HIGH);
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.
A set of functions such as gpiod_set_value() is available to work with
the new descriptor-oriented interface.
Boards using platform data can also hog GPIO lines by defining GPIO hog tables.
.. code-block:: c
struct gpiod_hog gpio_hog_table[] = {
GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH),
{ }
};
And the table can be added to the board code as follows::
gpiod_add_hogs(gpio_hog_table);
The line will be hogged as soon as the gpiochip is created or - in case the
chip was created earlier - when the hog table is registered.
Arrays of pins
--------------
In addition to requesting pins belonging to a function one by one, a device may
also request an array of pins assigned to the function. The way those pins are
mapped to the device determines if the array qualifies for fast bitmap
processing. If yes, a bitmap is passed over get/set array functions directly
between a caller and a respective .get/set_multiple() callback of a GPIO chip.
In order to qualify for fast bitmap processing, the array must meet the
following requirements:
- pin hardware number of array member 0 must also be 0,
- pin hardware numbers of consecutive array members which belong to the same
chip as member 0 does must also match their array indexes.
Otherwise fast bitmap processing path is not used in order to avoid consecutive
pins which belong to the same chip but are not in hardware order being processed
separately.
If the array applies for fast bitmap processing path, pins which belong to
different chips than member 0 does, as well as those with indexes different from
their hardware pin numbers, are excluded from the fast path, both input and
output. Moreover, open drain and open source pins are excluded from fast bitmap
output processing.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
GPIO mapping 개요
1-12문서 제목은 `GPIO Mappings`이며, GPIO를 특정 device와 function에 할당하는 방법을 설명합니다.
모든 platform에서 GPIO library를 enable할 수 있습니다. Platform이 GPIO 기능의 존재를 반드시 요구한다면 Kconfig에서 `GPIOLIB`을 select해야 합니다.
GPIO mapping 방식은 platform이 hardware layout을 기술하는 방법에 따라 달라집니다. 현재 Device Tree, ACPI, platform data로 mapping을 정의할 수 있습니다.
Platform hardware description 방식별 GPIO mapping 위치입니다.
Device Tree GPIO mapping
13-59Device Tree에서는 GPIO를 device와 function에 쉽게 mapping할 수 있습니다. 정확한 방식은 GPIO를 제공하는 controller에 따라 다르므로 해당 controller의 Device Tree binding을 확인해야 합니다.
Mapping은 consumer device node의 `<function>-gpios` property에 정의합니다. `<function>`은 driver가 `gpiod_get()`으로 요청할 function name입니다.
foo_device {
compatible = "acme,foo";
...
led-gpios = <&gpio 15 GPIO_ACTIVE_HIGH>, /* red */
<&gpio 16 GPIO_ACTIVE_HIGH>, /* green */
<&gpio 17 GPIO_ACTIVE_HIGH>; /* blue */
power-gpios = <&gpio 1 GPIO_ACTIVE_LOW>;
};
단수 suffix인 `<function>-gpio`도 구 binding과의 compatibility를 위해 지원하지만 deprecated되었으므로 새 binding에는 사용하지 않아야 합니다.
예제 property는 GPIO 15, 16, 17을 `led` function으로, GPIO 1을 `power` function으로 driver에 제공합니다.
struct gpio_desc *red, *green, *blue, *power;
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_OUT_HIGH);
LED GPIO는 active high이고 power GPIO는 active low이므로 `gpiod_is_active_low(power)`는 true입니다.
`gpiod_get()` 계열의 두 번째 parameter인 `con_id`는 Device Tree suffix `gpios` 또는 `gpio` 앞의 `<function>` prefix와 일치해야 합니다. `led-gpios`에서는 hyphen을 제외한 `led`를 사용합니다.
내부적으로 GPIO subsystem은 `con_id`와 GPIO suffix를 `snprintf(... "%s-%s", con_id, gpio_suffixes[])` 방식으로 결합해 실제 property name을 만듭니다.
Property entry와 descriptor request의 대응입니다.
ACPI GPIO mapping
60-96ACPI도 Device Tree와 비슷한 방식으로 GPIO function name을 지원합니다. 앞의 DT 예제는 ACPI 5.1에서 도입된 `_DSD` Device Specific Data를 사용해 다음과 같은 동등한 ACPI description으로 바꿀 수 있습니다.
Device (FOO) {
Name (_CRS, ResourceTemplate () {
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 15 } // red
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 16 } // green
GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 17 } // blue
GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionOutputOnly,
"\\_SB.GPI0", 0, ResourceConsumer) { 1 } // power
})
Name (_DSD, Package () {
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package () {
Package () {
"led-gpios",
Package () {
^FOO, 0, 0, 1,
^FOO, 1, 0, 1,
^FOO, 2, 0, 1,
}
},
Package () { "power-gpios", Package () { ^FOO, 3, 0, 0 } },
}
})
}
`_CRS`의 네 `GpioIo` resource는 red, green, blue, power line을 기술하고 `_DSD`의 `led-gpios`와 `power-gpios` package가 consumer function에 연결합니다.
ACPI GPIO binding의 자세한 내용은 `Documentation/firmware-guide/acpi/gpio-properties.rst`를 참조합니다.
Software node 기반 GPIO
97-161Software node를 사용하면 board-specific code가 `struct software_node`와 `struct property_entry`로 memory 안에 Device Tree와 비슷한 구조를 만들 수 있습니다. 이를 platform device에 연결하면 driver는 ACPI나 Device Tree system과 동일하게 표준 device properties API로 설정을 조회할 수 있습니다.
Software-node-backed GPIO는 `PROPERTY_ENTRY_GPIO()` macro로 기술합니다. 이 macro는 GPIO controller를 나타내는 software node와 consumer device를 연결해 consumer가 `gpiod_get()`, `gpiod_get_optional()` 같은 일반 gpiolib API를 사용하게 합니다.
GPIO controller를 나타내는 software node를 controller device 자체에 attach할 필요는 없습니다. Node가 등록되어 있고 그 name이 GPIO controller label과 일치하기만 하면 됩니다.
다음은 legacy system에서 `platform_data` 대신 GPIO-connected LED 하나를 기술하는 예제입니다.
.. code-block:: c
#include <linux/property.h>
#include <linux/gpio/machine.h>
#include <linux/gpio/property.h>
/*
* 1. Define a node for the GPIO controller. Its .name must match the
* controller's label.
*/
static const struct software_node gpio_controller_node = {
.name = "gpio-foo",
};
/* 2. Define the properties for the LED device. */
static const struct property_entry led_device_props[] = {
PROPERTY_ENTRY_STRING("label", "myboard:green:status"),
PROPERTY_ENTRY_STRING("linux,default-trigger", "heartbeat"),
PROPERTY_ENTRY_GPIO("gpios", &gpio_controller_node, 42, GPIO_ACTIVE_HIGH),
{ }
};
/* 3. Define the software node for the LED device. */
static const struct software_node led_device_swnode = {
.name = "status-led",
.properties = led_device_props,
};
/*
* 4. Register the software nodes and the platform device.
*/
const struct software_node *swnodes[] = {
&gpio_controller_node,
&led_device_swnode,
NULL
};
software_node_register_node_group(swnodes);
// Then register a platform_device for "leds-gpio" and associate
// it with &led_device_swnode via .fwnode.
예제는 controller label과 일치하는 node를 만들고 LED property에 label, default trigger, active-high GPIO 42를 넣습니다. 두 software node를 group으로 등록한 뒤 `leds-gpio` platform device의 `.fwnode`에 LED node를 연결합니다.
Board file을 software node로 변환하는 전체 지침은 `Documentation/driver-api/gpio/legacy-boards.rst`를 참조합니다.
Controller node에서 consumer platform device까지의 연결입니다.
Platform data lookup 정의
162-200마지막으로 platform data로 GPIO를 device와 function에 binding할 수 있습니다. 이를 사용하는 board file은 source path `include/linux/gpio/machine.h`의 header를 include해야 합니다.
#include <linux/gpio/machine.h>
GPIO는 `gpiod_lookup` instance로 구성된 lookup table로 mapping합니다. 두 helper macro는 다음과 같습니다.
GPIO_LOOKUP(key, chip_hwnum, con_id, flags)
GPIO_LOOKUP_IDX(key, chip_hwnum, con_id, idx, flags)
`key`는 GPIO를 제공하는 `gpiod_chip` instance label 또는 GPIO line name입니다. `chip_hwnum`은 chip 안의 hardware GPIO 번호이며, `key`가 GPIO line name임을 나타낼 때는 `U16_MAX`를 사용합니다.
`con_id`는 device 관점의 GPIO function name이며 `NULL`이면 모든 function과 일치합니다. `idx`는 해당 function 안에서 GPIO의 index입니다.
`flags`는 polarity와 electrical·power-state 특성을 지정합니다.
- `GPIO_ACTIVE_HIGH`: GPIO line이 active high
- `GPIO_ACTIVE_LOW`: GPIO line이 active low
- `GPIO_OPEN_DRAIN`: open drain으로 설정
- `GPIO_OPEN_SOURCE`: open source로 설정
- `GPIO_PERSISTENT`: suspend/resume 동안 값을 유지
- `GPIO_TRANSITORY`: suspend/resume 동안 electrical state를 잃을 수 있음
향후 flag는 더 많은 property를 지원하도록 확장될 수 있습니다. GPIO line name은 전역적으로 unique하다고 보장되지 않으므로 첫 번째 match를 사용합니다. `GPIO_LOOKUP()`은 `idx = 0`인 `GPIO_LOOKUP_IDX()`의 shortcut입니다.
Lookup macro parameter의 의미입니다.
Lookup table 등록과 사용
201-241Lookup table은 빈 entry로 끝나며 `dev_id`는 이 GPIO를 사용할 device identifier입니다. `dev_id`가 `NULL`이면 device가 `NULL`인 `gpiod_get()` call과 일치합니다.
.. code-block:: c
struct gpiod_lookup_table gpios_table = {
.dev_id = "foo.0",
.table = {
GPIO_LOOKUP_IDX("gpio.0", 15, "led", 0, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 16, "led", 1, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP_IDX("gpio.0", 17, "led", 2, GPIO_ACTIVE_HIGH),
GPIO_LOOKUP("gpio.0", 1, "power", GPIO_ACTIVE_LOW),
{ },
},
};
Board code는 다음과 같이 table을 등록합니다.
gpiod_add_lookup_table(&gpios_table);
그러면 `foo.0`을 제어하는 driver가 다음과 같이 descriptor를 얻을 수 있습니다.
struct gpio_desc *red, *green, *blue, *power;
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_OUT_HIGH);
`led` GPIO는 active high로 mapping되므로 `GPIOD_OUT_HIGH` 요청 후 실제 signal이 1이 되어 LED가 켜집니다. `power` GPIO는 active low이므로 실제 signal은 0입니다.
Legacy integer GPIO interface와 달리 active-low property는 mapping 단계에서 처리되므로 GPIO consumer에는 투명합니다. 새 descriptor-oriented interface에서는 `gpiod_set_value()` 같은 function 집합을 사용합니다.
Board mapping이 driver descriptor 요청으로 해석되는 방식입니다.
Platform data GPIO hog
242-257Platform data를 사용하는 board는 GPIO hog table을 정의해 line을 hog할 수도 있습니다.
.. code-block:: c
struct gpiod_hog gpio_hog_table[] = {
GPIO_HOG("gpio.0", 10, "foo", GPIO_ACTIVE_LOW, GPIOD_OUT_HIGH),
{ }
};
Board code는 다음과 같이 hog table을 등록합니다.
gpiod_add_hogs(gpio_hog_table);
Line은 gpiochip이 생성되는 즉시 hog됩니다. Chip이 먼저 생성된 경우에는 hog table이 등록될 때 hog됩니다.
gpiochip과 hog table 등록 순서에 따른 적용 시점입니다.
Pin array와 fast bitmap path
258-281Device는 function에 속한 pin을 하나씩 요청하는 대신 전체 pin array를 요청할 수 있습니다. Device에 mapping된 방식에 따라 array가 fast bitmap processing 대상인지 결정됩니다.
Fast path 대상이면 caller와 GPIO chip의 `.get/set_multiple()` callback 사이에서 bitmap을 직접 전달합니다.
Fast bitmap processing을 사용하려면 array member 0의 hardware pin number가 0이어야 하며, member 0과 같은 chip에 속하는 연속 member의 hardware number가 array index와 일치해야 합니다.
조건을 만족하지 않으면 같은 chip의 연속 pin이지만 hardware order가 아닌 pin을 따로 처리하는 것을 피하기 위해 fast path를 사용하지 않습니다.
Array가 fast path 대상이어도 member 0과 다른 chip에 속한 pin, index와 hardware pin number가 다른 pin은 input·output fast path에서 제외됩니다. Open drain과 open source pin도 fast bitmap output 처리에서 제외됩니다.
Fast path 포함·제외 조건을 정리했습니다.
요약과 해설
board.rst:1-281GPIO mapping은 firmware description이나 board lookup table을 descriptor-oriented consumer API에 연결합니다. Polarity는 mapping layer에서 처리되며 pin array는 hardware 순서 조건을 만족할 때 bitmap fast path를 사용합니다.