source: rtems/c/src/lib/libbsp/powerpc/ep1a/console/mc68360_scc.c @ c499856

4.115
Last change on this file since c499856 was c499856, checked in by Chris Johns <chrisj@…>, on 03/20/14 at 21:10:47

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 27.5 KB
Line 
1/*  This file contains the termios TTY driver for the
2 *  Motorola MC68360 SCC ports.
3 *
4 *  COPYRIGHT (c) 1989-2008.
5 *  On-Line Applications Research Corporation (OAR).
6 *
7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
9 *  http://www.rtems.org/license/LICENSE.
10 */
11
12#include <stdio.h>
13#include <termios.h>
14#include <bsp.h>
15#include <libcpu/io.h>
16#include <rtems/libio.h>
17#include <bsp/pci.h>
18#include <bsp/irq.h>
19#include <libchip/serial.h>
20#include "m68360.h"
21#include <libchip/sersupp.h>
22#include <stdlib.h>
23#include <rtems/bspIo.h>
24#include <string.h>
25
26#if 0
27#define DEBUG_360
28#endif
29
30#if 1   /* XXX */
31int EP1A_READ_LENGTH_GREATER_THAN_1 = 0;
32
33#define MC68360_LENGTH_SIZE 400
34int mc68360_length_array[ MC68360_LENGTH_SIZE ];
35int mc68360_length_count=0;
36
37void mc68360_Show_length_array(void) {
38  int i;
39  for (i=0; i<MC68360_LENGTH_SIZE; i++)
40    printf(" %d", mc68360_length_array[i] );
41  printf("\n\n");
42}
43#endif
44
45
46M68360_t    M68360_chips = NULL;
47
48#define SYNC     eieio
49#define mc68360_scc_Is_422( _minor ) (Console_Port_Tbl[minor]->sDeviceName[7] == '4' )
50
51
52void mc68360_scc_nullFunc(void) {}
53
54uint8_t scc_read8(
55  const char       *name,
56  volatile uint8_t *address
57)
58{
59  uint8_t value;
60
61#ifdef DEBUG_360
62  printk( "RD8 %s 0x%08x ", name, address );
63#endif
64  value = *address;
65#ifdef DEBUG_360
66  printk( "0x%02x\n", value );
67#endif
68
69  return value;
70}
71
72void scc_write8(
73  const char       *name,
74  volatile uint8_t *address,
75  uint8_t           value
76)
77{
78#ifdef DEBUG_360
79  printk( "WR8 %s 0x%08x 0x%02x\n", name, address, value );
80#endif
81  *address = value;
82}
83
84
85uint16_t scc_read16(
86  const char        *name,
87  volatile uint16_t *address
88)
89{
90  uint16_t value;
91
92#ifdef DEBUG_360
93  printk( "RD16 %s 0x%08x ", name, address );
94#endif
95  value = *address;
96#ifdef DEBUG_360
97  printk( "0x%04x\n", value );
98#endif
99
100  return value;
101}
102
103void scc_write16(
104  const char        *name,
105  volatile uint16_t *address,
106  uint16_t           value
107)
108{
109#ifdef DEBUG_360
110  printk( "WR16 %s 0x%08x 0x%04x\n", name, address, value );
111#endif
112  *address = value;
113}
114
115
116uint32_t scc_read32(
117  const char        *name,
118  volatile uint32_t *address
119)
120{
121  uint32_t value;
122
123#ifdef DEBUG_360
124  printk( "RD32 %s 0x%08x ", name, address );
125#endif
126  value = *address;
127#ifdef DEBUG_360
128  printk( "0x%08x\n", value );
129#endif
130
131  return value;
132}
133
134void scc_write32(
135  const char        *name,
136  volatile uint32_t *address,
137  uint32_t           value
138)
139{
140#ifdef DEBUG_360
141  printk( "WR32 %s 0x%08x 0x%08x\n", name, address, value );
142#endif
143  *address = value;
144}
145
146void mc68360_sccShow_Regs(int minor){
147  M68360_serial_ports_t  ptr;
148  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
149
150  printk( "scce 0x%08x", &ptr->pSCCR->scce );
151  printk( " 0x%04x\n", ptr->pSCCR->scce );
152
153}
154
155#define TX_BUFFER_ADDRESS( _ptr ) \
156  ((char *)ptr->txBuf - (char *)ptr->chip->board_data->baseaddr)
157#define RX_BUFFER_ADDRESS( _ptr ) \
158  ((char *)ptr->rxBuf - (char *)ptr->chip->board_data->baseaddr)
159
160
161/**************************************************************************
162 * Function: mc68360_sccBRGC                                             *
163 **************************************************************************
164 * Description:                                                           *
165 *                                                                        *
166 *    This function is called to compute the divisor register values for  *
167 *    a given baud rate.                                                  *
168 *                                                                        *
169 *                                                                        *
170 * Inputs:                                                                *
171 *                                                                        *
172 *    int baud  - Baud rate (in bps).                                     *
173 *                                                                        *
174 * Output:                                                                *
175 *                                                                        *
176 *    int  - baud rate generator configuration.                           *
177 *                                                                        *
178 **************************************************************************/
179static int
180mc68360_sccBRGC(int baud, int m360_clock_rate)
181{
182   int data;
183#if 0
184   int divisor;
185   int div16;
186
187   div16 = 0;
188   divisor = ((m360_clock_rate / 16) + (baud / 2)) / baud;
189   if (divisor > 4096)
190   {
191      div16   = 1;
192      divisor = (divisor + 8) / 16;
193   }
194   return(M360_BRG_EN | M360_BRG_EXTC_BRGCLK |
195          ((divisor - 1) << 1) | div16);
196#endif
197
198  /*
199   * configure baud rate generator for 16x bit rate, where.....
200   * b    =   desired baud rate
201   * clk  =   system clock (33mhz)
202   * d    =   clock dividor value
203   *
204   * for b > 300  :   d = clk/(b*16)
205   * for b<= 300  :   d = (clk/ (b*16*16))-1)
206   */
207
208  SYNC();
209  if( baud > 300 ) data = 33333333 / (baud * 16 );
210  else             data = (33333333 / (baud * 16 * 16) ) - 1;
211  data *= 2;
212  data &= 0x00001ffe ;
213
214  /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
215  data |= ((baud>300)? 0 : 1 ) ;
216  data |= 0x010000 ;
217
218  return data;
219}
220
221
222/**************************************************************************
223 * Function: sccInterruptHandler                                          *
224 **************************************************************************
225 * Description:                                                           *
226 *                                                                        *
227 *    This is the interrupt service routine for the console UART.  It     *
228 *    handles both receive and transmit interrupts.  The bulk of the      *
229 *    work is done by termios.                                            *
230 *                                                                        *
231 * Inputs:                                                                *
232 *                                                                        *
233 *    chip  - structure of chip specific information                      *
234 *                                                                        *
235 * Output:                                                                *
236 *                                                                        *
237 *    none                                                                *
238 *                                                                        *
239 **************************************************************************/
240void mc68360_sccInterruptHandler( M68360_t chip )
241{
242  volatile m360_t    *m360;
243  int                port;
244  uint16_t           status;
245  uint16_t           length;
246  int                i;
247  char               data;
248  int                clear_isr;
249
250
251#ifdef DEBUG_360
252  printk("mc68360_sccInterruptHandler\n");
253#endif
254  for (port=0; port<4; port++) {
255
256      clear_isr = FALSE;
257      m360  = chip->m360;
258
259      /*
260       * XXX - Can we add something here to check if this is our interrupt.
261       * XXX - We need a parameter here so that we know which 360 instead of
262       *       looping through them all!
263       */
264
265      /*
266       * Handle a RX interrupt.
267       */
268      if ( scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x1)
269      {
270        clear_isr = TRUE;
271        scc_write16("scce", &chip->port[port].pSCCR->scce, 0x1 );
272        status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
273        while ((status & M360_BD_EMPTY) == 0)
274        {
275           length= scc_read16("sccRxBd->length",&chip->port[port].sccRxBd->length);
276if (length > 1)
277  EP1A_READ_LENGTH_GREATER_THAN_1 = length;
278
279           for (i=0;i<length;i++) {
280             data= chip->port[port].rxBuf[i];
281             rtems_termios_enqueue_raw_characters(
282               Console_Port_Data[ chip->port[port].minor ].termios_data,
283               &data,
284               1);
285           }
286           scc_write16( "sccRxBd->status", &chip->port[port].sccRxBd->status,
287                        M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
288           status =scc_read16( "sccRxBd->status", &chip->port[port].sccRxBd->status);
289        }
290      }
291
292      /*
293       * Handle a TX interrupt.
294       */
295      if (scc_read16("scce", &chip->port[port].pSCCR->scce) & 0x2)
296      {
297        clear_isr = TRUE;
298        scc_write16("scce", &chip->port[port].pSCCR->scce, 0x2);
299        status = scc_read16("sccTxBd->status", &chip->port[port].sccTxBd->status);
300        if ((status & M360_BD_EMPTY) == 0)
301        {
302           scc_write16("sccTxBd->status",&chip->port[port].sccTxBd->status,0);
303#if 1
304           rtems_termios_dequeue_characters(
305             Console_Port_Data[chip->port[port].minor].termios_data,
306             chip->port[port].sccTxBd->length);
307#else
308           mc68360_scc_write_support_int(chip->port[port].minor,"*****", 5);
309#endif
310        }
311      }
312
313      /*
314       * Clear SCC interrupt-in-service bit.
315       */
316      if ( clear_isr )
317        scc_write32( "cisr", &m360->cisr, (0x80000000 >> chip->port[port].channel) );
318  }
319}
320
321/*
322 *  mc68360_scc_open
323 *
324 *  This function opens a port for communication.
325 *
326 *  Default state is 9600 baud, 8 bits, No parity, and 1 stop bit.
327 */
328
329int mc68360_scc_open(
330  int      major,
331  int      minor,
332  void    * arg
333)
334{
335  M68360_serial_ports_t  ptr;
336  volatile m360_t       *m360;
337  uint32_t               data;
338
339#ifdef DEBUG_360
340  printk("mc68360_scc_open %d\n", minor);
341#endif
342
343
344  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
345  m360  = ptr->chip->m360;
346
347  /*
348   * Enable the receiver and the transmitter.
349   */
350
351  SYNC();
352  data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l);
353  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
354    (data | M360_GSMR_ENR | M360_GSMR_ENT) );
355
356  data  = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK );
357  data &= (~PMCQ1_INT_MASK_QUICC);
358  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data );
359
360  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS );
361  data &= (~PMCQ1_INT_STATUS_QUICC);
362  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data );
363
364  return RTEMS_SUCCESSFUL;
365}
366
367uint32_t mc68360_scc_calculate_pbdat( M68360_t chip )
368{
369  uint32_t               i;
370  uint32_t               pbdat_data;
371  int                    minor;
372  uint32_t               type422data[4] = {
373    0x00440,  0x00880,  0x10100,  0x20200
374  };
375
376  pbdat_data = 0x3;
377  for (i=0; i<4; i++) {
378    minor = chip->port[i].minor;
379    if mc68360_scc_Is_422( minor )
380      pbdat_data |= type422data[i];
381  }
382
383  return pbdat_data;
384}
385
386/*
387 *  mc68360_scc_initialize_interrupts
388 *
389 *  This routine initializes the console's receive and transmit
390 *  ring buffers and loads the appropriate vectors to handle the interrupts.
391 */
392
393void mc68360_scc_initialize_interrupts(int minor)
394{
395  M68360_serial_ports_t  ptr;
396  volatile m360_t       *m360;
397  uint32_t               data;
398  uint32_t               buffers_start;
399  uint32_t               tmp_u32;
400
401#ifdef DEBUG_360
402  printk("mc68360_scc_initialize_interrupts: minor %d\n", minor );
403  printk("Console_Port_Tbl[minor]->pDeviceParams 0x%08x\n",
404    Console_Port_Tbl[minor]->pDeviceParams );
405#endif
406
407  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
408  m360  = ptr->chip->m360;
409
410#ifdef DEBUG_360
411  printk("m360 0x%08x baseaddr 0x%08x\n",
412     m360, ptr->chip->board_data->baseaddr);
413#endif
414
415  buffers_start = ptr->chip->board_data->baseaddr + 0x00200000 +
416            ( (M68360_RX_BUF_SIZE + M68360_TX_BUF_SIZE) * (ptr->channel-1));
417  ptr->rxBuf = (uint8_t *) buffers_start;
418  ptr->txBuf = (uint8_t *)(buffers_start + M68360_RX_BUF_SIZE);
419#ifdef DEBUG_360
420  printk("rxBuf 0x%08x  txBuf 0x%08x\n", ptr->rxBuf, ptr->txBuf );
421#endif
422  /*
423   * Set Channel Drive Enable bits in EPLD
424   */
425  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
426  SYNC();
427  data = data & ~(PMCQ1_DRIVER_ENABLE_3 | PMCQ1_DRIVER_ENABLE_2 |
428                  PMCQ1_DRIVER_ENABLE_1 | PMCQ1_DRIVER_ENABLE_0);
429  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE, data);
430  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_DRIVER_ENABLE );
431  SYNC();
432
433  /*
434   * Disable the receiver and the transmitter.
435   */
436
437  SYNC();
438  tmp_u32 = scc_read32( "gsmr_l", &ptr->pSCCR->gsmr_l );
439  tmp_u32 &= (~(M360_GSMR_ENR | M360_GSMR_ENT ) ) ;
440  scc_write32( "gsmr_l", &ptr->pSCCR->gsmr_l, tmp_u32 );
441
442  /*
443   * Disable Interrupt Error and Interrupt Breakpoint
444   * Set SAID to 4 XXX - Shouldn't it be 7 for slave mode
445   * Set SAISM to 7
446   */
447  SYNC();
448  scc_write16( "sdcr", &m360->sdcr, 0x0740 );
449
450  /*
451   * Clear status -- reserved interrupt, SDMA channel error, SDMA breakpoint
452   */
453  scc_write8( "sdsr", &m360->sdsr, 0x07 );
454  SYNC();
455
456  /*
457   * Initialize timer information in RISC Controller Configuration Register
458   */
459  scc_write16( "rccr", &m360->rccr, 0x8100 );
460  SYNC();
461
462  /*
463   * XXX
464   */
465  scc_write16( "papar", &m360->papar, 0xffff );
466  scc_write16( "padir", &m360->padir, 0x5500 ); /* From Memo    */
467  scc_write16( "paodr", &m360->paodr, 0x0000 );
468  SYNC();
469
470  /*
471   * XXX
472   */
473
474#if 0
475  scc_write32( "pbpar", &m360->pbpar, 0x00000000 );
476  scc_write32( "pbdir", &m360->pbdir, 0x0003ffff );
477  scc_write32( "pbdat", &m360->pbdat, 0x0000003f );
478  SYNC();
479#else
480  data = mc68360_scc_calculate_pbdat( ptr->chip );
481  scc_write32( "pbpar", &m360->pbpar, 0x00000000 );
482  scc_write32( "pbdat", &m360->pbdat, data );
483  SYNC();
484  scc_write32( "pbdir", &m360->pbdir, 0x0003fc3 );
485  SYNC();
486#endif
487
488
489  /*
490   * XXX
491   */
492  scc_write16( "pcpar", &m360->pcpar, 0x0000 );
493  scc_write16( "pcdir", &m360->pcdir, 0x0000 );
494  scc_write16( "pcso", &m360->pcso, 0x0000 );
495  SYNC();
496
497  /*
498   * configure baud rate generator for 16x bit rate, where.....
499   * b    =   desired baud rate
500   * clk  =   system clock (33mhz)
501   * d    =   clock dividor value
502   *
503   * for b > 300  :   d = clk/(b*16)
504   * for b<= 300  :   d = (clk/ (b*16*16))-1)
505   */
506  SYNC();
507  if( ptr->baud > 300 ) data = 33333333 / (ptr->baud * 16 );
508  else                  data = (33333333 / (ptr->baud * 16 * 16) ) - 1;
509  data *= 2 ;
510  data &= 0x00001ffe ;
511
512  /* really data = 0x010000 | data | ((baud>300)? 0 : 1 ) ; */
513  data |= ((ptr->baud>300)? 0 : 1 ) ;
514  data |= 0x010000 ;
515
516  scc_write32( "pBRGC", ptr->pBRGC, data );
517
518  data =  (((ptr->channel-1)*8) | (ptr->channel-1)) ;
519  data = data << ((ptr->channel-1)*8) ;
520  data |= scc_read32( "sicr", &m360->sicr );
521  scc_write32( "sicr", &m360->sicr, data );
522
523  /*
524   * initialise SCC parameter ram
525   */
526  SYNC();
527  scc_write16( "pSCCB->rbase", &ptr->pSCCB->rbase,
528               (char *)(ptr->sccRxBd) - (char *)m360 );
529  scc_write16( "pSCCB->tbase", &ptr->pSCCB->tbase,
530               (char *)(ptr->sccTxBd) - (char *)m360 );
531
532  scc_write8( "pSCCB->rfcr", &ptr->pSCCB->rfcr, 0x15 ); /* 0x15 0x18 */
533  scc_write8( "pSCCB->tfcr", &ptr->pSCCB->tfcr, 0x15 ); /* 0x15 0x18 */
534
535  scc_write16( "pSCCB->mrblr", &ptr->pSCCB->mrblr, M68360_RX_BUF_SIZE );
536
537  /*
538   * initialise tx and rx scc parameters
539   */
540  SYNC();
541  data  = M360_CR_INIT_TX_RX_PARAMS | 0x01;
542  data |= (M360_CR_CH_NUM * (ptr->channel-1) );
543  scc_write16( "CR", &m360->cr, data );
544
545  /*
546   * initialise uart specific parameter RAM
547   */
548  SYNC();
549  scc_write16( "pSCCB->un.uart.max_idl", &ptr->pSCCB->un.uart.max_idl, 15000 );
550  scc_write16( "pSCCB->un.uart.brkcr", &ptr->pSCCB->un.uart.brkcr, 0x0001 );
551  scc_write16( "pSCCB->un.uart.parec", &ptr->pSCCB->un.uart.parec, 0x0000 );
552
553  scc_write16( "pSCCB->un,uart.frmec", &ptr->pSCCB->un.uart.frmec, 0x0000 );
554
555  scc_write16( "pSCCB->un.uart.nosec", &ptr->pSCCB->un.uart.nosec, 0x0000 );
556  scc_write16( "pSCCB->un.uart.brkec", &ptr->pSCCB->un.uart.brkec, 0x0000 );
557  scc_write16( "pSCCB->un.uart.uaddr0", &ptr->pSCCB->un.uart.uaddr[0], 0x0000 );
558  scc_write16( "pSCCB->un.uart.uaddr1", &ptr->pSCCB->un.uart.uaddr[1], 0x0000 );
559  scc_write16( "pSCCB->un.uart.toseq", &ptr->pSCCB->un.uart.toseq, 0x0000 );
560  scc_write16( "pSCCB->un.uart.char0",
561               &ptr->pSCCB->un.uart.character[0], 0x0039 );
562  scc_write16( "pSCCB->un.uart.char1",
563               &ptr->pSCCB->un.uart.character[1], 0x8000 );
564  scc_write16( "pSCCB->un.uart.char2",
565               &ptr->pSCCB->un.uart.character[2], 0x8000 );
566  scc_write16( "pSCCB->un.uart.char3",
567               &ptr->pSCCB->un.uart.character[3], 0x8000 );
568  scc_write16( "pSCCB->un.uart.char4",
569               &ptr->pSCCB->un.uart.character[4], 0x8000 );
570  scc_write16( "pSCCB->un.uart.char5",
571               &ptr->pSCCB->un.uart.character[5], 0x8000 );
572  scc_write16( "pSCCB->un.uart.char6",
573               &ptr->pSCCB->un.uart.character[6], 0x8000 );
574  scc_write16( "pSCCB->un.uart.char7",
575               &ptr->pSCCB->un.uart.character[7], 0x8000 );
576
577  scc_write16( "pSCCB->un.uart.rccm", &ptr->pSCCB->un.uart.rccm, 0xc0ff );
578
579  /*
580   * setup buffer descriptor stuff
581   */
582  SYNC();
583  scc_write16( "sccRxBd->status", &ptr->sccRxBd->status, 0x0000 );
584  SYNC();
585  scc_write16( "sccRxBd->length", &ptr->sccRxBd->length, 0x0000 );
586  scc_write16( "sccRxBd->status", &ptr->sccRxBd->status,
587               M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT );
588  /* XXX Radstone Example writes RX buffer ptr as two u16's */
589  scc_write32( "sccRxBd->buffer", &ptr->sccRxBd->buffer,
590               RX_BUFFER_ADDRESS( ptr ) );
591
592  SYNC();
593  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0x0000 );
594  SYNC();
595  scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, 0x0000 );
596  /* XXX Radstone Example writes TX buffer ptr as two u16's */
597  scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
598               TX_BUFFER_ADDRESS( ptr ) );
599
600  /*
601   * clear previous events and set interrupt priorities
602   */
603  scc_write16( "pSCCR->scce", &ptr->pSCCR->scce, 0x1bef ); /* From memo   */
604  SYNC();
605  SYNC();
606  scc_write32( "cicr", &m360->cicr, 0x001b9f40 );
607  SYNC();
608
609  /* scc_write32( "cicr", &m360->cicr, scc_read32( "cicr", &m360->cicr ) ); */
610
611  scc_write16( "pSCCR->sccm", &ptr->pSCCR->sccm, M360_SCCE_TX | M360_SCCE_RX );
612
613  data = scc_read32("cimr", &m360->cimr);
614  data |= (0x80000000 >> ptr->channel);
615  scc_write32( "cimr", &m360->cimr, data );
616  SYNC();
617  scc_write32( "cipr", &m360->cipr, scc_read32( "cipr", &m360->cipr ) );
618
619  scc_write32( "pSCCR->gsmr_h", &ptr->pSCCR->gsmr_h, M360_GSMR_RFW );
620  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
621        (M360_GSMR_TDCR_16X | M360_GSMR_RDCR_16X | M360_GSMR_MODE_UART) );
622
623  scc_write16( "pSCCR->dsr", &ptr->pSCCR->dsr, 0x7e7e );
624  SYNC();
625
626  scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr,
627               (M360_PSMR_CL8 | M360_PSMR_UM_NORMAL | M360_PSMR_TPM_ODD) );
628  SYNC();
629
630#if 0          /* XXX - ??? */
631  /*
632   * Enable the receiver and the transmitter.
633   */
634
635  SYNC();
636  data = scc_read32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l);
637  scc_write32( "pSCCR->gsmr_l", &ptr->pSCCR->gsmr_l,
638    (data | M360_GSMR_ENR | M360_GSMR_ENT) );
639
640  data  = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK );
641  data &= (~PMCQ1_INT_MASK_QUICC);
642  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_MASK, data );
643
644  data = PMCQ1_Read_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS );
645  data &= (~PMCQ1_INT_STATUS_QUICC);
646  PMCQ1_Write_EPLD(ptr->chip->board_data->baseaddr, PMCQ1_INT_STATUS, data );
647#endif
648}
649
650/*
651 *  mc68360_scc_write_support_int
652 *
653 *  Console Termios output entry point when using interrupt driven output.
654 */
655
656int mc68360_scc_write_support_int(
657  int         minor,
658  const char *buf,
659  int         len
660)
661{
662  rtems_interrupt_level  Irql;
663  M68360_serial_ports_t  ptr;
664
665#if 1
666  mc68360_length_array[ mc68360_length_count ] = len;
667  mc68360_length_count++;
668  if ( mc68360_length_count >= MC68360_LENGTH_SIZE )
669    mc68360_length_count=0;
670#endif
671
672  ptr   = Console_Port_Tbl[minor]->pDeviceParams;
673
674  /*
675   *  We are using interrupt driven output and termios only sends us
676   *  one character at a time.
677   */
678
679  if ( !len )
680    return 0;
681
682  /*
683   *
684   */
685#ifdef DEBUG_360
686  printk("mc68360_scc_write_support_int: char 0x%x length %d\n",
687       (unsigned int)*buf, len );
688#endif
689  /*
690   *  We must copy the data from the global memory space to MC68360 space
691   */
692
693  rtems_interrupt_disable(Irql);
694
695  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status, 0 );
696  memcpy((void *) ptr->txBuf, buf, len);
697  scc_write32( "sccTxBd->buffer", &ptr->sccTxBd->buffer,
698               TX_BUFFER_ADDRESS(ptr->txBuf) );
699  scc_write16( "sccTxBd->length", &ptr->sccTxBd->length, len );
700  scc_write16( "sccTxBd->status", &ptr->sccTxBd->status,
701               (M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT) );
702
703  rtems_interrupt_enable(Irql);
704
705  return len;
706}
707
708/*
709 *  mc68360_scc_write_polled
710 *
711 *  This routine polls out the requested character.
712 */
713
714void mc68360_scc_write_polled(
715  int   minor,
716  char  cChar
717)
718{
719#ifdef DEBUG_360
720  printk("mc68360_scc_write_polled: %c\n", cChar);
721#endif
722}
723
724/*
725 *  mc68681_set_attributes
726 *
727 *  This function sets the DUART channel to reflect the requested termios
728 *  port settings.
729 */
730
731int mc68360_scc_set_attributes(
732  int minor,
733  const struct termios *t
734)
735{
736   int                    baud;
737   volatile m360_t        *m360;
738   M68360_serial_ports_t  ptr;
739   uint16_t               value;
740
741#ifdef DEBUG_360
742printk("mc68360_scc_set_attributes\n");
743#endif
744
745   ptr   = Console_Port_Tbl[minor]->pDeviceParams;
746   m360  = ptr->chip->m360;
747
748   switch (t->c_cflag & CBAUD)
749   {
750      case B50:      baud = 50;      break;
751      case B75:      baud = 75;      break;
752      case B110:     baud = 110;     break;
753      case B134:     baud = 134;     break;
754      case B150:     baud = 150;     break;
755      case B200:     baud = 200;     break;
756      case B300:     baud = 300;     break;
757      case B600:     baud = 600;     break;
758      case B1200:    baud = 1200;    break;
759      case B1800:    baud = 1800;    break;
760      case B2400:    baud = 2400;    break;
761      case B4800:    baud = 4800;    break;
762      case B9600:    baud = 9600;    break;
763      case B19200:   baud = 19200;   break;
764      case B38400:   baud = 38400;   break;
765      case B57600:   baud = 57600;   break;
766      case B115200:  baud = 115200;  break;
767      case B230400:  baud = 230400;  break;
768      case B460800:  baud = 460800;  break;
769      default:       baud = -1;      break;
770   }
771
772   if (baud > 0)
773   {
774      scc_write32(
775        "pBRGC",
776        ptr->pBRGC,
777        mc68360_sccBRGC(baud, ptr->chip->m360_clock_rate)
778      );
779   }
780
781  /* Initial value of PSMR should be 0 */
782  value = M360_PSMR_UM_NORMAL;
783
784  /* set the number of data bits, 8 is most common */
785  if (t->c_cflag & CSIZE)                     /* was it specified? */
786  {
787    switch (t->c_cflag & CSIZE) {
788      case CS5: value |= M360_PSMR_CL5; break;
789      case CS6: value |= M360_PSMR_CL6; break;
790      case CS7: value |= M360_PSMR_CL7; break;
791      case CS8: value |= M360_PSMR_CL8; break;
792    }
793  } else {
794    value |= M360_PSMR_CL8;         /* default to 8 data bits */
795  }
796
797  /* the number of stop bits */
798  if (t->c_cflag & CSTOPB)
799    value |= M360_PSMR_SL_2;   /* Two stop bits */
800  else
801    value |= M360_PSMR_SL_1;   /* One stop bit  */
802
803  /* Set Parity M360_PSMR_PEN bit should be clear on no parity so
804   * do nothing in that case
805   */
806  if (t->c_cflag & PARENB)                /* enable parity detection? */
807  {
808    value |= M360_PSMR_PEN;
809    if (t->c_cflag & PARODD){
810      value |= M360_PSMR_RPM_ODD;        /* select odd parity */
811      value |= M360_PSMR_TPM_ODD;
812    } else {
813      value |= M360_PSMR_RPM_EVEN;       /* select even parity */
814      value |= M360_PSMR_TPM_EVEN;
815    }
816  }
817
818  SYNC();
819  scc_write16( "pSCCR->psmr", &ptr->pSCCR->psmr, value );
820  SYNC();
821
822  return 0;
823}
824
825/*
826 *  mc68360_scc_close
827 *
828 *  This function shuts down the requested port.
829 */
830
831int mc68360_scc_close(
832  int      major,
833  int      minor,
834  void    *arg
835)
836{
837  return(RTEMS_SUCCESSFUL);
838}
839
840/*
841 *  mc68360_scc_inbyte_nonblocking_polled
842 *
843 *  Console Termios polling input entry point.
844 */
845
846int mc68360_scc_inbyte_nonblocking_polled(
847  int minor
848)
849{
850    return -1;
851}
852
853/*
854 *  mc68360_scc_write_support_polled
855 *
856 *  Console Termios output entry point when using polled output.
857 *
858 */
859
860ssize_t mc68360_scc_write_support_polled(
861  int         minor,
862  const char *buf,
863  size_t      len
864)
865{
866  printk("mc68360_scc_write_support_polled: minor %d char %c len %d\n",
867         minor, buf, len );
868  return len;
869}
870
871/*
872 *  mc68360_scc_init
873 *
874 *  This function initializes the DUART to a quiecsent state.
875 */
876
877void mc68360_scc_init(int minor)
878{
879#ifdef DEBUG_360
880  printk("mc68360_scc_init\n");
881#endif
882}
883
884int mc68360_scc_create_chip( PPMCQ1BoardData BoardData, uint8_t int_vector )
885{
886  M68360_t   chip;
887  int        i;
888
889#ifdef DEBUG_360
890  printk("mc68360_scc_create_chip\n");
891#endif
892
893  /*
894   * Create console structure for this card
895   * XXX - Note Does this need to be moved up to if a QUICC is fitted
896   *       section?
897   */
898  if ((chip = malloc(sizeof(struct _m68360_per_chip))) == NULL)
899  {
900    printk("Error Unable to allocate memory for _m68360_per_chip\n");
901    return RTEMS_IO_ERROR;
902  }
903
904  chip->next                    = M68360_chips;
905  chip->m360                    = (void *)BoardData->baseaddr;
906  chip->m360_interrupt          = int_vector;
907  chip->m360_clock_rate         = 25000000;
908  chip->board_data              = BoardData;
909  M68360_chips                  = chip;
910
911  for (i=1; i<=4; i++) {
912    chip->port[i-1].channel     = i;
913    chip->port[i-1].chip        = chip;
914    chip->port[i-1].baud        = 9600;
915
916    switch( i ) {
917      case 1:
918        chip->port[i-1].pBRGC = &chip->m360->brgc1;
919        chip->port[i-1].pSCCB = (m360SCCparms_t *) &chip->m360->scc1p;
920        chip->port[i-1].pSCCR = &chip->m360->scc1;
921        M360SetupMemory( chip );            /* Do this first time through */
922        break;
923      case 2:
924        chip->port[i-1].pBRGC = &chip->m360->brgc2;
925        chip->port[i-1].pSCCB = &chip->m360->scc2p;
926        chip->port[i-1].pSCCR = &chip->m360->scc2;
927        break;
928      case 3:
929        chip->port[i-1].pBRGC = &chip->m360->brgc3;
930        chip->port[i-1].pSCCB = &chip->m360->scc3p;
931        chip->port[i-1].pSCCR = &chip->m360->scc3;
932        break;
933      case 4:
934        chip->port[i-1].pBRGC = &chip->m360->brgc4;
935        chip->port[i-1].pSCCB = &chip->m360->scc4p;
936        chip->port[i-1].pSCCR = &chip->m360->scc4;
937        break;
938      default:
939        printk("Invalid mc68360 channel %d\n", i);
940        return RTEMS_IO_ERROR;
941    }
942
943    /*
944     * Allocate buffer descriptors.
945     */
946
947    chip->port[i-1].sccRxBd = M360AllocateBufferDescriptors(chip, 1);
948    chip->port[i-1].sccTxBd = M360AllocateBufferDescriptors(chip, 1);
949  }
950
951  rsPMCQ1QuiccIntConnect(
952    chip->board_data->busNo,
953    chip->board_data->slotNo,
954    chip->board_data->funcNo,
955    &mc68360_sccInterruptHandler,
956    chip
957  );
958
959  return RTEMS_SUCCESSFUL;
960}
961
962const console_fns mc68360_scc_fns = {
963  libchip_serial_default_probe,        /* deviceProbe */
964  mc68360_scc_open,                    /* deviceFirstOpen */
965  NULL,                                /* deviceLastClose */
966  NULL,                                /* deviceRead */
967  mc68360_scc_write_support_int,       /* deviceWrite */
968  mc68360_scc_initialize_interrupts,   /* deviceInitialize */
969  mc68360_scc_write_polled,            /* deviceWritePolled */
970  mc68360_scc_set_attributes,          /* deviceSetAttributes */
971  TRUE                                 /* deviceOutputUsesInterrupts */
972};
973
974const console_fns mc68360_scc_polled = {
975  libchip_serial_default_probe,             /* deviceProbe */
976  mc68360_scc_open,                         /* deviceFirstOpen */
977  mc68360_scc_close,                        /* deviceLastClose */
978  mc68360_scc_inbyte_nonblocking_polled,    /* deviceRead */
979  mc68360_scc_write_support_polled,         /* deviceWrite */
980  mc68360_scc_init,                         /* deviceInitialize */
981  mc68360_scc_write_polled,                 /* deviceWritePolled */
982  mc68360_scc_set_attributes,               /* deviceSetAttributes */
983  FALSE                                     /* deviceOutputUsesInterrupts */
984};
985
Note: See TracBrowser for help on using the repository browser.