]>
Commit | Line | Data |
---|---|---|
0c32d96d WD |
1 | /* |
2 | * (C) Copyright 2005 | |
3 | * Thomas.Lange@corelatus.se | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include <command.h> | |
26 | #include <asm/au1x00.h> | |
27 | #include <asm/addrspace.h> | |
28 | #include <asm/mipsregs.h> | |
5c15010e | 29 | #include <asm/io.h> |
0c32d96d WD |
30 | #include <watchdog.h> |
31 | ||
32 | #include "ee_access.h" | |
33 | ||
34 | static int wdi_status = 0; | |
35 | ||
0c32d96d WD |
36 | #define SDRAM_SIZE ((64*1024*1024)-(12*4096)) |
37 | ||
38 | ||
7daf2ebe | 39 | #define SERIAL_LOG_BUFFER CKSEG1ADDR(SDRAM_SIZE + (8*4096)) |
0c32d96d WD |
40 | |
41 | void inline log_serial_char(char c){ | |
42 | char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER; | |
43 | int serial_log_offset; | |
44 | u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER; | |
45 | ||
46 | serial_log_offset = *serial_log_offsetp; | |
47 | ||
48 | *(serial_log_buffer + serial_log_offset) = c; | |
49 | ||
50 | serial_log_offset++; | |
51 | ||
52 | if(serial_log_offset >= 4096){ | |
53 | serial_log_offset = 4; | |
54 | } | |
55 | *serial_log_offsetp = serial_log_offset; | |
56 | } | |
57 | ||
58 | void init_log_serial(void){ | |
59 | char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER; | |
60 | u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER; | |
61 | ||
62 | /* Copy buffer from last run */ | |
b87dfd28 WD |
63 | memcpy(serial_log_buffer + 4096, |
64 | serial_log_buffer, | |
0c32d96d WD |
65 | 4096); |
66 | ||
67 | memset(serial_log_buffer, 0, 4096); | |
68 | ||
b87dfd28 | 69 | *serial_log_offsetp = 4; |
0c32d96d WD |
70 | } |
71 | ||
72 | ||
73 | void hw_watchdog_reset(void){ | |
74 | volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET; | |
75 | volatile u32 *sys_outputclear = (volatile u32*)SYS_OUTPUTCLR; | |
76 | if(wdi_status){ | |
77 | *sys_outputset = GPIO_CPU_LED|GPIO_WDI; | |
78 | wdi_status = 0; | |
79 | } | |
80 | else{ | |
81 | *sys_outputclear = GPIO_CPU_LED|GPIO_WDI; | |
82 | wdi_status = 1; | |
83 | } | |
84 | } | |
85 | ||
9973e3c6 | 86 | phys_size_t initdram(int board_type) |
0c32d96d WD |
87 | { |
88 | /* Sdram is setup by assembler code */ | |
89 | /* If memory could be changed, we should return the true value here */ | |
90 | ||
91 | WATCHDOG_RESET(); | |
92 | ||
93 | return (SDRAM_SIZE); | |
94 | } | |
95 | ||
96 | /* In cpu/mips/cpu.c */ | |
97 | void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 ); | |
98 | ||
99 | void set_ledcard(u32 value){ | |
100 | /* Clock 24 bits to led card */ | |
101 | int i; | |
102 | volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET; | |
103 | volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR; | |
104 | ||
105 | /* Start with known values */ | |
106 | *sys_outputclr = GPIO_LEDCLK|GPIO_LEDD; | |
107 | ||
108 | for(i=0;i<24;i++){ | |
109 | if(value&0x00800000){ | |
110 | *sys_outputset = GPIO_LEDD; | |
111 | } | |
112 | else{ | |
113 | *sys_outputclr = GPIO_LEDD; | |
114 | } | |
115 | udelay(1); | |
116 | *sys_outputset = GPIO_LEDCLK; | |
117 | udelay(1); | |
118 | *sys_outputclr = GPIO_LEDCLK; | |
119 | udelay(1); | |
b87dfd28 | 120 | |
0c32d96d WD |
121 | value<<=1; |
122 | } | |
123 | /* Data is enable output */ | |
124 | *sys_outputset = GPIO_LEDD; | |
125 | } | |
126 | ||
127 | int checkboard (void) | |
128 | { | |
129 | volatile u32 *sys_counter = (volatile u32*)SYS_COUNTER_CNTRL; | |
130 | volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET; | |
131 | volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR; | |
132 | u32 proc_id; | |
133 | ||
134 | WATCHDOG_RESET(); | |
135 | ||
136 | *sys_counter = 0x100; /* Enable 32 kHz oscillator for RTC/TOY */ | |
137 | ||
e2ad8426 | 138 | proc_id = read_c0_prid(); |
0c32d96d WD |
139 | |
140 | switch (proc_id >> 24) { | |
141 | case 0: | |
142 | puts ("Board: GTH2\n"); | |
143 | printf ("CPU: Au1000 500 MHz, id: 0x%02x, rev: 0x%02x\n", | |
144 | (proc_id >> 8) & 0xFF, proc_id & 0xFF); | |
145 | break; | |
146 | default: | |
147 | printf ("Unsupported cpu %d, proc_id=0x%x\n", proc_id >> 24, proc_id); | |
148 | } | |
5c15010e JCPV |
149 | |
150 | set_io_port_base(0); | |
151 | ||
0c32d96d WD |
152 | #ifdef CONFIG_IDE_PCMCIA |
153 | /* PCMCIA is on a 36 bit physical address. | |
154 | We need to map it into a 32 bit addresses */ | |
155 | write_one_tlb(20, /* index */ | |
156 | 0x01ffe000, /* Pagemask, 16 MB pages */ | |
6d0f6bcf | 157 | CONFIG_SYS_PCMCIA_IO_BASE, /* Hi */ |
0c32d96d WD |
158 | 0x3C000017, /* Lo0 */ |
159 | 0x3C200017); /* Lo1 */ | |
160 | ||
161 | write_one_tlb(21, /* index */ | |
162 | 0x01ffe000, /* Pagemask, 16 MB pages */ | |
6d0f6bcf | 163 | CONFIG_SYS_PCMCIA_ATTR_BASE, /* Hi */ |
0c32d96d WD |
164 | 0x3D000017, /* Lo0 */ |
165 | 0x3D200017); /* Lo1 */ | |
166 | ||
167 | write_one_tlb(22, /* index */ | |
168 | 0x01ffe000, /* Pagemask, 16 MB pages */ | |
6d0f6bcf | 169 | CONFIG_SYS_PCMCIA_MEM_ADDR, /* Hi */ |
0c32d96d WD |
170 | 0x3E000017, /* Lo0 */ |
171 | 0x3E200017); /* Lo1 */ | |
172 | ||
173 | #endif /* CONFIG_IDE_PCMCIA */ | |
174 | ||
175 | /* Wait for GPIO ports to become stable */ | |
176 | udelay(5000); /* FIXME */ | |
177 | ||
178 | /* Release reset of ethernet PHY chips */ | |
179 | /* Always do this, because linux does not know about it */ | |
180 | *sys_outputset = GPIO_ERESET; | |
181 | ||
182 | /* Kill FPGA:s */ | |
183 | *sys_outputclr = GPIO_CACONFIG|GPIO_DPACONFIG; | |
184 | udelay(2); | |
185 | *sys_outputset = GPIO_CACONFIG|GPIO_DPACONFIG; | |
186 | ||
187 | /* Turn front led yellow */ | |
188 | set_ledcard(0x00100000); | |
189 | ||
190 | return 0; | |
191 | } | |
192 | ||
193 | #define POWER_OFFSET 0xF0000 | |
194 | #define SW_WATCHDOG_REASON 13 | |
195 | ||
196 | #define BOOTDATA_OFFSET 0xF8000 | |
197 | #define MAX_ATTEMPTS 5 | |
198 | ||
199 | #define FAILSAFE_BOOT 1 | |
200 | #define SYSTEM_BOOT 2 | |
201 | #define SYSTEM2_BOOT 3 | |
202 | ||
203 | #define WRITE_FLASH16(a, d) \ | |
204 | do \ | |
205 | { \ | |
206 | *((volatile u16 *) (a)) = (d);\ | |
207 | } while(0) | |
208 | ||
209 | static void write_bootdata (volatile u16 * addr, u8 System, u8 Count) | |
210 | { | |
211 | u16 data; | |
6d0f6bcf | 212 | volatile u16 *flash = (u16 *) (CONFIG_SYS_FLASH_BASE); |
0c32d96d WD |
213 | |
214 | switch(System){ | |
215 | case FAILSAFE_BOOT: | |
216 | printf ("Setting failsafe boot in flash\n"); | |
217 | break; | |
218 | case SYSTEM_BOOT: | |
219 | printf ("Setting system boot in flash\n"); | |
220 | break; | |
221 | case SYSTEM2_BOOT: | |
222 | printf ("Setting system2 boot in flash\n"); | |
223 | break; | |
224 | default: | |
225 | printf ("Invalid system data %u, setting failsafe\n", System); | |
226 | System = FAILSAFE_BOOT; | |
227 | } | |
228 | ||
229 | if ((Count < 1) | (Count > MAX_ATTEMPTS)) { | |
230 | printf ("Invalid boot count %u, setting 1\n", Count); | |
231 | Count = 1; | |
232 | } | |
b87dfd28 | 233 | |
0c32d96d WD |
234 | printf ("Boot attempt %d\n", Count); |
235 | ||
236 | data = (System << 8) | Count; | |
237 | /* AMD 16 bit */ | |
238 | WRITE_FLASH16 (&flash[0x555], 0xAAAA); | |
239 | WRITE_FLASH16 (&flash[0x2AA], 0x5555); | |
240 | WRITE_FLASH16 (&flash[0x555], 0xA0A0); | |
241 | ||
242 | WRITE_FLASH16 (addr, data); | |
243 | } | |
244 | ||
245 | static int random_system(void){ | |
b87dfd28 | 246 | /* EEPROM read failed. Just try to choose one |
0c32d96d | 247 | system release and hope it works */ |
b87dfd28 | 248 | |
0c32d96d WD |
249 | /* FIXME */ |
250 | return(SYSTEM_BOOT); | |
251 | } | |
252 | ||
253 | static int switch_system(int old_system){ | |
254 | u8 Rx[10]; | |
255 | u8 Tx[5]; | |
256 | int valid_release; | |
257 | ||
258 | if(old_system==FAILSAFE_BOOT){ | |
259 | /* Find out which system release to use */ | |
260 | ||
261 | /* Copy from nvram to scratchpad */ | |
262 | Tx[0] = RECALL_MEMORY; | |
263 | Tx[1] = 7; /* Page */ | |
264 | if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) { | |
265 | printf ("EE user page 7 recall failed\n"); | |
266 | return (random_system()); | |
267 | } | |
268 | ||
269 | Tx[0] = READ_SCRATCHPAD; | |
270 | if (ee_do_cpu_command (Tx, 2, Rx, 9, 1)) { | |
271 | printf ("EE user page 7 read failed\n"); | |
272 | return (random_system()); | |
273 | } | |
274 | /* Crc in 9:th byte */ | |
275 | if (!ee_crc_ok (Rx, 8, *(Rx + 8))) { | |
276 | printf ("EE read failed, page 7. CRC error\n"); | |
277 | return (random_system()); | |
278 | } | |
279 | ||
280 | valid_release = Rx[7]; | |
281 | if((valid_release==0xFF)| | |
282 | ((valid_release&1) == 0)){ | |
283 | return(SYSTEM_BOOT); | |
284 | } | |
285 | else{ | |
286 | return(SYSTEM2_BOOT); | |
287 | } | |
288 | } | |
289 | else{ | |
290 | return(FAILSAFE_BOOT); | |
291 | } | |
292 | } | |
293 | ||
294 | static void check_boot_tries (void) | |
295 | { | |
296 | /* Count the number of boot attemps | |
297 | switch system if too many */ | |
298 | ||
299 | int i; | |
300 | volatile u16 *addr; | |
301 | volatile u16 data; | |
302 | u8 system = FAILSAFE_BOOT; | |
303 | u8 count; | |
304 | ||
6d0f6bcf | 305 | addr = (u16 *) (CONFIG_SYS_FLASH_BASE + BOOTDATA_OFFSET); |
0c32d96d WD |
306 | |
307 | if (*addr == 0xFFFF) { | |
308 | printf ("*** No bootdata exists. ***\n"); | |
309 | write_bootdata (addr, FAILSAFE_BOOT, 1); | |
310 | } else { | |
311 | /* Search for latest written bootdata */ | |
312 | i = 0; | |
313 | while ((*(addr + 1) != 0xFFFF) & (i < 8000)) { | |
314 | addr++; | |
315 | i++; | |
316 | } | |
317 | if (i >= 8000) { | |
318 | /* Whoa, dont write any more */ | |
319 | printf ("*** No bootdata found. Not updating flash***\n"); | |
320 | } else { | |
321 | /* See how many times we have tried to boot real system */ | |
322 | data = *addr; | |
323 | system = data >> 8; | |
324 | count = data & 0xFF; | |
b87dfd28 WD |
325 | if ((system != SYSTEM_BOOT) & |
326 | (system != SYSTEM2_BOOT) & | |
0c32d96d WD |
327 | (system != FAILSAFE_BOOT)) { |
328 | printf ("*** Wrong system %d\n", system); | |
329 | system = FAILSAFE_BOOT; | |
330 | count = 1; | |
331 | } else { | |
332 | switch (count) { | |
333 | case 0: | |
334 | case 1: | |
335 | case 2: | |
336 | case 3: | |
337 | case 4: | |
338 | /* Try same system again if needed */ | |
339 | count++; | |
340 | break; | |
341 | ||
342 | case 5: | |
343 | /* Switch system and reset tries */ | |
344 | count = 1; | |
345 | system = switch_system(system); | |
346 | printf ("***Too many boot attempts, switching system***\n"); | |
347 | break; | |
348 | default: | |
349 | /* Switch system, start over and hope it works */ | |
350 | printf ("***Unexpected data on addr 0x%x, %u***\n", | |
351 | (u32) addr, data); | |
352 | count = 1; | |
353 | system = switch_system(system); | |
354 | } | |
355 | } | |
356 | write_bootdata (addr + 1, system, count); | |
357 | } | |
358 | } | |
359 | switch(system){ | |
360 | case FAILSAFE_BOOT: | |
361 | printf ("Booting failsafe system\n"); | |
362 | setenv ("bootargs", "panic=1 root=/dev/hda7"); | |
363 | setenv ("bootcmd", "ide reset;disk 0x81000000 0:5;run addmisc;bootm"); | |
364 | break; | |
365 | ||
366 | case SYSTEM_BOOT: | |
367 | printf ("Using normal system\n"); | |
368 | setenv ("bootargs", "panic=1 root=/dev/hda4"); | |
369 | setenv ("bootcmd", "ide reset;disk 0x81000000 0:2;run addmisc;bootm"); | |
370 | break; | |
371 | ||
372 | case SYSTEM2_BOOT: | |
373 | printf ("Using normal system2\n"); | |
374 | setenv ("bootargs", "panic=1 root=/dev/hda9"); | |
375 | setenv ("bootcmd", "ide reset;disk 0x81000000 0:8;run addmisc;bootm"); | |
376 | break; | |
377 | default: | |
378 | printf ("Invalid system %d\n", system); | |
379 | printf ("Hanging\n"); | |
380 | while(1); | |
381 | } | |
382 | } | |
383 | ||
384 | int misc_init_r(void){ | |
385 | u8 Rx[80]; | |
386 | u8 Tx[5]; | |
387 | int page; | |
388 | int read = 0; | |
389 | ||
390 | WATCHDOG_RESET(); | |
391 | ||
392 | if (ee_init_cpu_data ()) { | |
393 | printf ("EEPROM init failed\n"); | |
394 | return (0); | |
395 | } | |
396 | ||
397 | /* Check which release to boot */ | |
398 | check_boot_tries (); | |
399 | ||
400 | /* Read the pages where ethernet address is stored */ | |
401 | ||
402 | for (page = EE_USER_PAGE_0; page <= EE_USER_PAGE_0 + 2; page++) { | |
403 | /* Copy from nvram to scratchpad */ | |
404 | Tx[0] = RECALL_MEMORY; | |
405 | Tx[1] = page; | |
406 | if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) { | |
407 | printf ("EE user page %d recall failed\n", page); | |
408 | return (0); | |
409 | } | |
410 | ||
411 | Tx[0] = READ_SCRATCHPAD; | |
412 | if (ee_do_cpu_command (Tx, 2, Rx + read, 9, 1)) { | |
413 | printf ("EE user page %d read failed\n", page); | |
414 | return (0); | |
415 | } | |
416 | /* Crc in 9:th byte */ | |
417 | if (!ee_crc_ok (Rx + read, 8, *(Rx + read + 8))) { | |
418 | printf ("EE read failed, page %d. CRC error\n", page); | |
419 | return (0); | |
420 | } | |
421 | read += 8; | |
422 | } | |
423 | ||
424 | /* Add eos after eth addr */ | |
425 | Rx[17] = 0; | |
426 | ||
427 | printf ("Ethernet addr read from eeprom: %s\n\n", Rx); | |
428 | ||
429 | if ((Rx[2] != ':') | | |
430 | (Rx[5] != ':') | | |
431 | (Rx[8] != ':') | (Rx[11] != ':') | (Rx[14] != ':')) { | |
432 | printf ("*** ethernet addr invalid, using default ***\n"); | |
433 | } else { | |
7e14fc65 | 434 | setenv ("ethaddr", (char *)Rx); |
0c32d96d WD |
435 | } |
436 | return (0); | |
437 | } |