summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sparc/leon3/console/console.c
diff options
context:
space:
mode:
Diffstat (limited to 'c/src/lib/libbsp/sparc/leon3/console/console.c')
-rw-r--r--c/src/lib/libbsp/sparc/leon3/console/console.c349
1 files changed, 26 insertions, 323 deletions
diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index 989d1cf516..9012492bb6 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -28,34 +28,17 @@
#include <bsp.h>
#include <bsp/fatal.h>
-#include <rtems/libio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <rtems/bspIo.h>
-#include <leon.h>
-#include <rtems/termiostypes.h>
-#include <apbuart.h>
+#include <apbuart_termios.h>
int syscon_uart_index __attribute__((weak)) = 0;
/* body is in debugputs.c */
-
-struct apbuart_priv {
- struct apbuart_regs *regs;
- unsigned int freq_hz;
-#if CONSOLE_USE_INTERRUPTS
- int irq;
- void *cookie;
- volatile int sending;
- char *buf;
-#endif
-};
-static struct apbuart_priv apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
+static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
static int uarts = 0;
-static struct apbuart_priv *leon3_console_get_uart(int minor)
+static struct apbuart_context *leon3_console_get_uart(int minor)
{
- struct apbuart_priv *uart;
+ struct apbuart_context *uart;
if (minor == 0)
uart = &apbuarts[syscon_uart_index];
@@ -65,160 +48,6 @@ static struct apbuart_priv *leon3_console_get_uart(int minor)
return uart;
}
-#if CONSOLE_USE_INTERRUPTS
-
-/* Handle UART interrupts */
-static void leon3_console_isr(void *arg)
-{
- struct apbuart_priv *uart = arg;
- unsigned int status;
- char data;
-
- /* Get all received characters */
- while ((status=uart->regs->status) & APBUART_STATUS_DR) {
- /* Data has arrived, get new data */
- data = uart->regs->data;
-
- /* Tell termios layer about new character */
- rtems_termios_enqueue_raw_characters(uart->cookie, &data, 1);
- }
-
- if (
- (status & APBUART_STATUS_TE)
- && (uart->regs->ctrl & APBUART_CTRL_TI) != 0
- ) {
- /* write_interrupt will get called from this function */
- rtems_termios_dequeue_characters(uart->cookie, 1);
- }
-}
-
-/*
- * Console Termios Write-Buffer Support Entry Point
- *
- */
-static int leon3_console_write_support(int minor, const char *buf, size_t len)
-{
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
- int sending;
-
- if (len > 0) {
- /* Enable TX interrupt (interrupt is edge-triggered) */
- uart->regs->ctrl |= APBUART_CTRL_TI;
-
- /* start UART TX, this will result in an interrupt when done */
- uart->regs->data = *buf;
-
- sending = 1;
- } else {
- /* No more to send, disable TX interrupts */
- uart->regs->ctrl &= ~APBUART_CTRL_TI;
-
- /* Tell close that we sent everything */
- sending = 0;
- }
-
- uart->sending = sending;
-
- return 0;
-}
-
-#else
-
-/*
- * Console Termios Support Entry Points
- */
-static ssize_t leon3_console_write_polled(
- int minor,
- const char *buf,
- size_t len
-)
-{
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
- int nwrite = 0;
-
- while (nwrite < len) {
- apbuart_outbyte_polled(uart->regs, *buf++, 1, 0);
- nwrite++;
- }
- return nwrite;
-}
-
-static int leon3_console_pollRead(int minor)
-{
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
-
- return apbuart_inbyte_nonblocking(uart->regs);
-}
-
-#endif
-
-static int leon3_console_set_attributes(int minor, const struct termios *t)
-{
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
- unsigned int scaler;
- unsigned int ctrl;
- int baud;
-
- switch (t->c_cflag & CSIZE) {
- default:
- case CS5:
- case CS6:
- case CS7:
- /* Hardware doesn't support other than CS8 */
- return -1;
- case CS8:
- break;
- }
-
- /*
- * FIXME: This read-modify-write sequence is broken since interrupts may
- * interfere.
- */
-
- /* Read out current value */
- ctrl = uart->regs->ctrl;
-
- switch (t->c_cflag & (PARENB|PARODD)) {
- case (PARENB|PARODD):
- /* Odd parity */
- ctrl |= APBUART_CTRL_PE|APBUART_CTRL_PS;
- break;
-
- case PARENB:
- /* Even parity */
- ctrl &= ~APBUART_CTRL_PS;
- ctrl |= APBUART_CTRL_PE;
- break;
-
- default:
- case 0:
- case PARODD:
- /* No Parity */
- ctrl &= ~(APBUART_CTRL_PS|APBUART_CTRL_PE);
- }
-
- if (!(t->c_cflag & CLOCAL)) {
- ctrl |= APBUART_CTRL_FL;
- } else {
- ctrl &= ~APBUART_CTRL_FL;
- }
-
- /* Update new settings */
- uart->regs->ctrl = ctrl;
-
- /* Baud rate */
- baud = rtems_termios_baud_to_number(t->c_cflag);
- if (baud > 0) {
- /* Calculate Baud rate generator "scaler" number */
- scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10;
-
- /* Set new baud rate by setting scaler */
- uart->regs->scaler = scaler;
- }
-
- return 0;
-}
-
/* AMBA PP find routine. Extract AMBA PnP information into data structure. */
static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
{
@@ -226,9 +55,7 @@ static int find_matching_apbuart(struct ambapp_dev *dev, int index, void *arg)
/* Extract needed information of one APBUART */
apbuarts[uarts].regs = (struct apbuart_regs *)apb->start;
-#if CONSOLE_USE_INTERRUPTS
apbuarts[uarts].irq = apb->irq;
-#endif
/* Get APBUART core frequency, it is assumed that it is the same
* as Bus frequency where the UART is situated
*/
@@ -251,17 +78,18 @@ static void leon3_console_scan_uarts(void)
GAISLER_APBUART, find_matching_apbuart, NULL);
}
-/*
- * Console Device Driver Entry Points
- *
- */
-
rtems_device_driver console_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg
)
{
+ const rtems_termios_device_handler *handler =
+#if CONSOLE_USE_INTERRUPTS
+ &apbuart_handler_interrupt;
+#else
+ &apbuart_handler_polled;
+#endif
rtems_status_code status;
int i;
char console_name[16];
@@ -297,7 +125,14 @@ rtems_device_driver console_initialize(
* On a MP system one should not open UARTs that other OS instances use.
*/
if (syscon_uart_index < uarts) {
- status = rtems_io_register_name("/dev/console", major, 0);
+ minor = 0;
+ status = rtems_termios_device_install(
+ CONSOLE_DEVICE_NAME,
+ major,
+ minor,
+ handler,
+ leon3_console_get_uart(syscon_uart_index)
+ );
if (status != RTEMS_SUCCESSFUL)
bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV);
}
@@ -306,147 +141,15 @@ rtems_device_driver console_initialize(
if (i == syscon_uart_index)
continue; /* skip UART that is registered as /dev/console */
console_name[13] = 'a' + i;
- rtems_io_register_name( console_name, major, i+1);
+ minor = i + 1;
+ rtems_termios_device_install(
+ console_name,
+ major,
+ minor,
+ handler,
+ leon3_console_get_uart(syscon_uart_index)
+ );
}
return RTEMS_SUCCESSFUL;
}
-
-#if CONSOLE_USE_INTERRUPTS
-static struct rtems_termios_tty *leon3_console_get_tty(
- rtems_libio_open_close_args_t *args
-)
-{
- return args->iop->data1;
-}
-#endif
-
-static int leon3_console_first_open(int major, int minor, void *arg)
-{
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
-
-#if CONSOLE_USE_INTERRUPTS
- rtems_status_code sc;
-
- uart->cookie = leon3_console_get_tty(arg);
-
- /* Register Interrupt handler */
- sc = rtems_interrupt_handler_install(uart->irq, "console",
- RTEMS_INTERRUPT_SHARED,
- leon3_console_isr,
- uart);
- if (sc != RTEMS_SUCCESSFUL)
- return -1;
-
- uart->sending = 0;
- /* Enable Receiver and transmitter and Turn on RX interrupts */
- uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE |
- APBUART_CTRL_RI;
-#else
- /* Initialize UART on opening */
- uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
-#endif
- uart->regs->status = 0;
-
- return 0;
-}
-
-#if CONSOLE_USE_INTERRUPTS
-static int leon3_console_last_close(int major, int minor, void *arg)
-{
- struct rtems_termios_tty *tty = leon3_console_get_tty(arg);
- struct apbuart_priv *uart = leon3_console_get_uart(minor);
- rtems_interrupt_lock_context lock_ctx;
-
- /* Turn off RX interrupts */
- rtems_termios_interrupt_lock_acquire(tty, &lock_ctx);
- uart->regs->ctrl &= ~(APBUART_CTRL_RI);
- rtems_termios_interrupt_lock_release(tty, &lock_ctx);
-
- /**** Flush device ****/
- while (uart->sending) {
- /* Wait until all data has been sent */
- }
-
- /* uninstall ISR */
- rtems_interrupt_handler_remove(uart->irq, leon3_console_isr, uart);
-
- return 0;
-}
-#endif
-
-rtems_device_driver console_open(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void * arg
-)
-{
-#if CONSOLE_USE_INTERRUPTS
- /* Interrupt mode routines */
- static const rtems_termios_callbacks Callbacks = {
- leon3_console_first_open, /* firstOpen */
- leon3_console_last_close, /* lastClose */
- NULL, /* pollRead */
- leon3_console_write_support, /* write */
- leon3_console_set_attributes,/* setAttributes */
- NULL, /* stopRemoteTx */
- NULL, /* startRemoteTx */
- 1 /* outputUsesInterrupts */
- };
-#else
- /* Polling mode routines */
- static const rtems_termios_callbacks Callbacks = {
- leon3_console_first_open, /* firstOpen */
- NULL, /* lastClose */
- leon3_console_pollRead, /* pollRead */
- leon3_console_write_polled, /* write */
- leon3_console_set_attributes,/* setAttributes */
- NULL, /* stopRemoteTx */
- NULL, /* startRemoteTx */
- 0 /* outputUsesInterrupts */
- };
-#endif
-
- assert(minor <= uarts);
- if (minor > uarts || minor == (syscon_uart_index + 1))
- return RTEMS_INVALID_NUMBER;
-
- return rtems_termios_open(major, minor, arg, &Callbacks);
-}
-
-rtems_device_driver console_close(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void * arg
-)
-{
- return rtems_termios_close(arg);
-}
-
-rtems_device_driver console_read(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void * arg
-)
-{
- return rtems_termios_read(arg);
-}
-
-rtems_device_driver console_write(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void * arg
-)
-{
- return rtems_termios_write(arg);
-}
-
-rtems_device_driver console_control(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void * arg
-)
-{
- return rtems_termios_ioctl(arg);
-}
-