drivers: serial: ns16550: Enable simultaneous support of IO, MMIO and PCIe

Enabled simultaneous support by adding a DTS variable named “io-mapped”.
There are 3 possibilities through instance in dtsi file.
Under PCIe, PCIe ns16550.
Under soc and has a variable io-mapped, legacy(IO mapped).
Under soc and don’t have a variable io-mapped, MMIO mapped.
Simultaneous access can be enabled by a Kconfig.
For PCIe instances UART initialization should be done post-kernel as it
depends on PCIe initialization.

Co-authored-by: Najumon BA <najumon.ba@intel.com>
Signed-off-by: Anisetti Avinash Krishna <anisetti.avinash.krishna@intel.com>
This commit is contained in:
Anisetti Avinash Krishna 2023-03-27 11:19:13 +05:30 committed by Anas Nashif
parent 4978a651a7
commit 26133e995d
3 changed files with 206 additions and 82 deletions

View file

@ -66,6 +66,12 @@ config UART_NS16550_ACCESS_IOPORT
When enabled, NS16550 will not be a memory mapped device. This option
must be selected at SoC/board level if needed.
config UART_NS16550_SIMULT_ACCESS
bool
help
When enabled, NS16550 supports IO, MMIO, PCIe UART devices simultaneously.
For io-mapped instances, io-mapped DTS property need to be added in dtsi.
menu "NS16550 Workarounds"
config UART_NS16550_WA_ISR_REENABLE_INTERRUPT

View file

