blob: 72629ce2b3161c71da243bbbf9032126d2403f15 [file] [log] [blame]
wdenk4989f872004-03-14 15:06:13 +00001/*
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
Wolfgang Denkc856ccc2005-09-25 02:00:47 +020027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
wdenk4989f872004-03-14 15:06:13 +000028 * 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>
Sergei Poselenov29809c12008-08-14 14:08:28 +020037#include <div64.h>
wdenk4989f872004-03-14 15:06:13 +000038
Wolfgang Denk6405a152006-03-31 18:32:53 +020039DECLARE_GLOBAL_DATA_PTR;
40
wdenk4989f872004-03-14 15:06:13 +000041void flash__init (void);
42void ether__init (void);
43void peripheral_power_enable (void);
44
45#if defined(CONFIG_SHOW_BOOT_PROGRESS)
46void show_boot_progress(int progress)
47{
Wolfgang Denkadf20a12005-09-25 01:48:28 +020048 printf("Boot reached stage %d\n", progress);
wdenk4989f872004-03-14 15:06:13 +000049}
50#endif
51
52#define COMP_MODE_ENABLE ((unsigned int)0x0000EAEF)
53
wdenk4989f872004-03-14 15:06:13 +000054/*
55 * Miscellaneous platform dependent initialisations
56 */
57
58int board_init (void)
59{
wdenk4989f872004-03-14 15:06:13 +000060 /* arch number of Integrator Board */
wdenk767fbd42004-10-10 18:41:04 +000061 gd->bd->bi_arch_number = MACH_TYPE_CINTEGRATOR;
wdenk4989f872004-03-14 15:06:13 +000062
63 /* adress of boot parameters */
64 gd->bd->bi_boot_params = 0x00000100;
65
wdenk361f4a22004-07-11 18:10:30 +000066 gd->flags = 0;
67
Wolfgang Denkadf20a12005-09-25 01:48:28 +020068#ifdef CONFIG_CM_REMAP
69extern void cm_remap(void);
70 cm_remap(); /* remaps writeable memory to 0x00000000 */
71#endif
72
wdenk4989f872004-03-14 15:06:13 +000073 icache_enable ();
74
75 flash__init ();
76 ether__init ();
77 return 0;
78}
79
80
81int misc_init_r (void)
82{
83 setenv("verify", "n");
84 return (0);
85}
86
87/******************************
88 Routine:
89 Description:
90******************************/
91void flash__init (void)
92{
93}
94/*************************************************************
95 Routine:ether__init
96 Description: take the Ethernet controller out of reset and wait
Wolfgang Denkadf20a12005-09-25 01:48:28 +020097 for the EEPROM load to complete.
wdenk4989f872004-03-14 15:06:13 +000098*************************************************************/
99void ether__init (void)
100{
101}
102
103/******************************
104 Routine:
105 Description:
106******************************/
107int dram_init (void)
108{
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200109 gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200110 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200111
112#ifdef CONFIG_CM_SPD_DETECT
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200113 {
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200114extern void dram_query(void);
115 unsigned long cm_reg_sdram;
116 unsigned long sdram_shift;
117
118 dram_query(); /* Assembler accesses to CM registers */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200119 /* Queries the SPD values */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200120
121 /* Obtain the SDRAM size from the CM SDRAM register */
122
123 cm_reg_sdram = *(volatile ulong *)(CM_BASE + OS_SDRAM);
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200124 /* 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 *
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200132 */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200133 sdram_shift = ((cm_reg_sdram & 0x0000001C)/4)%4;
134 gd->bd->bi_dram[0].size = 0x01000000 << sdram_shift;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200135
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200136 }
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200137#endif /* CM_SPD_DETECT */
138
wdenk4989f872004-03-14 15:06:13 +0000139 return 0;
140}
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200141
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 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200146/* U-Boot expects a 32 bit timer, running at CONFIG_SYS_HZ */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200147/* Keep total timer count to avoid losing decrements < div_timer */
148static unsigned long long total_count = 0;
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200149static unsigned long long lastdec; /* Timer reading at last call */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200150static unsigned long long div_clock = 1; /* Divisor applied to timer clock */
151static unsigned long long div_timer = 1; /* Divisor to convert timer reading
152 * change to U-Boot ticks
153 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200154/* CONFIG_SYS_HZ = CONFIG_SYS_HZ_CLOCK/(div_clock * div_timer) */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200155static ulong timestamp; /* U-Boot ticks since startup */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200156
157#define TIMER_LOAD_VAL ((ulong)0xFFFFFFFF)
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200158#define READ_TIMER (*(volatile ulong *)(CONFIG_SYS_TIMERBASE+4))
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200159
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200160/* all function return values in U-Boot ticks i.e. (1/CONFIG_SYS_HZ) sec
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200161 * - unless otherwise stated
162 */
163
164/* starts up a counter
165 * - the Integrator/CP timer can be set up to issue an interrupt */
166int interrupt_init (void)
167{
168 /* Load timer with initial value */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200169 *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 0) = TIMER_LOAD_VAL;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200170 /* Set timer to be
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200171 * 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
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200178 */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200179 *(volatile ulong *)(CONFIG_SYS_TIMERBASE + 8) = 0x000000C2;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200180 /* init the timestamp */
181 total_count = 0ULL;
182 reset_timer_masked();
183
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200184 div_timer = (unsigned long long)(CONFIG_SYS_HZ_CLOCK / CONFIG_SYS_HZ);
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200185 div_timer /= div_clock;
186
187 return (0);
188}
189
190/*
191 * timer without interrupts
192 */
193void reset_timer (void)
194{
195 reset_timer_masked ();
196}
197
198ulong get_timer (ulong base_ticks)
199{
200 return get_timer_masked () - base_ticks;
201}
202
203void set_timer (ulong ticks)
204{
205 timestamp = ticks;
206 total_count = (unsigned long long)ticks * div_timer;
207}
208
209/* delay usec useconds */
210void udelay (unsigned long usec)
211{
212 ulong tmo, tmp;
213
214 /* Convert to U-Boot ticks */
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200215 tmo = usec * CONFIG_SYS_HZ;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200216 tmo /= (1000000L);
217
218 tmp = get_timer_masked(); /* get current timestamp */
219 tmo += tmp; /* form target timestamp */
220
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200221 while (get_timer_masked () < tmo) {/* loop till event */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200222 /*NOP*/;
223 }
224}
225
226void reset_timer_masked (void)
227{
228 /* capure current decrementer value */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200229 lastdec = (unsigned long long)READ_TIMER;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200230 /* start "advancing" time stamp from 0 */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200231 timestamp = 0L;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200232}
233
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200234/* converts the timer reading to U-Boot ticks */
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200235/* the timestamp is the number of ticks since reset */
236ulong get_timer_masked (void)
237{
238 /* get current count */
239 unsigned long long now = (unsigned long long)READ_TIMER;
240
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200241 if(now > lastdec) {
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200242 /* Must have wrapped */
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200243 total_count += lastdec + TIMER_LOAD_VAL + 1 - now;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200244 } else {
245 total_count += lastdec - now;
246 }
Wolfgang Denkc856ccc2005-09-25 02:00:47 +0200247 lastdec = now;
Sergei Poselenov29809c12008-08-14 14:08:28 +0200248
249 /* Reuse "now" */
250 now = total_count;
251 do_div(now, div_timer);
252 timestamp = now;
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200253
254 return timestamp;
255}
256
257/* waits specified delay value and resets timestamp */
258void 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 */
267unsigned 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 */
276ulong get_tbclk (void)
277{
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +0200278 return (ulong)(((unsigned long long)CONFIG_SYS_HZ_CLOCK)/div_clock);
Wolfgang Denkadf20a12005-09-25 01:48:28 +0200279}