diff options
-rw-r--r-- | chip/npcx/gpio.c | 581 | ||||
-rw-r--r-- | include/compile_time_macros.h | 4 |
2 files changed, 315 insertions, 270 deletions
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c index a2178fcc35..4656d0b6e7 100644 --- a/chip/npcx/gpio.c +++ b/chip/npcx/gpio.c @@ -19,204 +19,217 @@ #include "system_chip.h" #include "lpc_chip.h" -/* Marco functions for GPIO WUI/ALT table */ -#define NPCX_GPIO(grp, pin) \ - GPIO_PORT_##grp, MASK_PIN##pin -#define NPCX_GPIO_NONE \ - GPIO_PORT_COUNT, 0xFF -#define NPCX_WUI(tbl, grp, pin) \ - MIWU_TABLE_##tbl, MIWU_GROUP_##grp, MASK_PIN##pin - -#define ALT_MASK(pin) \ - CONCAT2(MASK_PIN, pin) -#define ALT_PIN(grp, pin) \ - ALT_MASK(NPCX_DEVALT##grp##_##pin) -#define NPCX_ALT(grp, pin) \ - ALT_GROUP_##grp, ALT_PIN(grp, pin) - /* 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 */ -struct gpio_wui_map { - uint8_t gpio_port; - uint8_t gpio_mask; - uint8_t wui_table; - uint8_t wui_group; - uint8_t wui_mask; +struct npcx_gpio { + uint8_t port : 4; + uint8_t bit : 3; + uint8_t valid : 1; }; +BUILD_ASSERT(sizeof(struct npcx_gpio) == 1); + struct gpio_wui_item { - struct gpio_wui_map wui_map[8]; - uint8_t irq; + 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 */ + { { 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 }, + /* 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 }, }, }; -const struct gpio_wui_item gpio_wui_table[] = { - /* MIWU0 Group A */ - { { { NPCX_GPIO(8, 0), NPCX_WUI(0, 1, 0) }, - { NPCX_GPIO(8, 1), NPCX_WUI(0, 1, 1) }, - { NPCX_GPIO(8, 2), NPCX_WUI(0, 1, 2) }, - { NPCX_GPIO(8, 3), NPCX_WUI(0, 1, 3) }, - { NPCX_GPIO(8, 4), NPCX_WUI(0, 1, 4) }, - { NPCX_GPIO(8, 5), NPCX_WUI(0, 1, 5) }, - { NPCX_GPIO(8, 6), NPCX_WUI(0, 1, 6) }, - { NPCX_GPIO(8, 7), NPCX_WUI(0, 1, 7) }, - }, NPCX_IRQ_MTC_WKINTAD_0 }, - /* MIWU0 Group B */ - { { { NPCX_GPIO(9, 0), NPCX_WUI(0, 2, 0) }, - { NPCX_GPIO(9, 1), NPCX_WUI(0, 2, 1) }, - { NPCX_GPIO(9, 2), NPCX_WUI(0, 2, 2) }, - { NPCX_GPIO(9, 3), NPCX_WUI(0, 2, 3) }, - { NPCX_GPIO(9, 4), NPCX_WUI(0, 2, 4) }, - { NPCX_GPIO(9, 5), NPCX_WUI(0, 2, 5) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 2, 6) }, /* MSWC Wake-Up */ - { NPCX_GPIO_NONE, NPCX_WUI(0, 2, 7) }, /* T0OUT Wake-Up */ - }, NPCX_IRQ_TWD_WKINTB_0 }, - /* MIWU0 Group C */ - { { { NPCX_GPIO(9, 6), NPCX_WUI(0, 3, 0) }, - { NPCX_GPIO(9, 7), NPCX_WUI(0, 3, 1) }, - { NPCX_GPIO(A, 0), NPCX_WUI(0, 3, 2) }, - { NPCX_GPIO(A, 1), NPCX_WUI(0, 3, 3) }, - { NPCX_GPIO(A, 2), NPCX_WUI(0, 3, 4) }, - { NPCX_GPIO(A, 3), NPCX_WUI(0, 3, 5) }, - { NPCX_GPIO(A, 4), NPCX_WUI(0, 3, 6) }, - { NPCX_GPIO(A, 5), NPCX_WUI(0, 3, 7) }, - }, NPCX_IRQ_WKINTC_0 }, - /* MIWU0 Group D */ - { { { NPCX_GPIO(A, 6), NPCX_WUI(0, 4, 0) }, - { NPCX_GPIO(A, 7), NPCX_WUI(0, 4, 1) }, - { NPCX_GPIO(B, 0), NPCX_WUI(0, 4, 2) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 4, 3) }, /* SMB0 Wake-Up */ - { NPCX_GPIO_NONE, NPCX_WUI(0, 4, 4) }, /* SMB1 Wake-Up */ - { NPCX_GPIO(B, 1), NPCX_WUI(0, 4, 5) }, - { NPCX_GPIO(B, 2), NPCX_WUI(0, 4, 6) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 4, 7) }, /* MTC Wake-Up */ - }, NPCX_IRQ_MTC_WKINTAD_0 }, - - /* MIWU0 Group E */ - { { { NPCX_GPIO(B, 3), NPCX_WUI(0, 5 , 0) }, - { NPCX_GPIO(B, 4), NPCX_WUI(0, 5 , 1) }, - { NPCX_GPIO(B, 5), NPCX_WUI(0, 5 , 2) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 5 , 3) }, - { NPCX_GPIO(B, 7), NPCX_WUI(0, 5 , 4) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 5 , 5) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 5 , 6) }, /* Host Wake-Up */ - { NPCX_GPIO_NONE, NPCX_WUI(0, 5 , 7) }, /* LRESET Wake-Up */ - }, NPCX_IRQ_WKINTEFGH_0 }, - - /* MIWU0 Group F */ - { { { NPCX_GPIO(C, 0), NPCX_WUI(0, 6, 0) }, - { NPCX_GPIO(C, 1), NPCX_WUI(0, 6, 1) }, - { NPCX_GPIO(C, 2), NPCX_WUI(0, 6, 2) }, - { NPCX_GPIO(C, 3), NPCX_WUI(0, 6, 3) }, - { NPCX_GPIO(C, 4), NPCX_WUI(0, 6, 4) }, - { NPCX_GPIO(C, 5), NPCX_WUI(0, 6, 5) }, - { NPCX_GPIO(C, 6), NPCX_WUI(0, 6, 6) }, - { NPCX_GPIO(C, 7), NPCX_WUI(0, 6, 7) }, - }, NPCX_IRQ_WKINTEFGH_0 }, - /* MIWU0 Group G */ - { { { NPCX_GPIO(D, 0), NPCX_WUI(0, 7, 0) }, - { NPCX_GPIO(D, 1), NPCX_WUI(0, 7, 1) }, - { NPCX_GPIO(D, 2), NPCX_WUI(0, 7, 2) }, - { NPCX_GPIO(D, 3), NPCX_WUI(0, 7, 3) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 7, 4) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 7, 5) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 7, 6) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 7, 7) }, - }, NPCX_IRQ_WKINTEFGH_0 }, - /* MIWU0 Group H */ - { { { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 0) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 1) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 2) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 3) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 4) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 5) }, - { NPCX_GPIO_NONE, NPCX_WUI(0, 8, 6) }, - { NPCX_GPIO(E, 7), NPCX_WUI(0, 8, 7) }, - }, NPCX_IRQ_WKINTEFGH_0 }, - - /* MIWU1 Group A */ - { { { NPCX_GPIO(0, 0), NPCX_WUI(1, 1, 0) }, - { NPCX_GPIO(0, 1), NPCX_WUI(1, 1, 1) }, - { NPCX_GPIO(0, 2), NPCX_WUI(1, 1, 2) }, - { NPCX_GPIO(0, 3), NPCX_WUI(1, 1, 3) }, - { NPCX_GPIO(0, 4), NPCX_WUI(1, 1, 4) }, - { NPCX_GPIO(0, 5), NPCX_WUI(1, 1, 5) }, - { NPCX_GPIO(0, 6), NPCX_WUI(1, 1, 6) }, - { NPCX_GPIO(0, 7), NPCX_WUI(1, 1, 7) }, - }, NPCX_IRQ_WKINTA_1 }, - /* MIWU1 Group B */ - { { { NPCX_GPIO(1, 0), NPCX_WUI(1, 2, 0) }, - { NPCX_GPIO(1, 1), NPCX_WUI(1, 2, 1) }, - { NPCX_GPIO_NONE, NPCX_WUI(1, 2, 2) }, - { NPCX_GPIO(1, 3), NPCX_WUI(1, 2, 3) }, - { NPCX_GPIO(1, 4), NPCX_WUI(1, 2, 4) }, - { NPCX_GPIO(1, 5), NPCX_WUI(1, 2, 5) }, - { NPCX_GPIO(1, 6), NPCX_WUI(1, 2, 6) }, - { NPCX_GPIO(1, 7), NPCX_WUI(1, 2, 7) }, - }, NPCX_IRQ_WKINTB_1 }, - /* MIWU1 Group C -- Skipping */ - /* MIWU1 Group D */ - { { { NPCX_GPIO(2, 0), NPCX_WUI(1, 4, 0) }, - { NPCX_GPIO(2, 1), NPCX_WUI(1, 4, 1) }, - { NPCX_GPIO_NONE, NPCX_WUI(1, 4, 2) }, - { NPCX_GPIO(3, 3), NPCX_WUI(1, 4, 3) }, - { NPCX_GPIO(3, 4), NPCX_WUI(1, 4, 4) }, - { NPCX_GPIO_NONE, NPCX_WUI(1, 4, 5) }, - { NPCX_GPIO(3, 6), NPCX_WUI(1, 4, 6) }, - { NPCX_GPIO(3, 7), NPCX_WUI(1, 4, 7) }, - }, NPCX_IRQ_WKINTD_1 }, - - /* MIWU1 Group E */ - { { { NPCX_GPIO(4, 0), NPCX_WUI(1, 5, 0) }, - { NPCX_GPIO(4, 1), NPCX_WUI(1, 5, 1) }, - { NPCX_GPIO(4, 2), NPCX_WUI(1, 5, 2) }, - { NPCX_GPIO(4, 3), NPCX_WUI(1, 5, 3) }, - { NPCX_GPIO(4, 4), NPCX_WUI(1, 5, 4) }, - { NPCX_GPIO(4, 5), NPCX_WUI(1, 5, 5) }, - { NPCX_GPIO(4, 6), NPCX_WUI(1, 5, 6) }, - { NPCX_GPIO(4, 7), NPCX_WUI(1, 5, 7) }, - }, NPCX_IRQ_WKINTE_1 }, - - /* MIWU1 Group F */ - { { { NPCX_GPIO(5, 0), NPCX_WUI(1, 6, 0) }, - { NPCX_GPIO(5, 1), NPCX_WUI(1, 6, 1) }, - { NPCX_GPIO(5, 2), NPCX_WUI(1, 6, 2) }, - { NPCX_GPIO(5, 3), NPCX_WUI(1, 6, 3) }, - { NPCX_GPIO(5, 4), NPCX_WUI(1, 6, 4) }, - { NPCX_GPIO(5, 5), NPCX_WUI(1, 6, 5) }, - { NPCX_GPIO(5, 6), NPCX_WUI(1, 6, 6) }, - { NPCX_GPIO(5, 7), NPCX_WUI(1, 6, 7) }, - }, NPCX_IRQ_WKINTF_1 }, - /* MIWU1 Group G */ - { { { NPCX_GPIO(6, 0), NPCX_WUI(1, 7, 0) }, - { NPCX_GPIO(6, 1), NPCX_WUI(1, 7, 1) }, - { NPCX_GPIO(6, 2), NPCX_WUI(1, 7, 2) }, - { NPCX_GPIO(6, 3), NPCX_WUI(1, 7, 3) }, - { NPCX_GPIO(6, 4), NPCX_WUI(1, 7, 4) }, - { NPCX_GPIO(6, 5), NPCX_WUI(1, 7, 5) }, - { NPCX_GPIO(6, 6), NPCX_WUI(1, 7, 6) }, - { NPCX_GPIO(7, 1), NPCX_WUI(1, 7, 7) }, - }, NPCX_IRQ_WKINTG_1 }, - /* MIWU1 Group H */ - { { { NPCX_GPIO(7, 0), NPCX_WUI(1, 8, 0) }, - { NPCX_GPIO(6, 7), NPCX_WUI(1, 8, 1) }, - { NPCX_GPIO(7, 2), NPCX_WUI(1, 8, 2) }, - { NPCX_GPIO(7, 3), NPCX_WUI(1, 8, 3) }, - { NPCX_GPIO(7, 4), NPCX_WUI(1, 8, 4) }, - { NPCX_GPIO(7, 5), NPCX_WUI(1, 8, 5) }, - { NPCX_GPIO(7, 6), NPCX_WUI(1, 8, 6) }, - { NPCX_GPIO_NONE, NPCX_WUI(1, 8, 7) }, - }, 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; + uint8_t inverted : 1; }; struct gpio_alt_map { - uint8_t gpio_port; - uint8_t gpio_mask; - uint8_t alt_group; - uint8_t alt_mask; + struct npcx_gpio gpio; + struct npcx_alt alt; }; +BUILD_ASSERT(sizeof(struct gpio_alt_map) == 2); + +/* Convenient macros to initialize the gpio_alt_table */ +#define NPCX_ALT(grp, pin) { ALT_GROUP_##grp, NPCX_DEVALT##grp##_##pin, 0 } +#define NPCX_ALT_INV(grp, pin) { ALT_GROUP_##grp, NPCX_DEVALT##grp##_##pin, 1 } + const struct gpio_alt_map gpio_alt_table[] = { /* I2C Module */ { NPCX_GPIO(B, 2), NPCX_ALT(2, I2C0_1_SL)}, /* SMB0SDA1 */ @@ -269,73 +282,97 @@ const struct gpio_alt_map gpio_alt_table[] = { /*****************************************************************************/ /* Internal functions */ -const struct gpio_wui_map *gpio_find_wui_from_io(uint8_t port, uint8_t mask) + +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) { - int i, j; - for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) { - const struct gpio_wui_map *map = gpio_wui_table[i].wui_map; - for (j = 0; j < 8; j++, map++) { - if (map->gpio_port == port && map->gpio_mask == mask) - return map; - } - } - return NULL; + return (gpio.valid && (gpio.port == port) && ((1 << gpio.bit) == mask)); } -int gpio_find_irq_from_io(uint8_t port, uint8_t mask) +static struct gpio_wui_gpio_info gpio_find_wui_from_io(uint8_t port, + uint8_t mask) { - int i, j; + int i, j, k; + for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) { - const struct gpio_wui_map *map = gpio_wui_table[i].wui_map; - for (j = 0; j < 8; j++, map++) { - if (map->gpio_port == port && map->gpio_mask == mask) - return gpio_wui_table[i].irq; + 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 int gpio_find_irq_from_io(uint8_t port, uint8_t mask) +{ + struct gpio_wui_gpio_info wui = gpio_find_wui_from_io(port, mask); + + if (wui.valid) + return gpio_wui_table[wui.table][wui.group].irq; + return -1; } -void gpio_pwm_io_type_sel(uint8_t alt_mask, uint8_t func) +static void gpio_pwm_io_type_sel(uint8_t chan, uint8_t func) { - uint8_t chan = 0; - do { - alt_mask = (alt_mask >> 1); - if (alt_mask == 0) - break; - chan++; - } while (1); - - /* Set PWM open drain output is open drain type*/ if (func & PWM_IO_OD) + /* Set PWM open drain output is open drain type*/ SET_BIT(NPCX_PWMCTLEX(chan), NPCX_PWMCTLEX_OD_OUT); - else /* Set PWM open drain output is push-pull type*/ + else + /* Set PWM open drain output is push-pull type*/ CLEAR_BIT(NPCX_PWMCTLEX(chan), NPCX_PWMCTLEX_OD_OUT); } -int gpio_alt_sel(uint8_t port, uint8_t mask, int8_t func) +static int gpio_alt_sel(uint8_t port, uint8_t bit, int8_t func) { - int i; - const struct gpio_alt_map *map = gpio_alt_table; - for (i = 0; i < ARRAY_SIZE(gpio_alt_table); i++, map++) { - if (map->gpio_port == port && - (map->gpio_mask == mask)) { - /* Enable alternative function if func >=0 */ - if (func <= 0) /* GPIO functionality */ - NPCX_DEVALT(map->alt_group) &= ~(map->alt_mask); - else { - NPCX_DEVALT(map->alt_group) |= (map->alt_mask); - /* PWM optional functionality */ - if (func & PWM_IO_FUNC) - gpio_pwm_io_type_sel(map->alt_mask, - func); - } + struct gpio_alt_map const *map; + + for (map = ARRAY_BEGIN(gpio_alt_table); + map < ARRAY_END(gpio_alt_table); + map++) { + if (gpio_match(port, 1 << bit, map->gpio)) { + uint8_t alt_mask = 1 << map->alt.bit; + + /* + * func < 0 -> GPIO functionality + * map->alt.inverted -> Set DEVALT bit for GPIO + */ + if ((func < 0) ^ map->alt.inverted) + NPCX_DEVALT(map->alt.group) &= ~alt_mask; + else + NPCX_DEVALT(map->alt.group) |= alt_mask; + + /* PWM optional functionality */ + if ((func >= 0) && (func & PWM_IO_FUNC)) + gpio_pwm_io_type_sel(map->alt.bit, func); + return 1; } } + return -1; } -void gpio_execute_isr(uint8_t port, uint8_t mask) +static void gpio_execute_isr(uint8_t port, uint8_t mask) { int i; const struct gpio_info *g = gpio_list; @@ -349,18 +386,16 @@ void gpio_execute_isr(uint8_t port, uint8_t mask) } /* Set interrupt type for GPIO input */ -void gpio_interrupt_type_sel(uint8_t port, uint8_t mask, uint32_t flags) +static void gpio_interrupt_type_sel(uint8_t port, uint8_t mask, uint32_t flags) { - const struct gpio_wui_map *map = gpio_find_wui_from_io(port, mask); - uint8_t table, group, pmask; + 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; - if (map == NULL) + if (!wui.valid) return; - table = map->wui_table; - group = map->wui_group; - pmask = map->wui_mask; - /* Handle interrupt for level trigger */ if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) { @@ -428,29 +463,24 @@ void gpio_set_alternate_function(uint32_t port, uint32_t mask, int func) { /* Enable alternative pins by func*/ int pin; - uint8_t pmask; + /* check each bit from mask */ - for (pin = 0; pin < 8; pin++) { - pmask = (mask & (1 << pin)); - if (pmask) - gpio_alt_sel(port, pmask, func); - } + for (pin = 0; pin < 8; pin++) + if (mask & (1 << pin)) + gpio_alt_sel(port, pin, func); } test_mockable int gpio_get_level(enum gpio_signal signal) { - return (NPCX_PDIN(gpio_list[signal].port) & - gpio_list[signal].mask) ? 1 : 0; + return !!(NPCX_PDIN(gpio_list[signal].port) & gpio_list[signal].mask); } void gpio_set_level(enum gpio_signal signal, int value) { if (value) - NPCX_PDOUT(gpio_list[signal].port) |= - gpio_list[signal].mask; + NPCX_PDOUT(gpio_list[signal].port) |= gpio_list[signal].mask; else - NPCX_PDOUT(gpio_list[signal].port) &= - ~gpio_list[signal].mask; + NPCX_PDOUT(gpio_list[signal].port) &= ~gpio_list[signal].mask; } void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags) @@ -583,6 +613,13 @@ void gpio_pre_init(void) /* Set up GPIO based on flags */ gpio_set_flags_by_mask(g->port, g->mask, flags); + + /* + * Ensure that any GPIO defined in gpio.inc is actually + * configured as a GPIO, and not left in its default state, + * which may or may not be as a GPIO. + */ + gpio_set_alternate_function(g->port, g->mask, -1); } } @@ -591,10 +628,12 @@ void gpio_pre_init(void) * bank is different for different systems. */ static void gpio_init(void) { - int i; + int i, j; /* Enable IRQs now that pins are set up */ for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) - task_enable_irq(gpio_wui_table[i].irq); + 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); } DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); @@ -611,32 +650,34 @@ DECLARE_HOOK(HOOK_INIT, gpio_init, HOOK_PRIO_DEFAULT); static void gpio_interrupt(int int_no) { #if DEBUG_GPIO - static uint8_t i, pin, wui_mask; + static uint8_t i, j, pin, wui_mask; #else - uint8_t i, pin, wui_mask; + uint8_t i, j, pin, wui_mask; #endif + for (i = 0; i < ARRAY_SIZE(gpio_wui_table); i++) { - /* If interrupt number is the same */ - if (gpio_wui_table[i].irq == int_no) { - /* Mapping relationship between WUI and GPIO */ - const struct gpio_wui_map *map = - gpio_wui_table[i].wui_map; + 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(map->wui_table , map->wui_group); + wui_mask = NPCX_WKPND(i, j); /* If pending bits is not zero */ - if (wui_mask) { - /* Clear pending bits of WUI */ - NPCX_WKPCL(map->wui_table , map->wui_group) - = wui_mask; - - for (pin = 0; pin < 8; pin++, map++) { - /* If pending bit is high, execute ISR*/ - if (wui_mask & (1<<pin)) - gpio_execute_isr(map->gpio_port, - map->gpio_mask); - } - } + if (!wui_mask) + continue; + + /* Clear pending bits of WUI */ + NPCX_WKPCL(i, j) = wui_mask; + + for (pin = 0; pin < 8; pin++, gpio++) + /* If pending bit is high, execute ISR*/ + if (wui_mask & (1 << pin)) + gpio_execute_isr(gpio->port, + 1 << gpio->bit); } } } diff --git a/include/compile_time_macros.h b/include/compile_time_macros.h index 9b543f9493..f25ffd8407 100644 --- a/include/compile_time_macros.h +++ b/include/compile_time_macros.h @@ -18,6 +18,10 @@ /* Number of elements in an array */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +/* Make for loops that iterate over pointers to array entries more readable */ +#define ARRAY_BEGIN(array) (array) +#define ARRAY_END(array) ((array) + ARRAY_SIZE(array)) + /* Just in case - http://gcc.gnu.org/onlinedocs/gcc/Offsetof.html */ #ifndef offsetof #define offsetof(type, member) __builtin_offsetof(type, member) |