diff options
Diffstat (limited to 'board/gth2')
-rw-r--r-- | board/gth2/Makefile | 41 | ||||
-rw-r--r-- | board/gth2/config.mk | 42 | ||||
-rw-r--r-- | board/gth2/ee_access.c | 347 | ||||
-rw-r--r-- | board/gth2/ee_access.h | 30 | ||||
-rw-r--r-- | board/gth2/ee_dev.h | 96 | ||||
-rw-r--r-- | board/gth2/flash.c | 43 | ||||
-rw-r--r-- | board/gth2/gth2.c | 435 | ||||
-rw-r--r-- | board/gth2/lowlevel_init.S | 454 | ||||
-rw-r--r-- | board/gth2/u-boot.lds | 68 |
9 files changed, 1556 insertions, 0 deletions
diff --git a/board/gth2/Makefile b/board/gth2/Makefile new file mode 100644 index 0000000..8ef3a51 --- /dev/null +++ b/board/gth2/Makefile @@ -0,0 +1,41 @@ +# +# (C) Copyright 2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o ee_access.o +SOBJS = lowlevel_init.o + +$(LIB): .depend $(OBJS) $(SOBJS) + $(AR) crv $@ $(OBJS) $(SOBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/gth2/config.mk b/board/gth2/config.mk new file mode 100644 index 0000000..6d21ba1 --- /dev/null +++ b/board/gth2/config.mk @@ -0,0 +1,42 @@ +# +# (C) Copyright 2004-2005 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# 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 +# + +# +# AMD Alchemy AU1000, MIPS32 core +# + +ifeq ($(TBASE),0) +TEXT_BASE = 0 +else +ifeq ($(TBASE),1) +TEXT_BASE = 0xbfc10070 +else +ifeq ($(TBASE),2) +TEXT_BASE = 0xbfc30070 +else +## Only to make ordinary make work +TEXT_BASE = 0x90000000 +endif +endif +endif + diff --git a/board/gth2/ee_access.c b/board/gth2/ee_access.c new file mode 100644 index 0000000..e293139 --- /dev/null +++ b/board/gth2/ee_access.c @@ -0,0 +1,347 @@ +/* Module for handling DALLAS DS2438, smart battery monitor + Chip can store up to 40 bytes of user data in EEPROM, + perform temp, voltage and current measurements. + Chip also contains a unique serial number. + + Always read/write LSb first + + For documentaion, see data sheet for DS2438, 2438.pdf + + By Thomas.Lange@corelatus.com 001025 + + Copyright (C) 2000-2005 Corelatus AB */ + +/* 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/io.h> +#include "ee_dev.h" +#include "ee_access.h" + +/* static int Debug = 1; */ +#undef E_DEBUG +#define E_DEBUG(fmt,args...) /* */ +/* #define E_DEBUG(fmt,args...) printk("EEA:"fmt,##args); */ + +/* We dont have kernel functions */ +#define printk printf +#define KERN_DEBUG +#define KERN_ERR +#define EIO 1 + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +/* lookup table ripped from DS app note 17, understanding and using cyclic redundancy checks... */ + +static u8 crc_lookup[256] = { + 0, 94, 188, 226, 97, 63, 221, 131, + 194, 156, 126, 32, 163, 253, 31, 65, + 157, 195, 33, 127, 252, 162, 64, 30, + 95, 1, 227, 189, 62, 96, 130, 220, + 35, 125, 159, 193, 66, 28, 254, 160, + 225, 191, 93, 3, 128, 222, 60, 98, + 190, 224, 2, 92, 223, 129, 99, 61, + 124, 34, 192, 158, 29, 67, 161, 255, + 70, 24, 250, 164, 39, 121, 155, 197, + 132, 218, 56, 102, 229, 187, 89, 7, + 219, 133, 103, 57, 186, 228, 6, 88, + 25, 71, 165, 251, 120, 38, 196, 154, + 101, 59, 217, 135, 4, 90, 184, 230, + 167, 249, 27, 69, 198, 152, 122, 36, + 248, 166, 68, 26, 153, 199, 37, 123, + 58, 100, 134, 216, 91, 5, 231, 185, + 140, 210, 48, 110, 237, 179, 81, 15, + 78, 16, 242, 172, 47, 113, 147, 205, + 17, 79, 173, 243, 112, 46, 204, 146, + 211, 141, 111, 49, 178, 236, 14, 80, + 175, 241, 19, 77, 206, 144, 114, 44, + 109, 51, 209, 143, 12, 82, 176, 238, + 50, 108, 142, 208, 83, 13, 239, 177, + 240, 174, 76, 18, 145, 207, 45, 115, + 202, 148, 118, 40, 171, 245, 23, 73, + 8, 86, 180, 234, 105, 55, 213, 139, + 87, 9, 235, 181, 54, 104, 138, 212, + 149, 203, 41, 119, 244, 170, 72, 22, + 233, 183, 85, 11, 136, 214, 52, 106, + 43, 117, 151, 201, 74, 20, 246, 168, + 116, 42, 200, 150, 21, 75, 169, 247, + 182, 232, 10, 84, 215, 137, 107, 53 +}; + +static void +write_gpio_data(int value ){ + if(value){ + /* Tristate */ + gpio_tristate(GPIO_EEDQ); + } + else{ + /* Drive 0 */ + gpio_clear(GPIO_EEDQ); + } +} + +static u8 make_new_crc( u8 Old_crc, u8 New_value ){ + /* Compute a new checksum with new byte, using previous checksum as input + See DS app note 17, understanding and using cyclic redundancy checks... + Also see DS2438, page 11 */ + return( crc_lookup[Old_crc ^ New_value ]); +} + +int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ){ + /* Check if the checksum for this buffer is correct */ + u8 Curr_crc=0; + int i; + u8 *Curr_byte = Buffer; + + for(i=0;i<Len;i++){ + Curr_crc = make_new_crc( Curr_crc, *Curr_byte); + Curr_byte++; + } + E_DEBUG("Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc); + + if(Curr_crc == Crc){ + /* Good */ + return(TRUE); + } + printk(KERN_ERR"EE checksum error, Calculated CRC = 0x%x, read = 0x%x\n", Curr_crc, Crc); + return(FALSE); +} + +static void +set_idle(void){ + /* Send idle and keep start time + Continous 1 is idle */ + WRITE_PORT(1); +} + + +static int +do_cpu_reset(void){ + /* Release reset and verify that chip responds with presence pulse */ + int Retries=0; + while(Retries<15){ + udelay(RESET_LOW_TIME); + + /* Send reset */ + WRITE_PORT(0); + udelay(RESET_LOW_TIME); + + /* Release reset */ + WRITE_PORT(1); + + /* Wait for EEPROM to drive output */ + udelay(PRESENCE_TIMEOUT); + if(!READ_PORT){ + /* Ok, EEPROM is driving a 0 */ + E_DEBUG("Presence detected\n"); + if(Retries){ + E_DEBUG("Retries %d\n",Retries); + } + /* Make sure chip releases pin */ + udelay(PRESENCE_LOW_TIME); + return 0; + } + Retries++; + } + + printk(KERN_ERR"eeprom did not respond when releasing reset\n"); + + /* Make sure chip releases pin */ + udelay(PRESENCE_LOW_TIME); + + /* Set to idle again */ + set_idle(); + + return(-EIO); +} + +static u8 +read_cpu_byte(void){ + /* Read a single byte from EEPROM + Read LSb first */ + int i; + int Value; + u8 Result=0; + u32 Flags; + + E_DEBUG("Reading byte\n"); + + for(i=0;i<8;i++){ + /* Small delay between pulses */ + udelay(1); + +#ifdef __KERNEL__ + /* Disable irq */ + save_flags(Flags); + cli(); +#endif + + /* Pull down pin short time to start read + See page 26 in data sheet */ + + WRITE_PORT(0); + udelay(READ_LOW); + WRITE_PORT(1); + + /* Wait for chip to drive pin */ + udelay(READ_TIMEOUT); + + Value = READ_PORT; + if(Value) + Value=1; + +#ifdef __KERNEL__ + /* Enable irq */ + restore_flags(Flags); +#endif + + /* Wait for chip to release pin */ + udelay(TOTAL_READ_LOW-READ_TIMEOUT); + + /* LSb first */ + Result|=Value<<i; + /* E_DEBUG("Read %d\n",Value); */ + + } + + E_DEBUG("Read byte 0x%x\n",Result); + + return(Result); +} + +static void +write_cpu_byte(u8 Byte){ + /* Write a single byte to EEPROM + Write LSb first */ + int i; + int Value; + u32 Flags; + + E_DEBUG("Writing byte 0x%x\n",Byte); + + for(i=0;i<8;i++){ + /* Small delay between pulses */ + udelay(1); + Value = Byte&1; + +#ifdef __KERNEL__ + /* Disable irq */ + save_flags(Flags); + cli(); +#endif + + /* Pull down pin short time for a 1, long time for a 0 + See page 26 in data sheet */ + + WRITE_PORT(0); + if(Value){ + /* Write a 1 */ + udelay(WRITE_1_LOW); + } + else{ + /* Write a 0 */ + udelay(WRITE_0_LOW); + } + + WRITE_PORT(1); + +#ifdef __KERNEL__ + /* Enable irq */ + restore_flags(Flags); +#endif + + if(Value) + /* Wait for chip to read the 1 */ + udelay(TOTAL_WRITE_LOW-WRITE_1_LOW); + + /* E_DEBUG("Wrote %d\n",Value); */ + Byte>>=1; + } +} + +int ee_do_cpu_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ){ + /* Execute this command string, including + giving reset and setting to idle after command + if Rx_len is set, we read out data from EEPROM */ + int i; + + E_DEBUG("Command, Tx_len %d, Rx_len %d\n", Tx_len, Rx_len ); + + if(do_cpu_reset()){ + /* Failed! */ + return(-EIO); + } + + if(Send_skip) + /* Always send SKIP_ROM first to tell chip we are sending a command, + except when we read out rom data for chip */ + write_cpu_byte(SKIP_ROM); + + /* Always have Tx data */ + for(i=0;i<Tx_len;i++){ + write_cpu_byte(Tx[i]); + } + + if(Rx_len){ + for(i=0;i<Rx_len;i++){ + Rx[i]=read_cpu_byte(); + } + } + + set_idle(); + + E_DEBUG("Command done\n"); + + return(0); +} + +int ee_init_cpu_data(void){ + int i; + u8 Tx[10]; + + /* Leave it floting since altera is driving the same pin */ + set_idle(); + + /* Copy all User EEPROM data to scratchpad */ + for(i=0;i<USER_PAGES;i++){ + Tx[0]=RECALL_MEMORY; + Tx[1]=EE_USER_PAGE_0+i; + if(ee_do_cpu_command(Tx,2,NULL,0,TRUE)) return(-EIO); + } + + /* Make sure chip doesnt store measurements in NVRAM */ + Tx[0]=WRITE_SCRATCHPAD; + Tx[1]=0; /* Page */ + Tx[2]=9; + if(ee_do_cpu_command(Tx,3,NULL,0,TRUE)) return(-EIO); + + Tx[0]=COPY_SCRATCHPAD; + if(ee_do_cpu_command(Tx,2,NULL,0,TRUE)) return(-EIO); + + for(i=0;i<10;i++){ + udelay(1000); + } + + return(0); +} diff --git a/board/gth2/ee_access.h b/board/gth2/ee_access.h new file mode 100644 index 0000000..c21730e --- /dev/null +++ b/board/gth2/ee_access.h @@ -0,0 +1,30 @@ +/* By Thomas.Lange@Corelatus.com 001025 */ + +/* Definitions for EEPROM/VOLT METER DS2438 */ +/* Copyright (C) 2000-2005 Corelatus AB */ + +#ifndef INCeeaccessh +#define INCeeaccessh + +#include <asm/types.h> +#include "ee_dev.h" + +int ee_do_cpu_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ); +int ee_init_cpu_data(void); + +int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ); + +/* Defs for altera reg */ +#define EE_WRITE_SHIFT 8 /* bits to shift left */ +#define EE_READ_SHIFT 16 /* bits to shift left */ +#define EE_DONE 0x80000000 +#define EE_BUSY 0x40000000 +#define EE_ERROR 0x20000000 + +/* Commands */ +#define EE_CMD_NOP 0 +#define EE_CMD_INIT_RES 1 +#define EE_CMD_WR_BYTE 2 +#define EE_CMD_RD_BYTE 3 + +#endif /* INCeeaccessh */ diff --git a/board/gth2/ee_dev.h b/board/gth2/ee_dev.h new file mode 100644 index 0000000..acc3418 --- /dev/null +++ b/board/gth2/ee_dev.h @@ -0,0 +1,96 @@ +/* By Thomas.Lange@Corelatus.com 001025 */ +/* Definitions for EEPROM/VOLT METER DS2438 */ +/* Copyright (C) 2000-2005 Corelatus AB */ + +/* 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 + */ + +#ifndef INCeedevh +#define INCeedevh + +#define E_DEBUG(fmt,args...) if( Debug ) printk(KERN_DEBUG"EE: " fmt, ##args) + +/* MIPS */ +#define WRITE_PORT(Value) write_gpio_data(Value) + +#define READ_PORT (gpio_read()&GPIO_EEDQ) + +/* 64 bytes chip */ +#define EE_CHIP_SIZE 64 + +/* Board with new current resistor */ +#define EE_GTH_0304 1 + +/* new dsp and 64 MB SDRAM */ +#define EE_DSP_64 0x10 + +/* microsecs */ +/* Pull line down at least this long for reset pulse */ +#define RESET_LOW_TIME 490 + +/* Read presence pulse after we release reset pulse */ +#define PRESENCE_TIMEOUT 100 +#define PRESENCE_LOW_TIME 200 + +#define WRITE_0_LOW 60 +#define WRITE_1_LOW 1 +#define TOTAL_WRITE_LOW 60 + +#define READ_LOW 1 +#define READ_TIMEOUT 10 +#define TOTAL_READ_LOW 70 + +/* Rom function commands */ +#define READ_ROM 0x33 +#define MATCH_ROM 0x55 +#define SKIP_ROM 0xCC +#define SEARCH_ROM 0xF0 + + +/* Memory_command_function */ +#define WRITE_SCRATCHPAD 0x4E +#define READ_SCRATCHPAD 0xBE +#define COPY_SCRATCHPAD 0x48 +#define RECALL_MEMORY 0xB8 +#define CONVERT_TEMP 0x44 +#define CONVERT_VOLTAGE 0xB4 + +/* Chip is divided in 8 pages, 8 bytes each */ + +#define EE_PAGE_SIZE 8 + +/* All chip data we want are in page 0 */ + +/* Bytes in page 0 */ +#define EE_P0_STATUS 0 +#define EE_P0_TEMP_LSB 1 +#define EE_P0_TEMP_MSB 2 +#define EE_P0_VOLT_LSB 3 +#define EE_P0_VOLT_MSB 4 +#define EE_P0_CURRENT_LSB 5 +#define EE_P0_CURRENT_MSB 6 + + +/* 40 byte user data is located at page 3-7 */ +#define EE_USER_PAGE_0 3 +#define USER_PAGES 5 + +/* Layout of gth user pages usage */ +/* Bytes 0-16 ethernet addr in ascii ( len 17 ) */ + +#define EE_ETHERNET_OFFSET 0 + +#endif /* INCeedevh */ diff --git a/board/gth2/flash.c b/board/gth2/flash.c new file mode 100644 index 0000000..f96edff --- /dev/null +++ b/board/gth2/flash.c @@ -0,0 +1,43 @@ +/* + * (C) Copyright 2005 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * 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> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * flash_init() + * + * sets up flash_info and returns size of FLASH (bytes) + */ +unsigned long flash_init (void) +{ + printf ("Skipping flash_init\n"); + return (0); +} + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + printf ("write_buff not implemented\n"); + return (-1); +} diff --git a/board/gth2/gth2.c b/board/gth2/gth2.c new file mode 100644 index 0000000..77fc5b4 --- /dev/null +++ b/board/gth2/gth2.c @@ -0,0 +1,435 @@ +/* + * (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 <watchdog.h> + +#include "ee_access.h" + +static int wdi_status = 0; + +unsigned long mips_io_port_base = 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_32bit_cp0_register(CP0_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); + } +#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", Rx); + } + return (0); +} diff --git a/board/gth2/lowlevel_init.S b/board/gth2/lowlevel_init.S new file mode 100644 index 0000000..62e3657 --- /dev/null +++ b/board/gth2/lowlevel_init.S @@ -0,0 +1,454 @@ +/* Memory sub-system initialization code */ + +#include <config.h> +#include <version.h> +#include <asm/regdef.h> +#include <asm/au1x00.h> +#include <asm/mipsregs.h> + +#define CP0_Config0 $16 +#define MEM_1MS ((CFG_MHZ) * 1000) +#define GPIO_RJ1LY (1<<22) +#define GPIO_CFRESET (1<<10) + + .text + .set noreorder + .set mips32 + + .globl lowlevel_init +lowlevel_init: + /* + * Step 2) Establish Status Register + * (set BEV, clear ERL, clear EXL, clear IE) + */ + li t1, 0x00400000 + mtc0 t1, CP0_STATUS + + /* + * Step 3) Establish CP0 Config0 + * (set OD, set K0=3) + */ + li t1, 0x00080003 + mtc0 t1, CP0_CONFIG + + /* + * Step 4) Disable Watchpoint facilities + */ + li t1, 0x00000000 + mtc0 t1, CP0_WATCHLO + mtc0 t1, CP0_IWATCHLO + /* + * Step 5) Disable the performance counters + */ + mtc0 zero, CP0_PERFORMANCE + nop + + /* + * Step 6) Establish EJTAG Debug register + */ + mtc0 zero, CP0_DEBUG + nop + + /* + * Step 7) Establish Cause + * (set IV bit) + */ + li t1, 0x00800000 + mtc0 t1, CP0_CAUSE + + /* Establish Wired (and Random) */ + mtc0 zero, CP0_WIRED + nop + + /* No workaround if running from ram */ + lui t0, 0xffc0 + lui t3, 0xbfc0 + and t1, ra, t0 + bne t1, t3, noCacheJump + nop + + /*** From AMD YAMON ***/ + /* + * Step 8) Initialize the caches + */ + li t0, (16*1024) + li t1, 32 + li t2, 0x80000000 + addu t3, t0, t2 +cacheloop: + cache 0, 0(t2) + cache 1, 0(t2) + addu t2, t1 + bne t2, t3, cacheloop + nop + + /* Save return address */ + move t3, ra + + /* Run from cacheable space now */ + bal cachehere + nop +cachehere: + li t1, ~0x20000000 /* convert to KSEG0 */ + and t0, ra, t1 + addi t0, 5*4 /* 5 insns beyond cachehere */ + jr t0 + nop + + /* Restore return address */ + move ra, t3 + + /* + * Step 9) Initialize the TLB + */ + li t0, 0 # index value + li t1, 0x00000000 # entryhi value + li t2, 32 # 32 entries + +tlbloop: + /* Probe TLB for matching EntryHi */ + mtc0 t1, CP0_ENTRYHI + tlbp + nop + + /* Examine Index[P], 1=no matching entry */ + mfc0 t3, CP0_INDEX + li t4, 0x80000000 + and t3, t4, t3 + addiu t1, t1, 1 # increment t1 (asid) + beq zero, t3, tlbloop + nop + + /* Initialize the TLB entry */ + mtc0 t0, CP0_INDEX + mtc0 zero, CP0_ENTRYLO0 + mtc0 zero, CP0_ENTRYLO1 + mtc0 zero, CP0_PAGEMASK + tlbwi + + /* Do it again */ + addiu t0, t0, 1 + bne t0, t2, tlbloop + nop + + /* First setup pll:s to make serial work ok */ + /* We have a 12.5 MHz crystal */ + li t0, SYS_CPUPLL + li t1, 0x28 /* CPU clock, 500 MHz */ + sw t1, 0(t0) + sync + nop + nop + + /* wait 1mS for clocks to settle */ + li t1, MEM_1MS +1: add t1, -1 + bne t1, zero, 1b + nop + /* Setup AUX PLL */ + li t0, SYS_AUXPLL + li t1, 0 + sw t1, 0(t0) /* aux pll */ + sync + + /* Static memory controller */ + /* RCE0 - can not change while fetching, do so from icache */ + move t2, ra /* Store return address */ + bal getAddr + nop + +getAddr: + move t1, ra + move ra, t2 /* Move return addess back */ + + cache 0x14,0(t1) + cache 0x14,32(t1) + /*** /From YAMON ***/ + +noCacheJump: + + /* Static memory controller */ + + /* RCE0 AMD 29LV800 Flash */ + li t0, MEM_STCFG0 + li t1, 0x00000243 + sw t1, 0(t0) + + li t0, MEM_STTIME0 + li t1, 0x040181D7 /* FIXME */ + sw t1, 0(t0) + + li t0, MEM_STADDR0 + li t1, 0x11E03F80 + sw t1, 0(t0) + + /* RCE1 PCMCIA 250ns */ + li t0, MEM_STCFG1 + li t1, 0x00000002 + sw t1, 0(t0) + + li t0, MEM_STTIME1 + li t1, 0x280E3E07 + sw t1, 0(t0) + + li t0, MEM_STADDR1 + li t1, 0x10000000 + sw t1, 0(t0) + + /* RCE2 CP Altera */ + li t0, MEM_STCFG2 + li t1, 0x00000280 /* BE, EW */ + sw t1, 0(t0) + + li t0, MEM_STTIME2 + li t1, 0x0303000c + sw t1, 0(t0) + + li t0, MEM_STADDR2 + li t1, 0x10c03f80 /* 1 MB */ + sw t1, 0(t0) + + /* RCE3 DP Altera */ + li t0, MEM_STCFG3 + li t1, 0x00000280 /* BE, EW */ + sw t1, 0(t0) + + li t0, MEM_STTIME3 + li t1, 0x0303000c + sw t1, 0(t0) + + li t0, MEM_STADDR3 + li t1, 0x10e03f80 /* 1 MB */ + sw t1, 0(t0) + + sync + + /* Set peripherals to a known state */ + li t0, IC0_CFG0CLR + li t1, 0xFFFFFFFF + sw t1, 0(t0) + + li t0, IC0_CFG0CLR + sw t1, 0(t0) + + li t0, IC0_CFG1CLR + sw t1, 0(t0) + + li t0, IC0_CFG2CLR + sw t1, 0(t0) + + li t0, IC0_SRCSET + sw t1, 0(t0) + + li t0, IC0_ASSIGNSET + sw t1, 0(t0) + + li t0, IC0_WAKECLR + sw t1, 0(t0) + + li t0, IC0_RISINGCLR + sw t1, 0(t0) + + li t0, IC0_FALLINGCLR + sw t1, 0(t0) + + li t0, IC0_TESTBIT + li t1, 0x00000000 + sw t1, 0(t0) + sync + + li t0, IC1_CFG0CLR + li t1, 0xFFFFFFFF + sw t1, 0(t0) + + li t0, IC1_CFG0CLR + sw t1, 0(t0) + + li t0, IC1_CFG1CLR + sw t1, 0(t0) + + li t0, IC1_CFG2CLR + sw t1, 0(t0) + + li t0, IC1_SRCSET + sw t1, 0(t0) + + li t0, IC1_ASSIGNSET + sw t1, 0(t0) + + li t0, IC1_WAKECLR + sw t1, 0(t0) + + li t0, IC1_RISINGCLR + sw t1, 0(t0) + + li t0, IC1_FALLINGCLR + sw t1, 0(t0) + + li t0, IC1_TESTBIT + li t1, 0x00000000 + sw t1, 0(t0) + sync + + li t0, SYS_FREQCTRL0 + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, SYS_FREQCTRL1 + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, SYS_CLKSRC + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, SYS_PININPUTEN + li t1, 0x00000000 + sw t1, 0(t0) + sync + + li t0, 0xB1100100 + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, 0xB1400100 + li t1, 0x00000000 + sw t1, 0(t0) + + + li t0, SYS_WAKEMSK + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, SYS_WAKESRC + li t1, 0x00000000 + sw t1, 0(t0) + + /* wait 1mS before setup */ + li t1, MEM_1MS +1: add t1, -1 + bne t1, zero, 1b + nop + + +/* SDCS 0 SDRAM */ + li t0, MEM_SDMODE0 + li t1, 0x592CD1 + sw t1, 0(t0) + + li t0, MEM_SDMODE1 + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, MEM_SDMODE2 + li t1, 0x00000000 + sw t1, 0(t0) + +/* 64 MB SDRAM at addr 0 */ + li t0, MEM_SDADDR0 + li t1, 0x001003F0 + sw t1, 0(t0) + + + li t0, MEM_SDADDR1 + li t1, 0x00000000 + sw t1, 0(t0) + + li t0, MEM_SDADDR2 + li t1, 0x00000000 + sw t1, 0(t0) + + sync + + li t0, MEM_SDREFCFG + li t1, 0x880007A1 /* Disable */ + sw t1, 0(t0) + sync + + li t0, MEM_SDPRECMD + sw zero, 0(t0) + sync + + li t0, MEM_SDAUTOREF + sw zero, 0(t0) + sync + sw zero, 0(t0) + sync + + li t0, MEM_SDREFCFG + li t1, 0x8A0007A1 /* Enable */ + sw t1, 0(t0) + sync + + li t0, MEM_SDWRMD0 + li t1, 0x00000023 + sw t1, 0(t0) + sync + + /* wait 1mS after setup */ + li t1, MEM_1MS +1: add t1, -1 + bne t1, zero, 1b + nop + + /* Setup GPIO pins */ + + li t0, SYS_PINFUNC + li t1, 0x00007025 /* 0x8080 */ + sw t1, 0(t0) + + li t0, SYS_TRIOUTCLR + li t1, 0xFFFFFFFF /* 0x1FFF */ + sw t1, 0(t0) + + /* Turn yellow front led on */ + /* Release reset on CF */ + li t0, SYS_OUTPUTCLR + li t1, GPIO_RJ1LG + sw t1, 0(t0) + li t0, SYS_OUTPUTSET + li t1, GPIO_RJ1LY|GPIO_CFRESET + sw t1, 0(t0) + sync + j clearmem + nop + + .globl memtest +memtest: + /* Fill memory with address */ + li t0, 0x80000000 + li t1, 0xFFF000 /* 64 MB */ +mt0: sw t0, 0(t0) + add t1, -1 + add t0, 4 + bne t1, zero, mt0 + nop + nop + /* Verify addr */ + li t0, 0x80000000 + li t1, 0xFFF000 /* 64 MB */ +mt1: lw t2, 0(t0) + bne t0, t2, memhang + add t1, -1 + add t0, 4 + bne t1, zero, mt1 + nop + nop + .globl clearmem +clearmem: + /* Clear memory */ + li t0, 0x80000000 + li t1, 0xFFF000 /* 64 MB */ +mtc: sw zero, 0(t0) + add t1, -1 + add t0, 4 + bne t1, zero, mtc + nop + nop +memtestend: + j ra + nop + +memhang: + b memhang + nop diff --git a/board/gth2/u-boot.lds b/board/gth2/u-boot.lds new file mode 100644 index 0000000..8ba0b6d --- /dev/null +++ b/board/gth2/u-boot.lds @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2003-2005 + * Wolfgang Denk Engineering, <wd@denx.de> + * + * 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 + */ + +/* +OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips") +*/ +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips") +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .sdata : { *(.sdata) } + + _gp = ALIGN(16); + + __got_start = .; + .got : { *(.got) } + __got_end = .; + + .sdata : { *(.sdata) } + + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + uboot_end_data = .; + num_got_entries = (__got_end - __got_start) >> 2; + + . = ALIGN(4); + .sbss : { *(.sbss) } + .bss : { *(.bss) } + uboot_end = .; +} |