1 //==========================================================================
5 // HAL misc board support code
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.
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.
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
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.
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.
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.
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 //========================================================================*/
43 #include <pkgconf/hal.h>
44 #include <pkgconf/system.h>
45 #include CYGBLD_HAL_PLATFORM_H
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
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 #include <cyg/infra/diag.h> // diag_printf
60 #ifdef MXCFLASH_SELECT_NAND
61 #include <cyg/io/imx_nfc.h>
64 // Most initialization has already been done before we get here.
65 // All we do here is set up the interrupt environment.
66 // FIXME: some of the stuff in hal_platform_setup could be moved here.
69 * System_rev will have the following format
70 * 31-12 = part # (0x31, 0x32, 0x27, 0x91131, 0x91321, etc)
75 unsigned int system_rev = CHIP_REV_1_0;
76 static int find_correct_chip;
78 #define SBMR_BOOT_CFG1_SHIFT 0
79 #define SBMR_BOOT_CFG1_MASK (0xff << SBMR_BOOT_CFG1_SHIFT)
80 #define SBMR_BOOT_CFG1(r) (((r) & SBMR_BOOT_CFG1_MASK) >> SBMR_BOOT_CFG1_SHIFT)
82 #define SBMR_BOOT_CFG2_SHIFT 8
83 #define SBMR_BOOT_CFG2_MASK (0xff << SBMR_BOOT_CFG2_SHIFT)
84 #define SBMR_BOOT_CFG2(r) (((r) & SBMR_BOOT_CFG2_MASK) >> SBMR_BOOT_CFG2_SHIFT)
86 #define SBMR_BOOT_CFG3_SHIFT 16
87 #define SBMR_BOOT_CFG3_MASK (0xff << SBMR_BOOT_CFG3_SHIFT)
88 #define SBMR_BOOT_CFG3(r) (((r) & SBMR_BOOT_CFG3_MASK) >> SBMR_BOOT_CFG3_SHIFT)
90 #define SBMR_BMOD_SHIFT 24
91 #define SBMR_BMOD_MASK (0x3 << SBMR_BMOD_SHIFT)
92 #define SBMR_BMOD(r) (((r) & SBMR_BMOD_MASK) >> SBMR_BMOD_SHIFT)
94 #define SBMR_BT_FUSE_SEL_SHIFT 26
95 #define SBMR_BT_FUSE_SEL_MASK (3 << SBMR_BT_FUSE_SEL_SHIFT)
96 #define SBMR_BT_FUSE_SEL(r) (((r) & SBMR_BT_FUSE_SEL_MASK) >> SBMR_BT_FUSE_SEL_SHIFT)
99 * This functions reads the IIM module and returns the system revision number.
100 * It returns the IIM silicon revision reg value if valid product rev is found.
101 . Otherwise, it returns -1.
103 static int read_system_rev(void)
107 prev = readl(IIM_BASE_ADDR + IIM_PREV_OFF) >> 3;
108 srev = readl(IIM_BASE_ADDR + IIM_SREV_OFF);
110 system_rev = 0x53 << PART_NUMBER_OFFSET; /* For MX53 Platform*/
112 /* Now try to retrieve the silicon rev from IIM's SREV register */
116 #ifdef MXCFLASH_SELECT_NAND
117 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
118 unsigned int is_mlc, unsigned int num_of_chips);
119 extern nfc_setup_func_t *nfc_setup;
122 #ifdef MXCFLASH_SELECT_MMC
123 //extern mxc_mmc_check_sdhc_boot_slot *check_sdhc_slot;
126 int mxc_check_sdhc_boot_slot(unsigned int port, unsigned int *sdhc_addr);
128 void hal_hardware_init(void)
132 ver = read_system_rev();
134 find_correct_chip = ver;
136 if (ver != CHIP_VERSION_NONE) {
137 /* Valid product revision found. Check actual silicon rev from the ROM code. */
139 HAL_PLATFORM_EXTRA[5] = '1';
140 HAL_PLATFORM_EXTRA[7] = '0';
141 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
142 system_rev |= 0 << MINOR_NUMBER_OFFSET;
143 } else if (ver == 0x2) {
144 HAL_PLATFORM_EXTRA[5] = '1';
145 HAL_PLATFORM_EXTRA[7] = '1';
146 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
147 system_rev |= 1 << MINOR_NUMBER_OFFSET;
148 } else if (ver == 0x10) {
149 HAL_PLATFORM_EXTRA[5] = '2';
150 HAL_PLATFORM_EXTRA[7] = '0';
151 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
152 system_rev |= 0 << MINOR_NUMBER_OFFSET;
153 } else if (ver == 0x3) {
154 HAL_PLATFORM_EXTRA[5] = '2';
155 HAL_PLATFORM_EXTRA[7] = '1';
156 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
157 system_rev |= 1 << MINOR_NUMBER_OFFSET;
159 HAL_PLATFORM_EXTRA[5] = 'x';
160 HAL_PLATFORM_EXTRA[7] = 'x';
161 system_rev |= 3 << MAJOR_NUMBER_OFFSET;
162 system_rev |= 0 << MINOR_NUMBER_OFFSET;
163 find_correct_chip = CHIP_VERSION_UNKNOWN;
168 #ifdef CYGSEM_HAL_ENABLE_ICACHE_ON_STARTUP
171 #ifdef CYGSEM_HAL_ENABLE_DCACHE_ON_STARTUP
174 // enable EPIT and start it with 32KHz input clock
175 writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
177 // make sure reset is complete
178 while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
179 static int retries = 10000;
184 writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
185 writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
187 writel(0, EPIT_BASE_ADDR + EPITCMPR); // always compare with 0
189 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
190 // increase the WDOG timeout value to the max
191 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
193 // Perform any platform specific initializations
196 // Set up eCos/ROM interfaces
199 #ifdef MXCFLASH_SELECT_NAND
200 nfc_setup = mxc_nfc_soc_setup;
204 // -------------------------------------------------------------------------
205 void hal_clock_initialize(cyg_uint32 period)
209 // This routine is called during a clock interrupt.
211 // Define this if you want to ensure that the clock is perfect (i.e. does
212 // not drift). One reason to leave it turned off is that it costs some
213 // us per system clock interrupt for this maintenance.
214 #undef COMPENSATE_FOR_CLOCK_DRIFT
216 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
220 // Read the current value of the clock, returning the number of hardware
221 // "ticks" that have occurred (i.e. how far away the current value is from
224 // Note: The "contract" for this function is that the value is the number
225 // of hardware clocks that have happened since the last interrupt (i.e.
226 // when it was reset). This value is used to measure interrupt latencies.
227 // However, since the hardware counter runs freely, this routine computes
228 // the difference between the current clock period and the number of hardware
229 // ticks left before the next timer interrupt.
230 void hal_clock_read(cyg_uint32 *pvalue)
234 // This is to cope with the test read used by tm_basic with
235 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
236 // in the ISR, *before* resetting the clock. Which returns 1tick +
237 // latency if we just use plain hal_clock_read().
238 void hal_clock_latency(cyg_uint32 *pvalue)
242 unsigned int hal_timer_count(void)
244 return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
247 #define WDT_MAGIC_1 0x5555
248 #define WDT_MAGIC_2 0xAAAA
249 #define MXC_WDT_WSR 0x2
251 unsigned int i2c_base_addr[] = {
255 unsigned int i2c_num = 2;
257 static unsigned int led_on = 0;
259 // Delay for some number of micro-seconds
261 void hal_delay_us(unsigned int usecs)
264 * This causes overflow.
265 * unsigned int delayCount = (usecs * 32768) / 1000000;
266 * So use the following one instead
268 unsigned int delayCount = (usecs * 512) / 15625;
270 // issue the service sequence instructions
271 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
272 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
273 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
276 if (delayCount == 0) {
280 writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
282 writel(delayCount, EPIT_BASE_ADDR + EPITLR);
284 while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
285 if ((++led_on % 3000) == 0)
289 // -------------------------------------------------------------------------
291 // This routine is called to respond to a hardware interrupt (IRQ). It
292 // should interrogate the hardware and return the IRQ vector number.
293 int hal_IRQ_handler(void)
295 #ifdef HAL_EXTENDED_IRQ_HANDLER
298 // Use platform specific IRQ handler, if defined
299 // Note: this macro should do a 'return' with the appropriate
300 // interrupt number if such an extended interrupt exists. The
301 // assumption is that the line after the macro starts 'normal' processing.
302 HAL_EXTENDED_IRQ_HANDLER(index);
305 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
312 void hal_interrupt_mask(int vector)
314 // diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
315 #ifdef HAL_EXTENDED_INTERRUPT_MASK
316 // Use platform specific handling, if defined
317 // Note: this macro should do a 'return' for "extended" values of 'vector'
318 // Normal vectors are handled by code subsequent to the macro call.
319 HAL_EXTENDED_INTERRUPT_MASK(vector);
323 void hal_interrupt_unmask(int vector)
325 // diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
327 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
328 // Use platform specific handling, if defined
329 // Note: this macro should do a 'return' for "extended" values of 'vector'
330 // Normal vectors are handled by code subsequent to the macro call.
331 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
335 void hal_interrupt_acknowledge(int vector)
338 // diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
339 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
340 // Use platform specific handling, if defined
341 // Note: this macro should do a 'return' for "extended" values of 'vector'
342 // Normal vectors are handled by code subsequent to the macro call.
343 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
347 void hal_interrupt_configure(int vector, int level, int up)
350 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
351 // Use platform specific handling, if defined
352 // Note: this macro should do a 'return' for "extended" values of 'vector'
353 // Normal vectors are handled by code subsequent to the macro call.
354 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
358 void hal_interrupt_set_level(int vector, int level)
361 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
362 // Use platform specific handling, if defined
363 // Note: this macro should do a 'return' for "extended" values of 'vector'
364 // Normal vectors are handled by code subsequent to the macro call.
365 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
368 // Interrupt priorities are not configurable.
371 #ifdef MXCFLASH_SELECT_NAND
372 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
373 unsigned int is_mlc, unsigned int num_of_chips)
377 tmp = readl(NFC_FLASH_CONFIG2_REG);
379 /* Set the ST_CMD to be 0x70 for all NAND devices */
380 tmp &= ~(0xFF << 24);
382 /* spare size = 64 byte */
383 tmp = (tmp & ~(0xff << 16)) | ((64 / 2) << 16);
385 /* Set the Page Size */
402 /* set ECC_MODE to 4bit ECC */
403 tmp = (tmp & ~(3 << 6)) | (0 << 6);
404 /* set pages/block to 64 */
405 tmp = (tmp & ~(3 << 8)) | (1 << 8);
407 /* Set the number of addr phases & ECC mode to default value */
409 tmp |= (0x2 << 12) | 0x038;
410 writel(tmp, NFC_FLASH_CONFIG2_REG);
412 tmp = readl(NFC_FLASH_CONFIG3_REG);
414 /* Set the No SDMA bit */
417 /* Set the Status Busy Bit to 0x6 (default) */
421 /* Set the Flash Width */
422 if (io_sz == MXC_NAND_16_BIT) {
428 /* Set the Number of Nand Chips */
430 tmp |= (num_of_chips - 1) << 12;
431 if (num_of_chips > 1)
435 /* STATUS_SAMP_SEL */
438 writel(tmp, NFC_FLASH_CONFIG3_REG);
444 int mx53_iomux_setup(iomux_v3_cfg_t pad)
447 diag_printf("pad=%016llx MUX_OFS=%03x PAD_OFS=%03x INP_SEL_OFS=%03x MUX_MODE=%02x PAD_CTL=%04x INP_SEL=%x PAD_CTL_VALID=%d\n",
448 pad, IOMUX_MUX_CTRL_OFS(pad), IOMUX_PAD_CTRL_OFS(pad),
449 IOMUX_INP_SEL_OFS(pad), IOMUX_MUX_MODE(pad), IOMUX_PAD_CTRL(pad),
450 IOMUX_INP_SEL(pad), IOMUX_PAD_CTRL_VALID(pad));
451 if (readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)) !=
452 IOMUX_MUX_MODE(pad)) {
453 diag_printf("Changing IOMUX[%03x] from %02x to %02x\n",
454 IOMUX_MUX_CTRL_OFS(pad),
455 readl(IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad)),
456 IOMUX_MUX_MODE(pad));
459 writel(IOMUX_MUX_MODE(pad),
460 IOMUXC_BASE_ADDR + IOMUX_MUX_CTRL_OFS(pad));
462 if (IOMUX_PAD_CTRL_VALID(pad)) {
464 if (readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)) !=
465 IOMUX_PAD_CTRL(pad)) {
466 diag_printf("Changing PAD_CTRL[%03x] from %04x to %04x\n",
467 IOMUX_PAD_CTRL_OFS(pad),
468 readl(IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad)),
469 IOMUX_PAD_CTRL(pad));
472 writel(IOMUX_PAD_CTRL(pad), IOMUXC_BASE_ADDR + IOMUX_PAD_CTRL_OFS(pad));
474 if (IOMUX_INP_SEL_OFS(pad)) {
476 if (readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)) !=
477 IOMUX_INP_SEL(pad)) {
478 diag_printf("Changing INP_SEL[%03x] from %x to %x\n",
479 IOMUX_INP_SEL_OFS(pad),
480 readl(IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad)),
484 writel(IOMUX_INP_SEL(pad), IOMUXC_BASE_ADDR + IOMUX_INP_SEL_OFS(pad));
489 int mx53_iomux_setup_pads(iomux_v3_cfg_t *pad, int num_pads)
494 for (i = 0; i < num_pads; i++) {
495 ret = mx53_iomux_setup(pad[i]);
502 static void show_sys_info(void)
504 cyg_uint32 sbmr = readl(SRC_BASE_ADDR + 0x4);
505 cyg_uint32 srsr = readl(SRC_BASE_ADDR + 0x8);
506 const char *dlm = "";
507 int bt_mem = (SBMR_BOOT_CFG1(sbmr) & (0xf << 4)) >> 4;
509 if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
510 diag_printf("Unrecognized chip version: 0x%08x!\n", read_system_rev());
511 diag_printf("Assuming chip version=0x%08x\n", system_rev);
512 } else if (find_correct_chip == CHIP_VERSION_NONE) {
513 diag_printf("Unrecognized chip: 0x%08x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
516 diag_printf("Reset reason: ");
518 if (srsr & (1 << 0)) {
519 diag_printf("%sPOWER_ON", dlm);
522 if (srsr & (1 << 2)) {
523 diag_printf("%sCSU", dlm);
526 if (srsr & (1 << 3)) {
527 diag_printf("%sUSER", dlm);
530 if (srsr & (1 << 4)) {
533 HAL_READ_UINT16(WDOG_BASE_ADDR + 4, wrsr);
534 if (wrsr & (1 << 0)) {
535 diag_printf("%sSOFT", dlm);
538 if (wrsr & (1 << 1)) {
539 diag_printf("%sWATCHDOG", dlm);
543 if (srsr & (1 << 5)) {
544 diag_printf("%sJTAG_HW", dlm);
547 if (srsr & (1 << 6)) {
548 diag_printf("%sJTAG_SW", dlm);
551 if (srsr & (1 << 16)) {
552 diag_printf("%sWARM BOOT", dlm);
557 diag_printf("UNKNOWN: %08x\n", srsr);
559 diag_printf(" RESET\n");
562 diag_printf("BOOT_MODE: ");
563 switch (SBMR_BMOD(sbmr)) {
565 diag_printf("Internal Boot (from %s)\n",
566 SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "GPIO");
570 diag_printf("FSL Test Mode\n");
574 diag_printf("Internal Boot (from %s)\n",
575 SBMR_BT_FUSE_SEL(sbmr) ? "FUSES" : "UART/USB");
579 diag_printf("Serial Boot Loader\n");
581 diag_printf("Boot Medium: ");
582 switch (SBMR_BMOD(sbmr)) {
586 diag_printf("WEIM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
588 } else if (bt_mem == 2) {
589 diag_printf("HD %sATA\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
591 } else if (bt_mem == 3) {
592 diag_printf("Serial ROM %s\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
594 } else if ((bt_mem & ~1) == 4) {
595 diag_printf("SD %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
597 } else if ((bt_mem & ~1) == 6) {
598 diag_printf("MMC %s speed\n", SBMR_BOOT_CFG1(sbmr) & (1 << 3) ?
600 } else if (bt_mem & (1 << 3)) {
601 diag_printf("NAND\n");
603 diag_printf("UNKNOWN: 0x%x\n", bt_mem);
608 diag_printf("UNKNOWN\n");
612 diag_printf("UART/USB\n");
614 diag_printf("Boot Clock: %d MHz\n",
615 (SBMR_BOOT_CFG1(sbmr) & (1 << 1)) ? 400 : 800);
616 diag_printf("OSC Freq: %s\n",
617 (SBMR_BOOT_CFG2(sbmr) & (1 << 3)) ? " 24 MHz" : "auto");
618 diag_printf("PLL2 Freq: %d MHz\n",
619 (SBMR_BOOT_CFG2(sbmr) & (1 << 4)) ? 333 : 400);
620 diag_printf("Secure Boot: %s\n",
621 (SBMR_BOOT_CFG2(sbmr) & (2 << 0)) ? "On" : "Off");
624 RedBoot_init(show_sys_info, RedBoot_INIT_LAST);