@ -204,32 +204,12 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE");
#define IIRC(dev) (((struct uart_ns16550_dev_data *)(dev)->data)->iir_cache)
#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT
#define INBYTE(x) sys_in8(x)
#define INWORD(x) sys_in32(x)
#define OUTBYTE(x, d) sys_out8(d, x)
#define OUTWORD(x, d) sys_out32(d, x)
#else
#define INBYTE(x) sys_read8(x)
#define INWORD(x) sys_read32(x)
#define OUTBYTE(x, d) sys_write8(d, x)
#define OUTWORD(x, d) sys_write32(d, x)
#endif /* CONFIG_UART_NS16550_ACCESS_IOPORT */
#ifdef CONFIG_UART_NS16550_ACCESS_WORD_ONLY
#undef INBYTE
#define INBYTE(x) INWORD(x)
#undef OUTBYTE
#define OUTBYTE(x, d) OUTWORD(x, d)
#endif
/* device config */
struct uart_ns16550_device_config {
#ifndef CONFIG_UART_NS16550_ACCESS_IOPORT
DEVICE_MMIO_ROM;
#else
uint32_t port;
#endif
union {
DEVICE_MMIO_ROM;
uint32_t port;
};
uint32_t sys_clk_freq;
const struct device *clock_dev;
clock_control_subsys_t clock_subsys;
@ -246,13 +226,14 @@ struct uart_ns16550_device_config {
#if defined(CONFIG_PINCTRL)
const struct pinctrl_dev_config *pincfg;
#endif
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
bool io_map;
#endif
};
/** Device data structure */
struct uart_ns16550_dev_data {
#ifndef CONFIG_UART_NS16550_ACCESS_IOPORT
DEVICE_MMIO_RAM;
#endif
struct uart_config uart_config;
struct k_spinlock lock;
uint8_t fifo_size;
@ -272,6 +253,82 @@ struct uart_ns16550_dev_data {
#endif
};
static void ns16550_outbyte(const struct uart_ns16550_device_config *cfg,
uintptr_t port, uint8_t val)
{
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
if (cfg->io_map) {
if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
sys_out32(val, port);
} else {
sys_out8(val, port);
}
} else {
#else
{
#endif
/* MMIO mapped */
if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
sys_write32(val, port);
} else {
sys_write8(val, port);
}
}
}
static uint8_t ns16550_inbyte(const struct uart_ns16550_device_config *cfg,
uintptr_t port)
{
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
if (cfg->io_map) {
if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
return sys_in32(port);
} else {
return sys_in8(port);
}
} else {
#else
{
#endif
/* MMIO mapped */
if (IS_ENABLED(CONFIG_UART_NS16550_ACCESS_WORD_ONLY)) {
return sys_read32(port);
} else {
return sys_read8(port);
}
}
return 0;
}
#if UART_NS16550_PCP_ENABLED
static void ns16550_outword(const struct uart_ns16550_device_config *cfg,
uintptr_t port, uint32_t val)
{
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
if (cfg->io_map) {
sys_out32(val, port);
} else {
#else
{
#endif
/* MMIO mapped */
sys_write32(val, port);
}
}
static uint32_t ns16550_inword(const struct uart_ns16550_device_config *cfg,
uintptr_t port)
{
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
if (cfg->io_map) {
return sys_in32(port);
}
#endif
/* MMIO mapped */
return sys_read32(port);
}
#endif
static inline uint8_t reg_interval(const struct device *dev)
{
const struct uart_ns16550_device_config *config = dev->config;
@ -283,18 +340,26 @@ static const struct uart_driver_api uart_ns16550_driver_api;
static inline uintptr_t get_port(const struct device *dev)
{
#ifndef CONFIG_UART_NS16550_ACCESS_IOPORT
return DEVICE_MMIO_GET(dev);
#else
uintptr_t port;
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
const struct uart_ns16550_device_config *config = dev->config;
return config->port;
if (config->io_map) {
port = config->port;
} else {
#else
{
#endif
port = DEVICE_MMIO_GET(dev);
}
return port;
}
static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t pclk)
{
struct uart_ns16550_dev_data * const dev_data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
uint32_t divisor; /* baud rate divisor */
uint8_t lcr_cache;
@ -307,13 +372,13 @@ static void set_baud_rate(const struct device *dev, uint32_t baud_rate, uint32_t
/ baud_rate) >> 4;
/* set the DLAB to access the baud rate divisor registers */
lcr_cache = INBYTE(LCR(dev));
OUTBYTE(LCR(dev), LCR_DLAB | lcr_cache);
OUTBYTE(BRDL(dev), (unsigned char)(divisor & 0xff));
OUTBYTE(BRDH(dev), (unsigned char)((divisor >> 8) & 0xff));
lcr_cache = ns16550_inbyte(dev_cfg, LCR(dev));
ns16550_outbyte(dev_cfg, LCR(dev), LCR_DLAB | lcr_cache);
ns16550_outbyte(dev_cfg, BRDL(dev), (unsigned char)(divisor & 0xff));
ns16550_outbyte(dev_cfg, BRDH(dev), (unsigned char)((divisor >> 8) & 0xff));
/* restore the DLAB to access the baud rate divisor registers */
OUTBYTE(LCR(dev), lcr_cache);
ns16550_outbyte(dev_cfg, LCR(dev), lcr_cache);
dev_data->uart_config.baudrate = baud_rate;
}
@ -343,7 +408,7 @@ static int uart_ns16550_configure(const struct device *dev,
#endif
#if UART_NS16550_DLF_ENABLED
OUTBYTE(DLF(dev), dev_data->dlf);
ns16550_outbyte(dev_cfg, DLF(dev), dev_data->dlf);
#endif
#if UART_NS16550_PCP_ENABLED
@ -351,8 +416,8 @@ static int uart_ns16550_configure(const struct device *dev,
if (pcp) {
pcp |= PCP_EN;
OUTWORD(PCP(dev), pcp & ~PCP_UPDATE);
OUTWORD(PCP(dev), pcp | PCP_UPDATE);
ns16550_outbyte(dev_cfg, PCP(dev), pcp & ~PCP_UPDATE);
ns16550_outbyte(dev_cfg, PCP(dev), pcp | PCP_UPDATE);
}
#endif
@ -374,7 +439,7 @@ static int uart_ns16550_configure(const struct device *dev,
set_baud_rate(dev, cfg->baudrate, pclk);
/* Local structure to hold temporary values to pass to OUTBYTE() */
/* Local structure to hold temporary values to pass to ns16550_outbyte() */
struct uart_config uart_cfg;
switch (cfg->data_bits) {
@ -422,8 +487,8 @@ static int uart_ns16550_configure(const struct device *dev,
dev_data->uart_config = *cfg;
/* data bits, stop bits, parity, clear DLAB */
OUTBYTE(LCR(dev),
uart_cfg.data_bits | uart_cfg.stop_bits | uart_cfg.parity);
ns16550_outbyte(dev_cfg, LCR(dev),
uart_cfg.data_bits | uart_cfg.stop_bits | uart_cfg.parity);
mdc = MCR_OUT2 | MCR_RTS | MCR_DTR;
#if defined(CONFIG_UART_NS16550_VARIANT_NS16750) || \
@ -433,21 +498,21 @@ static int uart_ns16550_configure(const struct device *dev,
}
#endif
OUTBYTE(MDC(dev), mdc);
ns16550_outbyte(dev_cfg, MDC(dev), mdc);
/*
* Program FIFO: enabled, mode 0 (set for compatibility with quark),
* generate the interrupt at 8th byte
* Clear TX and RX FIFO
*/
OUTBYTE(FCR(dev),
FCR_FIFO | FCR_MODE0 | FCR_FIFO_8 | FCR_RCVRCLR | FCR_XMITCLR
ns16550_outbyte(dev_cfg, FCR(dev),
FCR_FIFO | FCR_MODE0 | FCR_FIFO_8 | FCR_RCVRCLR | FCR_XMITCLR
#ifdef CONFIG_UART_NS16550_VARIANT_NS16750
| FCR_FIFO_64
| FCR_FIFO_64
#endif
);
);
if ((INBYTE(IIR(dev)) & IIR_FE) == IIR_FE) {
if ((ns16550_inbyte(dev_cfg, IIR(dev)) & IIR_FE) == IIR_FE) {
#ifdef CONFIG_UART_NS16550_VARIANT_NS16750
dev_data->fifo_size = 64;
#elif defined(CONFIG_UART_NS16550_VARIANT_NS16950)
@ -460,10 +525,10 @@ static int uart_ns16550_configure(const struct device *dev,
}
/* clear the port */
INBYTE(RDR(dev));
ns16550_inbyte(dev_cfg, RDR(dev));
/* disable interrupts */
OUTBYTE(IER(dev), 0x00);
ns16550_outbyte(dev_cfg, IER(dev), 0x00);
out:
k_spin_unlock(&dev_data->lock, key);
@ -503,7 +568,6 @@ static int uart_ns16550_init(const struct device *dev)
ARG_UNUSED(dev_cfg);
#ifndef CONFIG_UART_NS16550_ACCESS_IOPORT
#if DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie)
if (dev_cfg->pcie) {
struct pcie_bar mbar;
@ -520,10 +584,16 @@ static int uart_ns16550_init(const struct device *dev)
} else
#endif /* DT_ANY_INST_ON_BUS_STATUS_OKAY(pcie) */
{
#if defined(CONFIG_UART_NS16550_ACCESS_IOPORT) || defined(CONFIG_UART_NS16550_SIMULT_ACCESS)
/* Map directly from DTS */
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
if (!dev_cfg->io_map) {
#else
{
#endif
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
}
}
#endif /* !UART_NS15660_ACCESS_IOPORT */
ret = uart_ns16550_configure(dev, &data->uart_config);
if (ret != 0) {
return ret;
@ -547,12 +617,13 @@ static int uart_ns16550_init(const struct device *dev)
static int uart_ns16550_poll_in(const struct device *dev, unsigned char *c)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
int ret = -1;
k_spinlock_key_t key = k_spin_lock(&data->lock);
if ((INBYTE(LSR(dev)) & LSR_RXRDY) != 0) {
if ((ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_RXRDY) != 0) {
/* got a character */
*c = INBYTE(RDR(dev));
*c = ns16550_inbyte(dev_cfg, RDR(dev));
ret = 0;
}
@ -577,12 +648,13 @@ static void uart_ns16550_poll_out(const struct device *dev,
unsigned char c)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
while ((INBYTE(LSR(dev)) & LSR_THRE) == 0) {
while ((ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_THRE) == 0) {
}
OUTBYTE(THR(dev), c);
ns16550_outbyte(dev_cfg, THR(dev), c);
k_spin_unlock(&data->lock, key);
}
@ -598,8 +670,9 @@ static void uart_ns16550_poll_out(const struct device *dev,
static int uart_ns16550_err_check(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
int check = (INBYTE(LSR(dev)) & LSR_EOB_MASK);
int check = (ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_EOB_MASK);
k_spin_unlock(&data->lock, key);
@ -622,11 +695,12 @@ static int uart_ns16550_fifo_fill(const struct device *dev,
int size)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
int i;
k_spinlock_key_t key = k_spin_lock(&data->lock);
for (i = 0; (i < size) && (i < data->fifo_size); i++) {
OUTBYTE(THR(dev), tx_data[i]);
ns16550_outbyte(dev_cfg, THR(dev), tx_data[i]);
}
k_spin_unlock(&data->lock, key);
@ -647,11 +721,12 @@ static int uart_ns16550_fifo_read(const struct device *dev, uint8_t *rx_data,
const int size)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
int i;
k_spinlock_key_t key = k_spin_lock(&data->lock);
for (i = 0; (i < size) && (INBYTE(LSR(dev)) & LSR_RXRDY) != 0; i++) {
rx_data[i] = INBYTE(RDR(dev));
for (i = 0; (i < size) && (ns16550_inbyte(dev_cfg, LSR(dev)) & LSR_RXRDY) != 0; i++) {
rx_data[i] = ns16550_inbyte(dev_cfg, RDR(dev));
}
k_spin_unlock(&data->lock, key);
@ -667,6 +742,7 @@ static int uart_ns16550_fifo_read(const struct device *dev, uint8_t *rx_data,
static void uart_ns16550_irq_tx_enable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
#if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM)
@ -689,7 +765,7 @@ static void uart_ns16550_irq_tx_enable(const struct device *dev)
}
}
#endif
OUTBYTE(IER(dev), INBYTE(IER(dev)) | IER_TBE);
ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) | IER_TBE);
k_spin_unlock(&data->lock, key);
}
@ -702,9 +778,11 @@ static void uart_ns16550_irq_tx_enable(const struct device *dev)
static void uart_ns16550_irq_tx_disable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
OUTBYTE(IER(dev), INBYTE(IER(dev)) & (~IER_TBE));
ns16550_outbyte(dev_cfg, IER(dev),
ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_TBE));
#if defined(CONFIG_UART_INTERRUPT_DRIVEN) && defined(CONFIG_PM)
struct uart_ns16550_dev_data *const dev_data = dev->data;
@ -758,9 +836,10 @@ static int uart_ns16550_irq_tx_ready(const struct device *dev)
static int uart_ns16550_irq_tx_complete(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
int ret = ((INBYTE(LSR(dev)) & (LSR_TEMT | LSR_THRE))
int ret = ((ns16550_inbyte(dev_cfg, LSR(dev)) & (LSR_TEMT | LSR_THRE))
== (LSR_TEMT | LSR_THRE)) ? 1 : 0;
k_spin_unlock(&data->lock, key);
@ -776,9 +855,10 @@ static int uart_ns16550_irq_tx_complete(const struct device *dev)
static void uart_ns16550_irq_rx_enable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
OUTBYTE(IER(dev), INBYTE(IER(dev)) | IER_RXRDY);
ns16550_outbyte(dev_cfg, IER(dev), ns16550_inbyte(dev_cfg, IER(dev)) | IER_RXRDY);
k_spin_unlock(&data->lock, key);
}
@ -791,9 +871,11 @@ static void uart_ns16550_irq_rx_enable(const struct device *dev)
static void uart_ns16550_irq_rx_disable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
OUTBYTE(IER(dev), INBYTE(IER(dev)) & (~IER_RXRDY));
ns16550_outbyte(dev_cfg, IER(dev),
ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_RXRDY));
k_spin_unlock(&data->lock, key);
}
@ -825,9 +907,11 @@ static int uart_ns16550_irq_rx_ready(const struct device *dev)
static void uart_ns16550_irq_err_enable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
OUTBYTE(IER(dev), INBYTE(IER(dev)) | IER_LSR);
ns16550_outbyte(dev_cfg, IER(dev),
ns16550_inbyte(dev_cfg, IER(dev)) | IER_LSR);
k_spin_unlock(&data->lock, key);
}
@ -842,9 +926,11 @@ static void uart_ns16550_irq_err_enable(const struct device *dev)
static void uart_ns16550_irq_err_disable(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
OUTBYTE(IER(dev), INBYTE(IER(dev)) & (~IER_LSR));
ns16550_outbyte(dev_cfg, IER(dev),
ns16550_inbyte(dev_cfg, IER(dev)) & (~IER_LSR));
k_spin_unlock(&data->lock, key);
}
@ -878,9 +964,10 @@ static int uart_ns16550_irq_is_pending(const struct device *dev)
static int uart_ns16550_irq_update(const struct device *dev)
{
struct uart_ns16550_dev_data *data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&data->lock);
IIRC(dev) = INBYTE(IIR(dev));
IIRC(dev) = ns16550_inbyte(dev_cfg, IIR(dev));
k_spin_unlock(&data->lock, key);
@ -922,10 +1009,11 @@ static void uart_ns16550_isr(const struct device *dev)
}
#ifdef CONFIG_UART_NS16550_WA_ISR_REENABLE_INTERRUPT
uint8_t cached_ier = INBYTE(IER(dev));
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
uint8_t cached_ier = ns16550_inbyte(dev_cfg, IER(dev));
OUTBYTE(IER(dev), 0U);
OUTBYTE(IER(dev), cached_ier);
ns16550_outbyte(dev_cfg, IER(dev), 0U);
ns16550_outbyte(dev_cfg, IER(dev), cached_ier);
#endif
}
@ -966,7 +1054,7 @@ static int uart_ns16550_line_ctrl_set(const struct device *dev,
case UART_LINE_CTRL_RTS:
case UART_LINE_CTRL_DTR:
key = k_spin_lock(&data->lock);
mdc = INBYTE(MDC(dev));
mdc = ns16550_inbyte(dev_cfg, MDC(dev));
if (ctrl == UART_LINE_CTRL_RTS) {
chg = MCR_RTS;
@ -979,7 +1067,7 @@ static int uart_ns16550_line_ctrl_set(const struct device *dev,
} else {
mdc &= ~(chg);
}
OUTBYTE(MDC(dev), mdc);
ns16550_outbyte(dev_cfg, MDC(dev), mdc);
k_spin_unlock(&data->lock, key);
return 0;
}
@ -1006,10 +1094,11 @@ static int uart_ns16550_drv_cmd(const struct device *dev, uint32_t cmd,
#if UART_NS16550_DLF_ENABLED
if (cmd == CMD_SET_DLF) {
struct uart_ns16550_dev_data * const dev_data = dev->data;
const struct uart_ns16550_device_config * const dev_cfg = dev->config;
k_spinlock_key_t key = k_spin_lock(&dev_data->lock);
dev_data->dlf = p;
OUTBYTE(DLF(dev), dev_data->dlf);
ns16550_outbyte(dev_cfg, DLF(dev), dev_data->dlf);
k_spin_unlock(&dev_data->lock, key);
return 0;
}
@ -1095,13 +1184,27 @@ static const struct uart_driver_api uart_ns16550_driver_api = {
}
#ifdef CONFIG_UART_NS16550_ACCESS_IOPORT
#define DEV_CONFIG_REG_INIT(n) \
.port = DT_INST_REG_ADDR(n),
#define REG_INIT(n) \
.port = DT_INST_REG_ADDR(n), \
.io_map = true,
#else
#define DEV_CONFIG_REG_INIT_PCIE0(n) DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)),
#define DEV_CONFIG_REG_INIT_PCIE1(n)
#define DEV_CONFIG_REG_INIT(n) \
_CONCAT(DEV_CONFIG_REG_INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n)
#define REG_INIT_PCIE1(n)
#define REG_INIT_PCIE0(n) DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)),
#define DEV_REG_PORT_IO_1(n) \
.port = DT_INST_REG_ADDR(n),
#define DEV_REG_PORT_IO_0(n) \
_CONCAT(REG_INIT_PCIE, DT_INST_ON_BUS(n, pcie))(n)
#ifdef CONFIG_UART_NS16550_SIMULT_ACCESS
#define DEV_IO_INIT(n) \
.io_map = DT_INST_PROP(n, io_mapped),
#else
#define DEV_IO_INIT(n)
#endif
#define REG_INIT(n) \
_CONCAT(DEV_REG_PORT_IO_, DT_INST_PROP(n, io_mapped))(n) \
DEV_IO_INIT(n)
#endif
#ifdef CONFIG_UART_INTERRUPT_DRIVEN
@ -1145,13 +1248,24 @@ static const struct uart_driver_api uart_ns16550_driver_api = {
#define DEV_DATA_DLF_INIT(n) \
_CONCAT(DEV_DATA_DLF, DT_INST_NODE_HAS_PROP(n, dlf))(n)
/* UART on PCIe should be initialized POST_KERNEL as PCIe loads
* as PRE_KERNEL_1 and these UART instances should not load before PCIe.
* In some platforms legacy UART instance is used for console and
* shell so it should load as PRE_KERNEL_1.
*/
#define DEV_BOOT_PRIO0(n) PRE_KERNEL_1
#define DEV_BOOT_PRIO1(n) POST_KERNEL
#define NS16550_BOOT_PRIO(n) \
_CONCAT(DEV_BOOT_PRIO, DT_INST_ON_BUS(n, pcie))(n)
#define UART_NS16550_DEVICE_INIT(n) \
UART_NS16550_IRQ_FUNC_DECLARE(n); \
DEV_PCIE_DECLARE(n); \
IF_ENABLED(DT_INST_NODE_HAS_PROP(n, pinctrl_0), \
(PINCTRL_DT_INST_DEFINE(n))); \
static const struct uart_ns16550_device_config uart_ns16550_dev_cfg_##n = { \
DEV_CONFIG_REG_INIT(n) \
REG_INIT(n) \
COND_CODE_1(DT_INST_NODE_HAS_PROP(n, clock_frequency), ( \
.sys_clk_freq = DT_INST_PROP(n, clock_frequency), \
.clock_dev = NULL, \
@ -1180,7 +1294,7 @@ static const struct uart_driver_api uart_ns16550_driver_api = {
}; \
DEVICE_DT_INST_DEFINE(n, &uart_ns16550_init, NULL, \
&uart_ns16550_dev_data_##n, &uart_ns16550_dev_cfg_##n, \
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
NS16550_BOOT_PRIO(n), CONFIG_SERIAL_INIT_PRIORITY, \
&uart_ns16550_driver_api); \
UART_NS16550_IRQ_FUNC_DEFINE(n)

View file

@ -17,3 +17,7 @@ properties:
dlf:
type: int
description: divisor latch fraction (DLF, if supported)
io-mapped:
type: boolean
description: specify registers are IO mapped or memory mapped