GPIO
Introduction
GPIO, short for General-Purpose Input/Output, is a type of pin that can be dynamically configured and controlled during software execution. All GPIOs are in input mode after power-up, and can be set to pull-up or pull-down through software. They can also be configured as interrupt pins, and their drive strength is programmable. The core of GPIO operation involves populating the methods and parameters of the GPIO bank and registering it with the kernel using gpiochip_add.
GPIO Pin Calculation
The LKD3568 has 5 groups of GPIO banks: GPIO0~GPIO4, each group is further divided with identifiers A0~A7, B0~B7, C0~C7, D0~D7. The following formulas are commonly used to calculate the pins:
GPIO pin calculation formula: pin = bank * 32 + number
GPIO group number calculation formula: number = group * 8 + X
Here is a demonstration of the calculation method for GPIO4_D5 pin: bank = 4; //GPIO4_D5 => 4, bank ∈ [0,4]
group = 3; //GPIO4_D5 => 3, group ∈ {(A=0), (B=1), (C=2), (D=3)}
X = 5; //GPIO4_D5 => 5, X ∈ [0,7]
number = group * 8 + X = 3 * 8 + 5 = 29
pin = bank*32 + number= 4 * 32 + 29 = 157;
GPIO | Identifier | Pin | Identifier | Pin | Identifier | Pin | Identifier | Pin |
---|---|---|---|---|---|---|---|---|
GPIO0 | A0 | 0 | B0 | 8 | C0 | 16 | D0 | 24 |
A1 | 1 | B1 | 9 | C1 | 17 | D1 | 25 | |
A2 | 2 | B2 | 10 | C2 | 18 | D2 | 26 | |
A3 | 3 | B3 | 11 | C3 | 19 | D3 | 27 | |
A4 | 4 | B4 | 12 | C4 | 20 | D4 | 28 | |
A5 | 5 | B5 | 13 | C5 | 21 | D5 | 29 | |
A6 | 6 | B6 | 14 | C6 | 22 | D6 | 30 | |
A7 | 7 | B7 | 15 | C7 | 23 | D7 | 31 | |
GPIO1 | A0 | 32 | B0 | 40 | C0 | 48 | D0 | 56 |
A1 | 33 | B1 | 41 | C1 | 49 | D1 | 57 | |
A2 | 34 | B2 | 42 | C2 | 50 | D2 | 58 | |
A3 | 35 | B3 | 43 | C3 | 51 | D3 | 59 | |
A4 | 36 | B4 | 44 | C4 | 52 | D4 | 60 | |
A5 | 37 | B5 | 45 | C5 | 53 | D5 | 61 | |
A6 | 38 | B6 | 46 | C6 | 54 | D6 | 62 | |
A7 | 39 | B7 | 47 | C7 | 55 | D7 | 63 | |
GPIO2 | A0 | 64 | B0 | 72 | C0 | 80 | D0 | 88 |
A1 | 65 | B1 | 73 | C1 | 81 | D1 | 89 | |
A2 | 66 | B2 | 74 | C2 | 82 | D2 | 90 | |
A3 | 67 | B3 | 75 | C3 | 83 | D3 | 91 | |
A4 | 68 | B4 | 76 | C4 | 84 | D4 | 92 | |
A5 | 69 | B5 | 77 | C5 | 85 | D5 | 93 | |
A6 | 70 | B6 | 78 | C6 | 86 | D6 | 94 | |
A7 | 71 | B7 | 79 | C7 | 87 | D7 | 95 | |
GPIO3 | A0 | 96 | B0 | 104 | C0 | 112 | D0 | 120 |
A1 | 97 | B1 | 105 | C1 | 113 | D1 | 121 | |
A2 | 98 | B2 | 106 | C2 | 114 | D2 | 122 | |
A3 | 99 | B3 | 107 | C3 | 115 | D3 | 123 | |
A4 | 100 | B4 | 108 | C4 | 116 | D4 | 124 | |
A5 | 101 | B5 | 109 | C5 | 117 | D5 | 125 | |
A6 | 102 | B6 | 110 | C6 | 118 | D6 | 126 | |
A7 | 103 | B7 | 111 | C7 | 119 | D7 | 127 | |
GPIO4 | A0 | 128 | B0 | 136 | C0 | 144 | D0 | 152 |
A1 | 129 | B1 | 137 | C1 | 145 | D1 | 153 | |
A2 | 130 | B2 | 138 | C2 | 146 | D2 | 154 | |
A3 | 131 | B3 | 139 | C3 | 147 | D3 | 155 | |
A4 | 132 | B4 | 140 | C4 | 148 | D4 | 156 | |
A5 | 133 | B5 | 141 | C5 | 149 | D5 | 157 | |
A6 | 134 | B6 | 142 | C6 | 150 | D6 | 158 | |
A7 | 135 | B7 | 143 | C7 | 151 | D7 | 159 |
The device tree property description corresponding to GPIO4_D5 is: <&gpio4 29 IRQ_TYPE_EDGE_RISING>. As defined by the macros in kernel/include/dt-bindings/pinctrl/rockchip.h
, GPIO4_D5 can also be described as <&gpio4 RK_PD5 IRQ_TYPE_EDGE_RISING>.
#define RK_PA0 0
#define RK_PA1 1
#define RK_PA2 2
#define RK_PA3 3
#define RK_PA4 4
#define RK_PA5 5
#define RK_PA6 6
#define RK_PA7 7
#define RK_PB0 8
#define RK_PB1 9
#define RK_PB2 10
#define RK_PB3 11
......
GPIO4_D5 may be occupied by other functions; the following is just an example. When the pin is not multiplexed by other peripherals, we can export the pin for use through export.
:/ # ls /sys/class/gpio/
export gpiochip128 gpiochip32 gpiochip64 unexport
gpiochip0 gpiochip255 gpiochip500 gpiochip96
:/ # echo 157 > /sys/class/gpio/export
:/ # ls /sys/class/gpio/
export gpiochip0 gpiochip255 gpiochip500 gpiochip96
gpio157 gpiochip128 gpiochip32 gpiochip64 unexport
:/ # ls /sys/class/gpio/gpio157
active_low device direction edge power subsystem uevent value
:/ # cat /sys/class/gpio/gpio157/direction
in
:/ # cat /sys/class/gpio/gpio157/value
0
FAQs
Q1: How do I switch the MUX value of a PIN to a general GPIO?
A1: When using GPIO request, the MUX value of that PIN will be forcibly switched to GPIO. Therefore, ensure that the PIN is not being used by other modules when using it for GPIO functionality.
Q2: Why do I get a value of 0x00000000 when I read with IO commands?
A2: If you read a GPIO register with IO commands and get an abnormal value, such as 0x00000000 or 0xffffffff, please confirm whether the CLK of that GPIO is turned off. The CLK of GPIO is controlled by CRU. You can check whether the CLK is on by reading the CRU_CLKGATE_CON* registers in the datasheet. If it is not on, you can use the io command to set the corresponding register to turn on the CLK. After turning on the CLK, you should be able to read the correct register value.
Q3: What should I check if the voltage measured at the PIN is incorrect?
A3: If the voltage measured at the PIN is incorrect, excluding external factors, confirm whether the IO voltage source of that PIN is correct and whether the IO-Domain configuration is correct.
Q4: What is the difference between gpio_set_value() and gpio_direction_output()?
A4: If you are not going to dynamically switch between input and output when using the GPIO, it is recommended to set the GPIO output direction at the start. Later, when pulling high or low, use the gpio_set_value() interface instead of gpio_direction_output(). This is because the gpio_direction_output() interface contains a mutex lock, which can cause errors in interrupt context calls. Moreover, compared to gpio_set_value(), gpio_direction_output() does more things, which is wasteful.