diff options
-rw-r--r-- | chip/stm32/clock-stm32h7.c | 84 | ||||
-rw-r--r-- | chip/stm32/hwtimer32.c | 5 | ||||
-rw-r--r-- | chip/stm32/registers.h | 28 |
3 files changed, 86 insertions, 31 deletions
diff --git a/chip/stm32/clock-stm32h7.c b/chip/stm32/clock-stm32h7.c index f454571e8e..edbbb6ea32 100644 --- a/chip/stm32/clock-stm32h7.c +++ b/chip/stm32/clock-stm32h7.c @@ -18,27 +18,35 @@ #define STM32_HSI_CLOCK 64000000 /* * PLL1 configuration: - * CPU freq = VCO / (DIVP + 1) = HSI / DIVM * DIVN / (DIVP + 1) - * = 64 * 4 * 50 / (4 + 1) - * = 160 Mhz + * CPU freq = VCO / DIVP = HSI / DIVM * DIVN / DIVP + * = 64 / 4 * 50 / 2 + * = 400 Mhz + * System clock = 400 Mhz + * HPRE = /2 => AHB/Timer clock = 200 Mhz */ #if !defined(PLL1_DIVM) && !defined(PLL1_DIVN) && !defined(PLL1_DIVP) #define PLL1_DIVM 4 #define PLL1_DIVN 50 -#define PLL1_DIVP 4 +#define PLL1_DIVP 2 #endif -#define PLL1_FREQ (STM32_HSI_CLOCK / PLL1_DIVM * PLL1_DIVN / (PLL1_DIVP+1)) +#define PLL1_FREQ (STM32_HSI_CLOCK / PLL1_DIVM * PLL1_DIVN / PLL1_DIVP) + +/* Flash latency settings for AHB/ACLK at 64 Mhz and Vcore in VOS1 range */ +#define FLASH_ACLK_64MHZ (STM32_FLASH_ACR_WRHIGHFREQ_85MHZ | \ + (0 << STM32_FLASH_ACR_LATENCY_SHIFT)) +/* Flash latency settings for AHB/ACLK at 200 Mhz and Vcore in VOS1 range */ +#define FLASH_ACLK_200MHZ (STM32_FLASH_ACR_WRHIGHFREQ_285MHZ | \ + (2 << STM32_FLASH_ACR_LATENCY_SHIFT)) enum clock_osc { - OSC_INIT = 0, /* Uninitialized */ - OSC_HSI, /* High-speed internal oscillator */ + OSC_HSI = 0, /* High-speed internal oscillator */ OSC_CSI, /* Multi-speed internal oscillator: NOT IMPLEMENTED */ OSC_HSE, /* High-speed external oscillator: NOT IMPLEMENTED */ OSC_PLL, /* PLL */ }; static int freq = STM32_HSI_CLOCK; -static int current_osc; +static int current_osc = OSC_HSI; int clock_get_freq(void) { @@ -63,6 +71,13 @@ void clock_wait_bus_cycles(enum bus_type bus, uint32_t cycles) } } +static void clock_flash_latency(uint32_t target_acr) +{ + STM32_FLASH_ACR(0) = target_acr; + while (STM32_FLASH_ACR(0) != target_acr) + ; +} + static void clock_enable_osc(enum clock_osc osc) { uint32_t ready; @@ -113,20 +128,24 @@ static void clock_switch_osc(enum clock_osc osc) static void clock_set_osc(enum clock_osc osc) { - uint32_t val; - if (osc == current_osc) return; - if (current_osc != OSC_INIT) - hook_notify(HOOK_PRE_FREQ_CHANGE); + hook_notify(HOOK_PRE_FREQ_CHANGE); switch (osc) { case OSC_HSI: /* Switch to HSI */ clock_switch_osc(osc); - freq = STM32_HSI_CLOCK; + /* Restore /1 HPRE (AHB prescaler) */ + STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV1 + | STM32_RCC_D1CFGR_D1PPRE_DIV1 + | STM32_RCC_D1CFGR_D1CPRE_DIV1; + /* Use more optimized flash latency settings for 64-MHz ACLK */ + clock_flash_latency(FLASH_ACLK_64MHZ); + /* Turn off the PLL1 to save power */ + STM32_RCC_CR &= ~STM32_RCC_CR_PLL1ON; break; case OSC_PLL: @@ -141,15 +160,13 @@ static void clock_set_osc(enum clock_osc osc) | STM32_RCC_PLLDIV_DIVN(PLL1_DIVN); /* turn on PLL1 and wait that it's ready */ clock_enable_osc(OSC_PLL); - freq = PLL1_FREQ; - - /* Adjust flash latency */ - val = STM32_FLASH_ACR_WRHIGHFREQ_185MHZ | - (2 << STM32_FLASH_ACR_LATENCY_SHIFT); - STM32_FLASH_ACR(0) = val; - while (val != STM32_FLASH_ACR(0)) - ; - + /* Put /2 on HPRE (AHB prescaler) to keep at the 200Mhz max */ + STM32_RCC_D1CFGR = STM32_RCC_D1CFGR_HPRE_DIV2 + | STM32_RCC_D1CFGR_D1PPRE_DIV1 + | STM32_RCC_D1CFGR_D1CPRE_DIV1; + freq = PLL1_FREQ / 2; + /* Increase flash latency before transition the clock */ + clock_flash_latency(FLASH_ACLK_200MHZ); /* Switch to PLL */ clock_switch_osc(OSC_PLL); break; @@ -157,13 +174,8 @@ static void clock_set_osc(enum clock_osc osc) break; } - /* Notify modules of frequency change unless we're initializing */ - if (current_osc != OSC_INIT) { - current_osc = osc; - hook_notify(HOOK_FREQ_CHANGE); - } else { - current_osc = osc; - } + current_osc = osc; + hook_notify(HOOK_FREQ_CHANGE); } void clock_enable_module(enum module_id module, int enable) @@ -199,6 +211,20 @@ void clock_init(void) */ STM32_AXI_TARG_FN_MOD(7) |= READ_ISS_OVERRIDE; + /* + * Ensure the SPI is always clocked at the same frequency + * by putting it on the fixed 64-Mhz HSI clock. + * per_ck is clocked directly by the HSI (as per the default settings). + */ + STM32_RCC_D2CCIP1R = (STM32_RCC_D2CCIP1R & + ~(STM32_RCC_D2CCIP1R_SPI123SEL_MASK | + STM32_RCC_D2CCIP1R_SPI45SEL_MASK)) + | STM32_RCC_D2CCIP1R_SPI123SEL_PERCK + | STM32_RCC_D2CCIP1R_SPI45SEL_HSI; + + /* Use more optimized flash latency settings for ACLK = HSI = 64 Mhz */ + clock_flash_latency(FLASH_ACLK_64MHZ); + #if 0 /* Keep default for now: HSI at 64 Mhz */ clock_set_osc(OSC_PLL); #endif diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c index c04f326770..683d5ff669 100644 --- a/chip/stm32/hwtimer32.c +++ b/chip/stm32/hwtimer32.c @@ -130,7 +130,8 @@ defined(CHIP_FAMILY_STM32H7) *reg &= ~mask; } -#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) +#if defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) || \ + defined(CHIP_FAMILY_STM32H7) /* for families using a variable clock feeding the timer */ static void update_prescaler(void) { @@ -171,7 +172,7 @@ static void update_prescaler(void) #endif /* CONFIG_WATCHDOG_HELP */ } DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT); -#endif /* defined(CHIP_FAMILY_STM32L) || defined(CHIP_FAMILY_STM32L4) */ +#endif /* CHIP_FAMILY_STM32L || CHIP_FAMILY_STM32L4 || CHIP_FAMILY_STM32H7 */ int __hw_clock_source_init(uint32_t start_t) { diff --git a/chip/stm32/registers.h b/chip/stm32/registers.h index 432fc9a221..3a549beb5f 100644 --- a/chip/stm32/registers.h +++ b/chip/stm32/registers.h @@ -1388,6 +1388,21 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_CFGR_SWS_HSE (2 << 3) #define STM32_RCC_CFGR_SWS_PLL1 (3 << 3) #define STM32_RCC_CFGR_SWS_MASK (3 << 3) +#define STM32_RCC_D1CFGR_HPRE_DIV1 (0 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV2 (8 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV4 (9 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV8 (10 << 0) +#define STM32_RCC_D1CFGR_HPRE_DIV16 (11 << 0) +#define STM32_RCC_D1CFGR_D1PPRE_DIV1 (0 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV2 (4 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV4 (5 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV8 (6 << 4) +#define STM32_RCC_D1CFGR_D1PPRE_DIV16 (7 << 4) +#define STM32_RCC_D1CFGR_D1CPRE_DIV1 (0 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV2 (8 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV4 (9 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV8 (10 << 8) +#define STM32_RCC_D1CFGR_D1CPRE_DIV16 (11 << 8) #define STM32_RCC_PLLCKSEL_PLLSRC_HSI (0 << 0) #define STM32_RCC_PLLCKSEL_PLLSRC_CSI (1 << 0) #define STM32_RCC_PLLCKSEL_PLLSRC_HSE (2 << 0) @@ -1411,6 +1426,19 @@ typedef volatile struct timer_ctlr timer_ctlr_t; #define STM32_RCC_PLLDIV_DIVQ(q) (((q) - 1) << 16) #define STM32_RCC_PLLDIV_DIVR(r) (((r) - 1) << 24) #define STM32_RCC_PLLFRAC(n) ((n) << 3) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL1Q (0 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL2P (1 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PLL3P (2 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_I2SCKIN (3 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_PERCK (4 << 12) +#define STM32_RCC_D2CCIP1R_SPI123SEL_MASK (7 << 12) +#define STM32_RCC_D2CCIP1R_SPI45SEL_APB (0 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL2Q (1 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_PLL3Q (2 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_HSI (3 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_CSI (4 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_HSE (5 << 16) +#define STM32_RCC_D2CCIP1R_SPI45SEL_MASK (7 << 16) #define STM32_RCC_D2CCIP2_USART234578SEL_PCLK (0 << 0) #define STM32_RCC_D2CCIP2_USART234578SEL_PLL2Q (1 << 0) #define STM32_RCC_D2CCIP2_USART234578SEL_PLL3Q (2 << 0) |