diff options
-rw-r--r-- | board/samus_pd/board.c | 9 | ||||
-rw-r--r-- | board/samus_pd/board.h | 18 | ||||
-rw-r--r-- | chip/stm32/i2c-stm32f0.c | 24 | ||||
-rw-r--r-- | chip/stm32/registers.h | 1 | ||||
-rw-r--r-- | common/usb_pd_protocol.c | 46 | ||||
-rw-r--r-- | include/system.h | 1 |
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. */ |