diff --git a/arch/arm/src/samd5e5/Kconfig b/arch/arm/src/samd5e5/Kconfig index ebb870cde24..339f49549c5 100644 --- a/arch/arm/src/samd5e5/Kconfig +++ b/arch/arm/src/samd5e5/Kconfig @@ -474,20 +474,6 @@ config SAMD5E5_DMAC_NDESC Each additional DMA descriptor will require 16-bytes for LPRAM memory. -config SAMD5E5_EIC_CLKGEN - int "EIC Clock Generator" - default 2 - range 0 11 - ---help--- - Some optional functions need a peripheral clock, which can either be - a generic clock (GCLK_EIC, for wider frequency selection) or a Ultra - Low Power 32KHz clock (CLK_ULP32K, for highest power efficiency). One - of the clock sources must be configured and enabled before using the - peripheral. - - This option assumes that GCLK will be used and provides the GCL - number to be used - choice prompt "SERCOM0 mode" default SAMD5E5_SERCOM0_ISUSART diff --git a/arch/arm/src/samd5e5/Make.defs b/arch/arm/src/samd5e5/Make.defs index c40c02379fe..2069522f7c8 100644 --- a/arch/arm/src/samd5e5/Make.defs +++ b/arch/arm/src/samd5e5/Make.defs @@ -87,11 +87,8 @@ endif # Required SAMD5x/E5x files CHIP_ASRCS = -# REVISIT: sam_clockconfig.c and sam_eic.c -#CHIP_CSRCS = sam_clockconfig.c sam_cmcc.c sam_gclk.c sam_irq.c -CHIP_CSRCS = sam_cmcc.c sam_gclk.c sam_irq.c -CHIP_CSRCS += sam_lowputc.c sam_port.c sam_serial.c sam_start.c -CHIP_CSRCS += sam_supc.c sam_usart.c +CHIP_CSRCS = sam_clockconfig.c sam_cmcc.c sam_eic.c sam_gclk.c sam_irq.c +CHIP_CSRCS += sam_lowputc.c sam_port.c sam_serial.c sam_start.c sam_usart.c # Configuration-dependent SAMD5x/E5x files diff --git a/arch/arm/src/samd5e5/chip/sam_eic.h b/arch/arm/src/samd5e5/chip/sam_eic.h index 3ba51067755..5fce8fb2250 100644 --- a/arch/arm/src/samd5e5/chip/sam_eic.h +++ b/arch/arm/src/samd5e5/chip/sam_eic.h @@ -145,12 +145,12 @@ #define EIC_CONFIG0_FILTEN(n) (3 + ((n) << 2)) /* Filter n enable, n=0-7 */ #define EIC_CONFIG0_SENSE_SHIFT(n) ((n) << 2) /* Filter n input sense, n=0-7 */ #define EIC_CONFIG0_SENSE_MASK(n) (7 << EIC_CONFIG0_SENSE_SHIFT(n)) -# define EIC_CONFIG0_SENSE_NONE (0 << EIC_CONFIG0_SENSE_SHIFT(n)) /* No detection */ -# define EIC_CONFIG0_SENSE_RISE (1 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Rising edge detection */ -# define EIC_CONFIG0_SENSE_FALL (2 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Falling edge detection */ -# define EIC_CONFIG0_SENSE_BOTH (3 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Both edge detection */ -# define EIC_CONFIG0_SENSE_HIGH (4 << EIC_CONFIG0_SENSE_SHIFT(n)) /* High level detection */ -# define EIC_CONFIG0_SENSE_LOW (5 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Low level detection */ +# define EIC_CONFIG0_SENSE_NONE(n) (0 << EIC_CONFIG0_SENSE_SHIFT(n)) /* No detection */ +# define EIC_CONFIG0_SENSE_RISE(n) (1 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Rising edge detection */ +# define EIC_CONFIG0_SENSE_FALL(n) (2 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Falling edge detection */ +# define EIC_CONFIG0_SENSE_BOTH(n) (3 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Both edge detection */ +# define EIC_CONFIG0_SENSE_HIGH(n) (4 << EIC_CONFIG0_SENSE_SHIFT(n)) /* High level detection */ +# define EIC_CONFIG0_SENSE_LOW(n) (5 << EIC_CONFIG0_SENSE_SHIFT(n)) /* Low level detection */ /* Configuration 1 register */ diff --git a/arch/arm/src/samd5e5/chip/sam_gclk.h b/arch/arm/src/samd5e5/chip/sam_gclk.h index 6be4ae75231..1a37fc5da45 100644 --- a/arch/arm/src/samd5e5/chip/sam_gclk.h +++ b/arch/arm/src/samd5e5/chip/sam_gclk.h @@ -47,6 +47,10 @@ /******************************************************************************************** * Pre-processor Definitions ********************************************************************************************/ + +#define SAM_NGLCK 12 /* 12 Clock generators, 0-11 */ +#define SAM_NCHANNELS 48 /* 48 Clock generators, 0..47 */ + /* GCLK register offsets ********************************************************************/ #define SAM_GCLK_CTRLA_OFFSET 0x0000 /* Control register */ @@ -61,7 +65,7 @@ #define SAM_GCLK_SYNCHBUSY (SAM_GCLK_BASE + SAM_GCLK_SYNCHBUSY_OFFSET) #define SAM_GCLK_GENCTRL(n) (SAM_GCLK_BASE + SAM_GCLK_GENCTRL_OFFSET(n)) -#define SAM_GCLK_PCHCTRL(m) (SAM_GCLK_BASE + SAM_GCLK_PCHCTRL_OFFSET(m)) +#define SAM_GCLK_PCHCTRL(n) (SAM_GCLK_BASE + SAM_GCLK_PCHCTRL_OFFSET(n)) /* GCLK register bit definitions ************************************************************/ @@ -84,11 +88,13 @@ # define GCLK_SYNCHBUSY_GENCTRL8 (1 << 10) /* Bit 10: Generator control 8 busy */ # define GCLK_SYNCHBUSY_GENCTRL9 (1 << 11) /* Bit 11: Generator control 9 busy */ # define GCLK_SYNCHBUSY_GENCTRL10 (1 << 12) /* Bit 12: Generator control 10 busy */ +# define GCLK_SYNCHBUSY_GENCTRL11 (1 << 13) /* Bit 13: Generator control 11 busy */ /* General clock generator n */ #define GCLK_GENCTRL_SRC_SHIFT (0) /* Bits 0-4: Generator source selection */ #define GCLK_GENCTRL_SRC_MASK (31 << GCLK_GENCTRL_SRC_SHIFT) +# define GCLK_GENCTRL_SRC(n) ((uint32_t)(n) << GCLK_GENCTRL_SRC_SHIFT) # define GCLK_GENCTRL_SRC_XOSC0 (0 << GCLK_GENCTRL_SRC_SHIFT) /* XOSC 0 oscillator input */ # define GCLK_GENCTRL_SRC_XOSC1 (1 << GCLK_GENCTRL_SRC_SHIFT) /* XOSC 1 oscillator input */ # define GCLK_GENCTRL_SRC_GCLK_IN (2 << GCLK_GENCTRL_SRC_SHIFT) /* Generator input pad */ diff --git a/arch/arm/src/samd5e5/chip/sam_osc32kctrl.h b/arch/arm/src/samd5e5/chip/sam_osc32kctrl.h index 1abb6e0b355..2ae23569cbc 100644 --- a/arch/arm/src/samd5e5/chip/sam_osc32kctrl.h +++ b/arch/arm/src/samd5e5/chip/sam_osc32kctrl.h @@ -88,6 +88,7 @@ #define OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT (0) /* Bits 0-2: RTC clock source selection */ #define OSC32KCTRL_RTCCTRL_RTCSEL_MASK (7 << OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT) +# define OSC32KCTRL_RTCCTRL_RTCSEL(n) ((uint8_t)(n) << OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT) # define OSC32KCTRL_RTCCTRL_RTCSEL_ULP1K (0 << OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT) /* 1.024KHz from 32HKz internal ULP oscillator */ # define OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K (1 << OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT) /* 32.768KHz from 32KHz internal ULP oscillator */ # define OSC32KCTRL_RTCCTRL_RTCSEL_XOSC1K (4 << OSC32KCTRL_RTCCTRL_RTCSEL_SHIFT) /* 1.024kHz from 32KHz external oscillator */ diff --git a/arch/arm/src/samd5e5/chip/sam_oscctrl.h b/arch/arm/src/samd5e5/chip/sam_oscctrl.h index f5349ad2f1d..18fdb60835b 100644 --- a/arch/arm/src/samd5e5/chip/sam_oscctrl.h +++ b/arch/arm/src/samd5e5/chip/sam_oscctrl.h @@ -168,6 +168,9 @@ # define OSCCTRL_XOSCCTRL_STARTUP_250MS (13 << OSCCTRL_XOSCCTRL_STARTUP_SHIFT) /* 250000µs */ # define OSCCTRL_XOSCCTRL_STARTUP_500MS (14 << OSCCTRL_XOSCCTRL_STARTUP_SHIFT) /* 500000µs */ # define OSCCTRL_XOSCCTRL_STARTUP_1S (15 << OSCCTRL_XOSCCTRL_STARTUP_SHIFT) /* 1000000µs */ +#define OSCCTRL_XOSCCTRL_CFDPRESC_SHIFT (24) /* Bits 24-27: Clock Failure Detector Prescaler */ +#define OSCCTRL_XOSCCTRL_CFDPRESC_MASK (15 << OSCCTRL_XOSCCTRL_CFDPRESC_SHIFT) +# define OSCCTRL_XOSCCTRL_CFDPRESC(n) ((uint32_t)(n) << OSCCTRL_XOSCCTRL_CFDPRESC_SHIFT) /* DFLL48M control register A */ diff --git a/arch/arm/src/samd5e5/chip/sam_pinmap.h b/arch/arm/src/samd5e5/chip/sam_pinmap.h index ef034711f01..7bdc469634f 100644 --- a/arch/arm/src/samd5e5/chip/sam_pinmap.h +++ b/arch/arm/src/samd5e5/chip/sam_pinmap.h @@ -33,8 +33,8 @@ * ************************************************************************************/ -#ifndef __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_MEMORYMAP_H -#define __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_MEMORYMAP_H +#ifndef __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H +#define __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H /************************************************************************************ * Included Files @@ -43,10 +43,9 @@ #include #if defined(CONFIG_ARCH_CHIP_SAMD5X) || defined(ARCH_CHIP_SAME5X) -# include "chip/samd5e5_memorymap.h" +# include "chip/samd5e5_pinmap.h" #else # error "Unsupported SAMD5/E5 family" #endif -#endif /* __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_MEMORYMAP_H */ - +#endif /* __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H */ diff --git a/arch/arm/src/samd5e5/chip/samd5e5_pinmap.h b/arch/arm/src/samd5e5/chip/samd5e5_pinmap.h index 2abdb694d24..f4d75df4517 100644 --- a/arch/arm/src/samd5e5/chip/samd5e5_pinmap.h +++ b/arch/arm/src/samd5e5/chip/samd5e5_pinmap.h @@ -33,8 +33,8 @@ * ********************************************************************************************/ -#ifndef __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H -#define __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H +#ifndef __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD5E5_PINMAP_H +#define __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD5E5_PINMAP_H /******************************************************************************************** * Included Files @@ -787,4 +787,4 @@ * Public Functions ********************************************************************************************/ -#endif /* __ARCH_ARM_SRC_SAMD5E5_CHIP_SAM_PINMAP_H */ +#endif /* __ARCH_ARM_SRC_SAMD5E5_CHIP_SAMD5E5_PINMAP_H */ diff --git a/arch/arm/src/samd5e5/sam_clockconfig.c b/arch/arm/src/samd5e5/sam_clockconfig.c index c6bdcd281f1..ea2d2ae94c2 100644 --- a/arch/arm/src/samd5e5/sam_clockconfig.c +++ b/arch/arm/src/samd5e5/sam_clockconfig.c @@ -53,255 +53,207 @@ #include "chip/sam_nvmctrl.h" #include "sam_gclk.h" -#include - #include "sam_periphclks.h" -#include "sam_clockconfig.h" + +#include /* Normally must be included last */ +#include "sam_clockconfig.h" /* Needs to be included after board.h */ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* BOARD_GCLK_ENABLE looks optional, but it is not */ - -#ifndef BOARD_GCLK_ENABLE -# warning BOARD_GCLK_ENABLE must be defined -# define BOARD_GCLK_ENABLE 1 -#endif - -/* Force enabling of the FDPLL reference clock */ - -#ifdef BOARD_FDPLL96M_ENABLE -# if BOARD_FDPLL96M_REFCLK == OSCCTRL_DPLLCTRLB_REFLCK_XOSC && \ - !defined(BOARD_XOSC_ENABLE) -# warning Forcing BOARD_XOSC_ENABLE for FDPLL96M -# define BOARD_XOSC_ENABLE 1 -# elif BOARD_FDPLL96M_REFCLK == OSCCTRL_DPLLCTRLB_REFLCK_XOSCK32K && \ - !defined(BOARD_XOSC32K_ENABLE) -# warning Forcing BOARD_XOSC32K_ENABLE for FDPLL96M -# define BOARD_XOSC32K_ENABLE 1 -# elif BOARD_FDPLL96M_REFCLK == OSCCTRL_DPLLCTRLB_REFLCK_GLCK && \ - !defined(BOARD_GCLK_ENABLE) -# warning Forcing BOARD_GCLK_ENABLE for FDPLL96M -# define BOARD_GCLK_ENABLE 1 -# endif -#endif - /**************************************************************************** * Private Types ****************************************************************************/ -/**************************************************************************** - * Private Function Prototypes - ****************************************************************************/ - -static inline void sam_flash_waitstates(void); -static void sam_performance_level(uint8_t level); -#ifdef BOARD_XOSC_ENABLE -static inline void sam_xosc_config(void); -#endif -#ifdef BOARD_XOSC32K_ENABLE -static inline void sam_xosc32k_config(void); -#endif -#ifdef BOARD_OSC32K_ENABLE -static inline void sam_osc32k_config(void); -#endif -static inline void sam_osc16m_config(void); -#ifdef BOARD_DFLL48M_ENABLE -static inline void sam_dfll48m_config(void); -static inline void sam_dfll48m_enable(void); -#endif -#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL48M_ENABLE) && \ - !defined(BOARD_DFLL48M_OPENLOOP) -static inline void sam_dfll48m_refclk(void); -#endif -#ifdef BOARD_FDPLL96M_ENABLE -static inline void sam_fdpll96m_config(void); -static inline void sam_fdpll96m_refclk(void); -#endif -#ifdef BOARD_GCLK_ENABLE -static inline void sam_config_gclks(void); -#endif -static inline void sam_cpu_dividers(void); -static inline void sam_periph_clocks(void); - /**************************************************************************** * Private Data ****************************************************************************/ -/* This structure describes the configuration of every enabled GCLK */ +/* This is the currently configured CPU frequency */ -#ifdef BOARD_GCLK_ENABLE -static const struct sam_gclkconfig_s g_gclkconfig[] = +static uint32_t g_cpu_frequency; + +/* This describes the power-up clock configuration using data provided in the + * board.h header file. + */ + +static const struct sam_clockconfig_s g_initial_clocking = { - /* GCLK generator 0 (Main Clock) */ - - { - .gclk = 0, -#ifdef BOARD_GCLK0_RUN_IN_STANDBY - .runstandby = true, + .waitstates = BOARD_FLASH_WAITSTATES, + .cpudiv = BOARD_MCLK_CPUDIV, + .glckset1 = BOARD_GCLK_SET1, + .glckset2 = BOARD_GCLK_SET2, + .cpu_frequency = BOARD_CPU_FREQUENCY, +#if BOARD_HAVE_XOSC32K != 0 + .xosc32k = + { + .enable = BOARD_XOSC32K_ENABLE, + .highspeed = BOARD_XOSC32K_HIGHSPEED, + .extalen = BOARD_XOSC32K_XTALEN, + .en32k = BOARD_XOSC32K_EN32K, + .en1k = BOARD_XOSC32K_EN1K, + .runstdby = BOARD_XOSC32K_RUNSTDBY, + .ondemand = BOARD_XOSC32K_ONDEMAND, + .cfden = BOARD_XOSC32K_CFDEN, + .cfdeo = BOARD_XOSC32K_CFDEO, + .caliben = BOARD_XOSC32K_CALIBEN, + .startup = BOARD_XOSC32K_STARTUP, + .calib = BOARD_XOSC32K_CALIB, + .rtcsel = BOARD_XOSC32K_RTCSEL, + }, #endif -#ifdef BOARD_GCLK0_OUTPUT_ENABLE - .output = true, +#if BOARD_HAVE_XOSC0 != 0 + .xosc0 = + { + .enable = BOARD_XOSC0_ENABLE, + .extalen = BOARD_XOSC0_XTALEN, + .runstdby = BOARD_XOSC0_RUNSTDBY, + .ondemand = BOARD_XOSC0_ONDEMAND, + .lowgain = BOARD_XOSC0_LOWGAIN, + .enalc = BOARD_XOSC0_ENALC, + .cfden = BOARD_XOSC0_CFDEN, + .startup = BOARD_XOSC0_STARTUP, + .xosc_frequency = BOARD_XOSC0_FREQUENCY, + }, #endif - .prescaler = BOARD_GCLK0_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK0_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } - - /* GCLK generator 1 */ - -#ifdef BOARD_GCLK1_ENABLE - , - { - .gclk = 1, -#ifdef BOARD_GCLK1_RUN_IN_STANDBY - .runstandby = true; +#if BOARD_HAVE_XOSC1 != 0 + .xosc1 = + { + .enable = BOARD_XOSC1_ENABLE, + .extalen = BOARD_XOSC1_XTALEN, + .runstdby = BOARD_XOSC1_RUNSTDBY, + .ondemand = BOARD_XOSC1_ONDEMAND, + .lowgain = BOARD_XOSC1_LOWGAIN, + .enalc = BOARD_XOSC1_ENALC, + .cfden = BOARD_XOSC1_CFDEN, + .startup = BOARD_XOSC1_STARTUP, + .xosc_frequency = BOARD_XOSC1_FREQUENCY, + }, #endif -#ifdef BOARD_GCLK1_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK1_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK1_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 2 (RTC) */ - -#ifdef BOARD_GCLK2_ENABLE - , - { - .gclk = 2, -#ifdef BOARD_GCLK2_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK2_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK2_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK2_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 3 */ - -#ifdef BOARD_GCLK3_ENABLE - , - { - .gclk = 3, -#ifdef BOARD_GCLK3_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK3_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK3_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK3_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 4 */ - -#ifdef BOARD_GCLK4_ENABLE - , - { - .gclk = 4, -#ifdef BOARD_GCLK4_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK4_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK4_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK4_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 5 */ - -#ifdef BOARD_GCLK5_ENABLE - , - { - .gclk = 5, -#ifdef BOARD_GCLK5_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK5_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK5_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK5_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 6 */ - -#ifdef BOARD_GCLK6_ENABLE - , - { - .gclk = 6, -#ifdef BOARD_GCLK6_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK6_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK6_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK6_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 7 */ - -#ifdef BOARD_GCLK7_ENABLE - , - { - .gclk = 7, -#ifdef BOARD_GCLK7_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK7_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK7_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK7_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif - - /* GCLK generator 8 */ - -#ifdef BOARD_GCLK8_ENABLE - , - { - .gclk = 8, -#ifdef BOARD_GCLK8_RUN_IN_STANDBY - .runstandby = true; -#endif -#ifdef BOARD_GCLK8_OUTPUT_ENABLE - .output = true; -#endif - .prescaler = BOARD_GCLK8_PRESCALER, - .clksrc = (uint8_t)(BOARD_GCLK8_CLOCK_SOURCE >> GCLK_GENCTRL_SRC_SHIFT), - } -#endif -}; - -#define NGCLKS_ENABLED (sizeof(g_gclkconfig) / sizeof(struct sam_gclkconfig_s)) -#endif - -/* These are temporary GLCK0 configuration that may be needed at power up */ - -static const struct sam_gclkconfig_s g_gclk0_default = -{ - .gclk = 0, - .prescaler = 1, - .clksrc = (uint8_t)(GCLK_GENCTRL_SRC_OSC16M >> GCLK_GENCTRL_SRC_SHIFT), -}; - -static const struct sam_gclkconfig_s g_gclk0_ulp32kconfig = -{ - .gclk = 0, - .prescaler = 1, - .clksrc = (uint8_t)(GCLK_GENCTRL_SRC_OSCULP32K >> GCLK_GENCTRL_SRC_SHIFT), + .gclk = + { + { + .enable = BOARD_GCLK0_ENABLE, + .idc = BOARD_GCLK0_IDC, + .oov = BOARD_GCLK0_OOV, + .oe = BOARD_GCLK0_OE, + .divsel = BOARD_GCLK0_DIVSEL, + .runstdby = BOARD_GCLK0_RUNSTDBY, + .source = BOARD_GCLK0_SOURCE, + .div = BOARD_GCLK0_DIV + }, + { + .enable = BOARD_GCLK1_ENABLE, + .idc = BOARD_GCLK1_IDC, + .oov = BOARD_GCLK1_OOV, + .oe = BOARD_GCLK1_OE, + .divsel = BOARD_GCLK1_DIVSEL, + .runstdby = BOARD_GCLK1_RUNSTDBY, + .source = BOARD_GCLK1_SOURCE, + .div = BOARD_GCLK1_DIV + }, + { + .enable = BOARD_GCLK2_ENABLE, + .idc = BOARD_GCLK2_IDC, + .oov = BOARD_GCLK2_OOV, + .oe = BOARD_GCLK2_OE, + .divsel = BOARD_GCLK2_DIVSEL, + .runstdby = BOARD_GCLK2_RUNSTDBY, + .source = BOARD_GCLK2_SOURCE, + .div = BOARD_GCLK2_DIV + }, + { + .enable = BOARD_GCLK3_ENABLE, + .idc = BOARD_GCLK3_IDC, + .oov = BOARD_GCLK3_OOV, + .oe = BOARD_GCLK3_OE, + .divsel = BOARD_GCLK3_DIVSEL, + .runstdby = BOARD_GCLK3_RUNSTDBY, + .source = BOARD_GCLK3_SOURCE, + .div = BOARD_GCLK3_DIV + }, + { + .enable = BOARD_GCLK4_ENABLE, + .idc = BOARD_GCLK4_IDC, + .oov = BOARD_GCLK4_OOV, + .oe = BOARD_GCLK4_OE, + .divsel = BOARD_GCLK4_DIVSEL, + .runstdby = BOARD_GCLK4_RUNSTDBY, + .source = BOARD_GCLK4_SOURCE, + .div = BOARD_GCLK4_DIV + }, + { + .enable = BOARD_GCLK5_ENABLE, + .idc = BOARD_GCLK5_IDC, + .oov = BOARD_GCLK5_OOV, + .oe = BOARD_GCLK5_OE, + .divsel = BOARD_GCLK5_DIVSEL, + .runstdby = BOARD_GCLK5_RUNSTDBY, + .source = BOARD_GCLK5_SOURCE, + .div = BOARD_GCLK5_DIV + }, + { + .enable = BOARD_GCLK6_ENABLE, + .idc = BOARD_GCLK6_IDC, + .oov = BOARD_GCLK6_OOV, + .oe = BOARD_GCLK6_OE, + .divsel = BOARD_GCLK6_DIVSEL, + .runstdby = BOARD_GCLK6_RUNSTDBY, + .source = BOARD_GCLK6_SOURCE, + .div = BOARD_GCLK6_DIV + }, + { + .enable = BOARD_GCLK7_ENABLE, + .idc = BOARD_GCLK7_IDC, + .oov = BOARD_GCLK7_OOV, + .oe = BOARD_GCLK7_OE, + .divsel = BOARD_GCLK7_DIVSEL, + .runstdby = BOARD_GCLK7_RUNSTDBY, + .source = BOARD_GCLK7_SOURCE, + .div = BOARD_GCLK7_DIV + }, + { + .enable = BOARD_GCLK8_ENABLE, + .idc = BOARD_GCLK8_IDC, + .oov = BOARD_GCLK8_OOV, + .oe = BOARD_GCLK8_OE, + .divsel = BOARD_GCLK8_DIVSEL, + .runstdby = BOARD_GCLK8_RUNSTDBY, + .source = BOARD_GCLK8_SOURCE, + .div = BOARD_GCLK8_DIV + }, + { + .enable = BOARD_GCLK9_ENABLE, + .idc = BOARD_GCLK9_IDC, + .oov = BOARD_GCLK9_OOV, + .oe = BOARD_GCLK9_OE, + .divsel = BOARD_GCLK9_DIVSEL, + .runstdby = BOARD_GCLK9_RUNSTDBY, + .source = BOARD_GCLK9_SOURCE, + .div = BOARD_GCLK9_DIV + }, + { + .enable = BOARD_GCLK10_ENABLE, + .idc = BOARD_GCLK10_IDC, + .oov = BOARD_GCLK10_OOV, + .oe = BOARD_GCLK10_OE, + .divsel = BOARD_GCLK10_DIVSEL, + .runstdby = BOARD_GCLK10_RUNSTDBY, + .source = BOARD_GCLK10_SOURCE, + .div = BOARD_GCLK10_DIV + }, + { + .enable = BOARD_GCLK11_ENABLE, + .idc = BOARD_GCLK11_IDC, + .oov = BOARD_GCLK11_OOV, + .oe = BOARD_GCLK11_OE, + .divsel = BOARD_GCLK11_DIVSEL, + .runstdby = BOARD_GCLK11_RUNSTDBY, + .source = BOARD_GCLK11_SOURCE, + .div = BOARD_GCLK11_DIV + } + } }; /**************************************************************************** @@ -309,1053 +261,481 @@ static const struct sam_gclkconfig_s g_gclk0_ulp32kconfig = ****************************************************************************/ /**************************************************************************** - * Name: sam_flash_waitstates + * Name: sam_set_waitsates * * Description: - * Set the FLASH wait states based on settings in the board.h header file - * Depends on: - * - * BOARD_FLASH_WAITSTATES - Number of wait states - * - * Input Parameters: - * None - * - * Returned Value: - * None + * Set the number of FLASH wait states. * ****************************************************************************/ -static inline void sam_flash_waitstates(void) +static void sam_set_waitsates(const struct sam_clockconfig_s *config) { - uint32_t regval; - - /* Errata 13134: Correct the default value of the NVMCTRL.CTRLB.MANW bit */ - - regval = getreg32(SAM_NVMCTRL_CTRLB); - regval |= NVMCTRL_CTRLB_MANW; - putreg32(regval, SAM_NVMCTRL_CTRLB); - - /* Set the configured number of flash wait states */ - - regval &= ~NVMCTRL_CTRLB_RWS_MASK; - regval |= NVMCTRL_CTRLB_RWS(BOARD_FLASH_WAITSTATES); - putreg32(regval, SAM_NVMCTRL_CTRLB); + DEBUGASSERT(config->waitstates < 16); + modifyreg16(SAM_NVMCTRL_CTRLA, NVMCTRL_CTRLA_RWS_MASK, + NVMCTRL_CTRLA_RWS(config->waitstates) ); } /**************************************************************************** - * Name: sam_performance_level + * Name: sam_xosc32k_configure * * Description: - * "When scaling down the performance level, the bus frequency should be - * first scaled down in order to not exceed the maximum frequency allowed - * for the low performance level. - * - * "When scaling up the performance level (for example from PL0 to PL2), - * the bus frequency can be increased only once the performance level - * transition is completed, check the performance level status. - * - * Input Parameters: - * level - The new performance level - * - * Returned Value: - * None + * Configure XOSC32K * ****************************************************************************/ -static void sam_performance_level(uint8_t level) +#if BOARD_HAVE_XOSC32K != 0 +static void sam_xosc32k_configure(const struct sam_xosc32_config_s *config) { - /* Check if we are already at this performance level */ + uint32_t regval32; + uint32_t regval16; + uint32_t regval8; - if (level != (getreg8(SAM_PM_PLCFG) & PM_PLCFG_PLSEL_MASK)) + /* Configure the OSC32KCTRL register */ + + regval16 = OSC32KCTRL_XOSC32K_STARTUP(config->startup); + + if (config->enable) { - /* Clear performance level status and set the new performance level */ - - putreg8(PM_INT_PLRDY, SAM_PM_INTFLAG); - putreg8(level, SAM_PM_PLCFG); - - /* Wait for the new performance level to be ready */ - - while ((getreg16(SAM_PM_INTFLAG) & PM_INT_PLRDY) == 0); - } -} - -/**************************************************************************** - * Name: sam_xosc_config - * - * Description: - * Configure XOSC based on settings in the board.h header file - * Depends on: - * - * BOARD_XOSC_ENABLE - Boolean (defined / not defined) - * BOARD_XOSC_FREQUENCY - In Hz - * BOARD_XOSC_STARTUPTIME - See OSCCTRL_XOSCCTRL_STARTUP_* definitions - * BOARD_XOSC_ISCRYSTAL - Boolean (defined / not defined) - * BOARD_XOSC_AMPGC - Boolean (defined / not defined) - * BOARD_XOSC_ONDEMAND - Boolean (defined / not defined) - * BOARD_XOSC_RUNINSTANDBY - Boolean (defined / not defined) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_XOSC_ENABLE -static inline void sam_xosc_config(void) -{ - uint16_t regval; - - /* Configure the XOSC clock */ - - regval = getreg16(SAM_OSCCTRL_XOSCCTRL); - regval &= ~(OSCCTRL_XOSCCTRL_RUNSTDBY | OSCCTRL_XOSCCTRL_ONDEMAND | - OSCCTRL_XOSCCTRL_GAIN_MASK | OSCCTRL_XOSCCTRL_XTALEN | - OSCCTRL_XOSCCTRL_AMPGC | OSCCTRL_XOSCCTRL_STARTUP_MASK); - regval |= BOARD_XOSC_STARTUPTIME - -#ifdef BOARD_XOSC_ISCRYSTAL - /* XOSC is a crystal */ - - regval |= OSCCTRL_XOSCCTRL_XTALEN; -#endif - -#ifdef BOARD_XOSC_AMPGC - /* Enable automatic gain control */ - - regval |= OSCCTRL_XOSCCTRL_AMPGC; - -#else - /* Set gain if automatic gain control is not selected */ - -#if BOARD_XOSC_FREQUENCY <= 2000000 - regval |= OSCCTRL_XOSCCTRL_GAIN_2MHZ; -#elif BOARD_XOSC_FREQUENCY <= 4000000 - regval |= OSCCTRL_XOSCCTRL_GAIN_4MHZ; -#elif BOARD_XOSC_FREQUENCY <= 8000000 - regval |= OSCCTRL_XOSCCTRL_GAIN_8MHZ; -#elif BOARD_XOSC_FREQUENCY <= 16000000 - regval |= OSCCTRL_XOSCCTRL_GAIN_16MHZ; -#elif BOARD_XOSC_FREQUENCY <= 30000000 - regval |= OSCCTRL_XOSCCTRL_GAIN_30MHZ; -#else -# error BOARD_XOSC_FREQUENCY out of range -#endif -#endif /* BOARD_XOSC_AMPGC */ - -#ifdef BOARD_XOSC_ONDEMAND - regval |= OSCCTRL_XOSCCTRL_ONDEMAND; -#endif - -#ifdef BOARD_XOSC_RUNINSTANDBY - regval |= OSCCTRL_XOSCCTRL_RUNSTDBY; -#endif - - putreg16(regval, SAM_OSCCTRL_XOSCCTRL); - - /* Then enable the XOSC clock */ - - regval |= OSCCTRL_XOSCCTRL_ENABLE; - putreg16(regval, SAM_OSCCTRL_XOSCCTRL); -} -#else -# define sam_xosc_config() -#endif - -/**************************************************************************** - * Name: sam_xosc32k_config - * - * Description: - * Configure XOSC32K based on settings in the board.h header file. - * Depends on: - * - * BOARD_XOSC32K_ENABLE - Boolean (defined / not defined) - * BOARD_XOSC32K_FREQUENCY - In Hz - * BOARD_XOSC32K_STARTUPTIME - See OSC32KCTRL_XOSC32K_STARTUP_* definitions - * BOARD_XOSC32K_ISCRYSTAL - Boolean (defined / not defined) - * BOARD_XOSC32K_AAMPEN - Boolean (defined / not defined) - * BOARD_XOSC32K_EN1KHZ - Boolean (defined / not defined) - * BOARD_XOSC32K_EN32KHZ - Boolean (defined / not defined) - * BOARD_XOSC32K_ONDEMAND - Boolean (defined / not defined) - * BOARD_XOSC32K_RUNINSTANDBY - Boolean (defined / not defined) - * BOARD_XOSC32K_WRITELOCK - Boolean (defined / not defined) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_XOSC32K_ENABLE -static inline void sam_xosc32k_config(void) -{ - uint16_t regval; - - /* Configure XOSC32K (skipping the ONDEMANC SETTING until last) */ - - regval = getreg16(SAM_OSC32KCTRL_XOSC32K); - regval &= ~(OSC32KCTRL_XOSC32K_XTALEN | OSC32KCTRL_XOSC32K_EN32K | - OSC32KCTRL_XOSC32K_EN1K | OSC32KCTRL_XOSC32K_RUNSTDBY | - OSC32KCTRL_XOSC32K_ONDEMAND | OSC32KCTRL_XOSC32K_STARTUP_MASK | - OSC32KCTRL_XOSC32K_WRTLOCK); - regval |= BOARD_XOSC32K_STARTUPTIME; - -#ifdef BOARD_XOSC32K_ISCRYSTAL - regval |= OSC32KCTRL_XOSC32K_XTALEN; -#endif - -#ifdef BOARD_XOSC32K_EN1KHZ - regval |= OSC32KCTRL_XOSC32K_EN1K; -#endif - -#ifdef BOARD_XOSC32K_EN32KHZ - regval |= OSC32KCTRL_XOSC32K_EN32K; -#endif - -#ifdef BOARD_XOSC32K_RUNINSTANDBY - regval |= OSC32KCTRL_XOSC32K_RUNSTDBY; -#endif - - putreg16(regval, SAM_OSC32KCTRL_XOSC32K); - - /* Then enable the XOSC clock */ - - regval |= OSC32KCTRL_XOSC32K_ENABLE; - putreg16(regval, SAM_OSC32KCTRL_XOSC32K); - - /* Wait for XOSC32K to be ready */ - - while ((getreg32(SAM_OSC32KCTRL_STATUS) & OSC32KCTRL_INT_XOSC32KRDY) == 0); - -#ifdef BOARD_XOSC32K_ONDEMAND - /* Set the on-demand bit */ - - regval |= OSC32KCTRL_XOSC32K_ONDEMAND; - putreg16(regval, SAM_OSC32KCTRL_XOSC32K); -#endif - -#ifdef BOARD_XOSC32K_WRITELOCK - /* Lock this configuration until the next power up */ - - regval |= OSC32KCTRL_XOSC32K_WRTLOCK; - putreg16(regval, SAM_OSC32KCTRL_XOSC32K); -#endif -} -#else -# define sam_xosc32k_config() -#endif - -/**************************************************************************** - * Name: sam_osc32k_config - * - * Description: - * Configure OSC32K based on settings in the board.h header file. - * Depends on: - * - * BOARD_OSC32K_ENABLE - Boolean (defined / not defined) - * BOARD_OSC32K_FREQUENCY - In Hz - * BOARD_OSC32K_STARTUPTIME - See OSC32KCTRL_OSC32K_STARTUP_* definitions - * BOARD_OSC32K_EN1KHZ - Boolean (defined / not defined) - * BOARD_OSC32K_EN32KHZ - Boolean (defined / not defined) - * BOARD_OSC32K_ONDEMAND - Boolean (defined / not defined) - * BOARD_OSC32K_RUNINSTANDBY - Boolean (defined / not defined) - * BOARD_OSC32K_WRITELOCK - Boolean (defined / not defined) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_OSC32K_ENABLE -static inline void sam_osc32k_config(void) -{ - uint32_t regval; - - /* Configure OSC32K */ - - regval = getreg32(SAM_OSC32KCTRL_OSC32K); - regval &= ~(OSC32KCTRL_OSC32K_EN32K | OSC32KCTRL_OSC32K_EN1K | - OSC32KCTRL_OSC32K_RUNSTDBY | OSC32KCTRL_OSC32K_ONDEMAND | - OSC32KCTRL_OSC32K_STARTUP_MASK | OSC32KCTRL_OSC32K_WRTLOCK); - regval |= BOARD_OSC32K_STARTUPTIME; - -#ifdef BOARD_OSC32K_EN32KHZ - regval |= OSC32KCTRL_OSC32K_EN32K; -#endif - -#ifdef BOARD_OSC32K_EN1KHZ - regval |= OSC32KCTRL_OSC32K_EN1K; -#endif - -#ifdef BOARD_OSC32K_RUNINSTANDBY - regval |= OSC32KCTRL_OSC32K_RUNSTDBY; -#endif - -#ifdef BOARD_OSC32K_ONDEMAND - regval |= OSC32KCTRL_OSC32K_ONDEMAND; -#endif - - putreg32(regval, SAM_OSC32KCTRL_OSC32K); - - /* Then enable OSC32K */ - - regval |= OSC32KCTRL_OSC32K_ENABLE; - putreg32(regval, SAM_OSC32KCTRL_OSC32K); - -#ifdef BOARD_XOSC32K_WRITELOCK - /* Lock this configuration until the next power up */ - - regval |= OSC32KCTRL_OSC32K_WRTLOCK; - putreg16(regval, SAM_OSC32KCTRL_OSC32K); -#endif -} -#else -# define sam_osc32k_config() -#endif - -/**************************************************************************** - * Name: sam_osculp32k_config - * - * Description: - * Configure OSCULP32K - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#define sam_osculp32k_config() - -/**************************************************************************** - * Name: sam_osc16m_config - * - * Description: - * Configure OSC16M based on settings in the board.h header file. - * Depends on: - * - * BOARD_OSC16M_FSEL - See OSCCTRL_OSC16MCTRL_FSEL_* definitions - * BOARD_OSC16M_ONDEMAND - Boolean (defined / not defined) - * BOARD_OSC16M_RUNINSTANDBY - Boolean (defined / not defined) - * - * On any reset the synchronous clocks start to their initial state: - * - * OSC16M is enabled and divided by 8 - * GCLK_MAIN uses OSC16M as source - * CPU and BUS clocks are undivided - * - * The reset state of the OSC16M register is: - * - * FFxx CCCC CCCC CCCC xxxx xxPP ORxx xxEx - * xx00 xxxx xxxx xxxx 0000 0011 1000 0010 - * - * FRANGE FF Loaded from FLASH calibration at startup - * CALIB CCC...C Loaded from FLASH calibration at startup - * PRESC PP 3 = Divide by 8 - * ONDEMAND O 1 - * RUNSTBY R 0 - * ENABLE 1 1 - * - * NOTE that since we are running from OSC16M, it cannot be disable! - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void sam_osc16m_config(void) -{ - uint32_t regval; - bool enabled; - - /* After reset, OSC16M is enabled and serve4s as the default clock source - * at 4MHz. Since this particular logic only runs on reset, there is - * some additional unnecessary logic in the following. - */ - - /* Configure OSC16M */ - - regval = getreg32(SAM_OSCCTRL_OSC16MCTRL); - - /* Is OSC16M already enabled? Is it already running at the requested - * frequency? - */ - - enabled = ((regval & OSCCTRL_OSC16MCTRL_ENABLE) != 0); - if (enabled && (regval & OSCCTRL_OSC16MCTRL_FSEL_MASK) == BOARD_OSC16M_FSEL) - { - regval &= ~(OSCCTRL_OSC16MCTRL_ONDEMAND | OSCCTRL_OSC16MCTRL_RUNSTDBY); - -#ifdef BOARD_OSC16M_ONDEMAND - /* Select on-demand oscillator controls */ - - regval |= OSCCTRL_OSC16MCTRL_ONDEMAND; -#endif - -#ifdef BOARD_OSC16M_RUNINSTANDBY - /* The oscillator continues to run in standby sleep mode */ - - regval |= OSCCTRL_OSC16MCTRL_RUNSTDBY; -#endif - - /* Save the new OSC16M configuration */ - - putreg32(regval, SAM_OSCCTRL_OSC16MCTRL); + regval16 |= OSC32KCTRL_XOSC32K_ENABLE; } - /* Either the OSC16M is not running (which is not possible in this - * context) or else OSC16M is configured to run at a different frequency. - */ - - else + if (config->highspeed) { - /* If it is enabled, then we are probably running on OSC16M now. - * Select OSCULP32K as new clock source for main clock temporarily. - * This depends on the fact the GCLK0 is enabled at reset. - */ + regval16 |= OSC32KCTRL_XOSC32K_GCM_HS; + } - if (enabled) + if (config->extalen) + { + regval16 |= OSC32KCTRL_XOSC32K_XTALEN; + } + + if (config->en32k) + { + regval16 |= OSC32KCTRL_XOSC32K_EN32K; + } + + if (config->en1k) + { + regval16 |= OSC32KCTRL_XOSC32K_EN1K; + } + + if (config->runstdby) + { + regval16 |= OSC32KCTRL_XOSC32K_RUNSTDBY; + } + + if (config->ondemand) + { + regval16 |= OSC32KCTRL_XOSC32K_ONDEMAND; + } + + putreg16(regval16, SAM_OSC32KCTRL_XOSC32K); + + /* Configure the CFDCTRL register */ + + regval8 = config->cfden ? OSC32KCTRL_CFDCTRL_CFDEN : 0; + putreg8(regval8, SAM_OSC32KCTRL_CFDCTRL); + + regval8 = config->cfdeo ? OSC32KCTRL_EVCTRL_CFDEO : 0; + putreg8(regval8, SAM_OSC32KCTRL_EVCTRL); + + /* Setup OSCULP32K calibration */ + + if (config->caliben) + { + regval32 = getreg32(SAM_OSC32KCTRL_OSCULP32K); + regval32 &= ~OSC32KCTRL_OSCULP32K_CALIB_MASK; + regval32 |= OSC32KCTRL_OSCULP32K_CALIB(config->calib); + } + + /* Wait for XOSC32 to become ready if it was enabled */ + + if (config->enable && ! config->ondemand) + { + while ((getreg32(SAM_OSC32KCTRL_STATUS) & + OSC32KCTRL_INT_XOSC32KRDY) == 0) { - sam_gclk_config(&g_gclk0_ulp32kconfig); - - /* Disable OSC16M clock */ - - regval &= ~OSCCTRL_OSC16MCTRL_ENABLE; - putreg32(regval, SAM_OSCCTRL_OSC16MCTRL); - } - - /* Set the new OSC16M configuration */ - - regval &= ~(OSCCTRL_OSC16MCTRL_FSEL_MASK | OSCCTRL_OSC16MCTRL_RUNSTDBY | - OSCCTRL_OSC16MCTRL_ONDEMAND); - regval |= BOARD_OSC16M_FSEL; - -#ifdef BOARD_OSC16M_RUNINSTANDBY - /* The oscillator continues to run in standby sleep mode */ - - regval |= OSCCTRL_OSC16MCTRL_RUNSTDBY; -#endif - - /* Save the new OSC16M configuration */ - - putreg32(regval, SAM_OSCCTRL_OSC16MCTRL); - - /* Enable OSC16M */ - - regval |= OSCCTRL_OSC16MCTRL_ENABLE; - putreg32(regval, SAM_OSCCTRL_OSC16MCTRL); - - /* Wait for OSC16M to be ready */ - - while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_OSC16MRDY) == 0); - -#ifdef BOARD_OSC16M_ONDEMAND - /* Select on-demand oscillator controls */ - - regval |= OSCCTRL_OSC16MCTRL_ONDEMAND; - putreg32(regval, SAM_OSCCTRL_OSC16MCTRL); -#endif - - /* Re-select OSC16M for main clock again */ - - if (enabled) - { - sam_gclk_config(&g_gclk0_default); } } + + /* Set the RTC clock source */ + + putreg8(OSC32KCTRL_RTCCTRL_RTCSEL(config->rtcsel), + SAM_OSC32KCTRL_RTCCTRL); } +#endif /**************************************************************************** - * Name: sam_dfll48m_config + * Name: sam_xoscctrl * * Description: - * Configure the DFLL48M based on settings in the board.h header file. - * Depends on: - * - * BOARD_DFLL48M_CLOSEDLOOP - Boolean (defined / not defined) - * BOARD_DFLL48M_OPENLOOP - Boolean (defined / not defined) - * BOARD_DFLL48M_RECOVERY - Boolean (defined / not defined) - * BOARD_DFLL48M_TRACKAFTERFINELOCK - Boolean (defined / not defined) - * BOARD_DFLL48M_KEEPLOCKONWAKEUP - Boolean (defined / not defined) - * BOARD_DFLL48M_ENABLECHILLCYCLE - Boolean (defined / not defined) - * BOARD_DFLL48M_QUICKLOCK - Boolean (defined / not defined) - * BOARD_DFLL48M_RUNINSTDBY - Boolean (defined / not defined) - * BOARD_DFLL48M_ONDEMAND - Boolean (defined / not defined) - * BOARD_DFLL48M_COARSEVALUE - Value - * BOARD_DFLL48M_FINEVALUE - Value - * - * Open Loop mode only: - * BOARD_DFLL48M_COARSEVALUE - Value - * BOARD_DFLL48M_FINEVALUE - Value - * - * Closed loop mode only: - * BOARD_DFLL48M_REFCLK_CLKGEN - GCLK index in the range {0..8} - * BOARD_DFLL48M_MULTIPLIER - Value - * BOARD_DFLL48M_MAXCOARSESTEP - Value - * BOARD_DFLL48M_MAXFINESTEP - Value - * - * Input Parameters: - * None - * - * Returned Value: - * None + * Get the appropriate settings for the XOSCCTRL register for XOSC0 or 1. * ****************************************************************************/ -#ifdef BOARD_DFLL48M_ENABLE -static inline void sam_dfll48m_config(void) +#if BOARD_HAVE_XOSC0 != 0 || BOARD_HAVE_XOSC1 != 0 +static uint32_t sam_xoscctrl(const struct sam_xosc_config_s *config) { - uint16_t control; uint32_t regval; + uint8_t cfdpresc; + uint8_t imult; + uint8_t iptat; - /* Disable ONDEMAND mode while writing configurations (Errata 9905). This - * is probably not necessary on the first time configuration after reset. - */ + /* Some settings determined by the crystal frequency */ - control = getreg16(SAM_OSCCTRL_DFLLCTRL); - control &= ~(OSCCTRL_DFLLCTRL_ENABLE | OSCCTRL_DFLLCTRL_ONDEMAND); - putreg16(control, SAM_OSCCTRL_DFLLCTRL); - - /* Wait for the DFLL to synchronize */ - - while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_DFLLRDY) == 0); - - /* Set up the DFLL control register */ - - control &= ~(OSCCTRL_DFLLCTRL_MODE | OSCCTRL_DFLLCTRL_STABLE | - OSCCTRL_DFLLCTRL_LLAW | OSCCTRL_DFLLCTRL_USBCRM | - OSCCTRL_DFLLCTRL_RUNSTDBY | OSCCTRL_DFLLCTRL_CCDIS | - OSCCTRL_DFLLCTRL_QLDIS | OSCCTRL_DFLLCTRL_BPLCKC | - OSCCTRL_DFLLCTRL_WAITLOCK); - -#if defined(BOARD_DFLL48M_CLOSEDLOOP) - control |= OSCCTRL_DFLLCTRL_MODE; /* Closed loop mode */ -#elif defined(BOARD_DFLL48M_RECOVERY) - control |= OSCCTRL_DFLLCTRL_USBCRM; /* USB clock recovery mode */ -#endif - -#ifndef BOARD_DFLL48M_TRACKAFTERFINELOCK - control |= OSCCTRL_DFLLCTRL_STABLE; /* FINE calibration fixed after a fine lock */ -#endif - -#ifndef BOARD_DFLL48M_KEEPLOCKONWAKEUP - control |= OSCCTRL_DFLLCTRL_LLAW; /* Lose lock after wake */ -#endif - -#ifdef BOARD_DFLL48M_RUNINSTDBY - control |= OSCCTRL_DFLLCTRL_RUNSTDBY; /* Run in standby */ -#endif - -#ifndef BOARD_DFLL48M_ENABLECHILLCYCLE - control |= OSCCTRL_DFLLCTRL_CCDIS; /* Chill cycle disable */ -#endif - -#ifndef BOARD_DFLL48M_QUICKLOCK - control |= OSCCTRL_DFLLCTRL_QLDIS; /* Quick lock disable */ -#endif - -#ifdef BOARD_DFLL48M_BPLCKC - control |= OSCCTRL_DFLLCTRL_BPLCKC; /* Bypass coarse clock */ -#endif - -#ifdef BOARD_DFLL48M_WAITLOCK - control |= OSCCTRL_DFLLCTRL_WAITLOCK; /* Wait lock */ -#endif - - /* Then enable the DFLL (with ONDEMAND set to zero). */ - - putreg16(control, SAM_OSCCTRL_DFLLCTRL); - - /* Wait for the DFLL to synchronize */ - - while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_DFLLRDY) == 0); - - /* Set up the open loop mode multiplier register */ - -#ifndef BOARD_DFLL48M_OPENLOOP - regval = OSCCTRL_DFLLMUL_CSTEP(BOARD_DFLL48M_MAXCOARSESTEP) | - OSCCTRL_DFLLMUL_FSTEP(BOARD_DFLL48M_MAXFINESTEP) | - OSCCTRL_DFLLMUL_MUL(BOARD_DFLL48M_MULTIPLIER); - putreg32(regval, SAM_OSCCTRL_DFLLMUL); -#else - putreg32(0, SAM_OSCCTRL_DFLLMUL); -#endif - - /* Set up the DFLL value register */ - - regval = OSCCTRL_DFLLVAL_COARSE(BOARD_DFLL48M_COARSEVALUE) | - OSCCTRL_DFLLVAL_FINE(BOARD_DFLL48M_FINEVALUE); - putreg32(regval, SAM_OSCCTRL_DFLLVAL); -} -#else -# define sam_dfll48m_config() -#endif - -/**************************************************************************** - * Name: sam_dfll48m_enable - * - * Description: - * Enable the DFLL48M. - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_DFLL48M_ENABLE -static inline void sam_dfll48m_enable(void) -{ - uint16_t control; - - /* Enable the DFLL48M (with ONDEMAND still set to zero). */ - - control = getreg16(SAM_OSCCTRL_DFLLCTRL); - control |= OSCCTRL_DFLLCTRL_ENABLE; /* Enable the DFLL */ - putreg16(control, SAM_OSCCTRL_DFLLCTRL); - - /* Wait for the DFLL to synchronize */ - - while ((getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_DFLLRDY) == 0); - - /* Finally, set the state of the ONDEMAND bit if necessary */ - -#ifdef BOARD_DFLL48M_ONDEMAND - control |= OSCCTRL_DFLLCTRL_ONDEMAND; /* On demand control */ - putreg16(control, SAM_OSCCTRL_DFLLCTRL); -#endif -} -#else -# define sam_dfll48m_enable() -#endif - -/**************************************************************************** - * Name: sam_dfll48m_refclk - * - * Description: - * Enable DFLL reference clock if in closed loop mode. - * Depends on: - * - * BOARD_DFLL48M_REFCLK_CLKGEN - GCLK index in the range {0..8} - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_DFLL48M_ENABLE) && \ - !defined(BOARD_DFLL48M_OPENLOOP) -static inline void sam_dfll48m_refclk(void) -{ - sam_gclk_chan_enable(GCLK_CHAN_DFLL48M_REF, BOARD_DFLL48M_REFCLK_CLKGEN); -} -#else -# define sam_dfll48m_refclk() -#endif - -/**************************************************************************** - * Name: sam_fdpll96m_config - * - * Description: - * Configure and enable the DFLL based on settings in the board.h header - * file. - * Depends on: - * - * BOARD_FDPLL96M_ENABLE - Boolean (defined / not defined) - * BOARD_FDPLL96M_RUNINSTDBY - Boolean (defined / not defined) - * BOARD_FDPLL96M_ONDEMAND - Boolean (defined / not defined) - * BOARD_FDPLL96M_LBYPASS - Boolean (defined / not defined) - * BOARD_FDPLL96M_WUF - Boolean (defined / not defined) - * BOARD_FDPLL96M_LPEN - Boolean (defined / not defined) - * BOARD_FDPLL96M_FILTER - See OSCCTRL_DPLLCTRLB_FILTER_* definitions - * BOARD_FDPLL96M_REFCLK - See OSCCTRL_DPLLCTRLB_REFLCK_* definitions - * BOARD_FDPLL96M_LOCKTIME - See OSCCTRL_DPLLCTRLB_LTIME_* definitions - * BOARD_FDPLL96M_REFDIV - Numeric value, 1 - 2047 - * BOARD_FDPLL96M_PRESCALER - See OSCCTRL_DPLLPRESC_* definitions - * BOARD_FDPLL96M_REFFREQ - Numeric value - * BOARD_FDPLL96M_FREQUENCY - Numeric value - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_FDPLL96M_ENABLE -static inline void sam_fdpll96m_config(void) -{ - uint32_t ldr; - uint32_t refclk; - uint32_t regval; - uint8_t ldrfrac; - uint8_t ctrla; - - /* Get the reference clock frequency */ - - refclk = BOARD_FDPLL96M_REFFREQ; - -#if BOARD_FDPLL96M_REFCLK == OSCCTRL_DPLLCTRLB_REFLCK_XOSC - /* Only XOSC reference clock can be divided */ - - refclk = refclk / (2 * (BOARD_FDPLL96M_REFDIV + 1)); -#endif - - /* Calculate LDRFRAC and LDR */ - - ldr = (BOARD_FDPLL96M_FREQUENCY << 4) / refclk; - ldrfrac = (uint8_t)(ldr & 0x0f); - ldr = (ldr >> 4) - 1; - - /* Set DPLLCTRLA configuration (ut not the ONDEMAND bit) */ - - ctrla = 0; - -#ifdef BOARD_FDPLL96M_RUNINSTDBY - ctrla |= OSCCTRL_DPLLCTRLA_RUNSTDBY; -#endif - - putreg8(ctrla, SAM_OSCCTRL_DPLLCTRLA); - - /* Set the FDPLL96M ration register */ - - regval = OSCCTRL_DPLLRATIO_LDR(ldr) | OSCCTRL_DPLLRATIO_LDRFRAC(ldrfrac) - putreg32(reval, SAM_OSCCTRL_DPLLRATIO); - - /* Wait for synchronization */ - - while ((getreg8(SAM_OSCCTRL_DPLLSYNCBUSY) & OSCCTRL_DPLLSYNCBUSY_DPLLRATIO) != 0); - - /* Set DPLLCTRLB configuration */ - - regval = BOARD_FDPLL96M_FILTER | BOARD_FDPLL96M_LOCKTIME | - BOARD_FDPLL96M_REFCLK | - OSCCTRL_DPLLCTRLB_DIV(BOARD_FDPLL96M_REFDIV); - -#ifdef BOARD_FDPLL96M_LBYPASS - regval |= OSCCTRL_DPLLCTRLB_LBYPASS; -#endif -#ifdef BOARD_FDPLL96M_WUF - regval |= OSCCTRL_DPLLCTRLB_WUF; -#endif -#ifdef BOARD_FDPLL96M_LPEN - regval |= OSCCTRL_DPLLCTRLB_LPEN; -#endif - - putreg8(regval, SAM_OSCCTRL_DPLLCTRLA); - - /* Set the prescaler value */ - - putreg8(BOARD_FDPLL96M_PRESCALER, SAM_ OSCCTRL_DPLLPRESC); - - /* Wait for synchronization */ - - while ((getreg8(SAM_OSCCTRL_DPLLSYNCBUSY) & OSCCTRL_DPLLSYNCBUSY_DPLLPRESC) != 0); - - /* Enable the FDPLL96M output */ - - ctrla |= OSCCTRL_DPLLCTRLA_ENABLE; - putreg8(ctrla, SAM_OSCCTRL_DPLLCTRLA); - - /* Wait for synchronization */ - - while ((getreg8(SAM_OSCCTRL_DPLLSYNCBUSY) & OSCCTRL_DPLLSYNCBUSY_ENABLE) != 0); - - /* Wait for the FPDLL96M to become locked and ready */ - - while ((getreg8(SAM_OSCCTRL_DPLLSTATUS) & - (OSCCTRL_DPLLSTATUS_CLKRDY | OSCCTRL_DPLLSTATUS_LOCK)) != - (OSCCTRL_DPLLSTATUS_CLKRDY | OSCCTRL_DPLLSTATUS_LOCK)); - -#ifdef BOARD_FDPLL96M_ONDEMAND - /* Now set the ONDEMAND bit if so configured */ - - ctrla |= OSCCTRL_DPLLCTRLA_ONDEMAND; - putreg8(ctrla, SAM_OSCCTRL_DPLLCTRLA); -#endif -} -#else -# define sam_fdpll96m_config() -#endif - -/**************************************************************************** - * Name: sam_fdpll96m_refclk - * - * Description: - * Enable FDPLL96M internal lock timer and reference clock. - * Depends on: - * - * BOARD_FDPLL96M_ENABLE - Boolean (defined / not defined) - * BOARD_FDPLL96M_REFCLK - See OSCCTRL_DPLLCTRLB_REFLCK_* definitions - * BOARD_FDPLL96M_REFCLK_CLKGEN - GCLK index in the range {0..8} - * BOARD_FDPLL96M_LOCKTIME_ENABLE - Boolean (defined / not defined) - * BOARD_FDPLL96M_LOCKTIME_CLKGEN - GCLK index in the range {0..8} - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#if defined(BOARD_GCLK_ENABLE) && defined(BOARD_FDPLL96M_ENABLE) -static inline void sam_fdpll96m_refclk(void) -{ -#ifdef BOARD_FDPLL96M_LOCKTIME_ENABLE - /* Enable the GCLK that is configured to the FDPLL lock timer */ - - sam_gclk_chan_enable(GCLK_CHAN_DPLL_32K, BOARD_FDPLL96M_LOCKTIME_CLKGEN); -#endif - -#if BOARD_FDPLL96M_REFCLK == OSCCTRL_DPLLCTRLB_REFLCK_GLCK - /* Enable the GCLK that is configured to be the FDPLL reference clock */ - - sam_gclk_chan_enable(GCLK_CHAN_DPLL, BOARD_FDPLL96M_REFCLK_CLKGEN); -#endif -} -#else -# define sam_fdpll96m_refclk() -#endif - -/**************************************************************************** - * Name: sam_cpu_dividers - * - * Description: - * Setup PM main clock dividers to generate CPU and AHB. - * Depends on: - * - * BOARD_CPU_DIVIDER - See MCLK_CPUDIV_DIV* definitions - * BOARD_CPU_FRQUENCY - In Hz - * BOARD_CPU_FAILDECT - Boolean (defined / not defined) - * BOARD_LOWPOWER_DIVIDER - See MCLK_LPDIV_DIV_* definitions - * BOARD_LOWPOWER_FREQUENCY - In Hz - * BOARD_BACKUP_DIVIDER - See MCLK_BUPDIV_DIV_* definitions - * BOARD_BACKUP_FREQUENCY - In Hz - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -static inline void sam_cpu_dividers(void) -{ - uint8_t regval; - - /* Set CPU divider and, optionally, enable failure detection */ - - putreg8(BOARD_CPU_DIVIDER, SAM_MCLK_CPUDIV); - - /* Enable/disabled clock failure detection */ - - regval = getreg8(SAM_MCLK_CTRLA); -#ifdef BOARD_CPU_FAILDECT - regval |= MCLK_CTRLA_CFDEN; -#else - regval &= ~MCLK_CTRLA_CFDEN; -#endif - putreg8(regval, SAM_MCLK_CTRLA); - - /* Setup up lower power and backup dividers */ - - putreg8(BOARD_LOWPOWER_DIVIDER, SAM_MCLK_LPDIV); - putreg8(BOARD_BACKUP_DIVIDER, SAM_MCLK_BUPDIV); -} - -/**************************************************************************** - * Name: sam_config_gclks - * - * Description: - * Configure GCLK(s) based on settings in the board.h header file. - * Depends on: - * - * Global enable/disable. - * - * BOARD_GCLK_ENABLE - *MUST* be defined - * - * For n=1-7: - * BOARD_GCLKn_ENABLE - Boolean (defined / not defined) - * - * For n=0-8: - * BOARD_GCLKn_RUN_IN_STANDBY - Boolean (defined / not defined) - * BOARD_GCLKn_CLOCK_SOURCE - See GCLK_GENCTRL_SRC_* definitions - * BOARD_GCLKn_PRESCALER - Value - * BOARD_GCLKn_OUTPUT_ENABLE - Boolean (defined / not defined) - * - * Input Parameters: - * None - * - * Returned Value: - * None - * - ****************************************************************************/ - -#ifdef BOARD_GCLK_ENABLE -static inline void sam_config_gclks(void) -{ - int i; - - /* Turn on the APB GCLK interface clock */ - - sam_apb_gclk_enableperiph(); - - /* Reset the GCLK module */ - - putreg8(GCLK_CTRLA_SWRST, SAM_GCLK_CTRLA); - - /* Wait for the reset to complete */ - - while ((getreg8(SAM_GCLK_CTRLA) & GCLK_CTRLA_SWRST) != 0); - - /* Configure all GCLK generators, skipping GLCK_MAIN which is configured - * below. - */ - - for (i = 1; i < NGCLKS_ENABLED; i++) + if (config->xosc_frequency > 32000000) { - sam_gclk_config(&g_gclkconfig[i]); + cfdpresc = 0; + imult = 7; + iptat = 3; + } + else if (config->xosc_frequency > 24000000) + { + cfdpresc = 1; + imult = 6; + iptat = 3; + } + else if (config->xosc_frequency > 16000000) + { + cfdpresc = 2; + imult = 5; + iptat = 3; + } + else if (config->xosc_frequency > 8000000) + { + cfdpresc = 3; + imult = 4; + iptat = 3; + } + + /* Get the XOSCTCTL register *configuration */ + + regval = OSCCTRL_XOSCCTRL_IPTAT(ipta) | OSCCTRL_XOSCCTRL_IMULT(imult) | + OSCCTRL_XOSCCTRL_STARTUP(config->starup) | + OSCCTRL_XOSCCTRL_CFDPRESC(cfdpresc); + + if (config->enable) + { + regval |= OSCCTRL_XOSCCTRL_ENABLE; + } + + if (config->extalen) + { + regval |= OSCCTRL_XOSCCTRL_XTALEN; + } + + if (config->runstdby) + { + regval |= OSCCTRL_XOSCCTRL_RUNSTDBY; + } + + if (config->ondemand) + { + regval |= OSCCTRL_XOSCCTRL_ONDEMAND; + } + + if (config->lowgain) + { + regval |= OSCCTRL_XOSCCTRL_LOWBUFGAIN; + } + + if (config->enalc) + { + regval |= OSCCTRL_XOSCCTRL_ENALC; + } + + if (config->cfden) + { + regval |= OSCCTRL_XOSCCTRL_CFDEN; + } + + if (config->swben) + { + regval |= OSCCTRL_XOSCCTRL_SWBEN; + } + + return regval; +} +#endif + +/**************************************************************************** + * Name: sam_xosc32k_configure + * + * Description: + * Configure XOSC32K + * + ****************************************************************************/ + +#if BOARD_HAVE_XOSC0 != 0 +static void sam_xosc0_configure(const struct sam_clockconfig_s *config) +{ + uint32_t regval; + + /* Configure the XOSCTCTL register */ + + regval = sam_xoscctrl(config); + putreg32(regval, SAM_OSCCTRL_XOSCCTRL0); + + /* If the XOSC was enabled, then wait for it to become ready */ + + /* Wait for XOSC32 to become ready if it was enabled */ + + if (config->enable) + { + while (getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY0) == 0) + { + } + } + + /* Re-select OnDemand */ + + if (config->ondemand) + { + regval = getre32(SAM_OSCCTRL_XOSCCTRL0) + regval |=OSCCTRL_XOSCCTRL_ONDEMAND; + putreg32(regval, SAM_OSCCTRL_XOSCCTRL0); + } +} +#endif + +#if BOARD_HAVE_XOSC0 != 0 +void sam_xosc1_configure(const struct sam_xosc_config_s *config) +{ + uint32_t regval; + + /* Configure the XOSCTCTL register */ + + regval = sam_xoscctrl(config); + putreg32(regval, SAM_OSCCTRL_XOSCCTRL1); + + /* If the XOSC was enabled, then wait for it to become ready */ + + /* Wait for XOSC32 to become ready if it was enabled */ + + if (config->enable) + { + while (getreg32(SAM_OSCCTRL_STATUS) & OSCCTRL_INT_XOSCRDY1) == 0) + { + } + } + + /* Re-select OnDemand */ + + if (config->ondemand) + { + regval = getre32(SAM_OSCCTRL_XOSCCTRL1) + regval |=OSCCTRL_XOSCCTRL_ONDEMAND; + putreg32(regval, SAM_OSCCTRL_XOSCCTRL1); } } -#else -# define sam_config_gclks() #endif /**************************************************************************** - * Name: sam_periph_clocks + * Name: sam_mclk_configure * * Description: - * Setup initial peripheral clocking: - * - * Input Parameters: - * None - * - * Returned Value: - * None + * Configure master clock generator * ****************************************************************************/ -static inline void sam_periph_clocks(void) +static inline void sam_mclk_configure(uint8_t cpudiv) +{ + putreg8(cpudiv, SAM_MCLK_CPUDIV); +} + +/**************************************************************************** + * Name: sam_fdpll_configure + * + * Description: + * Configure FDPLL0 and FDPLL1 + * + ****************************************************************************/ + +static void sam_fdpll_configure(const struct sam_fdpll_config_s config[2]) { #warning Missing logic } +/**************************************************************************** + * Name: sam_gclk_configure + * + * Description: + * Configure one GLCK + * + ****************************************************************************/ + +static void sam_gclk_configure(uintptr_t regaddr, + const struct sam_gclk_config_s *config) +{ + uint32_t regval; + + /* Are we enabling or disabling the GLCK? */ + + if (config->enable) + { + /* Get the GLCK configuration */ + + regval = GCLK_GENCTRL_SRC(config->source) | GCLK_GENCTRL_GENEN | + GCLK_GENCTRL1_DIV(config->div); + + + if (config->idc) + { + regval |= GCLK_GENCTRL_IDC; + } + + if (config->oov) + { + regval |= GCLK_GENCTRL_OOV; + } + + if (config->oe) + { + regval |= GCLK_GENCTRL_OE; + } + + if (config->divsel) + { + regval |= GCLK_GENCTRL_DIVSEL; + } + + if (config->runstdby) + { + regval |= GCLK_GENCTRL_RUNSTDBY; + } + } + else + { + /* Disable the GLCK */ + + regval = 0; + } + + /* Write the GCLK configuration */ + + putreg32(regval, regaddr); +} + +/**************************************************************************** + * Name: sam_gclkset_configure + * + * Description: + * Configure a set of GLCKs + * + ****************************************************************************/ + +static void sam_gclkset_configure(uint16_t gclkset, + const struct sam_gclk_config_s *config) +{ + uint16_t mask; + int gclk; + + /* Try every GCLK */ + + for (gclk = 0; gclk < SAM_NGLCK && gclkset != 0; gclk++) + { + /* Check if this one is in the set */ + + mask = 1 << gclk; + if ((gclkset & mask) != 0) + { + /* Yes.. Remove it from the set and configure it */ + + gclkset &= ~mask; + sam_gclk_configure(SAM_GCLK_GENCTRL(gclk), &config[gclk]); + } + } +} + /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: sam_clockconfig + * Name: sam_clock_configure * * Description: - * Called to establish the clock settings based on the values in board.h. + * Configure the clock sub-system per the provided configuration data. * - * Input Parameters: - * None - * - * Returned Value: - * None + * This should be called only (1) early in the initialization sequence, or + * (2) later but within a critical section. * ****************************************************************************/ -void sam_clockconfig(void) +void sam_clock_configure(const struct sam_clockconfig_s *config) { - /* Clear pending interrupt status. */ + /* Check if the clock frequency is increasing or decreasing */ - putreg32(OSCCTRL_INT_ALL, SAM_OSCCTRL_INTFLAG); - putreg32(OSC32KCTRL_INT_ALL, SAM_OSC32KCTRL_INTFLAG); - putreg32(SUPC_INT_ALL, SAM_SUPC_INTFLAG); + if (config->cpu_frequency > g_cpu_frequency) + { + /* Increasing. The number of waits states should be larger. Set the + * new number of wait states before configuring the clocking. + */ - /* Set FLASH wait states */ + sam_set_waitsates(config); + } - sam_flash_waitstates(); +#if BOARD_HAVE_XOSC32K != 0 + /* Configure XOSC32 */ - /* Switch to PL2 to be sure configuration of GCLK0 is safe */ - - sam_performance_level(PM_PLCFG_PLSEL_PL2); - - /* Configure XOSC */ - - sam_xosc_config(); - - /* Configure XOSC32K */ - - sam_xosc32k_config(); - - /* Configure OSCK32K */ - - sam_osc32k_config(); - - /* Configure OSCULPK32K */ - - sam_osculp32k_config(); - - /* Configure OSC16M */ - - sam_osc16m_config(); - - /* Configure DFLL48M */ - - sam_dfll48m_config(); - - /* Configure GCLK(s) */ - - sam_config_gclks(); - - /* Enable DFLL reference clock if the DFLL is enabled in closed loop mode */ - - sam_dfll48m_refclk(); - - /* Enable DFLL48M */ - - sam_dfll48m_enable(); - - /* Enable FDPLL reference clock if the DFLL is enabled */ - - sam_fdpll96m_refclk(); - - /* Configure and enable FDPLL96M */ - - sam_fdpll96m_config(); - - /* Setup CPU and BUS clocks */ - - sam_cpu_dividers(); - - /* Configure the GCLK_MAIN last as it may depend on the DFLL, FDPLL or - * other generators - */ - - sam_gclk_config(&g_gclkconfig[0]); - -#if BOARD_CPU_FREQUENCY <= 12000000 - /* If CPU frequency is less than 12MHz, scale down performance level to - * PL0. - */ - - sam_performance_level(PM_PLCFG_PLSEL_PL0); + sam_xosc32k_configure(&config->xosc32k); #endif - /* Set up initial peripheral clocking */ +#if BOARD_HAVE_XOSC0 != 0 + /* Configure XOSC0 */ - sam_periph_clocks(); + sam_xosc0_configure(&config->xosc0); +#endif + +#if BOARD_HAVE_XOSC1 != 0 + /* Configure XOSC1 */ + + sam_xosc1_configure(&config->xosc1); +#endif + + /* Configure master clock generator */ + + sam_mclk_configure(config->cpudiv); + + /* Pre-configure some GCLKs before configuring the FDPLLs */ + + sam_gclkset_configure(config->glckset1, config->gclk); + + /* Configure the FDPLLs */ + + sam_fdpll_configure(config->fdpll); + + /* Configure the renaming GCLKs before configuring the FDPLLs */ + + sam_gclkset_configure(config->glckset2, config->gclk); + + /* Check if the clock frequency is increasing or decreasing */ + + if (config->cpu_frequency < g_cpu_frequency) + { + /* Decreasing. The number of waits states should be smaller. Set the + * new number of wait states after configuring the clocking. + */ + + sam_set_waitsates(config); + } +} + +/**************************************************************************** + * Name: sam_clock_initialize + * + * Description: + * Configure the initial power-up clocking. This function may be called + * only once by the power-up reset logic. + * + ****************************************************************************/ + +void sam_clock_initialize(void) +{ + /* Clear .bss used by this file in case it is called before .bss is + * initialized. + */ + + g_cpu_frequency = 0; + sam_clock_configure(&g_initial_clocking); } diff --git a/arch/arm/src/samd5e5/sam_clockconfig.h b/arch/arm/src/samd5e5/sam_clockconfig.h index 59526568e7f..6a0a83ebe52 100644 --- a/arch/arm/src/samd5e5/sam_clockconfig.h +++ b/arch/arm/src/samd5e5/sam_clockconfig.h @@ -50,6 +50,118 @@ * Public Types ************************************************************************************/ +#ifdef BOARD_HAVE_CLKDEFS +/* This structure defines the configuration of the 32.768KHz XOSC32 */ + +struct sam_xosc32_config_s +{ + uint8_t enable : 1; /* True: Enable XOSC32 */ + uint8_t highspeed : 1; /* Controls gain of the external oscillator */ + uint8_t extalen : 1; /* Crystal oscillator enable + * false: External clock connected on XIN32 + * true: Crystal connected to XIN32/XOUT32 */ + uint8_t en32k : 1; /* Enable 32KHz output */ + uint8_t en1k : 1; /* Enable 1KHz output */ + uint8_t runstdby : 1; /* Run in standby */ + uint8_t ondemand : 1; /* On-demand control */ + uint8_t cfden : 1; /* Clock failure detection */ + uint8_t cfdeo : 1; /* Clock failure event enable */ + uint8_t caliben : 1; /* OSCULP32K calibration enable */ + uint8_t startup; /* Start-up time: + * 0: 62592us 4: 2000092us + * 1: 125092us 5: 4000092us + * 2: 500092us 6: 8000092us + * 3: 1000092us */ + uint8_t calib; /* OSCULP32K calibration value (0-31) */ + uint8_t rtcsel; /* RTC clock selection + * 0 ULP1K 1.024kHz from 32KHz internal ULP + * oscillator + * 1 ULP32K 32.768kHz from 32KHz internal ULP + * oscillator + * 4 XOSC1K 1.024kHz from 32KHz external + * oscillator + * 5 XOSC32K 32.768kHz from 32KHz external crystal + * oscillator */ +}; + +/* This structure defines the configuration of XOSC0/1 */ + +struct sam_xosc_config_s +{ + uint8_t enable : 1; /* True: Enable XOSC32 */ + uint8_t extalen : 1; /* Crystal oscillator enable + * false: External clock connected + * true: Crystal connected */ + uint8_t runstdby : 1; /* Run in standby */ + uint8_t ondemand : 1; /* On-demand control */ + uint8_t lowgain : 1; /* Low buffer gain enable */ + uint8_t enalc : 1; /* Automatic loop control enable */ + uint8_t cfden : 1; /* Clock failure detection */ + uint8_t swben : 1; /* XOSC clock switch enable */ + uint8_t startup; /* Start-up time: + * 0 31us 8 7813us + * 1 61us 9 15625us + * 2 122us 10 31250us + * 3 244us 11 62500us + * 4 488us 12 125000us + * 5 977us 13 250000us + * 6 1953us 14 500000us + * 7 3906us 15 1000000us */ + uint32_t xosc_frequency; /* XOSC frequency */ +}; + +/* This structure defines the configuration of the FDPLL0/1 */ + +struct sam_fdpll_config_s +{ +}; + +/* This structure defines the configuration of a GCLK */ + +struct sam_gclk_config_s +{ + uint8_t enable : 1; /* True: Enable GCLK */ + uint8_t idc : 1; /* True: Improve duty cycle */ + uint8_t oov : 1; /* True: Clock output selection */ + uint8_t oe : 1; /* True: Output enable */ + uint8_t divsel : 1; /* True: Clock source divider */ + uint8_t runstdby : 1; /* Run in standby */ + uint8_t source; /* GLCK clock source: + * 0 XOSC 0 oscillator input + * 1 XOSC 1 oscillator input + * 2 Generator input pad + * 3 Generic clock generator 1 output + * 4 OSCULP32K oscillator output + * 5 XOSC32K oscillator output + * 6 DFLL oscillator output + * 7 DPLL0 output + * 8 DPLL1 output */ + uint16_t div; /* Division factor: 8-bits for all but GCLK1 */ +}; + +/* This structure defines the configuration of the clock sus-system */ + +struct sam_clockconfig_s +{ + uint8_t waitstates; /* NVM read wait states 9-15 */ + uint8_t cpudiv; /* MCLK divider to get CPU frequency */ + uint16_t glckset1; /* GLCKs to initialize prior to FDPLL init */ + uint16_t glckset2; /* GLCKs to initialize after to FDPLL init */ + uint32_t cpu_frequency; /* Resulting CPU frequency */ +#if BOARD_HAVE_XOSC32K != 0 + struct sam_xosc32_config_s xosc32k; /* XOSC32 configuration */ +#endif +#if BOARD_HAVE_XOSC0 != 0 + struct sam_xosc_config_s xosc0; /* XOSC0 configuration */ +#endif +#if BOARD_HAVE_XOSC1 != 0 + struct sam_xosc_config_s xosc1; /* XOSC1 configuration */ +#endif + struct sam_fdpll_config_s fdpll[2]; /* FDPLL0/1 configurations */ + struct sam_gclk_config_s gclk[12]; /* GLCK configurations */ +}; +#endif /* BOARD_HAVE_CLKDEFS */ + /************************************************************************************ * Inline Functions ************************************************************************************/ @@ -74,16 +186,29 @@ extern "C" ************************************************************************************/ /************************************************************************************ - * Name: sam_clockconfig + * Name: sam_clock_configure * * Description: - * Called to initialize the SAM3/4. This does whatever setup is needed to put the - * SoC in a usable state. This includes the initialization of clocking using the - * settings in board.h. + * Configure the clock sub-system per the provided configuration data. + * + * This should be called only (1) early in the initialization sequence, or (2) + * later but within a critical section. * ************************************************************************************/ -void sam_clockconfig(void); +struct sam_clockconfig_s; +void sam_clock_configure(const struct sam_clockconfig_s *config); + +/************************************************************************************ + * Name: sam_clock_initialize + * + * Description: + * Configure the initial power-up clocking. This function may be called + * only once by the power-up reset logic. + * + ************************************************************************************/ + +void sam_clock_initialize(void); #undef EXTERN #if defined(__cplusplus) diff --git a/arch/arm/src/samd5e5/sam_eic.c b/arch/arm/src/samd5e5/sam_eic.c index 6d6d6dd0c44..a740f8abcf7 100644 --- a/arch/arm/src/samd5e5/sam_eic.c +++ b/arch/arm/src/samd5e5/sam_eic.c @@ -39,8 +39,10 @@ #include +#include #include #include +#include #include "up_arch.h" #include "sam_gclk.h" @@ -97,7 +99,7 @@ void sam_eic_dumpregs(void) { irqinfo("EIC:\n"); irqinfo(" CTRLA: %02x\n", getreg8(SAM_EIC_CTRLA)); - irqinfo(" NMICTRL: %02x\n", getreg8(SAM_EIC_NVMICTRL)); + irqinfo(" NMICTRL: %02x\n", getreg8(SAM_EIC_NMICTRL)); irqinfo(" NMIFLAG: %04x\n", getreg16(SAM_EIC_NMIFLAG)); irqinfo(" SYNCBUSY: %08x\n", getreg32(SAM_EIC_SYNCBUSY)); irqinfo(" EVCTRL: %08x\n", getreg32(SAM_EIC_EVCTRL)); @@ -128,21 +130,27 @@ void sam_eic_dumpregs(void) int sam_eic_initialize(void) { - uint16_t regval; + uintptr_t regaddr; + uint32_t regval; /* Configure the EIC APB clock */ sam_apb_eic_enableperiph(); - regval = GCLK_CLKCTRL_ID_EIC | - GCLK_CLKCTRL_GEN(CONFIG_SAMD5E5_EIC_GCLKGEN) | - GCLK_CLKCTRL_CLKEN; + /* Use the selected GCLK_EIC. Some optional functions need a peripheral + * clock, which can either be a generic clock (GCLK_EIC, for wider + * frequency selection) or a Ultra Low Power 32KHz clock (CLK_ULP32K, for + * highest power efficiency). One of the clock sources must be configured + * and enabled before using the peripheral. + */ - putreg16(regval, SAM_GCLK_CLKCTRL); + regaddr = SAM_GCLK_PCHCTRL(GCLK_CHAN_EIC); + regval = GCLK_PCHCTRL_GEN(BOARD_GLCK_EIC) | GCLK_PCHCTRL_CHEN; + putreg32(regval, regaddr); - /* Enable the EIC APB clock */ + /* Enable the EIC, selecting clocking via the GLCK_EIC */ - putreg8(EIC_CTRLA_ENABLE, SAM_EIC_CTRLA); + putreg8(EIC_CTRLA_ENABLE | EIC_CTRLA_ENABLE, SAM_EIC_CTRLA); sam_eic_syncwait(); sam_eic_dumpregs(); @@ -241,6 +249,7 @@ int sam_eic_irq_ack(int irq) int eirq = irq - SAM_IRQ_EXTINT0; putreg32(EIC_EXTINT(eirq), SAM_EIC_INTENCLR); + return OK; } #endif /* CONFIG_SAMD5E5_EIC */ diff --git a/arch/arm/src/samd5e5/sam_lowputc.c b/arch/arm/src/samd5e5/sam_lowputc.c index e7b46bb3669..f194da4a497 100644 --- a/arch/arm/src/samd5e5/sam_lowputc.c +++ b/arch/arm/src/samd5e5/sam_lowputc.c @@ -293,18 +293,10 @@ int sam_usart_internal(const struct sam_usart_config_s * const config) /* Configure the GCLKs for the SERCOM module */ - sercom_coreclk_configure(config->sercom, config->gclkgen, false); + sercom_coreclk_configure(config->sercom, config->coregen, false); - if (config->sercom == 5) - { - channel = GCLK_CHAN_SERCOM5_CORE; - } - else - { - channel = config->sercom + GCLK_CHAN_SERCOM0_CORE; - } - - sam_gclk_chan_enable(channel, config->gclkgen); + channel = config->sercom + GCLK_CHAN_SERCOM0_CORE; + sam_gclk_chan_enable(channel, config->coregen); sercom_slowclk_configure(config->sercom, config->slowgen); diff --git a/arch/arm/src/samd5e5/sam_sercom.h b/arch/arm/src/samd5e5/sam_sercom.h index 103472ec8c3..60c51317703 100644 --- a/arch/arm/src/samd5e5/sam_sercom.h +++ b/arch/arm/src/samd5e5/sam_sercom.h @@ -47,7 +47,6 @@ #include "up_arch.h" #include "sam_config.h" #include "sam_periphclks.h" -#include "chip/sam_sercom.h" /**************************************************************************** * Pre-processor Definitions diff --git a/arch/arm/src/samd5e5/sam_serial.c b/arch/arm/src/samd5e5/sam_serial.c index 5b59c4c4cb7..d5a2ff30365 100644 --- a/arch/arm/src/samd5e5/sam_serial.c +++ b/arch/arm/src/samd5e5/sam_serial.c @@ -782,16 +782,21 @@ static int sam_attach(struct uart_dev_s *dev) const struct sam_usart_config_s * const config = priv->config; int ret; - /* Attach and enable the IRQ */ + /* Attach and enable the Tx and Rx IRQs */ - ret = irq_attach(config->irq, sam_interrupt, dev); + ret = irq_attach(config->txirq, sam_interrupt, dev); if (ret == OK) { - /* Enable the interrupt (RX and TX interrupts are still disabled - * in the USART - */ + ret = irq_attach(config->rxirq, sam_interrupt, dev); + if (ret == OK) + { + /* Enable the interrupt (RX and TX interrupts are still disabled + * in the USART + */ - up_enable_irq(config->irq); + up_enable_irq(config->txirq); + up_enable_irq(config->rxirq); + } } return ret; @@ -815,11 +820,13 @@ static void sam_detach(struct uart_dev_s *dev) /* Disable interrupts at the SERCOM device and at the NVIC */ sam_disableallints(priv); - up_disable_irq(config->irq); + up_disable_irq(config->txirq); + up_disable_irq(config->rxirq); /* Detach the interrupt handler */ - irq_detach(config->irq); + irq_detach(config->txirq); + irq_detach(config->rxirq); } /**************************************************************************** diff --git a/arch/arm/src/samd5e5/sam_start.c b/arch/arm/src/samd5e5/sam_start.c index 239f9db41e0..b1ea7532dc3 100644 --- a/arch/arm/src/samd5e5/sam_start.c +++ b/arch/arm/src/samd5e5/sam_start.c @@ -94,7 +94,7 @@ const uintptr_t g_idle_topstack = HEAP_BASE; ****************************************************************************/ #ifdef CONFIG_ARCH_FPU -static inline void sam_fpuconfig(void); +static inline void sam_fpu_configure(void); #endif #ifdef CONFIG_STACK_COLORATION static void go_os_start(void *pv, unsigned int nbytes) @@ -126,7 +126,7 @@ void __start(void) __attribute__ ((no_instrument_function)); #endif /**************************************************************************** - * Name: sam_fpuconfig + * Name: sam_fpu_configure * * Description: * Configure the FPU. Relative bit settings: @@ -151,7 +151,7 @@ void __start(void) __attribute__ ((no_instrument_function)); #ifdef CONFIG_ARCH_FPU #ifndef CONFIG_ARMV7M_LAZYFPU -static inline void sam_fpuconfig(void) +static inline void sam_fpu_configure(void) { uint32_t regval; @@ -181,7 +181,7 @@ static inline void sam_fpuconfig(void) #else -static inline void sam_fpuconfig(void) +static inline void sam_fpu_configure(void) { uint32_t regval; @@ -212,7 +212,7 @@ static inline void sam_fpuconfig(void) #endif #else -# define sam_fpuconfig() +# define sam_fpu_configure() #endif /**************************************************************************** @@ -312,10 +312,12 @@ void __start(void) } #endif - /* Configure the UART so that we can get debug output as soon as possible */ + /* Initialize clocking and the FPU. Configure the console UART so that + * we can get debug output as soon as possible. + */ - sam_clockconfig(); - sam_fpuconfig(); + sam_clock_initialize(); + sam_fpu_configure(); sam_lowsetup(); showprogress('A'); diff --git a/arch/arm/src/samd5e5/sam_usart.c b/arch/arm/src/samd5e5/sam_usart.c index 90ece6460b4..0cef4cba808 100644 --- a/arch/arm/src/samd5e5/sam_usart.c +++ b/arch/arm/src/samd5e5/sam_usart.c @@ -42,10 +42,13 @@ #include #include +#include #include -#include "sam_pinmap.h" +#include "chip/sam_memorymap.h" +#include "chip/sam_pinmap.h" #include "sam_gclk.h" +#include "sam_sercom.h" #include "sam_usart.h" #include @@ -64,9 +67,10 @@ const struct sam_usart_config_s g_usart0config = .sercom = 0, .parity = CONFIG_USART0_PARITY, .bits = CONFIG_USART0_BITS, - .irq = SAM_IRQ_SERCOM0, - .gclkgen = BOARD_SERCOM0_GCLKGEN, - .slowgen = BOARD_SERCOM0_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM0, + .rxirq = BOARD_RXIRQ_SERCOM0, + .coregen = BOARD_SERCOM0_COREGEN, + .slowgen = BOARD_SERCOM0_SLOWGEN, .stopbits2 = CONFIG_USART0_2STOP, .baud = CONFIG_USART0_BAUD, .pad0 = BOARD_SERCOM0_PINMAP_PAD0, @@ -85,9 +89,10 @@ const struct sam_usart_config_s g_usart1config = .sercom = 1, .parity = CONFIG_USART1_PARITY, .bits = CONFIG_USART1_BITS, - .irq = SAM_IRQ_SERCOM1, - .gclkgen = BOARD_SERCOM1_GCLKGEN, - .slowgen = BOARD_SERCOM1_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM1, + .rxirq = BOARD_RXIRQ_SERCOM1, + .coregen = BOARD_SERCOM1_COREGEN, + .slowgen = BOARD_SERCOM1_SLOWGEN, .stopbits2 = CONFIG_USART1_2STOP, .baud = CONFIG_USART1_BAUD, .pad0 = BOARD_SERCOM1_PINMAP_PAD0, @@ -106,9 +111,10 @@ const struct sam_usart_config_s g_usart2config = .sercom = 2, .parity = CONFIG_USART2_PARITY, .bits = CONFIG_USART2_BITS, - .irq = SAM_IRQ_SERCOM2, - .gclkgen = BOARD_SERCOM2_GCLKGEN, - .slowgen = BOARD_SERCOM2_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM2, + .rxirq = BOARD_RXIRQ_SERCOM2, + .coregen = BOARD_SERCOM2_COREGEN, + .slowgen = BOARD_SERCOM2_SLOWGEN, .stopbits2 = CONFIG_USART2_2STOP, .baud = CONFIG_USART2_BAUD, .pad0 = BOARD_SERCOM2_PINMAP_PAD0, @@ -127,9 +133,10 @@ const struct sam_usart_config_s g_usart3config = .sercom = 3, .parity = CONFIG_USART3_PARITY, .bits = CONFIG_USART3_BITS, - .irq = SAM_IRQ_SERCOM3, - .gclkgen = BOARD_SERCOM3_GCLKGEN, - .slowgen = BOARD_SERCOM3_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM3, + .rxirq = BOARD_RXIRQ_SERCOM3, + .coregen = BOARD_SERCOM3_COREGEN, + .slowgen = BOARD_SERCOM3_SLOWGEN, .stopbits2 = CONFIG_USART3_2STOP, .baud = CONFIG_USART3_BAUD, .pad0 = BOARD_SERCOM3_PINMAP_PAD0, @@ -148,9 +155,10 @@ const struct sam_usart_config_s g_usart4config = .sercom = 4, .parity = CONFIG_USART4_PARITY, .bits = CONFIG_USART4_BITS, - .irq = SAM_IRQ_SERCOM4, - .gclkgen = BOARD_SERCOM4_GCLKGEN, - .slowgen = BOARD_SERCOM4_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM4, + .rxirq = BOARD_RXIRQ_SERCOM4, + .coregen = BOARD_SERCOM4_COREGEN, + .slowgen = BOARD_SERCOM4_SLOWGEN, .stopbits2 = CONFIG_USART4_2STOP, .baud = CONFIG_USART4_BAUD, .pad0 = BOARD_SERCOM4_PINMAP_PAD0, @@ -169,9 +177,10 @@ const struct sam_usart_config_s g_usart5config = .sercom = 5, .parity = CONFIG_USART5_PARITY, .bits = CONFIG_USART5_BITS, - .irq = SAM_IRQ_SERCOM5, - .gclkgen = BOARD_SERCOM5_GCLKGEN, - .slowgen = BOARD_SERCOM5_SLOW_GCLKGEN, + .txirq = BOARD_TXIRQ_SERCOM5, + .rxirq = BOARD_RXIRQ_SERCOM5, + .coregen = BOARD_SERCOM5_COREGEN, + .slowgen = BOARD_SERCOM5_SLOWGEN, .stopbits2 = CONFIG_USART5_2STOP, .baud = CONFIG_USART5_BAUD, .pad0 = BOARD_SERCOM5_PINMAP_PAD0, @@ -184,6 +193,50 @@ const struct sam_usart_config_s g_usart5config = }; #endif +#ifdef SAMD5E5_HAVE_USART6 +const struct sam_usart_config_s g_usart6config = +{ + .sercom = 6, + .parity = CONFIG_USART6_PARITY, + .bits = CONFIG_USART6_BITS, + .txirq = BOARD_TXIRQ_SERCOM6, + .rxirq = BOARD_RXIRQ_SERCOM6, + .coregen = BOARD_SERCOM6_COREGEN, + .slowgen = BOARD_SERCOM6_SLOWGEN, + .stopbits2 = CONFIG_USART6_2STOP, + .baud = CONFIG_USART6_BAUD, + .pad0 = BOARD_SERCOM6_PINMAP_PAD0, + .pad1 = BOARD_SERCOM6_PINMAP_PAD1, + .pad2 = BOARD_SERCOM6_PINMAP_PAD2, + .pad3 = BOARD_SERCOM6_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM6_MUXCONFIG, + .frequency = BOARD_SERCOM6_FREQUENCY, + .base = SAM_SERCOM6_BASE, +}; +#endif + +#ifdef SAMD5E5_HAVE_USART7 +const struct sam_usart_config_s g_usart7config = +{ + .sercom = 7, + .parity = CONFIG_USART7_PARITY, + .bits = CONFIG_USART7_BITS, + .txirq = BOARD_TXIRQ_SERCOM7, + .rxirq = BOARD_RXIRQ_SERCOM7, + .coregen = BOARD_SERCOM7_COREGEN, + .slowgen = BOARD_SERCOM7_SLOWGEN, + .stopbits2 = CONFIG_USART7_2STOP, + .baud = CONFIG_USART7_BAUD, + .pad0 = BOARD_SERCOM7_PINMAP_PAD0, + .pad1 = BOARD_SERCOM7_PINMAP_PAD1, + .pad2 = BOARD_SERCOM7_PINMAP_PAD2, + .pad3 = BOARD_SERCOM7_PINMAP_PAD3, + .muxconfig = BOARD_SERCOM7_MUXCONFIG, + .frequency = BOARD_SERCOM7_FREQUENCY, + .base = SAM_SERCOM7_BASE, +}; +#endif + const struct sam_usart_config_s *g_usartconfig[SAMD5E5_NSERCOM] = { #if SAMD5E5_NSERCOM > 0 diff --git a/arch/arm/src/samd5e5/sam_usart.h b/arch/arm/src/samd5e5/sam_usart.h index 7fd4101c9cf..afdffb5086d 100644 --- a/arch/arm/src/samd5e5/sam_usart.h +++ b/arch/arm/src/samd5e5/sam_usart.h @@ -89,8 +89,9 @@ struct sam_usart_config_s uint8_t sercom; /* Identifies the SERCOM peripheral */ uint8_t parity; /* 0=none, 1=odd, 2=even */ uint8_t bits; /* Number of bits (5-9) */ - uint8_t irq; /* SERCOM IRQ number */ - uint8_t gclkgen; /* Source GCLK generator */ + uint8_t txirq; /* Tx SERCOM IRQ number */ + uint8_t rxirq; /* Rx SERCOM IRQ number */ + uint8_t coregen; /* Core GCLK generator */ uint8_t slowgen; /* Slow GCLK generator */ bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ uint32_t baud; /* Configured baud */ diff --git a/configs/metro-m4/include/board.h b/configs/metro-m4/include/board.h index 36821b80391..094537bf47e 100644 --- a/configs/metro-m4/include/board.h +++ b/configs/metro-m4/include/board.h @@ -52,445 +52,217 @@ ************************************************************************************/ /* Clocking *************************************************************************/ -/* Overview - * - * Since there is no high speed crystal, we will run from the OSC16M clock source. - * We will use its default, POR frequency of 4MHz to avoid an additional clock - * switch. - * - * OSC16M Output = 4MHz - * `- GCLK1 Input = 4MHz Prescaler = 1 output = 4MHz - * `- DFLL Input = 4MHz Multiplier = 12 output = 48MHz - * `- GCLK0 Input = 48MHz Prescaler = 1 output = 48MHz - * `- MCLK Input = 48Mhz CPU divider = 1 CPU frequency = 48MHz - * APBA divider = 1 APBA frequency = 48MHz - * APBB divider = 1 APBB frequency = 48MHz - * APBC divider = 1 APBC frequency = 48MHz - * APBD divider = 1 APBD frequency = 48MHz - * APBE divider = 1 APBE frequency = 48MHz - * - * The Adafruit Metro M4 has one on-board crystal: - * - * X4 32.768KHz XOSC32 - * - * REVISIT: Not currently used, may want to use as GCLK1 source with - * DFLL multiplier of ((48000000+16384)/32768) = 1465 which would yield - * a clock of 48,005,120 MHz. - */ -/* XOSC Configuration -- Not available - * - * BOARD_XOSC_ENABLE - Boolean (defined / not defined) - * BOARD_XOSC_FREQUENCY - In Hz - * BOARD_XOSC_STARTUPTIME - See SYSCTRL_XOSC_STARTUP_* definitions - * BOARD_XOSC_ISCRYSTAL - Boolean (defined / not defined) - * BOARD_XOSC_AMPGC - Boolean (defined / not defined) - * BOARD_XOSC_ONDEMAND - Boolean (defined / not defined) - * BOARD_XOSC_RUNINSTANDBY - Boolean (defined / not defined) - */ +#define BOARD_HAVE_CLKDEFS 1 -#undef BOARD_XOSC_ENABLE -#define BOARD_XOSC_FREQUENCY 12000000UL -#define BOARD_XOSC_STARTUPTIME SYSCTRL_XOSC_STARTUP_1S -#define BOARD_XOSC_ISCRYSTAL 1 -#define BOARD_XOSC_AMPGC 1 -#define BOARD_XOSC_ONDEMAND 1 -#undef BOARD_XOSC_RUNINSTANDBY +/* XOSC32 */ -/* XOSC32 Configuration -- Not used - * - * BOARD_XOSC32K_ENABLE - Boolean (defined / not defined) - * BOARD_XOSC32K_FREQUENCY - In Hz - * BOARD_XOSC32K_STARTUPTIME - See SYSCTRL_XOSC32K_STARTUP_* definitions - * BOARD_XOSC32K_ISCRYSTAL - Boolean (defined / not defined) - * BOARD_XOSC32K_AAMPEN - Boolean (defined / not defined) - * BOARD_XOSC32K_EN1KHZ - Boolean (defined / not defined) - * BOARD_XOSC32K_EN32KHZ - Boolean (defined / not defined) - * BOARD_XOSC32K_ONDEMAND - Boolean (defined / not defined) - * BOARD_XOSC32K_RUNINSTANDBY - Boolean (defined / not defined) - * BOARD_XOSC32K_WRITELOCK - Boolean (defined / not defined) - */ +#define BOARD_HAVE_XOSC32K 1 /* 32.768KHz XOSC32 crystal installed */ +#define BOARD_XOSC32K_ENABLE false /* Don't enable XOSC32 */ +#define BOARD_XOSC32K_XTALEN false /* External clock connected on XIN32 */ +#define BOARD_XOSC32K_EN32K false /* No 32KHz output */ +#define BOARD_XOSC32K_EN1K false /* No 1KHz output */ +#define BOARD_XOSC32K_HIGHSPEED true /* High speed mode */ +#define BOARD_XOSC32K_RUNSTDBY false /* Don't run in standby */ +#define BOARD_XOSC32K_ONDEMAND true /* Enable on-demand control */ +#define BOARD_XOSC32K_CFDEN false /* Clock failure detector not enabled */ +#define BOARD_XOSC32K_CFDEO false /* No clock failure event */ +#define BOARD_XOSC32K_CALIBEN false /* No OSCULP32K calibration */ +#define BOARD_XOSC32K_STARTUP 0 /* Startup time: 62592us */ +#define BOARD_XOSC32K_CALIB 0 /* Dummy OSCULP32K calibration value */ +#define BOARD_XOSC32K_RTCSEL 0 /* RTC clock = ULP1K */ +#define BOARD_XOSC32K_FREQUENCY 32768 /* XOSC32K frequency 32.768 KHz */ -#undef BOARD_XOSC32K_ENABLE -#ifdef CONFIG_METRO_M4_XOSC32K -# define BOARD_XOSC32K_ENABLE 1 -# define BOARD_XOSC32K_FREQUENCY 32768 /* 32.768KHz XTAL */ -# define BOARD_XOSC32K_STARTUPTIME OSC32KCTRL_XOSC32K_STARTUP_100MS -# define BOARD_XOSC32K_ISCRYSTAL 1 -# undef BOARD_XOSC32K_EN1KHZ -# define BOARD_XOSC32K_EN32KHZ 1 -# define BOARD_XOSC32K_ONDEMAND 1 -# undef BOARD_XOSC32K_RUNINSTANDBY -# undef BOARD_XOSC32K_WRITELOCK -#endif +/* XOSC0 */ -/* OSC32 Configuration -- not used - * - * BOARD_OSC32K_ENABLE - Boolean (defined / not defined) - * BOARD_OSC32K_FREQUENCY - In Hz - * BOARD_OSC32K_STARTUPTIME - See SYSCTRL_OSC32K_STARTUP_* definitions - * BOARD_OSC32K_EN1KHZ - Boolean (defined / not defined) - * BOARD_OSC32K_EN32KHZ - Boolean (defined / not defined) - * BOARD_OSC32K_ONDEMAND - Boolean (defined / not defined) - * BOARD_OSC32K_RUNINSTANDBY - Boolean (defined / not defined) - * BOARD_OSC32K_WRITELOCK - Boolean (defined / not defined) - */ +#define BOARD_HAVE_XOSC0 0 /* No XOSC0 clock/crystal installed */ +#define BOARD_XOSC0_ENABLE false /* Don't enable XOSC0 */ +#define BOARD_XOSC0_XTALEN false /* External clock connected */ +#define BOARD_XOSC0_RUNSTDBY false /* Don't run in standby */ +#define BOARD_XOSC0_ONDEMAND true /* Disable on-demand control */ +#define BOARD_XOSC0_LOWGAIN false /* Disable low buffer gain */ +#define BOARD_XOSC0_ENALC false /* Disable automatic loop control */ +#define BOARD_XOSC0_CFDEN false /* Clock failure detector not enabled */ +#define BOARD_XOSC0_SWBEN false /* XOSC clock switch not enabled */ +#define BOARD_XOSC0_STARTUP 0 /* XOSC0 start-up time 31µs */ +#define BOARD_XOSC0_FREQUENCY 12000000 /* XOSC0 frequency 12MHz */ -#undef BOARD_OSC32K_ENABLE -#define BOARD_OSC32K_FREQUENCY 32768 /* 32.768kHz internal oscillator */ -#define BOARD_OSC32K_STARTUPTIME SYSCTRL_OSC32K_STARTUP_4MS -#define BOARD_OSC32K_EN1KHZ 1 -#define BOARD_OSC32K_EN32KHZ 1 -#define BOARD_OSC32K_ONDEMAND 1 -#undef BOARD_OSC32K_RUNINSTANDBY -#undef BOARD_OSC32K_WRITELOCK +/* XOSC1 */ -/* OSC16M Configuration -- always enabled - * - * BOARD_OSC16M_FSEL - See OSCCTRL_OSC16MCTRL_FSEL_* definitions - * BOARD_OSC16M_ONDEMAND - Boolean (defined / not defined) - * BOARD_OSC16M_RUNINSTANDBY - Boolean (defined / not defined) - */ +#define BOARD_HAVE_XOSC1 0 /* No XOSC0 clock/crystal installed */ +#define BOARD_XOSC1_ENABLE false /* Don't enable XOSC1 */ +#define BOARD_XOSC1_XTALEN true /* External crystal connected */ +#define BOARD_XOSC1_RUNSTDBY false /* Don't run in standby */ +#define BOARD_XOSC1_ONDEMAND true /* Disable on-demand control */ +#define BOARD_XOSC1_LOWGAIN false /* Disable low buffer gain */ +#define BOARD_XOSC1_ENALC false /* Disable automatic loop control */ +#define BOARD_XOSC1_CFDEN false /* Clock failure detector not enabled */ +#define BOARD_XOSC1_SWBEN false /* XOSC clock switch not enabled */ +#define BOARD_XOSC1_STARTUP 0 /* XOSC0 start-up time 31µs */ +#define BOARD_XOSC1_FREQUENCY 12000000 /* XOSC0 frequency 12MHz */ +/* Master Clock (MCLK) */ -#if defined(CONFIG_METRO_M4_OSC16M_4MHZ) -# define BOARD_OSC16M_FSEL OSCCTRL_OSC16MCTRL_FSEL_4MHZ -# define BOARD_OSC16M_ONDEMAND 1 -# undef BOARD_OSC16M_RUNINSTANDBY -# define BOARD_OSC16M_FREQUENCY 4000000 /* 4MHz high-accuracy internal oscillator */ +#define BOARD_MCLK_CPUDIV 1 /* MCLK divder to get CPU frequency */ +#define BOARD_CPU_FREQUENCY 120000000 /* CPU frequency 120MHz */ -#elif defined(CONFIG_METRO_M4_OSC16M_8MHZ) -# define BOARD_OSC16M_FSEL OSCCTRL_OSC16MCTRL_FSEL_8MHZ -# define BOARD_OSC16M_ONDEMAND 1 -# undef BOARD_OSC16M_RUNINSTANDBY -# define BOARD_OSC16M_FREQUENCY 8000000 /* 8MHz high-accuracy internal oscillator */ +/* FDPLL0/1 -- To be provided */ -#elif defined(CONFIG_METRO_M4_OSC16M_12MHZ) -# define BOARD_OSC16M_FSEL OSCCTRL_OSC16MCTRL_FSEL_12MHZ -# define BOARD_OSC16M_ONDEMAND 1 -# undef BOARD_OSC16M_RUNINSTANDBY -# define BOARD_OSC16M_FREQUENCY 12000000 /* 12MHz high-accuracy internal oscillator */ +#define BOARD_FDPLL0_FREQUENCY 0 +#define BOARD_FDPLL1_FREQUENCY 0 -#elif defined(CONFIG_METRO_M4_OSC16M_16MHZ) -# define BOARD_OSC16M_FSEL OSCCTRL_OSC16MCTRL_FSEL_16MHZ -# define BOARD_OSC16M_ONDEMAND 1 -# undef BOARD_OSC16M_RUNINSTANDBY -# define BOARD_OSC16M_FREQUENCY 16000000 /* 18MHz high-accuracy internal oscillator */ +/* FDLL -- To be provided */ -#else -# error OSC16M operating freqency not defined (CONFIG_METRO_M4_OSC16M_*MHZ) -#endif +#define BOARD_DFLL_FREQUENCY 0 -/* OSCULP32K Configuration -- not used. */ +/* GCLK */ -#define BOARD_OSCULP32K_FREQUENCY 32000 /* 32kHz ultra-low-power internal oscillator */ +#define BOARD_GCLK_SET1 0x0000 /* The empty set */ +#define BOARD_GCLK_SET2 0x0fff /* All GCLKs */ -/* Digital Frequency Locked Loop configuration. In closed-loop mode, the - * DFLL output frequency (Fdfll) is given by: - * - * Fdfll = DFLLmul * Frefclk - * = 12 * 4000000 = 48MHz - * - * Where the reference clock is Generic Clock Channel 0 output of GLCK1. - * GCLCK1 provides OSC16M, undivided. - * - * When operating in open-loop mode, the output frequency of the DFLL will - * be determined by the values written to the DFLL Coarse Value bit group - * and the DFLL Fine Value bit group in the DFLL Value register. - * - * BOARD_DFLL48M_CLOSEDLOOP - Boolean (defined / not defined) - * BOARD_DFLL48M_OPENLOOP - Boolean (defined / not defined) - * BOARD_DFLL48M_RECOVERY - Boolean (defined / not defined) - * BOARD_DFLL48M_TRACKAFTERFINELOCK - Boolean (defined / not defined) - * BOARD_DFLL48M_KEEPLOCKONWAKEUP - Boolean (defined / not defined) - * BOARD_DFLL48M_ENABLECHILLCYCLE - Boolean (defined / not defined) - * BOARD_DFLL48M_QUICKLOCK - Boolean (defined / not defined) - * BOARD_DFLL48M_RUNINSTDBY - Boolean (defined / not defined) - * BOARD_DFLL48M_ONDEMAND - Boolean (defined / not defined) - * BOARD_DFLL48M_COARSEVALUE - Value - * BOARD_DFLL48M_FINEVALUE - Value - * - * Open Loop mode only: - * BOARD_DFLL48M_COARSEVALUE - Value - * BOARD_DFLL48M_FINEVALUE - Value - * - * Closed loop mode only: - * BOARD_DFLL48M_REFCLK_CLKGEN - GCLK index in the range {0..8} - * BOARD_DFLL48M_MULTIPLIER - Value - * BOARD_DFLL48M_MAXCOARSESTEP - Value - * BOARD_DFLL48M_MAXFINESTEP - Value - * - * BOARD_DFLL48M_FREQUENCY - The resulting frequency - */ +#define BOARD_GCLK0_ENABLE true /* Enable GCLK0 */ +#define BOARD_GCLK0_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK0_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK0_OE true /* Generate output on GCLK_IO */ +#define BOARD_GCLK0_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK0_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK0_SOURCE 7 /* Select DPLL0 output as GLCK0 source */ +#define BOARD_GCLK0_DIV 1 /* Division factor */ +#define BOARD_GCLK0_FREQUENCY BOARD_DPLL0_FREQUENCY -#undef BOARD_DFLL48M_ENABLE 1 /* Assume not using the DFLL48M */ -#undef BOARD_DFLL48M_CLOSEDLOOP -#undef BOARD_DFLL48M_OPENLOOP -#undef BOARD_DFLL48M_RECOVERY +#define BOARD_GCLK1_ENABLE true /* Enable GCLK1 */ +#define BOARD_GCLK1_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK1_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK1_OE true /* Generate output on GCLK_IO */ +#define BOARD_GCLK1_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK1_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK1_SOURCE 6 /* Select DFLL output as GLCK1 source */ +#define BOARD_GCLK1_DIV 1 /* Division factor */ +#define BOARD_GCLK1_FREQUENCY BOARD_DFLL_FREQUENCY -#ifdef CONFIG_METRO_M4_DFLL -# define BOARD_DFLL48M_ENABLE 1 /* Using the DFLL48M */ +#define BOARD_GCLK2_ENABLE false /* Don't enable GCLK2 */ +#define BOARD_GCLK2_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK2_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK2_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK2_DIVSEL 1 /* GCLK frequency is source/(2^(N+1) */ +#define BOARD_GCLK2_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK2_SOURCE 5 /* Select XOSC32K as GLCK2 source */ +#define BOARD_GCLK2_DIV 1 /* Division factor */ +#define BOARD_GCLK2_FREQUENCY (BOARD_XOSC32K_FREQUENCY / 4) -/* DFLL mode of operation */ +#define BOARD_GCLK3_ENABLE false /* Don't enable GCLK3 */ +#define BOARD_GCLK3_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK3_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK3_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK3_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK3_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK3_SOURCE 5 /* Select XOSC32K as GLCK3 source */ +#define BOARD_GCLK3_DIV 1 /* Division factor */ +#define BOARD_GCLK3_FREQUENCY BOARD_XOSC32K_FREQUENCY -# if defined(CONFIG_METRO_M4_DFLL_OPENLOOP) -# define BOARD_DFLL48M_OPENLOOP 1 /* In open loop mode */ -# elif defined(CONFIG_METRO_M4_DFLL_CLOSEDLOOP) -# define BOARD_DFLL48M_CLOSEDLOOP 1 /* In closed loop mode */ -# elif defined(CONFIG_METRO_M4_DFLL_RECOVERY) -# define BOARD_DFLL48M_RECOVERY 1 /* In USB recover mode */ -# else -# error DFLL mode not provided -# endif +#define BOARD_GCLK4_ENABLE true /* Enable GCLK4 */ +#define BOARD_GCLK4_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK4_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK4_OE true /* Generate output on GCLK_IO */ +#define BOARD_GCLK4_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK4_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK4_SOURCE 7 /* Select DPLL0 output as GLCK4 source */ +#define BOARD_GCLK4_DIV 1 /* Division factor */ +#define BOARD_GCLK4_FREQUENCY BOARD_DPLL0_FREQUENCY -/* DFLL source clock selection */ +#define BOARD_GCLK5_ENABLE true /* Enable GCLK5 */ +#define BOARD_GCLK5_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK5_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK5_OE true /* Generate output on GCLK_IO */ +#define BOARD_GCLK5_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK5_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK5_SOURCE 6 /* Select DFLL output as GLCK5 source */ +#define BOARD_GCLK5_DIV 24 /* Division factor */ +#define BOARD_GCLK5_FREQUENCY BOARD_DFLL_FREQUENCY -# if defined(CONFIG_METRO_M4_DFLL_OSC16MSRC) -# define BOARD_DFLL_SRC_FREQUENCY BOARD_OSC16M_FREQUENCY -# elif defined(CONFIG_METRO_M4_DFLL_XOSC32KSRC) -# define BOARD_DFLL_SRC_FREQUENCY BOARD_XOSC32K_FREQUENCY -# else -# error DFLL clock source not provided -# endif +#define BOARD_GCLK6_ENABLE false /* Don't enable GCLK6 */ +#define BOARD_GCLK6_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK6_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK6_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK6_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK6_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK6_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK6_DIV 1 /* Division factor */ +#define BOARD_GCLK6_FREQUENCY BOARD_XOSC1_FREQUENCY -/* Mode-independent options */ +#define BOARD_GCLK7_ENABLE false /* Don't enable GCLK7 */ +#define BOARD_GCLK7_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK7_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK7_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK7_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK7_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK7_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK7_DIV 1 /* Division factor */ +#define BOARD_GCLK7_FREQUENCY BOARD_XOSC1_FREQUENCY -# undef BOARD_DFLL48M_RUNINSTDBY -# undef BOARD_DFLL48M_ONDEMAND +#define BOARD_GCLK8_ENABLE false /* Don't enable GCLK8 */ +#define BOARD_GCLK8_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK8_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK8_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK8_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK8_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK8_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK8_DIV 1 /* Division factor */ +#define BOARD_GCLK8_FREQUENCY BOARD_XOSC1_FREQUENCY -/* DFLL open loop mode configuration */ +#define BOARD_GCLK9_ENABLE false /* Don't enable GCLK9 */ +#define BOARD_GCLK9_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK9_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK9_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK9_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK9_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK9_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK9_DIV 1 /* Division factor */ +#define BOARD_GCLK10_FREQUENCY BOARD_XOSC1_FREQUENCY -# define BOARD_DFLL48M_COARSEVALUE (0x1f / 4) -# define BOARD_DFLL48M_FINEVALUE (0xff / 4) +#define BOARD_GCLK10_ENABLE false /* Don't enable GCLK10 */ +#define BOARD_GCLK10_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK10_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK10_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK10_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK10_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK10_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK10_DIV 1 /* Division factor */ +#define BOARD_GCLK11_FREQUENCY BOARD_XOSC1_FREQUENCY -/* DFLL closed loop mode configuration */ +#define BOARD_GCLK11_ENABLE false /* Don't enable GCLK11 */ +#define BOARD_GCLK11_IDC false /* Don't improve duty cycle */ +#define BOARD_GCLK11_OOV false /* Clock output will be LOW */ +#define BOARD_GCLK11_OE false /* No generator output of GCLK_IO */ +#define BOARD_GCLK11_DIVSEL 0 /* GCLK frequency is source/DIV */ +#define BOARD_GCLK11_RUNSTDBY false /* Don't run in standby */ +#define BOARD_GCLK11_SOURCE 1 /* Select XOSC1 as GLCK5 source */ +#define BOARD_GCLK11_DIV 1 /* Division factor */ +#define BOARD_GCLK0_FREQUENCY BOARD_XOSC1_FREQUENCY -# define BOARD_DFLL48M_REFCLK_CLKGEN 1 -# define BOARD_DFLL48M_MULTIPLIER (48000000 / BOARD_DFLL_SRC_FREQUENCY) -# define BOARD_DFLL48M_QUICKLOCK 1 -# define BOARD_DFLL48M_TRACKAFTERFINELOCK 1 -# define BOARD_DFLL48M_KEEPLOCKONWAKEUP 1 -# define BOARD_DFLL48M_ENABLECHILLCYCLE 1 -# define BOARD_DFLL48M_MAXCOARSESTEP (0x1f / 4) -# define BOARD_DFLL48M_MAXFINESTEP (0xff / 4) +/* Peripheral clocking */ -# ifdef CONFIG_METRO_M4_DFLL_OPENLOOP -# define BOARD_DFLL48M_FREQUENCY (13720000) /* REVISIT: Needs to be measured */ -# else -# define BOARD_DFLL48M_FREQUENCY (BOARD_DFLL48M_MULTIPLIER * BOARD_DFLL_SRC_FREQUENCY) -# endif -#endif - -/* Fractional Digital Phase Locked Loop configuration. - * - * BOARD_FDPLL96M_ENABLE - Boolean (defined / not defined) - * BOARD_FDPLL96M_RUNINSTDBY - Boolean (defined / not defined) - * BOARD_FDPLL96M_ONDEMAND - Boolean (defined / not defined) - * BOARD_FDPLL96M_LBYPASS - Boolean (defined / not defined) - * BOARD_FDPLL96M_WUF - Boolean (defined / not defined) - * BOARD_FDPLL96M_LPEN - Boolean (defined / not defined) - * BOARD_FDPLL96M_FILTER - See OSCCTRL_DPLLCTRLB_FILTER_* definitions - * BOARD_FDPLL96M_REFCLK - See OSCCTRL_DPLLCTRLB_REFLCK_* definitions - * BOARD_FDPLL96M_REFCLK_CLKGEN - GCLK index in the range {0..8} - * BOARD_FDPLL96M_LOCKTIME_ENABLE - Boolean (defined / not defined) - * BOARD_FDPLL96M_LOCKTIME - See OSCCTRL_DPLLCTRLB_LTIME_* definitions - * BOARD_FDPLL96M_LOCKTIME_CLKGEN - GCLK index in the range {0..8} - * BOARD_FDPLL96M_REFDIV - Numeric value, 1 - 2047 - * BOARD_FDPLL96M_PRESCALER - See OSCCTRL_DPLLPRESC_* definitions - * BOARD_FDPLL96M_REFFREQ - Numeric value - * BOARD_FDPLL96M_FREQUENCY - Numeric value - */ - -#undef BOARD_FDPLL96M_ENABLE -#undef BOARD_FDPLL96M_RUNINSTDBY -#define BOARD_FDPLL96M_ONDEMAND 1 -#undef BOARD_FDPLL96M_LBYPASS -#undef BOARD_FDPLL96M_WUF -#undef BOARD_FDPLL96M_LPEN -#define BOARD_FDPLL96M_FILTER OSCCTRL_DPLLCTRLB_FILTER_DEFAULT -#define BOARD_FDPLL96M_REFCLK OSCCTRL_DPLLCTRLB_REFLCK_XOSCK32K -#define BOARD_FDPLL96M_REFCLK_CLKGEN 1 -#undef BOARD_FDPLL96M_LOCKTIME_ENABLE -#define BOARD_FDPLL96M_LOCKTIME OSCCTRL_DPLLCTRLB_LTIME_NONE -#define BOARD_FDPLL96M_LOCKTIME_CLKGEN 1 -#define BOARD_FDPLL96M_REFDIV 1 -#define BOARD_FDPLL96M_PRESCALER OSCCTRL_DPLLPRESC_DIV1 - -#define BOARD_FDPLL96M_REFFREQ 32768 -#define BOARD_FDPLL96M_FREQUENCY 48000000 - -/* GCLK Configuration - * - * Global enable/disable. - * - * BOARD_GCLK_ENABLE - *MUST* be defined - * - * For n=1-7: - * BOARD_GCLKn_ENABLE - Boolean (defined / not defined) - * - * For n=0-8: - * BOARD_GCLKn_RUN_IN_STANDBY - Boolean (defined / not defined) - * BOARD_GCLKn_CLOCK_SOURCE - See GCLK_GENCTRL_SRC_* definitions - * BOARD_GCLKn_PRESCALER - Value - * BOARD_GCLKn_OUTPUT_ENABLE - Boolean (defined / not defined) - */ - -#define BOARD_GCLK_ENABLE 1 - -/* GCLK generator 0 (Main Clock) - Source is the DFLL */ - -#ifdef CONFIG_METRO_M4_DFLL -# undef BOARD_GCLK0_RUN_IN_STANDBY -# define BOARD_GCLK0_CLOCK_SOURCE GCLK_GENCTRL_SRC_DFLL48M -# define BOARD_GCLK0_PRESCALER 1 -# undef BOARD_GCLK0_OUTPUT_ENABLE -# define BOARD_GCLK0_FREQUENCY (BOARD_DFLL48M_FREQUENCY / BOARD_GCLK0_PRESCALER) -#else -# undef BOARD_GCLK0_RUN_IN_STANDBY -# define BOARD_GCLK0_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -# define BOARD_GCLK0_PRESCALER 1 -# undef BOARD_GCLK0_OUTPUT_ENABLE -# define BOARD_GCLK0_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK0_PRESCALER) -#endif - -/* Configure GCLK generator 1 - Drives the DFLL */ - -#if defined(CONFIG_METRO_M4_DFLL_OSC16MSRC) -# define BOARD_GCLK1_ENABLE 1 -# undef BOARD_GCLK1_RUN_IN_STANDBY -# define BOARD_GCLK1_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -# define BOARD_GCLK1_PRESCALER 1 -# undef BOARD_GCLK1_OUTPUT_ENABLE -# define BOARD_GCLK1_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK1_PRESCALER) -#elif defined(CONFIG_METRO_M4_DFLL_XOSC32KSRC) -# define BOARD_GCLK1_ENABLE 1 -# undef BOARD_GCLK1_RUN_IN_STANDBY -# define BOARD_GCLK1_CLOCK_SOURCE GCLK_GENCTRL_SRC_XOSC32K -# define BOARD_GCLK1_PRESCALER 1 -# undef BOARD_GCLK1_OUTPUT_ENABLE -# define BOARD_GCLK1_FREQUENCY (BOARD_XOSC32K_FREQUENCY / BOARD_GCLK1_PRESCALER) -#else -# error DFLL clock source not provided -#endif - -/* Configure GCLK generator 2 (RTC) */ - -#undef BOARD_GCLK2_ENABLE -#undef BOARD_GCLK2_RUN_IN_STANDBY -#define BOARD_GCLK2_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC32K -#define BOARD_GCLK2_PRESCALER 32 -#undef BOARD_GCLK2_OUTPUT_ENABLE -#define BOARD_GCLK2_FREQUENCY (BOARD_OSC32K_FREQUENCY / BOARD_GCLK2_PRESCALER) - -/* Configure GCLK generator 3 */ - -#undef BOARD_GCLK3_ENABLE -#undef BOARD_GCLK3_RUN_IN_STANDBY -#define BOARD_GCLK3_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK3_PRESCALER 1 -#undef BOARD_GCLK3_OUTPUT_ENABLE -#define BOARD_GCLK3_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK3_PRESCALER) - -/* Configure GCLK generator 4 */ - -#undef BOARD_GCLK4_ENABLE -#undef BOARD_GCLK4_RUN_IN_STANDBY -#define BOARD_GCLK4_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK4_PRESCALER 1 -#undef BOARD_GCLK4_OUTPUT_ENABLE -#define BOARD_GCLK4_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK4_PRESCALER) - -/* Configure GCLK generator 5 */ - -#undef BOARD_GCLK5_ENABLE -#undef BOARD_GCLK5_RUN_IN_STANDBY -#define BOARD_GCLK5_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK5_PRESCALER 1 -#undef BOARD_GCLK5_OUTPUT_ENABLE -#define BOARD_GCLK5_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK5_PRESCALER) - -/* Configure GCLK generator 6 */ - -#undef BOARD_GCLK6_ENABLE -#undef BOARD_GCLK6_RUN_IN_STANDBY -#define BOARD_GCLK6_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK6_PRESCALER 1 -#undef BOARD_GCLK6_OUTPUT_ENABLE -#define BOARD_GCLK6_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK6_PRESCALER) - -/* Configure GCLK generator 7 */ - -#undef BOARD_GCLK7_ENABLE -#undef BOARD_GCLK7_RUN_IN_STANDBY -#define BOARD_GCLK7_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK7_PRESCALER 1 -#undef BOARD_GCLK7_OUTPUT_ENABLE -#define BOARD_GCLK7_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK7_PRESCALER) - -/* Configure GCLK generator 8 */ - -#undef BOARD_GCLK8_ENABLE -#undef BOARD_GCLK8_RUN_IN_STANDBY -#define BOARD_GCLK8_CLOCK_SOURCE GCLK_GENCTRL_SRC_OSC16M -#define BOARD_GCLK8_PRESCALER 1 -#undef BOARD_GCLK8_OUTPUT_ENABLE -#define BOARD_GCLK8_FREQUENCY (BOARD_OSC16M_FREQUENCY / BOARD_GCLK8_PRESCALER) - -/* The source of the main clock is always GCLK_MAIN. Also called GCLKGEN[0], this is - * the clock feeding the Power Manager. The Power Manager, in turn, generates main - * clock which is divided down to produce the CPU, AHB, and APB clocks. - * - * The main clock is initially OSC16M divided by 8. - */ - -#define BOARD_GCLK_MAIN_FREQUENCY BOARD_GCLK0_FREQUENCY - -/* Main clock dividers - * - * BOARD_CPU_DIVIDER - See MCLK_CPUDIV_DIV* definitions - * BOARD_CPU_FRQUENCY - In Hz - * BOARD_CPU_FAILDECT - Boolean (defined / not defined) - * BOARD_LOWPOWER_DIVIDER - See MCLK_LPDIV_DIV_* definitions - * BOARD_LOWPOWER_FREQUENCY - In Hz - * BOARD_BACKUP_DIVIDER - See MCLK_BUPDIV_DIV_* definitions - * BOARD_BACKUP_FREQUENCY - In Hz - */ - -#undef BOARD_CPU_FAILDECT -#define BOARD_CPU_DIVIDER MCLK_CPUDIV_DIV1 -#define BOARD_LOWPOWER_DIVIDER MCLK_LPDIV_DIV1 -#define BOARD_BACKUP_DIVIDER MCLK_BUPDIV_DIV1 - -/* Resulting frequencies */ - -#define BOARD_MCK_FREQUENCY (BOARD_GCLK_MAIN_FREQUENCY) -#define BOARD_CPU_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_LOWPOWER_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_BACKUP_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_APBA_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_APBB_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_APBC_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_APBD_FREQUENCY (BOARD_MCK_FREQUENCY) -#define BOARD_APBE_FREQUENCY (BOARD_MCK_FREQUENCY) +#define BOARD_GLCK_EIC 4 /* EIC GLCK index */ /* FLASH wait states * - * REVISIT: These values come from the SAMD20 - * Vdd Range Wait states Maximum Operating Frequency - * ------------- -------------- --------------------------- - * 1.62V to 2.7V 0 14 MHz - * 1 28 MHz - * 2 42 MHz - * 3 48 MHz - * 2.7V to 3.63V 0 24 MHz - * 1 48 MHz + * Vdd Range Wait states Maximum Operating Frequency + * --------- ----------- --------------------------- + * > 2.7V 0 24 MHz + * 1 51 MHz + * 2 77 MHz + * 3 101 MHz + * 4 119 MHz + * 5 120 MHz + * >1.71V 0 22 MHz + * 1 44 MHz + * 2 67 MHz + * 3 89 MHz + * 4 111 MHz + * 5 120 MHz */ -#if 0 -# define BOARD_FLASH_WAITSTATES 3 -#else -# define BOARD_FLASH_WAITSTATES 1 -#endif +#define BOARD_FLASH_WAITSTATES 6 /* LED definitions ******************************************************************/ /* The Adafruit Metro M4 has four LEDs, but only two are controllable by software: @@ -574,6 +346,11 @@ #define BOARD_SERCOM3_PINMAP_PAD2 0 /* (not used) */ #define BOARD_SERCOM3_PINMAP_PAD3 0 /* (not used) */ -#define BOARD_SERCOM3_FREQUENCY BOARD_GCLK0_FREQUENCY +#define BOARD_TXIRQ_SERCOM3 SAM_IRQ_SERCOM3_0 +#define BOARD_RXIRQ_SERCOM3 SAM_IRQ_SERCOM3_2 + +#define BOARD_SERCOM3_COREGEN 1 +#define BOARD_SERCOM3_SLOWGEN 3 +#define BOARD_SERCOM3_FREQUENCY BOARD_GCLK1_FREQUENCY #endif /* __CONFIG_METRO_M4_INCLUDE_BOARD_H */