aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/stoneyridge/acpi.c
diff options
context:
space:
mode:
authorRichard Spiegel <richard.spiegel@amd.corp-partner.google.com>2018-05-16 14:08:33 -0700
committerMartin Roth <martinroth@google.com>2018-06-13 14:24:42 +0000
commit93459d6278f1557f3e38c33b79a8fd739aa7ff68 (patch)
tree1634a2374ca5409bac233e126db330e0e3927787 /src/soc/amd/stoneyridge/acpi.c
parent572f4988ddb3b85bdce019de7d6a594bea070bfb (diff)
soc/amd/stoneyridge/acpi.c: Create GPIO acpigen procedures
There are some acpigen functionality that have not been implemented. They are defined as week within acpigen.c, in order to not break the build. This adds stoneyridge specific versions. BUG=b:79546790 TEST=Build grunt with added debug code to gpio_lib.asl. Boot to OS, activate ACPI debug, activate S3 stress test. Interrupt stress test, do a "cat /var/log/messages" saving the serial output. Examine the serial output, see added debug code showing action taken. Confirm action by reading proper register. Debug code removed. Change-Id: I9062d889f828a3175b89e6f4a3659ebbf90eac68 Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com> Reviewed-on: https://review.coreboot.org/26335 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/soc/amd/stoneyridge/acpi.c')
-rw-r--r--src/soc/amd/stoneyridge/acpi.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/soc/amd/stoneyridge/acpi.c b/src/soc/amd/stoneyridge/acpi.c
index d7aa088fb0..8130b79c2c 100644
--- a/src/soc/amd/stoneyridge/acpi.c
+++ b/src/soc/amd/stoneyridge/acpi.c
@@ -32,6 +32,7 @@
#include <soc/pci_devs.h>
#include <soc/southbridge.h>
#include <soc/nvs.h>
+#include <soc/gpio.h>
unsigned long acpi_fill_madt(unsigned long current)
{
@@ -303,3 +304,100 @@ void southbridge_inject_dsdt(struct device *device)
acpigen_pop_len();
}
}
+
+static void acpigen_soc_get_gpio_in_local5(uintptr_t addr)
+{
+ /*
+ * Store (\_SB.GPR2 (addr), Local5)
+ * \_SB.GPR2 is used to read control byte 2 from control register.
+ * / It is defined in gpio_lib.asl.
+ */
+ acpigen_write_store();
+ acpigen_emit_namestring("\\_SB.GPR2");
+ acpigen_write_integer(addr);
+ acpigen_emit_byte(LOCAL5_OP);
+}
+
+static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
+{
+ if (gpio_num >= GPIO_TOTAL_PINS) {
+ printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
+ " %d\n", gpio_num, GPIO_TOTAL_PINS);
+ return -1;
+ }
+ uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
+
+ acpigen_soc_get_gpio_in_local5(addr);
+
+ /* If (And (Local5, mask)) */
+ acpigen_write_if_and(LOCAL5_OP, mask);
+
+ /* Store (One, Local0) */
+ acpigen_write_store_ops(ONE_OP, LOCAL0_OP);
+
+ acpigen_pop_len(); /* If */
+
+ /* Else */
+ acpigen_write_else();
+
+ /* Store (Zero, Local0) */
+ acpigen_write_store_ops(ZERO_OP, LOCAL0_OP);
+
+ acpigen_pop_len(); /* Else */
+
+ return 0;
+}
+
+static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
+{
+ if (gpio_num >= GPIO_TOTAL_PINS) {
+ printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
+ " %d\n", gpio_num, GPIO_TOTAL_PINS);
+ return -1;
+ }
+ uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
+
+ acpigen_soc_get_gpio_in_local5(addr);
+
+ if (val) {
+ /* Or (Local5, GPIO_PIN_OUT, Local5) */
+ acpigen_write_or(LOCAL5_OP, GPIO_PIN_OUT, LOCAL5_OP);
+ } else {
+ /* Not (GPIO_PIN_OUT, Local6) */
+ acpigen_write_not(GPIO_PIN_OUT, LOCAL6_OP);
+
+ /* And (Local5, Local6, Local5) */
+ acpigen_write_and(LOCAL5_OP, LOCAL6_OP, LOCAL5_OP);
+ }
+
+ /*
+ * SB.GPW2 (addr, Local5)
+ * \_SB.GPW2 is used to write control byte in control register
+ * / byte 2. It is defined in gpio_lib.asl.
+ */
+ acpigen_emit_namestring("\\_SB.GPW2");
+ acpigen_write_integer(addr);
+ acpigen_emit_byte(LOCAL5_OP);
+
+ return 0;
+}
+
+int acpigen_soc_read_rx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_get_gpio_val(gpio_num, GPIO_PIN_IN);
+}
+
+int acpigen_soc_get_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_get_gpio_val(gpio_num, GPIO_PIN_OUT);
+}
+
+int acpigen_soc_set_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_set_gpio_val(gpio_num, 1);
+}
+
+int acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
+{
+ return acpigen_soc_set_gpio_val(gpio_num, 0);
+}