Skip to content

Commit a0d6289

Browse files
benpicconashif
authored andcommitted
i2c: sam0: Add support for SAME54
It shares the same peripheral with other sam0 parts while differing in the clock config. Signed-off-by: Benjamin Valentin <[email protected]>
1 parent 8922afb commit a0d6289

File tree

1 file changed

+67
-14
lines changed

1 file changed

+67
-14
lines changed

drivers/i2c/i2c_sam0.c

Lines changed: 67 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,21 @@ LOG_MODULE_REGISTER(i2c_sam0, CONFIG_I2C_LOG_LEVEL);
1717

1818
#include "i2c-priv.h"
1919

20+
#ifndef SERCOM_I2CM_CTRLA_MODE_I2C_MASTER
21+
#define SERCOM_I2CM_CTRLA_MODE_I2C_MASTER SERCOM_I2CM_CTRLA_MODE(5)
22+
#endif
23+
2024
struct i2c_sam0_dev_config {
2125
SercomI2cm *regs;
2226
u32_t bitrate;
27+
#ifdef MCLK
28+
volatile uint32_t *mclk;
29+
u32_t mclk_mask;
30+
u16_t gclk_core_id;
31+
#else
2332
u32_t pm_apbcmask;
2433
u16_t gclk_clkctrl_id;
25-
34+
#endif
2635
void (*irq_config_func)(struct device *dev);
2736

2837
#ifdef CONFIG_I2C_SAM0_DMA_DRIVEN
@@ -660,13 +669,20 @@ static int i2c_sam0_initialize(struct device *dev)
660669
SercomI2cm *i2c = cfg->regs;
661670
int retval;
662671

672+
#ifdef MCLK
673+
/* Enable the GCLK */
674+
GCLK->PCHCTRL[cfg->gclk_core_id].reg = GCLK_PCHCTRL_GEN_GCLK0 |
675+
GCLK_PCHCTRL_CHEN;
676+
/* Enable SERCOM clock in MCLK */
677+
*cfg->mclk |= cfg->mclk_mask;
678+
#else
663679
/* Enable the GCLK */
664680
GCLK->CLKCTRL.reg = cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 |
665681
GCLK_CLKCTRL_CLKEN;
666682

667683
/* Enable SERCOM clock in PM */
668684
PM->APBCMASK.reg |= cfg->pm_apbcmask;
669-
685+
#endif
670686
/* Disable all I2C interrupts */
671687
i2c->INTENCLR.reg = SERCOM_I2CM_INTENCLR_MASK;
672688

@@ -748,30 +764,67 @@ static const struct i2c_driver_api i2c_sam0_driver_api = {
748764
#define I2C_SAM0_DMA_CHANNELS(n)
749765
#endif
750766

751-
#define I2C_SAM0_DEVICE(n) \
752-
static void i2c_sam_irq_config_##n(struct device *dev); \
767+
#define DT_ATMEL_SAM0_I2C_SERCOM_IRQ(n, m) DT_ATMEL_SAM0_I2C_SERCOM_ ## n ## _IRQ_ ## m
768+
#define DT_ATMEL_SAM0_I2C_SERCOM_IRQ_PRIORITY(n, m) DT_ATMEL_SAM0_I2C_SERCOM_ ## n ## _IRQ_ ## m ## _PRIORITY
769+
770+
#define SAM0_I2C_IRQ_CONNECT(n, m) \
771+
do { \
772+
IRQ_CONNECT(DT_ATMEL_SAM0_I2C_SERCOM_IRQ(n, m), \
773+
DT_ATMEL_SAM0_I2C_SERCOM_IRQ_PRIORITY(n, m), \
774+
i2c_sam0_isr, DEVICE_GET(i2c_sam0_##n), 0); \
775+
irq_enable(DT_ATMEL_SAM0_I2C_SERCOM_IRQ(n, m)); \
776+
} while (0)
777+
778+
#ifdef DT_ATMEL_SAM0_I2C_0_IRQ_3
779+
#define I2C_SAM0_IRQ_HANDLER(n) \
780+
static void i2c_sam0_irq_config_##n(struct device *dev) \
781+
{ \
782+
SAM0_I2C_IRQ_CONNECT(n, 0); \
783+
SAM0_I2C_IRQ_CONNECT(n, 1); \
784+
SAM0_I2C_IRQ_CONNECT(n, 2); \
785+
SAM0_I2C_IRQ_CONNECT(n, 3); \
786+
}
787+
#else
788+
#define I2C_SAM0_IRQ_HANDLER(n) \
789+
static void i2c_sam0_irq_config_##n(struct device *dev) \
790+
{ \
791+
SAM0_I2C_IRQ_CONNECT(n, 0); \
792+
}
793+
#endif
794+
795+
#ifdef MCLK
796+
#define I2C_SAM0_CONFIG(n) \
797+
static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \
798+
.regs = (SercomI2cm *)DT_ATMEL_SAM0_I2C_SERCOM_##n##_BASE_ADDRESS, \
799+
.bitrate = DT_ATMEL_SAM0_I2C_SERCOM_##n##_CLOCK_FREQUENCY, \
800+
.mclk = MCLK_SERCOM##n, \
801+
.mclk_mask = MCLK_SERCOM##n##_MASK, \
802+
.gclk_core_id = SERCOM##n##_GCLK_ID_CORE, \
803+
.irq_config_func = &i2c_sam0_irq_config_##n \
804+
I2C_SAM0_DMA_CHANNELS(n) \
805+
}
806+
#else /* !MCLK */
807+
#define I2C_SAM0_CONFIG(n) \
753808
static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \
754809
.regs = (SercomI2cm *)DT_ATMEL_SAM0_I2C_SERCOM_##n##_BASE_ADDRESS, \
755810
.bitrate = DT_ATMEL_SAM0_I2C_SERCOM_##n##_CLOCK_FREQUENCY, \
756811
.pm_apbcmask = PM_APBCMASK_SERCOM##n, \
757812
.gclk_clkctrl_id = GCLK_CLKCTRL_ID_SERCOM##n##_CORE, \
758-
.irq_config_func = &i2c_sam_irq_config_##n, \
813+
.irq_config_func = &i2c_sam0_irq_config_##n, \
759814
I2C_SAM0_DMA_CHANNELS(n) \
760-
}; \
815+
}
816+
#endif
817+
818+
#define I2C_SAM0_DEVICE(n) \
819+
static void i2c_sam0_irq_config_##n(struct device *dev); \
820+
I2C_SAM0_CONFIG(n); \
761821
static struct i2c_sam0_dev_data i2c_sam0_dev_data_##n; \
762822
DEVICE_AND_API_INIT(i2c_sam0_##n, \
763823
DT_ATMEL_SAM0_I2C_SERCOM_##n##_LABEL, \
764824
&i2c_sam0_initialize, &i2c_sam0_dev_data_##n, \
765825
&i2c_sam0_dev_config_##n, POST_KERNEL, \
766826
CONFIG_I2C_INIT_PRIORITY, &i2c_sam0_driver_api);\
767-
static void i2c_sam_irq_config_##n(struct device *dev) \
768-
{ \
769-
IRQ_CONNECT(DT_ATMEL_SAM0_I2C_SERCOM_##n##_IRQ_0, \
770-
DT_ATMEL_SAM0_I2C_SERCOM_##n##_IRQ_0_PRIORITY, \
771-
i2c_sam0_isr, DEVICE_GET(i2c_sam0_##n), \
772-
0); \
773-
irq_enable(DT_ATMEL_SAM0_I2C_SERCOM_##n##_IRQ_0); \
774-
}
827+
I2C_SAM0_IRQ_HANDLER(n)
775828

776829
#if DT_ATMEL_SAM0_I2C_SERCOM_0_BASE_ADDRESS
777830
I2C_SAM0_DEVICE(0);

0 commit comments

Comments
 (0)