← Documents Documentation/firmware-guide/acpi/gpio-properties.rst GitHub 원문 ↗

Linux 6.18.37 · Firmware

_DSD Device Properties Related to GPIO

ACPI _DSD GPIO 이름·polarity·hog·line-name·driver mapping·_CRS fallback 규칙의 전문 번역입니다.

Source pathDocumentation/firmware-guide/acpi/gpio-properties.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

gpio-properties.rst:1-336

ACPI `_DSD` GPIO property는 `ref, index, pin, active_low` tuple로 `_CRS`의 `GpioIo()` 또는 `GpioInt()` resource에 이름을 붙인다. Resource index와 resource 내부 pin index는 모두 0부터 시작하며 `GpioInt()`의 active_low 값은 반드시 0이다.

Linux는 `GpioIo()`의 초기 output state를 pull bias와 polarity에서 유도한다. GPIO 배열에는 native signal을 나타내는 빈 slot을 둘 수 있지만, SPI chip-select polarity는 중복 부정을 피하도록 Active High로 표현해야 한다.

GPIO controller는 hog와 `gpio-line-names`를 제공할 수 있다. Line name 배열은 line 0부터 연속하며 빈 이름은 허용되고 전체 line보다 짧아도 되지만, 같은 controller 안의 이름은 고유해야 한다.

Firmware에 `_DSD`가 없으면 특정 ACPI ID를 아는 driver가 `struct acpi_gpio_mapping`을 등록할 수 있다. 이름 mapping 없이 non-NULL connection ID를 요청하면 `ERR_PTR(-ENOENT)`가 반환되며, `NULL` ID는 `_CRS` 직접 검색을 명시한다.

ACPI GPIO property 검토 순서
_CRS GPIO resource·controller·pin 순서 확인_DSD ref·index·pin·active_low 대조Bias·polarity 기반 초기 state 검증Hog·line-name 배열 위치와 고유성 검사_DSD가 없으면 특정 device용 driver mapping 등록Non-NULL connection ID와 NULL fallback 구분

