]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/gth2/gth2.c
Initial revision
[karo-tx-uboot.git] / board / gth2 / gth2.c
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>
29 #include <watchdog.h>
30
31 #include "ee_access.h"
32
33 static int wdi_status = 0;
34
35 unsigned 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
42 void 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
59 void 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 */
64         memcpy(serial_log_buffer + 4096,
65                serial_log_buffer,
66                4096);
67
68         memset(serial_log_buffer, 0, 4096);
69
70         *serial_log_offsetp = 4;
71 }
72
73
74 void 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
87 long 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 */
98 void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 );
99
100 void 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);
121
122                 value<<=1;
123         }
124         /* Data is enable output */
125         *sys_outputset = GPIO_LEDD;
126 }
127
128 int 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)      \
202 do                              \
203 {                               \
204   *((volatile u16 *) (a)) = (d);\
205  } while(0)
206
207 static 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         }
231
232         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
243 static int random_system(void){
244         /* EEPROM read failed. Just try to choose one
245            system release and hope it works */
246
247         /* FIXME */
248         return(SYSTEM_BOOT);
249 }
250
251 static 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
292 static 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;
323                         if ((system != SYSTEM_BOOT) &
324                             (system != SYSTEM2_BOOT) &
325                             (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
382 int 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 }