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 Apr 19, 2018 at 4:28:01 AM

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
Line 
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
14 *  http://www.rtems.org/license/LICENSE.
15 *
16 */
17
18#include <assert.h>
19
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
28#include RTEMS_XPARAMETERS_H
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
89static int xlite_write_char(uint32_t base, char ch)
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
114static void xlite_init(int minor )
115{
116   /* Nothing to do */
117}
118
119#if VIRTEX_CONSOLE_USE_INTERRUPTS
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);
127
128   while ((status & RX_FIFO_VALID_DATA) != 0) {
129      char c = (char) xlite_uart_read(base);
130
131      rtems_termios_enqueue_raw_characters(cd->termios_data, &c, 1);
132
133      status = xlite_uart_status(base);
134   }
135
136   if (cd->bActive) {
137      rtems_termios_dequeue_characters(cd->termios_data, 1);
138   }
139}
140#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
141
142static int xlite_open(
143  int      major,
144  int      minor,
145  void    *arg
146)
147{
148   const console_tbl *ct = Console_Port_Tbl[minor];
149   uint32_t base = ct->ulCtrlPort1;
150#if VIRTEX_CONSOLE_USE_INTERRUPTS
151   rtems_status_code sc;
152#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
153
154   /* clear status register */
155   *((volatile uint32_t*)(base+STAT_REG)) = 0;
156
157   /* clear control register; reset fifos */
158   *((volatile uint32_t*)(base+CTRL_REG)) = RST_RX_FIFO | RST_TX_FIFO;
159
160#if VIRTEX_CONSOLE_USE_INTERRUPTS
161   *((volatile uint32_t*)(base+CTRL_REG)) = ENABLE_INTR;
162
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}
175
176static int xlite_close(
177  int      major,
178  int      minor,
179  void    *arg
180)
181{
182   const console_tbl *ct = Console_Port_Tbl[minor];
183   uint32_t base = ct->ulCtrlPort1;
184#if VIRTEX_CONSOLE_USE_INTERRUPTS
185   rtems_status_code sc;
186#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
187
188   *((volatile uint32_t*)(base+CTRL_REG)) = 0;
189
190#if VIRTEX_CONSOLE_USE_INTERRUPTS
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;
200}
201
202
203
204static int xlite_read_polled (int minor )
205{
206   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
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
216#if VIRTEX_CONSOLE_USE_INTERRUPTS
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];
225
226  if (len > 0) {
227    const console_tbl *ct = Console_Port_Tbl[minor];
228    uint32_t base = ct->ulCtrlPort1;
229
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 */
241
242static ssize_t xlite_write_buffer_polled(
243  int         minor,
244  const char *buf,
245  size_t      len
246)
247{
248   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
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
266#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
267
268static void xlite_write_char_polled(
269  int   minor,
270  char  c
271)
272{
273   uint32_t base = Console_Port_Tbl[minor]->ulCtrlPort1;
274   xlite_write_char(base, c);
275   return;
276}
277
278static int xlite_set_attributes(int minor, const struct termios *t)
279{
280   return RTEMS_SUCCESSFUL;
281}
282
283
284
285
286
287
288
289static const console_fns xlite_fns_polled =
290{
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,
298#if VIRTEX_CONSOLE_USE_INTERRUPTS
299  .deviceWrite = xlite_write_interrupt_driven,
300  .deviceOutputUsesInterrupts = true
301#else /* VIRTEX_CONSOLE_USE_INTERRUPTS */
302  .deviceWrite = xlite_write_buffer_polled,
303  .deviceOutputUsesInterrupts = false
304#endif /* VIRTEX_CONSOLE_USE_INTERRUPTS */
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
317console_tbl     Console_Configuration_Ports[] = {
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 */
327   STDIN_BASEADDRESS,                      /* ulCtrlPort1 */
328   0,                                      /* ulCtrlPort2 */
329   0,                                      /* ulDataPort */
330   NULL,                                   /* getRegister */
331   NULL,                                   /* setRegister */
332   NULL, /* unused */                      /* getData */
333   NULL, /* unused */                      /* setData */
334   0,                                      /* ulClock */
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
340},
341#ifdef XPAR_UARTLITE_1_BASEADDR
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 */
351   XPAR_UARTLITE_1_BASEADDR,               /* ulCtrlPort1 */
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},
361#endif
362#ifdef XPAR_UARTLITE_2_BASEADDR
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 */
372   XPAR_UARTLITE_2_BASEADDR,               /* ulCtrlPort1 */
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},
382#endif
383#ifdef XPAR_UARTLITE_2_BASEADDR
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 */
393   XPAR_UARTLITE_3_BASEADDR,               /* ulCtrlPort1 */
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}
403#endif
404};
405
406unsigned long Console_Configuration_Count =
407  RTEMS_ARRAY_SIZE(Console_Configuration_Ports);
408
409
410#include <rtems/bspIo.h>
411
412static void outputChar(char ch)
413{
414   xlite_write_char_polled( 0, ch );
415}
416
417static int inputChar(void)
418{
419   return xlite_read_polled(0);
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.