diff --git a/arch/arm/src/sam34/chip/sam4l_scif.h b/arch/arm/src/sam34/chip/sam4l_scif.h index 30e2e8a8a6..54cb4da338 100644 --- a/arch/arm/src/sam34/chip/sam4l_scif.h +++ b/arch/arm/src/sam34/chip/sam4l_scif.h @@ -209,6 +209,8 @@ #define SCIF_PLL0_PLLEN (1 << 0) /* Bit 0: PLL Enable */ #define SCIF_PLL0_PLLOSC_SHIFT (1) /* Bits 1-2: PLL Oscillator Select */ #define SCIF_PLL0_PLLOSC_MASK (3 << SCIF_PLL0_PLLOSC_SHIFT) +# define SCIF_PLL0_PLLOSC_OSC0 (0 << SCIF_PLL0_PLLOSC_SHIFT) /* Output clock from Oscillator0 */ +# define SCIF_PLL0_PLLOSC_GCLK9 (1 << SCIF_PLL0_PLLOSC_SHIFT) /* Generic clock 9 */ #define SCIF_PLL0_PLLOPT_SHIFT (3) /* Bits 3-5: PLL Option */ #define SCIF_PLL0_PLLOPT_MASK (7 << SCIF_PLL0_PLLOPT_SHIFT) # define SCIF_PLL0_PLLOPT_FVO (1 << SCIF_PLL0_PLLOPT_SHIFT) /* Selects the VCO frequency range (fvco) */ @@ -220,6 +222,23 @@ #define SCIF_PLL0_PLLMUL_MASK (15 << SCIF_PLL0_PLLMUL_SHIFT) #define SCIF_PLL0_PLLCOUNT_SHIFT (24) /* Bits 24-24: PLL Count */ #define SCIF_PLL0_PLLCOUNT_MASK (63 << SCIF_PLL0_PLLCOUNT_SHIFT) +# define SCIF_PLL0_PLLCOUNT_MAX (63 << SCIF_PLL0_PLLCOUNT_SHIFT) + +/* PLL0 operates in two frequency ranges as determined by SCIF_PLL0_PLLOPT_FVO: + * + * 0: 80MHz < fvco < 180MHz + * 1: 160MHz < fvco < 240MHz + * + * These ranges and recommend threshold value are defined below: + */ + +#define SCIF_PLL0_VCO_RANGE1_MINFREQ 160000000 +#define SCIF_PLL0_VCO_RANGE1_MAXFREQ 240000000 +#define SCIF_PLL0_VCO_RANGE0_MINFREQ 80000000 +#define SCIF_PLL0_VCO_RANGE0_MAXFREQ 180000000 + +#define SAM_PLL0_VCO_RANGE_THRESHOLD \ + ((SCIF_PLL0_VCO_RANGE1_MINFREQ + SCIF_PLL0_VCO_RANGE0_MAXFREQ) >> 1) /* DFLL0 Config Register */ @@ -340,6 +359,20 @@ #define SCIF_GCCTRL_DIVEN (1 << 1) /* Bit 1: Divide Enable */ #define SCIF_GCCTRL_OSCSEL_SHIFT (8) /* Bits 8-12: Oscillator Select */ #define SCIF_GCCTRL_OSCSEL_MASK (31 << SCIF_GCCTRL_OSCSEL_SHIFT) +# define SCIF_GCCTRL_OSCSEL_RCSYS (0 << SCIF_GCCTRL_OSCSEL_SHIFT) /* System RC oscillator */ +# define SCIF_GCCTRL_OSCSEL_OSC32K (1 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from OSC32K */ +# define SCIF_GCCTRL_OSCSEL_DFLL0 (2 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from DFLL0 */ +# define SCIF_GCCTRL_OSCSEL_OSC0 (3 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from Oscillator0 */ +# define SCIF_GCCTRL_OSCSEL_RC80M (4 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from 80MHz RCOSC */ +# define SCIF_GCCTRL_OSCSEL_RCFAST (5 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from 4,8,12MHz RCFAST */ +# define SCIF_GCCTRL_OSCSEL_RC1M (6 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from 1MHz RC1M */ +# define SCIF_GCCTRL_OSCSEL_CPUCLK (7 << SCIF_GCCTRL_OSCSEL_SHIFT) /* The CPU clock */ +# define SCIF_GCCTRL_OSCSEL_HSBCLK (8 << SCIF_GCCTRL_OSCSEL_SHIFT) /* High Speed Bus clock */ +# define SCIF_GCCTRL_OSCSEL_PBACLK (9 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Peripheral Bus A clock */ +# define SCIF_GCCTRL_OSCSEL_PBBCLK (10 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Peripheral Bus B clock */ +# define SCIF_GCCTRL_OSCSEL_PBCCLK (11 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Peripheral Bus C clock */ +# define SCIF_GCCTRL_OSCSEL_PBDCLK (12 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Peripheral Bus D clock */ +# define SCIF_GCCTRL_OSCSEL_RC32K (13 << SCIF_GCCTRL_OSCSEL_SHIFT) /* Output from 32kHz RCOSC */ #define SCIF_GCCTRL_DIV_SHIFT (16) /* Bits 16-31: Division Factor */ #define SCIF_GCCTRL_DIV_MASK (0xffff << SCIF_GCCTRL_DIV_SHIFT) diff --git a/arch/arm/src/sam34/sam4l_clockconfig.c b/arch/arm/src/sam34/sam4l_clockconfig.c index 99025f55ef..20adad8c1a 100644 --- a/arch/arm/src/sam34/sam4l_clockconfig.c +++ b/arch/arm/src/sam34/sam4l_clockconfig.c @@ -62,133 +62,139 @@ * 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) */ +#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) */ /* Oscillator 0. This might be the system clock or the source clock for - * either PLL0 or DFPLL. + * either PLL0 or DFPLL. It might also be needed if OSC0 is the source + * clock for GCLK9. * * By selecting CONFIG_SAM_OSC0, you can also force the clock to be enabled * at boot time. */ #if defined(CONFIG_SAM_OSC0) || defined(BOARD_SYSCLK_SOURCE_OSC0) || \ - defined(BOARD_DFLL0_SOURCE_OSC0) || defined(BOARD_PLL0_SOURCE_OSC0) -# define NEED_OSC0 1 + defined(BOARD_DFLL0_SOURCE_OSC0) || defined(BOARD_PLL0_SOURCE_OSC0) || \ + defined(BOARD_GLCK9_SOURCE_OSC0) +# define NEED_OSC0 1 #endif #ifdef NEED_OSC0 # if !defined(BOARD_OSC0_STARTUP_US) # error BOARD_OSC0_STARTUP_US is not defined # elif BOARD_OSC0_STARTUP_US == 0 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_0 -# define OSC0_STARTUP_TIMEOUT 8 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_0 +# define SAM_OSC0_STARTUP_TIMEOUT 8 # elif BOARD_OSC0_STARTUP_US <= 557 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_64 -# define OSC0_STARTUP_TIMEOUT 80 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_64 +# define SAM_OSC0_STARTUP_TIMEOUT 80 # elif BOARD_OSC0_STARTUP_US <= 1100 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_128 -# define OSC0_STARTUP_TIMEOUT 160 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_128 +# define SAM_OSC0_STARTUP_TIMEOUT 160 # elif BOARD_OSC0_STARTUP_US <= 18000 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_2K -# define OSC0_STARTUP_TIMEOUT 2560 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_2K +# define SAM_OSC0_STARTUP_TIMEOUT 2560 # elif BOARD_OSC0_STARTUP_US <= 36000 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_4K -# define OSC0_STARTUP_TIMEOUT 5120 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_4K +# define SAM_OSC0_STARTUP_TIMEOUT 5120 # elif BOARD_OSC0_STARTUP_US <= 71000 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_8K -# define OSC0_STARTUP_TIMEOUT 10240 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_8K +# define SAM_OSC0_STARTUP_TIMEOUT 10240 # elif BOARD_OSC0_STARTUP_US <= 143000 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_16K -# define OSC0_STARTUP_TIMEOUT 20480 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_16K +# define SAM_OSC0_STARTUP_TIMEOUT 20480 # elif BOARD_OSC0_STARTUP_US <= 285000 -# define OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_32K -# define OSC0_STARTUP_TIMEOUT 40960 +# define SAM_OSC0_STARTUP_VALUE SCIF_OSCCTRL0_STARTUP_32K +# define SAM_OSC0_STARTUP_TIMEOUT 40960 # else # error BOARD_OSC0_STARTUP_US is out of range # endif # ifdef BOARD_OSC0_IS_XTAL -# define OSC0_MODE_VALUE SCIF_OSCCTRL0_MODE +# define SAM_OSC0_MODE_VALUE SCIF_OSCCTRL0_MODE # if BOARD_OSC0_FREQUENCY < 2000000 -# define OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(0) +# define SAM_OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(0) # elif BOARD_OSC0_FREQUENCY < 4000000 -# define OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(1) +# define SAM_OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(1) # elif BOARD_OSC0_FREQUENCY < 8000000 -# define OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(2) +# define SAM_OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(2) # elif BOARD_OSC0_FREQUENCY < 16000000 -# define OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(3) +# define SAM_OSC0_GAIN_VALUE SCIF_OSCCTRL0_GAIN(3) # else -# define OSC0_GAIN_VALUE ((0x1u << 4) | SCIF_OSCCTRL0_GAIN(0)) +# define SAM_OSC0_GAIN_VALUE ((0x1u << 4) | SCIF_OSCCTRL0_GAIN(0)) # endif # else -# define OSC0_MODE_VALUE 0 -# define OSC0_GAIN_VALUE 0 +# define SAM_OSC0_MODE_VALUE 0 +# define SAM_OSC0_GAIN_VALUE 0 # endif #endif -/* OSC32. The 32K oscillator may be the source clock for DFPLL0. +/* OSC32. The 32K oscillator may be the source clock for DFPLL0 or + * the source clock for GLK9 that might be used to driver PLL0. * * By selecting CONFIG_SAM_OSC32K, you can also force the clock to be * enabled at boot time. OSC32 may needed by other devices as well * (AST, WDT, PICUART, RTC). */ -#if defined(CONFIG_SAM_OSC32K) || defined(BOARD_DFLL0_SOURCE_OSC32K) -# define NEED_OSC32K 1 +#if defined(CONFIG_SAM_OSC32K) || defined(BOARD_DFLL0_SOURCE_OSC32K) || \ + defined(BOARD_GLCK9_SOURCE_OSC32K) +# define NEED_OSC32K 1 #endif #ifdef NEED_OSC32K # if !defined(BOARD_OSC32_STARTUP_US) # error BOARD_OSC32_STARTUP_US is not defined # elif BOARD_OSC32_STARTUP_US == 0 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_0 +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_0 # elif BOARD_OSC32_STARTUP_US <= 1100 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_128 +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_128 # elif BOARD_OSC32_STARTUP_US <= 72300 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_8K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_8K # elif BOARD_OSC32_STARTUP_US <= 143000 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_16K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_16K # elif BOARD_OSC32_STARTUP_US <= 570000 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_64K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_64K # elif BOARD_OSC32_STARTUP_US <= 1100000 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_128K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_128K # elif BOARD_OSC32_STARTUP_US <= 2300000 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_256K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_256K # elif BOARD_OSC32_STARTUP_US <= 4600000 -# define OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_512K +# define SAM_OSC32_STARTUP_VALUE BSCIF_OSCCTRL32_STARTUP_512K # else # error BOARD_OSC32_STARTUP_US is out of range # endif # ifdef BOARD_OSC32_IS_XTAL -# define OSC32_MODE_VALUE BSCIF_OSCCTRL32_MODE_XTAL +# define SAM_OSC32_MODE_VALUE SCIF_OSCCTRL32_MODE_XTAL # else -# define OSC32_MODE_VALUE BSCIF_OSCCTRL32_MODE_EXTCLK +# define SAM_OSC32_MODE_VALUE BSCIF_OSCCTRL32_MODE_EXTCLK # endif # ifndef BOARD_OSC32_SELCURR -# define BOARD_OSC32_SELCURR BSCIF_OSCCTRL32_SELCURR_300 +# define BOARD_OSC32_SELCURR BSCIF_OSCCTRL32_SELCURR_300 # endif #endif -/* RC80M. This might be the system clock or the source clock for the DFPLL. +/* RC80M. This might be the system clock or the source clock for the DFPLL + * or it could be the source for GCLK9 that drives PLL0. * * By selecting CONFIG_SAM_RC80M, you can also force the clock to be enabled * at boot time. */ #if defined(CONFIG_SAM_RC80M) || defined(BOARD_SYSCLK_SOURCE_RC80M) || \ - defined(BOARD_DFLL0_SOURCE_RC80M) -# define NEED_RC80M 1 + defined(BOARD_DFLL0_SOURCE_RC80M) || BOARD_GLCK9_SOURCE_RC80M +# define NEED_RC80M 1 #endif -/* RCFAST. The 12/8/4 fast RC oscillator may be used as the system clock. +/* RCFAST. The 12/8/4 fast RC oscillator may be used as the system clock + * or as the source for GLCK9 that drives PLL0. * If not then, it may be enabled by setting the CONFIG_SAM_RCFASTxM * configuration variable. */ @@ -204,49 +210,191 @@ # if defined(CONFIG_SAM_RCFAST8M) || defined(CONFIG_SAM_RCFAST4M) # error BOARD_SYSCLK_SOURCE_FCFAST12M inconsistent with CONFIG_SAM_RCFAST8/4M # endif -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_12MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_12MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST12M_FREQUENCY #elif defined(BOARD_SYSCLK_SOURCE_FCFAST8M) # if defined(CONFIG_SAM_RCFAST12M) || defined(CONFIG_SAM_RCFAST4M) # error BOARD_SYSCLK_SOURCE_FCFAST8M inconsistent with CONFIG_SAM_RCFAST12/4M # endif -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_8MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_8MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST8M_FREQUENCY #elif defined(BOARD_SYSCLK_SOURCE_FCFAST4M) # if defined(CONFIG_SAM_RCFAST12M) || defined(CONFIG_SAM_RCFAST8M) # error BOARD_SYSCLK_SOURCE_FCFAST4M inconsistent with CONFIG_SAM_RCFAST12/8M # endif -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_4MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_4MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST4M_FREQUENCY #elif defined(CONFIG_SAM_RCFAST12M) -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_12MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_12MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST12M_FREQUENCY #elif defined(CONFIG_SAM_RCFAST8M) -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_8MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_8MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST8M_FREQUENCY #elif defined(CONFIG_SAM_RCFAST4M) -# define NEED_RCFAST -# define RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_4MHZ +# define NEED_RCFAST 1 +# define SAM_RCFAST_RANGE SCIF_RCFASTCFG_FRANGE_4MHZ +# define SAM_RCFAST_FREQUENCY SAM_RCFAST4M_FREQUENCY #endif -/* RC1M. The 1M RC oscillator may be used as the system block. +/* RC1M. The 1M RC oscillator may be used as the system block or + * may be the source clock for GLCK9 that drives PLL0 * * By selecting CONFIG_SAM_RC1M, you can also force the clock to be * enabled at boot time. */ -#if defined(CONFIG_SAM_RC1M) || defined(BOARD_SYSCLK_SOURCE_RC1M) -# define NEED_RC1M 1 +#if defined(CONFIG_SAM_RC1M) || defined(BOARD_SYSCLK_SOURCE_RC1M) || \ + defined(BOARD_GLCK9_SOURCE_RC1M) +# define NEED_RC1M 1 #endif -/* RC32K. The 32KHz RC oscillator may be used as the input to DFLL0. +/* RC32K. The 32KHz RC oscillator may be used as the input to DFLL0 + * or as the input to GCLK9 that drives PLL0. * * By selecting CONFIG_SAM_RC32K, you can also force the clock to be * enabled at boot time. */ -#if defined(CONFIG_SAM_RC32K) || defined(BOARD_DFLL0_SOURCE_RC32K) -# define NEED_RC32K 1 +#if defined(CONFIG_SAM_RC32K) || defined(BOARD_DFLL0_SOURCE_RC32K) || \ + defined(BOARD_GLCK9_SOURCE_RC32K) +# define NEED_RC32K 1 +#endif + +/* GCLK9. May used as a source clock for PLL0 */ + +#ifdef BOARD_PLL0_SOURCE_GCLK9 +# define NEED_GLCK9 1 + +#ifdef NEED_GLCK9 +# if defined(BOARD_GLCK9_SOURCE_RCSYS) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_RCSYS +# define SAM_GCLK9_FREQUENCY SAM_RCSYS_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_OSC32K) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_OSC32K +# define SAM_GCLK9_FREQUENCY BOARD_OSC32_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_DFLL0) +# error BOARD_GLCK9_SOURCE_DFLL0 is not supported +# elif defined(BOARD_GLCK9_SOURCE_OSC0) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_OSC0 +# define SAM_GCLK9_FREQUENCY BOARD_OSC0_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_RC80M) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_RC80M +# define SAM_GCLK9_FREQUENCY SAM_RC80M_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_RCFAST) +# error BOARD_GLCK9_SOURCE_RCFAST is not supported (needs RCFAST configuration) +# elif defined(BOARD_GLCK9_SOURCE_RC1M) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_RC1M +# define SAM_GCLK9_FREQUENCY SAM_RCFAST_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_CPUCLK) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_CPUCLK +# define SAM_GCLK9_FREQUENCY BOARD_CPU_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_HSBCLK) +# error BOARD_GLCK9_SOURCE_HSBCLK is not supported (REVISIT) +# elif defined(BOARD_GLCK9_SOURCE_PBACLK) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_PBACLK +# define SAM_GCLK9_FREQUENCY BOARD_PBA_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_PBBCLK) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_PBBCLK +# define SAM_GCLK9_FREQUENCY BOARD_PBB_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_PBCCLK) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_PBCCLK +# define SAM_GCLK9_FREQUENCY BOARD_PBC_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_PBDCLK) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_PBDCLK +# define SAM_GCLK9_FREQUENCY BOARD_PBD_FREQUENCY +# elif defined(BOARD_GLCK9_SOURCE_RC32K) +# define SAM_GCLK9_SOURCE_VALUE SCIF_GCCTRL_OSCSEL_RC32K +# define SAM_GCLK9_FREQUENCY SAM_RC32K_FREQUENCY +# else +# error Missing GCLK9 source +# endif +#endif + +/* PLL0 */ + +#ifdef BOARD_SYSCLK_SOURCE_PLL0 +/* PLL0 source */ + +# if defined(BOARD_PLL0_SOURCE_OSC0) +# define SAM_PLL0_SOURCE SCIF_PLL0_PLLOSC_OSC0 +# define SAM_PLL0_SOURCE_FREQUENCY BOARD_OSC0_FREQUENCY +# elif defined(BOARD_PLL0_SOURCE_GCLK9) +# define SAM_PLL0_SOURCE SCIF_PLL0_PLLOSC_GCLK9 +# define SAM_PLL0_SOURCE_FREQUENCY SAM_GCLK9_FREQUENCY +# else +# error Missing PLL0 source +# endif + +/* PLL0 Multipler and Divider */ + +# if !defined(BOARD_PLL0_MUL) +# error BOARD_PLL0_MUL is not defined +# elif BOARD_PLL0_MUL <= 2 || BOARD_PLL0_MUL > 16 +# error BOARD_PLL0_MUL is out of range +# endif + +# if !defined(BOARD_PLL0_DIV) +# error BOARD_PLL0_DIV is not defined +# elif BOARD_PLL0_DIV < 1 || BOARD_PLL0_DIV > 15 +# error BOARD_PLL0_DIV is out of range +# endif + +/* PLL0 frequency ranges */ + +# define SAM_PLL0_MIN_FREQUENCY 40000000 +# define SAM_PLL0_MAX_FREQUENCY 240000000 + +/* PLL0 VCO frequency */ + +# define SAM_PLL0_VCO_DIV1_FREQUENCY \ + (SAM_PLL0_SOURCE_FREQUENCY * BOARD_PLL0_MUL / BOARD_PLL0_DIV) + +# if (SAM_PLL0_VCO_DIV1_FREQUENCY < SAM_PLL0_MIN_FREQUENCY) || \ + (SAM_PLL0_VCO_DIV1_FREQUENCY > SAM_PLL0_MAX_FREQUENCY) +# error PLL0 VCO frequency is out of range +# endif + +/* PLL0 Options: + * + * PLL0 supports an option to divide the frequency output by 2. We + * will do this division to bring the internal VCO frequency up to the + * minimum value + * + * PLL0 operates in two frequency ranges as determined by + * SCIF_PLL0_PLLOPT_FVO: + * + * 0: 80MHz < fvco < 180MHz + * 1: 160MHz < fvco < 240MHz + * + * Select the correct frequncy range using the recommended threshold + * value. + */ + +# if SAM_PLL0_VCO_DIV1_FREQUENCY < (2*SAM_PLL0_MIN_FREQUENCY) && BOARD_PLL0_MUL <= 8 +# define SAM_PLL0_VCO_FREQUENCY (2 * SAM_PLL0_VCO_DIV1_FREQUENCY) +# define SAM_PLL0_MUL (2 * BOARD_PLL0_MUL) + +# if SAM_PLL0_VCO_FREQUENCY > (SAM_PLL0_VCO_RANGE_THRESHOLD / 2) +# define SAM_PLL0_OPTIONS (SCIF_PLL0_PLLOPT_DIV2 | SCIF_PLL0_PLLOPT_FVO) +# else +# define SAM_PLL0_OPTIONS SCIF_PLL0_PLLOPT_DIV2 +# endif + +# else +# define SAM_PLL0_VCO_FREQUENCY SAM_PLL0_VCO_DIV1_FREQUENCY +# define SAM_PLL0_MUL BOARD_PLL0_MUL + +# if SAM_PLL0_VCO_FREQUENCY > SAM_PLL0_VCO_RANGE_THRESHOLD +# define SAM_PLL0_OPTIONS SCIF_PLL0_PLLOPT_FVO +# else +# define SAM_PLL0_OPTIONS 0 +# endif +# endif #endif /**************************************************************************** @@ -305,19 +453,15 @@ static inline void sam_picocache(void) #ifdef NEED_OSC0 static inline void sam_enableosc0(void) { - irqstate_t flags; uint32_t regval; - regval = OSC0_STARTUP_VALUE | OSC0_GAIN_VALUE | OSC0_MODE_VALUE | + /* Enable and configure OSC0 */ + + regval = SAM_OSC0_STARTUP_VALUE | SAM_OSC0_GAIN_VALUE | SAM_OSC0_MODE_VALUE | SCIF_OSCCTRL0_OSCEN; - - /* The following two statements must be atomic */ - - flags = irqsave(); putreg32(SCIF_UNLOCK_KEY(0xaa) | SCIF_UNLOCK_ADDR(SAM_SCIF_OSCCTRL0_OFFSET), SAM_SCIF_UNLOCK); putreg32(regval, SAM_SCIF_OSCCTRL0); - irqrestore(flags); /* Wait for OSC0 to be ready */ @@ -337,24 +481,19 @@ static inline void sam_enableosc0(void) #ifdef NEED_OSC32K static inline void sam_enableosc32(void) { - irqstate_t flags; uint32_t regval; /* Set up the OSCCTRL32 register using settings from the board.h file. * Also enable the oscillator and provide bother the 32KHz and 1KHz output. */ - regval = OSC32_STARTUP_VALUE | BOARD_OSC32_SELCURR | OSC32_MODE_VALUE | + regval = SAM_OSC32_STARTUP_VALUE | BOARD_OSC32_SELCURR | SAM_OSC32_MODE_VALUE | BSCIF_OSCCTRL32_EN1K | BSCIF_OSCCTRL32_EN32K | BSCIF_OSCCTRL32_OSC32EN; - /* The following two statements must be atomic */ - - flags = irqsave(); putreg32(BSCIF_UNLOCK_KEY(0xaa) | BSCIF_UNLOCK_ADDR(SAM_BSCIF_OSCCTRL32_OFFSET), SAM_BSCIF_UNLOCK); putreg32(regval, SAM_BSCIF_OSCCTRL32); - irqrestore(flags); /* Wait for OSC32 to be ready */ @@ -374,17 +513,14 @@ static inline void sam_enableosc32(void) #ifdef NEED_RC80M static inline void sam_enablerc80m(void) { - irqstate_t flags; uint32_t regval; - /* The following two statements must be atomic */ + /* Configure and enable RC80M */ - flags = irqsave(); regval = getreg32(SAM_SCIF_RC80MCR); putreg32(SCIF_UNLOCK_KEY(0xaa) | SCIF_UNLOCK_ADDR(SAM_SCIF_RC80MCR_OFFSET), SAM_SCIF_UNLOCK); putreg32(regval | SCIF_RC80MCR_EN, SAM_SCIF_RC80MCR); - irqrestore(flags); /* Wait for OSC32 to be ready */ @@ -404,20 +540,17 @@ static inline void sam_enablerc80m(void) #ifdef NEED_RCFAST static inline void sam_enablercfast(void) { - irqstate_t flags; uint32_t regval; - /* The following must be atomic */ + /* Configure and enable RCFAST */ - flags = irqsave(); regval = getreg32(SAM_SCIF_RCFASTCFG); regval &= ~SCIF_RCFASTCFG_FRANGE_MASK; - regval |= (RCFAST_RANGE | SCIF_RCFASTCFG_EN); + regval |= (SAM_RCFAST_RANGE | SCIF_RCFASTCFG_EN); putreg32(SCIF_UNLOCK_KEY(0xaa) | SCIF_UNLOCK_ADDR(SAM_SCIF_RCFASTCFG_OFFSET), SAM_SCIF_UNLOCK); putreg32(regval, SAM_SCIF_RCFASTCFG); - irqrestore(flags); /* Wait for RCFAST to be ready */ @@ -437,20 +570,17 @@ static inline void sam_enablercfast(void) #ifdef NEED_RC1M static inline void sam_enablerc1m(void) { - irqstate_t flags; uint32_t regval; - /* The following must be atomic */ + /* Configure and enable RC1M */ - flags = irqsave(); regval = getreg32(SAM_BSCIF_RC1MCR); regval &= ~BSCIF_RCFASTCFG_FRANGE_MASK; - regval |= (RCFAST_RANGE | BSCIF_RCFASTCFG_EN); + regval |= (SAM_RCFAST_RANGE | BSCIF_RCFASTCFG_EN); putreg32(BSCIF_UNLOCK_KEY(0xaa) | BSCIF_UNLOCK_ADDR(SAM_BSCIF_RC1MCR_OFFSET), SAM_BSCIF_UNLOCK); putreg32(regval | BSCIF_RC1MCR_CLKOEN, SAM_BSCIF_RC1MCR); - irqrestore(flags); /* Wait for RCFAST to be ready */ @@ -468,19 +598,16 @@ static inline void sam_enablerc1m(void) ****************************************************************************/ #ifdef NEED_RC32K -void sam_enablerc32k(void) +static inline void sam_enablerc32k(void) { - irqstate_t flags; uint32_t regval; - /* The following must be atomic */ + /* Configure and enable RC32K */ - flags = irqsave(); regval = getreg32(SAM_BSCIF_RC32KCR); putreg32(BSCIF_UNLOCK_KEY(0xaa) | BSCIF_UNLOCK_ADDR(SAM_BSCIF_RC32KCR_OFFSET), SAM_BSCIF_UNLOCK); putreg32(regval | BSCIF_RC32KCR_EN32K | BSCIF_RC32KCR_EN, SAM_BSCIF_RC32KCR); - irqrestore(flags); /* Wait for RCFAST to be ready */ @@ -488,6 +615,26 @@ void sam_enablerc32k(void) } #endif +/**************************************************************************** + * Name: sam_enableglck9 + * + * Description: + * Enable GLCK9. + * + ****************************************************************************/ + +#ifdef NEED_GLCK9 +static inline void sam_enableglck9(void) +{ + /* Enable the generic clock using the source specified in the board.h + * file. No division is used so that the GCLK9 frequency is the same + * as the source frequency. + */ + + putreg32(SAM_GCLK9_SOURCE_VALUE | SCIF_GCCTRL_CEN, SAM_SCIF_GCCTRL9); +} +#endif + /**************************************************************************** * Name: sam_enablepll0 * @@ -497,94 +644,47 @@ void sam_enablerc32k(void) ****************************************************************************/ #ifdef SAM_CLOCK_PLL0 +static inline void sam_pll0putreg(uint32_t regval, uint32_t regaddr, + uint32_t regoffset) +{ + putreg32(SCIF_UNLOCK_KEY(0xaa) | SCIF_UNLOCK_ADDR(regoffset), + SAM_SCIF_UNLOCK); + putreg32(regval, regaddr); +} + static inline void sam_enablepll0(void) { - /* Setup PLL0 */ + uint32_t regval; - regval = (SAM_PLL0_DIV << PM_PLL_PLLDIV_SHIFT) | (SAM_PLL0_MUL << PM_PLL_PLLMUL_SHIFT) | (16 << PM_PLL_PLLCOUNT_SHIFT) + /* Clear the PLL0 control register */ - /* Select PLL0/1 oscillator */ + sam_pll0putreg(0, SAM_SCIF_PLL0, SAM_SCIF_PLL0_OFFSET); -#if SAM_CLOCK_PLL_OSC1 - regval |= PM_PLL_PLLOSC; -#endif + /* Write the selected options */ - putreg32(regval, SAM_PM_PLL0); + regval = getreg32(SAM_SCIF_PLL0); + regval &= SCIF_PLL0_PLLOPT_MASK; + regval |= SAM_PLL0_OPTIONS; + sam_pll0putreg(regval, SAM_SCIF_PLL0, SAM_SCIF_PLL0_OFFSET); - /* Set PLL0 options */ + /* Set up the multiers and dividers */ - regval = getreg32(SAM_PM_PLL0); - regval &= ~PM_PLL_PLLOPT_MASK -#if SAM_PLL0_FREQ < 160000000 - regval |= PM_PLL_PLLOPT_VCO; -#endif -#if SAM_PLL0_DIV2 != 0 - regval |= PM_PLL_PLLOPT_XTRADIV; -#endif -#if SAM_PLL0_WBWM != 0 - regval |= PM_PLL_PLLOPT_WBWDIS; -#endif - putreg32(regval, SAM_PM_PLL0) + regval = getreg32(SAM_SCIF_PLL0); + regval &= ~(SCIF_PLL0_PLLOSC_MASK | SCIF_PLL0_PLLDIV_MASK | SCIF_PLL0_PLLMUL_MASK); + regval |= ((SAM_PLL0_MUL - 1) << SCIF_PLL0_PLLMUL_SHIFT) | + (BOARD_FDLL0_DIV << SCIF_PLL0_PLLDIV_SHIFT) | + SCIF_PLL0_PLLCOUNT_MAX | SAM_PLL0_SOURCE; + sam_pll0putreg(regval, SAM_SCIF_PLL0, SAM_SCIF_PLL0_OFFSET); - /* Enable PLL0 */ + /* And, finally, enable PLL0 */ - regval = getreg32(SAM_PM_PLL0); - regval |= PM_PLL_PLLEN; - putreg32(regval, SAM_PM_PLL0) + regval = getreg32(SAM_SCIF_PLL0); + regval |= SCIF_PLL_PLLEN; + sam_pll0putreg(regval, SAM_SCIF_PLL0, SAM_SCIF_PLL0_OFFSET); - /* Wait for PLL0 locked. */ + /* Wait for PLL0 to become locked */ - while ((getreg32(SAM_PM_POSCSR) & PM_POSCSR_LOCK0) == 0); -} -#endif - -/**************************************************************************** - * Name: sam_enablepll1 - * - * Description: - * Initialiaze PLL1 settings per the definitions in the board.h file. - * - ****************************************************************************/ - -#ifdef SAM_CLOCK_PLL1 -static inline void sam_enablepll1(void) -{ - /* Setup PLL1 */ - - regval = (SAM_PLL1_DIV << PM_PLL_PLLDIV_SHIFT) | (SAM_PLL1_MUL << PM_PLL_PLLMUL_SHIFT) | (16 << PM_PLL_PLLCOUNT_SHIFT) - - /* Select PLL0/1 oscillator */ - -#if SAM_CLOCK_PLL_OSC1 - regval |= PM_PLL_PLLOSC; -#endif - - putreg32(regval, SAM_PM_PLL1); - - /* Set PLL1 options */ - - regval = getreg32(SAM_PM_PLL1); - regval &= ~PM_PLL_PLLOPT_MASK -#if SAM_PLL1_FREQ < 160000000 - regval |= PM_PLL_PLLOPT_VCO; -#endif -#if SAM_PLL1_DIV2 != 0 - regval |= PM_PLL_PLLOPT_XTRADIV; -#endif -#if SAM_PLL1_WBWM != 0 - regval |= PM_PLL_PLLOPT_WBWDIS; -#endif - putreg32(regval, SAM_PM_PLL1) - - /* Enable PLL1 */ - - regval = getreg32(SAM_PM_PLL1); - regval |= PM_PLL_PLLEN; - putreg32(regval, SAM_PM_PLL1) - - /* Wait for PLL1 locked. */ - - while ((getreg32(SAM_PM_POSCSR) & PM_POSCSR_LOCK1) == 0); + while ((getreg32(SAM_SCIF_PCLKSR) & SCIF_INT_PLL0LOCK) == 0); } #endif @@ -596,49 +696,47 @@ static inline void sam_enablepll1(void) * ****************************************************************************/ -static inline void sam_setdividers(uint32_t cpudiv, uint32_t pbadiv, - uint32_t pbbdiv, uint32_t pbcdiv, - uint32_t pbddiv) +static inline void sam_setdividers(void) { - irqstate_t flags; - uint32_t cpusel = 0; - uint32_t pbasel = 0; - uint32_t pbbsel = 0; - uint32_t pbcsel = 0; - uint32_t pbdsel = 0; + uint32_t cpusel; + uint32_t pbasel; + uint32_t pbbsel; + uint32_t pbcsel; + uint32_t pbdsel; /* Get the register setting for each divider value */ - if (cpudiv > 0) - { - cpusel = (PM_CPUSEL(cpudiv - 1)) | PM_CPUSEL_DIV; - } +#if BOARD_CPU_SHIFT > 0 + cpusel = (PM_CPUSEL(BOARD_CPU_SHIFT - 1)) | PM_CPUSEL_DIV; +#else + cpusel = 0; +#endif - if (pbadiv > 0) - { - pbasel = (PM_PBSEL(pbadiv - 1)) | PM_PBSEL_DIV; - } +#if BOARD_PBA_SHIFT > 0 + pbasel = (PM_PBSEL(BOARD_PBA_SHIFT - 1)) | PM_PBSEL_DIV; +#else + pbasel = 0; +#endif - if (pbbdiv > 0) - { - pbbsel = (PM_PBSEL(pbbdiv - 1)) | PM_PBSEL_DIV; - } +#if BOARD_PBB_SHIFT >0 + pbbsel = (PM_PBSEL(BOARD_PBB_SHIFT - 1)) | PM_PBSEL_DIV; +#else + pbbsel = 0; +#endif - if (pbcdiv > 0) - { - pbcsel = (PM_PBSEL(pbcdiv - 1)) | PM_PBSEL_DIV; - } +#if BOARD_PBC_SHIFT > 0 + pbcsel = (PM_PBSEL(BOARD_PBC_SHIFT - 1)) | PM_PBSEL_DIV; +#else + pbcsel = 0; +#endif - if (pbddiv > 0) - { - pbdsel = (PM_PBSEL(pbddiv - 1)) | PM_PBSEL_DIV; - } +#if BOARD_PBD_SHIFT > 0 + pbdsel = (PM_PBSEL(BOARD_PBD_SHIFT - 1)) | PM_PBSEL_DIV; +#else + pbdsel = 0; +#endif - /* Then set the divider values. The following operations need to be atomic - * for the unlock-write sequeuences. - */ - - flags = irqsave(); + /* Then set the divider values. */ putreg32(PM_UNLOCK_KEY(0xaa) | PM_UNLOCK_ADDR(SAM_PM_CPUSEL_OFFSET), SAM_PM_UNLOCK); putreg32(cpusel, SAM_PM_CPUSEL); @@ -654,8 +752,6 @@ static inline void sam_setdividers(uint32_t cpudiv, uint32_t pbadiv, putreg32(PM_UNLOCK_KEY(0xaa) | PM_UNLOCK_ADDR(SAM_PM_PBDSEL_OFFSET), SAM_PM_UNLOCK); putreg32(pbdsel, SAM_PM_PBDSEL); - - irqrestore(flags); } /**************************************************************************** @@ -764,9 +860,7 @@ void sam_clockconfig(void) * be provided in the board.h header file. */ - sam_setdividers(BOARD_CPU_SHIFT, BOARD_PBA_SHIFT, BOARD_PBB_SHIFT, - BOARD_PBC_SHIFT, BOARD_PBD_SHIFT); - + sam_setdividers(); /* Select a power scaling mode and possible fast wakeup so that we get the * best possible flash performance. The following table shows the maximum @@ -864,8 +958,11 @@ void sam_clockconfig(void) sam_enablerc32k(); #endif - /* Enable the PLL or FDLL */ -#warning Missing Logic +#ifdef NEED_GLCK9 + /* Enable the GLCK9 */ + + sam_enableglck9(); +#endif /* Switch to the system clock selected by the settings in the board.h * header file. @@ -875,9 +972,8 @@ void sam_clockconfig(void) /* Since this function only executes at power up, we know that we are * already running from RCSYS. */ -#endif +#elif defined(BOARD_SYSCLK_SOURCE_OSC0) -#ifdef NEED_OSC0 /* Set up FLASH wait states */ sam_fws(SAM_FOSC0); @@ -885,9 +981,9 @@ void sam_clockconfig(void) /* Then switch the main clock to OSC0 */ sam_mainclk(PM_MCCTRL_MCSEL_OSC0); -#endif -#ifdef SAM_CLOCK_PLL0 +#elif defined(BOARD_SYSCLK_SOURCE_PLL0) + /* Enable PLL0 using the settings in board.h */ sam_enablepll0(); @@ -899,16 +995,20 @@ void sam_clockconfig(void) /* Then switch the main clock to PLL0 */ sam_mainclk(PM_MCCTRL_MCSEL_PLL0); + +#elif defined(BOARD_SYSCLK_SOURCE_DFLL0) +# error Missing logic +#elif defined(BOARD_SYSCLK_SOURCE_RC80M) +# error Missing logic +#elif defined(BOARD_SYSCLK_SOURCE_FCFAST12M) || defined(BOARD_SYSCLK_SOURCE_FCFAST8M) || \ + defined(BOARD_SYSCLK_SOURCE_FCFAST4M) +# error Missing logic +#elif defined(BOARD_SYSCLK_SOURCE_RC1M) +# error Missing logic +#else +# error "No SYSCLK source frequency" #endif -#ifdef SAM_CLOCK_PLL1 - /* Enable PLL1 using the settings in board.h */ - - sam_enablepll1(); -#endif - - /* Set up the USBB GCLK */ - #ifdef CONFIG_USBDEV void sam_usbclock(); #endif