From 434cad4d17e0583c0e43f93cf6712472a85cc3d6 Mon Sep 17 00:00:00 2001 From: Jussi Kivilinna Date: Tue, 22 Jan 2019 06:37:02 -0600 Subject: [PATCH] arch/arm/src/stm32f7/stm32_lse.c: Add configuration of LSE oscillator drive capability --- arch/arm/src/stm32f7/Kconfig | 25 +++++++ .../arm/src/stm32f7/chip/stm32f74xx75xx_rcc.h | 6 ++ .../arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h | 6 ++ arch/arm/src/stm32f7/stm32_lse.c | 75 +++++++++++++++---- 4 files changed, 97 insertions(+), 15 deletions(-) diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index 4b72417698..2031bf5fb4 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -2210,6 +2210,31 @@ config STM32F7_RTC_LSICLOCK Drive the RTC with the LSI clock endchoice #"RTC clock source" + +if STM32F7_RTC_LSECLOCK + +config STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY + int "LSE oscillator drive capability level at LSE start-up" + default 0 + range 0 3 + ---help--- + 0 = Low drive capability (default) + 1 = Medium high drive capability + 2 = Medium low drive capability + 3 = High drive capability + +config STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY + int "LSE oscillator drive capability level after LSE start-up" + default 0 + range 0 3 + ---help--- + 0 = Low drive capability (default) + 1 = Medium high drive capability + 2 = Medium low drive capability + 3 = High drive capability + +endif # STM32F7_RTC_LSECLOCK + endmenu # RTC Configuration config STM32F7_CUSTOM_CLOCKCONFIG diff --git a/arch/arm/src/stm32f7/chip/stm32f74xx75xx_rcc.h b/arch/arm/src/stm32f7/chip/stm32f74xx75xx_rcc.h index 4d90f7c96d..fa879fb667 100644 --- a/arch/arm/src/stm32f7/chip/stm32f74xx75xx_rcc.h +++ b/arch/arm/src/stm32f7/chip/stm32f74xx75xx_rcc.h @@ -534,6 +534,12 @@ #define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ #define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ #define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ +#define RCC_BDCR_LSEDRV_SHIFT (3) /* Bits 4:3: LSE oscillator Drive selection */ +#define RCC_BDCR_LSEDRV_MASK (3 << RCC_BDCR_LSEDRV_SHIFT) +# define RCC_BDCR_LSEDRV_LOW (0 << RCC_BDCR_LSEDRV_SHIFT) /* Low driving capability */ +# define RCC_BDCR_LSEDRV_MEDHI (1 << RCC_BDCR_LSEDRV_SHIFT) /* Medium high driving capability */ +# define RCC_BDCR_LSEDRV_MEDLO (2 << RCC_BDCR_LSEDRV_SHIFT) /* Medium low driving capability */ +# define RCC_BDCR_LSEDRV_HIGH (3 << RCC_BDCR_LSEDRV_SHIFT) /* High driving capability */ #define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ #define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) # define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ diff --git a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h index f94a4f1e73..f44969ce75 100644 --- a/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h +++ b/arch/arm/src/stm32f7/chip/stm32f76xx77xx_rcc.h @@ -555,6 +555,12 @@ #define RCC_BDCR_LSEON (1 << 0) /* Bit 0: External Low Speed oscillator enable */ #define RCC_BDCR_LSERDY (1 << 1) /* Bit 1: External Low Speed oscillator Ready */ #define RCC_BDCR_LSEBYP (1 << 2) /* Bit 2: External Low Speed oscillator Bypass */ +#define RCC_BDCR_LSEDRV_SHIFT (3) /* Bits 4:3: LSE oscillator Drive selection */ +#define RCC_BDCR_LSEDRV_MASK (3 << RCC_BDCR_LSEDRV_SHIFT) +# define RCC_BDCR_LSEDRV_LOW (0 << RCC_BDCR_LSEDRV_SHIFT) /* Low driving capability */ +# define RCC_BDCR_LSEDRV_MEDHI (1 << RCC_BDCR_LSEDRV_SHIFT) /* Medium high driving capability */ +# define RCC_BDCR_LSEDRV_MEDLO (2 << RCC_BDCR_LSEDRV_SHIFT) /* Medium low driving capability */ +# define RCC_BDCR_LSEDRV_HIGH (3 << RCC_BDCR_LSEDRV_SHIFT) /* High driving capability */ #define RCC_BDCR_RTCSEL_SHIFT (8) /* Bits 9:8: RTC clock source selection */ #define RCC_BDCR_RTCSEL_MASK (3 << RCC_BDCR_RTCSEL_SHIFT) # define RCC_BDCR_RTCSEL_NOCLK (0 << RCC_BDCR_RTCSEL_SHIFT) /* 00: No clock */ diff --git a/arch/arm/src/stm32f7/stm32_lse.c b/arch/arm/src/stm32f7/stm32_lse.c index 162630060b..8496b46751 100644 --- a/arch/arm/src/stm32f7/stm32_lse.c +++ b/arch/arm/src/stm32f7/stm32_lse.c @@ -45,6 +45,24 @@ #include "stm32_rcc.h" #include "stm32_pwr.h" +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#ifdef CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY +# if CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY < 0 || \ + CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY > 3 +# error "Invalid LSE drive capability setting" +#endif +#endif + +#ifdef CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY +# if CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY < 0 || \ + CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY > 3 +# error "Invalid LSE drive capability setting" +#endif +#endif + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -61,26 +79,53 @@ void stm32_rcc_enablelse(void) { uint32_t regval; - /* The LSE is in the RTC domain and write access is denied to this domain - * after reset, you have to enable write access using DBP bit in the PWR CR - * register before to configuring the LSE. - */ + /* Check if the External Low-Speed (LSE) oscillator is already running. */ - stm32_pwr_enablebkp(true); + regval = getreg32(STM32_RCC_BDCR); - /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit - * the RCC BDCR register. - */ + if ((regval & (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) != + (RCC_BDCR_LSEON | RCC_BDCR_LSERDY)) + { + /* The LSE is in the RTC domain and write access is denied to this + * domain after reset, you have to enable write access using DBP bit + * in the PWR CR register before to configuring the LSE. + */ - regval = getreg32(STM32_RCC_BDCR); - regval |= RCC_BDCR_LSEON; - putreg32(regval,STM32_RCC_BDCR); + stm32_pwr_enablebkp(true); - /* Wait for the LSE clock to be ready */ + /* Enable the External Low-Speed (LSE) oscillator by setting the + * LSEON bit the RCC BDCR register. + */ - while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0); + regval |= RCC_BDCR_LSEON; - /* Disable backup domain access if it was disabled on entry */ +#ifdef CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY + /* Set start-up drive capability for LSE oscillator. */ - stm32_pwr_enablebkp(false); + regval &= ~RCC_BDCR_LSEDRV_MASK; + regval |= CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY << + RCC_BDCR_LSEDRV_SHIFT; +#endif + + putreg32(regval, STM32_RCC_BDCR); + + /* Wait for the LSE clock to be ready */ + + while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0); + +#if defined(CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY) && \ + CONFIG_STM32F7_RTC_LSECLOCK_START_DRV_CAPABILITY != \ + CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY + /* Set running drive capability for LSE oscillator. */ + + regval &= ~RCC_BDCR_LSEDRV_MASK; + regval |= CONFIG_STM32F7_RTC_LSECLOCK_RUN_DRV_CAPABILITY << + RCC_BDCR_LSEDRV_SHIFT; + putreg32(regval, STM32_RCC_BDCR); +#endif + + /* Disable backup domain access if it was disabled on entry */ + + stm32_pwr_enablebkp(false); + } }