summaryrefslogtreecommitdiff
path: root/Documentation/acpi
diff options
context:
space:
mode:
Diffstat (limited to 'Documentation/acpi')
-rw-r--r--Documentation/acpi/gpio.md162
1 files changed, 162 insertions, 0 deletions
diff --git a/Documentation/acpi/gpio.md b/Documentation/acpi/gpio.md
new file mode 100644
index 0000000000..2c09148164
--- /dev/null
+++ b/Documentation/acpi/gpio.md
@@ -0,0 +1,162 @@
+# GPIO toggling in ACPI AML for coreboot #
+
+# Table of contents #
+- Introduction
+- Platform Interface
+- Implementation details
+- Arguments and Local Variables Management
+
+# Introduction #
+
+ACPI provides platform-independent interfaces enabling the operating
+system to perform power management for devices as well as the entire
+system. An operating system can simply call into Method()s implemented
+by the interface to request different power management operations. In
+order to be able to perform these operations, an interface might
+require toggling of GPIOs. e.g. a touchscreen device interface might
+require toggling of reset-gpio in order to take the device out of
+reset or to put it back into reset.
+
+Thus, any coreboot driver that implements such an ACPI interface might
+require the ability to toggle GPIOs. However, toggling of GPIO is not
+the same across different platforms and it will require the driver to
+depend upon platform to do the required work. This document presents a
+simple interface that can be used by any coreboot driver to generate
+ACPI AML code for reading or toggling platform GPIOs.
+
+# Platform Interface #
+
+All platforms that use drivers requiring ACPI AML code for GPIO
+interactions need to be implement the following functions:
+1. Return GPIO Rx value if it is acting as input
+ int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
+2. Return GPIO Tx value if it is acting as output
+ int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
+3. Set GPIO Tx value to 1 if it is acting as output
+ int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
+4. Set GPIO Tx value to 0 if it is acting as output
+ int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
+
+Each of the above functions takes as input gpio_num which is the gpio
+number that needs to be read or toggled and returns an integer which
+is:
+1. Error = -1
+2. Success = 0
+
+Above callback functions are chosen to be implemented in C rather than
+adding them as AML code callbacks for the following reasons:
+1. It is easier to add error prints in C which will inform the
+ developer that these callbacks are missing. It restricts debugging
+ to coreboot logs.
+2. GPIO conversion from number to register offset can be easily done
+ in C by reusing implemented functions rather than adding all the
+ logic to AML code or depending upon complicated macros to be added
+ to device-tree.
+3. Allows GPIO AML methods to be present under any device scope and
+ gives SoC the flexibility to call them without any restrictions.
+
+# Implementation Details #
+
+ACPI library in coreboot will provide weak definitions for all the
+above functions with error messages indicating that these functions
+are being used. This allows drivers to conditionally make use of GPIOs
+based on device-tree entries or any other config option. It is
+recommended that the SoC code in coreboot should provide
+implementations of all the above functions generating ACPI AML code
+irrespective of them being used in any driver. This allows mainboards
+to use any drivers and take advantage of this common infrastructure.
+
+Platforms are restricted to using Local5, Local6 and Local7 variables
+only in implementations of the above functions. Any AML methods called
+by the above functions do not have any such restrictions on use of
+Local variables in AML code. Local0 is to be used for all get/read
+functions to return values. This means that the driver code should not
+make any assumptions about the values in Local5, Local6 and Local7
+variables.
+
+ **Function** **Operation** **Return**
+ acpigen_soc_read_rx_gpio Generate ACPI AML code to Error = -1
+ read value of Rx in Local0. Success = 0
+ acpigen_soc_get_tx_gpio Generate ACPI AML code to Error = -1
+ get value of Tx in Local0. Success = 0
+ acpigen_soc_set_tx_gpio Generate ACPI AML code to Error = -1
+ set Tx to 1. Success = 0
+ acpigen_soc_clear_tx_gpio Generate ACPI AML code to Error = -1
+ set Tx to 0. Success = 0
+
+
+Ideally, the operation column in the above table should use one or
+more functions implemented by the platform in AML code library (like
+gpiolib.asl). In the example below SPC0 and GPC0 need to be
+implemented by the SoC in AML code library and they can be used by
+acpi_soc_set_tx_gpio to read and set bit in the appropriate register
+for the GPIO.
+
+**acpigen_soc_set_tx_gpio**
+
+ uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
+
+ /* Store (\_SB.GPC0(gpio_reg_offset, Local5) */
+ acpigen_write_store();
+ acpigen_emit_namestring(“\\_SB.GPC0”);
+ acpigen_write_integer(gpio_reg_offset);
+ acpigen_emit_byte(LOCAL5_OP);
+
+
+ /* Or (Local5, TX_BIT, Local5) */
+ acpigen_write_or(LOCAL5_OP, TX_BIT, LOCAL5_OP);
+
+ /* \_SB.SPC0(gpio_reg_offset, LOCAL5) */
+ acpigen_emit_namestring(“\\_SB.SPC0”);
+ acpigen_write_integer(gpio_reg_offset);
+ acpigen_emit_byte(LOCAL5_OP);
+
+ return 0;
+
+**acpigen_soc_get_tx_gpio**
+
+ uint64_t gpio_reg_offset = gpio_get_reg_offset(gpio_num);
+
+
+ /* Store (\_SB.GPC0(gpio_reg_offset, Local5) */
+ acpigen_write_store();
+ acpigen_emit_namestring(“\\_SB.GPC0”);
+ acpigen_write_integer(gpio_reg_offset);
+ acpigen_emit_byte(LOCAL5_OP);
+
+
+ /*
+ * If (And (Local5, TX_BIT)) Store (One, Local0) Else Store (Zero,
+ * Local0)
+ */
+ acpigen_write_if_and(Local5, TX_BIT);
+ acpigen_write_store_args(ONE_OP, LOCAL0_OP);
+ acpigen_pop_len();
+ acpigen_write_else();
+ acpigen_write_store_args(ZERO_OP, LOCAL0_OP);
+ acpigen_pop_len();
+
+ return 0;
+
+
+These are reference implementations and the platforms are free to
+implement these functions in any way they like. Coreboot driver can
+then simply call into these functions to generate ACPI AML code to
+get/set/clear any GPIO. In order to decide whether GPIO operations are
+required, driver code can rely either on some config option or read
+device-tree to use any user-provided GPIOs.
+
+# Arguments and Local Variables Management #
+
+Platform-defined functions can call methods using the same calling
+conventions provided by AML code. However, use of Local Variables is
+restricted to Local5, Local6 and Local7 unless they call into some
+other method. Called method can use any Local variables, Local0 -
+Local7. In case of functions expected to return back value to the
+caller, this value is expected to be returned in Local0.
+
+Driver code should not make any assumptions about the contents of
+Local5, Local6 and Local7 across callbacks to SoC code. If it makes a
+read or get call to SoC, the return value should be used from Local0
+on return. However, if it makes a set or clear call to SoC, the value
+in Local0 is undefined.