diff options
-rw-r--r-- | src/soc/amd/common/block/gpio_banks/gpio.c | 52 | ||||
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/gpio_banks.h | 69 |
2 files changed, 73 insertions, 48 deletions
diff --git a/src/soc/amd/common/block/gpio_banks/gpio.c b/src/soc/amd/common/block/gpio_banks/gpio.c index 4d6d164498..d7ac89667b 100644 --- a/src/soc/amd/common/block/gpio_banks/gpio.c +++ b/src/soc/amd/common/block/gpio_banks/gpio.c @@ -32,21 +32,22 @@ static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask) write32(address, reg32); } -static void program_smi(uint32_t trigger, int gevent_num) +static void program_smi(uint32_t flags, int gevent_num) { - /* - * 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); + uint8_t level; - if (trigger == GPIO_TRIGGER_LEVEL_HIGH) - configure_gevent_smi(gevent_num, SMI_MODE_SMI, SMI_SCI_LVL_HIGH); + if (!is_gpio_event_level_triggered(flags)) { + printk(BIOS_ERR, "ERROR: %s - Only level trigger allowed for SMI!\n", __func__); + assert(0); + return; + } + + if (is_gpio_event_active_high(flags)) + level = SMI_SCI_LVL_HIGH; + else + level = SMI_SCI_LVL_LOW; - if (trigger == GPIO_TRIGGER_LEVEL_LOW) - configure_gevent_smi(gevent_num, SMI_MODE_SMI, SMI_SCI_LVL_LOW); + configure_gevent_smi(gevent_num, SMI_MODE_SMI, level); } struct sci_trigger_regs { @@ -62,20 +63,18 @@ struct sci_trigger_regs { * In a similar fashion, polarity (rising/falling, hi/lo) of each GPE is * represented as a single bit in SMI_SCI_TRIG register. */ -static void fill_sci_trigger(uint32_t trigger, int gpe, struct sci_trigger_regs *regs) +static void fill_sci_trigger(uint32_t flags, int gpe, struct sci_trigger_regs *regs) { uint32_t mask = 1 << gpe; regs->mask |= mask; - /* Select level vs. edge triggered event. */ - if ((trigger == GPIO_TRIGGER_LEVEL_LOW) || (trigger == GPIO_TRIGGER_LEVEL_HIGH)) + if (is_gpio_event_level_triggered(flags)) regs->level |= mask; else regs->level &= ~mask; - /* Select rising/high vs falling/low trigger. */ - if ((trigger == GPIO_TRIGGER_EDGE_HIGH) || (trigger == GPIO_TRIGGER_LEVEL_HIGH)) + if (is_gpio_event_active_high(flags)) regs->polarity |= mask; else regs->polarity &= ~mask; @@ -217,38 +216,37 @@ void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) gpio_ptr = gpio_ctrl_ptr(gpio); - if (control_flags & GPIO_SPECIAL_FLAG) { + if (control_flags & GPIO_FLAG_SPECIAL_MASK) { gevent_num = get_gpio_gevent(gpio, gev_tbl, gev_items); 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: + switch (control_flags & GPIO_FLAG_SPECIAL_MASK) { + case GPIO_FLAG_DEBOUNCE: mem_read_write32(gpio_ptr, control, GPIO_DEBOUNCE_MASK); break; - case GPIO_WAKE_FLAG: + case GPIO_FLAG_WAKE: mem_read_write32(gpio_ptr, control, INT_WAKE_MASK); break; - case GPIO_INT_FLAG: + case GPIO_FLAG_INT: mem_read_write32(gpio_ptr, control, AMD_GPIO_CONTROL_MASK); break; - case GPIO_SMI_FLAG: + case GPIO_FLAG_SMI: mem_read_write32(gpio_ptr, control, INT_SCI_SMI_MASK); - program_smi(control_flags & FLAGS_TRIGGER_MASK, gevent_num); + program_smi(control_flags, gevent_num); break; - case GPIO_SCI_FLAG: + case GPIO_FLAG_SCI: mem_read_write32(gpio_ptr, control, INT_SCI_SMI_MASK); - fill_sci_trigger(control_flags & FLAGS_TRIGGER_MASK, gevent_num, - &sci_trigger_cfg); + fill_sci_trigger(control_flags, gevent_num, &sci_trigger_cfg); soc_route_sci(gevent_num); break; diff --git a/src/soc/amd/common/block/include/amdblocks/gpio_banks.h b/src/soc/amd/common/block/include/amdblocks/gpio_banks.h index 92aa8a2e4f..0521e4c520 100644 --- a/src/soc/amd/common/block/include/amdblocks/gpio_banks.h +++ b/src/soc/amd/common/block/include/amdblocks/gpio_banks.h @@ -4,6 +4,7 @@ #define __AMDBLOCK_GPIO_BANKS_H__ #include <stdint.h> +#include <stdbool.h> #include <stddef.h> struct soc_amd_gpio { @@ -106,27 +107,53 @@ enum { #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, -}; +/* + * Flags used for GPIO configuration. These provide additional information that does not go + * directly into GPIO control register. These are stored in `flags` field in soc_amd_gpio. + */ +#define GPIO_FLAG_EVENT_TRIGGER_LEVEL (1 << 0) +#define GPIO_FLAG_EVENT_TRIGGER_EDGE (0 << 0) +#define GPIO_FLAG_EVENT_TRIGGER_MASK (1 << 0) +#define GPIO_FLAG_EVENT_ACTIVE_HIGH (1 << 1) +#define GPIO_FLAG_EVENT_ACTIVE_LOW (0 << 1) +#define GPIO_FLAG_EVENT_ACTIVE_MASK (1 << 1) +#define GPIO_FLAG_SCI (1 << 2) +#define GPIO_FLAG_SMI (1 << 3) +#define GPIO_FLAG_DEBOUNCE (1 << 4) +#define GPIO_FLAG_WAKE (1 << 5) +#define GPIO_FLAG_INT (1 << 6) +#define GPIO_FLAG_SPECIAL_MASK (0x1f << 2) + +/* Trigger configuration for GPIO SCI/SMI events. */ +#define GPIO_FLAG_EVENT_TRIGGER_LEVEL_HIGH (GPIO_FLAG_EVENT_TRIGGER_LEVEL | \ + GPIO_FLAG_EVENT_ACTIVE_HIGH) +#define GPIO_FLAG_EVENT_TRIGGER_LEVEL_LOW (GPIO_FLAG_EVENT_TRIGGER_LEVEL | \ + GPIO_FLAG_EVENT_ACTIVE_LOW) +#define GPIO_FLAG_EVENT_TRIGGER_EDGE_HIGH (GPIO_FLAG_EVENT_TRIGGER_EDGE | \ + GPIO_FLAG_EVENT_ACTIVE_HIGH) +#define GPIO_FLAG_EVENT_TRIGGER_EDGE_LOW (GPIO_FLAG_EVENT_TRIGGER_EDGE | \ + GPIO_FLAG_EVENT_ACTIVE_LOW) + +static inline bool is_gpio_event_level_triggered(uint32_t flags) +{ + return (flags & GPIO_FLAG_EVENT_TRIGGER_MASK) == GPIO_FLAG_EVENT_TRIGGER_LEVEL; +} + +static inline bool is_gpio_event_edge_triggered(uint32_t flags) +{ + return (flags & GPIO_FLAG_EVENT_TRIGGER_MASK) == GPIO_FLAG_EVENT_TRIGGER_EDGE; +} + +static inline bool is_gpio_event_active_high(uint32_t flags) +{ + return (flags & GPIO_FLAG_EVENT_ACTIVE_MASK) == GPIO_FLAG_EVENT_ACTIVE_HIGH; +} + +static inline bool is_gpio_event_active_low(uint32_t flags) +{ + return (flags & GPIO_FLAG_EVENT_ACTIVE_MASK) == GPIO_FLAG_EVENT_ACTIVE_LOW; +} -#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 @@ -238,7 +265,7 @@ enum { GPIO_EVENT_INT ## _ ## action), \ .flags = GPIO_FLAG_INT } /* Auxiliary macro for SCI and SMI */ -#define PAD_AUX2(trigger, flag) (GPIO_TRIGGER ## _ ## trigger | flag) +#define PAD_AUX2(trigger, flag) (GPIO_FLAG_EVENT_TRIGGER ## _ ## trigger | flag) /* SCI pad configuration */ #define PAD_SCI(pin, pull, trigger) \ { .gpio = (pin), \ |