summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMary Ruthven <mruthven@chromium.org>2022-04-25 13:43:36 -0500
committerChromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com>2022-04-27 14:11:48 +0000
commit76d059d1441f3d87b38b100a2a477ac0d73b1cc7 (patch)
tree7a4201d82e76cd23699019ef08ee0a40d08bc5b2
parent0ab123eac0939364c96c07ed279148864c3e41fd (diff)
downloadchrome-ec-76d059d1441f3d87b38b100a2a477ac0d73b1cc7.tar.gz
gpio: add gpio flags to disable sleep
Add GPIO_SLEEP_DIS_LOW and GPIO_SLEEP_DIS_HIGH to disable sleep when a gpio with one of those flags is asserted. GPIO_SLEEP_DIS_LOW disables sleep when the signal is set to 0. GPIO_SLEEP_DIS_HIGH disables sleep when the signal is set to 1. This will disable all forms of sleep. The flags can be used for ccd signals to ensure cr50 doesn't enter sleep while c2d2 or servo micro are relying on a ccd signal to flash the device. These flags should not be add to signals used during normal cr50 operation. They disable regular sleep regular sleep so using them will significantly increase cr50 power consumption. This change adds GPIO_SLEEP_DIS_HIGH to AP_FLASH_SELECT. I'll add more signals in followup CLs. This change also replaces SLEEP_MASK_CHARGING with SLEEP_MASK_GPIO. Nothing was using SLEEP_MASK_CHARGING. BUG=b:229974371 TEST=Toggle AP_FLASH_SELECT while the AP is off. Verify cr50 doesn't enter deep sleep and the gpiocfg and sleepmask output looks ok. > gpioset AP_FLASH_SELECT 1 > gpiocfg GPIO0_GPIO1: read 0 drive 0 GPIO0_GPIO2: read 1 drive 1 GPIO1_GPIO0: read 0 INT_RISING GPIO1_GPIO1: read 0 INT_HIGH GPIO1_GPIO4: read 0 INT_FALLING GPIO1_GPIO5: read 0 drive 1 GPIO1_GPIO7: read 0 INT_RISING GPIO1_GPIO8: read 0 INT_FALLING gpio sleepmask: 00001000 > sleepmask sleep mask: 00000008 > gpioset AP_FLASH_SELECT 0 > gpiocfg GPIO0_GPIO1: read 0 drive 0 GPIO0_GPIO2: read 0 drive 0 GPIO1_GPIO0: read 0 INT_RISING GPIO1_GPIO1: read 0 INT_HIGH GPIO1_GPIO4: read 0 INT_FALLING GPIO1_GPIO5: read 0 drive 1 GPIO1_GPIO7: read 0 INT_RISING GPIO1_GPIO8: read 0 INT_FALLING gpio sleepmask: 00000000 > sleepmask sleep mask: 00000000 > Change-Id: I1de35455c5a6702635fb714b14d6791f8e5eb2ed Signed-off-by: Mary Ruthven <mruthven@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3605881 Reviewed-by: Vadim Bendebury <vbendeb@chromium.org>
-rw-r--r--board/cr50/board.c6
-rw-r--r--board/cr50/board.h2
-rw-r--r--board/cr50/gpio.inc3
-rw-r--r--chip/g/gpio.c44
-rw-r--r--include/config.h3
-rw-r--r--include/gpio.h7
-rw-r--r--include/system.h2
7 files changed, 62 insertions, 5 deletions
diff --git a/board/cr50/board.c b/board/cr50/board.c
index c5c88f82f2..bc19800758 100644
--- a/board/cr50/board.c
+++ b/board/cr50/board.c
@@ -593,9 +593,9 @@ DECLARE_IRQ(GC_IRQNUM_PMU_INTR_WAKEUP_INT, pmu_wakeup_interrupt, 1);
void board_configure_deep_sleep_wakepins(void)
{
/*
- * Eventually asserting AP_FLASH_SELECT will disable deep sleep. Until
- * that's enabled make sure cr50 doesn't enter deep sleep with
- * AP_FLASH_SELECT asserted.
+ * The AP_FLASH_SELECT gpio disables sleep when it's asserted, so it
+ * shouldn't be possible to get here with it asserted.
+ * Deassert it just to be safe.
*/
if (board_has_ec_cr50_comm_support())
gpio_set_level(GPIO_AP_FLASH_SELECT, 0);
diff --git a/board/cr50/board.h b/board/cr50/board.h
index a0586256d8..828b2d7d3d 100644
--- a/board/cr50/board.h
+++ b/board/cr50/board.h
@@ -48,6 +48,8 @@
/* Enable getting gpio flags to tell if open drain pins are asserted */
#define CONFIG_GPIO_GET_EXTENDED
+/* Disable sleep when gpios with GPIO_SLEEP_DIS flags are asserted. */
+#define CONFIG_GPIO_DISABLE_SLEEP
/* Flash configuration */
#undef CONFIG_FLASH_PSTATE
diff --git a/board/cr50/gpio.inc b/board/cr50/gpio.inc
index 12ed576291..d224189042 100644
--- a/board/cr50/gpio.inc
+++ b/board/cr50/gpio.inc
@@ -154,8 +154,9 @@ GPIO(EC_FLASH_SELECT, PIN(0, 1), GPIO_OUT_LOW)
/*
* If this gpio is changed, you must update the AP_FLASH_SELECT pinmux
* setup in board.c accordingly.
+ * Disable sleep when the signal is set high.
*/
-GPIO(AP_FLASH_SELECT, PIN(0, 2), GPIO_OUT_LOW)
+GPIO(AP_FLASH_SELECT, PIN(0, 2), GPIO_OUT_LOW | GPIO_SLEEP_DIS_HIGH)
/*
* Pull this low to reset the AP. (We reset the EC with the RBOX.)
diff --git a/chip/g/gpio.c b/chip/g/gpio.c
index 3704d1b1bf..b37588453f 100644
--- a/chip/g/gpio.c
+++ b/chip/g/gpio.c
@@ -8,6 +8,7 @@
#include "gpio.h"
#include "hooks.h"
#include "registers.h"
+#include "system.h"
#include "task.h"
/*
@@ -35,10 +36,51 @@ static void set_one_gpio_bit(uint32_t port, uint16_t mask, int value)
GR_GPIO_MASKHIGHBYTE(port, mask >> 8) = value ? mask : 0;
}
+static uint32_t gpio_sleepmask;
+
+static void gpio_control_sleep(enum gpio_signal signal, int enable)
+{
+#ifdef CONFIG_GPIO_DISABLE_SLEEP
+ uint32_t signal_mask;
+
+ /* There are only 32 gpios, so this shouldn't be possible. */
+ if (signal > 31)
+ return;
+
+ signal_mask = BIT(signal);
+
+ if (enable) {
+ gpio_sleepmask |= signal_mask;
+ disable_sleep(SLEEP_MASK_GPIO);
+ return;
+ }
+ if (!(gpio_sleepmask & signal_mask))
+ return;
+
+ gpio_sleepmask &= ~signal_mask;
+ if (gpio_sleepmask)
+ return;
+
+ /* The last gpio disabling sleep was deasserted. Reenable sleep. */
+ enable_sleep(SLEEP_MASK_GPIO);
+ /*
+ * Give extra time for activity to finish up. These signals are rarely
+ * asserted, so 10 seconds won't affect normal activity.
+ */
+ delay_sleep_by(10 * SECOND);
+#endif /* CONFIG_GPIO_DISABLE_SLEEP */
+}
+
void gpio_set_level(enum gpio_signal signal, int value)
{
const struct gpio_info *g = gpio_list + signal;
+ if (g->flags & GPIO_OUTPUT) {
+ if (g->flags & GPIO_SLEEP_DIS_HIGH)
+ gpio_control_sleep(signal, value);
+ else if (g->flags & GPIO_SLEEP_DIS_LOW)
+ gpio_control_sleep(signal, !value);
+ }
if (g->flags & GPIO_OPEN_DRAIN) {
if (value) {
GR_GPIO_CLRDOUTEN(g->port) = g->mask;
@@ -614,6 +656,8 @@ static int command_gpiocfg(int argc, char **argv)
show_gpiocfg(0);
show_gpiocfg(1);
+ ccprintf("\ngpio sleepmask: %08x\n", gpio_sleepmask);
+
return EC_SUCCESS;
}
DECLARE_SAFE_CONSOLE_COMMAND(gpiocfg, command_gpiocfg,
diff --git a/include/config.h b/include/config.h
index b37144331f..f48a640d68 100644
--- a/include/config.h
+++ b/include/config.h
@@ -1807,6 +1807,9 @@
/* Support getting gpio flags. */
#undef CONFIG_GPIO_GET_EXTENDED
+/* Support disabling sleep with GPIO flags. */
+#undef CONFIG_GPIO_DISABLE_SLEEP
+
/* Do we want to detect the lid angle? */
#undef CONFIG_LID_ANGLE
diff --git a/include/gpio.h b/include/gpio.h
index b0291b40f1..07d46dd055 100644
--- a/include/gpio.h
+++ b/include/gpio.h
@@ -37,6 +37,13 @@
#define GPIO_HIB_WAKE_LOW BIT(20) /* Hibernate wake on low level */
#define GPIO_HIB_WAKE_RISING BIT(21) /* Hibernate wake on rising edge */
#define GPIO_HIB_WAKE_FALLING BIT(22) /* Hibernate wake on falling edge */
+/*
+ * The SLEEP_DIS flags disable sleep when they're asserted. They disable regular
+ * and deep sleep, so they shouldn't be asserted as a part of normal operation.
+ * These flags should ONLY be used on debug signals.
+ */
+#define GPIO_SLEEP_DIS_LOW BIT(23) /* Disable sleep when set to 0. */
+#define GPIO_SLEEP_DIS_HIGH BIT(24) /* Disable sleep when set to 1. */
/* Common flag combinations */
#define GPIO_OUT_LOW (GPIO_OUTPUT | GPIO_LOW)
diff --git a/include/system.h b/include/system.h
index 9826dfa17f..49a85e6eb9 100644
--- a/include/system.h
+++ b/include/system.h
@@ -359,7 +359,7 @@ enum {
SLEEP_MASK_UART = BIT(1), /* UART communication ongoing */
SLEEP_MASK_I2C_CONTROLLER
= BIT(2), /* I2C communication ongoing */
- SLEEP_MASK_CHARGING = BIT(3), /* Charging loop ongoing */
+ SLEEP_MASK_GPIO = BIT(3), /* GPIO activity ongoing */
SLEEP_MASK_USB_PWR = BIT(4), /* USB power loop ongoing */
SLEEP_MASK_USB_PD = BIT(5), /* USB PD device connected */
SLEEP_MASK_SPI = BIT(6), /* SPI communications ongoing */