From 0f421539598717a91cd7eee2b1cbf7ed32cb22f9 Mon Sep 17 00:00:00 2001 From: Utkarsh Verma Date: Thu, 29 Aug 2024 02:10:12 +0800 Subject: [PATCH] dev/serial: Refactor the pl011 driver - Refactor the pl011 driver to be extensible. - Add IRQ support and baudrate configuration support for pl011 driver. - Modify related BSP. - Add doxygen comments for arm-pl011. Close #5026 Co-authored-by: Ning Yang --- bsps/aarch64/a53/console/console.c | 5 +- bsps/aarch64/a72/console/console.c | 5 +- bsps/aarch64/raspberrypi/console/console.c | 7 +- bsps/aarch64/raspberrypi/include/bsp/irq.h | 5 + bsps/aarch64/xilinx-versal/console/console.c | 41 +- .../dev/serial/versal-uart-polled.c | 194 ------- .../xilinx-versal/dev/serial/versal-uart.c | 225 +++++---- .../include/dev/serial/versal-uart-regs.h | 140 ----- .../include/dev/serial/versal-uart.h | 27 +- bsps/arm/raspberrypi/console/console-config.c | 4 +- .../realview-pbx-a9/console/console-polled.c | 7 +- bsps/arm/xen/console/console.c | 5 +- bsps/include/dev/serial/arm-pl011-regs.h | 27 +- bsps/include/dev/serial/arm-pl011.h | 110 +++- bsps/shared/dev/serial/arm-pl011.c | 478 +++++++++++++++++- .../aarch64/raspberrypi/bspraspberrypi4.yml | 4 + spec/build/bsps/aarch64/xilinx-versal/grp.yml | 4 +- spec/build/bsps/aarch64/xilinx-versal/obj.yml | 4 +- .../bsps/aarch64/xilinx-versal/optconirq.yml | 16 - spec/build/bsps/optconsolefifo.yml | 25 + 20 files changed, 808 insertions(+), 525 deletions(-) delete mode 100644 bsps/aarch64/xilinx-versal/dev/serial/versal-uart-polled.c delete mode 100644 bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart-regs.h delete mode 100644 spec/build/bsps/aarch64/xilinx-versal/optconirq.yml create mode 100644 spec/build/bsps/optconsolefifo.yml diff --git a/bsps/aarch64/a53/console/console.c b/bsps/aarch64/a53/console/console.c index 1854909c98..406ea5d1fc 100644 --- a/bsps/aarch64/a53/console/console.c +++ b/bsps/aarch64/a53/console/console.c @@ -44,8 +44,9 @@ arm_pl011_context a53_qemu_vpl011_context = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), - .regs = (volatile pl011 *) BSP_A53_QEMU_VPL011_BASE, - .initial_baud = 115200 + .regs = (arm_pl011_uart *) BSP_A53_QEMU_VPL011_BASE, + .initial_baud = 115200, + .clock = 24000000 }; const console_device console_device_table[] = { diff --git a/bsps/aarch64/a72/console/console.c b/bsps/aarch64/a72/console/console.c index 08532d68cd..1d6e977d26 100644 --- a/bsps/aarch64/a72/console/console.c +++ b/bsps/aarch64/a72/console/console.c @@ -44,8 +44,9 @@ arm_pl011_context a72_qemu_vpl011_context = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), - .regs = (volatile pl011 *) BSP_A72_QEMU_VPL011_BASE, - .initial_baud = 115200 + .regs = (arm_pl011_uart *) BSP_A72_QEMU_VPL011_BASE, + .initial_baud = 115200, + .clock = 24000000 }; const console_device console_device_table[] = { diff --git a/bsps/aarch64/raspberrypi/console/console.c b/bsps/aarch64/raspberrypi/console/console.c index 73bb0036ff..0736277eb6 100644 --- a/bsps/aarch64/raspberrypi/console/console.c +++ b/bsps/aarch64/raspberrypi/console/console.c @@ -39,13 +39,16 @@ #include #include #include +#include #include arm_pl011_context raspberrypi_4_context = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), - .regs = (volatile pl011 *) BSP_RPI4_PL011_BASE, - .initial_baud = 115200 + .regs = (arm_pl011_uart *)BSP_RPI4_PL011_BASE, + .initial_baud = 115200, + .clock = 48000000, + .irq = BCM2711_IRQ_PL011_UART }; const console_device console_device_table[] = { diff --git a/bsps/aarch64/raspberrypi/include/bsp/irq.h b/bsps/aarch64/raspberrypi/include/bsp/irq.h index f543295c07..0357837bae 100644 --- a/bsps/aarch64/raspberrypi/include/bsp/irq.h +++ b/bsps/aarch64/raspberrypi/include/bsp/irq.h @@ -50,6 +50,11 @@ /* Interrupt Vectors: SPI */ #define BCM2711_IRQ_SPI (BCM2711_IRQ_VC_PERIPHERAL_BASE + 54) +/* Interrupt Vectors: Videocore */ +#define BCM2711_IRQ_VC_PERIPHERAL_BASE 96 +#define BCM2711_IRQ_AUX (BCM2711_IRQ_VC_PERIPHERAL_BASE + 29) +#define BCM2711_IRQ_PL011_UART (BCM2711_IRQ_VC_PERIPHERAL_BASE + 57) + #define BCM2835_IRQ_ID_USB 9 #define BCM2835_IRQ_ID_AUX 29 #define BCM2835_IRQ_ID_SPI_SLAVE 43 diff --git a/bsps/aarch64/xilinx-versal/console/console.c b/bsps/aarch64/xilinx-versal/console/console.c index e7f752f1a7..232a1893be 100644 --- a/bsps/aarch64/xilinx-versal/console/console.c +++ b/bsps/aarch64/xilinx-versal/console/console.c @@ -38,19 +38,28 @@ #include #include +#include #include #include -static versal_uart_context versal_uart_instances[2] = { +static versal_pl011_context versal_uart_instances[2] = { { - .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "Versal UART 0" ), - .regs = (volatile struct versal_uart *) 0xff000000, - .irq = VERSAL_IRQ_UART_0 + .pl011_ctx = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Versal UART 0"), + .regs = (arm_pl011_uart *) 0xff000000, + .irq = VERSAL_IRQ_UART_0, + .clock = VERSAL_CLOCK_UART, + .initial_baud = VERSAL_UART_DEFAULT_BAUD + } }, { - .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "Versal UART 1" ), - .regs = (volatile struct versal_uart *) 0xff010000, - .irq = VERSAL_IRQ_UART_1 + .pl011_ctx = { + .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("Versal UART 1"), + .regs = (arm_pl011_uart *) 0xff010000, + .irq = VERSAL_IRQ_UART_1, + .clock = VERSAL_CLOCK_UART, + .initial_baud = VERSAL_UART_DEFAULT_BAUD + } } }; @@ -72,7 +81,7 @@ rtems_status_code console_initialize( &uart[0], &versal_uart_handler, NULL, - &versal_uart_instances[i].base + &versal_uart_instances[i].pl011_ctx.base ); if (i == BSP_CONSOLE_MINOR) { @@ -85,21 +94,23 @@ rtems_status_code console_initialize( void versal_debug_console_flush(void) { - versal_uart_reset_tx_flush(&versal_uart_instances[BSP_CONSOLE_MINOR].base); + versal_uart_reset_tx_flush( + &versal_uart_instances[BSP_CONSOLE_MINOR].pl011_ctx.base + ); } static void versal_debug_console_out(char c) { rtems_termios_device_context *base = - &versal_uart_instances[BSP_CONSOLE_MINOR].base; + &versal_uart_instances[BSP_CONSOLE_MINOR].pl011_ctx.base; - versal_uart_write_polled(base, c); + arm_pl011_write_polled(base, c); } static void versal_debug_console_init(void) { rtems_termios_device_context *base = - &versal_uart_instances[BSP_CONSOLE_MINOR].base; + &versal_uart_instances[BSP_CONSOLE_MINOR].pl011_ctx.base; (void) versal_uart_initialize(base); BSP_output_char = versal_debug_console_out; @@ -108,7 +119,7 @@ static void versal_debug_console_init(void) static void versal_debug_console_early_init(char c) { rtems_termios_device_context *base = - &versal_uart_instances[BSP_CONSOLE_MINOR].base; + &versal_uart_instances[BSP_CONSOLE_MINOR].pl011_ctx.base; (void) versal_uart_initialize(base); BSP_output_char = versal_debug_console_out; @@ -118,9 +129,9 @@ static void versal_debug_console_early_init(char c) static int versal_debug_console_in(void) { rtems_termios_device_context *base = - &versal_uart_instances[BSP_CONSOLE_MINOR].base; + &versal_uart_instances[BSP_CONSOLE_MINOR].pl011_ctx.base; - return versal_uart_read_polled(base); + return arm_pl011_read_polled(base); } BSP_output_char_function_type BSP_output_char = versal_debug_console_early_init; diff --git a/bsps/aarch64/xilinx-versal/dev/serial/versal-uart-polled.c b/bsps/aarch64/xilinx-versal/dev/serial/versal-uart-polled.c deleted file mode 100644 index 9453dc248b..0000000000 --- a/bsps/aarch64/xilinx-versal/dev/serial/versal-uart-polled.c +++ /dev/null @@ -1,194 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/* - * Copyright (C) 2021 Gedare Bloom - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include - -#include - -static inline volatile versal_uart *versal_uart_get_regs( - rtems_termios_device_context *base -) -{ - versal_uart_context *ctx = (versal_uart_context *) base; - return ctx->regs; -} - -/* - * Make weak and let the user override. - */ -uint32_t versal_uart_input_clock(void) __attribute__ ((weak)); - -uint32_t versal_uart_input_clock(void) -{ - return VERSAL_CLOCK_UART; -} - -int32_t versal_cal_baud_rate( - uint32_t baudrate, - uint32_t maxerror, - uint32_t *ibdiv, - uint32_t *fbdiv -) -{ - uint32_t calcbaudrate; - uint32_t bauderror; - uint32_t percenterror; - uint32_t fbdivrnd; - uint32_t inputclk = versal_uart_input_clock(); - - /* - * The baud rate cannot be larger than the UART clock / 16. - */ - if ((baudrate * 16) > inputclk) { - return -1; - } - - /* - * The UART clock cannot be larger than 16*65535*baudrate. - * Could maybe use an estimate (inputclk / 2**16) to save a division. - * This invariant gets checked below, by ensuring ibdiv < 2**16. - */ - - /* - * The UART clock cannot be more than 5/3 times faster than the LPD_LSBUS_CLK - * - TODO? - */ - - /* - * The baud rate divisor is a 16-bit integer and 6-bit fractional part. - * It is equal to the UART clock / (16 * baudrate). - */ - *ibdiv = inputclk / 16 / baudrate; - if ( *ibdiv > 1<<16 ) { - return -1; - } - - /* - * Find the fractional part. This can overflow with 32-bit arithmetic if - * inputclk > 536870911, so use 64-bit. Unfortunately, this means we have - * two 64-bit divisions here. - */ - fbdivrnd = ((((uint64_t)inputclk / 16) << 7) / baudrate) & 0x1; - *fbdiv = (((((uint64_t)inputclk / 16) << 6) / baudrate) & 0x3F) + fbdivrnd; - - /* - * calculate the baudrate and check if the error is too large. - */ - calcbaudrate = (((uint64_t)inputclk / 16) << 6) / ((*ibdiv << 6) | *fbdiv); - - if (baudrate > calcbaudrate) { - bauderror = baudrate - calcbaudrate; - } else { - bauderror = calcbaudrate - baudrate; - } - - percenterror = (bauderror * 100) / baudrate; - - if (maxerror < percenterror) { - return -1; - } - - return 0; -} - -int versal_uart_initialize(rtems_termios_device_context *base) -{ - volatile versal_uart *regs = versal_uart_get_regs(base); - uint32_t maxerr = 3; - uint32_t ibauddiv = 0; - uint32_t fbauddiv = 0; - int rv; - - versal_uart_reset_tx_flush(base); - - rv = versal_cal_baud_rate( - VERSAL_UART_DEFAULT_BAUD, - maxerr, - &ibauddiv, - &fbauddiv - ); - - if ( rv < 0 ) { - return rv; - } - - /* Line control: 8-bit word length, no parity, no FIFO, 1 stop bit */ - regs->uartlcr_h = VERSAL_UARTLCR_H_WLEN( VERSAL_UARTLCR_H_WLEN_8 ) - | VERSAL_UARTLCR_H_FEN; - - /* Control: receive, transmit, uart enable, no CTS, no RTS, no loopback */ - regs->uartcr = VERSAL_UARTCR_RXE - | VERSAL_UARTCR_TXE - | VERSAL_UARTCR_UARTEN; - - regs->uartibrd = VERSAL_UARTIBRD_BAUD_DIVINT(ibauddiv); - regs->uartfbrd = VERSAL_UARTFBRD_BAUD_DIVFRAC(fbauddiv); - - return 0; -} - -int versal_uart_read_polled(rtems_termios_device_context *base) -{ - volatile versal_uart *regs = versal_uart_get_regs(base); - - if ((regs->uartfr & VERSAL_UARTFR_RXFE) != 0) { - return -1; - } else { - return VERSAL_UARTDR_DATA_GET(regs->uartdr); - } -} - -void versal_uart_write_polled( - rtems_termios_device_context *base, - char c -) -{ - volatile versal_uart *regs = versal_uart_get_regs(base); - - while ((regs->uartfr & VERSAL_UARTFR_TXFF) != 0) { - /* Wait while full */ - } - - regs->uartdr = VERSAL_UARTDR_DATA(c); -} - -void versal_uart_reset_tx_flush(rtems_termios_device_context *base) -{ - volatile versal_uart *regs = versal_uart_get_regs(base); - int c = 4; - - while (c-- > 0) - versal_uart_write_polled(base, '\r'); - - while ((regs->uartfr & VERSAL_UARTFR_TXFE) == 0) { - /* Wait for empty */ - } - while ((regs->uartfr & VERSAL_UARTFR_BUSY) != 0) { - /* Wait for empty */ - } -} diff --git a/bsps/aarch64/xilinx-versal/dev/serial/versal-uart.c b/bsps/aarch64/xilinx-versal/dev/serial/versal-uart.c index bf469f66b2..63beda4cb2 100644 --- a/bsps/aarch64/xilinx-versal/dev/serial/versal-uart.c +++ b/bsps/aarch64/xilinx-versal/dev/serial/versal-uart.c @@ -26,88 +26,142 @@ */ #include -#include +#include #include #include static uint32_t versal_uart_intr_all(void) { - return VERSAL_UARTI_OEI | - VERSAL_UARTI_BEI | - VERSAL_UARTI_PEI | - VERSAL_UARTI_FEI | - VERSAL_UARTI_RTI | - VERSAL_UARTI_TXI | - VERSAL_UARTI_RXI | - VERSAL_UARTI_DSRMI | - VERSAL_UARTI_DCDMI | - VERSAL_UARTI_CTSMI | - VERSAL_UARTI_RIMI; + return PL011_UARTI_OEI | + PL011_UARTI_BEI | + PL011_UARTI_PEI | + PL011_UARTI_FEI | + PL011_UARTI_RTI | + PL011_UARTI_TXI | + PL011_UARTI_RXI | + PL011_UARTI_DSRMI | + PL011_UARTI_DCDMI | + PL011_UARTI_CTSMI | + PL011_UARTI_RIMI; } -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS -static void versal_uart_intr_clear(volatile versal_uart *regs, uint32_t ints) +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static void versal_uart_intr_clear(volatile arm_pl011_uart *regs, uint32_t ints) { - regs->uarticr = ints; + regs->base.uarticr = ints; } -static void versal_uart_intr_clearall(volatile versal_uart *regs) +static void versal_uart_intr_clearall(volatile arm_pl011_uart *regs) { versal_uart_intr_clear(regs, versal_uart_intr_all()); } -static void versal_uart_intr_enable(volatile versal_uart *regs, uint32_t ints) +static void versal_uart_intr_enable(volatile arm_pl011_uart *regs, uint32_t ints) { - regs->uartimsc |= ints; + regs->base.uartimsc |= ints; } #endif -static void versal_uart_intr_disable(volatile versal_uart *regs, uint32_t ints) +static void versal_uart_intr_disable(volatile arm_pl011_uart *regs, uint32_t ints) { - regs->uartimsc &= ~ints; + regs->base.uartimsc &= ~ints; } -static void versal_uart_intr_disableall(volatile versal_uart *regs) +static void versal_uart_intr_disableall(volatile arm_pl011_uart *regs) { versal_uart_intr_disable(regs, versal_uart_intr_all()); } -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS -static bool versal_uart_flags_clear(volatile versal_uart *regs, uint32_t flags) +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static bool versal_uart_flags_clear(volatile arm_pl011_uart *regs, uint32_t flags) { - return (regs->uartfr & flags) == 0; + return (regs->base.uartfr & flags) == 0; } static void versal_uart_interrupt(void *arg) { rtems_termios_tty *tty = arg; - versal_uart_context *ctx = rtems_termios_get_device_context(tty); - volatile versal_uart *regs = ctx->regs; - uint32_t uartmis = regs->uartmis; + versal_pl011_context *ctx = rtems_termios_get_device_context(tty); + volatile arm_pl011_uart *regs = (volatile arm_pl011_uart *) ctx->pl011_ctx.regs; + uint32_t uartmis = regs->base.uartmis; versal_uart_intr_clear(regs, uartmis); - if ((uartmis & (VERSAL_UARTI_RTI | VERSAL_UARTI_RXI)) != 0) { + if ((uartmis & (PL011_UARTI_RTI | PL011_UARTI_RXI)) != 0) { char buf[32]; int c = 0; while (c < sizeof(buf) && - versal_uart_flags_clear(regs, VERSAL_UARTFR_RXFE)) { - buf[c++] = (char) VERSAL_UARTDR_DATA_GET(regs->uartdr); + versal_uart_flags_clear(regs, PL011_UARTFR_RXFE)) { + buf[c++] = (char) PL011_UARTDR_DATA_GET(regs->base.uartdr); } rtems_termios_enqueue_raw_characters(tty, buf, c); } if (ctx->transmitting) { - int sent = ctx->tx_queued; + int sent = ctx->pl011_ctx.tx_queued_chars; ctx->transmitting = false; - ctx->tx_queued = 0; - versal_uart_intr_disable(regs, VERSAL_UARTI_TXI); + ctx->pl011_ctx.tx_queued_chars = 0; + versal_uart_intr_disable(regs, PL011_UARTI_TXI); rtems_termios_dequeue_characters(tty, sent); } } #endif +void versal_uart_reset_tx_flush(rtems_termios_device_context *base) +{ + volatile arm_pl011_uart *regs = (volatile arm_pl011_uart *) arm_pl011_get_regs(base); + int c = 4; + + while (c-- > 0) { + arm_pl011_write_polled(base, '\r'); + } + + while ((regs->base.uartfr & PL011_UARTFR_TXFE) == 0) { + /* Wait for empty */ + } + while ((regs->base.uartfr & PL011_UARTFR_BUSY) != 0) { + /* Wait for empty */ + } +} + +int versal_uart_initialize(rtems_termios_device_context *base) +{ + volatile pl011_base *regs = (volatile pl011_base *)arm_pl011_get_regs(base); + arm_pl011_context *ctx = (arm_pl011_context *) base; + uint32_t maxerr = 3; + uint32_t ibauddiv = 0; + uint32_t fbauddiv = 0; + int rv; + + versal_uart_reset_tx_flush(base); + + rv = arm_pl011_compute_baudrate_params( + &ibauddiv, + &fbauddiv, + VERSAL_UART_DEFAULT_BAUD, + ctx->clock, + maxerr + ); + if (rv != 0) { + return rv; + } + + /* Line control: 8-bit word length, no parity, no FIFO, 1 stop bit */ + regs->uartlcr_h = PL011_UARTLCR_H_WLEN( PL011_UARTLCR_H_WLEN_8 ) + | PL011_UARTLCR_H_FEN; + + /* Control: receive, transmit, uart enable, no CTS, no RTS, no loopback */ + regs->uartcr = PL011_UARTCR_RXE + | PL011_UARTCR_TXE + | PL011_UARTCR_UARTEN; + + regs->uartibrd = ibauddiv; + regs->uartfbrd = fbauddiv; + + return 0; +} + static bool versal_uart_first_open( rtems_termios_tty *tty, rtems_termios_device_context *base, @@ -115,25 +169,25 @@ static bool versal_uart_first_open( rtems_libio_open_close_args_t *args ) { -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS - versal_uart_context *ctx = (versal_uart_context *) base; - volatile versal_uart *regs = ctx->regs; +#ifdef BSP_CONSOLE_USE_INTERRUPTS + versal_pl011_context *ctx = (versal_pl011_context *) base; + volatile arm_pl011_uart *regs = (volatile arm_pl011_uart *) ctx->pl011_ctx.regs; rtems_status_code sc; ctx->transmitting = false; - ctx->tx_queued = 0; - ctx->first_send = true; + ctx->pl011_ctx.tx_queued_chars = 0; + ctx->pl011_ctx.needs_sw_triggered_tx_irq = true; #endif rtems_termios_set_initial_baud(tty, VERSAL_UART_DEFAULT_BAUD); versal_uart_initialize(base); -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS - regs->uartifls = VERSAL_UARTIFLS_RXIFLSEL(2) | VERSAL_UARTIFLS_TXIFLSEL(2); - regs->uartlcr_h |= VERSAL_UARTLCR_H_FEN; +#ifdef BSP_CONSOLE_USE_INTERRUPTS + regs->base.uartifls = PL011_UARTIFLS_RXIFLSEL(2) | PL011_UARTIFLS_TXIFLSEL(2); + regs->base.uartlcr_h |= PL011_UARTLCR_H_FEN; versal_uart_intr_disableall(regs); sc = rtems_interrupt_handler_install( - ctx->irq, + ctx->pl011_ctx.irq, "UART", RTEMS_INTERRUPT_SHARED, versal_uart_interrupt, @@ -143,21 +197,21 @@ static bool versal_uart_first_open( return false; } versal_uart_intr_clearall(regs); - versal_uart_intr_enable(regs, VERSAL_UARTI_RTI | VERSAL_UARTI_RXI); + versal_uart_intr_enable(regs, PL011_UARTI_RTI | PL011_UARTI_RXI); #endif return true; } -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS +#ifdef BSP_CONSOLE_USE_INTERRUPTS static void versal_uart_last_close( rtems_termios_tty *tty, rtems_termios_device_context *base, rtems_libio_open_close_args_t *args ) { - versal_uart_context *ctx = (versal_uart_context *) base; - rtems_interrupt_handler_remove(ctx->irq, versal_uart_interrupt, tty); + versal_pl011_context *ctx = (versal_pl011_context *) base; + rtems_interrupt_handler_remove(ctx->pl011_ctx.irq, versal_uart_interrupt, tty); } #endif @@ -167,37 +221,37 @@ static void versal_uart_write_support( size_t len ) { -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS - versal_uart_context *ctx = (versal_uart_context *) base; - volatile versal_uart *regs = ctx->regs; +#ifdef BSP_CONSOLE_USE_INTERRUPTS + versal_pl011_context *ctx = (versal_pl011_context *) base; + volatile arm_pl011_uart *regs = (volatile arm_pl011_uart *) ctx->pl011_ctx.regs; if (len > 0) { size_t len_remaining = len; const char *p = &buf[0]; - versal_uart_intr_enable(regs, VERSAL_UARTI_TXI); + versal_uart_intr_enable(regs, PL011_UARTI_TXI); /* * The PL011 IP in the Versal needs preloading the TX FIFO with * exactly 17 characters for the first TX interrupt to be * generated. */ - if (ctx->first_send) { - ctx->first_send = false; + if (ctx->pl011_ctx.needs_sw_triggered_tx_irq) { + ctx->pl011_ctx.needs_sw_triggered_tx_irq = false; for (int i = 0; i < 17; ++i) { - regs->uartdr = VERSAL_UARTDR_DATA('\r'); + regs->base.uartdr = PL011_UARTDR_DATA('\r'); } } - while (versal_uart_flags_clear(regs, VERSAL_UARTFR_TXFF) && + while (versal_uart_flags_clear(regs, PL011_UARTFR_TXFF) && len_remaining > 0) { - regs->uartdr = VERSAL_UARTDR_DATA(*p++); + regs->base.uartdr = PL011_UARTDR_DATA(*p++); --len_remaining; } - ctx->tx_queued = len - len_remaining; + ctx->pl011_ctx.tx_queued_chars = len - len_remaining; ctx->transmitting = true; } #else ssize_t i; for (i = 0; i < len; ++i) { - versal_uart_write_polled(base, buf[i]); + arm_pl011_write_polled(base, buf[i]); } #endif } @@ -207,8 +261,8 @@ static bool versal_uart_set_attributes( const struct termios *term ) { - versal_uart_context *ctx = (versal_uart_context *) context; - volatile versal_uart *regs = ctx->regs; + versal_pl011_context *ctx = (versal_pl011_context *) context; + volatile arm_pl011_uart *regs = (volatile arm_pl011_uart *) ctx->pl011_ctx.regs; int32_t baud; uint32_t ibauddiv = 0; uint32_t fbauddiv = 0; @@ -223,11 +277,12 @@ static bool versal_uart_set_attributes( if (baud > 0) { uint32_t maxerr = 3; - rc = versal_cal_baud_rate( - VERSAL_UART_DEFAULT_BAUD, - maxerr, - &ibauddiv, - &fbauddiv + rc = arm_pl011_compute_baudrate_params( + &ibauddiv, + &fbauddiv, + baud, + ctx->pl011_ctx.clock, + maxerr ); if (rc != 0) { return rc; @@ -237,15 +292,15 @@ static bool versal_uart_set_attributes( /* * Configure the mode register */ - mode = regs->uartlcr_h & VERSAL_UARTLCR_H_FEN; + mode = regs->base.uartlcr_h & PL011_UARTLCR_H_FEN; /* * Parity */ if ((term->c_cflag & PARENB) != 0) { - mode |= VERSAL_UARTLCR_H_PEN; + mode |= PL011_UARTLCR_H_PEN; if ((term->c_cflag & PARODD) == 0) { - mode |= VERSAL_UARTLCR_H_EPS; + mode |= PL011_UARTLCR_H_EPS; } } @@ -255,17 +310,17 @@ static bool versal_uart_set_attributes( switch (term->c_cflag & CSIZE) { case CS5: - mode = VERSAL_UARTLCR_H_WLEN_SET(mode, VERSAL_UARTLCR_H_WLEN_5); + mode = PL011_UARTLCR_H_WLEN_SET(mode, PL011_UARTLCR_H_WLEN_5); break; case CS6: - mode = VERSAL_UARTLCR_H_WLEN_SET(mode, VERSAL_UARTLCR_H_WLEN_6); + mode = PL011_UARTLCR_H_WLEN_SET(mode, PL011_UARTLCR_H_WLEN_6); break; case CS7: - mode = VERSAL_UARTLCR_H_WLEN_SET(mode, VERSAL_UARTLCR_H_WLEN_7); + mode = PL011_UARTLCR_H_WLEN_SET(mode, PL011_UARTLCR_H_WLEN_7); break; case CS8: default: - mode = VERSAL_UARTLCR_H_WLEN_SET(mode, VERSAL_UARTLCR_H_WLEN_8); + mode = PL011_UARTLCR_H_WLEN_SET(mode, PL011_UARTLCR_H_WLEN_8); break; } @@ -274,7 +329,7 @@ static bool versal_uart_set_attributes( */ if (term->c_cflag & CSTOPB) { /* 2 stop bits */ - mode |= VERSAL_UARTLCR_H_STP2; + mode |= PL011_UARTLCR_H_STP2; } versal_uart_intr_disableall(regs); @@ -283,27 +338,27 @@ static bool versal_uart_set_attributes( * Wait for any data in the TXFIFO to be sent then wait while the * transmiter is active. */ - while ((regs->uartfr & VERSAL_UARTFR_TXFE) == 0 || - (regs->uartfr & VERSAL_UARTFR_BUSY) != 0) { + while ((regs->base.uartfr & PL011_UARTFR_TXFE) == 0 || + (regs->base.uartfr & PL011_UARTFR_BUSY) != 0) { /* Wait */ } - regs->uartcr = VERSAL_UARTCR_UARTEN; + regs->base.uartcr = PL011_UARTCR_UARTEN; /* Ignore baud rate of B0. There are no modem control lines to de-assert */ if (baud > 0) { - regs->uartibrd = VERSAL_UARTIBRD_BAUD_DIVINT(ibauddiv); - regs->uartfbrd = VERSAL_UARTFBRD_BAUD_DIVFRAC(fbauddiv); + regs->base.uartibrd = ibauddiv; + regs->base.uartfbrd = fbauddiv; } - regs->uartlcr_h = mode; + regs->base.uartlcr_h = mode; /* Control: receive, transmit, uart enable, no CTS, no RTS, no loopback */ - regs->uartcr = VERSAL_UARTCR_RXE - | VERSAL_UARTCR_TXE - | VERSAL_UARTCR_UARTEN; + regs->base.uartcr = PL011_UARTCR_RXE + | PL011_UARTCR_TXE + | PL011_UARTCR_UARTEN; -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS +#ifdef BSP_CONSOLE_USE_INTERRUPTS versal_uart_intr_clearall(regs); - versal_uart_intr_enable(regs, VERSAL_UARTI_RTI | VERSAL_UARTI_RXI); + versal_uart_intr_enable(regs, PL011_UARTI_RTI | PL011_UARTI_RXI); #endif return true; @@ -313,11 +368,11 @@ const rtems_termios_device_handler versal_uart_handler = { .first_open = versal_uart_first_open, .set_attributes = versal_uart_set_attributes, .write = versal_uart_write_support, -#ifdef VERSAL_CONSOLE_USE_INTERRUPTS +#ifdef BSP_CONSOLE_USE_INTERRUPTS .last_close = versal_uart_last_close, .mode = TERMIOS_IRQ_DRIVEN #else - .poll_read = versal_uart_read_polled, + .poll_read = arm_pl011_read_polled, .mode = TERMIOS_POLLED #endif }; diff --git a/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart-regs.h b/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart-regs.h deleted file mode 100644 index 30f918bc60..0000000000 --- a/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart-regs.h +++ /dev/null @@ -1,140 +0,0 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - -/** - * @file - * - * @ingroup versal_uart_regs - * - * @brief Xilinx Versal UART register definitions. - * - */ - -/* - * Copyright (C) 2021 Gedare Bloom - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -/** - * @defgroup versal_uart_regs Xilinx Versal UART Register Definitions - * @ingroup versal - * @brief Xilinx Versal UART Register Definitions - * @{ - */ - -#ifndef LIBBSP_ARM_XILINX_VERSAL_UART_REGS_H -#define LIBBSP_ARM_XILINX_VERSAL_UART_REGS_H - -#include - -#define VERSAL_UART_FIFO_DEPTH 64 - -typedef struct versal_uart { - uint32_t uartdr; -#define VERSAL_UARTDR_OE BSP_BIT32(11) -#define VERSAL_UARTDR_BE BSP_BIT32(10) -#define VERSAL_UARTDR_PE BSP_BIT32(9) -#define VERSAL_UARTDR_FE BSP_BIT32(8) -#define VERSAL_UARTDR_DATA(val) BSP_FLD32(val, 0, 7) -#define VERSAL_UARTDR_DATA_GET(reg) BSP_FLD32GET(reg, 0, 7) -#define VERSAL_UARTDR_DATA_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) - uint32_t uartrsr_uartecr; -#define VERSAL_UARTRSR_UARTECR_OE BSP_BIT32(3) -#define VERSAL_UARTRSR_UARTECR_BE BSP_BIT32(2) -#define VERSAL_UARTRSR_UARTECR_PE BSP_BIT32(1) -#define VERSAL_UARTRSR_UARTECR_FE BSP_BIT32(0) - uint32_t reserved_08[4]; - uint32_t uartfr; -#define VERSAL_UARTFR_RI BSP_BIT32(8) -#define VERSAL_UARTFR_TXFE BSP_BIT32(7) -#define VERSAL_UARTFR_RXFF BSP_BIT32(6) -#define VERSAL_UARTFR_TXFF BSP_BIT32(5) -#define VERSAL_UARTFR_RXFE BSP_BIT32(4) -#define VERSAL_UARTFR_BUSY BSP_BIT32(3) -#define VERSAL_UARTFR_DCD BSP_BIT32(2) -#define VERSAL_UARTFR_DSR BSP_BIT32(1) -#define VERSAL_UARTFR_CTS BSP_BIT32(0) - uint32_t reserved_1c; - uint32_t uartilpr; -#define VERSAL_UARTILPR_ILPDVSR(val) BSP_FLD32(val, 0, 7) -#define VERSAL_UARTILPR_ILPDVSR_GET(reg) BSP_FLD32GET(reg, 0, 7) -#define VERSAL_UARTILPR_ILPDVSR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) - uint32_t uartibrd; -#define VERSAL_UARTIBRD_BAUD_DIVINT(val) BSP_FLD32(val, 0, 15) -#define VERSAL_UARTIBRD_BAUD_DIVINT_GET(reg) BSP_FLD32GET(reg, 0, 15) -#define VERSAL_UARTIBRD_BAUD_DIVINT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15) - uint32_t uartfbrd; -#define VERSAL_UARTFBRD_BAUD_DIVFRAC(val) BSP_FLD32(val, 0, 5) -#define VERSAL_UARTFBRD_BAUD_DIVFRAC_GET(reg) BSP_FLD32GET(reg, 0, 5) -#define VERSAL_UARTFBRD_BAUD_DIVFRAC_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5) - uint32_t uartlcr_h; -#define VERSAL_UARTLCR_H_SPS BSP_BIT32(7) -#define VERSAL_UARTLCR_H_WLEN(val) BSP_FLD32(val, 5, 6) -#define VERSAL_UARTLCR_H_WLEN_GET(reg) BSP_FLD32GET(reg, 5, 6) -#define VERSAL_UARTLCR_H_WLEN_SET(reg, val) BSP_FLD32SET(reg, val, 5, 6) -#define VERSAL_UARTLCR_H_WLEN_5 0x00U -#define VERSAL_UARTLCR_H_WLEN_6 0x01U -#define VERSAL_UARTLCR_H_WLEN_7 0x02U -#define VERSAL_UARTLCR_H_WLEN_8 0x03U -#define VERSAL_UARTLCR_H_FEN BSP_BIT32(4) -#define VERSAL_UARTLCR_H_STP2 BSP_BIT32(3) -#define VERSAL_UARTLCR_H_EPS BSP_BIT32(2) -#define VERSAL_UARTLCR_H_PEN BSP_BIT32(1) -#define VERSAL_UARTLCR_H_BRK BSP_BIT32(0) - uint32_t uartcr; -#define VERSAL_UARTCR_CTSEN BSP_BIT32(15) -#define VERSAL_UARTCR_RTSEN BSP_BIT32(14) -#define VERSAL_UARTCR_OUT2 BSP_BIT32(13) -#define VERSAL_UARTCR_OUT1 BSP_BIT32(12) -#define VERSAL_UARTCR_RTS BSP_BIT32(11) -#define VERSAL_UARTCR_DTR BSP_BIT32(10) -#define VERSAL_UARTCR_RXE BSP_BIT32(9) -#define VERSAL_UARTCR_TXE BSP_BIT32(8) -#define VERSAL_UARTCR_LBE BSP_BIT32(7) -#define VERSAL_UARTCR_UARTEN BSP_BIT32(0) - uint32_t uartifls; -#define VERSAL_UARTIFLS_RXIFLSEL(val) BSP_FLD32(val, 3, 5) -#define VERSAL_UARTIFLS_RXIFLSEL_GET(reg) BSP_FLD32GET(reg, 3, 5) -#define VERSAL_UARTIFLS_RXIFLSEL_SET(reg, val) BSP_FLD32SET(reg, val, 3, 5) -#define VERSAL_UARTIFLS_TXIFLSEL(val) BSP_FLD32(val, 0, 2) -#define VERSAL_UARTIFLS_TXIFLSEL_GET(reg) BSP_FLD32GET(reg, 0, 2) -#define VERSAL_UARTIFLS_TXIFLSEL_SET(reg, val) BSP_FLD32SET(reg, val, 0, 2) - uint32_t uartimsc; - uint32_t uartris; - uint32_t uartmis; - uint32_t uarticr; -#define VERSAL_UARTI_OEI BSP_BIT32(10) -#define VERSAL_UARTI_BEI BSP_BIT32(9) -#define VERSAL_UARTI_PEI BSP_BIT32(8) -#define VERSAL_UARTI_FEI BSP_BIT32(7) -#define VERSAL_UARTI_RTI BSP_BIT32(6) -#define VERSAL_UARTI_TXI BSP_BIT32(5) -#define VERSAL_UARTI_RXI BSP_BIT32(4) -#define VERSAL_UARTI_DSRMI BSP_BIT32(3) -#define VERSAL_UARTI_DCDMI BSP_BIT32(2) -#define VERSAL_UARTI_CTSMI BSP_BIT32(1) -#define VERSAL_UARTI_RIMI BSP_BIT32(0) -} versal_uart; - -/** @} */ - -#endif /* LIBBSP_ARM_XILINX_ZYNQ_UART_REGS_H */ diff --git a/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart.h b/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart.h index cc6b60b77c..ea6e53851b 100644 --- a/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart.h +++ b/bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart.h @@ -37,6 +37,8 @@ #define LIBBSP_ARM_XILINX_VERSAL_UART_H #include +#include +#include #ifdef __cplusplus extern "C" { @@ -52,13 +54,9 @@ extern "C" { */ typedef struct { - rtems_termios_device_context base; - volatile struct versal_uart *regs; - volatile size_t tx_queued; + arm_pl011_context pl011_ctx; volatile bool transmitting; - bool first_send; - rtems_vector_number irq; -} versal_uart_context; +} versal_pl011_context; extern const rtems_termios_device_handler versal_uart_handler; @@ -66,25 +64,8 @@ extern const rtems_termios_device_handler versal_uart_handler; int versal_uart_initialize(rtems_termios_device_context *base); -int versal_uart_read_polled(rtems_termios_device_context *base); - -void versal_uart_write_polled( - rtems_termios_device_context *base, - char c -); - -/** - * Flush TX FIFO and wait until it is empty. - */ void versal_uart_reset_tx_flush(rtems_termios_device_context *base); -int versal_cal_baud_rate( - uint32_t baudrate, - uint32_t maxerror, - uint32_t* ibdiv, - uint32_t* fbdiv -); - #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bsps/arm/raspberrypi/console/console-config.c b/bsps/arm/raspberrypi/console/console-config.c index 6b8eb80aa4..0af09e1361 100644 --- a/bsps/arm/raspberrypi/console/console-config.c +++ b/bsps/arm/raspberrypi/console/console-config.c @@ -46,7 +46,9 @@ #define MINIUART "/dev/ttyS0" #define FBCONS "/dev/fbcons" -arm_pl011_context pl011_context; +arm_pl011_context pl011_context = { + .clock = 48000000 +}; ns16550_context mini_uart_context; rpi_fb_context fb_context; diff --git a/bsps/arm/realview-pbx-a9/console/console-polled.c b/bsps/arm/realview-pbx-a9/console/console-polled.c index fc848d3d20..1874eba963 100644 --- a/bsps/arm/realview-pbx-a9/console/console-polled.c +++ b/bsps/arm/realview-pbx-a9/console/console-polled.c @@ -28,14 +28,15 @@ #include #include #include - +#include #include arm_pl011_context rvpbx_pl011_context = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), - .regs = (volatile pl011 *) 0x10009000, + .regs = (arm_pl011_uart *) 0x10009000, .irq = RVPBXA9_IRQ_UART_0, - .initial_baud = 115200 + .initial_baud = 115200, + .clock = 24000000 }; static void output_char(char c) diff --git a/bsps/arm/xen/console/console.c b/bsps/arm/xen/console/console.c index 05eceae438..20f187a7e9 100644 --- a/bsps/arm/xen/console/console.c +++ b/bsps/arm/xen/console/console.c @@ -37,9 +37,10 @@ arm_pl011_context xen_vpl011_context = { .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("PL011"), - .regs = (volatile pl011 *) BSP_XEN_VPL011_BASE, + .regs = (arm_pl011_uart *) BSP_XEN_VPL011_BASE, .irq = GUEST_VPL011_SPI, - .initial_baud = 115200 + .initial_baud = 115200, + .clock = 24000000 }; const console_device console_device_table[] = { diff --git a/bsps/include/dev/serial/arm-pl011-regs.h b/bsps/include/dev/serial/arm-pl011-regs.h index 222ec06108..1e4db94efa 100644 --- a/bsps/include/dev/serial/arm-pl011-regs.h +++ b/bsps/include/dev/serial/arm-pl011-regs.h @@ -33,6 +33,13 @@ * POSSIBILITY OF SUCH DAMAGE. */ +/** + * @defgroup ARM PL011 UART Register Definitions + * @ingroup RTEMSBSPsARMShared + * @brief UART Register Definitions + * @{ + */ + #ifndef LIBBSP_ARM_SHARED_ARM_PL011_REGS_H #define LIBBSP_ARM_SHARED_ARM_PL011_REGS_H @@ -69,10 +76,16 @@ typedef struct { #define PL011_UARTILPR_ILPDVSR_GET(reg) BSP_FLD32GET(reg, 0, 7) #define PL011_UARTILPR_ILPDVSR_SET(reg, val) BSP_FLD32SET(reg, val, 0, 7) uint32_t uartibrd; +#define PL011_UARTIBRD_BAUD_DIVINT_WIDTH 16 +#define PL011_UARTIBRD_BAUD_DIVINT_MASK \ + BSP_MSK32(0, PL011_UARTIBRD_BAUD_DIVINT_WIDTH - 1) #define PL011_UARTIBRD_BAUD_DIVINT(val) BSP_FLD32(val, 0, 15) #define PL011_UARTIBRD_BAUD_DIVINT_GET(reg) BSP_FLD32GET(reg, 0, 15) #define PL011_UARTIBRD_BAUD_DIVINT_SET(reg, val) BSP_FLD32SET(reg, val, 0, 15) uint32_t uartfbrd; +#define PL011_UARTFBRD_BAUD_DIVFRAC_WIDTH 6 +#define PL011_UARTFBRD_BAUD_DIVFRAC_MASK \ + BSP_MSK32(0, PL011_UARTFBRD_BAUD_DIVFRAC_WIDTH - 1) #define PL011_UARTFBRD_BAUD_DIVFRAC(val) BSP_FLD32(val, 0, 5) #define PL011_UARTFBRD_BAUD_DIVFRAC_GET(reg) BSP_FLD32GET(reg, 0, 5) #define PL011_UARTFBRD_BAUD_DIVFRAC_SET(reg, val) BSP_FLD32SET(reg, val, 0, 5) @@ -125,19 +138,13 @@ typedef struct { #define PL011_UARTI_DCDMI BSP_BIT32(2) #define PL011_UARTI_CTSMI BSP_BIT32(1) #define PL011_UARTI_RIMI BSP_BIT32(0) +#define PL011_UARTI_MASK BSP_MSK32(0, 10) uint32_t uartdmacr; #define PL011_UARTDMACR_DMAONERR BSP_BIT32(2) #define PL011_UARTDMACR_TXDMAE BSP_BIT32(1) #define PL011_UARTDMACR_RXDMAE BSP_BIT32(0) - uint32_t reserved_4c[997]; - uint32_t uartperiphid0; - uint32_t uartperiphid1; - uint32_t uartperiphid2; - uint32_t uartperiphid3; - uint32_t uartpcellid0; - uint32_t uartpcellid1; - uint32_t uartpcellid2; - uint32_t uartpcellid3; -} pl011; +} pl011_base; + +/** @} */ #endif /* LIBBSP_ARM_SHARED_ARM_PL011_REGS_H */ diff --git a/bsps/include/dev/serial/arm-pl011.h b/bsps/include/dev/serial/arm-pl011.h index a22fa1ac06..4194a10fdb 100644 --- a/bsps/include/dev/serial/arm-pl011.h +++ b/bsps/include/dev/serial/arm-pl011.h @@ -39,24 +39,126 @@ #include #include - +#include #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ +/** + * @defgroup ARM PL011 Support + * @ingroup RTEMSBSPsARMShared + * @brief UART Support + */ + +typedef struct { + pl011_base base; + uint32_t reserved_4c[997]; + uint32_t uartperiphid0; + uint32_t uartperiphid1; + uint32_t uartperiphid2; + uint32_t uartperiphid3; + uint32_t uartpcellid0; + uint32_t uartpcellid1; + uint32_t uartpcellid2; + uint32_t uartpcellid3; +} arm_pl011_uart; + typedef struct { rtems_termios_device_context base; - volatile pl011 *regs; + volatile arm_pl011_uart *regs; rtems_vector_number irq; uint32_t initial_baud; + uint32_t clock; + +#ifdef BSP_CONSOLE_USE_INTERRUPTS + /* + * Due to HW limitation, the first TX interrupt should be triggered by the + * software. This is because TX interrupts are based on transition through + * a level, rather than on the level itself. When the UART interrupt and + * UART is enabled before any data is written to the TXFIFO, the interrupt + * is not set. The interrupt is only set once the TXFIFO becomes empty + * after being filled to the trigger level. Until then, this flag variable + * ensures that the interrupt handler is software triggered. + */ + bool needs_sw_triggered_tx_irq; + + int tx_queued_chars; + rtems_termios_tty* tty; +#endif } arm_pl011_context; -bool arm_pl011_probe(rtems_termios_device_context *base); +#ifdef BSP_CONSOLE_USE_INTERRUPTS -void arm_pl011_write_polled(rtems_termios_device_context *base, char c); +#define FIFO_LEVEL_ONE_EIGHTH 0 +#define FIFO_LEVEL_ONE_FOURTH 1 +#define FIFO_LEVEL_ONE_HALF 2 +#define FIFO_LEVEL_THREE_FOURTH 3 +#define FIFO_LELEL_SEVEN_HALF 4 + +#define TXFIFO_IRQ_TRIGGER_LEVEL FIFO_LEVEL_ONE_EIGHTH +#define RXFIFO_IRQ_TRIGGER_LEVEL FIFO_LEVEL_ONE_HALF + +#endif extern const rtems_termios_device_handler arm_pl011_fns; +/** + * @brief Initialize pl011 registers. + * + * @param base Termios device context. + * + * @retval true Successfully initialized pl011 registers. + */ +bool arm_pl011_probe(rtems_termios_device_context *base); + +/** + * @brief Write a char using polling mode. + * + * @param base Termios device context. + * @param c Character to be written. + */ +void arm_pl011_write_polled(rtems_termios_device_context *base, char c); + +/** + * @brief Read a char using polling mode. + * + * @param base Termios device context. + * + * @retval Character read. + * @retval -1 rxfifo is empty. + */ +int arm_pl011_read_polled(rtems_termios_device_context *base); + +/** + * @brief Get register base address. + * + * @param base Termios device context. + * + * @retval Register base address. + */ +volatile arm_pl011_uart *arm_pl011_get_regs(rtems_termios_device_context *base); + +/** + * @brief Compute baudrate params. + * + * @param ibrd The integer part of the baud rate divisor value. + * @param fbrd The fractional part of the baud rate divisor value. + * @param baudrate Termios device context. + * @param clock The UART reference clock frequency. + * @param max_error Maximum error. + * + * @retval 0 Success. + * @retval 1 The error is too large. + * @retval 2 ibrd is invalid. + */ +int arm_pl011_compute_baudrate_params( + uint32_t *ibrd, + uint32_t *fbrd, + const uint32_t baudrate, + const uint32_t clock, + const unsigned short max_error +); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/bsps/shared/dev/serial/arm-pl011.c b/bsps/shared/dev/serial/arm-pl011.c index e9a8e3f5a4..35811c696f 100644 --- a/bsps/shared/dev/serial/arm-pl011.c +++ b/bsps/shared/dev/serial/arm-pl011.c @@ -26,64 +26,473 @@ */ #include +#include -static volatile pl011 *pl011_get_regs(rtems_termios_device_context *base) +static inline int arm_pl011_read_char(volatile pl011_base *regs_base) { - arm_pl011_context *ctx = (arm_pl011_context *) base; - - return ctx->regs; + return PL011_UARTDR_DATA_GET(regs_base->uartdr); } +static inline void arm_pl011_write_char( + volatile pl011_base *regs_base, + const char ch +) +{ + regs_base->uartdr = PL011_UARTDR_DATA_SET(regs_base->uartdr, ch); +} + +static inline bool arm_pl011_is_rxfifo_empty(volatile pl011_base *regs_base) +{ + return (regs_base->uartfr & PL011_UARTFR_RXFE) != 0; +} + +static inline bool arm_pl011_is_txfifo_full(volatile pl011_base *regs_base) +{ + return (regs_base->uartfr & PL011_UARTFR_TXFF) != 0; +} + +volatile arm_pl011_uart *arm_pl011_get_regs(rtems_termios_device_context *base) +{ + return ((arm_pl011_context *)base)->regs; +} bool arm_pl011_probe(rtems_termios_device_context *base) { - volatile pl011 *regs = pl011_get_regs(base); + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); - regs->uartlcr_h = PL011_UARTLCR_H_WLEN(PL011_UARTLCR_H_WLEN_8); - regs->uartcr = PL011_UARTCR_RXE + regs->base.uartlcr_h = PL011_UARTLCR_H_WLEN(PL011_UARTLCR_H_WLEN_8); + regs->base.uartcr = PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN; return true; } -static bool pl011_first_open( +static void arm_pl011_flush_fifos(const arm_pl011_context *context) +{ + volatile pl011_base *regs = (volatile pl011_base *) context->regs; + + regs->uartlcr_h &= ~PL011_UARTLCR_H_FEN; + regs->uartlcr_h |= PL011_UARTLCR_H_FEN; +} + +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static inline void arm_pl011_clear_irq( + volatile pl011_base *regs_base, + const uint32_t irq_mask +) +{ + /* ICR is a write-only register */ + regs_base->uarticr = irq_mask; +} + +static inline void arm_pl011_enable_irq( + volatile pl011_base *regs_base, + const uint32_t irq_mask +) +{ + regs_base->uartimsc |= irq_mask; +} +#endif + +static inline void arm_pl011_disable_irq( + volatile pl011_base *regs_base, + uint32_t irq_mask +) +{ + regs_base->uartimsc &= ~irq_mask; +} + +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static void arm_pl011_irq_handler(void *arg) +{ + arm_pl011_context *context = (void *) arg; + volatile arm_pl011_uart *regs = + arm_pl011_get_regs((rtems_termios_device_context *) context); + const uint32_t irqs = regs->base.uartmis; + char buffer[ARM_PL011_FIFO_DEPTH]; + /* RXFIFO got data */ + uint32_t rx_irq_mask = PL011_UARTI_RTI | PL011_UARTI_RXI; + if ((irqs & rx_irq_mask) != 0) { + arm_pl011_clear_irq(®s->base, rx_irq_mask); + + unsigned int i = 0; + while (i < sizeof(buffer) && !arm_pl011_is_rxfifo_empty(®s->base)) { + buffer[i] = arm_pl011_read_char(®s->base); + i++; + } + + (void) rtems_termios_enqueue_raw_characters(context->tty, buffer, i); + } + + /* + * Some characters got queued in the TXFIFO, so dequeue them from Termios' + * structures. + */ + if ((irqs & PL011_UARTI_TXI) != 0) { + /* + * First interrupt was raised, so no need to trigger the handler + * through software anymore. + */ + if (context->needs_sw_triggered_tx_irq == true) { + context->needs_sw_triggered_tx_irq = false; + } + + (void) rtems_termios_dequeue_characters(context->tty, + context->tx_queued_chars); + + /* + * Explicitly clear the transmit interrupt. This is necessary + * because there may not be enough bytes in the output buffer to + * fill the FIFO greater than the transmit interrupt trigger level. + * If FIFOs are disabled, this applies if there are 0 bytes to + * transmit and therefore nothing to fill the Tx holding register + * with. + */ + arm_pl011_clear_irq(®s->base, PL011_UARTI_TXI); + } +} + +static bool arm_pl011_first_open_irq( + rtems_termios_device_context *base, + arm_pl011_context *context +) +{ + rtems_status_code sc; + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); + /* Set FIFO trigger levels for interrupts */ + regs->base.uartifls = + PL011_UARTIFLS_TXIFLSEL_SET(regs->base.uartifls, TXFIFO_IRQ_TRIGGER_LEVEL); + regs->base.uartifls = + PL011_UARTIFLS_RXIFLSEL_SET(regs->base.uartifls, RXFIFO_IRQ_TRIGGER_LEVEL); + regs->base.uartlcr_h |= PL011_UARTLCR_H_FEN; + arm_pl011_disable_irq(®s->base, PL011_UARTI_MASK); + sc = rtems_interrupt_handler_install( + context->irq, + "UART", + RTEMS_INTERRUPT_SHARED, + arm_pl011_irq_handler, + context + ); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } + + /* Clear all interrupts */ + arm_pl011_clear_irq(®s->base, PL011_UARTI_MASK); + arm_pl011_enable_irq(®s->base, PL011_UARTI_RTI | PL011_UARTI_RXI); + return RTEMS_SUCCESSFUL; +} +#endif + +int arm_pl011_compute_baudrate_params( + uint32_t *ibrd, + uint32_t *fbrd, + const uint32_t baudrate, + const uint32_t clock, + const unsigned short max_error +) +{ + uint16_t scalar; + uint32_t computed_bauddiv, computed_baudrate, baud_error; + uint64_t scaled_bauddiv; + unsigned short round_off, percent_error; + /* + * The integer baudrate divisor, i.e. (clock / (baudrate * 16)), value + * should lie on [1, 2^16 - 1]. To ensure this, clock and baudrate have to + * be validated. + */ + *ibrd = clock / 16 / baudrate; + if (*ibrd < 1 || *ibrd > PL011_UARTIBRD_BAUD_DIVINT_MASK) { + return 2; + } + + /* Find the fractional part */ + scalar = 1 << (PL011_UARTFBRD_BAUD_DIVFRAC_WIDTH + 1); + scaled_bauddiv = + ((uint64_t) clock * scalar) / 16 / baudrate; + round_off = scaled_bauddiv & 0x1; + *fbrd = + ((scaled_bauddiv >> 1) & PL011_UARTFBRD_BAUD_DIVFRAC_MASK) + round_off; + + /* Calculate the baudrate and check if the error is too large */ + computed_bauddiv = + (*ibrd << PL011_UARTFBRD_BAUD_DIVFRAC_WIDTH) | *fbrd; + computed_baudrate = + ((uint64_t) clock << PL011_UARTFBRD_BAUD_DIVFRAC_WIDTH) + / 16 / computed_bauddiv; + + baud_error = computed_baudrate - baudrate; + if (baudrate > computed_baudrate) { + baud_error = baudrate - computed_baudrate; + } + + percent_error = (baud_error * 100) / baudrate; + if (percent_error >= max_error) { + return 1; + } + + return 0; +} + +static uint32_t arm_pl011_set_lcrh(const struct termios *term) +{ + /* enable FIFO */ + uint32_t lcrh = PL011_UARTLCR_H_FEN; + + /* Mode: parity */ + if ((term->c_cflag & PARENB) != 0) { + lcrh |= PL011_UARTLCR_H_PEN; + if ((term->c_cflag & PARODD) == 0) { + lcrh |= PL011_UARTLCR_H_EPS; + } + } + + /* Mode: character size */ + switch (term->c_cflag & CSIZE) { + case CS5: + lcrh |= PL011_UARTLCR_H_WLEN_SET(lcrh, PL011_UARTLCR_H_WLEN_5); + break; + case CS6: + lcrh |= PL011_UARTLCR_H_WLEN_SET(lcrh, PL011_UARTLCR_H_WLEN_6); + break; + case CS7: + lcrh |= PL011_UARTLCR_H_WLEN_SET(lcrh, PL011_UARTLCR_H_WLEN_7); + break; + case CS8: + default: + lcrh |= PL011_UARTLCR_H_WLEN_SET(lcrh, PL011_UARTLCR_H_WLEN_8); + } + + /* Mode: stop bits */ + if ((term->c_cflag & CSTOPB) != 0) { + /* 2 stop bits */ + lcrh |= PL011_UARTLCR_H_STP2; + } + return lcrh; +} + +static uint32_t arm_pl011_set_cr(const struct termios *term, volatile pl011_base *regs) +{ + uint32_t cr = regs->uartcr; + /* + * Control: Configure flow control + * NOTE: Flow control is untested + */ + cr &= ~(PL011_UARTCR_CTSEN | PL011_UARTCR_RTSEN); + if ((term->c_cflag & CCTS_OFLOW) != 0) { + cr |= PL011_UARTCR_CTSEN; + } + if ((term->c_cflag & CRTS_IFLOW) != 0) { + cr |= PL011_UARTCR_RTSEN; + } + + /* Control: Configure receiver */ + if ((term->c_cflag & CREAD) != 0) { + cr |= PL011_UARTCR_RXE; + } + + /* Control: Re-enable UART */ + cr |= PL011_UARTCR_UARTEN | PL011_UARTCR_TXE; + + return cr; +} + +static bool arm_pl011_set_attributes( + rtems_termios_device_context *base, + const struct termios *term +) +{ + uint32_t ibrd, fbrd, lcrh, baud, cr; + int err; + arm_pl011_context *context = (arm_pl011_context *) base; + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); + + /* Determine baudrate parameters */ + baud = rtems_termios_number_to_baud(term->c_ospeed); + if (baud == B0) { + return false; + } + + err = arm_pl011_compute_baudrate_params(&ibrd,&fbrd,baud,context->clock,3); + if (err != 0) { + return false; + } + + lcrh = arm_pl011_set_lcrh(term); + + /* Disable all interrupts */ + arm_pl011_disable_irq(®s->base, PL011_UARTI_MASK); + + /* + * Wait for any data in the TXFIFO to be sent then wait while the + * transmiter is active. + */ + while ( + (regs->base.uartfr & PL011_UARTFR_TXFE) == 0 || + (regs->base.uartfr & PL011_UARTFR_BUSY) != 0 + ) { + /* Wait */ + } + + regs->base.uartcr = PL011_UARTCR_UARTEN; + + /* Set the baudrate */ + regs->base.uartibrd = ibrd; + regs->base.uartfbrd = fbrd; + + /* + * Commit mode configurations + * NOTE: + * This has to happen after IBRD and FBRD as writing to LCRH is + * required to trigger the baudrate update. + */ + regs->base.uartlcr_h = lcrh; + + /* Control: Disable UART */ + regs->base.uartcr &= + ~(PL011_UARTCR_UARTEN | PL011_UARTCR_RXE | PL011_UARTCR_TXE); + cr = arm_pl011_set_cr(term, ®s->base); + arm_pl011_flush_fifos(context); + /* Commit changes to control register */ + regs->base.uartcr = cr; + +#ifdef BSP_CONSOLE_USE_INTERRUPTS + /* Clear all interrupts */ + arm_pl011_clear_irq(®s->base, PL011_UARTI_MASK); + + /* Re-enable RX interrupts */ + if ((term->c_cflag & CREAD) != 0) { + arm_pl011_enable_irq(®s->base, PL011_UARTI_RTI | PL011_UARTI_RXI); + } + + /* + * UART is freshly enabled, TXFIFO is empty, and interrupt will be enabled, + * so the next transmission will required software-trigger interrupt. + */ + context->needs_sw_triggered_tx_irq = true; +#endif + return true; +} + +static bool arm_pl011_first_open( struct rtems_termios_tty *tty, rtems_termios_device_context *base, struct termios *term, rtems_libio_open_close_args_t *args ) { - arm_pl011_context *ctx = (arm_pl011_context *) base; + arm_pl011_context *context = (arm_pl011_context *) base; +#ifdef BSP_CONSOLE_USE_INTERRUPTS + rtems_status_code sc; - rtems_termios_set_initial_baud(tty, ctx->initial_baud); + context->tty = tty; +#endif + if (rtems_termios_set_initial_baud(tty, context->initial_baud) != 0) { + return false; + } + + if (!arm_pl011_set_attributes(base, term)) { + return false; + } + +#ifdef BSP_CONSOLE_USE_INTERRUPTS + sc = arm_pl011_first_open_irq(base, context); + if (sc != RTEMS_SUCCESSFUL) { + return false; + } +#endif + return true; } -static int pl011_read_polled(rtems_termios_device_context *base) +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static void arm_pl011_last_close( + rtems_termios_tty *tty, + rtems_termios_device_context *base, + rtems_libio_open_close_args_t *args +) { - volatile pl011 *regs = pl011_get_regs(base); + const arm_pl011_context *context = (void *) base; + (void) rtems_interrupt_handler_remove( + context->irq, + arm_pl011_irq_handler, + tty + ); +} +#endif - if ((regs->uartfr & PL011_UARTFR_RXFE) != 0) { +int arm_pl011_read_polled(rtems_termios_device_context *base) +{ + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); + + if (arm_pl011_is_rxfifo_empty(®s->base)) { return -1; } else { - return PL011_UARTDR_DATA_GET(regs->uartdr); + return arm_pl011_read_char(®s->base); } } void arm_pl011_write_polled(rtems_termios_device_context *base, char c) { - volatile pl011 *regs = pl011_get_regs(base); + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); - while ((regs->uartfr & PL011_UARTFR_TXFF) != 0) { + /* Wait until TXFIFO has space */ + while (arm_pl011_is_txfifo_full(®s->base)) { /* Wait */ } - regs->uartdr = PL011_UARTDR_DATA(c); + arm_pl011_write_char(®s->base, c); } -static void pl011_write_support_polled( +#ifdef BSP_CONSOLE_USE_INTERRUPTS +static void arm_pl011_write_support_interrupt( + rtems_termios_device_context *base, + const char *buffer, + size_t buffer_len +) +{ + arm_pl011_context *context = (arm_pl011_context *) base; + volatile arm_pl011_uart *regs = arm_pl011_get_regs(base); + size_t i = 0; + + if (buffer_len > 0) { + arm_pl011_enable_irq(®s->base, PL011_UARTI_TXI); + /* + * When arm_pl011_write_support_interrupt writes the first character, + * if txfifo is full, it will return directly. This will cause this + * character to be lost. If txfifo is full, wait for it to be not full. + */ + while (arm_pl011_is_txfifo_full(®s->base)) { + /* wait for txfifo not full */ + } + while (!arm_pl011_is_txfifo_full(®s->base) && i < buffer_len) { + arm_pl011_write_char(®s->base, buffer[i]); + i++; + } + context->tx_queued_chars = i; + + if (context->needs_sw_triggered_tx_irq) { + /* + * The first write may not trigger the TX interrupt due to insufficient + * characters being written. Call rtems_termios_dequeue_characters() to + * continue writing. + */ + (void) rtems_termios_dequeue_characters(context->tty, + context->tx_queued_chars); + } + } else { + /* + * Termios will set n to zero to indicate that the transmitter is now + * inactive. The output buffer is empty in this case. The driver may + * disable the transmit interrupts now. + */ + arm_pl011_disable_irq(®s->base, PL011_UARTI_TXI); + } +} +#else +static void arm_pl011_write_support_polled( rtems_termios_device_context *base, const char *s, size_t n @@ -95,10 +504,33 @@ static void pl011_write_support_polled( arm_pl011_write_polled(base, s[i]); } } +#endif + +static void arm_pl011_write_buffer( + rtems_termios_device_context *base, + const char *buffer, + size_t n +) +{ +#ifdef BSP_CONSOLE_USE_INTERRUPTS + arm_pl011_write_support_interrupt(base, buffer, n); +#else + arm_pl011_write_support_polled(base, buffer, n); +#endif +} const rtems_termios_device_handler arm_pl011_fns = { - .first_open = pl011_first_open, - .poll_read = pl011_read_polled, - .write = pl011_write_support_polled, - .mode = TERMIOS_POLLED -}; + .first_open = arm_pl011_first_open, + .write = arm_pl011_write_buffer, + .set_attributes = arm_pl011_set_attributes, + .ioctl = NULL, +#ifdef BSP_CONSOLE_USE_INTERRUPTS + .last_close = arm_pl011_last_close, + .poll_read = NULL, + .mode = TERMIOS_IRQ_DRIVEN, +#else + .last_close = NULL, + .poll_read = arm_pl011_read_polled, + .mode = TERMIOS_POLLED, +#endif +}; \ No newline at end of file diff --git a/spec/build/bsps/aarch64/raspberrypi/bspraspberrypi4.yml b/spec/build/bsps/aarch64/raspberrypi/bspraspberrypi4.yml index db3579bad2..052aa3e7a8 100644 --- a/spec/build/bsps/aarch64/raspberrypi/bspraspberrypi4.yml +++ b/spec/build/bsps/aarch64/raspberrypi/bspraspberrypi4.yml @@ -39,6 +39,10 @@ links: uid: ../optgtuseps - role: build-dependency uid: abi +- role: build-dependency + uid: ../../optconsolefifo +- role: build-dependency + uid: ../../optconsoleirq - role: build-dependency uid: ../../optcachedata - role: build-dependency diff --git a/spec/build/bsps/aarch64/xilinx-versal/grp.yml b/spec/build/bsps/aarch64/xilinx-versal/grp.yml index 6abb54bc63..b61a475f60 100644 --- a/spec/build/bsps/aarch64/xilinx-versal/grp.yml +++ b/spec/build/bsps/aarch64/xilinx-versal/grp.yml @@ -25,7 +25,9 @@ links: - role: build-dependency uid: obj - role: build-dependency - uid: optconirq + uid: ../../optconsolefifo +- role: build-dependency + uid: ../../optconsoleirq - role: build-dependency uid: optloadoff - role: build-dependency diff --git a/spec/build/bsps/aarch64/xilinx-versal/obj.yml b/spec/build/bsps/aarch64/xilinx-versal/obj.yml index 8c477988f1..f74e6b51d9 100644 --- a/spec/build/bsps/aarch64/xilinx-versal/obj.yml +++ b/spec/build/bsps/aarch64/xilinx-versal/obj.yml @@ -17,14 +17,14 @@ install: - bsps/aarch64/include/bsp/aarch64-mmu.h - destination: ${BSP_INCLUDEDIR}/dev/serial source: - - bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart-regs.h + - bsps/include/dev/serial/arm-pl011.h - bsps/aarch64/xilinx-versal/include/dev/serial/versal-uart.h links: [] source: - bsps/aarch64/shared/cache/cache.c - bsps/aarch64/shared/mmu/vmsav8-64.c +- bsps/shared/dev/serial/arm-pl011.c - bsps/aarch64/xilinx-versal/console/console.c -- bsps/aarch64/xilinx-versal/dev/serial/versal-uart-polled.c - bsps/aarch64/xilinx-versal/dev/serial/versal-uart.c - bsps/aarch64/xilinx-versal/start/bspstart.c - bsps/aarch64/xilinx-versal/start/bspstarthooks.c diff --git a/spec/build/bsps/aarch64/xilinx-versal/optconirq.yml b/spec/build/bsps/aarch64/xilinx-versal/optconirq.yml deleted file mode 100644 index 00c5dbaebd..0000000000 --- a/spec/build/bsps/aarch64/xilinx-versal/optconirq.yml +++ /dev/null @@ -1,16 +0,0 @@ -SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause -actions: -- get-boolean: null -- define-condition: null -build-type: option -copyrights: -- Copyright (C) 2022 Chris Johns (chris@contemporary.software) -default: -- enabled-by: true - value: true -description: | - use interrupt driven mode for console devices (used by default) -enabled-by: true -links: [] -name: VERSAL_CONSOLE_USE_INTERRUPTS -type: build diff --git a/spec/build/bsps/optconsolefifo.yml b/spec/build/bsps/optconsolefifo.yml new file mode 100644 index 0000000000..9dcaa1e51c --- /dev/null +++ b/spec/build/bsps/optconsolefifo.yml @@ -0,0 +1,25 @@ +SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause +actions: +- get-integer: null +- assert-uint64: null +- env-assign: null +- format-and-define: null +build-type: option +copyrights: +- Copyright (C) 2024 Ning Yang +default: +- enabled-by: + - aarch64/xilinx_versal_aiedge + - aarch64/xilinx_versal_qemu + - aarch64/xilinx_versal_vck190 + value: 64 +- enabled-by: + - aarch64/raspberrypi4b + value: 32 +description: | + Set the size of UART FIFO +enabled-by: true +format: '{:#010x}' +links: [] +name: ARM_PL011_FIFO_DEPTH +type: build