File indexing completed on 2025-05-11 08:23:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
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
0043
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
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 );