serial: sam0: Add support for SAME54
The SAME5x/SAMD5x MCUs share their SERCOM peripherals with the samd2x and saml1x MCUs with only few registers changed. Signed-off-by: Benjamin Valentin <benjamin.valentin@ml-pa.com>
This commit is contained in:
parent
2e1d2889e2
commit
ca9a64bd13
1 changed files with 90 additions and 30 deletions
|
@ -12,13 +12,23 @@
|
|||
#include <drivers/uart.h>
|
||||
#include <drivers/dma.h>
|
||||
|
||||
#ifndef SERCOM_USART_CTRLA_MODE_USART_INT_CLK
|
||||
#define SERCOM_USART_CTRLA_MODE_USART_INT_CLK SERCOM_USART_CTRLA_MODE(0x1)
|
||||
#endif
|
||||
|
||||
/* Device constant configuration parameters */
|
||||
struct uart_sam0_dev_cfg {
|
||||
SercomUsart *regs;
|
||||
u32_t baudrate;
|
||||
u32_t pads;
|
||||
#ifdef MCLK
|
||||
volatile uint32_t *mclk;
|
||||
u32_t mclk_mask;
|
||||
u16_t gclk_core_id;
|
||||
#else
|
||||
u32_t pm_apbcmask;
|
||||
u16_t gclk_clkctrl_id;
|
||||
#endif
|
||||
#if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API
|
||||
void (*irq_config_func)(struct device *dev);
|
||||
#endif
|
||||
|
@ -373,12 +383,21 @@ static int uart_sam0_init(struct device *dev)
|
|||
const struct uart_sam0_dev_cfg *const cfg = DEV_CFG(dev);
|
||||
SercomUsart *const usart = cfg->regs;
|
||||
|
||||
#ifdef MCLK
|
||||
/* Enable the GCLK */
|
||||
GCLK->CLKCTRL.reg =
|
||||
cfg->gclk_clkctrl_id | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_CLKEN;
|
||||
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;
|
||||
#endif
|
||||
|
||||
/* Disable all USART interrupts */
|
||||
usart->INTENCLR.reg = SERCOM_USART_INTENCLR_MASK;
|
||||
|
@ -386,9 +405,9 @@ static int uart_sam0_init(struct device *dev)
|
|||
|
||||
/* 8 bits of data, no parity, 1 stop bit in normal mode */
|
||||
usart->CTRLA.reg =
|
||||
cfg->pads |
|
||||
cfg->pads
|
||||
/* Internal clock */
|
||||
SERCOM_USART_CTRLA_MODE_USART_INT_CLK
|
||||
| SERCOM_USART_CTRLA_MODE_USART_INT_CLK
|
||||
#if defined(SERCOM_USART_CTRLA_SAMPR)
|
||||
/* 16x oversampling with arithmetic baud rate generation */
|
||||
| SERCOM_USART_CTRLA_SAMPR(0)
|
||||
|
@ -398,7 +417,7 @@ static int uart_sam0_init(struct device *dev)
|
|||
wait_synchronization(usart);
|
||||
|
||||
/* Enable receiver and transmitter */
|
||||
usart->CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(0) |
|
||||
usart->CTRLB.reg = SERCOM_USART_CTRLB_CHSIZE(0) |
|
||||
SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN;
|
||||
wait_synchronization(usart);
|
||||
|
||||
|
@ -905,20 +924,39 @@ static const struct uart_driver_api uart_sam0_driver_api = {
|
|||
};
|
||||
|
||||
#if CONFIG_UART_INTERRUPT_DRIVEN || CONFIG_UART_ASYNC_API
|
||||
#define DT_ATMEL_SAM0_UART_SERCOM_IRQ(n, m) DT_ATMEL_SAM0_UART_SERCOM_ ## n ## _IRQ_ ## m
|
||||
#define DT_ATMEL_SAM0_UART_SERCOM_IRQ_PRIORITY(n, m) DT_ATMEL_SAM0_UART_SERCOM_ ## n ## _IRQ_ ## m ## _PRIORITY
|
||||
|
||||
#define SAM0_UART_IRQ_CONNECT(n, m) \
|
||||
do { \
|
||||
IRQ_CONNECT(DT_ATMEL_SAM0_UART_SERCOM_IRQ(n, m), \
|
||||
DT_ATMEL_SAM0_UART_SERCOM_IRQ_PRIORITY(n, m), \
|
||||
uart_sam0_isr, DEVICE_GET(uart_sam0_##n), 0); \
|
||||
irq_enable(DT_ATMEL_SAM0_UART_SERCOM_IRQ(n, m)); \
|
||||
} while (0)
|
||||
|
||||
#define UART_SAM0_IRQ_HANDLER_DECL(n) \
|
||||
static void uart_sam0_irq_config_##n(struct device *dev)
|
||||
static void uart_sam0_irq_config_##n(struct device *dev)
|
||||
#define UART_SAM0_IRQ_HANDLER_FUNC(n) \
|
||||
.irq_config_func = uart_sam0_irq_config_##n,
|
||||
|
||||
#ifdef DT_ATMEL_SAM0_UART_0_IRQ_3
|
||||
#define UART_SAM0_IRQ_HANDLER(n) \
|
||||
static void uart_sam0_irq_config_##n(struct device *dev) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_ATMEL_SAM0_UART_SERCOM_##n##_IRQ_0, \
|
||||
DT_ATMEL_SAM0_UART_SERCOM_##n##_IRQ_0_PRIORITY, \
|
||||
uart_sam0_isr, DEVICE_GET(uart_sam0_##n), \
|
||||
0); \
|
||||
irq_enable(DT_ATMEL_SAM0_UART_SERCOM_##n##_IRQ_0); \
|
||||
SAM0_UART_IRQ_CONNECT(n, 0); \
|
||||
SAM0_UART_IRQ_CONNECT(n, 1); \
|
||||
SAM0_UART_IRQ_CONNECT(n, 2); \
|
||||
SAM0_UART_IRQ_CONNECT(n, 3); \
|
||||
}
|
||||
#else
|
||||
#define UART_SAM0_IRQ_HANDLER(n) \
|
||||
static void uart_sam0_irq_config_##n(struct device *dev) \
|
||||
{ \
|
||||
SAM0_UART_IRQ_CONNECT(n, 0); \
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define UART_SAM0_IRQ_HANDLER_DECL(n)
|
||||
#define UART_SAM0_IRQ_HANDLER_FUNC(n)
|
||||
#define UART_SAM0_IRQ_HANDLER(n)
|
||||
|
@ -972,29 +1010,43 @@ static void uart_sam0_irq_config_##n(struct device *dev) \
|
|||
#endif
|
||||
|
||||
#define UART_SAM0_SERCOM_PADS(n) \
|
||||
(DT_ATMEL_SAM0_UART_SERCOM_##n##_RXPO << SERCOM_USART_CTRLA_RXPO_Pos) |\
|
||||
(DT_ATMEL_SAM0_UART_SERCOM_##n##_RXPO << SERCOM_USART_CTRLA_RXPO_Pos) | \
|
||||
(DT_ATMEL_SAM0_UART_SERCOM_##n##_TXPO << SERCOM_USART_CTRLA_TXPO_Pos)
|
||||
|
||||
#define UART_SAM0_CONFIG_DEFN(n) \
|
||||
static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \
|
||||
.regs = (SercomUsart *)DT_ATMEL_SAM0_UART_SERCOM_##n##_BASE_ADDRESS, \
|
||||
.baudrate = DT_ATMEL_SAM0_UART_SERCOM_##n##_CURRENT_SPEED, \
|
||||
.pm_apbcmask = PM_APBCMASK_SERCOM##n, \
|
||||
.gclk_clkctrl_id = GCLK_CLKCTRL_ID_SERCOM##n##_CORE, \
|
||||
.pads = UART_SAM0_SERCOM_PADS(n), \
|
||||
UART_SAM0_IRQ_HANDLER_FUNC(n) \
|
||||
UART_SAM0_DMA_CHANNELS(n) \
|
||||
#ifdef MCLK
|
||||
#define UART_SAM0_CONFIG_DEFN(n) \
|
||||
static const struct uart_sam0_dev_cfg uart_sam0_config_##n = { \
|
||||
.regs = (SercomUsart *)DT_ATMEL_SAM0_UART_SERCOM_##n##_BASE_ADDRESS, \
|
||||
.baudrate = DT_ATMEL_SAM0_UART_SERCOM_##n##_CURRENT_SPEED, \
|
||||
.mclk = MCLK_SERCOM##n, \
|
||||
.mclk_mask = MCLK_SERCOM##n##_MASK, \
|
||||
.gclk_core_id = SERCOM##n##_GCLK_ID_CORE, \
|
||||
.pads = UART_SAM0_SERCOM_PADS(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_ATMEL_SAM0_UART_SERCOM_##n##_BASE_ADDRESS, \
|
||||
.baudrate = DT_ATMEL_SAM0_UART_SERCOM_##n##_CURRENT_SPEED, \
|
||||
.pm_apbcmask = PM_APBCMASK_SERCOM##n, \
|
||||
.gclk_clkctrl_id = GCLK_CLKCTRL_ID_SERCOM##n##_CORE, \
|
||||
.pads = UART_SAM0_SERCOM_PADS(n), \
|
||||
UART_SAM0_IRQ_HANDLER_FUNC(n) \
|
||||
UART_SAM0_DMA_CHANNELS(n) \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define UART_SAM0_DEVICE_INIT(n) \
|
||||
static struct uart_sam0_dev_data uart_sam0_data_##n; \
|
||||
UART_SAM0_IRQ_HANDLER_DECL(n); \
|
||||
UART_SAM0_CONFIG_DEFN(n); \
|
||||
DEVICE_AND_API_INIT(uart_sam0_##n, DT_ATMEL_SAM0_UART_SERCOM_##n##_LABEL, \
|
||||
uart_sam0_init, &uart_sam0_data_##n, \
|
||||
&uart_sam0_config_##n, PRE_KERNEL_1, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&uart_sam0_driver_api); \
|
||||
#define UART_SAM0_DEVICE_INIT(n) \
|
||||
static struct uart_sam0_dev_data uart_sam0_data_##n; \
|
||||
UART_SAM0_IRQ_HANDLER_DECL(n); \
|
||||
UART_SAM0_CONFIG_DEFN(n); \
|
||||
DEVICE_AND_API_INIT(uart_sam0_##n, DT_ATMEL_SAM0_UART_SERCOM_##n##_LABEL, \
|
||||
uart_sam0_init, &uart_sam0_data_##n, \
|
||||
&uart_sam0_config_##n, PRE_KERNEL_1, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
&uart_sam0_driver_api); \
|
||||
UART_SAM0_IRQ_HANDLER(n)
|
||||
|
||||
#if DT_ATMEL_SAM0_UART_SERCOM_0_BASE_ADDRESS
|
||||
|
@ -1020,3 +1072,11 @@ UART_SAM0_DEVICE_INIT(4)
|
|||
#if DT_ATMEL_SAM0_UART_SERCOM_5_BASE_ADDRESS
|
||||
UART_SAM0_DEVICE_INIT(5)
|
||||
#endif
|
||||
|
||||
#if DT_ATMEL_SAM0_UART_SERCOM_6_BASE_ADDRESS
|
||||
UART_SAM0_DEVICE_INIT(6)
|
||||
#endif
|
||||
|
||||
#if DT_ATMEL_SAM0_UART_SERCOM7_BASE_ADDRESS
|
||||
UART_SAM0_DEVICE_INIT(7)
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue