source: rtems/c/src/lib/libcpu/powerpc/mpc8xx/console-generic/console-generic.c @ 8c49701

4.104.114.84.95
Last change on this file since 8c49701 was 8c49701, checked in by Joel Sherrill <joel.sherrill@…>, on Oct 18, 2000 at 3:46:07 PM

2000-10-18 Joel Sherrill <joel@…>

  • mpc8xx/console-generic/console-generic.c: Removed include of <bsp.h> by adding BSP dependent routine mbx8xx_console_use_maximum_buffer_size() which can be hard coded or check non-volatile memory for configuration.
  • Property mode set to 100644
File size: 32.2 KB
Line 
1/*
2 *  General Serial I/O functions.
3 *
4 *  This file contains the functions for performing serial I/O.
5 *  The actual system calls (console_*) should be in the BSP part
6 *  of the source tree. That way different BSPs can use whichever
7 *  SMCs and SCCs they want. Originally, all the stuff was in
8 *  this file, and it caused problems with one BSP using SCC2
9 *  as /dev/console, others using SMC1 for /dev/console, etc.
10 *
11 *  On-chip resources used:
12 *   resource   minor                note
13 *    SMC1       0
14 *    SMC2       1
15 *    SCC1       2                   N/A. Hardwired as ethernet port
16 *    SCC2       3
17 *    SCC3       4
18 *    SCC4       5
19 *    BRG1
20 *    BRG2
21 *    BRG3
22 *    BRG4
23 *  Author: Jay Monkman (jmonkman@frasca.com)
24 *  Copyright (C) 1998 by Frasca International, Inc.
25 *
26 *  Derived from c/src/lib/libbsp/m68k/gen360/console/console.c written by:
27 *    W. Eric Norum
28 *    Saskatchewan Accelerator Laboratory
29 *    University of Saskatchewan
30 *    Saskatoon, Saskatchewan, CANADA
31 *    eric@skatter.usask.ca
32 *
33 *  COPYRIGHT (c) 1989-1998.
34 *  On-Line Applications Research Corporation (OAR).
35 *
36 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
37 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>
38 *  Copyright (c) 1999, National Research Council of Canada
39 *
40 *  The license and distribution terms for this file may be
41 *  found in the file LICENSE in this distribution or at
42 *
43 *  http://www.OARcorp.com/rtems/license.html.
44 *
45 *  $Id$
46 */
47
48#include <rtems.h>
49#include <rtems/libio.h>
50#include <mpc8xx.h>
51#include <mpc8xx/console.h>
52#include <mpc8xx/cpm.h>
53#include <stdlib.h>
54#include <unistd.h>
55#include <termios.h>
56
57extern rtems_cpu_table Cpu_table;
58
59/* BSP supplied routine */
60extern int mbx8xx_console_use_maximum_buffer_size(void);
61
62#ifdef EPPCBUG_SMC1
63extern unsigned32 simask_copy;
64#endif
65
66/*
67 * Interrupt-driven input buffer
68 */
69#define RXBUFSIZE       16
70
71/*
72 *  I/O buffers and pointers to buffer descriptors.
73 *  Currently, single buffered input is done. This will work only
74 *  if the Rx interrupts are serviced quickly.
75 *
76 *  TODO: Add a least double buffering for safety.
77 */
78static volatile char rxBuf[NUM_PORTS][RXBUFSIZE];
79static volatile char txBuf[NUM_PORTS];
80
81/* SCC/SMC buffer descriptors */
82static volatile m8xxBufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS];
83
84/* Used to track the usage of the baud rate generators */
85static unsigned long brg_spd[4];
86static char  brg_used[4];
87
88/* Used to track termios private data for callbacks */
89struct rtems_termios_tty *ttyp[NUM_PORTS];
90
91/* Used to record previous ISR */
92static rtems_isr_entry old_handler[NUM_PORTS];
93
94/*
95 * Device-specific routines
96 */
97static int m8xx_get_brg_cd(int);
98static unsigned char m8xx_get_brg_clk(int);
99void m8xx_console_reserve_resources(rtems_configuration_table *);
100static int m8xx_smc_set_attributes(int, const struct termios*);
101static int m8xx_scc_set_attributes(int, const struct termios*);
102static rtems_isr m8xx_smc1_interrupt_handler(rtems_vector_number);
103static rtems_isr m8xx_smc2_interrupt_handler(rtems_vector_number);
104static rtems_isr m8xx_scc2_interrupt_handler(rtems_vector_number);
105#if defined(mpc860)
106static rtems_isr m8xx_scc3_interrupt_handler(rtems_vector_number);
107static rtems_isr m8xx_scc4_interrupt_handler(rtems_vector_number);
108#endif
109
110/*
111 * Compute baud-rate-generator configuration register value
112 */
113static int
114m8xx_get_brg_cd (int baud)
115{
116  int divisor;
117  int div16 = 0;
118
119  divisor = ((Cpu_table.clock_speed / 16) + (baud / 2)) / baud;
120  if (divisor > 4096) {
121    div16 = 1;
122    divisor = (divisor + 8) / 16;
123  }
124  return M8xx_BRG_EN | M8xx_BRG_EXTC_BRGCLK |
125    ((divisor - 1) << 1) | div16;
126}
127
128
129/*
130 *  This function will fail if more that 4 baud rates have been selected
131 *  at any time since the OS started. It needs to be fixed. FIXME
132 */
133static unsigned
134char m8xx_get_brg_clk(int baud)
135{
136  int i;
137
138  /* first try to find a BRG that is already at the right speed */
139  for ( i = 0; i < 4; i++ ) {
140    if ( brg_spd[i] == baud ) {
141      break;
142    }
143  }
144
145  if ( i == 4 ) { /* I guess we didn't find one */
146    for ( i = 0; i < 4; i++ ) {
147      if ( brg_used[i] == 0 ) {
148        break;
149      }
150    }
151  }
152  if (i != 4) {
153    brg_used[i]++;
154    brg_spd[i]=baud;
155    switch (i) {
156    case 0:
157      m8xx.brgc1 = M8xx_BRG_RST;
158      m8xx.brgc1 = m8xx_get_brg_cd(baud);
159      break;
160    case 1:
161      m8xx.brgc2 = M8xx_BRG_RST;
162      m8xx.brgc2 = m8xx_get_brg_cd(baud);
163      break;
164    case 2:
165      m8xx.brgc3 = M8xx_BRG_RST;
166      m8xx.brgc3 = m8xx_get_brg_cd(baud);
167      break;
168    case 3:
169      m8xx.brgc4 = M8xx_BRG_RST;
170      m8xx.brgc4 = m8xx_get_brg_cd(baud);
171      break;
172    }
173    return i;
174  }
175
176  else
177    return 0xff;
178}
179
180
181/*
182 * Hardware-dependent portion of tcsetattr().
183 */
184static int
185m8xx_smc_set_attributes (int minor, const struct termios *t)
186{
187  int baud, brg=0, csize=0, ssize, psize;
188  rtems_unsigned16 clen=0, cstopb, parenb, parodd, cread; 
189
190  /* Baud rate */
191  switch (t->c_cflag & CBAUD) {
192  default:      baud = -1;      break;
193  case B50:     baud = 50;      break;
194  case B75:     baud = 75;      break;
195  case B110:    baud = 110;     break;
196  case B134:    baud = 134;     break;
197  case B150:    baud = 150;     break;
198  case B200:    baud = 200;     break;
199  case B300:    baud = 300;     break;
200  case B600:    baud = 600;     break;
201  case B1200:   baud = 1200;    break;
202  case B1800:   baud = 1800;    break;
203  case B2400:   baud = 2400;    break;
204  case B4800:   baud = 4800;    break;
205  case B9600:   baud = 9600;    break;
206  case B19200:  baud = 19200;   break;
207  case B38400:  baud = 38400;   break;
208  case B57600:  baud = 57600;   break;
209  case B115200: baud = 115200;  break;
210  case B230400: baud = 230400;  break;
211  case B460800: baud = 460800;  break;
212  }
213  if (baud > 0)
214    brg = m8xx_get_brg_clk(baud);     /* 4 BRGs, 6 serial ports - hopefully */
215                                      /*  at least 2 ports will be the same */
216 
217  /* Number of data bits */
218  switch ( t->c_cflag & CSIZE ) {
219    case CS5:     csize = 5;       break;
220    case CS6:     csize = 6;       break;
221    case CS7:     csize = 7;       break;
222    case CS8:     csize = 8;       break;
223  }
224
225  /* Stop bits */
226  if ( t->c_cflag & CSTOPB ) {
227    cstopb = 0x0400;              /* Two stop bits */
228    ssize  = 2;
229  } else {
230    cstopb = 0x0000;              /* One stop bit */
231    ssize  = 1;
232  }
233
234  /* Parity */
235  if ( t->c_cflag & PARENB ) {
236    parenb = 0x0200;              /* Parity enabled on Tx and Rx */
237    psize  = 1;
238  } else {
239    parenb = 0x0000;              /* No parity on Tx and Rx */
240    psize  = 0;
241  }
242 
243  if ( t->c_cflag & PARODD )
244    parodd = 0x0000;              /* Odd parity */
245  else
246    parodd = 0x0100;
247
248  /*
249   * Character Length = start + data + parity + stop - 1
250   */ 
251  switch ( 1 + csize + psize + ssize - 1 ) {
252    case 6:     clen = 0x3000;       break;
253    case 7:     clen = 0x3800;       break;
254    case 8:     clen = 0x4000;       break;
255    case 9:     clen = 0x4800;       break;
256    case 10:    clen = 0x5000;       break;
257    case 11:    clen = 0x5800;       break;
258  }
259
260  if ( t->c_cflag & CREAD )
261    cread = 0x0023;             /* UART normal operation, enable Rx and Tx */
262  else
263    cread = 0x0021;             /* UART normal operation, enable Tx */
264   
265  /* Write the SIMODE/SMCMR registers */
266  switch (minor) {
267    case SMC1_MINOR:
268      m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) );
269      m8xx.smc1.smcmr = clen | cstopb | parenb | parodd | cread;
270      break;
271    case SMC2_MINOR:
272      m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) );
273      m8xx.smc2.smcmr = clen | cstopb | parenb | parodd | cread;
274      break;
275  }
276  return 0;
277}
278
279
280static int
281m8xx_scc_set_attributes (int minor, const struct termios *t)
282{
283  int baud, brg=0;
284  rtems_unsigned16 csize=0, cstopb, parenb, parodd;
285
286  /* Baud rate */
287  switch (t->c_cflag & CBAUD) {
288  default:      baud = -1;      break;
289  case B50:     baud = 50;      break;
290  case B75:     baud = 75;      break;
291  case B110:    baud = 110;     break;
292  case B134:    baud = 134;     break;
293  case B150:    baud = 150;     break;
294  case B200:    baud = 200;     break;
295  case B300:    baud = 300;     break;
296  case B600:    baud = 600;     break;
297  case B1200:   baud = 1200;    break;
298  case B1800:   baud = 1800;    break;
299  case B2400:   baud = 2400;    break;
300  case B4800:   baud = 4800;    break;
301  case B9600:   baud = 9600;    break;
302  case B19200:  baud = 19200;   break;
303  case B38400:  baud = 38400;   break;
304  case B57600:  baud = 57600;   break;
305  case B115200: baud = 115200;  break;
306  case B230400: baud = 230400;  break;
307  case B460800: baud = 460800;  break;
308  }
309  if (baud > 0)
310    brg = m8xx_get_brg_clk(baud);     /* 4 BRGs, 5 serial ports - hopefully */
311                                      /*  at least 2 ports will be the same */
312                                      /*  Write the SICR register below */
313   
314  /* Number of data bits */
315  switch ( t->c_cflag & CSIZE ) {
316    case CS5:     csize = 0x0000;       break;
317    case CS6:     csize = 0x1000;       break;
318    case CS7:     csize = 0x2000;       break;
319    case CS8:     csize = 0x3000;       break;
320  }
321
322  /* Stop bits */
323  if ( t->c_cflag & CSTOPB )
324    cstopb = 0x4000;              /* Two stop bits */
325  else
326    cstopb = 0x0000;              /* One stop bit */
327   
328  /* Parity */
329  if ( t->c_cflag & PARENB )
330    parenb = 0x0010;              /* Parity enabled on Tx and Rx */
331  else
332    parenb = 0x0000;              /* No parity on Tx and Rx */
333   
334  if ( t->c_cflag & PARODD )
335    parodd = 0x0000;              /* Odd parity */
336  else
337    parodd = 0x000a;
338
339  /* Write the SICR/PSMR Registers */
340  switch (minor) {
341    case SCC2_MINOR:
342      m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) );
343      m8xx.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc2.psmr & 0x8fe0) );
344      break;
345  #if defined(mpc860)
346    case SCC3_MINOR:
347      m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) );
348      m8xx.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc3.psmr & 0x8fe0) );
349      break;
350    case SCC4_MINOR:
351      m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) );
352      m8xx.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8xx.scc4.psmr & 0x8fe0) );
353      break;
354  #endif
355  }
356 
357  return 0;
358}
359
360
361int 
362m8xx_uart_setAttributes(
363  int minor,
364  const struct termios *t
365)
366{
367  /*
368   * Check that port number is valid
369   */
370  if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) ) 
371    return 0;
372
373  switch (minor) {
374    case SMC1_MINOR:
375    case SMC2_MINOR:
376      return m8xx_smc_set_attributes( minor, t );
377
378    case SCC2_MINOR:
379    case SCC3_MINOR:
380    case SCC4_MINOR:
381      return m8xx_scc_set_attributes( minor, t );
382  }
383  return 0;
384}
385
386
387/*
388 * Interrupt handlers
389 */
390static rtems_isr
391m8xx_scc2_interrupt_handler (rtems_vector_number v)
392{
393  int nb_overflow;
394
395  /*
396   * Buffer received?
397   */
398  if ((m8xx.scc2.sccm & M8xx_SCCE_RX) && (m8xx.scc2.scce & M8xx_SCCE_RX)) {
399    m8xx.scc2.scce = M8xx_SCCE_RX;    /* Clear the event */
400
401
402    /* Check that the buffer is ours */
403    if ((RxBd[SCC2_MINOR]->status & M8xx_BD_EMPTY) == 0) {
404      rtems_cache_invalidate_multiple_data_lines( 
405        (const void *) RxBd[SCC2_MINOR]->buffer, 
406        RxBd[SCC2_MINOR]->length );
407      nb_overflow = rtems_termios_enqueue_raw_characters(
408        (void *)ttyp[SCC2_MINOR],
409        (char *)RxBd[SCC2_MINOR]->buffer,
410        (int)RxBd[SCC2_MINOR]->length );
411      RxBd[SCC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
412                                 M8xx_BD_INTERRUPT;
413    }
414  }
415
416  /*
417   * Buffer transmitted?
418   */
419  if (m8xx.scc2.scce & M8xx_SCCE_TX) {
420    m8xx.scc2.scce = M8xx_SCCE_TX;  /* Clear the event */
421
422    /* Check that the buffer is ours */
423    if ((TxBd[SCC2_MINOR]->status & M8xx_BD_READY) == 0)
424      rtems_termios_dequeue_characters (
425        (void *)ttyp[SCC2_MINOR],
426        (int)TxBd[SCC2_MINOR]->length);
427  }
428  m8xx.cisr = 1UL << 29;  /* Clear SCC2 interrupt-in-service bit */
429}
430
431
432#ifdef mpc860
433static rtems_isr
434m8xx_scc3_interrupt_handler (rtems_vector_number v)
435{
436  int nb_overflow;
437
438  /*
439   * Buffer received?
440   */
441  if ((m8xx.scc3.sccm & M8xx_SCCE_RX) && (m8xx.scc3.scce & M8xx_SCCE_RX)) {
442    m8xx.scc3.scce = M8xx_SCCE_RX;  /* Clear the event */
443
444
445    /* Check that the buffer is ours */
446    if ((RxBd[SCC3_MINOR]->status & M8xx_BD_EMPTY) == 0) {
447      rtems_cache_invalidate_multiple_data_lines( 
448        (const void *) RxBd[SCC3_MINOR]->buffer, 
449        RxBd[SCC3_MINOR]->length );
450      nb_overflow = rtems_termios_enqueue_raw_characters(
451        (void *)ttyp[SCC3_MINOR],
452        (char *)RxBd[SCC3_MINOR]->buffer,
453        (int)RxBd[SCC3_MINOR]->length );
454      RxBd[SCC3_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
455                                 M8xx_BD_INTERRUPT;
456    }
457  }
458
459  /*
460   * Buffer transmitted?
461   */
462  if (m8xx.scc3.scce & M8xx_SCCE_TX) {
463    m8xx.scc3.scce = M8xx_SCCE_TX;    /* Clear the event */
464
465    /* Check that the buffer is ours */
466    if ((TxBd[SCC3_MINOR]->status & M8xx_BD_READY) == 0)
467      rtems_termios_dequeue_characters (
468        (void *)ttyp[SCC3_MINOR],
469        (int)TxBd[SCC3_MINOR]->length);
470  }
471  m8xx.cisr = 1UL << 28;  /* Clear SCC3 interrupt-in-service bit */
472}
473
474
475static rtems_isr
476m8xx_scc4_interrupt_handler (rtems_vector_number v)
477{
478  int nb_overflow;
479
480  /*
481   * Buffer received?
482   */
483  if ((m8xx.scc4.sccm & M8xx_SCCE_RX) && (m8xx.scc4.scce & M8xx_SCCE_RX)) {
484    m8xx.scc4.scce = M8xx_SCCE_RX;  /* Clear the event */
485
486
487    /* Check that the buffer is ours */
488    if ((RxBd[SCC4_MINOR]->status & M8xx_BD_EMPTY) == 0) {
489      rtems_cache_invalidate_multiple_data_lines( 
490        (const void *) RxBd[SCC4_MINOR]->buffer, 
491        RxBd[SCC4_MINOR]->length );
492      nb_overflow = rtems_termios_enqueue_raw_characters(
493        (void *)ttyp[SCC4_MINOR],
494        (char *)RxBd[SCC4_MINOR]->buffer,
495        (int)RxBd[SCC4_MINOR]->length );
496      RxBd[SCC4_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
497                                 M8xx_BD_INTERRUPT;
498    }
499  }
500
501  /*
502   * Buffer transmitted?
503   */
504  if (m8xx.scc4.scce & M8xx_SCCE_TX) {
505    m8xx.scc4.scce = M8xx_SCCE_TX;    /* Clear the event */
506
507    /* Check that the buffer is ours */
508    if ((TxBd[SCC4_MINOR]->status & M8xx_BD_READY) == 0)
509      rtems_termios_dequeue_characters (
510        (void *)ttyp[SCC4_MINOR],
511        (int)TxBd[SCC4_MINOR]->length);
512  }
513  m8xx.cisr = 1UL << 27;  /* Clear SCC4 interrupt-in-service bit */
514}
515#endif
516
517static rtems_isr
518m8xx_smc1_interrupt_handler (rtems_vector_number v)
519{
520  int nb_overflow;
521
522  /*
523   * Buffer received?
524   */
525  if (m8xx.smc1.smce & M8xx_SMCE_RX) {
526    m8xx.smc1.smce = M8xx_SMCE_RX;  /* Clear the event */
527
528
529    /* Check that the buffer is ours */
530    if ((RxBd[SMC1_MINOR]->status & M8xx_BD_EMPTY) == 0) {
531      rtems_cache_invalidate_multiple_data_lines( 
532        (const void *) RxBd[SMC1_MINOR]->buffer, 
533        RxBd[SMC1_MINOR]->length );
534      nb_overflow = rtems_termios_enqueue_raw_characters(
535        (void *)ttyp[SMC1_MINOR],
536        (char *)RxBd[SMC1_MINOR]->buffer,
537        (int)RxBd[SMC1_MINOR]->length );
538      RxBd[SMC1_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
539                                 M8xx_BD_INTERRUPT;
540    }
541  }
542
543  /*
544   * Buffer transmitted?
545   */
546  if (m8xx.smc1.smce & M8xx_SMCE_TX) {
547    m8xx.smc1.smce = M8xx_SMCE_TX;    /* Clear the event */
548
549    /* Check that the buffer is ours */
550    if ((TxBd[SMC1_MINOR]->status & M8xx_BD_READY) == 0)
551      rtems_termios_dequeue_characters (
552        (void *)ttyp[SMC1_MINOR],
553        (int)TxBd[SMC1_MINOR]->length);
554  }
555  m8xx.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
556}
557
558
559static rtems_isr
560m8xx_smc2_interrupt_handler (rtems_vector_number v)
561{
562  int nb_overflow;
563
564  /*
565   * Buffer received?
566   */
567  if (m8xx.smc2.smce & M8xx_SMCE_RX) {
568    m8xx.smc2.smce = M8xx_SMCE_RX;  /* Clear the event */
569
570
571    /* Check that the buffer is ours */
572    if ((RxBd[SMC2_MINOR]->status & M8xx_BD_EMPTY) == 0) {
573      rtems_cache_invalidate_multiple_data_lines( 
574        (const void *) RxBd[SMC2_MINOR]->buffer, 
575        RxBd[SMC2_MINOR]->length );
576      nb_overflow = rtems_termios_enqueue_raw_characters(
577        (void *)ttyp[SMC2_MINOR],
578        (char *)RxBd[SMC2_MINOR]->buffer,
579        (int)RxBd[SMC2_MINOR]->length );
580      RxBd[SMC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
581                                 M8xx_BD_INTERRUPT;
582    }
583  }
584
585  /*
586   * Buffer transmitted?
587   */
588  if (m8xx.smc2.smce & M8xx_SMCE_TX) {
589    m8xx.smc2.smce = M8xx_SMCE_TX;    /* Clear the event */
590
591    /* Check that the buffer is ours */
592    if ((TxBd[SMC2_MINOR]->status & M8xx_BD_READY) == 0)
593      rtems_termios_dequeue_characters (
594        (void *)ttyp[SMC2_MINOR],
595        (int)TxBd[SMC2_MINOR]->length);
596  }
597  m8xx.cisr = 1UL << 3;  /* Clear SMC2 interrupt-in-service bit */
598}
599
600
601void
602m8xx_uart_scc_initialize (int minor)
603{
604  unsigned char brg;
605  volatile m8xxSCCparms_t *sccparms = 0;
606  volatile m8xxSCCRegisters_t *sccregs = 0;
607
608  /*
609   * Check that minor number is valid
610   */
611  if ( (minor < SCC2_MINOR) || (minor > NUM_PORTS-1) ) 
612    return;
613
614  /* Get the sicr clock source bit values for 9600 bps */
615  brg = m8xx_get_brg_clk(9600);
616
617  /*
618   * Allocate buffer descriptors
619   */
620  RxBd[minor] = m8xx_bd_allocate(1);
621  TxBd[minor] = m8xx_bd_allocate(1);
622
623  /*
624   *  Get the address of the parameter RAM for the specified port,
625   *  configure I/O port A,C & D and put SMC in NMSI mode, connect
626   *  the SCC to the appropriate BRG.
627   *
628   *  SCC2 TxD is shared with port A bit 12
629   *  SCC2 RxD is shared with port A bit 13
630   *  SCC1 TxD is shared with port A bit 14
631   *  SCC1 RxD is shared with port A bit 15
632   *  SCC4 DCD is shared with port C bit 4
633   *  SCC4 CTS is shared with port C bit 5
634   *  SCC3 DCD is shared with port C bit 6
635   *  SCC3 CTS is shared with port C bit 7
636   *  SCC2 DCD is shared with port C bit 8
637   *  SCC2 CTS is shared with port C bit 9
638   *  SCC1 DCD is shared with port C bit 10
639   *  SCC1 CTS is shared with port C bit 11
640   *  SCC2 RTS is shared with port C bit 14
641   *  SCC1 RTS is shared with port C bit 15
642   *  SCC4 RTS is shared with port D bit 6
643   *  SCC3 RTS is shared with port D bit 7
644   *  SCC4 TxD is shared with port D bit 8
645   *  SCC4 RxD is shared with port D bit 9
646   *  SCC3 TxD is shared with port D bit 10
647   *  SCC3 RxD is shared with port D bit 11
648   */
649  switch (minor) {
650    case SCC2_MINOR:
651      sccparms = &m8xx.scc2p;
652      sccregs = &m8xx.scc2;
653     
654      m8xx.papar |=  0x000C;        /* PA12 & PA13 are dedicated peripheral pins */
655      m8xx.padir &= ~0x000C;        /* PA13 & PA12 must not drive the UART lines */
656      m8xx.paodr &= ~0x000C;        /* PA12 & PA13 are not open drain */
657      m8xx.pcpar |=  0x0002;        /* PC14 is SCC2 RTS */
658      m8xx.pcpar &= ~0x00C0;        /* PC8 & PC9 are SCC2 DCD and CTS */
659      m8xx.pcdir &= ~0x00C2;        /* PC8, PC9 & PC14 must not drive the UART lines */
660      m8xx.pcso  |=  0x00C0;        /* Enable DCD and CTS inputs */
661     
662      m8xx.sicr &= 0xFFFF00FF;      /* Clear TCS2 & RCS2, GR2=no grant, SC2=NMSI mode */
663      m8xx.sicr |= (brg<<11) | (brg<<8); /* TCS2 = RCS2 = brg */
664      break;
665
666#ifdef mpc860
667    case SCC3_MINOR:
668      sccparms = &m8xx.scc3p;
669      sccregs = &m8xx.scc3;
670     
671      m8xx.pcpar &= ~0x0300;        /* PC6 & PC7 are SCC3 DCD and CTS */
672      m8xx.pcdir &= ~0x0300;        /* PC6 & PC7 must not drive the UART lines */
673      m8xx.pcso  |=  0x0300;        /* Enable DCD and CTS inputs */
674      m8xx.pdpar |=  0x0130;        /* PD7, PD10 & PD11 are dedicated peripheral pins */
675     
676      m8xx.sicr &= 0xFF00FFFF;      /* Clear TCS3 & RCS3, GR3=no grant, SC3=NMSI mode */
677      m8xx.sicr |= (brg<<19) | (brg<<16); /* TCS3 = RCS3 = brg */
678      break;
679
680    case SCC4_MINOR:
681      sccparms = &m8xx.scc4p;
682      sccregs = &m8xx.scc4;
683     
684      m8xx.pcpar &= ~0x0C00;        /* PC4 & PC5 are SCC4 DCD and CTS */
685      m8xx.pcdir &= ~0x0C00;        /* PC4 & PC5 must not drive the UART lines */
686      m8xx.pcso  |=  0x0C00;        /* Enable DCD and CTS inputs */
687      m8xx.pdpar |=  0x02C0;        /* PD6, PD8 & PD9 are dedicated peripheral pins */
688       
689      m8xx.sicr &= 0x00FFFFFF;      /* Clear TCS4 & RCS4, GR4=no grant, SC4=NMSI mode */
690      m8xx.sicr |= (brg<<27) | (brg<<24); /* TCS4 = RCS4 = brg */
691      break;
692#endif
693  }
694
695  /*
696   *  Set up SDMA
697   */
698  m8xx.sdcr = 0x01;                 /* as per section 16.10.2.1 MPC821UM/AD */
699
700  /*
701   *  Set up the SCC parameter RAM.
702   */
703  sccparms->rbase = (char *)RxBd[minor] - (char *)&m8xx;
704  sccparms->tbase = (char *)TxBd[minor] - (char *)&m8xx;
705
706  sccparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
707  sccparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0);
708  if ( mbx8xx_console_use_maximum_buffer_size() )
709    sccparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
710  else
711    sccparms->mrblr = 1;            /* Maximum Rx buffer size */
712  sccparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
713  sccparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
714
715  sccparms->un.uart.parec = 0;      /* Clear parity error counter */
716  sccparms->un.uart.frmec = 0;      /* Clear framing error counter */
717  sccparms->un.uart.nosec = 0;      /* Clear noise counter */
718  sccparms->un.uart.brkec = 0;      /* Clear break counter */
719
720  sccparms->un.uart.uaddr[0] = 0;   /* Not in multidrop mode, so clear */
721  sccparms->un.uart.uaddr[1] = 0;   /* Not in multidrop mode, so clear */
722  sccparms->un.uart.toseq  = 0;     /* Tx Out-Of-SEQuence--no XON/XOFF now */
723
724  sccparms->un.uart.character[0] = 0x8000; /* Entry is invalid */
725  sccparms->un.uart.character[1] = 0x8000; /* Entry is invalid */
726  sccparms->un.uart.character[2] = 0x8000; /* Entry is invalid */
727  sccparms->un.uart.character[3] = 0x8000; /* Entry is invalid */
728  sccparms->un.uart.character[4] = 0x8000; /* Entry is invalid */
729  sccparms->un.uart.character[5] = 0x8000; /* Entry is invalid */
730  sccparms->un.uart.character[6] = 0x8000; /* Entry is invalid */
731  sccparms->un.uart.character[7] = 0x8000; /* Entry is invalid */
732
733
734  sccparms->un.uart.rccm = 0xc0ff;  /* No masking */
735
736  /*
737   * Set up the Receive Buffer Descriptor
738   */
739  RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT;
740  RxBd[minor]->length = 0;
741  RxBd[minor]->buffer = rxBuf[minor];
742
743  /*
744   * Setup the Transmit Buffer Descriptor
745   */
746  TxBd[minor]->status = M8xx_BD_WRAP;
747
748 /*
749   * Set up SCCx general and protocol-specific mode registers
750   */
751  sccregs->gsmr_h = 0x00000020;     /* RFW=low latency operation */
752  sccregs->gsmr_l = 0x00028004;     /* TDCR=RDCR=16x clock mode, MODE=uart*/
753  sccregs->scce = ~0;               /* Clear any pending event */
754  sccregs->sccm = 0;                /* Mask all interrupt/event sources */
755  sccregs->psmr = 0x3000;           /* Normal operation & mode, 1 stop bit,
756                                       8 data bits, no parity */
757  sccregs->dsr = 0x7E7E;            /* No fractional stop bits */
758  sccregs->gsmr_l = 0x00028034;     /* ENT=enable Tx, ENR=enable Rx */
759
760  /*
761   *  Initialize the Rx and Tx with the new parameters.
762   */
763  switch (minor) {
764    case SCC2_MINOR:
765      m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC2);
766      break;
767
768#ifdef mpc860
769    case SCC3_MINOR:
770      m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC3);
771      break;
772    case SCC4_MINOR:
773      m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SCC4);
774      break;
775#endif
776  }
777#if NVRAM_CONFIGURE == 1
778  if ( (nvram->console_mode & 0x06) == 0x02 ) {
779    switch (minor) {
780      case SCC2_MINOR:
781        rtems_interrupt_catch (m8xx_scc2_interrupt_handler,
782                               PPC_IRQ_CPM_SCC2,
783                               &old_handler[minor]);
784
785        sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
786        m8xx.cimr |= 1UL <<  29;      /* Enable SCC2 interrupts */
787        break;
788
789#ifdef mpc860
790      case SCC3_MINOR:
791        rtems_interrupt_catch (m8xx_scc3_interrupt_handler,
792                               PPC_IRQ_CPM_SCC3,
793                               &old_handler[minor]);
794
795        sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
796        m8xx.cimr |= 1UL <<  28;      /* Enable SCC2 interrupts */
797        break;
798     
799      case SCC4_MINOR:
800        rtems_interrupt_catch (m8xx_scc4_interrupt_handler,
801                               PPC_IRQ_CPM_SCC4,
802                               &old_handler[minor]);
803
804        sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
805        m8xx.cimr |= 1UL <<  27;      /* Enable SCC2 interrupts */
806        break;
807#endif /* mpc860 */
808    }
809  }
810 
811#else /* NVRAM_CONFIGURE != 1 */
812
813#if UARTS_IO_MODE == 1
814  switch (minor) {
815    case SCC2_MINOR:
816      rtems_interrupt_catch (m8xx_scc2_interrupt_handler,
817                             PPC_IRQ_CPM_SCC2,
818                             &old_handler[minor]);
819
820      sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
821      m8xx.cimr |= 1UL <<  29;      /* Enable SCC2 interrupts */
822      break;
823
824#ifdef mpc860
825    case SCC3_MINOR:
826      rtems_interrupt_catch (m8xx_scc3_interrupt_handler,
827                             PPC_IRQ_CPM_SCC3,
828                             &old_handler[minor]);
829
830      sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
831      m8xx.cimr |= 1UL <<  28;      /* Enable SCC2 interrupts */
832      break;
833     
834    case SCC4_MINOR:
835      rtems_interrupt_catch (m8xx_scc4_interrupt_handler,
836                             PPC_IRQ_CPM_SCC4,
837                             &old_handler[minor]);
838
839      sccregs->sccm = 3;            /* Enable SCC2 Rx & Tx interrupts */
840      m8xx.cimr |= 1UL <<  27;      /* Enable SCC2 interrupts */
841      break;
842#endif /* mpc860 */
843  }
844#endif /* UARTS_IO_MODE */
845
846#endif /* NVRAM_CONFIGURE */
847}
848
849
850void
851m8xx_uart_smc_initialize (int minor)
852{
853  unsigned char brg;
854  volatile m8xxSMCparms_t *smcparms = 0;
855  volatile m8xxSMCRegisters_t *smcregs = 0;
856
857  /*
858   * Check that minor number is valid
859   */
860  if ( (minor < SMC1_MINOR) || (minor > SMC2_MINOR) ) 
861    return;
862
863  /* Get the simode clock source bit values for 9600 bps */
864  brg = m8xx_get_brg_clk(9600);
865
866  /*
867   * Allocate buffer descriptors
868   */
869  RxBd[minor] = m8xx_bd_allocate (1);
870  TxBd[minor] = m8xx_bd_allocate (1);
871
872  /*
873   *  Get the address of the parameter RAM for the specified port,
874   *  configure I/O port B and put SMC in NMSI mode, connect the
875   *  SMC to the appropriate BRG.
876   *
877   *  SMC2 RxD is shared with port B bit 20
878   *  SMC2 TxD is shared with port B bit 21
879   *  SMC1 RxD is shared with port B bit 24
880   *  SMC1 TxD is shared with port B bit 25
881   */
882  switch (minor) {
883    case SMC1_MINOR:
884      smcparms = &m8xx.smc1p;
885      smcregs = &m8xx.smc1;
886     
887      m8xx.pbpar |=  0x000000C0;    /* PB24 & PB25 are dedicated peripheral pins */
888      m8xx.pbdir &= ~0x000000C0;    /* PB24 & PB25 must not drive UART lines */
889      m8xx.pbodr &= ~0x000000C0;    /* PB24 & PB25 are not open drain */
890
891      m8xx.simode &= 0xFFFF0FFF;    /* Clear SMC1CS & SMC1 for NMSI mode */
892      m8xx.simode |= brg << 12;     /* SMC1CS = brg */
893      break;
894
895    case SMC2_MINOR:
896      smcparms = &m8xx.smc2p;
897      smcregs = &m8xx.smc2;
898     
899      m8xx.pbpar |=  0x00000C00;    /* PB20 & PB21 are dedicated peripheral pins */
900      m8xx.pbdir &= ~0x00000C00;    /* PB20 & PB21 must not drive the UART lines */
901      m8xx.pbodr &= ~0x00000C00;    /* PB20 & PB21 are not open drain */
902     
903      m8xx.simode &= 0x0FFFFFFF;    /* Clear SMC2CS & SMC2 for NMSI mode */
904      m8xx.simode |= brg << 28;     /* SMC2CS = brg */
905      break;
906  }
907 
908  /*
909   * Set up SMC1 parameter RAM common to all protocols
910   */
911  smcparms->rbase = (char *)RxBd[minor] - (char *)&m8xx;
912  smcparms->tbase = (char *)TxBd[minor] - (char *)&m8xx;
913  smcparms->rfcr = M8xx_RFCR_MOT | M8xx_RFCR_DMA_SPACE(0);
914  smcparms->tfcr = M8xx_TFCR_MOT | M8xx_TFCR_DMA_SPACE(0);
915#if NVRAM_CONFIGURE == 1
916  if ( (nvram->console_mode & 0x06) == 0x02 )
917    smcparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
918  else
919    smcparms->mrblr = 1;            /* Maximum Rx buffer size */
920#else
921#if UARTS_IO_MODE == 1
922  smcparms->mrblr = RXBUFSIZE;      /* Maximum Rx buffer size */
923#else
924  smcparms->mrblr = 1;              /* Maximum Rx buffer size */
925#endif
926#endif
927
928  /*
929   * Set up SMC1 parameter RAM UART-specific parameters
930   */
931  smcparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
932  smcparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
933  smcparms->un.uart.brkec = 0;      /* Clear break counter */
934
935  /*
936   * Set up the Receive Buffer Descriptor
937   */
938  RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT;
939  RxBd[minor]->length = 0;
940  RxBd[minor]->buffer = rxBuf[minor];
941
942  /*
943   * Setup the Transmit Buffer Descriptor
944   */
945  TxBd[minor]->status = M8xx_BD_WRAP;
946
947  /*
948   * Set up SMCx general and protocol-specific mode registers
949   */
950  smcregs->smce = ~0;               /* Clear any pending events */
951  smcregs->smcm = 0;                /* Enable SMC Rx & Tx interrupts */
952  smcregs->smcmr = M8xx_SMCMR_CLEN(9) | M8xx_SMCMR_SM_UART;
953
954  /*
955   * Send "Init parameters" command
956   */
957  switch (minor) {
958    case SMC1_MINOR:
959      m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC1);
960      break;
961
962    case SMC2_MINOR:
963      m8xx_cp_execute_cmd (M8xx_CR_OP_INIT_RX_TX | M8xx_CR_CHAN_SMC2);
964      break;
965  }
966 
967  /*
968   * Enable receiver and transmitter
969   */
970  smcregs->smcmr |= M8xx_SMCMR_TEN | M8xx_SMCMR_REN;
971#if NVRAM_CONFIGURE == 1
972  if ( (nvram->console_mode & 0x06) == 0x02 ) {
973    switch (minor) {
974      case SMC1_MINOR:
975        rtems_interrupt_catch (m8xx_smc1_interrupt_handler,
976                                    PPC_IRQ_CPM_SMC1,
977                                    &old_handler[minor]);
978
979        smcregs->smcm = 3;            /* Enable SMC1 Rx & Tx interrupts */
980        m8xx.cimr |= 1UL <<  4;       /* Enable SMC1 interrupts */
981        break;
982     
983      case SMC2_MINOR:
984        rtems_interrupt_catch (m8xx_smc2_interrupt_handler,
985                                    PPC_IRQ_CPM_SMC2,
986                                    &old_handler[minor]);
987
988        smcregs->smcm = 3;            /* Enable SMC2 Rx & Tx interrupts */
989        m8xx.cimr |= 1UL <<  3;       /* Enable SMC2 interrupts */
990        break;
991    }
992  }
993#else
994#if UARTS_IO_MODE == 1
995  switch (minor) {
996    case SMC1_MINOR:
997      rtems_interrupt_catch (m8xx_smc1_interrupt_handler,
998                                  PPC_IRQ_CPM_SMC1,
999                                  &old_handler[minor]);
1000
1001      smcregs->smcm = 3;            /* Enable SMC1 Rx & Tx interrupts */
1002      m8xx.cimr |= 1UL <<  4;       /* Enable SMC1 interrupts */
1003      break;
1004     
1005    case SMC2_MINOR:
1006      rtems_interrupt_catch (m8xx_smc2_interrupt_handler,
1007                                  PPC_IRQ_CPM_SMC2,
1008                                  &old_handler[minor]);
1009
1010      smcregs->smcm = 3;            /* Enable SMC2 Rx & Tx interrupts */
1011      m8xx.cimr |= 1UL <<  3;       /* Enable SMC2 interrupts */
1012      break;
1013  }
1014#endif
1015
1016#endif
1017}
1018
1019void
1020m8xx_uart_initialize(void)
1021{
1022  int i;
1023 
1024  for (i=0; i < 4; i++) {
1025    brg_spd[i] = 0;
1026    brg_used[i] = 0;
1027  }
1028}
1029
1030
1031void 
1032m8xx_uart_interrupts_initialize(void)
1033{
1034#ifdef mpc860
1035  m8xx.cicr = 0x00E43F80;           /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
1036                                       SCdP=SCC4, IRL=1, HP=PC15, IEN=1 */
1037#else
1038  m8xx.cicr = 0x00043F80;           /* SCaP=SCC1, SCbP=SCC2, IRL=1, HP=PC15, IEN=1 */
1039#endif
1040  m8xx.simask |= M8xx_SIMASK_LVM1;  /* Enable level interrupts */
1041#ifdef EPPCBUG_SMC1
1042  simask_copy = m8xx.simask;
1043#endif
1044}
1045
1046
1047int
1048m8xx_uart_pollRead(
1049  int minor
1050)
1051{
1052  unsigned char c;
1053
1054  if (RxBd[minor]->status & M8xx_BD_EMPTY) {
1055    return -1;
1056  }
1057  rtems_cache_invalidate_multiple_data_lines( 
1058    (const void *) RxBd[minor]->buffer,
1059    RxBd[minor]->length
1060  );
1061  c = ((char *)RxBd[minor]->buffer)[0];
1062  RxBd[minor]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP;
1063  return c;
1064}
1065
1066
1067/*
1068 *  TODO: Get a free buffer and set it up.
1069 */
1070int 
1071m8xx_uart_write(
1072  int minor,
1073  const char *buf,
1074  int len
1075)
1076{
1077  rtems_cache_flush_multiple_data_lines( buf, len );
1078  TxBd[minor]->buffer = (char *) buf;
1079  TxBd[minor]->length = len;
1080  TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP | M8xx_BD_INTERRUPT;
1081  return 0;
1082}
1083 
1084
1085int
1086m8xx_uart_pollWrite(
1087  int minor,
1088  const char *buf,
1089  int len
1090)
1091{
1092  while (len--) {
1093    while (TxBd[minor]->status & M8xx_BD_READY)
1094      continue;
1095    txBuf[minor] = *buf++;
1096    rtems_cache_flush_multiple_data_lines( (void *)&txBuf[minor], 1 );
1097    TxBd[minor]->buffer = &txBuf[minor];
1098    TxBd[minor]->length = 1;
1099    TxBd[minor]->status = M8xx_BD_READY | M8xx_BD_WRAP;
1100  }
1101  return 0;
1102}
1103
1104void
1105m8xx_uart_reserve_resources(
1106  rtems_configuration_table *configuration
1107)
1108{
1109  rtems_termios_reserve_resources (configuration, NUM_PORTS);
1110}
Note: See TracBrowser for help on using the repository browser.