Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:49

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsMicroblaze
0007  *
0008  * @brief MicroBlaze console configuration
0009  */
0010 
0011 /*
0012  * Copyright (C) 2015 Hesham Almatary
0013  * Copyright (C) 2021 On-Line Applications Research Corporation (OAR)
0014  *
0015  * Redistribution and use in source and binary forms, with or without
0016  * modification, are permitted provided that the following conditions
0017  * are met:
0018  * 1. Redistributions of source code must retain the above copyright
0019  *    notice, this list of conditions and the following disclaimer.
0020  * 2. Redistributions in binary form must reproduce the above copyright
0021  *    notice, this list of conditions and the following disclaimer in the
0022  *    documentation and/or other materials provided with the distribution.
0023  *
0024  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0025  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0026  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0027  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0028  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0029  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0030  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0031  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0032  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0033  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0034  * POSSIBILITY OF SUCH DAMAGE.
0035  */
0036 
0037 #include <unistd.h>
0038 #include <string.h>
0039 #include <stdio.h>
0040 
0041 #include <sys/param.h>
0042 #include <bsp/console-termios.h>
0043 #include <bsp/fatal.h>
0044 #include <bspopts.h>
0045 #include <dev/serial/uartlite.h>
0046 
0047 #ifdef BSP_MICROBLAZE_FPGA_USE_FDT
0048 #include <bsp/fdt.h>
0049 #include <libfdt.h>
0050 #endif
0051 
0052 #include <rtems/console.h>
0053 
0054 #ifndef BSP_MICROBLAZE_FPGA_USE_FDT
0055 static uart_lite_context uart_lite_instances[] = {
0056   {
0057     .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "UARTLITE" ),
0058     .initial_baud = 115200,
0059     .address = BSP_MICROBLAZE_FPGA_UART_BASE,
0060 #if BSP_MICROBLAZE_FPGA_USE_UART
0061     .enabled = 1,
0062 #endif
0063 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0064     .irq = BSP_MICROBLAZE_FPGA_UART_IRQ
0065 #endif
0066   }
0067 };
0068 
0069 const console_device console_device_table[] = {
0070   {
0071     .device_file = "/dev/ttyS0",
0072     .handler = &microblaze_uart_fns,
0073     .context = &uart_lite_instances[0].base
0074   }
0075 };
0076 
0077 const size_t console_device_count = RTEMS_ARRAY_SIZE( console_device_table );
0078 #else
0079 static uart_lite_context uart_lite_instances[BSP_MICROBLAZE_FPGA_MAX_UARTS];
0080 console_device *dynamic_console_device_table;
0081 size_t dynamic_console_device_count;
0082 
0083 /* Override the console_device_table and console_device_count */
0084 #define console_device_table dynamic_console_device_table
0085 #define console_device_count dynamic_console_device_count
0086 #endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
0087 
0088 #ifdef BSP_MICROBLAZE_FPGA_USE_FDT
0089 static int microblaze_fpga_get_stdout_node(const void *fdt)
0090 {
0091   int node;
0092   int len;
0093   int offset;
0094   const char *console;
0095   const char *q;
0096 
0097   node = fdt_path_offset( fdt, "/chosen" );
0098   if ( node < 0 ) {
0099     return 0;
0100   }
0101 
0102   console = fdt_getprop( fdt, node, "stdout-path", NULL );
0103   if ( console == NULL ) {
0104     return 0;
0105   }
0106 
0107   q = strchr(console, ':');
0108   if ( !q ) {
0109     return 0;
0110   }
0111 
0112   len = q - console;
0113 
0114   /* Get the node specified by stdout-path */
0115   offset = fdt_path_offset_namelen( fdt, console, len );
0116   if (offset < 0) {
0117     return 0;
0118   }
0119 
0120   return offset;
0121 }
0122 
0123 static void initialize_uart_arrays(uint32_t max_uarts) {
0124   dynamic_console_device_table = calloc(max_uarts, sizeof(console_device));
0125   dynamic_console_device_count = max_uarts;
0126 
0127   for (uint32_t i = 0; i < max_uarts; i++) {
0128     rtems_termios_device_context_initialize(&uart_lite_instances[i].base, "UARTLITE");
0129     uart_lite_instances[i].initial_baud = 115200;
0130 
0131     dynamic_console_device_table[i].device_file = malloc(11);
0132     snprintf((char *)console_device_table[i].device_file, 11, "/dev/ttyS%u", i);
0133     dynamic_console_device_table[i].handler = &microblaze_uart_fns;
0134     dynamic_console_device_table[i].context = &uart_lite_instances[i].base;
0135   }
0136 }
0137 #endif
0138 
0139 rtems_device_driver console_initialize(
0140   rtems_device_major_number  major,
0141   rtems_device_minor_number  minor,
0142   void                      *arg
0143 )
0144 {
0145   uint32_t port;
0146   uint32_t stdout_port = BSP_MICROBLAZE_FPGA_CONSOLE_UART;
0147 
0148 #ifdef BSP_MICROBLAZE_FPGA_USE_FDT
0149   initialize_uart_arrays(BSP_MICROBLAZE_FPGA_MAX_UARTS);
0150 
0151   const char compatible[] = "xlnx,xps-uartlite-1.00.a";
0152   const void *fdt = bsp_fdt_get();
0153   int len;
0154   int stdout_node = microblaze_fpga_get_stdout_node(fdt);
0155   int node = fdt_node_offset_by_compatible( fdt, -1, compatible);
0156 
0157   while ( node != -FDT_ERR_NOTFOUND ) {
0158     const uint32_t *prop;
0159     const void *status;
0160     uint32_t disabled = 0;
0161     port = console_device_count;
0162 
0163     /* check if node device status has been set to disabled */
0164     status = fdt_getprop( fdt, node, "status", &len );
0165     if ( status != NULL ) {
0166       if ( strncmp( status, "disabled", MIN( 9, len) ) == 0 ) {
0167         disabled = 1;
0168       }
0169     }
0170 
0171     if ( !disabled ) {
0172       /* use port number property as the device table index */
0173       prop = fdt_getprop( fdt, node, "port-number", NULL );
0174       if ( prop != NULL ) {
0175         port = fdt32_to_cpu( prop[0] );
0176       }
0177 
0178       if ( port < console_device_count ) {
0179         prop = fdt_getprop( fdt, node, "reg", NULL );
0180         if ( prop != NULL ) {
0181           uint32_t address = fdt32_to_cpu( prop[0] );
0182           uart_lite_instances[ port ].address = address;
0183           uart_lite_instances[ port ].enabled = 1;
0184           if ( node == stdout_node ) {
0185             stdout_port = port;
0186           }
0187         }
0188 
0189 #ifdef BSP_MICROBLAZE_FPGA_CONSOLE_INTERRUPTS
0190         prop = fdt_getprop( fdt, node, "interrupts", NULL );
0191         if ( prop != NULL ) {
0192           uint32_t irq = fdt32_to_cpu( prop[0] );
0193           uart_lite_instances[ port ].irq = irq;
0194         }
0195 #endif
0196       }
0197     }
0198 
0199     node = fdt_node_offset_by_compatible( fdt, node, compatible );
0200 
0201     if ( disabled || ( port >= console_device_count ) )
0202       continue;
0203   }
0204 #endif /* BSP_MICROBLAZE_FPGA_USE_FDT */
0205 
0206   rtems_termios_initialize();
0207 
0208   for ( port = 0; port < console_device_count; port++ ) {
0209     const console_device *ctx = &console_device_table[ port ];
0210     rtems_status_code     sc;
0211 
0212     if ( !uart_lite_instances[ port ].enabled )
0213       continue;
0214 
0215     sc = rtems_termios_device_install(
0216       ctx->device_file,
0217       ctx->handler,
0218       ctx->flow,
0219       ctx->context
0220     );
0221     if ( sc != RTEMS_SUCCESSFUL ) {
0222       bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_0 );
0223     }
0224 
0225     if ( port == stdout_port ) {
0226       if ( link( ctx->device_file, CONSOLE_DEVICE_NAME ) != 0 ) {
0227         bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_1 );
0228       }
0229     }
0230   }
0231 
0232   return RTEMS_SUCCESSFUL;
0233 }