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