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

4.115
Last change on this file since 7ec9bd59 was 7ec9bd59, checked in by Joel Sherrill <joel.sherrill@…>, on 10/15/14 at 14:31:41

mpc8260 libcpu and mpc6260ads BSP: Fix warnings

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