From 2e4640f4a64078376523adbd0572463e4ab81c42 Mon Sep 17 00:00:00 2001 From: CHLin Date: Thu, 11 Oct 2018 14:08:28 +0800 Subject: npcx: add console command to better investigate power consumption of GPIOs This CL adds the console command to disable the input buffer of non-I2C and non-ISR GPIOs which are configured as either input or open-drain. The GPIOs set as 1.8V are also ignored because they are already disabled in the gpio_pre_init. Usage: 1. type "gpiodisable next" to disable the input buffer of next GPIO wihch is either input or open drain in the gpio list. (if the next one is I2C or 1.8V or ((!input) && (!open-drain)), it will ignore it and check the following next one). Ex: > gpiodisable next current GPIO : 16 LID_ACCEL_INT_L --> Ignore 1v8 pin! current GPIO : 17 PLT_RST_L --> Disable WKINEN! > gpiodisable next current GPIO : 18 SYS_RESET_L --> Disable WKINEN! > gpiodisable next current GPIO : 19 ENTERING_RW --> Not Input or OpenDrain current GPIO : 20 PCH_WAKE_L --> Disable WKINEN! ......... ......... > gpiodisable next current GPIO : 34 I2C0_SCL --> Ignore I2C pin! current GPIO : 35 I2C0_SDA --> Ignore I2C pin! current GPIO : 36 I2C1_SCL --> Ignore I2C pin! current GPIO : 37 I2C1_SDA --> Ignore I2C pin! current GPIO : 38 I2C2_SCL --> Ignore I2C pin! current GPIO : 39 I2C2_SDA --> Ignore I2C pin! current GPIO : 40 I2C3_SCL --> Ignore I2C pin! current GPIO : 41 I2C3_SDA --> Ignore I2C pin! current GPIO : 42 I2C4_SCL --> Ignore I2C pin! current GPIO : 43 I2C4_SDA --> Ignore I2C pin! current GPIO : 44 I2C7_SCL --> Ignore I2C pin! current GPIO : 45 I2C7_SDA --> Ignore I2C pin! current GPIO : 46 EN_USB_A0_5V --> Not Input or OpenDrain current GPIO : 47 EN_USB_A1_5V --> Not Input or OpenDrain current GPIO : 48 USB_A0_CHARGE_EN_L --> Not Input or OpenDrain current GPIO : 49 USB_A1_CHARGE_EN_L --> Not Input or OpenDrain current GPIO : 50 USB_C0_BC12_VBUS_ON --> Not Input or OpenDrain current GPIO : 51 USB_C0_BC12_CHG_DET_L --> Disable WKINEN! 2. Enable/Disable a specific GPIO's input buffer by "gpiodisable ${GPIO_NUM_IN_LIST} on|off" (use "gpiodisable list" can check the GPIO_NUM_IN_LIST of a GPIO) Ex: > gpiodisable list 16: LID_ACCEL_INT_L 17: PLT_RST_L 18: SYS_RESET_L ...... ...... > gpiodisable 17 off --> disable input buffer of GPIO PLT_RST_L > gpiodisable 17 on --> enable input buffer of GPIO PLT_RST_L BRANCH=none BUG=b:117139495 TEST=No build errors for "make buildall". TEST=Manually run the console commands and check the result as expected. Change-Id: I7c750804cf45218a3ab1baacefcda64833861b1f Signed-off-by: CHLin Reviewed-on: https://chromium-review.googlesource.com/1275765 Commit-Ready: CH Lin Tested-by: CH Lin Reviewed-by: Aseda Aboagye --- chip/npcx/gpio.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c index f8a17d98a8..8c3f6cde0a 100644 --- a/chip/npcx/gpio.c +++ b/chip/npcx/gpio.c @@ -712,3 +712,100 @@ DECLARE_IRQ(NPCX_IRQ_WKINTFG_2, __gpio_wk2fg_interrupt, 3); #endif #undef GPIO_IRQ_FUNC +#if DEBUG_GPIO && defined(CONFIG_LOW_POWER_IDLE) +/* + * Command used to disable input buffer of gpios one by one to + * investigate power consumption + */ +static int command_gpiodisable(int argc, char **argv) +{ + uint8_t i; + uint8_t offset; + const uint8_t non_isr_gpio_num = GPIO_COUNT - GPIO_IH_COUNT; + const struct gpio_info *g_list; + int flags; + static uint8_t idx = 0; + int num = -1; + int enable; + char *e; + + if (argc == 2) { + if (!strcasecmp(argv[1], "info")) { + offset = idx + GPIO_IH_COUNT; + g_list = gpio_list + offset; + flags = g_list->flags; + + ccprintf("Total GPIO declaration: %d\n", GPIO_COUNT); + ccprintf("Total Non-ISR GPIO declaration: %d\n", + non_isr_gpio_num); + ccprintf("Next GPIO Num to check by "); + ccprintf("\"gpiodisable next\"\n"); + ccprintf(" offset: %d\n", offset); + ccprintf(" current GPIO name: %s\n", g_list->name); + ccprintf(" current GPIO flags: 0x%08x\n", flags); + return EC_SUCCESS; + } + /* List all non-ISR GPIOs in gpio.inc */ + if (!strcasecmp(argv[1], "list")) { + for (i = GPIO_IH_COUNT; i < GPIO_COUNT; i++) + ccprintf("%d: %s\n", i, gpio_get_name(i)); + return EC_SUCCESS; + } + + if (!strcasecmp(argv[1], "next")) { + while (1) { + if (idx == non_isr_gpio_num) + break; + + offset = idx + GPIO_IH_COUNT; + g_list = gpio_list + offset; + flags = g_list->flags; + ccprintf("current GPIO : %d %s --> ", + offset, g_list->name); + if (gpio_is_i2c_pin(offset)) { + ccprintf("Ignore I2C pin!\n"); + idx++; + continue; + } else if (flags & GPIO_SEL_1P8V) { + ccprintf("Ignore 1v8 pin!\n"); + idx++; + continue; + } else { + if ((flags & GPIO_INPUT) || + (flags & GPIO_OPEN_DRAIN)) { + ccprintf("Disable WKINEN!\n"); + gpio_enable_wake_up_input( + offset, 0); + idx++; + break; + } + ccprintf("Not Input or OpenDrain\n"); + idx++; + continue; + } + }; + if (idx == non_isr_gpio_num) { + ccprintf("End of GPIO list, reset index!\n"); + idx = 0; + }; + return EC_SUCCESS; + } + } + if (argc == 3) { + num = strtoi(argv[1], &e, 0); + if (*e || num < GPIO_IH_COUNT || num >= GPIO_COUNT) + return EC_ERROR_PARAM1; + + if (parse_bool(argv[2], &enable)) + gpio_enable_wake_up_input(num, enable ? 1 : 0); + else + return EC_ERROR_PARAM2; + + return EC_SUCCESS; + } + return EC_ERROR_INVAL; +} +DECLARE_CONSOLE_COMMAND(gpiodisable, command_gpiodisable, + "info/list/next/ on|off", + "Disable GPIO input buffer to investigate power consumption"); +#endif -- cgit v1.2.1