Marshall Dawson would like Richard Spiegel, Martin Roth and Furquan Shaikh to review this change.

View Change

soc/amd/stoneyridge: Move GPIO support to common

The banked GPIO functionality in the AcpiMmio block has been consistent
since the Mullins product. Move the basic support into a common
directory.

Each product's pin availability, MUXes, and other details must remain
specific to the product.

Change-Id: I9cda00210a74de2bd1308ad43e2b867d24a67845
Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com>
---
M src/mainboard/amd/gardenia/bootblock/bootblock.c
M src/mainboard/amd/gardenia/mainboard.c
M src/mainboard/google/kahlee/bootblock/bootblock.c
M src/mainboard/google/kahlee/mainboard.c
M src/mainboard/google/kahlee/romstage.c
R src/soc/amd/common/acpi/gpio_bank_lib.asl
A src/soc/amd/common/block/gpio_banks/Kconfig
A src/soc/amd/common/block/gpio_banks/Makefile.inc
A src/soc/amd/common/block/gpio_banks/gpio.c
A src/soc/amd/common/block/include/amdblocks/gpio.h
M src/soc/amd/stoneyridge/Kconfig
M src/soc/amd/stoneyridge/acpi.c
M src/soc/amd/stoneyridge/acpi/soc.asl
M src/soc/amd/stoneyridge/gpio.c
M src/soc/amd/stoneyridge/i2c.c
M src/soc/amd/stoneyridge/include/soc/gpio.h
16 files changed, 667 insertions(+), 577 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/51/32651/1
diff --git a/src/mainboard/amd/gardenia/bootblock/bootblock.c b/src/mainboard/amd/gardenia/bootblock/bootblock.c
index 140bc07..2f4be03 100644
--- a/src/mainboard/amd/gardenia/bootblock/bootblock.c
+++ b/src/mainboard/amd/gardenia/bootblock/bootblock.c
@@ -23,5 +23,5 @@
size_t num_gpios;
const struct soc_amd_gpio *gpios;
gpios = early_gpio_table(&num_gpios);
- sb_program_gpios(gpios, num_gpios);
+ program_gpios(gpios, num_gpios);
}
diff --git a/src/mainboard/amd/gardenia/mainboard.c b/src/mainboard/amd/gardenia/mainboard.c
index b3f2285..3a4090c 100644
--- a/src/mainboard/amd/gardenia/mainboard.c
+++ b/src/mainboard/amd/gardenia/mainboard.c
@@ -82,7 +82,7 @@
size_t num_gpios;
const struct soc_amd_gpio *gpios;
gpios = gpio_table(&num_gpios);
- sb_program_gpios(gpios, num_gpios);
+ program_gpios(gpios, num_gpios);
}

/*************************************************
diff --git a/src/mainboard/google/kahlee/bootblock/bootblock.c b/src/mainboard/google/kahlee/bootblock/bootblock.c
index 038cfe2..3be308e 100644
--- a/src/mainboard/google/kahlee/bootblock/bootblock.c
+++ b/src/mainboard/google/kahlee/bootblock/bootblock.c
@@ -29,7 +29,7 @@
mainboard_ec_init();

gpios = variant_early_gpio_table(&num_gpios);
- sb_program_gpios(gpios, num_gpios);
+ program_gpios(gpios, num_gpios);
}

void bootblock_mainboard_init(void)
diff --git a/src/mainboard/google/kahlee/mainboard.c b/src/mainboard/google/kahlee/mainboard.c
index cfd5637..f218f3f 100644
--- a/src/mainboard/google/kahlee/mainboard.c
+++ b/src/mainboard/google/kahlee/mainboard.c
@@ -27,6 +27,7 @@
#include <soc/nvs.h>
#include <soc/pci_devs.h>
#include <soc/southbridge.h>
+#include <soc/smi.h>
#include <amdblocks/acpimmio.h>
#include <variant/ec.h>
#include <variant/thermal.h>
@@ -126,7 +127,7 @@
mainboard_ec_init();

gpios = variant_gpio_table(&num_gpios);
- sb_program_gpios(gpios, num_gpios);
+ program_gpios(gpios, num_gpios);

/*
* Some platforms use SCI not generated by a GPIO pin (event above 23).
diff --git a/src/mainboard/google/kahlee/romstage.c b/src/mainboard/google/kahlee/romstage.c
index 32f8356..8bc766e 100644
--- a/src/mainboard/google/kahlee/romstage.c
+++ b/src/mainboard/google/kahlee/romstage.c
@@ -34,7 +34,7 @@
const struct soc_amd_gpio *gpios;

gpios = variant_romstage_gpio_table(&num_gpios);
- sb_program_gpios(gpios, num_gpios);
+ program_gpios(gpios, num_gpios);

variant_romstage_entry(s3_resume);
}
diff --git a/src/soc/amd/stoneyridge/acpi/gpio_lib.asl b/src/soc/amd/common/acpi/gpio_bank_lib.asl
similarity index 100%
rename from src/soc/amd/stoneyridge/acpi/gpio_lib.asl
rename to src/soc/amd/common/acpi/gpio_bank_lib.asl
diff --git a/src/soc/amd/common/block/gpio_banks/Kconfig b/src/soc/amd/common/block/gpio_banks/Kconfig
new file mode 100644
index 0000000..115aa2c
--- /dev/null
+++ b/src/soc/amd/common/block/gpio_banks/Kconfig
@@ -0,0 +1,8 @@
+config SOC_AMD_COMMON_BLOCK_BANKED_GPIOS
+ bool
+ depends on SOC_AMD_COMMON_BLOCK_ACPIMMIO
+ default n
+ help
+ Select this option to use the newer style banks of GPIO signals.
+ These are at offsets +0x1500, +0x1600, and +0x1700 from the AcpiMmio
+ base.
diff --git a/src/soc/amd/common/block/gpio_banks/Makefile.inc b/src/soc/amd/common/block/gpio_banks/Makefile.inc
new file mode 100644
index 0000000..f1555b1
--- /dev/null
+++ b/src/soc/amd/common/block/gpio_banks/Makefile.inc
@@ -0,0 +1,6 @@
+bootblock-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
+verstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
+romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
+postcar-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
+ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
+smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_BANKED_GPIOS) += gpio.c
diff --git a/src/soc/amd/common/block/gpio_banks/gpio.c b/src/soc/amd/common/block/gpio_banks/gpio.c
new file mode 100644
index 0000000..0f3c2c7
--- /dev/null
+++ b/src/soc/amd/common/block/gpio_banks/gpio.c
@@ -0,0 +1,319 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2015 Google Inc.
+ * Copyright (C) 2015 Intel Corporation
+ * Copyright (C) 2017 Advanced Micro Devices, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <device/mmio.h>
+#include <device/device.h>
+#include <console/console.h>
+#include <gpio.h>
+#include <amdblocks/acpimmio.h>
+#include <soc/gpio.h>
+#include <soc/smi.h>
+#include <assert.h>
+
+extern const struct soc_amd_event gpio_event_table[];
+
+static int get_gpio_gevent(uint8_t gpio)
+{
+ int i;
+ size_t size;
+
+ size = soc_gpio_event_table_size();
+ for (i = 0; i < size; i++) {
+ if (gpio_event_table[i].gpio == gpio)
+ return (int)gpio_event_table[i].event;
+ }
+ return -1;
+}
+
+static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask)
+{
+ uint32_t reg32;
+
+ value &= mask;
+ reg32 = read32(address);
+ reg32 &= ~mask;
+ reg32 |= value;
+ write32(address, reg32);
+}
+
+__weak void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
+{
+ printk(BIOS_WARNING, "Warning: SMI disabled!\n");
+}
+
+static void program_smi(uint32_t flag, int gevent_num)
+{
+ uint32_t trigger;
+
+ trigger = flag & FLAGS_TRIGGER_MASK;
+ /*
+ * Only level trigger is allowed for SMI. Trigger values are 0
+ * through 3, with 0-1 being level trigger and 2-3 being edge
+ * trigger. GPIO_TRIGGER_EDGE_LOW is 2, so trigger has to be
+ * less than GPIO_TRIGGER_EDGE_LOW.
+ */
+ assert(trigger < GPIO_TRIGGER_EDGE_LOW);
+
+ if (trigger == GPIO_TRIGGER_LEVEL_HIGH)
+ configure_gevent_smi(gevent_num, SMI_MODE_SMI,
+ SMI_SCI_LVL_HIGH);
+ if (trigger == GPIO_TRIGGER_LEVEL_LOW)
+ configure_gevent_smi(gevent_num, SMI_MODE_SMI,
+ SMI_SCI_LVL_LOW);
+}
+
+static void route_sci(uint8_t event)
+{
+ smi_write8(SMI_SCI_MAP(event), event);
+}
+
+static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level)
+{
+ uint32_t trigger;
+
+ trigger = flag & FLAGS_TRIGGER_MASK;
+ switch (trigger) {
+ case GPIO_TRIGGER_LEVEL_LOW:
+ *edge = SCI_TRIGGER_LEVEL;
+ *level = 0;
+ break;
+ case GPIO_TRIGGER_LEVEL_HIGH:
+ *edge = SCI_TRIGGER_LEVEL;
+ *level = 1;
+ break;
+ case GPIO_TRIGGER_EDGE_LOW:
+ *edge = SCI_TRIGGER_EDGE;
+ *level = 0;
+ break;
+ case GPIO_TRIGGER_EDGE_HIGH:
+ *edge = SCI_TRIGGER_EDGE;
+ *level = 1;
+ break;
+ default:
+ break;
+ }
+}
+
+uintptr_t gpio_get_address(gpio_t gpio_num)
+{
+ uintptr_t gpio_address;
+
+ if (gpio_num < 64)
+ gpio_address = GPIO_BANK0_CONTROL(gpio_num);
+ else if (gpio_num < 128)
+ gpio_address = GPIO_BANK1_CONTROL(gpio_num);
+ else
+ gpio_address = GPIO_BANK2_CONTROL(gpio_num);
+
+ return gpio_address;
+}
+
+int gpio_get(gpio_t gpio_num)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+
+ return !!(reg & GPIO_PIN_STS);
+}
+
+void gpio_set(gpio_t gpio_num, int value)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+ reg &= ~GPIO_OUTPUT_MASK;
+ reg |= !!value << GPIO_OUTPUT_SHIFT;
+ write32((void *)gpio_address, reg);
+}
+
+void gpio_input_pulldown(gpio_t gpio_num)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+ reg &= ~GPIO_PULLUP_ENABLE;
+ reg |= GPIO_PULLDOWN_ENABLE;
+ write32((void *)gpio_address, reg);
+}
+
+void gpio_input_pullup(gpio_t gpio_num)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+ reg &= ~GPIO_PULLDOWN_ENABLE;
+ reg |= GPIO_PULLUP_ENABLE;
+ write32((void *)gpio_address, reg);
+}
+
+void gpio_input(gpio_t gpio_num)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+ reg &= ~GPIO_OUTPUT_ENABLE;
+ write32((void *)gpio_address, reg);
+}
+
+void gpio_output(gpio_t gpio_num, int value)
+{
+ uint32_t reg;
+ uintptr_t gpio_address = gpio_get_address(gpio_num);
+
+ reg = read32((void *)gpio_address);
+ reg |= GPIO_OUTPUT_ENABLE;
+ write32((void *)gpio_address, reg);
+ gpio_set(gpio_num, value);
+}
+
+const char *gpio_acpi_path(gpio_t gpio)
+{
+ return "\\_SB.GPIO";
+}
+
+uint16_t gpio_acpi_pin(gpio_t gpio)
+{
+ return gpio;
+}
+
+void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
+{
+ uint32_t *gpio_ptr, *inter_master;
+ uint32_t control, control_flags, edge_level, direction;
+ uint32_t mask, bit_edge, bit_level;
+ uint8_t mux, index, gpio;
+ uint8_t event;
+ int gevent_num;
+
+ inter_master = (uint32_t *)(uintptr_t)(ACPIMMIO_GPIO0_BASE
+ + GPIO_MASTER_SWITCH);
+ direction = 0;
+ edge_level = 0;
+ mask = 0;
+
+ /*
+ * Disable blocking wake/interrupt status generation while updating
+ * debounce registers. Otherwise when a debounce register is updated
+ * the whole GPIO controller will zero out all interrupt enable status
+ * bits while the delay happens. This could cause us to drop the bits
+ * due to the read-modify-write that happens on each register.
+ *
+ * Additionally disable interrupt generation so we don't get any
+ * spurious interrupts while updating the registers.
+ */
+ mem_read_write32(inter_master, 0, GPIO_MASK_STS_EN | GPIO_INTERRUPT_EN);
+
+ for (index = 0; index < size; index++) {
+ gpio = gpio_list_ptr[index].gpio;
+ mux = gpio_list_ptr[index].function;
+ control = gpio_list_ptr[index].control;
+ control_flags = gpio_list_ptr[index].flags;
+
+ iomux_write8(gpio, mux & AMD_GPIO_MUX_MASK);
+ iomux_read8(gpio); /* Flush posted write */
+
+ if (soc_override_event(gpio, mux, &event))
+ route_sci(event);
+
+ gpio_ptr = (uint32_t *)gpio_get_address(gpio);
+
+ if (control_flags & GPIO_SPECIAL_FLAG) {
+ gevent_num = get_gpio_gevent(gpio);
+ if (gevent_num < 0) {
+ printk(BIOS_WARNING, "Warning: GPIO pin %d has"
+ " no associated gevent!\n", gpio);
+ continue;
+ }
+ switch (control_flags & GPIO_SPECIAL_MASK) {
+ case GPIO_DEBOUNCE_FLAG:
+ mem_read_write32(gpio_ptr, control,
+ GPIO_DEBOUNCE_MASK);
+ break;
+ case GPIO_WAKE_FLAG:
+ mem_read_write32(gpio_ptr, control,
+ INT_WAKE_MASK);
+ break;
+ case GPIO_INT_FLAG:
+ mem_read_write32(gpio_ptr, control,
+ AMD_GPIO_CONTROL_MASK);
+ break;
+ case GPIO_SMI_FLAG:
+ mem_read_write32(gpio_ptr, control,
+ INT_SCI_SMI_MASK);
+ program_smi(control_flags, gevent_num);
+ break;
+ case GPIO_SCI_FLAG:
+ mem_read_write32(gpio_ptr, control,
+ INT_SCI_SMI_MASK);
+ get_sci_config_bits(control_flags, &bit_edge,
+ &bit_level);
+ edge_level |= bit_edge << gevent_num;
+ direction |= bit_level << gevent_num;
+ mask |= (1 << gevent_num);
+ route_sci(gevent_num);
+ break;
+ default:
+ printk(BIOS_WARNING, "Error, flags 0x%08x\n",
+ control_flags);
+ break;
+ }
+ } else {
+ mem_read_write32(gpio_ptr, control,
+ AMD_GPIO_CONTROL_MASK);
+ }
+ }
+
+ /*
+ * Re-enable interrupt status generation.
+ *
+ * We leave MASK_STATUS disabled because the kernel may reconfigure the
+ * debounce registers while the drivers load. This will cause interrupts
+ * to be missed during boot.
+ */
+ mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN);
+
+ /* Set all SCI trigger direction (high/low) */
+ mem_read_write32((uint32_t *)
+ (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_TRIG),
+ direction, mask);
+
+ /* Set all SCI trigger level (edge/level) */
+ mem_read_write32((uint32_t *)
+ (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_LEVEL),
+ edge_level, mask);
+}
+
+int gpio_interrupt_status(gpio_t gpio)
+{
+ uintptr_t gpio_address = gpio_get_address(gpio);
+ uint32_t reg = read32((void *)gpio_address);
+
+ if (reg & GPIO_INT_STATUS) {
+ /* Clear interrupt status, preserve wake status */
+ reg &= ~GPIO_WAKE_STATUS;
+ write32((void *)gpio_address, reg);
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/soc/amd/common/block/include/amdblocks/gpio.h b/src/soc/amd/common/block/include/amdblocks/gpio.h
new file mode 100644
index 0000000..e6da5c5
--- /dev/null
+++ b/src/soc/amd/common/block/include/amdblocks/gpio.h
@@ -0,0 +1,306 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2018 Silverback, ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __AMDBLOCK_GPIO_H__
+#define __AMDBLOCK_GPIO_H__
+
+#include <stdint.h>
+#include <stddef.h>
+
+struct soc_amd_gpio {
+ uint8_t gpio;
+ uint8_t function;
+ uint32_t control;
+ uint32_t flags;
+};
+
+struct soc_amd_event {
+ uint8_t gpio;
+ uint8_t event;
+};
+
+#define GPIO_BANK0_CONTROL(gpio) (ACPIMMIO_GPIO0_BASE + ((gpio) * 4))
+#define GPIO_BANK1_CONTROL(gpio) (ACPIMMIO_GPIO1_BASE + (((gpio) - 64) * 4))
+#define GPIO_BANK2_CONTROL(gpio) (ACPIMMIO_GPIO2_BASE + (((gpio) - 128) * 4))
+
+#define GPIO_MASTER_SWITCH 0xFC
+#define GPIO_MASK_STS_EN BIT(28)
+#define GPIO_INTERRUPT_EN BIT(30)
+
+#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)
+
+#define GPIO_ACTIVE_HIGH (0 << 9)
+#define GPIO_ACTIVE_LOW (1 << 9)
+#define GPIO_ACTIVE_BOTH (2 << 9)
+#define GPIO_ACTIVE_MASK (3 << 9)
+
+#define GPIO_INT_STATUS_EN (1 << 11)
+#define GPIO_INT_DELIVERY_EN (1 << 12)
+#define GPIO_INTERRUPT_MASK (3 << 11)
+#define GPIO_S0I3_WAKE_EN (1 << 13)
+#define GPIO_S3_WAKE_EN (1 << 14)
+#define GPIO_S4_S5_WAKE_EN (1 << 15)
+
+#define GPIO_PIN_STS (1 << 16)
+#define GPIO_PULLUP_ENABLE (1 << 20)
+#define GPIO_PULLDOWN_ENABLE (1 << 21)
+#define GPIO_OUTPUT_SHIFT 22
+#define GPIO_OUTPUT_MASK (1 << GPIO_OUTPUT_SHIFT)
+#define GPIO_OUTPUT_VALUE (1 << GPIO_OUTPUT_SHIFT)
+#define GPIO_OUTPUT_ENABLE (1 << 23)
+
+#define GPIO_INT_STATUS (1 << 28)
+#define GPIO_WAKE_STATUS (1 << 29)
+
+enum {
+ GEVENT_0,
+ GEVENT_1,
+ GEVENT_2,
+ GEVENT_3,
+ GEVENT_4,
+ GEVENT_5,
+ GEVENT_6,
+ GEVENT_7,
+ GEVENT_8,
+ GEVENT_9,
+ GEVENT_10,
+ GEVENT_11,
+ GEVENT_12,
+ GEVENT_13,
+ GEVENT_14,
+ GEVENT_15,
+ GEVENT_16,
+ GEVENT_17,
+ GEVENT_18,
+ GEVENT_19,
+ GEVENT_20,
+ GEVENT_21,
+ GEVENT_22,
+ GEVENT_23,
+ GEVENT_24,
+ GEVENT_25,
+ GEVENT_26,
+ GEVENT_27,
+ GEVENT_28,
+ GEVENT_29,
+ GEVENT_30,
+ GEVENT_31,
+};
+
+#define GPIO_OUTPUT_OUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_VALUE)
+#define GPIO_OUTPUT_OUT_LOW GPIO_OUTPUT_ENABLE
+
+#define GPIO_PULL_PULL_UP GPIO_PULLUP_ENABLE
+#define GPIO_PULL_PULL_DOWN GPIO_PULLDOWN_ENABLE
+#define GPIO_PULL_PULL_NONE 0
+
+#define AMD_GPIO_CONTROL_MASK 0x00f4ff00
+#define AMD_GPIO_MUX_MASK 0x03
+
+/* Definitions for PAD_INT. */
+#define GPIO_INT_EDGE_HIGH (GPIO_ACTIVE_HIGH | GPIO_EDGE_TRIG)
+#define GPIO_INT_EDGE_LOW (GPIO_ACTIVE_LOW | GPIO_EDGE_TRIG)
+#define GPIO_INT_BOTH_EDGES (GPIO_ACTIVE_BOTH | GPIO_EDGE_TRIG)
+#define GPIO_INT_LEVEL_HIGH (GPIO_ACTIVE_HIGH | GPIO_LEVEL_TRIG)
+#define GPIO_INT_LEVEL_LOW (GPIO_ACTIVE_LOW | GPIO_LEVEL_TRIG)
+
+enum {
+ GPIO_TRIGGER_LEVEL_LOW,
+ GPIO_TRIGGER_LEVEL_HIGH,
+ GPIO_TRIGGER_EDGE_LOW,
+ GPIO_TRIGGER_EDGE_HIGH,
+};
+
+#define GPIO_TRIGGER_INVALID -1
+#define SCI_TRIGGER_EDGE 0
+#define SCI_TRIGGER_LEVEL 1
+
+#define GPIO_SPECIAL_FLAG (1 << 31)
+#define GPIO_DEBOUNCE_FLAG (1 << 30)
+#define GPIO_WAKE_FLAG (1 << 29)
+#define GPIO_INT_FLAG (1 << 28)
+#define GPIO_SMI_FLAG (1 << 27)
+#define GPIO_SCI_FLAG (1 << 26)
+#define GPIO_FLAG_DEBOUNCE (GPIO_SPECIAL_FLAG | GPIO_DEBOUNCE_FLAG)
+#define GPIO_FLAG_WAKE (GPIO_SPECIAL_FLAG | GPIO_WAKE_FLAG)
+#define GPIO_FLAG_INT (GPIO_SPECIAL_FLAG | GPIO_INT_FLAG)
+#define GPIO_FLAG_SCI (GPIO_SPECIAL_FLAG | GPIO_SCI_FLAG)
+#define GPIO_FLAG_SMI (GPIO_SPECIAL_FLAG | GPIO_SMI_FLAG)
+
+#define FLAGS_TRIGGER_MASK 0x00000003
+#define GPIO_SPECIAL_MASK 0x7c000000
+#define GPIO_DEBOUNCE_MASK 0x000000ff
+#define INT_TRIGGER_MASK 0x00000700
+#define INT_WAKE_MASK 0x0000e700
+#define INT_SCI_SMI_MASK 0x00f40000
+
+#define IN_GLITCH_SHIFT 5
+#define GLITCH_LOW 1
+#define GLITCH_HIGH 2
+#define GLITCH_NONE 3
+#define GPIO_IN_PRESERVE_LOW_GLITCH (GLITCH_LOW << IN_GLITCH_SHIFT)
+#define GPIO_IN_PRESERVE_HIGH_GLITCH (GLITCH_HIGH << IN_GLITCH_SHIFT)
+#define GPIO_IN_REMOVE_GLITCH (GLITCH_NONE << IN_GLITCH_SHIFT)
+
+#define GPIO_TIMEBASE_61uS 0
+#define GPIO_TIMEBASE_183uS (1 << 4)
+#define GPIO_TIMEBASE_15560uS (1 << 7)
+#define GPIO_TIMEBASE_62440uS (GPIO_TIMEBASE_183uS | \
+ GPIO_TIMEBASE_15560uS)
+#define GPIO_IN_DEBOUNCE_DISABLED (0 | GPIO_TIMEBASE_61uS)
+#define GPIO_IN_60uS (1 | GPIO_TIMEBASE_61uS)
+#define GPIO_IN_120uS (2 | GPIO_TIMEBASE_61uS)
+#define GPIO_IN_200uS (3 | GPIO_TIMEBASE_61uS)
+#define GPIO_IN_500uS (8 | GPIO_TIMEBASE_61uS)
+#define GPIO_IN_1mS (5 | GPIO_TIMEBASE_183uS)
+#define GPIO_IN_2mS (11 | GPIO_TIMEBASE_183uS)
+#define GPIO_IN_15mS (1 | GPIO_TIMEBASE_15560uS)
+#define GPIO_IN_50mS (3 | GPIO_TIMEBASE_15560uS)
+#define GPIO_IN_100mS (6 | GPIO_TIMEBASE_15560uS)
+#define GPIO_IN_200mS (13 | GPIO_TIMEBASE_15560uS)
+#define GPIO_IN_500mS (8 | GPIO_TIMEBASE_62440uS)
+
+#define GPIO_EVENT_INT_STATUS GPIO_INT_STATUS_EN
+#define GPIO_EVENT_INT_DELIVER GPIO_INT_DELIVERY_EN
+#define GPIO_EVENT_INT_STATUS_DELIVER (GPIO_INT_STATUS_EN | \
+ GPIO_INT_DELIVERY_EN)
+#define GPIO_WAKE_S0i3 (1 << 13)
+#define GPIO_WAKE_S3 (1 << 14)
+#define GPIO_WAKE_S4_S5 (1 << 15)
+#define GPIO_WAKE_S0i3_S4_S5 (GPIO_WAKE_S0i3 | GPIO_WAKE_S4_S5)
+#define GPIO_WAKE_S3_S4_S5 (GPIO_WAKE_S3 | GPIO_WAKE_S4_S5)
+
+/*
+ * Several macros are available to declare programming of GPIO pins, and if
+ * needed, more than 1 macro can be used for any pin. However, some macros
+ * will have no effect if combined. For example debounce only affects input
+ * or one of the interrupts. Some macros should not be combined, such as SMI
+ * and regular interrupt. The defined macros and their parameters are:
+ * PAD_NF Define native alternate function for the pin.
+ * pin the pin to be programmed
+ * function the native function
+ * pull pull up, pull down or no pull
+ * PAD_GPI The pin is a GPIO input
+ * pin the pin to be programmed
+ * pull pull up, pull down or no pull
+ * PAD_GPO The pin is a GPIO output
+ * pin the pin to be programmed
+ * direction high or low
+ * PAD_INT The pin is regular interrupt that works while booting
+ * pin the pin to be programmed
+ * pull pull up, pull down or no pull
+ * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
+ * action STATUS, DELIVER, STATUS_DELIVER
+ * PAD_SCI The pin is a SCI source
+ * pin the pin to be programmed
+ * pull pull up, pull down or no pull
+ * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH
+ * PAD_SMI The pin is a SMI source
+ * pin the pin to be programmed
+ * pull pull up, pull down or no pull
+ * trigger LEVEL_LOW, LEVEL_HIGH
+ * PAD_WAKE The pin can wake, use after PAD_INT or PAD_SCI
+ * pin the pin to be programmed
+ * pull pull up, pull down or no pull
+ * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
+ * type S0i3, S3, S4_S5 or S4_S5 combinations (S0i3_S3 invalid)
+ * PAD_DEBOUNCE The input or interrupt will be debounced, invalid after
+ * PAD_NF
+ * pin the pin to be programmed
+ * debounce_type preserve low glitch, preserve high glitch, no glitch
+ * debounce_time the debounce time
+ */
+
+/* Native function pad configuration */
+#define PAD_NF(pin, func, pull) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## func, \
+ .control = GPIO_PULL ## _ ## pull, \
+ .flags = 0 }
+/* General purpose input pad configuration */
+#define PAD_GPI(pin, pull) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = GPIO_PULL ## _ ## pull, \
+ .flags = 0 }
+/* General purpose output pad configuration */
+#define PAD_GPO(pin, direction) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = GPIO_OUTPUT ## _OUT_ ## direction, \
+ .flags = 0 }
+/* Auxiliary macro for legacy interrupt and wake */
+#define PAD_AUX1(pull, trigger) (GPIO_PULL ## _ ## pull | \
+ GPIO_INT ## _ ## trigger)
+/* Legacy interrupt pad configuration */
+#define PAD_INT(pin, pull, trigger, action) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = (PAD_AUX1(pull, trigger) | \
+ GPIO_EVENT_INT ## _ ## action), \
+ .flags = GPIO_FLAG_INT }
+/* Auxiliary macro for SCI and SMI */
+#define PAD_AUX2(trigger, flag) (GPIO_TRIGGER ## _ ## trigger | flag)
+/* SCI pad configuration */
+#define PAD_SCI(pin, pull, trigger) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = GPIO_PULL ## _ ## pull, \
+ .flags = PAD_AUX2(trigger, GPIO_FLAG_SCI) }
+/* SMI pad configuration */
+#define PAD_SMI(pin, pull, trigger) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = GPIO_PULL ## _ ## pull, \
+ .flags = PAD_AUX2(trigger, GPIO_FLAG_SMI) }
+/* WAKE pad configuration */
+#define PAD_WAKE(pin, pull, trigger, type) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = (PAD_AUX1(pull, trigger) | \
+ GPIO_WAKE ## _ ## type), \
+ .flags = GPIO_FLAG_WAKE }
+/* pin debounce configuration */
+#define PAD_DEBOUNCE(pin, type, time) \
+ { .gpio = (pin), \
+ .function = pin ## _IOMUX_ ## GPIOxx, \
+ .control = (GPIO_IN ## _ ## type | GPIO_IN ## _ ## time), \
+ .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
+ *
+ * @param gpio_list_ptr = pointer to array of gpio configurations
+ * @param size = number of entries in array
+ *
+ * @return none
+ */
+void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size);
+/* Return the interrupt status and clear if set. */
+int gpio_interrupt_status(gpio_t gpio);
+size_t soc_gpio_event_table_size(void);
+int soc_override_event(uint8_t gpio, uint8_t mux, uint8_t *event);
+
+#endif /* __AMDBLOCK_GPIO_H__ */
diff --git a/src/soc/amd/stoneyridge/Kconfig b/src/soc/amd/stoneyridge/Kconfig
index d4e1feb..5333f59 100644
--- a/src/soc/amd/stoneyridge/Kconfig
+++ b/src/soc/amd/stoneyridge/Kconfig
@@ -47,6 +47,7 @@
select SOC_AMD_COMMON
select SOC_AMD_COMMON_BLOCK
select SOC_AMD_COMMON_BLOCK_ACPIMMIO
+ select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS
select SOC_AMD_COMMON_BLOCK_PCI
select SOC_AMD_COMMON_BLOCK_PI
select SOC_AMD_COMMON_BLOCK_PSP
diff --git a/src/soc/amd/stoneyridge/acpi.c b/src/soc/amd/stoneyridge/acpi.c
index 4f11ea2..2cd9632 100644
--- a/src/soc/amd/stoneyridge/acpi.c
+++ b/src/soc/amd/stoneyridge/acpi.c
@@ -317,9 +317,9 @@

static int acpigen_soc_get_gpio_val(unsigned int gpio_num, uint32_t mask)
{
- if (gpio_num >= GPIO_TOTAL_PINS) {
+ if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
- " %d\n", gpio_num, GPIO_TOTAL_PINS);
+ " %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
return -1;
}
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
@@ -347,9 +347,9 @@

static int acpigen_soc_set_gpio_val(unsigned int gpio_num, uint32_t val)
{
- if (gpio_num >= GPIO_TOTAL_PINS) {
+ if (gpio_num >= SOC_GPIO_TOTAL_PINS) {
printk(BIOS_WARNING, "Warning: Pin %d should be smaller than"
- " %d\n", gpio_num, GPIO_TOTAL_PINS);
+ " %d\n", gpio_num, SOC_GPIO_TOTAL_PINS);
return -1;
}
uintptr_t addr = (uintptr_t) gpio_get_address(gpio_num);
diff --git a/src/soc/amd/stoneyridge/acpi/soc.asl b/src/soc/amd/stoneyridge/acpi/soc.asl
index 6fd838a..52c7ee6 100644
--- a/src/soc/amd/stoneyridge/acpi/soc.asl
+++ b/src/soc/amd/stoneyridge/acpi/soc.asl
@@ -28,4 +28,4 @@
#include "sb_fch.asl"

/* Add GPIO library */
-#include <gpio_lib.asl>
+#include <soc/amd/common/acpi/gpio_bank_lib.asl>
diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c
index 7c96805..0800a5a 100644
--- a/src/soc/amd/stoneyridge/gpio.c
+++ b/src/soc/amd/stoneyridge/gpio.c
@@ -15,16 +15,11 @@
* GNU General Public License for more details.
*/

-#include <device/mmio.h>
-#include <device/device.h>
-#include <console/console.h>
-#include <gpio.h>
-#include <amdblocks/acpimmio.h>
+#include <stdint.h>
+#include <amdblocks/gpio.h>
#include <soc/gpio.h>
-#include <assert.h>
-#include "chip.h"

-static const struct soc_amd_event gpio_event_table[] = {
+const struct soc_amd_event gpio_event_table[] = {
{ GPIO_1, GEVENT_19 },
{ GPIO_2, GEVENT_8 },
{ GPIO_3, GEVENT_2 },
@@ -51,288 +46,16 @@
{ GPIO_69, GEVENT_17 },
};

-static int get_gpio_gevent(uint8_t gpio)
+size_t soc_gpio_event_table_size(void)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(gpio_event_table); i++) {
- if (gpio_event_table[i].gpio == gpio)
- return (int)gpio_event_table[i].event;
- }
- return -1;
+ return ARRAY_SIZE(gpio_event_table);
}

-static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask)
+int soc_override_event(uint8_t gpio, uint8_t mux, uint8_t *event)
{
- uint32_t reg32;
-
- value &= mask;
- reg32 = read32(address);
- reg32 &= ~mask;
- reg32 |= value;
- write32(address, reg32);
-}
-
-__weak void configure_gevent_smi(uint8_t gevent, uint8_t mode, uint8_t level)
-{
- printk(BIOS_WARNING, "Warning: SMI disabled!\n");
-}
-
-static void program_smi(uint32_t flag, int gevent_num)
-{
- uint32_t trigger;
-
- trigger = flag & FLAGS_TRIGGER_MASK;
- /*
- * Only level trigger is allowed for SMI. Trigger values are 0
- * through 3, with 0-1 being level trigger and 2-3 being edge
- * trigger. GPIO_TRIGGER_EDGE_LOW is 2, so trigger has to be
- * less than GPIO_TRIGGER_EDGE_LOW.
- */
- assert(trigger < GPIO_TRIGGER_EDGE_LOW);
-
- if (trigger == GPIO_TRIGGER_LEVEL_HIGH)
- configure_gevent_smi(gevent_num, SMI_MODE_SMI,
- SMI_SCI_LVL_HIGH);
- if (trigger == GPIO_TRIGGER_LEVEL_LOW)
- configure_gevent_smi(gevent_num, SMI_MODE_SMI,
- SMI_SCI_LVL_LOW);
-}
-
-static void route_sci(uint8_t event)
-{
- smi_write8(SMI_SCI_MAP(event), event);
-}
-
-static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level)
-{
- uint32_t trigger;
-
- trigger = flag & FLAGS_TRIGGER_MASK;
- switch (trigger) {
- case GPIO_TRIGGER_LEVEL_LOW:
- *edge = SCI_TRIGGER_LEVEL;
- *level = 0;
- break;
- case GPIO_TRIGGER_LEVEL_HIGH:
- *edge = SCI_TRIGGER_LEVEL;
- *level = 1;
- break;
- case GPIO_TRIGGER_EDGE_LOW:
- *edge = SCI_TRIGGER_EDGE;
- *level = 0;
- break;
- case GPIO_TRIGGER_EDGE_HIGH:
- *edge = SCI_TRIGGER_EDGE;
- *level = 1;
- break;
- default:
- break;
- }
-}
-
-uintptr_t gpio_get_address(gpio_t gpio_num)
-{
- uintptr_t gpio_address;
-
- if (gpio_num < 64)
- gpio_address = GPIO_BANK0_CONTROL(gpio_num);
- else if (gpio_num < 128)
- gpio_address = GPIO_BANK1_CONTROL(gpio_num);
- else
- gpio_address = GPIO_BANK2_CONTROL(gpio_num);
-
- return gpio_address;
-}
-
-int gpio_get(gpio_t gpio_num)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
-
- return !!(reg & GPIO_PIN_STS);
-}
-
-void gpio_set(gpio_t gpio_num, int value)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
- reg &= ~GPIO_OUTPUT_MASK;
- reg |= !!value << GPIO_OUTPUT_SHIFT;
- write32((void *)gpio_address, reg);
-}
-
-void gpio_input_pulldown(gpio_t gpio_num)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
- reg &= ~GPIO_PULLUP_ENABLE;
- reg |= GPIO_PULLDOWN_ENABLE;
- write32((void *)gpio_address, reg);
-}
-
-void gpio_input_pullup(gpio_t gpio_num)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
- reg &= ~GPIO_PULLDOWN_ENABLE;
- reg |= GPIO_PULLUP_ENABLE;
- write32((void *)gpio_address, reg);
-}
-
-void gpio_input(gpio_t gpio_num)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
- reg &= ~GPIO_OUTPUT_ENABLE;
- write32((void *)gpio_address, reg);
-}
-
-void gpio_output(gpio_t gpio_num, int value)
-{
- uint32_t reg;
- uintptr_t gpio_address = gpio_get_address(gpio_num);
-
- reg = read32((void *)gpio_address);
- reg |= GPIO_OUTPUT_ENABLE;
- write32((void *)gpio_address, reg);
- gpio_set(gpio_num, value);
-}
-
-const char *gpio_acpi_path(gpio_t gpio)
-{
- return "\\_SB.GPIO";
-}
-
-uint16_t gpio_acpi_pin(gpio_t gpio)
-{
- return gpio;
-}
-
-void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
-{
- uint32_t *gpio_ptr, *inter_master;
- uint32_t control, control_flags, edge_level, direction;
- uint32_t mask, bit_edge, bit_level;
- uint8_t mux, index, gpio;
- int gevent_num;
-
- inter_master = (uint32_t *)(uintptr_t)(ACPIMMIO_GPIO0_BASE
- + GPIO_MASTER_SWITCH);
- direction = 0;
- edge_level = 0;
- mask = 0;
-
- /*
- * Disable blocking wake/interrupt status generation while updating
- * debounce registers. Otherwise when a debounce register is updated
- * the whole GPIO controller will zero out all interrupt enable status
- * bits while the delay happens. This could cause us to drop the bits
- * due to the read-modify-write that happens on each register.
- *
- * Additionally disable interrupt generation so we don't get any
- * spurious interrupts while updating the registers.
- */
- mem_read_write32(inter_master, 0, GPIO_MASK_STS_EN | GPIO_INTERRUPT_EN);
-
- for (index = 0; index < size; index++) {
- gpio = gpio_list_ptr[index].gpio;
- mux = gpio_list_ptr[index].function;
- control = gpio_list_ptr[index].control;
- control_flags = gpio_list_ptr[index].flags;
-
- iomux_write8(gpio, mux & AMD_GPIO_MUX_MASK);
- iomux_read8(gpio); /* Flush posted write */
- /* special case if pin 2 is assigned to wake */
- if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK))
- route_sci(GPIO_2_EVENT);
- gpio_ptr = (uint32_t *)gpio_get_address(gpio);
-
- if (control_flags & GPIO_SPECIAL_FLAG) {
- gevent_num = get_gpio_gevent(gpio);
- if (gevent_num < 0) {
- printk(BIOS_WARNING, "Warning: GPIO pin %d has"
- " no associated gevent!\n", gpio);
- continue;
- }
- switch (control_flags & GPIO_SPECIAL_MASK) {
- case GPIO_DEBOUNCE_FLAG:
- mem_read_write32(gpio_ptr, control,
- GPIO_DEBOUNCE_MASK);
- break;
- case GPIO_WAKE_FLAG:
- mem_read_write32(gpio_ptr, control,
- INT_WAKE_MASK);
- break;
- case GPIO_INT_FLAG:
- mem_read_write32(gpio_ptr, control,
- AMD_GPIO_CONTROL_MASK);
- break;
- case GPIO_SMI_FLAG:
- mem_read_write32(gpio_ptr, control,
- INT_SCI_SMI_MASK);
- program_smi(control_flags, gevent_num);
- break;
- case GPIO_SCI_FLAG:
- mem_read_write32(gpio_ptr, control,
- INT_SCI_SMI_MASK);
- get_sci_config_bits(control_flags, &bit_edge,
- &bit_level);
- edge_level |= bit_edge << gevent_num;
- direction |= bit_level << gevent_num;
- mask |= (1 << gevent_num);
- route_sci(gevent_num);
- break;
- default:
- printk(BIOS_WARNING, "Error, flags 0x%08x\n",
- control_flags);
- break;
- }
- } else {
- mem_read_write32(gpio_ptr, control,
- AMD_GPIO_CONTROL_MASK);
- }
- }
-
- /*
- * Re-enable interrupt status generation.
- *
- * We leave MASK_STATUS disabled because the kernel may reconfigure the
- * debounce registers while the drivers load. This will cause interrupts
- * to be missed during boot.
- */
- mem_read_write32(inter_master, GPIO_INTERRUPT_EN, GPIO_INTERRUPT_EN);
-
- /* Set all SCI trigger direction (high/low) */
- mem_read_write32((uint32_t *)
- (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_TRIG),
- direction, mask);
-
- /* Set all SCI trigger level (edge/level) */
- mem_read_write32((uint32_t *)
- (uintptr_t)(ACPIMMIO_SMI_BASE + SMI_SCI_LEVEL),
- edge_level, mask);
-}
-
-int gpio_interrupt_status(gpio_t gpio)
-{
- uintptr_t gpio_address = gpio_get_address(gpio);
- uint32_t reg = read32((void *)gpio_address);
-
- if (reg & GPIO_INT_STATUS) {
- /* Clear interrupt status, preserve wake status */
- reg &= ~GPIO_WAKE_STATUS;
- write32((void *)gpio_address, reg);
+ /* special case if pin 2 is assigned to wake */
+ if ((gpio == 2) && !(mux & AMD_GPIO_MUX_MASK)) {
+ *event = GPIO_2_EVENT;
return 1;
}

diff --git a/src/soc/amd/stoneyridge/i2c.c b/src/soc/amd/stoneyridge/i2c.c
index c3e5539..7f65a4f 100644
--- a/src/soc/amd/stoneyridge/i2c.c
+++ b/src/soc/amd/stoneyridge/i2c.c
@@ -203,7 +203,7 @@
/* Save and reprogram I2C SCL pins */
for (i = 0; i < saved_pins_count; i++)
save_i2c_pin_registers(i2c_2_gpi[i].gpio, &save_table[i]);
- sb_program_gpios(i2c_2_gpi, saved_pins_count);
+ program_gpios(i2c_2_gpi, saved_pins_count);

/*
* Toggle SCL back and forth 9 times under 100KHz. A single read is
diff --git a/src/soc/amd/stoneyridge/include/soc/gpio.h b/src/soc/amd/stoneyridge/include/soc/gpio.h
index 26d0336..7d15609 100644
--- a/src/soc/amd/stoneyridge/include/soc/gpio.h
+++ b/src/soc/amd/stoneyridge/include/soc/gpio.h
@@ -21,59 +21,13 @@

#ifndef __ACPI__
#include <soc/iomap.h>
-#include <soc/smi.h>
-#include <types.h>
+#include <amdblocks/gpio.h>

-struct soc_amd_gpio {
- uint8_t gpio;
- uint8_t function;
- uint32_t control;
- uint32_t flags;
-};
+/* The following sections describe only the GPIOs defined for this SOC */

-struct soc_amd_event {
- uint8_t gpio;
- uint8_t event;
-};
+#define SOC_GPIO_TOTAL_PINS 149

-#define GPIO_MASTER_SWITCH 0xFC
-#define GPIO_MASK_STS_EN BIT(28)
-#define GPIO_INTERRUPT_EN BIT(30)
-
-#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)
-
-#define GPIO_ACTIVE_HIGH (0 << 9)
-#define GPIO_ACTIVE_LOW (1 << 9)
-#define GPIO_ACTIVE_BOTH (2 << 9)
-#define GPIO_ACTIVE_MASK (3 << 9)
-
-#define GPIO_INT_STATUS_EN (1 << 11)
-#define GPIO_INT_DELIVERY_EN (1 << 12)
-#define GPIO_INTERRUPT_MASK (3 << 11)
-#define GPIO_S0I3_WAKE_EN (1 << 13)
-#define GPIO_S3_WAKE_EN (1 << 14)
-#define GPIO_S4_S5_WAKE_EN (1 << 15)
-
-#define GPIO_PIN_STS (1 << 16)
-#define GPIO_PULLUP_ENABLE (1 << 20)
-#define GPIO_PULLDOWN_ENABLE (1 << 21)
-#define GPIO_OUTPUT_SHIFT 22
-#define GPIO_OUTPUT_MASK (1 << GPIO_OUTPUT_SHIFT)
-#define GPIO_OUTPUT_VALUE (1 << GPIO_OUTPUT_SHIFT)
-#define GPIO_OUTPUT_ENABLE (1 << 23)
-
-#define GPIO_INT_STATUS (1 << 28)
-#define GPIO_WAKE_STATUS (1 << 29)
-
-/* GPIO_0 - GPIO_62 */
-#define GPIO_BANK0_CONTROL(gpio) \
- (AMD_SB_ACPI_MMIO_ADDR + 0x1500 + ((gpio) * 4))
+/* Bank 0: GPIO_0 - GPIO_62 */
#define GPIO_0 0
#define GPIO_1 1
#define GPIO_2 2
@@ -105,9 +59,7 @@
#define GPIO_40 40
#define GPIO_42 42

-/* GPIO_64 - GPIO_127 */
-#define GPIO_BANK1_CONTROL(gpio) \
- (AMD_SB_ACPI_MMIO_ADDR + 0x1600 + (((gpio) - 64) * 4))
+/* Bank 1: GPIO_64 - GPIO_127 */
#define GPIO_64 64
#define GPIO_65 65
#define GPIO_66 66
@@ -150,10 +102,7 @@
#define GPIO_122 122
#define GPIO_126 126

-/* GPIO_128 - GPIO_183 */
-#define GPIO_BANK2_CONTROL(gpio) \
- (AMD_SB_ACPI_MMIO_ADDR + 0x1700 + (((gpio) - 128) * 4))
-/* GPIO_128 Reserved */
+/* Bank 2: GPIO_128 - GPIO_183 */
#define GPIO_129 129
#define GPIO_130 130
#define GPIO_131 131
@@ -353,230 +302,7 @@
#define GPIO_148_IOMUX_I2C1_SDA 0
#define GPIO_148_IOMUX_GPIOxx 1

-enum {
- GEVENT_0,
- GEVENT_1,
- GEVENT_2,
- GEVENT_3,
- GEVENT_4,
- GEVENT_5,
- GEVENT_6,
- GEVENT_7,
- GEVENT_8,
- GEVENT_9,
- GEVENT_10,
- GEVENT_11,
- GEVENT_12,
- GEVENT_13,
- GEVENT_14,
- GEVENT_15,
- GEVENT_16,
- GEVENT_17,
- GEVENT_18,
- GEVENT_19,
- GEVENT_20,
- GEVENT_21,
- GEVENT_22,
- GEVENT_23,
-};
#define GPIO_2_EVENT GEVENT_8

-#define GPIO_OUTPUT_OUT_HIGH (GPIO_OUTPUT_ENABLE | GPIO_OUTPUT_VALUE)
-#define GPIO_OUTPUT_OUT_LOW GPIO_OUTPUT_ENABLE
-
-#define GPIO_PULL_PULL_UP GPIO_PULLUP_ENABLE
-#define GPIO_PULL_PULL_DOWN GPIO_PULLDOWN_ENABLE
-#define GPIO_PULL_PULL_NONE 0
-
-#define AMD_GPIO_CONTROL_MASK 0x00f4ff00
-#define AMD_GPIO_MUX_MASK 0x03
-
-/* Definitions for PAD_INT. */
-#define GPIO_INT_EDGE_HIGH (GPIO_ACTIVE_HIGH | GPIO_EDGE_TRIG)
-#define GPIO_INT_EDGE_LOW (GPIO_ACTIVE_LOW | GPIO_EDGE_TRIG)
-#define GPIO_INT_BOTH_EDGES (GPIO_ACTIVE_BOTH | GPIO_EDGE_TRIG)
-#define GPIO_INT_LEVEL_HIGH (GPIO_ACTIVE_HIGH | GPIO_LEVEL_TRIG)
-#define GPIO_INT_LEVEL_LOW (GPIO_ACTIVE_LOW | GPIO_LEVEL_TRIG)
-
-enum {
- GPIO_TRIGGER_LEVEL_LOW,
- GPIO_TRIGGER_LEVEL_HIGH,
- GPIO_TRIGGER_EDGE_LOW,
- GPIO_TRIGGER_EDGE_HIGH,
-};
-
-#define GPIO_TRIGGER_INVALID -1
-#define SCI_TRIGGER_EDGE 0
-#define SCI_TRIGGER_LEVEL 1
-
-#define GPIO_SPECIAL_FLAG (1 << 31)
-#define GPIO_DEBOUNCE_FLAG (1 << 30)
-#define GPIO_WAKE_FLAG (1 << 29)
-#define GPIO_INT_FLAG (1 << 28)
-#define GPIO_SMI_FLAG (1 << 27)
-#define GPIO_SCI_FLAG (1 << 26)
-#define GPIO_FLAG_DEBOUNCE (GPIO_SPECIAL_FLAG | GPIO_DEBOUNCE_FLAG)
-#define GPIO_FLAG_WAKE (GPIO_SPECIAL_FLAG | GPIO_WAKE_FLAG)
-#define GPIO_FLAG_INT (GPIO_SPECIAL_FLAG | GPIO_INT_FLAG)
-#define GPIO_FLAG_SCI (GPIO_SPECIAL_FLAG | GPIO_SCI_FLAG)
-#define GPIO_FLAG_SMI (GPIO_SPECIAL_FLAG | GPIO_SMI_FLAG)
-
-#define FLAGS_TRIGGER_MASK 0x00000003
-#define GPIO_SPECIAL_MASK 0x7c000000
-#define GPIO_DEBOUNCE_MASK 0x000000ff
-#define INT_TRIGGER_MASK 0x00000700
-#define INT_WAKE_MASK 0x0000e700
-#define INT_SCI_SMI_MASK 0x00f40000
-
-#define IN_GLITCH_SHIFT 5
-#define GLITCH_LOW 1
-#define GLITCH_HIGH 2
-#define GLITCH_NONE 3
-#define GPIO_IN_PRESERVE_LOW_GLITCH (GLITCH_LOW << IN_GLITCH_SHIFT)
-#define GPIO_IN_PRESERVE_HIGH_GLITCH (GLITCH_HIGH << IN_GLITCH_SHIFT)
-#define GPIO_IN_REMOVE_GLITCH (GLITCH_NONE << IN_GLITCH_SHIFT)
-
-#define GPIO_TIMEBASE_61uS 0
-#define GPIO_TIMEBASE_183uS (1 << 4)
-#define GPIO_TIMEBASE_15560uS (1 << 7)
-#define GPIO_TIMEBASE_62440uS (GPIO_TIMEBASE_183uS | \
- GPIO_TIMEBASE_15560uS)
-#define GPIO_IN_DEBOUNCE_DISABLED (0 | GPIO_TIMEBASE_61uS)
-#define GPIO_IN_60uS (1 | GPIO_TIMEBASE_61uS)
-#define GPIO_IN_120uS (2 | GPIO_TIMEBASE_61uS)
-#define GPIO_IN_200uS (3 | GPIO_TIMEBASE_61uS)
-#define GPIO_IN_500uS (8 | GPIO_TIMEBASE_61uS)
-#define GPIO_IN_1mS (5 | GPIO_TIMEBASE_183uS)
-#define GPIO_IN_2mS (11 | GPIO_TIMEBASE_183uS)
-#define GPIO_IN_15mS (1 | GPIO_TIMEBASE_15560uS)
-#define GPIO_IN_50mS (3 | GPIO_TIMEBASE_15560uS)
-#define GPIO_IN_100mS (6 | GPIO_TIMEBASE_15560uS)
-#define GPIO_IN_200mS (13 | GPIO_TIMEBASE_15560uS)
-#define GPIO_IN_500mS (8 | GPIO_TIMEBASE_62440uS)
-
-#define GPIO_EVENT_INT_STATUS GPIO_INT_STATUS_EN
-#define GPIO_EVENT_INT_DELIVER GPIO_INT_DELIVERY_EN
-#define GPIO_EVENT_INT_STATUS_DELIVER (GPIO_INT_STATUS_EN | \
- GPIO_INT_DELIVERY_EN)
-#define GPIO_WAKE_S0i3 (1 << 13)
-#define GPIO_WAKE_S3 (1 << 14)
-#define GPIO_WAKE_S4_S5 (1 << 15)
-#define GPIO_WAKE_S0i3_S4_S5 (GPIO_WAKE_S0i3 | GPIO_WAKE_S4_S5)
-#define GPIO_WAKE_S3_S4_S5 (GPIO_WAKE_S3 | GPIO_WAKE_S4_S5)
-
-/*
- * Several macros are available to declare programming of GPIO pins, and if
- * needed, more than 1 macro can be used for any pin. However, some macros
- * will have no effect if combined. For example debounce only affects input
- * or one of the interrupts. Some macros should not be combined, such as SMI
- * and regular interrupt. The defined macros and their parameters are:
- * PAD_NF Define native alternate function for the pin.
- * pin the pin to be programmed
- * function the native function
- * pull pull up, pull down or no pull
- * PAD_GPI The pin is a GPIO input
- * pin the pin to be programmed
- * pull pull up, pull down or no pull
- * PAD_GPO The pin is a GPIO output
- * pin the pin to be programmed
- * direction high or low
- * PAD_INT The pin is regular interrupt that works while booting
- * pin the pin to be programmed
- * pull pull up, pull down or no pull
- * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
- * action STATUS, DELIVER, STATUS_DELIVER
- * PAD_SCI The pin is a SCI source
- * pin the pin to be programmed
- * pull pull up, pull down or no pull
- * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH
- * PAD_SMI The pin is a SMI source
- * pin the pin to be programmed
- * pull pull up, pull down or no pull
- * trigger LEVEL_LOW, LEVEL_HIGH
- * PAD_WAKE The pin can wake, use after PAD_INT or PAD_SCI
- * pin the pin to be programmed
- * pull pull up, pull down or no pull
- * trigger LEVEL_LOW, LEVEL_HIGH, EDGE_LOW, EDGE_HIGH, BOTH_EDGES
- * type S0i3, S3, S4_S5 or S4_S5 combinations (S0i3_S3 invalid)
- * PAD_DEBOUNCE The input or interrupt will be debounced, invalid after
- * PAD_NF
- * pin the pin to be programmed
- * debounce_type preserve low glitch, preserve high glitch, no glitch
- * debounce_time the debounce time
- */
-
-/* Native function pad configuration */
-#define PAD_NF(pin, func, pull) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## func, \
- .control = GPIO_PULL ## _ ## pull, \
- .flags = 0 }
-/* General purpose input pad configuration */
-#define PAD_GPI(pin, pull) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = GPIO_PULL ## _ ## pull, \
- .flags = 0 }
-/* General purpose output pad configuration */
-#define PAD_GPO(pin, direction) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = GPIO_OUTPUT ## _OUT_ ## direction, \
- .flags = 0 }
-/* Auxiliary macro for legacy interrupt and wake */
-#define PAD_AUX1(pull, trigger) (GPIO_PULL ## _ ## pull | \
- GPIO_INT ## _ ## trigger)
-/* Legacy interrupt pad configuration */
-#define PAD_INT(pin, pull, trigger, action) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = (PAD_AUX1(pull, trigger) | \
- GPIO_EVENT_INT ## _ ## action), \
- .flags = GPIO_FLAG_INT }
-/* Auxiliary macro for SCI and SMI */
-#define PAD_AUX2(trigger, flag) (GPIO_TRIGGER ## _ ## trigger | flag)
-/* SCI pad configuration */
-#define PAD_SCI(pin, pull, trigger) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = GPIO_PULL ## _ ## pull, \
- .flags = PAD_AUX2(trigger, GPIO_FLAG_SCI) }
-/* SMI pad configuration */
-#define PAD_SMI(pin, pull, trigger) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = GPIO_PULL ## _ ## pull, \
- .flags = PAD_AUX2(trigger, GPIO_FLAG_SMI) }
-/* WAKE pad configuration */
-#define PAD_WAKE(pin, pull, trigger, type) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = (PAD_AUX1(pull, trigger) | \
- GPIO_WAKE ## _ ## type), \
- .flags = GPIO_FLAG_WAKE }
-/* pin debounce configuration */
-#define PAD_DEBOUNCE(pin, type, time) \
- { .gpio = (pin), \
- .function = pin ## _IOMUX_ ## GPIOxx, \
- .control = (GPIO_IN ## _ ## type | GPIO_IN ## _ ## time), \
- .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
- *
- * @param gpio_list_ptr = pointer to array of gpio configurations
- * @param size = number of entries in array
- *
- * @return none
- */
-void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size);
-
-/* Return the interrupt status and clear if set. */
-int gpio_interrupt_status(gpio_t gpio);
-
#endif /* __ACPI__ */
#endif /* __STONEYRIDGE_GPIO_H__ */

To view, visit change 32651. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: I9cda00210a74de2bd1308ad43e2b867d24a67845
Gerrit-Change-Number: 32651
Gerrit-PatchSet: 1
Gerrit-Owner: Marshall Dawson <marshalldawson3rd@gmail.com>
Gerrit-Reviewer: Furquan Shaikh <furquan@google.com>
Gerrit-Reviewer: Marshall Dawson <marshalldawson3rd@gmail.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-Reviewer: Richard Spiegel <richard.spiegel@silverbackltd.com>
Gerrit-MessageType: newchange