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