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