From e352d4f3ada2f3484f6d2264a24dbf853ff79530 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 6 Jun 2013 11:18:52 -0600 Subject: [PATCH] Add register definitions for SAM4L BPM and SCIF blocks; SAM4L clock initialization now selects an optimal power scaling mode --- ChangeLog | 5 +- arch/arm/src/sam34/chip/sam4l_flashcalw.h | 30 +++++ arch/arm/src/sam34/sam4l_clockconfig.c | 134 ++++++++++++---------- arch/avr/src/at32uc3/at32uc3_clkinit.c | 24 ++-- configs/sam4l-xplained/include/board.h | 101 ++++++++-------- 5 files changed, 174 insertions(+), 120 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0141d60c6f..f372a56e6c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -4910,4 +4910,7 @@ logic (leveraged from AVR32). * nuttx/arch/arm/src/sam34/sam4l_periphclks.c/h: Add common logic to enabled/disable SAM4L peripheral clocking (2013-6-5). - + * nuttx/arch/arm/src/sam34/chip/sam4l_bpm.h and sam4l_scif.h: Add + register definitions for the SAM4L BMP and SCIF blocks (2013-6-6). + * nuttx/arch/arm/src/sam34/sam4l_clockconfig.c: New selects an + optimal power scaling mode (2013-6-6). 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); diff --git a/configs/sam4l-xplained/include/board.h b/configs/sam4l-xplained/include/board.h index 4aaefd3fbc..94d786a237 100644 --- a/configs/sam4l-xplained/include/board.h +++ b/configs/sam4l-xplained/include/board.h @@ -54,66 +54,73 @@ ************************************************************************************/ /* Clocking *************************************************************************/ -/* After power-on reset, the sam3u device is running on a 4MHz internal RC. These - * definitions will configure clocking with MCK = 48MHz, PLLA = 96, and CPU=48MHz. + +/* Select the DFLL as the source of the system clock. + * + * Options (define one): + * BOARD_SYSCLK_SOURCE_RCSYS - System RC oscillator + * BOARD_SYSCLK_SOURCE_OSC0 - Oscillator 0 + * BOARD_SYSCLK_SOURCE_PLL0 - Phase Locked Loop 0 + * BOARD_SYSCLK_SOURCE_DFLL0 - Digital Frequency Locked Loop + * BOARD_SYSCLK_SOURCE_RC80M - 80 MHz RC oscillator + * BOARD_SYSCLK_SOURCE_FCFAST12M - 12 MHz RC oscillator + * BOARD_SYSCLK_SOURCE_FCFAST8M - 8 MHz RC oscillator + * BOARD_SYSCLK_SOURCE_FCFAST4M - 4 MHz RC oscillator + * BOARD_SYSCLK_SOURCE_RC1M - 1 MHz RC oscillator */ -/* Main oscillator register settings */ +#define BOARD_SYSCLK_SOURCE_DFLL0 1 -#define BOARD_CKGR_MOR_MOSCXTST (63 << CKGR_MOR_MOSCXTST_SHIFT) /* Start-up Time */ +/* Nominal frequencies in on-chip RC oscillators. These are *not* configurable + * but appear here for use in frequency calculations. NOTE: These may frequencies + * may vary with temperature changes. + */ -/* PLLA configuration */ +#define BOARD_RCSYS_FREQUENCY 115000 /* Nominal frequency of RCSYS (Hz) */ +#define BOARD_RC32K_FREQUENCY 32768 /* Nominal frequency of RC32K (Hz) */ +#define BOARD_RC80M_FREQUENCY 80000000 /* Nominal frequency of RC80M (Hz) */ +#define BOARD_RCFAST4M_FREQUENCY 4000000 /* Nominal frequency of RCFAST4M (Hz) */ +#define BOARD_RCFAST8M_FREQUENCY 8000000 /* Nominal frequency of RCFAST8M (Hz) */ +#define BOARD_RCFAST12M_FREQUENCY 12000000 /* Nominal frequency of RCFAST12M (Hz) */ +#define BOARD_RC1M_FREQUENCY 1000000 /* Nominal frequency of RC1M (Hz) */ -#define BOARD_CKGR_PLLAR_MULA (7 << CKGR_PLLAR_MULA_SHIFT) -#define BOARD_CKGR_PLLAR_STMODE CKGR_PLLAR_STMODE_FAST -#define BOARD_CKGR_PLLAR_PLLACOUNT (63 << CKGR_PLLAR_PLLACOUNT_SHIFT) -#define BOARD_CKGR_PLLAR_DIVA CKGR_PLLAR_DIVA_BYPASS +/* On-board crystal frequencies */ -/* PMC master clock register settings */ +#define BOARD_OSC32_FREQUENCY 32768 -#define BOARD_PMC_MCKR_CSS PMC_MCKR_CSS_PLLA -#define BOARD_PMC_MCKR_PRES PMC_MCKR_PRES_DIV2 +/* Digital Frequency Locked Loop configuration + * Fdfll = (Fclk * DFLLmul) / DFLLdiv + * = 32768 * (48000000/32760) / 1 = 48MHz + * + * DFLL0 source options (select one): + * BOARD_DFLL0_SOURCE_RCSYS - System RC oscillator + * BOARD_DFLL0_SOURCE_OSC32K - 32.768KHz oscillator + * BOARD_DFLL0_SOURCE_OSC0 - Oscillator 0 + * BOARD_DFLL0_SOURCE_RC80M - 80 MHz RC oscillator + * BOARD_DFLL0_SOURCE_RC32K - 32 kHz RC oscillator + */ -/* USB UTMI PLL start-up time */ +#define BOARD_DFLL0_SOURCE_OSC32K 1 +#define BOARD_FDLL0_FREQUENCY 48000000 +#define BOARD_FDLL0_MUL (BOARD_FDLL0_FREQUENCY / BOARD_OSC32_FREQUENCY) +#define BOARD_FDLL0_DIV 1 -#define BOARD_CKGR_UCKR_UPLLCOUNT (3 << CKGR_UCKR_UPLLCOUNT_SHIFT) +/* System clock dividers: Fbus = Fsys >> BUSshift */ -/* System clock dividers: Fbus = Fsys / (2 ^ BUS_div) */ - -#define BOARD_SYSCLK_CPU_DIV 0 -#define BOARD_SYSCLK_PBA_DIV 0 -#define BOARD_SYSCLK_PBB_DIV 0 -#define BOARD_SYSCLK_PBC_DIV 0 -#define BOARD_SYSCLK_PBD_DIV 0 +#define BOARD_CPU_SHIFT 0 /* Fcpu = Fsys = 48MHz */ +#define BOARD_PBA_SHIFT 0 /* Fpba = Fsys = 48MHz */ +#define BOARD_PBB_SHIFT 0 /* Fpbb = Fsys = 48MHz */ +#define BOARD_PBC_SHIFT 0 /* Fpbc = Fsys = 48MHz */ +#define BOARD_PBD_SHIFT 0 /* Fpbd = Fsys = 48MHz */ /* Resulting frequencies */ -#define SAM_MAINOSC_FREQUENCY (12000000) -#define SAM_MCK_FREQUENCY (48000000) -#define SAM_PLLA_FREQUENCY (96000000) -#define SAM_CPU_FREQUENCY (48000000) - -/* HSMCI clocking - * - * Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK) - * divided by (2*(CLKDIV+1)). - * - * MCI_SPEED = MCK / (2*(CLKDIV+1)) - * CLKDIV = MCI / MCI_SPEED / 2 - 1 - */ - -/* MCK = 48MHz, CLKDIV = 59, MCI_SPEED = 48MHz / 2 * (59+1) = 400 KHz */ - -#define HSMCI_INIT_CLKDIV (59 << HSMCI_MR_CLKDIV_SHIFT) - -/* MCK = 48MHz, CLKDIV = 1, MCI_SPEED = 48MHz / 2 * (1+1) = 12 MHz */ - -#define HSMCI_MMCXFR_CLKDIV (3 << HSMCI_MR_CLKDIV_SHIFT) - -/* MCK = 48MHz, CLKDIV = 0, MCI_SPEED = 48MHz / 2 * (0+1) = 24 MHz */ - -#define HSMCI_SDXFR_CLKDIV (0 << HSMCI_MR_CLKDIV_SHIFT) -#define HSMCI_SDWIDEXFR_CLKDIV HSMCI_SDXFR_CLKDIV +#define BOARD_MAIN_FREQUENCY (12000000) +#define BOARD_CPU_FREQUENCY (BOARD_MAIN_FREQUENCY >> BOARD_CPU_SHIFT) +#define BOARD_PBA_FREQUENCY (BOARD_MAIN_FREQUENCY >> BOARD_PBA_SHIFT) +#define BOARD_PBB_FREQUENCY (BOARD_MAIN_FREQUENCY >> BOARD_PBB_SHIFT) +#define BOARD_PBC_FREQUENCY (BOARD_MAIN_FREQUENCY >> BOARD_PBC_SHIFT) +#define BOARD_PBD_FREQUENCY (BOARD_MAIN_FREQUENCY >> BOARD_PBD_SHIFT) /* LED definitions ******************************************************************/ /* There are three LEDs on board the SAM4L Xplained Pro board: The EDBG