Back to home page

LXR

 
 

    


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

0001 /**
0002  * @file
0003  *
0004  * @ingroup raspberrypi_usart
0005  *
0006  * @brief Console Configuration.
0007  */
0008 
0009 /*
0010  * Copyright (c) 2015 Yang Qiao
0011  * based on work by:
0012  * Copyright (c) 2013 Alan Cudmore
0013  *
0014  *  The license and distribution terms for this file may be
0015  *  found in the file LICENSE in this distribution or at
0016  *
0017  *  http://www.rtems.org/license/LICENSE
0018  *
0019  */
0020 
0021 #include <rtems/bspIo.h>
0022 #include <rtems/console.h>
0023 #include <rtems/sysinit.h>
0024 
0025 #include <libchip/serial.h>
0026 #include <libfdt.h>
0027 #include <libchip/ns16550.h>
0028 #include <dev/serial/arm-pl011.h>
0029 
0030 #include <bspopts.h>
0031 #include <bsp/usart.h>
0032 #include <bsp/raspberrypi.h>
0033 #include <bsp/fbcons.h>
0034 #include <bsp.h>
0035 #include <bsp/console-termios.h>
0036 #include <bsp/fdt.h>
0037 #include <bsp/fatal.h>
0038 #include <bsp/gpio.h>
0039 #include <bsp/rpi-gpio.h>
0040 
0041 /**
0042  * UART0 - PL011
0043  * UART1 - Mini UART
0044  */
0045 #define PL011     "/dev/ttyAMA0"
0046 #define MINIUART  "/dev/ttyS0"
0047 #define FBCONS    "/dev/fbcons"
0048 
0049 arm_pl011_context pl011_context = {
0050   .clock = 48000000
0051 };
0052 ns16550_context mini_uart_context;
0053 
0054 rpi_fb_context fb_context;
0055 
0056 static void output_char_pl011(char c)
0057 {
0058   arm_pl011_write_polled(&pl011_context.base, c);
0059 }
0060 
0061 static void output_char_mini_uart(char c)
0062 {
0063   ns16550_polled_putchar(&mini_uart_context.base, c);
0064 }
0065 
0066 void output_char_fb(char c)
0067 {
0068   fbcons_write_polled(&fb_context.base, c);
0069 }
0070 
0071 static uint8_t mini_uart_get_reg(uintptr_t port, uint8_t index)
0072 {
0073   volatile uint32_t *val = (volatile uint32_t *)port + index;
0074   return (uint8_t) *val;
0075 }
0076 
0077 static void mini_uart_set_reg(uintptr_t port, uint8_t index, uint8_t val)
0078 {
0079   volatile uint32_t *reg = (volatile uint32_t *)port + index;
0080   *reg = val;
0081 }
0082 
0083 static void init_ctx_arm_pl011(
0084   const void *fdt,
0085   int node
0086 )
0087 {
0088   arm_pl011_context *ctx = &pl011_context;
0089   rtems_termios_device_context_initialize(&ctx->base, "PL011UART");
0090   ctx->regs = raspberrypi_get_reg_of_node(fdt, node);
0091 }
0092 
0093 static uint32_t calculate_baud_divisor(
0094   ns16550_context *ctx,
0095   uint32_t baud
0096 )
0097 {
0098   uint32_t baudDivisor = (ctx->clock / (8 * baud)) - 1;
0099   return baudDivisor;
0100 }
0101 
0102 static void init_ctx_mini_uart(
0103   const void *fdt,
0104   int node
0105 )
0106 {
0107   const char *status;
0108   int len;
0109   ns16550_context *ctx;
0110 
0111   memset(&mini_uart_context, 0, sizeof(mini_uart_context));
0112   ctx = &mini_uart_context;
0113 
0114   rtems_termios_device_context_initialize(&ctx->base, "MiniUART");
0115 
0116   status = fdt_getprop(fdt, node, "status", &len);
0117   if ( status == NULL || strcmp(status, "disabled" ) == 0){
0118     return ;
0119   }
0120 
0121   ctx->port = (uintptr_t) raspberrypi_get_reg_of_node(fdt, node);
0122   ctx->initial_baud = MINI_UART_DEFAULT_BAUD;
0123   ctx->clock = BCM2835_CLOCK_FREQ;
0124   ctx->calculate_baud_divisor = calculate_baud_divisor;
0125   ctx->get_reg = mini_uart_get_reg;
0126   ctx->set_reg = mini_uart_set_reg;
0127 
0128   rtems_gpio_bsp_select_specific_io(0, 14, RPI_ALT_FUNC_5, NULL);
0129   rtems_gpio_bsp_select_specific_io(0, 15, RPI_ALT_FUNC_5, NULL);
0130   rtems_gpio_bsp_set_resistor_mode(0, 14, NO_PULL_RESISTOR);
0131   rtems_gpio_bsp_set_resistor_mode(0, 15, NO_PULL_RESISTOR);
0132 
0133   BCM2835_REG(AUX_ENABLES) |= 0x1;
0134   ns16550_probe(&ctx->base);
0135 }
0136 
0137 static void register_fb( void )
0138 {
0139   if (fbcons_probe(&fb_context.base) == true) {
0140     rtems_termios_device_install(
0141       FBCONS,
0142       &fbcons_fns,
0143       NULL,
0144       &fb_context.base);
0145   }
0146 }
0147 
0148 static void console_select( void )
0149 {
0150   const char *opt;
0151 
0152   opt = rpi_cmdline_get_arg("--console=");
0153 
0154   if ( opt ) {
0155     if ( strncmp( opt, "fbcons", sizeof( "fbcons" ) - 1 ) == 0 ) {
0156       if ( rpi_video_is_initialized() > 0 ) {
0157         BSP_output_char = output_char_fb;
0158         link(FBCONS, CONSOLE_DEVICE_NAME);
0159         return ;
0160       }
0161     } else if ( strncmp( opt, MINIUART, sizeof(MINIUART) - 1 ) == 0) {
0162       BSP_output_char = output_char_mini_uart;
0163       link(MINIUART, CONSOLE_DEVICE_NAME);
0164     } else if ( strncmp( opt, PL011, sizeof(PL011) - 1 ) == 0) {
0165       BSP_output_char = output_char_pl011;
0166       link(PL011, CONSOLE_DEVICE_NAME);
0167     }
0168   }else {
0169     /**
0170      * If no command line option was given, default to PL011.
0171      */
0172     BSP_output_char = output_char_pl011;
0173     link(PL011, CONSOLE_DEVICE_NAME);
0174   }
0175 }
0176 
0177 static void uart_probe(void)
0178 {
0179   static bool initialized = false;
0180   const void *fdt;
0181   const char *console;
0182   int len;
0183   int node;
0184 
0185   if ( initialized ) {
0186     return ;
0187   }
0188 
0189   fdt = bsp_fdt_get();
0190 
0191   node = fdt_node_offset_by_compatible(fdt, -1, "brcm,bcm2835-pl011");
0192   init_ctx_arm_pl011(fdt, node);
0193 
0194   node = fdt_node_offset_by_compatible(fdt, -1, "brcm,bcm2835-aux-uart");
0195   init_ctx_mini_uart(fdt, node);
0196 
0197   node = fdt_path_offset(fdt, "/aliases");
0198   console = fdt_getprop(fdt, node, "serial0", &len);
0199 
0200   if ( strcmp(console, "/soc/serial@7e215040" ) == 0) {
0201     BSP_output_char = output_char_mini_uart;
0202   }else {
0203     BSP_output_char = output_char_pl011;
0204   }
0205 
0206   initialized = true;
0207 }
0208 
0209 static void output_char(char c)
0210 {
0211   uart_probe();
0212   (*BSP_output_char)(c);
0213 }
0214 
0215 rtems_status_code console_initialize(
0216   rtems_device_major_number major,
0217   rtems_device_minor_number minor,
0218   void *arg
0219 )
0220 {
0221   rtems_termios_initialize();
0222 
0223   uart_probe();
0224   rtems_termios_device_install(
0225     PL011,
0226     &arm_pl011_fns,
0227     NULL,
0228     &pl011_context.base
0229   );
0230 
0231   rtems_termios_device_install(
0232     MINIUART,
0233     &ns16550_handler_polled,
0234     NULL,
0235     &mini_uart_context.base
0236   );
0237 
0238   register_fb();
0239 
0240   console_select();
0241 
0242   return RTEMS_SUCCESSFUL;
0243 }
0244 
0245 BSP_output_char_function_type BSP_output_char = output_char;
0246 
0247 BSP_polling_getchar_function_type BSP_poll_char = NULL;
0248 
0249 RTEMS_SYSINIT_ITEM(
0250   uart_probe,
0251   RTEMS_SYSINIT_BSP_START,
0252   RTEMS_SYSINIT_ORDER_LAST_BUT_5
0253 );