GPIO Mapping

Β· 1178 words Β· 3 minute read

GPIO λ§΅ν•‘ν•˜κΈ° πŸ”—

μ˜€λŠ˜μ€ gpio 맡핑을 μœ„ν•΄ λ””λ°”μ΄μŠ€ 트리λ₯Ό μ΄μš©ν•˜μ˜€μ§€λ§Œ μ •μƒμ μœΌλ‘œ μ„€μ •λ˜μ§€ μ•ŠλŠ” λ¬Έμ œκ°€ μžˆμ—ˆλ‹€. SoCμ—μ„œ GPIO Enable 에 λŒ€ν•œ 것이 문제일 것이라 μ˜ˆμƒλ˜μ§€λ§Œ, GPIO λ§΅ν•‘ν•˜λŠ” λ°©λ²•μœΌλ‘œ λ””λ°”μ΄μŠ€ 트리λ₯Ό μ΄μš©ν•˜λŠ” 것 외에 μ–΄λ–€ λŒ€μ•ˆμ΄ μžˆλŠ”μ§€ μ•Œμ•„λ³΄κ³ μž μ •λ¦¬ν•˜κ³ μž ν•œλ‹€.

GPIO 데이터λ₯Ό λ§΅ν•‘ν•˜μ—¬ μ‚¬μš©ν•  수 μžˆλŠ” 방법은 μ•„λž˜μ™€ 같이 μ„Έ 가지 방법이 μžˆλ‹€.

  1. λ””λ°”μ΄μŠ€ 트리 이용 (졜근 νŠΈλ Œλ“œ)
  2. Legacy Board & Machine Specific Codeμ—μ„œ ν”Œλž«νΌ λ°μ΄ν„°λ‘œ μ •μ˜
  • (μΆœμ²˜μ— λ”°λ₯΄λ©΄) GPIO 맡핑을 ν”Œλž«νΌ 데이터에 λ“±λ‘ν•˜μ—¬ μ‚¬μš©ν•˜λŠ” κ²½μš°λŠ” λ§Žμ§€ μ•Šκ³  λ‹¨μˆœν•˜κ²Œ ν•€ 번호둜 μ‚¬μš©ν•˜λŠ” κ²½μš°κ°€ λŒ€λΆ€λΆ„μ΄μ—ˆλ‹€κ³  ν•œλ‹€.
  1. ACPI νŽŒμ›¨μ–΄ ν…Œμ΄λΈ”μ— μ •μ˜

λ””λ°”μ΄μŠ€ 트리λ₯Ό μ‚¬μš©ν•˜λŠ” GPIO 맀핑 πŸ”—

λ””λ°”μ΄μŠ€ λ…Έλ“œ 내뢀에 “gpio-controller” 속성이 있으면 GPIO Controller λ…Έλ“œλ₯Ό μ˜λ―Έν•œλ‹€.

cell 개수 πŸ”—

#gpio-cells = <2> 속성은 μ…€ 데이터 2개λ₯Ό μ‚¬μš©ν•œλ‹€λŠ” 것을 μ˜λ―Έν•œλ‹€. μ•„λž˜ μ˜ˆμ‹œμ—μ„œλŠ” gpio1, gpio2에 λŒ€ν•΄ 각각 λ‹€μŒκ³Ό 같이 해석 κ°€λŠ₯ν•˜λ‹€.

  • gpio1 controllerλŠ” cell 2개λ₯Ό μ‚¬μš©ν•˜μ—¬ λ””λ°”μ΄μŠ€ λ“œλΌμ΄λ²„κ°€ 인자 2개λ₯Ό λ°›μ•„ μ²˜λ¦¬ν•œλ‹€.
  • gpio2 controllerλŠ” cell 1개λ₯Ό μ‚¬μš©ν•˜μ—¬ λ””λ°”μ΄μŠ€ λ“œλΌμ΄λ²„κ°€ 인자 1개λ₯Ό λ°›μ•„ μ²˜λ¦¬ν•œλ‹€.
  • μ§€μ •λ˜μ§€ μ•ŠλŠ” 경우 2 cell 방식을 μ‚¬μš©ν•œλ‹€.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
gpio1: gpio1 {
    gpio-controller;
    #gpio-cells = <2>;
};
gpio2: gpio2 {
    gpio-controller;
    #gpio-cells = <1>;
}

