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

4.104.114.84.9
Last change on this file since d3d9ef37 was d3d9ef37, checked in by Jennifer Averett <Jennifer.Averett@…>, on Apr 15, 2005 at 6:30:11 PM

2005-04-15 Jennifer Averett <jennifer.averett@…>

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