diff --git a/src/ec/ite/ec.mk b/src/ec/ite/ec.mk index eef69a3..2a4608b 100644 --- a/src/ec/ite/ec.mk +++ b/src/ec/ite/ec.mk @@ -9,6 +9,7 @@ ec-y += kbc.c ec-y += pmc.c ec-y += ps2.c ec-y += signature.c +ec-y += wuc.c ifeq ($(CONFIG_EC_ITE_IT8587E), y) CFLAGS+=-DCONFIG_EC_ITE_IT8587E=1 diff --git a/src/ec/ite/include/ec/wuc.h b/src/ec/ite/include/ec/wuc.h index 800fdba..43a79b3 100644 --- a/src/ec/ite/include/ec/wuc.h +++ b/src/ec/ite/include/ec/wuc.h @@ -55,4 +55,14 @@ volatile uint8_t __xdata __at(0x1B2D) WUESR13; volatile uint8_t __xdata __at(0x1B30) WUEMR14; volatile uint8_t __xdata __at(0x1B31) WUESR14; +enum WucEdgeMode { + EDGE_RISING, + EDGE_FALLING, + EDGE_BOTH, +}; + +void wuc_enable(uint8_t nr, enum WucEdgeMode detect); +void wuc_disable(uint8_t nr); +void wuc_clear(uint8_t nr); + #endif // _EC_WUC_H diff --git a/src/ec/ite/wuc.c b/src/ec/ite/wuc.c new file mode 100644 index 0000000..cf875c3 --- /dev/null +++ b/src/ec/ite/wuc.c @@ -0,0 +1,82 @@ +// SPDX-License-Identifier: GPL-3.0-only + +#include +#include +#include + +struct WucGroup { + volatile uint8_t *edge; + volatile uint8_t *sense; + volatile uint8_t *enable; +}; + +// clang-format off + +// Only groups 1, 3, and 4 have WUENR. +#define WUC_GROUP_EN(nr) { \ + .edge = &WUEMR ## nr, \ + .sense = &WUESR ## nr, \ + .enable = &WUENR ## nr, \ +} + +#define WUC_GROUP(nr) { \ + .edge = &WUEMR ## nr, \ + .sense = &WUESR ## nr, \ + .enable = NULL, \ +} + +static const struct WucGroup wuc[] = { + // Group 0 unused + WUC_GROUP_EN(1), + WUC_GROUP(2), + WUC_GROUP_EN(3), + WUC_GROUP_EN(4), + // Group 5 unused + WUC_GROUP(6), + WUC_GROUP(7), + WUC_GROUP(8), + WUC_GROUP(9), + WUC_GROUP(10), + WUC_GROUP(11), + WUC_GROUP(12), + WUC_GROUP(13), + WUC_GROUP(14), +}; + +// clang-format on + +void wuc_enable(uint8_t nr, enum WucEdgeMode detect) { + // XXX: SDCC doesn't optimize division with power-of-2. + const uint8_t group = nr >> 3U; + const uint8_t bit = nr % 8U; + + if (detect == EDGE_RISING) { + *(wuc[group].edge) &= ~BIT(bit); + } else if (detect == EDGE_FALLING || detect == EDGE_BOTH) { + *(wuc[group].edge) |= BIT(bit); + } + + *(wuc[group].sense) = BIT(bit); + + if (wuc[group].enable) { + *(wuc[group].enable) |= BIT(bit); + } +} + +void wuc_disable(uint8_t nr) { + // XXX: SDCC doesn't optimize division with power-of-2. + const uint8_t group = nr >> 3U; + const uint8_t bit = nr % 8U; + + if (wuc[group].enable) { + *(wuc[group].enable) &= ~BIT(bit); + } +} + +void wuc_clear(uint8_t nr) { + // XXX: SDCC doesn't optimize division with power-of-2. + const uint8_t group = nr >> 3U; + const uint8_t bit = nr % 8U; + + *(wuc[group].sense) = BIT(bit); +}