Merge 'next' branch
[platform/kernel/u-boot.git] / board / integratorcp / integratorcp.c
1 /*
2  * (C) Copyright 2002
3  * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
4  * Marius Groeger <mgroeger@sysgo.de>
5  *
6  * (C) Copyright 2002
7  * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch>
8  *
9  * (C) Copyright 2003
10  * Texas Instruments, <www.ti.com>
11  * Kshitij Gupta <Kshitij@ti.com>
12  *
13  * (C) Copyright 2004
14  * ARM Ltd.
15  * Philippe Robin, <philippe.robin@arm.com>
16  *
17  * See file CREDITS for list of people who contributed to this
18  * project.
19  *
20  * This program is free software; you can redistribute it and/or
21  * modify it under the terms of the GNU General Public License as
22  * published by the Free Software Foundation; either version 2 of
23  * the License, or (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28  * GNU General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, write to the Free Software
32  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
33  * MA 02111-1307 USA
34  */
35
36 #include <common.h>
37 #include <div64.h>
38
39 DECLARE_GLOBAL_DATA_PTR;
40
41 void flash__init (void);
42 void ether__init (void);
43 void peripheral_power_enable (void);
44
45 #if defined(CONFIG_SHOW_BOOT_PROGRESS)
46 void show_boot_progress(int progress)
47 {
48         printf("Boot reached stage %d\n", progress);
49 }
50 #endif
51
52 #define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF)
53
54 /*
55  * Miscellaneous platform dependent initialisations
56  */
57
58 int board_init (void)
59 {
60         /* arch number of Integrator Board */
61         gd->bd->bi_arch_number = MACH_TYPE_CINTEGRATOR;
62
63         /* adress of boot parameters */
64         gd->bd->bi_boot_params = 0x00000100;
65
66         gd->flags = 0;
67
68 #ifdef CONFIG_CM_REMAP
69 extern void cm_remap(void);
70         cm_remap();     /* remaps writeable memory to 0x00000000 */
71 #endif
72
73         icache_enable ();
74
75         flash__init ();
76         ether__init ();
77         return 0;
78 }
79
80
81 int misc_init_r (void)
82 {
83         setenv("verify", "n");
84         return (0);
85 }
86
87 /******************************
88  Routine:
89  Description:
90 ******************************/
91 void flash__init (void)
92 {
93 }
94 /*************************************************************
95  Routine:ether__init
96  Description: take the Ethernet controller out of reset and wait
97               for the EEPROM load to complete.
98 *************************************************************/
99 void ether__init (void)
100 {
101 }
102
103 /******************************
104  Routine:
105  Description:
106 ******************************/
107 int dram_init (void)
108 {
109         gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
110         gd->bd->bi_dram[0].size  = PHYS_SDRAM_1_SIZE;
111
112 #ifdef CONFIG_CM_SPD_DETECT
113     {
114 extern void dram_query(void);
115         unsigned long cm_reg_sdram;
116         unsigned long sdram_shift;
117
118         dram_query();   /* Assembler accesses to CM registers */
119                         /* Queries the SPD values             */
120
121         /* Obtain the SDRAM size from the CM SDRAM register */
122
123         cm_reg_sdram = *(volatile ulong *)(CM_BASE + OS_SDRAM);
124         /*   Register         SDRAM size
125          *
126          *   0xXXXXXXbbb000bb    16 MB
127          *   0xXXXXXXbbb001bb    32 MB
128          *   0xXXXXXXbbb010bb    64 MB
129          *   0xXXXXXXbbb011bb   128 MB
130          *   0xXXXXXXbbb100bb   256 MB
131          *
132          */
133         sdram_shift              = ((cm_reg_sdram & 0x0000001C)/4)%4;
134         gd->bd->bi_dram[0].size  = 0x01000000 << sdram_shift;
135
136     }
137 #endif /* CM_SPD_DETECT */
138
139         return 0;
140 }
141
142 /* The Integrator/CP timer1 is clocked at 1MHz
143  * can be divided by 16 or 256
144  * and can be set up as a 32-bit timer
145  */
146 /* U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ */
147 /* Keep total timer count to avoid losing decrements < div_timer */
148 static unsigned long long total_count = 0;
149 static unsigned long long lastdec;       /* Timer reading at last call     */
150 static unsigned long long div_clock = 1; /* Divisor applied to timer clock */
151 static unsigned long long div_timer = 1; /* Divisor to convert timer reading
152                                           * change to U-Boot ticks
153                                           */
154 /* CONFIG_SYS_HZ = CONFIG_SYS_HZ_CLOCK/(div_clock * div_timer) */
155 static ulong timestamp;         /* U-Boot ticks since startup         */
156
157 #define TIMER_LOAD_VAL ((ulong)0xFFFFFFFF)
158 #define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4))
159
160 /* all function return values in U-Boot ticks i.e. (1/CONFIG_SYS_HZ) sec
161  *  - unless otherwise stated
162  */
163
164 /* starts up a counter
165  * - the Integrator/CP timer can be set up to issue an interrupt */
166 int interrupt_init (void)
167 {
168         /* Load timer with initial value */
169         *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL;
170         /* Set timer to be
171          *      enabled           1
172          *      periodic          1
173          *      no interrupts     0
174          *      X                 0
175          *      divider 1        00 == less rounding error
176          *      32 bit            1
177          *      wrapping          0
178          */
179         *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x000000C2;
180         /* init the timestamp */
181         total_count = 0ULL;
182         reset_timer_masked();
183
184         div_timer  = (unsigned long long)(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ);
185         div_timer /= div_clock;
186
187         return (0);
188 }
189
190 /*
191  * timer without interrupts
192  */
193 void reset_timer (void)
194 {
195         reset_timer_masked ();
196 }
197
198 ulong get_timer (ulong base_ticks)
199 {
200         return get_timer_masked () - base_ticks;
201 }
202
203 void set_timer (ulong ticks)
204 {
205         timestamp   = ticks;
206         total_count = (unsigned long long)ticks * div_timer;
207 }
208
209 /* delay usec useconds */
210 void udelay (unsigned long usec)
211 {
212         ulong tmo, tmp;
213
214         /* Convert to U-Boot ticks */
215         tmo  = usec * CONFIG_SYS_HZ;
216         tmo /= (1000000L);
217
218         tmp  = get_timer_masked();      /* get current timestamp */
219         tmo += tmp;                     /* form target timestamp */
220
221         while (get_timer_masked () < tmo) {/* loop till event */
222                 /*NOP*/;
223         }
224 }
225
226 void reset_timer_masked (void)
227 {
228         /* capure current decrementer value    */
229         lastdec   = (unsigned long long)READ_TIMER;
230         /* start "advancing" time stamp from 0 */
231         timestamp = 0L;
232 }
233
234 /* converts the timer reading to U-Boot ticks          */
235 /* the timestamp is the number of ticks since reset    */
236 ulong get_timer_masked (void)
237 {
238         /* get current count */
239         unsigned long long now = (unsigned long long)READ_TIMER;
240
241         if(now > lastdec) {
242                 /* Must have wrapped */
243                 total_count += lastdec + TIMER_LOAD_VAL + 1 - now;
244         } else {
245                 total_count += lastdec - now;
246         }
247         lastdec   = now;
248
249         /* Reuse "now" */
250         now = total_count;
251         do_div(now, div_timer);
252         timestamp = now;
253
254         return timestamp;
255 }
256
257 /* waits specified delay value and resets timestamp */
258 void udelay_masked (unsigned long usec)
259 {
260         udelay(usec);
261 }
262
263 /*
264  * This function is derived from PowerPC code (read timebase as long long).
265  * On ARM it just returns the timer value.
266  */
267 unsigned long long get_ticks(void)
268 {
269         return (unsigned long long)get_timer(0);
270 }
271
272 /*
273  * Return the timebase clock frequency
274  * i.e. how often the timer decrements
275  */
276 ulong get_tbclk (void)
277 {
278         return (ulong)(((unsigned long long)CONFIG_SYS_HZ_CLOCK)/div_clock);
279 }