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 #define IIM_PROD_REV_SH 3
63 #define IIM_PROD_REV_LEN 5
64 #define IIM_SREV_REV_SH 4
65 #define IIM_SREV_REV_LEN 4
66 #define PART_NUMBER_OFFSET (12)
67 #define MAJOR_NUMBER_OFFSET (4)
68 #define MINOR_NUMBER_OFFSET (0)
69 // Most initialization has already been done before we get here.
70 // All we do here is set up the interrupt environment.
72 unsigned int system_rev;
74 externC void plf_hardware_init(void);
76 char HAL_PLATFORM_EXTRA[20] = "PASS x.x [x32 SDR]";
78 void hal_hardware_init(void)
80 volatile unsigned int temp;
81 volatile unsigned int esdctl0 = readl(SOC_ESDCTL_BASE);
82 volatile unsigned int v;
84 sys_ver = readl(SOC_SI_ID_REG) >> 28 ;
86 system_rev = 0x27 << PART_NUMBER_OFFSET;
89 case SOC_SILICONID_Rev1_0:
90 HAL_PLATFORM_EXTRA[5] = '1';
91 HAL_PLATFORM_EXTRA[7] = '0';
92 system_rev |= 1 << MAJOR_NUMBER_OFFSET;
93 system_rev |= 0 << MINOR_NUMBER_OFFSET;
95 case SOC_SILICONID_Rev2_0:
96 HAL_PLATFORM_EXTRA[5] = '2';
97 HAL_PLATFORM_EXTRA[7] = '0';
98 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
99 system_rev |= 0 << MINOR_NUMBER_OFFSET;
101 case SOC_SILICONID_Rev2_1:
102 HAL_PLATFORM_EXTRA[5] = '2';
103 HAL_PLATFORM_EXTRA[7] = '1';
104 system_rev |= 2 << MAJOR_NUMBER_OFFSET;
105 system_rev |= 1 << MINOR_NUMBER_OFFSET;
109 if ((esdctl0 & 0x20000) == 0x0) {
110 HAL_PLATFORM_EXTRA[11] = '1';
111 HAL_PLATFORM_EXTRA[12] = '6';
114 // enable user mode SOC register accesses
115 writel(1, SOC_AIPI1_BASE + SOC_AIPI_PAR_OFF);
116 writel(1, SOC_AIPI2_BASE + SOC_AIPI_PAR_OFF);
118 // Enable clko and divide it by 8
119 v = readl(SOC_CRM_PCDR0);
121 writel(v, SOC_CRM_PCDR0);
122 // Default for core clock
123 writel(0x7, SOC_CRM_CCSR);
124 // Enable clocks for FEC, GPIO, GPT2, IIM
125 writel(0x06810000, SOC_CRM_PCCR0);
126 // Enable clocks for UARTs, BROM, EMI, HCLK_FEC, PERCLK1, NFC
127 writel(0xFC4A0408, SOC_CRM_PCCR1);
129 // Mask all interrupts
130 writel(0xFFFFFFFF, SOC_AITC_NIMASK);
132 // Make all interrupts do IRQ and not FIQ
133 writel(0, SOC_AITC_INTTYPEH);
134 writel(0, SOC_AITC_INTTYPEL);
136 // Disable all GPIO interrupt sources
142 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
143 // increase the WDOG timeout value to the max
144 writew(readw(WDOG_BASE_ADDR) | 0xFF00, WDOG_BASE_ADDR);
147 // Perform any platform specific initializations
150 // Set up eCos/ROM interfaces
153 // init timer2 and start it -- use 32KHz clock
155 writel(0x4, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // counter reset when timer is disabled
156 writel(0x0, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // disable timer
158 writel(0x00008000, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // reset timer
159 while((readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET) & 0x8000) != 0); // make sure reset complete
161 writel(0x0, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // disable timer
162 writel(0, SOC_GPT2_BASE + GPT_TPRER_OFFSET);
163 temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
164 writel(temp | 0x00000100, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // free-run mode
165 temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
166 writel(temp | 0x00000008, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // 32KHz to prescaler
167 temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
168 writel(temp | 0x00000001, SOC_GPT2_BASE + GPT_TCTL_OFFSET); //enable timer
170 hal_delay_us(MX_STARTUP_DELAY);
173 // -------------------------------------------------------------------------
174 void hal_clock_initialize(cyg_uint32 period)
178 // This routine is called during a clock interrupt.
180 // Define this if you want to ensure that the clock is perfect (i.e. does
181 // not drift). One reason to leave it turned off is that it costs some
182 // us per system clock interrupt for this maintenance.
183 #undef COMPENSATE_FOR_CLOCK_DRIFT
185 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
189 // Read the current value of the clock, returning the number of hardware
190 // "ticks" that have occurred (i.e. how far away the current value is from
193 // Note: The "contract" for this function is that the value is the number
194 // of hardware clocks that have happened since the last interrupt (i.e.
195 // when it was reset). This value is used to measure interrupt latencies.
196 // However, since the hardware counter runs freely, this routine computes
197 // the difference between the current clock period and the number of hardware
198 // ticks left before the next timer interrupt.
199 void hal_clock_read(cyg_uint32 *pvalue)
203 // This is to cope with the test read used by tm_basic with
204 // CYGVAR_KERNEL_COUNTERS_CLOCK_LATENCY defined; we read the count ASAP
205 // in the ISR, *before* resetting the clock. Which returns 1tick +
206 // latency if we just use plain hal_clock_read().
207 void hal_clock_latency(cyg_uint32 *pvalue)
211 unsigned int hal_timer_count(void)
213 return readl(HAL_DELAY_TIMER + GPT_TCN_OFFSET);
216 #define WDT_MAGIC_1 0x5555
217 #define WDT_MAGIC_2 0xAAAA
218 #define MXC_WDT_WSR 0x2
220 static unsigned int led_on = 0;
222 // Delay for some number of micro-seconds
224 void hal_delay_us(unsigned int usecs)
226 unsigned long timerCount, timerCompare;
227 unsigned int delayCount = (usecs * 512) / 15625;
228 //diag_printf("entering mx2 hal_delay_us: %d, delaycount = %d, system_rev = %d\n\n", usecs, delayCount, system_rev);
230 if (delayCount == 0) {
234 // issue the service sequence instructions
235 if ((readw(WDOG_BASE_ADDR) & 4) != 0) {
236 writew(WDT_MAGIC_1, WDOG_BASE_ADDR + MXC_WDT_WSR);
237 writew(WDT_MAGIC_2, WDOG_BASE_ADDR + MXC_WDT_WSR);
240 writel(0x03, HAL_DELAY_TIMER + GPT_TSTAT_OFFSET); // clear the compare status bit
241 timerCount = readl(HAL_DELAY_TIMER + GPT_TCN_OFFSET);
243 timerCompare = timerCount + delayCount;
245 writel(timerCompare, HAL_DELAY_TIMER + GPT_TCMP_OFFSET); // setup compare reg
247 while ((0x1 & readl(HAL_DELAY_TIMER + GPT_TSTAT_OFFSET)) == 0); // return until compare bit is set
248 writel(0x03, HAL_DELAY_TIMER + GPT_TSTAT_OFFSET); // clear the compare status bit
250 if ((++led_on % 3000) == 0)
254 // -------------------------------------------------------------------------
256 // This routine is called to respond to a hardware interrupt (IRQ). It
257 // should interrogate the hardware and return the IRQ vector number.
258 int hal_IRQ_handler(void)
260 #ifdef HAL_EXTENDED_IRQ_HANDLER
263 // Use platform specific IRQ handler, if defined
264 // Note: this macro should do a 'return' with the appropriate
265 // interrupt number if such an extended interrupt exists. The
266 // assumption is that the line after the macro starts 'normal' processing.
267 HAL_EXTENDED_IRQ_HANDLER(index);
270 return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
277 void hal_interrupt_mask(int vector)
279 // diag_printf("6hal_interrupt_mask(vector=%d) \n", vector);
280 #ifdef HAL_EXTENDED_INTERRUPT_MASK
281 // Use platform specific handling, if defined
282 // Note: this macro should do a 'return' for "extended" values of 'vector'
283 // Normal vectors are handled by code subsequent to the macro call.
284 HAL_EXTENDED_INTERRUPT_MASK(vector);
288 void hal_interrupt_unmask(int vector)
290 // diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
292 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
293 // Use platform specific handling, if defined
294 // Note: this macro should do a 'return' for "extended" values of 'vector'
295 // Normal vectors are handled by code subsequent to the macro call.
296 HAL_EXTENDED_INTERRUPT_UNMASK(vector);
300 void hal_interrupt_acknowledge(int vector)
303 // diag_printf("8hal_interrupt_acknowledge(vector=%d) \n", vector);
304 #ifdef HAL_EXTENDED_INTERRUPT_UNMASK
305 // Use platform specific handling, if defined
306 // Note: this macro should do a 'return' for "extended" values of 'vector'
307 // Normal vectors are handled by code subsequent to the macro call.
308 HAL_EXTENDED_INTERRUPT_ACKNOWLEDGE(vector);
312 void hal_interrupt_configure(int vector, int level, int up)
315 #ifdef HAL_EXTENDED_INTERRUPT_CONFIGURE
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_CONFIGURE(vector, level, up);
323 void hal_interrupt_set_level(int vector, int level)
326 #ifdef HAL_EXTENDED_INTERRUPT_SET_LEVEL
327 // Use platform specific handling, if defined
328 // Note: this macro should do a 'return' for "extended" values of 'vector'
329 // Normal vectors are handled by code subsequent to the macro call.
330 HAL_EXTENDED_INTERRUPT_SET_LEVEL(vector, level);
333 // Interrupt priorities are not configurable.
336 /*------------------------------------------------------------------------*/