unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mx31 / 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_MX32     0x2
74
75 #define PROD_SIGNATURE_SUPPORTED_1  PROD_SIGNATURE_MX31
76 #define PROD_SIGNATURE_SUPPORTED_2  PROD_SIGNATURE_MX32
77 #define CHIP_VERSION_NONE           0xFFFFFFFF      // invalid product ID
78 #define CHIP_VERSION_UNKNOWN        0xDEADBEEF      // invalid chip rev
79
80 #define PART_NUMBER_OFFSET          (12)
81 #define MAJOR_NUMBER_OFFSET         (4)
82 #define MINOR_NUMBER_OFFSET         (0)
83
84 /*
85  * System_rev will have the following format
86  * 31-12 = part # (0x31, 0x32, 0x27, 0x91131, 0x91321, etc)
87  * 11-8 = unused
88  * 7-4 = major (1.y)
89  * 3-0 = minor (x.0)
90  */
91 unsigned int system_rev = CHIP_REV_1_0;
92 static int find_correct_chip;
93 int g_board_type = BOARD_TYPE_UNKNOWN;
94 extern char HAL_PLATFORM_EXTRA[60];
95
96 /*
97  * This functions reads the IIM module and returns the system revision number.
98  * It returns the IIM silicon revision reg value if valid product rev is found.
99  . Otherwise, it returns -1.
100  */
101 static int read_system_rev(void)
102 {
103     int val;
104
105     val = readl(IIM_BASE_ADDR + IIM_PREV_OFF);
106
107     /* If the IIM doesn't contain valid product signature, return
108      * the lowest revision number */
109     if ((MXC_GET_FIELD(val, IIM_PROD_REV_LEN, IIM_PROD_REV_SH) !=
110         PROD_SIGNATURE_SUPPORTED_1) &&
111         (MXC_GET_FIELD(val, IIM_PROD_REV_LEN, IIM_PROD_REV_SH) !=
112         PROD_SIGNATURE_SUPPORTED_2)){
113         return CHIP_VERSION_NONE;
114     }
115
116     /* Check if this is MX32 chip */
117     if (MXC_GET_FIELD(val, IIM_PROD_REV_LEN, IIM_PROD_REV_SH) ==
118         PROD_SIGNATURE_MX32) {
119         system_rev = 0x32 << PART_NUMBER_OFFSET; /* For MX32 Platform*/
120         if (g_board_type == BOARD_TYPE_ADS) {
121             HAL_PLATFORM_EXTRA[3] = '2';
122             HAL_PLATFORM_EXTRA[25] = '2';
123         } else if (g_board_type == BOARD_TYPE_3STACK) {
124             HAL_PLATFORM_EXTRA[3] = '2';
125             HAL_PLATFORM_EXTRA[29] = '2';
126         }
127     } else {
128         system_rev = 0x31 << PART_NUMBER_OFFSET; /* For MX31 Platform*/
129     }
130
131     /* Now trying to retrieve the silicon rev from IIM's SREV register */
132     return readl(IIM_BASE_ADDR + IIM_SREV_OFF);
133 }
134
135 extern nfc_setup_func_t *nfc_setup;
136 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
137                                       unsigned int is_mlc, unsigned int num_of_chips);
138 void hal_hardware_init(void)
139 {
140     volatile unsigned int esdmisc = readl(ESDCTL_BASE + 0x10);
141     volatile unsigned int esdctl0 = readl(ESDCTL_BASE);
142     int ver;
143     char chip_ver[2];
144
145     // Perform any platform specific initializations
146     plf_hardware_init();
147
148     ver = read_system_rev();
149
150     find_correct_chip = ver;
151
152     if (ver != CHIP_VERSION_NONE) {
153         /* Valid product revision found. Check actual silicon rev and
154          * NOT use the version from the ROM code. */
155         if (((ver >> 4) & 0xF) == 0x0) {
156             chip_ver[0] = '1';
157             chip_ver[1] = '0';
158             system_rev |= 1 << MAJOR_NUMBER_OFFSET      ;/*Major Number*/
159             system_rev |= 0 << MINOR_NUMBER_OFFSET      ;/*Minor Number*/
160         } else if (((ver >> 4) & 0xF) == 0x1) {
161             chip_ver[0] = '1';
162             chip_ver[1] = '1';
163             system_rev |= 1 << MAJOR_NUMBER_OFFSET      ;/*Major Number*/
164             system_rev |= 1 << MINOR_NUMBER_OFFSET      ;/*Minor Number*/
165         } else if (((ver >> 4) & 0xF) == 0x2) {
166             chip_ver[0] = '2';
167             chip_ver[1] = '0';
168             system_rev |= 2 << MAJOR_NUMBER_OFFSET      ;/*Major Number*/
169             system_rev |= 0 << MINOR_NUMBER_OFFSET      ;/*Minor Number*/
170         } else {
171             chip_ver[0] = 'x';
172             chip_ver[1] = 'x';
173             system_rev |= 1 << MAJOR_NUMBER_OFFSET      ;/*Major Number*/
174             system_rev |= 0 << MINOR_NUMBER_OFFSET      ;/*Minor Number*/
175             find_correct_chip = CHIP_VERSION_UNKNOWN;
176         }
177     }
178
179     if (g_board_type == BOARD_TYPE_ADS) {
180         HAL_PLATFORM_EXTRA[39] = chip_ver[0];
181         HAL_PLATFORM_EXTRA[41] = chip_ver[1];
182         if ((esdmisc & 0x4) == 0) {
183             HAL_PLATFORM_EXTRA[48] = 'S';
184         }
185         if ((esdctl0 & 0x30000) != 0x20000) {
186             HAL_PLATFORM_EXTRA[45] = '1';
187             HAL_PLATFORM_EXTRA[46] = '6';
188         }
189     } else if (g_board_type == BOARD_TYPE_3STACK) {
190         HAL_PLATFORM_EXTRA[43] = chip_ver[0];
191         HAL_PLATFORM_EXTRA[45] = chip_ver[1];
192         if ((esdmisc & 0x4) == 0) {
193             HAL_PLATFORM_EXTRA[52] = 'S';
194         }
195         if ((esdctl0 & 0x30000) != 0x20000) {
196             HAL_PLATFORM_EXTRA[49] = '1';
197             HAL_PLATFORM_EXTRA[50] = '6';
198         }
199     }
200
201     // Mask all interrupts
202     writel(0xFFFFFFFF, AVIC_NIMASK);
203
204     // Make all interrupts do IRQ and not FIQ
205     // FIXME: Change this if you use FIQs.
206     writel(0, AVIC_INTTYPEH);
207     writel(0, AVIC_INTTYPEL);
208
209     // Enable caches
210     HAL_ICACHE_ENABLE();
211     HAL_DCACHE_ENABLE();
212
213     // enable EPIT and start it with 32KHz input clock
214     writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
215
216     // make sure reset is complete
217     while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
218     }
219
220     writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
221     writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
222
223     writel(0, EPIT_BASE_ADDR + EPITCMPR);  // always compare with 0
224
225     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
226         // increase the WDOG timeout value to the max
227         writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
228     }
229
230     // Set up eCos/ROM interfaces
231     hal_if_init();
232
233     nfc_setup = (nfc_setup_func_t*)mxc_nfc_soc_setup;
234 }
235
236 // -------------------------------------------------------------------------
237 void hal_clock_initialize(cyg_uint32 period)
238 {
239 }
240
241 // This routine is called during a clock interrupt.
242
243 // Define this if you want to ensure that the clock is perfect (i.e. does
244 // not drift).  One reason to leave it turned off is that it costs some
245 // us per system clock interrupt for this maintenance.
246 #undef COMPENSATE_FOR_CLOCK_DRIFT
247
248 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
249 {
250 }
251
252 // Read the current value of the clock, returning the number of hardware
253 // "ticks" that have occurred (i.e. how far away the current value is from
254 // the start)
255
256 // Note: The "contract" for this function is that the value is the number
257 // of hardware clocks that have happened since the last interrupt (i.e.
258 // when it was reset).  This value is used to measure interrupt latencies.
259 // However, since the hardware counter runs freely, this routine computes
260 // the difference between the current clock period and the number of hardware
261 // ticks left before the next timer interrupt.
262 void hal_clock_read(cyg_uint32 *pvalue)
263 {
264 }
265
266 // This is to cope with the test read used by tm_basic with
267 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
268 // in the ISR, *before* resetting the clock.  Which returns 1tick +
269 // latency if we just use plain hal_clock_read().
270 void hal_clock_latency(cyg_uint32 *pvalue)
271 {
272 }
273
274 unsigned int hal_timer_count(void)
275 {
276     return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
277 }
278
279 #define WDT_MAGIC_1             0x5555
280 #define WDT_MAGIC_2             0xAAAA
281 #define MXC_WDT_WSR             0x2
282
283 unsigned int i2c_base_addr[] = {
284     I2C_BASE_ADDR,
285     I2C2_BASE_ADDR,
286     I2C3_BASE_ADDR
287 };
288 unsigned int i2c_num = 3;
289
290 static unsigned int led_on = 0;
291 //
292 // Delay for some number of micro-seconds
293 //
294 void hal_delay_us(unsigned int usecs)
295 {
296     /*
297      * This causes overflow.
298      * unsigned int delayCount = (usecs * 32768) / 1000000;
299      * So use the following one instead
300      */
301     unsigned int delayCount = (usecs * 512) / 15625;
302
303     if (delayCount == 0) {
304         return;
305     }
306
307     // issue the service sequence instructions
308     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
309         writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
310         writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
311     }
312
313     writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
314
315     writel(delayCount, EPIT_BASE_ADDR + EPITLR);
316
317     while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
318     if ((++led_on % 2000) == 0)
319         BOARD_DEBUG_LED(0);
320 }
321
322 // -------------------------------------------------------------------------
323
324 // This routine is called to respond to a hardware interrupt (IRQ).  It
325 // should interrogate the hardware and return the IRQ vector number.
326 int hal_IRQ_handler(void)
327 {
328 #ifdef HAL_EXTENDED_IRQ_HANDLER
329     cyg_uint32 index;
330
331     // Use platform specific IRQ handler, if defined
332     // Note: this macro should do a 'return' with the appropriate
333     // interrupt number if such an extended interrupt exists.  The
334     // assumption is that the line after the macro starts 'normal' processing.
335     HAL_EXTENDED_IRQ_HANDLER(index);
336 #endif
337
338     return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
339 }
340
341 //
342 // Interrupt control
343 //
344
345 void hal_interrupt_mask(int vector)
346 {
347 //    diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
348 #ifdef HAL_EXTENDED_INTERRUPT_MASK
349     // Use platform specific handling, if defined
350     // Note: this macro should do a 'return' for "extended" values of 'vector'
351     // Normal vectors are handled by code subsequent to the macro call.
352     HAL_EXTENDED_INTERRUPT_MASK(vector);
353 #endif
354 }
355
356 void hal_interrupt_unmask(int vector)
357 {
358 //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
359
360 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
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_UNMASK(vector);
365 #endif
366 }
367
368 void hal_interrupt_acknowledge(int vector)
369 {
370
371 //    diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
372 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
373     // Use platform specific handling, if defined
374     // Note: this macro should do a 'return' for "extended" values of 'vector'
375     // Normal vectors are handled by code subsequent to the macro call.
376     HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
377 #endif
378 }
379
380 void hal_interrupt_configure(int vector, int level, int up)
381 {
382
383 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
384     // Use platform specific handling, if defined
385     // Note: this macro should do a 'return' for "extended" values of 'vector'
386     // Normal vectors are handled by code subsequent to the macro call.
387     HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
388 #endif
389 }
390
391 void hal_interrupt_set_level(int vector, int level)
392 {
393
394 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
395     // Use platform specific handling, if defined
396     // Note: this macro should do a 'return' for "extended" values of 'vector'
397     // Normal vectors are handled by code subsequent to the macro call.
398     HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
399 #endif
400
401     // Interrupt priorities are not configurable.
402 }
403
404 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz, unsigned int is_mlc, unsigned int num_of_chips)
405 {
406     unsigned int tmp, res = -1;
407
408     if (is_mlc) {
409         tmp = readw(NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF) | (1 << 9);
410     } else {
411         tmp = readw(NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF) & (~(1 << 9));
412     }
413     writew(tmp, NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF);
414
415     if (pg_sz == 2048) {
416         tmp = readl(CCM_BASE_ADDR + CLKCTL_RCSR) | (1 << 30);
417     } else {
418         tmp = readl(CCM_BASE_ADDR + CLKCTL_RCSR) & (~(1 << 30));
419     }
420     writel(tmp, CCM_BASE_ADDR + CLKCTL_RCSR);
421
422     if (io_sz == 16) {
423         tmp = readl(CCM_BASE_ADDR + CLKCTL_RCSR) | (1 << 31);
424     } else {
425         tmp = readl(CCM_BASE_ADDR + CLKCTL_RCSR) & (~(1 << 31));
426     }
427     writel(tmp, CCM_BASE_ADDR + CLKCTL_RCSR);
428
429     tmp = system_rev >> PART_NUMBER_OFFSET;
430     switch (tmp) {
431     case 0x31:
432         res = MXC_NFC_V1;
433         break;
434     case 0x32:
435         res = MXC_NFC_V2;
436         break;
437     default:
438         diag_printf("Unknown chip version: 0x%x\n", tmp);
439     }
440     return res;
441 }
442
443 static void check_correct_chip(void)
444 {
445     if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
446         diag_printf("Unrecognized chip version: 0x%x!!!\n", read_system_rev());
447         diag_printf("Assuming chip version=0x%x\n", system_rev);
448     } else if (find_correct_chip == CHIP_VERSION_NONE) {
449         diag_printf("Unrecognized chip: 0x%x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
450     }
451 }
452
453 RedBoot_init(check_correct_chip, RedBoot_INIT_LAST);