enable-gpios = <&gpio2 2>;
data-gpios = <&gpio1 12 0>, <&gpio1 13 0>, <&gpio1 14 0>, <&gpio1 15 0>;

Pin control subsystem과의 연동 πŸ”—

pin control subsystem과의 연동은 gpio controller λ…Έλ“œμ—μ„œ “gpio-ranges” 속성을 μ‚¬μš©ν•œλ‹€. “gpio-ranges” 속성이 κ°€λ¦¬ν‚€λŠ” phandle은 μ—°κ³„λœ pin controller λ…Έλ“œλ₯Ό κ°€λ¦¬μΌœμ•Ό ν•œλ‹€. 그리고 1~3개의 인자λ₯Ό μ‚¬μš©ν•  수 있으며, λ°°μ—΄ μ‚¬μš©μ„ μ§€μ›ν•œλ‹€.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
iomux: iomux@FF10601c {
        compatible = "abilis,tb10x-iomux";
        reg = <0xFF10601c 0x4>;
        pctl_gpio_a: pctl-gpio-a {
                abilis,function = "gpioa";
        };
        pctl_uart0: pctl-uart0 {
                abilis,function = "uart0";
        };
};
uart@FF100000 {
        compatible = "snps,dw-apb-uart";
        reg = <0xFF100000 0x100>;
        clock-frequency = <166666666>;
        interrupts = <25 1>;
        reg-shift = <2>;
        reg-io-width = <4>;
        pinctrl-names = "default";
        pinctrl-0 = <&pctl_uart0>;
};
gpioa: gpio@FF140000 {
        compatible = "abilis,tb10x-gpio";
        reg = <0xFF140000 0x1000>;
        gpio-controller;
        #gpio-cells = <2>;
        ngpios = <3>;
        gpio-ranges = <&iomux 0 0>;
        gpio-ranges-group-names = "gpioa";
};

ACPI νŽŒμ›¨μ–΄λ₯Ό μ‚¬μš©ν•˜λŠ” GPIO 맀핑 πŸ”—

λ””λ°”μ΄μŠ€ 트리λ₯Ό μ‚¬μš©ν•˜λŠ” 방법과 μœ μ‚¬ν•˜κ²Œ ACPI λ””μŠ€ν¬λ¦½μ…˜μ„ μ‚¬μš©ν•˜λŠ” 방법이 μžˆλ‹€. ACPI 5.1μ—μ„œ μ†Œκ°œλœ [[[_DSD (Device Specific Data)|https://www.kernel.org/doc/Documentation/acpi/gpio-properties.txt]]λ₯Ό μ°Έκ³ ν•œλ‹€.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Device (FOO) {
    Name (_CRS, ResourceTemplate () {
        GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
            "\\_SB.GPI0") {15} // red
        GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
            "\\_SB.GPI0") {16} // green
        GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
            "\\_SB.GPI0") {17} // blue
        GpioIo (Exclusive, ..., IoRestrictionOutputOnly,
            "\\_SB.GPI0") {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},
            },
        }
    })    Name (_CRS, )
}

Platform 데이터에 GPIO 맡핑 (deprecated) πŸ”—

일뢀 μ‹œμŠ€ν…œμ—μ„œ μ•„λž˜μ˜ 맀크둜 ν•¨μˆ˜, APIλ₯Ό μ‚¬μš©ν•˜μ—¬ ν”Œλž«νΌ 데이터에 μ €μž₯ν•œ ν›„, 이λ₯Ό lookup ν•˜μ—¬ μ‚¬μš©ν•˜λŠ”λ° μ§€κΈˆμ€ μ‚¬μš©ν•˜μ§€ μ•ŠλŠ” 방법이닀.

1
2
GPIO_LOOKUP(chip_label, chip_hwnum, con_id, flag)
GPIO_LOOKUP_IDX(chip_label, chip_hwnum, con_id, idx, flags)

μ•„λž˜μ™€ 같이 GPIO Lookup Table을 μ •μ˜ν•œ 후에 μ•„λž˜μ™€ 같이 μ‚¬μš©ν•  수 μžˆλ‹€.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
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),
        { },
    },
};

gpiod_add_lookup_table(&gpios_table);

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);

좜처 πŸ”—