diff --git a/libplatsupport/include/platsupport/driver/ns16550/ns16550.h b/libplatsupport/include/platsupport/driver/ns16550/ns16550.h new file mode 100644 index 000000000..d43a64dfd --- /dev/null +++ b/libplatsupport/include/platsupport/driver/ns16550/ns16550.h @@ -0,0 +1,100 @@ +/* + * Copyright 2022, HENSOLDT Cyber GmbH + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * Driver for a 16550 compatible UART. + */ + +#pragma once + +#include +#include +#include +#include + +#define NS16550_IER_ERBFI BIT(0) /* Enable Received Data Available Interrupt */ +#define NS16550_IER_ETBEI BIT(1) /* Enable Transmitter Holding Register Empty Interrupt */ +#define NS16550_IER_ELSI BIT(2) /* Enable Receiver Line Status Interrupt */ +#define NS16550_IER_EDSSI BIT(3) /* Enable MODEM Status Interrupt */ + +#define NS16550_FCR_ENABLE_FIFOS BIT(0) +#define NS16550_FCR_RESET_RX_FIFO BIT(1) +#define NS16550_FCR_RESET_TX_FIFO BIT(2) +#define NS16550_FCR_TRIGGER_1 (0u << 6) +#define NS16550_FCR_TRIGGER_4 (1u << 6) +#define NS16550_FCR_TRIGGER_8 (2u << 6) +#define NS16550_FCR_TRIGGER_14 (3u << 6) + +#define NS16550_LCR_DLAB BIT(7) /* Divisor Latch Access */ + +#define NS16550_LSR_DR BIT(0) /* Data Ready */ +#define NS16550_LSR_THRE BIT(5) /* Transmitter Holding Register Empty */ + +typedef volatile struct { + uint8_t rbr_dll_thr; /* 0x00 Receiver Buffer Register (Read Only) + * Divisor Latch (LSB) + * Transmitter Holding Register (Write Only) + */ + uint8_t dlm_ier; /* 0x04 Divisor Latch (MSB) + * Interrupt Enable Register + */ + uint8_t iir_fcr; /* 0x08 Interrupt Identification Register (Read Only) + * FIFO Control Register (Write Only) + */ + uint8_t lcr; /* 0xC Line Control Register */ + uint8_t mcr; /* 0x10 MODEM Control Register */ + uint8_t lsr; /* 0x14 Line Status Register */ + uint8_t msr; /* 0x18 MODEM Status Register */ +} ns16550_regs_t; + + +/* + ******************************************************************************* + * UART access primitives + ******************************************************************************* + */ + +static bool ns16550_is_tx_empty(ns16550_regs_t *regs) +{ + /* The THRE bit is set when the FIFO is fully empty. There seems no way to + * detect if the FIFO is partially empty only, so we can't implement a + * "tx_ready" check. + */ + return (0 != (regs->lsr & NS16550_LSR_THRE)); +} + +static void ns16550_tx_byte(ns16550_regs_t *regs, uint8_t byte) +{ + /* Caller has to ensure TX FIFO is ready */ + regs->rbr_dll_thr = byte; +} + +static bool ns16550_is_rx_empty(ns16550_regs_t *regs) +{ + return (0 == (regs->lsr & NS16550_LSR_DR)); +} + + +static int ns16550_rx_byte(ns16550_regs_t *regs) +{ + /* Caller has to ensure RX FIFO has data */ + return regs->rbr_dll_thr; +} + + +/* + ******************************************************************************* + * UART access helpers + ******************************************************************************* + */ + +/* + * Returns a char from the TX FIFO or EOF if the FIFO is empty. + */ +static int ns16550_get_char_or_EOF(ns16550_regs_t *regs) +{ + return ns16550_is_rx_empty(regs) ? EOF : ns16550_rx_byte(regs); +} diff --git a/libplatsupport/include/platsupport/driver/pl011/pl011.h b/libplatsupport/include/platsupport/driver/pl011/pl011.h new file mode 100644 index 000000000..1fd51a5ee --- /dev/null +++ b/libplatsupport/include/platsupport/driver/pl011/pl011.h @@ -0,0 +1,117 @@ +/* + * Copyright 2022, HENSOLDT Cyber GmbH + * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +/* + * Driver for a ARM PL011 UART. + */ + +#pragma once + +#include +#include +#include +#include + +#define PL011_FR_TXFF BIT(5) +#define PL011_FR_RXFE BIT(4) + +typedef volatile struct { + uint32_t dr; /* 0x00 */ + uint32_t _rfu_04; /* 0x04 */ + uint32_t _rfu_08; /* 0x08 */ + uint32_t _rfu_0c; /* 0x0c */ + uint32_t _rfu_10; /* 0x10 */ + uint32_t _rfu_14; /* 0x14 */ + uint32_t fr; /* 0x18 */ + uint32_t _rfu_1c; /* 0x1c */ + uint32_t _rfu_20; /* 0x20 */ + uint32_t _rfu_24; /* 0x24 */ + uint32_t _rfu_28; /* 0x28 */ + uint32_t _rfu_2c; /* 0x2c */ + uint32_t _rfu_30; /* 0x30 */ + uint32_t _rfu_34; /* 0x34 */ + uint32_t imsc; /* 0x38 */ + uint32_t _rfu_3c; /* 0x3c */ + uint32_t _rfu_40; /* 0x40 */ + uint32_t icr; /* 0x44 */ + uint32_t _rfu_48; /* 0x48 */ + uint32_t _rfu_4c; /* 0x4c */ +} pl011_regs_t; + + +/* + ******************************************************************************* + * UART access primitives + ******************************************************************************* + */ + +static bool pl011_is_rx_fifo_empty(pl011_regs_t *regs) +{ + return (0 != (regs->fr & PL011_FR_RXFE)); +} + +static bool pl011_is_tx_fifo_full(pl011_regs_t *regs) +{ + return (0 != (regs->fr & PL011_FR_TXFF)); +} + +static void pl011_write_char(pl011_regs_t *regs, uint8_t c) +{ + /* Caller has to ensure TX FIFO has space */ + regs->dr = c; +} + +static uint8_t pl011_read_char(pl011_regs_t *regs) +{ + return (uint8_t)(regs->dr & 0xFF); +} + +static void pl011_clear_interrupt(pl011_regs_t *regs) +{ + regs->icr = 0x7f0; +} + +static void pl011_init(pl011_regs_t *regs) +{ + regs->imsc = 0x50; +} + + +/* + ******************************************************************************* + * UART access helpers + ******************************************************************************* + */ + +/* + * Returns a char from the TX FIFO or EOF if the FIFO is empty. + */ +int pl011_get_char_or_EOF(pl011_regs_t *regs) +{ + return pl011_is_rx_fifo_empty(regs) ? EOF : pl011_read_char(regs); +} + +/* + * Block until there is space in the TX FIFO, then outputs the char. Optionally + * output a CR (\r) first in case of LF (\n) to support terminal use case. + */ +void pl011_put_char_blocking(pl011_regs_t *regs, uint8_t c, bool is_auto_cr) +{ + + /* output CR (\r) before LF (\n) automatically if UART is a terminal */ + if ((c == '\n') && is_auto_cr) { + while (pl011_is_tx_fifo_full(regs)) { + /* busy loop */ + } + pl011_write_char(regs, '\r'); + } + + while (pl011_is_tx_fifo_full(regs)) { + /* busy loop */ + } + pl011_write_char(regs, c); +} diff --git a/libplatsupport/plat_include/qemu-riscv-virt/platsupport/plat/serial.h b/libplatsupport/plat_include/qemu-riscv-virt/platsupport/plat/serial.h index 47981329b..b096a02d6 100644 --- a/libplatsupport/plat_include/qemu-riscv-virt/platsupport/plat/serial.h +++ b/libplatsupport/plat_include/qemu-riscv-virt/platsupport/plat/serial.h @@ -2,6 +2,10 @@ * Copyright 2022, HENSOLDT Cyber GmbH * * SPDX-License-Identifier: BSD-2-Clause + * + * + * QEMU RISC-V virt emulates a 16550 compatible UART. + * */ #pragma once @@ -22,40 +26,3 @@ enum chardev_id { #define DEFAULT_SERIAL_PADDR UART0_PADDR #define DEFAULT_SERIAL_INTERRUPT UART0_IRQ - -/* QEMU RISC-V virt emulates a 16550 compatible UART. */ - -#define UART_IER_ERBFI BIT(0) /* Enable Received Data Available Interrupt */ -#define UART_IER_ETBEI BIT(1) /* Enable Transmitter Holding Register Empty Interrupt */ -#define UART_IER_ELSI BIT(2) /* Enable Receiver Line Status Interrupt */ -#define UART_IER_EDSSI BIT(3) /* Enable MODEM Status Interrupt */ - -#define UART_FCR_ENABLE_FIFOS BIT(0) -#define UART_FCR_RESET_RX_FIFO BIT(1) -#define UART_FCR_RESET_TX_FIFO BIT(2) -#define UART_FCR_TRIGGER_1 (0u << 6) -#define UART_FCR_TRIGGER_4 (1u << 6) -#define UART_FCR_TRIGGER_8 (2u << 6) -#define UART_FCR_TRIGGER_14 (3u << 6) - -#define UART_LCR_DLAB BIT(7) /* Divisor Latch Access */ - -#define UART_LSR_DR BIT(0) /* Data Ready */ -#define UART_LSR_THRE BIT(5) /* Transmitter Holding Register Empty */ - -typedef volatile struct { - uint8_t rbr_dll_thr; /* 0x00 Receiver Buffer Register (Read Only) - * Divisor Latch (LSB) - * Transmitter Holding Register (Write Only) - */ - uint8_t dlm_ier; /* 0x04 Divisor Latch (MSB) - * Interrupt Enable Register - */ - uint8_t iir_fcr; /* 0x08 Interrupt Identification Register (Read Only) - * FIFO Control Register (Write Only) - */ - uint8_t lcr; /* 0xC Line Control Register */ - uint8_t mcr; /* 0x10 MODEM Control Register */ - uint8_t lsr; /* 0x14 Line Status Register */ - uint8_t msr; /* 0x18 MODEM Status Register */ -} uart_regs_t; diff --git a/libplatsupport/src/plat/fvp/serial.c b/libplatsupport/src/plat/fvp/serial.c index 50fb44a5d..97663ebdd 100644 --- a/libplatsupport/src/plat/fvp/serial.c +++ b/libplatsupport/src/plat/fvp/serial.c @@ -1,54 +1,42 @@ /* + * Copyright 2022, HENSOLDT Cyber GmbH * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause + * + * + * FVP emulates PL011 UARTs. + * */ -/* Mostly copy/paste from the HiKey plat. - * Should be moved to a common driver file for PL011 */ - #include #include #include +#include #include "../../chardev.h" -#define RHR_MASK MASK(8) -#define UARTDR 0x000 -#define UARTFR 0x018 -#define UARTIMSC 0x038 -#define UARTICR 0x044 -#define PL011_UARTFR_TXFF BIT(5) -#define PL011_UARTFR_RXFE BIT(4) - -#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) +static pl011_regs_t *get_pl011_regs(ps_chardevice_t *dev) +{ + return (pl011_regs_t *)(dev->vaddr); +} int uart_getchar(ps_chardevice_t *d) { - int ch = EOF; - - if ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_RXFE) == 0) { - ch = *REG_PTR(d->vaddr, UARTDR) & RHR_MASK; - } - return ch; + pl011_regs_t *regs = get_pl011_regs(d); + return pl011_get_char_or_EOF(regs); } int uart_putchar(ps_chardevice_t *d, int c) { - if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { - uart_putchar(d, '\r'); - } - - while ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_TXFF) != 0) { - /* busy loop */ - } - *REG_PTR(d->vaddr, UARTDR) = c; - + pl011_regs_t *regs = get_pl011_regs(d); + pl011_put_char_blocking_auto_cr(regs, c, d->flags & SERIAL_AUTO_CR); return c; } static void uart_handle_irq(ps_chardevice_t *dev) { - *REG_PTR(dev->vaddr, UARTICR) = 0x7f0; + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_clear_interrupt(regs); } int uart_init(const struct dev_defn *defn, @@ -56,6 +44,8 @@ int uart_init(const struct dev_defn *defn, ps_chardevice_t *dev) { memset(dev, 0, sizeof(*dev)); + + /* Map device. */ void *vaddr = chardev_map(defn, ops); if (vaddr == NULL) { return -1; @@ -71,6 +61,9 @@ int uart_init(const struct dev_defn *defn, dev->ioops = *ops; dev->flags = SERIAL_AUTO_CR; - *REG_PTR(dev->vaddr, UARTIMSC) = 0x50; + /* Initialize the device. */ + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_init(regs); + return 0; } diff --git a/libplatsupport/src/plat/hikey/serial.c b/libplatsupport/src/plat/hikey/serial.c index 38b0e8cdb..eed6dabe0 100644 --- a/libplatsupport/src/plat/hikey/serial.c +++ b/libplatsupport/src/plat/hikey/serial.c @@ -1,51 +1,42 @@ /* + * Copyright 2022, HENSOLDT Cyber GmbH * Copyright 2017, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause + * + * + * HiKey uses PL011 UARTs. + * */ #include #include #include +#include #include "../../chardev.h" -#define RHR_MASK MASK(8) -#define UARTDR 0x000 -#define UARTFR 0x018 -#define UARTIMSC 0x038 -#define UARTICR 0x044 -#define PL011_UARTFR_TXFF BIT(5) -#define PL011_UARTFR_RXFE BIT(4) - -#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) +static pl011_regs_t *get_pl011_regs(ps_chardevice_t *dev) +{ + return (pl011_regs_t *)(dev->vaddr); +} int uart_getchar(ps_chardevice_t *d) { - int ch = EOF; - - if ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_RXFE) == 0) { - ch = *REG_PTR(d->vaddr, UARTDR) & RHR_MASK; - } - return ch; + pl011_regs_t *regs = get_pl011_regs(d); + return pl011_get_char_or_EOF(regs); } int uart_putchar(ps_chardevice_t *d, int c) { - if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { - uart_putchar(d, '\r'); - } - - while ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_TXFF) != 0) { - /* busy loop */ - } - *REG_PTR(d->vaddr, UARTDR) = c; - + pl011_regs_t *regs = get_pl011_regs(d); + pl011_put_char_blocking(regs, c, d->flags & SERIAL_AUTO_CR); return c; } static void uart_handle_irq(ps_chardevice_t *dev) { - *REG_PTR(dev->vaddr, UARTICR) = 0x7f0; + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_clear_interrupt(regs); } int uart_init(const struct dev_defn *defn, @@ -53,6 +44,8 @@ int uart_init(const struct dev_defn *defn, ps_chardevice_t *dev) { memset(dev, 0, sizeof(*dev)); + + /* Map device. */ void *vaddr = chardev_map(defn, ops); if (vaddr == NULL) { return -1; @@ -68,6 +61,9 @@ int uart_init(const struct dev_defn *defn, dev->ioops = *ops; dev->flags = SERIAL_AUTO_CR; - *REG_PTR(dev->vaddr, UARTIMSC) = 0x50; + /* Initialize the device. */ + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_init(regs); + return 0; } diff --git a/libplatsupport/src/plat/qemu-arm-virt/serial.c b/libplatsupport/src/plat/qemu-arm-virt/serial.c index 47b665e16..79d49ae8e 100644 --- a/libplatsupport/src/plat/qemu-arm-virt/serial.c +++ b/libplatsupport/src/plat/qemu-arm-virt/serial.c @@ -1,52 +1,42 @@ /* + * Copyright 2022, HENSOLDT Cyber GmbH * Copyright 2019, Data61, CSIRO (ABN 41 687 119 230) * * SPDX-License-Identifier: BSD-2-Clause + * + * + * QEMU arm-virt emulates a PL011 UART. + * */ -/* Mostly copy/paste from the HiKey plat. - * Should be moved to a common driver file for PL011 */ - #include #include #include +#include #include "../../chardev.h" -#define RHR_MASK MASK(8) -#define UARTDR 0x000 -#define UARTFR 0x018 -#define UARTIMSC 0x038 -#define UARTICR 0x044 -#define PL011_UARTFR_TXFF BIT(5) -#define PL011_UARTFR_RXFE BIT(4) - -#define REG_PTR(base, off) ((volatile uint32_t *)((base) + (off))) +static pl011_regs_t *get_pl011_regs(ps_chardevice_t *dev) +{ + return (pl011_regs_t *)(dev->vaddr); +} int uart_getchar(ps_chardevice_t *d) { - int ch = EOF; - - if ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_RXFE) == 0) { - ch = *REG_PTR(d->vaddr, UARTDR) & RHR_MASK; - } - return ch; + pl011_regs_t *regs = get_pl011_regs(d); + return pl011_get_char_or_EOF(regs); } int uart_putchar(ps_chardevice_t *d, int c) { - while ((*REG_PTR(d->vaddr, UARTFR) & PL011_UARTFR_TXFF) != 0); - - *REG_PTR(d->vaddr, UARTDR) = c; - if (c == '\n' && (d->flags & SERIAL_AUTO_CR)) { - uart_putchar(d, '\r'); - } - + pl011_regs_t *regs = get_pl011_regs(d); + pl011_put_char_blocking(regs, c, d->flags & SERIAL_AUTO_CR); return c; } static void uart_handle_irq(ps_chardevice_t *dev) { - *REG_PTR(dev->vaddr, UARTICR) = 0x7f0; + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_clear_interrupt(regs); } int uart_init(const struct dev_defn *defn, @@ -54,12 +44,14 @@ int uart_init(const struct dev_defn *defn, ps_chardevice_t *dev) { memset(dev, 0, sizeof(*dev)); + + /* Map device. */ void *vaddr = chardev_map(defn, ops); if (vaddr == NULL) { return -1; } - /* Set up all the device properties. */ + /* Set up all the device properties. */ dev->id = defn->id; dev->vaddr = (void *)vaddr; dev->read = &uart_read; @@ -69,6 +61,9 @@ int uart_init(const struct dev_defn *defn, dev->ioops = *ops; dev->flags = SERIAL_AUTO_CR; - *REG_PTR(dev->vaddr, UARTIMSC) = 0x50; + /* Initialize the device. */ + pl011_regs_t *regs = get_pl011_regs(dev); + pl011_init(regs); + return 0; } diff --git a/libplatsupport/src/plat/qemu-riscv-virt/serial.c b/libplatsupport/src/plat/qemu-riscv-virt/serial.c index a13989c89..cc8a814b3 100644 --- a/libplatsupport/src/plat/qemu-riscv-virt/serial.c +++ b/libplatsupport/src/plat/qemu-riscv-virt/serial.c @@ -2,55 +2,23 @@ * Copyright 2022, HENSOLDT Cyber GmbH * * SPDX-License-Identifier: BSD-2-Clause + * + * + * QEMU riscv-virt emulates a 16550 compatible UART. + * */ -/* QEMU RISC-V virt emulates a 16550 compatible UART. */ - #include #include #include +#include #include "../../chardev.h" -static uart_regs_t *uart_get_regs(ps_chardevice_t *dev) -{ - return (uart_regs_t *)(dev->vaddr); -} - -/* - ******************************************************************************* - * UART access primitives - ******************************************************************************* - */ - -static bool internal_uart_is_tx_empty(uart_regs_t *regs) -{ - /* The THRE bit is set when the FIFO is fully empty. On real hardware, there - * seems no way to detect if the FIFO is partially empty only, so we can't - * implement a "tx_ready" check. Since QEMU does not emulate a FIFO, this - * does not really matter. - */ - return (0 != (regs->lsr & UART_LSR_THRE)); -} - -static void internal_uart_tx_byte(uart_regs_t *regs, uint8_t byte) -{ - /* Caller has to ensure TX FIFO is ready */ - regs->rbr_dll_thr = byte; -} - -static bool internal_uart_is_rx_empty(uart_regs_t *regs) -{ - return (0 == (regs->lsr & UART_LSR_DR)); -} - - -static int internal_uart_rx_byte(uart_regs_t *regs) +static ns16550_regs_t *uart_get_regs(ps_chardevice_t *dev) { - /* Caller has to ensure RX FIFO has data */ - return regs->rbr_dll_thr; + return (ns16550_regs_t *)(dev->vaddr); } - /* ******************************************************************************* * UART access API @@ -59,7 +27,7 @@ static int internal_uart_rx_byte(uart_regs_t *regs) int uart_putchar(ps_chardevice_t *dev, int c) { - uart_regs_t *regs = uart_get_regs(dev); + ns16550_regs_t *regs = uart_get_regs(dev); /* There is no way to check for "TX ready", the only thing we have is a * check for "TX FIFO empty". This is not optimal, as we might wait here @@ -71,7 +39,7 @@ int uart_putchar(ps_chardevice_t *dev, int c) * However, since QEMU does not emulate a FIFO, we can just implement a * simple model here and block - expecting to never block practically. */ - while (!internal_uart_is_tx_empty(regs)) { + while (!ns16550_is_tx_empty(regs)) { /* busy waiting loop */ } @@ -80,27 +48,21 @@ int uart_putchar(ps_chardevice_t *dev, int c) /* If SERIAL_AUTO_CR is enabled, a CR is sent before any LF. */ if ((byte == '\n') && (dev->flags & SERIAL_AUTO_CR)) { - internal_uart_tx_byte(regs, '\r'); + ns16550_tx_byte(regs, '\r'); /* Since we have blocked until the FIFO is empty, we don't have to wait * here. And QEMU does not emulate a FIFOs anyway. */ } - internal_uart_tx_byte(regs, byte); + ns16550_tx_byte(regs, byte); return byte; } int uart_getchar(ps_chardevice_t *dev) { - uart_regs_t *regs = uart_get_regs(dev); - - /* if UART is empty return an error */ - if (internal_uart_is_rx_empty(regs)) { - return EOF; - } - - return internal_uart_rx_byte(regs) & 0xFF; + ns16550_regs_t *regs = uart_get_regs(dev); + return ns16550_get_char_or_EOF(regs); } static void uart_handle_irq(ps_chardevice_t *dev) @@ -108,29 +70,28 @@ static void uart_handle_irq(ps_chardevice_t *dev) /* No IRQ handling required here. */ } -static void uart_setup(ps_chardevice_t *dev) +static void ns16550_init(ns16550_regs_t *regs) { - uart_regs_t *regs = uart_get_regs(dev); - - regs->dlm_ier = 0; // disable interrupts + /* disable interrupts */ + regs->dlm_ier = 0; /* Baudrates and serial line parameters are not emulated by QEMU, so the * divisor is just a dummy. */ uint16_t clk_divisor = 1; /* dummy, would be for 115200 baud */ - regs->lcr = UART_LCR_DLAB; /* baud rate divisor setup */ + regs->lcr = NS16550_LCR_DLAB; /* baud rate divisor setup */ regs->dlm_ier = (clk_divisor >> 8) & 0xFF; regs->rbr_dll_thr = clk_divisor & 0xFF; regs->lcr = 0x03; /* set 8N1, clear DLAB to end baud rate divisor setup */ /* enable and reset FIFOs, interrupt for each byte */ - regs->iir_fcr = UART_FCR_ENABLE_FIFOS - | UART_FCR_RESET_RX_FIFO - | UART_FCR_RESET_TX_FIFO - | UART_FCR_TRIGGER_1; + regs->iir_fcr = NS16550_FCR_ENABLE_FIFOS + | NS16550_FCR_RESET_RX_FIFO + | NS16550_FCR_RESET_TX_FIFO + | NS16550_FCR_TRIGGER_1; /* enable RX interrupts */ - regs->dlm_ier = UART_IER_ERBFI; + regs->dlm_ier = NS16550_IER_ERBFI; } int uart_init(const struct dev_defn *defn, @@ -155,8 +116,9 @@ int uart_init(const struct dev_defn *defn, dev->ioops = *ops; dev->flags = SERIAL_AUTO_CR; - /* Set up the device. */ - uart_setup(dev); + /* Initialize the device. */ + ns16550_regs_t *regs = uart_get_regs(dev); + ns16550_init(regs); return 0; }