Firmware와 driver 양쪽에서 GPIO 의미를 보존하는 점검 절차다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ======================================
4 _DSD Device Properties Related to GPIO
5 ======================================
6
7 With the release of ACPI 5.1, the _DSD configuration object finally
8 allows names to be given to GPIOs (and other things as well) returned
9 by _CRS. Previously we were only able to use an integer index to find
10 the corresponding GPIO, which is pretty error prone (it depends on
11 the _CRS output ordering, for example).
12
13 With _DSD we can now query GPIOs using a name instead of an integer
14 index, like the ASL example below shows::
15
16 // Bluetooth device with reset and shutdown GPIOs
17 Device (BTH)
18 {
19 Name (_HID, ...)
20
21 Name (_CRS, ResourceTemplate ()
22 {
23 GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
24 "\\_SB.GPO0", 0, ResourceConsumer) { 15 }
25 GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
26 "\\_SB.GPO0", 0, ResourceConsumer) { 27, 31 }
27 })
28
29 Name (_DSD, Package ()
30 {
31 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
32 Package ()
33 {
34 Package () { "reset-gpios", Package () { ^BTH, 1, 1, 0 } },
35 Package () { "shutdown-gpios", Package () { ^BTH, 0, 0, 0 } },
36 }
37 })
38 }
39
40 The format of the supported GPIO property is::
41
42 Package () { "name", Package () { ref, index, pin, active_low }}
43
44 ref
45 The device that has _CRS containing GpioIo()/GpioInt() resources,
46 typically this is the device itself (BTH in our case).
47 index
48 Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
49 pin
50 Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
51 active_low
52 If 1, the GPIO is marked as active-low.
53
54 Since ACPI GpioIo() resource does not have a field saying whether it is
55 active-low or active-high, the "active_low" argument can be used here.
56 Setting it to 1 marks the GPIO as active-low.
57
58 Note, active_low in _DSD does not make sense for GpioInt() resource and
59 must be 0. GpioInt() resource has its own means of defining it.
60
61 In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
62 resource, second pin in that resource with the GPIO number of 31.
63
64 The GpioIo() resource unfortunately doesn't explicitly provide an initial
65 state of the output pin which driver should use during its initialization.
66
67 Linux tries to use common sense here and derives the state from the bias
68 and polarity settings. The table below shows the expectations:
69
70 +-------------+-------------+-----------------------------------------------+
71 | Pull Bias | Polarity | Requested... |
72 +=============+=============+===============================================+
73 | Implicit |
74 +-------------+-------------+-----------------------------------------------+
75 | **Default** | x | AS IS (assumed firmware configured it for us) |
76 +-------------+-------------+-----------------------------------------------+
77 | Explicit |
78 +-------------+-------------+-----------------------------------------------+
79 | **None** | x | AS IS (assumed firmware configured it for us) |
80 | | | with no Pull Bias |
81 +-------------+-------------+-----------------------------------------------+
82 | **Up** | x (no _DSD) | |
83 | +-------------+ as high, assuming non-active |
84 | | Low | |
85 | +-------------+-----------------------------------------------+
86 | | High | as high, assuming active |
87 +-------------+-------------+-----------------------------------------------+
88 | **Down** | x (no _DSD) | |
89 | +-------------+ as low, assuming non-active |
90 | | High | |
91 | +-------------+-----------------------------------------------+
92 | | Low | as low, assuming active |
93 +-------------+-------------+-----------------------------------------------+
94
95 That said, for our above example, since the bias setting is explicit and
96 _DSD is present, both GPIOs will be treated as active with a high
97 polarity and Linux will configure the pins in this state until a driver
98 reprograms them differently.
99
100 It is possible to leave holes in the array of GPIOs. This is useful in
101 cases like with SPI host controllers where some chip selects may be
102 implemented as GPIOs and some as native signals. For example a SPI host
103 controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
104 native::
105
106 Package () {
107 "cs-gpios",
108 Package () {
109 ^GPIO, 19, 0, 0, // chip select 0: GPIO
110 0, // chip select 1: native signal
111 ^GPIO, 20, 0, 0, // chip select 2: GPIO
112 }
113 }
114
115 Note, that historically ACPI has no means of the GPIO polarity and thus
116 the SPISerialBus() resource defines it on the per-chip basis. In order
117 to avoid a chain of negations, the GPIO polarity is considered being
118 Active High. Even for the cases when _DSD() is involved (see the example
119 above) the GPIO CS polarity must be defined Active High to avoid ambiguity.
120
121 Other supported properties
122 ==========================
123
124 Following Device Tree compatible device properties are also supported by
125 _DSD device properties for GPIO controllers:
126
127 - gpio-hog
128 - output-high
129 - output-low
130 - input
131 - line-name
132
133 Example::
134
135 Name (_DSD, Package () {
136 // _DSD Hierarchical Properties Extension UUID
137 ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
138 Package () {
139 Package () { "hog-gpio8", "G8PU" }
140 }
141 })
142
143 Name (G8PU, Package () {
144 ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
145 Package () {
146 Package () { "gpio-hog", 1 },
147 Package () { "gpios", Package () { 8, 0 } },
148 Package () { "output-high", 1 },
149 Package () { "line-name", "gpio8-pullup" },
150 }
151 })
152
153 - gpio-line-names
154
155 The ``gpio-line-names`` declaration is a list of strings ("names"), which
156 describes each line/pin of a GPIO controller/expander. This list, contained in
157 a package, must be inserted inside the GPIO controller declaration of an ACPI
158 table (typically inside the DSDT). The ``gpio-line-names`` list must respect the
159 following rules (see also the examples):
160
161 - the first name in the list corresponds with the first line/pin of the GPIO
162 controller/expander
163 - the names inside the list must be consecutive (no "holes" are permitted)
164 - the list can be incomplete and can end before the last GPIO line: in
165 other words, it is not mandatory to fill all the GPIO lines
166 - empty names are allowed (two quotation marks ``""`` correspond to an empty
167 name)
168 - names inside one GPIO controller/expander must be unique
169
170 Example of a GPIO controller of 16 lines, with an incomplete list with two
171 empty names::
172
173 Package () {
174 "gpio-line-names",
175 Package () {
176 "pin_0",
177 "pin_1",
178 "",
179 "",
180 "pin_3",
181 "pin_4_push_button",
182 }
183 }
184
185 At runtime, the above declaration produces the following result (using the
186 "libgpiod" tools)::
187
188 root@debian:~# gpioinfo gpiochip4
189 gpiochip4 - 16 lines:
190 line 0: "pin_0" unused input active-high
191 line 1: "pin_1" unused input active-high
192 line 2: unnamed unused input active-high
193 line 3: unnamed unused input active-high
194 line 4: "pin_3" unused input active-high
195 line 5: "pin_4_push_button" unused input active-high
196 line 6: unnamed unused input active-high
197 line 7 unnamed unused input active-high
198 line 8: unnamed unused input active-high
199 line 9: unnamed unused input active-high
200 line 10: unnamed unused input active-high
201 line 11: unnamed unused input active-high
202 line 12: unnamed unused input active-high
203 line 13: unnamed unused input active-high
204 line 14: unnamed unused input active-high
205 line 15: unnamed unused input active-high
206 root@debian:~# gpiofind pin_4_push_button
207 gpiochip4 5
208 root@debian:~#
209
210 Another example::
211
212 Package () {
213 "gpio-line-names",
214 Package () {
215 "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD",
216 "MUX7_IO", "LVL_C_A1", "MUX0_IO", "SPI1_MISO",
217 }
218 }
219
220 See Documentation/devicetree/bindings/gpio/gpio.txt for more information
221 about these properties.
222
223 ACPI GPIO Mappings Provided by Drivers
224 ======================================
225
226 There are systems in which the ACPI tables do not contain _DSD but provide _CRS
227 with GpioIo()/GpioInt() resources and device drivers still need to work with
228 them.
229
230 In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV,
231 available to the driver can be used to identify the device and that is supposed
232 to be sufficient to determine the meaning and purpose of all of the GPIO lines
233 listed by the GpioIo()/GpioInt() resources returned by _CRS. In other words,
234 the driver is supposed to know what to use from the GpioIo()/GpioInt() resources
235 for once it has identified the device. Having done that, it can simply assign names
236 to the GPIO lines it is going to use and provide the GPIO subsystem with a
237 mapping between those names and the ACPI GPIO resources corresponding to them.
238
239 To do that, the driver needs to define a mapping table as a NULL-terminated
240 array of struct acpi_gpio_mapping objects that each contains a name, a pointer
241 to an array of line data (struct acpi_gpio_params) objects and the size of that
242 array. Each struct acpi_gpio_params object consists of three fields,
243 crs_entry_index, line_index, active_low, representing the index of the target
244 GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target
245 line in that resource starting from zero, and the active-low flag for that line,
246 respectively, in analogy with the _DSD GPIO property format specified above.
247
248 For the example Bluetooth device discussed previously the data structures in
249 question would look like this::
250
251 static const struct acpi_gpio_params reset_gpio = { 1, 1, false };
252 static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false };
253
254 static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = {
255 { "reset-gpios", &reset_gpio, 1 },
256 { "shutdown-gpios", &shutdown_gpio, 1 },
257 { }
258 };
259
260 Next, the mapping table needs to be passed as the second argument to
261 acpi_dev_add_driver_gpios() or its managed analogue that will
262 register it with the ACPI device object pointed to by its first
263 argument. That should be done in the driver's .probe() routine.
264 On removal, the driver should unregister its GPIO mapping table by
265 calling acpi_dev_remove_driver_gpios() on the ACPI device object where that
266 table was previously registered.
267
268 Using the _CRS fallback
269 =======================
270
271 If a device does not have _DSD or the driver does not create ACPI GPIO
272 mapping, the Linux GPIO framework refuses to return any GPIOs. This is
273 because the driver does not know what it actually gets. For example, if we
274 have a device like below::
275
276 Device (BTH)
277 {
278 Name (_HID, ...)
279
280 Name (_CRS, ResourceTemplate () {
281 GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
282 "\\_SB.GPO0", 0, ResourceConsumer) { 15 }
283 GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
284 "\\_SB.GPO0", 0, ResourceConsumer) { 27 }
285 })
286 }
287
288 The driver might expect to get the right GPIO when it does::
289
290 desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW);
291 if (IS_ERR(desc))
292 ...error handling...
293
294 but since there is no way to know the mapping between "reset" and
295 the GpioIo() in _CRS the desc will hold ERR_PTR(-ENOENT).
296
297 The driver author can solve this by passing the mapping explicitly
298 (this is the recommended way and it's documented in the above chapter).
299
300 The ACPI GPIO mapping tables should not contaminate drivers that are not
301 knowing about which exact device they are servicing on. It implies that
302 the ACPI GPIO mapping tables are hardly linked to an ACPI ID and certain
303 objects, as listed in the above chapter, of the device in question.
304
305 Getting GPIO descriptor
306 =======================
307
308 There are two main approaches to get GPIO resource from ACPI::
309
310 desc = gpiod_get(dev, connection_id, flags);
311 desc = gpiod_get_index(dev, connection_id, index, flags);
312
313 We may consider two different cases here, i.e. when connection ID is
314 provided and otherwise.
315
316 Case 1::
317
318 desc = gpiod_get(dev, "non-null-connection-id", flags);
319 desc = gpiod_get_index(dev, "non-null-connection-id", index, flags);
320
321 Case 1 assumes that corresponding ACPI device description must have
322 defined device properties and will prevent from getting any GPIO resources
323 otherwise.
324
325 Case 2::
326
327 desc = gpiod_get(dev, NULL, flags);
328 desc = gpiod_get_index(dev, NULL, index, flags);
329
330 Case 2 explicitly tells GPIO core to look for resources in _CRS.
331
332 Be aware that gpiod_get_index() in cases 1 and 2, assuming that there
333 are two versions of ACPI device description provided and no mapping is
334 present in the driver, will return different resources. That's why a
335 certain driver has to handle them carefully as explained in the previous
336 chapter.
337

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

_DSD GPIO 이름과 property 형식

1-60

ACPI 5.1의 `_DSD` configuration object는 `_CRS`가 반환하는 GPIO를 비롯한 resource에 이름을 붙일 수 있게 했다. 이전에는 대응 GPIO를 integer index로만 찾아야 했고, 이 방식은 `_CRS` output 순서에 의존하므로 오류가 나기 쉬웠다.

이제 driver는 정수 index 대신 `_DSD`의 이름으로 GPIO를 질의할 수 있다. Bluetooth device BTH 예제에는 reset과 shutdown GPIO가 있고, `_CRS`는 controller `\_SB.GPO0`의 두 `GpioIo()` resource를 반환한다.

첫 `GpioIo()` resource는 output-only pin 15 하나를 포함한다. 두 번째 `GpioIo()` resource는 pin 27과 31을 포함한다. 둘 다 `Exclusive`, `PullUp`, `IoRestrictionOutputOnly`, `ResourceConsumer`로 기술되어 있다.

Device Properties UUID `daffd814-6eba-4d8c-8a91-bc9bbf4aa301` 아래에서 `reset-gpios`는 `{ ^BTH, 1, 1, 0 }`, `shutdown-gpios`는 `{ ^BTH, 0, 0, 0 }`으로 정의된다.

BTH _CRS GPIO resource
_CRS resource indexControllerResource pin indexGPIO number
0\_SB.GPO0015
1\_SB.GPO0027
1\_SB.GPO0131

Resource index와 내부 pin index를 분리해서 봐야 최종 GPIO number를 정확히 찾을 수 있다.

_DSD GPIO property 형식
필드의미기준
nameConsumer property 이름예: reset-gpios
refGpioIo()/GpioInt()가 있는 device보통 device 자신
index_CRS의 GPIO resource index0부터 시작
pin해당 resource 내부 pin index0부터 시작, 보통 0
active_low1이면 active-lowGpioIo() polarity 보완

Property 값은 참조 device, resource index, resource 내부 pin index, active-low flag 순서다.

지원 형식은 `Package () { "name", Package () { ref, index, pin, active_low } }`다. `ref`는 `GpioIo()` 또는 `GpioInt()` resource가 있는 device이고, 보통 현재 device 자신이다. `index`와 `pin`은 모두 0부터 시작한다.

ACPI `GpioIo()` resource에는 active-low인지 active-high인지 나타내는 필드가 없으므로 `_DSD`의 `active_low` argument가 이를 보완한다. 값을 1로 설정하면 GPIO를 active-low로 표시한다.

반면 `GpioInt()`에는 polarity를 정의하는 자체 수단이 있다. 따라서 `GpioInt()`를 참조하는 `_DSD` GPIO property에서 `active_low`는 의미가 없으며 반드시 0이어야 한다.

이름에서 물리 GPIO 찾기
Driver가 connection ID로 GPIO property 검색Property의 ref로 _CRS 소유 device 선택index로 GpioIo()/GpioInt() resource 선택pin으로 resource 내부 항목 선택active_low flag를 descriptor polarity에 반영

reset-gpios 같은 이름이 controller pin으로 해석되는 과정이다.

.. SPDX-License-Identifier: GPL-2.0

======================================
_DSD Device Properties Related to GPIO
======================================

With the release of ACPI 5.1, the _DSD configuration object finally
allows names to be given to GPIOs (and other things as well) returned
by _CRS. Previously we were only able to use an integer index to find
the corresponding GPIO, which is pretty error prone (it depends on
the _CRS output ordering, for example).

With _DSD we can now query GPIOs using a name instead of an integer
index, like the ASL example below shows::

  // Bluetooth device with reset and shutdown GPIOs
  Device (BTH)
  {
      Name (_HID, ...)

      Name (_CRS, ResourceTemplate ()
      {
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) { 15 }
          GpioIo (Exclusive, PullUp, 0, 0, IoRestrictionOutputOnly,
                  "\\_SB.GPO0", 0, ResourceConsumer) { 27, 31 }
      })

      Name (_DSD, Package ()
      {
          ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
          Package ()
          {
              Package () { "reset-gpios", Package () { ^BTH, 1, 1, 0 } },
              Package () { "shutdown-gpios", Package () { ^BTH, 0, 0, 0 } },
          }
      })
  }

The format of the supported GPIO property is::

  Package () { "name", Package () { ref, index, pin, active_low }}

ref
  The device that has _CRS containing GpioIo()/GpioInt() resources,
  typically this is the device itself (BTH in our case).
index
  Index of the GpioIo()/GpioInt() resource in _CRS starting from zero.
pin
  Pin in the GpioIo()/GpioInt() resource. Typically this is zero.
active_low
  If 1, the GPIO is marked as active-low.

Since ACPI GpioIo() resource does not have a field saying whether it is
active-low or active-high, the "active_low" argument can be used here.
Setting it to 1 marks the GPIO as active-low.

Note, active_low in _DSD does not make sense for GpioInt() resource and
must be 0. GpioInt() resource has its own means of defining it.

Bluetooth mapping과 초기 출력 상태

61-120

Bluetooth 예제에서 `reset-gpios`는 두 번째 `GpioIo()` resource의 두 번째 pin을 가리킨다. 즉 `{ ^BTH, 1, 1, 0 }`의 resource index 1과 pin index 1을 따라가면 GPIO number 31이다. `shutdown-gpios`는 resource index 0의 pin index 0이므로 GPIO 15다.

BTH 이름별 최종 GPIO
PropertyTuple_CRS resourcePin indexGPIO
reset-gpios{ ^BTH, 1, 1, 0 }두 번째131
shutdown-gpios{ ^BTH, 0, 0, 0 }첫 번째015

