diff --git a/arch/arm/src/sam34/chip/sam4l_flashcalw.h b/arch/arm/src/sam34/chip/sam4l_flashcalw.h index d2503aa18d..101ed90dbb 100644 --- a/arch/arm/src/sam34/chip/sam4l_flashcalw.h +++ b/arch/arm/src/sam34/chip/sam4l_flashcalw.h @@ -333,6 +333,36 @@ #define FLASH_CMD_HSEN 16 /* High Speed Mode Enable */ #define FLASH_CMD_HSDIS 17 /* High Speed Mode Disable */ +/* Maximum CPU frequency for 0 and 1 FLASH wait states (FWS) in various modes + * (Table 42-30 in the big data sheet). + * + * ------- ------------------- ---------- ---------- + * Power Flash Read Mode Flash Maximum + * Sclaing Wait Operating + * Mode HSEN HSDIS FASTWKUP States Frequency + * ------- ---- ----- -------- ---------- ---------- + * PS0 X X 1 12MHz + * " " X 0 18MHz + * " " X 1 36MHz + * PS1 X X 1 12MHz + * " " X 0 8MHz + * " " X 1 12MHz + * PS2 X 0 24Mhz + * " " X 1 48MHz + * ------- ---- ----- -------- ---------- ---------- + */ + +#define FLASH_MAXFREQ_PS0_HSDIS_FASTWKUP_FWS1 (12000000ul) +#define FLASH_MAXFREQ_PS0_HSDIS_FWS0 (18000000ul) +#define FLASH_MAXFREQ_PS0_HSDIS_FWS1 (36000000ul) + +#define FLASH_MAXFREQ_PS1_HSDIS_FASTWKUP_FWS1 (12000000ul) +#define FLASH_MAXFREQ_PS1_HSDIS_FWS0 (8000000ul) +#define FLASH_MAXFREQ_PS1_HSDIS_FWS1 (12000000ul) + +#define FLASH_MAXFREQ_PS2_HSEN_FWS0 (24000000ul) +#define FLASH_MAXFREQ_PS2_HSEN_FWS1 (48000000ul) + /************************************************************************************ * Public Types ************************************************************************************/ diff --git a/arch/arm/src/sam34/sam4l_clockconfig.c b/arch/arm/src/sam34/sam4l_clockconfig.c index 2857c7fb10..a26f401ee5 100644 --- a/arch/arm/src/sam34/sam4l_clockconfig.c +++ b/arch/arm/src/sam34/sam4l_clockconfig.c @@ -55,6 +55,17 @@ /**************************************************************************** * Private Definitions ****************************************************************************/ +/* Nominal frequencies in on-chip RC oscillators. These may frequencies + * may vary with temperature changes. + */ + +#define SAM_RCSYS_FREQUENCY 115000 /* Nominal frequency of RCSYS (Hz) */ +#define SAM_RC32K_FREQUENCY 32768 /* Nominal frequency of RC32K (Hz) */ +#define SAM_RC80M_FREQUENCY 80000000 /* Nominal frequency of RC80M (Hz) */ +#define SAM_RCFAST4M_FREQUENCY 4000000 /* Nominal frequency of RCFAST4M (Hz) */ +#define SAM_RCFAST8M_FREQUENCY 8000000 /* Nominal frequency of RCFAST8M (Hz) */ +#define SAM_RCFAST12M_FREQUENCY 12000000 /* Nominal frequency of RCFAST12M (Hz) */ +#define SAM_RC1M_FREQUENCY 1000000 /* Nominal frequency of RC1M (Hz) */ #if defined(SAM_CLOCK_OSC0) || \ (defined (SAM_CLOCK_PLL0) && defined(SAM_CLOCK_PLL0_OSC0)) || \ @@ -62,12 +73,6 @@ # define NEED_OSC0 #endif -#if defined(SAM_CLOCK_OSC1) || \ - (defined (SAM_CLOCK_PLL0) && defined(SAM_CLOCK_PLL0_OSC1)) || \ - (defined (SAM_CLOCK_PLL1) && defined(SAM_CLOCK_PLL1_OSC1)) -# define NEED_OSC1 -#endif - /**************************************************************************** * Private Types ****************************************************************************/ @@ -192,55 +197,6 @@ static inline void sam_enableosc0(void) } #endif -/**************************************************************************** - * Name: sam_enableosc1 - * - * Description: - * Initialiaze OSC0 settings per the definitions in the board.h file. - * - ****************************************************************************/ - -#ifdef NEED_OSC1 -static inline void sam_enableosc1(void) -{ - uint32_t regval; - - /* Enable OSC1 in the correct crystal mode by setting the mode value in OSCCTRL1 */ - - regval = getreg32(SAM_PM_OSCCTRL1); - regval &= ~PM_OSCCTRL_MODE_MASK; -#if SAM_FOSC1 < 900000 - regval |= PM_OSCCTRL_MODE_XTALp9; /* Crystal XIN 0.4-0.9MHz */ -#elif SAM_FOSC1 < 3000000 - regval |= PM_OSCCTRL_MODE_XTAL3; /* Crystal XIN 0.9-3.0MHz */ -#elif SAM_FOSC1 < 8000000 - regval |= PM_OSCCTRL_MODE_XTAL8; /* Crystal XIN 3.0-8.0MHz */ -#else - regval |= PM_OSCCTRL_MODE_XTALHI; /* Crystal XIN above 8.0MHz */ -#endif - putreg32(regval, SAM_PM_OSCCTRL1); - - /* Enable OSC1 using the startup time provided in board.h. This startup time - * is critical and depends on the characteristics of the crystal. - */ - - regval = getreg32(SAM_PM_OSCCTRL1); - regval &= ~PM_OSCCTRL_STARTUP_MASK; - regval |= (SAM_OSC1STARTUP << PM_OSCCTRL_STARTUP_SHIFT); - putreg32(regval, SAM_PM_OSCCTRL1); - - /* Enable OSC1 */ - - regval = getreg32(SAM_PM_MCCTRL); - regval |= PM_MCCTRL_OSC1EN; - putreg32(regval, SAM_PM_MCCTRL); - - /* Wait for OSC1 to be ready */ - - while ((getreg32(SAM_PM_POSCSR) & PM_POSCSR_OSC1RDY) == 0); -} -#endif - /**************************************************************************** * Name: sam_enablepll0 * @@ -505,17 +461,75 @@ static inline void sam_usbclock(void) void sam_clockconfig(void) { + uint32_t regval; + uint32_t bpmps; + bool fastwkup; + /* Enable clocking to the PICOCACHE */ sam_picocache(); - /* Configure dividers derived clocks. These divider definitions must be - * provided in the board.h header file. + /* Configure dividers for derived clocks. These divider definitions must + * be provided in the board.h header file. */ - sam_setdividers(BOARD_SYSCLK_CPU_DIV, BOARD_SYSCLK_PBA_DIV, - BOARD_SYSCLK_PBB_DIV, BOARD_SYSCLK_PBC_DIV, - BOARD_SYSCLK_PBD_DIV); + sam_setdividers(BOARD_CPU_SHIFT, BOARD_PBA_SHIFT, BOARD_PBB_SHIFT, + BOARD_PBC_SHIFT, BOARD_PBD_SHIFT); + + + /* Select a power scaling mode and possible fast wakeup so that we get the + * best possible flash performance. The following table shows the maximum + * CPU frequency for 0 and 1 FLASH wait states (FWS) in various modes + * (Table 42-30 in the big data sheet). + * + * ------- ------------------- ---------- ---------- + * Power Flash Read Mode Flash Maximum + * Sclaing Wait Operating + * Mode HSEN HSDIS FASTWKUP States Frequency + * ------- ---- ----- -------- ---------- ---------- + * PS0 X X 1 12MHz + * " " X 0 18MHz + * " " X 1 36MHz + * PS1 X X 1 12MHz + * " " X 0 8MHz + * " " X 1 12MHz + * PS2 X 0 24Mhz + * " " X 1 48MHz + * ------- ---- ----- -------- ---------- ---------- + */ + +#ifdef CONFIG_SAM_FLASH_HSEN + /* The high speed FLASH mode has been enabled. Select power scaling mode 2 */ + + bpmps = BPM_PMCON_PS2; + fastwkup = false; +#else + /* Not high speed mode. Check if we can go to power scaling mode 1. */ + + if (BOARD_CPU_FREQUENCY <= FLASH_MAXFREQ_PS1_HSDIS_FWS1) + { + /* Yes.. Do we also need to enable fast wakeup? */ + + bpmps = BPM_PMCON_PS1; + if (BOARD_CPU_FREQUENCY > FLASH_MAXFREQ_PS1_HSDIS_FWS0) + { + /* Yes.. enable fast wakeup */ + + regval = getreg32(SAM_BPM_PMCON); + regval |= BPM_PMCON_FASTWKUP; + putreg32(BPM_UNLOCK_KEY(0xaa) | BPM_UNLOCK_ADDR(SAM_BPM_PMCON_OFFSET), SAM_BPM_UNLOCK); + putreg32(regval, SAM_BPM_PMCON); + + /* We need to remember that we did this */ + + fastwkup = true; + } + } + else + { + bpmps = BPM_PMCON_PS0; + } +#endif #ifdef SAM_CLOCK_OSC32 /* Enable the 32KHz oscillator (need by the RTC module) */ diff --git a/arch/avr/src/at32uc3/at32uc3_clkinit.c b/arch/avr/src/at32uc3/at32uc3_clkinit.c index 1a39aad783..baaecbce37 100644 --- a/arch/avr/src/at32uc3/at32uc3_clkinit.c +++ b/arch/avr/src/at32uc3/at32uc3_clkinit.c @@ -98,7 +98,7 @@ static inline void up_enableosc32(void) { uint32_t regval; - + /* Select the 32KHz oscillator crystal */ regval = getreg32(AVR32_PM_OSCCTRL32); @@ -225,7 +225,7 @@ static inline void up_enableosc1(void) static inline void up_enablepll0(void) { /* Setup PLL0 */ - + regval = (AVR32_PLL0_DIV << PM_PLL_PLLDIV_SHIFT) | (AVR32_PLL0_MUL << PM_PLL_PLLMUL_SHIFT) | (16 << PM_PLL_PLLCOUNT_SHIFT) /* Select PLL0/1 oscillator */ @@ -256,7 +256,7 @@ static inline void up_enablepll0(void) regval = getreg32(AVR32_PM_PLL0); regval |= PM_PLL_PLLEN; putreg32(regval, AVR32_PM_PLL0) - + /* Wait for PLL0 locked. */ while ((getreg32(AVR32_PM_POSCSR) & PM_POSCSR_LOCK0) == 0); @@ -275,11 +275,11 @@ static inline void up_enablepll0(void) static inline void up_enablepll1(void) { /* Setup PLL1 */ - + regval = (AVR32_PLL1_DIV << PM_PLL_PLLDIV_SHIFT) | (AVR32_PLL1_MUL << PM_PLL_PLLMUL_SHIFT) | (16 << PM_PLL_PLLCOUNT_SHIFT) /* Select PLL0/1 oscillator */ - + #if AVR32_CLOCK_PLL_OSC1 regval |= PM_PLL_PLLOSC; #endif @@ -363,7 +363,7 @@ static inline void up_clksel(void) static void up_fws(uint32_t cpuclock) { uint32_t regval; - + regval = getreg32(AVR32_FLASHC_FCR); if (cpuclock > AVR32_FLASHC_FWS0_MAXFREQ) { @@ -387,7 +387,7 @@ static void up_fws(uint32_t cpuclock) static inline void up_mainclk(uint32_t mcsel) { uint32_t regval; - + regval = getreg32(AVR32_PM_MCCTRL); regval &= ~PM_MCCTRL_MCSEL_MASK; regval |= mcsel; @@ -422,7 +422,7 @@ static inline void up_usbclock(void) putreg32(regval, AVR32_PM_GCCTRL(AVR32_PM_GCLK_USBB)) /* Enable USB GCLK */ - + regval = getreg32(AVR32_PM_GCCTRL(AVR32_PM_GCLK_USBB)) regval |= PM_GCCTRL_CEN; putreg32(regval, AVR32_PM_GCCTRL(AVR32_PM_GCLK_USBB)) @@ -441,7 +441,7 @@ static inline void up_usbclock(void) * file. * **************************************************************************/ - + void up_clkinitialize(void) { #ifdef AVR32_CLOCK_OSC32 @@ -458,7 +458,7 @@ void up_clkinitialize(void) /* Set up FLASH wait states */ up_fws(AVR32_FOSC0); - + /* Then switch the main clock to OSC0 */ up_mainclk(PM_MCCTRL_MCSEL_OSC0); @@ -474,11 +474,11 @@ void up_clkinitialize(void) /* Enable PLL0 using the settings in board.h */ up_enablepll0(); - + /* Set up FLASH wait states */ up_fws(AVR32_CPU_CLOCK); - + /* Then switch the main clock to PLL0 */ up_mainclk(PM_MCCTRL_MCSEL_PLL0);