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
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.
66 externC void plf_hardware_init(void);
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 #define PROD_SIGNATURE_MX31 0x1
73 #define PROD_SIGNATURE_MXC91331 0x4
74 #define PROD_SIGNATURE_MXC91321 0x6
75 #define PROD_SIGNATURE_MXC91231 0x8
76 #define PROD_SIGNATURE_MXC91131 0x10
78 #if defined(CYGPKG_HAL_ARM_MXC91331_CHIP)
79 #define PROD_SIGNATURE_SUPPORTED PROD_SIGNATURE_MXC91331
80 #elif defined(CYGPKG_HAL_ARM_MXC91321_CHIP)
81 #define PROD_SIGNATURE_SUPPORTED PROD_SIGNATURE_MXC91321
83 #error Neither MXC91331 nor MXC91321 defined. What is it?
85 #define CHIP_VERSION_NONE 0xFFFFFFFF // invalid product ID
86 #define CHIP_VERSION_UNKNOWN 0xDEADBEEF // invalid chip rev
88 #define PART_NUMBER_OFFSET (12)
89 #define MAJOR_NUMBER_OFFSET (4)
90 #define MINOR_NUMBER_OFFSET (0)
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 /* If the IIM doesn't contain valid product signature, return
107 * the lowest revision number */
108 if (MXC_GET_FIELD(val, IIM_PROD_REV_LEN, IIM_PROD_REV_SH) !=
109 PROD_SIGNATURE_SUPPORTED) {
110 return CHIP_VERSION_NONE;
112 system_rev = 0x91321 << PART_NUMBER_OFFSET;
115 /* Now trying to retrieve the silicon rev from IIM's SREV register */
116 return readl(IIM_BASE_ADDR + IIM_SREV_OFF);
119 char HAL_PLATFORM_EXTRA[25] = "PASS 1.0.0 [x32 DDR]";
121 void hal_hardware_init(void)
123 volatile unsigned int esdmisc = readl(ESDCTL_BASE + 0x10);
124 volatile unsigned int esdctl0 = readl(ESDCTL_BASE);
125 int ver = read_system_rev();
127 find_correct_chip = ver;
129 #if defined(CYGPKG_HAL_ARM_MXC91331_CHIP)
130 unsigned char chip_ver = readb(INTERNAL_ROM_VA + 0x60);
132 if (ver != CHIP_VERSION_NONE) {
133 /* Valid product revision found. Check actual silicon rev and
134 * NOT use the version from the ROM code. */
135 switch (ver & 0xFF) {
137 HAL_PLATFORM_EXTRA[5] = '2';
138 HAL_PLATFORM_EXTRA[7] = '1';
139 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
140 system_rev |= 1 << MINOR_NUMBER_OFFSET;
143 HAL_PLATFORM_EXTRA[5] = 'x';
144 HAL_PLATFORM_EXTRA[7] = 'x';
145 HAL_PLATFORM_EXTRA[9] = 'x';
146 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
147 system_rev |= 0 << MINOR_NUMBER_OFFSET;
148 find_correct_chip = CHIP_VERSION_UNKNOWN;
153 HAL_PLATFORM_EXTRA[5] = '2';
154 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
155 system_rev |= 0 << MINOR_NUMBER_OFFSET;
159 if (ver != CHIP_VERSION_NONE) {
160 switch (ver & 0xFF) {
162 HAL_PLATFORM_EXTRA[5] = '1';
163 HAL_PLATFORM_EXTRA[7] = '0';
164 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
165 system_rev |= 0 << MINOR_NUMBER_OFFSET;
168 HAL_PLATFORM_EXTRA[5] = '1';
169 HAL_PLATFORM_EXTRA[7] = '1';
170 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
171 system_rev |= 1 << MINOR_NUMBER_OFFSET;
175 HAL_PLATFORM_EXTRA[5] = '1';
176 HAL_PLATFORM_EXTRA[7] = '2';
177 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
178 system_rev |= 2 << MINOR_NUMBER_OFFSET;
181 HAL_PLATFORM_EXTRA[5] = '1';
182 HAL_PLATFORM_EXTRA[7] = '2';
183 HAL_PLATFORM_EXTRA[9] = '2';
184 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
185 system_rev |= 2 << MINOR_NUMBER_OFFSET;
188 HAL_PLATFORM_EXTRA[5] = '2';
189 HAL_PLATFORM_EXTRA[7] = '3';
190 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
191 system_rev |= 3 << MINOR_NUMBER_OFFSET;
194 HAL_PLATFORM_EXTRA[5] = '2';
195 HAL_PLATFORM_EXTRA[7] = '3';
196 HAL_PLATFORM_EXTRA[9] = '2';
197 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
198 system_rev |= 3 << MINOR_NUMBER_OFFSET;
201 HAL_PLATFORM_EXTRA[5] = 'x';
202 HAL_PLATFORM_EXTRA[7] = 'x';
203 HAL_PLATFORM_EXTRA[9] = 'x';
204 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
205 system_rev |= 2 << MINOR_NUMBER_OFFSET;
206 find_correct_chip = CHIP_VERSION_UNKNOWN;
210 #endif // CYGPKG_HAL_ARM_MXC91331_CHIP
212 if ((esdmisc & 0x4) == 0) {
213 HAL_PLATFORM_EXTRA[16] = 'S';
215 if ((esdctl0 & 0x30000) != 0x20000) {
216 HAL_PLATFORM_EXTRA[13] = '1';
217 HAL_PLATFORM_EXTRA[14] = '6';
220 // Mask all interrupts
221 writel(0xFFFFFFFF, AVIC_NIMASK);
223 // Make all interrupts do IRQ and not FIQ
224 // FIXME: Change this if you use FIQs.
225 writel(0, AVIC_INTTYPEH);
226 writel(0, AVIC_INTTYPEL);
232 // enable EPIT and start it with 32KHz input clock
233 writel(0x00010000, EPIT_BASE_ADDR + EPITCR);
235 // make sure reset is complete
236 while ((readl(EPIT_BASE_ADDR + EPITCR) & 0x10000) != 0) {
239 writel(0x030E0002, EPIT_BASE_ADDR + EPITCR);
240 writel(0x030E0003, EPIT_BASE_ADDR + EPITCR);
242 writel(0, EPIT_BASE_ADDR + EPITCMPR); // always compare with 0
244 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
245 // increase the WDOG timeout value to the max
246 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
249 // Perform any platform specific initializations
252 // Set up eCos/ROM interfaces
256 // -------------------------------------------------------------------------
257 void hal_clock_initialize(cyg_uint32 period)
261 // This routine is called during a clock interrupt.
263 // Define this if you want to ensure that the clock is perfect (i.e. does
264 // not drift). One reason to leave it turned off is that it costs some
265 // us per system clock interrupt for this maintenance.
266 #undef COMPENSATE_FOR_CLOCK_DRIFT
268 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
272 // Read the current value of the clock, returning the number of hardware
273 // "ticks" that have occurred (i.e. how far away the current value is from
276 // Note: The "contract" for this function is that the value is the number
277 // of hardware clocks that have happened since the last interrupt (i.e.
278 // when it was reset). This value is used to measure interrupt latencies.
279 // However, since the hardware counter runs freely, this routine computes
280 // the difference between the current clock period and the number of hardware
281 // ticks left before the next timer interrupt.
282 void hal_clock_read(cyg_uint32 *pvalue)
286 // This is to cope with the test read used by tm_basic with
287 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
288 // in the ISR, *before* resetting the clock. Which returns 1tick +
289 // latency if we just use plain hal_clock_read().
290 void hal_clock_latency(cyg_uint32 *pvalue)
294 unsigned int hal_timer_count(void)
296 return (0xFFFFFFFF - readl(EPIT_BASE_ADDR + EPITCNR));
299 #define WDT_MAGIC_1 0x5555
300 #define WDT_MAGIC_2 0xAAAA
301 #define MXC_WDT_WSR 0x2
303 static unsigned int led_on = 0;
305 // Delay for some number of micro-seconds
307 void hal_delay_us(unsigned int usecs)
310 * This causes overflow.
311 * unsigned int delayCount = (usecs * 32768) / 1000000;
312 * So use the following one instead
314 unsigned int delayCount = (usecs * 512) / 15625;
316 if (delayCount == 0) {
320 // issue the service sequence instructions
321 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
322 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
323 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
326 writel(0x01, EPIT_BASE_ADDR + EPITSR); // clear the compare status bit
328 writel(delayCount, EPIT_BASE_ADDR + EPITLR);
330 while ((0x1 & readl(EPIT_BASE_ADDR + EPITSR)) == 0); // return until compare bit is set
331 if ((++led_on % 2000) == 0)
335 // -------------------------------------------------------------------------
337 // This routine is called to respond to a hardware interrupt (IRQ). It
338 // should interrogate the hardware and return the IRQ vector number.
339 int hal_IRQ_handler(void)
341 #ifdef HAL_EXTENDED_IRQ_HANDLER
344 // Use platform specific IRQ handler, if defined
345 // Note: this macro should do a 'return' with the appropriate
346 // interrupt number if such an extended interrupt exists. The
347 // assumption is that the line after the macro starts 'normal' processing.
348 HAL_EXTENDED_IRQ_HANDLER(index);
351 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
358 void hal_interrupt_mask(int vector)
360 // diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
361 #ifdef HAL_EXTENDED_INTERRUPT_MASK
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_MASK(vector);
369 void hal_interrupt_unmask(int vector)
371 // diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
373 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
374 // Use platform specific handling, if defined
375 // Note: this macro should do a 'return' for "extended" values of 'vector'
376 // Normal vectors are handled by code subsequent to the macro call.
377 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
381 void hal_interrupt_acknowledge(int vector)
384 // diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
385 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
386 // Use platform specific handling, if defined
387 // Note: this macro should do a 'return' for "extended" values of 'vector'
388 // Normal vectors are handled by code subsequent to the macro call.
389 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
393 void hal_interrupt_configure(int vector, int level, int up)
396 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
397 // Use platform specific handling, if defined
398 // Note: this macro should do a 'return' for "extended" values of 'vector'
399 // Normal vectors are handled by code subsequent to the macro call.
400 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
404 void hal_interrupt_set_level(int vector, int level)
407 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
408 // Use platform specific handling, if defined
409 // Note: this macro should do a 'return' for "extended" values of 'vector'
410 // Normal vectors are handled by code subsequent to the macro call.
411 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
414 // Interrupt priorities are not configurable.
417 static void check_correct_chip(void)
419 if (find_correct_chip == CHIP_VERSION_UNKNOWN) {
420 diag_printf("Unrecognized chip version: 0x%x!!!\n", read_system_rev());
421 diag_printf("Assuming chip version=0x%x\n", system_rev);
422 } else if (find_correct_chip == CHIP_VERSION_NONE) {
423 diag_printf("Unrecognized chip: 0x%x!!!\n", readl(IIM_BASE_ADDR + IIM_PREV_OFF));
427 RedBoot_init(check_correct_chip, RedBoot_INIT_LAST);