source: rtems/c/src/lib/libcpu/powerpc/mpc5xx/console-generic/console-generic.c @ 4216c57

4.104.114.95
Last change on this file since 4216c57 was 4216c57, checked in by Joel Sherrill <joel.sherrill@…>, on 12/04/07 at 22:19:37

2007-12-04 Joel Sherrill <joel.sherrill@…>

  • mpc5xx/console-generic/console-generic.c, mpc8260/timer/timer.c, new-exceptions/cpu.c, old-exceptions/cpu.c: Move interrupt_stack_size field from CPU Table to Configuration Table. Eliminate CPU Table from all ports. Delete references to CPU Table in all forms.
  • Property mode set to 100644
File size: 7.9 KB
Line 
1/*
2 *  General Serial I/O functions.
3 *
4 *  This file contains the functions for performing serial I/O.  The actual
5 *  system calls (console_*) should be in the BSP part of the source tree.
6 *  That way different BSPs can use whichever SCI they wish for /dev/console.
7 *
8 *  On-chip resources used:
9 *   resource   minor                note
10 *      SCI1      0
11 *      SCI2      1
12 *
13 *
14 *  MPC5xx port sponsored by Defence Research and Development Canada - Suffield
15 *  Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
16 *
17 *  Derived from
18 *    c/src/lib/libcpu/powerpc/mpc8xx/console_generic/console_generic.c:
19 *  Author: Jay Monkman (jmonkman@frasca.com)
20 *  Copyright (C) 1998 by Frasca International, Inc.
21 *
22 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by:
23 *    W. Eric Norum
24 *    Saskatchewan Accelerator Laboratory
25 *    University of Saskatchewan
26 *    Saskatoon, Saskatchewan, CANADA
27 *    eric@skatter.usask.ca
28 *
29 *  COPYRIGHT (c) 1989-1998.
30 *  On-Line Applications Research Corporation (OAR).
31 *
32 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
33 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
34 *  Copyright (c) 1999, National Research Council of Canada
35 *
36 *  The license and distribution terms for this file may be
37 *  found in the file LICENSE in this distribution or at
38 *
39 *  http://www.rtems.com/license/LICENSE.
40 *
41 *  $Id$
42 */
43
44#include <stdlib.h>
45#include <unistd.h>
46#include <termios.h>
47#include <rtems.h>
48#include <rtems/libio.h>
49#include <rtems/bspIo.h>   /* for printk */
50#include <mpc5xx.h>
51#include <mpc5xx/console.h>
52#include <libcpu/irq.h>
53
54
55/*
56 * SCI port descriptor table.
57 */
58typedef struct
59{
60  volatile m5xxSCIRegisters_t *regs;    /* hardware registers */
61  struct rtems_termios_tty *ttyp;       /* termios data for this port */
62} sci_desc;
63
64static sci_desc sci_descs[] = {
65  { &imb.qsmcm.sci1, 0 },               /* SCI 1 */
66  { &imb.qsmcm.sci2, 0 },               /* SCI 2 */
67};
68
69/*
70 * Number of SCI port initialization calls made so far.  Used to avoid
71 * installing the common interrupt handler more than once.
72 */
73int init_calls = 0;
74
75/*
76 * Default configuration.
77 */
78static struct termios default_termios = {
79  0,                                    /* input mode flags */
80  0,                                    /* output mode flags */
81  CS8 | CREAD | CLOCAL | B9600,         /* control mode flags */
82  0,                                    /* local mode flags */
83  0,                                    /* line discipline */
84  { 0 }                                 /* control characters */
85};
86
87 
88/*
89 * Termios callback functions
90 */
91
92int
93m5xx_uart_firstOpen(
94  int major,
95  int minor,
96  void *arg
97)
98{
99  rtems_libio_open_close_args_t *args = arg;
100  sci_desc* desc = &sci_descs[minor];
101  struct rtems_termios_tty *tty = args->iop->data1;
102
103  desc->ttyp = tty;                             /* connect tty */
104  if ( tty->device.outputUsesInterrupts == TERMIOS_IRQ_DRIVEN)
105    desc->regs->sccr1 |= QSMCM_SCI_RIE;         /* enable rx interrupt */
106
107  return RTEMS_SUCCESSFUL;
108}
109
110int
111m5xx_uart_lastClose(
112  int major,
113  int minor,
114  void* arg
115)
116{
117  sci_desc* desc = &sci_descs[minor];
118
119  desc->regs->sccr1 &= ~(QSMCM_SCI_RIE | QSMCM_SCI_TIE);  /* disable all */
120  desc->ttyp = NULL;                                      /* disconnect tty */
121
122  return RTEMS_SUCCESSFUL;
123}
124
125int
126m5xx_uart_pollRead(
127  int minor
128)
129{
130  volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
131  int c = -1;
132 
133  if ( regs ) {
134    while ( (regs->scsr & QSMCM_SCI_RDRF) == 0 )
135      ;
136    c = regs->scdr;
137  }
138
139  return c;
140}
141
142int
143m5xx_uart_write(
144  int minor,
145  const char *buf,
146  int len
147)
148{
149  volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
150
151  regs->scdr = *buf;                    /* start transmission */
152  regs->sccr1 |= QSMCM_SCI_TIE;         /* enable interrupt */
153  return 0;
154}
155
156int
157m5xx_uart_pollWrite(
158  int minor,
159  const char *buf,
160  int len
161)
162{
163  volatile m5xxSCIRegisters_t *regs = sci_descs[minor].regs;
164
165  while ( len-- ) {
166    while ( (regs->scsr & QSMCM_SCI_TDRE) == 0 )
167      ;
168    regs->scdr = *buf++;
169  }
170  return 0;
171}
172
173void
174m5xx_uart_reserve_resources(
175  rtems_configuration_table *configuration
176)
177{
178  rtems_termios_reserve_resources (configuration, NUM_PORTS);
179}
180
181int
182m5xx_uart_setAttributes(
183  int minor,
184  const struct termios *t
185)
186{
187  uint16_t sccr0 = sci_descs[minor].regs->sccr0;
188  uint16_t sccr1 = sci_descs[minor].regs->sccr1;
189  int baud;
190 
191  /*
192   * Check that port number is valid
193   */
194  if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
195    return RTEMS_INVALID_NUMBER;
196
197  /* Baud rate */
198  switch (t->c_cflag & CBAUD) {
199    default:      baud = -1;      break;
200    case B50:     baud = 50;      break;
201    case B75:     baud = 75;      break;
202    case B110:    baud = 110;     break;
203    case B134:    baud = 134;     break;
204    case B150:    baud = 150;     break;
205    case B200:    baud = 200;     break;
206    case B300:    baud = 300;     break;
207    case B600:    baud = 600;     break;
208    case B1200:   baud = 1200;    break;
209    case B1800:   baud = 1800;    break;
210    case B2400:   baud = 2400;    break;
211    case B4800:   baud = 4800;    break;
212    case B9600:   baud = 9600;    break;
213    case B19200:  baud = 19200;   break;
214    case B38400:  baud = 38400;   break;
215    case B57600:  baud = 57600;   break;
216    case B115200: baud = 115200;  break;
217    case B230400: baud = 230400;  break;
218    case B460800: baud = 460800;  break;
219  }
220  if (baud > 0) {
221    extern uint32_t bsp_clock_speed;
222    sccr0 &= ~QSMCM_SCI_BAUD(-1);
223    sccr0 |=
224      QSMCM_SCI_BAUD((bsp_clock_speed + (16 * baud)) / (32 * baud));
225  }
226     
227  /* Number of data bits -- not available with MPC5xx SCI */
228  switch ( t->c_cflag & CSIZE ) {
229    case CS5:     break;
230    case CS6:     break;
231    case CS7:     break;
232    case CS8:     break;
233  }
234
235  /* Stop bits -- not easily available with MPC5xx SCI */
236  if ( t->c_cflag & CSTOPB ) {
237    /* Two stop bits */
238  } else {
239    /* One stop bit */
240  }
241
242  /* Parity */
243  if ( t->c_cflag & PARENB )
244    sccr1 |= QSMCM_SCI_PE;
245  else
246    sccr1 &= ~QSMCM_SCI_PE;
247 
248  if ( t->c_cflag & PARODD )
249    sccr1 |= QSMCM_SCI_PT;
250  else
251    sccr1 &= ~QSMCM_SCI_PT;
252
253  /* Transmitter and receiver enable */
254  sccr1 |= QSMCM_SCI_TE;
255  if ( t->c_cflag & CREAD )
256    sccr1 |= QSMCM_SCI_RE;
257  else
258    sccr1 &= ~QSMCM_SCI_RE;
259   
260  /* Write hardware registers */
261  sci_descs[minor].regs->sccr0 = sccr0;
262  sci_descs[minor].regs->sccr1 = sccr1;
263 
264  return RTEMS_SUCCESSFUL;
265}
266
267
268/*
269 * Interrupt handling.
270 */
271static void
272m5xx_sci_interrupt_handler (rtems_irq_hdl_param unused)
273{
274  int minor;
275 
276  for ( minor = 0; minor < NUM_PORTS; minor++ ) {
277    sci_desc *desc = &sci_descs[minor];
278    int sccr1 = desc->regs->sccr1;
279    int scsr = desc->regs->scsr;
280       
281    /*
282     * Character received?
283     */
284    if ((sccr1 & QSMCM_SCI_RIE) && (scsr & QSMCM_SCI_RDRF)) {
285      char c = desc->regs->scdr;
286      rtems_termios_enqueue_raw_characters(desc->ttyp, &c, 1);
287    }
288    /*
289     * Transmitter empty?
290     */
291    if ((sccr1 & QSMCM_SCI_TIE) && (scsr & QSMCM_SCI_TDRE)) {
292      desc->regs->sccr1 &= ~QSMCM_SCI_TIE;
293      rtems_termios_dequeue_characters (desc->ttyp, 1);
294    }
295  }
296}
297
298void m5xx_sci_nop(const rtems_irq_connect_data* ptr)
299{
300}
301
302int m5xx_sci_isOn(const rtems_irq_connect_data* ptr)
303{
304  return 1;
305}
306
307/*
308 * Basic initialization.
309 */
310
311void
312m5xx_uart_initialize (int minor)
313{
314  /*
315   * Check that minor number is valid.
316   */
317  if ( (minor < SCI1_MINOR) || (minor > SCI2_MINOR) )
318    return;
319
320  /*
321   * Configure and enable receiver and transmitter.
322   */
323  m5xx_uart_setAttributes(minor, &default_termios);
324   
325  /*
326   * Connect interrupt if not yet done.
327   */
328  if ( init_calls++ == 0 ) {
329    rtems_irq_connect_data irq_data;
330
331    irq_data.name = CPU_IRQ_SCI;
332    irq_data.hdl  = m5xx_sci_interrupt_handler;
333    irq_data.on   = m5xx_sci_nop;       /* can't enable both channels here */
334    irq_data.off  = m5xx_sci_nop;       /* can't disable both channels here */
335    irq_data.isOn = m5xx_sci_isOn;
336   
337    if (!CPU_install_rtems_irq_handler (&irq_data)) {
338      printk("Unable to connect SCI Irq handler\n");
339      rtems_fatal_error_occurred(1);
340    }
341
342    imb.qsmcm.qdsci_il =                /* set interrupt level in port */
343      QSMCM_ILDSCI(CPU_irq_level_from_symbolic_name(CPU_IRQ_SCI));
344  }
345}
Note: See TracBrowser for help on using the repository browser.