source: rtems/c/src/lib/libcpu/powerpc/mpc8260/console-generic/console-generic.c @ f865fc5d

4.11
Last change on this file since f865fc5d was f865fc5d, checked in by Ralf Corsepius <ralf.corsepius@…>, on Dec 1, 2011 at 8:20:03 AM

2011-12-01 Ralf Corsépius <ralf.corsepius@…>

  • mpc8260/console-generic/console-generic.c, mpc8xx/console-generic/console-generic.c: Eliminate unused var "nb_overflow".
  • Property mode set to 100644
File size: 30.8 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
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 *  Modifications by Andy Dachs <a.dachs@sstl.co.uk> to add MPC8260
41 *  support.
42 *  Copyright (c) 2001, Surrey Satellite Technology Ltd
43 *    SCC1 and SSC2 are used on MPC8260ADS board
44 *    SMCs are unused
45 *
46 *  The license and distribution terms for this file may be
47 *  found in the file LICENSE in this distribution or at
48 *
49 *  http://www.rtems.com/license/LICENSE.
50 *
51 *  $Id$
52 */
53
54#include <rtems.h>
55#include <rtems/libio.h>
56#include <mpc8260.h>
57#include <mpc8260/console.h>
58#include <mpc8260/cpm.h>
59#include <stdlib.h>
60#include <unistd.h>
61#include <termios.h>
62#include <bsp/irq.h>
63#include <rtems/bspIo.h>   /* for printk */
64
65
66
67/* BSP supplied routine */
68extern int mbx8xx_console_get_configuration(void);
69
70
71/*
72 * Interrupt-driven input buffer
73 */
74#define RXBUFSIZE       16
75
76/*
77 *  I/O buffers and pointers to buffer descriptors.
78 *  Currently, single buffered input is done. This will work only
79 *  if the Rx interrupts are serviced quickly.
80 *
81 *  TODO: Add a least double buffering for safety.
82 */
83static volatile char rxBuf[NUM_PORTS][RXBUFSIZE];
84static volatile char txBuf[NUM_PORTS];
85
86/* SCC/SMC buffer descriptors */
87static volatile m8260BufferDescriptor_t *RxBd[NUM_PORTS], *TxBd[NUM_PORTS];
88
89
90
91/* Used to track termios private data for callbacks */
92struct rtems_termios_tty *ttyp[NUM_PORTS];
93
94#if 0
95/* Used to record previous ISR */
96static rtems_isr_entry old_handler[NUM_PORTS];
97#endif
98
99/*
100 * Device-specific routines
101 */
102static int m8xx_smc_set_attributes(int, const struct termios*);
103static int m8xx_scc_set_attributes(int, const struct termios*);
104static rtems_isr m8xx_smc1_interrupt_handler(rtems_irq_hdl_param unused);
105static rtems_isr m8xx_smc2_interrupt_handler(rtems_irq_hdl_param unused);
106static rtems_isr m8xx_scc1_interrupt_handler(rtems_irq_hdl_param unused);
107static rtems_isr m8xx_scc2_interrupt_handler(rtems_irq_hdl_param unused);
108static rtems_isr m8xx_scc3_interrupt_handler(rtems_irq_hdl_param unused);
109static rtems_isr m8xx_scc4_interrupt_handler(rtems_irq_hdl_param unused);
110
111
112
113/*
114 * Hardware-dependent portion of tcsetattr().
115 */
116static int
117m8xx_smc_set_attributes (int minor, const struct termios *t)
118{
119  int baud, brg=0, csize=0, ssize, psize;
120  uint16_t   clen=0, cstopb, parenb, parodd, cread;
121
122  /* Baud rate */
123  switch (t->c_cflag & CBAUD) {
124  default:      baud = -1;      break;
125  case B50:     baud = 50;      break;
126  case B75:     baud = 75;      break;
127  case B110:    baud = 110;     break;
128  case B134:    baud = 134;     break;
129  case B150:    baud = 150;     break;
130  case B200:    baud = 200;     break;
131  case B300:    baud = 300;     break;
132  case B600:    baud = 600;     break;
133  case B1200:   baud = 1200;    break;
134  case B1800:   baud = 1800;    break;
135  case B2400:   baud = 2400;    break;
136  case B4800:   baud = 4800;    break;
137  case B9600:   baud = 9600;    break;
138  case B19200:  baud = 19200;   break;
139  case B38400:  baud = 38400;   break;
140  case B57600:  baud = 57600;   break;
141  case B115200: baud = 115200;  break;
142  case B230400: baud = 230400;  break;
143  case B460800: baud = 460800;  break;
144  }
145  if (baud > 0) {
146   switch( minor ) {
147      case SMC1_MINOR:
148        /* SMC1 can only choose between BRG1 and 7 */
149        brg = m8xx_get_brg( M8260_SMC1_BRGS, baud*16 ) + 1;
150        m8260.cmxsmr &= ~0x30;
151        m8260.cmxsmr |= (brg==1? 0x00: 0x10 );
152        break;
153      case SMC2_MINOR:
154        /* SMC2 can only choose between BRG2 and 8 */
155        brg = m8xx_get_brg(  M8260_SMC2_BRGS, baud*16 ) + 1;
156        m8260.cmxsmr &= ~0x30;
157        m8260.cmxsmr |= (brg==2? 0x00: 0x01 );
158        break;
159    }
160  }
161
162  /* Number of data bits */
163  switch ( t->c_cflag & CSIZE ) {
164    case CS5:     csize = 5;       break;
165    case CS6:     csize = 6;       break;
166    case CS7:     csize = 7;       break;
167    case CS8:     csize = 8;       break;
168  }
169
170  /* Stop bits */
171  if ( t->c_cflag & CSTOPB ) {
172    cstopb = 0x0400;              /* Two stop bits */
173    ssize  = 2;
174  } else {
175    cstopb = 0x0000;              /* One stop bit */
176    ssize  = 1;
177  }
178
179  /* Parity */
180  if ( t->c_cflag & PARENB ) {
181    parenb = 0x0200;              /* Parity enabled on Tx and Rx */
182    psize  = 1;
183  } else {
184    parenb = 0x0000;              /* No parity on Tx and Rx */
185    psize  = 0;
186  }
187
188  if ( t->c_cflag & PARODD )
189    parodd = 0x0000;              /* Odd parity */
190  else
191    parodd = 0x0100;
192
193  /*
194   * Character Length = start + data + parity + stop - 1
195   */
196  switch ( 1 + csize + psize + ssize - 1 ) {
197    case 6:     clen = 0x3000;       break;
198    case 7:     clen = 0x3800;       break;
199    case 8:     clen = 0x4000;       break;
200    case 9:     clen = 0x4800;       break;
201    case 10:    clen = 0x5000;       break;
202    case 11:    clen = 0x5800;       break;
203  }
204
205  if ( t->c_cflag & CREAD )
206    cread = 0x0023;             /* UART normal operation, enable Rx and Tx */
207  else
208    cread = 0x0021;             /* UART normal operation, enable Tx */
209
210  /* Write the SIMODE/SMCMR registers */
211  switch (minor) {
212    case SMC1_MINOR:
213/*
214      m8xx.simode = ( (m8xx.simode & 0xffff8fff) | (brg << 12) );
215*/
216      m8260.smc1.smcmr = clen | cstopb | parenb | parodd | cread;
217      break;
218    case SMC2_MINOR:
219      /* CHECK THIS */
220/*
221      m8xx.simode = ( (m8xx.simode & 0x8fffffff) | (brg << 28) );
222*/
223      m8260.smc2.smcmr = clen | cstopb | parenb | parodd | cread;
224      break;
225  }
226  return 0;
227}
228
229
230static int
231m8xx_scc_set_attributes (int minor, const struct termios *t)
232{
233  int baud, brg=0;
234  uint16_t   csize=0, cstopb, parenb, parodd;
235
236  /* Baud rate */
237  switch (t->c_cflag & CBAUD) {
238  default:      baud = -1;      break;
239  case B50:     baud = 50;      break;
240  case B75:     baud = 75;      break;
241  case B110:    baud = 110;     break;
242  case B134:    baud = 134;     break;
243  case B150:    baud = 150;     break;
244  case B200:    baud = 200;     break;
245  case B300:    baud = 300;     break;
246  case B600:    baud = 600;     break;
247  case B1200:   baud = 1200;    break;
248  case B1800:   baud = 1800;    break;
249  case B2400:   baud = 2400;    break;
250  case B4800:   baud = 4800;    break;
251  case B9600:   baud = 9600;    break;
252  case B19200:  baud = 19200;   break;
253  case B38400:  baud = 38400;   break;
254  case B57600:  baud = 57600;   break;
255  case B115200: baud = 115200;  break;
256  case B230400: baud = 230400;  break;
257  case B460800: baud = 460800;  break;
258  }
259  if (baud > 0) {
260    brg = m8xx_get_brg( M8260_SCC_BRGS, baud*16 );
261    m8260.cmxscr &= ~(0xFF000000 >> (8*(minor-SCC1_MINOR)) );
262    m8260.cmxscr |= ((brg<<(3+8*(3-(minor-SCC1_MINOR)))) &
263                     (brg<<(8*(3-(minor-SCC1_MINOR)))));
264  }
265  /* Number of data bits */
266  switch ( t->c_cflag & CSIZE ) {
267    case CS5:     csize = 0x0000;       break;
268    case CS6:     csize = 0x1000;       break;
269    case CS7:     csize = 0x2000;       break;
270    case CS8:     csize = 0x3000;       break;
271  }
272
273  /* Stop bits */
274  if ( t->c_cflag & CSTOPB )
275    cstopb = 0x4000;              /* Two stop bits */
276  else
277    cstopb = 0x0000;              /* One stop bit */
278
279  /* Parity */
280  if ( t->c_cflag & PARENB )
281    parenb = 0x0010;              /* Parity enabled on Tx and Rx */
282  else
283    parenb = 0x0000;              /* No parity on Tx and Rx */
284
285  if ( t->c_cflag & PARODD )
286    parodd = 0x0000;              /* Odd parity */
287  else
288    parodd = 0x000a;
289
290  /* Write the SICR/PSMR Registers */
291  switch (minor) {
292    case SCC1_MINOR:
293/*
294      m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) );
295*/
296      m8260.scc1.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc1.psmr & 0x8fe0) );
297      break;
298    case SCC2_MINOR:
299/*
300      m8xx.sicr = ( (m8xx.sicr & 0xffffc0ff) | (brg << 11) | (brg << 8) );
301*/
302      m8260.scc2.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc2.psmr & 0x8fe0) );
303      break;
304    case SCC3_MINOR:
305/*
306      m8xx.sicr = ( (m8xx.sicr & 0xffc0ffff) | (brg << 19) | (brg << 16) );
307*/
308      m8260.scc3.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc3.psmr & 0x8fe0) );
309      break;
310    case SCC4_MINOR:
311/*
312      m8xx.sicr = ( (m8xx.sicr & 0xc0ffffff) | (brg << 27) | (brg << 24) );
313*/
314      m8260.scc4.psmr = ( (cstopb | csize | parenb | parodd) | (m8260.scc4.psmr & 0x8fe0) );
315      break;
316  }
317
318  return 0;
319}
320
321
322int
323m8xx_uart_setAttributes(
324  int minor,
325  const struct termios *t
326)
327{
328  /*
329   * Check that port number is valid
330   */
331  if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) )
332    return 0;
333
334  switch (minor) {
335    case SMC1_MINOR:
336    case SMC2_MINOR:
337      return m8xx_smc_set_attributes( minor, t );
338
339    case SCC1_MINOR:
340    case SCC2_MINOR:
341    case SCC3_MINOR:
342    case SCC4_MINOR:
343      return m8xx_scc_set_attributes( minor, t );
344  }
345  return 0;
346}
347
348
349/*
350 * Interrupt handlers
351 */
352
353static void
354m8xx_scc1_interrupt_handler (rtems_irq_hdl_param unused)
355{
356  /*
357   * Buffer received?
358   */
359  if ((m8260.scc1.sccm & M8260_SCCE_RX) && (m8260.scc1.scce & M8260_SCCE_RX)) {
360    m8260.scc1.scce = M8260_SCCE_RX;    /* Clear the event */
361
362
363    /* Check that the buffer is ours */
364    if ((RxBd[SCC1_MINOR]->status & M8260_BD_EMPTY) == 0) {
365      rtems_cache_invalidate_multiple_data_lines(
366        (const void *) RxBd[SCC1_MINOR]->buffer,
367        RxBd[SCC1_MINOR]->length );
368      rtems_termios_enqueue_raw_characters(
369        (void *)ttyp[SCC1_MINOR],
370        (char *)RxBd[SCC1_MINOR]->buffer,
371        (int)RxBd[SCC1_MINOR]->length );
372      RxBd[SCC1_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
373                                 M8260_BD_INTERRUPT;
374    }
375  }
376
377  /*
378   * Buffer transmitted?
379   */
380  if (m8260.scc1.scce & M8260_SCCE_TX) {
381    m8260.scc1.scce = M8260_SCCE_TX;  /* Clear the event */
382
383    /* Check that the buffer is ours */
384    if ((TxBd[SCC1_MINOR]->status & M8260_BD_READY) == 0)
385      rtems_termios_dequeue_characters (
386        (void *)ttyp[SCC1_MINOR],
387        (int)TxBd[SCC1_MINOR]->length);
388  }
389
390#if 0
391  m8260.sipnr_l |= M8260_SIMASK_SCC1;      /* Clear pending register */
392#endif
393}
394
395static void
396m8xx_scc2_interrupt_handler (rtems_irq_hdl_param unused)
397{
398  /*
399   * Buffer received?
400   */
401  if ((m8260.scc2.sccm & M8260_SCCE_RX) && (m8260.scc2.scce & M8260_SCCE_RX)) {
402    m8260.scc2.scce = M8260_SCCE_RX;    /* Clear the event */
403
404
405    /* Check that the buffer is ours */
406    if ((RxBd[SCC2_MINOR]->status & M8260_BD_EMPTY) == 0) {
407      rtems_cache_invalidate_multiple_data_lines(
408        (const void *) RxBd[SCC2_MINOR]->buffer,
409        RxBd[SCC2_MINOR]->length );
410      rtems_termios_enqueue_raw_characters(
411        (void *)ttyp[SCC2_MINOR],
412        (char *)RxBd[SCC2_MINOR]->buffer,
413        (int)RxBd[SCC2_MINOR]->length );
414      RxBd[SCC2_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
415                                 M8260_BD_INTERRUPT;
416    }
417  }
418
419  /*
420   * Buffer transmitted?
421   */
422  if (m8260.scc2.scce & M8260_SCCE_TX) {
423    m8260.scc2.scce = M8260_SCCE_TX;  /* Clear the event */
424
425    /* Check that the buffer is ours */
426    if ((TxBd[SCC2_MINOR]->status & M8260_BD_READY) == 0)
427      rtems_termios_dequeue_characters (
428        (void *)ttyp[SCC2_MINOR],
429        (int)TxBd[SCC2_MINOR]->length);
430  }
431
432#if 0
433  m8260.sipnr_l |= M8260_SIMASK_SCC2;      /* Clear pending register */
434#endif
435}
436
437
438static void
439m8xx_scc3_interrupt_handler (rtems_irq_hdl_param unused)
440{
441  /*
442   * Buffer received?
443   */
444  if ((m8260.scc3.sccm & M8260_SCCE_RX) && (m8260.scc3.scce & M8260_SCCE_RX)) {
445    m8260.scc3.scce = M8260_SCCE_RX;  /* Clear the event */
446
447
448    /* Check that the buffer is ours */
449    if ((RxBd[SCC3_MINOR]->status & M8260_BD_EMPTY) == 0) {
450      rtems_cache_invalidate_multiple_data_lines(
451        (const void *) RxBd[SCC3_MINOR]->buffer,
452        RxBd[SCC3_MINOR]->length );
453      rtems_termios_enqueue_raw_characters(
454        (void *)ttyp[SCC3_MINOR],
455        (char *)RxBd[SCC3_MINOR]->buffer,
456        (int)RxBd[SCC3_MINOR]->length );
457      RxBd[SCC3_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
458                                 M8260_BD_INTERRUPT;
459    }
460  }
461
462  /*
463   * Buffer transmitted?
464   */
465  if (m8260.scc3.scce & M8260_SCCE_TX) {
466    m8260.scc3.scce = M8260_SCCE_TX;    /* Clear the event */
467
468    /* Check that the buffer is ours */
469    if ((TxBd[SCC3_MINOR]->status & M8260_BD_READY) == 0)
470      rtems_termios_dequeue_characters (
471        (void *)ttyp[SCC3_MINOR],
472        (int)TxBd[SCC3_MINOR]->length);
473  }
474
475
476#if 0
477  m8260.sipnr_l |= M8260_SIMASK_SCC3;      /* Clear pending register */
478#endif
479}
480
481
482static void
483m8xx_scc4_interrupt_handler (rtems_irq_hdl_param unused)
484{
485  /*
486   * Buffer received?
487   */
488  if ((m8260.scc4.sccm & M8260_SCCE_RX) && (m8260.scc4.scce & M8260_SCCE_RX)) {
489    m8260.scc4.scce = M8260_SCCE_RX;  /* Clear the event */
490
491
492    /* Check that the buffer is ours */
493    if ((RxBd[SCC4_MINOR]->status & M8260_BD_EMPTY) == 0) {
494      rtems_cache_invalidate_multiple_data_lines(
495        (const void *) RxBd[SCC4_MINOR]->buffer,
496        RxBd[SCC4_MINOR]->length );
497      rtems_termios_enqueue_raw_characters(
498        (void *)ttyp[SCC4_MINOR],
499        (char *)RxBd[SCC4_MINOR]->buffer,
500        (int)RxBd[SCC4_MINOR]->length );
501      RxBd[SCC4_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
502                                 M8260_BD_INTERRUPT;
503    }
504  }
505
506  /*
507   * Buffer transmitted?
508   */
509  if (m8260.scc4.scce & M8260_SCCE_TX) {
510    m8260.scc4.scce = M8260_SCCE_TX;    /* Clear the event */
511
512    /* Check that the buffer is ours */
513    if ((TxBd[SCC4_MINOR]->status & M8260_BD_READY) == 0)
514      rtems_termios_dequeue_characters (
515        (void *)ttyp[SCC4_MINOR],
516        (int)TxBd[SCC4_MINOR]->length);
517  }
518
519#if 0
520  m8260.sipnr_l |= M8260_SIMASK_SCC4;      /* Clear pending register */
521#endif
522}
523
524static void
525m8xx_smc1_interrupt_handler (rtems_irq_hdl_param unused)
526{
527  /*
528   * Buffer received?
529   */
530  if (m8260.smc1.smce & M8260_SMCE_RX) {
531    m8260.smc1.smce = M8260_SMCE_RX;  /* Clear the event */
532
533
534    /* Check that the buffer is ours */
535    if ((RxBd[SMC1_MINOR]->status & M8260_BD_EMPTY) == 0) {
536      rtems_cache_invalidate_multiple_data_lines(
537        (const void *) RxBd[SMC1_MINOR]->buffer,
538        RxBd[SMC1_MINOR]->length );
539      rtems_termios_enqueue_raw_characters(
540        (void *)ttyp[SMC1_MINOR],
541        (char *)RxBd[SMC1_MINOR]->buffer,
542        (int)RxBd[SMC1_MINOR]->length );
543      RxBd[SMC1_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
544                                 M8260_BD_INTERRUPT;
545    }
546  }
547
548  /*
549   * Buffer transmitted?
550   */
551  if (m8260.smc1.smce & M8260_SMCE_TX) {
552    m8260.smc1.smce = M8260_SMCE_TX;    /* Clear the event */
553
554    /* Check that the buffer is ours */
555    if ((TxBd[SMC1_MINOR]->status & M8260_BD_READY) == 0)
556      rtems_termios_dequeue_characters (
557        (void *)ttyp[SMC1_MINOR],
558        (int)TxBd[SMC1_MINOR]->length);
559  }
560
561#if 0
562  m8260.sipnr_l = 0x00001000; /* Clear SMC1 interrupt-in-service bit */
563#endif
564}
565
566
567static void
568m8xx_smc2_interrupt_handler (rtems_irq_hdl_param unused)
569{
570  /*
571   * Buffer received?
572   */
573  if (m8260.smc2.smce & M8260_SMCE_RX) {
574    m8260.smc2.smce = M8260_SMCE_RX;  /* Clear the event */
575
576
577    /* Check that the buffer is ours */
578    if ((RxBd[SMC2_MINOR]->status & M8260_BD_EMPTY) == 0) {
579      rtems_cache_invalidate_multiple_data_lines(
580        (const void *) RxBd[SMC2_MINOR]->buffer,
581        RxBd[SMC2_MINOR]->length );
582      rtems_termios_enqueue_raw_characters(
583        (void *)ttyp[SMC2_MINOR],
584        (char *)RxBd[SMC2_MINOR]->buffer,
585        (int)RxBd[SMC2_MINOR]->length );
586      RxBd[SMC2_MINOR]->status = M8260_BD_EMPTY | M8260_BD_WRAP |
587                                 M8260_BD_INTERRUPT;
588    }
589  }
590
591  /*
592   * Buffer transmitted?
593   */
594  if (m8260.smc2.smce & M8260_SMCE_TX) {
595    m8260.smc2.smce = M8260_SMCE_TX;    /* Clear the event */
596
597    /* Check that the buffer is ours */
598    if ((TxBd[SMC2_MINOR]->status & M8260_BD_READY) == 0)
599      rtems_termios_dequeue_characters (
600        (void *)ttyp[SMC2_MINOR],
601        (int)TxBd[SMC2_MINOR]->length);
602  }
603
604#if 0
605  m8260.sipnr_l = 0x00000800; /* Clear SMC2 interrupt-in-service bit */
606#endif
607}
608
609
610void m8xx_scc_enable(const rtems_irq_connect_data* ptr)
611{
612  volatile m8260SCCRegisters_t *sccregs = 0;
613  switch (ptr->name) {
614  case BSP_CPM_IRQ_SCC4 :
615    m8260.sipnr_l |= M8260_SIMASK_SCC4;
616    sccregs = &m8260.scc4;
617    break;
618  case BSP_CPM_IRQ_SCC3 :
619    m8260.sipnr_l |= M8260_SIMASK_SCC3;
620    sccregs = &m8260.scc3;
621    break;
622  case BSP_CPM_IRQ_SCC2 :
623    m8260.sipnr_l |= M8260_SIMASK_SCC2;
624    sccregs = &m8260.scc2;
625    break;
626  case BSP_CPM_IRQ_SCC1 :
627    m8260.sipnr_l |= M8260_SIMASK_SCC1;
628    sccregs = &m8260.scc1;
629    break;
630  default:
631    break;
632  }
633  sccregs->sccm = 3;
634}
635
636void m8xx_scc_disable(const rtems_irq_connect_data* ptr)
637{
638  volatile m8260SCCRegisters_t *sccregs = 0;
639  switch (ptr->name) {
640  case BSP_CPM_IRQ_SCC4 :
641    sccregs = &m8260.scc4;
642    break;
643  case BSP_CPM_IRQ_SCC3 :
644    sccregs = &m8260.scc3;
645    break;
646  case BSP_CPM_IRQ_SCC2 :
647    sccregs = &m8260.scc2;
648    break;
649  case BSP_CPM_IRQ_SCC1 :
650    sccregs = &m8260.scc1;
651    break;
652  default:
653    break;
654  }
655  sccregs->sccm &= (~3);
656}
657
658int m8xx_scc_isOn(const rtems_irq_connect_data* ptr)
659{
660 return BSP_irq_enabled_at_cpm (ptr->name);
661}
662
663static rtems_irq_connect_data consoleIrqData =
664{
665  BSP_CPM_IRQ_SCC1,
666  (rtems_irq_hdl)m8xx_scc1_interrupt_handler,
667  NULL,
668  (rtems_irq_enable) m8xx_scc_enable,
669  (rtems_irq_disable) m8xx_scc_disable,
670  (rtems_irq_is_enabled) m8xx_scc_isOn
671};
672
673
674void
675m8xx_uart_scc_initialize (int minor)
676{
677  unsigned char brg;
678  volatile m8260SCCparms_t *sccparms = 0;
679  volatile m8260SCCRegisters_t *sccregs = 0;
680
681  /*
682   * Check that minor number is valid
683   */
684  if ( (minor < SCC1_MINOR) || (minor > NUM_PORTS-1) )
685    return;
686
687  /* Get the sicr clock source bit values for 9600 bps */
688  brg = m8xx_get_brg(M8260_SCC_BRGS, 9600*16);
689
690  m8260.cmxscr &= ~(0xFF000000 >> (8*(minor-SCC1_MINOR)) );
691  m8260.cmxscr |= (brg<<(3+8*(3-(minor-SCC1_MINOR))));
692  m8260.cmxscr |= (brg<<(8*(3-(minor-SCC1_MINOR))));
693
694  /*
695   * Allocate buffer descriptors
696   */
697  RxBd[minor] = m8xx_bd_allocate(1);
698  TxBd[minor] = m8xx_bd_allocate(1);
699
700  /*
701   * Configure ports to enable TXDx and RXDx pins
702   */
703
704  m8260.ppard |=  (0x07 << ((minor-SCC1_MINOR)*3));
705  m8260.psord &= ~(0x07 << ((minor-SCC1_MINOR)*3));
706  if( minor == SCC1_MINOR )
707    m8260.psord |= 0x02;
708  m8260.pdird |=  (0x06 << ((minor-SCC1_MINOR)*3));
709  m8260.pdird &= ~(0x01 << ((minor-SCC1_MINOR)*3));
710
711
712  /*
713   * Set up SMC1 parameter RAM common to all protocols
714   */
715  if( minor == SCC1_MINOR ) {
716    sccparms = (m8260SCCparms_t*)&m8260.scc1p;
717    sccregs  = (m8260SCCRegisters_t*)&m8260.scc1;
718  }
719  else if( minor == SCC2_MINOR ) {
720    sccparms = (m8260SCCparms_t*)&m8260.scc2p;
721    sccregs  = (m8260SCCRegisters_t*)&m8260.scc2;
722  }
723  else if( minor == SCC3_MINOR ) {
724    sccparms = (m8260SCCparms_t*)&m8260.scc3p;
725    sccregs  = (m8260SCCRegisters_t*)&m8260.scc3;
726  }
727  else {
728    sccparms = (m8260SCCparms_t*)&m8260.scc4p;
729    sccregs  = (m8260SCCRegisters_t*)&m8260.scc4;
730  }
731
732  sccparms->rbase = (char *)RxBd[minor] - (char *)&m8260;
733  sccparms->tbase = (char *)TxBd[minor] - (char *)&m8260;
734
735
736
737
738  sccparms->rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS;
739  sccparms->tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS;
740  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 )
741    sccparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
742  else
743    sccparms->mrblr = 1;            /* Maximum Rx buffer size */
744  sccparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
745  sccparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
746
747  sccparms->un.uart.parec = 0;      /* Clear parity error counter */
748  sccparms->un.uart.frmec = 0;      /* Clear framing error counter */
749  sccparms->un.uart.nosec = 0;      /* Clear noise counter */
750  sccparms->un.uart.brkec = 0;      /* Clear break counter */
751
752  sccparms->un.uart.uaddr[0] = 0;   /* Not in multidrop mode, so clear */
753  sccparms->un.uart.uaddr[1] = 0;   /* Not in multidrop mode, so clear */
754  sccparms->un.uart.toseq  = 0;     /* Tx Out-Of-SEQuence--no XON/XOFF now */
755
756  sccparms->un.uart.character[0] = 0x8000; /* Entry is invalid */
757  sccparms->un.uart.character[1] = 0x8000; /* Entry is invalid */
758  sccparms->un.uart.character[2] = 0x8000; /* Entry is invalid */
759  sccparms->un.uart.character[3] = 0x8000; /* Entry is invalid */
760  sccparms->un.uart.character[4] = 0x8000; /* Entry is invalid */
761  sccparms->un.uart.character[5] = 0x8000; /* Entry is invalid */
762  sccparms->un.uart.character[6] = 0x8000; /* Entry is invalid */
763  sccparms->un.uart.character[7] = 0x8000; /* Entry is invalid */
764
765
766  sccparms->un.uart.rccm = 0xc0ff;  /* No masking */
767
768  /*
769   * Set up the Receive Buffer Descriptor
770   */
771  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
772  RxBd[minor]->length = 0;
773  RxBd[minor]->buffer = rxBuf[minor];
774
775  /*
776   * Setup the Transmit Buffer Descriptor
777   */
778  TxBd[minor]->status = M8260_BD_WRAP;
779
780 /*
781   * Set up SCCx general and protocol-specific mode registers
782   */
783  sccregs->gsmr_h = 0x00000020;     /* RFW=low latency operation */
784  sccregs->gsmr_l = 0x00028004;     /* TDCR=RDCR=16x clock mode, MODE=uart*/
785  sccregs->scce = ~0;               /* Clear any pending event */
786  sccregs->sccm = 0;                /* Mask all interrupt/event sources */
787  sccregs->psmr = 0x3000;           /* Normal operation & mode, 1 stop bit,
788                                       8 data bits, no parity */
789  sccregs->dsr = 0x7E7E;            /* No fractional stop bits */
790  sccregs->gsmr_l = 0x00028034;     /* ENT=enable Tx, ENR=enable Rx */
791
792  /*
793   *  Initialize the Rx and Tx with the new parameters.
794   */
795  switch (minor) {
796    case SCC1_MINOR:
797      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC1);
798      break;
799    case SCC2_MINOR:
800      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC2);
801      break;
802    case SCC3_MINOR:
803      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC3);
804      break;
805    case SCC4_MINOR:
806      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SCC4);
807      break;
808  }
809
810  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) {
811    switch (minor) {
812      case SCC1_MINOR:
813        consoleIrqData.name = BSP_CPM_IRQ_SCC1;
814        consoleIrqData.hdl = m8xx_scc1_interrupt_handler;
815        break;
816      case SCC2_MINOR:
817        consoleIrqData.name = BSP_CPM_IRQ_SCC2;
818        consoleIrqData.hdl = m8xx_scc2_interrupt_handler;
819        break;
820      case SCC3_MINOR:
821        consoleIrqData.name = BSP_CPM_IRQ_SCC3;
822        consoleIrqData.hdl = m8xx_scc3_interrupt_handler;
823        break;
824      case SCC4_MINOR:
825        consoleIrqData.name = BSP_CPM_IRQ_SCC4;
826        consoleIrqData.hdl = m8xx_scc4_interrupt_handler;
827        break;
828
829    }
830    if (!BSP_install_rtems_irq_handler (&consoleIrqData)) {
831      printk("Unable to connect SCC Irq handler\n");
832      rtems_fatal_error_occurred(1);
833    }
834  }
835}
836
837
838
839void m8xx_smc_enable(const rtems_irq_connect_data* ptr)
840{
841  volatile m8260SMCRegisters_t *smcregs = 0;
842  switch (ptr->name) {
843  case BSP_CPM_IRQ_SMC1 :
844    smcregs = &m8260.smc1;
845    break;
846  case BSP_CPM_IRQ_SMC2 :
847    smcregs = &m8260.smc2;
848    break;
849  default:
850    break;
851  }
852  smcregs->smcm = 3;
853}
854
855void m8xx_smc_disable(const rtems_irq_connect_data* ptr)
856{
857  volatile m8260SMCRegisters_t *smcregs = 0;
858  switch (ptr->name) {
859  case BSP_CPM_IRQ_SMC1 :
860    smcregs = &m8260.smc1;
861    break;
862  case BSP_CPM_IRQ_SMC2 :
863    smcregs = &m8260.smc2;
864    break;
865  default:
866    break;
867  }
868  smcregs->smcm &= (~3);
869}
870
871int m8xx_smc_isOn(const rtems_irq_connect_data* ptr)
872{
873 return BSP_irq_enabled_at_cpm (ptr->name);
874}
875
876
877void
878m8xx_uart_smc_initialize (int minor)
879{
880  unsigned char brg;
881  volatile m8260SMCparms_t *smcparms = 0;
882  volatile m8260SMCRegisters_t *smcregs = 0;
883
884  /*
885   * Check that minor number is valid
886   */
887  if ( (minor < SMC1_MINOR) || (minor > SMC2_MINOR) )
888    return;
889
890  /* Get the simode clock source bit values for 9600 bps */
891  if( minor == SMC1_MINOR )
892    brg = m8xx_get_brg(M8260_SMC1_BRGS, 9600*16);
893  else
894    brg = m8xx_get_brg(M8260_SMC2_BRGS, 9600*16);
895
896  /*
897   * Allocate buffer descriptors
898   */
899  RxBd[minor] = m8xx_bd_allocate (1);
900  TxBd[minor] = m8xx_bd_allocate (1);
901
902  /*
903   *  Get the address of the parameter RAM for the specified port,
904   *  configure I/O port B and put SMC in NMSI mode, connect the
905   *  SMC to the appropriate BRG.
906   *
907   *  SMC2 RxD is shared with port B bit 20
908   *  SMC2 TxD is shared with port B bit 21
909   *  SMC1 RxD is shared with port B bit 24
910   *  SMC1 TxD is shared with port B bit 25
911   */
912  switch (minor) {
913    case SMC1_MINOR:
914      smcparms = &m8260.smc1p;
915      smcregs  = &m8260.smc1;
916
917#if 0
918      m8260.pbpar |=  0x000000C0;    /* PB24 & PB25 are dedicated peripheral pins */
919      m8260.pbdir &= ~0x000000C0;    /* PB24 & PB25 must not drive UART lines */
920      m8260.pbodr &= ~0x000000C0;    /* PB24 & PB25 are not open drain */
921
922      m8260.simode &= 0xFFFF0FFF;    /* Clear SMC1CS & SMC1 for NMSI mode */
923      m8260.simode |= brg << 12;     /* SMC1CS = brg */
924#endif
925      break;
926
927    case SMC2_MINOR:
928      smcparms = &m8260.smc2p;
929      smcregs = &m8260.smc2;
930#if 0
931      m8260.pbpar |=  0x00000C00;    /* PB20 & PB21 are dedicated peripheral pins */
932      m8260.pbdir &= ~0x00000C00;    /* PB20 & PB21 must not drive the UART lines */
933      m8260.pbodr &= ~0x00000C00;    /* PB20 & PB21 are not open drain */
934
935      m8260.simode &= 0x0FFFFFFF;    /* Clear SMC2CS & SMC2 for NMSI mode */
936      m8260.simode |= brg << 28;     /* SMC2CS = brg */
937#endif
938      break;
939  }
940
941  /*
942   * Set up SMC parameter RAM common to all protocols
943   */
944  smcparms->rbase = (char *)RxBd[minor] - (char *)&m8260;
945  smcparms->tbase = (char *)TxBd[minor] - (char *)&m8260;
946  smcparms->rfcr = M8260_RFCR_MOT | M8260_RFCR_60X_BUS;
947  smcparms->tfcr = M8260_TFCR_MOT | M8260_TFCR_60X_BUS;
948  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 )
949    smcparms->mrblr = RXBUFSIZE;    /* Maximum Rx buffer size */
950  else
951    smcparms->mrblr = 1;            /* Maximum Rx buffer size */
952
953  /*
954   * Set up SMC1 parameter RAM UART-specific parameters
955   */
956  smcparms->un.uart.max_idl = 10;   /* Set nb of idle chars to close buffer */
957  smcparms->un.uart.brkcr = 0;      /* Set nb of breaks to send for STOP Tx */
958  smcparms->un.uart.brkec = 0;      /* Clear break counter */
959
960  /*
961   * Set up the Receive Buffer Descriptor
962   */
963  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
964  RxBd[minor]->length = 0;
965  RxBd[minor]->buffer = rxBuf[minor];
966
967  /*
968   * Setup the Transmit Buffer Descriptor
969   */
970  TxBd[minor]->status = M8260_BD_WRAP;
971
972  /*
973   * Set up SMCx general and protocol-specific mode registers
974   */
975  smcregs->smce = ~0;               /* Clear any pending events */
976  smcregs->smcm = 0;                /* Enable SMC Rx & Tx interrupts */
977  smcregs->smcmr = M8260_SMCMR_CLEN(9) | M8260_SMCMR_SM_UART;
978
979  /*
980   * Send "Init parameters" command
981   */
982  switch (minor) {
983    case SMC1_MINOR:
984      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SMC1);
985      break;
986
987    case SMC2_MINOR:
988      m8xx_cp_execute_cmd (M8260_CR_OP_INIT_RX_TX | M8260_CR_SMC2);
989      break;
990  }
991
992  /*
993   * Enable receiver and transmitter
994   */
995  smcregs->smcmr |= M8260_SMCMR_TEN | M8260_SMCMR_REN;
996  if ( (mbx8xx_console_get_configuration() & 0x06) == 0x02 ) {
997    consoleIrqData.on = m8xx_smc_enable;
998    consoleIrqData.off = m8xx_smc_disable;
999    consoleIrqData.isOn = m8xx_smc_isOn;
1000    switch (minor) {
1001      case SMC1_MINOR:
1002        consoleIrqData.name = BSP_CPM_IRQ_SMC1;
1003        consoleIrqData.hdl  = m8xx_smc1_interrupt_handler;
1004        break;
1005
1006      case SMC2_MINOR:
1007        consoleIrqData.name = BSP_CPM_IRQ_SMC2;
1008        consoleIrqData.hdl  = m8xx_smc2_interrupt_handler;
1009        break;
1010#if 0
1011      case SMC1_MINOR:
1012        rtems_interrupt_catch (m8xx_smc1_interrupt_handler,
1013                                    PPC_IRQ_CPM_SMC1,
1014                                    &old_handler[minor]);
1015
1016        smcregs->smcm = 3;            /* Enable SMC1 Rx & Tx interrupts */
1017        m8260.sipnr_l |= M8260_SIMASK_SMC1;      /* Clear pending register */
1018        m8260.simr_l  |= M8260_SIMASK_SMC1;      /* Enable SMC1 interrupts */
1019        break;
1020
1021      case SMC2_MINOR:
1022        rtems_interrupt_catch (m8xx_smc2_interrupt_handler,
1023                                    PPC_IRQ_CPM_SMC2,
1024                                    &old_handler[minor]);
1025
1026        smcregs->smcm = 3;            /* Enable SMC2 Rx & Tx interrupts */
1027        m8260.sipnr_l |= M8260_SIMASK_SMC2;      /* Clear pending register */
1028        m8260.simr_l  |= M8260_SIMASK_SMC2;      /* Enable SMC2 interrupts */
1029        break;
1030#endif
1031    }
1032    if (!BSP_install_rtems_irq_handler (&consoleIrqData)) {
1033      printk("Unable to connect SMC Irq handler\n");
1034      rtems_fatal_error_occurred(1);
1035    }
1036  }
1037}
1038
1039void
1040m8xx_uart_initialize(void)
1041{
1042
1043}
1044
1045
1046void
1047m8xx_uart_interrupts_initialize(void)
1048{
1049#ifdef mpc8260
1050  /* CHECK THIS */
1051
1052#else
1053
1054#if defined(mpc860)
1055  m8xx.cicr = 0x00E43F80;           /* SCaP=SCC1, SCbP=SCC2, SCcP=SCC3,
1056                                       SCdP=SCC4, IRL=1, HP=PC15, IEN=1 */
1057#else
1058  m8xx.cicr = 0x00043F80;           /* SCaP=SCC1, SCbP=SCC2, IRL=1, HP=PC15, IEN=1 */
1059#endif
1060  m8xx.simask |= M8xx_SIMASK_LVM1;  /* Enable level interrupts */
1061
1062#endif
1063}
1064
1065
1066int
1067m8xx_uart_pollRead(
1068  int minor
1069)
1070{
1071  unsigned char c;
1072
1073  if (RxBd[minor]->status & M8260_BD_EMPTY) {
1074    return -1;
1075  }
1076  rtems_cache_invalidate_multiple_data_lines(
1077    (const void *) RxBd[minor]->buffer,
1078    RxBd[minor]->length
1079  );
1080  c = ((char *)RxBd[minor]->buffer)[0];
1081  RxBd[minor]->status = M8260_BD_EMPTY | M8260_BD_WRAP;
1082  return c;
1083}
1084
1085
1086/*
1087 *  TODO: Get a free buffer and set it up.
1088 */
1089ssize_t
1090m8xx_uart_write(
1091  int minor,
1092  const char *buf,
1093  size_t len
1094)
1095{
1096  while( (TxBd[minor]->status) & M8260_BD_READY );
1097
1098  rtems_cache_flush_multiple_data_lines( buf, len );
1099  TxBd[minor]->buffer = (char *) buf;
1100  TxBd[minor]->length = len;
1101  TxBd[minor]->status = M8260_BD_READY | M8260_BD_WRAP | M8260_BD_INTERRUPT;
1102  return 0;
1103}
1104
1105
1106ssize_t
1107m8xx_uart_pollWrite(
1108  int minor,
1109  const char *buf,
1110  size_t len
1111)
1112{
1113  size_t retval = len;
1114
1115  while (len--) {
1116    while (TxBd[minor]->status & M8260_BD_READY)
1117      continue;
1118    txBuf[minor] = *buf++;
1119    rtems_cache_flush_multiple_data_lines( (void *)&txBuf[minor], 1 );
1120    TxBd[minor]->buffer = &txBuf[minor];
1121    TxBd[minor]->length = 1;
1122    TxBd[minor]->status = M8260_BD_READY | M8260_BD_WRAP;
1123  }
1124
1125  return retval;
1126}
Note: See TracBrowser for help on using the repository browser.