summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Staaf <robotboy@chromium.org>2016-02-29 13:55:32 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-03-02 11:22:51 -0800
commitc86c7799dd89af5d8d0303d38c264e6bcc0271e5 (patch)
tree65abd4054bc25dd6e218a34749b6c26b3e4c17f9
parent62055e53b6fa4a914618d4e97617663a2b62980a (diff)
downloadchrome-ec-c86c7799dd89af5d8d0303d38c264e6bcc0271e5.tar.gz
NPCX: Refactor GPIO driver for functionality and size
Body 5678901234567890123456789012345678901234567890123456789012345678901 Previously the GPIO driver used quite redundant encodings for its WUI and DEVALT mapping tables. This refactor compresses those tables significantly, while adding the ability to represent an inverted DEVALT bit. The resulting RO firmware image for Wheatley is 384 bytes smaller. This commit also corrects the interpretation of the func parameter to gpio_set_alternate_function. Any non-negative func should be interpreted as a request to switch a pin to an alternate mode. Signed-off-by: Anton Staaf <robotboy@chromium.org> BRANCH=None BUG=None TEST=make buildall -j Ran on Wheatley, manually verified basic functionality Change-Id: I3a56a4b56d13a70a30c388e7e2c77dd7acd3838a Reviewed-on: https://chromium-review.googlesource.com/329761 Commit-Ready: Anton Staaf <robotboy@chromium.org> Tested-by: Anton Staaf <robotboy@chromium.org> Reviewed-by: Mulin Chao <mlchao@nuvoton.com> Reviewed-by: Shawn N <shawnn@chromium.org>
-rw-r--r--chip/npcx/gpio.c581
-rw-r--r--include/compile_time_macros.h4
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)