From d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Thu, 19 Apr 2018 06:28:01 +0200 Subject: bsps: Move console drivers to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/powerpc/virtex/console/consolelite.c | 425 ++++++++++++++++++++++++++++++ 1 file changed, 425 insertions(+) create mode 100644 bsps/powerpc/virtex/console/consolelite.c (limited to 'bsps/powerpc/virtex') diff --git a/bsps/powerpc/virtex/console/consolelite.c b/bsps/powerpc/virtex/console/consolelite.c new file mode 100644 index 0000000000..4d0b2db17f --- /dev/null +++ b/bsps/powerpc/virtex/console/consolelite.c @@ -0,0 +1,425 @@ +/* + * This file contains the console driver for the xilinx uart lite. + * + * Author: Keith Robertson + * COPYRIGHT (c) 2005 by Linn Products Ltd, Scotland. + * + * Derived from libbsp/no_cpu/no_bsp/console.c and therefore also: + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + */ + +#include + +#include +#include +#include + +#include +#include +#include + +#include RTEMS_XPARAMETERS_H + +/* Status Register Masks */ +#define PARITY_ERROR 0x80 /* Parity Error */ +#define FRAME_ERROR 0x40 /* Frame Error */ +#define OVERRUN_ERROR 0x20 /* Overrun Error */ +#define STATUS_REG_ERROR_MASK ( PARITY_ERROR | FRAME_ERROR | OVERRUN_ERROR ) + +#define INTR_ENABLED 0x10 /* Interrupts are enabled */ +#define TX_FIFO_FULL 0x08 /* Transmit FIFO is full */ +#define TX_FIFO_EMPTY 0x04 /* Transmit FIFO is empty */ +#define RX_FIFO_FULL 0x02 /* Receive FIFO is full */ +#define RX_FIFO_VALID_DATA 0x01 /* Receive FIFO has valid data */ +/* Control Register Masks*/ +#define ENABLE_INTR 0x10 /* Enable interrupts */ +#define RST_RX_FIFO 0x02 /* Reset and clear RX FIFO */ +#define RST_TX_FIFO 0x01 /* Reset and clear TX FIFO */ + +/* General Defines */ +#define TX_FIFO_SIZE 16 +#define RX_FIFO_SIZE 16 + + + + +#define RECV_REG 0 +#define TRAN_REG 4 +#define STAT_REG 8 +#define CTRL_REG 12 + + + +RTEMS_INLINE_ROUTINE uint32_t xlite_uart_control(uint32_t base) +{ + uint32_t c = *((volatile uint32_t*)(base+CTRL_REG)); + return c; +} + + +RTEMS_INLINE_ROUTINE uint32_t xlite_uart_status(uint32_t base) +{ + uint32_t c = *((volatile uint32_t*)(base+STAT_REG)); + return c; +} + + +RTEMS_INLINE_ROUTINE uint32_t xlite_uart_read(uint32_t base) +{ + uint32_t c = *((volatile uint32_t*)(base+RECV_REG)); + return c; +} + + +RTEMS_INLINE_ROUTINE void xlite_uart_write(uint32_t base, char ch) +{ + *(volatile uint32_t*)(base+TRAN_REG) = (uint32_t)ch; + return; +} + + + +static int xlite_write_char(uint32_t base, char ch) +{ + uint32_t retrycount= 0, idler, status; + + while( ((status = xlite_uart_status(base)) & TX_FIFO_FULL) != 0 ) + { + ++retrycount; + + /* uart tx is busy */ + if( retrycount == 0x4000 ) + { + /* retrycount is arbitrary- just make it big enough so the uart is sure to be timed out before it trips */ + return -1; + } + + /* spin for a bit so we can sample the register rather than + * continually reading it */ + for( idler= 0; idler < 0x2000; idler++); + } + + xlite_uart_write(base, ch); + + return 1; +} + +static void xlite_init(int minor ) +{ + /* Nothing to do */ +} + +#if VIRTEX_CONSOLE_USE_INTERRUPTS +static void xlite_interrupt_handler(void *arg) +{ + int minor = (int) arg; + const console_tbl *ct = Console_Port_Tbl[minor]; + console_data *cd = &Console_Port_Data[minor]; + uint32_t base = ct->ulCtrlPort1; + uint32_t status = xlite_uart_status(base); + + while ((status & RX_FIFO_VALID_DATA) != 0) { + char c = (char) xlite_uart_read(base); + + rtems_termios_enqueue_raw_characters(cd->termios_data, &c, 1); + + status = xlite_uart_status(base); + } + + if (cd->bActive) { + rtems_termios_dequeue_characters(cd->termios_data, 1); + } +} +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + +static int xlite_open( + int major, + int minor, + void *arg +) +{ + const console_tbl *ct = Console_Port_Tbl[minor]; + uint32_t base = ct->ulCtrlPort1; +#if VIRTEX_CONSOLE_USE_INTERRUPTS + rtems_status_code sc; +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + + /* clear status register */ + *((volatile uint32_t*)(base+STAT_REG)) = 0; + + /* clear control register; reset fifos */ + *((volatile uint32_t*)(base+CTRL_REG)) = RST_RX_FIFO | RST_TX_FIFO; + +#if VIRTEX_CONSOLE_USE_INTERRUPTS + *((volatile uint32_t*)(base+CTRL_REG)) = ENABLE_INTR; + + sc = rtems_interrupt_handler_install( + ct->ulIntVector, + "xlite", + RTEMS_INTERRUPT_UNIQUE, + xlite_interrupt_handler, + (void *) minor + ); + assert(sc == RTEMS_SUCCESSFUL); +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + + return 0; +} + +static int xlite_close( + int major, + int minor, + void *arg +) +{ + const console_tbl *ct = Console_Port_Tbl[minor]; + uint32_t base = ct->ulCtrlPort1; +#if VIRTEX_CONSOLE_USE_INTERRUPTS + rtems_status_code sc; +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + + *((volatile uint32_t*)(base+CTRL_REG)) = 0; + +#if VIRTEX_CONSOLE_USE_INTERRUPTS + sc = rtems_interrupt_handler_remove( + ct->ulIntVector, + xlite_interrupt_handler, + (void *) minor + ); + assert(sc == RTEMS_SUCCESSFUL); +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + + return 0; +} + + + +static int xlite_read_polled (int minor ) +{ + uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1; + + unsigned int status = xlite_uart_status(base); + + if(status & RX_FIFO_VALID_DATA) + return (int)xlite_uart_read(base); + else + return -1; +} + +#if VIRTEX_CONSOLE_USE_INTERRUPTS + +static ssize_t xlite_write_interrupt_driven( + int minor, + const char *buf, + size_t len +) +{ + console_data *cd = &Console_Port_Data[minor]; + + if (len > 0) { + const console_tbl *ct = Console_Port_Tbl[minor]; + uint32_t base = ct->ulCtrlPort1; + + xlite_uart_write(base, buf[0]); + + cd->bActive = true; + } else { + cd->bActive = false; + } + + return 0; +} + +#else /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + +static ssize_t xlite_write_buffer_polled( + int minor, + const char *buf, + size_t len +) +{ + uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1; + int nwrite = 0; + + /* + * poll each byte in the string out of the port. + */ + while (nwrite < len) + { + if( xlite_write_char(base, *buf++) < 0 ) break; + nwrite++; + } + + /* + * return the number of bytes written. + */ + return nwrite; +} + +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + +static void xlite_write_char_polled( + int minor, + char c +) +{ + uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1; + xlite_write_char(base, c); + return; +} + +static int xlite_set_attributes(int minor, const struct termios *t) +{ + return RTEMS_SUCCESSFUL; +} + + + + + + + +static const console_fns xlite_fns_polled = +{ + .deviceProbe = libchip_serial_default_probe, + .deviceFirstOpen = xlite_open, + .deviceLastClose = xlite_close, + .deviceRead = xlite_read_polled, + .deviceInitialize = xlite_init, + .deviceWritePolled = xlite_write_char_polled, + .deviceSetAttributes = xlite_set_attributes, +#if VIRTEX_CONSOLE_USE_INTERRUPTS + .deviceWrite = xlite_write_interrupt_driven, + .deviceOutputUsesInterrupts = true +#else /* VIRTEX_CONSOLE_USE_INTERRUPTS */ + .deviceWrite = xlite_write_buffer_polled, + .deviceOutputUsesInterrupts = false +#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */ +}; + + + + + + +/* +** Set ulCtrlPort1 to the base address of each UART Lite instance. Set in vhdl model. +*/ + + +console_tbl Console_Configuration_Ports[] = { +{ + "/dev/ttyS0", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &xlite_fns_polled, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) NULL, /* NULL */ /* pDeviceParams */ + STDIN_BASEADDRESS, /* ulCtrlPort1 */ + 0, /* ulCtrlPort2 */ + 0, /* ulDataPort */ + NULL, /* getRegister */ + NULL, /* setRegister */ + NULL, /* unused */ /* getData */ + NULL, /* unused */ /* setData */ + 0, /* ulClock */ + #ifdef XPAR_XPS_INTC_0_RS232_UART_INTERRUPT_INTR + .ulIntVector = XPAR_XPS_INTC_0_RS232_UART_INTERRUPT_INTR + #else + .ulIntVector = 0 + #endif +}, +#ifdef XPAR_UARTLITE_1_BASEADDR +{ + "/dev/ttyS1", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &xlite_fns_polled, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) NULL, /* NULL */ /* pDeviceParams */ + XPAR_UARTLITE_1_BASEADDR, /* ulCtrlPort1 */ + 0, /* ulCtrlPort2 */ + 0, /* ulDataPort */ + NULL, /* getRegister */ + NULL, /* setRegister */ + NULL, /* unused */ /* getData */ + NULL, /* unused */ /* setData */ + 0, /* ulClock */ + 0 /* ulIntVector -- base for port */ +}, +#endif +#ifdef XPAR_UARTLITE_2_BASEADDR +{ + "/dev/ttyS2", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &xlite_fns_polled, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) NULL, /* NULL */ /* pDeviceParams */ + XPAR_UARTLITE_2_BASEADDR, /* ulCtrlPort1 */ + 0, /* ulCtrlPort2 */ + 0, /* ulDataPort */ + NULL, /* getRegister */ + NULL, /* setRegister */ + NULL, /* unused */ /* getData */ + NULL, /* unused */ /* setData */ + 0, /* ulClock */ + 0 /* ulIntVector -- base for port */ +}, +#endif +#ifdef XPAR_UARTLITE_2_BASEADDR +{ + "/dev/ttyS3", /* sDeviceName */ + SERIAL_CUSTOM, /* deviceType */ + &xlite_fns_polled, /* pDeviceFns */ + NULL, /* deviceProbe, assume it is there */ + NULL, /* pDeviceFlow */ + 16, /* ulMargin */ + 8, /* ulHysteresis */ + (void *) NULL, /* NULL */ /* pDeviceParams */ + XPAR_UARTLITE_3_BASEADDR, /* ulCtrlPort1 */ + 0, /* ulCtrlPort2 */ + 0, /* ulDataPort */ + NULL, /* getRegister */ + NULL, /* setRegister */ + NULL, /* unused */ /* getData */ + NULL, /* unused */ /* setData */ + 0, /* ulClock */ + 0 /* ulIntVector -- base for port */ +} +#endif +}; + +unsigned long Console_Configuration_Count = + RTEMS_ARRAY_SIZE(Console_Configuration_Ports); + + +#include + +static void outputChar(char ch) +{ + xlite_write_char_polled( 0, ch ); +} + +static int inputChar(void) +{ + return xlite_read_polled(0); +} + +BSP_output_char_function_type BSP_output_char = outputChar; +BSP_polling_getchar_function_type BSP_poll_char = inputChar; + + -- cgit v1.2.3