]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/hal/arm/xscale/ixp425/v2_0/src/ixp425_diag.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / xscale / ixp425 / v2_0 / src / ixp425_diag.c
1 /*=============================================================================
2 //
3 //      ixp425_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, 2003 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 //#####DESCRIPTIONBEGIN####
42 //
43 // Author(s):   msalter
44 // Contributors:msalter
45 // Date:        2002-12-08
46 // Purpose:     HAL diagnostic output
47 // Description: Implementations of HAL diagnostic output support.
48 //
49 //####DESCRIPTIONEND####
50 //
51 //===========================================================================*/
52
53 #include <pkgconf/hal.h>
54 #include CYGBLD_HAL_VARIANT_H           // Variant specific configuration
55 #include CYGBLD_HAL_PLATFORM_H          // Platform specific configuration
56
57 #include <cyg/infra/cyg_type.h>         // base types
58 #include <cyg/infra/cyg_trac.h>         // tracing macros
59 #include <cyg/infra/cyg_ass.h>          // assertion macros
60
61 #include <cyg/hal/hal_arch.h>           // basic machine info
62 #include <cyg/hal/hal_intr.h>           // interrupt macros
63 #include <cyg/hal/hal_io.h>             // IO macros
64 #include <cyg/hal/hal_diag.h>
65 #include <cyg/hal/drv_api.h>
66 #include <cyg/hal/hal_if.h>             // interface API
67 #include <cyg/hal/hal_misc.h>           // Helper functions
68
69 #if !defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && !defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
70 #define IXP425_NUM_UARTS 0
71 #elif defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
72 #define IXP425_NUM_UARTS 2
73 #else
74 #define IXP425_NUM_UARTS 1
75 #endif
76
77 #if IXP425_NUM_UARTS > 0
78
79 /*---------------------------------------------------------------------------*/
80 /* 16550 compatible UARTS */
81
82 // Define the serial registers.
83 #define CYG_DEV_RBR   0x00 // receiver buffer register, read, dlab = 0
84 #define CYG_DEV_THR   0x00 // transmitter holding register, write, dlab = 0
85 #define CYG_DEV_DLL   0x00 // divisor latch (LS), read/write, dlab = 1
86 #define CYG_DEV_IER   0x01 // interrupt enable register, read/write, dlab = 0
87 #define CYG_DEV_DLM   0x01 // divisor latch (MS), read/write, dlab = 1
88 #define CYG_DEV_IIR   0x02 // interrupt identification register, read, dlab = 0
89 #define CYG_DEV_FCR   0x02 // fifo control register, write, dlab = 0
90 #define CYG_DEV_LCR   0x03 // line control register, write
91 #define CYG_DEV_MCR   0x04 // modem control register, write
92 #define CYG_DEV_LSR   0x05 // line status register, read
93 #define CYG_DEV_MSR   0x06 // modem status register, read
94 #define CYG_DEV_SCR   0x07 // scratch pad register
95
96 // Interrupt Enable Register
97 #define SIO_IER_RCV 0x01
98 #define SIO_IER_XMT 0x02
99 #define SIO_IER_LS  0x04
100 #define SIO_IER_MS  0x08
101 #define SIO_IER_UUE 0x40  // UART Unit Enable
102
103 // The line status register bits.
104 #define SIO_LSR_DR      0x01            // data ready
105 #define SIO_LSR_OE      0x02            // overrun error
106 #define SIO_LSR_PE      0x04            // parity error
107 #define SIO_LSR_FE      0x08            // framing error
108 #define SIO_LSR_BI      0x10            // break interrupt
109 #define SIO_LSR_THRE    0x20            // transmitter holding register empty
110 #define SIO_LSR_TEMT    0x40            // transmitter register empty
111 #define SIO_LSR_ERR     0x80            // any error condition
112
113 // The modem status register bits.
114 #define SIO_MSR_DCTS  0x01              // delta clear to send
115 #define SIO_MSR_DDSR  0x02              // delta data set ready
116 #define SIO_MSR_TERI  0x04              // trailing edge ring indicator
117 #define SIO_MSR_DDCD  0x08              // delta data carrier detect
118 #define SIO_MSR_CTS   0x10              // clear to send
119 #define SIO_MSR_DSR   0x20              // data set ready
120 #define SIO_MSR_RI    0x40              // ring indicator
121 #define SIO_MSR_DCD   0x80              // data carrier detect
122
123 // The line control register bits.
124 #define SIO_LCR_WLS0   0x01             // word length select bit 0
125 #define SIO_LCR_WLS1   0x02             // word length select bit 1
126 #define SIO_LCR_STB    0x04             // number of stop bits
127 #define SIO_LCR_PEN    0x08             // parity enable
128 #define SIO_LCR_EPS    0x10             // even parity select
129 #define SIO_LCR_SP     0x20             // stick parity
130 #define SIO_LCR_SB     0x40             // set break
131 #define SIO_LCR_DLAB   0x80             // divisor latch access bit
132
133 // Modem Control Register
134 #define SIO_MCR_DTR    0x01
135 #define SIO_MCR_RTS    0x02
136 #define SIO_MCR_OUT1   0x04
137 #define SIO_MCR_OUT2   0x08
138 #define SIO_MCR_LOOP   0x10
139 #define SIO_MCR_AFE    0x20
140
141 #define UART1_BASE      0xC8000000 
142 #define UART2_BASE      0xC8001000
143
144 //-----------------------------------------------------------------------------
145 typedef struct {
146     cyg_uint32* base;
147     cyg_int32 msec_timeout;
148     int isr_vector;
149     cyg_int32 baud_rate;
150 } channel_data_t;
151
152
153 //-----------------------------------------------------------------------------
154 // Based on 14.7456 MHz xtal
155 static int
156 set_baud( channel_data_t *chan )
157 {
158     cyg_uint32* base = chan->base;
159     cyg_uint16 div = 921600 / chan->baud_rate;
160     cyg_uint32 lcr;
161
162     HAL_READ_UINT32(base+CYG_DEV_LCR, lcr);
163     HAL_WRITE_UINT32(base+CYG_DEV_LCR, lcr|SIO_LCR_DLAB);
164     HAL_WRITE_UINT32(base+CYG_DEV_DLL, div & 0xff);
165     HAL_WRITE_UINT32(base+CYG_DEV_DLM, (div >> 8) & 0xff);
166     HAL_WRITE_UINT32(base+CYG_DEV_LCR, lcr);
167     return 1;
168 }
169
170 static void
171 cyg_hal_plf_serial_init_channel(void* __ch_data)
172 {
173     cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
174     channel_data_t* chan = (channel_data_t*)__ch_data;
175     
176     HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_UUE);
177
178     // 8-1-no parity.
179     HAL_WRITE_UINT32(base+CYG_DEV_LCR, SIO_LCR_WLS0 | SIO_LCR_WLS1);
180     chan->baud_rate = CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL_BAUD;
181     set_baud( chan );
182     HAL_WRITE_UINT32(base+CYG_DEV_FCR, 0x07);  // Enable & clear FIFO
183     HAL_WRITE_UINT32(base+CYG_DEV_MCR, SIO_MCR_OUT2);  // Enable interrupt to core
184 }
185
186 void
187 cyg_hal_plf_serial_putc(void *__ch_data, char c)
188 {
189     cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
190     cyg_uint32 lsr, val;
191     CYGARC_HAL_SAVE_GP();
192
193     do {
194        HAL_READ_UINT32(base+CYG_DEV_LSR, lsr);
195     } while ((lsr & SIO_LSR_THRE) == 0);
196     
197     val = c;
198     HAL_WRITE_UINT32(base+CYG_DEV_THR, val);
199
200     CYGARC_HAL_RESTORE_GP();
201 }
202
203 static cyg_bool
204 cyg_hal_plf_serial_getc_nonblock(void* __ch_data, cyg_uint8* ch)
205 {
206     cyg_uint32* base = ((channel_data_t*)__ch_data)->base;
207     cyg_uint32 lsr, val;
208
209     HAL_READ_UINT32(base+CYG_DEV_LSR, lsr);
210     if ((lsr & SIO_LSR_DR) == 0)
211         return false;
212
213     HAL_READ_UINT32(base+CYG_DEV_RBR, val);
214     *ch = val;
215
216     return true;
217 }
218
219 cyg_uint8
220 cyg_hal_plf_serial_getc(void* __ch_data)
221 {
222     cyg_uint8 ch;
223     CYGARC_HAL_SAVE_GP();
224
225     while(!cyg_hal_plf_serial_getc_nonblock(__ch_data, &ch));
226
227     CYGARC_HAL_RESTORE_GP();
228     return ch;
229 }
230
231 static channel_data_t plf_ser_channels[] = {
232 #if defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && !defined(HAL_PLATFORM_UART2_FIRST)
233     { (cyg_uint32*)UART1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1 },
234 #endif
235 #if defined(CYGSEM_HAL_IXP425_PLF_USES_UART2)
236     { (cyg_uint32*)UART2_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART2 }
237 #endif
238 #if defined(CYGSEM_HAL_IXP425_PLF_USES_UART1) && defined(HAL_PLATFORM_UART2_FIRST)
239     { (cyg_uint32*)UART1_BASE, 1000, CYGNUM_HAL_INTERRUPT_UART1 },
240 #endif
241 };
242
243 static void
244 cyg_hal_plf_serial_write(void* __ch_data, const cyg_uint8* __buf, 
245                          cyg_uint32 __len)
246 {
247     CYGARC_HAL_SAVE_GP();
248
249     while(__len-- > 0)
250         cyg_hal_plf_serial_putc(__ch_data, *__buf++);
251
252     CYGARC_HAL_RESTORE_GP();
253 }
254
255 static void
256 cyg_hal_plf_serial_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
257 {
258     CYGARC_HAL_SAVE_GP();
259
260     while(__len-- > 0)
261         *__buf++ = cyg_hal_plf_serial_getc(__ch_data);
262
263     CYGARC_HAL_RESTORE_GP();
264 }
265
266 cyg_bool
267 cyg_hal_plf_serial_getc_timeout(void* __ch_data, cyg_uint8* ch)
268 {
269     int delay_count;
270     channel_data_t* chan = (channel_data_t*)__ch_data;
271     cyg_bool res;
272     CYGARC_HAL_SAVE_GP();
273
274     delay_count = chan->msec_timeout * 10; // delay in .1 ms steps
275
276     for(;;) {
277         res = cyg_hal_plf_serial_getc_nonblock(__ch_data, ch);
278         if (res || 0 == delay_count--)
279             break;
280         
281         CYGACC_CALL_IF_DELAY_US(100);
282     }
283
284     CYGARC_HAL_RESTORE_GP();
285     return res;
286 }
287
288 static int
289 cyg_hal_plf_serial_control(void *__ch_data, __comm_control_cmd_t __func, ...)
290 {
291     static int irq_state = 0;
292     channel_data_t* chan = (channel_data_t*)__ch_data;
293     int ret = 0;
294     CYGARC_HAL_SAVE_GP();
295
296     switch (__func) {
297     case __COMMCTL_IRQ_ENABLE:
298         irq_state = 1;
299
300         HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_RCV | SIO_IER_UUE);
301         HAL_INTERRUPT_UNMASK(chan->isr_vector);
302         break;
303     case __COMMCTL_IRQ_DISABLE:
304         ret = irq_state;
305         irq_state = 0;
306
307         HAL_WRITE_UINT32(chan->base+CYG_DEV_IER, SIO_IER_UUE);
308         HAL_INTERRUPT_MASK(chan->isr_vector);
309         break;
310     case __COMMCTL_DBG_ISR_VECTOR:
311         ret = chan->isr_vector;
312         break;
313     case __COMMCTL_SET_TIMEOUT:
314     {
315         va_list ap;
316
317         va_start(ap, __func);
318
319         ret = chan->msec_timeout;
320         chan->msec_timeout = va_arg(ap, cyg_uint32);
321
322         va_end(ap);
323     }        
324     case __COMMCTL_GETBAUD:
325         ret = chan->baud_rate;
326         break;
327     case __COMMCTL_SETBAUD:
328     {
329         cyg_uint32 b;
330         va_list ap;
331
332         va_start(ap, __func);
333         b = va_arg(ap, cyg_int32);
334         va_end(ap);
335
336         if (b < 300 || b > 115200)
337             ret = -1;
338         else {
339             chan->baud_rate = b;
340             ret = set_baud(chan);
341         }
342         break;
343     }
344     default:
345         break;
346     }
347     CYGARC_HAL_RESTORE_GP();
348     return ret;
349 }
350
351 static int
352 cyg_hal_plf_serial_isr(void *__ch_data, int* __ctrlc, 
353                        CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
354 {
355     int res = 0;
356     channel_data_t* chan = (channel_data_t*)__ch_data;
357     char c;
358     cyg_uint8 lsr;
359     CYGARC_HAL_SAVE_GP();
360
361     cyg_drv_interrupt_acknowledge(chan->isr_vector);
362
363     *__ctrlc = 0;
364     HAL_READ_UINT32(chan->base+CYG_DEV_LSR, lsr);
365     if ( (lsr & SIO_LSR_DR) != 0 ) {
366
367         HAL_READ_UINT32(chan->base+CYG_DEV_RBR, c);
368         if( cyg_hal_is_break( &c , 1 ) )
369             *__ctrlc = 1;
370
371         res = CYG_ISR_HANDLED;
372     }
373
374     CYGARC_HAL_RESTORE_GP();
375     return res;
376 }
377
378 void
379 cyg_hal_ixp425_serial_init(void)
380 {
381     hal_virtual_comm_table_t* comm;
382     int i, cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
383
384     for (i = 0; i < IXP425_NUM_UARTS; i++) {
385
386         // Disable interrupts.
387         HAL_INTERRUPT_MASK(plf_ser_channels[i].isr_vector);
388
389         // Init channels
390         cyg_hal_plf_serial_init_channel(&plf_ser_channels[i]);
391
392         // Setup procs in the vector table
393         CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
394         comm = CYGACC_CALL_IF_CONSOLE_PROCS();
395         CYGACC_COMM_IF_CH_DATA_SET(*comm, &plf_ser_channels[i]);
396         CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
397         CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
398         CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
399         CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
400         CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
401         CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
402         CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
403     }
404     // Restore original console
405     CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
406 }
407
408 // If the platform provides some channels of its own, then this function will be
409 // provided by that platform.
410 #if !defined(CYGNUM_HAL_IXP425_PLF_SERIAL_CHANNELS) || !CYGNUM_HAL_IXP425_PLF_SERIAL_CHANNELS 
411 void
412 cyg_hal_plf_comms_init(void)
413 {
414     static int initialized = 0;
415
416     if (initialized)
417         return;
418
419     initialized = 1;
420
421     cyg_hal_ixp425_serial_init();
422 }
423 #endif
424
425 #endif // IXP425_NUM_UARTS > 0
426
427 /*---------------------------------------------------------------------------*/
428
429 void
430 hal_diag_led(int n)
431 {
432 }
433
434 /*---------------------------------------------------------------------------*/
435 /* End of hal_diag.c */