forked from Imagelibrary/rtems
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
This commit is contained in:
425
bsps/powerpc/virtex/console/consolelite.c
Normal file
425
bsps/powerpc/virtex/console/consolelite.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* This file contains the console driver for the xilinx uart lite.
|
||||
*
|
||||
* Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
|
||||
* 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 <assert.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <bsp/irq.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <libchip/serial.h>
|
||||
#include <libchip/sersupp.h>
|
||||
|
||||
#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 <rtems/bspIo.h>
|
||||
|
||||
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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user