unified MX27, MX25, MX37 trees
[karo-tx-redboot.git] / packages / hal / arm / mx27 / var / v2_0 / src / soc_misc.c
1 //==========================================================================
2 //
3 //      soc_misc.c
4 //
5 //      HAL misc board support code
6 //
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.
12 //
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.
16 //
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
20 // for more details.
21 //
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.
25 //
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.
32 //
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.
35 //
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 //========================================================================*/
41
42 #include <redboot.h>
43 #include <pkgconf/hal.h>
44 #include <pkgconf/system.h>
45 #include CYGBLD_HAL_PLATFORM_H
46
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
50
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
60 #include <cyg/infra/diag.h>             // diag_printf
61
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.
71
72 unsigned int system_rev;
73 int sys_ver;
74 externC void plf_hardware_init(void);
75
76 char HAL_PLATFORM_EXTRA[20] = "PASS x.x [x32 SDR]";
77
78 void hal_hardware_init(void)
79 {
80         unsigned int temp;
81         unsigned int esdctl0 = readl(SOC_ESDCTL_BASE);
82         unsigned int v;
83
84         sys_ver = readl(SOC_SI_ID_REG) >> 28 ;
85
86         system_rev = 0x27 << PART_NUMBER_OFFSET;
87
88         switch (sys_ver) {
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;
94                 break;
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;
100                 break;
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;
106                 break;
107         }
108
109         if ((esdctl0 & 0x20000) == 0x0) {
110                 HAL_PLATFORM_EXTRA[11] = '1';
111                 HAL_PLATFORM_EXTRA[12] = '6';
112         }
113
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);
117
118         // Enable clko and divide it by 8
119         v = readl(SOC_CRM_PCDR0);
120         v |= 0xF << 22;
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);
128
129         // Mask all interrupts
130         writel(0xFFFFFFFF, SOC_AITC_NIMASK);
131
132         // Make all interrupts do IRQ and not FIQ
133         writel(0, SOC_AITC_INTTYPEH);
134         writel(0, SOC_AITC_INTTYPEL);
135
136         // Disable all GPIO interrupt sources
137
138         // Enable caches
139         HAL_ICACHE_ENABLE();
140         HAL_DCACHE_ENABLE();
141
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);
145         }
146
147         // init timer2 and start it -- use 32KHz clock
148
149         writel(0x4, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // counter reset when timer is disabled
150         writel(0x0, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // disable timer
151
152         writel(0x00008000, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // reset timer
153         while((readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET) & 0x8000) != 0); // make sure reset complete
154
155         writel(0x0, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // disable timer
156         writel(0, SOC_GPT2_BASE + GPT_TPRER_OFFSET);
157         temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
158         writel(temp | 0x00000100, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // free-run mode
159         temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
160         writel(temp | 0x00000008, SOC_GPT2_BASE + GPT_TCTL_OFFSET); // 32KHz to prescaler
161         temp = readl(SOC_GPT2_BASE + GPT_TCTL_OFFSET);
162         writel(temp | 0x00000001, SOC_GPT2_BASE + GPT_TCTL_OFFSET); //enable timer
163
164         // Perform any platform specific initializations
165         plf_hardware_init();
166
167         // Set up eCos/ROM interfaces
168         hal_if_init();
169
170         hal_delay_us(MX_STARTUP_DELAY);
171 }
172
173 // -------------------------------------------------------------------------
174 void hal_clock_initialize(cyg_uint32 period)
175 {
176 }
177
178 // This routine is called during a clock interrupt.
179
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
184
185 void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
186 {
187 }
188
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
191 // the start)
192
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)
200 {
201 }
202
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)
208 {
209 }
210
211 unsigned int hal_timer_count(void)
212 {
213         return readl(HAL_DELAY_TIMER + GPT_TCN_OFFSET);
214 }
215
216 #define WDT_MAGIC_1             0x5555
217 #define WDT_MAGIC_2             0xAAAA
218 #define MXC_WDT_WSR             0x2
219
220 static unsigned int led_on = 0;
221 //
222 // Delay for some number of micro-seconds
223 //
224 void hal_delay_us(unsigned int usecs)
225 {
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);
229
230         if (delayCount == 0) {
231                 return;
232         }
233
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);
238         }
239
240         writel(0x03, HAL_DELAY_TIMER + GPT_TSTAT_OFFSET);      // clear the compare status bit
241         timerCount = readl(HAL_DELAY_TIMER + GPT_TCN_OFFSET);
242
243         timerCompare = timerCount + delayCount;
244
245         writel(timerCompare, HAL_DELAY_TIMER + GPT_TCMP_OFFSET);  // setup compare reg
246
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
249
250         if ((++led_on % 3000) == 0)
251                 BOARD_DEBUG_LED(0);
252 }
253
254 // -------------------------------------------------------------------------
255
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)
259 {
260 #ifdef HAL_EXTENDED_IRQ_HANDLER
261         cyg_uint32 index;
262
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);
268 #endif
269
270         return CYGNUM_HAL_INTERRUPT_NONE; // This shouldn't happen!
271 }
272
273 //
274 // Interrupt control
275 //
276
277 void hal_interrupt_mask(int vector)
278 {
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);
285 #endif
286 }
287
288 void hal_interrupt_unmask(int vector)
289 {
290         //    diag_printf("7hal_interrupt_unmask(vector=%d) \n", vector);
291
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);
297 #endif
298 }
299
300 void hal_interrupt_acknowledge(int vector)
301 {
302
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);
309 #endif
310 }
311
312 void hal_interrupt_configure(int vector, int level, int up)
313 {
314
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);
320 #endif
321 }
322
323 void hal_interrupt_set_level(int vector, int level)
324 {
325
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);
331 #endif
332
333         // Interrupt priorities are not configurable.
334 }
335
336 /*------------------------------------------------------------------------*/
337