drivers: serial: introduce new Telink B91 Serial driver
Serial driver basic support for new Telink B91 platform. Signed-off-by: Yuriy Vynnychek <yura.vynnychek@telink-semi.com>
This commit is contained in:
parent
6c76b416ee
commit
15818a8245
5 changed files with 585 additions and 0 deletions
|
@ -291,6 +291,7 @@
|
|||
/drivers/sensor/lsm*/ @avisconti
|
||||
/drivers/sensor/mpr/ @sven-hm
|
||||
/drivers/sensor/st*/ @avisconti
|
||||
/drivers/serial/*b91* @yurvyn
|
||||
/drivers/serial/uart_altera_jtag_hal.c @nashif
|
||||
/drivers/serial/*ns16550* @dcpleung @nashif @jenmwms @aasthagr
|
||||
/drivers/serial/*nrfx* @Mierunski @anangl
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
zephyr_library()
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_ALTERA_JTAG uart_altera_jtag_hal.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_TELINK_B91 uart_b91.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_IMX uart_imx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_CC13XX_CC26XX uart_cc13xx_cc26xx.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_UART_CC32XX uart_cc32xx.c)
|
||||
|
|
|
@ -79,6 +79,8 @@ config UART_DRV_CMD
|
|||
|
||||
comment "Serial Drivers"
|
||||
|
||||
source "drivers/serial/Kconfig.b91"
|
||||
|
||||
source "drivers/serial/Kconfig.ns16550"
|
||||
|
||||
source "drivers/serial/Kconfig.mcux"
|
||||
|
|
12
drivers/serial/Kconfig.b91
Normal file
12
drivers/serial/Kconfig.b91
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright (c) 2021 Telink Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Telink B91 UART configuration options
|
||||
|
||||
config UART_TELINK_B91
|
||||
bool "Telink B91 UART driver"
|
||||
depends on SOC_RISCV_TELINK_B91
|
||||
select SERIAL_HAS_DRIVER
|
||||
select SERIAL_SUPPORT_INTERRUPT
|
||||
help
|
||||
This option enables the B91 serial driver.
|
569
drivers/serial/uart_b91.c
Normal file
569
drivers/serial/uart_b91.c
Normal file
|
@ -0,0 +1,569 @@
|
|||
/*
|
||||
* Copyright (c) 2021 Telink Semiconductor
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "analog.h"
|
||||
#include "clock.h"
|
||||
|
||||
#include <device.h>
|
||||
#include <drivers/uart.h>
|
||||
#include <drivers/pinmux.h>
|
||||
#include <dt-bindings/pinctrl/b91-pinctrl.h>
|
||||
|
||||
|
||||
/* Driver dts compatibility: telink,b91_uart */
|
||||
#define DT_DRV_COMPAT telink_b91_uart
|
||||
|
||||
/* Get UART instance */
|
||||
#define GET_UART(dev) ((volatile struct uart_b91_t *) \
|
||||
((const struct uart_b91_config *)dev->config)->uart_addr)
|
||||
|
||||
/* Get UART configuration */
|
||||
#define GET_CFG(dev) ((const struct uart_b91_config *)dev->config)
|
||||
|
||||
/* Get instance data */
|
||||
#define DEV_DATA(dev) ((struct uart_b91_data *const)dev->data)
|
||||
|
||||
/* UART TX buffer count max value */
|
||||
#define UART_TX_BUF_CNT ((uint8_t)8u)
|
||||
|
||||
/* Parity type */
|
||||
#define UART_PARITY_NONE ((uint8_t)0u)
|
||||
#define UART_PARITY_EVEN ((uint8_t)1u)
|
||||
#define UART_PARITY_ODD ((uint8_t)2u)
|
||||
|
||||
/* Stop bits length */
|
||||
#define UART_STOP_BIT_1 ((uint8_t)0u)
|
||||
#define UART_STOP_BIT_1P5 BIT(4)
|
||||
#define UART_STOP_BIT_2 BIT(5)
|
||||
|
||||
|
||||
/* B91 UART registers structure */
|
||||
struct uart_b91_t {
|
||||
uint8_t data_buf[4];
|
||||
uint16_t clk_div;
|
||||
uint8_t ctrl0;
|
||||
uint8_t ctrl1;
|
||||
uint8_t ctrl2;
|
||||
uint8_t ctrl3;
|
||||
uint16_t rxtimeout;
|
||||
uint8_t bufcnt;
|
||||
uint8_t status;
|
||||
uint8_t txrx_status;
|
||||
uint8_t state;
|
||||
};
|
||||
|
||||
/* B91 UART data structure */
|
||||
struct uart_b91_data {
|
||||
uint8_t tx_byte_index;
|
||||
uint8_t rx_byte_index;
|
||||
struct uart_config cfg;
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
uart_irq_callback_user_data_t callback;
|
||||
void *cb_data;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* B91 UART config structure */
|
||||
struct uart_b91_config {
|
||||
const uint32_t *pinctrl_list;
|
||||
size_t pinctrl_list_size;
|
||||
uint32_t uart_addr;
|
||||
uint32_t baud_rate;
|
||||
void (*pirq_connect)(void);
|
||||
};
|
||||
|
||||
/* rxtimeout register enums */
|
||||
enum {
|
||||
UART_ERR_IRQ_MASK = BIT(15),
|
||||
};
|
||||
|
||||
/* ctrl0 register enums */
|
||||
enum {
|
||||
UART_RX_IRQ_MASK = BIT(6),
|
||||
UART_TX_IRQ_MASK = BIT(7),
|
||||
};
|
||||
|
||||
/* ctrl3 register enums */
|
||||
enum {
|
||||
FLD_UART_RX_IRQ_TRIQ_LEV_OFFSET = 0,
|
||||
FLD_UART_TX_IRQ_TRIQ_LEV_OFFSET = 4,
|
||||
};
|
||||
|
||||
/* bufcnt register enums */
|
||||
enum {
|
||||
FLD_UART_RX_BUF_CNT_OFFSET = 0,
|
||||
FLD_UART_TX_BUF_CNT_OFFSET = 4,
|
||||
};
|
||||
|
||||
/* status register enums */
|
||||
enum {
|
||||
UART_IRQ_STATUS = BIT(3),
|
||||
UART_RX_ERR_STATUS = BIT(7),
|
||||
};
|
||||
|
||||
|
||||
/* Get tx fifo count */
|
||||
static inline uint8_t uart_b91_get_tx_bufcnt(volatile struct uart_b91_t *uart)
|
||||
{
|
||||
return (uart->bufcnt & FLD_UART_TX_BUF_CNT) >> FLD_UART_TX_BUF_CNT_OFFSET;
|
||||
}
|
||||
|
||||
/* Get rx fifo count */
|
||||
static inline uint8_t uart_b91_get_rx_bufcnt(volatile struct uart_b91_t *uart)
|
||||
{
|
||||
return (uart->bufcnt & FLD_UART_RX_BUF_CNT) >> FLD_UART_RX_BUF_CNT_OFFSET;
|
||||
}
|
||||
|
||||
/* Check for prime */
|
||||
static uint8_t uart_b91_is_prime(uint32_t n)
|
||||
{
|
||||
uint32_t i = 5;
|
||||
|
||||
if (n <= 3) {
|
||||
return 1;
|
||||
} else if ((n % 2 == 0) || (n % 3 == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 5; i * i < n; i += 6) {
|
||||
if ((n % i == 0) || (n % (i + 2)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Calculate the best bit width */
|
||||
static void uart_b91_cal_div_and_bwpc(uint32_t baudrate, uint32_t pclk,
|
||||
uint16_t *divider, uint8_t *bwpc)
|
||||
{
|
||||
uint8_t i = 0, j = 0;
|
||||
uint32_t primeInt = 0;
|
||||
uint8_t primeDec = 0;
|
||||
uint32_t D_intdec[13], D_int[13];
|
||||
uint8_t D_dec[13];
|
||||
|
||||
primeInt = pclk / baudrate;
|
||||
primeDec = 10 * pclk / baudrate - 10 * primeInt;
|
||||
|
||||
if (uart_b91_is_prime(primeInt)) {
|
||||
primeInt += 1;
|
||||
} else if (primeDec > 5) {
|
||||
primeInt += 1;
|
||||
if (uart_b91_is_prime(primeInt)) {
|
||||
primeInt -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 3; i <= 15; i++) {
|
||||
D_intdec[i - 3] = (10 * primeInt) / (i + 1);
|
||||
D_dec[i - 3] = D_intdec[i - 3] - 10 * (D_intdec[i - 3] / 10);
|
||||
D_int[i - 3] = D_intdec[i - 3] / 10;
|
||||
}
|
||||
|
||||
/* find the max and min one decimation point */
|
||||
uint8_t position_min = 0, position_max = 0;
|
||||
uint32_t min = 0xffffffff, max = 0x00;
|
||||
|
||||
for (j = 0; j < 13; j++) {
|
||||
if ((D_dec[j] <= min) && (D_int[j] != 0x01)) {
|
||||
min = D_dec[j];
|
||||
position_min = j;
|
||||
}
|
||||
if (D_dec[j] >= max) {
|
||||
max = D_dec[j];
|
||||
position_max = j;
|
||||
}
|
||||
}
|
||||
|
||||
if ((D_dec[position_min] < 5) && (D_dec[position_max] >= 5)) {
|
||||
if (D_dec[position_min] < (10 - D_dec[position_max])) {
|
||||
*bwpc = position_min + 3;
|
||||
*divider = D_int[position_min] - 1;
|
||||
} else {
|
||||
*bwpc = position_max + 3;
|
||||
*divider = D_int[position_max];
|
||||
}
|
||||
} else if ((D_dec[position_min] < 5) && (D_dec[position_max] < 5)) {
|
||||
*bwpc = position_min + 3;
|
||||
*divider = D_int[position_min] - 1;
|
||||
} else {
|
||||
*bwpc = position_max + 3;
|
||||
*divider = D_int[position_max];
|
||||
}
|
||||
}
|
||||
|
||||
/* Initializes the UART instance */
|
||||
static void uart_b91_init(volatile struct uart_b91_t *uart, uint16_t divider,
|
||||
uint8_t bwpc, uint8_t parity, uint8_t stop_bit)
|
||||
{
|
||||
/* config clock */
|
||||
divider = divider | FLD_UART_CLK_DIV_EN;
|
||||
uart->ctrl0 = bwpc;
|
||||
uart->clk_div = divider;
|
||||
|
||||
/* config parity */
|
||||
if (parity) {
|
||||
/* enable parity function */
|
||||
uart->ctrl1 |= FLD_UART_PARITY_ENABLE;
|
||||
|
||||
if (parity == UART_PARITY_EVEN) {
|
||||
/* enable even parity */
|
||||
uart->ctrl1 &= (~FLD_UART_PARITY_POLARITY);
|
||||
} else if (parity == UART_PARITY_ODD) {
|
||||
/* enable odd parity */
|
||||
uart->ctrl1 |= FLD_UART_PARITY_POLARITY;
|
||||
}
|
||||
} else {
|
||||
uart->ctrl1 &= (~FLD_UART_PARITY_ENABLE); /* disable parity function */
|
||||
}
|
||||
|
||||
/* stop bit config */
|
||||
uart->ctrl1 &= (~FLD_UART_STOP_SEL);
|
||||
uart->ctrl1 |= stop_bit;
|
||||
}
|
||||
|
||||
/* API implementation: irq handler */
|
||||
static void uart_b91_irq_handler(const struct device *dev)
|
||||
{
|
||||
#ifndef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
ARG_UNUSED(dev);
|
||||
#else
|
||||
struct uart_b91_data *data = DEV_DATA(dev);
|
||||
|
||||
if (data->callback != NULL) {
|
||||
data->callback(dev, data->cb_data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* API implementation: configure */
|
||||
static int uart_b91_configure(const struct device *dev,
|
||||
const struct uart_config *cfg)
|
||||
{
|
||||
uint16_t divider;
|
||||
uint8_t bwpc;
|
||||
uint8_t parity;
|
||||
uint8_t stop_bits;
|
||||
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
/* check parity */
|
||||
if (cfg->parity == UART_CFG_PARITY_NONE) {
|
||||
parity = UART_PARITY_NONE;
|
||||
} else if (cfg->parity == UART_CFG_PARITY_ODD) {
|
||||
parity = UART_PARITY_ODD;
|
||||
} else if (cfg->parity == UART_CFG_PARITY_EVEN) {
|
||||
parity = UART_PARITY_EVEN;
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* check stop bits */
|
||||
if (cfg->stop_bits == UART_CFG_STOP_BITS_1) {
|
||||
stop_bits = UART_STOP_BIT_1;
|
||||
} else if (cfg->stop_bits == UART_CFG_STOP_BITS_1_5) {
|
||||
stop_bits = UART_STOP_BIT_1P5;
|
||||
} else if (cfg->stop_bits == UART_CFG_STOP_BITS_2) {
|
||||
stop_bits = UART_STOP_BIT_2;
|
||||
} else {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* check flow control */
|
||||
if (cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/* UART configure */
|
||||
uart_b91_cal_div_and_bwpc(cfg->baudrate, sys_clk.pclk * 1000 * 1000, ÷r, &bwpc);
|
||||
uart_b91_init(uart, divider, bwpc, parity, stop_bits);
|
||||
|
||||
/* save configuration */
|
||||
DEV_DATA(dev)->cfg = *cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API implementation: config_get */
|
||||
static int uart_b91_config_get(const struct device *dev,
|
||||
struct uart_config *cfg)
|
||||
{
|
||||
*cfg = DEV_DATA(dev)->cfg;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API implementation: driver initialization */
|
||||
static int uart_b91_driver_init(const struct device *dev)
|
||||
{
|
||||
uint16_t divider = 0u;
|
||||
uint8_t bwpc = 0u;
|
||||
const struct device *pinmux;
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
const struct uart_b91_config *cfg = GET_CFG(dev);
|
||||
|
||||
pinmux = DEVICE_DT_GET(DT_NODELABEL(pinmux));
|
||||
if (!device_is_ready(pinmux)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
for (int i = 0; i < cfg->pinctrl_list_size; i++) {
|
||||
pinmux_pin_set(pinmux, B91_PINMUX_GET_PIN(cfg->pinctrl_list[i]),
|
||||
B91_PINMUX_GET_FUNC(cfg->pinctrl_list[i]));
|
||||
}
|
||||
|
||||
uart_b91_cal_div_and_bwpc(cfg->baud_rate, sys_clk.pclk * 1000 * 1000, ÷r, &bwpc);
|
||||
uart_b91_init(uart, divider, bwpc, UART_PARITY_NONE, UART_STOP_BIT_1);
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
cfg->pirq_connect();
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API implementation: poll_out */
|
||||
static void uart_b91_poll_out(const struct device *dev, uint8_t c)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
struct uart_b91_data *data = DEV_DATA(dev);
|
||||
|
||||
while (uart_b91_get_tx_bufcnt(uart) >= UART_TX_BUF_CNT) {
|
||||
};
|
||||
|
||||
uart->data_buf[data->tx_byte_index] = c;
|
||||
data->tx_byte_index = (data->tx_byte_index + 1) % ARRAY_SIZE(uart->data_buf);
|
||||
}
|
||||
|
||||
/* API implementation: poll_in */
|
||||
static int uart_b91_poll_in(const struct device *dev, unsigned char *c)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
struct uart_b91_data *data = DEV_DATA(dev);
|
||||
|
||||
if (uart_b91_get_rx_bufcnt(uart) == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
*c = uart->data_buf[data->rx_byte_index];
|
||||
data->rx_byte_index = (data->rx_byte_index + 1) % ARRAY_SIZE(uart->data_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* API implementation: err_check */
|
||||
static int uart_b91_err_check(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
return ((uart->status & UART_RX_ERR_STATUS) != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
|
||||
/* API implementation: fifo_fill */
|
||||
static int uart_b91_fifo_fill(const struct device *dev,
|
||||
const uint8_t *tx_data,
|
||||
int size)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < size; i++) {
|
||||
uart_b91_poll_out(dev, tx_data[i]);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* API implementation: fifo_read */
|
||||
static int uart_b91_fifo_read(const struct device *dev,
|
||||
uint8_t *rx_data,
|
||||
const int size)
|
||||
{
|
||||
int rx_count;
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
for (rx_count = 0; rx_count < size; rx_count++) {
|
||||
if (uart_b91_get_rx_bufcnt(uart) == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
uart_b91_poll_in(dev, &rx_data[rx_count]);
|
||||
}
|
||||
|
||||
return rx_count;
|
||||
}
|
||||
|
||||
/* API implementation: irq_tx_enable */
|
||||
static void uart_b91_irq_tx_enable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->ctrl3 = (uart->ctrl3 & (~FLD_UART_TX_IRQ_TRIQ_LEV)) |
|
||||
BIT(FLD_UART_TX_IRQ_TRIQ_LEV_OFFSET);
|
||||
uart->ctrl0 |= UART_TX_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_tx_disable */
|
||||
static void uart_b91_irq_tx_disable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->ctrl0 &= ~UART_TX_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_tx_ready */
|
||||
static int uart_b91_irq_tx_ready(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
return (uart_b91_get_tx_bufcnt(uart) < UART_TX_BUF_CNT) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* API implementation: irq_tx_complete */
|
||||
static int uart_b91_irq_tx_complete(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
return (uart_b91_get_tx_bufcnt(uart) == 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* API implementation: irq_rx_enable */
|
||||
static void uart_b91_irq_rx_enable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->ctrl3 = (uart->ctrl3 & (~FLD_UART_RX_IRQ_TRIQ_LEV)) |
|
||||
BIT(FLD_UART_RX_IRQ_TRIQ_LEV_OFFSET);
|
||||
uart->ctrl0 |= UART_RX_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_rx_disable */
|
||||
static void uart_b91_irq_rx_disable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->ctrl0 &= ~UART_RX_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_rx_ready */
|
||||
static int uart_b91_irq_rx_ready(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
return (uart_b91_get_rx_bufcnt(uart) > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* API implementation: irq_err_enable */
|
||||
static void uart_b91_irq_err_enable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->rxtimeout |= UART_ERR_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_err_disable*/
|
||||
static void uart_b91_irq_err_disable(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
uart->rxtimeout &= ~UART_ERR_IRQ_MASK;
|
||||
}
|
||||
|
||||
/* API implementation: irq_is_pending */
|
||||
static int uart_b91_irq_is_pending(const struct device *dev)
|
||||
{
|
||||
volatile struct uart_b91_t *uart = GET_UART(dev);
|
||||
|
||||
return ((uart->status & UART_IRQ_STATUS) != 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* API implementation: irq_update */
|
||||
static int uart_b91_irq_update(const struct device *dev)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
/* nothing to be done */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* API implementation: irq_callback_set */
|
||||
static void uart_b91_irq_callback_set(const struct device *dev,
|
||||
uart_irq_callback_user_data_t cb,
|
||||
void *cb_data)
|
||||
{
|
||||
struct uart_b91_data *data = DEV_DATA(dev);
|
||||
|
||||
data->callback = cb;
|
||||
data->cb_data = cb_data;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_UART_INTERRUPT_DRIVEN */
|
||||
|
||||
static const struct uart_driver_api uart_b91_driver_api = {
|
||||
.poll_in = uart_b91_poll_in,
|
||||
.poll_out = uart_b91_poll_out,
|
||||
.err_check = uart_b91_err_check,
|
||||
.configure = uart_b91_configure,
|
||||
.config_get = uart_b91_config_get,
|
||||
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
|
||||
.fifo_fill = uart_b91_fifo_fill,
|
||||
.fifo_read = uart_b91_fifo_read,
|
||||
.irq_tx_enable = uart_b91_irq_tx_enable,
|
||||
.irq_tx_disable = uart_b91_irq_tx_disable,
|
||||
.irq_tx_ready = uart_b91_irq_tx_ready,
|
||||
.irq_tx_complete = uart_b91_irq_tx_complete,
|
||||
.irq_rx_enable = uart_b91_irq_rx_enable,
|
||||
.irq_rx_disable = uart_b91_irq_rx_disable,
|
||||
.irq_rx_ready = uart_b91_irq_rx_ready,
|
||||
.irq_err_enable = uart_b91_irq_err_enable,
|
||||
.irq_err_disable = uart_b91_irq_err_disable,
|
||||
.irq_is_pending = uart_b91_irq_is_pending,
|
||||
.irq_update = uart_b91_irq_update,
|
||||
.irq_callback_set = uart_b91_irq_callback_set,
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
#define UART_B91_INIT(n) \
|
||||
\
|
||||
static void uart_b91_irq_connect_##n(void); \
|
||||
\
|
||||
static const uint32_t uart_pins_##n[] = \
|
||||
B91_PINMUX_DT_INST_GET_ARRAY(n, 0); \
|
||||
\
|
||||
static const struct uart_b91_config uart_b91_cfg_##n = \
|
||||
{ \
|
||||
.uart_addr = DT_INST_REG_ADDR(n), \
|
||||
.baud_rate = DT_INST_PROP(n, current_speed), \
|
||||
.pinctrl_list_size = ARRAY_SIZE(uart_pins_##n), \
|
||||
.pinctrl_list = uart_pins_##n, \
|
||||
.pirq_connect = uart_b91_irq_connect_##n \
|
||||
}; \
|
||||
\
|
||||
static struct uart_b91_data uart_b91_data_##n; \
|
||||
\
|
||||
DEVICE_DT_INST_DEFINE(n, uart_b91_driver_init, \
|
||||
NULL, \
|
||||
&uart_b91_data_##n, \
|
||||
&uart_b91_cfg_##n, \
|
||||
PRE_KERNEL_1, \
|
||||
CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \
|
||||
(void *)&uart_b91_driver_api); \
|
||||
\
|
||||
static void uart_b91_irq_connect_##n(void) \
|
||||
{ \
|
||||
IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \
|
||||
uart_b91_irq_handler, \
|
||||
DEVICE_DT_INST_GET(n), 0); \
|
||||
\
|
||||
riscv_plic_irq_enable(DT_INST_IRQN(n)); \
|
||||
riscv_plic_set_priority(DT_INST_IRQN(n), DT_INST_IRQ(n, priority)); \
|
||||
}
|
||||
|
||||
DT_INST_FOREACH_STATUS_OKAY(UART_B91_INIT)
|
Loading…
Add table
Add a link
Reference in a new issue