diff options
author | Yen Lin <yelin@nvidia.com> | 2014-12-08 12:22:09 -0800 |
---|---|---|
committer | chrome-internal-fetch <chrome-internal-fetch@google.com> | 2014-12-17 21:08:20 +0000 |
commit | ec12acc81f47e9b88517cd4a955414f7a1ee1cf6 (patch) | |
tree | 89f0ae233acc097c53c92e8fbbb7799f9d33d9c3 | |
parent | a7bae3588cb976405b90677a324de06c71fa3f48 (diff) | |
download | chrome-ec-ec12acc81f47e9b88517cd4a955414f7a1ee1cf6.tar.gz |
clock-stm32l: properly setting HSI/MSI clock based on the RM
According the STM32L RM, when writing to RCC_CFGR to change HSI or MSI
clock source, SWS bits of RCC_CFGR register have to be checked if the
new clock source is taken into account. Also, when writing ACC64 bit and
LATENCY bit to FLASH_ACR register, those bits have to be checked too.
Also changed in this CL is to disable MSI if HSI is enabled, and disable
HSI if MSI is enabled.
BUG=chrome-os-partner:32936
BRANCH=none
TEST=passed suspend_stress_test on big, blaze and nyan
Change-Id: I3ec660d149ecdec3ca3097239612bf2c542d0548
Signed-off-by: Yen Lin <yelin@nvidia.com>
Reviewed-on: https://chromium-review.googlesource.com/234490
Reviewed-by: Kary Jin <karyj@nvidia.com>
Tested-by: Kary Jin <karyj@nvidia.com>
Reviewed-by: Andrew Bresticker <abrestic@chromium.org>
(cherry picked from commit 400d9dca8c41f74cf0c2587e881707b80bb17d3d)
Reviewed-on: https://chromium-review.googlesource.com/236050
-rw-r--r-- | chip/stm32/clock-stm32l.c | 52 | ||||
-rw-r--r-- | chip/stm32/registers.h | 2 |
2 files changed, 47 insertions, 7 deletions
diff --git a/chip/stm32/clock-stm32l.c b/chip/stm32/clock-stm32l.c index 502a8187c3..e0c7ebc747 100644 --- a/chip/stm32/clock-stm32l.c +++ b/chip/stm32/clock-stm32l.c @@ -82,22 +82,38 @@ static void clock_set_osc(enum clock_osc osc) /* * Set the recommended flash settings for 16MHz clock. * - * The 3 bits must be programmed strictly sequentially, but it - * is faster not to read-back the value of the ACR register in - * the middle of the sequence so use a temporary variable. + * The 3 bits must be programmed strictly sequentially. + * Also, follow the RM to check 64-bit access and latency bit + * after writing those bits to the FLASH_ACR register. */ tmp_acr = STM32_FLASH_ACR; /* Enable 64-bit access */ tmp_acr |= STM32_FLASH_ACR_ACC64; STM32_FLASH_ACR = tmp_acr; + /* Check ACC64 bit == 1 */ + while (!(STM32_FLASH_ACR & STM32_FLASH_ACR_ACC64)) + ; + /* Enable Prefetch Buffer */ tmp_acr |= STM32_FLASH_ACR_PRFTEN; STM32_FLASH_ACR = tmp_acr; + /* Flash 1 wait state */ tmp_acr |= STM32_FLASH_ACR_LATENCY; STM32_FLASH_ACR = tmp_acr; + /* Check LATENCY bit == 1 */ + while (!(STM32_FLASH_ACR & STM32_FLASH_ACR_LATENCY)) + ; + /* Switch to HSI */ STM32_RCC_CFGR = STM32_RCC_CFGR_SW_HSI; + /* RM says to check SWS bits to make sure HSI is the sysclock */ + while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != + STM32_RCC_CFGR_SWS_HSI) + ; + + /* Disable MSI */ + STM32_RCC_CR &= ~STM32_RCC_CR_MSION; freq = HSI_CLOCK; break; @@ -107,28 +123,50 @@ static void clock_set_osc(enum clock_osc osc) STM32_RCC_ICSCR = (STM32_RCC_ICSCR & ~STM32_RCC_ICSCR_MSIRANGE_MASK) | STM32_RCC_ICSCR_MSIRANGE_1MHZ; + /* Ensure that MSI is ON */ + if (!(STM32_RCC_CR & STM32_RCC_CR_MSIRDY)) { + /* Enable MSI */ + STM32_RCC_CR |= STM32_RCC_CR_MSION; + /* Wait for MSI to be ready */ + while (!(STM32_RCC_CR & STM32_RCC_CR_MSIRDY)) + ; + } + + /* Switch to MSI */ STM32_RCC_CFGR = STM32_RCC_CFGR_SW_MSI; + /* RM says to check SWS bits to make sure MSI is the sysclock */ + while ((STM32_RCC_CFGR & STM32_RCC_CFGR_SWS_MASK) != + STM32_RCC_CFGR_SWS_MSI) + ; /* * Set the recommended flash settings for <= 2MHz clock. * - * The 3 bits must be programmed strictly sequentially, but it - * is faster not to read-back the value of the ACR register in - * the middle of the sequence so use a temporary variable. + * The 3 bits must be programmed strictly sequentially. + * Also, follow the RM to check 64-bit access and latency bit + * after writing those bits to the FLASH_ACR register. */ tmp_acr = STM32_FLASH_ACR; /* Flash 0 wait state */ tmp_acr &= ~STM32_FLASH_ACR_LATENCY; STM32_FLASH_ACR = tmp_acr; + /* Check LATENCY bit == 0 */ + while (STM32_FLASH_ACR & STM32_FLASH_ACR_LATENCY) + ; + /* Disable prefetch Buffer */ tmp_acr &= ~STM32_FLASH_ACR_PRFTEN; STM32_FLASH_ACR = tmp_acr; + /* Disable 64-bit access */ tmp_acr &= ~STM32_FLASH_ACR_ACC64; STM32_FLASH_ACR = tmp_acr; + /* Check ACC64 bit == 0 */ + while (STM32_FLASH_ACR & STM32_FLASH_ACR_ACC64) + ; /* Disable HSI */ - STM32_RCC_CR &= STM32_RCC_CR_HSION; + STM32_RCC_CR &= ~STM32_RCC_CR_HSION; /* Enable LPSDSR */ STM32_PWR_CR |= STM32_PWR_CR_LPSDSR; diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index fd1fc984f5..cc8f6598e5 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -545,6 +545,8 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_CR REG32(STM32_RCC_BASE + 0x00) #define STM32_RCC_CR_HSION (1 << 0) #define STM32_RCC_CR_HSIRDY (1 << 1) +#define STM32_RCC_CR_MSION (1 << 8) +#define STM32_RCC_CR_MSIRDY (1 << 9) #define STM32_RCC_CR_PLLON (1 << 24) #define STM32_RCC_CR_PLLRDY (1 << 25) #define STM32_RCC_ICSCR REG32(STM32_RCC_BASE + 0x04) |