[41c9282] | 1 | /* |
---|
| 2 | * This file contains the TTY driver for the serial ports on the LEON. |
---|
| 3 | * |
---|
| 4 | * This driver uses the termios pseudo driver. |
---|
| 5 | * |
---|
| 6 | * COPYRIGHT (c) 1989-1998. |
---|
| 7 | * On-Line Applications Research Corporation (OAR). |
---|
| 8 | * |
---|
| 9 | * Modified for LEON3 BSP. |
---|
| 10 | * COPYRIGHT (c) 2004. |
---|
| 11 | * Gaisler Research. |
---|
| 12 | * |
---|
| 13 | * The license and distribution terms for this file may be |
---|
| 14 | * found in the file LICENSE in this distribution or at |
---|
[c499856] | 15 | * http://www.rtems.org/license/LICENSE. |
---|
[41c9282] | 16 | */ |
---|
| 17 | |
---|
[62694fd] | 18 | /* Define CONSOLE_USE_INTERRUPTS to enable APBUART interrupt handling instead |
---|
| 19 | * of polling mode. |
---|
| 20 | * |
---|
| 21 | * Note that it is not possible to use the interrupt mode of the driver |
---|
| 22 | * together with the "old" APBUART and -u to GRMON. However the new |
---|
| 23 | * APBUART core (from GRLIB 1.0.17-b2710) has the GRMON debug bit and can |
---|
| 24 | * handle interrupts. |
---|
| 25 | * |
---|
| 26 | * NOTE: This can be defined in the make/custom/leon3.cfg file. |
---|
| 27 | */ |
---|
| 28 | |
---|
[41c9282] | 29 | #include <bsp.h> |
---|
[46d7fa5] | 30 | #include <bsp/fatal.h> |
---|
[5823bae8] | 31 | #include <bsp/apbuart_termios.h> |
---|
[41c9282] | 32 | |
---|
[e428dc4a] | 33 | /* The LEON3 BSP UART driver can rely on the Driver Manager if the |
---|
| 34 | * DrvMgr is initialized during startup. Otherwise the classic driver |
---|
| 35 | * must be used. |
---|
| 36 | * |
---|
| 37 | * The DrvMgr APBUART driver is located in the shared/uart directory |
---|
| 38 | */ |
---|
| 39 | #ifndef RTEMS_DRVMGR_STARTUP |
---|
| 40 | |
---|
[4b557617] | 41 | int syscon_uart_index __attribute__((weak)) = 0; |
---|
| 42 | |
---|
[41c9282] | 43 | /* body is in debugputs.c */ |
---|
[21abc43] | 44 | static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS]; |
---|
[ddf0d60] | 45 | static int uarts = 0; |
---|
[41c9282] | 46 | |
---|
[9c96ea7] | 47 | static rtems_termios_device_context *leon3_console_get_context(int index) |
---|
[6fe6d017] | 48 | { |
---|
[9c96ea7] | 49 | struct apbuart_context *uart = &apbuarts[index]; |
---|
[6fe6d017] | 50 | |
---|
[7fd5e89] | 51 | rtems_termios_device_context_initialize(&uart->base, "APBUART"); |
---|
| 52 | |
---|
| 53 | return &uart->base; |
---|
[6fe6d017] | 54 | } |
---|
| 55 | |
---|
[ddf0d60] | 56 | /* AMBA PP find routine. Extract AMBA PnP information into data structure. */ |
---|
[1d5d6de] | 57 | static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg) |
---|
[ddf0d60] | 58 | { |
---|
| 59 | struct ambapp_apb_info *apb = (struct ambapp_apb_info *)dev->devinfo; |
---|
| 60 | |
---|
| 61 | /* Extract needed information of one APBUART */ |
---|
[226d48d8] | 62 | apbuarts[uarts].regs = (struct apbuart_regs *)apb->start; |
---|
[62694fd] | 63 | apbuarts[uarts].irq = apb->irq; |
---|
[ddf0d60] | 64 | /* Get APBUART core frequency, it is assumed that it is the same |
---|
| 65 | * as Bus frequency where the UART is situated |
---|
| 66 | */ |
---|
| 67 | apbuarts[uarts].freq_hz = ambapp_freq_get(&ambapp_plb, dev); |
---|
| 68 | uarts++; |
---|
| 69 | |
---|
| 70 | if (uarts >= BSP_NUMBER_OF_TERMIOS_PORTS) |
---|
| 71 | return 1; /* Satisfied number of UARTs, stop search */ |
---|
| 72 | else |
---|
| 73 | return 0; /* Continue searching for more UARTs */ |
---|
| 74 | } |
---|
| 75 | |
---|
| 76 | /* Find all UARTs */ |
---|
[1d5d6de] | 77 | static void leon3_console_scan_uarts(void) |
---|
[ddf0d60] | 78 | { |
---|
| 79 | memset(apbuarts, 0, sizeof(apbuarts)); |
---|
| 80 | |
---|
| 81 | /* Find APBUART cores */ |
---|
| 82 | ambapp_for_each(&ambapp_plb, (OPTIONS_ALL|OPTIONS_APB_SLVS), VENDOR_GAISLER, |
---|
| 83 | GAISLER_APBUART, find_matching_apbuart, NULL); |
---|
[4b557617] | 84 | } |
---|
[41c9282] | 85 | |
---|
| 86 | rtems_device_driver console_initialize( |
---|
| 87 | rtems_device_major_number major, |
---|
| 88 | rtems_device_minor_number minor, |
---|
| 89 | void *arg |
---|
| 90 | ) |
---|
| 91 | { |
---|
[21abc43] | 92 | const rtems_termios_device_handler *handler = |
---|
| 93 | #if CONSOLE_USE_INTERRUPTS |
---|
| 94 | &apbuart_handler_interrupt; |
---|
| 95 | #else |
---|
| 96 | &apbuart_handler_polled; |
---|
| 97 | #endif |
---|
[41c9282] | 98 | rtems_status_code status; |
---|
[4b557617] | 99 | int i; |
---|
[921bb59] | 100 | char console_name[16]; |
---|
[41c9282] | 101 | |
---|
| 102 | rtems_termios_initialize(); |
---|
| 103 | |
---|
[ddf0d60] | 104 | /* Find UARTs */ |
---|
[1d5d6de] | 105 | leon3_console_scan_uarts(); |
---|
[ddf0d60] | 106 | |
---|
[4b557617] | 107 | /* Update syscon_uart_index to index used as /dev/console |
---|
| 108 | * Let user select System console by setting syscon_uart_index. If the |
---|
| 109 | * BSP is to provide the default UART (syscon_uart_index==0): |
---|
| 110 | * non-MP: APBUART[0] is system console |
---|
| 111 | * MP: LEON CPU index select UART |
---|
| 112 | */ |
---|
| 113 | if (syscon_uart_index == 0) { |
---|
| 114 | #if defined(RTEMS_MULTIPROCESSING) |
---|
| 115 | syscon_uart_index = LEON3_Cpu_Index; |
---|
| 116 | #else |
---|
| 117 | syscon_uart_index = 0; |
---|
| 118 | #endif |
---|
| 119 | } else { |
---|
| 120 | syscon_uart_index = syscon_uart_index - 1; /* User selected sys-console */ |
---|
| 121 | } |
---|
[41c9282] | 122 | |
---|
[4b557617] | 123 | /* Register Device Names |
---|
| 124 | * |
---|
| 125 | * 0 /dev/console - APBUART[USER-SELECTED, DEFAULT=APBUART[0]] |
---|
| 126 | * 1 /dev/console_a - APBUART[0] (by default not present because is console) |
---|
| 127 | * 2 /dev/console_b - APBUART[1] |
---|
| 128 | * ... |
---|
| 129 | * |
---|
| 130 | * On a MP system one should not open UARTs that other OS instances use. |
---|
| 131 | */ |
---|
| 132 | if (syscon_uart_index < uarts) { |
---|
[21abc43] | 133 | minor = 0; |
---|
| 134 | status = rtems_termios_device_install( |
---|
| 135 | CONSOLE_DEVICE_NAME, |
---|
| 136 | major, |
---|
| 137 | minor, |
---|
| 138 | handler, |
---|
[a830cb8] | 139 | NULL, |
---|
[7fd5e89] | 140 | leon3_console_get_context(syscon_uart_index) |
---|
[21abc43] | 141 | ); |
---|
[41c9282] | 142 | if (status != RTEMS_SUCCESSFUL) |
---|
[46d7fa5] | 143 | bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV); |
---|
[41c9282] | 144 | } |
---|
[4b557617] | 145 | strcpy(console_name,"/dev/console_a"); |
---|
| 146 | for (i = 0; i < uarts; i++) { |
---|
| 147 | if (i == syscon_uart_index) |
---|
| 148 | continue; /* skip UART that is registered as /dev/console */ |
---|
| 149 | console_name[13] = 'a' + i; |
---|
[21abc43] | 150 | minor = i + 1; |
---|
| 151 | rtems_termios_device_install( |
---|
| 152 | console_name, |
---|
| 153 | major, |
---|
| 154 | minor, |
---|
| 155 | handler, |
---|
[a830cb8] | 156 | NULL, |
---|
[9c96ea7] | 157 | leon3_console_get_context(i) |
---|
[21abc43] | 158 | ); |
---|
[41c9282] | 159 | } |
---|
| 160 | |
---|
| 161 | return RTEMS_SUCCESSFUL; |
---|
| 162 | } |
---|
[e428dc4a] | 163 | |
---|
| 164 | #endif |
---|