summaryrefslogtreecommitdiff
path: root/chip/npcx/gpio.c
diff options
context:
space:
mode:
authorJack Rosenthal <jrosenth@chromium.org>2021-11-04 12:11:58 -0600
committerCommit Bot <commit-bot@chromium.org>2021-11-05 04:22:34 +0000
commit252457d4b21f46889eebad61d4c0a65331919cec (patch)
tree01856c4d31d710b20e85a74c8d7b5836e35c3b98 /chip/npcx/gpio.c
parent08f5a1e6fc2c9467230444ac9b582dcf4d9f0068 (diff)
downloadchrome-ec-stabilize-voshyr-14637.B-ish.tar.gz
In the interest of making long-term branch maintenance incur as little technical debt on us as possible, we should not maintain any files on the branch we are not actually using. This has the added effect of making it extremely clear when merging CLs from the main branch when changes have the possibility to affect us. The follow-on CL adds a convenience script to actually pull updates from the main branch and generate a CL for the update. BUG=b:204206272 BRANCH=ish TEST=make BOARD=arcada_ish && make BOARD=drallion_ish Signed-off-by: Jack Rosenthal <jrosenth@chromium.org> Change-Id: I17e4694c38219b5a0823e0a3e55a28d1348f4b18 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3262038 Reviewed-by: Jett Rink <jettrink@chromium.org> Reviewed-by: Tom Hughes <tomhughes@chromium.org>
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