_DSD tuple을 _CRS 배열에 적용한 결과다.

`GpioIo()` resource에는 driver가 초기화 중 사용해야 할 output pin의 초기 state가 명시적으로 들어 있지 않다. Linux는 pull bias와 polarity 설정을 조합해 합리적인 초기 state를 유도한다.

GpioIo 출력 초기 상태
Pull biasPolarityLinux가 요청하는 상태해석
Default (implicit)무관AS ISFirmware가 이미 설정했다고 가정
None (explicit)무관AS ISPull bias 없이 firmware 상태 유지
Up미지정 또는 active-lowHighNon-active로 가정
Upactive-highHighActive로 가정
Down미지정 또는 active-highLowNon-active로 가정
Downactive-lowLowActive로 가정

원문의 기대값 표를 bias, polarity와 Linux 요청 상태로 재구성했다.

Implicit `Default` bias는 polarity와 관계없이 현재 상태를 그대로 두며 firmware가 대신 설정했다고 가정한다. Explicit `None`도 pull bias만 없앤 채 현재 상태를 유지한다.

Explicit `Up`은 pin을 high로 요청한다. `_DSD`가 없어 polarity를 알 수 없거나 active-low이면 high를 non-active로 간주하고, active-high이면 high를 active로 간주한다. Explicit `Down`은 반대로 pin을 low로 요청하며, polarity 미지정 또는 active-high이면 non-active, active-low이면 active로 본다.

BTH 예제는 explicit `PullUp`이며 `_DSD`가 존재하고 두 property의 `active_low`가 0이다. 따라서 두 GPIO는 high polarity에서 active로 취급되고, driver가 다르게 재program할 때까지 Linux가 pin을 high active state로 설정한다.

GPIO 배열에는 빈 slot을 둘 수 있다. SPI host controller에서 일부 chip select는 GPIO로, 다른 chip select는 native signal로 구현되는 경우가 대표적이다.

예제 `cs-gpios`는 chip select 0을 `^GPIO`의 GPIO 19, chip select 1을 숫자 `0`으로 표시한 native signal, chip select 2를 GPIO 20에 대응시킨다. 빈 slot은 뒤의 index가 당겨지지 않도록 보존한다.

SPI cs-gpios의 빈 slot
Chip selectPackage entry구현
0^GPIO, 19, 0, 0GPIO
10Native signal
2^GPIO, 20, 0, 0GPIO

GPIO와 native chip select가 섞여 있어도 logical chip-select index는 유지된다.

역사적으로 ACPI에는 GPIO polarity를 나타낼 수단이 없었고 `SPISerialBus()` resource가 chip별 polarity를 정의했다. 연속적인 polarity 부정을 피하려고 GPIO chip-select property의 polarity는 Active High로 간주한다. `_DSD()`를 사용하는 경우에도 모호성을 없애려면 GPIO CS polarity를 Active High로 정의해야 한다.

In our Bluetooth example the "reset-gpios" refers to the second GpioIo()
resource, second pin in that resource with the GPIO number of 31.

The GpioIo() resource unfortunately doesn't explicitly provide an initial
state of the output pin which driver should use during its initialization.

