diff options
author | Daniel Kurtz <djkurtz@chromium.org> | 2017-04-18 21:13:30 +0800 |
---|---|---|
committer | Aaron Durbin <adurbin@chromium.org> | 2017-04-24 22:32:52 +0200 |
commit | 50340f5480c943b6434c9b5e6178731a9977cae3 (patch) | |
tree | e42965d633f28200cd08aed407aa8d8a37198a01 /src/soc/mediatek/mt8173/gpio.c | |
parent | 732618975ee688059ca50f87a76f8a3bed8d4fb1 (diff) |
mediatek/mt8173: Add EINT support
Add basic support to configure GPIOs to poll for external interrupts
(EINT).
BRANCH=none
BUG=b:36786804
TEST=Boot rowan w/ serial enabled, verify coreboot and depthcharge are
configured to use IRQ flow control when talking to the Cr50 TPM.
Change-Id: I9d52591661a5a74ec1fd9a081f606f0a08a3a6ab
Signed-off-by: Daniel Kurtz <djkurtz@chromium.org>
Reviewed-on: https://review.coreboot.org/19362
Reviewed-by: Julius Werner <jwerner@chromium.org>
Tested-by: build bot (Jenkins)
Diffstat (limited to 'src/soc/mediatek/mt8173/gpio.c')
-rw-r--r-- | src/soc/mediatek/mt8173/gpio.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/soc/mediatek/mt8173/gpio.c b/src/soc/mediatek/mt8173/gpio.c index e19c769c33..c5ca08b923 100644 --- a/src/soc/mediatek/mt8173/gpio.c +++ b/src/soc/mediatek/mt8173/gpio.c @@ -25,6 +25,7 @@ enum { MAX_GPIO_REG_BITS = 16, MAX_GPIO_MODE_PER_REG = 5, GPIO_MODE_BITS = 3, + MAX_EINT_REG_BITS = 32, }; enum { @@ -48,6 +49,12 @@ static void pos_bit_calc_for_mode(u32 pin, u32 *pos, u32 *bit) *bit = (pin % MAX_GPIO_MODE_PER_REG) * GPIO_MODE_BITS; } +static void pos_bit_calc_for_eint(u32 pin, u32 *pos, u32 *bit) +{ + *pos = pin / MAX_EINT_REG_BITS; + *bit = pin % MAX_EINT_REG_BITS; +} + static s32 gpio_set_dir(u32 pin, u32 dir) { u32 pos; @@ -175,3 +182,58 @@ void gpio_output(gpio_t gpio, int value) gpio_set_dir(gpio, GPIO_DIRECTION_OUT); gpio_set_mode(gpio, GPIO_MODE); } + +int gpio_eint_poll(gpio_t gpio) +{ + u32 pos; + u32 bit; + u32 status; + + assert(gpio <= MAX_8173_GPIO); + + pos_bit_calc_for_eint(gpio, &pos, &bit); + + status = (read32(&mt8173_eint->sta.regs[pos]) >> bit) & 0x1; + + if (status) + write32(&mt8173_eint->ack.regs[pos], 1 << bit); + + return status; +} + +void gpio_eint_configure(gpio_t gpio, enum gpio_irq_type type) +{ + u32 pos; + u32 bit, mask; + + assert(gpio <= MAX_8173_GPIO); + + pos_bit_calc_for_eint(gpio, &pos, &bit); + mask = 1 << bit; + + /* Make it an input first. */ + gpio_input_pullup(gpio); + + write32(&mt8173_eint->d0en[pos], mask); + + switch (type) { + case IRQ_TYPE_EDGE_FALLING: + write32(&mt8173_eint->sens_clr.regs[pos], mask); + write32(&mt8173_eint->pol_clr.regs[pos], mask); + break; + case IRQ_TYPE_EDGE_RISING: + write32(&mt8173_eint->sens_clr.regs[pos], mask); + write32(&mt8173_eint->pol_set.regs[pos], mask); + break; + case IRQ_TYPE_LEVEL_LOW: + write32(&mt8173_eint->sens_set.regs[pos], mask); + write32(&mt8173_eint->pol_clr.regs[pos], mask); + break; + case IRQ_TYPE_LEVEL_HIGH: + write32(&mt8173_eint->sens_set.regs[pos], mask); + write32(&mt8173_eint->pol_set.regs[pos], mask); + break; + } + + write32(&mt8173_eint->mask_clr.regs[pos], mask); +} |