diff --git a/arch/arm/src/samdl/chip/saml_gclk.h b/arch/arm/src/samdl/chip/saml_gclk.h index 4e64e7c8bf..fbd6aab7a9 100644 --- a/arch/arm/src/samdl/chip/saml_gclk.h +++ b/arch/arm/src/samdl/chip/saml_gclk.h @@ -58,8 +58,8 @@ #define SAM_GCLK_CTRLA_OFFSET 0x0000 /* Control register */ #define SAM_GCLK_SYNCHBUSY_OFFSET 0x0004 /* Status register */ -#define SAM_GCLK_GENCTRL_OFFSET(n) (0x0020 + ((n) << 2) /* General clock generator n */ -#define SAM_GCLK_PCHCTRL_OFFSET(m) (0x0080 + ((m) << 2) /* Peripheral channel control m */ +#define SAM_GCLK_GENCTRL_OFFSET(n) (0x0020 + ((n) << 2)) /* General clock generator n */ +#define SAM_GCLK_PCHCTRL_OFFSET(m) (0x0080 + ((m) << 2)) /* Peripheral channel control m */ /* GCLK register addresses ******************************************************************/ @@ -132,51 +132,51 @@ #define GCLK_PCHCTRL_CHEN (1 << 6) /* Bit 6: Channel enable */ #define GCLK_PCHCTRL_WRTLOCK (1 << 7) /* Bit 7: Write lock */ -/* PCHCTRL mapping **************************************************************************/ +/* PCHCTRL channel mapping ******************************************************************/ -#define GCLK__DFLL48M_REF 0 /* DFLL48M Reference */ -#define GCLK__DPLL 1 /* FDPLL96M input clock source for reference */ -#define GCLK__DPLL_32K 2 /* FDPLL96M 32kHz clock for FDPLL96M internal lock timer */ -#define GCLK__EIC 3 /* EIC */ -#define GCLK__USB 4 /* USB */ -#define GCLK__EVSYS_CHANNEL_0 5 /* EVSYS_CHANNEL_0 */ -#define GCLK__EVSYS_CHANNEL_1 6 /* EVSYS_CHANNEL_1 */ -#define GCLK__EVSYS_CHANNEL_2 7 /* EVSYS_CHANNEL_2 */ -#define GCLK__EVSYS_CHANNEL_3 8 /* EVSYS_CHANNEL_3 */ -#define GCLK__EVSYS_CHANNEL_4 9 /* EVSYS_CHANNEL_4 */ -#define GCLK__EVSYS_CHANNEL_5 10 /* EVSYS_CHANNEL_5 */ -#define GCLK__EVSYS_CHANNEL_6 11 /* EVSYS_CHANNEL_6 */ -#define GCLK__EVSYS_CHANNEL_7 12 /* EVSYS_CHANNEL_7 */ -#define GCLK__EVSYS_CHANNEL_8 13 /* EVSYS_CHANNEL_8 */ -#define GCLK__EVSYS_CHANNEL_9 14 /* EVSYS_CHANNEL_9 */ -#define GCLK__EVSYS_CHANNEL_10 15 /* EVSYS_CHANNEL_10 */ -#define GCLK__EVSYS_CHANNEL_11 16 /* EVSYS_CHANNEL_11 */ -#define GCLK__SERCOM0_SLOW 17 /* SERCOM0_SLOW */ -#define GCLK__SERCOM1_SLOW 17 /* SERCOM1_SLOW */ -#define GCLK__SERCOM2_SLOW 17 /* SERCOM2_SLOW */ -#define GCLK__SERCOM3_SLOW 17 /* SERCOM3_SLOW */ -#define GCLK__SERCOM4_SLOW 17 /* SERCOM4_SLOW */ -#define GCLK__SERCOM0_CORE 18 /* SERCOM0_CORE */ -#define GCLK__SERCOM1_CORE 19 /* SERCOM1_CORE */ -#define GCLK__SERCOM2_CORE 20 /* SERCOM2_CORE */ -#define GCLK__SERCOM3_CORE 21 /* SERCOM3_CORE */ -#define GCLK__SERCOM4_CORE 22 /* SERCOM4_CORE */ -#define GCLK__SERCOM5_SLOW 23 /* SERCOM5_SLOW */ -#define GCLK__SERCOM5_CORE 24 /* SERCOM5_CORE */ -#define GCLK_TCC0 25 /* TCC0 */ -#define GCLK_TCC1 25 /* TCC1 */ -#define GCLK_TCC2 26 /* TCC2 */ -#define GCLK_TC3_1 26 /* TC3 */ -#define GCLK_TC0 27 /* TC0 */ -#define GCLK_TC1 27 /* TC1 */ -#define GCLK_TC2 28 /* TC2 */ -#define GCLK_TC3_2 28 /* TC3 */ -#define GCLK__TC4 29 /* TC4 */ -#define GCLK__ADC 30 /* ADC */ -#define GCLK__AC 31 /* AC */ -#define GCLK__DAC 32 /* DAC */ -#define GCLK__PTC 33 /* PTC */ -#define GCLK__CCL 34 /* CCL */ +#define GCLK_CHAN_DFLL48M_REF 0 /* DFLL48M Reference */ +#define GCLK_CHAN_DPLL 1 /* FDPLL96M input clock source for reference */ +#define GCLK_CHAN_DPLL_32K 2 /* FDPLL96M 32kHz clock for FDPLL96M internal lock timer */ +#define GCLK_CHAN_EIC 3 /* EIC */ +#define GCLK_CHAN_USB 4 /* USB */ +#define GCLK_CHAN_EVSYS_CH0 5 /* EVSYS_CHANNEL_0 */ +#define GCLK_CHAN_EVSYS_CH1 6 /* EVSYS_CHANNEL_1 */ +#define GCLK_CHAN_EVSYS_CH2 7 /* EVSYS_CHANNEL_2 */ +#define GCLK_CHAN_EVSYS_CH3 8 /* EVSYS_CHANNEL_3 */ +#define GCLK_CHAN_EVSYS_CH4 9 /* EVSYS_CHANNEL_4 */ +#define GCLK_CHAN_EVSYS_CH5 10 /* EVSYS_CHANNEL_5 */ +#define GCLK_CHAN_EVSYS_CH6 11 /* EVSYS_CHANNEL_6 */ +#define GCLK_CHAN_EVSYS_CH7 12 /* EVSYS_CHANNEL_7 */ +#define GCLK_CHAN_EVSYS_CH8 13 /* EVSYS_CHANNEL_8 */ +#define GCLK_CHAN_EVSYS_CH9 14 /* EVSYS_CHANNEL_9 */ +#define GCLK_CHAN_EVSYS_CH10 15 /* EVSYS_CHANNEL_10 */ +#define GCLK_CHAN_EVSYS_CH11 16 /* EVSYS_CHANNEL_11 */ +#define GCLK_CHAN_SERCOM0_SLOW 17 /* SERCOM0_SLOW */ +#define GCLK_CHAN_SERCOM1_SLOW 17 /* SERCOM1_SLOW */ +#define GCLK_CHAN_SERCOM2_SLOW 17 /* SERCOM2_SLOW */ +#define GCLK_CHAN_SERCOM3_SLOW 17 /* SERCOM3_SLOW */ +#define GCLK_CHAN_SERCOM4_SLOW 17 /* SERCOM4_SLOW */ +#define GCLK_CHAN_SERCOM0_CORE 18 /* SERCOM0_CORE */ +#define GCLK_CHAN_SERCOM1_CORE 19 /* SERCOM1_CORE */ +#define GCLK_CHAN_SERCOM2_CORE 20 /* SERCOM2_CORE */ +#define GCLK_CHAN_SERCOM3_CORE 21 /* SERCOM3_CORE */ +#define GCLK_CHAN_SERCOM4_CORE 22 /* SERCOM4_CORE */ +#define GCLK_CHAN_SERCOM5_SLOW 23 /* SERCOM5_SLOW */ +#define GCLK_CHAN_SERCOM5_CORE 24 /* SERCOM5_CORE */ +#define GCLK_CHAN_TCC0 25 /* TCC0 */ +#define GCLK_CHAN_TCC1 25 /* TCC1 */ +#define GCLK_CHAN_TCC2 26 /* TCC2 */ +#define GCLK_CHAN_TC3_1 26 /* TC3 */ +#define GCLK_CHAN_TC0 27 /* TC0 */ +#define GCLK_CHAN_TC1 27 /* TC1 */ +#define GCLK_CHAN_TC2 28 /* TC2 */ +#define GCLK_CHAN_TC3_2 28 /* TC3 */ +#define GCLK_CHAN_TC4 29 /* TC4 */ +#define GCLK_CHAN_ADC 30 /* ADC */ +#define GCLK_CHAN_AC 31 /* AC */ +#define GCLK_CHAN_DAC 32 /* DAC */ +#define GCLK_CHAN_PTC 33 /* PTC */ +#define GCLK_CHAN_CCL 34 /* CCL */ /******************************************************************************************** * Public Types diff --git a/arch/arm/src/samdl/sam_gclk.c b/arch/arm/src/samdl/sam_gclk.c index 3ed25a7253..2b875563cd 100644 --- a/arch/arm/src/samdl/sam_gclk.c +++ b/arch/arm/src/samdl/sam_gclk.c @@ -42,6 +42,8 @@ #include #include +#include + #include "up_arch.h" #include "sam_gclk.h" @@ -200,3 +202,90 @@ void sam_gclk_config(FAR const struct sam_gclkconfig_s *config) sam_gclck_waitsyncbusy(); } + +/**************************************************************************** + * Name: sam_gclk_chan_enable + * + * Description: + * Configure and enable a GCLK peripheral channel. + * + * Input Parameters: + * channel - Index of the GCLK channel to be enabled + * srcgen - The GCLK source generator index + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FAMILY_SAML21 +void sam_gclk_chan_enable(uint8_t channel, uint8_t srcgen) +{ + irqstate_t flags; + uint32_t regaddr; + uint32_t regval; + + /* Get the address of the peripheral channel control register */ + + regaddr = SAM_GCLK_PCHCTRL(channel); + + /* Disable generic clock channel */ + + flags = irqsave(); + sam_gclk_chan_disable(channel); + + /* Configure the peripheral channel */ + + regval = GCLK_PCHCTRL_GEN(srcgen); + putreg32(regval, regaddr); + + /* Enable the peripheral channel */ + + regval |= GCLK_PCHCTRL_CHEN; + putreg32(regval, regaddr); + + /* Wait for clock synchronization */ + + while ((getreg32(regaddr) &GCLK_PCHCTRL_CHEN) == 0); + irqrestore(flags); +} +#endif + +/**************************************************************************** + * Name: sam_gclk_chan_disable + * + * Description: + * Disable a GCLK peripheral channel. + * + * Input Parameters: + * channel - Index of the GCLK channel to be disabled + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FAMILY_SAML21 +void sam_gclk_chan_disable(uint8_t channel) +{ + irqstate_t flags; + uint32_t regaddr; + uint32_t regval; + + /* Get the address of the peripheral channel control register */ + + regaddr = SAM_GCLK_PCHCTRL(channel); + + /* Disable generic clock channel */ + + flags = irqsave(); + regval = getreg32(regaddr); + regval &= ~GCLK_PCHCTRL_CHEN; + putreg32(regval, regaddr); + + /* Wait for clock synchronization */ + + while ((getreg32(regaddr) &GCLK_PCHCTRL_CHEN) != 0); + irqrestore(flags); +} +#endif diff --git a/arch/arm/src/samdl/sam_gclk.h b/arch/arm/src/samdl/sam_gclk.h index 8292df0cbb..7c91b7f111 100644 --- a/arch/arm/src/samdl/sam_gclk.h +++ b/arch/arm/src/samdl/sam_gclk.h @@ -114,6 +114,43 @@ extern "C" void sam_gclk_config(FAR const struct sam_gclkconfig_s *config); +/**************************************************************************** + * Name: sam_gclk_chan_enable + * + * Description: + * Configure and enable a GCLK peripheral channel. + * + * Input Parameters: + * channel - Index of the GCLK channel to be enabled + * srcgen - The GCLK source generator index + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FAMILY_SAML21 +void sam_gclk_chan_enable(uint8_t channel, uint8_t srcgen); +#endif + +/**************************************************************************** + * Name: sam_gclk_chan_disable + * + * Description: + * Disable a GCLK peripheral channel. + * + * Input Parameters: + * channel - Index of the GCLK channel to be disabled + * + * Returned Value: + * None + * + ****************************************************************************/ + +#ifdef CONFIG_ARCH_FAMILY_SAML21 +void sam_gclk_chan_disable(uint8_t channel); +#endif + #undef EXTERN #if defined(__cplusplus) } diff --git a/arch/arm/src/samdl/saml_clockconfig.c b/arch/arm/src/samdl/saml_clockconfig.c index 6d5f53fc6c..e5369e9ddb 100644 --- a/arch/arm/src/samdl/saml_clockconfig.c +++ b/arch/arm/src/samdl/saml_clockconfig.c @@ -1029,7 +1029,11 @@ static inline void sam_fdpll96m_config(void) * Enable FDPLL96M internal lock timer and reference clock. * Depends on: * - * BOARD_FDPLL96M_SRCGCLKGEN - See GCLK_CLKCTRL_GEN* definitions + * BOARD_FDPLL96M_ENABLE - Boolean (defined / not defined) + * BOARD_FDPLL96M_REFCLK - See OSCCTRL_DPLLCTRLB_REFLCK_* definitions + * BOARD_FDPLL96M_REFCLK_CLKGEN - See GCLK_CLKCTRL_GEN* definitions + * BOARD_FDPLL96M_LOCKTIME_ENABLE - Boolean (defined / not defined) + * BOARD_FDPLL96M_LOCKTIME_CLKGEN - See GCLK_CLKCTRL_GEN* definitions * * Input Parameters: * None @@ -1042,6 +1046,17 @@ static inline void sam_fdpll96m_config(void) #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 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_enable()