1 //=============================================================================
5 // HAL diagnostic I/O support routines for MPC8260/QUICC2
7 //=============================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //=============================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors:hmt, gthomas
47 // Purpose: HAL diagnostics I/O support
50 //####DESCRIPTIONEND####
52 //=============================================================================
54 #include <pkgconf/hal.h>
55 #include <cyg/hal/hal_mem.h> // HAL memory definitions
56 #include <cyg/infra/cyg_type.h>
57 #include <cyg/hal/hal_if.h> // hal_if_init
58 #include <cyg/hal/hal_io.h> // hal_if_init
59 #include <cyg/hal/hal_misc.h> // cyg_hal_is_break
61 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED
63 #include <cyg/hal/hal_diag.h>
64 #include <cyg/hal/ppc_regs.h>
65 #include <cyg/hal/var_intr.h>
66 #include <cyg/hal/mpc8260.h> // Needed for IMMR structure
68 // For Baud Rate Calculation, see MPC8260 PowerQUICC II User's Manual
69 // 16.3 UART Baud Rate Examples, page 16-5.
70 // BRGCx[DIV16] = 0 ==> value of 1 (Prescale divider)
71 // BRGCx[EXTC] = 16.667 MHz (Baud Rate generator input clock)
72 // GSMRx_L[xDCR] = 16 (Sampling Rate)
74 // BRGCx[EXTC] / (BRGCx[DIV16] * UART_BAUD_RATE * GSMRx_L[xDCR])
75 // UART_CLK_DIV = ((66.667 MHz / 4) / (UART_BAUD_RATE * 16)) - 1
76 // UART_CLK_DIV = ((66.667 MHz ) / (UART_BAUD_RATE * 64)) - 1
77 // UART_CLK_DIV = ((CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000 )
78 // / (UART_BAUD_RATE * 64)) (Calculation will truncate, so
80 #define UART_BIT_RATE(n) \
81 (((int)(CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000))/(n * 64))
82 #define UART_BAUD_RATE CYGNUM_HAL_DIAG_BAUD
85 /***********************/
86 /* Global Declarations */
87 /***********************/
90 volatile t_PQ2IMM *IMM; /* IMM base pointer */
91 volatile BDRINGS *RxTxBD; /* buffer descriptors base pointer */
92 volatile LB *SCC1Buffers; /* SCC1 base pointers */
94 #define SMC1_PRAM 0x04703800
95 #define BD_RX_ERROR 0xBF /* Mask for set of Receive Buffer Errors,
96 including: DE, LG, NO, AB, CR, OV, CD */
98 /*---------------------*/
99 /* Function Prototypes */
100 /*---------------------*/
102 static void InitSCC1Uart(void);
103 static void ConfigSCC1Clock(void);
104 static void InitParallelPorts(void);
105 static cyg_uint8 SCC1Poll(void);
106 static void InitBDs(void);
109 cyg_hal_plf_serial_getc(void* __ch_data);
112 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch);
115 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch);
118 cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch);
121 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
124 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len);
127 cyg_hal_plf_serial_init_channel(void);
130 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
131 CYG_ADDRWORD __vector, CYG_ADDRWORD __data);
134 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...);
137 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc,
138 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
140 t_PQ2IMM *immr = (t_PQ2IMM*) __ch_data;
141 struct cp_bufdesc *bd;
146 CYGARC_HAL_SAVE_GP();
150 dbg_values[10+dbg_values[3]] =
151 RxTxBD->RxBD.bd_cstatus
152 | (immr->scc_regs[SCC1].scce<<16);
155 if (immr->scc_regs[SCC1].scce & 0x0001) {
157 // Clear the event by writing a "1" to the prpoper bit.
158 immr->scc_regs[SCC1].scce = 0x0001;
160 if((RxTxBD->RxBD.bd_cstatus & 0x8000) == 0){
161 ch = *(RxTxBD->RxBD.bd_addr);
162 /*----------------------*/
163 /* Set Buffer Empty bit */
164 /*----------------------*/
165 //dbg_values[10+dbg_values[3]] = __vector | 0xffff0000;
166 //dbg_values[10+dbg_values[3]] |= ch << 8;
168 RxTxBD->RxBD.bd_cstatus |= 0x8000;
170 if( cyg_hal_is_break( &ch , 1 ) ){
173 //dbg_values[7] = immr->ic_sivec;
176 // Interrupt handled. Acknowledge it.
177 //eppc->cpmi_cisr = 0x10;
178 // Clear interrupt in SIPNR_L by writing a one to bit 8 (0x800000)
179 HAL_READ_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIPNR_L,
181 regval |= 0x00800000;
182 HAL_WRITE_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIPNR_L,
185 res = CYG_ISR_HANDLED;
189 CYGARC_HAL_RESTORE_GP();
193 /* Early initialization of comm channels. Must not rely
194 * on interrupts, yet. Interrupt operation can be enabled
195 * in _bsp_board_init().
198 cyg_hal_plf_serial_init(void)
200 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
201 hal_virtual_comm_table_t* comm;
202 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
204 static int init = 0; // It's wrong to do this more than once
208 // init_channel sets the global *IMM == 0x04700000, the base of the
209 // Internal Memory map for the MPC8260
210 cyg_hal_plf_serial_init_channel();
212 // Setup procs in the vector table
215 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);// Should be configurable!
216 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
217 CYGACC_COMM_IF_CH_DATA_SET(*comm, IMM);
218 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
219 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
220 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
221 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
222 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
223 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
224 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
226 // Restore original console
227 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
229 #else // No CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
230 static int init = 0; // It's wrong to do this more than once
234 cyg_hal_plf_serial_init_channel();
239 cyg_hal_plf_serial_init_channel(void)
241 /* We will assume here that the IMMR has been programmed such that
242 * the internal Memory Map starts at 0x04700000. Initialization
243 * should have done that setup.
246 IMM = (t_PQ2IMM *)0x04700000; /* MPC8260 internal register map */
248 /*----------------------------------------------------------------------*/
249 /* Get a pointer to the BD area on DP RAM. The buffer descriptors (BDs) */
250 /* and the Rx/Tx data buffers will be located right after SCC1's para- */
251 /* meter RAM area because only 2 BDs and 2 data buffers are being used */
252 /* for this port and SCC1 only uses 64 bytes of it's allotted 256 for */
253 /* it's parameter ram. One BD and one data buffer each for transmit and */
254 /* receive will be used. This buffer descriptor area will take up 16 */
256 /*----------------------------------------------------------------------*/
259 RxTxBD = (BDRINGS *) 0x04708070;
260 // (((CYG_WORD)&(IMM->pram.serials.scc_pram[SCC1])) + 72);
262 //RxTxBD = (BDRINGS *)
263 // (((CYG_WORD)&(IMM->pram.serials.scc_pram[SCC1])) + 72);
265 /*-------------------------------------------------------------------*/
266 /* Establish the buffer pool in Dual Port RAM. We do this because the*/
267 /* pool size is only 2 bytes (1 for Rx and 1 for Tx) and to avoid */
268 /* disabling data cache for the memory region where BufferPool would */
269 /* reside. The CPM does not recognize data in buffer pools once it */
270 /* been cached. It's acesses are direct through DMA to external */
272 /*-------------------------------------------------------------------*/
274 //SCC1Buffers = (LB *)
275 // (((CYG_WORD)&(IMM->pram.serials.scc_pram[SCC1])) + 96);
277 SCC1Buffers = (LB *) 0x04708090;
278 // (((CYG_WORD)&(IMM->pram.serials.scc_pram[SCC1]))
281 /*----------------------------------------*/
282 /* Initialize SCC1 and buffer descriptors */
283 /*----------------------------------------*/
290 /*---------------------------------------------------------------------------
292 * FUNCTION NAME: InitBDs
297 * Initializes BD rings to point RX BDs to first half of buffer pool and TX
298 * BDs to second half of buffer pool. This function also initializes the
299 * buffer descriptors control and data length fields. It also ensures that
300 * transmit and recieve functions are disabled before buffer descriptors are
303 * EXTERNAL EFFECTS: Disable Tx/Rx functions. Changes BDs in dual port ram.
309 *---------------------------------------------------------------------------*/
315 /*--------------------------------------------------------------------*/
316 /* First let's ensure the SCC1 functions are off while we program the */
317 /* buffer descriptors and the parameter ram. Clear the ENT/ENR bits */
318 /* in the GSMR -- disable Transmit/Receive */
319 /*--------------------------------------------------------------------*/
321 IMM->scc_regs[SCC1].gsmr_l &= DISABLE_TX_RX;
323 /*--------------------------------------*/
324 /* Issue Init Stop TX Command for SCC1. */
325 /*--------------------------------------*/
327 while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD);
329 IMM->cpm_cpcr = SCC1_PAGE_SUBBLOCK |
331 CPCR_FLG; /* ISSUE COMMAND */
333 while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD);
336 /*-----------------------------------*/
337 /* Setup Receiver Buffer Descriptors */
338 /*-----------------------------------*/
340 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
341 || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
342 /* Set receive Buffer to generate an interrupt when buffer full */
343 RxTxBD->RxBD.bd_cstatus = 0xB000; /* 0xB000; */
345 RxTxBD->RxBD.bd_cstatus = 0xA000; /* Empty, Wrap Bit */
347 //dbg_values[3] = RxTxBD->RxBD.bd_cstatus;
348 RxTxBD->RxBD.bd_length = 1;
349 RxTxBD->RxBD.bd_addr = &(SCC1Buffers->RxBuffer);
351 /*--------------------------------------*/
352 /* Setup Transmitter Buffer Descriptors */
353 /*--------------------------------------*/
355 RxTxBD->TxBD.bd_cstatus = 0x2800; /* Buffer not yet ready; Wrap Bit
356 Clear-to-send_report */
358 RxTxBD->TxBD.bd_length = 1;
359 RxTxBD->TxBD.bd_addr = &(SCC1Buffers->TxBuffer);
364 /*---------------------------------------------------------------------------
366 * FUNCTION NAME: InitSCC1Uart
371 * SCC1 Uart Mode Initialization Routine.
375 * Initializes SCC1 to operate in Uart mode at 9600 Baud, No Parity, 8 data
376 * bits, and 1 stop bit.
382 *--------------------------------------------------------------------------*/
388 /*----------------------------------------------------------------------*/
389 /* Configure the parallel ports so that TXD and RXD are connected to */
390 /* the appropriate port pins and are configured according to their */
392 /*----------------------------------------------------------------------*/
396 /*------------------------------------------*/
397 /* Configure Clock Source and Clock Routing */
398 /*------------------------------------------*/
402 /*-----------------------------------*/
403 /* Initialize the Buffer Descriptors */
404 /*-----------------------------------*/
408 /*----------------------------------------------------------------------*/
409 /* Program Rx and Tx Function Codes (RFCRx/TFCRx). */
411 /* - Bits 0-1 reserved. Set to zero. */
413 /* - GBL (Global) = 0 = Snooping Disabled. */
415 /* - BO (Byte Ordering) = 11 = Big-endian or true little-endian. */
417 /* - TC[2] (Transfer Code) = 0 = Transfer code is 0 */
419 /* - DTB (Data Bus Indicator) = 1 = */
421 /* Use the Local Bus for SDMA operation. In this example it doesn't */
422 /* matter because the buffer were located in parameter ram. Normally */
423 /* this bit would be set because data buffers normally will reside */
424 /* in Local memory. */
425 /*----------------------------------------------------------------------*/
427 IMM->pram.serials.scc_pram[SCC1].rfcr = 0x18;
429 IMM->pram.serials.scc_pram[SCC1].tfcr = 0x18;
431 IMM->scc_regs[SCC1].psmr = 0xB000;
433 /*------------------------------------------------------------*/
434 /* Set RBASE, TBASE -- Rx,Tx Buffer Descriptor Base Addresses */
435 /*------------------------------------------------------------*/
437 IMM->pram.serials.scc_pram[SCC1].rbase = (CYG_WORD16)&RxTxBD->RxBD;
439 IMM->pram.serials.scc_pram[SCC1].tbase = (CYG_WORD16)&RxTxBD->TxBD;
441 /*-----------------------------------------*/
442 /* Set MRBLR -- Max. Receive Buffer Length */
443 /*-----------------------------------------*/
445 IMM->pram.serials.scc_pram[SCC1].mrblr = 1;
447 /*----------------------------------------------------------------------*/
448 /* Program the General SCC Mode Register High (GSMR_H) */
450 /* - Bits 0-14 Reserved. Set to 0. */
452 /* - GDE (Glitch Detect Enable) = 0 = No Glitch Detect. BRG supplies */
453 /* the clock so there's no need to */
454 /* detect glitches. */
456 /* - TCRC (Transparent CRC) = 00 = This field is ignored for Uart mode. */
458 /* - REVD (Reverse Data) = 0 = This field is ignored for Uart mode. */
460 /* - TRX,TTX (Transparent Receiver/Transmitter) = 00 = Normal operation */
462 /* - CDP,CTSP (CD/ & CTS/ sampling) = 00 = Normal Operation (envelope */
465 /* - CDS,CTSS (CD/ & CTSS Sampling) = 00 = */
467 /* CD/ or CTS/ is assumed to be asynchronous with data. It is */
468 /* internally synchronized by the SCC, then data is received (CD/) */
469 /* or sent (CTS/) after several clock delays. */
471 /* - TFL (Transmit FIFO length) = 0 = */
473 /* Normal Operation. The SCC transmit FIFO is 32 bytes. */
475 /* - RFW (Rx FIFO Width) = 1 = */
477 /* Low-latency operation.The receive FIFO is 8 bits wide, reducing */
478 /* the Rx FIFO to a quarter of it's normal size. This allows data to */
479 /* be written to the buffer as soon as a character is received, */
480 /* instead of waiting to receive 32 bits. This configuration must be */
481 /* chosen for character-oriented protocols, such as UART. It can */
482 /* also be used for low-performance, low-latency, transparent */
485 /* - TXSY (Trasnmitter Synchronized) = 0 = */
487 /* No synchronization between receiver and transmitter. */
489 /* - SYNL (Sync Length) = 0 = An external sync (CD/) is used instead of */
490 /* the sync pattern in the DSR. */
492 /* - RTSM (RTS/ Mode) = 0 = Send idles between frames as defined by the */
493 /* protocol and the TEND bit. TRS/ is negated */
494 /* between frames. */
496 /* - RSYN (Receive Synchronization Timing) = 0 = This field is ignored */
499 /*----------------------------------------------------------------------*/
501 IMM->scc_regs[SCC1].gsmr_h = 0x00000060;
504 /*----------------------------------------------------------------------*/
505 /* Program the General SCC Mode Register High (GSMR_L) */
507 /* - Bit 0 Reserved. Set to 0. */
509 /* - EDGE (Clock Edge) = 00 = Ignored in Uart Mode. */
511 /* - TCI (Transmit Clock Invert) = 0 = Normal Operation */
513 /* - TSNC (Transmit Sense) = 00 = Infinite. Carrier sense is always */
516 /* - RINV (DPLL Rx Input Invert) = 0 = Do not invert. */
518 /* - TINV (DPLL Tx Input Invert) = 0 = Do not invert. */
520 /* - TPL (Tx Preamble Length) = 000 = No Preamble. */
522 /* - TPP (Tx Preamble Pattern) = 00 = All zeros. This field is ignored */
525 /* - TEND (Transmitter Frame Ending) = 0 = */
527 /* Default operation. TxD is encoded only when data is sent, */
528 /* including the preamble and opening and closing flags/syncs. When */
529 /* no data is available to send, the signal is driven high. */
531 /* - TDCR (Transmitter DPLL Clock Rate) = 10 = */
533 /* 16x clock mode. This value is normally chosen for Uart mode. */
535 /* - RDCR (Receiver DPLL Clock Rate) = 10 = */
537 /* 16x clock mode. This value is normally chosen for Uart mode. */
539 /* - RENC (Receiver Decoding Method) = 000 = */
541 /* NRZ. Required for Uart Mode (asynchronous or synchronous). */
543 /* - TENC (Transmitter Encoding Method) = 000 = */
545 /* NRZ. Required for Uart Mode (asynchronous or synchronous). */
547 /* - DIAG (Diagnostic Mode) = 01 = Loopback */
549 /* - ENR (Enable Receiver) = 0 = Disabled for now. Will enabled later in*/
552 /* - ENT (Enable Transmitter) = 0 = Disabled for now. Will enable later */
553 /* in this function. */
555 /* - MODE (Channel Protocol Mode) = 0100 = Uart mode. */
557 /*----------------------------------------------------------------------*/
560 IMM->scc_regs[SCC1].gsmr_l = 0x00028004;
562 /*-----------------------------------------*/
563 /* Clear SCCE Register by writing all 1's. */
564 /*-----------------------------------------*/
566 IMM->scc_regs[SCC1].scce = ALL_ONES;
568 /*----------------------------------------------------------------------*/
569 /* Issue Init RX & TX Parameters Command for SCC1. This command to the */
570 /* CP lets it know to reinitialize SCC1 with the new parameter RAM */
571 /* values. When the ENT/ENR bits are set below Hunt Mode will begin */
573 /*----------------------------------------------------------------------*/
575 while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD);
577 IMM->cpm_cpcr = SCC1_PAGE_SUBBLOCK |
578 CPCR_INIT_TX_RX_PARAMS |
579 CPCR_FLG; /* ISSUE COMMAND */
581 while ((IMM->cpm_cpcr & CPCR_FLG) != READY_TO_RX_CMD);
583 /*-------------------------------------------------------------*/
584 /* Set the ENT/ENR bits in the GSMR -- Enable Transmit/Receive */
585 /*-------------------------------------------------------------*/
587 IMM->scc_regs[SCC1].gsmr_l |= GSMR_L1_ENT | GSMR_L1_ENR;
588 #if defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT) \
589 || defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT)
592 // Fill out the control Character Table. Make the first entry
593 // an end of table line.
594 // cc[0] = 0x4003 ==> reject if char = 0x3, write to RCCR
595 IMM->pram.serials.scc_pram[SCC1].SpecificProtocol.u.cc[0] = 0x4003;
598 for (i = 0; i < 8; i++){
599 IMM->pram.serials.scc_pram[SCC1].SpecificProtocol.u.cc[i] = 0x8000;
603 IMM->pram.serials.scc_pram[SCC1].SpecificProtocol.u.rccm = 0xc000;
605 /*-----------------------------------------*/
606 /* Write to the SCCM mask register to enable an CCR interrupt*/
607 /*-----------------------------------------*/
608 IMM->scc_regs[SCC1].sccm = 0x1;
610 /* Unmask the CPM SCC1 interrupt */
611 HAL_READ_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
612 regval |= 0x00800000;
613 HAL_WRITE_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
616 } /* end SCC1HInit() */
619 /*--------------------------------------------------------------------------
621 * FUNCTION NAME: ConfigSCC1Clock
625 * This function will configure SCC1 to utilize Baud Rate Generator #1. It
626 * will program the the baud rate generator and configure the SMXSCR
627 * register in the CPM Mux block to route the clock to SCC1. SCC2, SCC3, and
628 * SCC4 are also programmed to assume Baud Rate Generator #1, #2, and #3
629 * respectively to be routed to them. There was no special reason for doing
630 * this; The bit values needed to be programmed to something.
633 * EXTERNAL EFFECTS: BRGC1 and CMXSCR
639 *--------------------------------------------------------------------------*/
641 void ConfigSCC1Clock()
644 /* FIXME --- This picture is not accurate */
645 /*----------------------------------------------------------------------*/
646 /* Initialize Baud Rate Generator #1 to generate a 9600 clock. The */
647 /* source of the clock starts with the input clock that is generated */
648 /* external to the MPC8260 by a clock generator. This clock is then */
649 /* fed to the CPM PLL where it is multiplied up and the output freq- */
650 /* uency is determined by the MODCLK_HI bits in the Hard Reset Config- */
651 /* uration Word and MODCK pins on the MPC8260. This output is fed to a */
652 /* general purpose Baud Rate Generator Divider that services all 8 baud */
653 /* rate generators. From the output of this divider the the clock goes */
654 /* to the baud rate generator circuitry where, in this case, BRGCLK is */
655 /* selected to be BRGO1 (the output clock). This frequency is deter- */
656 /* mined by a Divide by 1 or 16 divider and then a 12 bit Prescaler */
657 /* divider. the clock then goes to the CPM Mux where BRG1 is selected */
658 /* to be TCLK and RCLK to SCC1. This is accomplished by programming the */
659 /* CMXSCR register. TCLK and RCLK are then routed to the SCC1 DPLL */
660 /* circuitry at 9600 baud where the DPLL will be programmed to multiply */
661 /* the frequency by X16 for UART over-sampling. Here a diagram and the */
664 /* ---------- --------- --------------------- */
665 /* |External| |MPC8260| 132 Mhz |General Purpose | 16.5 Mhz */
666 /* |Clk Gen |----|CPM PLL|---------|Baud Rate Generator|--------->| */
667 /* |66 Mhz | |Block | |Divider [/8] (SCCR)| | */
668 /* ---------- --------- --------------------- | */
670 /* |<-------------------------------------------------------------| */
672 /* | ------------------------ ------------------- */
673 /* |-->|Divide by 1 or 16 in | 1.03125 Mhz |12 Bit Prescaler | BRG01 */
674 /* |Baud Rate Generator |------------->|in Baud Rate Gen. |--| */
675 /* |Block [/16 selected] | |Block [107(0x6B) | | */
676 /* |(BRGC1 Programmed) | |(BRGC1 Programmed)| | */
677 /* ------------------------ -------------------- | */
679 /* |<--------------------------------------------------------------| */
681 /* | -------------- TCLK ---------- */
682 /* | 9.638 Khz | CPM Mux |------>| SCC1 |----> TCLK*16 }*16 for */
683 /* |----------->| (CMXSCR) | RCLK | DPLL | }over- */
684 /* |(Programmed)|------>| *16 |----> RCLK*16 }sampling */
685 /* -------------- |(GSMR_L)| */
688 /* SCCR was programmed in init8260.s. BRGC1,CMXSCR will be programmed */
689 /* in this function. GSMR_L will be programmed in InitSCC1Uart(). */
691 /*----------------------------------------------------------------------*/
693 /*----------------------------------------------------------------------*/
694 /* Program Baud Rate Generator Configuration #1 Register (BRGC1). */
696 /* - Bits 0-13 are reserved. Set to 0. */
698 /* - RST (Reset BRG) = 0 = Enable the BRG */
700 /* - EN (Enable BRG Count) = 1 = Enable clocks to the BRG */
702 /* - EXTC (External Clock Source) = 00 = */
704 /* The BRG input clock comes from the BRGCLK */
706 /* - ATB (AutoBaud) = 0 = Normal operation of the BRG. */
708 /* - CD (Clock Divider) = 0x6C = 108 decimal = */
710 /* The input frequency is 1.03125 Mhz Dividing it by 107 will give */
711 /* 9.638 Khz. However 1 must be added to the count value because it */
712 /* counts down to 0. So the programmed value is 108. */
714 /* PF edit - changed CD = 0x1A = 26 ==> baud rate of 4 * 9600 = 38400 */
715 /* - DIV16 (Divide-by-16) = 0 = divide by 1. */
716 /*----------------------------------------------------------------------*/
718 // IMM->brgs_brgc1 = 0x000100D6;
719 //IMM->brgs_brgc1 = 0x00010034; /* Attempt to get 38400 baud */
720 // IMM->brgs_brgc1 = 0x00010022; /* Attempt to get 57600 baud */
721 //IMM->brgs_brgc1 = 0x00010010; /* Attempt to get 115200 baud */
722 IMM->brgs_brgc1 = 0x00010000 | (UART_BIT_RATE(UART_BAUD_RATE) << 1);
724 /*----------------------------------------------------------------------*/
725 /* Program the CMX SCC Route Register (CMXSCR). */
727 /* - GR1 (Grant support of SCC1) = 0 = */
729 /* SCC1 transmitter does not support the grant mechanism. The grant */
730 /* is always asserted internally. */
732 /* - SC1 (SCC1 connection) = 0 */
734 /* SCC1 is not connected to the TSA of the SIs but is connected */
735 /* directly to the NMSIx pins. */
737 /* - RS1CS (Receive SCC1 or clock source) = 000 = */
739 /* SCC1 receive clock is BRG1. */
741 /* - TS1CS (Transmit SCC1 clock source) = 000 = */
743 /* SCC1 transmit clock is BRG1. */
745 /* - GR2 (Grant support of SCC2) = 0 = */
747 /* SCC1 transmitter does not support the grant mechanism. The grant */
748 /* is always asserted internally. */
750 /* - SC2 (SCC2 connection) = 0 */
752 /* SCC2 is not connected to the TSA of the SIs but is connected */
753 /* directly to the NMSIx pins. */
755 /* - RS2CS (Receive SCC2 or clock source) = 001 = */
757 /* SCC1 receive clock is BRG2. */
759 /* - TS2CS (Transmit SCC2 clock source) = 001 = */
761 /* SCC2 transmit clock is BRG2. */
763 /* - GR3 (Grant support of SCC3) = 0 = */
765 /* SCC3 transmitter does not support the grant mechanism. The grant */
766 /* is always asserted internally. */
768 /* - SC3 (SCC3 connection) = 0 */
770 /* SCC3 is not connected to the TSA of the SIs but is connected */
771 /* directly to the NMSIx pins. */
773 /* - RS3CS (Receive SCC3 or clock source) = 010 = */
775 /* SCC3 receive clock is BRG3. */
777 /* - TS3CS (Transmit SCC3 clock source) = 010 = */
779 /* SCC3 transmit clock is BRG3. */
781 /* - GR4 (Grant support of SCC4) = 0 = */
783 /* SCC4 transmitter does not support the grant mechanism. The grant */
784 /* is always asserted internally. */
786 /* - SC4 (SCC4 connection) = 0 */
788 /* SCC4 is not connected to the TSA of the SIs but is connected */
789 /* directly to the NMSIx pins. */
791 /* - RS4CS (Receive SCC4 or clock source) = 011 = */
793 /* SCC4 receive clock is BRG4. */
795 /* - TS4CS (Transmit SCC4 clock source) = 011 = */
797 /* SCC4 transmit clock is BRG4. */
799 /*----------------------------------------------------------------------*/
801 IMM->cpm_mux_cmxscr = 0x0009121B;
803 } /* end of ConfigSCC1Clock() */
807 /*--------------------------------------------------------------------------
809 * FUNCTION NAME: InitParallelPorts
813 * This function programs the parallel port configuration registers to
814 * utilize the pins required for proper SCC1 operation. The pins programmed
815 * here are TxD and RxD for SCC1 and CD1 for SCC1.
817 * EXTERNAL EFFECTS: Parallel Port C and D Configuration Registers
823 *--------------------------------------------------------------------------*/
825 void InitParallelPorts()
828 /*--------------------------------------------*/
829 /* Program the Port Special Options Registers */
830 /*--------------------------------------------*/
832 IMM->io_regs[PORT_C].psor &= 0xFFFDFFFF; /* CD/ pin 14 */
833 IMM->io_regs[PORT_D].psor &= 0xFFFFFFFC; /* clear first */
834 IMM->io_regs[PORT_D].psor |= 0x00000002; /* TXD pin 30| RXD pin 31 */
836 /*-------------------------------------------*/
837 /* Program the Port Pin Assignment Registers */
838 /*-------------------------------------------*/
840 IMM->io_regs[PORT_C].ppar |= 0x00020000; /* CD/ pin 14 */
841 IMM->io_regs[PORT_D].ppar |= 0x00000003; /* TXD pin 30| RXD pin 31 */
843 /*-------------------------------------------*/
844 /* Program the Port Data Direction Registers */
845 /*-------------------------------------------*/
847 IMM->io_regs[PORT_C].pdir &= 0xFFFDFFFF; /* CD/ pin 14 */
848 IMM->io_regs[PORT_D].pdir &= 0xFFFFFFFC; /* clear first */
849 IMM->io_regs[PORT_D].pdir |= 0x00000002; /* TXD pin 30| RXD pin 31 */
851 /*---------------------------------------*/
852 /* Program the Port Open-Drain Registers */
853 /*---------------------------------------*/
855 IMM->io_regs[PORT_C].podr &= 0xFFFDFFFF; /* CD/ pin 14 */
856 IMM->io_regs[PORT_D].podr &= 0xFFFFFFFC; /* TXD pin 30| RXD pin 31 */
860 /*---------------------------------------------------------------------------
862 * FUNCTION NAME: BDRxError
866 * Return TRUE if Buffer Descriptor Status bd_cstatus indicates Receive
867 * Error; Return FALSE otherwise note Receive Errors are as follows:
869 * 0x80: DPLL Error (DE)
870 * 0x20: Length Violation (LG)
871 * 0x10: Non-Octet Aligned (NO)
872 * 0x8: Rx Abort Sequence (AB)
873 * 0x4: Rx CRC Error (CR)
875 * 0x1: Carrier Detect Lost (CD)
877 * EXTERNAL EFFECTS: None
883 * RETURNS: TRUE if there was an error and FALSE if there wasn't
885 *---------------------------------------------------------------------------*/
887 CYG_WORD16 BDRxError(CYG_WORD16 bd_cstatus)
891 if (bd_cstatus & BD_RX_ERROR)
899 } /* end BDRxError */
901 /*---------------------------------------------------------------------------
903 * FUNCTION NAME: SCC1Poll
905 * DESCRIPTION: Poll SCC1 RxBD and check to see if a character was received
907 * EXTERNAL EFFECT: NONE
911 * RETURNS: A one if there is a character available in the receive buffer,
914 *--------------------------------------------------------------------------*/
916 cyg_uint8 SCC1Poll(void)
920 if(RxTxBD->RxBD.bd_cstatus & 0x8000)
923 return 0; /* character NOT available */
929 return 1; /* character IS available */
934 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
936 cyg_hal_plf_serial_putc(cyg_uint8 ch)
939 cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch)
942 /*-----------------------------------*/
943 /* Loop until transmission completed */
944 /*-----------------------------------*/
946 volatile CYG_WORD16 stat = 1;
948 stat = RxTxBD->TxBD.bd_cstatus & 0x8000;
951 while (RxTxBD->TxBD.bd_cstatus & 0x8000);
957 *(RxTxBD->TxBD.bd_addr) = ch;
958 RxTxBD->TxBD.bd_length = 1;
964 RxTxBD->TxBD.bd_cstatus |= 0x8000;
970 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
974 if ( (retval = SCC1Poll() ) ){ /* Check BD status for Rx characters */
975 *ch = cyg_hal_plf_serial_getc(__ch_data);
981 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
983 cyg_hal_plf_serial_getc(void)
986 cyg_hal_plf_serial_getc(void* __ch_data)
990 /*--------------------*/
991 /* Loop if RxBD empty */
992 /*--------------------*/
994 volatile short stat = 1;
996 stat = RxTxBD->RxBD.bd_cstatus & 0x8000;
999 while (RxTxBD->RxBD.bd_cstatus & 0x8000);
1005 ch = *(RxTxBD->RxBD.bd_addr);
1007 /*----------------------*/
1008 /* Set Buffer Empty bit */
1009 /*----------------------*/
1011 RxTxBD->RxBD.bd_cstatus |= 0x8000;
1019 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf,
1022 //CYGARC_HAL_SAVE_GP();
1025 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
1026 cyg_hal_plf_serial_putc(*__buf++);
1028 cyg_hal_plf_serial_putc(__ch_data, *__buf++);
1031 //CYGARC_HAL_RESTORE_GP();
1035 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
1037 CYGARC_HAL_SAVE_GP();
1040 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
1041 *__buf++ = cyg_hal_plf_serial_getc();
1043 *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
1045 CYGARC_HAL_RESTORE_GP();
1048 cyg_int32 msec_timeout = 1000;
1051 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
1053 int delay_count = msec_timeout * 10; // delay in .1 ms steps
1055 CYGARC_HAL_SAVE_GP();
1058 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
1059 if (res || 0 == delay_count--)
1062 CYGACC_CALL_IF_DELAY_US(100);
1065 CYGARC_HAL_RESTORE_GP();
1070 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
1072 static int irq_state = 0;
1075 CYGARC_HAL_SAVE_GP();
1078 case __COMMCTL_IRQ_ENABLE:
1079 //HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_CPM_SMC1);
1080 // For now, don't bother calling a macro, just do it here
1081 // Bit 8 in the SIMR_L corresponds to SCC1
1082 HAL_READ_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
1083 regval |= 0x00800000;
1085 HAL_WRITE_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
1086 asm volatile ("ori %0, 0, 0x1234;" \
1088 : "I" (22)); /* %0 ==> r2 */
1090 //RxTxBD->RxBD.bd_cstatus = 0xB000;
1094 case __COMMCTL_IRQ_DISABLE:
1097 //HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_CPM_SMC1);
1098 HAL_READ_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
1099 regval &= 0xFF7FFFFF;
1101 HAL_WRITE_UINT32( ((char *) IMM) + 0x10000 + CYGARC_REG_IMM_SIMR_L, regval);
1103 //RxTxBD->RxBD.bd_cstatus = 0xA000;
1105 case __COMMCTL_DBG_ISR_VECTOR:
1106 //ret = CYGNUM_HAL_INTERRUPT_CPM_SMC1;
1107 ret = CYGNUM_HAL_INTERRUPT_SCC1;
1111 case __COMMCTL_SET_TIMEOUT:
1115 va_start(ap, __func);
1118 msec_timeout = va_arg(ap, cyg_uint32);
1125 CYGARC_HAL_RESTORE_GP();