diff --git a/src/mainboard/google/kahlee/bootblock/bootblock.c b/src/mainboard/google/kahlee/bootblock/bootblock.c index aac1d955d9..8f124b36ff 100644 --- a/src/mainboard/google/kahlee/bootblock/bootblock.c +++ b/src/mainboard/google/kahlee/bootblock/bootblock.c @@ -50,11 +50,4 @@ void bootblock_mainboard_init(void) /* Setup TPM decode before verstage */ sb_tpm_decode_spi(); - - /* Configure cr50 interrupt pin for use in polling tpm status */ - if (IS_ENABLED(CONFIG_MAINBOARD_HAS_TPM_CR50)) { - const uint32_t flags = GPIO_EDGE_TRIG | GPIO_ACTIVE_LOW | - GPIO_INT_STATUS_EN; - gpio_set_interrupt(H1_PCH_INT, flags); - } } diff --git a/src/mainboard/google/kahlee/mainboard.c b/src/mainboard/google/kahlee/mainboard.c index a01ae0acf5..e090401ddf 100644 --- a/src/mainboard/google/kahlee/mainboard.c +++ b/src/mainboard/google/kahlee/mainboard.c @@ -169,8 +169,16 @@ static void mainboard_init(void *chip_info) gpios = variant_gpio_table(&num_gpios); sb_program_gpios(gpios, num_gpios); + /* + * Some platforms use SCI not generated by a GPIO pin (event above 23). + * For these boards, gpe_configure_sci() is still needed, but all GPIO + * generated events (23-0) must be removed from gpe_table[]. + * For boards that only have GPIO generated events, table gpe_table[] + * must be removed, and get_gpe_table() should return NULL. + */ gpes = get_gpe_table(&num); - gpe_configure_sci(gpes, num); + if (gpes != NULL) + gpe_configure_sci(gpes, num); /* Initialize i2c busses that were not initialized in bootblock */ i2c_soc_init(); diff --git a/src/mainboard/google/kahlee/variants/baseboard/gpio.c b/src/mainboard/google/kahlee/variants/baseboard/gpio.c index ff6141e525..c7bd6a5be9 100644 --- a/src/mainboard/google/kahlee/variants/baseboard/gpio.c +++ b/src/mainboard/google/kahlee/variants/baseboard/gpio.c @@ -32,16 +32,17 @@ static const struct soc_amd_gpio gpio_set_stage_reset_old[] = { PAD_GPO(GPIO_4, HIGH), /* GPIO_6 - APU_RST_L / EC_SMI_ODL, SMI */ - PAD_GPI(GPIO_6, PULL_UP), + PAD_SMI(GPIO_6, PULL_UP, LEVEL_LOW), /* GPIO_9 - H1_PCH_INT_ODL, SCI */ - PAD_GPI(GPIO_9, PULL_UP), + PAD_INT(GPIO_9, PULL_UP, EDGE_LOW, STATUS), + PAD_SCI(GPIO_9, PULL_UP, EDGE_LOW), /* GPIO_15 - EC_IN_RW_OD */ PAD_GPI(GPIO_15, PULL_UP), /* GPIO_22 - EC_SCI_ODL, SCI */ - PAD_GPI(GPIO_22, PULL_UP), + PAD_SCI(GPIO_22, PULL_UP, EDGE_LOW), /* GPIO_26 - APU_PCIE_RST_L */ PAD_NF(GPIO_26, PCIE_RST_L, PULL_NONE), @@ -85,16 +86,17 @@ static const struct soc_amd_gpio gpio_set_stage_reset[] = { PAD_GPO(GPIO_4, HIGH), /* GPIO_6 - APU_RST_L / EC_SMI_ODL, SMI */ - PAD_GPI(GPIO_6, PULL_UP), + PAD_SMI(GPIO_6, PULL_UP, LEVEL_LOW), /* GPIO_9 - H1_PCH_INT_ODL, SCI */ - PAD_GPI(GPIO_9, PULL_UP), + PAD_INT(GPIO_9, PULL_UP, EDGE_LOW, STATUS), + PAD_SCI(GPIO_9, PULL_UP, EDGE_LOW), /* GPIO_15 - EC_IN_RW_OD */ PAD_GPI(GPIO_15, PULL_UP), /* GPIO_22 - EC_SCI_ODL, SCI */ - PAD_GPI(GPIO_22, PULL_UP), + PAD_SCI(GPIO_22, PULL_UP, EDGE_LOW), /* GPIO_24 - EC_PCH_WAKE_L */ PAD_GPI(GPIO_24, PULL_UP), @@ -150,7 +152,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram_old[] = { PAD_GPI(GPIO_3, PULL_UP), /* GPIO_5 - PCH_TRACKPAD_INT_3V3_ODL, SCI */ - PAD_GPI(GPIO_5, PULL_UP), + PAD_SCI(GPIO_5, PULL_UP, EDGE_LOW), /* GPIO_7 - APU_PWROK_OD (currently not used) */ PAD_GPI(GPIO_7, PULL_UP), @@ -162,7 +164,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram_old[] = { PAD_NF(GPIO_10, S0A3_GPIO, PULL_UP), /* GPIO_11 - TOUCHSCREEN_INT_3V3_ODL, SCI */ - PAD_GPI(GPIO_11, PULL_UP), + PAD_SCI(GPIO_11, PULL_UP, EDGE_LOW), /* GPIO_12 - Unused (TP126) */ PAD_GPI(GPIO_12, PULL_UP), @@ -171,7 +173,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram_old[] = { PAD_GPI(GPIO_13, PULL_UP), /* GPIO_14 - APU_HP_INT_ODL, SCI */ - PAD_GPI(GPIO_14, PULL_UP), + PAD_SCI(GPIO_14, PULL_UP, EDGE_LOW), /* GPIO_16 - USB_C0_OC_L */ PAD_NF(GPIO_16, USB_OC0_L, PULL_UP), @@ -189,7 +191,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram_old[] = { PAD_NF(GPIO_20, I2C3_SDA, PULL_UP), /* GPIO_21 - APU_PEN_INT_ODL, SCI */ - PAD_GPI(GPIO_21, PULL_UP), + PAD_SCI(GPIO_21, PULL_UP, EDGE_LOW), /* GPIO_24 - USB_A1_OC_ODL */ PAD_NF(GPIO_24, USB_OC3_L, PULL_UP), @@ -314,7 +316,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram[] = { PAD_GPI(GPIO_3, PULL_UP), /* GPIO_5 - PCH_TRACKPAD_INT_3V3_ODL, SCI */ - PAD_GPI(GPIO_5, PULL_UP), + PAD_SCI(GPIO_5, PULL_UP, EDGE_LOW), /* GPIO_7 - APU_PWROK_OD (currently not used) */ PAD_GPI(GPIO_7, PULL_UP), @@ -326,7 +328,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram[] = { PAD_NF(GPIO_10, S0A3_GPIO, PULL_UP), /* GPIO_11 - TOUCHSCREEN_INT_3V3_ODL, SCI */ - PAD_GPI(GPIO_11, PULL_UP), + PAD_SCI(GPIO_11, PULL_UP, EDGE_LOW), /* GPIO_12 - EN_PP3300_TRACKPAD */ PAD_GPO(GPIO_12, HIGH), @@ -335,7 +337,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram[] = { PAD_GPI(GPIO_13, PULL_UP), /* GPIO_14 - APU_HP_INT_ODL, SCI */ - PAD_GPI(GPIO_14, PULL_UP), + PAD_SCI(GPIO_14, PULL_UP, EDGE_LOW), /* GPIO_16 - USB_C0_OC_L */ PAD_NF(GPIO_16, USB_OC0_L, PULL_UP), @@ -353,7 +355,7 @@ static const struct soc_amd_gpio gpio_set_stage_ram[] = { PAD_NF(GPIO_20, I2C3_SDA, PULL_UP), /* GPIO_21 - APU_PEN_INT_ODL, SCI */ - PAD_GPI(GPIO_21, PULL_UP), + PAD_SCI(GPIO_21, PULL_UP, EDGE_LOW), /* GPIO_25 - SD_CD */ PAD_NF(GPIO_25, SD0_CD, PULL_UP), @@ -486,73 +488,15 @@ struct soc_amd_gpio *variant_gpio_table(size_t *size) } /* - * GPE setup table must match ACPI GPE ASL - * { gevent, gpe, direction, level } + * This function is still needed for boards that sets gevents above 23 + * that will generate SCI or SMI, such as kahlee. Normally this function + * points to a table of gevents and what needs to be set. The code that + * calls it was modified so that when this function returns NULL then the + * caller does nothing. */ -static const struct sci_source gpe_table[] = { - - /* PCH_TRACKPAD_INT_3V3_ODL */ - { - .scimap = 7, - .gpe = 7, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* EC_PCH_WAKE_L */ - { - .scimap = EC_WAKE_GPI, - .gpe = EC_WAKE_GPI, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* H1_PCH_INT_ODL */ - { - .scimap = 22, - .gpe = 22, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* TOUCHSCREEN_INT_3V3_ODL */ - { - .scimap = 18, - .gpe = 18, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - - /* APU_HP_INT_ODL */ - { - .scimap = 6, - .gpe = 6, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* APU_PEN_INT_ODL */ - { - .scimap = 5, - .gpe = 5, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* EC_SCI_ODL */ - { - .scimap = 3, - .gpe = 3, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, -}; - const __weak struct sci_source *get_gpe_table(size_t *num) { - *num = ARRAY_SIZE(gpe_table); - return gpe_table; + return NULL; } int __weak variant_get_xhci_oc_map(uint16_t *map) diff --git a/src/mainboard/google/kahlee/variants/kahlee/gpio.c b/src/mainboard/google/kahlee/variants/kahlee/gpio.c index 8f30e4b40e..30723508db 100644 --- a/src/mainboard/google/kahlee/variants/kahlee/gpio.c +++ b/src/mainboard/google/kahlee/variants/kahlee/gpio.c @@ -26,7 +26,7 @@ */ static const struct soc_amd_gpio gpio_set_stage_reset[] = { /* AGPIO2, to become event generator */ - PAD_GPI(GPIO_2, PULL_UP), + PAD_SCI(GPIO_2, PULL_UP, EDGE_LOW), /* SER_TX */ PAD_NF(GPIO_8, SerPortTX_OUT, PULL_UP), @@ -44,7 +44,7 @@ static const struct soc_amd_gpio gpio_set_stage_reset[] = { PAD_NF(GPIO_20, I2C3_SDA, PULL_UP), /* AGPIO22 EC_SCI */ - PAD_GPI(GPIO_22, PULL_UP), + PAD_SCI(GPIO_22, PULL_UP, EDGE_LOW), /* SPI_TPM_CS_L */ PAD_NF(GPIO_76, SPI_TPM_CS_L, PULL_DOWN), @@ -120,22 +120,6 @@ const struct soc_amd_gpio *variant_gpio_table(size_t *size) */ static const struct sci_source gpe_table[] = { - /* EC AGPIO22/Gevent3 -> GPE 3 */ - { - .scimap = 3, - .gpe = 3, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_EDG, - }, - - /* PCIE/WLAN AGPIO2/Gevent8 -> GPE8 */ - { - .scimap = 8, - .gpe = 8, - .direction = SMI_SCI_LVL_LOW, - .level = SMI_SCI_LVL, - }, - /* EHCI USB_PME -> GPE24 */ { .scimap = 24, diff --git a/src/soc/amd/stoneyridge/Makefile.inc b/src/soc/amd/stoneyridge/Makefile.inc index 54b1198b32..c2d48d5f6d 100644 --- a/src/soc/amd/stoneyridge/Makefile.inc +++ b/src/soc/amd/stoneyridge/Makefile.inc @@ -50,6 +50,7 @@ bootblock-y += tsc_freq.c bootblock-y += southbridge.c bootblock-y += nb_util.c bootblock-$(CONFIG_SPI_FLASH) += spi.c +bootblock-$(CONFIG_HAVE_SMI_HANDLER) += smi_util.c romstage-y += BiosCallOuts.c romstage-y += i2c.c @@ -69,6 +70,7 @@ romstage-y += tsc_freq.c romstage-y += southbridge.c romstage-y += nb_util.c romstage-$(CONFIG_SPI_FLASH) += spi.c +romstage-$(CONFIG_HAVE_SMI_HANDLER) += smi_util.c verstage-y += gpio.c verstage-y += i2c.c diff --git a/src/soc/amd/stoneyridge/gpio.c b/src/soc/amd/stoneyridge/gpio.c index 4520df7a6f..1b7f0557df 100644 --- a/src/soc/amd/stoneyridge/gpio.c +++ b/src/soc/amd/stoneyridge/gpio.c @@ -19,6 +19,110 @@ #include #include #include +#include +#include + +static const struct soc_amd_event gpio_event_table[] = { + { GPIO_1, GEVENT_19 }, + { GPIO_2, GEVENT_8 }, + { GPIO_3, GEVENT_2 }, + { GPIO_4, GEVENT_4 }, + { GPIO_5, GEVENT_7 }, + { GPIO_6, GEVENT_10 }, + { GPIO_7, GEVENT_11 }, + { GPIO_8, GEVENT_23 }, + { GPIO_9, GEVENT_22 }, + { GPIO_11, GEVENT_18 }, + { GPIO_13, GEVENT_21 }, + { GPIO_14, GEVENT_6 }, + { GPIO_15, GEVENT_20 }, + { GPIO_16, GEVENT_12 }, + { GPIO_17, GEVENT_13 }, + { GPIO_18, GEVENT_14 }, + { GPIO_21, GEVENT_5 }, + { GPIO_22, GEVENT_3 }, + { GPIO_23, GEVENT_16 }, + { GPIO_24, GEVENT_15 }, + { GPIO_65, GEVENT_0 }, + { GPIO_66, GEVENT_1 }, + { GPIO_68, GEVENT_9 }, + { GPIO_69, GEVENT_17 }, +}; + +static int get_gpio_gevent(uint8_t gpio) +{ + 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; +} + +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 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; + } +} static uintptr_t gpio_get_address(gpio_t gpio_num) { @@ -108,18 +212,79 @@ uint16_t gpio_acpi_pin(gpio_t gpio) return gpio; } -void gpio_set_interrupt(gpio_t gpio, uint32_t flags) +void sb_program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) { - uintptr_t gpio_address = gpio_get_address(gpio); - uint32_t reg = read32((void *)gpio_address); + uint8_t *mux_ptr; + uint32_t *gpio_ptr; + uint32_t control, control_flags, edge_level, direction; + uint32_t mask, bit_edge, bit_level; + uint8_t mux, index, gpio; + int gevent_num; - /* Clear registers that are being updated */ - reg &= ~(GPIO_TRIGGER_MASK | GPIO_ACTIVE_MASK | GPIO_INTERRUPT_MASK); + direction = 0; + edge_level = 0; + mask = 0; + 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; - /* Clear any extra bits in the flags */ - flags &= (GPIO_TRIGGER_MASK | GPIO_ACTIVE_MASK | GPIO_INTERRUPT_MASK); + mux_ptr = (uint8_t *)(uintptr_t)(gpio + AMD_GPIO_MUX); + write8(mux_ptr, mux & AMD_GPIO_MUX_MASK); + gpio_ptr = (uint32_t *)gpio_get_address(gpio); - write32((void *)gpio_address, reg | flags); + 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); + break; + default: + printk(BIOS_WARNING, "Error, flags 0x%08x\n", + control_flags); + break; + } + } else { + mem_read_write32(gpio_ptr, control, + AMD_GPIO_CONTROL_MASK); + } + } + /* Set all SCI trigger direction (high/low) */ + mem_read_write32((uint32_t *)(uintptr_t)(APU_SMI_BASE + SMI_SCI_TRIG), + direction, mask); + + /* Set all SCI trigger level (edge/level) */ + mem_read_write32((uint32_t *)(uintptr_t)(APU_SMI_BASE + SMI_SCI_LEVEL), + edge_level, mask); } int gpio_interrupt_status(gpio_t gpio) diff --git a/src/soc/amd/stoneyridge/include/soc/gpio.h b/src/soc/amd/stoneyridge/include/soc/gpio.h index cbc99e4d31..e43f2c7306 100644 --- a/src/soc/amd/stoneyridge/include/soc/gpio.h +++ b/src/soc/amd/stoneyridge/include/soc/gpio.h @@ -21,8 +21,21 @@ #ifndef __ACPI__ #include +#include #include +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_EDGE_TRIG (0 << 8) #define GPIO_LEVEL_TRIG (1 << 8) #define GPIO_TRIGGER_MASK (1 << 8) @@ -35,12 +48,16 @@ #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) @@ -325,38 +342,228 @@ #define GPIO_148_IOMUX_I2C1_SDA 0 #define GPIO_148_IOMUX_GPIOxx 1 -#define GPIO_ENABLE_OUTPUT BIT(7) -#define GPIO_OUTPUT_VALUE BIT(6) -#define GPIO_PULL_DOWN_ENABLE BIT(5) -#define GPIO_PULL_UP_ENABLE BIT(4) +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_OUTPUT_OUT_HIGH (GPIO_ENABLE_OUTPUT | GPIO_OUTPUT_VALUE) -#define GPIO_OUTPUT_OUT_LOW GPIO_ENABLE_OUTPUT +#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_PULL_UP_ENABLE -#define GPIO_PULL_PULL_DOWN GPIO_PULL_DOWN_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_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_IN_NO_DEBOUNCE (DEBOUNCE_NONE << IN_GLITCH_SHIFT) +#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_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 } + .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 } + .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 } + .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; -/* Update interrupt settings for given GPIO */ -void gpio_set_interrupt(gpio_t gpio, uint32_t flags); +/** + * @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); diff --git a/src/soc/amd/stoneyridge/include/soc/southbridge.h b/src/soc/amd/stoneyridge/include/soc/southbridge.h index 0a23fcacd4..10b1f4328b 100644 --- a/src/soc/amd/stoneyridge/include/soc/southbridge.h +++ b/src/soc/amd/stoneyridge/include/soc/southbridge.h @@ -306,7 +306,6 @@ #define WIDEIO_RANGE_ERROR -1 #define TOTAL_WIDEIO_PORTS 3 -#define AMD_GPIO_MUX_MASK 0x03 #if ENV_BOOTBLOCK #define GPIO_TABLE_BOOTBLOCK 1 @@ -354,12 +353,6 @@ #define FCH_AOAC_STAT0 BIT(6) #define FCH_AOAC_STAT1 BIT(7) -struct soc_amd_gpio { - uint8_t gpio; - uint8_t function; - uint8_t control; -}; - struct stoneyridge_aoac { int enable; int status; @@ -442,15 +435,6 @@ uint32_t get_uma_size(void); * @return 64bit base address */ uint64_t get_uma_base(void); -/** - * @brief program a particular set of GPIO - * - * @param gpio_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_ptr, size_t size); /** * @brief Find the size of a particular wide IO * diff --git a/src/soc/amd/stoneyridge/southbridge.c b/src/soc/amd/stoneyridge/southbridge.c index 5a3a442415..cc21601c3e 100644 --- a/src/soc/amd/stoneyridge/southbridge.c +++ b/src/soc/amd/stoneyridge/southbridge.c @@ -173,27 +173,6 @@ const struct irq_idx_name *sb_get_apic_reg_association(size_t *size) return irq_association; } -void sb_program_gpios(const struct soc_amd_gpio *gpio_ptr, size_t size) -{ - void *tmp_ptr; - uint8_t control, mux, index; - - for (index = 0; index < size; index++) { - mux = gpio_ptr[index].function; - control = gpio_ptr[index].control; - tmp_ptr = (void *)(gpio_ptr[index].gpio + AMD_GPIO_MUX); - write8(tmp_ptr, mux & AMD_GPIO_MUX_MASK); - - /* - * Get the address of AMD_GPIO_CONTROL (dword) relative - * to the desired pin and program bits 16-23. - */ - tmp_ptr = (void *)(gpio_ptr[index].gpio * sizeof(uint32_t) + - AMD_GPIO_CONTROL + 2); - write8(tmp_ptr, control); - } -} - /** * @brief Find the size of a particular wide IO *