Commit 34b11b9f authored by Yuri Tikhonov's avatar Yuri Tikhonov
Browse files

RT72064. stm32f2: change sys freq from 16MHz up to 120MHz



Beside of faster working we'll need HSE for clocking MAC (previously
we was clocked by HSI, by poweron default).
Signed-off-by: default avatarYuri Tikhonov <yur@emcraft.com>
parent 00d4509d
......@@ -24,47 +24,349 @@
#include "clock.h"
#if !defined(CONFIG_STM32F2_HSE_HZ)
# error "Value of the External oscillator, CONFIG_STM32F2_HSE_HZ, is not set."
/*
* STM32F2 Clock configuration is set by the number of CONFIG options.
*
* Source for system clock must be selected:
* - CONFIG_STM32F2_SYS_CLK_HSI: HSI oscillator used as sys clock,
* CONFIG_STM32F2_SYS_CLK_HSE: HSE oscillator used as sys clock,
* CONFIG_STM32F2_SYS_CLK_PLL: PLL used as sys clock.
*
* In case of CONFIG_STM32F2_SYS_CLK_HSE or CONFIG_STM32F2_SYS_CLK_PLL with
* CONFIG_STM32F2_PLL_SRC_HSE configurations, the following option must be set:
* - CONFIG_STM32F2_HSE_HZ: HSE oscillator frequency value.
*
* In case of CONFIG_STM32F2_SYS_CLK_PLL configuration, the following options
* must be set:
* - CONFIG_STM32F2_PLL_SRC_HSI: HSI clock used as PLL clock entry,
* CONFIG_STM32F2_PLL_SRC_HSE: HSE clock used as PLL clock entry;
* - CONFIG_STM32F2_PLL_M: division factor for PLL input clock;
* - CONFIG_STM32F2_PLL_N: multiplication factor for VCO;
* - CONFIG_STM32F2_PLL_P: division factor for main system clock;
* - CONFIG_STM32F2_PLL_Q: division factor for USB OTG FS, SDIO and RNG clocks.
* Then:
* Fsys = Fvco / P : PLL general clock output;
* Fvco = Fin * N / M : VCO clock (Fin is the frequency of PLL source);
* Fout = Fvco / Q : USB OTG FS, SDIO, RNG clock output.
*
* !!! Note, beside of the options specified above VCC voltage may limit the
* acceptable range of system clock, below is assumed that VDD(V) is equal to
* 3.3V (i.e. in range of [2.7; 3.6]).
* See AN3362 "Clock configuration tool for STM32F2xx microcontrollers"
* application note, and stm32f2xx_rcc.c code of STM32F2xx_StdPeriph_Driver
* library from STM for details.
*/
/*
* Check configuration params
*/
#if ((!!defined(CONFIG_STM32F2_SYS_CLK_HSI) + \
!!defined(CONFIG_STM32F2_SYS_CLK_HSE) + \
!!defined(CONFIG_STM32F2_SYS_CLK_PLL)) != 1)
# error "Incorrect SYS Clock source configuration."
#endif
#if defined(CONFIG_STM32F2_SYS_CLK_HSE) || \
(defined(CONFIG_STM32F2_SYS_CLK_PLL) && \
defined(CONFIG_STM32F2_PLL_SRC_HSE))
# if !defined(CONFIG_STM32F2_HSE_HZ)
# error "External oscillator HSE value is not set."
# endif
#endif
#if defined(CONFIG_STM32F2_SYS_CLK_PLL)
# if ((!!defined(CONFIG_STM32F2_PLL_SRC_HSI) + \
!!defined(CONFIG_STM32F2_PLL_SRC_HSE)) != 1)
# error "Incorrect PLL clock source configuration."
# endif
# if ((!!defined(CONFIG_STM32F2_PLL_M) + \
!!defined(CONFIG_STM32F2_PLL_N) + \
!!defined(CONFIG_STM32F2_PLL_P) + \
!!defined(CONFIG_STM32F2_PLL_Q)) != 4)
# error "Incomplete PLL configuration."
# endif
# if (CONFIG_STM32F2_PLL_M < 2) || (CONFIG_STM32F2_PLL_M > 63)
# error "Incorrect PLL_M value."
# endif
# if (CONFIG_STM32F2_PLL_N < 192) || (CONFIG_STM32F2_PLL_N > 432)
# error "Incorrect PLL_N value."
# endif
# if (CONFIG_STM32F2_PLL_P != 2) && (CONFIG_STM32F2_PLL_P != 4) && \
(CONFIG_STM32F2_PLL_P != 6) && (CONFIG_STM32F2_PLL_P != 8)
# error "Incorrect PLL_P value."
# endif
# if (CONFIG_STM32F2_PLL_Q < 4) || (CONFIG_STM32F2_PLL_Q > 15)
# error "Incorrect PLL_Q value."
# endif
#endif
/*
* Internal oscillator value
*/
#define STM32F2_HSI_HZ 16000000
#define STM32F2_HSI_HZ 16000000 /* 16 MHz */
/*
* Get the SYS CLK value according to configuration
*/
#if defined(CONFIG_STM32F2_SYS_CLK_HSI)
# define STM32F2_SYS_CLK STM32F2_HSI_HZ
#elif defined(CONFIG_STM32F2_SYS_CLK_HSE)
# define STM32F2_SYS_CLK CONFIG_STM32F2_HSE_HZ
#else
# if defined(CONFIG_STM32F2_PLL_SRC_HSE)
# define STM32F2_PLL_IN_HZ CONFIG_STM32F2_HSE_HZ
# else
# define STM32F2_PLL_IN_HZ STM32F2_HSI_HZ
# endif
# define STM32F2_SYS_CLK ((STM32F2_PLL_IN_HZ * \
CONFIG_STM32F2_PLL_N) / \
(CONFIG_STM32F2_PLL_M * \
CONFIG_STM32F2_PLL_P))
#endif
/*
* Get the Flash latency value for this SYS CLK
*/
# if (STM32F2_SYS_CLK > 0) && (STM32F2_SYS_CLK <= 30000000)
# define STM32F2_FLASH_WS 0
#elif (STM32F2_SYS_CLK > 30000000) && (STM32F2_SYS_CLK <= 60000000)
# define STM32F2_FLASH_WS 1
#elif (STM32F2_SYS_CLK > 60000000) && (STM32F2_SYS_CLK <= 90000000)
# define STM32F2_FLASH_WS 2
#elif (STM32F2_SYS_CLK > 90000000) && (STM32F2_SYS_CLK <= 120000000)
# define STM32F2_FLASH_WS 3
#else
# error "Incorrect System clock value configuration."
# define STM32F2_FLASH_WS 0 /* to avoid compile-time err */
#endif
/*
* Offsets and bitmasks of some RCC regs
*/
#define STM32F2_RCC_CFGR_SWS_BIT 0
#define STM32F2_RCC_CFGR_SWS_MSK 0x000F
#define STM32F2_RCC_CR_HSEON (1 << 16) /* HSE clock enable */
#define STM32F2_RCC_CR_HSERDY (1 << 17) /* HSE clock ready */
#define STM32F2_RCC_CR_PLLON (1 << 24) /* PLL clock enable */
#define STM32F2_RCC_CR_PLLRDY (1 << 25) /* PLL clock ready */
#define STM32F2_RCC_CFGR_SW_BIT 0 /* System clock switch */
#define STM32F2_RCC_CFGR_SW_MSK 0x3
#define STM32F2_RCC_CFGR_SWS_BIT 2 /* System clock switch status */
#define STM32F2_RCC_CFGR_SWS_MSK 0x3
#define STM32F2_RCC_CFGR_SWS_HSI 0x0
#define STM32F2_RCC_CFGR_SWS_HSE 0x1
#define STM32F2_RCC_CFGR_SWS_PLL 0x2
#define STM32F2_RCC_CFGR_HPRE_BIT 4 /* AHB prescaler */
#define STM32F2_RCC_CFGR_HPRE_MSK 0xF
#define STM32F2_RCC_CFGR_HPRE_DIVNO 0x0
#define STM32F2_RCC_CFGR_HPRE_DIV2 0x8
#define STM32F2_RCC_CFGR_HPRE_DIV4 0x9
#define STM32F2_RCC_CFGR_HPRE_DIV8 0xA
#define STM32F2_RCC_CFGR_HPRE_DIV16 0xB
#define STM32F2_RCC_CFGR_HPRE_DIV64 0xC
#define STM32F2_RCC_CFGR_HPRE_DIV128 0xD
#define STM32F2_RCC_CFGR_HPRE_DIV256 0xE
#define STM32F2_RCC_CFGR_HPRE_DIV512 0xF
#define STM32F2_RCC_CFGR_HPRE_BIT 4
#define STM32F2_RCC_CFGR_HPRE_MSK 0x000F
#define STM32F2_RCC_CFGR_PPRE1_BIT 10 /* APB Low speed presc (APB1) */
#define STM32F2_RCC_CFGR_PPRE1_MSK 0x7
#define STM32F2_RCC_CFGR_PPRE1_DIV0 0x0
#define STM32F2_RCC_CFGR_PPRE1_DIV2 0x4
#define STM32F2_RCC_CFGR_PPRE1_DIV4 0x5
#define STM32F2_RCC_CFGR_PPRE1_DIV8 0x6
#define STM32F2_RCC_CFGR_PPRE1_DIV16 0x7
#define STM32F2_RCC_CFGR_PPRE1_BIT 10
#define STM32F2_RCC_CFGR_PPRE1_MSK 0x0007
#define STM32F2_RCC_CFGR_PPRE2_BIT 13 /* APB high-speed presc (APB2)*/
#define STM32F2_RCC_CFGR_PPRE2_MSK 0x7
#define STM32F2_RCC_CFGR_PPRE2_DIVNO 0x0
#define STM32F2_RCC_CFGR_PPRE2_DIV2 0x4
#define STM32F2_RCC_CFGR_PPRE2_DIV4 0x5
#define STM32F2_RCC_CFGR_PPRE2_DIV8 0x6
#define STM32F2_RCC_CFGR_PPRE2_DIV16 0x7
#define STM32F2_RCC_CFGR_PPRE2_BIT 13
#define STM32F2_RCC_CFGR_PPRE2_MSK 0x0007
#define STM32F2_RCC_PLLCFGR_HSESRC (1 << 22) /* Main PLL entry clock src */
#define STM32F2_RCC_PLLCFGR_PLLSRC_BIT 22
#define STM32F2_RCC_PLLCFGR_PLLSRC_MSK 0x0001
#define STM32F2_RCC_PLLCFGR_PLLM_BIT 0 /* Div factor for input clock */
#define STM32F2_RCC_PLLCFGR_PLLM_MSK 0x3F
#define STM32F2_RCC_PLLCFGR_PLLM_BIT 0
#define STM32F2_RCC_PLLCFGR_PLLM_MSK 0x003F
#define STM32F2_RCC_PLLCFGR_PLLN_BIT 6 /* Mult factor for VCO */
#define STM32F2_RCC_PLLCFGR_PLLN_MSK 0x1FF
#define STM32F2_RCC_PLLCFGR_PLLN_BIT 6
#define STM32F2_RCC_PLLCFGR_PLLN_MSK 0x01FF
#define STM32F2_RCC_PLLCFGR_PLLP_BIT 16 /* Div factor for main sysclk */
#define STM32F2_RCC_PLLCFGR_PLLP_MSK 0x3
#define STM32F2_RCC_PLLCFGR_PLLP_BIT 16
#define STM32F2_RCC_PLLCFGR_PLLP_MSK 0x0003
#define STM32F2_RCC_PLLCFGR_PLLQ_BIT 24 /* Div factor for USB,SDIO,.. */
#define STM32F2_RCC_PLLCFGR_PLLQ_MSK 0xF
/*
* Flash registers base
*/
#define STM32F2_FLASH_BASE (STM32F2_AHB1PERITH_BASE + 0x3C00)
/*
* Flash ACR definitions
*/
#define STM32F2_FLASH_ACR_LAT_BIT 0 /* Latency */
#define STM32F2_FLASH_ACR_LAT_MSK 0x3
#define STM32F2_FLASH_ACR_PRFTEN (1 << 8) /* Prefetch enable */
#define STM32F2_FLASH_ACR_ICEN (1 << 9) /* Instruction cache enable*/
/*
* Timeouts (in cycles)
*/
#define STM32F2_HSE_STARTUP_TIMEOUT 0x0500
/*
* Flash register map
*/
struct stm32f2_flash_regs {
u32 acr; /* Access control */
u32 keyr; /* Key */
u32 optkeyr; /* Option key */
u32 sr; /* Status */
u32 cr; /* Control */
u32 optcr; /* Option control */
};
/*
* Clock values
*/
static u32 clock_val[CLOCK_END];
/*
* Enable instruction cache, prefetch and set the Flash wait latency
* according to the clock configuration used (HCLK value).
* We _must_ do this before changing System clock source (or will crash on
* fetching instructions of while() wait cycle).
* In case of HSI clock - no Sys clock change happens, but, for consistency,
* we configure Flash this way as well.
*/
static void flash_setup(void)
{
volatile struct stm32f2_flash_regs *flash_regs;
flash_regs = (struct stm32f2_flash_regs *)STM32F2_FLASH_BASE;
flash_regs->acr = STM32F2_FLASH_ACR_PRFTEN |
STM32F2_FLASH_ACR_ICEN |
(STM32F2_FLASH_WS << STM32F2_FLASH_ACR_LAT_BIT);
}
#if !defined(CONFIG_STM32F2_SYS_CLK_HSI)
/*
* Set-up clock configuration.
*/
static void clock_setup(void)
{
volatile struct stm32f2_rcc_regs *rcc_regs;
u32 val;
int i;
/*
* Get RCC regs base
*/
rcc_regs = (struct stm32f2_rcc_regs *)STM32F2_RCC_BASE;
/*
* Enable HSE, and wait it becomes ready
*/
rcc_regs->cr |= STM32F2_RCC_CR_HSEON;
for (i = 0; i < STM32F2_HSE_STARTUP_TIMEOUT; i++) {
if (rcc_regs->cr & STM32F2_RCC_CR_HSERDY)
break;
}
if (!(rcc_regs->cr & STM32F2_RCC_CR_HSERDY)) {
/*
* Have no HSE clock
*/
goto out;
}
val = rcc_regs->cfgr;
/*
* HCLK = SYSCLK / 1
*/
val &= ~(STM32F2_RCC_CFGR_HPRE_MSK << STM32F2_RCC_CFGR_HPRE_BIT);
val |= STM32F2_RCC_CFGR_HPRE_DIVNO << STM32F2_RCC_CFGR_HPRE_BIT;
/*
* PCLK2 = HCLK / 2
*/
val &= ~(STM32F2_RCC_CFGR_PPRE2_MSK << STM32F2_RCC_CFGR_PPRE2_BIT);
val |= STM32F2_RCC_CFGR_PPRE2_DIV2 << STM32F2_RCC_CFGR_PPRE2_BIT;
/*
* PCLK1 = HCLK / 4
*/
val &= ~(STM32F2_RCC_CFGR_PPRE1_MSK << STM32F2_RCC_CFGR_PPRE1_BIT);
val |= STM32F2_RCC_CFGR_PPRE1_DIV4 << STM32F2_RCC_CFGR_PPRE1_BIT;
rcc_regs->cfgr = val;
# if defined(CONFIG_STM32F2_SYS_CLK_PLL)
/*
* Configure the main PLL
*/
# if defined(CONFIG_STM32F2_PLL_SRC_HSE)
val = STM32F2_RCC_PLLCFGR_HSESRC;
# else
val = 0;
# endif
val |= CONFIG_STM32F2_PLL_M << STM32F2_RCC_PLLCFGR_PLLM_BIT;
val |= CONFIG_STM32F2_PLL_N << STM32F2_RCC_PLLCFGR_PLLN_BIT;
val |= ((CONFIG_STM32F2_PLL_P >> 1) - 1) <<
STM32F2_RCC_PLLCFGR_PLLP_BIT;
val |= CONFIG_STM32F2_PLL_Q << STM32F2_RCC_PLLCFGR_PLLQ_BIT;
rcc_regs->pllcfgr = val;
/*
* Enable the main PLL, and wait until main PLL becomes ready.
* Note: we wait infinitely here, since the max time necessary for
* PLL to lock is probably not a constant. There's no timeout here in
* STM lib code as well.
*/
rcc_regs->cr |= STM32F2_RCC_CR_PLLON;
while (rcc_regs->cr & STM32F2_RCC_CR_PLLRDY);
/*
* Select PLL as system source if it's setup OK, and HSE otherwise
*/
if (!(rcc_regs->cr & STM32F2_RCC_CR_PLLRDY))
val = STM32F2_RCC_CFGR_SWS_PLL;
else
val = STM32F2_RCC_CFGR_SWS_HSE;
# else
/*
* Select HSE as system source
*/
val = STM32F2_RCC_CFGR_SWS_HSE;
# endif /* CONFIG_STM32F2_SYS_CLK_PLL */
/*
* Configure Flash prefetch, Instruction cache, and wait
* latency.
*/
flash_setup();
/*
* Change system clock source, and wait (infinite!) till it done
*/
rcc_regs->cfgr &= ~(STM32F2_RCC_CFGR_SW_MSK <<
STM32F2_RCC_CFGR_SW_BIT);
rcc_regs->cfgr |= val << STM32F2_RCC_CFGR_SW_BIT;
while ((rcc_regs->cfgr & (STM32F2_RCC_CFGR_SWS_MSK <<
STM32F2_RCC_CFGR_SWS_BIT)) !=
(val << STM32F2_RCC_CFGR_SWS_BIT));
out:
return;
}
#endif /* CONFIG_STM32F2_SYS_CLK_HSI */
/*
* Initialize the reference clocks.
*/
......@@ -77,19 +379,34 @@ void clock_init(void)
(struct stm32f2_rcc_regs *)STM32F2_RCC_BASE;
u32 tmp, presc, pllvco, pllp, pllm;
#if !defined(CONFIG_STM32F2_SYS_CLK_HSI)
/*
* Set clocks to cfg, which is differs from the poweron default
*/
clock_setup();
#else
/*
* For consistency with !HSI configs, enable prefetch and cache
*/
flash_setup();
#endif
/*
* Get SYSCLK
*/
tmp = rcc_regs->cfgr >> STM32F2_RCC_CFGR_SWS_BIT;
tmp &= STM32F2_RCC_CFGR_SWS_MSK;
switch (tmp) {
case 0x00: /* HSI used as system clock source */
case STM32F2_RCC_CFGR_SWS_HSI:
/* HSI used as system clock source */
clock_val[CLOCK_SYSCLK] = STM32F2_HSI_HZ;
break;
case 0x04: /* HSE used as system clock source */
case STM32F2_RCC_CFGR_SWS_HSE:
/* HSE used as system clock source */
clock_val[CLOCK_SYSCLK] = CONFIG_STM32F2_HSE_HZ;
break;
case 0x08: /* PLL used as system clock source */
case STM32F2_RCC_CFGR_SWS_PLL:
/* PLL used as system clock source */
/*
* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLLM) * PLLN
* SYSCLK = PLL_VCO / PLLP
......@@ -97,7 +414,7 @@ void clock_init(void)
pllm = rcc_regs->pllcfgr >> STM32F2_RCC_PLLCFGR_PLLM_BIT;
pllm &= STM32F2_RCC_PLLCFGR_PLLM_MSK;
if (rcc_regs->pllcfgr & (1 << STM32F2_RCC_PLLCFGR_PLLSRC_BIT)) {
if (rcc_regs->pllcfgr & STM32F2_RCC_PLLCFGR_HSESRC) {
/* HSE used as PLL clock source */
tmp = CONFIG_STM32F2_HSE_HZ;
} else {
......
......@@ -20,6 +20,8 @@
*/
#include <common.h>
#include <asm/arch/stm32f2.h>
#include "clock.h"
/*
* Print the CPU specific information
......@@ -28,6 +30,12 @@ int print_cpuinfo(void)
{
printf("CPU: %s\n", "STM32 F2 series (Cortex-M3)");
#if defined(DEBUG)
printf("Frequencies: SYSCLK=%d, HCLK=%d, PCLK1=%d, PCLK2=%d\n",
clock_get(CLOCK_SYSCLK), clock_get(CLOCK_HCLK),
clock_get(CLOCK_PCLK1), clock_get(CLOCK_PCLK2));
#endif
return 0;
}
......
......@@ -65,9 +65,18 @@
#define CONFIG_ARCH_CPU_INIT
/*
* External oscillator value
*/
#define CONFIG_STM32F2_HSE_HZ 25000000
* Clock configuration (see stm32f2/clock.c for details):
* - use PLL as the system clock;
* - use HSE as the PLL source;
* - configure PLL to get 120MHz system clock.
*/
#define CONFIG_STM32F2_SYS_CLK_PLL
#define CONFIG_STM32F2_PLL_SRC_HSE
#define CONFIG_STM32F2_HSE_HZ 25000000 /* 25 MHz */
#define CONFIG_STM32F2_PLL_M 25
#define CONFIG_STM32F2_PLL_N 240
#define CONFIG_STM32F2_PLL_P 2
#define CONFIG_STM32F2_PLL_Q 5
/*
* Number of clock ticks in 1 sec
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment