]> git.kernelconcepts.de Git - karo-tx-redboot.git/blob - packages/hal/arm/mx51/var/v2_0/src/soc_misc.c
unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mx51 / 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 int _mxc_fis;
68
69 /*
70  * System_rev will have the following format
71  * 31-12 = part # (0x31, 0x32, 0x27, 0x91131, 0x91321, etc)
72  * 11-8 = unused
73  * 7-4 = major (1.y)
74  * 3-0 = minor (x.0)
75  */
76 unsigned int system_rev = CHIP_REV_1_0;
77 static int find_correct_chip;
78 extern char HAL_PLATFORM_EXTRA[20];
79 extern int _mxc_fis;
80 static int _reset_reason;
81
82 struct soc_sbmr {
83         unsigned int bt_mem_ctl:2,
84         bt_bus_width:1,
85         bt_page_size:2,
86         rsv2:1,
87         bt_spare_size:1,
88         bt_mem_type:2,
89         rsv1:1,
90         bt_ecc_sel:1,
91         bt_usb_src_0:1,
92         bt_eeprom_cfg:1,
93         dir_bt_dis:1,
94         bmod:2,
95         bt_weim_muxed:2,
96         bt_spare:1,
97         bt_sdmmc_src:2,
98         bt_chih_freq_sel:2,
99         bt_i2c_src:2,
100         bt_uart_src:2,
101         bt_cspi_src:2,
102         rsv0:3;
103 } __attribute__ ((packed));
104 struct soc_sbmr *soc_sbmr = (struct soc_sbmr *) (SRC_BASE_ADDR + 0x4);
105 /*
106  * This functions reads the IIM module and returns the system revision number.
107  * It returns the IIM silicon revision reg value if valid product rev is found.
108  . Otherwise, it returns -1.
109  */
110 static int read_system_rev(void)
111 {
112     int val;
113     int *rom_id_address;
114
115     rom_id_address = ROM_BASE_ADDRESS_VIRT + ROM_SI_REV_OFFSET;
116
117     val = readl(IIM_BASE_ADDR + IIM_PREV_OFF);
118
119     system_rev = 0x51 << PART_NUMBER_OFFSET; /* For MX51 Platform*/
120
121     /* Now trying to retrieve the silicon rev from IIM's SREV register */
122     return *rom_id_address;
123 }
124
125 #ifdef MXCFLASH_SELECT_NAND
126 extern nfc_setup_func_t *nfc_setup;
127 #endif
128 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
129                                       unsigned int is_mlc, unsigned int num_of_chips);
130 void hal_hardware_init(void)
131 {
132     int ver = read_system_rev();
133     unsigned int i;
134     unsigned int *fis_addr = (unsigned int *)IRAM_BASE_ADDR;
135
136      _reset_reason = readl(SRC_BASE_ADDR + 0x8);
137     switch (*fis_addr) {
138     case FROM_MMC_FLASH:
139         _mxc_fis = FROM_MMC_FLASH;
140         break;
141     case FROM_NAND_FLASH:
142         _mxc_fis = FROM_NAND_FLASH;
143         break;
144     case FROM_SPI_NOR_FLASH:
145         _mxc_fis = FROM_SPI_NOR_FLASH;
146         break;
147     default:
148         if (soc_sbmr->bt_mem_ctl == 0x3) {
149             if (soc_sbmr->bt_mem_type == 0) {
150                 _mxc_fis = MMC_FLASH_BOOT;
151             } else if (soc_sbmr->bt_mem_type == 3) {
152                 _mxc_fis = SPI_NOR_FLASH_BOOT;
153             }
154         } else if (soc_sbmr->bt_mem_ctl == 1) {
155             _mxc_fis = NAND_FLASH_BOOT;
156         }
157     }
158
159     find_correct_chip = ver;
160
161     if (ver != CHIP_VERSION_NONE) {
162         /* Valid product revision found. Check actual silicon rev from the ROM code. */
163         if (ver == 0x1) {
164             HAL_PLATFORM_EXTRA[5] = '1';
165             HAL_PLATFORM_EXTRA[7] = '0';
166             system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
167             system_rev |= 0 << MINOR_NUMBER_OFFSET; /*Minor Number*/
168         } else if (ver == 0x2) {
169             HAL_PLATFORM_EXTRA[5] = '1';
170             HAL_PLATFORM_EXTRA[7] = '1';
171             system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
172             system_rev |= 1 << MINOR_NUMBER_OFFSET; /*Minor Number*/
173         } else if (ver == 0x10) {
174             HAL_PLATFORM_EXTRA[5] = '2';
175             HAL_PLATFORM_EXTRA[7] = '0';
176             system_rev |= 2 << MAJOR_NUMBER_OFFSET; /*Major Number*/
177             system_rev |= 0 << MINOR_NUMBER_OFFSET; /*Minor Number*/
178         } else {
179             HAL_PLATFORM_EXTRA[5] = 'x';
180             HAL_PLATFORM_EXTRA[7] = 'x';
181             system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
182             system_rev |= 0 << MINOR_NUMBER_OFFSET; /*Minor Number*/
183             find_correct_chip = CHIP_VERSION_UNKNOWN;
184         }
185
186     }
187     // Enable caches
188     HAL_ICACHE_ENABLE();
189     HAL_DCACHE_ENABLE();
190
191     // enable EPIT and start it with 32KHz input clock
192     writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
193
194     // make sure reset is complete
195     while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
196     }
197
198     writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
199     writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
200
201     writel(0, EPIT_BASE_ADDR + EPITCMPR);  // always compare with 0
202
203     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
204         // increase the WDOG timeout value to the max
205         writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
206     }
207
208     // Perform any platform specific initializations
209     plf_hardware_init();
210
211     // Set up eCos/ROM interfaces
212     hal_if_init();
213
214     // initial NAND setup
215     writel(0xFFFF0000, UNLOCK_BLK_ADD0_REG);
216     writel(0xFFFF0000, UNLOCK_BLK_ADD1_REG);
217     writel(0xFFFF0000, UNLOCK_BLK_ADD2_REG);
218     writel(0xFFFF0000, UNLOCK_BLK_ADD3_REG);
219     writel(0xFFFF0000, UNLOCK_BLK_ADD4_REG);
220     writel(0xFFFF0000, UNLOCK_BLK_ADD5_REG);
221     writel(0xFFFF0000, UNLOCK_BLK_ADD6_REG);
222     writel(0xFFFF0000, UNLOCK_BLK_ADD7_REG);
223
224     // unlock all the CS's
225     for (i = 0; i < 8; i++) {
226         writel(0x84 | (i << 3), NFC_WR_PROT_REG);
227     }
228     writel(0, NFC_IPC_REG);
229 #ifdef MXCFLASH_SELECT_NAND
230     nfc_setup = (nfc_setup_func_t*)mxc_nfc_soc_setup;
231 #endif
232 }
233
234 // -------------------------------------------------------------------------
235 void hal_clock_initialize(cyg_uint32 period)
236 {
237 }
238
239 // This routine is called during a clock interrupt.
240
241 // Define this if you want to ensure that the clock is perfect (i.e. does
242 // not drift).  One reason to leave it turned off is that it costs some
243 // us per system clock interrupt for this maintenance.
244 #undef COMPENSATE_FOR_CLOCK_DRIFT
245
246 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
247 {
248 }
249
250 // Read the current value of the clock, returning the number of hardware
251 // "ticks" that have occurred (i.e. how far away the current value is from
252 // the start)
253
254 // Note: The "contract" for this function is that the value is the number
255 // of hardware clocks that have happened since the last interrupt (i.e.
256 // when it was reset).  This value is used to measure interrupt latencies.
257 // However, since the hardware counter runs freely, this routine computes
258 // the difference between the current clock period and the number of hardware
259 // ticks left before the next timer interrupt.
260 void hal_clock_read(cyg_uint32 *pvalue)
261 {
262 }
263
264 // This is to cope with the test read used by tm_basic with
265 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
266 // in the ISR, *before* resetting the clock.  Which returns 1tick +
267 // latency if we just use plain hal_clock_read().
268 void hal_clock_latency(cyg_uint32 *pvalue)
269 {
270 }
271
272 unsigned int hal_timer_count(void)
273 {
274     return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
275 }
276
277 #define WDT_MAGIC_1             0x5555
278 #define WDT_MAGIC_2             0xAAAA
279 #define MXC_WDT_WSR             0x2
280
281 unsigned int i2c_base_addr[] = {
282     I2C_BASE_ADDR,
283     I2C2_BASE_ADDR,
284 };
285 unsigned int i2c_num = 2;
286
287 //
288 // Delay for some number of micro-seconds
289 //
290 void hal_delay_us(unsigned int usecs)
291 {
292     /*
293      * This causes overflow.
294      * unsigned int delayCount = (usecs * 32768) / 1000000;
295      * So use the following one instead
296      */
297     unsigned int delayCount = (usecs * 512) / 15625;
298
299     if (delayCount == 0) {
300         return;
301     }
302
303     // issue the service sequence instructions
304     if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
305         writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
306         writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
307     }
308
309     writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
310
311     writel(delayCount, EPIT_BASE_ADDR + EPITLR);
312
313     while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
314 }
315
316 // -------------------------------------------------------------------------
317
318 // This routine is called to respond to a hardware interrupt (IRQ).  It
319 // should interrogate the hardware and return the IRQ vector number.
320 int hal_IRQ_handler(void)
321 {
322 #ifdef HAL_EXTENDED_IRQ_HANDLER
323     cyg_uint32 index;
324
325     // Use platform specific IRQ handler, if defined
326     // Note: this macro should do a 'return' with the appropriate
327     // interrupt number if such an extended interrupt exists.  The
328     // assumption is that the line after the macro starts 'normal' processing.
329     HAL_EXTENDED_IRQ_HANDLER(index);
330 #endif
331
332     return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
333 }
334
335 //
336 // Interrupt control
337 //
338
339 void hal_interrupt_mask(int vector)
340 {
341 //    diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
342 #ifdef HAL_EXTENDED_INTERRUPT_MASK
343     // Use platform specific handling, if defined
344     // Note: this macro should do a 'return' for "extended" values of 'vector'
345     // Normal vectors are handled by code subsequent to the macro call.
346     HAL_EXTENDED_INTERRUPT_MASK(vector);
347 #endif
348 }
349
350 void hal_interrupt_unmask(int vector)
351 {
352 //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
353
354 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
355     // Use platform specific handling, if defined
356     // Note: this macro should do a 'return' for "extended" values of 'vector'
357     // Normal vectors are handled by code subsequent to the macro call.
358     HAL_EXTENDED_INTERRUPT_UNMASK(vector);
359 #endif
360 }
361
362 void hal_interrupt_acknowledge(int vector)
363 {
364
365 //    diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
366 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
367     // Use platform specific handling, if defined
368     // Note: this macro should do a 'return' for "extended" values of 'vector'
369     // Normal vectors are handled by code subsequent to the macro call.
370     HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
371 #endif
372 }
373
374 void hal_interrupt_configure(int vector, int level, int up)
375 {
376
377 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
378     // Use platform specific handling, if defined
379     // Note: this macro should do a 'return' for "extended" values of 'vector'
380     // Normal vectors are handled by code subsequent to the macro call.
381     HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
382 #endif
383 }
384
385 void hal_interrupt_set_level(int vector, int level)
386 {
387
388 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
389     // Use platform specific handling, if defined
390     // Note: this macro should do a 'return' for "extended" values of 'vector'
391     // Normal vectors are handled by code subsequent to the macro call.
392     HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
393 #endif
394
395     // Interrupt priorities are not configurable.
396 }
397
398 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz, unsigned int is_mlc, unsigned int num_of_chips)
399 {
400     unsigned int nfc_config_reg3;
401
402     if (pg_sz == 2048 && io_sz == 8) {
403         writel(0x70202179, NFC_FLASH_CONFIG2_REG);
404         nfc_config_reg3 = 0x00160608 | ((num_of_chips - 1) << 12);
405         if (num_of_chips > 1)
406             nfc_config_reg3 |= 0x1;
407         writel(nfc_config_reg3, NFC_FLASH_CONFIG3_REG);
408     } else if (pg_sz == 4096 && io_sz == 8) {
409         // This only works for 4KB with 218 spare area size
410         writel(0x706D217A, NFC_FLASH_CONFIG2_REG); // default is 0x706D273A
411         nfc_config_reg3 = 0x00120608 | ((num_of_chips - 1) << 12);
412         if (num_of_chips > 1)
413             nfc_config_reg3 |= 0x1;
414         writel(nfc_config_reg3, NFC_FLASH_CONFIG3_REG);
415     } else {
416         diag_printf("not supported nand flash: pg_sz=%d, io_sz=%d\n",
417                     pg_sz, io_sz);
418         while (1) {
419         }
420     }
421     return MXC_NFC_V3;
422 }
423
424 static void show_sys_info(void)
425 {
426     if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
427         diag_printf("Unrecognized chip version: 0x%x!!!\n", read_system_rev());
428         diag_printf("Assuming chip version=0x%x\n", system_rev);
429     } else if (find_correct_chip == CHIP_VERSION_NONE) {
430         diag_printf("Unrecognized chip: 0x%x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
431     }
432
433     diag_printf("Reset reason: ");
434     switch (_reset_reason) {
435     case 0x09:
436         diag_printf("User reset\n");
437         break;
438     case 0x01:
439         diag_printf("Power-on reset\n");
440         break;
441     case 0x10:
442     case 0x11:
443         diag_printf("WDOG reset\n");
444         break;
445     default:
446         diag_printf("Unknown: 0x%x\n", _reset_reason);
447     }
448
449     if (_mxc_fis == MMC_FLASH_BOOT) {
450         diag_printf("fis/fconfig from MMC\n");
451     } else if (_mxc_fis == SPI_NOR_FLASH_BOOT) {
452         diag_printf("fis/fconfig from SPI-NOR\n");
453     } else if (_mxc_fis == NAND_FLASH_BOOT) {
454         diag_printf("fis/fconfig from NAND\n");
455     } else {
456         diag_printf("Use \"factive [MMC|SPI|NAND]\" to choose fis/fconfig storage\n");
457     }
458
459     //diag_printf("SBMR = 0x%x\n", readl(SRC_BASE_ADDR + 0x4));
460     diag_printf("Boot switch: ");
461     if (soc_sbmr->bmod == 0) {
462         diag_printf("INTERNAL\n");
463     } else if (soc_sbmr->bmod == 3){
464         diag_printf("BOOTSTRAP\n");
465     } else if (soc_sbmr->bmod == 0x1 && soc_sbmr->dir_bt_dis == 0) {
466             diag_printf("TEST EXEC\n");
467     } else {
468         diag_printf("UNKNOWN\n");
469     }
470     diag_printf("\t");
471     if (soc_sbmr->bt_mem_ctl == 0) {
472         diag_printf("WEIM: ");
473         if (soc_sbmr->bt_mem_type == 0) {
474             diag_printf("NOR");
475         } else if (soc_sbmr->bt_mem_type == 2) {
476             diag_printf("ONE NAND");
477         } else {
478             diag_printf("UNKNOWN");
479         }
480     } else if (soc_sbmr->bt_mem_ctl == 1) {
481         diag_printf("NAND: ADDR CYCLES:");
482         if (soc_sbmr->bt_mem_type == 0) {
483             diag_printf("3: ");
484         } else if (soc_sbmr->bt_mem_type == 1) {
485             diag_printf("4: ");
486         } else if (soc_sbmr->bt_mem_type == 2) {
487             diag_printf("5: ");
488         } else {
489             diag_printf("UNKNOWN: ");
490         }
491         if (soc_sbmr->bt_ecc_sel == 0) {
492             diag_printf("SLC: ");
493         } else {
494             diag_printf("MLC: ");
495         }
496         if (soc_sbmr->bt_spare_size == 0) {
497             diag_printf("128B spare (4-bit ECC): ");
498         } else {
499             diag_printf("218B spare (8-bit ECC): ");
500         }
501         diag_printf("PAGE SIZE: ");
502         if (soc_sbmr->bt_page_size == 0) {
503             diag_printf("512: ");
504         } else if (soc_sbmr->bt_page_size == 1) {
505             diag_printf("2K: ");
506         } else if (soc_sbmr->bt_page_size == 2) {
507             diag_printf("4K: ");
508         } else {
509             diag_printf("UNKNOWN: ");
510         }
511         diag_printf("BUS WIDTH: ");
512         if (soc_sbmr->bt_bus_width == 0) {
513             diag_printf("8");
514         } else {
515             diag_printf("16");
516         }
517     } else if (soc_sbmr->bt_mem_ctl == 3) {
518         diag_printf("EXPANSION: ");
519         if (soc_sbmr->bt_mem_type == 0) {
520             diag_printf("SD/MMC-%d", soc_sbmr->bt_sdmmc_src);
521         } else if (soc_sbmr->bt_mem_type == 2) {
522             diag_printf("I2C-NOR: ");
523             if (soc_sbmr->bt_sdmmc_src == 0) {
524                 diag_printf("I2C-1");
525             } else if (soc_sbmr->bt_sdmmc_src == 1) {
526                 diag_printf("I2C-2");
527             } else if (soc_sbmr->bt_sdmmc_src == 2) {
528                 diag_printf("HS-I2C");
529             } else {
530                 diag_printf("UNKNOWN");
531             }
532         } else if (soc_sbmr->bt_mem_type == 3) {
533             diag_printf("SPI-NOR: ");
534             if (soc_sbmr->bt_sdmmc_src == 0) {
535                 diag_printf("eCSPI1");
536             } else if (soc_sbmr->bt_sdmmc_src == 1) {
537                 diag_printf("eCSPI2");
538             } else if (soc_sbmr->bt_sdmmc_src == 2) {
539                 diag_printf("CSPI");
540             } else {
541                 diag_printf("UNKNOWN");
542             }
543         } else {
544             diag_printf("UNKNOWN");
545         }
546     } else {
547         diag_printf("UNKNOWN");
548     }
549     diag_printf("\n");
550 }
551
552 RedBoot_init(show_sys_info, RedBoot_INIT_LAST);