Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

786 lines
26 KiB

/*
* Copyright (c) 2025 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT renesas_rza2m_scif_uart
#include <zephyr/drivers/uart.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/pinctrl.h>
#include <zephyr/drivers/interrupt_controller/gic.h>
#include <zephyr/logging/log.h>
#include <zephyr/irq.h>
#include <zephyr/spinlock.h>
LOG_MODULE_REGISTER(uart_renesas_rza2m_scif, CONFIG_UART_LOG_LEVEL);
struct scif_reg {
uint8_t offset, size;
};
enum {
RZA2M_SMR, /* Serial Mode Register */
RZA2M_BRR, /* Bit Rate Register */
RZA2M_SCR, /* Serial Control Register */
RZA2M_FSR, /* Serial Status Register */
RZA2M_FCR, /* FIFO Control Register */
RZA2M_FDR, /* FIFO Data Count Register */
RZA2M_FTDR, /* Transmit (FIFO) Data Register */
RZA2M_FRDR, /* Receive (FIFO) Data Register */
RZA2M_LSR, /* Line Status Register */
RZA2M_TFDR, /* Transmit FIFO Data Count Register */
RZA2M_RFDR, /* Receive FIFO Data Count Register */
RZA2M_SPTR, /* Serial Port Register */
RZA2M_SEMR, /* Serial extended mode register */
RZA2M_FTCR, /* FIFO Trigger Control Register */
RZA2M_SCIF_NR_REGS,
};
struct scif_params {
const struct scif_reg regs[RZA2M_SCIF_NR_REGS];
uint16_t init_lsr_mask;
uint16_t init_interrupt_mask;
};
struct uart_rza2m_scif_cfg {
DEVICE_MMIO_ROM; /* Must be first */
const struct device *clock_dev;
clock_control_subsys_t clock_subsys;
const struct pinctrl_dev_config *pcfg;
const struct scif_params *params;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
void (*irq_config_func)(const struct device *dev);
#endif
};
struct uart_rza2m_scif_int {
uint16_t rxi_status;
uint16_t line_status;
};
struct uart_rza2m_scif_data {
DEVICE_MMIO_RAM; /* Must be first */
struct uart_config current_config;
uint8_t channel;
uint32_t clk_rate;
struct k_spinlock lock;
struct uart_rza2m_scif_int int_data;
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
uart_irq_callback_user_data_t irq_cb;
void *irq_cb_data;
#endif
};
#define RZA2M_SCIF_DEFAULT_SPEED 115200
#define RZA2M_SCIF_DEFAULT_PARITY UART_CFG_PARITY_NONE
#define RZA2M_SCIF_DEFAULT_STOP_BITS UART_CFG_STOP_BITS_1
#define RZA2M_SCIF_DEFAULT_DATA_BITS UART_CFG_DATA_BITS_8
/* SMR (Serial Mode Register) */
#define RZA2M_SMR_C_A BIT(7) /* Communication Mode */
#define RZA2M_SMR_CHR BIT(6) /* 7-bit Character Length */
#define RZA2M_SMR_PE BIT(5) /* Parity Enable */
#define RZA2M_SMR_O_E BIT(4) /* Odd Parity */
#define RZA2M_SMR_STOP BIT(3) /* Stop Bit Length */
#define RZA2M_SMR_CKS_MASK (BIT(0) | BIT(1)) /* Clock Select */
#define RZA2M_SMR_CKS_SHIFT 0 /* Clock Select shift */
/* SCR (Serial Control Register) */
#define RZA2M_SCR_TIE BIT(7) /* Transmit Interrupt Enable */
#define RZA2M_SCR_RIE BIT(6) /* Receive Interrupt Enable */
#define RZA2M_SCR_TE BIT(5) /* Transmit Enable */
#define RZA2M_SCR_RE BIT(4) /* Receive Enable */
#define RZA2M_SCR_REIE BIT(3) /* Receive Error Interrupt Enable */
#define RZA2M_SCR_TEIE BIT(2) /* Transmit End Interrupt Enable */
#define RZA2M_SCR_CKE1 BIT(1) /* Clock Enable 1 */
#define RZA2M_SCR_CKE0 BIT(0) /* Clock Enable 0 */
/* FCR (FIFO Control Register) */
#define RZA2M_FCR_RTRG1 BIT(7) /* Receive FIFO Data Count Trigger 1 */
#define RZA2M_FCR_RTRG0 BIT(6) /* Receive FIFO Data Count Trigger 0 */
#define RZA2M_FCR_TTRG1 BIT(5) /* Transmit FIFO Data Count Trigger 1 */
#define RZA2M_FCR_TTRG0 BIT(4) /* Transmit FIFO Data Count Trigger 0 */
#define RZA2M_FCR_MCE BIT(3) /* Modem Control Enable */
#define RZA2M_FCR_TFRST BIT(2) /* Transmit FIFO Data Register Reset */
#define RZA2M_FCR_RFRST BIT(1) /* Receive FIFO Data Register Reset */
#define RZA2M_FCR_LOOP BIT(0) /* Loopback Test */
/* FSR (Serial Status Register) */
#define RZA2M_FSR_PER3 BIT(15) /* Parity Error Count 3 */
#define RZA2M_FSR_PER2 BIT(14) /* Parity Error Count 2 */
#define RZA2M_FSR_PER1 BIT(13) /* Parity Error Count 1 */
#define RZA2M_FSR_PER0 BIT(12) /* Parity Error Count 0 */
#define RZA2M_FSR_FER3 BIT(11) /* Framing Error Count 3 */
#define RZA2M_FSR_FER2 BIT(10) /* Framing Error Count 2 */
#define RZA2M_FSR_FER1 BIT(9) /* Framing Error Count 1 */
#define RZA2M_FSR_FER0 BIT(8) /* Framing Error Count 0 */
#define RZA2M_FSR_ER BIT(7) /* Receive Error */
#define RZA2M_FSR_TEND BIT(6) /* Transmission ended */
#define RZA2M_FSR_TDFE BIT(5) /* Transmit FIFO Data Empty */
#define RZA2M_FSR_BRK BIT(4) /* Break Detect */
#define RZA2M_FSR_FER BIT(3) /* Framing Error */
#define RZA2M_FSR_PER BIT(2) /* Parity Error */
#define RZA2M_FSR_RDF BIT(1) /* Receive FIFO Data Full */
#define RZA2M_FSR_DR BIT(0) /* Receive Data Ready */
/* SPTR (Serial Port Register) on SCIFA */
#define RZA2M_SPTR_SPB2IO BIT(1) /* Serial Port Break Input/Output */
#define RZA2M_SPTR_SPB2DT BIT(0) /* Serial Port Break Data Select */
/* LSR (Line Status Register) on SCIFA */
#define RZA2M_LSR_TO_SCIFA BIT(2) /* Timeout on SCIFA */
#define RZA2M_LSR_ORER BIT(0) /* Overrun Error */
/* Serial Extended Mode Register */
#define RZA2M_SEMR_ABCS0 BIT(0) /* Asynchronous Base Clock Select */
#define RZA2M_SEMR_NFEN BIT(2) /* Noise Cancellation Enable */
#define RZA2M_SEMR_DIR BIT(3) /* Data Transfer Direction Select */
#define RZA2M_SEMR_MDDRS BIT(4) /* Modulation Duty Register Select */
#define RZA2M_SEMR_BRME BIT(5) /* Bit Rate Modulation Enable */
/* Baud Rate Generator Double-Speed Mode Select */
#define RZA2M_SEMR_BGDM BIT(7)
#define RZA2M_SCIF_DRV_ERR (-1)
/* clang-format off */
/* Registers */
static const struct scif_params port_params = {
.regs = {
[RZA2M_SMR] = {0x00, 16},
[RZA2M_BRR] = {0x02, 8},
[RZA2M_SCR] = {0x04, 16},
[RZA2M_FTDR] = {0x06, 8},
[RZA2M_FSR] = {0x08, 16},
[RZA2M_FRDR] = {0x0A, 8},
[RZA2M_FCR] = {0x0C, 16},
[RZA2M_FDR] = {0x0E, 16},
[RZA2M_SPTR] = {0x10, 16},
[RZA2M_LSR] = {0x12, 16},
[RZA2M_SEMR] = {0x14, 8},
[RZA2M_FTCR] = {0x16, 16},
},
.init_lsr_mask = RZA2M_LSR_ORER,
.init_interrupt_mask =
RZA2M_SCR_TIE | RZA2M_SCR_RIE | RZA2M_SCR_REIE | RZA2M_SCR_TEIE,
};
/* clang-format on */
#define RZA2M_NUM_DIVISORS_ASYNC (9)
/* Baud divisor info */
/**
* When ABCS = 0 & BGDM = 0, divisor = 64 x 2^(2n - 1)
* When ABCS = 1 & BGDM = 0 OR ABCS = 0 & BGDM = 1, divisor = 32 x 2^(2n - 1)
* When ABCS = 1 & BGDM = 1, divisor = 16 x 2^(2n - 1)
*/
typedef struct {
int16_t divisor; /* Clock divisor */
uint8_t abcs; /* ABCS value to get divisor */
uint8_t bgdm; /* BGDM value to get divisor */
uint8_t cks; /* CKS value to get divisor (CKS = n) */
} st_baud_divisorb_t;
/* Divisor result, ABCS, BGDM, n */
static const st_baud_divisorb_t gs_scifa_async_baud[RZA2M_NUM_DIVISORS_ASYNC] = {
{8, 1, 1, 0}, {16, 0, 1, 0}, {32, 0, 0, 0}, {64, 0, 1, 1}, {128, 0, 0, 1},
{256, 0, 1, 2}, {512, 0, 0, 2}, {1024, 0, 1, 3}, {2048, 0, 0, 3}};
static uint8_t uart_rza2m_scif_read_8(const struct device *dev, uint32_t offs)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
uint32_t offset = config->params->regs[offs].offset;
return sys_read8(DEVICE_MMIO_GET(dev) + offset);
}
static void uart_rza2m_scif_write_8(const struct device *dev, uint32_t offs, uint8_t value)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
uint32_t offset = config->params->regs[offs].offset;
sys_write8(value, DEVICE_MMIO_GET(dev) + offset);
}
static uint16_t uart_rza2m_scif_read_16(const struct device *dev, uint32_t offs)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
uint32_t offset = config->params->regs[offs].offset;
return sys_read16(DEVICE_MMIO_GET(dev) + offset);
}
static void uart_rza2m_scif_write_16(const struct device *dev, uint32_t offs, uint16_t value)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
uint32_t offset = config->params->regs[offs].offset;
sys_write16(value, DEVICE_MMIO_GET(dev) + offset);
}
static uint8_t find_divisor_index(uint8_t channel, uint32_t desired_baud_rate, uint32_t clock_freq)
{
/* Find the divisor; table has associated ABCS, BGDM and CKS values */
/* BRR must be 255 or less */
/* BRR = (PCLK / (divisor * desired_baud)) - 1 */
/* BRR = (ratio / divisor) - 1 */
uint32_t ratio = clock_freq / desired_baud_rate;
uint8_t divisor_index = 0;
if (channel == 0) {
/* The hardware manual states that for channel 0, P1f/16 input is not provided */
/* So the setting CKS [1:0] 1 0 cannot be used */
/* This restriction may be lifted in future releases */
while ((divisor_index < RZA2M_NUM_DIVISORS_ASYNC) &&
((ratio >= (uint32_t)(gs_scifa_async_baud[divisor_index].divisor * 256)) ||
(2 == gs_scifa_async_baud[divisor_index].cks))) {
divisor_index++;
}
} else {
/* Cast to uint32_t for comparison with ratio */
while ((divisor_index < RZA2M_NUM_DIVISORS_ASYNC) &&
(ratio >= (uint32_t)(gs_scifa_async_baud[divisor_index].divisor * 256))) {
divisor_index++;
}
}
return divisor_index;
}
static int uart_rza2m_scif_set_baudrate(const struct device *dev, uint8_t channel,
uint32_t baud_rate)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
uint8_t reg_8;
uint32_t clk_freq = data->clk_rate;
uint8_t divisor_index;
uint32_t divisor;
uint32_t brr;
divisor_index = find_divisor_index(channel, baud_rate, clk_freq);
divisor = (uint32_t)gs_scifa_async_baud[divisor_index].divisor;
brr = clk_freq / (divisor * baud_rate);
if (brr == 0) {
return RZA2M_SCIF_DRV_ERR; /* Illegal value; return error */
}
/* Divide by half the divisor */
brr = clk_freq / ((divisor * baud_rate) / 2);
/* Formula: BRR = (PCLK / (divisor * desired_baud)) - 1 */
/* If (BRR * 2) is odd, "round up" by ignoring -1; divide by 2 again for rest of divisor */
brr = ((brr & 0x01) ? (brr / 2) : ((brr / 2) - 1));
/* Write BRR */
uart_rza2m_scif_write_8(dev, RZA2M_BRR, brr);
/* Write CKS[1:0] */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SMR);
reg_16 &= ~(RZA2M_SMR_CKS_MASK << RZA2M_SMR_CKS_SHIFT);
reg_16 |= (gs_scifa_async_baud[divisor_index].cks & RZA2M_SMR_CKS_MASK)
<< RZA2M_SMR_CKS_SHIFT;
uart_rza2m_scif_write_16(dev, RZA2M_SMR, reg_16);
/* Write ABCS0 and BGDM */
reg_8 = uart_rza2m_scif_read_8(dev, RZA2M_SEMR);
reg_8 = reg_8 | (gs_scifa_async_baud[divisor_index].abcs ? RZA2M_SEMR_ABCS0 : 0);
reg_8 = reg_8 | (gs_scifa_async_baud[divisor_index].bgdm ? RZA2M_SEMR_BGDM : 0);
uart_rza2m_scif_write_8(dev, RZA2M_SEMR, reg_8);
return 0;
}
static int uart_rza2m_scif_poll_in(const struct device *dev, unsigned char *p_char)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
int ret = 0;
k_spinlock_key_t key = k_spin_lock(&data->lock);
/* Receive FIFO empty */
if (!(uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_RDF)) {
ret = -1;
goto unlock;
}
*p_char = uart_rza2m_scif_read_8(dev, RZA2M_FRDR);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FSR);
reg_16 &= ~RZA2M_FSR_RDF;
uart_rza2m_scif_write_16(dev, RZA2M_FSR, reg_16);
unlock:
k_spin_unlock(&data->lock, key);
return ret;
}
static void uart_rza2m_scif_poll_out(const struct device *dev, unsigned char out_char)
{
struct uart_rza2m_scif_data *data = dev->data;
k_spinlock_key_t key = k_spin_lock(&data->lock);
/* Wait for empty space in transmit FIFO */
while (!(uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_TDFE)) {
}
uart_rza2m_scif_write_8(dev, RZA2M_FTDR, out_char);
while (!(uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_TEND)) {
}
k_spin_unlock(&data->lock, key);
}
static int uart_rza2m_scif_err_check(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
struct uart_rza2m_scif_int int_data = data->int_data;
int err = 0;
if (int_data.line_status & RZA2M_LSR_ORER) {
err |= UART_ERROR_OVERRUN;
}
if (int_data.rxi_status & RZA2M_FSR_FER) {
err |= UART_ERROR_FRAMING;
}
if (int_data.rxi_status & RZA2M_FSR_PER) {
err |= UART_ERROR_PARITY;
}
if (int_data.rxi_status & RZA2M_FSR_BRK) {
err |= UART_BREAK;
}
return err;
}
static int uart_rza2m_scif_configure(const struct device *dev, const struct uart_config *cfg)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key;
int err;
err = 0;
if (cfg->data_bits < UART_CFG_DATA_BITS_7 || cfg->data_bits > UART_CFG_DATA_BITS_8 ||
cfg->stop_bits == UART_CFG_STOP_BITS_0_5 || cfg->stop_bits == UART_CFG_STOP_BITS_1_5 ||
cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
return -ENOTSUP;
}
key = k_spin_lock(&data->lock);
/* Set the TXD output high */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SPTR);
reg_16 |= (RZA2M_SPTR_SPB2DT | RZA2M_SPTR_SPB2IO);
uart_rza2m_scif_write_16(dev, RZA2M_SPTR, reg_16);
/* Disable Transmit and Receive */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 &= ~(RZA2M_SCR_TE | RZA2M_SCR_RE | RZA2M_SCR_TIE | RZA2M_SCR_RIE);
reg_16 &= ~(RZA2M_SCR_TEIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
/* Emptying Transmit and Receive FIFO */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FCR);
reg_16 |= (RZA2M_FCR_TFRST | RZA2M_FCR_RFRST);
uart_rza2m_scif_write_16(dev, RZA2M_FCR, reg_16);
/* Resetting Errors Registers */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FSR);
reg_16 &= ~(RZA2M_FSR_ER | RZA2M_FSR_DR | RZA2M_FSR_BRK | RZA2M_FSR_RDF);
uart_rza2m_scif_write_16(dev, RZA2M_FSR, reg_16);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_LSR);
reg_16 &= ~(config->params->init_lsr_mask);
uart_rza2m_scif_write_16(dev, RZA2M_LSR, reg_16);
/* Select internal clock */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 &= ~(RZA2M_SCR_CKE1 | RZA2M_SCR_CKE0);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
/* Serial Configuration (8N1) & Clock divider selection */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SMR);
reg_16 &= ~(RZA2M_SMR_C_A | RZA2M_SMR_CHR | RZA2M_SMR_PE | RZA2M_SMR_O_E | RZA2M_SMR_STOP);
switch (cfg->parity) {
case UART_CFG_PARITY_NONE:
break;
case UART_CFG_PARITY_ODD:
reg_16 |= RZA2M_SMR_PE | RZA2M_SMR_O_E;
break;
case UART_CFG_PARITY_EVEN:
reg_16 |= RZA2M_SMR_PE;
break;
default:
return -ENOTSUP;
}
if (cfg->stop_bits == UART_CFG_STOP_BITS_2) {
reg_16 |= RZA2M_SMR_STOP;
}
if (cfg->data_bits == UART_CFG_DATA_BITS_7) {
reg_16 |= RZA2M_SMR_CHR;
}
uart_rza2m_scif_write_16(dev, RZA2M_SMR, reg_16);
/* Set baudrate */
err = uart_rza2m_scif_set_baudrate(dev, data->channel, cfg->baudrate);
if (err) {
return -EIO;
}
/* FIFOs data count trigger configuration */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FCR);
reg_16 &= ~(RZA2M_FCR_RTRG1 | RZA2M_FCR_RTRG0 | RZA2M_FCR_TTRG1 | RZA2M_FCR_TTRG0 |
RZA2M_FCR_MCE | RZA2M_FCR_TFRST | RZA2M_FCR_RFRST);
uart_rza2m_scif_write_16(dev, RZA2M_FCR, reg_16);
/* Enable Transmit & Receive + disable Interrupts */
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 |= (RZA2M_SCR_TE | RZA2M_SCR_RE);
reg_16 &= ~(config->params->init_interrupt_mask);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
data->current_config = *cfg;
k_spin_unlock(&data->lock, key);
return err;
}
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
static int uart_rza2m_scif_config_get(const struct device *dev, struct uart_config *cfg)
{
struct uart_rza2m_scif_data *data = dev->data;
*cfg = data->current_config;
return 0;
}
#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */
static int uart_rza2m_scif_init(const struct device *dev)
{
const struct uart_rza2m_scif_cfg *config = dev->config;
struct uart_rza2m_scif_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->clock_subsys);
if (ret < 0) {
return ret;
}
ret = clock_control_get_rate(config->clock_dev,
(clock_control_subsys_t)config->clock_subsys, &data->clk_rate);
if (ret < 0) {
return ret;
}
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
ret = uart_rza2m_scif_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_rza2m_scif_irq_is_enabled(const struct device *dev, uint32_t irq)
{
return !!(uart_rza2m_scif_read_16(dev, RZA2M_SCR) & irq);
}
static int uart_rza2m_scif_fifo_fill(const struct device *dev, const uint8_t *tx_data, int len)
{
struct uart_rza2m_scif_data *data = dev->data;
int num_tx = 0;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
while (((len - num_tx) > 0) && (uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_TDFE)) {
/* Send current byte */
uart_rza2m_scif_write_8(dev, RZA2M_FTDR, tx_data[num_tx]);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FSR);
reg_16 &= ~(RZA2M_FSR_TDFE | RZA2M_FSR_TEND);
uart_rza2m_scif_write_16(dev, RZA2M_FSR, reg_16);
num_tx++;
}
k_spin_unlock(&data->lock, key);
return num_tx;
}
static int uart_rza2m_scif_fifo_read(const struct device *dev, uint8_t *rx_data, const int size)
{
struct uart_rza2m_scif_data *data = dev->data;
int num_rx = 0;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
while (((size - num_rx) > 0) && (uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_RDF)) {
/* Receive current byte */
rx_data[num_rx++] = uart_rza2m_scif_read_8(dev, RZA2M_FRDR);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_FSR);
reg_16 &= ~(RZA2M_FSR_RDF);
uart_rza2m_scif_write_16(dev, RZA2M_FSR, reg_16);
}
k_spin_unlock(&data->lock, key);
return num_rx;
}
static void uart_rza2m_scif_irq_tx_enable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 |= (RZA2M_SCR_TIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static void uart_rza2m_scif_irq_tx_disable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 &= ~(RZA2M_SCR_TIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static int uart_rza2m_scif_irq_tx_ready(const struct device *dev)
{
return !!(uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_TDFE);
}
static void uart_rza2m_scif_irq_rx_enable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 |= (RZA2M_SCR_RIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static void uart_rza2m_scif_irq_rx_disable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 &= ~(RZA2M_SCR_RIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static int uart_rza2m_scif_irq_rx_ready(const struct device *dev)
{
return !!(uart_rza2m_scif_read_16(dev, RZA2M_FSR) & RZA2M_FSR_RDF);
}
static void uart_rza2m_scif_irq_err_enable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 |= (RZA2M_SCR_REIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static void uart_rza2m_scif_irq_err_disable(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
uint16_t reg_16;
k_spinlock_key_t key = k_spin_lock(&data->lock);
reg_16 = uart_rza2m_scif_read_16(dev, RZA2M_SCR);
reg_16 &= ~(RZA2M_SCR_REIE);
uart_rza2m_scif_write_16(dev, RZA2M_SCR, reg_16);
k_spin_unlock(&data->lock, key);
}
static int uart_rza2m_scif_irq_is_pending(const struct device *dev)
{
return (uart_rza2m_scif_irq_rx_ready(dev) &&
uart_rza2m_scif_irq_is_enabled(dev, RZA2M_SCR_RIE)) ||
(uart_rza2m_scif_irq_tx_ready(dev) &&
uart_rza2m_scif_irq_is_enabled(dev, RZA2M_SCR_TIE));
}
static int uart_rza2m_scif_irq_update(const struct device *dev)
{
ARG_UNUSED(dev);
return 1;
}
static void uart_rza2m_scif_irq_callback_set(const struct device *dev,
uart_irq_callback_user_data_t cb, void *cb_data)
{
struct uart_rza2m_scif_data *data = dev->data;
data->irq_cb = cb;
data->irq_cb_data = cb_data;
}
void uart_rza2m_scif_isr(const struct device *dev)
{
struct uart_rza2m_scif_data *data = dev->data;
if (data->irq_cb) {
data->irq_cb(dev, data->irq_cb_data);
}
/* Get interrupt status */
data->int_data.rxi_status = uart_rza2m_scif_read_16(dev, RZA2M_FSR);
data->int_data.rxi_status &= (RZA2M_FSR_FER | RZA2M_FSR_PER | RZA2M_FSR_BRK);
data->int_data.line_status = uart_rza2m_scif_read_16(dev, RZA2M_LSR);
data->int_data.line_status &= RZA2M_LSR_ORER;
}
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
static DEVICE_API(uart, uart_rza2m_scif_driver_api) = {
.poll_in = uart_rza2m_scif_poll_in,
.poll_out = uart_rza2m_scif_poll_out,
.err_check = uart_rza2m_scif_err_check,
#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE
.configure = uart_rza2m_scif_configure,
.config_get = uart_rza2m_scif_config_get,
#endif
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
.fifo_fill = uart_rza2m_scif_fifo_fill,
.fifo_read = uart_rza2m_scif_fifo_read,
.irq_tx_enable = uart_rza2m_scif_irq_tx_enable,
.irq_tx_disable = uart_rza2m_scif_irq_tx_disable,
.irq_tx_ready = uart_rza2m_scif_irq_tx_ready,
.irq_rx_enable = uart_rza2m_scif_irq_rx_enable,
.irq_rx_disable = uart_rza2m_scif_irq_rx_disable,
.irq_rx_ready = uart_rza2m_scif_irq_rx_ready,
.irq_err_enable = uart_rza2m_scif_irq_err_enable,
.irq_err_disable = uart_rza2m_scif_irq_err_disable,
.irq_is_pending = uart_rza2m_scif_irq_is_pending,
.irq_update = uart_rza2m_scif_irq_update,
.irq_callback_set = uart_rza2m_scif_irq_callback_set,
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
};
/* Device Instantiation */
#define UART_RZA2M_DECLARE_CFG(n, IRQ_FUNC_INIT) \
PINCTRL_DT_INST_DEFINE(n); \
uint32_t clock_subsys##n = DT_INST_CLOCKS_CELL(n, clk_id); \
static const struct uart_rza2m_scif_cfg uart_rza2m_scif_cfg_##n = { \
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \
.clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \
.clock_subsys = (clock_control_subsys_t)(&clock_subsys##n), \
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
.params = &port_params, \
IRQ_FUNC_INIT}
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
#define UART_RZA2M_SET_IRQ(n, name) \
IRQ_CONNECT(DT_INST_IRQ_BY_NAME(n, name, irq) - GIC_SPI_INT_BASE, \
DT_INST_IRQ_BY_NAME(n, name, priority), uart_rza2m_scif_isr, \
DEVICE_DT_INST_GET(n), 0); \
\
irq_enable(DT_INST_IRQ_BY_NAME(n, name, irq) - GIC_SPI_INT_BASE);
#define UART_RZA2M_IRQ_CONFIG_FUNC(n) \
static void irq_config_func_##n(const struct device *dev) \
{ \
UART_RZA2M_SET_IRQ(n, eri); \
UART_RZA2M_SET_IRQ(n, rxi); \
UART_RZA2M_SET_IRQ(n, txi); \
UART_RZA2M_SET_IRQ(n, tei); \
}
#define UART_RZA2M_IRQ_CFG_FUNC_INIT(n) .irq_config_func = irq_config_func_##n
#define UART_RZA2M_INIT_CFG(n) UART_RZA2M_DECLARE_CFG(n, UART_RZA2M_IRQ_CFG_FUNC_INIT(n))
#else
#define UART_RZA2M_IRQ_CONFIG_FUNC(n)
#define UART_RZA2M_IRQ_CFG_FUNC_INIT
#define UART_RZA2M_INIT_CFG(n) UART_RZA2M_DECLARE_CFG(n, UART_RZA2M_IRQ_CFG_FUNC_INIT)
#endif
#define UART_RZA2M_INIT(n) \
static struct uart_rza2m_scif_data uart_rza2m_scif_data_##n = { \
.current_config = \
{ \
.baudrate = DT_INST_PROP_OR(n, current_speed, \
RZA2M_SCIF_DEFAULT_SPEED), \
.parity = \
DT_INST_ENUM_IDX_OR(n, parity, RZA2M_SCIF_DEFAULT_PARITY), \
.stop_bits = DT_INST_ENUM_IDX_OR(n, stop_bits, \
RZA2M_SCIF_DEFAULT_STOP_BITS), \
.data_bits = DT_INST_ENUM_IDX_OR(n, data_bits, \
RZA2M_SCIF_DEFAULT_DATA_BITS), \
.flow_ctrl = UART_CFG_FLOW_CTRL_NONE, \
}, \
.channel = DT_INST_PROP(n, channel), \
}; \
static const struct uart_rza2m_scif_cfg uart_rza2m_scif_cfg_##n; \
DEVICE_DT_INST_DEFINE(n, uart_rza2m_scif_init, NULL, &uart_rza2m_scif_data_##n, \
&uart_rza2m_scif_cfg_##n, PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
&uart_rza2m_scif_driver_api); \
\
UART_RZA2M_IRQ_CONFIG_FUNC(n) \
UART_RZA2M_INIT_CFG(n);
DT_INST_FOREACH_STATUS_OKAY(UART_RZA2M_INIT)