Linux tries to use common sense here and derives the state from the bias
and polarity settings. The table below shows the expectations:

+-------------+-------------+-----------------------------------------------+
| Pull Bias   | Polarity    | Requested...                                  |
+=============+=============+===============================================+
| Implicit                                                                  |
+-------------+-------------+-----------------------------------------------+
| **Default** | x           | AS IS (assumed firmware configured it for us) |
+-------------+-------------+-----------------------------------------------+
| Explicit                                                                  |
+-------------+-------------+-----------------------------------------------+
| **None**    | x           | AS IS (assumed firmware configured it for us) |
|             |             | with no Pull Bias                             |
+-------------+-------------+-----------------------------------------------+
| **Up**      | x (no _DSD) |                                               |
|             +-------------+ as high, assuming non-active                  |
|             | Low         |                                               |
|             +-------------+-----------------------------------------------+
|             | High        | as high, assuming active                      |
+-------------+-------------+-----------------------------------------------+
| **Down**    | x (no _DSD) |                                               |
|             +-------------+ as low, assuming non-active                   |
|             | High        |                                               |
|             +-------------+-----------------------------------------------+
|             | Low         | as low, assuming active                       |
+-------------+-------------+-----------------------------------------------+

That said, for our above example, since the bias setting is explicit and
_DSD is present, both GPIOs will be treated as active with a high
polarity and Linux will configure the pins in this state until a driver
reprograms them differently.

It is possible to leave holes in the array of GPIOs. This is useful in
cases like with SPI host controllers where some chip selects may be
implemented as GPIOs and some as native signals. For example a SPI host
controller can have chip selects 0 and 2 implemented as GPIOs and 1 as
native::

  Package () {
      "cs-gpios",
      Package () {
          ^GPIO, 19, 0, 0, // chip select 0: GPIO
          0,               // chip select 1: native signal
          ^GPIO, 20, 0, 0, // chip select 2: GPIO
      }
  }

Note, that historically ACPI has no means of the GPIO polarity and thus
the SPISerialBus() resource defines it on the per-chip basis. In order
to avoid a chain of negations, the GPIO polarity is considered being
Active High. Even for the cases when _DSD() is involved (see the example
above) the GPIO CS polarity must be defined Active High to avoid ambiguity.

GPIO hog와 gpio-line-names 규칙

121-168

ACPI GPIO controller의 `_DSD`는 Device Tree와 호환되는 `gpio-hog`, `output-high`, `output-low`, `input`, `line-name` property를 지원한다.

예제는 `_DSD` Hierarchical Properties Extension UUID `dbb8e3e6-5886-4ba6-8795-1319f52a966b`를 사용해 `hog-gpio8` child name을 `G8PU` package에 연결한다.

`G8PU`는 Device Properties UUID `daffd814-6eba-4d8c-8a91-bc9bbf4aa301` 아래에 `gpio-hog=1`, `gpios={ 8, 0 }`, `output-high=1`, `line-name="gpio8-pullup"`을 제공한다. 결과적으로 GPIO 8을 output-high hog로 예약하고 사람이 읽을 line name을 붙인다.

GPIO hog hierarchical property
GPIO controller _DSDHierarchical Properties Extension UUIDhog-gpio8 이름을 G8PU에 연결G8PU Device Properties UUID 해석gpio-hog·gpios·output-high·line-name 적용

Controller의 hierarchical entry가 data-only child package의 실제 hog 설정으로 이어진다.

G8PU hog property
Property역할
gpio-hog1Hog node 표시
gpios{ 8, 0 }GPIO line 8과 flag
output-high1Output high로 초기화
line-namegpio8-pullupLine 식별 이름

예제의 GPIO 8 pull-up hog 설정을 항목별로 정리했다.

`gpio-line-names`는 GPIO controller 또는 expander의 각 line/pin을 설명하는 문자열 목록이다. 이 package는 보통 DSDT 안의 GPIO controller 선언 내부에 넣는다.

목록의 첫 이름은 controller의 첫 line에 대응한다. 항목은 중간 index를 생략하지 않고 연속되어야 한다. 다만 목록 자체는 마지막 GPIO 전에 끝나도 되므로 모든 line을 채울 의무는 없다.

빈 이름 `""`은 허용된다. 빈 문자열도 해당 index를 차지하므로 뒤의 이름 위치를 보존하는 데 사용한다. 같은 GPIO controller 또는 expander 안에서 비어 있지 않은 line name은 서로 고유해야 한다.

gpio-line-names 작성 규칙
규칙요구사항
시작점첫 항목은 GPIO line 0
연속성항목 index에 hole 금지
길이마지막 GPIO 전에 끝나는 불완전 목록 허용
빈 이름"" 허용, 해당 index는 유지
고유성한 controller 안의 이름은 unique

배열 위치와 이름의 유효성을 결정하는 다섯 규칙이다.

Other supported properties
==========================

Following Device Tree compatible device properties are also supported by
_DSD device properties for GPIO controllers:

- gpio-hog
- output-high
- output-low
- input
- line-name

Example::

  Name (_DSD, Package () {
      // _DSD Hierarchical Properties Extension UUID
      ToUUID("dbb8e3e6-5886-4ba6-8795-1319f52a966b"),
      Package () {
          Package () { "hog-gpio8", "G8PU" }
      }
  })

  Name (G8PU, Package () {
      ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
      Package () {
          Package () { "gpio-hog", 1 },
          Package () { "gpios", Package () { 8, 0 } },
          Package () { "output-high", 1 },
          Package () { "line-name", "gpio8-pullup" },
      }
  })

- gpio-line-names

The ``gpio-line-names`` declaration is a list of strings ("names"), which
describes each line/pin of a GPIO controller/expander. This list, contained in
a package, must be inserted inside the GPIO controller declaration of an ACPI
table (typically inside the DSDT). The ``gpio-line-names`` list must respect the
following rules (see also the examples):

  - the first name in the list corresponds with the first line/pin of the GPIO
    controller/expander
  - the names inside the list must be consecutive (no "holes" are permitted)
  - the list can be incomplete and can end before the last GPIO line: in
    other words, it is not mandatory to fill all the GPIO lines
  - empty names are allowed (two quotation marks ``""`` correspond to an empty
    name)
  - names inside one GPIO controller/expander must be unique

gpio-line-names와 libgpiod 결과

169-222

16-line GPIO controller 예제는 이름 여섯 개만 제공하는 불완전 목록이며 그중 두 항목은 빈 문자열이다. 배열 위치는 line 0부터 순서대로 `pin_0`, `pin_1`, 빈 이름, 빈 이름, `pin_3`, `pin_4_push_button`에 대응한다.

이름 문자열의 숫자는 GPIO index를 결정하지 않는다. 실제 index는 package 안의 위치로 결정되므로 `pin_3` 문자열은 다섯 번째 항목인 line 4, `pin_4_push_button`은 여섯 번째 항목인 line 5에 나타난다. 원문의 이 배치를 임의로 고치면 firmware ABI가 달라진다.

16-line controller 이름 배열
Package index문자열gpioinfo 표시
0pin_0line 0: pin_0
1pin_1line 1: pin_1
2""line 2: unnamed
3""line 3: unnamed
4pin_3line 4: pin_3
5pin_4_push_buttonline 5: pin_4_push_button
6-15목록 없음unnamed

Package 위치와 runtime line을 그대로 대응시켰다.

Runtime에서 `gpioinfo gpiochip4`를 실행하면 gpiochip4가 16 line을 가진 것으로 표시된다. Line 0과 1은 각각 `pin_0`, `pin_1`, line 2와 3은 `unnamed`, line 4는 `pin_3`, line 5는 `pin_4_push_button`으로 보인다. 목록이 끝난 line 6부터 15도 `unnamed`다.

예제 출력에서 line은 모두 unused input active-high 상태다. `gpiofind pin_4_push_button`은 이름을 검색해 `gpiochip4 5`를 반환하므로 해당 이름이 line 5에 배치되었음을 확인할 수 있다.

gpio-line-names runtime 확인
DSDT controller 안의 gpio-line-names package배열 위치를 GPIO line index로 사용빈 문자열과 목록 이후 line은 unnamedgpioinfo gpiochip4로 전체 line 확인gpiofind 이름으로 chip·offset 검색

Firmware package가 libgpiod 도구에서 보이는 이름으로 변환되는 과정이다.

두 번째 예제는 line 0부터 7까지 `SPI0_CS_N`, `EXP2_INT`, `MUX6_IO`, `UART0_RXD`, `MUX7_IO`, `LVL_C_A1`, `MUX0_IO`, `SPI1_MISO`를 연속해서 지정한다.

두 번째 line-name 예제
Line이름
0SPI0_CS_N
1EXP2_INT
2MUX6_IO
3UART0_RXD
4MUX7_IO
5LVL_C_A1
6MUX0_IO
7SPI1_MISO

8개 이름이 package 순서대로 GPIO line 0부터 7에 대응한다.

이 property들에 관한 추가 정보는 원문이 가리키는 `Documentation/devicetree/bindings/gpio/gpio.txt`를 참조한다.


Example of a GPIO controller of 16 lines, with an incomplete list with two
empty names::

  Package () {
      "gpio-line-names",
      Package () {
          "pin_0",
          "pin_1",
          "",
          "",
          "pin_3",
          "pin_4_push_button",
      }
  }

At runtime, the above declaration produces the following result (using the
"libgpiod" tools)::

  root@debian:~# gpioinfo gpiochip4
  gpiochip4 - 16 lines:
          line   0:      "pin_0"       unused   input  active-high
          line   1:      "pin_1"       unused   input  active-high
          line   2:      unnamed       unused   input  active-high
          line   3:      unnamed       unused   input  active-high
          line   4:      "pin_3"       unused   input  active-high
          line   5: "pin_4_push_button" unused input active-high
          line   6:      unnamed       unused   input  active-high
          line   7       unnamed       unused   input  active-high
          line   8:      unnamed       unused   input  active-high
          line   9:      unnamed       unused   input  active-high
          line  10:      unnamed       unused   input  active-high
          line  11:      unnamed       unused   input  active-high
          line  12:      unnamed       unused   input  active-high
          line  13:      unnamed       unused   input  active-high
          line  14:      unnamed       unused   input  active-high
          line  15:      unnamed       unused   input  active-high
  root@debian:~# gpiofind pin_4_push_button
  gpiochip4 5
  root@debian:~#

Another example::

  Package () {
      "gpio-line-names",
      Package () {
          "SPI0_CS_N", "EXP2_INT", "MUX6_IO", "UART0_RXD",
          "MUX7_IO", "LVL_C_A1", "MUX0_IO", "SPI1_MISO",
      }
  }

See Documentation/devicetree/bindings/gpio/gpio.txt for more information
about these properties.

Driver가 제공하는 ACPI GPIO mapping

223-267

일부 system의 ACPI table에는 `_DSD`가 없지만 `_CRS`에는 `GpioIo()` 또는 `GpioInt()` resource가 있다. 이런 system에서도 device driver가 GPIO를 사용해야 할 수 있다.

Driver가 볼 수 있는 `_HID`, `_CID`, `_CLS`, `_SUB`, `_HRV` 같은 ACPI device identification object로 device를 확실히 식별할 수 있다면, 그 정보만으로 `_CRS`가 나열한 모든 GPIO line의 의미와 목적을 결정할 수 있어야 한다.

