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