bsps/microblaze: Add support for multiple UARTs

This commit is contained in:
Maldonado, Sergio E. (GSFC-580.0)
2023-02-27 22:44:51 -06:00
committed by Joel Sherrill
parent 1fbfc4eeac
commit c627a13239
9 changed files with 275 additions and 30 deletions

View File

@@ -49,8 +49,10 @@ typedef struct {
rtems_termios_device_context base; rtems_termios_device_context base;
uintptr_t address; uintptr_t address;
uint32_t initial_baud; uint32_t initial_baud;
uint32_t enabled;
#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
bool transmitting; bool transmitting;
uint32_t irq;
#endif #endif
} uart_lite_context; } uart_lite_context;

View File

@@ -34,39 +34,200 @@
* POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
*/ */
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/param.h>
#include <bsp/console-termios.h> #include <bsp/console-termios.h>
#include <bsp/microblaze-fdt-support.h> #include <bsp/fatal.h>
#include <bspopts.h>
#include <dev/serial/uartlite.h> #include <dev/serial/uartlite.h>
#include <bspopts.h> #ifdef BSP_MICROBLAZE_FPGA_USE_FDT
#include <bsp/fdt.h>
#include <libfdt.h>
#endif
uart_lite_context microblaze_qemu_uart_context = { #include <rtems/console.h>
.base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "UARTLITE" ),
.initial_baud = 115200 #ifndef BSP_MICROBLAZE_FPGA_USE_FDT
static uart_lite_context uart_lite_instances[] = {
{
.base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "UARTLITE" ),
.initial_baud = 115200,
.address = BSP_MICROBLAZE_FPGA_UART_BASE,
#if BSP_MICROBLAZE_FPGA_USE_UART
.enabled = 1,
#endif
#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
.irq = BSP_MICROBLAZE_FPGA_UART_IRQ
#endif
}
}; };
static bool fill_uart_base(rtems_termios_device_context *context)
{
uint32_t mblaze_uart_base;
mblaze_uart_base = try_get_prop_from_device_tree(
"xlnx,xps-uartlite-1.00.a",
"reg",
BSP_MICROBLAZE_FPGA_UART_BASE
);
microblaze_qemu_uart_context.address = mblaze_uart_base;
return true;
}
const console_device console_device_table[] = { const console_device console_device_table[] = {
{ {
.device_file = "/dev/ttyS0", .device_file = "/dev/ttyS0",
.probe = fill_uart_base,
.handler = &microblaze_uart_fns, .handler = &microblaze_uart_fns,
.context = &microblaze_qemu_uart_context.base .context = &uart_lite_instances[0].base
} }
}; };
const size_t console_device_count = RTEMS_ARRAY_SIZE( console_device_table ); const size_t console_device_count = RTEMS_ARRAY_SIZE( console_device_table );
#else
static uart_lite_context uart_lite_instances[BSP_MICROBLAZE_FPGA_MAX_UARTS];
console_device *dynamic_console_device_table;
size_t dynamic_console_device_count;
/* Override the console_device_table and console_device_count */
#define console_device_table dynamic_console_device_table
#define console_device_count dynamic_console_device_count
#endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
#ifdef BSP_MICROBLAZE_FPGA_USE_FDT
static int microblaze_fpga_get_stdout_node(const void *fdt)
{
int node;
int len;
int offset;
const char *console;
const char *q;
node = fdt_path_offset( fdt, "/chosen" );
if ( node < 0 ) {
return 0;
}
console = fdt_getprop( fdt, node, "stdout-path", NULL );
if ( console == NULL ) {
return 0;
}
q = strchr(console, ':');
if ( !q ) {
return 0;
}
len = q - console;
/* Get the node specified by stdout-path */
offset = fdt_path_offset_namelen( fdt, console, len );
if (offset < 0) {
return 0;
}
return offset;
}
static void initialize_uart_arrays(uint32_t max_uarts) {
dynamic_console_device_table = calloc(max_uarts, sizeof(console_device));
dynamic_console_device_count = max_uarts;
for (uint32_t i = 0; i < max_uarts; i++) {
rtems_termios_device_context_initialize(&uart_lite_instances[i].base, "UARTLITE");
uart_lite_instances[i].initial_baud = 115200;
dynamic_console_device_table[i].device_file = malloc(11);
snprintf((char *)console_device_table[i].device_file, 11, "/dev/ttyS%u", i);
dynamic_console_device_table[i].handler = &microblaze_uart_fns;
dynamic_console_device_table[i].context = &uart_lite_instances[i].base;
}
}
#endif
rtems_device_driver console_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg
)
{
uint32_t port;
uint32_t stdout_port = BSP_MICROBLAZE_FPGA_CONSOLE_UART;
#ifdef BSP_MICROBLAZE_FPGA_USE_FDT
initialize_uart_arrays(BSP_MICROBLAZE_FPGA_MAX_UARTS);
const char compatible[] = "xlnx,xps-uartlite-1.00.a";
const void *fdt = bsp_fdt_get();
int len;
int stdout_node = microblaze_fpga_get_stdout_node(fdt);
int node = fdt_node_offset_by_compatible( fdt, -1, compatible);
while ( node != -FDT_ERR_NOTFOUND ) {
const uint32_t *prop;
const void *status;
uint32_t disabled = 0;
port = console_device_count;
/* check if node device status has been set to disabled */
status = fdt_getprop( fdt, node, "status", &len );
if ( status != NULL ) {
if ( strncmp( status, "disabled", MIN( 9, len) ) == 0 ) {
disabled = 1;
}
}
if ( !disabled ) {
/* use port number property as the device table index */
prop = fdt_getprop( fdt, node, "port-number", NULL );
if ( prop != NULL ) {
port = fdt32_to_cpu( prop[0] );
}
if ( port < console_device_count ) {
prop = fdt_getprop( fdt, node, "reg", NULL );
if ( prop != NULL ) {
uint32_t address = fdt32_to_cpu( prop[0] );
uart_lite_instances[ port ].address = address;
uart_lite_instances[ port ].enabled = 1;
if ( node == stdout_node ) {
stdout_port = port;
}
}
#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
prop = fdt_getprop( fdt, node, "interrupts", NULL );
if ( prop != NULL ) {
uint32_t irq = fdt32_to_cpu( prop[0] );
uart_lite_instances[ port ].irq = irq;
}
#endif
}
}
node = fdt_node_offset_by_compatible( fdt, node, compatible );
if ( disabled || ( port >= console_device_count ) )
continue;
}
#endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
rtems_termios_initialize();
for ( port = 0; port < console_device_count; port++ ) {
const console_device *ctx = &console_device_table[ port ];
rtems_status_code sc;
if ( !uart_lite_instances[ port ].enabled )
continue;
sc = rtems_termios_device_install(
ctx->device_file,
ctx->handler,
ctx->flow,
ctx->context
);
if ( sc != RTEMS_SUCCESSFUL ) {
bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_0 );
}
if ( port == stdout_port ) {
if ( link( ctx->device_file, CONSOLE_DEVICE_NAME ) != 0 ) {
bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_1 );
}
}
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -71,14 +71,8 @@ static bool uart_first_open(
#ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
XUartLite_EnableIntr( ctx->address ); XUartLite_EnableIntr( ctx->address );
uint32_t uart_irq_num = try_get_prop_from_device_tree(
"xlnx,xps-uartlite-1.00.a",
"interrupts",
1
);
sc = rtems_interrupt_handler_install( sc = rtems_interrupt_handler_install(
uart_irq_num, ctx->irq,
"UART", "UART",
RTEMS_INTERRUPT_SHARED, RTEMS_INTERRUPT_SHARED,
microblaze_uart_interrupt, microblaze_uart_interrupt,

View File

@@ -54,6 +54,8 @@ links:
uid: opticachesize uid: opticachesize
- role: build-dependency - role: build-dependency
uid: optintcbaseaddress uid: optintcbaseaddress
- role: build-dependency
uid: optmaxuarts
- role: build-dependency - role: build-dependency
uid: optramlen uid: optramlen
- role: build-dependency - role: build-dependency
@@ -66,6 +68,14 @@ links:
uid: opttimerfrequency uid: opttimerfrequency
- role: build-dependency - role: build-dependency
uid: optuartlitebaseaddress uid: optuartlitebaseaddress
- role: build-dependency
uid: optuseuart
- role: build-dependency
uid: optuartirq
- role: build-dependency
uid: optuartirq
- role: build-dependency
uid: optconsoleuart
- role: build-dependency - role: build-dependency
uid: optusefdt uid: optusefdt
- role: build-dependency - role: build-dependency

View File

@@ -47,7 +47,6 @@ source:
- bsps/shared/dev/cpucounter/cpucounterfrequency.c - bsps/shared/dev/cpucounter/cpucounterfrequency.c
- bsps/shared/dev/cpucounter/cpucounterread.c - bsps/shared/dev/cpucounter/cpucounterread.c
- bsps/shared/dev/getentropy/getentropy-cpucounter.c - bsps/shared/dev/getentropy/getentropy-cpucounter.c
- bsps/shared/dev/serial/console-termios-init.c
- bsps/shared/dev/serial/console-termios.c - bsps/shared/dev/serial/console-termios.c
- bsps/shared/irq/irq-default-handler.c - bsps/shared/irq/irq-default-handler.c
- bsps/shared/start/bspfatal-default.c - bsps/shared/start/bspfatal-default.c

View File

@@ -0,0 +1,21 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
actions:
actions:
- get-integer: null
- assert-uint32: null
- env-assign: null
- format-and-define: null
build-type: option
copyrights:
- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
default:
- enabled-by: true
value: 0
default-by-variant: []
description: |
default uart console device port number
enabled-by: true
format: '{}'
links: []
name: BSP_MICROBLAZE_FPGA_CONSOLE_UART
type: build

View File

@@ -0,0 +1,21 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
actions:
actions:
- get-integer: null
- assert-uint32: null
- env-assign: null
- format-and-define: null
build-type: option
copyrights:
- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
default:
- enabled-by: true
value: 1
default-by-variant: []
description: |
maximum number of UART devices
enabled-by: true
format: '{}'
links: []
name: BSP_MICROBLAZE_FPGA_MAX_UARTS
type: build

View File

@@ -0,0 +1,20 @@
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
actions:
- get-integer: null
- assert-uint32: null
- env-assign: null
- format-and-define: null
build-type: option
copyrights:
- Copyright (C) 2023 On-Line Applications Research Corporation (OAR)
default:
- enabled-by: true
value: 3
default-by-variant: []
description: |
irq number of the AXI UART Lite
enabled-by: true
format: '{:#010x}'
links: []
name: BSP_MICROBLAZE_FPGA_UART_IRQ
type: build

View File

@@ -0,0 +1,17 @@
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) 2023 On-Line Applications Research Corporation (OAR)
default:
- enabled-by: true
value: true
default-by-variant: []
description: |
define if UART is used
enabled-by: true
links: []
name: BSP_MICROBLAZE_FPGA_USE_UART
type: build