즉 driver는 식별한 특정 device에서 어느 `GpioIo()` 또는 `GpioInt()` line을 써야 하는지 알고 있어야 한다. 그런 경우 사용할 line에 이름을 부여하고, 그 이름과 ACPI GPIO resource 사이의 mapping을 GPIO subsystem에 제공할 수 있다.

Driver 제공 mapping의 전제
_HID·_CID·_CLS·_SUB·_HRV로 device 식별해당 model의 _CRS GPIO 의미를 driver가 확인사용할 line별 connection name 결정acpi_gpio_params 배열 작성acpi_gpio_mapping table로 GPIO subsystem에 등록

Firmware _DSD가 없을 때 특정 device 지식으로 이름을 복원하는 경로다.

Mapping table은 `struct acpi_gpio_mapping` object의 NULL-terminated 배열이다. 각 entry는 이름, line data 배열인 `struct acpi_gpio_params` pointer, 그리고 그 배열 크기를 담는다.

각 `struct acpi_gpio_params`는 `crs_entry_index`, `line_index`, `active_low` 세 필드로 이루어진다. 각각 `_CRS`에서 0부터 세는 대상 GPIO resource index, resource 안에서 0부터 세는 line index, 해당 line의 active-low flag다. 구조는 앞서 설명한 `_DSD` GPIO property 형식과 대응한다.

struct acpi_gpio_params 필드
필드의미시작값
crs_entry_index_CRS의 GpioIo()/GpioInt() resource0
line_index선택 resource 내부 line0
active_lowActive-low 여부false 또는 true

Driver mapping도 _DSD tuple과 같은 세 좌표를 사용한다.

앞의 Bluetooth device는 `reset_gpio = { 1, 1, false }`, `shutdown_gpio = { 0, 0, false }`로 표현된다. `bluetooth_acpi_gpios[]`는 `reset-gpios`를 `reset_gpio`, `shutdown-gpios`를 `shutdown_gpio`에 각각 크기 1로 연결하고 빈 `{ }` entry로 종료한다.

Bluetooth driver mapping
Connection namecrs_entry_indexline_indexactive_low
reset-gpios11false
shutdown-gpios00false

Firmware _DSD 예제와 동일한 reset·shutdown 좌표를 C 구조체로 표현한다.

Driver의 `.probe()` routine에서 mapping table을 `acpi_dev_add_driver_gpios()`의 두 번째 인자로 전달한다. 첫 인자는 mapping을 등록할 ACPI device object다. Managed analogue를 사용할 수도 있다.

Device 제거 시에는 mapping을 등록했던 같은 ACPI device object에 `acpi_dev_remove_driver_gpios()`를 호출해 table을 해제해야 한다.

ACPI GPIO Mappings Provided by Drivers
======================================

There are systems in which the ACPI tables do not contain _DSD but provide _CRS
with GpioIo()/GpioInt() resources and device drivers still need to work with
them.

In those cases ACPI device identification objects, _HID, _CID, _CLS, _SUB, _HRV,
available to the driver can be used to identify the device and that is supposed
to be sufficient to determine the meaning and purpose of all of the GPIO lines
listed by the GpioIo()/GpioInt() resources returned by _CRS.  In other words,
the driver is supposed to know what to use from the GpioIo()/GpioInt() resources
for once it has identified the device. Having done that, it can simply assign names
to the GPIO lines it is going to use and provide the GPIO subsystem with a
mapping between those names and the ACPI GPIO resources corresponding to them.

To do that, the driver needs to define a mapping table as a NULL-terminated
array of struct acpi_gpio_mapping objects that each contains a name, a pointer
to an array of line data (struct acpi_gpio_params) objects and the size of that
array.  Each struct acpi_gpio_params object consists of three fields,
crs_entry_index, line_index, active_low, representing the index of the target
GpioIo()/GpioInt() resource in _CRS starting from zero, the index of the target
line in that resource starting from zero, and the active-low flag for that line,
respectively, in analogy with the _DSD GPIO property format specified above.

For the example Bluetooth device discussed previously the data structures in
question would look like this::

  static const struct acpi_gpio_params reset_gpio = { 1, 1, false };
  static const struct acpi_gpio_params shutdown_gpio = { 0, 0, false };

  static const struct acpi_gpio_mapping bluetooth_acpi_gpios[] = {
      { "reset-gpios", &reset_gpio, 1 },
      { "shutdown-gpios", &shutdown_gpio, 1 },
      { }
  };

Next, the mapping table needs to be passed as the second argument to
acpi_dev_add_driver_gpios() or its managed analogue that will
register it with the ACPI device object pointed to by its first
argument. That should be done in the driver's .probe() routine.
On removal, the driver should unregister its GPIO mapping table by
calling acpi_dev_remove_driver_gpios() on the ACPI device object where that
table was previously registered.

_CRS fallback과 명시적 mapping

268-304

Device에 `_DSD`가 없고 driver도 ACPI GPIO mapping을 만들지 않으면 Linux GPIO framework는 GPIO 반환을 거부한다. Driver가 실제로 어떤 GPIO를 받는지 알 수 없기 때문이다.

예제 BTH device의 `_CRS`는 controller `\_SB.GPO0`에 GPIO 15와 27을 각각 별도 `GpioIo()` resource로 제공하지만, 이 두 line 중 어느 것이 reset인지 설명하는 `_DSD`는 없다.

이 상태에서 driver가 `gpiod_get(dev, "reset", GPIOD_OUT_LOW)`을 호출해도 `"reset"`과 `_CRS`의 어느 `GpioIo()`가 대응하는지 알 방법이 없다. 따라서 `desc`에는 `ERR_PTR(-ENOENT)`가 들어간다.

