Add MMIO mapping for UART Renesas driver in order to avoid mappings inside mmu_regions.c file(s). There are a lot of changes inside SCIF driver inside this commit, because reg addr and size may be stored in RAM or ROM and appropriately in different driver structures data or cfg, and, because the name of field reg base is changed. Note: it is common approach according to Zephyr documentation. Signed-off-by: Mykola Kvach <mykola_kvach@epam.com>
585 lines
16 KiB
C
585 lines
16 KiB
C
/*
|
|
* Copyright (c) 2021 IoT.bzh
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define DT_DRV_COMPAT renesas_rcar_scif
|
|
|
|
#include <errno.h>
|
|
#include <zephyr/device.h>
|
|
#include <zephyr/devicetree.h>
|
|
#include <zephyr/drivers/uart.h>
|
|
#include <zephyr/drivers/clock_control.h>
|
|
#include <zephyr/drivers/clock_control/renesas_cpg_mssr.h>
|
|
#include <zephyr/drivers/pinctrl.h>
|
|
#include <zephyr/irq.h>
|
|
#include <zephyr/spinlock.h>
|
|
|
|
struct uart_rcar_cfg {
|
|
DEVICE_MMIO_ROM; /* Must be first */
|
|
const struct device *clock_dev;
|
|
struct rcar_cpg_clk mod_clk;
|
|
struct rcar_cpg_clk bus_clk;
|
|
const struct pinctrl_dev_config *pcfg;
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
void (*irq_config_func)(const struct device *dev);
|
|
#endif
|
|
};
|
|
|
|
struct uart_rcar_data {
|
|
DEVICE_MMIO_RAM; /* Must be first */
|
|
struct uart_config current_config;
|
|
uint32_t clk_rate;
|
|
struct k_spinlock lock;
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
uart_irq_callback_user_data_t callback;
|
|
void *cb_data;
|
|
#endif
|
|
};
|
|
|
|
/* Registers */
|
|
#define SCSMR 0x00 /* Serial Mode Register */
|
|
#define SCBRR 0x04 /* Bit Rate Register */
|
|
#define SCSCR 0x08 /* Serial Control Register */
|
|
#define SCFTDR 0x0c /* Transmit FIFO Data Register */
|
|
#define SCFSR 0x10 /* Serial Status Register */
|
|
#define SCFRDR 0x14 /* Receive FIFO Data Register */
|
|
#define SCFCR 0x18 /* FIFO Control Register */
|
|
#define SCFDR 0x1c /* FIFO Data Count Register */
|
|
#define SCSPTR 0x20 /* Serial Port Register */
|
|
#define SCLSR 0x24 /* Line Status Register */
|
|
#define DL 0x30 /* Frequency Division Register */
|
|
#define CKS 0x34 /* Clock Select Register */
|
|
|
|
/* SCSMR (Serial Mode Register) */
|
|
#define SCSMR_C_A BIT(7) /* Communication Mode */
|
|
#define SCSMR_CHR BIT(6) /* 7-bit Character Length */
|
|
#define SCSMR_PE BIT(5) /* Parity Enable */
|
|
#define SCSMR_O_E BIT(4) /* Odd Parity */
|
|
#define SCSMR_STOP BIT(3) /* Stop Bit Length */
|
|
#define SCSMR_CKS1 BIT(1) /* Clock Select 1 */
|
|
#define SCSMR_CKS0 BIT(0) /* Clock Select 0 */
|
|
|
|
/* SCSCR (Serial Control Register) */
|
|
#define SCSCR_TEIE BIT(11) /* Transmit End Interrupt Enable */
|
|
#define SCSCR_TIE BIT(7) /* Transmit Interrupt Enable */
|
|
#define SCSCR_RIE BIT(6) /* Receive Interrupt Enable */
|
|
#define SCSCR_TE BIT(5) /* Transmit Enable */
|
|
#define SCSCR_RE BIT(4) /* Receive Enable */
|
|
#define SCSCR_REIE BIT(3) /* Receive Error Interrupt Enable */
|
|
#define SCSCR_TOIE BIT(2) /* Timeout Interrupt Enable */
|
|
#define SCSCR_CKE1 BIT(1) /* Clock Enable 1 */
|
|
#define SCSCR_CKE0 BIT(0) /* Clock Enable 0 */
|
|
|
|
/* SCFCR (FIFO Control Register) */
|
|
#define SCFCR_RTRG1 BIT(7) /* Receive FIFO Data Count Trigger 1 */
|
|
#define SCFCR_RTRG0 BIT(6) /* Receive FIFO Data Count Trigger 0 */
|
|
#define SCFCR_TTRG1 BIT(5) /* Transmit FIFO Data Count Trigger 1 */
|
|
#define SCFCR_TTRG0 BIT(4) /* Transmit FIFO Data Count Trigger 0 */
|
|
#define SCFCR_MCE BIT(3) /* Modem Control Enable */
|
|
#define SCFCR_TFRST BIT(2) /* Transmit FIFO Data Register Reset */
|
|
#define SCFCR_RFRST BIT(1) /* Receive FIFO Data Register Reset */
|
|
#define SCFCR_LOOP BIT(0) /* Loopback Test */
|
|
|
|
/* SCFSR (Serial Status Register) */
|
|
#define SCFSR_PER3 BIT(15) /* Parity Error Count 3 */
|
|
#define SCFSR_PER2 BIT(14) /* Parity Error Count 2 */
|
|
#define SCFSR_PER1 BIT(13) /* Parity Error Count 1 */
|
|
#define SCFSR_PER0 BIT(12) /* Parity Error Count 0 */
|
|
#define SCFSR_FER3 BIT(11) /* Framing Error Count 3 */
|
|
#define SCFSR_FER2 BIT(10) /* Framing Error Count 2 */
|
|
#define SCFSR_FER_1 BIT(9) /* Framing Error Count 1 */
|
|
#define SCFSR_FER0 BIT(8) /* Framing Error Count 0 */
|
|
#define SCFSR_ER BIT(7) /* Receive Error */
|
|
#define SCFSR_TEND BIT(6) /* Transmission ended */
|
|
#define SCFSR_TDFE BIT(5) /* Transmit FIFO Data Empty */
|
|
#define SCFSR_BRK BIT(4) /* Break Detect */
|
|
#define SCFSR_FER BIT(3) /* Framing Error */
|
|
#define SCFSR_PER BIT(2) /* Parity Error */
|
|
#define SCFSR_RDF BIT(1) /* Receive FIFO Data Full */
|
|
#define SCFSR_DR BIT(0) /* Receive Data Ready */
|
|
|
|
/* SCLSR (Line Status Register) on (H)SCIF */
|
|
#define SCLSR_TO BIT(2) /* Timeout */
|
|
#define SCLSR_ORER BIT(0) /* Overrun Error */
|
|
|
|
static void uart_rcar_write_8(const struct device *dev,
|
|
uint32_t offs, uint8_t value)
|
|
{
|
|
sys_write8(value, DEVICE_MMIO_GET(dev) + offs);
|
|
}
|
|
|
|
static uint16_t uart_rcar_read_16(const struct device *dev,
|
|
uint32_t offs)
|
|
{
|
|
return sys_read16(DEVICE_MMIO_GET(dev) + offs);
|
|
}
|
|
|
|
static void uart_rcar_write_16(const struct device *dev,
|
|
uint32_t offs, uint16_t value)
|
|
{
|
|
sys_write16(value, DEVICE_MMIO_GET(dev) + offs);
|
|
}
|
|
|
|
static void uart_rcar_set_baudrate(const struct device *dev,
|
|
uint32_t baud_rate)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
uint8_t reg_val;
|
|
|
|
reg_val = ((data->clk_rate + 16 * baud_rate) / (32 * baud_rate) - 1);
|
|
uart_rcar_write_8(dev, SCBRR, reg_val);
|
|
}
|
|
|
|
static int uart_rcar_poll_in(const struct device *dev, unsigned char *p_char)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
uint16_t reg_val;
|
|
int ret = 0;
|
|
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
/* Receive FIFO empty */
|
|
if (!((uart_rcar_read_16(dev, SCFSR)) & SCFSR_RDF)) {
|
|
ret = -1;
|
|
goto unlock;
|
|
}
|
|
|
|
*p_char = uart_rcar_read_16(dev, SCFRDR);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCFSR);
|
|
reg_val &= ~SCFSR_RDF;
|
|
uart_rcar_write_16(dev, SCFSR, reg_val);
|
|
|
|
unlock:
|
|
k_spin_unlock(&data->lock, key);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void uart_rcar_poll_out(const struct device *dev, unsigned char out_char)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
/* Wait for empty space in transmit FIFO */
|
|
while (!(uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE)) {
|
|
}
|
|
|
|
uart_rcar_write_8(dev, SCFTDR, out_char);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCFSR);
|
|
reg_val &= ~(SCFSR_TDFE | SCFSR_TEND);
|
|
uart_rcar_write_16(dev, SCFSR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static int uart_rcar_configure(const struct device *dev,
|
|
const struct uart_config *cfg)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key;
|
|
|
|
if (cfg->parity != UART_CFG_PARITY_NONE ||
|
|
cfg->stop_bits != UART_CFG_STOP_BITS_1 ||
|
|
cfg->data_bits != UART_CFG_DATA_BITS_8 ||
|
|
cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
|
|
return -ENOTSUP;
|
|
}
|
|
|
|
key = k_spin_lock(&data->lock);
|
|
|
|
/* Disable Transmit and Receive */
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val &= ~(SCSCR_TE | SCSCR_RE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
/* Emptying Transmit and Receive FIFO */
|
|
reg_val = uart_rcar_read_16(dev, SCFCR);
|
|
reg_val |= (SCFCR_TFRST | SCFCR_RFRST);
|
|
uart_rcar_write_16(dev, SCFCR, reg_val);
|
|
|
|
/* Resetting Errors Registers */
|
|
reg_val = uart_rcar_read_16(dev, SCFSR);
|
|
reg_val &= ~(SCFSR_ER | SCFSR_DR | SCFSR_BRK | SCFSR_RDF);
|
|
uart_rcar_write_16(dev, SCFSR, reg_val);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCLSR);
|
|
reg_val &= ~(SCLSR_TO | SCLSR_ORER);
|
|
uart_rcar_write_16(dev, SCLSR, reg_val);
|
|
|
|
/* Select internal clock */
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val &= ~(SCSCR_CKE1 | SCSCR_CKE0);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
/* Serial Configuration (8N1) & Clock divider selection */
|
|
reg_val = uart_rcar_read_16(dev, SCSMR);
|
|
reg_val &= ~(SCSMR_C_A | SCSMR_CHR | SCSMR_PE | SCSMR_O_E | SCSMR_STOP |
|
|
SCSMR_CKS1 | SCSMR_CKS0);
|
|
uart_rcar_write_16(dev, SCSMR, reg_val);
|
|
|
|
/* Set baudrate */
|
|
uart_rcar_set_baudrate(dev, cfg->baudrate);
|
|
|
|
/* FIFOs data count trigger configuration */
|
|
reg_val = uart_rcar_read_16(dev, SCFCR);
|
|
reg_val &= ~(SCFCR_RTRG1 | SCFCR_RTRG0 | SCFCR_TTRG1 | SCFCR_TTRG0 |
|
|
SCFCR_MCE | SCFCR_TFRST | SCFCR_RFRST);
|
|
uart_rcar_write_16(dev, SCFCR, reg_val);
|
|
|
|
/* Enable Transmit & Receive + disable Interrupts */
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val |= (SCSCR_TE | SCSCR_RE);
|
|
reg_val &= ~(SCSCR_TIE | SCSCR_RIE | SCSCR_TEIE | SCSCR_REIE |
|
|
SCSCR_TOIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
data->current_config = *cfg;
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
|
static int uart_rcar_config_get(const struct device *dev,
|
|
struct uart_config *cfg)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
*cfg = data->current_config;
|
|
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
|
|
|
|
static int uart_rcar_init(const struct device *dev)
|
|
{
|
|
const struct uart_rcar_cfg *config = dev->config;
|
|
struct uart_rcar_data *data = dev->data;
|
|
int ret;
|
|
|
|
/* Configure dt provided device signals when available */
|
|
ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
if (!device_is_ready(config->clock_dev)) {
|
|
return -ENODEV;
|
|
}
|
|
|
|
ret = clock_control_on(config->clock_dev,
|
|
(clock_control_subsys_t)&config->mod_clk);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
ret = clock_control_get_rate(config->clock_dev,
|
|
(clock_control_subsys_t)&config->bus_clk,
|
|
&data->clk_rate);
|
|
if (ret < 0) {
|
|
return ret;
|
|
}
|
|
|
|
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
|
|
|
ret = uart_rcar_configure(dev, &data->current_config);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
config->irq_config_func(dev);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
|
|
static bool uart_rcar_irq_is_enabled(const struct device *dev,
|
|
uint32_t irq)
|
|
{
|
|
return !!(uart_rcar_read_16(dev, SCSCR) & irq);
|
|
}
|
|
|
|
static int uart_rcar_fifo_fill(const struct device *dev,
|
|
const uint8_t *tx_data,
|
|
int len)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
int num_tx = 0;
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
while (((len - num_tx) > 0) &&
|
|
(uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE)) {
|
|
/* Send current byte */
|
|
uart_rcar_write_8(dev, SCFTDR, tx_data[num_tx]);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCFSR);
|
|
reg_val &= ~(SCFSR_TDFE | SCFSR_TEND);
|
|
uart_rcar_write_16(dev, SCFSR, reg_val);
|
|
|
|
num_tx++;
|
|
}
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
|
|
return num_tx;
|
|
}
|
|
|
|
static int uart_rcar_fifo_read(const struct device *dev, uint8_t *rx_data,
|
|
const int size)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
int num_rx = 0;
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
while (((size - num_rx) > 0) &&
|
|
(uart_rcar_read_16(dev, SCFSR) & SCFSR_RDF)) {
|
|
/* Receive current byte */
|
|
rx_data[num_rx++] = uart_rcar_read_16(dev, SCFRDR);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCFSR);
|
|
reg_val &= ~(SCFSR_RDF);
|
|
uart_rcar_write_16(dev, SCFSR, reg_val);
|
|
|
|
}
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
|
|
return num_rx;
|
|
}
|
|
|
|
static void uart_rcar_irq_tx_enable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val |= (SCSCR_TIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static void uart_rcar_irq_tx_disable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val &= ~(SCSCR_TIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static int uart_rcar_irq_tx_ready(const struct device *dev)
|
|
{
|
|
return !!(uart_rcar_read_16(dev, SCFSR) & SCFSR_TDFE);
|
|
}
|
|
|
|
static void uart_rcar_irq_rx_enable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val |= (SCSCR_RIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static void uart_rcar_irq_rx_disable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val &= ~(SCSCR_RIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static int uart_rcar_irq_rx_ready(const struct device *dev)
|
|
{
|
|
return !!(uart_rcar_read_16(dev, SCFSR) & SCFSR_RDF);
|
|
}
|
|
|
|
static void uart_rcar_irq_err_enable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val |= (SCSCR_REIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static void uart_rcar_irq_err_disable(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
uint16_t reg_val;
|
|
k_spinlock_key_t key = k_spin_lock(&data->lock);
|
|
|
|
reg_val = uart_rcar_read_16(dev, SCSCR);
|
|
reg_val &= ~(SCSCR_REIE);
|
|
uart_rcar_write_16(dev, SCSCR, reg_val);
|
|
|
|
k_spin_unlock(&data->lock, key);
|
|
}
|
|
|
|
static int uart_rcar_irq_is_pending(const struct device *dev)
|
|
{
|
|
return (uart_rcar_irq_rx_ready(dev) && uart_rcar_irq_is_enabled(dev, SCSCR_RIE)) ||
|
|
(uart_rcar_irq_tx_ready(dev) && uart_rcar_irq_is_enabled(dev, SCSCR_TIE));
|
|
}
|
|
|
|
static int uart_rcar_irq_update(const struct device *dev)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static void uart_rcar_irq_callback_set(const struct device *dev,
|
|
uart_irq_callback_user_data_t cb,
|
|
void *cb_data)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
data->callback = cb;
|
|
data->cb_data = cb_data;
|
|
}
|
|
|
|
/**
|
|
* @brief Interrupt service routine.
|
|
*
|
|
* This simply calls the callback function, if one exists.
|
|
*
|
|
* @param arg Argument to ISR.
|
|
*/
|
|
void uart_rcar_isr(const struct device *dev)
|
|
{
|
|
struct uart_rcar_data *data = dev->data;
|
|
|
|
if (data->callback) {
|
|
data->callback(dev, data->cb_data);
|
|
}
|
|
}
|
|
|
|
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
|
|
|
static const struct uart_driver_api uart_rcar_driver_api = {
|
|
.poll_in = uart_rcar_poll_in,
|
|
.poll_out = uart_rcar_poll_out,
|
|
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
|
|
.configure = uart_rcar_configure,
|
|
.config_get = uart_rcar_config_get,
|
|
#endif
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
.fifo_fill = uart_rcar_fifo_fill,
|
|
.fifo_read = uart_rcar_fifo_read,
|
|
.irq_tx_enable = uart_rcar_irq_tx_enable,
|
|
.irq_tx_disable = uart_rcar_irq_tx_disable,
|
|
.irq_tx_ready = uart_rcar_irq_tx_ready,
|
|
.irq_rx_enable = uart_rcar_irq_rx_enable,
|
|
.irq_rx_disable = uart_rcar_irq_rx_disable,
|
|
.irq_rx_ready = uart_rcar_irq_rx_ready,
|
|
.irq_err_enable = uart_rcar_irq_err_enable,
|
|
.irq_err_disable = uart_rcar_irq_err_disable,
|
|
.irq_is_pending = uart_rcar_irq_is_pending,
|
|
.irq_update = uart_rcar_irq_update,
|
|
.irq_callback_set = uart_rcar_irq_callback_set,
|
|
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
|
};
|
|
|
|
/* Device Instantiation */
|
|
#define UART_RCAR_DECLARE_CFG(n, IRQ_FUNC_INIT) \
|
|
PINCTRL_DT_INST_DEFINE(n); \
|
|
static const struct uart_rcar_cfg uart_rcar_cfg_##n = { \
|
|
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \
|
|
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
|
|
.mod_clk.module = \
|
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, module), \
|
|
.mod_clk.domain = \
|
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 0, domain), \
|
|
.bus_clk.module = \
|
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 1, module), \
|
|
.bus_clk.domain = \
|
|
DT_INST_CLOCKS_CELL_BY_IDX(n, 1, domain), \
|
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
|
IRQ_FUNC_INIT \
|
|
}
|
|
|
|
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
|
#define UART_RCAR_CONFIG_FUNC(n) \
|
|
static void irq_config_func_##n(const struct device *dev) \
|
|
{ \
|
|
IRQ_CONNECT(DT_INST_IRQN(n), \
|
|
DT_INST_IRQ(n, priority), \
|
|
uart_rcar_isr, \
|
|
DEVICE_DT_INST_GET(n), 0); \
|
|
\
|
|
irq_enable(DT_INST_IRQN(n)); \
|
|
}
|
|
#define UART_RCAR_IRQ_CFG_FUNC_INIT(n) \
|
|
.irq_config_func = irq_config_func_##n
|
|
#define UART_RCAR_INIT_CFG(n) \
|
|
UART_RCAR_DECLARE_CFG(n, UART_RCAR_IRQ_CFG_FUNC_INIT(n))
|
|
#else
|
|
#define UART_RCAR_CONFIG_FUNC(n)
|
|
#define UART_RCAR_IRQ_CFG_FUNC_INIT
|
|
#define UART_RCAR_INIT_CFG(n) \
|
|
UART_RCAR_DECLARE_CFG(n, UART_RCAR_IRQ_CFG_FUNC_INIT)
|
|
#endif
|
|
|
|
#define UART_RCAR_INIT(n) \
|
|
static struct uart_rcar_data uart_rcar_data_##n = { \
|
|
.current_config = { \
|
|
.baudrate = DT_INST_PROP(n, current_speed), \
|
|
.parity = UART_CFG_PARITY_NONE, \
|
|
.stop_bits = UART_CFG_STOP_BITS_1, \
|
|
.data_bits = UART_CFG_DATA_BITS_8, \
|
|
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \
|
|
}, \
|
|
}; \
|
|
\
|
|
static const struct uart_rcar_cfg uart_rcar_cfg_##n; \
|
|
\
|
|
DEVICE_DT_INST_DEFINE(n, \
|
|
uart_rcar_init, \
|
|
NULL, \
|
|
&uart_rcar_data_##n, \
|
|
&uart_rcar_cfg_##n, \
|
|
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
|
|
&uart_rcar_driver_api); \
|
|
\
|
|
UART_RCAR_CONFIG_FUNC(n) \
|
|
\
|
|
UART_RCAR_INIT_CFG(n);
|
|
|
|
DT_INST_FOREACH_STATUS_OKAY(UART_RCAR_INIT)
|