diff options
author | wdenk <wdenk> | 2003-10-09 19:00:25 (GMT) |
---|---|---|
committer | wdenk <wdenk> | 2003-10-09 19:00:25 (GMT) |
commit | 15647dc7fd86bbaeb68740929ecb9f8473c7ceae (patch) | |
tree | 1f2cefc002e07f517bcaf19b5a400b5a8a543e0c /board/etin/debris | |
parent | a0ff7f2eda50de4d4096265a086c94ac640fab7c (diff) | |
download | u-boot-15647dc7fd86bbaeb68740929ecb9f8473c7ceae.tar.xz |
* Patches by Thomas Lange, 09 Oct 2003:
- fix cmd_ide.c for non ppc boards (read/write functions did not
add ATA base address)
- fix for shannon board
- #ifdef CONFIG_IDE_8xx_DIRECT some otherwise unused code
* Patch by Sangmoon Kim, 07 Oct 2003:
add support for debris board
Diffstat (limited to 'board/etin/debris')
-rw-r--r-- | board/etin/debris/Makefile | 40 | ||||
-rw-r--r-- | board/etin/debris/config.mk | 31 | ||||
-rw-r--r-- | board/etin/debris/debris.c | 158 | ||||
-rw-r--r-- | board/etin/debris/flash.c | 720 | ||||
-rw-r--r-- | board/etin/debris/phantom.c | 310 | ||||
-rw-r--r-- | board/etin/debris/speed.h | 54 | ||||
-rw-r--r-- | board/etin/debris/u-boot.lds | 128 |
7 files changed, 1441 insertions, 0 deletions
diff --git a/board/etin/debris/Makefile b/board/etin/debris/Makefile new file mode 100644 index 0000000..305a1bf --- /dev/null +++ b/board/etin/debris/Makefile @@ -0,0 +1,40 @@ +# +# (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 $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o phantom.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/etin/debris/config.mk b/board/etin/debris/config.mk new file mode 100644 index 0000000..64debf5 --- /dev/null +++ b/board/etin/debris/config.mk @@ -0,0 +1,31 @@ +# +# (C) Copyright 2000, 2001 +# Sangmoon, Etin Systems, dogoil@etinsys.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 +# + +# +# Debris boards +# + +#TEXT_BASE = 0x00090000 +TEXT_BASE = 0xFFF00000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) diff --git a/board/etin/debris/debris.c b/board/etin/debris/debris.c new file mode 100644 index 0000000..fe075f1 --- /dev/null +++ b/board/etin/debris/debris.c @@ -0,0 +1,158 @@ +/* + * (C) Copyright 2000 + * Sangmoon Kim, Etin Systems. dogoil@etinsys.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 <mpc824x.h> +#include <pci.h> + +int checkboard (void) +{ + /*TODO: Check processor type */ + + puts ( "Board: Debris " +#ifdef CONFIG_MPC8240 + "8240" +#endif +#ifdef CONFIG_MPC8245 + "8245" +#endif + " ##Test not implemented yet##\n"); + return 0; +} + +#if 0 /* NOT USED */ +int checkflash (void) +{ + /* TODO: XXX XXX XXX */ + printf ("## Test not implemented yet ##\n"); + + return (0); +} +#endif + +long int initdram (int board_type) +{ + int i, cnt; + volatile uchar * base= CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { +/* ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1);*/ + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +} + +/* + * Initialize PCI Devices, report devices found. + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_debris_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x10, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET1_IOADDR, + PCI_ENET1_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { } +}; +#endif + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_debris_config_table, +#endif +}; + +void pci_init_board(void) +{ + pci_mpc824x_init(&hose); +} + +void *nvram_read(void *dest, const long src, size_t count) +{ + volatile uchar *d = (volatile uchar*) dest; + volatile uchar *s = (volatile uchar*) src; + while(count--) { + *d++ = *s++; + asm volatile("sync"); + } + return dest; +} + +void nvram_write(long dest, const void *src, size_t count) +{ + volatile uchar *d = (volatile uchar*)dest; + volatile uchar *s = (volatile uchar*)src; + while(count--) { + *d++ = *s++; + asm volatile("sync"); + } +} + +int misc_init_r(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* Write ethernet addr in NVRAM for VxWorks */ + nvram_write(CFG_ENV_ADDR + CFG_NVRAM_VXWORKS_OFFS, + (char*)&gd->bd->bi_enetaddr[0], 6); + return 0; +} diff --git a/board/etin/debris/flash.c b/board/etin/debris/flash.c new file mode 100644 index 0000000..a4100e5 --- /dev/null +++ b/board/etin/debris/flash.c @@ -0,0 +1,720 @@ +/* + * board/eva/flash.c + * + * (C) Copyright 2002 + * Sangmoon Kim, Etin Systems, dogoil@etinsys.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 <asm/processor.h> +#include <asm/pci_io.h> +#include <mpc824x.h> + +int (*do_flash_erase)(flash_info_t*, uint32_t, uint32_t); +int (*write_dword)(flash_info_t*, ulong, uint64_t); + +typedef uint64_t cfi_word; + +#define cfi_read(flash, addr) *((volatile cfi_word*)(flash->start[0] + addr)) + +#define cfi_write(flash, val, addr) \ + move64((cfi_word*)&val, \ + (cfi_word*)(flash->start[0] + addr)) + +#define CMD(x) ((((cfi_word)x)<<48)|(((cfi_word)x)<<32)|(((cfi_word)x)<<16)|(((cfi_word)x))) + +static void write32(unsigned long addr, uint32_t value) +{ + *(volatile uint32_t*)(addr) = value; + asm volatile("sync"); +} + +static uint32_t read32(unsigned long addr) +{ + uint32_t value; + value = *(volatile uint32_t*)addr; + asm volatile("sync"); + return value; +} + +static cfi_word cfi_cmd(flash_info_t *flash, uint8_t cmd, uint32_t addr) +{ + uint32_t base = flash->start[0]; + uint32_t val=(cmd << 16) | cmd; + addr <<= 3; + write32(base + addr, val); + return addr; +} + +static uint16_t cfi_read_query(flash_info_t *flash, uint32_t addr) +{ + uint32_t base = flash->start[0]; + addr <<= 3; + return (uint16_t)read32(base + addr); +} + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +static void move64(uint64_t *src, uint64_t *dest) +{ + asm volatile("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ + "stfd 0, 0(4)" /* *dest = fpr0 */ + : : : "fr0" ); /* Clobbers fr0 */ + return; +} + +static int cfi_write_dword(flash_info_t *flash, ulong dest, cfi_word data) +{ + unsigned long start; + cfi_word status = 0; + + status = cfi_read(flash, dest); + data &= status; + + cfi_cmd(flash, 0x40, 0); + cfi_write(flash, data, dest); + + udelay(10); + start = get_timer (0); + for(;;) { + status = cfi_read(flash, dest); + status &= CMD(0x80); + if(status == CMD(0x80)) + break; + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + cfi_cmd(flash, 0xff, 0); + return 1; + } + udelay(1); + } + cfi_cmd(flash, 0xff, 0); + + return 0; +} + +static int jedec_write_dword (flash_info_t *flash, ulong dest, cfi_word data) +{ + ulong start; + cfi_word status = 0; + + status = cfi_read(flash, dest); + if(status != CMD(0xffff)) return 2; + + cfi_cmd(flash, 0xaa, 0x555); + cfi_cmd(flash, 0x55, 0x2aa); + cfi_cmd(flash, 0xa0, 0x555); + + cfi_write(flash, data, dest); + + udelay(10); + start = get_timer (0); + status = ~data; + while(status != data) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) + return 1; + status = cfi_read(flash, dest); + udelay(1); + } + return 0; +} + +static __inline__ unsigned long get_msr(void) +{ + unsigned long msr; + __asm__ __volatile__ ("mfmsr %0" : "=r" (msr) :); + return msr; +} + +static __inline__ void set_msr(unsigned long msr) +{ + __asm__ __volatile__ ("mtmsr %0" : : "r" (msr)); +} + +int write_buff (flash_info_t *flash, uchar *src, ulong addr, ulong cnt) +{ + ulong wp; + int i, s, l, rc; + cfi_word data; + uint8_t *t = (uint8_t*)&data; + unsigned long base = flash->start[0]; + uint32_t msr; + + if (flash->flash_id == FLASH_UNKNOWN) + return 4; + + if (cnt == 0) + return 0; + + addr -= base; + + msr = get_msr(); + set_msr(msr|MSR_FP); + + wp = (addr & ~7); /* get lower word aligned address */ + + if((addr-wp) != 0) { + data = cfi_read(flash, wp); + s = addr & 7; + l = ( cnt < (8-s) ) ? cnt : (8-s); + for(i = 0; i < l; i++) + t[s+i] = *src++; + if ((rc = write_dword(flash, wp, data)) != 0) + goto DONE; + wp += 8; + cnt -= l; + } + + while (cnt >= 8) { + for (i = 0; i < 8; i++) + t[i] = *src++; + if ((rc = write_dword(flash, wp, data)) != 0) + goto DONE; + wp += 8; + cnt -= 8; + } + + if (cnt == 0) { + rc = 0; + goto DONE; + } + + data = cfi_read(flash, wp); + for(i = 0; i < cnt; i++) + t[i] = *src++; + rc = write_dword(flash, wp, data); +DONE: + set_msr(msr); + return rc; +} + +static int cfi_erase_oneblock(flash_info_t *flash, uint32_t sect) +{ + int sa; + int flag; + ulong start, last, now; + cfi_word status; + + flag = disable_interrupts(); + + sa = (flash->start[sect] - flash->start[0]); + write32(flash->start[sect], 0x00200020); + write32(flash->start[sect], 0x00d000d0); + + if (flag) + enable_interrupts(); + + udelay(1000); + start = get_timer (0); + last = start; + + for (;;) { + status = cfi_read(flash, sa); + status &= CMD(0x80); + if (status == CMD(0x80)) + break; + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + cfi_cmd(flash, 0xff, 0); + printf ("Timeout\n"); + return ERR_TIMOUT; + } + + if ((now - last) > 1000) { + serial_putc ('.'); + last = now; + } + udelay(10); + } + cfi_cmd(flash, 0xff, 0); + return ERR_OK; +} + +static int cfi_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last) +{ + int sect; + int rc = ERR_OK; + + for (sect = s_first; sect <= s_last; sect++) { + if (flash->protect[sect] == 0) { + rc = cfi_erase_oneblock(flash, sect); + if (rc != ERR_OK) break; + } + } + printf (" done\n"); + return rc; +} + +static int jedec_erase(flash_info_t *flash, uint32_t s_first, uint32_t s_last) +{ + int sect; + cfi_word status; + int sa = -1; + int flag; + ulong start, last, now; + + flag = disable_interrupts(); + + cfi_cmd(flash, 0xaa, 0x555); + cfi_cmd(flash, 0x55, 0x2aa); + cfi_cmd(flash, 0x80, 0x555); + cfi_cmd(flash, 0xaa, 0x555); + cfi_cmd(flash, 0x55, 0x2aa); + for ( sect = s_first; sect <= s_last; sect++) { + if (flash->protect[sect] == 0) { + sa = flash->start[sect] - flash->start[0]; + write32(flash->start[sect], 0x00300030); + } + } + if (flag) + enable_interrupts(); + + if (sa < 0) + goto DONE; + + udelay (1000); + start = get_timer (0); + last = start; + for(;;) { + status = cfi_read(flash, sa); + if (status == CMD(0xffff)) + break; + + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return ERR_TIMOUT; + } + + if ((now - last) > 1000) { + serial_putc ('.'); + last = now; + } + udelay(10); + } +DONE: + cfi_cmd(flash, 0xf0, 0); + + printf (" done\n"); + + return ERR_OK; +} + +int flash_erase (flash_info_t *flash, int s_first, int s_last) +{ + int sect; + int prot; + + if ((s_first < 0) || (s_first > s_last)) { + if (flash->flash_id == FLASH_UNKNOWN) + printf ("- missing\n"); + else + printf ("- no sectors to erase\n"); + return ERR_NOT_ERASED; + } + if (flash->flash_id == FLASH_UNKNOWN) { + printf ("Can't erase unknown flash type - aborted\n"); + return ERR_NOT_ERASED; + } + + prot = 0; + for (sect = s_first; sect <= s_last; sect++) + if (flash->protect[sect]) prot++; + + if (prot) + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + else + printf ("\n"); + + return do_flash_erase(flash, s_first, s_last); +} + +struct jedec_flash_info { + const uint16_t mfr_id; + const uint16_t dev_id; + const char *name; + const int DevSize; + const int InterfaceDesc; + const int NumEraseRegions; + const ulong regions[4]; +}; + +#define ERASEINFO(size,blocks) (size<<8)|(blocks-1) + +#define SIZE_1MiB 20 +#define SIZE_2MiB 21 +#define SIZE_4MiB 22 + +static const struct jedec_flash_info jedec_table[] = { + { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV800T, + name: "AMD AM29LV800T", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV800B, + name: "AMD AM29LV800B", + DevSize: SIZE_1MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,15), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV160T, + name: "AMD AM29LV160T", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x10000,31), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1) + } + }, { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV160B, + name: "AMD AM29LV160B", + DevSize: SIZE_2MiB, + NumEraseRegions: 4, + regions: {ERASEINFO(0x04000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x08000,1), + ERASEINFO(0x10000,31) + } + }, { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV320T, + name: "AMD AM29LV320T", + DevSize: SIZE_4MiB, + NumEraseRegions: 2, + regions: {ERASEINFO(0x10000,63), + ERASEINFO(0x02000,8) + } + + }, { + mfr_id: (uint16_t)AMD_MANUFACT, + dev_id: (uint16_t)AMD_ID_LV320B, + name: "AMD AM29LV320B", + DevSize: SIZE_4MiB, + NumEraseRegions: 2, + regions: {ERASEINFO(0x02000,8), + ERASEINFO(0x10000,63) + } + } +}; + +static ulong cfi_init(uint32_t base, flash_info_t *flash) +{ + int sector; + int block; + int block_count; + int offset = 0; + int reverse = 0; + int primary; + int mfr_id; + int dev_id; + + flash->start[0] = base; + cfi_cmd(flash, 0xF0, 0); + cfi_cmd(flash, 0x98, 0); + if ( !( cfi_read_query(flash, 0x10) == 'Q' && + cfi_read_query(flash, 0x11) == 'R' && + cfi_read_query(flash, 0x12) == 'Y' )) { + cfi_cmd(flash, 0xff, 0); + return 0; + } + + flash->size = 1 << cfi_read_query(flash, 0x27); + flash->size *= 4; + block_count = cfi_read_query(flash, 0x2c); + primary = cfi_read_query(flash, 0x15); + if ( cfi_read_query(flash, primary + 4) == 0x30) + reverse = (cfi_read_query(flash, 0x1) & 0x01); + else + reverse = (cfi_read_query(flash, primary+15) == 3); + + flash->sector_count = 0; + + for ( block = reverse ? block_count - 1 : 0; + reverse ? block >= 0 : block < block_count; + reverse ? block-- : block ++) { + int sector_size = + (cfi_read_query(flash, 0x2d + block*4+2) | + (cfi_read_query(flash, 0x2d + block*4+3) << 8)) << 8; + int sector_count = + (cfi_read_query(flash, 0x2d + block*4+0) | + (cfi_read_query(flash, 0x2d + block*4+1) << 8)) + 1; + for(sector = 0; sector < sector_count; sector++) { + flash->start[flash->sector_count++] = base + offset; + offset += sector_size * 4; + } + } + mfr_id = cfi_read_query(flash, 0x00); + dev_id = cfi_read_query(flash, 0x01); + + cfi_cmd(flash, 0xff, 0); + + flash->flash_id = (mfr_id << 16) | dev_id; + + for (sector = 0; sector < flash->sector_count; sector++) { + write32(flash->start[sector], 0x00600060); + write32(flash->start[sector], 0x00d000d0); + } + cfi_cmd(flash, 0xff, 0); + + for (sector = 0; sector < flash->sector_count; sector++) + flash->protect[sector] = 0; + + do_flash_erase = cfi_erase; + write_dword = cfi_write_dword; + + return flash->size; +} + +static ulong jedec_init(unsigned long base, flash_info_t *flash) +{ + int i; + int block, block_count; + int sector, offset; + int mfr_id, dev_id; + flash->start[0] = base; + cfi_cmd(flash, 0xF0, 0x000); + cfi_cmd(flash, 0xAA, 0x555); + cfi_cmd(flash, 0x55, 0x2AA); + cfi_cmd(flash, 0x90, 0x555); + mfr_id = cfi_read_query(flash, 0x000); + dev_id = cfi_read_query(flash, 0x0001); + cfi_cmd(flash, 0xf0, 0x000); + + for(i=0; i<sizeof(jedec_table)/sizeof(struct jedec_flash_info); i++) { + if((jedec_table[i].mfr_id == mfr_id) && + (jedec_table[i].dev_id == dev_id)) { + + flash->flash_id = (mfr_id << 16) | dev_id; + flash->size = 1 << jedec_table[0].DevSize; + flash->size *= 4; + block_count = jedec_table[i].NumEraseRegions; + offset = 0; + flash->sector_count = 0; + for (block = 0; block < block_count; block++) { + int sector_size = jedec_table[i].regions[block]; + int sector_count = (sector_size & 0xff) + 1; + sector_size >>= 8; + for (sector=0; sector<sector_count; sector++) { + flash->start[flash->sector_count++] = + base + offset; + offset += sector_size * 4; + } + } + break; + } + } + + for (sector = 0; sector < flash->sector_count; sector++) + flash->protect[sector] = 0; + + do_flash_erase = jedec_erase; + write_dword = jedec_write_dword; + + return flash->size; +} + +inline void mtibat1u(unsigned int x) +{ + __asm__ __volatile__ ("mtspr 530, %0" :: "r" (x)); +} + +inline void mtibat1l(unsigned int x) +{ + __asm__ __volatile__ ("mtspr 531, %0" :: "r" (x)); +} + +inline void mtdbat1u(unsigned int x) +{ + __asm__ __volatile__ ("mtspr 538, %0" :: "r" (x)); +} + +inline void mtdbat1l(unsigned int x) +{ + __asm__ __volatile__ ("mtspr 539, %0" :: "r" (x)); +} + +unsigned long flash_init (void) +{ + unsigned long size = 0; + int i; + unsigned int msr; + + /* BAT1 */ + CONFIG_WRITE_WORD(ERCR3, 0x0C00000C); + CONFIG_WRITE_WORD(ERCR4, 0x0800000C); + msr = get_msr(); + set_msr(msr & ~(MSR_IR | MSR_DR)); + mtibat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT); + mtibat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP); + mtdbat1l(0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT); + mtdbat1u(0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP); + set_msr(msr); + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) + flash_info[i].flash_id = FLASH_UNKNOWN; + size = cfi_init(FLASH_BASE0_PRELIM, &flash_info[0]); + if (!size) + size = jedec_init(FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) + printf ("# Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", + size, size<<20); + + return size; +} + +void flash_print_info (flash_info_t *flash) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *p; + + if (flash->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + flash_init(); + } + + if (flash->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (((flash->flash_id) >> 16) & 0xff) { + case 0x01: + printf ("AMD "); + break; + case 0x04: + printf("FUJITSU "); + break; + case 0x20: + printf("STM "); + break; + case 0xBF: + printf("SST "); + break; + case 0x89: + case 0xB0: + printf("INTEL "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch ((flash->flash_id) & 0xffff) { + case (uint16_t)AMD_ID_LV800T: + printf ("AM29LV800T\n"); + break; + case (uint16_t)AMD_ID_LV800B: + printf ("AM29LV800B\n"); + break; + case (uint16_t)AMD_ID_LV160T: + printf ("AM29LV160T\n"); + break; + case (uint16_t)AMD_ID_LV160B: + printf ("AM29LV160B\n"); + break; + case (uint16_t)AMD_ID_LV320T: + printf ("AM29LV320T\n"); + break; + case (uint16_t)AMD_ID_LV320B: + printf ("AM29LV320B\n"); + break; + case (uint16_t)INTEL_ID_28F800C3T: + printf ("28F800C3T\n"); + break; + case (uint16_t)INTEL_ID_28F800C3B: + printf ("28F800C3B\n"); + break; + case (uint16_t)INTEL_ID_28F160C3T: + printf ("28F160C3T\n"); + break; + case (uint16_t)INTEL_ID_28F160C3B: + printf ("28F160C3B\n"); + break; + case (uint16_t)INTEL_ID_28F320C3T: + printf ("28F320C3T\n"); + break; + case (uint16_t)INTEL_ID_28F320C3B: + printf ("28F320C3B\n"); + break; + case (uint16_t)INTEL_ID_28F640C3T: + printf ("28F640C3T\n"); + break; + case (uint16_t)INTEL_ID_28F640C3B: + printf ("28F640C3B\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + if (flash->size >= (1 << 20)) { + printf (" Size: %ld MB in %d Sectors\n", + flash->size >> 20, flash->sector_count); + } else { + printf (" Size: %ld kB in %d Sectors\n", + flash->size >> 10, flash->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i = 0; i < flash->sector_count; ++i) { + /* Check if whole sector is erased*/ + if (i != (flash->sector_count-1)) + size = flash->start[i+1] - flash->start[i]; + else + size = flash->start[0] + flash->size - flash->start[i]; + + erased = 1; + p = (volatile unsigned long *)flash->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) { + if (*p++ != 0xffffffff) { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf ("\n "); + + printf (" %08lX%s%s", + flash->start[i], + erased ? " E" : " ", + flash->protect[i] ? "RO " : " "); + } + printf ("\n"); +} diff --git a/board/etin/debris/phantom.c b/board/etin/debris/phantom.c new file mode 100644 index 0000000..0b81fc0 --- /dev/null +++ b/board/etin/debris/phantom.c @@ -0,0 +1,310 @@ +/* + * board/eva/phantom.c + * + * Phantom RTC device driver for EVA + * + * Author: Sangmoon Kim + * dogoil@etinsys.com + * + * Copyright 2002 Etinsys Inc. + * + * 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. + */ + +#include <common.h> +#include <command.h> +#include <rtc.h> + +#if (CONFIG_COMMANDS & CFG_CMD_DATE) + +#define RTC_BASE (CFG_NVRAM_BASE_ADDR + 0x7fff8) + +#define RTC_YEAR ( RTC_BASE + 7 ) +#define RTC_MONTH ( RTC_BASE + 6 ) +#define RTC_DAY_OF_MONTH ( RTC_BASE + 5 ) +#define RTC_DAY_OF_WEEK ( RTC_BASE + 4 ) +#define RTC_HOURS ( RTC_BASE + 3 ) +#define RTC_MINUTES ( RTC_BASE + 2 ) +#define RTC_SECONDS ( RTC_BASE + 1 ) +#define RTC_CENTURY ( RTC_BASE + 0 ) + +#define RTC_CONTROLA RTC_CENTURY +#define RTC_CONTROLB RTC_SECONDS +#define RTC_CONTROLC RTC_DAY_OF_WEEK + +#define RTC_CA_WRITE 0x80 +#define RTC_CA_READ 0x40 + +#define RTC_CB_OSC_DISABLE 0x80 + +#define RTC_CC_BATTERY_FLAG 0x80 +#define RTC_CC_FREQ_TEST 0x40 + + +static int phantom_flag = -1; +static int century_flag = -1; + +static uchar rtc_read(unsigned int addr) +{ + return *(volatile unsigned char *)(addr); +} + +static void rtc_write(unsigned int addr, uchar val) +{ + *(volatile unsigned char *)(addr) = val; +} + +static unsigned char phantom_rtc_sequence[] = { + 0xc5, 0x3a, 0xa3, 0x5c, 0xc5, 0x3a, 0xa3, 0x5c +}; + +static unsigned char* phantom_rtc_read(int addr, unsigned char rtc[8]) +{ + int i, j; + unsigned char v; + unsigned char save = rtc_read(addr); + + for (j = 0; j < 8; j++) { + v = phantom_rtc_sequence[j]; + for (i = 0; i < 8; i++) { + rtc_write(addr, v & 1); + v >>= 1; + } + } + for (j = 0; j < 8; j++) { + v = 0; + for (i = 0; i < 8; i++) { + if(rtc_read(addr) & 1) + v |= 1 << i; + } + rtc[j] = v; + } + rtc_write(addr, save); + return rtc; +} + +static void phantom_rtc_write(int addr, unsigned char rtc[8]) +{ + int i, j; + unsigned char v; + unsigned char save = rtc_read(addr); + for (j = 0; j < 8; j++) { + v = phantom_rtc_sequence[j]; + for (i = 0; i < 8; i++) { + rtc_write(addr, v & 1); + v >>= 1; + } + } + for (j = 0; j < 8; j++) { + v = rtc[j]; + for (i = 0; i < 8; i++) { + rtc_write(addr, v & 1); + v >>= 1; + } + } + rtc_write(addr, save); +} + +static int get_phantom_flag(void) +{ + int i; + unsigned char rtc[8]; + + phantom_rtc_read(RTC_BASE, rtc); + + for(i = 1; i < 8; i++) { + if (rtc[i] != rtc[0]) + return 1; + } + return 0; +} + +void rtc_reset(void) +{ + if (phantom_flag < 0) + phantom_flag = get_phantom_flag(); + + if (phantom_flag) { + unsigned char rtc[8]; + phantom_rtc_read(RTC_BASE, rtc); + if(rtc[4] & 0x30) { + printf( "real-time-clock was stopped. Now starting...\n" ); + rtc[4] &= 0x07; + phantom_rtc_write(RTC_BASE, rtc); + } + } else { + uchar reg_a, reg_b, reg_c; + reg_a = rtc_read( RTC_CONTROLA ); + reg_b = rtc_read( RTC_CONTROLB ); + + if ( reg_b & RTC_CB_OSC_DISABLE ) + { + printf( "real-time-clock was stopped. Now starting...\n" ); + reg_a |= RTC_CA_WRITE; + reg_b &= ~RTC_CB_OSC_DISABLE; + rtc_write( RTC_CONTROLA, reg_a ); + rtc_write( RTC_CONTROLB, reg_b ); + } + + /* make sure read/write clock register bits are cleared */ + reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ ); + rtc_write( RTC_CONTROLA, reg_a ); + + reg_c = rtc_read( RTC_CONTROLC ); + if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 ) + printf( "RTC battery low. Clock setting may not be reliable.\n"); + } +} + +inline unsigned bcd2bin (uchar n) +{ + return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +inline unsigned char bin2bcd (unsigned int n) +{ + return (((n / 10) << 4) | (n % 10)); +} + +static int get_century_flag(void) +{ + int flag = 0; + int bcd, century; + bcd = rtc_read( RTC_CENTURY ); + century = bcd2bin( bcd & 0x3F ); + rtc_write( RTC_CENTURY, bin2bcd(century+1)); + if (bcd == rtc_read( RTC_CENTURY )) + flag = 1; + rtc_write( RTC_CENTURY, bcd); + return flag; +} + +void rtc_get( struct rtc_time *tmp) +{ + if (phantom_flag < 0) + phantom_flag = get_phantom_flag(); + + if (phantom_flag) + { + unsigned char rtc[8]; + + phantom_rtc_read(RTC_BASE, rtc); + + tmp->tm_sec = bcd2bin(rtc[1] & 0x7f); + tmp->tm_min = bcd2bin(rtc[2] & 0x7f); + tmp->tm_hour = bcd2bin(rtc[3] & 0x1f); + tmp->tm_wday = bcd2bin(rtc[4] & 0x7); + tmp->tm_mday = bcd2bin(rtc[5] & 0x3f); + tmp->tm_mon = bcd2bin(rtc[6] & 0x1f); + tmp->tm_year = bcd2bin(rtc[7]) + 1900; + tmp->tm_yday = 0; + tmp->tm_isdst = 0; + + if( (rtc[3] & 0x80) && (rtc[3] & 0x40) ) tmp->tm_hour += 12; + if (tmp->tm_year < 1970) tmp->tm_year += 100; + } else { + uchar sec, min, hour; + uchar mday, wday, mon, year; + + int century; + + uchar reg_a; + + if (century_flag < 0) + century_flag = get_century_flag(); + + reg_a = rtc_read( RTC_CONTROLA ); + /* lock clock registers for read */ + rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ )); + + sec = rtc_read( RTC_SECONDS ); + min = rtc_read( RTC_MINUTES ); + hour = rtc_read( RTC_HOURS ); + mday = rtc_read( RTC_DAY_OF_MONTH ); + wday = rtc_read( RTC_DAY_OF_WEEK ); + mon = rtc_read( RTC_MONTH ); + year = rtc_read( RTC_YEAR ); + century = rtc_read( RTC_CENTURY ); + + /* unlock clock registers after read */ + rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ )); + + tmp->tm_sec = bcd2bin( sec & 0x7F ); + tmp->tm_min = bcd2bin( min & 0x7F ); + tmp->tm_hour = bcd2bin( hour & 0x3F ); + tmp->tm_mday = bcd2bin( mday & 0x3F ); + tmp->tm_mon = bcd2bin( mon & 0x1F ); + tmp->tm_wday = bcd2bin( wday & 0x07 ); + + if (century_flag) { + tmp->tm_year = bcd2bin( year ) + + ( bcd2bin( century & 0x3F ) * 100 ); + } else { + tmp->tm_year = bcd2bin( year ) + 1900; + if (tmp->tm_year < 1970) tmp->tm_year += 100; + } + + tmp->tm_yday = 0; + tmp->tm_isdst= 0; + } +} + +void rtc_set( struct rtc_time *tmp ) +{ + if (phantom_flag < 0) + phantom_flag = get_phantom_flag(); + + if (phantom_flag) { + uint year; + unsigned char rtc[8]; + + year = tmp->tm_year; + year -= (year < 2000) ? 1900 : 2000; + + rtc[0] = bin2bcd(0); + rtc[1] = bin2bcd(tmp->tm_sec); + rtc[2] = bin2bcd(tmp->tm_min); + rtc[3] = bin2bcd(tmp->tm_hour); + rtc[4] = bin2bcd(tmp->tm_wday); + rtc[5] = bin2bcd(tmp->tm_mday); + rtc[6] = bin2bcd(tmp->tm_mon); + rtc[7] = bin2bcd(year); + + phantom_rtc_write(RTC_BASE, rtc); + } else { + uchar reg_a; + if (century_flag < 0) + century_flag = get_century_flag(); + + /* lock clock registers for write */ + reg_a = rtc_read( RTC_CONTROLA ); + rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE )); + + rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon )); + + rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday )); + rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday )); + rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour )); + rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min )); + rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec )); + + /* break year up into century and year in century */ + if (century_flag) { + rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 )); + rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 )); + reg_a &= 0xc0; + reg_a |= bin2bcd( tmp->tm_year / 100 ); + } else { + rtc_write(RTC_YEAR, bin2bcd(tmp->tm_year - + ((tmp->tm_year < 2000) ? 1900 : 2000))); + } + + /* unlock clock registers after read */ + rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE )); + } +} + +#endif diff --git a/board/etin/debris/speed.h b/board/etin/debris/speed.h new file mode 100644 index 0000000..b66393b --- /dev/null +++ b/board/etin/debris/speed.h @@ -0,0 +1,54 @@ +/* + * (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 + */ + +/*----------------------------------------------------------------------- + * Timer value for timer 2, ICLK = 10 + * + * SPEED_FCOUNT2 = GCLK / (16 * (TIMER_TMR_PS + 1)) + * SPEED_TMR3_PS = (GCLK / (16 * SPEED_FCOUNT3)) - 1 + * + * SPEED_FCOUNT2 timer 2 counting frequency + * GCLK CPU clock + * SPEED_TMR2_PS prescaler + */ +#define SPEED_TMR2_PS (250 - 1) /* divide by 250 */ + +/*----------------------------------------------------------------------- + * Timer value for PIT + * + * PIT_TIME = SPEED_PITC / PITRTCLK + * PITRTCLK = 8192 + */ +#define SPEED_PITC (82 << 16) /* start counting from 82 */ + +/* + * The new value for PTA is calculated from + * + * PTA = (gclk * Trefresh) / (2 ^ (2 * DFBRG) * PTP * NCS) + * + * gclk CPU clock (not bus clock !) + * Trefresh Refresh cycle * 4 (four word bursts used) + * DFBRG For normal mode (no clock reduction) always 0 + * PTP Prescaler (already adjusted for no. of banks and 4K / 8K refresh) + * NCS Number of SDRAM banks (chip selects) on this UPM. + */ diff --git a/board/etin/debris/u-boot.lds b/board/etin/debris/u-boot.lds new file mode 100644 index 0000000..ab22203 --- /dev/null +++ b/board/etin/debris/u-boot.lds @@ -0,0 +1,128 @@ +/* + * (C) Copyright 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 + */ + +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/mpc824x/start.o (.text) + lib_ppc/board.o (.text) + lib_ppc/ppcstring.o (.text) + + . = DEFINED(env_offset) ? env_offset : .; + common/environment.o (.text) + + *(.text) + + *(.fixup) + *(.got1) + . = ALIGN(16); + *(.rodata) + *(.rodata1) + } + .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 = .); +} |