]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx21/var/v2_0/src/soc_misc.c
Initial revision
[karo-tx-redboot.git] / packages / hal / arm / mx21 / var / v2_0 / src / soc_misc.c
1 //==========================================================================
2 //
3 //      soc_misc.c
4 //
5 //      HAL misc board support 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 <redboot.h>
43 #include <pkgconf/hal.h>
44 #include <pkgconf/system.h>
45 #include CYGBLD_HAL_PLATFORM_H
46
47 #include <cyg/infra/cyg_type.h>         // base types
48 #include <cyg/infra/cyg_trac.h>         // tracing macros
49 #include <cyg/infra/cyg_ass.h>          // assertion macros
50
51 #include <cyg/hal/hal_misc.h>           // Size constants
52 #include <cyg/hal/hal_io.h>             // IO macros
53 #include <cyg/hal/hal_arch.h>           // Register state info
54 #include <cyg/hal/hal_diag.h>
55 #include <cyg/hal/hal_intr.h>           // Interrupt names
56 #include <cyg/hal/hal_cache.h>          // Cache control
57 #include <cyg/hal/hal_soc.h>         // Hardware definitions
58 #include <cyg/hal/hal_mm.h>             // MMap table definitions
59
60 #include <cyg/infra/diag.h>             // diag_printf
61
62 // Most initialization has already been done before we get here.
63 // All we do here is set up the interrupt environment.
64
65 unsigned int system_rev;
66 externC void plf_hardware_init(void);
67
68 char HAL_PLATFORM_EXTRA[20] = "PASS x.x [x32 SDR]";
69
70 void hal_hardware_init(void)
71 {
72     volatile unsigned int temp;
73     volatile unsigned int esdctl0 = readl(ESDCTL_BASE);
74     
75     system_rev = readl(MX21_SI_ID_REG);
76
77     if (system_rev == MX21_SILICONID_Rev2_x) {
78         HAL_PLATFORM_EXTRA[5] = '2';
79         HAL_PLATFORM_EXTRA[7] = 'x';
80     } else if (system_rev == MX21_SILICONID_Rev3_0) {
81         HAL_PLATFORM_EXTRA[5] = '3';
82         HAL_PLATFORM_EXTRA[7] = '0';
83     } else if (system_rev == MX21_SILICONID_Rev3_1) {
84         HAL_PLATFORM_EXTRA[5] = '3';
85         HAL_PLATFORM_EXTRA[7] = '1';
86     }
87
88     if ((esdctl0 & 0x20000) == 0x0) {
89             HAL_PLATFORM_EXTRA[11] = '1';
90             HAL_PLATFORM_EXTRA[12] = '6';
91     }
92
93     // Mask all interrupts
94     writel(0xFFFFFFFF, MX21_AITC_NIMASK);
95
96     // Make all interrupts do IRQ and not FIQ
97     // FIXME: Change this if you use FIQs.
98     writel(0, MX21_AITC_INTTYPEH);
99     writel(0, MX21_AITC_INTTYPEL);
100
101     // Disable all GPIO interrupt sources
102     
103     // Enable caches
104     HAL_ICACHE_ENABLE();
105     HAL_DCACHE_ENABLE();
106
107     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
108         // increase the WDOG timeout value to the max
109         writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
110     }
111
112     // Perform any platform specific initializations
113     plf_hardware_init();
114
115     // Set up eCos/ROM interfaces
116     hal_if_init();
117
118     //init timer2 and start it -- assuming that per clock 1 runs at 44MHz)
119
120
121     writel(0x4, MX21_Timer2_BASE + KHwTimerTCL); // counter reset when timer is disabled
122     writel(0x0, MX21_Timer2_BASE + KHwTimerTCL); // disable timer
123         
124     writel(0x00008000, MX21_Timer2_BASE + KHwTimerTCL); // reset timer
125     while((readl(MX21_Timer2_BASE + KHwTimerTCL) & 0x8000) != 0); // make sure reset complete
126     
127     writel(0x0, MX21_Timer2_BASE + KHwTimerTCL); // disable timer
128     writel(DelayTimerPresVal, MX21_Timer2_BASE + KHwTimerTPRER);
129     temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
130     writel(temp & (~0x00000100), MX21_Timer2_BASE + KHwTimerTCL); // restart mode
131     temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
132     writel(temp | 0x00000002, MX21_Timer2_BASE + KHwTimerTCL); // PERCLK1 to prescaler
133     temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
134     writel(temp | 0x00000001, MX21_Timer2_BASE + KHwTimerTCL); //enable timer
135
136     hal_delay_us(MX_STARTUP_DELAY);
137
138     //Reset ethernet here
139     BitSetEIO(EIO_RESET_BASE);
140     hal_delay_us(10000);
141     BitClearEIO(EIO_RESET_BASE);
142     hal_delay_us(100000);
143     readb(BOARD_CS_UART_BASE + 1);
144     hal_delay_us(100000);
145
146     if (system_rev == MX21_SILICONID_Rev2_x) {
147             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR2);
148             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR3);
149             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR4);
150             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR5);
151             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR6);
152             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR7);
153             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR8);
154             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR10);
155             writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR11);
156             writel(0x7FC07FF8, MX21_DSCR_BASE + DSCR9);
157         }
158 }
159
160 // -------------------------------------------------------------------------
161 void hal_clock_initialize(cyg_uint32 period)
162 {
163 }
164
165 // This routine is called during a clock interrupt.
166
167 // Define this if you want to ensure that the clock is perfect (i.e. does
168 // not drift).  One reason to leave it turned off is that it costs some
169 // us per system clock interrupt for this maintenance.
170 #undef COMPENSATE_FOR_CLOCK_DRIFT
171
172 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
173 {
174 }
175
176 // Read the current value of the clock, returning the number of hardware
177 // "ticks" that have occurred (i.e. how far away the current value is from
178 // the start)
179
180 // Note: The "contract" for this function is that the value is the number
181 // of hardware clocks that have happened since the last interrupt (i.e.
182 // when it was reset).  This value is used to measure interrupt latencies.
183 // However, since the hardware counter runs freely, this routine computes
184 // the difference between the current clock period and the number of hardware
185 // ticks left before the next timer interrupt.
186 void hal_clock_read(cyg_uint32 *pvalue)
187 {
188 }
189
190 // This is to cope with the test read used by tm_basic with
191 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
192 // in the ISR, *before* resetting the clock.  Which returns 1tick +
193 // latency if we just use plain hal_clock_read().
194 void hal_clock_latency(cyg_uint32 *pvalue)
195 {
196 }
197
198 unsigned int hal_timer_count(void)
199 {
200     return readl(HAL_DELAY_TIMER_MX2 + KHwTimerTCN);
201 }
202
203 #define WDT_MAGIC_1             0x5555
204 #define WDT_MAGIC_2             0xAAAA
205 #define MXC_WDT_WSR             0x2
206
207 static unsigned int led_on = 0;
208 //
209 // Delay for some number of micro-seconds
210 //
211 void hal_delay_us(unsigned int usecs)
212 {
213     volatile unsigned long timerCount, timerCompare, tmp;
214     const unsigned long TIMERMAXCOUNT = 0xFFFFFFFF;
215     unsigned long delayCount = usecs * ((MX21_PERCLK1/(DelayTimerPresVal+1))/1000000);
216  //diag_printf("entering mx2 hal_delay_us: %d, delaycount = %d, system_rev = %d\n\n", usecs, delayCount, system_rev);
217
218     if (delayCount == 0) {
219         return;
220     }
221
222     // issue the service sequence instructions
223     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
224         writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
225         writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
226     }
227
228     writel(0x03, HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT); // clear the compare status bit
229     timerCount = readl(HAL_DELAY_TIMER_MX2 + KHwTimerTCN);
230    
231     
232     tmp = TIMERMAXCOUNT - timerCount;
233
234     if (tmp < delayCount) {
235         timerCompare = delayCount - tmp;
236     } else {
237         timerCompare = delayCount + timerCount;
238     }
239     writel(timerCompare, HAL_DELAY_TIMER_MX2 + KHwTimerTCMP);  // setup compare reg
240
241     while ( (0x1 & readl(HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT)) == 0 ); // return until compare bit is set
242     writel(0x03, HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT); // clear the compare status bit
243
244     if ((++led_on % 2000) == 0)
245         BOARD_DEBUG_LED(0);
246 }
247
248 // -------------------------------------------------------------------------
249
250 // This routine is called to respond to a hardware interrupt (IRQ).  It
251 // should interrogate the hardware and return the IRQ vector number.
252 int hal_IRQ_handler(void)
253 {
254 #ifdef HAL_EXTENDED_IRQ_HANDLER
255     cyg_uint32 index;
256
257     // Use platform specific IRQ handler, if defined
258     // Note: this macro should do a 'return' with the appropriate
259     // interrupt number if such an extended interrupt exists.  The
260     // assumption is that the line after the macro starts 'normal' processing.
261     HAL_EXTENDED_IRQ_HANDLER(index);
262 #endif
263
264     return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
265 }
266
267 //
268 // Interrupt control
269
270 void hal_interrupt_mask(int vector)
271 {
272 //    diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
273 #ifdef HAL_EXTENDED_INTERRUPT_MASK
274     // Use platform specific handling, if defined
275     // Note: this macro should do a 'return' for "extended" values of 'vector'
276     // Normal vectors are handled by code subsequent to the macro call.
277     HAL_EXTENDED_INTERRUPT_MASK(vector);
278 #endif
279 }
280
281 void hal_interrupt_unmask(int vector)
282 {
283 //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
284
285 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
286     // Use platform specific handling, if defined
287     // Note: this macro should do a 'return' for "extended" values of 'vector'
288     // Normal vectors are handled by code subsequent to the macro call.
289     HAL_EXTENDED_INTERRUPT_UNMASK(vector);
290 #endif
291 }
292
293 void hal_interrupt_acknowledge(int vector)
294 {
295
296 //    diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
297 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
298     // Use platform specific handling, if defined
299     // Note: this macro should do a 'return' for "extended" values of 'vector'
300     // Normal vectors are handled by code subsequent to the macro call.
301     HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
302 #endif
303 }
304
305 void hal_interrupt_configure(int vector, int level, int up)
306 {
307
308 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
309     // Use platform specific handling, if defined
310     // Note: this macro should do a 'return' for "extended" values of 'vector'
311     // Normal vectors are handled by code subsequent to the macro call.
312     HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
313 #endif
314 }
315
316 void hal_interrupt_set_level(int vector, int level)
317 {
318
319 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
320     // Use platform specific handling, if defined
321     // Note: this macro should do a 'return' for "extended" values of 'vector'
322     // Normal vectors are handled by code subsequent to the macro call.
323     HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
324 #endif
325
326     // Interrupt priorities are not configurable.
327 }
328
329 /*------------------------------------------------------------------------*/
330