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.
65 unsigned int system_rev;
66 externC void plf_hardware_init(void);
68 char HAL_PLATFORM_EXTRA[20] = "PASS x.x [x32 SDR]";
70 void hal_hardware_init(void)
72 volatile unsigned int temp;
73 volatile unsigned int esdctl0 = readl(ESDCTL_BASE);
75 system_rev = readl(MX21_SI_ID_REG);
77 if (system_rev == MX21_SILICONID_Rev2_x) {
78 HAL_PLATFORM_EXTRA[5] = '2';
79 HAL_PLATFORM_EXTRA[7] = 'x';
80 } else if (system_rev == MX21_SILICONID_Rev3_0) {
81 HAL_PLATFORM_EXTRA[5] = '3';
82 HAL_PLATFORM_EXTRA[7] = '0';
83 } else if (system_rev == MX21_SILICONID_Rev3_1) {
84 HAL_PLATFORM_EXTRA[5] = '3';
85 HAL_PLATFORM_EXTRA[7] = '1';
88 if ((esdctl0 & 0x20000) == 0x0) {
89 HAL_PLATFORM_EXTRA[11] = '1';
90 HAL_PLATFORM_EXTRA[12] = '6';
93 // Mask all interrupts
94 writel(0xFFFFFFFF, MX21_AITC_NIMASK);
96 // Make all interrupts do IRQ and not FIQ
97 // FIXME: Change this if you use FIQs.
98 writel(0, MX21_AITC_INTTYPEH);
99 writel(0, MX21_AITC_INTTYPEL);
101 // Disable all GPIO interrupt sources
107 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
108 // increase the WDOG timeout value to the max
109 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
112 // Perform any platform specific initializations
115 // Set up eCos/ROM interfaces
118 //init timer2 and start it -- assuming that per clock 1 runs at 44MHz)
121 writel(0x4, MX21_Timer2_BASE + KHwTimerTCL); // counter reset when timer is disabled
122 writel(0x0, MX21_Timer2_BASE + KHwTimerTCL); // disable timer
124 writel(0x00008000, MX21_Timer2_BASE + KHwTimerTCL); // reset timer
125 while((readl(MX21_Timer2_BASE + KHwTimerTCL) & 0x8000) != 0); // make sure reset complete
127 writel(0x0, MX21_Timer2_BASE + KHwTimerTCL); // disable timer
128 writel(DelayTimerPresVal, MX21_Timer2_BASE + KHwTimerTPRER);
129 temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
130 writel(temp & (~0x00000100), MX21_Timer2_BASE + KHwTimerTCL); // restart mode
131 temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
132 writel(temp | 0x00000002, MX21_Timer2_BASE + KHwTimerTCL); // PERCLK1 to prescaler
133 temp = readl(MX21_Timer2_BASE + KHwTimerTCL);
134 writel(temp | 0x00000001, MX21_Timer2_BASE + KHwTimerTCL); //enable timer
136 hal_delay_us(MX_STARTUP_DELAY);
138 //Reset ethernet here
139 BitSetEIO(EIO_RESET_BASE);
141 BitClearEIO(EIO_RESET_BASE);
142 hal_delay_us(100000);
143 readb(BOARD_CS_UART_BASE + 1);
144 hal_delay_us(100000);
146 if (system_rev == MX21_SILICONID_Rev2_x) {
147 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR2);
148 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR3);
149 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR4);
150 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR5);
151 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR6);
152 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR7);
153 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR8);
154 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR10);
155 writel(0x7FFF7FFF, MX21_DSCR_BASE + DSCR11);
156 writel(0x7FC07FF8, MX21_DSCR_BASE + DSCR9);
160 // -------------------------------------------------------------------------
161 void hal_clock_initialize(cyg_uint32 period)
165 // This routine is called during a clock interrupt.
167 // Define this if you want to ensure that the clock is perfect (i.e. does
168 // not drift). One reason to leave it turned off is that it costs some
169 // us per system clock interrupt for this maintenance.
170 #undef COMPENSATE_FOR_CLOCK_DRIFT
172 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
176 // Read the current value of the clock, returning the number of hardware
177 // "ticks" that have occurred (i.e. how far away the current value is from
180 // Note: The "contract" for this function is that the value is the number
181 // of hardware clocks that have happened since the last interrupt (i.e.
182 // when it was reset). This value is used to measure interrupt latencies.
183 // However, since the hardware counter runs freely, this routine computes
184 // the difference between the current clock period and the number of hardware
185 // ticks left before the next timer interrupt.
186 void hal_clock_read(cyg_uint32 *pvalue)
190 // This is to cope with the test read used by tm_basic with
191 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
192 // in the ISR, *before* resetting the clock. Which returns 1tick +
193 // latency if we just use plain hal_clock_read().
194 void hal_clock_latency(cyg_uint32 *pvalue)
198 unsigned int hal_timer_count(void)
200 return readl(HAL_DELAY_TIMER_MX2 + KHwTimerTCN);
203 #define WDT_MAGIC_1 0x5555
204 #define WDT_MAGIC_2 0xAAAA
205 #define MXC_WDT_WSR 0x2
207 static unsigned int led_on = 0;
209 // Delay for some number of micro-seconds
211 void hal_delay_us(unsigned int usecs)
213 volatile unsigned long timerCount, timerCompare, tmp;
214 const unsigned long TIMERMAXCOUNT = 0xFFFFFFFF;
215 unsigned long delayCount = usecs * ((MX21_PERCLK1/(DelayTimerPresVal+1))/1000000);
216 //diag_printf("entering mx2 hal_delay_us: %d, delaycount = %d, system_rev = %d\n\n", usecs, delayCount, system_rev);
218 if (delayCount == 0) {
222 // issue the service sequence instructions
223 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
224 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
225 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
228 writel(0x03, HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT); // clear the compare status bit
229 timerCount = readl(HAL_DELAY_TIMER_MX2 + KHwTimerTCN);
232 tmp = TIMERMAXCOUNT - timerCount;
234 if (tmp < delayCount) {
235 timerCompare = delayCount - tmp;
237 timerCompare = delayCount + timerCount;
239 writel(timerCompare, HAL_DELAY_TIMER_MX2 + KHwTimerTCMP); // setup compare reg
241 while ( (0x1 & readl(HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT)) == 0 ); // return until compare bit is set
242 writel(0x03, HAL_DELAY_TIMER_MX2 + KHwTimerTSTAT); // clear the compare status bit
244 if ((++led_on % 2000) == 0)
248 // -------------------------------------------------------------------------
250 // This routine is called to respond to a hardware interrupt (IRQ). It
251 // should interrogate the hardware and return the IRQ vector number.
252 int hal_IRQ_handler(void)
254 #ifdef HAL_EXTENDED_IRQ_HANDLER
257 // Use platform specific IRQ handler, if defined
258 // Note: this macro should do a 'return' with the appropriate
259 // interrupt number if such an extended interrupt exists. The
260 // assumption is that the line after the macro starts 'normal' processing.
261 HAL_EXTENDED_IRQ_HANDLER(index);
264 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
270 void hal_interrupt_mask(int vector)
272 // diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
273 #ifdef HAL_EXTENDED_INTERRUPT_MASK
274 // Use platform specific handling, if defined
275 // Note: this macro should do a 'return' for "extended" values of 'vector'
276 // Normal vectors are handled by code subsequent to the macro call.
277 HAL_EXTENDED_INTERRUPT_MASK(vector);
281 void hal_interrupt_unmask(int vector)
283 // diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
285 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
286 // Use platform specific handling, if defined
287 // Note: this macro should do a 'return' for "extended" values of 'vector'
288 // Normal vectors are handled by code subsequent to the macro call.
289 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
293 void hal_interrupt_acknowledge(int vector)
296 // diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
297 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
298 // Use platform specific handling, if defined
299 // Note: this macro should do a 'return' for "extended" values of 'vector'
300 // Normal vectors are handled by code subsequent to the macro call.
301 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
305 void hal_interrupt_configure(int vector, int level, int up)
308 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
309 // Use platform specific handling, if defined
310 // Note: this macro should do a 'return' for "extended" values of 'vector'
311 // Normal vectors are handled by code subsequent to the macro call.
312 HAL_EXTENDED_INTERRUPT_CONFIGURE(vector, level, up);
316 void hal_interrupt_set_level(int vector, int level)
319 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
320 // Use platform specific handling, if defined
321 // Note: this macro should do a 'return' for "extended" values of 'vector'
322 // Normal vectors are handled by code subsequent to the macro call.
323 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
326 // Interrupt priorities are not configurable.
329 /*------------------------------------------------------------------------*/