diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts index 3827dc104d993c..006a588ad77a02 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts @@ -82,6 +82,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml index 428d79e1110643..64d075fa29740e 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart vendor: atmel diff --git a/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts b/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts index 83f5df99c05a2e..59e890b328ba67 100644 --- a/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts +++ b/boards/atmel/sam0/samd20_xpro/samd20_xpro.dts @@ -51,6 +51,12 @@ clock-frequency = ; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-spi"; diff --git a/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml b/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml index 548bd6c462a885..cb51b34188c9b9 100644 --- a/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml +++ b/boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml @@ -1,3 +1,6 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + identifier: samd20_xpro name: SAM D20 Xplained Pro type: mcu @@ -9,10 +12,10 @@ toolchain: flash: 256 ram: 32 supported: - - adc - flash - gpio - i2c + - rtc - spi - uart - watchdog diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts b/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts index f390bc106de9a9..74a496b392af5b 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.dts @@ -71,6 +71,12 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml index c41c94432857c6..753091c14b481d 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml @@ -12,12 +12,12 @@ toolchain: flash: 256 ram: 32 supported: - - adc - counter - dma - gpio - i2c - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/same54_xpro/same54_xpro.dts b/boards/atmel/sam0/same54_xpro/same54_xpro.dts index f8d957727cd4d5..2666c055dc7b48 100644 --- a/boards/atmel/sam0/same54_xpro/same54_xpro.dts +++ b/boards/atmel/sam0/same54_xpro/same54_xpro.dts @@ -68,6 +68,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom2 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/same54_xpro/same54_xpro.yaml b/boards/atmel/sam0/same54_xpro/same54_xpro.yaml index 1cddeeaf7ad9d5..27bb5f475064ae 100644 --- a/boards/atmel/sam0/same54_xpro/same54_xpro.yaml +++ b/boards/atmel/sam0/same54_xpro/same54_xpro.yaml @@ -18,6 +18,7 @@ supported: - i2c - netif:eth - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts b/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts index c0e0e43d666ba3..65f4b0c8531b80 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.dts @@ -71,6 +71,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-spi"; diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml index be39f0dc5173ec..b92484160db0aa 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/samr21_xpro/samr21_xpro-pinctrl.dtsi b/boards/atmel/sam0/samr21_xpro/samr21_xpro-pinctrl.dtsi index de5b64f0f8cfd9..81f7bce508abc2 100644 --- a/boards/atmel/sam0/samr21_xpro/samr21_xpro-pinctrl.dtsi +++ b/boards/atmel/sam0/samr21_xpro/samr21_xpro-pinctrl.dtsi @@ -1,11 +1,17 @@ /* - * Copyright (c) 2022, Gerson Fernando Budke + * Copyright (c) 2022-2024, Gerson Fernando Budke * SPDX-License-Identifier: Apache-2.0 */ #include &pinctrl { + adc_default: adc_default { + group1 { + pinmux = ; + }; + }; + pwm_default: pwm_default { group1 { pinmux = ; diff --git a/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts b/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts index 01ed0e8826ce38..00d35cdea325a4 100644 --- a/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts +++ b/boards/atmel/sam0/samr21_xpro/samr21_xpro.dts @@ -106,6 +106,12 @@ clock-frequency = <48000000>; }; +&adc { + status = "okay"; + pinctrl-0 = <&adc_default>; + pinctrl-names = "default"; +}; + &tcc0 { status = "okay"; compatible = "atmel,sam0-tcc-pwm"; @@ -116,6 +122,12 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml b/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml index 25ce756d667c9c..893cde253b8008 100644 --- a/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml +++ b/boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml @@ -1,6 +1,7 @@ # Copyright (c) 2019 Benjamin Valentin # Copyright (c) 2019-2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 + identifier: samr21_xpro name: SAM R21 Xplained Pro type: mcu @@ -18,6 +19,7 @@ supported: - i2c - netif - pwm + - rtc - spi - uart - usb_device diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts b/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts index 964cd8af4dfc9f..cea5d539eda3d7 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.dts @@ -71,6 +71,14 @@ pinctrl-names = "default"; }; +&rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + + assigned-clocks = <&osc32kctrl 4>; +}; + &sercom0 { status = "okay"; compatible = "atmel,sam0-uart"; diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml index 488fba3bb324e9..0b88aec5649b06 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml @@ -18,6 +18,7 @@ supported: - gpio - i2c - pwm + - rtc - spi - uart - usb_device diff --git a/drivers/adc/adc_sam0.c b/drivers/adc/adc_sam0.c index b7b1f59aa8ed74..de6d053a2ecb0b 100644 --- a/drivers/adc/adc_sam0.c +++ b/drivers/adc/adc_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +15,8 @@ #include LOG_MODULE_REGISTER(adc_sam0, CONFIG_ADC_LOG_LEVEL); +/* clang-format off */ + #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" @@ -46,18 +49,12 @@ struct adc_sam0_data { struct adc_sam0_cfg { Adc *regs; const struct pinctrl_dev_config *pcfg; - -#ifdef MCLK + volatile uint32_t *mclk; uint32_t mclk_mask; - uint32_t gclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t gclk; -#endif - uint32_t freq; uint16_t prescaler; - void (*config_func)(const struct device *dev); }; @@ -449,14 +446,17 @@ static int adc_sam0_init(const struct device *dev) Adc *const adc = cfg->regs; int retval; -#ifdef MCLK - GCLK->PCHCTRL[cfg->gclk_id].reg = cfg->gclk_mask | GCLK_PCHCTRL_CHEN; + *cfg->mclk |= cfg->mclk_mask; - MCLK_ADC |= cfg->mclk_mask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; #else - PM->APBCMASK.bit.ADC_ = 1; - - GCLK->CLKCTRL.reg = cfg->gclk | GCLK_CLKCTRL_CLKEN; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); @@ -515,81 +515,79 @@ static const struct adc_driver_api adc_sam0_api = { #ifdef MCLK -#define ADC_SAM0_CLOCK_CONTROL(n) \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_mask = UTIL_CAT(GCLK_PCHCTRL_GEN_GCLK, \ - DT_INST_PROP(n, gclk)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), \ - .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ - UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), - -#define ADC_SAM0_CONFIGURE(n) \ -do { \ - const struct adc_sam0_cfg *const cfg = dev->config; \ - Adc * const adc = cfg->regs; \ - adc->CALIB.reg = ADC_SAM0_BIASCOMP(n) \ - | ADC_SAM0_BIASR2R(n) \ - | ADC_SAM0_BIASREFBUF(n); \ +#define ADC_SAM0_CONFIGURE(n) \ +do { \ + const struct adc_sam0_cfg *const cfg = dev->config; \ + Adc * const adc = cfg->regs; \ + adc->CALIB.reg = ADC_SAM0_BIASCOMP(n) \ + | ADC_SAM0_BIASR2R(n) \ + | ADC_SAM0_BIASREFBUF(n); \ } while (false) #else -#define ADC_SAM0_CLOCK_CONTROL(n) \ - .gclk = UTIL_CAT(GCLK_CLKCTRL_GEN_GCLK, DT_INST_PROP(n, gclk)) |\ - GCLK_CLKCTRL_ID_ADC, \ - .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ - UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), - -#define ADC_SAM0_CONFIGURE(n) \ -do { \ - const struct adc_sam0_cfg *const cfg = dev->config; \ - Adc * const adc = cfg->regs; \ - /* Linearity is split across two words */ \ +#define ADC_SAM0_CONFIGURE(n) \ +do { \ + const struct adc_sam0_cfg *const cfg = dev->config; \ + Adc * const adc = cfg->regs; \ + /* Linearity is split across two words */ \ uint32_t lin = ((*(uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & \ - ADC_FUSES_LINEARITY_0_Msk) >> \ - ADC_FUSES_LINEARITY_0_Pos; \ - lin |= (((*(uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & \ - ADC_FUSES_LINEARITY_1_Msk) >> \ - ADC_FUSES_LINEARITY_1_Pos) << 4; \ + ADC_FUSES_LINEARITY_0_Msk) >> \ + ADC_FUSES_LINEARITY_0_Pos; \ + lin |= (((*(uint32_t *)ADC_FUSES_LINEARITY_1_ADDR) & \ + ADC_FUSES_LINEARITY_1_Msk) >> \ + ADC_FUSES_LINEARITY_1_Pos) << 4; \ uint32_t bias = ((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR) & \ - ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; \ - adc->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | \ - ADC_CALIB_LINEARITY_CAL(lin); \ + ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos; \ + adc->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | \ + ADC_CALIB_LINEARITY_CAL(lin); \ } while (false) #endif -#define ADC_SAM0_DEVICE(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static void adc_sam0_config_##n(const struct device *dev); \ - static const struct adc_sam0_cfg adc_sam_cfg_##n = { \ - .regs = (Adc *)DT_INST_REG_ADDR(n), \ - ADC_SAM0_CLOCK_CONTROL(n) \ - .freq = UTIL_CAT(UTIL_CAT(SOC_ATMEL_SAM0_GCLK, \ - DT_INST_PROP(n, gclk)), \ - _FREQ_HZ) / \ - DT_INST_PROP(n, prescaler), \ - .config_func = &adc_sam0_config_##n, \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - }; \ - static struct adc_sam0_data adc_sam_data_##n = { \ - ADC_CONTEXT_INIT_TIMER(adc_sam_data_##n, ctx), \ - ADC_CONTEXT_INIT_LOCK(adc_sam_data_##n, ctx), \ - ADC_CONTEXT_INIT_SYNC(adc_sam_data_##n, ctx), \ - }; \ - DEVICE_DT_INST_DEFINE(n, adc_sam0_init, NULL, \ - &adc_sam_data_##n, \ - &adc_sam_cfg_##n, POST_KERNEL, \ - CONFIG_ADC_INIT_PRIORITY, \ - &adc_sam0_api); \ - static void adc_sam0_config_##n(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, resrdy, irq), \ - DT_INST_IRQ_BY_NAME(n, resrdy, priority), \ - adc_sam0_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQ_BY_NAME(n, resrdy, irq)); \ - ADC_SAM0_CONFIGURE(n); \ +#define ADC_SAM0_GCLK_FREQ(n) \ + UTIL_CAT(UTIL_CAT(SOC_ATMEL_SAM0_GCLK, \ + DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen)), \ + _FREQ_HZ) + +#define ADC_SAM0_FREQ(n) \ + .prescaler = UTIL_CAT(ADC_CTRLx_PRESCALER_DIV, \ + UTIL_CAT(DT_INST_PROP(n, prescaler), _Val)), \ + .freq = ADC_SAM0_GCLK_FREQ(n) / DT_INST_PROP(n, prescaler) + +#define ADC_SAM0_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static void adc_sam0_config_##n(const struct device *dev); \ + static const struct adc_sam0_cfg adc_sam_cfg_##n = { \ + .regs = (Adc *)DT_INST_REG_ADDR(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + ADC_SAM0_FREQ(n), \ + .config_func = &adc_sam0_config_##n, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + static struct adc_sam0_data adc_sam_data_##n = { \ + ADC_CONTEXT_INIT_TIMER(adc_sam_data_##n, ctx), \ + ADC_CONTEXT_INIT_LOCK(adc_sam_data_##n, ctx), \ + ADC_CONTEXT_INIT_SYNC(adc_sam_data_##n, ctx), \ + }; \ + DEVICE_DT_INST_DEFINE(n, adc_sam0_init, NULL, \ + &adc_sam_data_##n, \ + &adc_sam_cfg_##n, POST_KERNEL, \ + CONFIG_ADC_INIT_PRIORITY, \ + &adc_sam0_api); \ + static void adc_sam0_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, resrdy, irq), \ + DT_INST_IRQ_BY_NAME(n, resrdy, priority), \ + adc_sam0_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQ_BY_NAME(n, resrdy, irq)); \ + ADC_SAM0_CONFIGURE(n); \ } DT_INST_FOREACH_STATUS_OKAY(ADC_SAM0_DEVICE) + +/* clang-format on */ diff --git a/drivers/can/can_sam0.c b/drivers/can/can_sam0.c index adcbf6a567db66..48dfe3a9420606 100644 --- a/drivers/can/can_sam0.c +++ b/drivers/can/can_sam0.c @@ -3,6 +3,7 @@ * Copyright (c) 2021 Alexander Wachter * Copyright (c) 2022 Kamil Serwus * Copyright (c) 2023 Sebastian Schlupp + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +18,8 @@ LOG_MODULE_REGISTER(can_sam0, CONFIG_CAN_LOG_LEVEL); +/* clang-format off */ + #define DT_DRV_COMPAT atmel_sam0_can struct can_sam0_config { @@ -26,7 +29,8 @@ struct can_sam0_config { const struct pinctrl_dev_config *pcfg; volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; + uint32_t gclk_gen; + uint16_t gclk_id; int divider; }; @@ -109,6 +113,12 @@ static int can_sam0_get_core_clock(const struct device *dev, uint32_t *rate) static void can_sam0_clock_enable(const struct can_sam0_config *cfg) { + *cfg->mclk |= cfg->mclk_mask; + + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; + /* Enable the GLCK7 with DIV*/ #if defined(CONFIG_SOC_SERIES_SAME51) || defined(CONFIG_SOC_SERIES_SAME54) /*DFFL has to be used as clock source for the ATSAME51/54 family of SoCs*/ @@ -121,13 +131,6 @@ static void can_sam0_clock_enable(const struct can_sam0_config *cfg) | GCLK_GENCTRL_DIV(cfg->divider) | GCLK_GENCTRL_GENEN; #endif - - /* Route channel */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK7 - | GCLK_PCHCTRL_CHEN; - - /* Enable CAN clock in MCLK */ - *cfg->mclk |= cfg->mclk_mask; } static int can_sam0_init(const struct device *dev) @@ -211,9 +214,10 @@ static void config_can_##inst##_irq(void) \ static const struct can_sam0_config can_sam0_cfg_##inst = { \ .base = CAN_MCAN_DT_INST_MCAN_ADDR(inst), \ .mram = (mem_addr_t)POINTER_TO_UINT(&can_sam0_mram_##inst), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(inst), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(inst, bit), \ .divider = DT_INST_PROP(inst, divider), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .config_irq = config_can_##inst##_irq, \ @@ -243,3 +247,5 @@ static void config_can_##inst##_irq(void) \ CAN_SAM0_DEVICE_INST(inst) DT_INST_FOREACH_STATUS_OKAY(CAN_SAM0_INST) + +/* clang-format on */ diff --git a/drivers/counter/counter_sam0_tc32.c b/drivers/counter/counter_sam0_tc32.c index 7dde721febd842..509b9ffb6b1ece 100644 --- a/drivers/counter/counter_sam0_tc32.c +++ b/drivers/counter/counter_sam0_tc32.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +16,8 @@ #include LOG_MODULE_REGISTER(counter_sam0_tc32, CONFIG_COUNTER_LOG_LEVEL); +/* clang-format off */ + struct counter_sam0_tc32_ch_data { counter_alarm_callback_t callback; void *user_data; @@ -31,16 +34,11 @@ struct counter_sam0_tc32_config { struct counter_config_info info; TcCount32 *regs; const struct pinctrl_dev_config *pcfg; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif uint16_t prescaler; - void (*irq_config_func)(const struct device *dev); }; @@ -336,20 +334,17 @@ static int counter_sam0_tc32_initialize(const struct device *dev) TcCount32 *tc = cfg->regs; int retval; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable TC clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* @@ -403,60 +398,54 @@ static const struct counter_driver_api counter_sam0_tc32_driver_api = { }; -#ifdef MCLK -#define COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch), -#else -#define COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id), -#endif - -#define SAM0_TC32_PRESCALER(n) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(n, prescaler), \ +#define SAM0_TC32_PRESCALER(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, prescaler), \ (DT_INST_PROP(n, prescaler)), (1)) -#define COUNTER_SAM0_TC32_DEVICE(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static void counter_sam0_tc32_config_##n(const struct device *dev); \ - static const struct counter_sam0_tc32_config \ - \ - counter_sam0_tc32_dev_config_##n = { \ - .info = { \ - .max_top_value = UINT32_MAX, \ - .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ - SAM0_TC32_PRESCALER(n), \ - .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ - .channels = 1 \ - }, \ - .regs = (TcCount32 *)DT_INST_REG_ADDR(n), \ - COUNTER_SAM0_TC32_CLOCK_CONTROL(n) \ - .prescaler = UTIL_CAT(TC_CTRLA_PRESCALER_DIV, \ - SAM0_TC32_PRESCALER(n)), \ - .irq_config_func = &counter_sam0_tc32_config_##n, \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - }; \ - \ - static struct counter_sam0_tc32_data counter_sam0_tc32_dev_data_##n;\ - \ - DEVICE_DT_INST_DEFINE(n, \ - &counter_sam0_tc32_initialize, \ - NULL, \ - &counter_sam0_tc32_dev_data_##n, \ - &counter_sam0_tc32_dev_config_##n, \ - PRE_KERNEL_1, \ - CONFIG_COUNTER_INIT_PRIORITY, \ - &counter_sam0_tc32_driver_api); \ - \ - static void counter_sam0_tc32_config_##n(const struct device *dev) \ - { \ - IRQ_CONNECT(DT_INST_IRQN(n), \ - DT_INST_IRQ(n, priority), \ - counter_sam0_tc32_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - irq_enable(DT_INST_IRQN(n)); \ +#define COUNTER_SAM0_TC32_DEVICE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static void counter_sam0_tc32_config_##n(const struct device *dev); \ + static const struct counter_sam0_tc32_config \ + \ + counter_sam0_tc32_dev_config_##n = { \ + .info = { \ + .max_top_value = UINT32_MAX, \ + .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ + SAM0_TC32_PRESCALER(n), \ + .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ + .channels = 1 \ + }, \ + .regs = (TcCount32 *)DT_INST_REG_ADDR(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + .prescaler = UTIL_CAT(TC_CTRLA_PRESCALER_DIV, \ + SAM0_TC32_PRESCALER(n)), \ + .irq_config_func = &counter_sam0_tc32_config_##n, \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + }; \ + \ + static struct counter_sam0_tc32_data counter_sam0_tc32_dev_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, \ + &counter_sam0_tc32_initialize, \ + NULL, \ + &counter_sam0_tc32_dev_data_##n, \ + &counter_sam0_tc32_dev_config_##n, \ + PRE_KERNEL_1, \ + CONFIG_COUNTER_INIT_PRIORITY, \ + &counter_sam0_tc32_driver_api); \ + \ + static void counter_sam0_tc32_config_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + counter_sam0_tc32_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ } DT_INST_FOREACH_STATUS_OKAY(COUNTER_SAM0_TC32_DEVICE) + +/* clang-format on */ diff --git a/drivers/dac/dac_sam0.c b/drivers/dac/dac_sam0.c index d831eb44e75b31..67d016652f8065 100644 --- a/drivers/dac/dac_sam0.c +++ b/drivers/dac/dac_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +15,8 @@ #include LOG_MODULE_REGISTER(dac_sam0, CONFIG_DAC_LOG_LEVEL); +/* clang-format off */ + /* * Maps between the DTS reference property names and register values. Note that * the ASF uses the 09/2015 names which differ from the 03/2020 datasheet. @@ -27,8 +30,10 @@ LOG_MODULE_REGISTER(dac_sam0, CONFIG_DAC_LOG_LEVEL); struct dac_sam0_cfg { Dac *regs; const struct pinctrl_dev_config *pcfg; - uint8_t pm_apbc_bit; - uint8_t gclk_clkctrl_id; + volatile uint32_t *mclk; + uint32_t mclk_mask; + uint32_t gclk_gen; + uint16_t gclk_id; uint8_t refsel; }; @@ -77,18 +82,24 @@ static int dac_sam0_init(const struct device *dev) Dac *regs = cfg->regs; int retval; - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; + *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; +#endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); if (retval < 0) { return retval; } - /* Enable the clock in PM */ - PM->APBCMASK.reg |= 1 << cfg->pm_apbc_bit; - /* Reset then configure the DAC */ regs->CTRLA.bit.SWRST = 1; while (regs->STATUS.bit.SYNCBUSY) { @@ -110,24 +121,27 @@ static const struct dac_driver_api api_sam0_driver_api = { .write_value = dac_sam0_write_value }; -#define SAM0_DAC_REFSEL(n) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(n, reference), \ +#define SAM0_DAC_REFSEL(n) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, reference), \ (DT_INST_ENUM_IDX(n, reference)), (0)) -#define SAM0_DAC_INIT(n) \ - PINCTRL_DT_INST_DEFINE(n); \ - static const struct dac_sam0_cfg dac_sam0_cfg_##n = { \ - .regs = (Dac *)DT_INST_REG_ADDR(n), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - .pm_apbc_bit = DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit), \ - .gclk_clkctrl_id = \ - DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id), \ - .refsel = UTIL_CAT(SAM0_DAC_REFSEL_, SAM0_DAC_REFSEL(n)), \ - }; \ - \ - DEVICE_DT_INST_DEFINE(n, &dac_sam0_init, NULL, NULL, \ - &dac_sam0_cfg_##n, POST_KERNEL, \ - CONFIG_DAC_INIT_PRIORITY, \ +#define SAM0_DAC_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static const struct dac_sam0_cfg dac_sam0_cfg_##n = { \ + .regs = (Dac *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + .refsel = UTIL_CAT(SAM0_DAC_REFSEL_, SAM0_DAC_REFSEL(n)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &dac_sam0_init, NULL, NULL, \ + &dac_sam0_cfg_##n, POST_KERNEL, \ + CONFIG_DAC_INIT_PRIORITY, \ &api_sam0_driver_api) DT_INST_FOREACH_STATUS_OKAY(SAM0_DAC_INIT); + +/* clang-format on */ diff --git a/drivers/i2c/i2c_sam0.c b/drivers/i2c/i2c_sam0.c index ff0b6c67fb652c..231d674b5a517b 100644 --- a/drivers/i2c/i2c_sam0.c +++ b/drivers/i2c/i2c_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Derek Hageman + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +19,8 @@ #include LOG_MODULE_REGISTER(i2c_sam0, CONFIG_I2C_LOG_LEVEL); +/* clang-format off */ + #include "i2c-priv.h" #ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER @@ -34,14 +37,10 @@ struct i2c_sam0_dev_config { SercomI2cm *regs; const struct pinctrl_dev_config *pcfg; uint32_t bitrate; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; void (*irq_config_func)(const struct device *dev); #ifdef CONFIG_I2C_SAM0_DMA_DRIVEN @@ -711,20 +710,19 @@ static int i2c_sam0_initialize(const struct device *dev) SercomI2cm *i2c = cfg->regs; int retval; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - /* Enable SERCOM clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif + /* Disable all I2C interrupts */ i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK; @@ -822,9 +820,10 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .irq_config_func = &i2c_sam0_irq_config_##n, \ I2C_SAM0_DMA_CHANNELS(n) \ } @@ -834,8 +833,10 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ .regs = (SercomI2cm *)DT_INST_REG_ADDR(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .irq_config_func = &i2c_sam0_irq_config_##n, \ I2C_SAM0_DMA_CHANNELS(n) \ } @@ -856,3 +857,5 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ I2C_SAM0_IRQ_HANDLER(n) DT_INST_FOREACH_STATUS_OKAY(I2C_SAM0_DEVICE) + +/* clang-format on */ diff --git a/drivers/pwm/pwm_sam0_tcc.c b/drivers/pwm/pwm_sam0_tcc.c index 3a12c81b76c9a9..cb52f4babd6a43 100644 --- a/drivers/pwm/pwm_sam0_tcc.c +++ b/drivers/pwm/pwm_sam0_tcc.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +18,8 @@ #include #include +/* clang-format off */ + /* Static configuration */ struct pwm_sam0_config { Tcc *regs; @@ -25,15 +28,10 @@ struct pwm_sam0_config { uint8_t counter_size; uint16_t prescaler; uint32_t freq; - -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; + uint32_t gclk_gen; uint16_t gclk_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif }; /* Wait for the peripheral to finish all commands */ @@ -106,15 +104,17 @@ static int pwm_sam0_init(const struct device *dev) Tcc *regs = cfg->regs; int retval; - /* Enable the clocks */ -#ifdef MCLK - GCLK->PCHCTRL[cfg->gclk_id].reg = - GCLK_PCHCTRL_GEN_GCLK0 | GCLK_PCHCTRL_CHEN; *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; #else - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - PM->APBCMASK.reg |= cfg->pm_apbcmask; + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif retval = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); @@ -140,34 +140,28 @@ static const struct pwm_driver_api pwm_sam0_driver_api = { .get_cycles_per_sec = pwm_sam0_get_cycles_per_sec, }; -#ifdef MCLK -#define PWM_SAM0_INIT_CLOCKS(inst) \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(inst), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, mclk, bit)), \ - .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, periph_ch) -#else -#define PWM_SAM0_INIT_CLOCKS(inst) \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(inst, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, clkctrl_id) -#endif - -#define PWM_SAM0_INIT(inst) \ - PINCTRL_DT_INST_DEFINE(inst); \ - static const struct pwm_sam0_config pwm_sam0_config_##inst = { \ - .regs = (Tcc *)DT_INST_REG_ADDR(inst), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ - .channels = DT_INST_PROP(inst, channels), \ - .counter_size = DT_INST_PROP(inst, counter_size), \ - .prescaler = UTIL_CAT(TCC_CTRLA_PRESCALER_DIV, \ - DT_INST_PROP(inst, prescaler)), \ - .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ - DT_INST_PROP(inst, prescaler), \ - PWM_SAM0_INIT_CLOCKS(inst), \ - }; \ - \ - DEVICE_DT_INST_DEFINE(inst, &pwm_sam0_init, NULL, \ - NULL, &pwm_sam0_config_##inst, \ - POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ +#define PWM_SAM0_INIT(inst) \ + PINCTRL_DT_INST_DEFINE(inst); \ + static const struct pwm_sam0_config pwm_sam0_config_##inst = { \ + .regs = (Tcc *)DT_INST_REG_ADDR(inst), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .channels = DT_INST_PROP(inst, channels), \ + .counter_size = DT_INST_PROP(inst, counter_size), \ + .prescaler = UTIL_CAT(TCC_CTRLA_PRESCALER_DIV, \ + DT_INST_PROP(inst, prescaler)), \ + .freq = SOC_ATMEL_SAM0_GCLK0_FREQ_HZ / \ + DT_INST_PROP(inst, prescaler), \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(inst, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(inst), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(inst, bit), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, &pwm_sam0_init, NULL, \ + NULL, &pwm_sam0_config_##inst, \ + POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ &pwm_sam0_driver_api); DT_INST_FOREACH_STATUS_OKAY(PWM_SAM0_INIT) + +/* clang-format on */ diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index 6b298b969b71c8..eab48049825929 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -22,6 +22,7 @@ zephyr_library_sources_ifdef(CONFIG_RTC_SHELL rtc_shell.c) zephyr_library_sources_ifdef(CONFIG_RTC_FAKE rtc_fake.c) zephyr_library_sources_ifdef(CONFIG_RTC_SMARTBOND rtc_smartbond.c) zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM rtc_sam.c) +zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM0 rtc_sam0.c) zephyr_library_sources_ifdef(CONFIG_RTC_RPI_PICO rtc_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_RTC_RV3028 rtc_rv3028.c) zephyr_library_sources_ifdef(CONFIG_RTC_NUMAKER rtc_numaker.c) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 5dd3eaf1301b7a..2cb2046824b48b 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -53,6 +53,7 @@ source "drivers/rtc/Kconfig.pcf8563" source "drivers/rtc/Kconfig.rpi_pico" source "drivers/rtc/Kconfig.rv3028" source "drivers/rtc/Kconfig.sam" +source "drivers/rtc/Kconfig.sam0" source "drivers/rtc/Kconfig.smartbond" source "drivers/rtc/Kconfig.stm32" source "drivers/rtc/Kconfig.numaker" diff --git a/drivers/rtc/Kconfig.sam0 b/drivers/rtc/Kconfig.sam0 new file mode 100644 index 00000000000000..2221fee0d883d2 --- /dev/null +++ b/drivers/rtc/Kconfig.sam0 @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +config RTC_ATMEL_SAM0 + bool "Atmel SAM RTC driver" + default y + depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED \ + && !$(dt_nodelabel_bool_prop,rtc,systimer) + help + Atmel Real-Time Clock (RTC) driver used on SAM0 SoC series. diff --git a/drivers/rtc/rtc_sam0.c b/drivers/rtc/rtc_sam0.c new file mode 100644 index 00000000000000..a21ad275638a2e --- /dev/null +++ b/drivers/rtc/rtc_sam0.c @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2024 Gerson Fernando Budke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT atmel_sam0_rtc + +/** @file + * @brief RTC driver for Atmel SAM0 MCU family. + */ + +#include + +#include +#include +#include "rtc_utils.h" + +#include +LOG_MODULE_REGISTER(rtc_sam0, CONFIG_RTC_LOG_LEVEL); + +/* clang-format off */ + +#define RTC_SAM0_TIME_MASK \ + (RTC_ALARM_TIME_MASK_SECOND \ + | RTC_ALARM_TIME_MASK_MINUTE \ + | RTC_ALARM_TIME_MASK_HOUR \ + | RTC_ALARM_TIME_MASK_MONTHDAY \ + | RTC_ALARM_TIME_MASK_MONTH \ + | RTC_ALARM_TIME_MASK_YEAR \ + ) + +#define RTC_SAM0_CALIBRATE_PPB_MAX (127) +#define RTC_SAM0_CALIBRATE_PPB_QUANTA (1000) + +enum rtc_sam0_counter_mode { + COUNTER_MODE_0, + COUNTER_MODE_1, + COUNTER_MODE_2, +}; + +struct rtc_sam0_config { + Rtc *regs; + enum rtc_sam0_counter_mode mode; + uint16_t prescaler; + + volatile uint32_t *mclk; + uint32_t mclk_mask; + uint32_t gclk_gen; + uint16_t gclk_id; + bool has_gclk; + bool has_osc32kctrl; + uint8_t osc32_src; + uint32_t evt_ctrl_msk; + +#ifdef CONFIG_RTC_ALARM + uint8_t alarms_count; +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_CALIBRATION + int32_t cal_constant; +#endif +}; + +struct rtc_sam0_data_cb { + rtc_alarm_callback cb; + void *cb_data; +}; + +struct rtc_sam0_data { + struct k_spinlock lock; +#ifdef CONFIG_RTC_ALARM + struct rtc_sam0_data_cb *const alarms; +#endif /* CONFIG_RTC_ALARM */ +}; + +static inline void rtc_sam0_sync(Rtc *rtc) +{ + /* Wait for synchronization */ +#ifdef MCLK + while (rtc->MODE0.SYNCBUSY.reg & RTC_MODE0_SYNCBUSY_MASK) { + } +#else + while (rtc->MODE0.STATUS.reg & RTC_STATUS_SYNCBUSY) { + } +#endif +} + +static int rtc_sam0_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t datetime = 0; + + if (rtc_utils_validate_rtc_time(timeptr, RTC_SAM0_TIME_MASK) == false) { + return -EINVAL; + } + + datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec); + datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min); + datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour); + datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday); + datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1); + datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + +#ifdef MCLK + regs->CTRLA.reg &= ~RTC_MODE0_CTRLA_ENABLE; + rtc_sam0_sync(cfg->regs); + regs->CLOCK.reg = datetime; + regs->CTRLA.reg |= RTC_MODE0_CTRLA_ENABLE; +#else + regs->CTRL.reg &= ~RTC_MODE0_CTRL_ENABLE; + rtc_sam0_sync(cfg->regs); + regs->CLOCK.reg = datetime; + regs->CTRL.reg |= RTC_MODE0_CTRL_ENABLE; +#endif + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rtc_sam0_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + RTC_MODE2_CLOCK_Type calendar = cfg->regs->MODE2.CLOCK; + + timeptr->tm_sec = calendar.bit.SECOND; + timeptr->tm_min = calendar.bit.MINUTE; + timeptr->tm_hour = calendar.bit.HOUR; + timeptr->tm_mday = calendar.bit.DAY; + timeptr->tm_mon = calendar.bit.MONTH - 1; + timeptr->tm_year = calendar.bit.YEAR + 99; + timeptr->tm_wday = -1; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + timeptr->tm_nsec = 0; + + LOG_DBG("D/M/Y H:M:S %02d/%02d/%02d %02d:%02d:%02d", + timeptr->tm_mday, timeptr->tm_mon + 1, timeptr->tm_year - 99, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + + return 0; +} + +#ifdef CONFIG_RTC_ALARM +static uint32_t rtc_sam0_datetime_from_tm(const struct rtc_time *timeptr, uint32_t mask) +{ + uint32_t datetime = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + datetime |= RTC_MODE2_CLOCK_SECOND(timeptr->tm_sec); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + datetime |= RTC_MODE2_CLOCK_MINUTE(timeptr->tm_min); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + datetime |= RTC_MODE2_CLOCK_HOUR(timeptr->tm_hour); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + datetime |= RTC_MODE2_CLOCK_DAY(timeptr->tm_mday); + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + datetime |= RTC_MODE2_CLOCK_MONTH(timeptr->tm_mon + 1); + } + + if (mask & RTC_ALARM_TIME_MASK_YEAR) { + datetime |= RTC_MODE2_CLOCK_YEAR(timeptr->tm_year - 99); + } + + return datetime; +} + +static void rtc_sam0_tm_from_datetime(struct rtc_time *timeptr, uint32_t mask, + RTC_MODE2_ALARM_Type calendar) +{ + memset(timeptr, 0x00, sizeof(struct rtc_time)); + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + timeptr->tm_sec = calendar.bit.SECOND; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + timeptr->tm_min = calendar.bit.MINUTE; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + timeptr->tm_hour = calendar.bit.HOUR; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + timeptr->tm_mday = calendar.bit.DAY; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + timeptr->tm_mon = calendar.bit.MONTH - 1; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + timeptr->tm_year = calendar.bit.YEAR + 99; + } + + timeptr->tm_wday = -1; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + timeptr->tm_nsec = 0; +} + +static uint32_t rtc_sam0_alarm_msk_from_mask(uint32_t mask) +{ + uint32_t alarm_mask = 0; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + alarm_mask = RTC_MODE2_MASK_SEL_SS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + alarm_mask = RTC_MODE2_MASK_SEL_MMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + alarm_mask = RTC_MODE2_MASK_SEL_HHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + alarm_mask = RTC_MODE2_MASK_SEL_DDHHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTH) { + alarm_mask = RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val; + } + + if (mask & RTC_ALARM_TIME_MASK_YEAR) { + alarm_mask = RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val; + } + + return alarm_mask; +} + +static uint32_t rtc_sam0_mask_from_alarm_msk(uint32_t alarm_mask) +{ + uint32_t mask = 0; + + switch (alarm_mask) { + case RTC_MODE2_MASK_SEL_YYMMDDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_YEAR; + case RTC_MODE2_MASK_SEL_MMDDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MONTH; + case RTC_MODE2_MASK_SEL_DDHHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + case RTC_MODE2_MASK_SEL_HHMMSS_Val: + mask |= RTC_ALARM_TIME_MASK_HOUR; + case RTC_MODE2_MASK_SEL_MMSS_Val: + mask |= RTC_ALARM_TIME_MASK_MINUTE; + case RTC_MODE2_MASK_SEL_SS_Val: + mask |= RTC_ALARM_TIME_MASK_SECOND; + } + + return mask; +} + +static int rtc_sam0_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + ARG_UNUSED(dev); + ARG_UNUSED(id); + + *mask = RTC_SAM0_TIME_MASK; + + return 0; +} + +static int rtc_sam0_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t mask_supported = RTC_SAM0_TIME_MASK; + uint32_t datetime; + uint32_t alarm_msk; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + if ((mask > 0) && (timeptr == NULL)) { + return -EINVAL; + } + + if (mask & ~mask_supported) { + return -EINVAL; + } + + if (rtc_utils_validate_rtc_time(timeptr, mask) == false) { + return -EINVAL; + } + + datetime = rtc_sam0_datetime_from_tm(timeptr, mask); + alarm_msk = rtc_sam0_alarm_msk_from_mask(mask); + + LOG_INF("S: datetime: %d, mask: %d", datetime, alarm_msk); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(DT_INST_IRQN(0)); + + rtc_sam0_sync(cfg->regs); + regs->Mode2Alarm[id].ALARM.reg = datetime; + regs->Mode2Alarm[id].MASK.reg = RTC_MODE2_MASK_SEL(alarm_msk); + regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id)); + + irq_enable(DT_INST_IRQN(0)); + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static int rtc_sam0_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + RTC_MODE2_ALARM_Type datetime; + uint32_t alarm_msk; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + if ((mask == NULL) || (timeptr == NULL)) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + rtc_sam0_sync(cfg->regs); + + datetime = regs->Mode2Alarm[id].ALARM; + alarm_msk = regs->Mode2Alarm[id].MASK.reg; + + LOG_INF("G: datetime: %d, mask: %d", datetime.reg, alarm_msk); + + k_spin_unlock(&data->lock, key); + + *mask = rtc_sam0_mask_from_alarm_msk(alarm_msk); + + rtc_sam0_tm_from_datetime(timeptr, *mask, datetime); + + return 0; +} + +static int rtc_sam0_alarm_is_pending(const struct device *dev, uint16_t id) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + if ((regs->INTFLAG.reg & RTC_MODE2_INTFLAG_ALARM(BIT(id))) == 0) { + k_spin_unlock(&data->lock, key); + + return 0; + } + + regs->INTFLAG.reg = RTC_MODE2_INTFLAG_ALARM(BIT(id)); + + k_spin_unlock(&data->lock, key); + + return 1; +} + +static int rtc_sam0_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + + if (BIT(id) > RTC_MODE2_INTFLAG_ALARM_Msk) { + return -EINVAL; + } + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + irq_disable(DT_INST_IRQN(0)); + + data->alarms[id].cb = callback; + data->alarms[id].cb_data = user_data; + + if (callback) { + regs->INTENSET.reg = RTC_MODE2_INTENSET_ALARM(BIT(id)); + } else { + regs->INTENCLR.reg = RTC_MODE2_INTENCLR_ALARM(BIT(id)); + } + + irq_enable(DT_INST_IRQN(0)); + + k_spin_unlock(&data->lock, key); + + return 0; +} + +static void rtc_sam0_isr(const struct device *dev) +{ + const struct rtc_sam0_config *cfg = dev->config; + struct rtc_sam0_data *data = dev->data; + RtcMode2 *regs = &cfg->regs->MODE2; + uint32_t int_flags = regs->INTFLAG.reg; + + for (int i = 0; i < cfg->alarms_count; ++i) { + if (int_flags & RTC_MODE2_INTFLAG_ALARM(BIT(i))) { + if (data->alarms[i].cb != NULL) { + data->alarms[i].cb(dev, i, data->alarms[i].cb_data); + } + } + } + + regs->INTFLAG.reg |= int_flags; +} + +#endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_CALIBRATION +static int rtc_sam0_set_calibration(const struct device *dev, int32_t calibration) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode2 *regs = &cfg->regs->MODE2; + int32_t correction = (int32_t)((float)cfg->cal_constant + * (float)calibration + * (float)1e-9) + ; + uint32_t abs_correction = abs(correction); + + LOG_DBG("Correction: %d, Absolute: %d, Calibration: %d", + correction, abs_correction, calibration); + + if (abs_correction == 0) { + regs->FREQCORR.reg = 0; + return 0; + } + + if (abs_correction > RTC_SAM0_CALIBRATE_PPB_MAX) { + LOG_ERR("The calibration %d result in an out of range value %d", + calibration, abs_correction); + return -EINVAL; + } + + rtc_sam0_sync(cfg->regs); + regs->FREQCORR.reg = RTC_FREQCORR_VALUE(abs_correction) + | (correction < 0 ? RTC_FREQCORR_SIGN : 0) + ; + + LOG_DBG("W REG: 0x%02x", regs->FREQCORR.reg); + + return 0; +} + +static int rtc_sam0_get_calibration(const struct device *dev, int32_t *calibration) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode2 *regs = &cfg->regs->MODE2; + int32_t correction; + + if (calibration == NULL) { + return -EINVAL; + } + + correction = regs->FREQCORR.bit.VALUE; + + if (correction == 0) { + *calibration = 0; + } else { + *calibration = (correction * 1e9) / cfg->cal_constant; + } + + if (regs->FREQCORR.bit.SIGN) { + *calibration *= -1; + } + + LOG_DBG("R REG: 0x%02x", regs->FREQCORR.reg); + + return 0; +} +#endif /* CONFIG_RTC_CALIBRATION */ + +static int rtc_sam0_init(const struct device *dev) +{ + const struct rtc_sam0_config *cfg = dev->config; + RtcMode0 *regs = &cfg->regs->MODE0; + + LOG_DBG("Counter Mode %d selected", cfg->mode); + LOG_DBG("gclk_id: %d, gclk_gen: %d, prescaler: %d, osc32k: %d", + cfg->gclk_id, cfg->gclk_gen, cfg->prescaler, cfg->osc32_src); + + *cfg->mclk |= cfg->mclk_mask; + +#ifdef MCLK + if (cfg->has_gclk) { + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; + } +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; +#endif + rtc_sam0_sync(cfg->regs); + +#ifdef MCLK + if (cfg->has_osc32kctrl) { + OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL(cfg->osc32_src); + } +#endif + + rtc_sam0_sync(cfg->regs); + regs->EVCTRL.reg = (cfg->evt_ctrl_msk & RTC_MODE0_EVCTRL_MASK); + +#ifdef MCLK + regs->CTRLA.reg = RTC_MODE0_CTRLA_ENABLE + | RTC_MODE0_CTRLA_COUNTSYNC + | RTC_MODE0_CTRLA_MODE(cfg->mode) + | RTC_MODE0_CTRLA_PRESCALER(cfg->prescaler + 1) + ; +#else + regs->CTRL.reg = RTC_MODE0_CTRL_ENABLE + | RTC_MODE0_CTRL_MODE(cfg->mode) + | RTC_MODE0_CTRL_PRESCALER(cfg->prescaler) + ; +#endif + + regs->INTFLAG.reg = 0; +#ifdef CONFIG_RTC_ALARM + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_sam0_isr, + DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +#endif + return 0; +} + +static const struct rtc_driver_api rtc_sam0_driver_api = { + .set_time = rtc_sam0_set_time, + .get_time = rtc_sam0_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rtc_sam0_alarm_get_supported_fields, + .alarm_set_time = rtc_sam0_alarm_set_time, + .alarm_get_time = rtc_sam0_alarm_get_time, + .alarm_is_pending = rtc_sam0_alarm_is_pending, + .alarm_set_callback = rtc_sam0_alarm_set_callback, +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_CALIBRATION + .set_calibration = rtc_sam0_set_calibration, + .get_calibration = rtc_sam0_get_calibration, +#endif /* CONFIG_RTC_CALIBRATION */ +}; + +#define RTC_SAM0_GCLK(n) \ + COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, gclk), \ + ( \ + .has_gclk = true, \ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id) \ + ), \ + ( \ + .has_gclk = false, \ + .gclk_gen = 0, \ + .gclk_id = 0 \ + )) + +#define RTC_SAM0_OSC32KCTRL(n) \ + COND_CODE_1(DT_INST_CLOCKS_HAS_NAME(n, osc32kctrl), \ + ( \ + .has_osc32kctrl = true, \ + .osc32_src = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, osc32kctrl, src) \ + ), \ + ( \ + .has_osc32kctrl = false, \ + .osc32_src = 0 \ + )) + +#define RTC_SAM0_DEVICE(n) \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, counter_mode), \ + "sam0:rtc: Missing counter-mode devicetree property"); \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(n, prescaler), \ + "sam0:rtc: Missing prescaler devicetree property"); \ + \ + static const struct rtc_sam0_config rtc_sam0_config_##n = { \ + .regs = (Rtc *)DT_INST_REG_ADDR(n), \ + .mode = DT_INST_ENUM_IDX(n, counter_mode), \ + .prescaler = DT_INST_ENUM_IDX(n, prescaler), \ + .evt_ctrl_msk = DT_INST_PROP(n, event_control_msk), \ + RTC_SAM0_GCLK(n), \ + RTC_SAM0_OSC32KCTRL(n), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + .alarms_count = DT_INST_PROP(n, alarms_count), \ + )) \ + IF_ENABLED(CONFIG_RTC_CALIBRATION, ( \ + .cal_constant = DT_INST_PROP(n, cal_constant), \ + )) \ + }; \ + \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + static struct rtc_sam0_data_cb \ + rtc_sam0_data_cb_##n[DT_INST_PROP(n, alarms_count)] = {}; \ + )) \ + \ + static struct rtc_sam0_data rtc_sam0_data_##n = { \ + IF_ENABLED(CONFIG_RTC_ALARM, ( \ + .alarms = rtc_sam0_data_cb_##n, \ + )) \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, rtc_sam0_init, \ + NULL, \ + &rtc_sam0_data_##n, \ + &rtc_sam0_config_##n, POST_KERNEL, \ + CONFIG_RTC_INIT_PRIORITY, \ + &rtc_sam0_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(RTC_SAM0_DEVICE); + +/* clang-format on */ diff --git a/drivers/serial/uart_sam0.c b/drivers/serial/uart_sam0.c index 35931fe5a17a09..60b6e6f1aa0597 100644 --- a/drivers/serial/uart_sam0.c +++ b/drivers/serial/uart_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,6 +18,8 @@ #include #include +/* clang-format off */ + #ifndef SERCOM_USART_CTRLA_MODE_USART_INT_CLK #define SERCOM_USART_CTRLA_MODE_USART_INT_CLK SERCOM_USART_CTRLA_MODE(0x1) #endif @@ -35,14 +38,11 @@ struct uart_sam0_dev_cfg { uint32_t baudrate; uint32_t pads; bool collision_detect; -#ifdef MCLK volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; + #if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_SAM0_ASYNC void (*irq_config_func)(const struct device *dev); #endif @@ -510,20 +510,17 @@ static int uart_sam0_init(const struct device *dev) SercomUsart * const usart = cfg->regs; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable SERCOM clock in MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* Disable all USART interrupts */ @@ -1272,34 +1269,20 @@ static void uart_sam0_irq_config_##n(const struct device *dev) \ #define UART_SAM0_SERCOM_COLLISION_DETECT(n) \ (DT_INST_PROP(n, collision_detection)) -#ifdef MCLK -#define UART_SAM0_CONFIG_DEFN(n) \ -static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \ - .regs = (SercomUsart *)DT_INST_REG_ADDR(n), \ - .baudrate = DT_INST_PROP(n, current_speed), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ - .pads = UART_SAM0_SERCOM_PADS(n), \ - .collision_detect = UART_SAM0_SERCOM_COLLISION_DETECT(n), \ - .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ - UART_SAM0_IRQ_HANDLER_FUNC(n) \ - UART_SAM0_DMA_CHANNELS(n) \ -} -#else #define UART_SAM0_CONFIG_DEFN(n) \ static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \ .regs = (SercomUsart *)DT_INST_REG_ADDR(n), \ .baudrate = DT_INST_PROP(n, current_speed), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = UART_SAM0_SERCOM_PADS(n), \ .collision_detect = UART_SAM0_SERCOM_COLLISION_DETECT(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ UART_SAM0_IRQ_HANDLER_FUNC(n) \ UART_SAM0_DMA_CHANNELS(n) \ } -#endif #define UART_SAM0_DEVICE_INIT(n) \ PINCTRL_DT_INST_DEFINE(n); \ @@ -1314,3 +1297,5 @@ DEVICE_DT_INST_DEFINE(n, uart_sam0_init, NULL, \ UART_SAM0_IRQ_HANDLER(n) DT_INST_FOREACH_STATUS_OKAY(UART_SAM0_DEVICE_INIT) + +/* clang-format on */ diff --git a/drivers/spi/spi_sam0.c b/drivers/spi/spi_sam0.c index b0da362ea86f66..8a0b34c1d93dae 100644 --- a/drivers/spi/spi_sam0.c +++ b/drivers/spi/spi_sam0.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +10,8 @@ #include LOG_MODULE_REGISTER(spi_sam0); +/* clang-format off */ + #include "spi_context.h" #include #include @@ -27,14 +30,12 @@ struct spi_sam0_config { SercomSpi *regs; uint32_t pads; const struct pinctrl_dev_config *pcfg; -#ifdef MCLK + volatile uint32_t *mclk; uint32_t mclk_mask; - uint16_t gclk_core_id; -#else - uint32_t pm_apbcmask; - uint16_t gclk_clkctrl_id; -#endif + uint32_t gclk_gen; + uint16_t gclk_id; + #ifdef CONFIG_SPI_ASYNC const struct device *dma_dev; uint8_t tx_dma_request; @@ -645,20 +646,17 @@ static int spi_sam0_init(const struct device *dev) struct spi_sam0_data *data = dev->data; SercomSpi *regs = cfg->regs; -#ifdef MCLK - /* Enable the GCLK */ - GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 | - GCLK_PCHCTRL_CHEN; - - /* Enable the MCLK */ *cfg->mclk |= cfg->mclk_mask; -#else - /* Enable the GCLK */ - GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | - GCLK_CLKCTRL_CLKEN; - /* Enable SERCOM clock in PM */ - PM->APBCMASK.reg |= cfg->pm_apbcmask; +#ifdef MCLK + GCLK->PCHCTRL[cfg->gclk_id].reg = GCLK_PCHCTRL_CHEN + | GCLK_PCHCTRL_GEN(cfg->gclk_gen) + ; +#else + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(cfg->gclk_gen) + | GCLK_CLKCTRL_ID(cfg->gclk_id) + ; #endif /* Disable all SPI interrupts */ @@ -721,9 +719,10 @@ static const struct spi_driver_api spi_sam0_driver_api = { #define SPI_SAM0_DEFINE_CONFIG(n) \ static const struct spi_sam0_config spi_sam0_config_##n = { \ .regs = (SercomSpi *)DT_INST_REG_ADDR(n), \ - .mclk = (volatile uint32_t *)MCLK_MASK_DT_INT_REG_ADDR(n), \ - .mclk_mask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, bit)), \ - .gclk_core_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, periph_ch),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = SPI_SAM0_SERCOM_PADS(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ SPI_SAM0_DMA_CHANNELS(n) \ @@ -732,8 +731,10 @@ static const struct spi_sam0_config spi_sam0_config_##n = { \ #define SPI_SAM0_DEFINE_CONFIG(n) \ static const struct spi_sam0_config spi_sam0_config_##n = { \ .regs = (SercomSpi *)DT_INST_REG_ADDR(n), \ - .pm_apbcmask = BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, pm, bit)), \ - .gclk_clkctrl_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, clkctrl_id),\ + .gclk_gen = DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(n, gclk, gen), \ + .gclk_id = DT_INST_CLOCKS_CELL_BY_NAME(n, gclk, id), \ + .mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n), \ + .mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, bit), \ .pads = SPI_SAM0_SERCOM_PADS(n), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ SPI_SAM0_DMA_CHANNELS(n) \ @@ -755,3 +756,5 @@ static const struct spi_sam0_config spi_sam0_config_##n = { \ &spi_sam0_driver_api); DT_INST_FOREACH_STATUS_OKAY(SPI_SAM0_DEVICE_INIT) + +/* clang-format on */ diff --git a/drivers/timer/Kconfig.sam0_rtc b/drivers/timer/Kconfig.sam0_rtc index 14c4ee73939fdb..05e4485ae18c83 100644 --- a/drivers/timer/Kconfig.sam0_rtc +++ b/drivers/timer/Kconfig.sam0_rtc @@ -1,12 +1,14 @@ # Copyright (c) 2014-2015 Wind River Systems, Inc. # Copyright (c) 2016 Cadence Design Systems, Inc. # Copyright (c) 2019 Intel Corp. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 config SAM0_RTC_TIMER bool "Atmel SAM0 series RTC timer" default y - depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED + depends on DT_HAS_ATMEL_SAM0_RTC_ENABLED \ + && $(dt_nodelabel_bool_prop,rtc,systimer) select PINCTRL select TICKLESS_CAPABLE help diff --git a/drivers/timer/sam0_rtc_timer.c b/drivers/timer/sam0_rtc_timer.c index 8e87b1848bb307..f9e02203f37391 100644 --- a/drivers/timer/sam0_rtc_timer.c +++ b/drivers/timer/sam0_rtc_timer.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 omSquare s.r.o. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +26,8 @@ #include #include +/* clang-format off */ + /* RTC registers. */ #define RTC0 ((RtcMode0 *) DT_INST_REG_ADDR(0)) @@ -66,10 +69,6 @@ BUILD_ASSERT(CYCLES_PER_TICK > 1, #endif /* CONFIG_TICKLESS_KERNEL */ -/* Helper macro to get the correct GCLK GEN based on configuration. */ -#define GCLK_GEN(n) GCLK_EVAL(n) -#define GCLK_EVAL(n) GCLK_CLKCTRL_GEN_GCLK##n - /* Tick/cycle count of the last announce call. */ static volatile uint32_t rtc_last; @@ -247,27 +246,31 @@ uint32_t sys_clock_cycle_get_32(void) static int sys_clock_driver_init(void) { - int retval; + volatile uint32_t *mclk = ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(0); + uint32_t mclk_mask = ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(0, bit); + *cfg->mclk |= cfg->mclk_mask; #ifdef MCLK - MCLK->APBAMASK.reg |= MCLK_APBAMASK_RTC; OSC32KCTRL->RTCCTRL.reg = OSC32KCTRL_RTCCTRL_RTCSEL_ULP32K; #else - /* Set up bus clock and GCLK generator. */ - PM->APBAMASK.reg |= PM_APBAMASK_RTC; - GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(RTC_GCLK_ID) | GCLK_CLKCTRL_CLKEN - | GCLK_GEN(DT_INST_PROP(0, clock_generator)); + GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN + | GCLK_CLKCTRL_GEN(DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(0, gclk, gen)) + | GCLK_CLKCTRL_ID(DT_INST_CLOCKS_CELL_BY_NAME(0, gclk, id)) + ; /* Synchronize GCLK. */ while (GCLK->STATUS.bit.SYNCBUSY) { } #endif - retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); - if (retval < 0) { +#ifndef CONFIG_TICKLESS_KERNEL + int retval = pinctrl_apply_state(pcfg, PINCTRL_STATE_DEFAULT); + + if (retval < 0 && retval != -ENOENT) { return retval; } +#endif /* Reset module to hardware defaults. */ rtc_reset(); @@ -330,3 +333,5 @@ static int sys_clock_driver_init(void) SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); + +/* clang-format on */ diff --git a/dts/arm/atmel/samc21.dtsi b/dts/arm/atmel/samc21.dtsi index 095e98437f05b1..c95d72be9dcd8a 100644 --- a/dts/arm/atmel/samc21.dtsi +++ b/dts/arm/atmel/samc21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Kamil Serwus + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,15 +16,17 @@ soc { adc1: adc@42004800 { compatible = "atmel,sam0-adc"; - status = "disabled"; reg = <0x42004800 0x30>; interrupts = <26 0>; interrupt-names = "resrdy"; clocks = <&gclk 34>, <&mclk 0x1c 18>; clock-names = "GCLK", "MCLK"; - gclk = <0>; - prescaler = <4>; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; #io-channel-cells = <1>; + status = "disabled"; + + prescaler = <4>; }; sercom4: sercom@42001400 { @@ -32,6 +35,8 @@ interrupts = <13 0>; clocks = <&gclk 23>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -41,6 +46,8 @@ interrupts = <14 0>; clocks = <&gclk 25>, <&mclk 0x1c 6>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -51,9 +58,12 @@ interrupt-names = "int0"; clocks = <&gclk 26>, <&mclk 0x10 8>; clock-names = "GCLK", "MCLK"; - bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; - divider = <12>; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; + + divider = <12>; + bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; }; can1: can@42002000 { @@ -63,9 +73,12 @@ interrupt-names = "int0"; clocks = <&gclk 27>, <&mclk 0x10 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; divider = <12>; - status = "disabled"; }; }; }; diff --git a/dts/arm/atmel/samc2x.dtsi b/dts/arm/atmel/samc2x.dtsi index a0e57c5c75f191..3173d3006265bf 100644 --- a/dts/arm/atmel/samc2x.dtsi +++ b/dts/arm/atmel/samc2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Kamil Serwus + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,21 @@ / { aliases { + port-a = &porta; + port-b = &portb; + port-c = &portc; + + rtc = &rtc; + + sercom-0 = &sercom0; + sercom-1 = &sercom1; + sercom-2 = &sercom2; + sercom-3 = &sercom3; + + tcc-0 = &tcc0; + tcc-1 = &tcc1; + tcc-2 = &tcc2; + watchdog0 = &wdog; }; @@ -43,31 +59,16 @@ <0x0080A048 0x4>; }; - aliases { - port-a = &porta; - port-b = &portb; - port-c = &portc; - - sercom-0 = &sercom0; - sercom-1 = &sercom1; - sercom-2 = &sercom2; - sercom-3 = &sercom3; - - tcc-0 = &tcc0; - tcc-1 = &tcc1; - tcc-2 = &tcc2; - }; - soc { nvmctrl: nvmctrl@41004000 { compatible = "atmel,sam0-nvmctrl"; reg = <0x41004000 0x22>; interrupts = <6 0>; - lock-regions = <16>; - #address-cells = <1>; #size-cells = <1>; + lock-regions = <16>; + flash0: flash@0 { compatible = "soc-nv-flash"; write-block-size = <4>; @@ -75,15 +76,23 @@ }; mclk: mclk@40000800 { - compatible = "atmel,samc2x-mclk"; + compatible = "atmel,sam0-mclk"; reg = <0x40000800 0x400>; #clock-cells = <2>; }; + osc32kctrl: osc32kctrl@40001400 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001400 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; + }; + gclk: gclk@40001c00 { - compatible = "atmel,samc2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; eic: eic@40002800 { @@ -118,9 +127,11 @@ interrupt-names = "resrdy"; clocks = <&gclk 33>, <&mclk 0x1c 17>; clock-names = "GCLK", "MCLK"; - gclk = <0>; - prescaler = <4>; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; #io-channel-cells = <1>; + + prescaler = <4>; }; sercom0: sercom@42000400 { @@ -129,6 +140,8 @@ interrupts = <9 0>; clocks = <&gclk 19>, <&mclk 0x1c 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -138,6 +151,8 @@ interrupts = <10 0>; clocks = <&gclk 20>, <&mclk 0x1c 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -147,6 +162,8 @@ interrupts = <11 0>; clocks = <&gclk 21>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -156,6 +173,8 @@ interrupts = <12 0>; clocks = <&gclk 22>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; status = "disabled"; }; @@ -165,6 +184,8 @@ interrupts = <17 0>; clocks = <&gclk 28>, <&mclk 0x1c 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -176,6 +197,8 @@ interrupts = <18 0>; clocks = <&gclk 28>, <&mclk 0x1c 10>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -187,6 +210,8 @@ interrupts = <19 0>; clocks = <&gclk 29>, <&mclk 0x1c 11>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; @@ -225,10 +250,16 @@ rtc: rtc@40002400 { compatible = "atmel,sam0-rtc"; - reg = <0x40002400 0x1C>; - interrupts = <3 0>; - clock-generator = <0>; + reg = <0x40002400 0x24>; + interrupts = <2 0>; + clocks = <&osc32kctrl>, <&mclk 0x14 9>; + clock-names = "OSC32KCTRL", "MCLK"; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; + + alarms-count = <1>; + cal-constant = <(4096 * 240)>; }; }; }; diff --git a/dts/arm/atmel/samd20.dtsi b/dts/arm/atmel/samd20.dtsi index 01af6c4e4503de..78533a3ae0a534 100644 --- a/dts/arm/atmel/samd20.dtsi +++ b/dts/arm/atmel/samd20.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Sean Nyekjaer + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +21,8 @@ interrupts = <13 0>; clocks = <&gclk 0x13>, <&pm 0x20 8>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc2: tc@42002800 { @@ -28,6 +31,8 @@ interrupts = <15 0>; clocks = <&gclk 0x14>, <&pm 0x20 10>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tc6: tc@42003800 { @@ -36,61 +41,93 @@ interrupts = <19 0>; clocks = <&gclk 0x16>, <&pm 0x20 14>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; }; }; +&adc { + interrupts = <21 0>; + interrupt-names = "resrdy"; + clocks = <&gclk 0x17>, <&pm 0x20 16>; + clock-names = "GCLK", "PM"; + /* + * 2.1 MHz is ADC max clock + * 8 MHz GCLK / 4 = 2 MHz + * Generator 3: DFLL48M / 8MHz + */ + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; +}; + &dac0 { interrupts = <23 0>; clocks = <&gclk 26>, <&pm 0x20 18>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <7 0>; clocks = <&gclk 0xd>, <&pm 0x20 2>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <8 0>; clocks = <&gclk 0xe>, <&pm 0x20 3>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <9 0>; clocks = <&gclk 0xf>, <&pm 0x20 4>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <10 0>; clocks = <&gclk 0x10>, <&pm 0x20 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <11 0>; clocks = <&gclk 0x11>, <&pm 0x20 6>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <12 0>; clocks = <&gclk 0x12>, <&pm 0x20 7>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; -&tc4 { - interrupts = <17 0>; - clocks = <&gclk 0x15>, <&pm 0x20 12>; +&rtc { + clocks = <&gclk 2>, <&pm 0x18 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 4>; + assigned-clock-names = "GCLK"; }; -&adc { - interrupts = <21 0>; - interrupt-names = "resrdy"; - clocks = <&gclk 0x17>, <&pm 0x20 16>; +&tc4 { + interrupts = <17 0>; + clocks = <&gclk 0x15>, <&pm 0x20 12>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/samd21.dtsi b/dts/arm/atmel/samd21.dtsi index f8b12ed570ae90..28e23f55a1a194 100644 --- a/dts/arm/atmel/samd21.dtsi +++ b/dts/arm/atmel/samd21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,9 +15,10 @@ soc { usb0: usb@41005000 { compatible = "atmel,sam0-usb"; - status = "disabled"; reg = <0x41005000 0x1000>; interrupts = <7 0>; + status = "disabled"; + num-bidir-endpoints = <8>; }; @@ -33,6 +35,8 @@ interrupts = <21 0>; clocks = <&gclk 0x1d>, <&pm 0x20 14>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; tcc0: tcc@42002000 { @@ -41,6 +45,8 @@ interrupts = <15 0>; clocks = <&gclk 26>, <&pm 0x20 8>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <4>; counter-size = <24>; @@ -52,6 +58,8 @@ interrupts = <16 0>; clocks = <&gclk 26>, <&pm 0x20 9>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <24>; @@ -63,6 +71,8 @@ interrupts = <17 0>; clocks = <&gclk 27>, <&pm 0x20 10>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; channels = <2>; counter-size = <16>; @@ -70,57 +80,87 @@ }; }; +&adc { + interrupts = <23 0>; + interrupt-names = "resrdy"; + clocks = <&gclk 0x1e>, <&pm 0x20 16>; + clock-names = "GCLK", "PM"; + /* + * 2.1 MHz is ADC max clock + * 8 MHz GCLK / 4 = 2 MHz + * Generator 3: DFLL48M / 8MHz + */ + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; +}; + &dac0 { interrupts = <25 0>; clocks = <&gclk 33>, <&pm 0x20 18>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <9 0>; clocks = <&gclk 0x14>, <&pm 0x20 2>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <10 0>; clocks = <&gclk 0x15>, <&pm 0x20 3>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <11 0>; clocks = <&gclk 0x16>, <&pm 0x20 4>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <12 0>; clocks = <&gclk 0x17>, <&pm 0x20 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <13 0>; clocks = <&gclk 0x18>, <&pm 0x20 6>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <14 0>; clocks = <&gclk 0x19>, <&pm 0x20 7>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; -&tc4 { - interrupts = <19 0>; - clocks = <&gclk 0x1c>, <&pm 0x20 12>; +&rtc { + clocks = <&gclk 4>, <&pm 0x18 5>; clock-names = "GCLK", "PM"; + assigned-clocks = <&gclk 4>; + assigned-clock-names = "GCLK"; }; -&adc { - clocks = <&gclk 0x1e>, <&pm 0x20 16>; +&tc4 { + interrupts = <19 0>; + clocks = <&gclk 0x1c>, <&pm 0x20 12>; clock-names = "GCLK", "PM"; - interrupts = <23 0>; - interrupt-names = "resrdy"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/samd2x.dtsi b/dts/arm/atmel/samd2x.dtsi index c247daffc1a516..89de20ed6c90b0 100644 --- a/dts/arm/atmel/samd2x.dtsi +++ b/dts/arm/atmel/samd2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Google LLC. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +14,22 @@ / { aliases { + adc-0 = &adc; + + port-a = &porta; + port-b = &portb; + + rtc = &rtc; + + sercom-0 = &sercom0; + sercom-1 = &sercom1; + sercom-2 = &sercom2; + sercom-3 = &sercom3; + sercom-4 = &sercom4; + sercom-5 = &sercom5; + + tc-4 = &tc4; + watchdog0 = &wdog; }; @@ -43,21 +60,6 @@ <0x0080A048 0x4>; }; - aliases { - port-a = &porta; - port-b = &portb; - adc-0 = &adc; - - sercom-0 = &sercom0; - sercom-1 = &sercom1; - sercom-2 = &sercom2; - sercom-3 = &sercom3; - sercom-4 = &sercom4; - sercom-5 = &sercom5; - - tc-4 = &tc4; - }; - soc { nvmctrl: nvmctrl@41004000 { compatible = "atmel,sam0-nvmctrl"; @@ -75,16 +77,17 @@ }; pm: pm@40000400 { - compatible = "atmel,samd2x-pm"; + compatible = "atmel,sam0-mclk"; reg = <0x40000400 0x400>; interrupts = <0 0>; #clock-cells = <2>; }; gclk: gclk@40000c00 { - compatible = "atmel,samd2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40000c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; eic: eic@40001800 { @@ -148,6 +151,7 @@ tc4: tc@42003000 { compatible = "atmel,sam0-tc32"; reg = <0x42003000 0x20>; + status = "disabled"; }; pinctrl: pinctrl@41004400 { @@ -178,28 +182,28 @@ compatible = "atmel,sam0-rtc"; reg = <0x40001400 0x1C>; interrupts = <3 0>; - clock-generator = <0>; + clocks = <&gclk 4 4>, <&pm 0x18 5>; + clock-names = "GCLK", "PM"; status = "disabled"; + + alarms-count = <1>; + cal-constant = <(1024 * 976)>; }; adc: adc@42004000 { compatible = "atmel,sam0-adc"; reg = <0x42004000 0x2B>; + #io-channel-cells = <1>; + status = "disabled"; - /* - * 2.1 MHz max, so clock it with the - * 8 MHz GCLK / 4 = 2 MHz - */ - gclk = <3>; prescaler = <4>; - #io-channel-cells = <1>; }; dac0: dac@42004800 { compatible = "atmel,sam0-dac"; - status = "disabled"; reg = <0x42004800 0x10>; #io-channel-cells = <0>; + status = "disabled"; }; }; }; diff --git a/dts/arm/atmel/samd5x.dtsi b/dts/arm/atmel/samd5x.dtsi index b64abc5de4554c..a2518e0cf53e12 100644 --- a/dts/arm/atmel/samd5x.dtsi +++ b/dts/arm/atmel/samd5x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 ML!PA Consulting GmbH + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,28 +12,6 @@ #include / { - chosen { - zephyr,flash-controller = &nvmctrl; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - - cpu0: cpu@0 { - device_type = "cpu"; - compatible = "arm,cortex-m4f"; - reg = <0>; - #address-cells = <1>; - #size-cells = <1>; - - mpu: mpu@e000ed90 { - compatible = "arm,armv7m-mpu"; - reg = <0xe000ed90 0x40>; - }; - }; - }; - aliases { adc-0 = &adc0; adc-1 = &adc1; @@ -42,6 +21,8 @@ port-c = &portc; port-d = &portd; + rtc = &rtc; + sercom-0 = &sercom0; sercom-1 = &sercom1; sercom-2 = &sercom2; @@ -66,7 +47,27 @@ }; chosen { + zephyr,flash-controller = &nvmctrl; zephyr,entropy = &trng; + zephyr,flash-controller = &nvmctrl; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; }; soc { @@ -89,26 +90,35 @@ }; mclk: mclk@40000800 { - compatible = "atmel,samd5x-mclk"; + compatible = "atmel,sam0-mclk"; reg = <0x40000800 0x400>; #clock-cells = <2>; }; + osc32kctrl: osc32kctrl@40001400 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001400 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; + }; + gclk: gclk@40001c00 { - compatible = "atmel,samd5x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001c00 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; nvmctrl: nvmctrl@41004000 { compatible = "atmel,sam0-nvmctrl"; reg = <0x41004000 0x22>; interrupts = <29 0>, <30 0>; - lock-regions = <32>; #address-cells = <1>; #size-cells = <1>; + lock-regions = <32>; + flash0: flash@0 { compatible = "soc-nv-flash"; write-block-size = <8>; @@ -119,6 +129,7 @@ compatible = "atmel,sam0-dmac"; reg = <0x4100A000 0x50>; interrupts = <31 0>, <32 0>, <33 0>, <34 0>, <35 0>; + #dma-cells = <2>; }; @@ -161,72 +172,88 @@ compatible = "atmel,sam0-sercom"; reg = <0x40003000 0x40>; interrupts = <46 0>, <47 0>, <48 0>, <49 0>; - status = "disabled"; clocks = <&gclk 7>, <&mclk 0x14 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom1: sercom@40003400 { compatible = "atmel,sam0-sercom"; reg = <0x40003400 0x40>; interrupts = <50 0>, <51 0>, <52 0>, <53 0>; - status = "disabled"; clocks = <&gclk 8>, <&mclk 0x14 13>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom2: sercom@41012000 { compatible = "atmel,sam0-sercom"; reg = <0x41012000 0x40>; interrupts = <54 0>, <55 0>, <56 0>, <57 0>; - status = "disabled"; clocks = <&gclk 23>, <&mclk 0x18 9>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom3: sercom@41014000 { compatible = "atmel,sam0-sercom"; reg = <0x41014000 0x40>; interrupts = <58 0>, <59 0>, <60 0>, <61 0>; - status = "disabled"; clocks = <&gclk 24>, <&mclk 0x18 10>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom4: sercom@43000000 { compatible = "atmel,sam0-sercom"; reg = <0x43000000 0x40>; interrupts = <62 0>, <63 0>, <64 0>, <65 0>; - status = "disabled"; clocks = <&gclk 34>, <&mclk 0x20 0>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom5: sercom@43000400 { compatible = "atmel,sam0-sercom"; reg = <0x43000400 0x40>; interrupts = <66 0>, <67 0>, <68 0>, <69 0>; - status = "disabled"; clocks = <&gclk 35>, <&mclk 0x20 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom6: sercom@43000800 { compatible = "atmel,sam0-sercom"; reg = <0x43000800 0x40>; interrupts = <70 0>, <71 0>, <72 0>, <73 0>; - status = "disabled"; clocks = <&gclk 36>, <&mclk 0x20 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; sercom7: sercom@43000c00 { compatible = "atmel,sam0-sercom"; reg = <0x43000C00 0x40>; interrupts = <74 0>, <75 0>, <76 0>, <77 0>; - status = "disabled"; clocks = <&gclk 37>, <&mclk 0x20 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; pinctrl: pinctrl@41008000 { @@ -270,9 +297,10 @@ usb0: usb@41000000 { compatible = "atmel,sam0-usb"; - status = "disabled"; reg = <0x41000000 0x1000>; interrupts = <80 0>, <81 0>, <82 0>, <83 0>; + status = "disabled"; + num-bidir-endpoints = <8>; }; @@ -284,10 +312,16 @@ rtc: rtc@40002400 { compatible = "atmel,sam0-rtc"; - reg = <0x40002400 0x1C>; + reg = <0x40002400 0x40>; interrupts = <11 0>; - clock-generator = <0>; + clocks = <&osc32kctrl>, <&mclk 0x14 9>; + clock-names = "OSC32KCTRL", "MCLK"; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; + + alarms-count = <2>; + cal-constant = <(8192 * 128)>; }; adc0: adc@43001c00 { @@ -295,18 +329,21 @@ reg = <0x43001C00 0x4A>; interrupts = <118 0>, <119 0>; interrupt-names = "overrun", "resrdy"; + clocks = <&gclk 40>, <&mclk 0x20 7>; + clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + #io-channel-cells = <1>; + status = "disabled"; /* - * 16 MHz max, source clock must not exceed 100 MHz. - * - table 54-8, section 54.6, page 2020 - * - table 54-24, section 54.10.4, page 2031 - * -> 48 MHz GCLK(2) / 4 = 12 MHz - */ - gclk = <2>; + * 16 MHz is ADC max clock, source clock must not exceed 100 MHz. + * - table 54-8, section 54.6, page 2020 + * - table 54-24, section 54.10.4, page 2031 + * 48 MHz GCLK / 4 = 12 MHz + * Generator 2: DFLL48M / 4 + */ prescaler = <4>; - #io-channel-cells = <1>; - clocks = <&gclk 40>, <&mclk 0x20 7>; - clock-names = "GCLK", "MCLK"; calib-offset = <0>; }; @@ -315,18 +352,21 @@ reg = <0x43002000 0x4A>; interrupts = <120 0>, <121 0>; interrupt-names = "overrun", "resrdy"; + clocks = <&gclk 41>, <&mclk 0x20 8>; + clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + #io-channel-cells = <1>; + status = "disabled"; /* - * 16 MHz max, source clock must not exceed 100 MHz. - * - table 54-8, section 54.6, page 2020 - * - table 54-24, section 54.10.4, page 2031 - * -> 48 MHz GCLK(2) / 4 = 12 MHz - */ - gclk = <2>; + * 16 MHz is ADC max clock, source clock must not exceed 100 MHz. + * - table 54-8, section 54.6, page 2020 + * - table 54-24, section 54.10.4, page 2031 + * 48 MHz GCLK / 4 = 12 MHz + * Generator 2: DFLL48M / 4 + */ prescaler = <4>; - #io-channel-cells = <1>; - clocks = <&gclk 41>, <&mclk 0x20 8>; - clock-names = "GCLK", "MCLK"; calib-offset = <14>; }; @@ -336,6 +376,9 @@ interrupts = <107 0>; clocks = <&gclk 9>, <&mclk 0x14 14>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; tc2: tc@4101a000 { @@ -344,6 +387,9 @@ interrupts = <109 0>; clocks = <&gclk 26>, <&mclk 0x18 13>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; tc4: tc@42001400 { @@ -352,6 +398,9 @@ interrupts = <111 0>; clocks = <&gclk 30>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; tc6: tc@43001400 { @@ -360,6 +409,9 @@ interrupts = <113 0>; clocks = <&gclk 39>, <&mclk 0x20 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; }; tcc0: tcc@41016000 { @@ -369,6 +421,10 @@ <90 0>, <91 0>; clocks = <&gclk 25>, <&mclk 0x18 11>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + channels = <6>; counter-size = <24>; }; @@ -379,6 +435,10 @@ interrupts = <92 0>, <93 0>, <94 0>, <95 0>, <96 0>; clocks = <&gclk 25>, <&mclk 0x18 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + channels = <4>; counter-size = <24>; }; @@ -389,6 +449,10 @@ interrupts = <97 0>, <98 0>, <99 0>, <100 0>; clocks = <&gclk 29>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + channels = <3>; counter-size = <16>; }; @@ -399,6 +463,10 @@ interrupts = <101 0>, <102 0>, <103 0>; clocks = <&gclk 29>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + channels = <2>; counter-size = <16>; }; @@ -409,6 +477,10 @@ interrupts = <104 0>, <105 0>, <106 0>; clocks = <&gclk 38>, <&mclk 0x20 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + channels = <2>; counter-size = <16>; }; diff --git a/dts/arm/atmel/same5x.dtsi b/dts/arm/atmel/same5x.dtsi index 750094cfafef9e..6dd59752904aa5 100644 --- a/dts/arm/atmel/same5x.dtsi +++ b/dts/arm/atmel/same5x.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2020 Stephanos Ioannidis * Copyright (c) 2023 Sebastian Schlupp + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,17 +15,18 @@ reg = <0x42000800 0x400>; interrupts = <84 0>; interrupt-names = "gmac"; + status = "disabled"; + num-queues = <1>; local-mac-address = [00 00 00 00 00 00]; - status = "disabled"; }; mdio: mdio@42000800 { compatible = "atmel,sam-mdio"; reg = <0x42000800 0x400>; - status = "disabled"; #address-cells = <1>; #size-cells = <0>; + status = "disabled"; }; can0: can@42000000 { @@ -34,9 +36,12 @@ interrupt-names = "int0", "int1"; clocks = <&gclk 27>, <&mclk 0x10 17>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; divider = <12>; - status = "disabled"; }; can1: can@42000400 { @@ -46,9 +51,12 @@ interrupt-names = "int0", "int1"; clocks = <&gclk 28>, <&mclk 0x10 18>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; + bosch,mram-cfg = <0x0 128 64 64 64 64 32 32>; divider = <12>; - status = "disabled"; }; }; }; diff --git a/dts/arm/atmel/saml21.dtsi b/dts/arm/atmel/saml21.dtsi index 524c28d3d2defa..ce44c7d5b13b5a 100644 --- a/dts/arm/atmel/saml21.dtsi +++ b/dts/arm/atmel/saml21.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Argentum Systems Ltd. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,9 +11,10 @@ soc { usb0: usb@41000000 { compatible = "atmel,sam0-usb"; - status = "disabled"; reg = <0x41000000 0x1000>; interrupts = <6 0>; + status = "disabled"; + num-bidir-endpoints = <8>; }; @@ -29,6 +31,9 @@ interrupts = <14 0>; clocks = <&gclk 25>, <&mclk 0x1c 5>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; channels = <4>; counter-size = <24>; @@ -40,6 +45,9 @@ interrupts = <15 0>; clocks = <&gclk 25>, <&mclk 0x1c 6>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; channels = <4>; counter-size = <24>; @@ -51,6 +59,9 @@ interrupts = <16 0>; clocks = <&gclk 26>, <&mclk 0x1c 7>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; + status = "disabled"; channels = <2>; counter-size = <16>; @@ -58,57 +69,80 @@ }; }; +&adc { + interrupts = <22 0>; + interrupt-names = "resrdy"; + clocks = <&gclk 30>, <&mclk 0x20 3>; + clock-names = "GCLK", "MCLK"; + /* + * 16 MHz is ADC max clock + * 48 MHz DFLL / 2 / 2 = 12 MHz + * Generator 3: 48MHz + */ + assigned-clocks = <&gclk 3>; + assigned-clock-names = "GCLK"; +}; + &dac { interrupts = <24 0>; clocks = <&gclk 32>, <&mclk 0x1c 12>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom0 { interrupts = <8 0>; clocks = <&gclk 18>, <&mclk 0x1c 0>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom1 { interrupts = <9 0>; clocks = <&gclk 19>, <&mclk 0x1c 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom2 { interrupts = <10 0>; clocks = <&gclk 20>, <&mclk 0x1c 2>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom3 { interrupts = <11 0>; clocks = <&gclk 21>, <&mclk 0x1c 3>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom4 { interrupts = <12 0>; clocks = <&gclk 22>, <&mclk 0x1c 4>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &sercom5 { interrupts = <13 0>; clocks = <&gclk 24>, <&mclk 0x20 1>; clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; &tc4 { interrupts = <21 0>; clocks = <&gclk 29>, <&mclk 0x20 2>; clock-names = "GCLK", "MCLK"; -}; - -&adc { - interrupts = <22 0>; - interrupt-names = "resrdy"; - clocks = <&gclk 30>, <&mclk 0x20 3>; - clock-names = "GCLK", "MCLK"; + assigned-clocks = <&gclk 0>; + assigned-clock-names = "GCLK"; }; diff --git a/dts/arm/atmel/saml2x.dtsi b/dts/arm/atmel/saml2x.dtsi index 2bad616c81af94..16dc17ccffc1d7 100644 --- a/dts/arm/atmel/saml2x.dtsi +++ b/dts/arm/atmel/saml2x.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Argentum Systems Ltd. + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,12 +14,14 @@ / { aliases { + rtc = &rtc; + watchdog0 = &wdog; }; chosen { - zephyr,flash-controller = &nvmctrl; zephyr,entropy = &trng; + zephyr,flash-controller = &nvmctrl; }; cpus { @@ -50,11 +53,12 @@ compatible = "atmel,sam0-nvmctrl"; reg = <0x41004000 0x22>; interrupts = <4 0>; - lock-regions = <16>; #address-cells = <1>; #size-cells = <1>; + lock-regions = <16>; + flash0: flash@0 { compatible = "soc-nv-flash"; reg = <0 0x40000>; @@ -62,23 +66,24 @@ }; }; - pm: pm@40000400 { - compatible = "atmel,saml2x-pm"; + mclk: mclk@40000400 { + compatible = "atmel,sam0-mclk"; reg = <0x40000400 0x400>; - interrupts = <0 0>; #clock-cells = <2>; }; - mclk: mclk@40000400 { - compatible = "atmel,saml2x-mclk"; - reg = <0x40000400 0x400>; - #clock-cells = <2>; + osc32kctrl: osc32kctrl@40001000 { + compatible = "atmel,sam0-osc32kctrl"; + reg = <0x40001000 0x400>; + #clock-cells = <0>; + #assigned-clock-cells = <1>; }; gclk: gclk@40001800 { - compatible = "atmel,saml2x-gclk"; + compatible = "atmel,sam0-gclk"; reg = <0x40001800 0x400>; #clock-cells = <1>; + #assigned-clock-cells = <1>; }; dmac: dmac@44000400 { @@ -139,6 +144,7 @@ tc4: tc@43000800 { compatible = "atmel,sam0-tc32"; reg = <0x43000800 0x34>; + status = "disabled"; }; pinctrl: pinctrl@40002800 { @@ -167,30 +173,32 @@ rtc: rtc@40002000 { compatible = "atmel,sam0-rtc"; - reg = <0x40002000 0x1c>; + reg = <0x40002000 0x44>; interrupts = <2 0>; - clock-generator = <0>; + clocks = <&osc32kctrl>, <&mclk 0x14 8>; + clock-names = "OSC32KCTRL", "MCLK"; + assigned-clocks = <&osc32kctrl 0>; + assigned-clock-names = "OSC32KCTRL"; status = "disabled"; + + alarms-count = <1>; + cal-constant = <(8192 * 128)>; }; adc: adc@43000c00 { compatible = "atmel,sam0-adc"; reg = <0x43000c00 0x30>; + #io-channel-cells = <1>; + status = "disabled"; - /* - * 16 MHz max, so clock it with the - * 48 MHz DFLL / 2 / 2 = 12 MHz - */ - gclk = <3>; prescaler = <2>; - #io-channel-cells = <1>; }; dac: dac@42003000 { compatible = "atmel,sam0-dac"; - status = "disabled"; reg = <0x42003000 0x1a>; #io-channel-cells = <0>; + status = "disabled"; }; trng: random@42003800 { diff --git a/dts/arm/atmel/samr21.dtsi b/dts/arm/atmel/samr21.dtsi index 786597c3ca31fa..9b67073db85492 100644 --- a/dts/arm/atmel/samr21.dtsi +++ b/dts/arm/atmel/samr21.dtsi @@ -1,10 +1,11 @@ /* * Copyright (c) 2019 Benjamin Valentin + * Copyright (c) 2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ -#include +#include / { aliases { @@ -12,21 +13,6 @@ }; soc { - usb0: usb@41005000 { - compatible = "atmel,sam0-usb"; - status = "disabled"; - reg = <0x41005000 0x1000>; - interrupts = <7 0>; - num-bidir-endpoints = <8>; - }; - - dmac: dmac@41004800 { - compatible = "atmel,sam0-dmac"; - reg = <0x41004800 0x50>; - interrupts = <6 0>; - #dma-cells = <2>; - }; - pinctrl: pinctrl@41004400 { ranges = <0x41004400 0x41004400 0x180>; @@ -43,87 +29,5 @@ compatible = "atmel,sam0-pinmux"; reg = <0x41004500 0x80>; }; - - tcc0: tcc@42002000 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002000 0x80>; - interrupts = <15 0>; - clocks = <&gclk 26>, <&pm 0x20 8>; - clock-names = "GCLK", "PM"; - - channels = <4>; - counter-size = <24>; - }; - - tcc1: tcc@42002400 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002400 0x80>; - interrupts = <16 0>; - clocks = <&gclk 26>, <&pm 0x20 9>; - clock-names = "GCLK", "PM"; - - channels = <2>; - counter-size = <24>; - }; - - tcc2: tcc@42002800 { - compatible = "atmel,sam0-tcc"; - reg = <0x42002800 0x80>; - interrupts = <17 0>; - clocks = <&gclk 27>, <&pm 0x20 10>; - clock-names = "GCLK", "PM"; - - channels = <2>; - counter-size = <16>; - }; }; }; - -&sercom0 { - interrupts = <9 0>; - clocks = <&gclk 0x14>, <&pm 0x20 2>; - clock-names = "GCLK", "PM"; -}; - -&sercom1 { - interrupts = <10 0>; - clocks = <&gclk 0x15>, <&pm 0x20 3>; - clock-names = "GCLK", "PM"; -}; - -&sercom2 { - interrupts = <11 0>; - clocks = <&gclk 0x16>, <&pm 0x20 4>; - clock-names = "GCLK", "PM"; -}; - -&sercom3 { - interrupts = <12 0>; - clocks = <&gclk 0x17>, <&pm 0x20 5>; - clock-names = "GCLK", "PM"; -}; - -&sercom4 { - interrupts = <13 0>; - clocks = <&gclk 0x18>, <&pm 0x20 6>; - clock-names = "GCLK", "PM"; -}; - -&sercom5 { - interrupts = <14 0>; - clocks = <&gclk 0x19>, <&pm 0x20 7>; - clock-names = "GCLK", "PM"; -}; - -&tc4 { - interrupts = <19 0>; - clocks = <&gclk 0x1c>, <&pm 0x20 12>; - clock-names = "GCLK", "PM"; -}; - -&adc { - clocks = <&gclk 0x1e>, <&pm 0x20 16>; - clock-names = "GCLK", "PM"; - interrupts = <23 0>; - interrupt-names = "resrdy"; -}; diff --git a/dts/arm/atmel/samr34.dtsi b/dts/arm/atmel/samr34.dtsi index 17164005d99392..b749b67f4fd73e 100644 --- a/dts/arm/atmel/samr34.dtsi +++ b/dts/arm/atmel/samr34.dtsi @@ -36,20 +36,22 @@ &sercom4 { /* SERCOM4 is used to interface with the internal LoRa radio */ compatible = "atmel,sam0-spi"; + #address-cells = <1>; + #size-cells = <0>; status = "disabled"; + + cs-gpios = <&portb 31 GPIO_ACTIVE_LOW>; dipo = <0>; dopo = <1>; - cs-gpios = <&portb 31 GPIO_ACTIVE_LOW>; - #address-cells = <1>; - #size-cells = <0>; pinctrl-0 = <&sercom4_default>; pinctrl-names = "default"; lora: sx1276@0 { compatible = "semtech,sx1276"; - status = "disabled"; reg = <0>; + status = "disabled"; + reset-gpios = <&portb 15 GPIO_ACTIVE_LOW>; /* nRST */ dio-gpios = <&portb 16 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, /* DIO0 */ diff --git a/dts/bindings/adc/atmel,sam0-adc.yaml b/dts/bindings/adc/atmel,sam0-adc.yaml index e403b2316b6b7f..23f7864c663f45 100644 --- a/dts/bindings/adc/atmel,sam0-adc.yaml +++ b/dts/bindings/adc/atmel,sam0-adc.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2019 Derek Hageman +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 family ADC @@ -22,10 +23,11 @@ properties: clock-names: required: true - gclk: - type: int + assigned-clocks: + required: true + + assigned-clock-names: required: true - description: generic clock generator source prescaler: type: int diff --git a/dts/bindings/arm/atmel,samd2x-pm.yaml b/dts/bindings/arm/atmel,samd2x-pm.yaml deleted file mode 100644 index 7fa232b815d1af..00000000000000 --- a/dts/bindings/arm/atmel,samd2x-pm.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD2x Power Manager (PM) - -compatible: "atmel,samd2x-pm" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/base/base.yaml b/dts/bindings/base/base.yaml index 485c4dfe7d122a..b616b5c69bdd78 100644 --- a/dts/bindings/base/base.yaml +++ b/dts/bindings/base/base.yaml @@ -60,6 +60,14 @@ properties: type: string-array description: name of each clock + assigned-clocks: + type: phandle-array + description: Assigned-clock information + + assigned-clock-names: + type: string-array + description: Name of each assigned-clock + "#address-cells": type: int description: number of address cells in reg property diff --git a/dts/bindings/can/atmel,sam0-can.yaml b/dts/bindings/can/atmel,sam0-can.yaml index 7002386c9228da..c9a1c9203b7e9a 100644 --- a/dts/bindings/can/atmel,sam0-can.yaml +++ b/dts/bindings/can/atmel,sam0-can.yaml @@ -1,3 +1,6 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + description: Specialization of Bosch m_can CAN FD controller for Atmel SAM0 compatible: "atmel,sam0-can" @@ -22,6 +25,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + divider: type: int required: true diff --git a/dts/bindings/clock/atmel,sam0-gclk.yaml b/dts/bindings/clock/atmel,sam0-gclk.yaml new file mode 100644 index 00000000000000..d8f011bf64d0a0 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-gclk.yaml @@ -0,0 +1,65 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAMD0 Generic Clock Controller (GCLK) + +compatible: "atmel,sam0-gclk" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 1 + description: | + - The ID cell is the peripheral identification. + + These information are used on GCLK->CLKCTRL register to select the + clock for an specific peripheral. + + Example 1: Connect the XOSC32K to RTC on SAMD2x + Assuming that generator 2 have the following configuration: + GLKC->GENCTRL: + SRC: 5 (XOSC32K) + ID: 2 (Generator 2) + + Then to enable the clock to the peripheral + Generator: 2 + Identificator: 4 (GCLK_RTC) + + &rtc { + /* The peripheral is fixed and it is defined at soc devictree + * clocks property + */ + clocks = <&gclk 4>, <&pm 0x18 5>; + clock-names = "GCLK", "PM"; + + /* The generator is user selectable and because of that it is + * defined at board + */ + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + + Example 2: Connect the XOSC32K to RTC on SAMD5x + In the SAMD5x the RTC is direct connected on the OSC32KCTRL and no + generator is used. See atmel,sam0-osc32kctrl.yaml for reference. + + "#assigned-clock-cells": + required: true + type: int + const: 1 + description: | + - The GEN cell is an integer number that represents the index of + the generic clock generator. It is usually a number between 0~8 + but could be more depending of the SoC. + +clock-cells: + - id + +assigned-clock-cells: + - gen diff --git a/dts/bindings/clock/atmel,sam0-mclk.yaml b/dts/bindings/clock/atmel,sam0-mclk.yaml new file mode 100644 index 00000000000000..efc07b6ffa98f9 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-mclk.yaml @@ -0,0 +1,48 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAM0 Main Clock Controller (MCLK) + +compatible: "atmel,sam0-mclk" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + description: | + - The OFFSET cell is an address of a bus mask. The buses can be + AHB and APB[A-D]. Each bus mask can enable a paripheral clock + selecting the BIT position in the mask. + - The BIT cell is the peripheral bit mask. + + These information are used on PM and MCLK register to select the + clock for an specific peripheral. The generator 2 is used on this + example and can be defined by the user at board. + + Example: Enable SERCOM0 on SAMD21 + &sercom0 { + clocks = <&gclk 0x14>, <&pm 0x20 2>; + clock-names = "GCLK", "PM"; + + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + + Example: Enable SERCOM0 on SAME54 + &sercom0 { + clocks = <&gclk 7>, <&mclk 0x14 12>; + clock-names = "GCLK", "MCLK"; + + assigned-clocks = <&gclk 2>; + assigned-clock-names = "GCLK"; + }; + +clock-cells: + - offset + - bit diff --git a/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml b/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml new file mode 100644 index 00000000000000..e3c7e607e1b024 --- /dev/null +++ b/dts/bindings/clock/atmel,sam0-osc32kctrl.yaml @@ -0,0 +1,37 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + +description: Atmel SAM0 32kHz Oscillator Controller (OSC32KCTRL) + +compatible: "atmel,sam0-osc32kctrl" + +include: + - base.yaml + - clock-controller.yaml + +properties: + reg: + required: true + + "#clock-cells": + const: 0 + + "#assigned-clock-cells": + required: true + type: int + const: 1 + description: | + It selects the OSC32CTRL clock to be routed to RTC peripheral + + Example: Connect the XOSC32K to RTC on SAMD5x + + &rtc { + clocks = <&mclk 0x14 9 &osc32kctrl>; + clock-names = "MCLK", "OSC32KCTRL"; + + assigned-clocks = <&osc32kctrl 4>; + assigned-clock-names = "OSC32KCTRL"; + }; + +assigned-clock-cells: + - src diff --git a/dts/bindings/clock/atmel,samc2x-gclk.yaml b/dts/bindings/clock/atmel,samc2x-gclk.yaml deleted file mode 100644 index d1e97272df72f4..00000000000000 --- a/dts/bindings/clock/atmel,samc2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2022 Kamil Serwus -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMC2x Generic Clock Controller (GCLK) - -compatible: "atmel,samc2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,samc2x-mclk.yaml b/dts/bindings/clock/atmel,samc2x-mclk.yaml deleted file mode 100644 index 227fa5246c0150..00000000000000 --- a/dts/bindings/clock/atmel,samc2x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2022, Kamil Serwus -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMC2x Generic Clock Controller (MCLK) - -compatible: "atmel,samc2x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/clock/atmel,samd2x-gclk.yaml b/dts/bindings/clock/atmel,samd2x-gclk.yaml deleted file mode 100644 index f5188aef05f90a..00000000000000 --- a/dts/bindings/clock/atmel,samd2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD2x Generic Clock Controller (GCLK) - -compatible: "atmel,samd2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - clkctrl_id diff --git a/dts/bindings/clock/atmel,samd5x-gclk.yaml b/dts/bindings/clock/atmel,samd5x-gclk.yaml deleted file mode 100644 index 68fd94b44eb82a..00000000000000 --- a/dts/bindings/clock/atmel,samd5x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD5x Generic Clock Controller (GCLK) - -compatible: "atmel,samd5x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,samd5x-mclk.yaml b/dts/bindings/clock/atmel,samd5x-mclk.yaml deleted file mode 100644 index 603196570daea9..00000000000000 --- a/dts/bindings/clock/atmel,samd5x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAMD5x Generic Clock Controller (MCLK) - -compatible: "atmel,samd5x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/clock/atmel,saml2x-gclk.yaml b/dts/bindings/clock/atmel,saml2x-gclk.yaml deleted file mode 100644 index 3c9020d505237c..00000000000000 --- a/dts/bindings/clock/atmel,saml2x-gclk.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2021 Argentum Systems Ltd. -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAML2x Generic Clock Controller (GCLK) - -compatible: "atmel,saml2x-gclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 1 - -clock-cells: - - periph_ch diff --git a/dts/bindings/clock/atmel,saml2x-mclk.yaml b/dts/bindings/clock/atmel,saml2x-mclk.yaml deleted file mode 100644 index ed89ba36f12e37..00000000000000 --- a/dts/bindings/clock/atmel,saml2x-mclk.yaml +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2021 Argentum Systems Ltd. -# SPDX-License-Identifier: Apache-2.0 - -description: Atmel SAML2x Generic Clock Controller (MCLK) - -compatible: "atmel,saml2x-mclk" - -include: [clock-controller.yaml, base.yaml] - -properties: - reg: - required: true - - "#clock-cells": - const: 2 - -clock-cells: - - offset - - bit diff --git a/dts/bindings/counter/atmel,sam0-tc32.yaml b/dts/bindings/counter/atmel,sam0-tc32.yaml index c523e6e4104989..f70fed93fa3d7a 100644 --- a/dts/bindings/counter/atmel,sam0-tc32.yaml +++ b/dts/bindings/counter/atmel,sam0-tc32.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2019 Derek Hageman +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 basic timer counter (TC) operating in 32-bit wide mode @@ -22,6 +23,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + prescaler: type: int description: Timer prescaler diff --git a/dts/bindings/dac/atmel,sam0-dac.yaml b/dts/bindings/dac/atmel,sam0-dac.yaml index 05ffd62d33742a..e0ca96ab247398 100644 --- a/dts/bindings/dac/atmel,sam0-dac.yaml +++ b/dts/bindings/dac/atmel,sam0-dac.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2020 Google LLC. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 family DAC @@ -19,6 +20,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + reference: type: string description: Reference voltage source diff --git a/dts/bindings/i2c/atmel,sam0-i2c.yaml b/dts/bindings/i2c/atmel,sam0-i2c.yaml index 9f8d34e95f95a0..f824f718dbbe96 100644 --- a/dts/bindings/i2c/atmel,sam0-i2c.yaml +++ b/dts/bindings/i2c/atmel,sam0-i2c.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2019 Derek Hageman +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 series SERCOM I2C node @@ -22,6 +23,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + dmas: description: | Optional TX & RX dma specifiers. Each specifier will have a phandle diff --git a/dts/bindings/pwm/atmel,sam0-tcc-pwm.yaml b/dts/bindings/pwm/atmel,sam0-tcc-pwm.yaml index 358528f47ef22e..bfea2ea81bab1b 100644 --- a/dts/bindings/pwm/atmel,sam0-tcc-pwm.yaml +++ b/dts/bindings/pwm/atmel,sam0-tcc-pwm.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2020 Google LLC. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 TCC in PWM mode @@ -23,6 +24,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + channels: type: int required: true diff --git a/dts/bindings/rtc/atmel,sam0-rtc.yaml b/dts/bindings/rtc/atmel,sam0-rtc.yaml index f2210e8bfb4e06..4555be9cb5b041 100644 --- a/dts/bindings/rtc/atmel,sam0-rtc.yaml +++ b/dts/bindings/rtc/atmel,sam0-rtc.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2018 omSquare s.r.o. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 RTC @@ -6,14 +7,123 @@ description: Atmel SAM0 RTC compatible: "atmel,sam0-rtc" include: - - name: rtc.yaml + - name: rtc-device.yaml - name: pinctrl-device.yaml properties: reg: required: true - clock-generator: + clocks: + required: true + + clock-names: + required: true + + assigned-clocks: + required: true + + assigned-clock-names: + required: true + + systimer: + type: boolean + description: | + Selects RTC peripheral to be used as a system timer and replace + the ARM systick. When this option is selected the normal RTC + functionality is in exclusive mode and the normal RTC functions + will not be available. + + The systimer exclusive functionality can be enabled using the + following devicetree entry: + + &rtc { + status = "okay"; + systimer; + }; + + cal-constant: type: int - description: clock generator index required: true + description: | + Define the constant used to calculate the calibration. More + information can be found in the datasheet of each SoC series + at RTC Frequency Correction topic. + + Example: + Correction in ppm = (FREQCORR.VALUE * 1e6 ppm) / (8192 * 128) + + &rtc { + cal-constant = <8192 * 128>; + }; + + counter-mode: + type: string + enum: + - "count-32" + - "count-16" + - "clock" + description: | + Configure the RTC counter operating mode. In mode 0, the counter + register is configured as a 32-bit counter. In mode 1, simmilar + to mode 0, the counter register is only 16-bit counter. In mode + 2 the counter register is configured as a clock/calendar. + + &rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + }; + + prescaler: + type: int + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + - 256 + - 512 + - 1024 + description: | + Enable CLKOUT at given frequency. When disabled, CLKOUT pin is LOW. + The default is 0 and corresponds to the disable the CLKOUT signal. + + &rtc { + status = "okay"; + counter-mode = "clock"; + prescaler = <1024>; + }; + + event-control-msk: + type: int + default: 0 + description: | + Enable peripheral event sources by bitmask. By default all the channels + are always disabled. + + Event Table: + + bit Event Source + 0 Periodic Interval 0 Event Output + 1 Periodic Interval 1 Event Output + 2 Periodic Interval 2 Event Output + 3 Periodic Interval 3 Event Output + 4 Periodic Interval 4 Event Output + 5 Periodic Interval 5 Event Output + 6 Periodic Interval 6 Event Output + 7 Periodic Interval 7 Event Output + 8 Compare/Alarm 0 Event Output + 9 Compare/Alarm 0 Event Output + 14 Tamper Event Output + 15 Overflow Event Output + 16 Tamper Event Input + + Example how to enable Compare/Alarm 0 Event Output: + &rtc { + event-control-msk = <100>; + }; diff --git a/dts/bindings/serial/atmel,sam0-uart.yaml b/dts/bindings/serial/atmel,sam0-uart.yaml index f817137d7b69e4..cd2fc792d8c0b1 100644 --- a/dts/bindings/serial/atmel,sam0-uart.yaml +++ b/dts/bindings/serial/atmel,sam0-uart.yaml @@ -1,3 +1,6 @@ +# Copyright (c) 2024 Gerson Fernando Budke +# SPDX-License-Identifier: Apache-2.0 + description: Atmel SAM0 SERCOM UART driver compatible: "atmel,sam0-uart" @@ -19,6 +22,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + rxpo: type: int required: true diff --git a/dts/bindings/spi/atmel,sam0-spi.yaml b/dts/bindings/spi/atmel,sam0-spi.yaml index 8b1c79b8220864..bc9950c96786e4 100644 --- a/dts/bindings/spi/atmel,sam0-spi.yaml +++ b/dts/bindings/spi/atmel,sam0-spi.yaml @@ -1,4 +1,5 @@ # Copyright (c) 2018, Google LLC. +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 description: Atmel SAM0 SERCOM SPI controller @@ -19,6 +20,12 @@ properties: clock-names: required: true + assigned-clocks: + required: true + + assigned-clock-names: + required: true + dipo: type: int required: true diff --git a/include/zephyr/devicetree/clocks.h b/include/zephyr/devicetree/clocks.h index 1721de650ec909..64bb7df43521e4 100644 --- a/include/zephyr/devicetree/clocks.h +++ b/include/zephyr/devicetree/clocks.h @@ -347,6 +347,331 @@ extern "C" { #define DT_INST_CLOCKS_CELL(inst, cell) \ DT_INST_CLOCKS_CELL_BY_IDX(inst, 0, cell) +/** + * @brief Test if a node has a assigned-clocks phandle-array property at a given index + * + * This expands to 1 if the given index is valid assigned-clocks property phandle-array index. + * Otherwise, it expands to 0. + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <...>, <...>; + * }; + * + * n2: node-2 { + * assigned-clocks = <...>; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 0) // 1 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 1) // 1 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n1), 2) // 0 + * DT_ASSIGNED_CLOCKS_HAS_IDX(DT_NODELABEL(n2), 1) // 0 + * + * @param node_id node identifier; may or may not have any assigned-clocks property + * @param idx index of a assigned-clocks property phandle-array whose existence to check + * @return 1 if the index exists, 0 otherwise + */ +#define DT_ASSIGNED_CLOCKS_HAS_IDX(node_id, idx) \ + DT_PROP_HAS_IDX(node_id, assigned_clocks, idx) + +/** + * @brief Test if a node has a clock-names array property holds a given name + * + * This expands to 1 if the name is available as assigned-clocks-name array property cell. + * Otherwise, it expands to 0. + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <...>, <...>; + * clock-names = "alpha", "beta"; + * }; + * + * n2: node-2 { + * assigned-clocks = <...>; + * clock-names = "alpha"; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), alpha) // 1 + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n1), beta) // 1 + * DT_ASSIGNED_CLOCKS_HAS_NAME(DT_NODELABEL(n2), beta) // 0 + * + * @param node_id node identifier; may or may not have any clock-names property. + * @param name lowercase-and-underscores clock-names cell value name to check + * @return 1 if the assigned-clock name exists, 0 otherwise + */ +#define DT_ASSIGNED_CLOCKS_HAS_NAME(node_id, name) \ + DT_PROP_HAS_NAME(node_id, assigned_clocks, name) + +/** + * @brief Get the number of elements in a assigned-clocks property + * + * Example devicetree fragment: + * + * n1: node-1 { + * assigned-clocks = <&foo>, <&bar>; + * }; + * + * n2: node-2 { + * assigned-clocks = <&foo>; + * }; + * + * Example usage: + * + * DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n1)) // 2 + * DT_NUM_ASSIGNED_CLOCKS(DT_NODELABEL(n2)) // 1 + * + * @param node_id node identifier with a assigned-clocks property + * @return number of elements in the property + */ +#define DT_NUM_ASSIGNED_CLOCKS(node_id) \ + DT_PROP_LEN(node_id, assigned-clocks) + + +/** + * @brief Get the node identifier for the controller phandle from a + * "assigned-clocks" phandle-array property at an index + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { ... }; + * + * clk2: clock-controller@... { ... }; + * + * n: node { + * assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 0)) // DT_NODELABEL(clk1) + * DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_NODELABEL(n), 1)) // DT_NODELABEL(clk2) + * + * @param node_id node identifier + * @param idx logical index into "assigned-clocks" + * @return the node identifier for the clock controller referenced at + * index "idx" + * @see DT_PHANDLE_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, idx) \ + DT_PHANDLE_BY_IDX(node_id, assigned_clocks, idx) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) + * @param node_id node identifier + * @return a node identifier for the assigned-clocks controller at index 0 + * in "assigned-clocks" + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CTLR(node_id) DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(node_id, 0) + +/** + * @brief Get the node identifier for the controller phandle from a + * assigned-clocks phandle-array property by name + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { ... }; + * + * clk2: clock-controller@... { ... }; + * + * n: node { + * assigned-clocks = <&clk1 10 20>, <&clk2 30 40>; + * clock-names = "alpha", "beta"; + * }; + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_NODELABEL(n), beta) // DT_NODELABEL(clk2) + * + * @param node_id node identifier + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @return the node identifier for the clock controller referenced by name + * @see DT_PHANDLE_BY_NAME() + */ +#define DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(node_id, name) \ + DT_PHANDLE_BY_NAME(node_id, assigned_clocks, name) + +/** + * @brief Get a assigned-clock specifier's cell value at an index + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { + * compatible = "vnd,clock"; + * #assigned-clock-cells = < 2 >; + * }; + * + * n: node { + * assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; + * }; + * + * Bindings fragment for the vnd,clock compatible: + * + * assigned-clock-cells: + * - bus + * - bits + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 0, bus) // 10 + * DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_NODELABEL(n), 1, bits) // 40 + * + * @param node_id node identifier for a node with a assigned-clocks property + * @param idx logical index into assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index "idx" + * @see DT_PHA_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, idx, cell) \ + DT_PHA_BY_IDX(node_id, assigned_clocks, idx, cell) + +/** + * @brief Get a assigned-clock specifier's cell value by name + * + * Example devicetree fragment: + * + * clk1: clock-controller@... { + * compatible = "vnd,clock"; + * #assigned-clock-cells = < 2 >; + * }; + * + * n: node { + * assigned-clocks = < &clk1 10 20 >, < &clk1 30 40 >; + * clock-names = "alpha", "beta"; + * }; + * + * Bindings fragment for the vnd,clock compatible: + * + * assigned-clock-cells: + * - bus + * - bits + * + * Example usage: + * + * DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), alpha, bus) // 10 + * DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_NODELABEL(n), beta, bits) // 40 + * + * @param node_id node identifier for a node with a assigned-clocks property + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @param cell lowercase-and-underscores cell name + * @return the cell value in the specifier at the named element + * @see DT_PHA_BY_NAME() + */ +#define DT_ASSIGNED_CLOCKS_CELL_BY_NAME(node_id, name, cell) \ + DT_PHA_BY_NAME(node_id, assigned_clocks, name, cell) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) + * @param node_id node identifier for a node with a assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index 0 + * @see DT_ASSIGNED_CLOCKS_CELL_BY_IDX() + */ +#define DT_ASSIGNED_CLOCKS_CELL(node_id, cell) DT_ASSIGNED_CLOCKS_CELL_BY_IDX(node_id, 0, cell) + +/** + * @brief Equivalent to DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) + * @param inst DT_DRV_COMPAT instance number; may or may not have any assigned-clocks property + * @param idx index of a assigned-clocks property phandle-array whose existence to check + * @return 1 if the index exists, 0 otherwise + */ +#define DT_INST_ASSIGNED_CLOCKS_HAS_IDX(inst, idx) \ + DT_ASSIGNED_CLOCKS_HAS_IDX(DT_DRV_INST(inst), idx) + +/** + * @brief Equivalent to DT_CLOCK_HAS_NAME(DT_DRV_INST(inst), name) + * @param inst DT_DRV_COMPAT instance number; may or may not have any clock-names property. + * @param name lowercase-and-underscores clock-names cell value name to check + * @return 1 if the assigned-clock name exists, 0 otherwise + */ +#define DT_INST_ASSIGNED_CLOCKS_HAS_NAME(inst, name) \ + DT_ASSIGNED_CLOCKS_HAS_NAME(DT_DRV_INST(inst), name) + +/** + * @brief Equivalent to DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) + * @param inst instance number + * @return number of elements in the assigned-clocks property + */ +#define DT_INST_NUM_ASSIGNED_CLOCKS(inst) \ + DT_NUM_ASSIGNED_CLOCKS(DT_DRV_INST(inst)) + +/** + * @brief Get the node identifier for the controller phandle from a + * "assigned-clocks" phandle-array property at an index + * + * @param inst instance number + * @param idx logical index into "assigned-clocks" + * @return the node identifier for the clock controller referenced at + * index "idx" + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_IDX() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, idx) \ + DT_ASSIGNED_CLOCKS_CTLR_BY_IDX(DT_DRV_INST(inst), idx) + +/** + * @brief Equivalent to DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) + * @param inst instance number + * @return a node identifier for the assigned-clocks controller at index 0 + * in "assigned-clocks" + * @see DT_ASSIGNED_CLOCKS_CTLR() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR(inst) DT_INST_ASSIGNED_CLOCKS_CTLR_BY_IDX(inst, 0) + +/** + * @brief Get the node identifier for the controller phandle from a + * assigned-clocks phandle-array property by name + * + * @param inst instance number + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @return the node identifier for the clock controller referenced by + * the named element + * @see DT_ASSIGNED_CLOCKS_CTLR_BY_NAME() + */ +#define DT_INST_ASSIGNED_CLOCKS_CTLR_BY_NAME(inst, name) \ + DT_ASSIGNED_CLOCKS_CTLR_BY_NAME(DT_DRV_INST(inst), name) + +/** + * @brief Get a DT_DRV_COMPAT instance's assigned-clock specifier's cell value + * at an index + * @param inst DT_DRV_COMPAT instance number + * @param idx logical index into assigned-clocks property + * @param cell lowercase-and-underscores cell name + * @return the cell value at index "idx" + * @see DT_ASSIGNED_CLOCKS_CELL_BY_IDX() + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, idx, cell) \ + DT_ASSIGNED_CLOCKS_CELL_BY_IDX(DT_DRV_INST(inst), idx, cell) + +/** + * @brief Get a DT_DRV_COMPAT instance's assigned-clock specifier's cell value by name + * @param inst DT_DRV_COMPAT instance number + * @param name lowercase-and-underscores name of a assigned-clocks element + * as defined by the node's clock-names property + * @param cell lowercase-and-underscores cell name + * @return the cell value in the specifier at the named element + * @see DT_ASSIGNED_CLOCKS_CELL_BY_NAME() + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL_BY_NAME(inst, name, cell) \ + DT_ASSIGNED_CLOCKS_CELL_BY_NAME(DT_DRV_INST(inst), name, cell) + +/** + * @brief Equivalent to DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) + * @param inst DT_DRV_COMPAT instance number + * @param cell lowercase-and-underscores cell name + * @return the value of the cell inside the specifier at index 0 + */ +#define DT_INST_ASSIGNED_CLOCKS_CELL(inst, cell) \ + DT_INST_ASSIGNED_CLOCKS_CELL_BY_IDX(inst, 0, cell) + /** * @} */ diff --git a/soc/atmel/sam0/common/Kconfig.samd2x b/soc/atmel/sam0/common/Kconfig.samd2x index f23b6557963139..e9a210a2167586 100644 --- a/soc/atmel/sam0/common/Kconfig.samd2x +++ b/soc/atmel/sam0/common/Kconfig.samd2x @@ -1,3 +1,4 @@ +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_SAMD20 || SOC_SERIES_SAMD21 || SOC_SERIES_SAMR21 @@ -35,6 +36,21 @@ config SOC_ATMEL_SAMD_XOSC32K_CRYSTAL Enable the crystal oscillator (if disabled, expect a clock signal on XIN32). +DT_ATMEL_RTC := $(dt_nodelabel_path,rtc) +DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock) + +config SOC_ATMEL_SAMD_XOSC32K_PRESCALER + int "XOSC32 Generic Clock Prescaler" + range 1 512 + default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)" + default 1 + depends on SOC_ATMEL_SAMD_XOSC32K + help + Configure the prescaler for the generic clock output + connected on the xosc32. When using RTC in calendar mode + the GCLK should be divided by 32 to RTC receive the + 1024 Hz reference clock. + config SOC_ATMEL_SAMD_XOSC bool "External 0.4..32 MHz clock source" help diff --git a/soc/atmel/sam0/common/Kconfig.samd5x b/soc/atmel/sam0/common/Kconfig.samd5x index dd05fe605d1e47..aa930f2652af59 100644 --- a/soc/atmel/sam0/common/Kconfig.samd5x +++ b/soc/atmel/sam0/common/Kconfig.samd5x @@ -1,4 +1,5 @@ # Copyright (c) 2019 ML!PA Consulting GmbH +# Copyright (c) 2024 Gerson Fernando Budke # SPDX-License-Identifier: Apache-2.0 if SOC_SERIES_SAMD51 || SOC_SERIES_SAME51 || SOC_SERIES_SAME53 || SOC_SERIES_SAME54 @@ -10,6 +11,34 @@ config SOC_ATMEL_SAMD5X_XOSC32K startup. This can then be selected as the main clock source for the SOC. +config SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL + bool "External 32.768 kHz clock is a crystal oscillator" + depends on SOC_ATMEL_SAMD5X_XOSC32K + default y + help + Enable the crystal oscillator (if disabled, expect a clock + signal on XIN32). + +config SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS + bool "XOSC32 High Speed gain" + depends on SOC_ATMEL_SAMD5X_XOSC32K + help + When this option is selected the gain is set High Speed + instead standard. + +DT_ATMEL_RTC := $(dt_nodelabel_path,rtc) +DT_ATMEL_RTC_COUNTER_CLOCK_MODE := $(dt_node_str_prop_equals,$(DT_ATMEL_RTC),counter-mode,clock) + +config SOC_ATMEL_SAMD5X_OSC32K_PRESCALER + int "XOSC32 Generic Clock Prescaler" + range 1 512 + default 32 if "$(DT_ATMEL_RTC_COUNTER_CLOCK_MODE)" + default 1 + help + Configure the prescaler for the generic clock output connected on the + xosc32 or osculp32k. When using RTC in calendar mode the GCLK should + be divided by 32 to RTC receive the 1024 Hz reference clock. + choice prompt "Main clock source" default SOC_ATMEL_SAMD5X_DEFAULT_AS_MAIN diff --git a/soc/atmel/sam0/common/atmel_sam0_dt.h b/soc/atmel/sam0/common/atmel_sam0_dt.h index f803596c872ac4..5e2ee46d12709d 100644 --- a/soc/atmel/sam0/common/atmel_sam0_dt.h +++ b/soc/atmel/sam0/common/atmel_sam0_dt.h @@ -1,6 +1,6 @@ /* * Copyright (c) 2020 Linaro Ltd. - * Copyright (c) 2021 Gerson Fernando Budke + * Copyright (c) 2021-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,15 +9,33 @@ * @brief Atmel SAM0 MCU family devicetree helper macros */ +/* clang-format off */ + #ifndef _ATMEL_SAM0_DT_H_ #define _ATMEL_SAM0_DT_H_ -/* Helper macro to get MCLK register address for corresponding - * that has corresponding clock enable bit. +#define ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, cell) \ + (volatile uint32_t *) \ + (DT_REG_ADDR(DT_INST_PHANDLE_BY_NAME(n, clocks, cell)) + \ + DT_INST_CLOCKS_CELL_BY_NAME(n, cell, offset)) + +#define ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, name, cell) \ + BIT(DT_INST_CLOCKS_CELL_BY_NAME(n, name, cell)) + +/* Helper macro to get register address that control peripheral clock + * enable bit. */ -#define MCLK_MASK_DT_INT_REG_ADDR(n) \ - (DT_REG_ADDR(DT_INST_PHANDLE_BY_NAME(n, clocks, mclk)) + \ - DT_INST_CLOCKS_CELL_BY_NAME(n, mclk, offset)) +#define ATMEL_SAM0_DT_INST_MCLK_PM_REG_ADDR_OFFSET(n) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_REG_ADDR_OFFSET(n, pm))) + +/* Helper macro to get peripheral clock bit mask. + */ +#define ATMEL_SAM0_DT_INST_MCLK_PM_PERIPH_MASK(n, cell) \ + COND_CODE_1(DT_NODE_HAS_STATUS_OKAY(DT_NODELABEL(mclk)), \ + (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, mclk, cell)), \ + (ATMEL_SAM0_DT_INST_CELL_PERIPH_MASK(n, pm, cell))) /* Helper macros for use with ATMEL SAM0 DMAC controller * return 0xff as default value if there is no 'dmas' property @@ -49,3 +67,5 @@ DT_PROP(DT_PATH(cpus, cpu_0), clock_frequency) #endif /* _ATMEL_SAM0_SOC_DT_H_ */ + +/* clang-format on */ diff --git a/soc/atmel/sam0/common/soc_samc2x.c b/soc/atmel/sam0/common/soc_samc2x.c index 1581b62eef2e75..38826d13434da1 100644 --- a/soc/atmel/sam0/common/soc_samc2x.c +++ b/soc/atmel/sam0/common/soc_samc2x.c @@ -10,11 +10,19 @@ * @brief Atmel SAMC MCU series initialization code */ +/* GCLK Gen 0 -> GCLK_MAIN @ OSC48M + * GCLK Gen 2 -> WDT @ reserved + * GCLK Gen 0 -> ADC @ OSC48M + * GCLK Gen 4 -> RTC @ reserved + */ + #include #include #include #include +/* clang-format off */ + static void flash_waitstates_init(void) { /* Two wait state at 48 MHz. */ @@ -50,3 +58,5 @@ void soc_reset_hook(void) mclk_init(); gclks_init(); } + +/* clang-format on */ diff --git a/soc/atmel/sam0/common/soc_samd2x.c b/soc/atmel/sam0/common/soc_samd2x.c index f915459a576627..7db21a962921cb 100644 --- a/soc/atmel/sam0/common/soc_samd2x.c +++ b/soc/atmel/sam0/common/soc_samd2x.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2017 Google LLC. * Copyright (c) 2023 Ionut Catalin Pavel - * Copyright (c) 2023 Gerson Fernando Budke + * Copyright (c) 2023-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -20,6 +20,7 @@ * GCLK Gen 1 -> DFLL48M (variable) * GCLK Gen 2 -> WDT @ 32768 Hz * GCLK Gen 3 -> ADC @ 8 MHz + * GCLK Gen 4 -> RTC @ xtal 32768 Hz */ #include @@ -29,6 +30,8 @@ #include #include +/* clang-format off */ + /** * Fix different naming conventions for SAMD20 */ @@ -38,6 +41,23 @@ #define FUSES_OSC32K_CAL_Msk FUSES_OSC32KCAL_Msk #endif +static void gclk_connect(uint8_t gclk, uint32_t src, uint32_t div, uint32_t flags) +{ + GCLK->GENDIV.reg = GCLK_GENDIV_ID(gclk) + | GCLK_GENDIV_DIV(div); + + while (GCLK->STATUS.bit.SYNCBUSY) { + } + + GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(gclk) + | GCLK_GENCTRL_GENEN + | src + | flags; + + while (GCLK->STATUS.bit.SYNCBUSY) { + } +} + static inline void osc8m_init(void) { uint32_t reg; @@ -57,19 +77,7 @@ static inline void osc8m_init(void) /* Use 8Mhz clock as gclk_main to allow switching between clocks * when using bootloaders */ - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) - | GCLK_GENDIV_DIV(0); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) - | GCLK_GENCTRL_SRC_OSC8M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(0, GCLK_GENCTRL_SRC_OSC8M, 0, 0); } #if !CONFIG_SOC_ATMEL_SAMD_OSC32K || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN @@ -149,28 +157,17 @@ static inline void dfll48m_init(void) { uint32_t fcal, ccal; - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1) + gclk_connect(1, #if CONFIG_SOC_ATMEL_SAMD_OSC32K_AS_MAIN - | GCLK_GENCTRL_SRC_OSC32K + GCLK_GENCTRL_SRC_OSC32K, #elif CONFIG_SOC_ATMEL_SAMD_XOSC32K_AS_MAIN - | GCLK_GENCTRL_SRC_XOSC32K + GCLK_GENCTRL_SRC_XOSC32K, #elif CONFIG_SOC_ATMEL_SAMD_OSC8M_AS_MAIN - | GCLK_GENCTRL_SRC_OSC8M + GCLK_GENCTRL_SRC_OSC8M, #elif CONFIG_SOC_ATMEL_SAMD_XOSC_AS_MAIN - | GCLK_GENCTRL_SRC_XOSC + GCLK_GENCTRL_SRC_XOSC, #endif - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_RUNSTDBY - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK1_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + SOC_ATMEL_SAM0_GCLK1_DIV, GCLK_GENCTRL_RUNSTDBY); /* Route multiplexer 0 to DFLL48M */ GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(0) @@ -222,19 +219,7 @@ static inline void flash_waitstates_init(void) #else static inline void gclk_main_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK0_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) - | GCLK_GENCTRL_SRC_DFLL48M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(0, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK0_DIV, 0); } #endif @@ -243,19 +228,16 @@ static inline void gclk_main_configure(void) #else static inline void gclk_adc_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(3) - | GCLK_GENDIV_DIV(SOC_ATMEL_SAM0_GCLK3_DIV); - - while (GCLK->STATUS.bit.SYNCBUSY) { - } - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(3) - | GCLK_GENCTRL_SRC_DFLL48M - | GCLK_GENCTRL_IDC - | GCLK_GENCTRL_GENEN; + gclk_connect(3, GCLK_GENCTRL_SRC_DFLL48M, SOC_ATMEL_SAM0_GCLK3_DIV, 0); +} +#endif - while (GCLK->STATUS.bit.SYNCBUSY) { - } +#if !CONFIG_RTC_ATMEL_SAM0 || CONFIG_SOC_ATMEL_SAMD_DEFAULT_AS_MAIN +#define gclk_rtc_configure() +#else +static inline void gclk_rtc_configure(void) +{ + gclk_connect(4, GCLK_GENCTRL_SRC_XOSC32K, CONFIG_SOC_ATMEL_SAMD_XOSC32K_PRESCALER, 0); } #endif @@ -264,16 +246,7 @@ static inline void gclk_adc_configure(void) #else static inline void gclk_wdt_configure(void) { - GCLK->GENDIV.reg = GCLK_GENDIV_ID(2) - | GCLK_GENDIV_DIV(4); - - GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(2) - | GCLK_GENCTRL_GENEN - | GCLK_GENCTRL_SRC_OSCULP32K - | GCLK_GENCTRL_DIVSEL; - - while (GCLK->STATUS.bit.SYNCBUSY) { - } + gclk_connect(2, GCLK_GENCTRL_SRC_OSCULP32K, 4, GCLK_GENCTRL_DIVSEL); } #endif @@ -296,6 +269,9 @@ void soc_reset_hook(void) flash_waitstates_init(); gclk_main_configure(); gclk_adc_configure(); + gclk_rtc_configure(); gclk_wdt_configure(); osc8m_disable(); } + +/* clang-format on */ diff --git a/soc/atmel/sam0/common/soc_samd5x.c b/soc/atmel/sam0/common/soc_samd5x.c index f9f337f0f3b2f5..0dc8b018938fc9 100644 --- a/soc/atmel/sam0/common/soc_samd5x.c +++ b/soc/atmel/sam0/common/soc_samd5x.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2019 ML!PA Consulting GmbH - * Copyright (c) 2023 Gerson Fernando Budke + * Copyright (c) 2023-2024 Gerson Fernando Budke * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,25 +10,56 @@ * @brief Atmel SAMD MCU series initialization code */ +/* The CPU clock will be configured to the DT requested value, + * and run via DFLL48M. + * + * Reference -> GCLK Gen 1 -> DFLL48M -> GCLK Gen 0 -> GCLK_MAIN + * + * GCLK Gen 0 -> GCLK_MAIN @ DPLL0 + * GCLK Gen 1 -> DFLL48M @ 32768 Hz + * GCLK Gen 2 -> USB @ DFLL48M + * GCLK Gen 3 -> ADC @ reserved + * GCLK Gen 4 -> RTC @ xtal 32768 Hz + */ + #include #include #include #include +/* clang-format off */ + #define SAM0_DFLL_FREQ_HZ (48000000U) #define SAM0_DPLL_FREQ_MIN_HZ (96000000U) #define SAM0_DPLL_FREQ_MAX_HZ (200000000U) -#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN -static void osc32k_init(void) +#if !CONFIG_SOC_ATMEL_SAMD5X_XOSC32K +#define xosc32k_init() +#else +static inline void xosc32k_init(void) { - OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE | OSC32KCTRL_XOSC32K_XTALEN - | OSC32KCTRL_XOSC32K_EN32K | OSC32KCTRL_XOSC32K_RUNSTDBY - | OSC32KCTRL_XOSC32K_STARTUP(0) | OSC32KCTRL_XOSC32K_CGM_XT; + OSC32KCTRL->XOSC32K.reg = OSC32KCTRL_XOSC32K_ENABLE +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_CRYSTAL + | OSC32KCTRL_XOSC32K_XTALEN +#endif +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_GAIN_HS + | OSC32KCTRL_XOSC32K_CGM_HS +#else + | OSC32KCTRL_XOSC32K_CGM_XT +#endif + | OSC32KCTRL_XOSC32K_EN32K + | OSC32KCTRL_XOSC32K_EN1K + | OSC32KCTRL_XOSC32K_RUNSTDBY + | OSC32KCTRL_XOSC32K_STARTUP(1); while (!OSC32KCTRL->STATUS.bit.XOSC32KRDY) { } +} +#endif +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K_AS_MAIN +static void osc32k_init(void) +{ GCLK->GENCTRL[1].reg = GCLK_GENCTRL_SRC(GCLK_SOURCE_XOSC32K) | GCLK_GENCTRL_RUNSTDBY | GCLK_GENCTRL_GENEN; @@ -127,6 +158,7 @@ void soc_reset_hook(void) CMCC->CTRL.bit.CEN = 0; gclk_reset(); + xosc32k_init(); osc32k_init(); dfll_init(); dpll_init(0, dfll_div * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); @@ -136,4 +168,15 @@ void soc_reset_hook(void) /* connect GCLK2 to 48 MHz DFLL for USB */ gclk_connect(2, GCLK_SOURCE_DFLL48M, 0); + + /* connect GCLK4 to xosc32k for RTC. The output is 1024 Hz*/ + gclk_connect(4, +#if CONFIG_SOC_ATMEL_SAMD5X_XOSC32K + GCLK_SOURCE_XOSC32K, +#else + GCLK_SOURCE_OSCULP32K, +#endif + CONFIG_SOC_ATMEL_SAMD5X_OSC32K_PRESCALER); } + +/* clang-format on */ diff --git a/soc/atmel/sam0/common/soc_saml2x.c b/soc/atmel/sam0/common/soc_saml2x.c index 3dd657a52f2251..fbb4db2d90b389 100644 --- a/soc/atmel/sam0/common/soc_saml2x.c +++ b/soc/atmel/sam0/common/soc_saml2x.c @@ -16,6 +16,8 @@ #include #include +/* clang-format off */ + /* the SAML21 currently operates only in Performance Level 2... sleep * and low-power operation are not currently supported by the BSP * @@ -27,6 +29,7 @@ * GCLK Gen 1 -> DFLL48M (variable) * GCLK Gen 2 -> USB @ 48 MHz * GCLK Gen 3 -> ADC @ 24 MHz (further /2 in the ADC peripheral) + * GCLK Gen 4 -> RTC @ reserved */ static inline void gclk_reset(void) @@ -57,6 +60,7 @@ static inline void osc32k_init(void) | !OSC32KCTRL_OSC32K_ONDEMAND | OSC32KCTRL_OSC32K_RUNSTDBY | OSC32KCTRL_OSC32K_EN32K + | OSC32KCTRL_OSC32K_EN1K | OSC32KCTRL_OSC32K_ENABLE; /* wait for ready */ @@ -75,6 +79,7 @@ static inline void xosc32k_init(void) | !OSC32KCTRL_XOSC32K_ONDEMAND | OSC32KCTRL_XOSC32K_RUNSTDBY | OSC32KCTRL_XOSC32K_EN32K + | OSC32KCTRL_XOSC32K_EN1K #if CONFIG_SOC_ATMEL_SAML_XOSC32K_CRYSTAL | OSC32KCTRL_XOSC32K_XTALEN #endif @@ -266,3 +271,5 @@ void soc_reset_hook(void) gclk_usb_configure(); gclk_adc_configure(); } + +/* clang-format on */ diff --git a/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samc21n_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samd20_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf b/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/same54_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf b/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/saml21_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y diff --git a/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf b/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf new file mode 100644 index 00000000000000..80e21536ba3563 --- /dev/null +++ b/tests/drivers/rtc/rtc_api/boards/samr21_xpro.conf @@ -0,0 +1,3 @@ +CONFIG_RTC_ALARM=y +CONFIG_TEST_RTC_ALARM_TIME_MASK=63 +CONFIG_RTC_CALIBRATION=y