summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMulin Chao <mlchao@nuvoton.com>2017-03-03 17:53:27 +0800
committerchrome-bot <chrome-bot@chromium.org>2017-03-21 23:15:09 -0700
commitd788973c18fa3ab99a79408a9e779ba485ac1fc7 (patch)
tree6007bb06d7ee382cc01a345d06a5d05d88e1ce0d
parenta4f6a548d8f3e05d01563b52095b03cecb23fe28 (diff)
downloadchrome-ec-d788973c18fa3ab99a79408a9e779ba485ac1fc7.tar.gz
npcx: gpio: refactor gpio driver for better interrupt latency.
By generating the wui mapping table for GPIO pins which have interrupt handler like CL 451366 did, we needn't browse all items in original gpio_wui_table to find the MIWU info. It saves code space and improves interrupt lantency. BRANCH=none BUG=none TEST=Test gpio functionality on npcx_evb, reef and poppy. Change-Id: I77e9ad439ecf6a501a7976fe5099dd309dba81ee Signed-off-by: Vincent Palatin <vpalatin@chromium.org> Signed-off-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-on: https://chromium-review.googlesource.com/449514
-rw-r--r--chip/npcx/gpio.c433
-rw-r--r--chip/npcx/gpio_wui.h156
2 files changed, 267 insertions, 322 deletions
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
index 831c70e6de..b3916027fc 100644
--- a/chip/npcx/gpio.c
+++ b/chip/npcx/gpio.c
@@ -8,6 +8,7 @@
#include "clock.h"
#include "common.h"
#include "gpio.h"
+#include "gpio_wui.h"
#include "keyboard_config.h"
#include "hooks.h"
#include "registers.h"
@@ -21,6 +22,18 @@
#include "ec_commands.h"
#include "host_command.h"
+struct npcx_wui {
+ uint8_t table : 2;
+ uint8_t group : 3;
+ uint8_t bit : 3;
+};
+
+/* Constants for GPIO interrupt mapping */
+#define GPIO_INT(name, pin, flags, signal) NPCX_WUI_GPIO_##pin,
+static const struct npcx_wui gpio_wui_table[] = {
+ #include "gpio.wrap"
+};
+
/* Flags for PWM IO type */
#define PWM_IO_FUNC (1 << 1) /* PWM optional func bit */
#define PWM_IO_OD (1 << 2) /* PWM IO open-drain bit */
@@ -33,200 +46,9 @@ struct npcx_gpio {
BUILD_ASSERT(sizeof(struct npcx_gpio) == 1);
-struct gpio_wui_item {
- struct npcx_gpio gpio[8];
- uint8_t irq;
-};
-
-/* Macros to initialize the gpio_wui_table */
#define NPCX_GPIO_NONE { 0, 0, 0}
#define NPCX_GPIO(port, pin) {GPIO_PORT_##port, pin, 1}
-const struct gpio_wui_item gpio_wui_table[2][8] = {
- /* MIWU0 */
- {
- /* Group A*/
- { { NPCX_GPIO(8, 0),
- NPCX_GPIO(8, 1),
- NPCX_GPIO(8, 2),
- NPCX_GPIO(8, 3),
- NPCX_GPIO(8, 4),
- NPCX_GPIO(8, 5),
- NPCX_GPIO(8, 6),
- NPCX_GPIO(8, 7), },
- NPCX_IRQ_MTC_WKINTAD_0 },
- /* Group B */
- { { NPCX_GPIO(9, 0),
- NPCX_GPIO(9, 1),
- NPCX_GPIO(9, 2),
- NPCX_GPIO(9, 3),
- NPCX_GPIO(9, 4),
- NPCX_GPIO(9, 5),
- NPCX_GPIO_NONE, /* MSWC Wake-Up */
- NPCX_GPIO_NONE, }, /* T0OUT Wake-Up */
- NPCX_IRQ_TWD_WKINTB_0 },
- /* Group C */
- { { NPCX_GPIO(9, 6),
- NPCX_GPIO(9, 7),
- NPCX_GPIO(A, 0),
- NPCX_GPIO(A, 1),
- NPCX_GPIO(A, 2),
- NPCX_GPIO(A, 3),
- NPCX_GPIO(A, 4),
- NPCX_GPIO(A, 5), },
- NPCX_IRQ_WKINTC_0 },
- /* Group D */
- { { NPCX_GPIO(A, 6),
- NPCX_GPIO(A, 7),
- NPCX_GPIO(B, 0),
- NPCX_GPIO_NONE, /* SMB0 Wake-Up */
- NPCX_GPIO_NONE, /* SMB1 Wake-Up */
- NPCX_GPIO(B, 1),
- NPCX_GPIO(B, 2),
- NPCX_GPIO_NONE, }, /* MTC Wake-Up */
- NPCX_IRQ_MTC_WKINTAD_0 },
- /* Group E */
- { { NPCX_GPIO(B, 3),
- NPCX_GPIO(B, 4),
- NPCX_GPIO(B, 5),
- NPCX_GPIO_NONE,
- NPCX_GPIO(B, 7),
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE, /* Host Wake-Up */
- NPCX_GPIO_NONE, }, /* LRESET Wake-Up */
- NPCX_IRQ_WKINTEFGH_0 },
- /* Group F */
- { { NPCX_GPIO(C, 0),
- NPCX_GPIO(C, 1),
- NPCX_GPIO(C, 2),
- NPCX_GPIO(C, 3),
- NPCX_GPIO(C, 4),
- NPCX_GPIO(C, 5),
- NPCX_GPIO(C, 6),
- NPCX_GPIO(C, 7), },
- NPCX_IRQ_WKINTEFGH_0 },
- /* Group G */
- { { NPCX_GPIO(D, 0),
- NPCX_GPIO(D, 1),
- NPCX_GPIO(D, 2),
- NPCX_GPIO(D, 3),
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE, },
- NPCX_IRQ_WKINTEFGH_0 },
- /* Group H */
- { { NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO(E, 7), },
- NPCX_IRQ_WKINTEFGH_0 }, },
- /* MIWU1 */
- {
- /* Group A */
- { { NPCX_GPIO(0, 0),
- NPCX_GPIO(0, 1),
- NPCX_GPIO(0, 2),
- NPCX_GPIO(0, 3),
- NPCX_GPIO(0, 4),
- NPCX_GPIO(0, 5),
- NPCX_GPIO(0, 6),
- NPCX_GPIO(0, 7), },
- NPCX_IRQ_WKINTA_1 },
- /* Group B */
- { { NPCX_GPIO(1, 0),
- NPCX_GPIO(1, 1),
- NPCX_GPIO_NONE,
- NPCX_GPIO(1, 3),
- NPCX_GPIO(1, 4),
- NPCX_GPIO(1, 5),
- NPCX_GPIO(1, 6),
- NPCX_GPIO(1, 7), },
- NPCX_IRQ_WKINTB_1 },
- /* Group C */
-#ifdef HAS_TASK_KEYSCAN
- { { NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE,
- NPCX_GPIO_NONE, },
- NPCX_IRQ_COUNT },
-#else
- { { NPCX_GPIO(3, 1),
- NPCX_GPIO(3, 0),
- NPCX_GPIO(2, 7),
- NPCX_GPIO(2, 6),
- NPCX_GPIO(2, 5),
- NPCX_GPIO(2, 4),
- NPCX_GPIO(2, 3),
- NPCX_GPIO(2, 2), },
- NPCX_IRQ_KSI_WKINTC_1 },
-#endif
- /* Group D */
- { { NPCX_GPIO(2, 0),
- NPCX_GPIO(2, 1),
- NPCX_GPIO_NONE,
- NPCX_GPIO(3, 3),
- NPCX_GPIO(3, 4),
- NPCX_GPIO_NONE,
- NPCX_GPIO(3, 6),
- NPCX_GPIO(3, 7), },
- NPCX_IRQ_WKINTD_1 },
- /* Group E */
- { { NPCX_GPIO(4, 0),
- NPCX_GPIO(4, 1),
- NPCX_GPIO(4, 2),
- NPCX_GPIO(4, 3),
- NPCX_GPIO(4, 4),
- NPCX_GPIO(4, 5),
- NPCX_GPIO(4, 6),
- NPCX_GPIO(4, 7), },
- NPCX_IRQ_WKINTE_1 },
- /* Group F */
- { { NPCX_GPIO(5, 0),
- NPCX_GPIO(5, 1),
- NPCX_GPIO(5, 2),
- NPCX_GPIO(5, 3),
- NPCX_GPIO(5, 4),
- NPCX_GPIO(5, 5),
- NPCX_GPIO(5, 6),
- NPCX_GPIO(5, 7), },
- NPCX_IRQ_WKINTF_1 },
- /* Group G */
- { { NPCX_GPIO(6, 0),
- NPCX_GPIO(6, 1),
- NPCX_GPIO(6, 2),
- NPCX_GPIO(6, 3),
- NPCX_GPIO(6, 4),
- NPCX_GPIO(6, 5),
- NPCX_GPIO(6, 6),
- NPCX_GPIO(7, 1), },
- NPCX_IRQ_WKINTG_1 },
- /* Group H */
- { { NPCX_GPIO(7, 0),
- NPCX_GPIO(6, 7),
- NPCX_GPIO(7, 2),
- NPCX_GPIO(7, 3),
- NPCX_GPIO(7, 4),
- NPCX_GPIO(7, 5),
- NPCX_GPIO(7, 6),
- NPCX_GPIO_NONE, },
- NPCX_IRQ_WKINTH_1 }, },
-};
-
-/*
- * Only the first two MIWU tables are supported.
- */
-BUILD_ASSERT(ARRAY_SIZE(gpio_wui_table) == 2);
-BUILD_ASSERT(ARRAY_SIZE(gpio_wui_table[0]) == MIWU_GROUP_COUNT);
-
struct npcx_alt {
uint8_t group : 4;
uint8_t bit : 3;
@@ -372,45 +194,11 @@ const struct gpio_lvol_item gpio_lvol_table[] = {
/*****************************************************************************/
/* Internal functions */
-struct gpio_wui_gpio_info {
- uint8_t table : 1;
- uint8_t group : 3;
- uint8_t bit : 3;
- uint8_t valid : 1;
-};
-
-BUILD_ASSERT(sizeof(struct gpio_wui_gpio_info) == 1);
-
static int gpio_match(uint8_t port, uint8_t mask, struct npcx_gpio gpio)
{
return (gpio.valid && (gpio.port == port) && ((1 << gpio.bit) == mask));
}
-static struct gpio_wui_gpio_info gpio_find_wui_from_io(uint8_t port,
- uint8_t mask)
-{
- int i, j, k;
-
- for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) {
- for (j = 0; j < ARRAY_SIZE(gpio_wui_table[0]); j++) {
- const struct npcx_gpio *gpio =
- gpio_wui_table[i][j].gpio;
-
- for (k = 0; k < 8; k++) {
- if (gpio_match(port, mask, gpio[k]))
- return ((struct gpio_wui_gpio_info) {
- .table = i,
- .group = j,
- .bit = k,
- .valid = 1,
- });
- }
- }
- }
-
- return ((struct gpio_wui_gpio_info) { .valid = 0 });
-}
-
static void gpio_pwm_io_type_sel(uint8_t chan, uint8_t func)
{
if (func & PWM_IO_OD)
@@ -451,33 +239,20 @@ static int gpio_alt_sel(uint8_t port, uint8_t bit, int8_t func)
return -1;
}
-static void gpio_execute_isr(uint8_t port, uint8_t mask)
-{
- int i;
- const struct gpio_info *g = gpio_list;
- /* Find GPIOs and execute interrupt service routine */
- for (i = 0; i < GPIO_IH_COUNT; i++, g++) {
- if (port == g->port && mask == g->mask) {
- gpio_irq_handlers[i](i);
- return;
- }
- }
-}
-
/* Set interrupt type for GPIO input */
-static void gpio_interrupt_type_sel(uint8_t port, uint8_t mask, uint32_t flags)
+static void gpio_interrupt_type_sel(enum gpio_signal signal, uint32_t flags)
{
- struct gpio_wui_gpio_info wui = gpio_find_wui_from_io(port, mask);
- uint8_t table = wui.table;
- uint8_t group = wui.group;
- uint8_t pmask = 1 << wui.bit;
+ uint8_t table, group, pmask;
- if (!wui.valid)
+ if (signal >= ARRAY_SIZE(gpio_wui_table))
return;
+ table = gpio_wui_table[signal].table;
+ group = gpio_wui_table[signal].group;
+ pmask = 1 << gpio_wui_table[signal].bit;
+
/* Handle interrupt for level trigger */
- if ((flags & GPIO_INT_F_HIGH) ||
- (flags & GPIO_INT_F_LOW)) {
+ if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) {
/* Set detection mode to level */
NPCX_WKMOD(table, group) |= pmask;
/* Handle interrupting on level high */
@@ -496,8 +271,7 @@ static void gpio_interrupt_type_sel(uint8_t port, uint8_t mask, uint32_t flags)
NPCX_WKPCL(table, group) |= pmask;
}
/* Handle interrupt for edge trigger */
- else if ((flags & GPIO_INT_F_RISING) ||
- (flags & GPIO_INT_F_FALLING)) {
+ else if ((flags & GPIO_INT_F_RISING) || (flags & GPIO_INT_F_FALLING)) {
/* Set detection mode to edge */
NPCX_WKMOD(table, group) &= ~pmask;
/* Handle interrupting on both edges */
@@ -627,8 +401,15 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
gpio_low_voltage_level_sel(port, mask, 0);
/* Set up interrupt type */
- if (flags & GPIO_INPUT)
- gpio_interrupt_type_sel(port, mask, flags);
+ if (flags & GPIO_INT_ANY) {
+ const struct gpio_info *g = gpio_list;
+ enum gpio_signal gpio_int;
+
+ /* Find gpio signal in GPIO_INTs by port and mask */
+ for (gpio_int = 0; gpio_int < GPIO_IH_COUNT; gpio_int++, g++)
+ if ((g->port == port) && (g->mask & mask))
+ gpio_interrupt_type_sel(gpio_int, flags);
+ }
/* Set level 0:low 1:high*/
if (flags & GPIO_HIGH)
@@ -643,43 +424,44 @@ void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
int gpio_enable_interrupt(enum gpio_signal signal)
{
- const struct gpio_info *g = gpio_list + signal;
- struct gpio_wui_gpio_info wui = gpio_find_wui_from_io(g->port, g->mask);
+ struct npcx_wui wui;
- /* Set MIWU enable bit */
- if (wui.valid)
- NPCX_WKEN(wui.table, wui.group) |= (1 << wui.bit);
- else
+ /* Fail if not an interrupt handler */
+ if (signal >= GPIO_IH_COUNT)
return EC_ERROR_PARAM1;
+ wui = gpio_wui_table[signal];
+ /* Set MIWU enable bit */
+ NPCX_WKEN(wui.table, wui.group) |= 1 << wui.bit;
+
return EC_SUCCESS;
}
int gpio_disable_interrupt(enum gpio_signal signal)
{
- const struct gpio_info *g = gpio_list + signal;
- struct gpio_wui_gpio_info wui = gpio_find_wui_from_io(g->port, g->mask);
+ struct npcx_wui wui;
- /* Clear MIWU enable bit */
- if (wui.valid)
- NPCX_WKEN(wui.table, wui.group) &= ~(1 << wui.bit);
- else
+ /* Fail if not an interrupt handler */
+ if (signal >= GPIO_IH_COUNT)
return EC_ERROR_PARAM1;
+ wui = gpio_wui_table[signal];
+ NPCX_WKEN(wui.table, wui.group) &= ~(1 << wui.bit);
+
return EC_SUCCESS;
}
int gpio_clear_pending_interrupt(enum gpio_signal signal)
{
- const struct gpio_info *g = gpio_list + signal;
- struct gpio_wui_gpio_info wui = gpio_find_wui_from_io(g->port, g->mask);
+ struct npcx_wui wui;
- /* Clear pending interrupt for this signal */
- if (wui.valid)
- NPCX_WKPCL(wui.table, wui.group) |= (1 << wui.bit);
- else
+ /* Fail if not an interrupt handler */
+ if (signal >= GPIO_IH_COUNT)
return EC_ERROR_PARAM1;
+ wui = gpio_wui_table[signal];
+ NPCX_WKPCL(wui.table, wui.group) |= 1 << wui.bit;
+
return EC_SUCCESS;
}
@@ -749,13 +531,21 @@ void gpio_pre_init(void)
* bank is different for different systems. */
static void gpio_init(void)
{
- int i, j;
/* Enable IRQs now that pins are set up */
- for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++)
- for (j = 0; j < ARRAY_SIZE(gpio_wui_table[0]); j++)
- if (gpio_wui_table[i][j].irq < NPCX_IRQ_COUNT)
- task_enable_irq(gpio_wui_table[i][j].irq);
-
+ task_enable_irq(NPCX_IRQ_MTC_WKINTAD_0);
+ task_enable_irq(NPCX_IRQ_WKINTEFGH_0);
+ task_enable_irq(NPCX_IRQ_WKINTC_0);
+ task_enable_irq(NPCX_IRQ_TWD_WKINTB_0);
+ task_enable_irq(NPCX_IRQ_WKINTA_1);
+ task_enable_irq(NPCX_IRQ_WKINTB_1);
+#ifndef HAS_TASK_KEYSCAN
+ task_enable_irq(NPCX_IRQ_KSI_WKINTC_1);
+#endif
+ task_enable_irq(NPCX_IRQ_WKINTD_1);
+ task_enable_irq(NPCX_IRQ_WKINTE_1);
+ task_enable_irq(NPCX_IRQ_WKINTF_1);
+ task_enable_irq(NPCX_IRQ_WKINTG_1);
+ task_enable_irq(NPCX_IRQ_WKINTH_1);
}
DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT);
@@ -765,40 +555,32 @@ DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT);
/**
* Handle a GPIO interrupt.
*
- * @param int_no Interrupt number for GPIO
+ * @param wui_int wui table & group for GPIO interrupt no.
*/
-static void gpio_interrupt(int int_no)
+static void gpio_interrupt(struct npcx_wui wui_int)
{
- uint8_t i, j, pin, wui_mask;
-
- for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) {
- for (j = 0; j < ARRAY_SIZE(gpio_wui_table[0]); j++) {
- const struct npcx_gpio *gpio =
- gpio_wui_table[i][j].gpio;
-
- if (gpio_wui_table[i][j].irq != int_no)
- continue;
-
- /* Get pending mask */
- wui_mask = NPCX_WKPND(i, j);
-
- /* Get enabled mask */
- wui_mask &= NPCX_WKEN(i, j);
-
- /* If pending bits is not zero */
- if (!wui_mask)
- continue;
-
- for (pin = 0; pin < 8; pin++, gpio++)
- /* If GPIO's pending bit is set, execute ISR */
- if ((wui_mask & (1 << pin)) && gpio->valid) {
- /* Clear pending bit of GPIO */
- NPCX_WKPCL(i, j) = (1 << pin);
- /* Execute GPIO's ISR */
- gpio_execute_isr(gpio->port,
- 1 << gpio->bit);
- }
+ int i;
+ uint8_t wui_mask;
+ uint8_t table = wui_int.table;
+ uint8_t group = wui_int.group;
+
+ /* Get pending mask */
+ wui_mask = NPCX_WKPND(table, group) & NPCX_WKEN(table, group);
+
+ /* Find GPIOs and execute interrupt service routine */
+ for (i = 0; i < GPIO_IH_COUNT && wui_mask; i++) {
+ uint8_t pin_mask = 1 << gpio_wui_table[i].bit;
+
+ if ((gpio_wui_table[i].table == table) &&
+ (gpio_wui_table[i].group == group) &&
+ (wui_mask & pin_mask)) {
+ /* Clear pending bit of GPIO */
+ NPCX_WKPCL(table, group) = pin_mask;
+ /* Execute GPIO's ISR */
+ gpio_irq_handlers[i](i);
+ /* In case declare the same GPIO in gpio_wui_table */
+ wui_mask &= ~pin_mask;
}
}
}
@@ -808,10 +590,10 @@ static void gpio_interrupt(int int_no)
* the port, then call the master handler above.
*/
-#define GPIO_IRQ_FUNC(_irq_func, int_no) \
-void _irq_func(void) \
-{ \
- gpio_interrupt(int_no); \
+#define GPIO_IRQ_FUNC(_irq_func, wui_int) \
+void _irq_func(void) \
+{ \
+ gpio_interrupt(wui_int); \
}
/* If we need to handle the other type interrupts except GPIO, add code here */
@@ -837,7 +619,12 @@ void __gpio_wk0efgh_interrupt(void)
#endif
else
#endif
- gpio_interrupt(NPCX_IRQ_WKINTEFGH_0);
+ {
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_5));
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_6));
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_7));
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_8));
+ }
}
void __gpio_rtc_interrupt(void)
@@ -850,23 +637,25 @@ void __gpio_rtc_interrupt(void)
host_set_events(EC_HOST_EVENT_MASK(EC_HOST_EVENT_RTC));
} else
#endif
- gpio_interrupt(NPCX_IRQ_MTC_WKINTAD_0);
+ {
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_1));
+ gpio_interrupt(WUI_INT(MIWU_TABLE_0, MIWU_GROUP_4));
+ }
}
-GPIO_IRQ_FUNC(__gpio_wk0ad_interrupt , NPCX_IRQ_MTC_WKINTAD_0);
-GPIO_IRQ_FUNC(__gpio_wk0b_interrupt , NPCX_IRQ_TWD_WKINTB_0);
-GPIO_IRQ_FUNC(__gpio_wk0c_interrupt , NPCX_IRQ_WKINTC_0);
-GPIO_IRQ_FUNC(__gpio_wk1a_interrupt , NPCX_IRQ_WKINTA_1);
-GPIO_IRQ_FUNC(__gpio_wk1b_interrupt , NPCX_IRQ_WKINTB_1);
+GPIO_IRQ_FUNC(__gpio_wk0b_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_2));
+GPIO_IRQ_FUNC(__gpio_wk0c_interrupt, WUI_INT(MIWU_TABLE_0, MIWU_GROUP_3));
+GPIO_IRQ_FUNC(__gpio_wk1a_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_1));
+GPIO_IRQ_FUNC(__gpio_wk1b_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_2));
#ifndef HAS_TASK_KEYSCAN
/* Delcare GPIO irq functions for KSI pins if there's no keyboard scan task, */
-GPIO_IRQ_FUNC(__gpio_wk1c_interrupt , NPCX_IRQ_KSI_WKINTC_1);
+GPIO_IRQ_FUNC(__gpio_wk1c_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_3));
#endif
-GPIO_IRQ_FUNC(__gpio_wk1d_interrupt , NPCX_IRQ_WKINTD_1);
-GPIO_IRQ_FUNC(__gpio_wk1e_interrupt , NPCX_IRQ_WKINTE_1);
-GPIO_IRQ_FUNC(__gpio_wk1f_interrupt , NPCX_IRQ_WKINTF_1);
-GPIO_IRQ_FUNC(__gpio_wk1g_interrupt , NPCX_IRQ_WKINTG_1);
-GPIO_IRQ_FUNC(__gpio_wk1h_interrupt , NPCX_IRQ_WKINTH_1);
+GPIO_IRQ_FUNC(__gpio_wk1d_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_4));
+GPIO_IRQ_FUNC(__gpio_wk1e_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_5));
+GPIO_IRQ_FUNC(__gpio_wk1f_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_6));
+GPIO_IRQ_FUNC(__gpio_wk1g_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_7));
+GPIO_IRQ_FUNC(__gpio_wk1h_interrupt, WUI_INT(MIWU_TABLE_1, MIWU_GROUP_8));
DECLARE_IRQ(NPCX_IRQ_MTC_WKINTAD_0, __gpio_rtc_interrupt, 2);
DECLARE_IRQ(NPCX_IRQ_TWD_WKINTB_0, __gpio_wk0b_interrupt, 2);
diff --git a/chip/npcx/gpio_wui.h b/chip/npcx/gpio_wui.h
new file mode 100644
index 0000000000..c768097502
--- /dev/null
+++ b/chip/npcx/gpio_wui.h
@@ -0,0 +1,156 @@
+/* Copyright 2017 The Chromium OS Authors. All rights reserved.
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+/* GPIO interrupt/wake-up mapping */
+
+#ifndef __CROS_EC_GPIO_WUI_H
+#define __CROS_EC_GPIO_WUI_H
+
+#include "common.h"
+
+#define NPCX_WUI_GPIO_PIN(port, index) NPCX_WUI_GPIO_##port##_##index
+#define WUI(tbl, grp, idx) ((struct npcx_wui) { .table = tbl, .group = grp, \
+ .bit = idx })
+#define WUI_INT(tbl, grp) WUI(tbl, grp, 0)
+
+/* MIWU0 */
+/* Group A: NPCX_IRQ_MTC_WKINTAD_0 */
+#define NPCX_WUI_GPIO_8_0 WUI(0, MIWU_GROUP_1, 0)
+#define NPCX_WUI_GPIO_8_1 WUI(0, MIWU_GROUP_1, 1)
+#define NPCX_WUI_GPIO_8_2 WUI(0, MIWU_GROUP_1, 2)
+#define NPCX_WUI_GPIO_8_3 WUI(0, MIWU_GROUP_1, 3)
+#define NPCX_WUI_GPIO_8_4 WUI(0, MIWU_GROUP_1, 4)
+#define NPCX_WUI_GPIO_8_5 WUI(0, MIWU_GROUP_1, 5)
+#define NPCX_WUI_GPIO_8_6 WUI(0, MIWU_GROUP_1, 6)
+#define NPCX_WUI_GPIO_8_7 WUI(0, MIWU_GROUP_1, 7)
+
+/* Group B: NPCX_IRQ_TWD_WKINTB_0 */
+#define NPCX_WUI_GPIO_9_0 WUI(0, MIWU_GROUP_2, 0)
+#define NPCX_WUI_GPIO_9_1 WUI(0, MIWU_GROUP_2, 1)
+#define NPCX_WUI_GPIO_9_2 WUI(0, MIWU_GROUP_2, 2)
+#define NPCX_WUI_GPIO_9_3 WUI(0, MIWU_GROUP_2, 3)
+#define NPCX_WUI_GPIO_9_4 WUI(0, MIWU_GROUP_2, 4)
+#define NPCX_WUI_GPIO_9_5 WUI(0, MIWU_GROUP_2, 5)
+
+/* Group C: NPCX_IRQ_WKINTC_0 */
+#define NPCX_WUI_GPIO_9_6 WUI(0, MIWU_GROUP_3, 0)
+#define NPCX_WUI_GPIO_9_7 WUI(0, MIWU_GROUP_3, 1)
+#define NPCX_WUI_GPIO_A_0 WUI(0, MIWU_GROUP_3, 2)
+#define NPCX_WUI_GPIO_A_1 WUI(0, MIWU_GROUP_3, 3)
+#define NPCX_WUI_GPIO_A_2 WUI(0, MIWU_GROUP_3, 4)
+#define NPCX_WUI_GPIO_A_3 WUI(0, MIWU_GROUP_3, 5)
+#define NPCX_WUI_GPIO_A_4 WUI(0, MIWU_GROUP_3, 6)
+#define NPCX_WUI_GPIO_A_5 WUI(0, MIWU_GROUP_3, 7)
+
+/* Group D: NPCX_IRQ_MTC_WKINTAD_0 */
+#define NPCX_WUI_GPIO_A_6 WUI(0, MIWU_GROUP_4, 0)
+#define NPCX_WUI_GPIO_A_7 WUI(0, MIWU_GROUP_4, 1)
+#define NPCX_WUI_GPIO_B_0 WUI(0, MIWU_GROUP_4, 2)
+#define NPCX_WUI_GPIO_B_1 WUI(0, MIWU_GROUP_4, 5)
+#define NPCX_WUI_GPIO_B_2 WUI(0, MIWU_GROUP_4, 6)
+
+/* Group E: NPCX_IRQ_WKINTEFGH_0 */
+#define NPCX_WUI_GPIO_B_3 WUI(0, MIWU_GROUP_5, 0)
+#define NPCX_WUI_GPIO_B_4 WUI(0, MIWU_GROUP_5, 1)
+#define NPCX_WUI_GPIO_B_5 WUI(0, MIWU_GROUP_5, 2)
+#define NPCX_WUI_GPIO_B_7 WUI(0, MIWU_GROUP_5, 4)
+
+/* Group F: NPCX_IRQ_WKINTEFGH_0 */
+#define NPCX_WUI_GPIO_C_0 WUI(0, MIWU_GROUP_6, 0)
+#define NPCX_WUI_GPIO_C_1 WUI(0, MIWU_GROUP_6, 1)
+#define NPCX_WUI_GPIO_C_2 WUI(0, MIWU_GROUP_6, 2)
+#define NPCX_WUI_GPIO_C_3 WUI(0, MIWU_GROUP_6, 3)
+#define NPCX_WUI_GPIO_C_4 WUI(0, MIWU_GROUP_6, 4)
+#define NPCX_WUI_GPIO_C_5 WUI(0, MIWU_GROUP_6, 5)
+#define NPCX_WUI_GPIO_C_6 WUI(0, MIWU_GROUP_6, 6)
+#define NPCX_WUI_GPIO_C_7 WUI(0, MIWU_GROUP_6, 7)
+
+/* Group G: NPCX_IRQ_WKINTEFGH_0 */
+#define NPCX_WUI_GPIO_D_0 WUI(0, MIWU_GROUP_7, 0)
+#define NPCX_WUI_GPIO_D_1 WUI(0, MIWU_GROUP_7, 1)
+#define NPCX_WUI_GPIO_D_2 WUI(0, MIWU_GROUP_7, 2)
+#define NPCX_WUI_GPIO_D_3 WUI(0, MIWU_GROUP_7, 3)
+
+/* Group H: NPCX_IRQ_WKINTEFGH_0 */
+#define NPCX_WUI_GPIO_E_7 WUI(0, MIWU_GROUP_8, 7)
+
+/* MIWU1 */
+/* Group A: NPCX_IRQ_WKINTA_1 */
+#define NPCX_WUI_GPIO_0_0 WUI(1, MIWU_GROUP_1, 0)
+#define NPCX_WUI_GPIO_0_1 WUI(1, MIWU_GROUP_1, 1)
+#define NPCX_WUI_GPIO_0_2 WUI(1, MIWU_GROUP_1, 2)
+#define NPCX_WUI_GPIO_0_3 WUI(1, MIWU_GROUP_1, 3)
+#define NPCX_WUI_GPIO_0_4 WUI(1, MIWU_GROUP_1, 4)
+#define NPCX_WUI_GPIO_0_5 WUI(1, MIWU_GROUP_1, 5)
+#define NPCX_WUI_GPIO_0_6 WUI(1, MIWU_GROUP_1, 6)
+#define NPCX_WUI_GPIO_0_7 WUI(1, MIWU_GROUP_1, 7)
+
+/* Group B: NPCX_IRQ_WKINTB_1 */
+#define NPCX_WUI_GPIO_1_0 WUI(1, MIWU_GROUP_2, 0)
+#define NPCX_WUI_GPIO_1_1 WUI(1, MIWU_GROUP_2, 1)
+#define NPCX_WUI_GPIO_1_3 WUI(1, MIWU_GROUP_2, 3)
+#define NPCX_WUI_GPIO_1_4 WUI(1, MIWU_GROUP_2, 4)
+#define NPCX_WUI_GPIO_1_5 WUI(1, MIWU_GROUP_2, 5)
+#define NPCX_WUI_GPIO_1_6 WUI(1, MIWU_GROUP_2, 6)
+#define NPCX_WUI_GPIO_1_7 WUI(1, MIWU_GROUP_2, 7)
+
+/* Group C: NPCX_IRQ_KSI_WKINTC_1 */
+#define NPCX_WUI_GPIO_3_1 WUI(1, MIWU_GROUP_3, 0)
+#define NPCX_WUI_GPIO_3_0 WUI(1, MIWU_GROUP_3, 1)
+#define NPCX_WUI_GPIO_2_7 WUI(1, MIWU_GROUP_3, 2)
+#define NPCX_WUI_GPIO_2_6 WUI(1, MIWU_GROUP_3, 3)
+#define NPCX_WUI_GPIO_2_5 WUI(1, MIWU_GROUP_3, 4)
+#define NPCX_WUI_GPIO_2_4 WUI(1, MIWU_GROUP_3, 5)
+#define NPCX_WUI_GPIO_2_3 WUI(1, MIWU_GROUP_3, 6)
+#define NPCX_WUI_GPIO_2_2 WUI(1, MIWU_GROUP_3, 7)
+
+/* Group D: NPCX_IRQ_WKINTD_1 */
+#define NPCX_WUI_GPIO_2_0 WUI(1, MIWU_GROUP_4, 0)
+#define NPCX_WUI_GPIO_2_1 WUI(1, MIWU_GROUP_4, 1)
+#define NPCX_WUI_GPIO_3_3 WUI(1, MIWU_GROUP_4, 3)
+#define NPCX_WUI_GPIO_3_4 WUI(1, MIWU_GROUP_4, 4)
+#define NPCX_WUI_GPIO_3_6 WUI(1, MIWU_GROUP_4, 6)
+#define NPCX_WUI_GPIO_3_7 WUI(1, MIWU_GROUP_4, 7)
+
+/* Group E: NPCX_IRQ_WKINTE_1 */
+#define NPCX_WUI_GPIO_4_0 WUI(1, MIWU_GROUP_5, 0)
+#define NPCX_WUI_GPIO_4_1 WUI(1, MIWU_GROUP_5, 1)
+#define NPCX_WUI_GPIO_4_2 WUI(1, MIWU_GROUP_5, 2)
+#define NPCX_WUI_GPIO_4_3 WUI(1, MIWU_GROUP_5, 3)
+#define NPCX_WUI_GPIO_4_4 WUI(1, MIWU_GROUP_5, 4)
+#define NPCX_WUI_GPIO_4_5 WUI(1, MIWU_GROUP_5, 5)
+#define NPCX_WUI_GPIO_4_6 WUI(1, MIWU_GROUP_5, 6)
+#define NPCX_WUI_GPIO_4_7 WUI(1, MIWU_GROUP_5, 7)
+
+/* Group F: NPCX_IRQ_WKINTF_1 */
+#define NPCX_WUI_GPIO_5_0 WUI(1, MIWU_GROUP_6, 0)
+#define NPCX_WUI_GPIO_5_1 WUI(1, MIWU_GROUP_6, 1)
+#define NPCX_WUI_GPIO_5_2 WUI(1, MIWU_GROUP_6, 2)
+#define NPCX_WUI_GPIO_5_3 WUI(1, MIWU_GROUP_6, 3)
+#define NPCX_WUI_GPIO_5_4 WUI(1, MIWU_GROUP_6, 4)
+#define NPCX_WUI_GPIO_5_5 WUI(1, MIWU_GROUP_6, 5)
+#define NPCX_WUI_GPIO_5_6 WUI(1, MIWU_GROUP_6, 6)
+#define NPCX_WUI_GPIO_5_7 WUI(1, MIWU_GROUP_6, 7)
+
+/* Group G: NPCX_IRQ_WKINTG_1 */
+#define NPCX_WUI_GPIO_6_0 WUI(1, MIWU_GROUP_7, 0)
+#define NPCX_WUI_GPIO_6_1 WUI(1, MIWU_GROUP_7, 1)
+#define NPCX_WUI_GPIO_6_2 WUI(1, MIWU_GROUP_7, 2)
+#define NPCX_WUI_GPIO_6_3 WUI(1, MIWU_GROUP_7, 3)
+#define NPCX_WUI_GPIO_6_4 WUI(1, MIWU_GROUP_7, 4)
+#define NPCX_WUI_GPIO_6_5 WUI(1, MIWU_GROUP_7, 5)
+#define NPCX_WUI_GPIO_6_6 WUI(1, MIWU_GROUP_7, 6)
+#define NPCX_WUI_GPIO_7_1 WUI(1, MIWU_GROUP_7, 7)
+
+/* Group H: NPCX_IRQ_WKINTH_1 */
+#define NPCX_WUI_GPIO_7_0 WUI(1, MIWU_GROUP_8, 0)
+#define NPCX_WUI_GPIO_6_7 WUI(1, MIWU_GROUP_8, 1)
+#define NPCX_WUI_GPIO_7_2 WUI(1, MIWU_GROUP_8, 2)
+#define NPCX_WUI_GPIO_7_3 WUI(1, MIWU_GROUP_8, 3)
+#define NPCX_WUI_GPIO_7_4 WUI(1, MIWU_GROUP_8, 4)
+#define NPCX_WUI_GPIO_7_5 WUI(1, MIWU_GROUP_8, 5)
+#define NPCX_WUI_GPIO_7_6 WUI(1, MIWU_GROUP_8, 6)
+
+#endif /* __CROS_EC_GPIO_WUI_H */