unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mxc91321 / 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 // FIXME: some of the stuff in hal_platform_setup could be moved here.
65
66 externC void plf_hardware_init(void);
67
68 #define IIM_PROD_REV_SH         3
69 #define IIM_PROD_REV_LEN        5
70 #define IIM_SREV_REV_SH         4
71 #define IIM_SREV_REV_LEN        4
72 #define PROD_SIGNATURE_MX31     0x1
73 #define PROD_SIGNATURE_MXC91321 0x6
74
75 #if defined(CYGPKG_HAL_ARM_MXC91321_CHIP)
76 #define PROD_SIGNATURE_SUPPORTED  PROD_SIGNATURE_MXC91321
77 #else
78 #error MXC91321 not defined. What is it?
79 #endif
80 #define CHIP_VERSION_NONE           0xFFFFFFFF      // invalid product ID
81 #define CHIP_VERSION_UNKNOWN        0xDEADBEEF      // invalid chip rev
82
83 #define PART_NUMBER_OFFSET    (12)
84 #define MAJOR_NUMBER_OFFSET    (4)
85 #define MINOR_NUMBER_OFFSET    (0)
86
87 unsigned int system_rev = CHIP_REV_1_0;
88 static int find_correct_chip;
89
90 /*
91  * This functions reads the IIM module and returns the system revision number.
92  * It returns the IIM silicon revision reg value if valid product rev is found.
93  . Otherwise, it returns -1.
94  */
95 static int read_system_rev(void)
96 {
97     int val;
98
99     val = readl(IIM_BASE_ADDR + IIM_PREV_OFF);
100
101     /* If the IIM doesn't contain valid product signature, return
102      * the lowest revision number */
103     if (MXC_GET_FIELD(val, IIM_PROD_REV_LEN, IIM_PROD_REV_SH) !=
104         PROD_SIGNATURE_SUPPORTED) {
105         return CHIP_VERSION_NONE;
106     } else {
107         system_rev = 0x91321 << PART_NUMBER_OFFSET;
108     }
109
110     /* Now trying to retrieve the silicon rev from IIM's SREV register */
111     return readl(IIM_BASE_ADDR + IIM_SREV_OFF);
112 }
113
114 char HAL_PLATFORM_EXTRA[25] = "PASS 1.0.0 [x32 DDR]";
115
116 void hal_hardware_init(void)
117 {
118     volatile unsigned int esdmisc = readl(ESDCTL_BASE + 0x10);
119     volatile unsigned int esdctl0 = readl(ESDCTL_BASE);
120     int ver = read_system_rev();
121
122     find_correct_chip = ver;
123
124     if (ver != CHIP_VERSION_NONE) {
125         switch (ver & 0xFF) {
126         case 0x0:
127             HAL_PLATFORM_EXTRA[5] = '1';
128             HAL_PLATFORM_EXTRA[7] = '0';
129             system_rev |= 1 << MAJOR_NUMBER_OFFSET;
130             system_rev |= 0 << MINOR_NUMBER_OFFSET;
131             break;
132         case 0x11:
133             HAL_PLATFORM_EXTRA[5] = '1';
134             HAL_PLATFORM_EXTRA[7] = '1';
135             system_rev |= 1 << MAJOR_NUMBER_OFFSET;
136             system_rev |= 1 << MINOR_NUMBER_OFFSET;
137             break;
138         case 0x20:
139         case 0x22:
140             HAL_PLATFORM_EXTRA[5] = '1';
141             HAL_PLATFORM_EXTRA[7] = '2';
142             system_rev |= 1 << MAJOR_NUMBER_OFFSET;
143             system_rev |= 2 << MINOR_NUMBER_OFFSET;
144             break;
145         case 0x24:
146             HAL_PLATFORM_EXTRA[5] = '1';
147             HAL_PLATFORM_EXTRA[7] = '2';
148             HAL_PLATFORM_EXTRA[9] = '2';
149             system_rev |= 1 << MAJOR_NUMBER_OFFSET;
150             system_rev |= 2 << MINOR_NUMBER_OFFSET;
151             break;
152         case 0x50:
153             HAL_PLATFORM_EXTRA[5] = '2';
154             HAL_PLATFORM_EXTRA[7] = '3';
155             system_rev |= 2 << MAJOR_NUMBER_OFFSET;
156             system_rev |= 3 << MINOR_NUMBER_OFFSET;
157             break;
158         case 0x52:
159             HAL_PLATFORM_EXTRA[5] = '2';
160             HAL_PLATFORM_EXTRA[7] = '3';
161             HAL_PLATFORM_EXTRA[9] = '2';
162             system_rev |= 2 << MAJOR_NUMBER_OFFSET;
163             system_rev |= 3 << MINOR_NUMBER_OFFSET;
164             break;
165         default:
166             HAL_PLATFORM_EXTRA[5] = 'x';
167             HAL_PLATFORM_EXTRA[7] = 'x';
168             HAL_PLATFORM_EXTRA[9] = 'x';
169             system_rev |= 1 << MAJOR_NUMBER_OFFSET;
170             system_rev |= 2 << MINOR_NUMBER_OFFSET;
171             find_correct_chip = CHIP_VERSION_UNKNOWN;
172             break;
173         }
174     }
175
176     if ((esdmisc & 0x4) == 0) {
177         HAL_PLATFORM_EXTRA[16] = 'S';
178     }
179     if ((esdctl0 & 0x30000) != 0x20000) {
180         HAL_PLATFORM_EXTRA[13] = '1';
181         HAL_PLATFORM_EXTRA[14] = '6';
182     }
183
184     // Mask all interrupts
185     writel(0xFFFFFFFF, AVIC_NIMASK);
186
187     // Make all interrupts do IRQ and not FIQ
188     // FIXME: Change this if you use FIQs.
189     writel(0, AVIC_INTTYPEH);
190     writel(0, AVIC_INTTYPEL);
191
192     // Enable caches
193     HAL_ICACHE_ENABLE();
194     HAL_DCACHE_ENABLE();
195
196     // enable EPIT and start it with 32KHz input clock
197     writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
198
199     // make sure reset is complete
200     while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
201     }
202
203     writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
204     writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
205
206     writel(0, EPIT_BASE_ADDR + EPITCMPR);  // always compare with 0
207
208     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
209         // increase the WDOG timeout value to the max
210         writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
211     }
212
213     // Perform any platform specific initializations
214     plf_hardware_init();
215
216     // Set up eCos/ROM interfaces
217     hal_if_init();
218 }
219
220 // -------------------------------------------------------------------------
221 void hal_clock_initialize(cyg_uint32 period)
222 {
223 }
224
225 // This routine is called during a clock interrupt.
226
227 // Define this if you want to ensure that the clock is perfect (i.e. does
228 // not drift).  One reason to leave it turned off is that it costs some
229 // us per system clock interrupt for this maintenance.
230 #undef COMPENSATE_FOR_CLOCK_DRIFT
231
232 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
233 {
234 }
235
236 // Read the current value of the clock, returning the number of hardware
237 // "ticks" that have occurred (i.e. how far away the current value is from
238 // the start)
239
240 // Note: The "contract" for this function is that the value is the number
241 // of hardware clocks that have happened since the last interrupt (i.e.
242 // when it was reset).  This value is used to measure interrupt latencies.
243 // However, since the hardware counter runs freely, this routine computes
244 // the difference between the current clock period and the number of hardware
245 // ticks left before the next timer interrupt.
246 void hal_clock_read(cyg_uint32 *pvalue)
247 {
248 }
249
250 // This is to cope with the test read used by tm_basic with
251 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
252 // in the ISR, *before* resetting the clock.  Which returns 1tick +
253 // latency if we just use plain hal_clock_read().
254 void hal_clock_latency(cyg_uint32 *pvalue)
255 {
256 }
257
258 unsigned int hal_timer_count(void)
259 {
260     return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
261 }
262
263 #define WDT_MAGIC_1             0x5555
264 #define WDT_MAGIC_2             0xAAAA
265 #define MXC_WDT_WSR             0x2
266
267 static unsigned int led_on = 0;
268 //
269 // Delay for some number of micro-seconds
270 //
271 void hal_delay_us(unsigned int usecs)
272 {
273     /*
274      * This causes overflow.
275      * unsigned int delayCount = (usecs * 32768) / 1000000;
276      * So use the following one instead
277      */
278     unsigned int delayCount = (usecs * 512) / 15625;
279
280     if (delayCount == 0) {
281         return;
282     }
283
284     // issue the service sequence instructions
285     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
286         writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
287         writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
288     }
289
290     writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
291
292     writel(delayCount, EPIT_BASE_ADDR + EPITLR);
293
294     while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
295     if ((++led_on % 2000) == 0)
296         BOARD_DEBUG_LED(0);
297 }
298
299 // -------------------------------------------------------------------------
300
301 // This routine is called to respond to a hardware interrupt (IRQ).  It
302 // should interrogate the hardware and return the IRQ vector number.
303 int hal_IRQ_handler(void)
304 {
305 #ifdef HAL_EXTENDED_IRQ_HANDLER
306     cyg_uint32 index;
307
308     // Use platform specific IRQ handler, if defined
309     // Note: this macro should do a 'return' with the appropriate
310     // interrupt number if such an extended interrupt exists.  The
311     // assumption is that the line after the macro starts 'normal' processing.
312     HAL_EXTENDED_IRQ_HANDLER(index);
313 #endif
314
315     return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
316 }
317
318 //
319 // Interrupt control
320 //
321
322 void hal_interrupt_mask(int vector)
323 {
324 //        diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
325 #ifdef HAL_EXTENDED_INTERRUPT_MASK
326     // Use platform specific handling, if defined
327     // Note: this macro should do a 'return' for "extended" values of 'vector'
328     // Normal vectors are handled by code subsequent to the macro call.
329     HAL_EXTENDED_INTERRUPT_MASK(vector);
330 #endif
331 }
332
333 void hal_interrupt_unmask(int vector)
334 {
335 //        diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
336
337 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
338     // Use platform specific handling, if defined
339     // Note: this macro should do a 'return' for "extended" values of 'vector'
340     // Normal vectors are handled by code subsequent to the macro call.
341     HAL_EXTENDED_INTERRUPT_UNMASK(vector);
342 #endif
343 }
344
345 void hal_interrupt_acknowledge(int vector)
346 {
347
348 //        diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
349 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
350     // Use platform specific handling, if defined
351     // Note: this macro should do a 'return' for "extended" values of 'vector'
352     // Normal vectors are handled by code subsequent to the macro call.
353     HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
354 #endif
355 }
356
357 void hal_interrupt_configure(int vector, int level, int up)
358 {
359
360 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
361     // Use platform specific handling, if defined
362     // Note: this macro should do a 'return' for "extended" values of 'vector'
363     // Normal vectors are handled by code subsequent to the macro call.
364     HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
365 #endif
366 }
367
368 void hal_interrupt_set_level(int vector, int level)
369 {
370
371 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
372     // Use platform specific handling, if defined
373     // Note: this macro should do a 'return' for "extended" values of 'vector'
374     // Normal vectors are handled by code subsequent to the macro call.
375     HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
376 #endif
377
378     // Interrupt priorities are not configurable.
379 }
380
381 static void check_correct_chip(void)
382 {
383     if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
384         diag_printf("Unrecognized chip version: 0x%x!!!\n", read_system_rev());
385         diag_printf("Assuming chip version=0x%x\n", system_rev);
386     } else if (find_correct_chip == CHIP_VERSION_NONE) {
387         diag_printf("Unrecognized chip: 0x%x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
388     }
389 }
390
391 RedBoot_init(check_correct_chip, RedBoot_INIT_LAST);