Documentation: Update 4.21 release notes for upcoming release
[coreboot.git] / Documentation / acpi / gpio.md
blob2d38f99582edffa681383aca23842926baf6dd2b
1 # GPIO toggling in ACPI AML for coreboot
3 ## Table of contents
4 - Introduction
5 - Platform Interface
6 - Helper routines
7 - Implementation details
8 - Arguments and Local Variables Management
10 ## Introduction
12 ACPI provides platform-independent interfaces enabling the operating
13 system to perform power management for devices as well as the entire
14 system. An operating system can simply call into Method()s implemented
15 by the interface to request different power management operations. In
16 order to be able to perform these operations, an interface might
17 require toggling of GPIOs. e.g. a touchscreen device interface might
18 require toggling of reset-gpio in order to take the device out of
19 reset or to put it back into reset.
21 Thus, any coreboot driver that implements such an ACPI interface might
22 require the ability to toggle GPIOs. However, toggling of GPIO is not
23 the same across different platforms and it will require the driver to
24 depend upon platform to do the required work. This document presents a
25 simple interface that can be used by any coreboot driver to generate
26 ACPI AML code for reading or toggling platform GPIOs.
28 ## Platform Interface
30 All platforms that use drivers requiring ACPI AML code for GPIO
31 interactions need to be implement the following functions:
32 1. Return GPIO Rx value if it is acting as input
33    int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
34 2. Return GPIO Tx value if it is acting as output
35    int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
36 3. Set GPIO Tx value to 1 if it is acting as output
37    int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
38 4. Set GPIO Tx value to 0 if it is acting as output
39    int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
41 Each of the above functions takes as input gpio_num which is the gpio
42 number that needs to be read or toggled and returns an integer which
43 is:
44 1. Error = -1
45 2. Success = 0
47 Above callback functions are chosen to be implemented in C rather than
48 adding them as AML code callbacks for the following reasons:
49 1. It is easier to add error prints in C which will inform the
50    developer that these callbacks are missing. It restricts debugging
51    to coreboot logs.
52 2. GPIO conversion from number to register offset can be easily done
53    in C by reusing implemented functions rather than adding all the
54    logic to AML code or depending upon complicated macros to be added
55    to device-tree.
56 3. Allows GPIO AML methods to be present under any device scope and
57    gives SoC the flexibility to call them without any restrictions.
59 ## Helper routines
61 In order to relieve drivers of the task of implementing the same code
62 for enabling/disabling Tx GPIOs based on the GPIO polarity, helper
63 routines are provided which implement this common code and can be used
64 directly in the driver routines:
65 1. Enable Tx GPIO
66    int acpigen_enable_tx_gpio(struct acpi_gpio gpio)
67 2. Disable Tx GPIO
68    int acpigen_disable_tx_gpio(struct acpi_gpio gpio)
70 Both the above functions take as input struct acpi_gpio type and
71 return -1 on error and 0 on success. These helper routines end up
72 calling the platform specific acpigen_soc_{set,clear}_tx_gpio
73 functions internally. Thus, all the ACPI AML calling conventions for
74 the platform functions apply to these helper functions as well.
76 3. Get Rx GPIO
77    int acpigen_get_rx_gpio(struct acpi_gpio gpio)
79 This function takes as input, an struct acpi_gpio type and outputs
80 AML code to read the *logical* value of a gpio (after taking its
81 polarity into consideration), into the Local0 variable. It calls
82 the platform specific acpigen_soc_read_rx_gpio() to actually read
83 the raw Rx gpio value.
85 ## Implementation Details
87 Platforms are restricted to using Local5, Local6 and Local7 variables
88 only in implementations of the above functions. Any AML methods called
89 by the above functions do not have any such restrictions on use of
90 Local variables in AML code. Local0 is to be used for all get/read
91 functions to return values. This means that the driver code should not
92 make any assumptions about the values in Local5, Local6 and Local7
93 variables.
95 ```
96  **Function**                   **Operation**                **Return**
97  acpigen_soc_read_rx_gpio     Generate ACPI AML code to      Error = -1
98                               read value of Rx in Local0.    Success = 0
99  acpigen_soc_get_tx_gpio      Generate ACPI AML code to      Error = -1
100                               get value of Tx in Local0.     Success = 0
101  acpigen_soc_set_tx_gpio      Generate ACPI AML code to      Error = -1
102                               set Tx to 1.                   Success = 0
103  acpigen_soc_clear_tx_gpio    Generate ACPI AML code to      Error = -1
104                               set Tx to 0.                   Success = 0
107 Ideally, the operation column in the above table should use one or
108 more functions implemented by the platform in AML code library (like
109 gpiolib.asl). In the example below SPC0 and GPC0 need to be
110 implemented by the SoC in AML code library and they can be used by
111 acpi_soc_set_tx_gpio to read and set bit in the appropriate register
112 for the GPIO.
114 **acpigen_soc_set_tx_gpio**
116         uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
118         /* Store (\_SB.GPC0(gpio_reg_offset, Local5) */
119         acpigen_write_store();
120         acpigen_emit_namestring(“\\_SB.GPC0”);
121         acpigen_write_integer(gpio_reg_offset);
122         acpigen_emit_byte(LOCAL5_OP);
125         /* Or (Local5, TX_BIT, Local5) */
126         acpigen_write_or(LOCAL5_OP, TX_BIT, LOCAL5_OP);
128         /* \_SB.SPC0(gpio_reg_offset, LOCAL5) */
129         acpigen_emit_namestring(“\\_SB.SPC0”);
130         acpigen_write_integer(gpio_reg_offset);
131         acpigen_emit_byte(LOCAL5_OP);
133         return 0;
135 **acpigen_soc_get_tx_gpio**
137         uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
140         /* Store (\_SB.GPC0(gpio_reg_offset, Local5) */
141         acpigen_write_store();
142         acpigen_emit_namestring(“\\_SB.GPC0”);
143         acpigen_write_integer(gpio_reg_offset);
144         acpigen_emit_byte(LOCAL5_OP);
147         /*
148          * If (And (Local5, TX_BIT)) Store (One, Local0) Else Store (Zero,
149          * Local0)
150          */
151         acpigen_write_if_and(Local5, TX_BIT);
152         acpigen_write_store_args(ONE_OP, LOCAL0_OP);
153         acpigen_write_else();
154         acpigen_write_store_args(ZERO_OP, LOCAL0_OP);
155         acpigen_pop_len();
157         return 0;
160 These are reference implementations and the platforms are free to
161 implement these functions in any way they like. coreboot driver can
162 then simply call into these functions to generate ACPI AML code to
163 get/set/clear any GPIO. In order to decide whether GPIO operations are
164 required, driver code can rely either on some config option or read
165 device-tree to use any user-provided GPIOs.
167 ## Arguments and Local Variables Management
169 Platform-defined functions can call methods using the same calling
170 conventions provided by AML code. However, use of Local Variables is
171 restricted to Local5, Local6 and Local7 unless they call into some
172 other method. Called method can use any Local variables, Local0 -
173 Local7. In case of functions expected to return back value to the
174 caller, this value is expected to be returned in Local0.
176 Driver code should not make any assumptions about the contents of
177 Local5, Local6 and Local7 across callbacks to SoC code. If it makes a
178 read or get call to SoC, the return value should be used from Local0
179 on return. However, if it makes a set or clear call to SoC, the value
180 in Local0 is undefined.