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

4.115
Last change on this file since cfaa366 was cfaa366, checked in by Joel Sherrill <joel.sherrill@…>, on 05/03/12 at 17:55:58

General - Remove extraneous blank line in license message

Many files had an extra blank line in the license text
found in the file header. This patch removes that line.

The script that did this also turned off execute permission
when it was turned on incorrectly.

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