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
60 #include <cyg/infra/diag.h> // diag_printf
61 #include <cyg/io/imx_nfc.h>
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.
67 externC void plf_hardware_init(void);
69 #define IIM_PROD_REV_SH 3
70 #define IIM_PROD_REV_LEN 5
71 #define IIM_SREV_REV_SH 4
72 #define IIM_SREV_REV_LEN 4
74 #define PROD_SIGNATURE_MX25 0x1F
76 #define PROD_SIGNATURE_SUPPORTED_1 PROD_SIGNATURE_MX25
78 #define CHIP_VERSION_NONE 0xFFFFFFFF // invalid product ID
79 #define CHIP_VERSION_UNKNOWN 0xDEADBEEF // invalid chip rev
81 #define PART_NUMBER_OFFSET 12
82 #define MAJOR_NUMBER_OFFSET 4
83 #define MINOR_NUMBER_OFFSET 0
86 * System_rev will have the following format
87 * 31-12 = part # (0x31, 0x32, 0x27, 0x91131, 0x91321, 0x35, etc)
92 unsigned int system_rev = CHIP_REV_1_0;
93 static int find_correct_chip;
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.
100 static int read_system_rev(void)
104 val = readl(IIM_BASE_ADDR + IIM_PREV_OFF);
106 system_rev = 0x25 << PART_NUMBER_OFFSET; /* For MX25 Platform*/
107 /* If the IIM doesn't contain a 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)) {
112 return CHIP_VERSION_NONE;
116 /* Now trying to retrieve the silicon rev from IIM's SREV register */
117 return readl(IIM_BASE_ADDR + IIM_SREV_OFF);
120 extern nfc_setup_func_t *nfc_setup;
121 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz,
122 unsigned int is_mlc, unsigned int num_of_chips);
123 void hal_hardware_init(void)
127 ver = read_system_rev();
128 find_correct_chip = ver;
130 if (ver != CHIP_VERSION_NONE) {
131 /* Valid product revision found. Check actual silicon rev from the ROM code. */
133 HAL_PLATFORM_EXTRA[5] = '1';
134 HAL_PLATFORM_EXTRA[7] = '0';
135 system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
136 system_rev |= 0 << MINOR_NUMBER_OFFSET; /*Minor Number*/
137 } else if (ver == 0x1) {
138 HAL_PLATFORM_EXTRA[5] = '1';
139 HAL_PLATFORM_EXTRA[7] = '1';
140 system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
141 system_rev |= 1 << MINOR_NUMBER_OFFSET; /*Minor Number*/
143 HAL_PLATFORM_EXTRA[5] = 'z';
144 HAL_PLATFORM_EXTRA[7] = 'z';
145 system_rev |= 1 << MAJOR_NUMBER_OFFSET; /*Major Number*/
146 system_rev |= 0 << MINOR_NUMBER_OFFSET; /*Minor Number*/
147 find_correct_chip = CHIP_VERSION_UNKNOWN;
151 // Mask all interrupts
152 writel(0xFFFFFFFF, ASIC_NIMASK);
154 // Make all interrupts do IRQ and not FIQ
155 // FIXME: Change this if you use FIQs.
156 writel(0, ASIC_INTTYPEH);
157 writel(0, ASIC_INTTYPEL);
163 // enable EPIT and start it with 32KHz input clock
164 writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
166 // make sure reset is complete
167 while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
170 writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
171 writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
173 writel(0, EPIT_BASE_ADDR + EPITCMPR); // always compare with 0
175 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
176 // increase the WDOG timeout value to the max
177 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
180 // Perform any platform specific initializations
183 // Set up eCos/ROM interfaces
186 nfc_setup = (nfc_setup_func_t*)mxc_nfc_soc_setup;
189 // -------------------------------------------------------------------------
190 void hal_clock_initialize(cyg_uint32 period)
194 // This routine is called during a clock interrupt.
196 // Define this if you want to ensure that the clock is perfect (i.e. does
197 // not drift). One reason to leave it turned off is that it costs some
198 // us per system clock interrupt for this maintenance.
199 #undef COMPENSATE_FOR_CLOCK_DRIFT
201 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
205 // Read the current value of the clock, returning the number of hardware
206 // "ticks" that have occurred (i.e. how far away the current value is from
209 // Note: The "contract" for this function is that the value is the number
210 // of hardware clocks that have happened since the last interrupt (i.e.
211 // when it was reset). This value is used to measure interrupt latencies.
212 // However, since the hardware counter runs freely, this routine computes
213 // the difference between the current clock period and the number of hardware
214 // ticks left before the next timer interrupt.
215 void hal_clock_read(cyg_uint32 *pvalue)
219 // This is to cope with the test read used by tm_basic with
220 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
221 // in the ISR, *before* resetting the clock. Which returns 1tick +
222 // latency if we just use plain hal_clock_read().
223 void hal_clock_latency(cyg_uint32 *pvalue)
227 unsigned int hal_timer_count(void)
229 return 0 - readl(EPIT_BASE_ADDR + EPITCNR);
232 #define WDT_MAGIC_1 0x5555
233 #define WDT_MAGIC_2 0xAAAA
234 #define MXC_WDT_WSR 0x2
236 unsigned int i2c_base_addr[] = {
241 unsigned int i2c_num = 3;
243 static unsigned int led_on = 0;
245 // Delay for some number of microseconds
247 void hal_delay_us(unsigned int usecs)
250 * This causes overflow.
251 * unsigned int delayCount = (usecs * 32000) / 1000000;
252 * So use the following one instead
254 unsigned int delayCount = (usecs * 512) / 16000;
256 if (delayCount == 0) {
260 // issue the service sequence instructions
261 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
262 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
263 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
266 writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
268 writel(delayCount, EPIT_BASE_ADDR + EPITLR);
270 while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
271 if ((++led_on % 2000) == 0)
275 // -------------------------------------------------------------------------
277 // This routine is called to respond to a hardware interrupt (IRQ). It
278 // should interrogate the hardware and return the IRQ vector number.
279 int hal_IRQ_handler(void)
281 #ifdef HAL_EXTENDED_IRQ_HANDLER
284 // Use platform specific IRQ handler, if defined
285 // Note: this macro should do a 'return' with the appropriate
286 // interrupt number if such an extended interrupt exists. The
287 // assumption is that the line after the macro starts 'normal' processing.
288 HAL_EXTENDED_IRQ_HANDLER(index);
291 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
298 void hal_interrupt_mask(int vector)
300 // diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
301 #ifdef HAL_EXTENDED_INTERRUPT_MASK
302 // Use platform specific handling, if defined
303 // Note: this macro should do a 'return' for "extended" values of 'vector'
304 // Normal vectors are handled by code subsequent to the macro call.
305 HAL_EXTENDED_INTERRUPT_MASK(vector);
309 void hal_interrupt_unmask(int vector)
311 // diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
313 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
314 // Use platform specific handling, if defined
315 // Note: this macro should do a 'return' for "extended" values of 'vector'
316 // Normal vectors are handled by code subsequent to the macro call.
317 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
321 void hal_interrupt_acknowledge(int vector)
324 // diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
325 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
326 // Use platform specific handling, if defined
327 // Note: this macro should do a 'return' for "extended" values of 'vector'
328 // Normal vectors are handled by code subsequent to the macro call.
329 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
333 void hal_interrupt_configure(int vector, int level, int up)
336 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
337 // Use platform specific handling, if defined
338 // Note: this macro should do a 'return' for "extended" values of 'vector'
339 // Normal vectors are handled by code subsequent to the macro call.
340 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
344 void hal_interrupt_set_level(int vector, int level)
347 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
348 // Use platform specific handling, if defined
349 // Note: this macro should do a 'return' for "extended" values of 'vector'
350 // Normal vectors are handled by code subsequent to the macro call.
351 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
354 // Interrupt priorities are not configurable.
357 unsigned int mxc_nfc_soc_setup(unsigned int pg_sz, unsigned int io_sz, unsigned int is_mlc,
358 unsigned int num_of_chips)
362 tmp = readw(NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF) | (1 << 8);
364 tmp = readw(NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF) & ~(1 << 8);
367 writew(tmp, NAND_REG_BASE + NAND_FLASH_CONFIG1_REG_OFF);
368 tmp = readl(CCM_BASE_ADDR + CLKCTL_RCSR);
385 writel(tmp, CCM_BASE_ADDR + CLKCTL_RCSR);
389 #define WDOG_WRSR ((CYG_WORD16 *)(WDOG_BASE_ADDR + 0x4))
390 #define CRM_RCSR ((CYG_WORD32 *)(CCM_BASE_ADDR + 0x28))
392 static void check_reset_source(void)
395 char *reset_cause = "UNKNOWN";
399 HAL_READ_UINT32(CRM_RCSR, rcsr);
400 HAL_READ_UINT16(WDOG_WRSR, wrsr);
403 reset_cause = "POWER_ON RESET";
404 } else if (rcsr == 1) {
405 reset_cause = "EXTERNAL RESET";
406 } else if (rcsr & (1 << 3)) {
407 reset_cause = "JTAG RESET";
408 } else if (rcsr & (1 << 2)) {
409 reset_cause = "SOFT RESET";
410 } else if (rcsr & (1 << 1)) {
411 if (wrsr & (1 << 0)) {
412 reset_cause = "SOFTWARE RESET";
413 } else if (wrsr & (1 << 1)) {
414 reset_cause = "WATCHDOG TIMEOUT";
417 diag_printf("Unknown RESET cause: RCSR=0x%08x WRSR=0x%04x\n", rcsr, wrsr);
420 diag_printf("Last RESET cause: %s\n", reset_cause);
422 unsigned int rest = readl(CCM_BASE_ADDR + CLKCTL_RCSR) & 0xF;
425 diag_printf("hardware reset by POR\n");
427 diag_printf("hardware reset by Board reset signal\n");
429 diag_printf("hardware reset by WDOG\n");
431 diag_printf("hardware reset by SOFT RESET\n");
433 diag_printf("hardware reset by JTAG SW RESET\n");
435 diag_printf("hardware reset by unknown source (REST=%x)\n", rest);
439 RedBoot_init(check_reset_source, RedBoot_INIT_LAST);
441 static void check_correct_chip(void)
443 if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
444 diag_printf("Unrecognized chip version: 0x%x!!!\n", read_system_rev());
445 diag_printf("Assuming chip version=0x%x\n", system_rev);
446 } else if (find_correct_chip == CHIP_VERSION_NONE) {
447 diag_printf("Unrecognized chip: 0x%x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
451 RedBoot_init(check_correct_chip, RedBoot_INIT_LAST);