Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drivers: rtc: sam0: Add RTC calendar driver and clock fixes #81819

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/samc21n_xpro/samc21n_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- gpio
- i2c
- pwm
- rtc
- spi
- uart
vendor: atmel
6 changes: 6 additions & 0 deletions boards/atmel/sam0/samd20_xpro/samd20_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@
clock-frequency = <DT_FREQ_M(48)>;
};

&rtc {
status = "okay";
counter-mode = "clock";
prescaler = <1024>;
};

&sercom0 {
status = "okay";
compatible = "atmel,sam0-spi";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/samd20_xpro/samd20_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ supported:
- flash
- gpio
- i2c
- rtc
- spi
- uart
- watchdog
Expand Down
6 changes: 6 additions & 0 deletions boards/atmel/sam0/samd21_xpro/samd21_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@
pinctrl-names = "default";
};

&rtc {
status = "okay";
counter-mode = "clock";
prescaler = <1024>;
};

&sercom0 {
status = "okay";
compatible = "atmel,sam0-uart";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- gpio
- i2c
- pwm
- rtc
- spi
- uart
- usb_device
Expand Down
8 changes: 8 additions & 0 deletions boards/atmel/sam0/same54_xpro/same54_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/same54_xpro/same54_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- i2c
- netif:eth
- pwm
- rtc
- spi
- uart
- usb_device
Expand Down
8 changes: 8 additions & 0 deletions boards/atmel/sam0/saml21_xpro/saml21_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- gpio
- i2c
- pwm
- rtc
- spi
- uart
- usb_device
Expand Down
6 changes: 6 additions & 0 deletions boards/atmel/sam0/samr21_xpro/samr21_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,12 @@
pinctrl-names = "default";
};

&rtc {
status = "okay";
counter-mode = "clock";
prescaler = <1024>;
};

&sercom0 {
status = "okay";
compatible = "atmel,sam0-uart";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/samr21_xpro/samr21_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- i2c
- netif
- pwm
- rtc
- spi
- uart
- usb_device
Expand Down
8 changes: 8 additions & 0 deletions boards/atmel/sam0/samr34_xpro/samr34_xpro.dts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
1 change: 1 addition & 0 deletions boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ supported:
- gpio
- i2c
- pwm
- rtc
- spi
- uart
- usb_device
Expand Down
116 changes: 55 additions & 61 deletions drivers/adc/adc_sam0.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2019 Derek Hageman <[email protected]>
* Copyright (c) 2024 Gerson Fernando Budke <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -46,18 +47,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);
};

Expand Down Expand Up @@ -449,14 +444,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);
Expand Down Expand Up @@ -515,14 +513,6 @@ 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; \
Expand All @@ -534,62 +524,66 @@ do { \

#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 */ \
uint32_t lin = ((*(uint32_t *)ADC_FUSES_LINEARITY_0_ADDR) & \
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; \
uint32_t bias = ((*(uint32_t *)ADC_FUSES_BIASCAL_ADDR) & \
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); \
} 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)
24 changes: 13 additions & 11 deletions drivers/can/can_sam0.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 <[email protected]>
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -26,7 +27,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;
};

Expand Down Expand Up @@ -109,6 +111,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*/
Expand All @@ -121,13 +129,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)
Expand Down Expand Up @@ -211,9 +212,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, \
Expand Down
Loading
Loading