1 //==========================================================================
5 // PowerPC QUICC basic Serial IO using port(s) SMC1/SMC2/SCC1/SCC2/SCC3
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, 2003 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: Provide basic Serial IO for MPC8xx boards (like Motorola MBX)
48 // Description: Serial IO for MPC8xx boards which connect their debug channel
49 // to SMCx or SCCx; or any QUICC user who wants to use SMCx/SCCx
53 //####DESCRIPTIONEND####
55 //==========================================================================
57 #include <pkgconf/hal.h>
58 #include <pkgconf/hal_powerpc_quicc.h>
59 #include <cyg/infra/cyg_type.h>
60 #include <cyg/hal/hal_cache.h>
62 #include <cyg/hal/hal_arch.h>
64 // eCos headers decribing PowerQUICC:
65 #include <cyg/hal/quicc/ppc8xx.h>
67 #include <cyg/hal/quicc/quicc_smc1.h>
69 #include <cyg/hal/hal_stub.h> // target_register_t
70 #include <cyg/hal/hal_intr.h> // HAL_INTERRUPT_UNMASK(...)
71 #include <cyg/hal/hal_if.h> // Calling interface definitions
72 #include <cyg/hal/hal_misc.h> // Helper functions
73 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED
74 #include <string.h> // memset
76 #define UART_BIT_RATE(n) ((((int)(CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000)/16)/n)-1)
77 #define UART_BAUD_RATE CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
79 // Note: buffers will be placed just after descriptors
80 // Sufficient space should be provided between descrptors
81 // for the buffers (single characters)
84 int Txnum; // Number of Tx buffers
85 int Rxnum; // Number of Rx buffers
86 int intnum; // Interrupt bit
87 int timeout; // Timeout in msec
88 int pram; // [Pointer] to PRAM data
89 int regs; // [Pointer] to control registers
90 volatile struct cp_bufdesc *next_rxbd;
91 int irq; // Interrupt state
92 int init; // Has port been initialized?
93 volatile unsigned long *brg; // Baud rate generator
96 static struct port_info ports[] = {
97 #if CYGNUM_HAL_QUICC_SMC1 > 0
98 { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC1, 1000,
99 (int)&((EPPC *)0)->pram[2].scc.pothers.smc_modem.psmc.u,
100 (int)&((EPPC *)0)->smc_regs[0]
103 #if CYGNUM_HAL_QUICC_SMC2 > 0
104 { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC2_PIP, 1000,
105 (int)&((EPPC *)0)->pram[3].scc.pothers.smc_modem.psmc.u,
106 (int)&((EPPC *)0)->smc_regs[1]
109 #if CYGNUM_HAL_QUICC_SCC1 > 0
110 { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC1, 1000,
111 (int)&((EPPC *)0)->pram[0].scc.pscc.u,
112 (int)&((EPPC *)0)->scc_regs[0]
115 #if CYGNUM_HAL_QUICC_SCC2 > 0
116 { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC2, 1000,
117 (int)&((EPPC *)0)->pram[1].scc.pscc.u,
118 (int)&((EPPC *)0)->scc_regs[1]
121 #if CYGNUM_HAL_QUICC_SCC3 > 0
122 { 1, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC3, 1000,
123 (int)&((EPPC *)0)->pram[2].scc.pscc.u,
124 (int)&((EPPC *)0)->scc_regs[2]
130 * Initialize SMCX as a uart.
132 * Comments below reference Motorola's "MPC860 User Manual".
133 * The basic initialization steps are from Section 16.15.8
137 cyg_hal_smcx_init_channel(struct port_info *info, int port)
139 EPPC *eppc = eppc_base();
141 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
142 volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
143 struct cp_bufdesc *txbd, *rxbd;
145 if (info->init) return;
149 #if CYGNUM_HAL_QUICC_SMC1 > 0
152 * Set up the PortB pins for UART operation.
153 * Set PAR and DIR to allow SMCTXD1 and SMRXD1
156 eppc->pip_pbpar |= 0xc0;
157 eppc->pip_pbdir &= ~0xc0;
161 #if CYGNUM_HAL_QUICC_SMC2 > 0
164 * Set up the PortA pins for UART operation.
165 * Set PAR and DIR to allow SMCTXD2 and SMRXD2
168 eppc->pio_papar |= 0xc0;
169 eppc->pio_padir &= ~0xc0;
170 eppc->pio_paodr &= ~0xc0;
176 // Set up baud rate generator. These are allocated from a
177 // pool, based on the port number and type. The allocator
178 // will arrange to have the selected baud rate clock steered
180 info->brg = _mpc8xx_allocate_brg(port);
181 *(info->brg) = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
184 * Set pointers to buffer descriptors.
185 * (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13)
187 uart_pram->rbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum);
188 uart_pram->tbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum);
191 * SDMA & LCD bus request level 5
192 * (Section 16.10.2.1)
197 * Set Rx and Tx function code
198 * (Section 16.15.4.2)
200 uart_pram->rfcr = 0x18;
201 uart_pram->tfcr = 0x18;
203 /* max receive buffer length */
204 uart_pram->mrblr = 1;
206 /* disable max_idle feature */
207 uart_pram->max_idl = 0;
209 /* no last brk char received */
210 uart_pram->brkln = 0;
212 /* no break condition occurred */
213 uart_pram->brkec = 0;
215 /* 1 break char sent on top XMIT */
216 uart_pram->brkcr = 1;
218 /* setup RX buffer descriptors */
219 rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
220 info->next_rxbd = rxbd;
221 for (i = 0; i < info->Rxnum; i++) {
223 rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
224 rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
228 rxbd->ctrl |= QUICC_BD_CTL_Wrap;
230 /* setup TX buffer descriptor */
231 txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
233 txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc))));
237 * Clear any previous events. Mask interrupts.
238 * (Section 16.15.7.14 and 16.15.7.15)
240 regs->smc_smce = 0xff;
241 regs->smc_smcm = 1; // RX interrupts only, for ctrl-c
244 * Set 8,n,1 characters, then also enable rx and tx.
245 * (Section 16.15.7.11)
247 regs->smc_smcmr = 0x4820;
248 regs->smc_smcmr = 0x4823;
251 * Init Rx & Tx params for SMCx
253 eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY;
255 info->irq = 0; // Interrupts not enabled
259 //#define UART_BUFSIZE 32
261 //static bsp_queue_t uart_queue;
262 //static char uart_buffer[UART_BUFSIZE];
264 #define QUICC_SMCE_TX 0x02 // Tx interrupt
265 #define QUICC_SMCE_RX 0x01 // Rx interrupt
266 #define QUICC_SMCMR_TEN (1<<1) // Enable transmitter
267 #define QUICC_SMCMR_REN (1<<0) // Enable receiver
269 #ifdef CYGDBG_DIAG_BUF
270 extern int enable_diag_uart;
271 #endif // CYGDBG_DIAG_BUF
274 cyg_hal_sxx_putc(void* __ch_data, cyg_uint8 ch)
276 volatile struct cp_bufdesc *bd, *first;
277 EPPC *eppc = eppc_base();
278 struct port_info *info = (struct port_info *)__ch_data;
279 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
280 volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
283 CYGARC_HAL_SAVE_GP();
285 /* tx buffer descriptor */
286 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr);
288 // Scan for a free buffer
290 while (bd->ctrl & QUICC_BD_CTL_Ready) {
291 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
292 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
296 if (bd == first) break;
299 while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait for buffer free
300 if (bd->ctrl & QUICC_BD_CTL_Int) {
301 // This buffer has just completed interrupt output. Reset bits
302 bd->ctrl &= ~QUICC_BD_CTL_Int;
308 bd->ctrl |= QUICC_BD_CTL_Ready;
309 // Flush cache if necessary - buffer may be in cacheable memory
310 HAL_DCACHE_IS_ENABLED(cache_state);
312 HAL_DCACHE_FLUSH(bd->buffer, 1);
315 #ifdef CYGDBG_DIAG_BUF
316 enable_diag_uart = 0;
317 #endif // CYGDBG_DIAG_BUF
319 while (bd->ctrl & QUICC_BD_CTL_Ready) {
320 // Wait until buffer free
321 if (++timeout == 0x7FFFF) {
322 // A really long time!
323 #ifdef CYGDBG_DIAG_BUF
324 diag_printf("bd fail? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate);
325 #endif // CYGDBG_DIAG_BUF
326 regs->smc_smcmr &= ~QUICC_SMCMR_TEN; // Disable transmitter
327 bd->ctrl &= ~QUICC_BD_CTL_Ready;
328 regs->smc_smcmr |= QUICC_SMCMR_TEN; // Enable transmitter
329 bd->ctrl |= QUICC_BD_CTL_Ready;
331 #ifdef CYGDBG_DIAG_BUF
332 diag_printf("bd retry? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate);
333 first = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
335 diag_printf("bd: %x, ctrl: %x, length: %x\n", first, first->ctrl, first->length);
336 if (first->ctrl & QUICC_BD_CTL_Wrap) break;
339 #endif // CYGDBG_DIAG_BUF
342 while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait until buffer free
344 #ifdef CYGDBG_DIAG_BUF
345 enable_diag_uart = 1;
346 #endif // CYGDBG_DIAG_BUF
348 CYGARC_HAL_RESTORE_GP();
353 * Get a character from a port, non-blocking
354 * This function can be called on either an SMC or SCC port
357 cyg_hal_sxx_getc_nonblock(void* __ch_data, cyg_uint8* ch)
359 volatile struct cp_bufdesc *bd;
360 EPPC *eppc = eppc_base();
361 struct port_info *info = (struct port_info *)__ch_data;
362 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
365 /* rx buffer descriptor */
366 bd = info->next_rxbd;
368 if (bd->ctrl & QUICC_BD_CTL_Ready)
374 bd->buffer[0] = '\0';
375 bd->ctrl |= QUICC_BD_CTL_Ready;
376 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
377 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
381 info->next_rxbd = bd;
383 // Note: the MBX860 does not seem to snoop/invalidate the data cache properly!
384 HAL_DCACHE_IS_ENABLED(cache_state);
386 HAL_DCACHE_INVALIDATE(bd->buffer, uart_pram->mrblr); // Make sure no stale data
393 * Get a character from a port, blocking
394 * This function can be called on either an SMC or SCC port
397 cyg_hal_sxx_getc(void* __ch_data)
400 CYGARC_HAL_SAVE_GP();
402 while(!cyg_hal_sxx_getc_nonblock(__ch_data, &ch));
404 CYGARC_HAL_RESTORE_GP();
410 cyg_hal_sxx_write(void* __ch_data, const cyg_uint8* __buf,
413 CYGARC_HAL_SAVE_GP();
416 cyg_hal_sxx_putc(__ch_data, *__buf++);
418 CYGARC_HAL_RESTORE_GP();
422 * Read a sequence of characters from a port
423 * This function can be called on either an SMC or SCC port
426 cyg_hal_sxx_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
428 CYGARC_HAL_SAVE_GP();
431 *__buf++ = cyg_hal_sxx_getc(__ch_data);
433 CYGARC_HAL_RESTORE_GP();
437 * Read a character from a port, with a timeout
438 * This function can be called on either an SMC or SCC port
441 cyg_hal_sxx_getc_timeout(void* __ch_data, cyg_uint8* ch)
443 struct port_info *info = (struct port_info *)__ch_data;
444 int delay_count = info->timeout * 10; // delay in .1 ms steps
446 CYGARC_HAL_SAVE_GP();
449 res = cyg_hal_sxx_getc_nonblock(__ch_data, ch);
450 if (res || 0 == delay_count--)
453 CYGACC_CALL_IF_DELAY_US(100);
456 CYGARC_HAL_RESTORE_GP();
461 * Control/query the state of a port
462 * This function can be called on either an SMC or SCC port
465 cyg_hal_sxx_control(void *__ch_data, __comm_control_cmd_t __func, ...)
467 struct port_info *info = (struct port_info *)__ch_data;
469 CYGARC_HAL_SAVE_GP();
472 case __COMMCTL_IRQ_ENABLE:
473 HAL_INTERRUPT_UNMASK(info->intnum);
476 case __COMMCTL_IRQ_DISABLE:
479 HAL_INTERRUPT_MASK(info->intnum);
481 case __COMMCTL_DBG_ISR_VECTOR:
484 case __COMMCTL_SET_TIMEOUT:
488 va_start(ap, __func);
491 info->timeout = va_arg(ap, cyg_uint32);
498 CYGARC_HAL_RESTORE_GP();
503 * Low-level interrupt (ISR) handler
504 * This function can be called on only an SMC port
507 cyg_hal_smcx_isr(void *__ch_data, int* __ctrlc,
508 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
510 EPPC *eppc = eppc_base();
511 volatile struct cp_bufdesc *bd;
512 struct port_info *info = (struct port_info *)__ch_data;
513 volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
514 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
517 CYGARC_HAL_SAVE_GP();
520 if (regs->smc_smce & QUICC_SMCE_RX) {
522 regs->smc_smce = QUICC_SMCE_RX;
524 /* rx buffer descriptors */
525 bd = info->next_rxbd;
527 if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) {
529 // then there be a character waiting
532 bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
533 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
534 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
538 info->next_rxbd = bd;
540 if( cyg_hal_is_break( &ch , 1 ) )
544 // Interrupt handled. Acknowledge it.
545 HAL_INTERRUPT_ACKNOWLEDGE(info->intnum);
546 res = CYG_ISR_HANDLED;
549 CYGARC_HAL_RESTORE_GP();
553 #if (CYGNUM_HAL_QUICC_SCC1+CYGNUM_HAL_QUICC_SCC2+CYGNUM_HAL_QUICC_SCC3) > 0
555 * Initialize an SCC as a uart.
557 * Comments below reference Motorola's "MPC860 User Manual".
558 * The basic initialization steps are from Section 16.15.8
562 cyg_hal_sccx_init_channel(struct port_info *info, int port)
564 EPPC *eppc = eppc_base();
566 volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram);
567 volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs);
568 struct cp_bufdesc *txbd, *rxbd;
570 if (info->init) return;
574 * Set up the Port pins for UART operation.
577 #if CYGNUM_HAL_QUICC_SCC1 > 0
579 eppc->pio_papar |= 0x03;
580 eppc->pio_padir &= ~0x03;
581 eppc->pio_paodr &= ~0x03;
583 /* CTS on PortC.11 */
584 eppc->pio_pcdir &= 0x800;
585 eppc->pio_pcpar &= 0x800;
586 eppc->pio_pcso |= 0x800;
588 /* RTS on PortB.19 */
589 eppc->pip_pbpar |= 0x1000;
590 eppc->pip_pbdir |= 0x1000;
594 #if CYGNUM_HAL_QUICC_SCC2 > 0
597 eppc->pio_papar |= 0x0C;
598 eppc->pio_padir &= ~0x0C;
599 eppc->pio_paodr &= ~0x0C;
601 /* CTS on PortC.11 */
602 eppc->pio_pcdir &= 0xC00;
603 eppc->pio_pcpar &= 0xC00;
604 eppc->pio_pcso |= 0xC00;
606 /* RTS on PortB.19 */
607 eppc->pip_pbpar |= 0x2000;
608 eppc->pip_pbdir |= 0x2000;
612 #if CYGNUM_HAL_QUICC_SCC3 > 0
614 #if defined(CYGHWR_HAL_POWERPC_MPC8XX_850)
616 // CAUTION! Enabling these bits made the port get stuck :-(
617 /* CTS/RTS/CD on PortC.4/5/13 */
618 eppc->pio_pcdir &= 0x0C04;
619 eppc->pio_pcpar &= 0x0C00;
620 // eppc->pio_pcpar |= 0x0004;
621 eppc->pio_pcso |= 0x0C00;
624 /* RxD/TxD on PortB.24/25 */
625 eppc->pip_pbpar |= 0x00C0;
626 eppc->pip_pbdir |= 0x00C0;
627 eppc->pip_pbodr &= ~0x00C0;
629 #elif defined(CYGHWR_HAL_POWERPC_MPC8XX_852T)
630 eppc->pio_papar |= 0x30;
631 eppc->pio_padir &= ~0x30;
632 eppc->pio_paodr &= ~0x30;
634 #error "Cannot route SCC3 I/O"
640 // Set up baud rate generator. These are allocated from a
641 // pool, based on the port number and type. The allocator
642 // will arrange to have the selected baud rate clock steered
644 info->brg = _mpc8xx_allocate_brg(port);
645 *(info->brg) = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
648 * Set pointers to buffer descriptors.
650 uart_pram->rbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Rxnum + info->Rxnum);
651 uart_pram->tbase = _mpc8xx_allocBd(sizeof(struct cp_bufdesc)*info->Txnum + info->Txnum);
654 * SDMA & LCD bus request level 5
659 * Set Rx and Tx function code
661 uart_pram->rfcr = 0x18;
662 uart_pram->tfcr = 0x18;
664 /* max receive buffer length */
665 uart_pram->mrblr = 1;
667 /* disable max_idle feature */
668 uart_pram->max_idl = 0;
670 /* no last brk char received */
671 uart_pram->brkln = 0;
673 /* no break condition occurred */
674 uart_pram->brkec = 0;
676 /* 1 break char sent on top XMIT */
677 uart_pram->brkcr = 1;
680 uart_pram->rccm = 0xC0FF;
682 /* control characters */
683 for (i = 0; i < 8; i++) {
684 uart_pram->cc[i] = 0x8000; // Mark unused
687 /* setup RX buffer descriptors */
688 rxbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
689 info->next_rxbd = rxbd;
690 for (i = 0; i < info->Rxnum; i++) {
692 rxbd->buffer = ((char *)eppc + (uart_pram->rbase+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
693 rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
697 rxbd->ctrl |= QUICC_BD_CTL_Wrap;
699 /* setup TX buffer descriptor */
700 txbd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
702 txbd->buffer = ((char *)eppc + (uart_pram->tbase+(info->Txnum*sizeof(struct cp_bufdesc))));
706 * Clear any previous events. Mask interrupts.
707 * (Section 16.15.7.14 and 16.15.7.15)
709 regs->scc_scce = 0xffff;
710 regs->scc_sccm = 1; // RX interrupts only, for ctrl-c
713 * Set 8,n,1 characters
715 regs->scc_psmr = (3<<12);
716 regs->scc_gsmr_h = 0x20; // 8bit FIFO
717 regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART
720 * Init Rx & Tx params for SCCX
722 eppc->cp_cr = QUICC_CPM_CR_INIT_TXRX | port | QUICC_CPM_CR_BUSY;
724 regs->scc_gsmr_l |= 0x30; // Enable Rx, Tx
730 cyg_hal_sccx_isr(void *__ch_data, int* __ctrlc,
731 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
733 EPPC *eppc = eppc_base();
734 volatile struct cp_bufdesc *bd;
735 struct port_info *info = (struct port_info *)__ch_data;
736 volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs);
737 volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram);
740 CYGARC_HAL_SAVE_GP();
743 if (regs->scc_scce & QUICC_SMCE_RX) {
745 regs->scc_scce = QUICC_SMCE_RX;
747 /* rx buffer descriptors */
748 bd = info->next_rxbd;
750 if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) {
752 // then there be a character waiting
755 bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
756 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
757 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->rbase);
761 info->next_rxbd = bd;
763 if( cyg_hal_is_break( &ch , 1 ) )
767 // Interrupt handled. Acknowledge it.
768 HAL_INTERRUPT_ACKNOWLEDGE(info->intnum);
769 res = CYG_ISR_HANDLED;
772 CYGARC_HAL_RESTORE_GP();
775 #endif // CYGNUM_HAL_QUICC_SCCX
778 * Early initialization of comm channels. Must not rely
779 * on interrupts, yet. Interrupt operation can be enabled
780 * in _bsp_board_init().
783 cyg_hal_plf_serial_init(void)
785 hal_virtual_comm_table_t* comm;
786 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
788 static int init = 0; // It's wrong to do this more than once
793 // Setup procs in the vector table
795 #if CYGNUM_HAL_QUICC_SMC1 > 0
797 cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC1);
798 CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
799 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
800 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
801 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write);
802 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
803 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc);
804 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
805 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
806 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr);
807 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
811 #if CYGNUM_HAL_QUICC_SMC2 > 0
813 cyg_hal_smcx_init_channel(&ports[chan], QUICC_CPM_SMC2);
814 CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
815 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
816 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
817 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write);
818 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
819 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc);
820 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
821 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
822 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smcx_isr);
823 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
827 #if CYGNUM_HAL_QUICC_SCC1 > 0
829 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC1);
830 CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
831 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
832 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
833 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write);
834 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
835 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc);
836 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
837 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
838 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
839 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
843 #if CYGNUM_HAL_QUICC_SCC2 > 0
845 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC2);
846 CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
847 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
848 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
849 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write);
850 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
851 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc);
852 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
853 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
854 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
855 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
859 #if CYGNUM_HAL_QUICC_SCC3 > 0
861 cyg_hal_sccx_init_channel(&ports[chan], QUICC_CPM_SCC3);
862 CYGACC_CALL_IF_SET_CONSOLE_COMM(chan);// Should be configurable!
863 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
864 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[chan]);
865 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_sxx_write);
866 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
867 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_sxx_putc);
868 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
869 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
870 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_sccx_isr);
871 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
875 // Restore original console
876 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);