summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/amd/stoneyridge/acpi.c98
-rw-r--r--src/soc/amd/stoneyridge/gpio.c2
-rw-r--r--src/soc/amd/stoneyridge/include/soc/gpio.h6
3 files changed, 105 insertions, 1 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);
+}
diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c
index 3bb77b7010..65134762a8 100644
--- a/src/soc/amd/stoneyridge/gpio.c
+++ b/src/soc/amd/stoneyridge/gpio.c
@@ -130,7 +130,7 @@ static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level)
}
}
-static uintptr_t gpio_get_address(gpio_t gpio_num)
+uintptr_t gpio_get_address(gpio_t gpio_num)
{
uintptr_t gpio_address;
diff --git a/src/soc/amd/stoneyridge/include/soc/gpio.h b/src/soc/amd/stoneyridge/include/soc/gpio.h
index 6133bf1684..6e722933b8 100644
--- a/src/soc/amd/stoneyridge/include/soc/gpio.h
+++ b/src/soc/amd/stoneyridge/include/soc/gpio.h
@@ -36,6 +36,10 @@ struct soc_amd_event {
uint8_t event;
};
+#define GPIO_TOTAL_PINS 149
+#define GPIO_PIN_IN (1 << 0) /* for byte access */
+#define GPIO_PIN_OUT (1 << 6) /* for byte access */
+
#define GPIO_EDGE_TRIG (0 << 8)
#define GPIO_LEVEL_TRIG (1 << 8)
#define GPIO_TRIGGER_MASK (1 << 8)
@@ -555,6 +559,8 @@ enum {
.flags = GPIO_FLAG_DEBOUNCE }
typedef uint32_t gpio_t;
+/* Get the address of the control register of a particular pin */
+uintptr_t gpio_get_address(gpio_t gpio_num);
/**
* @brief program a particular set of GPIO