stm32l5: Optional LSE xtal drive strength ramp-up

Ported from stm32f7/h7: If configured this way, ramp-up the LSE crystal
oscillator driving strength until the LSE starts up.

Signed-off-by: Michael Jung <mijung@gmx.net>
This commit is contained in:
Michael Jung 2021-03-17 20:05:07 +01:00 committed by Xiang Xiao
parent 738034e2eb
commit 2dbfa54150
3 changed files with 92 additions and 28 deletions

View File

@ -248,6 +248,10 @@ config STM32L5_PWR
bool "PWR"
default n
config STM32L5_RTC
bool "RTC"
default n
config STM32L5_LPUART1
bool "LPUART1"
default n
@ -389,10 +393,24 @@ endchoice
if STM32L5_RTC_LSECLOCK
config STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
bool "Automaticaly boost the LSE oscillator drive capability level until it starts-up"
default n
---help---
This will cycle through the values from low to high. To avoid
damaging the the crystal. We want to use the lowest setting that gets
the OSC running. See app note AN2867
0 = Low drive capability (default)
1 = Medium low drive capability
2 = Medium high drive capability
3 = High drive capability
config STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY
int "LSE oscillator drive capability level at LSE start-up"
default 0
range 0 3
depends on !STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
---help---
0 = Low drive capability (default)
1 = Medium low drive capability
@ -403,6 +421,7 @@ config STM32L5_RTC_LSECLOCK_RUN_DRV_CAPABILITY
int "LSE oscillator drive capability level after LSE start-up"
default 0
range 0 3
depends on !STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
---help---
0 = Low drive capability (default)
1 = Medium low drive capability

View File

@ -70,6 +70,20 @@
#endif
#endif
/****************************************************************************
* Private Data
****************************************************************************/
#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
static const uint32_t drives[4] =
{
RCC_BDCR_LSEDRV_LOW,
RCC_BDCR_LSEDRV_MEDLO,
RCC_BDCR_LSEDRV_MEDHI,
RCC_BDCR_LSEDRV_HIGH
};
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
@ -87,6 +101,9 @@ void stm32l5_rcc_enablelse(void)
bool writable;
uint32_t regval;
volatile int32_t timeout;
#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
volatile int32_t drive = 0;
#endif
/* Check if both the External Low-Speed (LSE) oscillator and the LSE system
* clock are already running.
@ -113,46 +130,72 @@ void stm32l5_rcc_enablelse(void)
regval |= RCC_BDCR_LSEON;
#ifdef CONFIG_STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY
/* Set start-up drive capability for LSE oscillator. */
regval &= ~RCC_BDCR_LSEDRV_MASK;
regval |= CONFIG_STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY <<
RCC_BDCR_LSEDRV_SHIFT;
#endif
putreg32(regval, STM32L5_RCC_BDCR);
/* Wait for the LSE clock to be ready (or until a timeout elapsed)
/* Set start-up drive capability for LSE oscillator. LSE must be OFF
* to change drive strength.
*/
for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--)
regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
regval |= CONFIG_STM32L5_RTC_LSECLOCK_START_DRV_CAPABILITY <<
RCC_BDCR_LSEDRV_SHIFT;
putreg32(regval, STM32L5_RCC_BDCR);
regval |= RCC_BDCR_LSEON;
#endif
#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
do
{
/* Check if the LSERDY flag is the set in the BDCR */
regval &= ~(RCC_BDCR_LSEDRV_MASK | RCC_BDCR_LSEON);
regval |= drives[drive++];
putreg32(regval, STM32L5_RCC_BDCR);
regval |= RCC_BDCR_LSEON;
#endif
regval = getreg32(STM32L5_RCC_BDCR);
putreg32(regval, STM32L5_RCC_BDCR);
if (regval & RCC_BDCR_LSERDY)
/* Wait for the LSE clock to be ready (or until a timeout elapsed)
*/
for (timeout = LSERDY_TIMEOUT; timeout > 0; timeout--)
{
/* If so, then break-out with timeout > 0 */
/* Check if the LSERDY flag is the set in the BDCR */
regval = getreg32(STM32L5_RCC_BDCR);
if (regval & RCC_BDCR_LSERDY)
{
/* If so, then break-out with timeout > 0 */
break;
}
}
#ifdef CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY
if (timeout != 0)
{
break;
}
}
while (drive < sizeof(drives) / sizeof(drives[0]));
#endif
/* Enable LSE system clock. The LSE system clock seems to provide a
* means to gate the LSE clock distribution to peripherals. It must be
* enabled for MSI PLL mode (syncing the MSI to the LSE).
*/
regval |= RCC_BDCR_LSESYSEN;
putreg32(regval, STM32L5_RCC_BDCR);
/* Wait for the LSE system clock to be ready */
while (!((regval = getreg32(STM32L5_RCC_BDCR)) & RCC_BDCR_LSESYSRDY))
if (timeout != 0)
{
up_waste();
/* Enable LSE system clock. The LSE system clock seems to provide
* a means to gate the LSE clock distribution to peripherals. It
* must be enabled for MSI PLL mode (syncing the MSI to the LSE).
*/
regval |= RCC_BDCR_LSESYSEN;
putreg32(regval, STM32L5_RCC_BDCR);
/* Wait for the LSE system clock to be ready */
while (!((regval = getreg32(STM32L5_RCC_BDCR)) &
RCC_BDCR_LSESYSRDY))
{
up_waste();
}
}
#if defined(CONFIG_STM32L5_RTC_LSECLOCK_RUN_DRV_CAPABILITY) && \

View File

@ -54,6 +54,8 @@ CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_SDCLONE_DISABLE=y
CONFIG_STACK_COLORATION=y
CONFIG_STM32L5_RTC=y
CONFIG_STM32L5_RTC_AUTO_LSECLOCK_START_DRV_CAPABILITY=y
CONFIG_STM32L5_USART3=y
CONFIG_SYSTEM_NSH=y
CONFIG_SYSTEM_STACKMONITOR=y