123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437 |
- /*
- * (C) Copyright 2005
- * Thomas.Lange@corelatus.se
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
- #include <common.h>
- #include <command.h>
- #include <asm/au1x00.h>
- #include <asm/addrspace.h>
- #include <asm/mipsregs.h>
- #include <asm/io.h>
- #include <watchdog.h>
- #include "ee_access.h"
- static int wdi_status = 0;
- #define SDRAM_SIZE ((64*1024*1024)-(12*4096))
- #define SERIAL_LOG_BUFFER KSEG1ADDR(SDRAM_SIZE + (8*4096))
- void inline log_serial_char(char c){
- char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER;
- int serial_log_offset;
- u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER;
- serial_log_offset = *serial_log_offsetp;
- *(serial_log_buffer + serial_log_offset) = c;
- serial_log_offset++;
- if(serial_log_offset >= 4096){
- serial_log_offset = 4;
- }
- *serial_log_offsetp = serial_log_offset;
- }
- void init_log_serial(void){
- char *serial_log_buffer = (char*)SERIAL_LOG_BUFFER;
- u32 *serial_log_offsetp = (u32*)SERIAL_LOG_BUFFER;
- /* Copy buffer from last run */
- memcpy(serial_log_buffer + 4096,
- serial_log_buffer,
- 4096);
- memset(serial_log_buffer, 0, 4096);
- *serial_log_offsetp = 4;
- }
- void hw_watchdog_reset(void){
- volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
- volatile u32 *sys_outputclear = (volatile u32*)SYS_OUTPUTCLR;
- if(wdi_status){
- *sys_outputset = GPIO_CPU_LED|GPIO_WDI;
- wdi_status = 0;
- }
- else{
- *sys_outputclear = GPIO_CPU_LED|GPIO_WDI;
- wdi_status = 1;
- }
- }
- long int initdram(int board_type)
- {
- /* Sdram is setup by assembler code */
- /* If memory could be changed, we should return the true value here */
- WATCHDOG_RESET();
- return (SDRAM_SIZE);
- }
- /* In cpu/mips/cpu.c */
- void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 );
- void set_ledcard(u32 value){
- /* Clock 24 bits to led card */
- int i;
- volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
- volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR;
- /* Start with known values */
- *sys_outputclr = GPIO_LEDCLK|GPIO_LEDD;
- for(i=0;i<24;i++){
- if(value&0x00800000){
- *sys_outputset = GPIO_LEDD;
- }
- else{
- *sys_outputclr = GPIO_LEDD;
- }
- udelay(1);
- *sys_outputset = GPIO_LEDCLK;
- udelay(1);
- *sys_outputclr = GPIO_LEDCLK;
- udelay(1);
- value<<=1;
- }
- /* Data is enable output */
- *sys_outputset = GPIO_LEDD;
- }
- int checkboard (void)
- {
- volatile u32 *sys_counter = (volatile u32*)SYS_COUNTER_CNTRL;
- volatile u32 *sys_outputset = (volatile u32*)SYS_OUTPUTSET;
- volatile u32 *sys_outputclr = (volatile u32*)SYS_OUTPUTCLR;
- u32 proc_id;
- WATCHDOG_RESET();
- *sys_counter = 0x100; /* Enable 32 kHz oscillator for RTC/TOY */
- proc_id = read_c0_prid();
- switch (proc_id >> 24) {
- case 0:
- puts ("Board: GTH2\n");
- printf ("CPU: Au1000 500 MHz, id: 0x%02x, rev: 0x%02x\n",
- (proc_id >> 8) & 0xFF, proc_id & 0xFF);
- break;
- default:
- printf ("Unsupported cpu %d, proc_id=0x%x\n", proc_id >> 24, proc_id);
- }
- set_io_port_base(0);
- #ifdef CONFIG_IDE_PCMCIA
- /* PCMCIA is on a 36 bit physical address.
- We need to map it into a 32 bit addresses */
- write_one_tlb(20, /* index */
- 0x01ffe000, /* Pagemask, 16 MB pages */
- CFG_PCMCIA_IO_BASE, /* Hi */
- 0x3C000017, /* Lo0 */
- 0x3C200017); /* Lo1 */
- write_one_tlb(21, /* index */
- 0x01ffe000, /* Pagemask, 16 MB pages */
- CFG_PCMCIA_ATTR_BASE, /* Hi */
- 0x3D000017, /* Lo0 */
- 0x3D200017); /* Lo1 */
- write_one_tlb(22, /* index */
- 0x01ffe000, /* Pagemask, 16 MB pages */
- CFG_PCMCIA_MEM_ADDR, /* Hi */
- 0x3E000017, /* Lo0 */
- 0x3E200017); /* Lo1 */
- #endif /* CONFIG_IDE_PCMCIA */
- /* Wait for GPIO ports to become stable */
- udelay(5000); /* FIXME */
- /* Release reset of ethernet PHY chips */
- /* Always do this, because linux does not know about it */
- *sys_outputset = GPIO_ERESET;
- /* Kill FPGA:s */
- *sys_outputclr = GPIO_CACONFIG|GPIO_DPACONFIG;
- udelay(2);
- *sys_outputset = GPIO_CACONFIG|GPIO_DPACONFIG;
- /* Turn front led yellow */
- set_ledcard(0x00100000);
- return 0;
- }
- #define POWER_OFFSET 0xF0000
- #define SW_WATCHDOG_REASON 13
- #define BOOTDATA_OFFSET 0xF8000
- #define MAX_ATTEMPTS 5
- #define FAILSAFE_BOOT 1
- #define SYSTEM_BOOT 2
- #define SYSTEM2_BOOT 3
- #define WRITE_FLASH16(a, d) \
- do \
- { \
- *((volatile u16 *) (a)) = (d);\
- } while(0)
- static void write_bootdata (volatile u16 * addr, u8 System, u8 Count)
- {
- u16 data;
- volatile u16 *flash = (u16 *) (CFG_FLASH_BASE);
- switch(System){
- case FAILSAFE_BOOT:
- printf ("Setting failsafe boot in flash\n");
- break;
- case SYSTEM_BOOT:
- printf ("Setting system boot in flash\n");
- break;
- case SYSTEM2_BOOT:
- printf ("Setting system2 boot in flash\n");
- break;
- default:
- printf ("Invalid system data %u, setting failsafe\n", System);
- System = FAILSAFE_BOOT;
- }
- if ((Count < 1) | (Count > MAX_ATTEMPTS)) {
- printf ("Invalid boot count %u, setting 1\n", Count);
- Count = 1;
- }
- printf ("Boot attempt %d\n", Count);
- data = (System << 8) | Count;
- /* AMD 16 bit */
- WRITE_FLASH16 (&flash[0x555], 0xAAAA);
- WRITE_FLASH16 (&flash[0x2AA], 0x5555);
- WRITE_FLASH16 (&flash[0x555], 0xA0A0);
- WRITE_FLASH16 (addr, data);
- }
- static int random_system(void){
- /* EEPROM read failed. Just try to choose one
- system release and hope it works */
- /* FIXME */
- return(SYSTEM_BOOT);
- }
- static int switch_system(int old_system){
- u8 Rx[10];
- u8 Tx[5];
- int valid_release;
- if(old_system==FAILSAFE_BOOT){
- /* Find out which system release to use */
- /* Copy from nvram to scratchpad */
- Tx[0] = RECALL_MEMORY;
- Tx[1] = 7; /* Page */
- if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) {
- printf ("EE user page 7 recall failed\n");
- return (random_system());
- }
- Tx[0] = READ_SCRATCHPAD;
- if (ee_do_cpu_command (Tx, 2, Rx, 9, 1)) {
- printf ("EE user page 7 read failed\n");
- return (random_system());
- }
- /* Crc in 9:th byte */
- if (!ee_crc_ok (Rx, 8, *(Rx + 8))) {
- printf ("EE read failed, page 7. CRC error\n");
- return (random_system());
- }
- valid_release = Rx[7];
- if((valid_release==0xFF)|
- ((valid_release&1) == 0)){
- return(SYSTEM_BOOT);
- }
- else{
- return(SYSTEM2_BOOT);
- }
- }
- else{
- return(FAILSAFE_BOOT);
- }
- }
- static void check_boot_tries (void)
- {
- /* Count the number of boot attemps
- switch system if too many */
- int i;
- volatile u16 *addr;
- volatile u16 data;
- u8 system = FAILSAFE_BOOT;
- u8 count;
- addr = (u16 *) (CFG_FLASH_BASE + BOOTDATA_OFFSET);
- if (*addr == 0xFFFF) {
- printf ("*** No bootdata exists. ***\n");
- write_bootdata (addr, FAILSAFE_BOOT, 1);
- } else {
- /* Search for latest written bootdata */
- i = 0;
- while ((*(addr + 1) != 0xFFFF) & (i < 8000)) {
- addr++;
- i++;
- }
- if (i >= 8000) {
- /* Whoa, dont write any more */
- printf ("*** No bootdata found. Not updating flash***\n");
- } else {
- /* See how many times we have tried to boot real system */
- data = *addr;
- system = data >> 8;
- count = data & 0xFF;
- if ((system != SYSTEM_BOOT) &
- (system != SYSTEM2_BOOT) &
- (system != FAILSAFE_BOOT)) {
- printf ("*** Wrong system %d\n", system);
- system = FAILSAFE_BOOT;
- count = 1;
- } else {
- switch (count) {
- case 0:
- case 1:
- case 2:
- case 3:
- case 4:
- /* Try same system again if needed */
- count++;
- break;
- case 5:
- /* Switch system and reset tries */
- count = 1;
- system = switch_system(system);
- printf ("***Too many boot attempts, switching system***\n");
- break;
- default:
- /* Switch system, start over and hope it works */
- printf ("***Unexpected data on addr 0x%x, %u***\n",
- (u32) addr, data);
- count = 1;
- system = switch_system(system);
- }
- }
- write_bootdata (addr + 1, system, count);
- }
- }
- switch(system){
- case FAILSAFE_BOOT:
- printf ("Booting failsafe system\n");
- setenv ("bootargs", "panic=1 root=/dev/hda7");
- setenv ("bootcmd", "ide reset;disk 0x81000000 0:5;run addmisc;bootm");
- break;
- case SYSTEM_BOOT:
- printf ("Using normal system\n");
- setenv ("bootargs", "panic=1 root=/dev/hda4");
- setenv ("bootcmd", "ide reset;disk 0x81000000 0:2;run addmisc;bootm");
- break;
- case SYSTEM2_BOOT:
- printf ("Using normal system2\n");
- setenv ("bootargs", "panic=1 root=/dev/hda9");
- setenv ("bootcmd", "ide reset;disk 0x81000000 0:8;run addmisc;bootm");
- break;
- default:
- printf ("Invalid system %d\n", system);
- printf ("Hanging\n");
- while(1);
- }
- }
- int misc_init_r(void){
- u8 Rx[80];
- u8 Tx[5];
- int page;
- int read = 0;
- WATCHDOG_RESET();
- if (ee_init_cpu_data ()) {
- printf ("EEPROM init failed\n");
- return (0);
- }
- /* Check which release to boot */
- check_boot_tries ();
- /* Read the pages where ethernet address is stored */
- for (page = EE_USER_PAGE_0; page <= EE_USER_PAGE_0 + 2; page++) {
- /* Copy from nvram to scratchpad */
- Tx[0] = RECALL_MEMORY;
- Tx[1] = page;
- if (ee_do_cpu_command (Tx, 2, NULL, 0, 1)) {
- printf ("EE user page %d recall failed\n", page);
- return (0);
- }
- Tx[0] = READ_SCRATCHPAD;
- if (ee_do_cpu_command (Tx, 2, Rx + read, 9, 1)) {
- printf ("EE user page %d read failed\n", page);
- return (0);
- }
- /* Crc in 9:th byte */
- if (!ee_crc_ok (Rx + read, 8, *(Rx + read + 8))) {
- printf ("EE read failed, page %d. CRC error\n", page);
- return (0);
- }
- read += 8;
- }
- /* Add eos after eth addr */
- Rx[17] = 0;
- printf ("Ethernet addr read from eeprom: %s\n\n", Rx);
- if ((Rx[2] != ':') |
- (Rx[5] != ':') |
- (Rx[8] != ':') | (Rx[11] != ':') | (Rx[14] != ':')) {
- printf ("*** ethernet addr invalid, using default ***\n");
- } else {
- setenv ("ethaddr", (char *)Rx);
- }
- return (0);
- }
|