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

4.104.114.84.95
Last change on this file since e9ae97fb was e9ae97fb, checked in by Joel Sherrill <joel.sherrill@…>, on Nov 9, 2001 at 12:04:57 AM

2001-11-08 Dennis Ehlin (ECS) <Dennis.Ehlin@…>

This modification is part of the submitted modifications necessary to
support the IBM PPC405 family. This submission was reviewed by
Thomas Doerfler <Thomas.Doerfler@…> who ensured it did
not negatively impact the ppc403 BSPs. The submission and tracking
process was captured as PR50.

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