]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx25/var/v2_0/src/soc_diag.c
Added TX25 bootsplash support
[karo-tx-redboot.git] / packages / hal / arm / mx25 / var / v2_0 / src / soc_diag.c
1 /*=============================================================================
2 //
3 //  hal_diag.c
4 //
5 //  HAL diagnostic output code
6 //
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 //
13 // 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 // Software Foundation; either version 2 or (at your option) any later version.
16 //
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
20 // for more details.
21 //
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
25 //
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
32 //
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
35 //
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 //===========================================================================*/
41
42 #include <pkgconf/hal.h>
43 #include <pkgconf/system.h>
44 #include CYGBLD_HAL_PLATFORM_H
45
46 #include <cyg/infra/cyg_type.h>                 // base types
47 #include <cyg/infra/cyg_trac.h>                 // tracing macros
48 #include <cyg/infra/cyg_ass.h>                  // assertion macros
49
50 #include <cyg/hal/hal_arch.h>                   // basic machine info
51 #include <cyg/hal/hal_intr.h>                   // interrupt macros
52 #include <cyg/hal/hal_io.h>                             // IO macros
53 #include <cyg/hal/hal_if.h>                             // Calling interface definitions
54 #include <cyg/hal/hal_diag.h>
55 #include <cyg/hal/drv_api.h>                    // cyg_drv_interrupt_acknowledge
56 #include <cyg/hal/hal_misc.h>                   // Helper functions
57 #include <cyg/hal/hal_soc.h>                    // Hardware definitions
58
59 /*
60  * UART Control Register 0 Bit Fields.
61  */
62 #define EUartUCR1_ADEN          (1 << 15)                       // Auto dectect interrupt
63 #define EUartUCR1_ADBR          (1 << 14)                       // Auto detect baud rate
64 #define EUartUCR1_TRDYEN        (1 << 13)                       // Transmitter ready interrupt enable
65 #define EUartUCR1_IDEN          (1 << 12)                       // Idle condition interrupt
66 #define EUartUCR1_RRDYEN        (1 << 9)                        // Recv ready interrupt enable
67 #define EUartUCR1_RDMAEN        (1 << 8)                        // Recv ready DMA enable
68 #define EUartUCR1_IREN          (1 << 7)                        // Infrared interface enable
69 #define EUartUCR1_TXMPTYEN      (1 << 6)                        // Transimitter empty interrupt enable
70 #define EUartUCR1_RTSDEN        (1 << 5)                        // RTS delta interrupt enable
71 #define EUartUCR1_SNDBRK        (1 << 4)                        // Send break
72 #define EUartUCR1_TDMAEN        (1 << 3)                        // Transmitter ready DMA enable
73 #define EUartUCR1_DOZE          (1 << 1)                        // Doze
74 #define EUartUCR1_UARTEN        (1 << 0)                        // UART enabled
75 #define EUartUCR2_ESCI          (1 << 15)                       // Escape seq interrupt enable
76 #define EUartUCR2_IRTS          (1 << 14)                       // Ignore RTS pin
77 #define EUartUCR2_CTSC          (1 << 13)                       // CTS pin control
78 #define EUartUCR2_CTS           (1 << 12)                       // Clear to send
79 #define EUartUCR2_ESCEN         (1 << 11)                       // Escape enable
80 #define EUartUCR2_PREN          (1 << 8)                        // Parity enable
81 #define EUartUCR2_PROE          (1 << 7)                        // Parity odd/even
82 #define EUartUCR2_STPB          (1 << 6)                        // Stop
83 #define EUartUCR2_WS            (1 << 5)                        // Word size
84 #define EUartUCR2_RTSEN         (1 << 4)                        // Request to send interrupt enable
85 #define EUartUCR2_ATEN          (1 << 3)                        // Aging timer enable
86 #define EUartUCR2_TXEN          (1 << 2)                        // Transmitter enabled
87 #define EUartUCR2_RXEN          (1 << 1)                        // Receiver enabled
88 #define EUartUCR2_SRST_         (1 << 0)                        // SW reset
89 #define EUartUCR3_PARERREN      (1 << 12)                       // Parity enable
90 #define EUartUCR3_FRAERREN      (1 << 11)                       // Frame error interrupt enable
91 #define EUartUCR3_ADNIMP        (1 << 7)                        // Autobaud detection not improved
92 #define EUartUCR3_RXDSEN        (1 << 6)                        // Receive status interrupt enable
93 #define EUartUCR3_AIRINTEN      (1 << 5)                        // Async IR wake interrupt enable
94 #define EUartUCR3_AWAKEN        (1 << 4)                        // Async wake interrupt enable
95 #define EUartUCR3_RXDMUXSEL (1 << 2)                    // RXD muxed input selected
96 #define EUartUCR3_INVT          (1 << 1)                        // Inverted Infrared transmission
97 #define EUartUCR3_ACIEN         (1 << 0)                        // Autobaud counter interrupt enable
98 #define EUartUCR4_CTSTL_32      (32 << 10)                      // CTS trigger level (32 chars)
99 #define EUartUCR4_INVR          (1 << 9)                        // Inverted infrared reception
100 #define EUartUCR4_ENIRI         (1 << 8)                        // Serial infrared interrupt enable
101 #define EUartUCR4_WKEN          (1 << 7)                        // Wake interrupt enable
102 #define EUartUCR4_IRSC          (1 << 5)                        // IR special case
103 #define EUartUCR4_LPBYP         (1 << 4)                        // Low power bypass
104 #define EUartUCR4_TCEN          (1 << 3)                        // Transmit complete interrupt enable
105 #define EUartUCR4_BKEN          (1 << 2)                        // Break condition interrupt enable
106 #define EUartUCR4_OREN          (1 << 1)                        // Receiver overrun interrupt enable
107 #define EUartUCR4_DREN          (1 << 0)                        // Recv data ready interrupt enable
108 #define EUartUFCR_RXTL_SHF      0                                       // Receiver trigger level shift
109 #define EUartUFCR_RFDIV_1       (5 << 7)                        // Reference freq divider (div 1)
110 #define EUartUFCR_RFDIV_2       (4 << 7)                        // Reference freq divider (div 2)
111 #define EUartUFCR_RFDIV_3       (3 << 7)                        // Reference freq divider (div 3)
112 #define EUartUFCR_RFDIV_4       (2 << 7)                        // Reference freq divider (div 4)
113 #define EUartUFCR_RFDIV_5       (1 << 7)                        // Reference freq divider (div 5)
114 #define EUartUFCR_RFDIV_6       (0 << 7)                        // Reference freq divider (div 6)
115 #define EUartUFCR_RFDIV_7       (6 << 7)                        // Reference freq divider (div 7)
116 #define EUartUFCR_TXTL_SHF      10                                      // Transmitter trigger level shift
117 #define EUartUSR1_PARITYERR (1 << 15)                   // Parity error interrupt flag
118 #define EUartUSR1_RTSS          (1 << 14)                       // RTS pin status
119 #define EUartUSR1_TRDY          (1 << 13)                       // Transmitter ready interrupt/dma flag
120 #define EUartUSR1_RTSD          (1 << 12)                       // RTS delta
121 #define EUartUSR1_ESCF          (1 << 11)                       // Escape seq interrupt flag
122 #define EUartUSR1_FRAMERR       (1 << 10)                       // Frame error interrupt flag
123 #define EUartUSR1_RRDY          (1 << 9)                        // Receiver ready interrupt/dma flag
124 #define EUartUSR1_AGTIM         (1 << 8)                        // Aging timeout interrupt status
125 #define EUartUSR1_RXDS          (1 << 6)                        // Receiver idle interrupt flag
126 #define EUartUSR1_AIRINT        (1 << 5)                        // Async IR wake interrupt flag
127 #define EUartUSR1_AWAKE         (1 << 4)                        // Aysnc wake interrupt flag
128 #define EUartUSR2_ADET          (1 << 15)                       // Auto baud rate detect complete
129 #define EUartUSR2_TXFE          (1 << 14)                       // Transmit buffer FIFO empty
130 #define EUartUSR2_IDLE          (1 << 12)                       // Idle condition
131 #define EUartUSR2_ACST          (1 << 11)                       // Autobaud counter stopped
132 #define EUartUSR2_IRINT         (1 << 8)                        // Serial infrared interrupt flag
133 #define EUartUSR2_WAKE          (1 << 7)                        // Wake
134 #define EUartUSR2_RTSF          (1 << 4)                        // RTS edge interrupt flag
135 #define EUartUSR2_TXDC          (1 << 3)                        // Transmitter complete
136 #define EUartUSR2_BRCD          (1 << 2)                        // Break condition
137 #define EUartUSR2_ORE           (1 << 1)                        // Overrun error
138 #define EUartUSR2_RDR           (1 << 0)                        // Recv data ready
139 #define EUartUTS_FRCPERR        (1 << 13)                       // Force parity error
140 #define EUartUTS_LOOP           (1 << 12)                       // Loop tx and rx
141 #define EUartUTS_TXEMPTY        (1 << 6)                        // TxFIFO empty
142 #define EUartUTS_RXEMPTY        (1 << 5)                        // RxFIFO empty
143 #define EUartUTS_TXFULL         (1 << 4)                        // TxFIFO full
144 #define EUartUTS_RXFULL         (1 << 3)                        // RxFIFO full
145 #define EUartUTS_SOFTRST        (1 << 0)                        // Software reset
146
147 #define EUartUFCR_RFDIV                                                 EUartUFCR_RFDIV_1
148
149 #if (EUartUFCR_RFDIV==EUartUFCR_RFDIV_1)
150 #define MXC_UART_REFFREQ                                                (get_peri_clock(PER_UART_CLK) / 1)
151 #endif
152
153 #if (EUartUFCR_RFDIV==EUartUFCR_RFDIV_2)
154 #define MXC_UART_REFFREQ                                                (get_peri_clock(PER_UART_CLK) / 2)
155 #endif
156
157 #if (EUartUFCR_RFDIV==EUartUFCR_RFDIV_4)
158 #define MXC_UART_REFFREQ                                                (get_peri_clock(PER_UART_CLK) / 4)
159 #endif
160
161 /* The Freescale 3Stack board has two external UART ports which are mapped first
162  * for whatever strange reason.
163  * Other manufacturers may not have these UARTS on their boards but would
164  * as well like to have their serial ports start at '0'!
165  */
166 #ifdef CYGPKG_HAL_ARM_MX25_3STACK
167 #define MXC_UART_CHAN_OFFSET    2
168 #else
169 #define MXC_UART_CHAN_OFFSET    0
170 #endif
171
172
173 //=============================================================================
174 // MXC Serial Port (UARTx) for Debug
175 //=============================================================================
176 #ifdef UART_WIDTH_32
177 struct mxc_serial {
178         volatile cyg_uint32 urxd[16];
179         volatile cyg_uint32 utxd[16];
180         volatile cyg_uint32 ucr1;
181         volatile cyg_uint32 ucr2;
182         volatile cyg_uint32 ucr3;
183         volatile cyg_uint32 ucr4;
184         volatile cyg_uint32 ufcr;
185         volatile cyg_uint32 usr1;
186         volatile cyg_uint32 usr2;
187         volatile cyg_uint32 uesc;
188         volatile cyg_uint32 utim;
189         volatile cyg_uint32 ubir;
190         volatile cyg_uint32 ubmr;
191         volatile cyg_uint32 ubrc;
192         volatile cyg_uint32 onems;
193         volatile cyg_uint32 uts;
194 };
195 #else
196 struct mxc_serial {
197         volatile cyg_uint16 urxd[1];
198         volatile cyg_uint16 resv0[31];
199
200         volatile cyg_uint16 utxd[1];
201         volatile cyg_uint16 resv1[31];
202         volatile cyg_uint16 ucr1;
203         volatile cyg_uint16 resv2;
204         volatile cyg_uint16 ucr2;
205         volatile cyg_uint16 resv3;
206         volatile cyg_uint16 ucr3;
207         volatile cyg_uint16 resv4;
208         volatile cyg_uint16 ucr4;
209         volatile cyg_uint16 resv5;
210         volatile cyg_uint16 ufcr;
211         volatile cyg_uint16 resv6;
212         volatile cyg_uint16 usr1;
213         volatile cyg_uint16 resv7;
214         volatile cyg_uint16 usr2;
215         volatile cyg_uint16 resv8;
216         volatile cyg_uint16 uesc;
217         volatile cyg_uint16 resv9;
218         volatile cyg_uint16 utim;
219         volatile cyg_uint16 resv10;
220         volatile cyg_uint16 ubir;
221         volatile cyg_uint16 resv11;
222         volatile cyg_uint16 ubmr;
223         volatile cyg_uint16 resv12;
224         volatile cyg_uint16 ubrc;
225         volatile cyg_uint16 resv13;
226         volatile cyg_uint16 onems;
227         volatile cyg_uint16 resv14;
228         volatile cyg_uint16 uts;
229         volatile cyg_uint16 resv15;
230 };
231 #endif
232
233 typedef struct {
234         volatile struct mxc_serial *base;
235         cyg_int32 msec_timeout;
236         int isr_vector;
237         int baud_rate;
238 } channel_data_t;
239
240 static channel_data_t channels[] = {
241 #if CYGHWR_HAL_ARM_SOC_UART1 != 0
242         {(volatile struct mxc_serial*)UART1_BASE_ADDR, 1000,
243          CYGNUM_HAL_INTERRUPT_UART1, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD},
244 #endif
245 #if CYGHWR_HAL_ARM_SOC_UART2 != 0
246         {(volatile struct mxc_serial*)UART2_BASE_ADDR, 1000,
247          CYGNUM_HAL_INTERRUPT_UART2, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD},
248 #endif
249 #if CYGHWR_HAL_ARM_SOC_UART3 != 0
250         {(volatile struct mxc_serial*)UART3_BASE_ADDR, 1000,
251          CYGNUM_HAL_INTERRUPT_UART3, CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD},
252 #endif
253 };
254
255 /*---------------------------------------------------------------------------*/
256
257 static void init_serial_channel(channel_data_t *__ch_data)
258 {
259         volatile struct mxc_serial *base = __ch_data->base;
260
261         /* Wait for UART to finish transmitting */
262         while (!(base->uts & EUartUTS_TXEMPTY));
263
264         /* Disable UART */
265         base->ucr1 &= ~EUartUCR1_UARTEN;
266
267         /* Set to default POR state */
268         base->ucr1 = 0x00000000;
269         base->ucr2 = 0x00000000;
270
271         while (!(base->ucr2 & EUartUCR2_SRST_));
272
273         base->ucr3 = 0x00000704;
274         base->ucr4 = 0x00008000;
275         base->ufcr = 0x00000801;
276         base->uesc = 0x0000002B;
277         base->utim = 0x00000000;
278         base->ubir = 0x00000000;
279         base->ubmr = 0x00000000;
280         base->onems = 0x00000000;
281         base->uts  = 0x00000000;
282
283         /* Configure FIFOs */
284         base->ufcr = (1 << EUartUFCR_RXTL_SHF) | EUartUFCR_RFDIV |
285                 (2 << EUartUFCR_TXTL_SHF);
286
287         /* Setup One MS timer */
288         base->onems = MXC_UART_REFFREQ / 1000;
289
290         /* Set to 8N1 */
291         base->ucr2 &= ~EUartUCR2_PREN;
292         base->ucr2 |= EUartUCR2_WS;
293         base->ucr2 &= ~EUartUCR2_STPB;
294
295         /* Ignore RTS */
296         base->ucr2 |= EUartUCR2_IRTS;
297
298         /* Enable UART */
299         base->ucr1 |= EUartUCR1_UARTEN;
300
301         /* Enable FIFOs */
302         base->ucr2 |= EUartUCR2_SRST_ | EUartUCR2_RXEN | EUartUCR2_TXEN;
303
304         /* Clear status flags */
305         base->usr2 |= EUartUSR2_ADET  |
306                                   EUartUSR2_IDLE  |
307                                   EUartUSR2_IRINT |
308                                   EUartUSR2_WAKE  |
309                                   EUartUSR2_RTSF  |
310                                   EUartUSR2_BRCD  |
311                                   EUartUSR2_ORE   |
312                                   EUartUSR2_RDR;
313
314         /* Clear status flags */
315         base->usr1 |= EUartUSR1_PARITYERR |
316                                   EUartUSR1_RTSD          |
317                                   EUartUSR1_ESCF          |
318                                   EUartUSR1_FRAMERR       |
319                                   EUartUSR1_AIRINT        |
320                                   EUartUSR1_AWAKE;
321
322         /* Set the numerator value minus one of the BRM ratio */
323         base->ubir = (__ch_data->baud_rate / 100) - 1;
324
325         /* Set the denominator value minus one of the BRM ratio */
326         base->ubmr = (MXC_UART_REFFREQ / 1600) - 1;
327 }
328
329 static void stop_serial_channel(channel_data_t *__ch_data)
330 {
331         volatile struct mxc_serial *base = __ch_data->base;
332
333         /* Wait for UART to finish transmitting */
334         while (!(base->uts & EUartUTS_TXEMPTY));
335
336         /* Disable UART */
337         base->ucr1 &= ~EUartUCR1_UARTEN;
338 }
339
340 //#define debug_uart_log_buf
341 #ifdef debug_uart_log_buf
342 #define DIAG_BUFSIZE 2048
343 static char __log_buf[DIAG_BUFSIZE];
344 static int diag_bp = 0;
345 #endif
346
347 void cyg_hal_plf_serial_putc(void *__ch_data, char c)
348 {
349         channel_data_t *chan = __ch_data;
350         volatile struct mxc_serial *base = chan->base;
351 #ifdef debug_uart_log_buf
352         __log_buf[diag_bp++] = c;
353 #endif
354
355         CYGARC_HAL_SAVE_GP();
356
357         // Wait for Tx FIFO not full
358         while (base->uts & EUartUTS_TXFULL)
359                 ;
360         base->utxd[0] = c;
361
362         CYGARC_HAL_RESTORE_GP();
363 }
364
365 static cyg_bool cyg_hal_plf_serial_getc_nonblock(void *__ch_data,
366                                                                                                 cyg_uint8 *ch)
367 {
368         channel_data_t *chan = __ch_data;
369         volatile struct mxc_serial *base = chan->base;
370
371         // If receive fifo is empty, return false
372         if (base->uts & EUartUTS_RXEMPTY)
373                 return false;
374
375         *ch = (char)base->urxd[0];
376
377         return true;
378 }
379
380 cyg_uint8 cyg_hal_plf_serial_getc(void *__ch_data)
381 {
382         cyg_uint8 ch;
383         CYGARC_HAL_SAVE_GP();
384
385         while (!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
386
387         CYGARC_HAL_RESTORE_GP();
388         return ch;
389 }
390
391 static void cyg_hal_plf_serial_write(void *__ch_data, const cyg_uint8 *__buf,
392                                                                         cyg_uint32 __len)
393 {
394         CYGARC_HAL_SAVE_GP();
395
396         while (__len-- > 0)
397                 cyg_hal_plf_serial_putc(__ch_data, *__buf++);
398
399         CYGARC_HAL_RESTORE_GP();
400 }
401
402 static void cyg_hal_plf_serial_read(void *__ch_data, cyg_uint8 *__buf,
403                                                                         cyg_uint32 __len)
404 {
405         CYGARC_HAL_SAVE_GP();
406
407         while (__len-- > 0)
408                 *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
409
410         CYGARC_HAL_RESTORE_GP();
411 }
412
413 cyg_bool cyg_hal_plf_serial_getc_timeout(void *__ch_data,
414                                                                                 cyg_uint8 *ch)
415 {
416         int delay_count;
417         channel_data_t *chan = __ch_data;
418         cyg_bool res;
419         CYGARC_HAL_SAVE_GP();
420
421         delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
422
423         for (;;) {
424                 res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
425                 if (res || 0 == delay_count--)
426                         break;
427
428                 CYGACC_CALL_IF_DELAY_US(100);
429         }
430
431         CYGARC_HAL_RESTORE_GP();
432         return res;
433 }
434
435 static int cyg_hal_plf_serial_control(void *__ch_data,
436                                                                         __comm_control_cmd_t __func, ...)
437 {
438         static int irq_state = 0;
439         channel_data_t *chan = __ch_data;
440         int ret = -1;
441         va_list ap;
442
443         CYGARC_HAL_SAVE_GP();
444         va_start(ap, __func);
445
446         switch (__func) {
447         case __COMMCTL_GETBAUD:
448                 ret = chan->baud_rate;
449                 break;
450         case __COMMCTL_SETBAUD:
451                 chan->baud_rate = va_arg(ap, cyg_int32);
452                 // Should we verify this value here?
453                 init_serial_channel(chan);
454                 ret = 0;
455                 break;
456         case __COMMCTL_IRQ_ENABLE:
457                 irq_state = 1;
458
459                 chan->base->ucr1 |= EUartUCR1_RRDYEN;
460
461                 HAL_INTERRUPT_UNMASK(chan->isr_vector);
462                 break;
463         case __COMMCTL_IRQ_DISABLE:
464                 ret = irq_state;
465                 irq_state = 0;
466
467                 chan->base->ucr1 &= ~EUartUCR1_RRDYEN;
468
469                 HAL_INTERRUPT_MASK(chan->isr_vector);
470                 break;
471         case __COMMCTL_DBG_ISR_VECTOR:
472                 ret = chan->isr_vector;
473                 break;
474         case __COMMCTL_SET_TIMEOUT:
475                 ret = chan->msec_timeout;
476                 chan->msec_timeout = va_arg(ap, cyg_uint32);
477                 break;
478         default:
479                 break;
480         }
481         va_end(ap);
482         CYGARC_HAL_RESTORE_GP();
483         return ret;
484 }
485
486 static int cyg_hal_plf_serial_isr(void *__ch_data, int *__ctrlc,
487                                                                 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
488 {
489         int res = 0;
490         channel_data_t *chan = __ch_data;
491         char c;
492
493         CYGARC_HAL_SAVE_GP();
494
495         cyg_drv_interrupt_acknowledge(chan->isr_vector);
496
497         *__ctrlc = 0;
498         if (!(chan->base->uts & EUartUTS_RXEMPTY)) {
499                 c = (char)chan->base->urxd[0];
500
501                 if (cyg_hal_is_break(&c, 1))
502                         *__ctrlc = 1;
503
504                 res = CYG_ISR_HANDLED;
505         }
506
507         CYGARC_HAL_RESTORE_GP();
508         return res;
509 }
510
511 #define NUMOF(x) (sizeof(x) / sizeof(x[0]))
512
513 void cyg_hal_plf_serial_init(void)
514 {
515         hal_virtual_comm_table_t *comm;
516         int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
517         int i;
518         static int jjj = 0;
519
520         // Init channels
521         for (i = 0;      i < NUMOF(channels);  i++) {
522                 init_serial_channel(&channels[i]);
523                 CYGACC_CALL_IF_SET_CONSOLE_COMM(i + MXC_UART_CHAN_OFFSET);
524                 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
525                 CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[i]);
526                 CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
527                 CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
528                 CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
529                 CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
530                 CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
531                 CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
532                 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
533                 if (jjj == 0) {
534                         cyg_hal_plf_serial_putc(&channels[i], '+');
535                         jjj++;
536                 }
537         }
538
539         // Restore original console
540         CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
541 }
542
543 void cyg_hal_plf_serial_stop(void)
544 {
545         int i;
546
547         // Init channels
548         for (i = 0;      i < NUMOF(channels);  i++) {
549                 stop_serial_channel(&channels[i]);
550         }
551 }
552
553 //=============================================================================
554 // Compatibility with older stubs
555 //=============================================================================
556
557 #ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
558
559 #include <cyg/hal/hal_stub.h>                   // cyg_hal_gdb_interrupt
560
561 #define MXC_UART1_CHAN          (0 + MXC_UART_CHAN_OFFSET)
562 #define MXC_UART2_CHAN          (1 + MXC_UART_CHAN_OFFSET)
563 #define MXC_UART3_CHAN          (2 + MXC_UART_CHAN_OFFSET)
564 #define MXC_UART4_CHAN          (3 + MXC_UART_CHAN_OFFSET)
565 #define MXC_UART5_CHAN          (4 + MXC_UART_CHAN_OFFSET)
566 #define MXC_UART6_CHAN          (5 + MXC_UART_CHAN_OFFSET)
567
568 #undef __BASE
569
570 #if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == MXC_UART1_CHAN)
571 #define __BASE ((void*)UART1_BASE_ADDR)
572 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART1
573 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == MXC_UART2_CHAN)
574 #define __BASE ((void*)UART2_BASE_ADDR)
575 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART2
576 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == MXC_UART3_CHAN)
577 #define __BASE ((void*)UART3_BASE_ADDR)
578 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART3
579 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == MXC_UART4_CHAN)
580 #define __BASE ((void*)UART4_BASE_ADDR)
581 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART4
582 #elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == MXC_UART5_CHAN)
583 #define __BASE ((void*)UART5_BASE_ADDR)
584 #define CYGHWR_HAL_GDB_PORT_VECTOR CYGNUM_HAL_INTERRUPT_UART5
585 #endif
586
587 #ifdef __BASE
588
589 #ifdef CYGSEM_HAL_ROM_MONITOR
590 #define CYG_HAL_STARTUP_ROM
591 #define CYG_HAL_STARTUP_ROMRAM
592 #undef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
593 #endif
594
595 #if (defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)) && !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
596 #define HAL_DIAG_USES_HARDWARE
597 #elif !defined(CYGDBG_HAL_DIAG_TO_DEBUG_CHAN)
598 #define HAL_DIAG_USES_HARDWARE
599 #elif CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL != CYGNUM_HAL_VIRTUAL_VECTOR_DEBUG_CHANNEL
600 #define HAL_DIAG_USES_HARDWARE
601 #endif
602
603 static channel_data_t channel = {
604         __BASE, 0, CYGHWR_HAL_GDB_PORT_VECTOR
605 };
606
607 #ifdef HAL_DIAG_USES_HARDWARE
608
609 void hal_diag_init(void)
610 {
611         static int init = 0;
612         char *msg = "\n\rARM eCos\n\r";
613
614         if (init++) return;
615
616         init_serial_channel(&channel);
617
618         while (*msg) hal_diag_write_char(*msg++);
619 }
620
621 #ifdef DEBUG_DIAG
622 #ifndef CYG_HAL_STARTUP_ROM
623 #define DIAG_BUFSIZE 2048
624 static char diag_buffer[DIAG_BUFSIZE];
625 static int diag_bp = 0;
626 #endif
627 #endif
628
629 void hal_diag_write_char(char c)
630 {
631 #ifdef DEBUG_DIAG
632 #ifndef CYG_HAL_STARTUP_ROM
633         diag_buffer[diag_bp++] = c;
634         if (diag_bp == sizeof(diag_buffer)) diag_bp = 0;
635 #endif
636 #endif
637         cyg_hal_plf_serial_putc(&channel, c);
638 }
639
640 void hal_diag_read_char(char *c)
641 {
642         *c = cyg_hal_plf_serial_getc(&channel);
643 }
644
645 #else // not HAL_DIAG_USES_HARDWARE - it uses GDB protocol
646
647 void hal_diag_read_char(char *c)
648 {
649         *c = cyg_hal_plf_serial_getc(&channel);
650 }
651
652 void hal_diag_write_char(char c)
653 {
654         static char line[100];
655         static int pos = 0;
656
657         // FIXME: Some LED blinking might be nice right here.
658
659         // No need to send CRs
660         if (c == '\r') return;
661
662         line[pos++] = c;
663
664         if (c == '\n' || pos == sizeof(line)) {
665                 CYG_INTERRUPT_STATE old;
666
667                 // Disable interrupts. This prevents GDB trying to interrupt us
668                 // while we are in the middle of sending a packet. The serial
669                 // receive interrupt will be seen when we re-enable interrupts
670                 // later.
671 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
672                 CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
673 #else
674                 HAL_DISABLE_INTERRUPTS(old);
675 #endif
676                 while (1) {
677                         static char hex[] = "0123456789ABCDEF";
678                         cyg_uint8 csum = 0;
679                         int i;
680 #ifndef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
681                         char c1;
682 #endif
683                         cyg_hal_plf_serial_putc(&channel, '$');
684                         cyg_hal_plf_serial_putc(&channel, 'O');
685                         csum += 'O';
686                         for (i = 0; i < pos; i++) {
687                                 char ch = line[i];
688                                 char h = hex[(ch >> 4) & 0xF];
689                                 char l = hex[ch & 0xF];
690                                 cyg_hal_plf_serial_putc(&channel, h);
691                                 cyg_hal_plf_serial_putc(&channel, l);
692                                 csum += h;
693                                 csum += l;
694                         }
695                         cyg_hal_plf_serial_putc(&channel, '#');
696                         cyg_hal_plf_serial_putc(&channel, hex[(csum >> 4) & 0xF]);
697                         cyg_hal_plf_serial_putc(&channel, hex[csum & 0xF]);
698
699 #ifdef CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
700
701                         break; // regardless
702
703 #else // not CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT Ie. usually...
704
705                         // Wait for the ACK character '+' from GDB here and handle
706                         // receiving a ^C instead.  This is the reason for this clause
707                         // being a loop.
708                         c1 = cyg_hal_plf_serial_getc(&channel);
709
710                         if (c1 == '+')
711                                 break;                          // a good acknowledge
712
713 #ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
714                         cyg_drv_interrupt_acknowledge(CYGHWR_HAL_GDB_PORT_VECTOR);
715                         if (c1 == '\003') {
716                                 // Ctrl-C: breakpoint.
717                                 cyg_hal_gdb_interrupt((target_register_t)__builtin_return_address(0));
718                                 break;
719                         }
720 #endif // CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
721
722 #endif // ! CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT
723                         // otherwise, loop round again
724                 }
725
726                 pos = 0;
727
728                 // And re-enable interrupts
729 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
730                 CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
731 #else
732                 HAL_RESTORE_INTERRUPTS(old);
733 #endif
734         }
735 }
736 #endif
737
738 #endif // __BASE
739
740 #endif // !CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
741
742 /*---------------------------------------------------------------------------*/
743 /* End of hal_diag.c */