summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chip/stm32/clock-stm32h7.c84
-rw-r--r--chip/stm32/hwtimer32.c5
-rw-r--r--chip/stm32/registers.h28
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)