From ba624e7241a2caed6a78b4f5e34b37a6c90c60bb Mon Sep 17 00:00:00 2001 From: Alec Berg Date: Sat, 27 Sep 2014 11:56:04 -0700 Subject: [PATCH] zinger: add hibernate if disconnected for 60s Automatically go into hibernate (standby mode) if not powering anything for 60 seconds. Will wake up when it is plugged into something (senses pull-down on CC line). BUG=chrome-os-partner:28335 BRANCH=samus TEST=load onto zinger. if disconnected for 60s, see hibernate print on zinger console. when connected to a device, verified it boots again. Change-Id: I2564c6192395bb5e4f6d7586c2725f13a4581049 Signed-off-by: Alec Berg Reviewed-on: https://chromium-review.googlesource.com/220837 Reviewed-by: Vincent Palatin --- board/zinger/board.h | 2 ++ board/zinger/hardware.c | 27 +++++++++++++++++++++++++++ board/zinger/usb_pd_policy.c | 13 +++++++++++++ common/usb_pd_protocol.c | 2 +- include/usb_pd.h | 15 ++++++++++++--- 5 files changed, 55 insertions(+), 4 deletions(-) diff --git a/board/zinger/board.h b/board/zinger/board.h index 2b420e496a..91a96f50e0 100644 --- a/board/zinger/board.h +++ b/board/zinger/board.h @@ -41,6 +41,7 @@ #undef CONFIG_DEBUG_STACK_OVERFLOW #undef CONFIG_FLASH #undef CONFIG_FMAP +#define CONFIG_HIBERNATE_WAKEUP_PINS STM32_PWR_CSR_EWUP1 /* debug printf flash footprinf is about 1400 bytes */ #define CONFIG_DEBUG_PRINTF @@ -92,6 +93,7 @@ void set_rtc_alarm(uint32_t delay_s, uint32_t delay_us, void reset_rtc_alarm(uint32_t *rtc, uint32_t *rtcss); int32_t get_rtc_diff(uint32_t rtc0, uint32_t rtc0ss, uint32_t rtc1, uint32_t rtc1ss); +void __enter_hibernate(uint32_t seconds, uint32_t microseconds); /* Reboot the CPU */ void cpu_reset(void); diff --git a/board/zinger/hardware.c b/board/zinger/hardware.c index 061f3bdf89..b2d6604766 100644 --- a/board/zinger/hardware.c +++ b/board/zinger/hardware.c @@ -73,6 +73,14 @@ static void pins_init(void) * PF0 (OUT - GPIO) : LM5050 FET driver off * PF1 (OUT - GPIO) : discharge FET */ + + /* + * Clear power control/status register to disable wakeup + * pin A0, so that we can change it to an output. + */ + STM32_PWR_CSR = 0; + STM32_PWR_CR |= 0xc; + STM32_GPIO_ODR(GPIO_A) = HIGH(0) | HIGH(4); STM32_GPIO_AFRL(GPIO_A) = AFx(7, 1); STM32_GPIO_AFRH(GPIO_A) = AFx(9, 1) | AFx(10, 1); @@ -157,7 +165,26 @@ static void irq_init(void) extern void runtime_init(void); void hardware_init(void) { + uint32_t raw_cause = STM32_RCC_CSR; + uint32_t pwr_status = STM32_PWR_CSR; + power_init(); + + /* Clear the hardware reset cause by setting the RMVF bit */ + STM32_RCC_CSR |= 1 << 24; + /* Clear SBF in PWR_CSR */ + STM32_PWR_CR |= 1 << 3; + + /* + * WORKAROUND: as we cannot de-activate the watchdog during + * long hibernation, we are woken-up once by the watchdog and + * go back to hibernate if we detect that condition, without + * watchdog initialized this time. + * The RTC deadline (if any) is already set. + */ + if ((pwr_status & 0x2) && (raw_cause & 0x60000000)) + __enter_hibernate(0, 0); + system_init(); runtime_init(); /* sets clock */ pins_init(); diff --git a/board/zinger/usb_pd_policy.c b/board/zinger/usb_pd_policy.c index f54841bb72..543db00541 100644 --- a/board/zinger/usb_pd_policy.c +++ b/board/zinger/usb_pd_policy.c @@ -256,12 +256,25 @@ void pd_power_supply_reset(int port) int pd_board_checks(void) { + static timestamp_t hib_to; + static int hib_to_ready; int vbus_volt; int ovp_idx; /* Reload the watchdog */ STM32_IWDG_KR = STM32_IWDG_KR_RELOAD; + /* If output is disabled for long enough, then hibernate */ + if (!pd_is_connected(0) && hib_to_ready) { + if (get_time().val >= hib_to.val) { + debug_printf("hibernate\n"); + __enter_hibernate(0, 0); + } + } else { + hib_to.val = get_time().val + 60*SECOND; + hib_to_ready = 1; + } + vbus_volt = adc_read_channel(ADC_CH_V_SENSE); vbus_amp = adc_read_channel(ADC_CH_A_SENSE); diff --git a/common/usb_pd_protocol.c b/common/usb_pd_protocol.c index 8547eae1bf..7989e506ad 100644 --- a/common/usb_pd_protocol.c +++ b/common/usb_pd_protocol.c @@ -285,7 +285,7 @@ static inline void set_state_timeout(int port, } /* Return flag for pd state is connected */ -static int pd_is_connected(int port) +int pd_is_connected(int port) { if (pd[port].task_state == PD_STATE_DISABLED) return 0; diff --git a/include/usb_pd.h b/include/usb_pd.h index 08c8038b3a..fbbd92902a 100644 --- a/include/usb_pd.h +++ b/include/usb_pd.h @@ -228,9 +228,6 @@ enum pd_data_msg_type { #define PD_RST2 0x19 #define PD_EOP 0x0D -/* Issue PD soft reset */ -void pd_soft_reset(void); - /* --- Policy layer functions --- */ /** @@ -513,6 +510,15 @@ void pd_hw_release(int port); */ void pd_hw_init(int port); +/* --- Protocol layer functions --- */ +/** + * Get connected state + * + * @param port USB-C port number + * @return True if port is in connected state + */ +int pd_is_connected(int port); + /** * Get port polarity. * @@ -539,4 +545,7 @@ void pd_comm_enable(int enable); */ void pd_ping_enable(int port, int enable); +/* Issue PD soft reset */ +void pd_soft_reset(void); + #endif /* __USB_PD_H */