xref: /aosp_15_r20/external/coreboot/Documentation/acpi/gpio.md (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1# GPIO toggling in ACPI AML for coreboot
2
3## Table of contents
4- Introduction
5- Platform Interface
6- Helper routines
7- Implementation details
8- Arguments and Local Variables Management
9
10## Introduction
11
12ACPI provides platform-independent interfaces enabling the operating
13system to perform power management for devices as well as the entire
14system. An operating system can simply call into Method()s implemented
15by the interface to request different power management operations. In
16order to be able to perform these operations, an interface might
17require toggling of GPIOs. e.g. a touchscreen device interface might
18require toggling of reset-gpio in order to take the device out of
19reset or to put it back into reset.
20
21Thus, any coreboot driver that implements such an ACPI interface might
22require the ability to toggle GPIOs. However, toggling of GPIO is not
23the same across different platforms and it will require the driver to
24depend upon platform to do the required work. This document presents a
25simple interface that can be used by any coreboot driver to generate
26ACPI AML code for reading or toggling platform GPIOs.
27
28## Platform Interface
29
30All platforms that use drivers requiring ACPI AML code for GPIO
31interactions need to be implement the following functions:
321. Return GPIO Rx value if it is acting as input
33   int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
342. Return GPIO Tx value if it is acting as output
35   int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
363. Set GPIO Tx value to 1 if it is acting as output
37   int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
384. Set GPIO Tx value to 0 if it is acting as output
39   int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
40
41Each of the above functions takes as input gpio_num which is the gpio
42number that needs to be read or toggled and returns an integer which
43is:
441. Error = -1
452. Success = 0
46
47Above callback functions are chosen to be implemented in C rather than
48adding them as AML code callbacks for the following reasons:
491. 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.
522. 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.
563. Allows GPIO AML methods to be present under any device scope and
57   gives SoC the flexibility to call them without any restrictions.
58
59## Helper routines
60
61In order to relieve drivers of the task of implementing the same code
62for enabling/disabling Tx GPIOs based on the GPIO polarity, helper
63routines are provided which implement this common code and can be used
64directly in the driver routines:
651. Enable Tx GPIO
66   int acpigen_enable_tx_gpio(struct acpi_gpio gpio)
672. Disable Tx GPIO
68   int acpigen_disable_tx_gpio(struct acpi_gpio gpio)
69
70Both the above functions take as input struct acpi_gpio type and
71return -1 on error and 0 on success. These helper routines end up
72calling the platform specific acpigen_soc_{set,clear}_tx_gpio
73functions internally. Thus, all the ACPI AML calling conventions for
74the platform functions apply to these helper functions as well.
75
763. Get Rx GPIO
77   int acpigen_get_rx_gpio(struct acpi_gpio gpio)
78
79This function takes as input, an struct acpi_gpio type and outputs
80AML code to read the *logical* value of a gpio (after taking its
81polarity into consideration), into the Local0 variable. It calls
82the platform specific acpigen_soc_read_rx_gpio() to actually read
83the raw Rx gpio value.
84
85## Implementation Details
86
87Platforms are restricted to using Local5, Local6 and Local7 variables
88only in implementations of the above functions. Any AML methods called
89by the above functions do not have any such restrictions on use of
90Local variables in AML code. Local0 is to be used for all get/read
91functions to return values. This means that the driver code should not
92make any assumptions about the values in Local5, Local6 and Local7
93variables.
94
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
105```
106
107Ideally, the operation column in the above table should use one or
108more functions implemented by the platform in AML code library (like
109gpiolib.asl). In the example below SPC0 and GPC0 need to be
110implemented by the SoC in AML code library and they can be used by
111acpi_soc_set_tx_gpio to read and set bit in the appropriate register
112for the GPIO.
113
114**acpigen_soc_set_tx_gpio**
115
116	uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
117
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);
123
124
125	/* Or (Local5, TX_BIT, Local5) */
126	acpigen_write_or(LOCAL5_OP, TX_BIT, LOCAL5_OP);
127
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);
132
133	return 0;
134
135**acpigen_soc_get_tx_gpio**
136
137	uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
138
139
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);
145
146
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();
156
157	return 0;
158
159
160These are reference implementations and the platforms are free to
161implement these functions in any way they like. coreboot driver can
162then simply call into these functions to generate ACPI AML code to
163get/set/clear any GPIO. In order to decide whether GPIO operations are
164required, driver code can rely either on some config option or read
165device-tree to use any user-provided GPIOs.
166
167## Arguments and Local Variables Management
168
169Platform-defined functions can call methods using the same calling
170conventions provided by AML code. However, use of Local Variables is
171restricted to Local5, Local6 and Local7 unless they call into some
172other method. Called method can use any Local variables, Local0 -
173Local7. In case of functions expected to return back value to the
174caller, this value is expected to be returned in Local0.
175
176Driver code should not make any assumptions about the contents of
177Local5, Local6 and Local7 across callbacks to SoC code. If it makes a
178read or get call to SoC, the return value should be used from Local0
179on return. However, if it makes a set or clear call to SoC, the value
180in Local0 is undefined.
181