diff options
author | Brian J. Nemec <bnemec@chromium.org> | 2019-11-11 23:51:35 -0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-01-18 01:16:43 +0000 |
commit | 771dd33b149fb94725edf0e29670207b9a013cb6 (patch) | |
tree | 295d1dbe58d3c280054ee8bf89ae9345f8205c83 /chip/stm32 | |
parent | c520344abe270967b1bd96d43559fb00c0d431d4 (diff) | |
download | chrome-ec-771dd33b149fb94725edf0e29670207b9a013cb6.tar.gz |
ServoMicro: Enable Brownout detection with PVD circuit
Enables the programmable voltage detector (PVD) interrupt in
ServoMicro. This interrupt fires when the supply voltage drops
from the expected 3.3V to under 2.3V after power on. This gives
several hundred microseconds of time for the device to respond
to the power reduction.
In order to ensure that the ServoMicro does not enter a
non-responsive state, it triggers a reboot of the system to
restore it to a good configuration.
BRANCH=servo
BUG=chromium:1023715
TEST=Configured GPIO output to trigger on pvd_interrupt()
and verified the interrupt fires during the following
situations using Saleae analyzer:
* USB Power removed from working device
* Ramping supply voltage from 1.5V to 5V with a DC supply
* Repoducing failure condition from crbug/1016051
1 Connect ServoMicro to Cyan board
2 dut-control power_state:on
3 dut-control fw_wp_vref:pp3300
4 dut-control power_state:off
5 GPIO toggles and system reset occurs
Change-Id: I721f48ab84b01d52a5f98747cc9d879ff2876a07
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/1911759
Reviewed-by: Ruben Rodriguez Buchillon <coconutruben@chromium.org>
Tested-by: Brian Nemec <bnemec@chromium.org>
Commit-Queue: Brian Nemec <bnemec@chromium.org>
Auto-Submit: Brian Nemec <bnemec@chromium.org>
Diffstat (limited to 'chip/stm32')
-rw-r--r-- | chip/stm32/registers-stm32f0.h | 14 | ||||
-rw-r--r-- | chip/stm32/registers.h | 1 | ||||
-rw-r--r-- | chip/stm32/system.c | 36 |
3 files changed, 47 insertions, 4 deletions
diff --git a/chip/stm32/registers-stm32f0.h b/chip/stm32/registers-stm32f0.h index 72d3cdb7a6..442edaed9a 100644 --- a/chip/stm32/registers-stm32f0.h +++ b/chip/stm32/registers-stm32f0.h @@ -277,6 +277,11 @@ /* --- Power / Reset / Clocks --- */ +#define STM32_PWR_CR REG32(STM32_PWR_BASE + 0x00) +#define STM32_PWD_PVD_LS_MASK (0x07 << 5) +#define STM32_PWD_PVD_LS(n) ((n & 0x07) << 5) +#define STM32_PWR_PVDE BIT(4) + #define STM32_PWR_CSR REG32(STM32_PWR_BASE + 0x04) #define STM32_PWR_CSR_EWUP1 BIT(8) @@ -382,8 +387,8 @@ #define RESET_CAUSE_OTHER 0xfe000000 #define RESET_CAUSE_RMVF 0x01000000 /* Power cause in PWR CSR register */ -#define STM32_PWR_RESET_CAUSE STM32_PWR_CSR -#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR +#define STM32_PWR_RESET_CAUSE STM32_PWR_CSR +#define STM32_PWR_RESET_CAUSE_CLR STM32_PWR_CR #define RESET_CAUSE_SBF 0x00000002 #define RESET_CAUSE_SBF_CLR 0x00000004 @@ -528,8 +533,9 @@ typedef volatile struct stm32_spi_regs stm32_spi_regs_t; #define STM32_EXTI_SWIER REG32(STM32_EXTI_BASE + 0x10) #define STM32_EXTI_PR REG32(STM32_EXTI_BASE + 0x14) -#define EXTI_RTC_ALR_EVENT BIT(17) -#define EXTI_COMP2_EVENT BIT(22) +#define EXTI_PVD_EVENT BIT(16) +#define EXTI_RTC_ALR_EVENT BIT(17) +#define EXTI_COMP2_EVENT BIT(22) /* --- ADC --- */ #define STM32_ADC_ISR REG32(STM32_ADC1_BASE + 0x00) diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 08b9d61e20..5926dda278 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -229,6 +229,7 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_PB1_USART3 BIT(18) #define STM32_RCC_PB1_USART4 BIT(19) #define STM32_RCC_PB1_USART5 BIT(20) +#define STM32_RCC_PB1_PWREN BIT(28) #define STM32_RCC_PB2_SPI1 BIT(12) /* Reset causes definitions */ diff --git a/chip/stm32/system.c b/chip/stm32/system.c index 0864b8bc9d..37e5d66b78 100644 --- a/chip/stm32/system.c +++ b/chip/stm32/system.c @@ -178,6 +178,38 @@ void chip_pre_init(void) STM32_DBGMCU_APB2FZ |= apb2fz_reg; } +#ifdef CONFIG_PVD +/* Configures the programmable voltage detector to monitor for brown out conditions. */ +static void configure_pvd(void) +{ + /* Clear Interrupt Enable Mask Register. */ + STM32_EXTI_IMR &= ~EXTI_PVD_EVENT; + + /* Clear Rising and Falling Trigger Selection Registers. */ + STM32_EXTI_RTSR &= ~EXTI_PVD_EVENT; + STM32_EXTI_FTSR &= ~EXTI_PVD_EVENT; + + /* Clear the value of the PVD Level Selection. */ + STM32_PWR_CR &= ~STM32_PWD_PVD_LS_MASK; + + /* Set the new value of the PVD Level Selection. */ + STM32_PWR_CR |= STM32_PWD_PVD_LS(PVD_THRESHOLD); + + /* Enable Power Clock. */ + STM32_RCC_APB1ENR |= STM32_RCC_PB1_PWREN; + + /* Configure the NVIC for PVD. */ + task_enable_irq(STM32_IRQ_PVD); + + /* Configure interrupt mode. */ + STM32_EXTI_IMR |= EXTI_PVD_EVENT; + STM32_EXTI_RTSR |= EXTI_PVD_EVENT; + + /* Enable the PVD Output. */ + STM32_PWR_CR |= STM32_PWR_PVDE; +} +#endif + void system_pre_init(void) { #ifdef CONFIG_SOFTWARE_PANIC @@ -256,6 +288,10 @@ void system_pre_init(void) bkpdata_write(BKPDATA_INDEX_SAVED_PANIC_EXCEPTION, 0); } #endif + +#ifdef CONFIG_PVD + configure_pvd(); +#endif } void system_reset(int flags) |