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:
parent
419c6901d9
commit
c4f5e4e793
|
@ -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)
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue