ec: add a io-sweep function Add a "ec io-sweep" function to test if a series of GPIO are connected correctly to the EC. BUG=none TEST=ec io_sweep Change-Id: I9cafe8d9e9c25f807f2f8fefeb6075adfd353550 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec-aic-tester/+/6182581 Tested-by: Fabio Baltieri <fabiobaltieri@google.com> Commit-Queue: Keith Short <keithshort@chromium.org> Reviewed-by: Keith Short <keithshort@chromium.org>
diff --git a/firmware/boards/google/ec_aic_tester/ec_aic_tester.dts b/firmware/boards/google/ec_aic_tester/ec_aic_tester.dts index 97db69c..a5e247b 100644 --- a/firmware/boards/google/ec_aic_tester/ec_aic_tester.dts +++ b/firmware/boards/google/ec_aic_tester/ec_aic_tester.dts
@@ -106,6 +106,43 @@ aic-pins { compatible = "cros,aic-pins"; ec-rst-gpios = <&gpioe 3 GPIO_ACTIVE_LOW>; + io-gpios = <&gpioc 2 GPIO_ACTIVE_HIGH>, /* CCD_MODE_L */ + <&gpioc 4 GPIO_ACTIVE_HIGH>, /* EN_PP5000_FAN */ + <&gpioe 13 GPIO_ACTIVE_HIGH>, /* I2C_MECC_PDC4_INT_L */ + + /* TODO: figure out why some signals are not getting + * through on the NPCX AIC board + */ + + /* KSI */ + /* <&gpiok 0 GPIO_ACTIVE_HIGH>, */ /* MCU_OUT_KBD_SCANIN_A_ODL */ + <&gpiok 1 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_B_ODL */ + <&gpiok 2 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_C_ODL */ + /* <&gpiok 3 GPIO_ACTIVE_HIGH>, */ /* MCU_OUT_KBD_SCANIN_D_ODL */ + <&gpiok 4 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_E_ODL */ + <&gpiok 5 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_F_ODL */ + <&gpiok 6 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_G_ODL */ + <&gpiok 7 GPIO_ACTIVE_HIGH>, /* MCU_OUT_KBD_SCANIN_H_ODL */ + + /* KSO */ + /* <&gpioj 0 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_A */ + /* <&gpioj 1 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_B */ + <&gpioj 2 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_C */ + <&gpioj 3 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_D */ + <&gpioj 4 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_E */ + <&gpioj 5 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_F */ + /* <&gpioj 6 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_G */ + /* <&gpioj 7 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_H */ + /* <&gpioj 8 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_J */ + /* <&gpioj 9 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_K */ + <&gpioj 10 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_L */ + <&gpioj 11 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_M */ + <&gpioj 12 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_N */ + <&gpioj 13 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_P */ + <&gpioj 14 GPIO_ACTIVE_HIGH>, /* MCU_IN_KBD_SCANOUT_Q */ + <&gpioj 15 GPIO_ACTIVE_HIGH>; /* MCU_IN_KBD_SCANOUT_R */ + /* <&gpioh 3 GPIO_ACTIVE_HIGH>, */ /* MCU_IN_KBD_SCANOUT_S */ + /* <&gpioj 4 GPIO_ACTIVE_HIGH>; */ /* MCU_IN_KBD_SCANOUT_T */ }; npcx-boot {
diff --git a/firmware/dts/bindings/cros,aic-pins.yaml b/firmware/dts/bindings/cros,aic-pins.yaml index 4b57bb9..ab14aa4 100644 --- a/firmware/dts/bindings/cros,aic-pins.yaml +++ b/firmware/dts/bindings/cros,aic-pins.yaml
@@ -11,3 +11,7 @@ ec-rst-gpios: type: phandle-array required: true + + io-gpios: + type: phandle-array + required: true
diff --git a/firmware/src/ec.c b/firmware/src/ec.c index 23cf607..fd537d7 100644 --- a/firmware/src/ec.c +++ b/firmware/src/ec.c
@@ -13,6 +13,7 @@ #include <zephyr/kernel.h> #include <zephyr/logging/log.h> #include <zephyr/shell/shell.h> +#include <zephyr/sys/util.h> LOG_MODULE_REGISTER(ec, LOG_LEVEL_INF); @@ -22,6 +23,9 @@ static const struct gpio_dt_spec ec_rst_gpio = GPIO_DT_SPEC_INST_GET(0, ec_rst_gpios); +static const struct gpio_dt_spec ec_io_gpio[] = { DT_INST_FOREACH_PROP_ELEM_SEP( + 0, io_gpios, GPIO_DT_SPEC_GET_BY_IDX, (, )) }; + static const struct device *reg_pp3300_mecc_core = DEVICE_DT_GET(DT_NODELABEL(pp3300_mecc_core)); static const struct device *reg_pp3300_mecc_z = @@ -88,6 +92,75 @@ INPUT_CALLBACK_DEFINE(DEVICE_DT_GET(DT_NODELABEL(gpio_keys)), button_input_cb, NULL); +static int expect_pin(const struct shell *sh, uint8_t i) +{ + /* TODO: make it work with more than 32 pins */ + uint32_t state = 0; + uint32_t expect = BIT(i); + + for (uint8_t j = 0; j < ARRAY_SIZE(ec_io_gpio); j++) { + const struct gpio_dt_spec *gpio = &ec_io_gpio[j]; + int val; + + val = gpio_pin_get_dt(gpio); + if (val) { + state |= BIT(j); + } + } + + if (state != expect) { + shell_print(sh, "unexpected state (%d) %08x != %08x", i, state, + expect); + return -1; + } + + shell_info(sh, "match state (%d) %08x", i, state); + return 0; +} + +#define IO_SWEEP_TIMEOUT_MS 5000 + +static int cmd_io_sweep(const struct shell *sh, size_t argc, char **argv) +{ + uint64_t start_time; + int ret; + + for (uint8_t i = 0; i < ARRAY_SIZE(ec_io_gpio); i++) { + const struct gpio_dt_spec *gpio = &ec_io_gpio[i]; + + ret = gpio_pin_configure_dt(gpio, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("gpio configuration failed: %d", ret); + return ret; + } + } + + start_time = k_uptime_get(); + for (uint8_t i = 0; i < ARRAY_SIZE(ec_io_gpio); i++) { + while (true) { + if (k_uptime_get() - start_time > IO_SWEEP_TIMEOUT_MS) { + goto timeout; + } + + ret = expect_pin(sh, i); + if (ret < 0) { + k_sleep(K_MSEC(100)); + continue; + } + break; + } + } + + shell_info(sh, "sweep matched all pins successfully"); + + return 0; + +timeout: + shell_error(sh, "timeout"); + + return -ETIME; +} + void ec_reset(void) { gpio_pin_set_dt(&ec_rst_gpio, 1); @@ -120,10 +193,13 @@ return 0; } -SHELL_STATIC_SUBCMD_SET_CREATE( - ec_cmds, SHELL_CMD_ARG(reset, NULL, "reset", cmd_ec_reset, 1, 0), +/* clang-format off */ +SHELL_STATIC_SUBCMD_SET_CREATE(ec_cmds, + SHELL_CMD_ARG(io_sweep, NULL, "io_sweep", cmd_io_sweep, 1, 0), SHELL_CMD_ARG(power, NULL, "power on|off", cmd_ec_power, 2, 0), + SHELL_CMD_ARG(reset, NULL, "reset", cmd_ec_reset, 1, 0), SHELL_SUBCMD_SET_END); +/* clang-format on */ SHELL_CMD_REGISTER(ec, &ec_cmds, "EC control commands", NULL);