summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlec Berg <alecaberg@chromium.org>2014-09-18 17:00:10 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-09-23 00:04:59 +0000
commit23ad46d3b8b9bce7f122abb4356e2c09b5dfc0c6 (patch)
treed351d99d33f0c0c968392fadeac6e479ae6d0438
parent0a147973bb6a16714925cc7d701b9b6cffc73cb2 (diff)
downloadchrome-ec-23ad46d3b8b9bce7f122abb4356e2c09b5dfc0c6.tar.gz
samus_pd: enable low power idle
Enable low power idle for samus_pd. Low power idle is only entered when no USB PD device is connected. BUG=chrome-os-partner:31226 BRANCH=none TEST=load onto samus_pd, use idlestats command to verify that we are going into deep sleep (STOP mode). Run 30 min. and verify no watchdog reboots or anything out of ordinary. Also, verify that host commands from EC work when going into deep sleep by sending host commands on the EC console with pdcmd 0 0. Change-Id: I3e2e04e6c4c0a84e291286dbed90945847e0dfdd Signed-off-by: Alec Berg <alecaberg@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/218957 Reviewed-by: Todd Broch <tbroch@chromium.org> Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--board/samus_pd/board.c9
-rw-r--r--board/samus_pd/board.h18
-rw-r--r--chip/stm32/i2c-stm32f0.c24
-rw-r--r--chip/stm32/registers.h1
-rw-r--r--common/usb_pd_protocol.c46
-rw-r--r--include/system.h1
6 files changed, 74 insertions, 25 deletions
diff --git a/board/samus_pd/board.c b/board/samus_pd/board.c
index a62299d71c..f250dd34a6 100644
--- a/board/samus_pd/board.c
+++ b/board/samus_pd/board.c
@@ -50,21 +50,27 @@ void pch_evt(enum gpio_signal signal)
switch (ps) {
case POWER_S5:
if (gpio_get_level(GPIO_PCH_SLP_S5_L)) {
+ /* S5 -> S3 */
hook_notify(HOOK_CHIPSET_STARTUP);
ps = POWER_S3;
}
break;
case POWER_S3:
if (gpio_get_level(GPIO_PCH_SLP_S3_L)) {
+ /* S3 -> S0: disable deep sleep */
+ disable_sleep(SLEEP_MASK_AP_RUN);
hook_notify(HOOK_CHIPSET_RESUME);
ps = POWER_S0;
} else if (!gpio_get_level(GPIO_PCH_SLP_S5_L)) {
+ /* S3 -> S5 */
hook_notify(HOOK_CHIPSET_SHUTDOWN);
ps = POWER_S5;
}
break;
case POWER_S0:
if (!gpio_get_level(GPIO_PCH_SLP_S3_L)) {
+ /* S0 -> S3: enable deep sleep */
+ enable_sleep(SLEEP_MASK_AP_RUN);
hook_notify(HOOK_CHIPSET_SUSPEND);
ps = POWER_S3;
}
@@ -117,12 +123,15 @@ static void board_init(void)
/* Determine initial chipset state */
if (slp_s5 && slp_s3) {
+ disable_sleep(SLEEP_MASK_AP_RUN);
hook_notify(HOOK_CHIPSET_RESUME);
ps = POWER_S0;
} else if (slp_s5 && !slp_s3) {
+ enable_sleep(SLEEP_MASK_AP_RUN);
hook_notify(HOOK_CHIPSET_STARTUP);
ps = POWER_S3;
} else {
+ enable_sleep(SLEEP_MASK_AP_RUN);
hook_notify(HOOK_CHIPSET_SHUTDOWN);
ps = POWER_S5;
}
diff --git a/board/samus_pd/board.h b/board/samus_pd/board.h
index 4cc58a56e4..a3364071b7 100644
--- a/board/samus_pd/board.h
+++ b/board/samus_pd/board.h
@@ -12,14 +12,21 @@
#define CPU_CLOCK 48000000
/* the UART console is on USART1 (PA9/PA10) */
-#undef CONFIG_UART_CONSOLE
+#undef CONFIG_UART_CONSOLE
#define CONFIG_UART_CONSOLE 1
/* Optional features */
+#define CONFIG_ADC
#define CONFIG_BOARD_PRE_INIT
+#define CONFIG_FORCE_CONSOLE_RESUME
+#define CONFIG_HW_CRC
+#define CONFIG_I2C
+#undef CONFIG_LID_SWITCH
+#define CONFIG_LOW_POWER_IDLE
#define CONFIG_STM_HWTIMER32
+#undef CONFIG_TASK_PROFILING
#define CONFIG_USB_POWER_DELIVERY
-#undef CONFIG_USB_PD_COMM_ENABLED
+#undef CONFIG_USB_PD_COMM_ENABLED
#define CONFIG_USB_PD_COMM_ENABLED 0
#define CONFIG_USB_PD_CUSTOM_VDM
#define CONFIG_USB_PD_DUAL_ROLE
@@ -27,14 +34,9 @@
#define CONFIG_USB_PD_INTERNAL_COMP
#define CONFIG_USB_PD_READ_INFO_ON_CONNECT
#define CONFIG_USBC_SS_MUX
-#define CONFIG_ADC
-#define CONFIG_HW_CRC
-#define CONFIG_I2C
#define CONFIG_USB_SWITCH_TSU6721
#define CONFIG_VBOOT_HASH
-#undef CONFIG_WATCHDOG_HELP
-#undef CONFIG_LID_SWITCH
-#undef CONFIG_TASK_PROFILING
+#undef CONFIG_WATCHDOG_HELP
/* I2C ports configuration */
#define I2C_PORT_MASTER 1
diff --git a/chip/stm32/i2c-stm32f0.c b/chip/stm32/i2c-stm32f0.c
index 5dc40fcebc..47393fc209 100644
--- a/chip/stm32/i2c-stm32f0.c
+++ b/chip/stm32/i2c-stm32f0.c
@@ -104,9 +104,21 @@ static void i2c_init_port(const struct i2c_port_t *p)
if (!(STM32_RCC_APB1ENR & (1 << (21 + port))))
STM32_RCC_APB1ENR |= 1 << (21 + port);
- /* Default clock to i2c port 0 is HSI (8MHz). Change to SYSCLK. */
- if (port == 0)
+ if (port == 0) {
+#if defined(CONFIG_HOSTCMD_I2C_SLAVE_ADDR) && \
+defined(CONFIG_LOW_POWER_IDLE) && \
+(I2C_PORT_EC == STM32_I2C1_PORT)
+ /*
+ * Use HSI (8MHz) for i2c clock. This allows smooth wakeup
+ * from STOP mode since HSI is only clock running immediately
+ * upon exit from STOP mode.
+ */
+ STM32_RCC_CFGR3 &= ~0x10;
+#else
+ /* Use SYSCLK for i2c clock. */
STM32_RCC_CFGR3 |= 0x10;
+#endif
+ }
/* Configure GPIOs */
gpio_config_module(MODULE_I2C, 1);
@@ -418,6 +430,14 @@ static void i2c_init(void)
#ifdef CONFIG_HOSTCMD_I2C_SLAVE_ADDR
STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_RXIE | STM32_I2C_CR1_ERRIE
| STM32_I2C_CR1_ADDRIE | STM32_I2C_CR1_STOPIE;
+#if defined(CONFIG_LOW_POWER_IDLE) && (I2C_PORT_EC == STM32_I2C1_PORT)
+ /*
+ * If using low power idle and EC port is I2C1, then set I2C1 to wake
+ * from STOP mode on address match. Note, this only works on I2C1 and
+ * only if the clock to I2C1 is HSI 8MHz.
+ */
+ STM32_I2C_CR1(I2C_PORT_EC) |= STM32_I2C_CR1_WUPEN;
+#endif
STM32_I2C_OAR1(I2C_PORT_EC) = 0x8000 | CONFIG_HOSTCMD_I2C_SLAVE_ADDR;
task_enable_irq(IRQ_SLAVE);
#endif
diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h
index 4b557cb8e9..a806c74afa 100644
--- a/chip/stm32/registers.h
+++ b/chip/stm32/registers.h
@@ -415,6 +415,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t;
#define STM32_I2C_CR1_NACKIE (1 << 4)
#define STM32_I2C_CR1_STOPIE (1 << 5)
#define STM32_I2C_CR1_ERRIE (1 << 7)
+#define STM32_I2C_CR1_WUPEN (1 << 18)
#define STM32_I2C_CR2(n) REG32(stm32_i2c_reg(n, 0x04))
#define STM32_I2C_CR2_RD_WRN (1 << 10)
#define STM32_I2C_CR2_START (1 << 13)
diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c
index 161a851519..b49d66ac88 100644
--- a/common/usb_pd_protocol.c
+++ b/common/usb_pd_protocol.c
@@ -15,6 +15,7 @@
#include "host_command.h"
#include "registers.h"
#include "sha1.h"
+#include "system.h"
#include "task.h"
#include "timer.h"
#include "util.h"
@@ -283,9 +284,27 @@ static inline void set_state_timeout(int port,
pd[port].timeout_state = timeout_state;
}
+/* Return flag for pd state is connected */
+static int pd_is_connected(int port)
+{
+ if (pd[port].task_state == PD_STATE_DISABLED)
+ return 0;
+
+#ifdef CONFIG_USB_PD_DUAL_ROLE
+ /* Check if sink is connected */
+ if (pd[port].role == PD_ROLE_SINK)
+ return pd[port].task_state != PD_STATE_SNK_DISCONNECTED;
+#endif
+ /* Must be a source */
+ return pd[port].task_state != PD_STATE_SRC_DISCONNECTED;
+}
+
static inline void set_state(int port, enum pd_states next_state)
{
enum pd_states last_state = pd[port].task_state;
+#ifdef CONFIG_LOW_POWER_IDLE
+ int i;
+#endif
set_state_timeout(port, 0, 0);
pd[port].task_state = next_state;
@@ -298,6 +317,18 @@ static inline void set_state(int port, enum pd_states next_state)
}
#endif
+#ifdef CONFIG_LOW_POWER_IDLE
+ /* If any PD port is connected, then disable deep sleep */
+ for (i = 0; i < PD_PORT_COUNT; i++) {
+ if (pd_is_connected(i))
+ break;
+ }
+ if (i == PD_PORT_COUNT)
+ enable_sleep(SLEEP_MASK_USB_PD);
+ else
+ disable_sleep(SLEEP_MASK_USB_PD);
+#endif
+
/* Log state transition, except for toggling between sink and source */
if (last_state == next_state)
return;
@@ -640,21 +671,6 @@ static void handle_vdm_request(int port, int cnt, uint32_t *payload)
vid, payload[0] & 0xFFFF);
}
-/* Return flag for pd state is connected */
-static int pd_is_connected(int port)
-{
- if (pd[port].task_state == PD_STATE_DISABLED)
- return 0;
-
-#ifdef CONFIG_USB_PD_DUAL_ROLE
- /* Check if sink is connected */
- if (pd[port].role == PD_ROLE_SINK)
- return pd[port].task_state != PD_STATE_SNK_DISCONNECTED;
-#endif
- /* Must be a source */
- return pd[port].task_state != PD_STATE_SRC_DISCONNECTED;
-}
-
static void execute_hard_reset(int port)
{
pd[port].msg_id = 0;
diff --git a/include/system.h b/include/system.h
index b4c68bd3ce..6d38cae769 100644
--- a/include/system.h
+++ b/include/system.h
@@ -291,6 +291,7 @@ enum {
SLEEP_MASK_I2C = (1 << 2), /* I2C master communication on-going */
SLEEP_MASK_CHARGING = (1 << 3), /* Charging loop on-going */
SLEEP_MASK_USB_PWR = (1 << 4), /* USB power loop on-going */
+ SLEEP_MASK_USB_PD = (1 << 5), /* USB PD device connected */
SLEEP_MASK_FORCE_NO_DSLEEP = (1 << 15), /* Force disable. */