source: rtems/c/src/lib/libcpu/powerpc/ppc403/console/console405.c @ fc22287

4.11
Last change on this file since fc22287 was fc22287, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 15, 2014 at 7:24:06 PM

libcpu/powerpc/ppc403/console/console405.c: Fix warnings

  • Property mode set to 100644
File size: 13.9 KB
Line 
1/*
2 *  This file contains the PowerPC 405GP console IO package.
3 */
4
5/*
6 *  Author:     Thomas Doerfler <td@imd.m.isar.de>
7 *              IMD Ingenieurbuero fuer Microcomputertechnik
8 *
9 *  COPYRIGHT (c) 1998 by IMD
10 *
11 *  Changes from IMD are covered by the original distributions terms.
12 *  changes include interrupt support and termios support
13 *  for backward compatibility, the original polled driver has been
14 *  renamed to console.c.polled
15 *
16 *  This file has been initially created (polled version) by
17 *
18 *  Author:     Andrew Bray <andy@i-cubed.co.uk>
19 *
20 *  COPYRIGHT (c) 1995 by i-cubed ltd.
21 *
22 *  To anyone who acknowledges that this file is provided "AS IS"
23 *  without any express or implied warranty:
24 *      permission to use, copy, modify, and distribute this file
25 *      for any purpose is hereby granted without fee, provided that
26 *      the above copyright notice and this notice appears in all
27 *      copies, and that the name of i-cubed limited not be used in
28 *      advertising or publicity pertaining to distribution of the
29 *      software without specific, written prior permission.
30 *      i-cubed limited makes no representations about the suitability
31 *      of this software for any purpose.
32 *
33 *  Modifications for spooling (interrupt driven) console driver
34 *            by Thomas Doerfler <td@imd.m.isar.de>
35 *  for these modifications:
36 *  COPYRIGHT (c) 1997 by IMD, Puchheim, Germany.
37 *
38 *
39 *  To anyone who acknowledges that this file is provided "AS IS"
40 *  without any express or implied warranty:
41 *      permission to use, copy, modify, and distribute this file
42 *      for any purpose is hereby granted without fee, provided that
43 *      the above copyright notice and this notice appears in all
44 *      copies. IMD makes no representations about the suitability
45 *      of this software for any purpose.
46 *
47 *  Derived from c/src/lib/libbsp/no_cpu/no_bsp/console/console.c:
48 *
49 *  COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994.
50 *  On-Line Applications Research Corporation (OAR).
51 *
52 *  Modifications for PPC405GP by Dennis Ehlin
53 */
54
55#define NO_BSP_INIT
56
57#include <rtems.h>
58#include <rtems/libio.h>
59#include "../irq/ictrl.h"
60#include <stdlib.h>                                     /* for atexit() */
61#include <rtems/console.h>
62
63struct async {
64/*---------------------------------------------------------------------------+
65| Data Register.
66+---------------------------------------------------------------------------*/
67  unsigned char RBR;    /* 0x00 */
68  #define THR   RBR
69/*---------------------------------------------------------------------------+
70| Interrupt registers
71+---------------------------------------------------------------------------*/
72  unsigned char IER;    /* 0x01 */
73  #define IER_RCV                0x01
74  #define IER_XMT                0x02
75  #define IER_LS                 0x04
76  #define IER_MS                 0x08
77
78  unsigned char ISR;    /* 0x02 */
79  #define ISR_MS                 0x00
80  #define ISR_nIP                0x01
81  #define ISR_Tx                 0x02
82  #define ISR_Rx                 0x04
83  #define ISR_LS                 0x06
84  #define ISR_RxTO               0x0C
85  #define ISR_64BFIFO            0x20
86  #define ISR_FIFOworks          0x40
87  #define ISR_FIFOen             0x80
88
89/*---------------------------------------------------------------------------+
90| FIFO Control registers
91+---------------------------------------------------------------------------*/
92  #define FCR   ISR
93  #define FCR_FE                0x01    /* FIFO enable */
94  #define FCR_CRF               0x02    /* Clear receive FIFO */
95  #define FCR_CTF               0x04    /* Clear transmit FIFO */
96  #define FCR_DMA               0x08    /* DMA mode select */
97  #define FCR_F64               0x20    /* Enable 64 byte fifo (16750+) */
98  #define FCR_RT14              0xC0    /* Set Rx trigger at 14 */
99  #define FCR_RT8               0x80    /* Set Rx trigger at 8 */
100  #define FCR_RT4               0x40    /* Set Rx trigger at 4 */
101  #define FCR_RT1               0x00    /* Set Rx trigger at 1 */
102
103/*---------------------------------------------------------------------------+
104| Baud rate divisor registers
105+---------------------------------------------------------------------------*/
106  #define DLL   RBR
107  #define DLM   IER
108
109/*---------------------------------------------------------------------------+
110| Alternate function registers
111+---------------------------------------------------------------------------*/
112  #define AFR   ISR
113
114/*---------------------------------------------------------------------------+
115| Line control Register.
116+---------------------------------------------------------------------------*/
117  unsigned char LCR;    /* 0x03 */
118  #define LCR_WL5                0x00   /* Word length 5 */
119  #define LCR_WL6                0x01   /* Word length 6 */
120  #define LCR_WL7                0x02   /* Word length 7 */
121  #define LCR_WL8                0x03   /* Word length 8 */
122
123  #define LCR_SB1                0x00   /* 1 stop bits */
124  #define LCR_SB1_5              0x04   /* 1.5 stop bits , only valid with 5 bit words*/
125  #define LCR_SB1_5              0x04   /* 2 stop bits */
126
127  #define LCR_PN                 0x00   /* Parity NONE */
128  #define LCR_PE                 0x0C   /* Parity EVEN */
129  #define LCR_PO                 0x08   /* Parity ODD */
130  #define LCR_PM                 0x28   /* Forced "mark" parity */
131  #define LCR_PS                 0x38   /* Forced "space" parity */
132
133  #define LCR_DL                 0x80   /* Enable baudrate latch */
134
135/*---------------------------------------------------------------------------+
136| Modem control Register.
137+---------------------------------------------------------------------------*/
138  unsigned char MCR;    /* 0x04 */
139  #define MCR_DTR                0x01
140  #define MCR_RTS                0x02
141  #define MCR_INT                0x08   /* Enable interrupts */
142  #define MCR_LOOP               0x10   /* Loopback mode */
143
144/*---------------------------------------------------------------------------+
145| Line status Register.
146+---------------------------------------------------------------------------*/
147  unsigned char LSR;    /* 0x05 */
148  #define LSR_RSR                0x01
149  #define LSR_OE                 0x02
150  #define LSR_PE                 0x04
151  #define LSR_FE                 0x08
152  #define LSR_BI                 0x10
153  #define LSR_THE                0x20
154  #define LSR_TEMT               0x40
155  #define LSR_FIE                0x80
156
157/*---------------------------------------------------------------------------+
158| Modem status Register.
159+---------------------------------------------------------------------------*/
160  unsigned char MSR;    /* 0x06 */
161  #define UART_MSR_DCTS          0x01
162  #define UART_MSR_DDSR          0x02
163  #define UART_MSR_TERI          0x04
164  #define UART_MSR_DDCD          0x08
165  #define UART_MSR_CTS           0x10
166  #define UART_MSR_DSR           0x20
167  #define UART_MSR_RI            0x40
168  #define UART_MSR_CD            0x80
169
170/*---------------------------------------------------------------------------+
171| Scratch pad Register.
172+---------------------------------------------------------------------------*/
173  unsigned char SCR;    /* 0x07 */
174};
175
176
177#define USE_UART 0 /* 0=UART0 1=UART1 */
178#define UART_INTERNAL_CLOCK_DIVISOR 16
179
180typedef volatile struct async *pasync;
181static const pasync port = (pasync)(0xEF600300   + (USE_UART*0x100));   /* 0xEF600300 - port A,  0xEF600400 - port B */
182
183static void *spittyp;         /* handle for termios */
184int ppc403_spi_interrupt = 0; /* do not use interrupts... */
185
186extern uint32_t bsp_serial_per_sec;
187extern uint32_t bsp_serial_rate;
188extern bool bsp_serial_external_clock;
189
190static int spiBaudRound(double x)
191{
192  return (int)((int)((x-(int)x)*1000)>500 ? x+1 : x);
193}
194
195static void
196spiBaudSet(uint32_t   baudrate)
197{
198  uint32_t   tmp;
199
200  tmp = spiBaudRound( (double)bsp_serial_per_sec / (baudrate * 16) );
201
202  port->LCR = port->LCR | LCR_DL;
203
204  port->DLL = tmp & 0xff;
205  port->DLM = tmp >> 8;
206
207  port->LCR = port->LCR & ~LCR_DL;
208}
209/*
210 * Hardware-dependent portion of tcsetattr().
211 */
212static int
213spiSetAttributes (int minor, const struct termios *t)
214{
215  int baud;
216
217  /* FIXME: check c_cflag & CRTSCTS for hardware flowcontrol */
218  /* FIXME: check and IMPLEMENT XON/XOFF                     */
219  switch (t->c_cflag & CBAUD) {
220  default:      baud = -1;      break;
221  case B50:     baud = 50;      break;
222  case B75:     baud = 75;      break;
223  case B110:    baud = 110;     break;
224  case B134:    baud = 134;     break;
225  case B150:    baud = 150;     break;
226  case B200:    baud = 200;     break;
227  case B300:    baud = 300;     break;
228  case B600:    baud = 600;     break;
229  case B1200:   baud = 1200;    break;
230  case B1800:   baud = 1800;    break;
231  case B2400:   baud = 2400;    break;
232  case B4800:   baud = 4800;    break;
233  case B9600:   baud = 9600;    break;
234  case B19200:  baud = 19200;   break;
235  case B38400:  baud = 38400;   break;
236  case B57600:  baud = 57600;   break;
237  case B115200: baud = 115200;  break;
238  case B230400: baud = 230400;  break;
239  case B460800: baud = 460800;  break;
240  }
241  if (baud > 0) {
242    spiBaudSet(baud);
243  }
244  return 0;
245}
246
247static int
248spiPollRead (int minor)
249{
250
251  /* Wait for character */
252  while ((port->LSR & LSR_RSR)==0);
253
254  return port->RBR;
255}
256
257static ssize_t
258spiPollWrite(int minor, const char *buf, size_t len)
259{
260
261  while (len-- > 0) {
262    while (!(port->LSR & LSR_THE));
263    port->THR = *buf++;
264  }
265  return 0;
266}
267
268/*
269 * enable/disable RTS line to start/stop remote transmitter
270 */
271static int
272spiStartRemoteTx (int minor)
273{
274/* Not implemented !
275  rtems_interrupt_level level;
276
277  rtems_interrupt_disable (level);
278  port->SPCTL |= CRRts;            activate RTS
279  rtems_interrupt_enable (level);
280*/
281  return 0;
282}
283
284static int
285spiStopRemoteTx (int minor)
286{
287/* Not implemented !
288  rtems_interrupt_level level;
289
290  rtems_interrupt_disable (level);
291  port->SPCTL &= ~CRRts;            deactivate RTS
292  rtems_interrupt_enable (level);
293*/
294  return 0;
295}
296
297static ssize_t InterruptWrite (int minor, const char *buf, size_t len)
298{
299  if (len > 0) {
300    port->IER |= IER_XMT;     /* always enable tx interrupt */
301    port->THR = *buf;       /* write char to send         */
302  }
303
304  return 0;
305}
306
307static rtems_isr serial_ISR(rtems_vector_number v)
308{
309  unsigned char _isr;
310  char ch;
311  int res;
312
313  _isr=port->ISR & 0x0E;
314
315   if ((_isr == ISR_Rx) || (_isr==ISR_RxTO)) {
316        ch = port->RBR;
317        rtems_termios_enqueue_raw_characters (spittyp,&ch,1);
318   }
319
320   if (_isr == ISR_Tx) {
321        res = rtems_termios_dequeue_characters (spittyp,1);
322        if (res==0) {
323                port->IER &= ~IER_XMT;
324                }
325
326   }
327}
328
329/*
330 * deinit SPI
331 */
332static void
333spiDeInit(void)
334{
335  /*
336   * disable interrupts for serial port
337   * set it to state to work with polling boot monitor, if any...
338   */
339
340  /* set up baud rate to original state */
341  spiBaudSet(bsp_serial_rate);
342
343  port->IER = 0;
344}
345
346/*
347 * init SPI
348 */
349static rtems_status_code
350spiInitialize(void)
351{
352  register unsigned tmp;
353  rtems_isr_entry previous_isr; /* this is a dummy */
354  unsigned char _ier;
355
356  /*
357   * Initialise the serial port
358   */
359
360  /*
361   * Select clock source and set uart internal clock divisor
362   */
363
364  __asm__ volatile ("mfdcr %0, 0x0b1" : "=r" (tmp)); /* CPC_CR0 0x0b1 */
365
366  /* UART0 bit 24 0x80, UART1 bit 25 0x40 */
367  tmp |= (bsp_serial_external_clock ?  (USE_UART ? 0x40 : 0x80) : 0);
368
369  tmp |= (bsp_serial_external_clock ?  0: ((UART_INTERNAL_CLOCK_DIVISOR -1) << 1));
370
371  __asm__ volatile ("mtdcr 0x0b1, %0" : "=r" (tmp) : "0" (tmp)); /* CPC_CR0 0x0b1*/
372
373  /* Disable port interrupts while changing hardware */
374  _ier = port->IER;
375  port->IER = 0;
376
377  /* set up port control: 8 bit,1 stop,no parity */
378  port->LCR = LCR_WL8 | LCR_SB1 | LCR_PN;
379
380  /* set up baud rate */
381  spiBaudSet(bsp_serial_rate);
382
383  if (ppc403_spi_interrupt) {
384
385    /* add rx/tx isr to vector table */
386    if (USE_UART==0)
387        ictrl_set_vector(serial_ISR,PPC_IRQ_EXT_UART0,&previous_isr);
388    else
389        ictrl_set_vector(serial_ISR,PPC_IRQ_EXT_UART1,&previous_isr);
390
391    /* Enable and clear FIFO */
392    port->FCR = FCR_FE | FCR_CRF | FCR_CTF | FCR_RT8;
393
394    /* Enable recive interrupts, don't enable TxInt yet */
395    port->IER=IER_RCV;
396  }
397  else {
398    port->IER=_ier;
399  }
400
401  atexit(spiDeInit);
402
403  return RTEMS_SUCCESSFUL;
404}
405
406/*
407 ***************
408 * BOILERPLATE *
409 ***************
410 */
411
412/*  console_initialize
413 *
414 *  This routine initializes the console IO driver.
415 *
416 *  Input parameters: NONE
417 *
418 *  Output parameters:  NONE
419 *
420 *  Return values:
421 */
422
423rtems_device_driver console_initialize(
424  rtems_device_major_number  major,
425  rtems_device_minor_number  minor,
426  void                      *arg
427)
428{
429  rtems_status_code status;
430
431  /*
432   * Set up TERMIOS
433   */
434  rtems_termios_initialize ();
435
436  /*
437   * Do device-specific initialization
438   */
439  spiInitialize ();
440
441  /*
442   * Register the device
443   */
444  status = rtems_io_register_name ("/dev/console", major, 0);
445  if (status != RTEMS_SUCCESSFUL)
446    rtems_fatal_error_occurred (status);
447  return RTEMS_SUCCESSFUL;
448}
449
450/*
451 *  Open entry point
452 */
453rtems_device_driver console_open(
454  rtems_device_major_number major,
455  rtems_device_minor_number minor,
456  void                    * arg
457)
458{
459  rtems_status_code sc;
460  static const rtems_termios_callbacks intrCallbacks = {
461    NULL,               /* firstOpen */
462    NULL,               /* lastClose */
463    NULL,               /* pollRead */
464    InterruptWrite,     /* write */
465    spiSetAttributes,   /* setAttributes */
466    spiStopRemoteTx,    /* stopRemoteTx */
467    spiStartRemoteTx,   /* startRemoteTx */
468    1                   /* outputUsesInterrupts */
469  };
470
471  static const rtems_termios_callbacks pollCallbacks = {
472    NULL,               /* firstOpen */
473    NULL,               /* lastClose */
474    spiPollRead,        /* pollRead */
475    spiPollWrite,       /* write */
476    spiSetAttributes,   /* setAttributes */
477    spiStopRemoteTx,    /* stopRemoteTx */
478    spiStartRemoteTx,   /* startRemoteTx */
479    0                   /* outputUsesInterrupts */
480  };
481
482  if (ppc403_spi_interrupt) {
483    rtems_libio_open_close_args_t *args = arg;
484    sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
485    spittyp = args->iop->data1;
486  }
487  else {
488    sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
489  }
490  return sc;
491}
492
493/*
494 *  Close entry point
495 */
496rtems_device_driver console_close(
497  rtems_device_major_number major,
498  rtems_device_minor_number minor,
499  void                    * arg
500)
501{
502  return rtems_termios_close (arg);
503}
504
505/*
506 * read bytes from the serial port. We only have stdin.
507 */
508rtems_device_driver console_read(
509  rtems_device_major_number major,
510  rtems_device_minor_number minor,
511  void                    * arg
512)
513{
514  return rtems_termios_read (arg);
515}
516
517/*
518 * write bytes to the serial port. Stdout and stderr are the same.
519 */
520rtems_device_driver console_write(
521  rtems_device_major_number major,
522  rtems_device_minor_number minor,
523  void                    * arg
524)
525{
526  return rtems_termios_write (arg);
527}
528
529/*
530 *  IO Control entry point
531 */
532rtems_device_driver console_control(
533  rtems_device_major_number major,
534  rtems_device_minor_number minor,
535  void                    * arg
536)
537{
538  return rtems_termios_ioctl (arg);
539}
Note: See TracBrowser for help on using the repository browser.