diff options
author | Kevin | 2014-11-15 11:48:36 +0800 |
---|---|---|
committer | Kevin | 2014-11-15 11:48:36 +0800 |
commit | d04075478d378d9e15f3e1abfd14b0bd124077d4 (patch) | |
tree | 733dd964582f388b9e3e367c249946cd32a2851f /board/gth | |
download | FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.gz FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.tar.bz2 FOSSEE-netbook-uboot-source-d04075478d378d9e15f3e1abfd14b0bd124077d4.zip |
init commit via android 4.4 uboot
Diffstat (limited to 'board/gth')
-rwxr-xr-x | board/gth/Makefile | 40 | ||||
-rwxr-xr-x | board/gth/README | 18 | ||||
-rwxr-xr-x | board/gth/config.mk | 40 | ||||
-rwxr-xr-x | board/gth/ee_access.c | 335 | ||||
-rwxr-xr-x | board/gth/ee_access.h | 16 | ||||
-rwxr-xr-x | board/gth/ee_dev.h | 85 | ||||
-rwxr-xr-x | board/gth/flash.c | 649 | ||||
-rwxr-xr-x | board/gth/gth.c | 595 | ||||
-rwxr-xr-x | board/gth/u-boot.lds | 130 |
9 files changed, 1908 insertions, 0 deletions
diff --git a/board/gth/Makefile b/board/gth/Makefile new file mode 100755 index 0000000..e14c12e --- /dev/null +++ b/board/gth/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000, 2001 +# 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 + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/gth/README b/board/gth/README new file mode 100755 index 0000000..241c70b --- /dev/null +++ b/board/gth/README @@ -0,0 +1,18 @@ +Written by Thomas.Lange@corelatus.com 010805 + +To make a system for gth that actually works ;-) +the variable TBASE needs to be set to 0,1 or 2 +depending on location where image is supposed to +be started from. +E.g. make TBASE=1 + +0: Start from RAM, base 0 + +1: Start from flash_base + 0x10070 + +2: Start from flash_base + 0x30070 + +When using 1 or 2, the image is supposed to be launched +from miniboot that boots the first U-Boot image found in +flash. +For miniboot code, description, see www.opensource.se diff --git a/board/gth/config.mk b/board/gth/config.mk new file mode 100755 index 0000000..3c80156 --- /dev/null +++ b/board/gth/config.mk @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000, 2001 +# 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 +# + +# +ifeq ($(TBASE),0) +TEXT_BASE = 0 +else +ifeq ($(TBASE),1) +TEXT_BASE = 0x80010070 +else +ifeq ($(TBASE),2) +TEXT_BASE = 0x80030070 +else +## Only to make ordinary make work +TEXT_BASE = 0x90000000 +endif +endif +endif + +OBJCFLAGS = --set-section-flags=.ppcenv=contents,alloc,load,data diff --git a/board/gth/ee_access.c b/board/gth/ee_access.c new file mode 100755 index 0000000..716c90e --- /dev/null +++ b/board/gth/ee_access.c @@ -0,0 +1,335 @@ +/* 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 */ + +#include <common.h> +#include <config.h> +#include <mpc8xx.h> + +#include <../board/gth/ee_dev.h> + +/* We dont have kernel functions */ +#define printk printf +#define KERN_DEBUG +#define KERN_ERR +#define EIO 1 + +static int Debug = 0; + +#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 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_reset(void){ + /* Release reset and verify that chip responds with presence pulse */ + int Retries = 0; + while(Retries<5){ + 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_byte(void){ + /* Read a single byte from EEPROM + Read LSb first */ + int i; + int Value; + u8 Result=0; +#ifndef CFG_IMMR + u32 Flags; +#endif + + E_DEBUG("Reading byte\n"); + + for(i=0;i<8;i++){ + /* Small delay between pulses */ + udelay(1); + +#ifndef CFG_IMMR + /* 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; + +#ifndef CFG_IMMR + /* 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 byte 0x%x\n",Result); + + return(Result); +} + +static void +write_byte(u8 Byte){ + /* Write a single byte to EEPROM + Write LSb first */ + int i; + int Value; +#ifndef CFG_IMMR + u32 Flags; +#endif + + E_DEBUG("Writing byte 0x%x\n",Byte); + + for(i=0;i<8;i++){ + /* Small delay between pulses */ + udelay(1); + Value = Byte&1; + +#ifndef CFG_IMMR + /* 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); + +#ifndef CFG_IMMR + /* Enable irq */ + restore_flags(Flags); +#endif + + if(Value) + /* Wait for chip to read the 1 */ + udelay(TOTAL_WRITE_LOW-WRITE_1_LOW); + Byte>>=1; + } +} + +int ee_do_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_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_byte(SKIP_ROM); + + /* Always have Tx data */ + for(i=0;i<Tx_len;i++){ + write_byte(Tx[i]); + } + + if(Rx_len){ + for(i=0;i<Rx_len;i++){ + Rx[i]=read_byte(); + } + } + + set_idle(); + + E_DEBUG("Command done\n"); + + return(0); +} + +int ee_init_data(void){ + int i; + u8 Tx[10]; + int tmp; + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + while(0){ + tmp = 1-tmp; + if(tmp) + immap->im_ioport.iop_padat &= ~PA_FRONT_LED; + else + immap->im_ioport.iop_padat |= PA_FRONT_LED; + udelay(1); + } + + /* Set port to open drain to be able to read data from + port without setting it to input */ + PORT_B_PAR &= ~PB_EEPROM; + PORT_B_ODR |= PB_EEPROM; + SET_PORT_B_OUTPUT(PB_EEPROM); + + /* Set idle mode */ + 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_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_command(Tx,3,NULL,0,TRUE)) return(-EIO); + + Tx[0]=COPY_SCRATCHPAD; + if(ee_do_command(Tx,2,NULL,0,TRUE)) return(-EIO); + + /* FIXME check status bit instead + Could take 10 ms to store in EEPROM */ + for(i=0;i<10;i++){ + udelay(1000); + } + + return(0); +} diff --git a/board/gth/ee_access.h b/board/gth/ee_access.h new file mode 100755 index 0000000..e847f2c --- /dev/null +++ b/board/gth/ee_access.h @@ -0,0 +1,16 @@ +/* By Thomas.Lange@Corelatus.com 001025 + + Definitions for EEPROM/VOLT METER DS2438 */ + +#ifndef INCeeaccessh +#define INCeeaccessh + +int ee_do_command( u8 *Tx, int Tx_len, u8 *Rx, int Rx_len, int Send_skip ); +int ee_init_data(void); +int ee_crc_ok( u8 *Buffer, int Len, u8 Crc ); + +#ifndef TRUE +#define TRUE 1 +#endif + +#endif /* INCeeaccessh */ diff --git a/board/gth/ee_dev.h b/board/gth/ee_dev.h new file mode 100755 index 0000000..417c7b6 --- /dev/null +++ b/board/gth/ee_dev.h @@ -0,0 +1,85 @@ +/* By Thomas.Lange@Corelatus.com 001025 + $Revision: 1.6 $ + + Definitions for EEPROM/VOLT METER DS2438 + Copyright (C) 2000-2001 Corelatus AB */ + +#ifndef INCeedevh +#define INCeedevh + +#define E_DEBUG(fmt,args...) if( Debug ) printk(KERN_DEBUG"EE: " fmt, ##args) + +#define PORT_B_PAR ((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbpar +#define PORT_B_ODR ((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbodr +#define PORT_B_DIR ((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdir +#define PORT_B_DAT ((volatile immap_t *)CFG_IMMR)->im_cpm.cp_pbdat + +#define SET_PORT_B_INPUT(Mask) PORT_B_DIR &= ~(Mask) +#define SET_PORT_B_OUTPUT(Mask) PORT_B_DIR |= Mask + +#define WRITE_PORT_B(Mask,Value) { \ + if (Value) PORT_B_DAT |= Mask; \ + else PORT_B_DAT &= ~(Mask); \ + } +#define WRITE_PORT(Value) WRITE_PORT_B(PB_EEPROM,Value) + +#define READ_PORT (PORT_B_DAT&PB_EEPROM) + +/* 64 bytes chip */ +#define EE_CHIP_SIZE 64 + +/* We use this resistor for measuring the current drain on 3.3V */ +#define CURRENT_RESISTOR 0.022 + +/* 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 80 +#define WRITE_1_LOW 2 +#define TOTAL_WRITE_LOW 80 + +#define READ_LOW 2 +#define READ_TIMEOUT 10 +#define TOTAL_READ_LOW 80 + +/*** 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 + +#endif /* INCeedevh */ diff --git a/board/gth/flash.c b/board/gth/flash.c new file mode 100755 index 0000000..41a5c50 --- /dev/null +++ b/board/gth/flash.c @@ -0,0 +1,649 @@ +/* + * (C) Copyright 2000 + * 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> +#include <mpc8xx.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + * Protection Flags: + */ +#define FLAG_PROTECT_SET 0x01 +#define FLAG_PROTECT_CLEAR 0x02 + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size_b0, size_b1; + int i; + + /*printf("faking");*/ + + return(0x1fffff); + + /* Init: no FLASHes known */ + for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) + { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) + { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + +#if 0 + if (FLASH_BASE1_PRELIM != 0x0) { + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + + if (size_b1 > size_b0) { + printf ("## ERROR: Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", + size_b1, size_b1<<20,size_b0, size_b0<<20); + + flash_info[0].flash_id = FLASH_UNKNOWN; + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[0].sector_count = -1; + flash_info[1].sector_count = -1; + flash_info[0].size = 0; + flash_info[1].size = 0; + return (0); + } + } else { +#endif + size_b1 = 0; + + /* Remap FLASH according to real size */ + memctl->memc_or0 = CFG_OR0_PRELIM; + memctl->memc_br0 = CFG_BR0_PRELIM; + + /* Re-do sizing to get full correct info */ + size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + + flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+monitor_flash_len-1, + &flash_info[0]); +#endif + + if (size_b1) + { + /* memctl->memc_or1 = CFG_OR1_PRELIM; + memctl->memc_br1 = CFG_BR1_PRELIM; */ + + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0), + &flash_info[1]); + + flash_get_offsets (CFG_FLASH_BASE + size_b0, &flash_info[1]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+monitor_flash_len-1, + &flash_info[1]); +#endif + } + else + { +/* memctl->memc_or1 = CFG_OR1_PRELIM; + FIXME memctl->memc_br1 = CFG_BR1_PRELIM; */ + + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + + return (size_b0 + size_b1); +} + + +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start adress table */ + if (info->flash_id & FLASH_BTYPE) + { + /* set sector offsets for bottom boot block type */ + for (i = 0; i < info->sector_count; i++) + { + info->start[i] = base + (i * 0x00040000); + } + } + else + { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + for (; i >= 0; i--) + { + info->start[i] = base + i * 0x00040000; + } + } + +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + +#if 0 + case FLASH_AM040B: + printf ("AM29F040B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM040T: + printf ("AM29F040T (4 Mbit, top boot sect)\n"); + break; +#endif + case FLASH_AM400B: + printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: + printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: + printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: + printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: + printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: + printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: + printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: + printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, + info->sector_count); + + printf (" Sector Start Addresses:"); + + for (i=0; i<info->sector_count; ++i) + { + if ((i % 5) == 0) + { + printf ("\n "); + } + + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " "); + } + + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; +#if 0 + ulong base = (ulong)addr; +#endif + ulong value; + + /* Write auto select command: read Manufacturer ID */ +#if 0 + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00900090; +#else + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x90909090; +#endif + + value = addr[0]; + + switch (value) + { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + break; + } + + value = addr[1]; /* device ID */ + + switch (value) + { +#if 0 + case AMD_ID_F040B: + info->flash_id += FLASH_AM040B; + info->sector_count = 8; + info->size = 0x00200000; + break; /* => 2 MB */ +#endif + case AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ +#if 0 /* enable when device IDs are available */ + case AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + + } + +#if 0 + /* set up sector start adress table */ + if (info->flash_id & FLASH_BTYPE) { + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x0000C000; + info->start[3] = base + 0x00010000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00020000) - 0x00060000; + } + } else { + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + } +#else + flash_get_offsets ((ulong)addr, &flash_info[0]); +#endif + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) + { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) + { + addr = (volatile unsigned long *)info->start[0]; +#if 0 + *addr = 0x00F000F0; /* reset bank */ +#else + *addr = 0xF0F0F0F0; /* reset bank */ +#endif + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + vu_long *addr = (vu_long*)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + +#if 0 + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00800080; + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; +#else + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0x80808080; + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; +#endif + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_long*)(info->start[sect]); +#if 0 + addr[0] = 0x00300030; +#else + addr[0] = 0x30303030; +#endif + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (vu_long*)(info->start[l_sect]); +#if 0 + while ((addr[0] & 0x00800080) != 0x00800080) +#else + while ((addr[0] & 0xFFFFFFFF) != 0xFFFFFFFF) +#endif + { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ + addr = (volatile unsigned long *)info->start[0]; +#if 0 + addr[0] = 0x00F000F0; /* reset bank */ +#else + addr[0] = 0xF0F0F0F0; /* reset bank */ +#endif + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<4 && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word(info, wp, data)); +} +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long*)(info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + +#if 0 + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00A000A0; +#else + addr[0x0555] = 0xAAAAAAAA; + addr[0x02AA] = 0x55555555; + addr[0x0555] = 0xA0A0A0A0; +#endif + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); +#if 0 + while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) +#else + while ((*((vu_long *)dest) & 0x80808080) != (data & 0x80808080)) +#endif + { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/gth/gth.c b/board/gth/gth.c new file mode 100755 index 0000000..b1fcbf5 --- /dev/null +++ b/board/gth/gth.c @@ -0,0 +1,595 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Adapted from FADS and other board config files to GTH by thomas@corelatus.com + * + * 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 <config.h> +#include <watchdog.h> +#include <mpc8xx.h> +#include "ee_access.h" +#include "ee_dev.h" + +#ifdef CONFIG_BDM +#undef printf +#define printf(a,...) /* nothing */ +#endif + + +int checkboard (void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + int Id = 0; + int Rev = 0; + u32 Pbdat; + + puts ("Board: "); + + /* Turn on leds and setup for reading rev and id */ + +#define PB_OUTS (PB_BLUE_LED|PB_ID_GND) +#define PB_INS (PB_ID_0|PB_ID_1|PB_ID_2|PB_ID_3|PB_REV_1|PB_REV_0) + + immap->im_cpm.cp_pbpar &= ~(PB_OUTS | PB_INS); + + immap->im_cpm.cp_pbdir &= ~PB_INS; + + immap->im_cpm.cp_pbdir |= PB_OUTS; + immap->im_cpm.cp_pbodr |= PB_OUTS; + immap->im_cpm.cp_pbdat &= ~PB_OUTS; + + /* Hold 100 Mbit in reset until fpga is loaded */ + immap->im_ioport.iop_pcpar &= ~PC_ENET100_RESET; + immap->im_ioport.iop_pcdir |= PC_ENET100_RESET; + immap->im_ioport.iop_pcso &= ~PC_ENET100_RESET; + immap->im_ioport.iop_pcdat &= ~PC_ENET100_RESET; + + /* Turn on front led to show that we are alive */ + immap->im_ioport.iop_papar &= ~PA_FRONT_LED; + immap->im_ioport.iop_padir |= PA_FRONT_LED; + immap->im_ioport.iop_paodr |= PA_FRONT_LED; + immap->im_ioport.iop_padat &= ~PA_FRONT_LED; + + Pbdat = immap->im_cpm.cp_pbdat; + + if (!(Pbdat & PB_ID_0)) + Id += 1; + if (!(Pbdat & PB_ID_1)) + Id += 2; + if (!(Pbdat & PB_ID_2)) + Id += 4; + if (!(Pbdat & PB_ID_3)) + Id += 8; + + if (Pbdat & PB_REV_0) + Rev += 1; + if (Pbdat & PB_REV_1) + Rev += 2; + + /* Turn ID off since we dont need it anymore */ + immap->im_cpm.cp_pbdat |= PB_ID_GND; + + printf ("GTH board, rev %d, id=0x%01x\n", Rev, Id); + return 0; +} + +#define _NOT_USED_ 0xffffffff +const uint sdram_table[] = { + /* Single read, offset 0 */ + 0x0f3dfc04, 0x0eefbc04, 0x01bf7c04, 0x0feafc00, + 0x1fb5fc45, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Burst read, Offset 0x8, 4 reads */ + 0x0f3dfc04, 0x0eefbc04, 0x00bf7c04, 0x00ffec00, + 0x00fffc00, 0x01eafc00, 0x1fb5fc00, 0xfffffc45, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Not used part of burst read is used for MRS, Offset 0x14 */ + 0xefeabc34, 0x1fb57c34, 0xfffffc05, _NOT_USED_, + /* _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, */ + + /* Single write, Offset 0x18 */ + 0x0f3dfc04, 0x0eebbc00, 0x01a27c04, 0x1fb5fc45, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Burst write, Offset 0x20. 4 writes */ + 0x0f3dfc04, 0x0eebbc00, 0x00b77c00, 0x00fffc00, + 0x00fffc00, 0x01eafc04, 0x1fb5fc45, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Not used part of burst write is used for precharge, Offset 0x2C */ + 0x0ff5fc04, 0xfffffc05, _NOT_USED_, _NOT_USED_, + /* _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, */ + + /* Period timer service. Offset 0x30. Refresh. Wait at least 70 ns after refresh command */ + 0x1ffd7c04, 0xfffffc04, 0xfffffc04, 0xfffffc05, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Exception, Offset 0x3C */ + 0xfffffc04, 0xfffffc05, _NOT_USED_, _NOT_USED_ +}; + +const uint fpga_table[] = { + /* Single read, offset 0 */ + 0x0cffec04, 0x00ffec04, 0x00ffec04, 0x00ffec04, + 0x00fffc04, 0x00fffc00, 0x00ffec04, 0xffffec05, + + /* Burst read, Offset 0x8 */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Single write, Offset 0x18 */ + 0x0cffec04, 0x00ffec04, 0x00ffec04, 0x00ffec04, + 0x00fffc04, 0x00fffc00, 0x00ffec04, 0xffffec05, + + /* Burst write, Offset 0x20. */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Period timer service. Offset 0x30. */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* Exception, Offset 0x3C */ + 0xfffffc04, 0xfffffc05, _NOT_USED_, _NOT_USED_ +}; + +int _initsdram (uint base, uint * noMbytes) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *mc = &immap->im_memctl; + volatile u32 *memptr; + + mc->memc_mptpr = MPTPR_PTP_DIV16; /* (16-17) */ + + /* SDRAM in UPMA + + GPL_0 is connected instead of A19 to SDRAM. + According to table 16-17, AMx should be 001, i.e. type 1 + and GPL_0 should hold address A10 when multiplexing */ + + mc->memc_mamr = (0x2E << MAMR_PTA_SHIFT) | MAMR_PTAE | MAMR_AMA_TYPE_1 | MAMR_G0CLA_A10 | MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_1X; /* (16-13) */ + + upmconfig (UPMA, (uint *) sdram_table, + sizeof (sdram_table) / sizeof (uint)); + + /* Perform init of sdram ( Datasheet Page 9 ) + Precharge */ + mc->memc_mcr = 0x8000212C; /* run upm a at 0x2C (16-15) */ + + /* Run 2 refresh cycles */ + mc->memc_mcr = 0x80002130; /* run upm a at 0x30 (16-15) */ + mc->memc_mcr = 0x80002130; /* run upm a at 0x30 (16-15) */ + + /* Set Mode register */ + mc->memc_mar = 0x00000088; /* set mode register (address) to 0x022 (16-17) */ + /* Lower 2 bits are not connected to chip */ + mc->memc_mcr = 0x80002114; /* run upm a at 0x14 (16-15) */ + + /* CS1, base 0x0000000 - 64 Mbyte, use UPM A */ + mc->memc_or1 = 0xfc000000 | OR_CSNT_SAM; + mc->memc_br1 = BR_MS_UPMA | BR_V; /* SDRAM base always 0 */ + + /* Test if we really have 64 MB SDRAM */ + memptr = (u32 *) 0; + *memptr = 0; + + memptr = (u32 *) 0x2000000; /* First u32 in upper 32 MB */ + *memptr = 0x12345678; + + memptr = (u32 *) 0; + if (*memptr == 0x12345678) { + /* Wrapped, only have 32 MB */ + mc->memc_or1 = 0xfe000000 | OR_CSNT_SAM; + *noMbytes = 32; + } else { + /* 64 MB */ + *noMbytes = 64; + } + + /* Setup FPGA in UPMB */ + upmconfig (UPMB, (uint *) fpga_table, + sizeof (fpga_table) / sizeof (uint)); + + /* Enable UPWAITB */ + mc->memc_mbmr = MBMR_GPL_B4DIS; /* (16-13) */ + + /* CS2, base FPGA_2_BASE - 4 MByte, use UPM B 32 Bit */ + mc->memc_or2 = 0xffc00000 | OR_BI; + mc->memc_br2 = FPGA_2_BASE | BR_MS_UPMB | BR_V; + + /* CS3, base FPGA_3_BASE - 4 MByte, use UPM B 16 bit */ + mc->memc_or3 = 0xffc00000 | OR_BI; + mc->memc_br3 = FPGA_3_BASE | BR_MS_UPMB | BR_V | BR_PS_16; + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +void _sdramdisable (void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + memctl->memc_br1 = 0x00000000; + + /* maybe we should turn off upmb here or something */ +} + +/* ------------------------------------------------------------------------- */ + +int initsdram (uint base, uint * noMbytes) +{ + *noMbytes = 32; + +#ifdef CONFIG_START_IN_RAM + /* SDRAM is already setup. Dont touch it */ + return 0; +#else + + if (!_initsdram (base, noMbytes)) { + + return 0; + } else { + _sdramdisable (); + + return -1; + } +#endif +} + +long int initdram (int board_type) +{ + u32 *i; + u32 j; + u32 k; + + /* GTH only have SDRAM */ + uint sdramsz; + + if (!initsdram (0x00000000, &sdramsz)) { + printf ("(%u MB SDRAM) ", sdramsz); + } else { + /******************************** + *SDRAM ERROR, HALT PROCESSOR + *********************************/ + printf ("SDRAM ERROR\n"); + while (1); + } + +#ifndef CONFIG_START_IN_RAM + +#define U32_S ((sdramsz<<18)-1) + +#if 1 + /* Do a simple memory test */ + for (i = (u32 *) 0, j = 0; (u32) i < U32_S; i += 2, j += 2) { + *i = j + (j << 17); + *(i + 1) = ~(j + (j << 18)); + } + + WATCHDOG_RESET (); + + printf ("."); + + for (i = (u32 *) 0, j = 0; (u32) i < U32_S; i += 2, j += 2) { + k = *i; + if (k != (j + (j << 17))) { + printf ("Mem test error, i=0x%x, 0x%x\n, 0x%x", (u32) i, j, k); + while (1); + } + k = *(i + 1); + if (k != ~(j + (j << 18))) { + printf ("Mem test error(+1), i=0x%x, 0x%x\n, 0x%x", + (u32) i + 1, j, k); + while (1); + } + } +#endif + + WATCHDOG_RESET (); + + /* Clear memory */ + for (i = (u32 *) 0; (u32) i < U32_S; i++) { + *i = 0; + } +#endif /* !start in ram */ + + WATCHDOG_RESET (); + + return (sdramsz << 20); +} + +#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 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); + + if ((System != FAILSAFE_BOOT) & (System != SYSTEM_BOOT)) { + 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; + } + + if (System == FAILSAFE_BOOT) { + printf ("Setting failsafe boot in flash\n"); + } else { + printf ("Setting system boot in flash\n"); + } + 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 void maybe_update_restart_reason (volatile u32 * addr32) +{ + /* Update addr if sw wd restart */ + volatile u16 *flash = (u16 *) (CFG_FLASH_BASE); + volatile u16 *addr_16 = (u16 *) addr32; + u32 rsr; + + /* Dont reset register now */ + rsr = ((volatile immap_t *) CFG_IMMR)->im_clkrst.car_rsr; + + rsr >>= 24; + + if (rsr & 0x10) { + /* Was really a sw wd restart, update reason */ + + printf ("Last restart by software watchdog\n"); + + /* AMD 16 bit */ + WRITE_FLASH16 (&flash[0x555], 0xAAAA); + WRITE_FLASH16 (&flash[0x2AA], 0x5555); + WRITE_FLASH16 (&flash[0x555], 0xA0A0); + + WRITE_FLASH16 (addr_16, 0); + + udelay (1000); + + WATCHDOG_RESET (); + + /* AMD 16 bit */ + WRITE_FLASH16 (&flash[0x555], 0xAAAA); + WRITE_FLASH16 (&flash[0x2AA], 0x5555); + WRITE_FLASH16 (&flash[0x555], 0xA0A0); + + WRITE_FLASH16 (addr_16 + 1, SW_WATCHDOG_REASON); + + } +} + +static void check_restart_reason (void) +{ + /* Update restart reason if sw watchdog was + triggered */ + + int i; + volatile u32 *raddr; + + raddr = (u32 *) (CFG_FLASH_BASE + POWER_OFFSET); + + if (*raddr == 0xFFFFFFFF) { + /* Nothing written */ + maybe_update_restart_reason (raddr); + } else { + /* Search for latest written reason */ + i = 0; + while ((*(raddr + 2) != 0xFFFFFFFF) & (i < 2000)) { + raddr += 2; + i++; + } + if (i >= 2000) { + /* Whoa, dont write any more */ + printf ("*** No free restart reason found ***\n"); + } else { + /* Check if written */ + if (*raddr == 0) { + /* Erased by kernel, no new reason written */ + maybe_update_restart_reason (raddr + 2); + } + } + } +} + +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; + int failsafe = 1; + u8 system; + 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 != 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 = 3 - 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 = 3 - system; + } + } + write_bootdata (addr + 1, system, count); + if (system == SYSTEM_BOOT) { + failsafe = 0; + } + } + } + if (failsafe) { + printf ("Booting failsafe system\n"); + setenv ("bootargs", "panic=1 root=/dev/hda7"); + setenv ("bootcmd", "disk 100000 0:5;bootm 100000"); + } else { + printf ("Using normal system\n"); + setenv ("bootargs", "panic=1 root=/dev/hda4"); + setenv ("bootcmd", "disk 100000 0:2;bootm 100000"); + } +} + +int misc_init_r (void) +{ + u8 Rx[80]; + u8 Tx[5]; + int page; + int read = 0; + volatile immap_t *immap = (immap_t *) CFG_IMMR; + + /* Kill fpga */ + immap->im_ioport.iop_papar &= ~(PA_FL_CONFIG | PA_FL_CE); + immap->im_ioport.iop_padir |= (PA_FL_CONFIG | PA_FL_CE); + immap->im_ioport.iop_paodr &= ~(PA_FL_CONFIG | PA_FL_CE); + + /* Enable fpga, active low */ + immap->im_ioport.iop_padat &= ~PA_FL_CE; + + /* Start configuration */ + immap->im_ioport.iop_padat &= ~PA_FL_CONFIG; + udelay (2); + + immap->im_ioport.iop_padat |= (PA_FL_CONFIG | PA_FL_CE); + + /* Check if we need to boot failsafe system */ + check_boot_tries (); + + /* Check if we need to update restart reason */ + check_restart_reason (); + + if (ee_init_data ()) { + printf ("EEPROM init failed\n"); + return (0); + } + + /* 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_command (Tx, 2, NULL, 0, TRUE)) { + printf ("EE user page %d recall failed\n", page); + return (0); + } + + Tx[0] = READ_SCRATCHPAD; + if (ee_do_command (Tx, 2, Rx + read, 9, TRUE)) { + 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); +} diff --git a/board/gth/u-boot.lds b/board/gth/u-boot.lds new file mode 100755 index 0000000..8ac4bda --- /dev/null +++ b/board/gth/u-boot.lds @@ -0,0 +1,130 @@ +/* + * (C) Copyright 2000 + * 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 + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/mpc8xx/start.o(.text) + *(.text) + common/environment.o(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + *(.rodata.str1.4) + *(.eh_frame) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + + . = .; + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} |