이름 없는 _CRS 요청 실패
_CRS에 GPIO 15·27 존재_DSD connection property 없음Driver mapping table도 없음gpiod_get(dev, "reset", ...) 호출reset과 resource 대응 불가ERR_PTR(-ENOENT) 반환

Resource가 존재해도 의미 mapping이 없으면 connection ID 요청은 실패한다.

권장 해결책은 앞 절에서 설명한 mapping을 driver가 명시적으로 제공하는 것이다. 이렇게 해야 resource 순서와 connection name의 관계를 review 가능한 코드로 고정할 수 있다.

ACPI GPIO mapping table은 자신이 정확히 어떤 device를 지원하는지 모르는 generic driver를 오염시켜서는 안 된다. Mapping은 특정 ACPI ID와 앞서 나열한 identification object에 단단히 결합되어야 하며, 확인되지 않은 다른 model에 재사용하면 안 된다.

_CRS-only device 처리
Firmware·driver 상태이름 요청 결과조치
_DSD mapping 있음정상Firmware property 사용
Driver mapping 있음정상특정 ACPI ID에 한정
둘 다 없음ERR_PTR(-ENOENT)명시적 driver mapping 추가

Connection ID를 안전하게 쓰기 위한 조건을 구분한다.

Using the _CRS fallback
=======================

If a device does not have _DSD or the driver does not create ACPI GPIO
mapping, the Linux GPIO framework refuses to return any GPIOs. This is
because the driver does not know what it actually gets. For example, if we
have a device like below::

  Device (BTH)
  {
      Name (_HID, ...)

      Name (_CRS, ResourceTemplate () {
          GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
                  "\\_SB.GPO0", 0, ResourceConsumer) { 15 }
          GpioIo (Exclusive, PullNone, 0, 0, IoRestrictionNone,
                  "\\_SB.GPO0", 0, ResourceConsumer) { 27 }
      })
  }

The driver might expect to get the right GPIO when it does::

  desc = gpiod_get(dev, "reset", GPIOD_OUT_LOW);
  if (IS_ERR(desc))
        ...error handling...

but since there is no way to know the mapping between "reset" and
the GpioIo() in _CRS the desc will hold ERR_PTR(-ENOENT).

The driver author can solve this by passing the mapping explicitly
(this is the recommended way and it's documented in the above chapter).

The ACPI GPIO mapping tables should not contaminate drivers that are not
knowing about which exact device they are servicing on. It implies that
the ACPI GPIO mapping tables are hardly linked to an ACPI ID and certain
objects, as listed in the above chapter, of the device in question.

GPIO descriptor 획득 API

305-336

ACPI에서 GPIO resource를 얻는 주요 API는 `gpiod_get(dev, connection_id, flags)`와 `gpiod_get_index(dev, connection_id, index, flags)` 두 가지다. 차이는 동일 connection의 여러 descriptor 중 index를 지정하는지 여부다.

해석은 connection ID가 non-NULL인지 `NULL`인지에 따라 크게 두 경우로 나뉜다.

Case 1에서 `gpiod_get(dev, "non-null-connection-id", flags)` 또는 `gpiod_get_index(dev, "non-null-connection-id", index, flags)`를 호출하면 대응 ACPI device description에 device property가 정의되어 있어야 한다. Property가 없으면 GPIO resource를 얻지 못하도록 막는다.

Case 2에서 `gpiod_get(dev, NULL, flags)` 또는 `gpiod_get_index(dev, NULL, index, flags)`를 호출하면 GPIO core에 `_CRS` resource를 직접 찾으라고 명시한다.

Connection ID별 GPIO 검색
connection_id검색 위치전제
Non-NULLDevice property·driver mapping이름과 resource 대응 필요
NULL_CRS GPIO resource호출자가 순서 의미를 책임짐

Non-NULL ID는 property mapping을 요구하고 NULL은 _CRS fallback을 명시한다.

gpiod_get 계열 선택
Connection ID property 존재 여부 확인이름 하나면 gpiod_get()이름 배열의 특정 항목이면 gpiod_get_index()Non-NULL ID면 _DSD·driver mapping 요구NULL ID면 _CRS 직접 검색반환 descriptor와 오류 검사

이름, index와 firmware description 형태에 따라 API를 고르는 순서다.

Driver mapping이 없고 ACPI device description의 두 version이 하나는 property mapping을 제공하고 다른 하나는 `_CRS` 순서만 제공한다고 가정하면, Case 1과 Case 2의 `gpiod_get_index()`는 서로 다른 resource를 반환할 수 있다. 따라서 특정 driver는 앞 절의 규칙에 따라 두 firmware 형태를 신중히 처리해야 한다.

안전한 구현은 non-NULL connection ID에는 명시적 mapping을 요구하고, `NULL` fallback은 대상 device의 `_CRS` 순서를 driver가 확실히 알고 있을 때만 사용하는 것이다.

Getting GPIO descriptor
=======================

There are two main approaches to get GPIO resource from ACPI::

  desc = gpiod_get(dev, connection_id, flags);
  desc = gpiod_get_index(dev, connection_id, index, flags);

We may consider two different cases here, i.e. when connection ID is
provided and otherwise.

Case 1::

  desc = gpiod_get(dev, "non-null-connection-id", flags);
  desc = gpiod_get_index(dev, "non-null-connection-id", index, flags);

Case 1 assumes that corresponding ACPI device description must have
defined device properties and will prevent from getting any GPIO resources
otherwise.

Case 2::

  desc = gpiod_get(dev, NULL, flags);
  desc = gpiod_get_index(dev, NULL, index, flags);

Case 2 explicitly tells GPIO core to look for resources in _CRS.

Be aware that gpiod_get_index() in cases 1 and 2, assuming that there
are two versions of ACPI device description provided and no mapping is
present in the driver, will return different resources. That's why a
certain driver has to handle them carefully as explained in the previous
chapter.