comparison packages/hal/powerpc/quicc/current/src/quicc_smc1.c @ 237:2b28abd155c7

Add support for SCC1 as a serial console.
author gthomas
date Thu, 11 Jul 2002 16:39:24 +0000
parents 278800005641
children b558d7de4fda
comparison
equal deleted inserted replaced
236:e7500517b4b4 237:2b28abd155c7
1 //========================================================================== 1 //==========================================================================
2 // 2 //
3 // quicc_smc1.c 3 // quicc_smc1.c
4 // 4 //
5 // PowerPC QUICC basic Serial IO using port SMC1 5 // PowerPC QUICC basic Serial IO using port SMC1/SCC1
6 // 6 //
7 //========================================================================== 7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN#### 8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // ------------------------------------------- 9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System. 10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc. 11 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12 // Copyright (C) 2002 Gary Thomas
12 // 13 //
13 // eCos is free software; you can redistribute it and/or modify it under 14 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free 15 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version. 16 // Software Foundation; either version 2 or (at your option) any later version.
16 // 17 //
41 //#####DESCRIPTIONBEGIN#### 42 //#####DESCRIPTIONBEGIN####
42 // 43 //
43 // Author(s): Red Hat 44 // Author(s): Red Hat
44 // Contributors: hmt, gthomas 45 // Contributors: hmt, gthomas
45 // Date: 1999-06-08 46 // Date: 1999-06-08
46 // Purpose: Provide basic Serial IO for MBX board 47 // Purpose: Provide basic Serial IO for MPC8xx boards (like Motorola MBX)
47 // Description: Serial IO for MBX boards which connect their debug channel 48 // Description: Serial IO for MPC8xx boards which connect their debug channel
48 // to SMC1; or any QUICC user who wants to use SMC1. 49 // to SMC1 or SCC1; or any QUICC user who wants to use SMC1/SCC1
49 // Usage: 50 // Usage:
50 // Notes: The driver hooks itself up on procs channel 0. This should 51 // Notes: The driver hooks itself up on procs channel 0. This should
51 // probably be made configurable, allowing the platform 52 // probably be made configurable, allowing the platform
52 // to specify location. 53 // to specify location.
53 // 54 //
76 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED 77 #include <cyg/hal/drv_api.h> // CYG_ISR_HANDLED
77 78
78 #define UART_BIT_RATE(n) (((int)(CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000)/16)/n) 79 #define UART_BIT_RATE(n) (((int)(CYGHWR_HAL_POWERPC_BOARD_SPEED*1000000)/16)/n)
79 #define UART_BAUD_RATE CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD 80 #define UART_BAUD_RATE CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD
80 81
81 #define Txbd 0x2800 /* Tx Buffer Descriptor Offset */ 82 // Note: buffers will be placed just after descriptors
82 #define Txbuf ((volatile char *)eppc + 0x2808) 83 // Sufficient space should be provided between descrptors
83 #define Rxbd 0x2810 /* Rx Buffer Descriptor Offset */ 84 // for the buffers (single characters)
84 #define NUM_Rxbd 4 85 struct port_info {
85 #define Rxbuf ((volatile char *)eppc + Rxbd + (NUM_Rxbd*sizeof(struct cp_bufdesc))) 86 int Txbd; // Offset to Tx descriptors
87 int Txnum; // Number of Tx buffers
88 int Rxbd; // Offset to Rx descriptors
89 int Rxnum; // Number of Rx buffers
90 int intnum; // Interrupt bit
91 int timeout; // Timeout in msec
92 int pram; // [Pointer] to PRAM data
93 int regs; // [Pointer] to control registers
94 volatile struct cp_bufdesc *next_rxbd;
95 int irq; // Interrupt state
96 };
97
98 static struct port_info ports[] = {
99 { 0x2800, 1, 0x2810, 4, CYGNUM_HAL_INTERRUPT_CPM_SMC1, 1000,
100 (int)&((EPPC *)0)->pram[2].scc.pothers.smc_modem.psmc.u,
101 (int)&((EPPC *)0)->smc_regs[0]
102 },
103 #if CYGNUM_HAL_QUICC_SCC1 > 0
104 { 0x2700, 1, 0x2710, 4, CYGNUM_HAL_INTERRUPT_CPM_SCC1, 1000,
105 (int)&((EPPC *)0)->pram[0].scc.pscc.u,
106 (int)&((EPPC *)0)->scc_regs[0]
107 },
108 #endif
109 };
86 110
87 // SMC Events (interrupts) 111 // SMC Events (interrupts)
88 #define QUICC_SMCE_BRK 0x10 // Break received 112 #define QUICC_SMCE_BRK 0x10 // Break received
89 #define QUICC_SMCE_BSY 0x04 // Busy - receive buffer overrun 113 #define QUICC_SMCE_BSY 0x04 // Busy - receive buffer overrun
90 #define QUICC_SMCE_TX 0x02 // Tx interrupt 114 #define QUICC_SMCE_TX 0x02 // Tx interrupt
91 #define QUICC_SMCE_RX 0x01 // Rx interrupt 115 #define QUICC_SMCE_RX 0x01 // Rx interrupt
92 116
93 static volatile struct cp_bufdesc *next_rxbd; 117 /*
118 * Reset the communications processor
119 */
120 static void
121 reset_cpm(void)
122 {
123 EPPC *eppc = eppc_base();
124 int i;
125 static int init_done = 0;
126
127 if (init_done) return;
128 init_done++;
129
130 eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY;
131 for (i = 0; i < 100000; i++);
132
133 }
94 134
95 /* 135 /*
96 * Initialize SMC1 as a uart. 136 * Initialize SMC1 as a uart.
97 * 137 *
98 * Comments below reference Motorola's "MPC860 User Manual". 138 * Comments below reference Motorola's "MPC860 User Manual".
99 * The basic initialization steps are from Section 16.15.8 139 * The basic initialization steps are from Section 16.15.8
100 * of that manual. 140 * of that manual.
101 */ 141 */
102 void 142 static void
103 cyg_hal_plf_serial_init_channel(void) 143 cyg_hal_smc1_init_channel(struct port_info *info)
104 { 144 {
105 EPPC *eppc; 145 EPPC *eppc = eppc_base();
106 int i; 146 int i;
107 volatile struct smc_uart_pram *uart_pram; 147 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
148 volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
108 struct cp_bufdesc *txbd, *rxbd; 149 struct cp_bufdesc *txbd, *rxbd;
109 150
110 static int init_done = 0; 151 static int init_done = 0;
111 if (init_done) return; 152 if (init_done) return;
112 init_done++; 153 init_done++;
113 154
114 eppc = eppc_base(); 155 reset_cpm();
115
116 /*
117 * Reset communications processor
118 */
119 eppc->cp_cr = QUICC_CPM_CR_RESET | QUICC_CPM_CR_BUSY;
120 for (i = 0; i < 100000; i++);
121
122 /* SMC1 Uart parameter ram */
123 uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u;
124 156
125 /* 157 /*
126 * Set up the PortB pins for UART operation. 158 * Set up the PortB pins for UART operation.
127 * Set PAR and DIR to allow SMCTXD1 and SMRXD1 159 * Set PAR and DIR to allow SMCTXD1 and SMRXD1
128 * (Table 16-39) 160 * (Table 16-39)
141 173
142 /* 174 /*
143 * Set pointers to buffer descriptors. 175 * Set pointers to buffer descriptors.
144 * (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13) 176 * (Sections 16.15.4.1, 16.15.7.12, and 16.15.7.13)
145 */ 177 */
146 uart_pram->rbase = Rxbd; 178 uart_pram->rbase = info->Rxbd;
147 uart_pram->tbase = Txbd; 179 uart_pram->tbase = info->Txbd;
148 180
149 /* 181 /*
150 * SDMA & LCD bus request level 5 182 * SDMA & LCD bus request level 5
151 * (Section 16.10.2.1) 183 * (Section 16.10.2.1)
152 */ 184 */
173 205
174 /* 1 break char sent on top XMIT */ 206 /* 1 break char sent on top XMIT */
175 uart_pram->brkcr = 1; 207 uart_pram->brkcr = 1;
176 208
177 /* setup RX buffer descriptors */ 209 /* setup RX buffer descriptors */
178 rxbd = (struct cp_bufdesc *)((char *)eppc + Rxbd); 210 rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
179 next_rxbd = rxbd; 211 info->next_rxbd = rxbd;
180 for (i = 0; i < NUM_Rxbd; i++) { 212 for (i = 0; i < info->Rxnum; i++) {
181 rxbd->length = 0; 213 rxbd->length = 0;
182 rxbd->buffer = Rxbuf+i; 214 rxbd->buffer = ((char *)eppc + (info->Rxbd+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
183 rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; 215 rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
184 if (i == (NUM_Rxbd-1)) { 216 if (i == ((info->Rxnum)-1)) {
185 rxbd->ctrl |= QUICC_BD_CTL_Wrap; 217 rxbd->ctrl |= QUICC_BD_CTL_Wrap;
186 } 218 }
187 rxbd++; 219 rxbd++;
188 } 220 }
189 // Compiler bug: for whatever reason, the Wrap code above fails! 221 // Compiler bug: for whatever reason, the Wrap code above fails!
190 rxbd = (struct cp_bufdesc *)((char *)eppc + Rxbd); 222 rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
191 rxbd[NUM_Rxbd-1].ctrl |= QUICC_BD_CTL_Wrap; 223 rxbd[(info->Rxnum)-1].ctrl |= QUICC_BD_CTL_Wrap;
192 224
193 /* setup TX buffer descriptor */ 225 /* setup TX buffer descriptor */
194 txbd = (struct cp_bufdesc *)((char *)eppc + Txbd); 226 txbd = (struct cp_bufdesc *)((char *)eppc + info->Txbd);
195 txbd->length = 1; 227 txbd->length = 1;
196 txbd->buffer = Txbuf; 228 txbd->buffer = ((char *)eppc + (info->Txbd+(info->Txnum*sizeof(struct cp_bufdesc))));
197 txbd->ctrl = 0x2000; 229 txbd->ctrl = 0x2000;
198 230
199 /* 231 /*
200 * Clear any previous events. Mask interrupts. 232 * Clear any previous events. Mask interrupts.
201 * (Section 16.15.7.14 and 16.15.7.15) 233 * (Section 16.15.7.14 and 16.15.7.15)
202 */ 234 */
203 eppc->smc_regs[0].smc_smce = 0xff; 235 regs->smc_smce = 0xff;
204 eppc->smc_regs[0].smc_smcm = 5; 236 regs->smc_smcm = 5;
205 237
206 /* 238 /*
207 * Set 8,n,1 characters, then also enable rx and tx. 239 * Set 8,n,1 characters, then also enable rx and tx.
208 * (Section 16.15.7.11) 240 * (Section 16.15.7.11)
209 */ 241 */
210 eppc->smc_regs[0].smc_smcmr = 0x4820; 242 regs->smc_smcmr = 0x4820;
211 eppc->smc_regs[0].smc_smcmr = 0x4823; 243 regs->smc_smcmr = 0x4823;
212 244
213 /* 245 /*
214 * Init Rx & Tx params for SMC1 246 * Init Rx & Tx params for SMC1
215 */ 247 */
216 eppc->cp_cr = 0x91; 248 eppc->cp_cr = 0x91;
217 249
250 info->irq = 0; // Interrupts not enabled
218 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // remove below 251 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // remove below
219 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT 252 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
220 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_CPM_SMC1 ); 253 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_CPM_SMC1 );
221 #endif 254 #endif
222 #endif 255 #endif
235 268
236 #ifdef CYGDBG_DIAG_BUF 269 #ifdef CYGDBG_DIAG_BUF
237 extern int enable_diag_uart; 270 extern int enable_diag_uart;
238 #endif // CYGDBG_DIAG_BUF 271 #endif // CYGDBG_DIAG_BUF
239 272
240 void 273 static void
241 cyg_hal_plf_serial_putc(void* __ch_data, cyg_uint8 ch) 274 cyg_hal_smc1_putc(void* __ch_data, cyg_uint8 ch)
242 { 275 {
243 volatile struct cp_bufdesc *bd, *first; 276 volatile struct cp_bufdesc *bd, *first;
244 EPPC *eppc = (EPPC*) __ch_data; 277 EPPC *eppc = eppc_base();
245 volatile struct smc_uart_pram *uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u; 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);
246 int timeout; 281 int timeout;
247 CYGARC_HAL_SAVE_GP(); 282 CYGARC_HAL_SAVE_GP();
248 283
249 /* tx buffer descriptor */ 284 /* tx buffer descriptor */
250 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr); 285 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr);
279 if (++timeout == 0x7FFFF) { 314 if (++timeout == 0x7FFFF) {
280 // A really long time! 315 // A really long time!
281 #ifdef CYGDBG_DIAG_BUF 316 #ifdef CYGDBG_DIAG_BUF
282 diag_printf("bd fail? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate); 317 diag_printf("bd fail? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate);
283 #endif // CYGDBG_DIAG_BUF 318 #endif // CYGDBG_DIAG_BUF
284 eppc->smc_regs[0].smc_smcmr &= ~QUICC_SMCMR_TEN; // Disable transmitter 319 regs->smc_smcmr &= ~QUICC_SMCMR_TEN; // Disable transmitter
285 bd->ctrl &= ~QUICC_BD_CTL_Ready; 320 bd->ctrl &= ~QUICC_BD_CTL_Ready;
286 eppc->smc_regs[0].smc_smcmr |= QUICC_SMCMR_TEN; // Enable transmitter 321 regs->smc_smcmr |= QUICC_SMCMR_TEN; // Enable transmitter
287 bd->ctrl |= QUICC_BD_CTL_Ready; 322 bd->ctrl |= QUICC_BD_CTL_Ready;
288 timeout = 0; 323 timeout = 0;
289 #ifdef CYGDBG_DIAG_BUF 324 #ifdef CYGDBG_DIAG_BUF
290 diag_printf("bd retry? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate); 325 diag_printf("bd retry? bd: %x, ctrl: %x, tx state: %x\n", bd, bd->ctrl, uart_pram->tstate);
291 first = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase); 326 first = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
305 340
306 CYGARC_HAL_RESTORE_GP(); 341 CYGARC_HAL_RESTORE_GP();
307 } 342 }
308 343
309 344
345 /*
346 * Get a character from a port, non-blocking
347 * This function can be called on either an SMC or SCC port
348 */
310 static cyg_bool 349 static cyg_bool
311 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch) 350 cyg_hal_sxx_getc_nonblock(void* __ch_data, cyg_uint8* ch)
312 { 351 {
313 volatile struct cp_bufdesc *bd; 352 volatile struct cp_bufdesc *bd;
314 EPPC *eppc = (EPPC*) __ch_data; 353 EPPC *eppc = eppc_base();
315 volatile struct smc_uart_pram *uart_pram = &eppc->pram[2].scc.pothers.smc_modem.psmc.u; 354 struct port_info *info = (struct port_info *)__ch_data;
355 volatile struct smc_uart_pram *uart_pram = (volatile struct smc_uart_pram *)((char *)eppc + info->pram);
316 int cache_state; 356 int cache_state;
317 357
318 /* rx buffer descriptor */ 358 /* rx buffer descriptor */
319 bd = next_rxbd; 359 bd = info->next_rxbd;
320 360
321 if (bd->ctrl & QUICC_BD_CTL_Ready) 361 if (bd->ctrl & QUICC_BD_CTL_Ready)
322 return false; 362 return false;
323 363
324 *ch = bd->buffer[0]; 364 *ch = bd->buffer[0];
325 365
326 bd->length = 0; 366 bd->length = 0;
327 bd->buffer[0] = '\0'; 367 bd->buffer[0] = '\0';
328 bd->ctrl |= QUICC_BD_CTL_Ready; 368 bd->ctrl |= QUICC_BD_CTL_Ready;
329 if (bd->ctrl & QUICC_BD_CTL_Wrap) { 369 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
330 bd = (struct cp_bufdesc *)((char *)eppc + Rxbd); 370 bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
331 } else { 371 } else {
332 bd++; 372 bd++;
333 } 373 }
334 next_rxbd = bd; 374 info->next_rxbd = bd;
335 375
336 // Note: the MBX860 does not seem to snoop/invalidate the data cache properly! 376 // Note: the MBX860 does not seem to snoop/invalidate the data cache properly!
337 HAL_DCACHE_IS_ENABLED(cache_state); 377 HAL_DCACHE_IS_ENABLED(cache_state);
338 if (cache_state) { 378 if (cache_state) {
339 HAL_DCACHE_INVALIDATE(bd->buffer, uart_pram->mrblr); // Make sure no stale data 379 HAL_DCACHE_INVALIDATE(bd->buffer, uart_pram->mrblr); // Make sure no stale data
340 } 380 }
341 381
342 return true; 382 return true;
343 } 383 }
344 384
345 cyg_uint8 385 /*
346 cyg_hal_plf_serial_getc(void* __ch_data) 386 * Get a character from a port, blocking
387 * This function can be called on either an SMC or SCC port
388 */
389 static cyg_uint8
390 cyg_hal_sxx_getc(void* __ch_data)
347 { 391 {
348 cyg_uint8 ch; 392 cyg_uint8 ch;
349 CYGARC_HAL_SAVE_GP(); 393 CYGARC_HAL_SAVE_GP();
350 394
351 while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch)); 395 while(!cyg_hal_sxx_getc_nonblock(__ch_data, &ch));
352 396
353 CYGARC_HAL_RESTORE_GP(); 397 CYGARC_HAL_RESTORE_GP();
354 return ch; 398 return ch;
355 } 399 }
356 400
357 401
358
359 static void 402 static void
360 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 403 cyg_hal_smc1_write(void* __ch_data, const cyg_uint8* __buf,
361 cyg_uint32 __len) 404 cyg_uint32 __len)
362 { 405 {
363 CYGARC_HAL_SAVE_GP(); 406 CYGARC_HAL_SAVE_GP();
364 407
365 while(__len-- > 0) 408 while(__len-- > 0)
366 cyg_hal_plf_serial_putc(__ch_data, *__buf++); 409 cyg_hal_smc1_putc(__ch_data, *__buf++);
367 410
368 CYGARC_HAL_RESTORE_GP(); 411 CYGARC_HAL_RESTORE_GP();
369 } 412 }
370 413
414 /*
415 * Read a sequence of characters from a port
416 * This function can be called on either an SMC or SCC port
417 */
371 static void 418 static void
372 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len) 419 cyg_hal_sxx_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
373 { 420 {
374 CYGARC_HAL_SAVE_GP(); 421 CYGARC_HAL_SAVE_GP();
375 422
376 while(__len-- > 0) 423 while(__len-- > 0)
377 *__buf++ = cyg_hal_plf_serial_getc(__ch_data); 424 *__buf++ = cyg_hal_sxx_getc(__ch_data);
378 425
379 CYGARC_HAL_RESTORE_GP(); 426 CYGARC_HAL_RESTORE_GP();
380 } 427 }
381 428
382 cyg_int32 msec_timeout = 1000; 429 /*
383 430 * Read a character from a port, with a timeout
384 cyg_bool 431 * This function can be called on either an SMC or SCC port
385 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch) 432 */
386 { 433 static cyg_bool
387 int delay_count = msec_timeout * 10; // delay in .1 ms steps 434 cyg_hal_sxx_getc_timeout(void* __ch_data, cyg_uint8* ch)
435 {
436 struct port_info *info = (struct port_info *)__ch_data;
437 int delay_count = info->timeout * 10; // delay in .1 ms steps
388 cyg_bool res; 438 cyg_bool res;
389 CYGARC_HAL_SAVE_GP(); 439 CYGARC_HAL_SAVE_GP();
390 440
391 for(;;) { 441 for(;;) {
392 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch); 442 res = cyg_hal_sxx_getc_nonblock(__ch_data, ch);
393 if (res || 0 == delay_count--) 443 if (res || 0 == delay_count--)
394 break; 444 break;
395 445
396 CYGACC_CALL_IF_DELAY_US(100); 446 CYGACC_CALL_IF_DELAY_US(100);
397 } 447 }
398 448
399 CYGARC_HAL_RESTORE_GP(); 449 CYGARC_HAL_RESTORE_GP();
400 return res; 450 return res;
401 } 451 }
402 452
453 /*
454 * Control/query the state of a port
455 * This function can be called on either an SMC or SCC port
456 */
403 static int 457 static int
404 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...) 458 cyg_hal_sxx_control(void *__ch_data, __comm_control_cmd_t __func, ...)
405 { 459 {
406 static int irq_state = 0; 460 struct port_info *info = (struct port_info *)__ch_data;
407 int ret = 0; 461 int ret = 0;
408 CYGARC_HAL_SAVE_GP(); 462 CYGARC_HAL_SAVE_GP();
409 463
410 switch (__func) { 464 switch (__func) {
411 case __COMMCTL_IRQ_ENABLE: 465 case __COMMCTL_IRQ_ENABLE:
412 HAL_INTERRUPT_UNMASK(CYGNUM_HAL_INTERRUPT_CPM_SMC1); 466 HAL_INTERRUPT_UNMASK(info->intnum);
413 irq_state = 1; 467 info->irq = 1;
414 break; 468 break;
415 case __COMMCTL_IRQ_DISABLE: 469 case __COMMCTL_IRQ_DISABLE:
416 ret = irq_state; 470 ret = info->irq;
417 irq_state = 0; 471 info->irq = 0;
418 HAL_INTERRUPT_MASK(CYGNUM_HAL_INTERRUPT_CPM_SMC1); 472 HAL_INTERRUPT_MASK(info->intnum);
419 break; 473 break;
420 case __COMMCTL_DBG_ISR_VECTOR: 474 case __COMMCTL_DBG_ISR_VECTOR:
421 ret = CYGNUM_HAL_INTERRUPT_CPM_SMC1; 475 ret = info->intnum;
422 break; 476 break;
423 case __COMMCTL_SET_TIMEOUT: 477 case __COMMCTL_SET_TIMEOUT:
424 { 478 {
425 va_list ap; 479 va_list ap;
426 480
427 va_start(ap, __func); 481 va_start(ap, __func);
428 482
429 ret = msec_timeout; 483 ret = info->timeout;
430 msec_timeout = va_arg(ap, cyg_uint32); 484 info->timeout = va_arg(ap, cyg_uint32);
431 485
432 va_end(ap); 486 va_end(ap);
433 } 487 }
434 default: 488 default:
435 break; 489 break;
436 } 490 }
437 CYGARC_HAL_RESTORE_GP(); 491 CYGARC_HAL_RESTORE_GP();
438 return ret; 492 return ret;
439 } 493 }
440 494
495 /*
496 * Low-level interrupt (ISR) handler
497 * This function can be called on only an SMC port
498 */
441 static int 499 static int
442 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 500 cyg_hal_smc1_isr(void *__ch_data, int* __ctrlc,
443 CYG_ADDRWORD __vector, CYG_ADDRWORD __data) 501 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
444 { 502 {
445 EPPC *eppc = (EPPC*) __ch_data; 503 EPPC *eppc = eppc_base();
446 volatile struct cp_bufdesc *bd; 504 volatile struct cp_bufdesc *bd;
505 struct port_info *info = (struct port_info *)__ch_data;
506 volatile struct smc_regs *regs = (volatile struct smc_regs *)((char *)eppc + info->regs);
447 char ch; 507 char ch;
448 int res = 0; 508 int res = 0;
449 CYGARC_HAL_SAVE_GP(); 509 CYGARC_HAL_SAVE_GP();
450 510
451 *__ctrlc = 0; 511 *__ctrlc = 0;
452 if (eppc->smc_regs[0].smc_smce & QUICC_SMCE_RX) { 512 if (regs->smc_smce & QUICC_SMCE_RX) {
453 513
454 eppc->smc_regs[0].smc_smce = QUICC_SMCE_RX; 514 regs->smc_smce = QUICC_SMCE_RX;
455 515
456 /* rx buffer descriptors */ 516 /* rx buffer descriptors */
457 bd = next_rxbd; 517 bd = info->next_rxbd;
458 518
459 if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) { 519 if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) {
460 520
461 // then there be a character waiting 521 // then there be a character waiting
462 ch = bd->buffer[0]; 522 ch = bd->buffer[0];
463 bd->length = 1; 523 bd->length = 1;
464 bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int; 524 bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
465 if (bd->ctrl & QUICC_BD_CTL_Wrap) { 525 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
466 bd = (struct cp_bufdesc *)((char *)eppc + Rxbd); 526 bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
467 } else { 527 } else {
468 bd++; 528 bd++;
469 } 529 }
470 next_rxbd = bd; 530 info->next_rxbd = bd;
471 531
472 if( cyg_hal_is_break( &ch , 1 ) ) 532 if( cyg_hal_is_break( &ch , 1 ) )
473 *__ctrlc = 1; 533 *__ctrlc = 1;
474 } 534 }
475 535
476 // Interrupt handled. Acknowledge it. 536 // Interrupt handled. Acknowledge it.
477 eppc->cpmi_cisr = 0x10; 537 HAL_INTERRUPT_ACKNOWLEDGE(info->intnum);
478 res = CYG_ISR_HANDLED; 538 res = CYG_ISR_HANDLED;
479 } 539 }
480 540
481 CYGARC_HAL_RESTORE_GP(); 541 CYGARC_HAL_RESTORE_GP();
482 return res; 542 return res;
483 } 543 }
544
545 #if CYGNUM_HAL_QUICC_SCC1 > 0
546 /*
547 * Initialize SCC1 as a uart.
548 *
549 * Comments below reference Motorola's "MPC860 User Manual".
550 * The basic initialization steps are from Section 16.15.8
551 * of that manual.
552 */
553 static void
554 cyg_hal_scc1_init_channel(struct port_info *info)
555 {
556 EPPC *eppc = eppc_base();
557 int i;
558 volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram);
559 volatile struct scc_regs *regs = (volatile struct scc_regs *)((char *)eppc + info->regs);
560 struct cp_bufdesc *txbd, *rxbd;
561
562 static int init_done = 0;
563 if (init_done) return;
564 init_done++;
565
566 reset_cpm();
567
568 /*
569 * Set up the PortA pins for UART operation.
570 */
571 eppc->pio_papar |= 0x03;
572 eppc->pio_padir &= ~0x03;
573 eppc->pio_paodr &= ~0x03;
574
575 /* CTS on PortC.11 */
576 eppc->pio_pcdir &= 0x800;
577 eppc->pio_pcpar &= 0x800;
578 eppc->pio_pcso |= 0x800;
579
580 /* RTS on PortB.19 */
581 eppc->pip_pbpar |= 0x1000;
582 eppc->pip_pbdir |= 0x1000;
583
584 /* Configure baud rate generator (Section 16.13.2) */
585 eppc->brgc2 = 0x10000 | (UART_BIT_RATE(UART_BAUD_RATE)<<1);
586
587 /*
588 * NMSI mode, BRG2 to SCC1
589 */
590 eppc->si_simode = 0;
591 eppc->si_sicr = (1<<3)|(1<<0);
592
593 /*
594 * Set pointers to buffer descriptors.
595 */
596 uart_pram->rbase = info->Rxbd;
597 uart_pram->tbase = info->Txbd;
598
599 /*
600 * SDMA & LCD bus request level 5
601 */
602 eppc->dma_sdcr = 1;
603
604 /*
605 * Set Rx and Tx function code
606 */
607 uart_pram->rfcr = 0x18;
608 uart_pram->tfcr = 0x18;
609
610 /* max receive buffer length */
611 uart_pram->mrblr = 1;
612
613 /* disable max_idle feature */
614 uart_pram->max_idl = 0;
615
616 /* no last brk char received */
617 uart_pram->brkln = 0;
618
619 /* no break condition occurred */
620 uart_pram->brkec = 0;
621
622 /* 1 break char sent on top XMIT */
623 uart_pram->brkcr = 1;
624
625 /* character mask */
626 uart_pram->rccm = 0xC0FF;
627
628 /* setup RX buffer descriptors */
629 rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
630 info->next_rxbd = rxbd;
631 for (i = 0; i < info->Rxnum; i++) {
632 rxbd->length = 0;
633 rxbd->buffer = ((char *)eppc + (info->Rxbd+(info->Rxnum*sizeof(struct cp_bufdesc))))+i;
634 rxbd->ctrl = QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
635 if (i == ((info->Rxnum)-1)) {
636 rxbd->ctrl |= QUICC_BD_CTL_Wrap;
637 }
638 rxbd++;
639 }
640 // Compiler bug: for whatever reason, the Wrap code above fails!
641 rxbd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
642 rxbd[(info->Rxnum)-1].ctrl |= QUICC_BD_CTL_Wrap;
643
644 /* setup TX buffer descriptor */
645 txbd = (struct cp_bufdesc *)((char *)eppc + info->Txbd);
646 txbd->length = 1;
647 txbd->buffer = ((char *)eppc + (info->Txbd+(info->Txnum*sizeof(struct cp_bufdesc))));
648 txbd->ctrl = 0x2000;
649
650 /*
651 * Init Rx & Tx params for SCC1
652 */
653 eppc->cp_cr = 0x41;
654
655 /*
656 * Clear any previous events. Mask interrupts.
657 * (Section 16.15.7.14 and 16.15.7.15)
658 */
659 regs->scc_scce = 0xff;
660 regs->scc_sccm = 5;
661
662 /*
663 * Set 8,n,1 characters
664 */
665 regs->scc_psmr = (3<<12);
666 regs->scc_gsmr_h = 0x20; // 8bit FIFO
667 regs->scc_gsmr_l = 0x00028004; // 16x TxCLK, 16x RxCLK, UART
668 regs->scc_gsmr_l |= 0x30; // Enable Rx, Tx
669
670 info->irq = 0;
671 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // remove below
672 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
673 HAL_INTERRUPT_UNMASK( CYGNUM_HAL_INTERRUPT_CPM_SCC1 );
674 #endif
675 #endif
676 }
677
678 static void
679 cyg_hal_scc1_putc(void* __ch_data, cyg_uint8 ch)
680 {
681 volatile struct cp_bufdesc *bd, *first;
682 EPPC *eppc = eppc_base();
683 struct port_info *info = (struct port_info *)__ch_data;
684 volatile struct uart_pram *uart_pram = (volatile struct uart_pram *)((char *)eppc + info->pram);
685 CYGARC_HAL_SAVE_GP();
686
687 /* tx buffer descriptor */
688 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbptr);
689
690 // Scan for a free buffer
691 first = bd;
692 while (bd->ctrl & QUICC_BD_CTL_Ready) {
693 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
694 bd = (struct cp_bufdesc *)((char *)eppc + uart_pram->tbase);
695 } else {
696 bd++;
697 }
698 if (bd == first) break;
699 }
700
701 while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait for buffer free
702 if (bd->ctrl & QUICC_BD_CTL_Int) {
703 // This buffer has just completed interrupt output. Reset bits
704 bd->ctrl &= ~QUICC_BD_CTL_Int;
705 bd->length = 0;
706 }
707
708 bd->buffer[bd->length++] = ch;
709 bd->ctrl |= QUICC_BD_CTL_Ready;
710
711 while (bd->ctrl & QUICC_BD_CTL_Ready) ; // Wait until buffer free
712 bd->length = 0;
713
714 CYGARC_HAL_RESTORE_GP();
715 }
716
717 static void
718 cyg_hal_scc1_write(void* __ch_data, const cyg_uint8* __buf,
719 cyg_uint32 __len)
720 {
721 CYGARC_HAL_SAVE_GP();
722
723 while(__len-- > 0)
724 cyg_hal_scc1_putc(__ch_data, *__buf++);
725
726 CYGARC_HAL_RESTORE_GP();
727 }
728
729 static int
730 cyg_hal_scc1_isr(void *__ch_data, int* __ctrlc,
731 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
732 {
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 char ch;
738 int res = 0;
739 CYGARC_HAL_SAVE_GP();
740
741 *__ctrlc = 0;
742 if (regs->scc_scce & QUICC_SMCE_RX) {
743
744 regs->scc_scce = QUICC_SMCE_RX;
745
746 /* rx buffer descriptors */
747 bd = info->next_rxbd;
748
749 if ((bd->ctrl & QUICC_BD_CTL_Ready) == 0) {
750
751 // then there be a character waiting
752 ch = bd->buffer[0];
753 bd->length = 1;
754 bd->ctrl |= QUICC_BD_CTL_Ready | QUICC_BD_CTL_Int;
755 if (bd->ctrl & QUICC_BD_CTL_Wrap) {
756 bd = (struct cp_bufdesc *)((char *)eppc + info->Rxbd);
757 } else {
758 bd++;
759 }
760 info->next_rxbd = bd;
761
762 if( cyg_hal_is_break( &ch , 1 ) )
763 *__ctrlc = 1;
764 }
765
766 // Interrupt handled. Acknowledge it.
767 HAL_INTERRUPT_ACKNOWLEDGE(info->intnum);
768 res = CYG_ISR_HANDLED;
769 }
770
771 CYGARC_HAL_RESTORE_GP();
772 return res;
773 }
774 #endif // CYGNUM_HAL_QUICC_SCC1
484 775
485 /* 776 /*
486 * Early initialization of comm channels. Must not rely 777 * Early initialization of comm channels. Must not rely
487 * on interrupts, yet. Interrupt operation can be enabled 778 * on interrupts, yet. Interrupt operation can be enabled
488 * in _bsp_board_init(). 779 * in _bsp_board_init().
495 786
496 static int init = 0; // It's wrong to do this more than once 787 static int init = 0; // It's wrong to do this more than once
497 if (init) return; 788 if (init) return;
498 init++; 789 init++;
499 790
500 cyg_hal_plf_serial_init_channel();
501
502 // Setup procs in the vector table 791 // Setup procs in the vector table
503 792
504 // Set channel 0 793 // Set channel 0 - SMC1
794 cyg_hal_smc1_init_channel(&ports[0]);
505 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);// Should be configurable! 795 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);// Should be configurable!
506 comm = CYGACC_CALL_IF_CONSOLE_PROCS(); 796 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
507 CYGACC_COMM_IF_CH_DATA_SET(*comm, eppc_base()); 797 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[0]);
508 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write); 798 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_smc1_write);
509 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read); 799 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
510 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc); 800 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_smc1_putc);
511 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc); 801 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
512 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control); 802 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
513 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr); 803 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_smc1_isr);
514 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout); 804 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
805
806 #if CYGNUM_HAL_QUICC_SCC1 > 0
807
808 // Set channel 1 - SCC1
809 cyg_hal_scc1_init_channel(&ports[1]);
810 CYGACC_CALL_IF_SET_CONSOLE_COMM(1);// Should be configurable!
811 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
812 CYGACC_COMM_IF_CH_DATA_SET(*comm, &ports[1]);
813 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_scc1_write);
814 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_sxx_read);
815 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_scc1_putc);
816 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_sxx_getc);
817 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_sxx_control);
818 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_scc1_isr);
819 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_sxx_getc_timeout);
820 #endif
515 821
516 // Restore original console 822 // Restore original console
517 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); 823 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
518 } 824 }
519 825