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.
 
 
 
 
 
 

128 lines
4.4 KiB

/*
* Copyright (c) 2024 Renesas Electronics Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT renesas_rx_uart_sci_qemu
#include <zephyr/drivers/uart.h>
#include <soc.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(renesas_rx_uart_sci_qemu, CONFIG_UART_LOG_LEVEL);
#define REG_MASK(reg) (BIT_MASK(_CONCAT(reg, _LEN)) << _CONCAT(reg, _POS))
/* Registers */
#define SMR 0x00 /*!< Serial Mode Register */
#define BRR 0x01 /*!< Bit Rate Register */
#define SCR 0x02 /*!< Serial Control Register */
#define TDR 0x03 /*!< Transmit Data Register */
#define SSR 0x04 /*!< Serial Status Register */
#define RDR 0x05 /*!< Receive Data Register */
/**
* SSR (Serial Status Register)
*
* - MPBT[0..1]: Multi-Processor Bit Transfer
* - MPB[1..2]: Multi-Processor
* - TEND[2..3]: Transmit End Flag
* - PER[3..4]: Parity Error Flag
* - FER[4..5]: Framing Error Flag
* - ORER[5..6]: Overrun Error Flag
* - RDRF[6..7]: Receive Data Full Flag
* - TDRE[7..8]: Transmit Data Empty Flag
*/
#define SSR_MPBT_POS (0)
#define SSR_MPBT_LEN (1)
#define SSR_MPB_POS (1)
#define SSR_MPB_LEN (1)
#define SSR_TEND_POS (2)
#define SSR_TEND_LEN (1)
#define SSR_PER_POS (3)
#define SSR_PER_LEN (1)
#define SSR_FER_POS (4)
#define SSR_FER_LEN (1)
#define SSR_ORER_POS (5)
#define SSR_ORER_LEN (1)
#define SSR_RDRF_POS (6)
#define SSR_RDRF_LEN (1)
#define SSR_TDRE_POS (7)
#define SSR_TDRE_LEN (1)
#define SCI_SCR_RE (1 << 4)
struct uart_renesas_rx_sci_qemu_cfg {
mem_addr_t regs;
};
struct uart_renesas_rx_sci_qemu_data {
const struct device *dev;
struct uart_config uart_config;
};
static uint8_t uart_renesas_rx_qemu_read_8(const struct device *dev, uint32_t offs)
{
const struct uart_renesas_rx_sci_qemu_cfg *config = dev->config;
return sys_read8(config->regs + offs);
}
static void uart_renesas_rx_qemu_write_8(const struct device *dev, uint32_t offs, uint8_t value)
{
const struct uart_renesas_rx_sci_qemu_cfg *config = dev->config;
sys_write8(value, config->regs + offs);
}
static int uart_renesas_rx_sci_qemu_poll_in(const struct device *dev, unsigned char *c)
{
uart_renesas_rx_qemu_write_8(dev, SCR, SCI_SCR_RE);
if ((uart_renesas_rx_qemu_read_8(dev, SSR) & REG_MASK(SSR_RDRF)) == 0) {
/* There are no characters available to read. */
return -1;
}
*c = uart_renesas_rx_qemu_read_8(dev, RDR);
return 0;
}
static void uart_renesas_rx_sci_qemu_poll_out(const struct device *dev, unsigned char c)
{
while (!(uart_renesas_rx_qemu_read_8(dev, SSR) & REG_MASK(SSR_TEND))) {
}
uart_renesas_rx_qemu_write_8(dev, TDR, c);
}
static DEVICE_API(uart, uart_rx_driver_api) = {
.poll_in = uart_renesas_rx_sci_qemu_poll_in,
.poll_out = uart_renesas_rx_sci_qemu_poll_out,
};
/* Device Instantiation */
#define UART_RENESAS_RX_SCI_QEMU_CFG_INIT(n) \
static const struct uart_renesas_rx_sci_qemu_cfg uart_rx_sci_cfg_##n = { \
.regs = DT_REG_ADDR(DT_INST_PARENT(n)), \
}
#define UART_RENESAS_RX_SCI_QEMU_INIT(n) \
UART_RENESAS_RX_SCI_QEMU_CFG_INIT(n); \
\
static struct uart_renesas_rx_sci_qemu_data uart_rx_sci_data_##n = { \
.uart_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, \
}, \
}; \
\
DEVICE_DT_INST_DEFINE(n, NULL, NULL, &uart_rx_sci_data_##n, &uart_rx_sci_cfg_##n, \
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, &uart_rx_driver_api);
DT_INST_FOREACH_STATUS_OKAY(UART_RENESAS_RX_SCI_QEMU_INIT)