soc/amd/common: Refactor GPIO SCI/SMI interrupts

Change-Id: Ib2c7cd70ab38d0d8e745b0a611b780d2b0b8dc5b
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/42687
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Raul Rangel <rrangel@chromium.org>
This commit is contained in:
Kyösti Mälkki 2020-06-22 12:03:51 +03:00 committed by Patrick Georgi
parent 419c6901d9
commit c4f5e4e793
2 changed files with 59 additions and 51 deletions

View File

@ -32,11 +32,8 @@ static void mem_read_write32(uint32_t *address, uint32_t value, uint32_t mask)
write32(address, reg32); write32(address, reg32);
} }
static void program_smi(uint32_t flag, int gevent_num) static void program_smi(uint32_t trigger, int gevent_num)
{ {
uint32_t trigger;
trigger = flag & FLAGS_TRIGGER_MASK;
/* /*
* Only level trigger is allowed for SMI. Trigger values are 0 * Only level trigger is allowed for SMI. Trigger values are 0
* through 3, with 0-1 being level trigger and 2-3 being edge * through 3, with 0-1 being level trigger and 2-3 being edge
@ -46,38 +43,58 @@ static void program_smi(uint32_t flag, int gevent_num)
assert(trigger < GPIO_TRIGGER_EDGE_LOW); assert(trigger < GPIO_TRIGGER_EDGE_LOW);
if (trigger == GPIO_TRIGGER_LEVEL_HIGH) if (trigger == GPIO_TRIGGER_LEVEL_HIGH)
configure_gevent_smi(gevent_num, SMI_MODE_SMI, configure_gevent_smi(gevent_num, SMI_MODE_SMI, SMI_SCI_LVL_HIGH);
SMI_SCI_LVL_HIGH);
if (trigger == GPIO_TRIGGER_LEVEL_LOW) if (trigger == GPIO_TRIGGER_LEVEL_LOW)
configure_gevent_smi(gevent_num, SMI_MODE_SMI, configure_gevent_smi(gevent_num, SMI_MODE_SMI, SMI_SCI_LVL_LOW);
SMI_SCI_LVL_LOW);
} }
static void get_sci_config_bits(uint32_t flag, uint32_t *edge, uint32_t *level) struct sci_trigger_regs {
{ uint32_t mask;
uint32_t trigger; uint32_t polarity;
uint32_t level;
};
trigger = flag & FLAGS_TRIGGER_MASK; /*
switch (trigger) { * For each general purpose event, GPE, the choice of edge/level triggered
case GPIO_TRIGGER_LEVEL_LOW: * event is represented as a single bit in SMI_SCI_LEVEL register.
*edge = SCI_TRIGGER_LEVEL; *
*level = 0; * In a similar fashion, polarity (rising/falling, hi/lo) of each GPE is
break; * represented as a single bit in SMI_SCI_TRIG register.
case GPIO_TRIGGER_LEVEL_HIGH: */
*edge = SCI_TRIGGER_LEVEL; static void fill_sci_trigger(uint32_t trigger, int gpe, struct sci_trigger_regs *regs)
*level = 1; {
break; uint32_t mask = 1 << gpe;
case GPIO_TRIGGER_EDGE_LOW:
*edge = SCI_TRIGGER_EDGE; regs->mask |= mask;
*level = 0;
break; /* Select level vs. edge triggered event. */
case GPIO_TRIGGER_EDGE_HIGH: if ((trigger == GPIO_TRIGGER_LEVEL_LOW) || (trigger == GPIO_TRIGGER_LEVEL_HIGH))
*edge = SCI_TRIGGER_EDGE; regs->level |= mask;
*level = 1; else
break; regs->level &= ~mask;
default:
break; /* Select rising/high vs falling/low trigger. */
} if ((trigger == GPIO_TRIGGER_EDGE_HIGH) || (trigger == GPIO_TRIGGER_LEVEL_HIGH))
regs->polarity |= mask;
else
regs->polarity &= ~mask;
}
/* TODO: See configure_scimap() implementations. */
static void set_sci_trigger(const struct sci_trigger_regs *regs)
{
uint32_t value;
value = smi_read32(SMI_SCI_TRIG);
value &= ~regs->mask;
value |= regs->polarity;
smi_write32(SMI_SCI_TRIG, value);
value = smi_read32(SMI_SCI_LEVEL);
value &= ~regs->mask;
value |= regs->level;
smi_write32(SMI_SCI_LEVEL, value);
} }
uintptr_t gpio_get_address(gpio_t gpio_num) uintptr_t gpio_get_address(gpio_t gpio_num)
@ -166,17 +183,13 @@ __weak void soc_gpio_hook(uint8_t gpio, uint8_t mux) {}
void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size) void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
{ {
uint32_t *gpio_ptr; uint32_t *gpio_ptr;
uint32_t control, control_flags, edge_level, direction; uint32_t control, control_flags;
uint32_t mask, bit_edge, bit_level;
uint8_t mux, index, gpio; uint8_t mux, index, gpio;
int gevent_num; int gevent_num;
const struct soc_amd_event *gev_tbl; const struct soc_amd_event *gev_tbl;
struct sci_trigger_regs sci_trigger_cfg = { 0 };
size_t gev_items; size_t gev_items;
direction = 0;
edge_level = 0;
mask = 0;
/* /*
* Disable blocking wake/interrupt status generation while updating * Disable blocking wake/interrupt status generation while updating
* debounce registers. Otherwise when a debounce register is updated * debounce registers. Otherwise when a debounce register is updated
@ -227,16 +240,16 @@ void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
case GPIO_SMI_FLAG: case GPIO_SMI_FLAG:
mem_read_write32(gpio_ptr, control, mem_read_write32(gpio_ptr, control,
INT_SCI_SMI_MASK); INT_SCI_SMI_MASK);
program_smi(control_flags, gevent_num);
program_smi(control_flags & FLAGS_TRIGGER_MASK, gevent_num);
break; break;
case GPIO_SCI_FLAG: case GPIO_SCI_FLAG:
mem_read_write32(gpio_ptr, control, mem_read_write32(gpio_ptr, control,
INT_SCI_SMI_MASK); INT_SCI_SMI_MASK);
get_sci_config_bits(control_flags, &bit_edge,
&bit_level); fill_sci_trigger(control_flags & FLAGS_TRIGGER_MASK, gevent_num,
edge_level |= bit_edge << gevent_num; &sci_trigger_cfg);
direction |= bit_level << gevent_num;
mask |= (1 << gevent_num);
soc_route_sci(gevent_num); soc_route_sci(gevent_num);
break; break;
default: default:
@ -259,11 +272,8 @@ void program_gpios(const struct soc_amd_gpio *gpio_list_ptr, size_t size)
*/ */
master_switch_set(GPIO_INTERRUPT_EN); master_switch_set(GPIO_INTERRUPT_EN);
/* Set all SCI trigger direction (high/low) */ /* Set all SCI trigger polarity (high/low) and level (edge/level). */
mem_read_write32((void *)(acpimmio_smi + SMI_SCI_TRIG), direction, mask); set_sci_trigger(&sci_trigger_cfg);
/* Set all SCI trigger level (edge/level) */
mem_read_write32((void *)(acpimmio_smi + SMI_SCI_LEVEL), edge_level, mask);
} }
int gpio_interrupt_status(gpio_t gpio) int gpio_interrupt_status(gpio_t gpio)

View File

@ -114,8 +114,6 @@ enum {
}; };
#define GPIO_TRIGGER_INVALID -1 #define GPIO_TRIGGER_INVALID -1
#define SCI_TRIGGER_EDGE 0
#define SCI_TRIGGER_LEVEL 1
#define GPIO_SPECIAL_FLAG (1 << 31) #define GPIO_SPECIAL_FLAG (1 << 31)
#define GPIO_DEBOUNCE_FLAG (1 << 30) #define GPIO_DEBOUNCE_FLAG (1 << 30)