uboot/board/gth2/gth2.c
<<
>>
Prefs
   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 <asm/io.h>
  30#include <watchdog.h>
  31
  32#include "ee_access.h"
  33
  34static int wdi_status = 0;
  35
  36#define SDRAM_SIZE ((64*1024*1024)-(12*4096))
  37
  38
  39#define SERIAL_LOG_BUFFER CKSEG1ADDR(SDRAM_SIZE + (8*4096))
  40
  41void 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
  58void 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 */
  63        memcpy(serial_log_buffer + 4096,
  64               serial_log_buffer,
  65               4096);
  66
  67        memset(serial_log_buffer, 0, 4096);
  68
  69        *serial_log_offsetp = 4;
  70}
  71
  72
  73void 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
  86phys_size_t initdram(int board_type)
  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 arch/mips/cpu/cpu.c */
  97void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 );
  98
  99void 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);
 120
 121                value<<=1;
 122        }
 123        /* Data is enable output */
 124        *sys_outputset = GPIO_LEDD;
 125}
 126
 127int 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
 138        proc_id = read_c0_prid();
 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        }
 149
 150        set_io_port_base(0);
 151
 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 */
 157                      CONFIG_SYS_PCMCIA_IO_BASE, /* Hi */
 158                      0x3C000017,         /* Lo0 */
 159                      0x3C200017);        /* Lo1 */
 160
 161        write_one_tlb(21,                   /* index */
 162                      0x01ffe000,           /* Pagemask, 16 MB pages */
 163                      CONFIG_SYS_PCMCIA_ATTR_BASE, /* Hi */
 164                      0x3D000017,           /* Lo0 */
 165                      0x3D200017);          /* Lo1 */
 166
 167        write_one_tlb(22,                   /* index */
 168                      0x01ffe000,           /* Pagemask, 16 MB pages */
 169                      CONFIG_SYS_PCMCIA_MEM_ADDR,  /* Hi */
 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)      \
 204do                              \
 205{                               \
 206  *((volatile u16 *) (a)) = (d);\
 207 } while(0)
 208
 209static void write_bootdata (volatile u16 * addr, u8 System, u8 Count)
 210{
 211        u16 data;
 212        volatile u16 *flash = (u16 *) (CONFIG_SYS_FLASH_BASE);
 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        }
 233
 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
 245static int random_system(void){
 246        /* EEPROM read failed. Just try to choose one
 247           system release and hope it works */
 248
 249        /* FIXME */
 250        return(SYSTEM_BOOT);
 251}
 252
 253static 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
 294static 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
 305        addr = (u16 *) (CONFIG_SYS_FLASH_BASE + BOOTDATA_OFFSET);
 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;
 325                        if ((system != SYSTEM_BOOT) &
 326                            (system != SYSTEM2_BOOT) &
 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
 384int 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 {
 434                setenv ("ethaddr", (char *)Rx);
 435        }
 436        return (0);
 437}
 438