source: rtems/bsps/powerpc/virtex/console/consolelite.c @ d7d66d7

5
Last change on this file since d7d66d7 was d7d66d7, checked in by Sebastian Huber <sebastian.huber@…>, on 04/19/18 at 04:28:01

bsps: Move console drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 11.7 KB
RevLine 
[862c2317]1/*
2 *  This file contains the console driver for the xilinx uart lite.
3 *
4 *  Author: Keith Robertson <kjrobert@alumni.uwaterloo.ca>
5 *  COPYRIGHT (c) 2005 by Linn Products Ltd, Scotland.
6 *
7 *  Derived from libbsp/no_cpu/no_bsp/console.c and therefore also:
8 *
9 *  COPYRIGHT (c) 1989-1999.
10 *  On-Line Applications Research Corporation (OAR).
11 *
12 *  The license and distribution terms for this file may be
13 *  found in the file LICENSE in this distribution or at
[c499856]14 *  http://www.rtems.org/license/LICENSE.
[862c2317]15 *
16 */
17
[0a697dd9]18#include <assert.h>
19
[862c2317]20#include <rtems.h>
21#include <rtems/libio.h>
22#include <bsp/irq.h>
23
24#include <bsp.h>
25#include <libchip/serial.h>
26#include <libchip/sersupp.h>
27
[c607d50e]28#include RTEMS_XPARAMETERS_H
[862c2317]29
30/* Status Register Masks */
31#define PARITY_ERROR       0x80 /* Parity Error */
32#define FRAME_ERROR        0x40 /* Frame Error */
33#define OVERRUN_ERROR      0x20 /* Overrun Error */
34#define STATUS_REG_ERROR_MASK ( PARITY_ERROR | FRAME_ERROR | OVERRUN_ERROR )
35
36#define INTR_ENABLED       0x10 /* Interrupts are enabled */
37#define TX_FIFO_FULL       0x08 /* Transmit FIFO is full */
38#define TX_FIFO_EMPTY      0x04 /* Transmit FIFO is empty */
39#define RX_FIFO_FULL       0x02 /* Receive FIFO is full */
40#define RX_FIFO_VALID_DATA 0x01 /* Receive FIFO has valid data */
41/* Control Register Masks*/
42#define ENABLE_INTR        0x10 /* Enable interrupts */
43#define RST_RX_FIFO        0x02 /* Reset and clear RX FIFO */
44#define RST_TX_FIFO        0x01 /* Reset and clear TX FIFO */
45
46/* General Defines */
47#define TX_FIFO_SIZE       16
48#define RX_FIFO_SIZE       16
49
50
51
52
53#define RECV_REG 0
54#define TRAN_REG 4
55#define STAT_REG 8
56#define CTRL_REG 12
57
58
59
60RTEMS_INLINE_ROUTINE uint32_t xlite_uart_control(uint32_t base)
61{
62  uint32_t c = *((volatile uint32_t*)(base+CTRL_REG));
63  return c;
64}
65
66
67RTEMS_INLINE_ROUTINE uint32_t xlite_uart_status(uint32_t base)
68{
69  uint32_t c = *((volatile uint32_t*)(base+STAT_REG));
70  return c;
71}
72
73
74RTEMS_INLINE_ROUTINE uint32_t xlite_uart_read(uint32_t base)
75{
76  uint32_t c = *((volatile uint32_t*)(base+RECV_REG));
77  return c;
78}
79
80
81RTEMS_INLINE_ROUTINE void xlite_uart_write(uint32_t base, char ch)
82{
83  *(volatile uint32_t*)(base+TRAN_REG) = (uint32_t)ch;
84  return;
85}
86
87
88
[dbf62b3]89static int xlite_write_char(uint32_t base, char ch)
[862c2317]90{
91   uint32_t  retrycount= 0, idler, status;
92
93   while( ((status = xlite_uart_status(base)) & TX_FIFO_FULL) != 0 )
94   {
95      ++retrycount;
96
97      /* uart tx is busy */
98      if( retrycount == 0x4000 )
99      {
100         /* retrycount is arbitrary- just make it big enough so the uart is sure to be timed out before it trips */
101         return -1;
102      }
103
104      /* spin for a bit so we can sample the register rather than
105       * continually reading it */
106      for( idler= 0; idler < 0x2000; idler++);
107   }
108
109   xlite_uart_write(base, ch);
110
111   return 1;
112}
113
[0a697dd9]114static void xlite_init(int minor )
115{
116   /* Nothing to do */
117}
[862c2317]118
[26c093e]119#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]120static void xlite_interrupt_handler(void *arg)
121{
122   int minor = (int) arg;
123   const console_tbl *ct = Console_Port_Tbl[minor];
124   console_data *cd = &Console_Port_Data[minor];
125   uint32_t base = ct->ulCtrlPort1;
126   uint32_t status = xlite_uart_status(base);
[862c2317]127
[0a697dd9]128   while ((status & RX_FIFO_VALID_DATA) != 0) {
129      char c = (char) xlite_uart_read(base);
[862c2317]130
[0a697dd9]131      rtems_termios_enqueue_raw_characters(cd->termios_data, &c, 1);
[862c2317]132
[0a697dd9]133      status = xlite_uart_status(base);
134   }
[862c2317]135
[0a697dd9]136   if (cd->bActive) {
137      rtems_termios_dequeue_characters(cd->termios_data, 1);
138   }
[862c2317]139}
[0a697dd9]140#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[862c2317]141
[dbf62b3]142static int xlite_open(
[862c2317]143  int      major,
144  int      minor,
145  void    *arg
146)
147{
[0a697dd9]148   const console_tbl *ct = Console_Port_Tbl[minor];
149   uint32_t base = ct->ulCtrlPort1;
[26c093e]150#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]151   rtems_status_code sc;
152#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[862c2317]153
154   /* clear status register */
155   *((volatile uint32_t*)(base+STAT_REG)) = 0;
156
[0a697dd9]157   /* clear control register; reset fifos */
[862c2317]158   *((volatile uint32_t*)(base+CTRL_REG)) = RST_RX_FIFO | RST_TX_FIFO;
159
[26c093e]160#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]161   *((volatile uint32_t*)(base+CTRL_REG)) = ENABLE_INTR;
[862c2317]162
[0a697dd9]163   sc = rtems_interrupt_handler_install(
164      ct->ulIntVector,
165      "xlite",
166      RTEMS_INTERRUPT_UNIQUE,
167      xlite_interrupt_handler,
168      (void *) minor
169   );
170   assert(sc == RTEMS_SUCCESSFUL);
171#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
172
173   return 0;
174}
[862c2317]175
[dbf62b3]176static int xlite_close(
[862c2317]177  int      major,
178  int      minor,
179  void    *arg
180)
181{
[0a697dd9]182   const console_tbl *ct = Console_Port_Tbl[minor];
183   uint32_t base = ct->ulCtrlPort1;
[26c093e]184#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]185   rtems_status_code sc;
186#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
187
188   *((volatile uint32_t*)(base+CTRL_REG)) = 0;
189
[26c093e]190#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]191   sc = rtems_interrupt_handler_remove(
192      ct->ulIntVector,
193      xlite_interrupt_handler,
194      (void *) minor
195   );
196   assert(sc == RTEMS_SUCCESSFUL);
197#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
198
199   return 0;
[862c2317]200}
201
202
203
[dbf62b3]204static int xlite_read_polled (int minor )
[862c2317]205{
[d5286a1f]206   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
[862c2317]207
208   unsigned int status = xlite_uart_status(base);
209
210   if(status & RX_FIFO_VALID_DATA)
211      return (int)xlite_uart_read(base);
212   else
213      return -1;
214}
215
[26c093e]216#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]217
218static ssize_t xlite_write_interrupt_driven(
219  int minor,
220  const char *buf,
221  size_t len
222)
223{
224  console_data *cd = &Console_Port_Data[minor];
[862c2317]225
[0a697dd9]226  if (len > 0) {
227    const console_tbl *ct = Console_Port_Tbl[minor];
228    uint32_t base = ct->ulCtrlPort1;
[862c2317]229
[0a697dd9]230    xlite_uart_write(base, buf[0]);
231
232    cd->bActive = true;
233  } else {
234    cd->bActive = false;
235  }
236
237  return 0;
238}
239
240#else /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[862c2317]241
[dbf62b3]242static ssize_t xlite_write_buffer_polled(
[862c2317]243  int         minor,
244  const char *buf,
[f16a1458]245  size_t      len
[862c2317]246)
247{
[d5286a1f]248   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
[862c2317]249   int nwrite = 0;
250
251   /*
252    * poll each byte in the string out of the port.
253    */
254   while (nwrite < len)
255   {
256      if( xlite_write_char(base, *buf++) < 0 ) break;
257      nwrite++;
258   }
259
260   /*
261    * return the number of bytes written.
262    */
263   return nwrite;
264}
265
[0a697dd9]266#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[862c2317]267
[dbf62b3]268static void xlite_write_char_polled(
[862c2317]269  int   minor,
270  char  c
271)
272{
[d5286a1f]273   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
[862c2317]274   xlite_write_char(base, c);
275   return;
276}
277
[dbf62b3]278static int xlite_set_attributes(int minor, const struct termios *t)
[862c2317]279{
280   return RTEMS_SUCCESSFUL;
281}
282
283
284
285
286
287
288
[dbf62b3]289static const console_fns xlite_fns_polled =
[862c2317]290{
[0a697dd9]291  .deviceProbe = libchip_serial_default_probe,
292  .deviceFirstOpen = xlite_open,
293  .deviceLastClose = xlite_close,
294  .deviceRead = xlite_read_polled,
295  .deviceInitialize = xlite_init,
296  .deviceWritePolled = xlite_write_char_polled,
297  .deviceSetAttributes = xlite_set_attributes,
[26c093e]298#if VIRTEX_CONSOLE_USE_INTERRUPTS
[0a697dd9]299  .deviceWrite = xlite_write_interrupt_driven,
300  .deviceOutputUsesInterrupts = true
[26c093e]301#else /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[0a697dd9]302  .deviceWrite = xlite_write_buffer_polled,
303  .deviceOutputUsesInterrupts = false
[26c093e]304#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
[862c2317]305};
306
307
308
309
310
311
312/*
313** Set ulCtrlPort1 to the base address of each UART Lite instance.  Set in vhdl model.
314*/
315
316
[d5286a1f]317console_tbl     Console_Configuration_Ports[] = {
[862c2317]318{
319  "/dev/ttyS0",                             /* sDeviceName */
320   SERIAL_CUSTOM,                           /* deviceType */
321   &xlite_fns_polled,                      /* pDeviceFns */
322   NULL,                                   /* deviceProbe, assume it is there */
323   NULL,                                   /* pDeviceFlow */
324   16,                                     /* ulMargin */
325   8,                                      /* ulHysteresis */
326   (void *) NULL,               /* NULL */ /* pDeviceParams */
[c607d50e]327   STDIN_BASEADDRESS,                      /* ulCtrlPort1 */
[862c2317]328   0,                                      /* ulCtrlPort2 */
329   0,                                      /* ulDataPort */
330   NULL,                                   /* getRegister */
331   NULL,                                   /* setRegister */
332   NULL, /* unused */                      /* getData */
333   NULL, /* unused */                      /* setData */
334   0,                                      /* ulClock */
[0a697dd9]335   #ifdef XPAR_XPS_INTC_0_RS232_UART_INTERRUPT_INTR
336     .ulIntVector = XPAR_XPS_INTC_0_RS232_UART_INTERRUPT_INTR
337   #else
338     .ulIntVector = 0
339   #endif
[862c2317]340},
[0110491]341#ifdef XPAR_UARTLITE_1_BASEADDR
[862c2317]342{
343  "/dev/ttyS1",                             /* sDeviceName */
344   SERIAL_CUSTOM,                           /* deviceType */
345   &xlite_fns_polled,                       /* pDeviceFns */
346   NULL,                                   /* deviceProbe, assume it is there */
347   NULL,                                   /* pDeviceFlow */
348   16,                                     /* ulMargin */
349   8,                                      /* ulHysteresis */
350   (void *) NULL,               /* NULL */ /* pDeviceParams */
[0110491]351   XPAR_UARTLITE_1_BASEADDR,               /* ulCtrlPort1 */
[862c2317]352   0,                                      /* ulCtrlPort2 */
353   0,                                      /* ulDataPort */
354   NULL,                                   /* getRegister */
355   NULL,                                   /* setRegister */
356   NULL, /* unused */                      /* getData */
357   NULL, /* unused */                      /* setData */
358   0,                                      /* ulClock */
359   0                                       /* ulIntVector -- base for port */
360},
[0110491]361#endif
362#ifdef XPAR_UARTLITE_2_BASEADDR
[862c2317]363{
364  "/dev/ttyS2",                             /* sDeviceName */
365   SERIAL_CUSTOM,                           /* deviceType */
366   &xlite_fns_polled,                       /* pDeviceFns */
367   NULL,                                   /* deviceProbe, assume it is there */
368   NULL,                                   /* pDeviceFlow */
369   16,                                     /* ulMargin */
370   8,                                      /* ulHysteresis */
371   (void *) NULL,               /* NULL */ /* pDeviceParams */
[0110491]372   XPAR_UARTLITE_2_BASEADDR,               /* ulCtrlPort1 */
[862c2317]373   0,                                      /* ulCtrlPort2 */
374   0,                                      /* ulDataPort */
375   NULL,                                   /* getRegister */
376   NULL,                                   /* setRegister */
377   NULL, /* unused */                      /* getData */
378   NULL, /* unused */                      /* setData */
379   0,                                      /* ulClock */
380   0                                       /* ulIntVector -- base for port */
381},
[0110491]382#endif
383#ifdef XPAR_UARTLITE_2_BASEADDR
[862c2317]384{
385  "/dev/ttyS3",                             /* sDeviceName */
386   SERIAL_CUSTOM,                           /* deviceType */
387   &xlite_fns_polled,                       /* pDeviceFns */
388   NULL,                                   /* deviceProbe, assume it is there */
389   NULL,                                   /* pDeviceFlow */
390   16,                                     /* ulMargin */
391   8,                                      /* ulHysteresis */
392   (void *) NULL,               /* NULL */ /* pDeviceParams */
[0110491]393   XPAR_UARTLITE_3_BASEADDR,               /* ulCtrlPort1 */
[862c2317]394   0,                                      /* ulCtrlPort2 */
395   0,                                      /* ulDataPort */
396   NULL,                                   /* getRegister */
397   NULL,                                   /* setRegister */
398   NULL, /* unused */                      /* getData */
399   NULL, /* unused */                      /* setData */
400   0,                                      /* ulClock */
401   0                                       /* ulIntVector -- base for port */
402}
[0110491]403#endif
[862c2317]404};
405
[0110491]406unsigned long Console_Configuration_Count =
407  RTEMS_ARRAY_SIZE(Console_Configuration_Ports);
[862c2317]408
409
410#include <rtems/bspIo.h>
411
[dbf62b3]412static void outputChar(char ch)
[862c2317]413{
414   xlite_write_char_polled( 0, ch );
415}
416
[dbf62b3]417static int inputChar(void)
[862c2317]418{
[f16a1458]419   return xlite_read_polled(0);
[862c2317]420}
421
422BSP_output_char_function_type BSP_output_char = outputChar;
423BSP_polling_getchar_function_type BSP_poll_char = inputChar;
424
425
Note: See TracBrowser for help on using the repository browser.