summaryrefslogtreecommitdiff
path: root/chip/npcx/gpio.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/npcx/gpio.c')
-rw-r--r--chip/npcx/gpio.c765
1 files changed, 0 insertions, 765 deletions
diff --git a/chip/npcx/gpio.c b/chip/npcx/gpio.c
deleted file mode 100644
index e740f0aa9f..0000000000
--- a/chip/npcx/gpio.c
+++ /dev/null
@@ -1,765 +0,0 @@
-/* Copyright 2014 The Chromium OS Authors. All rights reserved.
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/* GPIO module for Chrome EC */
-
-#include "common.h"
-#include "gpio.h"
-#include "gpio_chip.h"
-#include "i2c.h"
-#include "hooks.h"
-#include "registers.h"
-#include "task.h"
-#include "timer.h"
-#include "util.h"
-#include "system.h"
-#include "system_chip.h"
-#include "ec_commands.h"
-#include "host_command.h"
-#include "hwtimer_chip.h"
-
-#if !(DEBUG_GPIO)
-#define CPUTS(...)
-#define CPRINTS(...)
-#else
-#define CPUTS(outstr) cputs(CC_GPIO, outstr)
-#define CPRINTS(format, args...) cprints(CC_GPIO, format, ## args)
-#endif
-
-/* Constants for GPIO interrupt mapping */
-#define GPIO_INT(name, pin, flags, signal) NPCX_WUI_GPIO_##pin,
-#ifdef CONFIG_LOW_POWER_IDLE
-/* Extend gpio_wui_table for the bypass of better power consumption */
-#define GPIO(name, pin, flags) NPCX_WUI_GPIO_##pin,
-#define UNIMPLEMENTED(name) WUI_NONE,
-#else
-/* Ignore GPIO and UNIMPLEMENTED definitions if not using lower power idle */
-#define GPIO(name, pin, flags)
-#define UNIMPLEMENTED(name)
-#endif
-static const struct npcx_wui gpio_wui_table[] = {
- #include "gpio.wrap"
-};
-
-struct npcx_gpio {
- uint8_t port : 4;
- uint8_t bit : 3;
- uint8_t valid : 1;
-};
-
-BUILD_ASSERT(sizeof(struct npcx_gpio) == 1);
-
-#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9
-struct npcx_alt {
- uint8_t group;
- uint8_t bit : 3;
- uint8_t inverted : 1;
- uint8_t reserved : 4;
-};
-#else
-struct npcx_alt {
- uint8_t group : 4;
- uint8_t bit : 3;
- uint8_t inverted : 1;
-};
-#endif
-
-struct gpio_alt_map {
- struct npcx_gpio gpio;
- struct npcx_alt alt;
-};
-
-#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX9
-BUILD_ASSERT(sizeof(struct gpio_alt_map) == 3);
-#else
-BUILD_ASSERT(sizeof(struct gpio_alt_map) == 2);
-#endif
-
-/* Constants for GPIO alternative mapping */
-const __const_data struct gpio_alt_map gpio_alt_table[] = NPCX_ALT_TABLE;
-
-struct gpio_lvol_item {
- struct npcx_gpio lvol_gpio[8];
-};
-
-/* Constants for GPIO low-voltage mapping */
-const struct gpio_lvol_item gpio_lvol_table[] = NPCX_LVOL_TABLE;
-
-/*****************************************************************************/
-/* Internal functions */
-
-static int gpio_match(uint8_t port, uint8_t bit, struct npcx_gpio gpio)
-{
- return (gpio.valid && (gpio.port == port) && (gpio.bit == bit));
-}
-
-#ifdef CONFIG_CMD_GPIO_EXTENDED
-static uint8_t gpio_is_alt_sel(uint8_t port, uint8_t bit)
-{
- struct gpio_alt_map const *map;
- uint8_t alt_mask, devalt;
-
- for (map = ARRAY_BEGIN(gpio_alt_table);
- map < ARRAY_END(gpio_alt_table);
- map++) {
- if (gpio_match(port, bit, map->gpio)) {
- alt_mask = 1 << map->alt.bit;
- devalt = NPCX_DEVALT(map->alt.group);
- /*
- * alt.inverted == 0:
- * !!(devalt & alt_mask) == 0 -> GPIO
- * !!(devalt & alt_mask) == 1 -> Alternate
- * alt.inverted == 1:
- * !!(devalt & alt_mask) == 0 -> Alternate
- * !!(devalt & alt_mask) == 1 -> GPIO
- */
- return !!(devalt & alt_mask) ^ map->alt.inverted;
- }
- }
- return 0;
-}
-#endif
-
-static int gpio_alt_sel(uint8_t port, uint8_t bit,
- enum gpio_alternate_func 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, bit, map->gpio)) {
- uint8_t alt_mask = 1 << map->alt.bit;
-
- /*
- * func < GPIO_ALT_FUNC_DEFAULT -> GPIO functionality
- * map->alt.inverted -> Set DEVALT bit for GPIO
- */
- if ((func < GPIO_ALT_FUNC_DEFAULT) ^ map->alt.inverted)
- NPCX_DEVALT(map->alt.group) &= ~alt_mask;
- else
- NPCX_DEVALT(map->alt.group) |= alt_mask;
-
- return 1;
- }
- }
-
- if (func > GPIO_ALT_FUNC_DEFAULT)
- CPRINTS("Warn! No alter func in port%d, pin%d", port, bit);
-
- return -1;
-}
-
-/* Set interrupt type for GPIO input */
-static void gpio_interrupt_type_sel(enum gpio_signal signal, uint32_t flags)
-{
- uint8_t table, group, pmask;
-
- if (signal >= GPIO_IH_COUNT)
- return;
-
- table = gpio_wui_table[signal].table;
- group = gpio_wui_table[signal].group;
- pmask = 1 << gpio_wui_table[signal].bit;
-
- ASSERT(flags & GPIO_INT_ANY);
-
- /* Handle interrupt for level trigger */
- if ((flags & GPIO_INT_F_HIGH) || (flags & GPIO_INT_F_LOW)) {
- /* Set detection mode to level */
- NPCX_WKMOD(table, group) |= pmask;
- /* Handle interrupting on level high */
- if (flags & GPIO_INT_F_HIGH)
- NPCX_WKEDG(table, group) &= ~pmask;
- /* Handle interrupting on level low */
- else if (flags & GPIO_INT_F_LOW)
- NPCX_WKEDG(table, group) |= pmask;
- }
- /* Handle interrupt for edge trigger */
- else {
- /* Set detection mode to edge */
- NPCX_WKMOD(table, group) &= ~pmask;
- /* Handle interrupting on both edges */
- if ((flags & GPIO_INT_F_RISING) &&
- (flags & GPIO_INT_F_FALLING)) {
- /* Enable any edge */
- NPCX_WKAEDG(table, group) |= pmask;
- }
- /* Handle interrupting on rising edge */
- else if (flags & GPIO_INT_F_RISING) {
- /* Disable any edge */
- NPCX_WKAEDG(table, group) &= ~pmask;
- NPCX_WKEDG(table, group) &= ~pmask;
- }
- /* Handle interrupting on falling edge */
- else if (flags & GPIO_INT_F_FALLING) {
- /* Disable any edge */
- NPCX_WKAEDG(table, group) &= ~pmask;
- NPCX_WKEDG(table, group) |= pmask;
- }
- }
-
- /* Enable wake-up input sources */
- NPCX_WKINEN(table, group) |= pmask;
- /*
- * Clear pending bit since it might be set
- * if WKINEN bit is changed.
- */
- NPCX_WKPCL(table, group) |= pmask;
-
- /* No support analog mode */
-}
-
-#ifdef CONFIG_CMD_GPIO_EXTENDED
-static uint8_t gpio_is_low_voltage_level_sel(uint8_t port, uint8_t bit)
-{
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(gpio_lvol_table); i++) {
- const struct npcx_gpio *gpio = gpio_lvol_table[i].lvol_gpio;
-
- for (j = 0; j < ARRAY_SIZE(gpio_lvol_table[0].lvol_gpio); j++) {
- if (gpio_match(port, bit, gpio[j]))
- return IS_BIT_SET(NPCX_LV_GPIO_CTL(i), j);
- }
- }
- return 0;
-}
-#endif
-
-/* Select low voltage detection level */
-void gpio_low_voltage_level_sel(uint8_t port, uint8_t bit, uint8_t low_voltage)
-{
- int i, j;
-
- for (i = 0; i < ARRAY_SIZE(gpio_lvol_table); i++) {
- const struct npcx_gpio *gpio = gpio_lvol_table[i].lvol_gpio;
-
- for (j = 0; j < ARRAY_SIZE(gpio_lvol_table[0].lvol_gpio); j++) {
- if (gpio_match(port, bit, gpio[j])) {
- if (low_voltage)
- /* Select vol-detect level for 1.8V */
- SET_BIT(NPCX_LV_GPIO_CTL(i), j);
- else
- /* Select vol-detect level for 3.3V */
- CLEAR_BIT(NPCX_LV_GPIO_CTL(i), j);
- return;
- }
- }
- }
-
- if (low_voltage)
- CPRINTS("Warn! No low voltage support in port:0x%x, bit:%d",
- port, bit);
-}
-
-/* Set the low voltage detection level by mask */
-static void gpio_low_vol_sel_by_mask(uint8_t p, uint8_t mask, uint8_t low_vol)
-{
- int bit;
- uint32_t lv_mask = mask;
-
- while (lv_mask) {
- bit = get_next_bit(&lv_mask);
- gpio_low_voltage_level_sel(p, bit, low_vol);
- };
-}
-/* The bypass of low voltage IOs for better power consumption */
-#ifdef CONFIG_LOW_POWER_IDLE
-static int gpio_is_i2c_pin(enum gpio_signal signal)
-{
- int i;
-
- for (i = 0; i < i2c_ports_used; i++)
- if (i2c_ports[i].scl == signal || i2c_ports[i].sda == signal)
- return 1;
-
- return 0;
-}
-
-static void gpio_enable_wake_up_input(enum gpio_signal signal, int enable)
-{
- const struct npcx_wui *wui = gpio_wui_table + signal;
-
- /* Is it a valid wui mapping item? */
- if (wui->table != MIWU_TABLE_COUNT) {
- /* Turn on/off input io buffer by WKINENx registers */
- if (enable)
- SET_BIT(NPCX_WKINEN(wui->table, wui->group), wui->bit);
- else
- CLEAR_BIT(NPCX_WKINEN(wui->table, wui->group),
- wui->bit);
- }
-}
-
-void gpio_enable_1p8v_i2c_wake_up_input(int enable)
-{
- int i;
-
- /* Set input buffer of 1.8V i2c ports. */
- for (i = 0; i < i2c_ports_used; i++) {
- if (gpio_list[i2c_ports[i].scl].flags & GPIO_SEL_1P8V)
- gpio_enable_wake_up_input(i2c_ports[i].scl, enable);
- if (gpio_list[i2c_ports[i].sda].flags & GPIO_SEL_1P8V)
- gpio_enable_wake_up_input(i2c_ports[i].sda, enable);
- }
-}
-#endif
-
-/*
- * Make sure the bit depth of low voltage register.
- */
-BUILD_ASSERT(ARRAY_SIZE(gpio_lvol_table[0].lvol_gpio) == 8);
-
-/*****************************************************************************/
-/* IC specific low-level driver */
-
-void gpio_set_alternate_function(uint32_t port, uint32_t mask,
- enum gpio_alternate_func func)
-{
- /* Enable alternative pins by func */
- int pin;
-
- /* check each bit from mask */
- for (pin = 0; pin < 8; pin++)
- if (mask & BIT(pin))
- gpio_alt_sel(port, pin, func);
-}
-
-test_mockable int gpio_get_level(enum gpio_signal signal)
-{
- ASSERT(signal_is_gpio(signal));
-
- return !!(NPCX_PDIN(gpio_list[signal].port) & gpio_list[signal].mask);
-}
-
-void gpio_set_level(enum gpio_signal signal, int value)
-{
- ASSERT(signal_is_gpio(signal));
-
- if (value)
- NPCX_PDOUT(gpio_list[signal].port) |= gpio_list[signal].mask;
- else
- NPCX_PDOUT(gpio_list[signal].port) &= ~gpio_list[signal].mask;
-}
-
-#ifdef CONFIG_GPIO_GET_EXTENDED
-int gpio_get_flags_by_mask(uint32_t port, uint32_t mask)
-{
- uint32_t flags = 0;
-
- if (NPCX_PDIR(port) & mask)
- flags |= GPIO_OUTPUT;
- else
- flags |= GPIO_INPUT;
-
- if (NPCX_PDIN(port) & mask)
- flags |= GPIO_HIGH;
- else
- flags |= GPIO_LOW;
-
- if (NPCX_PTYPE(port) & mask)
- flags |= GPIO_OPEN_DRAIN;
-
- /* If internal pulling is enabled */
- if (NPCX_PPULL(port) & mask) {
- if (NPCX_PPUD(port) & mask)
- flags |= GPIO_PULL_DOWN;
- else
- flags |= GPIO_PULL_UP;
- }
-
- if (gpio_is_alt_sel(port, GPIO_MASK_TO_NUM(mask)))
- flags |= GPIO_ALTERNATE;
-
- if (gpio_is_low_voltage_level_sel(port, GPIO_MASK_TO_NUM(mask)))
- flags |= GPIO_SEL_1P8V;
-
- if (NPCX_PLOCK_CTL(port) & mask)
- flags |= GPIO_LOCKED;
-
- return flags;
-}
-#endif
-
-void gpio_set_flags_by_mask(uint32_t port, uint32_t mask, uint32_t flags)
-{
- /* If all GPIO pins are locked, return directly */
-#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7
- if ((NPCX_PLOCK_CTL(port) & mask) == mask)
- return;
-#endif
-
- /*
- * Configure pin as input, if requested. Output is configured only
- * after setting all other attributes, so as not to create a
- * temporary incorrect logic state 0:input 1:output
- */
- if (!(flags & GPIO_OUTPUT))
- NPCX_PDIR(port) &= ~mask;
-
- /* Select open drain 0:push-pull 1:open-drain */
- if (flags & GPIO_OPEN_DRAIN)
- NPCX_PTYPE(port) |= mask;
- else
- NPCX_PTYPE(port) &= ~mask;
-
- /* Select pull-up/down of GPIO 0:pull-up 1:pull-down */
- if (flags & GPIO_PULL_UP) {
- if (flags & GPIO_SEL_1P8V) {
- CPRINTS("Warn! enable internal PU and low voltage mode"
- " at the same time is illegal. port 0x%x, mask 0x%x",
- port, mask);
- } else {
- NPCX_PPUD(port) &= ~mask;
- NPCX_PPULL(port) |= mask; /* enable pull down/up */
- }
- } else if (flags & GPIO_PULL_DOWN) {
- NPCX_PPUD(port) |= mask;
- NPCX_PPULL(port) |= mask; /* enable pull down/up */
- } else {
- /* No pull up/down */
- NPCX_PPULL(port) &= ~mask; /* disable pull down/up */
- }
-
- /* 1.8V low voltage select */
- if (flags & GPIO_SEL_1P8V) {
- /*
- * Set IO type to open-drain before selecting low-voltage level
- */
- NPCX_PTYPE(port) |= mask;
- gpio_low_vol_sel_by_mask(port, mask, 1);
- } else
- gpio_low_vol_sel_by_mask(port, mask, 0);
-
- /* Set up interrupt type */
- if (flags & GPIO_INT_ANY) {
- const struct gpio_info *g = gpio_list;
- enum gpio_signal gpio_int;
-
- /* Find gpio signal in GPIO_INTs by port and mask */
- for (gpio_int = 0; gpio_int < GPIO_IH_COUNT; gpio_int++, g++)
- if ((g->port == port) && (g->mask & mask))
- gpio_interrupt_type_sel(gpio_int, flags);
- }
-
- /* Set level 0:low 1:high*/
- if (flags & GPIO_HIGH)
- NPCX_PDOUT(port) |= mask;
- else if (flags & GPIO_LOW)
- NPCX_PDOUT(port) &= ~mask;
-
- /* Configure pin as output, if requested 0:input 1:output */
- if (flags & GPIO_OUTPUT)
- NPCX_PDIR(port) |= mask;
-
- /* Lock GPIO output and configuration if need */
-#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7
- if (flags & GPIO_LOCKED)
- NPCX_PLOCK_CTL(port) |= mask;
-#endif
-}
-
-int gpio_enable_interrupt(enum gpio_signal signal)
-{
- struct npcx_wui wui;
-
- /* Fail if not an interrupt handler */
- if (signal >= GPIO_IH_COUNT)
- return EC_ERROR_PARAM1;
-
- wui = gpio_wui_table[signal];
- /* Set MIWU enable bit */
- NPCX_WKEN(wui.table, wui.group) |= 1 << wui.bit;
-
- return EC_SUCCESS;
-}
-
-int gpio_disable_interrupt(enum gpio_signal signal)
-{
- struct npcx_wui wui;
-
- /* Fail if not an interrupt handler */
- if (signal >= GPIO_IH_COUNT)
- return EC_ERROR_PARAM1;
-
- wui = gpio_wui_table[signal];
- NPCX_WKEN(wui.table, wui.group) &= ~(1 << wui.bit);
-
- return EC_SUCCESS;
-}
-
-int gpio_clear_pending_interrupt(enum gpio_signal signal)
-{
- struct npcx_wui wui;
-
- /* Fail if not an interrupt handler */
- if (signal >= GPIO_IH_COUNT)
- return EC_ERROR_PARAM1;
-
- wui = gpio_wui_table[signal];
- NPCX_WKPCL(wui.table, wui.group) |= 1 << wui.bit;
-
- return EC_SUCCESS;
-}
-
-void gpio_pre_init(void)
-{
- const struct gpio_info *g = gpio_list;
- const struct unused_pin_info *u = unused_pin_list;
- int is_warm;
- int flags;
- int i, j;
-
- system_check_bbram_on_reset();
- is_warm = system_is_reboot_warm();
-
- /*
- * On power-on of some boards, H1 releases the EC from reset but then
- * quickly asserts and releases the reset a second time. This means the
- * EC sees 2 resets: (1) power-on reset, (2) reset-pin reset. If we add
- * a delay between reset (1) and configuring GPIO output levels, then
- * reset (2) will happen before the end of the delay so we avoid extra
- * output toggles.
- *
- * Make sure to set up the timer before using udelay().
- */
- if (IS_ENABLED(CONFIG_BOARD_RESET_AFTER_POWER_ON) &&
- system_get_reset_flags() & EC_RESET_FLAG_INITIAL_PWR) {
- __hw_early_init_hwtimer(0);
- udelay(2 * SECOND);
- /* Shouldn't get here, but proceeding anyway... */
- }
-
-#ifdef CHIP_FAMILY_NPCX7
- /*
- * TODO: Set bit 7 of DEVCNT again for npcx7 series. Please see Errata
- * for more information. It will be fixed in next chip.
- */
- SET_BIT(NPCX_DEVCNT, 7);
-#endif
-#if NPCX_FAMILY_VERSION >= NPCX_FAMILY_NPCX7
- /* Lock VCC_RST# alternative bit in case switch to GPO77 unexpectedly */
- SET_BIT(NPCX_DEV_CTL4, NPCX_DEV_CTL4_VCC1_RST_LK);
-#endif
-
- /* Pin_Mux for FIU/SPI (set to GPIO) */
- SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_GPIO_NO_SPIP);
-#if defined(NPCX_INT_FLASH_SUPPORT)
- SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
-#endif
-
- /* Pin_Mux for PWRGD */
- SET_BIT(NPCX_DEVALT(1), NPCX_DEVALT1_NO_PWRGD);
-
- /* Pin_Mux for PECI */
-#ifndef CONFIG_PECI
- SET_BIT(NPCX_DEVALT(0xA), NPCX_DEVALTA_NO_PECI_EN);
-#endif
-
- /* Pin_Mux for LPC & SHI */
-#ifdef CONFIG_HOSTCMD_SHI
- /* Switching to eSPI mode for SHI interface */
- NPCX_DEVCNT |= 0x08;
- /* Alternate Intel bus interface LPC/eSPI to GPIOs first */
- SET_BIT(NPCX_DEVALT(ALT_GROUP_1), NPCX_DEVALT1_NO_LPC_ESPI);
-#endif
-
- /* Clear all interrupt pending and enable bits of GPIOS */
- for (i = 0; i < 2; i++) {
- for (j = 0; j < 8; j++) {
- NPCX_WKPCL(i, j) = 0xFF;
- NPCX_WKEN(i, j) = 0;
- }
- }
-
- /* No support enable clock for the GPIO port in run and sleep. */
- /* Set flag for each GPIO pin in gpio_list */
- for (i = 0; i < GPIO_COUNT; i++, g++) {
- flags = g->flags;
-
- if (flags & GPIO_DEFAULT)
- continue;
- /*
- * If this is a warm reboot, don't set the output levels or
- * we'll shut off the AP.
- */
- if (is_warm)
- flags &= ~(GPIO_LOW | GPIO_HIGH);
-
- /* 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,
- GPIO_ALT_FUNC_NONE);
- }
-
- /* The bypass of low voltage IOs for better power consumption */
-#ifdef CONFIG_LOW_POWER_IDLE
- /* Disable input buffer of 1.8V GPIOs without ISR */
- g = gpio_list + GPIO_IH_COUNT;
- for (i = GPIO_IH_COUNT; i < GPIO_COUNT; i++, g++) {
- /*
- * I2c ports are both alternate mode and normal gpio pin, but
- * the alternate mode needs the wake up input even though the
- * normal gpio definition doesn't have an ISR.
- */
- if ((g->flags & GPIO_SEL_1P8V) && !gpio_is_i2c_pin(i))
- gpio_enable_wake_up_input(i, 0);
- }
-#endif
-
- /* Configure unused pins as GPIO INPUT with PU to save power. */
- for (i = 0; i < unused_pin_count; i++, u++) {
- gpio_set_flags_by_mask(u->port, u->mask,
- GPIO_INPUT | GPIO_PULL_UP);
- gpio_set_alternate_function(g->port, g->mask,
- GPIO_ALT_FUNC_NONE);
- }
-}
-
-/*****************************************************************************/
-/* Interrupt handlers */
-
-/**
- * Handle a GPIO interrupt.
- *
- * @param wui_int wui table & group for GPIO interrupt no.
- */
-
-void gpio_interrupt(struct npcx_wui wui_int)
-{
- int i;
- uint8_t wui_mask;
- uint8_t table = wui_int.table;
- uint8_t group = wui_int.group;
-
- /* Get pending mask */
- wui_mask = NPCX_WKPND(table, group) & NPCX_WKEN(table, group);
-
- /* Find GPIOs and execute interrupt service routine */
- for (i = 0; i < GPIO_IH_COUNT && wui_mask; i++) {
- uint8_t pin_mask = 1 << gpio_wui_table[i].bit;
-
- if ((gpio_wui_table[i].table == table) &&
- (gpio_wui_table[i].group == group) &&
- (wui_mask & pin_mask)) {
- /* Clear pending bit of GPIO */
- NPCX_WKPCL(table, group) = pin_mask;
- /* Execute GPIO's ISR */
- gpio_irq_handlers[i](i);
- /* In case declare the same GPIO in gpio_wui_table */
- wui_mask &= ~pin_mask;
- }
- }
-
- if (wui_mask)
- /* No ISR for this interrupt, just clear it */
- NPCX_WKPCL(table, group) = wui_mask;
-}
-
-#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/<num> on|off",
- "Disable GPIO input buffer to investigate power consumption");
-#endif