From 935ac6e7a35fcf3bf29c204f2db41c7b5310f9d4 Mon Sep 17 00:00:00 2001 From: Marian Buschsieweke Date: Wed, 27 Nov 2024 09:02:20 +0100 Subject: [PATCH] fixup! cpu/sam0_common: implement SERCOM time-sharing --- cpu/sam0_common/include/periph_cpu_common.h | 19 +++++++ cpu/sam0_common/periph/sercom.c | 59 ++------------------- cpu/samd21/include/periph_cpu.h | 17 ++++++ cpu/samd5x/include/periph_cpu.h | 31 +++++++++++ cpu/saml1x/include/periph_cpu.h | 15 ++++++ cpu/saml21/include/periph_cpu.h | 30 +++++++++++ 6 files changed, 115 insertions(+), 56 deletions(-) diff --git a/cpu/sam0_common/include/periph_cpu_common.h b/cpu/sam0_common/include/periph_cpu_common.h index 0870eb28091cc..18e032f9b5af1 100644 --- a/cpu/sam0_common/include/periph_cpu_common.h +++ b/cpu/sam0_common/include/periph_cpu_common.h @@ -355,6 +355,25 @@ typedef void (*sercom_irq_cb_t)(void *arg); void sercom_acquire(sercom_t sercom, uint8_t gclk, sercom_irq_cb_t irq_cb, void *irq_arg); +/** + * @brief Enable the SERCOM APB clock + * @param[in] sercom The SERCOM to enable the clock of + */ +static inline void sercom_apb_enable(sercom_t sercom); + +/** + * @brief Disable the SERCOM APB clock + * @param[in] sercom The SERCOM to disable the clock of + */ +static inline void sercom_apb_disable(sercom_t sercom); + +/** + * @brief Enable GCLK clock signal to the given SEROM + * @param[in] sercom The SERCOM to clock + * @param[in] gclk Generator clock + */ +static inline void sercom_gclk_enable(sercom_t sercom, uint8_t gclk); + /** * @brief Release exclusive access to the given SERCOM and disable it * (low power mode) diff --git a/cpu/sam0_common/periph/sercom.c b/cpu/sam0_common/periph/sercom.c index 15029d1a937f0..77199a94304b5 100644 --- a/cpu/sam0_common/periph/sercom.c +++ b/cpu/sam0_common/periph/sercom.c @@ -86,44 +86,10 @@ Sercom *sercom_get_baseaddr(sercom_t sercom) */ static void _sercom_clk_enable(sercom_t sercom, uint8_t gclk) { -#if defined(CPU_COMMON_SAMD21) - PM->APBCMASK.reg |= (PM_APBCMASK_SERCOM0 << sercom); -#elif defined (CPU_COMMON_SAMD5X) - if (sercom < 2) { - MCLK->APBAMASK.reg |= (1 << (sercom + 12)); - } else if (sercom < 4) { - MCLK->APBBMASK.reg |= (1 << (sercom + 7)); - } else { - MCLK->APBDMASK.reg |= (1 << (sercom - 4)); - } -#else - if (sercom < 5) { - MCLK->APBCMASK.reg |= (MCLK_APBCMASK_SERCOM0 << sercom); - } -#if defined(CPU_COMMON_SAML21) - else { - MCLK->APBDMASK.reg |= (MCLK_APBDMASK_SERCOM5); - } -#endif /* CPU_COMMON_SAML21 */ -#endif + sercom_apb_enable(sercom); sam0_gclk_enable(gclk); -#if defined(CPU_COMMON_SAMD21) - GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(gclk) | - (SERCOM0_GCLK_ID_CORE + sercom)); - while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {} -#elif defined(CPU_COMMON_SAMD5X) - GCLK->PCHCTRL[_sercom_gclk_id_core(sercom)].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); -#else - if (sercom < 5) { - GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE + sercom].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); - } -#if defined(CPU_COMMON_SAML21) - else { - GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); - } -#endif /* CPU_COMMON_SAML21 */ -#endif + sercom_gclk_enable(sercom, gclk); } /** @@ -133,26 +99,7 @@ static void _sercom_clk_enable(sercom_t sercom, uint8_t gclk) */ static void _sercom_clk_disable(sercom_t sercom) { -#if defined(CPU_COMMON_SAMD21) - PM->APBCMASK.reg &= ~(PM_APBCMASK_SERCOM0 << sercom); -#elif defined (CPU_COMMON_SAMD5X) - if (sercom < 2) { - MCLK->APBAMASK.reg &= ~(1 << (sercom + 12)); - } else if (sercom < 4) { - MCLK->APBBMASK.reg &= ~(1 << (sercom + 7)); - } else { - MCLK->APBDMASK.reg &= ~(1 << (sercom - 4)); - } -#else - if (sercom < 5) { - MCLK->APBCMASK.reg &= ~(MCLK_APBCMASK_SERCOM0 << sercom); - } -#if defined (CPU_COMMON_SAML21) - else { - MCLK->APBDMASK.reg &= ~(MCLK_APBDMASK_SERCOM5); - } -#endif /* CPU_COMMON_SAML21 */ -#endif + sercom_apb_disable(sercom); } /** diff --git a/cpu/samd21/include/periph_cpu.h b/cpu/samd21/include/periph_cpu.h index f75d1849ad51f..8d306a8226b57 100644 --- a/cpu/samd21/include/periph_cpu.h +++ b/cpu/samd21/include/periph_cpu.h @@ -95,6 +95,23 @@ static inline int _sercom_id(SercomUsart *sercom) return ((((uint32_t)sercom) >> 10) & 0x7) - 2; } +static inline void sercom_apb_enable(sercom_t sercom) +{ + PM->APBCMASK.reg |= (PM_APBCMASK_SERCOM0 << sercom); +} + +static inline void sercom_apb_disable(sercom_t sercom) +{ + PM->APBCMASK.reg &= ~(PM_APBCMASK_SERCOM0 << sercom); +} + +static inline void sercom_gclk_enable(sercom_t sercom, uint8_t gclk) +{ + GCLK->CLKCTRL.reg = (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(gclk) | + (SERCOM0_GCLK_ID_CORE + sercom)); + while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {} +} + /** * @brief Pins that can be used for ADC input */ diff --git a/cpu/samd5x/include/periph_cpu.h b/cpu/samd5x/include/periph_cpu.h index eeb0c85c86a8e..0686a2b6e71b1 100644 --- a/cpu/samd5x/include/periph_cpu.h +++ b/cpu/samd5x/include/periph_cpu.h @@ -296,6 +296,37 @@ struct sam0_aux_cfg_mapping { #define SAM0_SDHC1_PIN_SDCK GPIO_PIN(PA, 21) /**< Clock */ /** @} */ +static inline void sercom_apb_enable(sercom_t sercom) +{ + if (sercom < 2) { + MCLK->APBAMASK.reg |= (1 << (sercom + 12)); + } + else if (sercom < 4) { + MCLK->APBBMASK.reg |= (1 << (sercom + 7)); + } + else { + MCLK->APBDMASK.reg |= (1 << (sercom - 4)); + } +} + +static inline void sercom_apb_disable(sercom_t sercom) +{ + if (sercom < 2) { + MCLK->APBAMASK.reg &= ~(1 << (sercom + 12)); + } + else if (sercom < 4) { + MCLK->APBBMASK.reg &= ~(1 << (sercom + 7)); + } + else { + MCLK->APBDMASK.reg &= ~(1 << (sercom - 4)); + } +} + +static inline void sercom_gclk_enable(sercom_t sercom, uint8_t gclk) +{ + GCLK->PCHCTRL[_sercom_gclk_id_core(sercom)].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); +} + #ifdef __cplusplus } #endif diff --git a/cpu/saml1x/include/periph_cpu.h b/cpu/saml1x/include/periph_cpu.h index 0234fd106404f..8fcfa477f35f8 100644 --- a/cpu/saml1x/include/periph_cpu.h +++ b/cpu/saml1x/include/periph_cpu.h @@ -155,6 +155,21 @@ struct sam0_aux_cfg_mapping { uint32_t user_crc; /**< CRC of NVM User Row bits 223:64 (words 2…6) */ }; +static inline void sercom_apb_enable(sercom_t sercom) +{ + MCLK->APBCMASK.reg |= (MCLK_APBCMASK_SERCOM0 << sercom); +} + +static inline void sercom_apb_disable(sercom_t sercom) +{ + MCLK->APBCMASK.reg &= ~(MCLK_APBCMASK_SERCOM0 << sercom); +} + +static inline void sercom_gclk_enable(sercom_t sercom, uint8_t gclk) +{ + GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE + sercom].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); +} + #ifdef __cplusplus } #endif diff --git a/cpu/saml21/include/periph_cpu.h b/cpu/saml21/include/periph_cpu.h index 2afc51424c5dd..56c22c578b126 100644 --- a/cpu/saml21/include/periph_cpu.h +++ b/cpu/saml21/include/periph_cpu.h @@ -169,6 +169,36 @@ struct sam0_aux_cfg_mapping { }; /** @} */ +static inline void sercom_apb_enable(sercom_t sercom) +{ + if (sercom < 5) { + MCLK->APBCMASK.reg |= (MCLK_APBCMASK_SERCOM0 << sercom); + } + else { + MCLK->APBDMASK.reg |= (MCLK_APBDMASK_SERCOM5); + } +} + +static inline void sercom_apb_disable(sercom_t sercom) +{ + if (sercom < 5) { + MCLK->APBCMASK.reg &= ~(MCLK_APBCMASK_SERCOM0 << sercom); + } + else { + MCLK->APBDMASK.reg &= ~(MCLK_APBDMASK_SERCOM5); + } +} + +static inline void sercom_gclk_enable(sercom_t sercom, uint8_t gclk) +{ + if (sercom < 5) { + GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE + sercom].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); + } + else { + GCLK->PCHCTRL[SERCOM5_GCLK_ID_CORE].reg = (GCLK_PCHCTRL_CHEN | GCLK_PCHCTRL_GEN(gclk)); + } +} + #ifdef __cplusplus } #endif