diff options
55 files changed, 6604 insertions, 423 deletions
@@ -2,6 +2,29 @@ Changes since U-Boot 0.2.2: ====================================================================== +* Patch by Rick Bronson, 16 Mar 2003: + Add support for Atmel AT91RM9200DK w/NAND + +* Patches by Robert Schwebel, 19 Mar 2003: + - use arm-linux-gcc as default compiler for ARM + - fix i2c fixup code + - fix missing baudrate setting + - added $loadaddr / CFG_LOAD_ADDR support to loadb + - moved "ignoring trailing characters" _before_ u-boot wants to + print out diagnostics messages; removes bogus characters at the + end of transmission + +* Patch by John Zhan, 18 Mar 2003: + Add support for SinoVee Microsystems SC8xx boards + +* Patch by Rolf Offermanns, 21 Mar 2003: + ported the dnp1110 related changes from the current armboot cvs to + current u-boot cvs. smc91111 does not work. problem marked in + smc91111.c, grep for "FIXME". + +* Patch by Brian Auld, 25 Mar 2003: + Add support for STM flash chips on ebony board + * Add PCI support for MPC8250 Boards (PM825 module) * Patch by Stefan Roese, 25 Mar 2003: @@ -46,6 +46,10 @@ N: Raphael Bossek E: raphael.bossek@solutions4linux.de D: 8xxrom-0.3.0 +N: Rick Bronson +E: rick@efn.org +D: Atmel AT91RM9200DK w/NAND support + N: David Brown E: DBrown03@harris.com D: Extensions to 8xxrom-0.3.0 @@ -262,6 +266,10 @@ N: Christian Vejlbo E: christian.vejlbo@tellabs.com D: FADS860T ethernet support +N: John Zhan +E: zhanz@sinovee.com +D: Support for SinoVee Microsystems SC8xx SBC + N: Alex Zuepke E: azu@sysgo.de D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM diff --git a/MAINTAINERS b/MAINTAINERS index 292a290..56f296d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -32,6 +32,10 @@ Jerry Van Baren <vanbaren_gerald@si.com> sacsng MPC8260 +Rick Bronson <rick@efn.org> + + AT91RM9200DK at91rm9200 + Oliver Brown <obrown@adventnetworks.com> gw8260 MPC8260 @@ -197,6 +201,10 @@ Rune Torgersen <runet@innovsys.com> MPC8266ADS MPC8266 +John Zhan <zhanz@sinovee.com> + + svm_sc8xx MPC8xx + ------------------------------------------------------------------------- Unknown / orphaned boards: @@ -25,9 +25,10 @@ LIST_8xx=" \ lwmon MBX MBX860T MHPC \ MVS1 NETVIA NX823 pcu_e \ R360MPI RPXClassic RPXlite RRvision \ - SM850 SPD823TS SXNI855T TOP860 \ - TQM823L TQM823L_LCD TQM850L TQM855L \ - TQM860L TQM860L_FEC TTTech v37 \ + SM850 SPD823TS svm_sc8xx SXNI855T \ + TOP860 TQM823L TQM823L_LCD TQM850L \ + TQM855L TQM860L TQM860L_FEC TTTech \ + v37 \ " ######################################################################### @@ -83,13 +84,13 @@ LIST_ppc="${LIST_8xx} ${LIST_824x} ${LIST_8260} \ ## StrongARM Systems ######################################################################### -LIST_SA="lart shannon dnp1110" +LIST_SA="at91rm9200dk dnp1110 lart shannon" ######################################################################### ## ARM7 Systems ######################################################################### -LIST_ARM7="impa7 ep7312" +LIST_ARM7="ep7312 impa7" ######################################################################### ## ARM9 Systems @@ -101,7 +102,7 @@ LIST_ARM9="smdk2400 smdk2410 trab VCMA9" ## Xscale Systems ######################################################################### -LIST_xscale="lubbock cradle csb226 innokom" +LIST_xscale="cradle csb226 innokom lubbock" LIST_arm="${LIST_SA} ${LIST_ARM7} ${LIST_ARM9} ${LIST_xscale}" @@ -57,7 +57,7 @@ ifeq ($(ARCH),ppc) CROSS_COMPILE = ppc_8xx- endif ifeq ($(ARCH),arm) -CROSS_COMPILE = arm_920TDI- +CROSS_COMPILE = arm-linux- endif ifeq ($(ARCH),i386) #CROSS_COMPILE = i386-elf- @@ -314,6 +314,10 @@ SM850_config : unconfig SPD823TS_config: unconfig @./mkconfig $(@:_config=) ppc mpc8xx spd8xx +svm_sc8xx_config: unconfig + @ >include/config.h + @./mkconfig $(@:_config=) ppc mpc8xx svm_sc8xx + SXNI855T_config: unconfig @./mkconfig $(@:_config=) ppc mpc8xx sixnet @@ -624,6 +628,9 @@ ELPPC_config: unconfig ## StrongARM Systems ######################################################################### +at91rm9200dk_config : unconfig + @./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk + lart_config : unconfig @./mkconfig $(@:_config=) arm sa1100 lart @@ -1549,6 +1549,7 @@ configuration. Low Level (hardware related) configuration options: +--------------------------------------------------- - CFG_CACHELINE_SIZE: Cache Line Size of the CPU. @@ -1928,7 +1929,7 @@ Some configuration options can be set using Environment Variables: ipaddr - IP address; needed for tftpboot command loadaddr - Default load address for commands like "bootp", - "rarpboot", "tftpboot" or "diskboot" + "rarpboot", "tftpboot", "loadb" or "diskboot" loads_echo - see CONFIG_LOADS_ECHO diff --git a/board/at91rm9200dk/Makefile b/board/at91rm9200dk/Makefile new file mode 100644 index 0000000..d925d33 --- /dev/null +++ b/board/at91rm9200dk/Makefile @@ -0,0 +1,47 @@ +# +# (C) Copyright 2003 +# 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 := at91rm9200dk.o flash.o +SOBJS := + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CPPFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +-include .depend + +######################################################################### diff --git a/board/at91rm9200dk/at91rm9200dk.c b/board/at91rm9200dk/at91rm9200dk.c new file mode 100644 index 0000000..7c3670b --- /dev/null +++ b/board/at91rm9200dk/at91rm9200dk.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.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 <AT91RM9200.h> + +/* ------------------------------------------------------------------------- */ +/* + * Miscelaneous platform dependent initialisations + */ + +int board_init(void) + { + DECLARE_GLOBAL_DATA_PTR; + + /* memory and cpu-speed are setup before relocation */ + /* so we do _nothing_ here */ + + /* arch number of AT91RM9200DK-Board */ + gd->bd->bi_arch_number = 251; + /* adress of boot parameters */ + gd->bd->bi_boot_params = PHYS_SDRAM + 0x100; + + return 0; +} + +int dram_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM; + gd->bd->bi_dram[0].size = PHYS_SDRAM_SIZE; + return 0; +} + +/* + * Disk On Chip (NAND) Millenium initialization. + * The NAND lives in the CS2* space + */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +extern void +nand_probe(ulong physadr); + +#define AT91_SMARTMEDIA_BASE 0x40000000 /* physical address to access memory on NCS3 */ +void +nand_init(void) +{ + /* Setup Smart Media, fitst enable the address range of CS3 */ + *AT91C_EBI_CSA |= AT91C_EBI_CS3A_SMC_SmartMedia; + /* set the bus interface characteristics based on + tDS Data Set up Time 30 - ns + tDH Data Hold Time 20 - ns + tALS ALE Set up Time 20 - ns + 16ns at 60 MHz ~= 3 */ +/*memory mapping structures */ +#define SM_ID_RWH (5 << 28) +#define SM_RWH (1 << 28) +#define SM_RWS (0 << 24) +#define SM_TDF (1 << 8) +#define SM_NWS (3) + AT91C_BASE_SMC2->SMC2_CSR[3] = ( SM_RWH|SM_RWS | AT91C_SMC2_ACSS_STANDARD | + AT91C_SMC2_DBW_8 | SM_TDF | + AT91C_SMC2_WSEN | SM_NWS); + + /* enable the SMOE line PC0=SMCE, A21=CLE, A22=ALE */ + *AT91C_PIOC_ASR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE; + *AT91C_PIOC_PDR = AT91C_PC0_BFCK | AT91C_PC1_BFRDY_SMOE | AT91C_PC3_BFBAA_SMWE; + + /* Configure PC2 as input (signal READY of the SmartMedia) */ + *AT91C_PIOC_PER = AT91C_PC2_BFAVD; /* enable direct output enable */ + *AT91C_PIOC_ODR = AT91C_PC2_BFAVD; /* disable output */ + + /* Configure PB1 as input (signal Card Detect of the SmartMedia) */ + *AT91C_PIOB_PER = AT91C_PIO_PB1; /* enable direct output enable */ + *AT91C_PIOB_ODR = AT91C_PIO_PB1; /* disable output */ + + if (*AT91C_PIOB_PDSR & AT91C_PIO_PB1) + printf ("No "); + printf ("SmartMedia card inserted\n"); + + printf("Probing at 0x%.8x\n", AT91_SMARTMEDIA_BASE); + nand_probe(AT91_SMARTMEDIA_BASE); +} +#endif diff --git a/board/at91rm9200dk/config.mk b/board/at91rm9200dk/config.mk new file mode 100644 index 0000000..a682451 --- /dev/null +++ b/board/at91rm9200dk/config.mk @@ -0,0 +1,2 @@ +TEXT_BASE = 0x21fa0000 + diff --git a/board/at91rm9200dk/flash.c b/board/at91rm9200dk/flash.c new file mode 100644 index 0000000..6497f11 --- /dev/null +++ b/board/at91rm9200dk/flash.c @@ -0,0 +1,397 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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> + +ulong myflush(void); + + +#define FLASH_BANK_SIZE 0x200000 /* 2 MB */ +#define MAIN_SECT_SIZE 0x10000 /* 64 KB */ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + + +#define CMD_READ_ARRAY 0x00F0 +#define CMD_UNLOCK1 0x00AA +#define CMD_UNLOCK2 0x0055 +#define CMD_ERASE_SETUP 0x0080 +#define CMD_ERASE_CONFIRM 0x0030 +#define CMD_PROGRAM 0x00A0 +#define CMD_UNLOCK_BYPASS 0x0020 + +#define MEM_FLASH_ADDR1 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00005555<<1))) +#define MEM_FLASH_ADDR2 (*(volatile u16 *)(CFG_FLASH_BASE + (0x00002AAA<<1))) + +#define BIT_ERASE_DONE 0x0080 +#define BIT_RDY_MASK 0x0080 +#define BIT_PROGRAM_ERROR 0x0020 +#define BIT_TIMEOUT 0x80000000 /* our flag */ + +#define READY 1 +#define ERR 2 +#define TMO 4 + +/*----------------------------------------------------------------------- + */ + +ulong flash_init(void) +{ + int i, j; + ulong size = 0; + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) + { + ulong flashbase = 0; + flash_info[i].flash_id = + (ATM_MANUFACT & FLASH_VENDMASK) | + (ATM_ID_BV1614 & FLASH_TYPEMASK); + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CFG_MAX_FLASH_SECT; + memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); + if (i == 0) + flashbase = PHYS_FLASH_1; + else + panic("configured to many flash banks!\n"); + for (j = 0; j < flash_info[i].sector_count; j++) + { + + if (j <= 9) + { + /* 1st to 8th are 8 KB */ + if (j <= 7) + { + flash_info[i].start[j] = flashbase + j*0x2000; + } + + /* 9th and 10th are both 32 KB */ + if ((j == 8) || (j == 9)) + { + flash_info[i].start[j] = flashbase + 0x10000 + (j-8)*0x8000; + } + } + else + { + flash_info[i].start[j] = flashbase + (j-8)*MAIN_SECT_SIZE; + } + } + size += flash_info[i].size; + } + + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_ENV_ADDR - 1, + &flash_info[0]); + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + switch (info->flash_id & FLASH_VENDMASK) + { + case (ATM_MANUFACT & FLASH_VENDMASK): + printf("Atmel: "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) + { + case (ATM_ID_BV1614 & FLASH_TYPEMASK): + printf("AT49BV1614 (16Mbit)\n"); + break; + default: + printf("Unknown Chip Type\n"); + goto Done; + 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"); + +Done: +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + ulong result; + int iflag, cflag, prot, sect; + int rc = ERR_OK; + int chip1; + + /* first look for protection bits */ + + if (info->flash_id == FLASH_UNKNOWN) + return ERR_UNKNOWN_FLASH_TYPE; + + if ((s_first < 0) || (s_first > s_last)) { + return ERR_INVAL; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (ATM_MANUFACT & FLASH_VENDMASK)) { + return ERR_UNKNOWN_FLASH_VENDOR; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + cflag = icache_status(); + icache_disable(); + iflag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last && !ctrlc(); sect++) + { + printf("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + + if (info->protect[sect] == 0) + { /* not protected */ + volatile u16 *addr = (volatile u16 *)(info->start[sect]); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_ERASE_SETUP; + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + *addr = CMD_ERASE_CONFIRM; + + /* wait until flash is ready */ + chip1 = 0; + + do + { + result = *addr; + + /* check timeout */ + if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) + { + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + chip1 = TMO; + break; + } + + if (!chip1 && (result & 0xFFFF) & BIT_ERASE_DONE) + chip1 = READY; + + } while (!chip1); + + MEM_FLASH_ADDR1 = CMD_READ_ARRAY; + + if (chip1 == ERR) + { + rc = ERR_PROG_ERROR; + goto outahere; + } + if (chip1 == TMO) + { + rc = ERR_TIMOUT; + goto outahere; + } + + printf("ok.\n"); + } + else /* it was protected */ + { + printf("protected!\n"); + } + } + + if (ctrlc()) + printf("User Interrupt!\n"); + +outahere: + /* allow flash to settle - wait 10 ms */ + udelay_masked(10000); + + if (iflag) + enable_interrupts(); + + if (cflag) + icache_enable(); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +volatile static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile u16 *addr = (volatile u16 *)dest; + ulong result; + int rc = ERR_OK; + int cflag, iflag; + int chip1; + + /* + * Check if Flash is (sufficiently) erased + */ + result = *addr; + if ((result & data) != data) + return ERR_NOT_ERASED; + + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + cflag = icache_status(); + icache_disable(); + iflag = disable_interrupts(); + + MEM_FLASH_ADDR1 = CMD_UNLOCK1; + MEM_FLASH_ADDR2 = CMD_UNLOCK2; + MEM_FLASH_ADDR1 = CMD_PROGRAM; + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + + /* wait until flash is ready */ + chip1 = 0; + do + { + result = *addr; + + /* check timeout */ + if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) + { + chip1 = ERR | TMO; + break; + } + if (!chip1 && ((result & 0x80) == (data & 0x80))) + chip1 = READY; + + } while (!chip1); + + *addr = CMD_READ_ARRAY; + + if (chip1 == ERR || *addr != data) + rc = ERR_PROG_ERROR; + + if (iflag) + enable_interrupts(); + + if (cflag) + icache_enable(); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong wp, data; + int rc; + + if(addr & 1) { + printf("unaligned destination not supported\n"); + return ERR_ALIGN; + }; + + if((int)src & 1) { + printf("unaligned source not supported\n"); + return ERR_ALIGN; + }; + + wp = addr; + + while (cnt >= 2) { + data = *((volatile u16*)src); + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + src += 2; + wp += 2; + cnt -= 2; + } + + if(cnt == 1) { + data = (*((volatile u8*)src)) | (*((volatile u8*)(wp+1)) << 8); + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + src += 1; + wp += 1; + cnt -= 1; + }; + + return ERR_OK; +} diff --git a/board/at91rm9200dk/u-boot.lds b/board/at91rm9200dk/u-boot.lds new file mode 100644 index 0000000..2447bca --- /dev/null +++ b/board/at91rm9200dk/u-boot.lds @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@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-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/at91rm9200/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/dnp1110/dnp1110.c b/board/dnp1110/dnp1110.c index d6b1815..4a2b44e 100644 --- a/board/dnp1110/dnp1110.c +++ b/board/dnp1110/dnp1110.c @@ -23,7 +23,7 @@ */ #include <common.h> - +#include <SA-1100.h> /* ------------------------------------------------------------------------- */ @@ -41,8 +41,9 @@ int board_init (void) /* arch number of DNP1110-Board */ gd->bd->bi_arch_number = 255; - /* adress of boot parameters */ - gd->bd->bi_boot_params = 0xc0000100; + /* flash vpp on */ + PPDR |= 0x80; /* assumes LCD controller is off */ + PPSR |= 0x80; return 0; } diff --git a/board/dnp1110/flash.c b/board/dnp1110/flash.c index ca9aff9..bb6d2e7 100644 --- a/board/dnp1110/flash.c +++ b/board/dnp1110/flash.c @@ -1,7 +1,9 @@ /* - * (C) Copyright 2002 - * Sysgo Real-Time Solutions, GmbH <www.elinos.com> - * Rolf Offermanns <rof@sysgo.de> + * (C) Copyright 2001 + * Kyle Harris, Nexus Technologies, Inc. kharris@nexus-tech.net + * + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. * * See file CREDITS for list of people who contributed to this * project. @@ -23,81 +25,58 @@ */ #include <common.h> - -ulong myflush(void); +#include <linux/byteorder/swab.h> -#define FLASH_BANK_SIZE 0x800000 -#define MAIN_SECT_SIZE 0x20000 -#define PARAM_SECT_SIZE 0x4000 - -/* puzzle magic for lart - * data_*_flash are def'd in flashasm.S - */ +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ -extern u32 data_from_flash(u32); -extern u32 data_to_flash(u32); +/* Board support for 1 or 2 flash devices */ +#undef FLASH_PORT_WIDTH32 +#define FLASH_PORT_WIDTH16 -#define PUZZLE_FROM_FLASH(x) (x) -#define PUZZLE_TO_FLASH(x) (x) +#ifdef FLASH_PORT_WIDTH16 +#define FLASH_PORT_WIDTH ushort +#define FLASH_PORT_WIDTHV vu_short +#define SWAP(x) __swab16(x) +#else +#define FLASH_PORT_WIDTH ulong +#define FLASH_PORT_WIDTHV vu_long +#define SWAP(x) __swab32(x) +#endif -flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV +#define mb() __asm__ __volatile__ ("" : : : "memory") -#define CMD_READ_ARRAY 0x00FF00FF -#define CMD_IDENTIFY 0x00900090 -#define CMD_ERASE_SETUP 0x00200020 -#define CMD_ERASE_CONFIRM 0x00D000D0 -#define CMD_PROGRAM 0x00400040 -#define CMD_RESUME 0x00D000D0 -#define CMD_SUSPEND 0x00B000B0 -#define CMD_STATUS_READ 0x00700070 -#define CMD_STATUS_RESET 0x00500050 - -#define BIT_BUSY 0x00800080 -#define BIT_ERASE_SUSPEND 0x00400040 -#define BIT_ERASE_ERROR 0x00200020 -#define BIT_PROGRAM_ERROR 0x00100010 -#define BIT_VPP_RANGE_ERROR 0x00080008 -#define BIT_PROGRAM_SUSPEND 0x00040004 -#define BIT_PROTECT_ERROR 0x00020002 -#define BIT_UNDEFINED 0x00010001 - -#define BIT_SEQUENCE_ERROR 0x00300030 -#define BIT_TIMEOUT 0x80000000 +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (FPW *addr, flash_info_t *info); +static int write_data (flash_info_t *info, ulong dest, FPW data); +static void flash_get_offsets (ulong base, flash_info_t *info); +void inline spin_wheel(void); /*----------------------------------------------------------------------- */ -ulong flash_init(void) +unsigned long flash_init (void) { - int i, j; + int i; ulong size = 0; for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { - ulong flashbase = 0; - flash_info[i].flash_id = - (INTEL_MANUFACT & FLASH_VENDMASK) | - (INTEL_ID_28F160F3B & FLASH_TYPEMASK); - flash_info[i].size = FLASH_BANK_SIZE; - flash_info[i].sector_count = CFG_MAX_FLASH_SECT; - memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); - if (i == 0) - flashbase = PHYS_FLASH_1; - else - panic("configured to many flash banks!\n"); - for (j = 0; j < flash_info[i].sector_count; j++) - { - if (j <= 7) - { - flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE; - } - else - { - flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE; - } - } + switch (i) + { + case 0: + flash_get_size((FPW *)PHYS_FLASH_1, &flash_info[i]); + flash_get_offsets(PHYS_FLASH_1, &flash_info[i]); + break; + default: + panic("configured to many flash banks!\n"); + break; + } size += flash_info[i].size; } @@ -118,150 +97,138 @@ ulong flash_init(void) /*----------------------------------------------------------------------- */ -void flash_print_info (flash_info_t *info) +static void flash_get_offsets (ulong base, flash_info_t *info) { - int i; - - switch (info->flash_id & FLASH_VENDMASK) - { - case (INTEL_MANUFACT & FLASH_VENDMASK): - printf("Intel: "); - break; - default: - printf("Unknown Vendor "); - break; - } + int i; - switch (info->flash_id & FLASH_TYPEMASK) - { - case (INTEL_ID_28F160F3B & FLASH_TYPEMASK): - printf("2x 28F160F3B (16Mbit)\n"); - break; - default: - printf("Unknown Chip Type\n"); - goto Done; - 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 "); + if (info->flash_id == FLASH_UNKNOWN) { + return; } - printf (" %08lX%s", info->start[i], - info->protect[i] ? " (RO)" : " "); - } - printf ("\n"); -Done: + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) { + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + (i * PHYS_FLASH_SECT_SIZE); + info->protect[i] = 0; + } + } } /*----------------------------------------------------------------------- */ - -int flash_error (ulong code) +void flash_print_info (flash_info_t *info) { - /* Check bit patterns */ - /* SR.7=0 is busy, SR.7=1 is ready */ - /* all other flags indicate error on 1 */ - /* SR.0 is undefined */ - /* Timeout is our faked flag */ - - /* sequence is described in Intel 290644-005 document */ - - /* check Timeout */ - if (code & BIT_TIMEOUT) - { - printf ("Timeout\n"); - return ERR_TIMOUT; - } + int i; - /* check Busy, SR.7 */ - if (~code & BIT_BUSY) - { - printf ("Busy\n"); - return ERR_PROG_ERROR; - } + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } - /* check Vpp low, SR.3 */ - if (code & BIT_VPP_RANGE_ERROR) - { - printf ("Vpp range error\n"); - return ERR_PROG_ERROR; + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: printf ("INTEL "); break; + default: printf ("Unknown Vendor "); break; } - /* check Device Protect Error, SR.1 */ - if (code & BIT_PROTECT_ERROR) - { - printf ("Device protect error\n"); - return ERR_PROG_ERROR; - } + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F128J3A: + printf ("28F128J3A\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; +} - /* check Command Seq Error, SR.4 & SR.5 */ - if (code & BIT_SEQUENCE_ERROR) - { - printf ("Command seqence error\n"); - return ERR_PROG_ERROR; +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (FPW *addr, flash_info_t *info) +{ + volatile FPW value; + /* Write auto select command: read Manufacturer ID */ + addr[0x5555] = (FPW)0x00AA00AA; + addr[0x2AAA] = (FPW)0x00550055; + addr[0x5555] = (FPW)0x00900090; + + mb(); + value = addr[0]; + + switch (value) { + + case (FPW)INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + addr[0] = (FPW)0x00FF00FF; /* restore read mode */ + return (0); /* no or unknown flash */ } - /* check Block Erase Error, SR.5 */ - if (code & BIT_ERASE_ERROR) - { - printf ("Block erase error\n"); - return ERR_PROG_ERROR; - } + mb(); + value = addr[1]; /* device ID */ + switch (value) { - /* check Program Error, SR.4 */ - if (code & BIT_PROGRAM_ERROR) - { - printf ("Program error\n"); - return ERR_PROG_ERROR; - } + case (FPW)INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 0x02000000; + break; /* => 16 MB */ - /* check Block Erase Suspended, SR.6 */ - if (code & BIT_ERASE_SUSPEND) - { - printf ("Block erase suspended\n"); - return ERR_PROG_ERROR; + default: + info->flash_id = FLASH_UNKNOWN; + break; } - /* check Program Suspended, SR.2 */ - if (code & BIT_PROGRAM_SUSPEND) - { - printf ("Program suspended\n"); - return ERR_PROG_ERROR; - } + if (info->sector_count > CFG_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CFG_MAX_FLASH_SECT); + info->sector_count = CFG_MAX_FLASH_SECT; + } + + addr[0] = (FPW)0x00FF00FF; /* restore read mode */ - /* OK, no error */ - return ERR_OK; + return (info->size); } + /*----------------------------------------------------------------------- */ int flash_erase (flash_info_t *info, int s_first, int s_last) { - ulong result; - int iflag, cflag, prot, sect; - int rc = ERR_OK; - - /* first look for protection bits */ - - if (info->flash_id == FLASH_UNKNOWN) - return ERR_UNKNOWN_FLASH_TYPE; + int flag, prot, sect; + ulong type, start, last; + int rcode = 0; if ((s_first < 0) || (s_first > s_last)) { - return ERR_INVAL; + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; } - if ((info->flash_id & FLASH_VENDMASK) != - (INTEL_MANUFACT & FLASH_VENDMASK)) { - return ERR_UNKNOWN_FLASH_VENDOR; + type = (info->flash_id & FLASH_VENDMASK); + if ((type != FLASH_MAN_INTEL)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; } prot = 0; @@ -270,152 +237,79 @@ int flash_erase (flash_info_t *info, int s_first, int s_last) prot++; } } - if (prot) - return ERR_PROTECTED; - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - cflag = icache_status(); - icache_disable(); - iflag = disable_interrupts(); + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + start = get_timer (0); + last = start; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); /* Start erase on unprotected sectors */ - for (sect = s_first; sect<=s_last && !ctrlc(); sect++) - { + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + FPWV *addr = (FPWV *)(info->start[sect]); + FPW status; + printf("Erasing sector %2d ... ", sect); /* arm simple, non interrupt dependent timer */ reset_timer_masked(); - if (info->protect[sect] == 0) - { /* not protected */ - vu_long *addr = (vu_long *)(info->start[sect]); - - *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET); - *addr = PUZZLE_TO_FLASH(CMD_ERASE_SETUP); - *addr = PUZZLE_TO_FLASH(CMD_ERASE_CONFIRM); - - /* wait until flash is ready */ - do - { - /* check timeout */ - if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) - { - *addr = PUZZLE_TO_FLASH(CMD_SUSPEND); - result = BIT_TIMEOUT; - break; - } - - result = PUZZLE_FROM_FLASH(*addr); - } while (~result & BIT_BUSY); - - *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY); - - if ((rc = flash_error(result)) != ERR_OK) - goto outahere; - - printf("ok.\n"); - } - else /* it was protected */ - { - printf("protected!\n"); + *addr = (FPW)0x00500050; /* clear status register */ + *addr = (FPW)0x00200020; /* erase setup */ + *addr = (FPW)0x00D000D0; /* erase confirm */ + + while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) { + if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = (FPW)0x00B000B0; /* suspend erase */ + *addr = (FPW)0x00FF00FF; /* reset to read mode */ + rcode = 1; + break; } } - if (ctrlc()) - printf("User Interrupt!\n"); - -outahere: - /* allow flash to settle - wait 10 ms */ - udelay_masked(10000); - - if (iflag) - enable_interrupts(); - - if (cflag) - icache_enable(); - - return rc; -} - -/*----------------------------------------------------------------------- - * Copy memory to flash - */ - -volatile static int write_word (flash_info_t *info, ulong dest, ulong data) -{ - vu_long *addr = (vu_long *)dest; - ulong result; - int rc = ERR_OK; - int cflag, iflag; - - /* Check if Flash is (sufficiently) erased - */ - result = PUZZLE_FROM_FLASH(*addr); - if ((result & data) != data) - return ERR_NOT_ERASED; - - /* - * Disable interrupts which might cause a timeout - * here. Remember that our exception vectors are - * at address 0 in the flash, and we don't want a - * (ticker) exception to happen while the flash - * chip is in programming mode. - */ - cflag = icache_status(); - icache_disable(); - iflag = disable_interrupts(); - - *addr = PUZZLE_TO_FLASH(CMD_STATUS_RESET); - *addr = PUZZLE_TO_FLASH(CMD_PROGRAM); - *addr = data; - - /* arm simple, non interrupt dependent timer */ - reset_timer_masked(); - - /* wait until flash is ready */ - do - { - /* check timeout */ - if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) - { - *addr = PUZZLE_TO_FLASH(CMD_SUSPEND); - result = BIT_TIMEOUT; - break; - } - - result = PUZZLE_FROM_FLASH(*addr); - } while (~result & BIT_BUSY); - - *addr = PUZZLE_TO_FLASH(CMD_READ_ARRAY); - - rc = flash_error(result); + *addr = (FPW)0x00500050; /* clear status register cmd. */ + *addr = (FPW)0x00FF00FF; /* resest to read mode */ - if (iflag) - enable_interrupts(); - - if (cflag) - icache_enable(); - - return rc; + printf (" done\n"); + } + } + return rcode; } /*----------------------------------------------------------------------- - * Copy memory to flash. + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + * 4 - Flash not identified */ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) { - ulong cp, wp, data; - int l; - int i, rc; + ulong cp, wp; + FPW data; + int count, i, l, rc, port_width; - wp = (addr & ~3); /* get lower word aligned address */ + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } +/* get lower word aligned address */ +#ifdef FLASH_PORT_WIDTH16 + wp = (addr & ~1); + port_width = 2; +#else + wp = (addr & ~3); + port_width = 4; +#endif /* * handle unaligned start bytes @@ -423,51 +317,109 @@ int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) if ((l = addr - wp) != 0) { data = 0; for (i=0, cp=wp; i<l; ++i, ++cp) { - data = (data >> 8) | (*(uchar *)cp << 24); + data = (data << 8) | (*(uchar *)cp); } - for (; i<4 && cnt>0; ++i) { - data = (data >> 8) | (*src++ << 24); + for (; i<port_width && cnt>0; ++i) { + data = (data << 8) | *src++; --cnt; ++cp; } - for (; cnt==0 && i<4; ++i, ++cp) { - data = (data >> 8) | (*(uchar *)cp << 24); + for (; cnt==0 && i<port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); } - if ((rc = write_word(info, wp, data)) != 0) { + if ((rc = write_data(info, wp, SWAP(data))) != 0) { return (rc); } - wp += 4; + wp += port_width; } /* * handle word aligned part */ - while (cnt >= 4) { - data = *((vu_long*)src); - if ((rc = write_word(info, wp, data)) != 0) { + count = 0; + while (cnt >= port_width) { + data = 0; + for (i=0; i<port_width; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_data(info, wp, SWAP(data))) != 0) { return (rc); } - src += 4; - wp += 4; - cnt -= 4; + wp += port_width; + cnt -= port_width; + if (count++ > 0x800) + { + spin_wheel(); + count = 0; + } } if (cnt == 0) { - return ERR_OK; + return (0); } /* * handle unaligned tail bytes */ data = 0; - for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { - data = (data >> 8) | (*src++ << 24); + for (i=0, cp=wp; i<port_width && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; --cnt; } - for (; i<4; ++i, ++cp) { - data = (data >> 8) | (*(uchar *)cp << 24); + for (; i<port_width; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_data(info, wp, SWAP(data))); +} + +/*----------------------------------------------------------------------- + * Write a word or halfword to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_data (flash_info_t *info, ulong dest, FPW data) +{ + FPWV *addr = (FPWV *)dest; + ulong status; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + printf("not erased at %08lx (%x)\n",(ulong)addr,*addr); + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *addr = (FPW)0x00400040; /* write setup */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + + /* wait while polling the status register */ + while (((status = *addr) & (FPW)0x00800080) != (FPW)0x00800080) { + if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) { + *addr = (FPW)0x00FF00FF; /* restore read mode */ + return (1); + } } - return write_word(info, wp, data); + *addr = (FPW)0x00FF00FF; /* restore read mode */ + + return (0); +} + +void inline +spin_wheel(void) +{ + static int p=0; + static char w[] = "\\/-"; + + printf("\010%c", w[p]); + (++p == 3) ? (p = 0) : 0; } + diff --git a/board/dnp1110/memsetup.S b/board/dnp1110/memsetup.S index bebd697..6539c20 100644 --- a/board/dnp1110/memsetup.S +++ b/board/dnp1110/memsetup.S @@ -25,8 +25,8 @@ -#include <config.h> -#include <version.h> +#include "config.h" +#include "version.h" /* some parameters for the board */ @@ -34,63 +34,103 @@ MEM_BASE: .long 0xa0000000 MEM_START: .long 0xc0000000 -#define MDCNFG 0x00 -#define MDCAS0 0x04 -#define MDCAS1 0x08 -#define MDCAS2 0x0c -#define MSC0 0x10 -#define MSC1 0x14 -#define MECR 0x18 - -mdcas0: .long 0xc71c703f -mdcas1: .long 0xffc71c71 -mdcas2: .long 0xffffffff -/* mdcnfg: .long 0x0bb2bcbf */ -mdcnfg: .long 0x0334b22f @ alt -/* mcs0: .long 0xfff8fff8 */ -msc0: .long 0xad8c4888 @ alt -mecr: .long 0x00060006 -/* mecr: .long 0x994a994a @ alt */ +#define MDCNFG 0x00 +#define MDCAS00 0x04 /* CAS waveform rotate reg 0 */ +#define MDCAS01 0x08 /* CAS waveform rotate reg 1 bank */ +#define MDCAS02 0x0C /* CAS waveform rotate reg 2 bank */ +#define MDREFR 0x1C /* DRAM refresh control reg */ +#define MDCAS20 0x20 /* CAS waveform rotate reg 0 bank */ +#define MDCAS21 0x24 /* CAS waveform rotate reg 1 bank */ +#define MDCAS22 0x28 /* CAS waveform rotate reg 2 bank */ +#define MECR 0x18 /* Expansion memory (PCMCIA) bus configuration register */ +#define MSC0 0x10 /* static memory control reg 0 */ +#define MSC1 0x14 /* static memory control reg 1 */ +#define MSC2 0x2C /* static memory control reg 2 */ +#define SMCNFG 0x30 /* SMROM configuration reg */ + +mdcas00: .long 0x5555557F +mdcas01: .long 0x55555555 +mdcas02: .long 0x55555555 +mdcas20: .long 0x5555557F +mdcas21: .long 0x55555555 +mdcas22: .long 0x55555555 +mdcnfg: .long 0x0000B25C +mdrefr: .long 0x007000C1 +mecr: .long 0x10841084 +msc0: .long 0x00004774 +msc1: .long 0x00000000 +msc2: .long 0x00000000 +smcnfg: .long 0x00000000 /* setting up the memory */ .globl memsetup memsetup: - ldr r0, MEM_BASE - /* Setup the flash memory */ - ldr r1, msc0 - str r1, [r0, #MSC0] + ldr r0, MEM_BASE /* Set up the DRAM */ - /* MDCAS0 */ - ldr r1, mdcas0 - str r1, [r0, #MDCAS0] + /* MDCAS00 */ + ldr r1, mdcas00 + str r1, [r0, #MDCAS00] - /* MDCAS1 */ - ldr r1, mdcas1 - str r1, [r0, #MDCAS1] + /* MDCAS01 */ + ldr r1, mdcas01 + str r1, [r0, #MDCAS01] - /* MDCAS2 */ - ldr r1, mdcas2 - str r1, [r0, #MDCAS2] + /* MDCAS02 */ + ldr r1, mdcas02 + str r1, [r0, #MDCAS02] - /* MDCNFG */ - ldr r1, mdcnfg - str r1, [r0, #MDCNFG] + /* MDCAS20 */ + ldr r1, mdcas20 + str r1, [r0, #MDCAS20] + + /* MDCAS21 */ + ldr r1, mdcas21 + str r1, [r0, #MDCAS21] + + /* MDCAS22 */ + ldr r1, mdcas22 + str r1, [r0, #MDCAS22] + + /* MDREFR */ + ldr r1, mdrefr + str r1, [r0, #MDREFR] /* Set up PCMCIA space */ ldr r1, mecr str r1, [r0, #MECR] - /* Load something to activate bank */ - ldr r1, MEM_START + /* Setup the flash memory and other */ + ldr r1, msc0 + str r1, [r0, #MSC0] + ldr r1, msc1 + str r1, [r0, #MSC1] + + ldr r1, msc2 + str r1, [r0, #MSC2] + + ldr r1, smcnfg + str r1, [r0, #SMCNFG] + + /* MDCNFG */ + ldr r1, mdcnfg + bic r1, r1, #0x00000001 + str r1, [r0, #MDCNFG] + + /* Load something to activate bank */ + ldr r2, MEM_START .rept 8 - ldr r0, [r1] + ldr r1, [r2] .endr + /* MDCNFG */ + ldr r1, mdcnfg + orr r1, r1, #0x00000001 + str r1, [r0, #MDCNFG] + /* everything is fine now */ mov pc, lr - diff --git a/board/ebony/flash.c b/board/ebony/flash.c index 6efd566..961c616 100644 --- a/board/ebony/flash.c +++ b/board/ebony/flash.c @@ -327,6 +327,9 @@ void flash_print_info (flash_info_t *info) case (FLASH_WORD_SIZE)SST_MANUFACT: info->flash_id = FLASH_MAN_SST; break; + case (FLASH_WORD_SIZE)STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; default: info->flash_id = FLASH_UNKNOWN; info->sector_count = 0; @@ -349,6 +352,11 @@ void flash_print_info (flash_info_t *info) info->sector_count = 32; info->size = 0x00200000; break; /* => 2 MB */ + case (FLASH_WORD_SIZE)STM_ID_F040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x0080000; /* => 512 ko */ + break; case (FLASH_WORD_SIZE)AMD_ID_F040B: info->flash_id += FLASH_AM040; info->sector_count = 8; diff --git a/board/innokom/flash.c b/board/innokom/flash.c index b56707d..32c57d8 100644 --- a/board/innokom/flash.c +++ b/board/innokom/flash.c @@ -9,6 +9,9 @@ * (C) Copyright 2002 * Robert Schwebel, Pengutronix, <r.schwebel@pengutronix.de> * + * (C) Copyright 2002 + * Kai-Uwe Bloem, GDS, <kai-uwe.bloem@auerswald.de> + * * See file CREDITS for list of people who contributed to this * project. * diff --git a/board/innokom/innokom.c b/board/innokom/innokom.c index 0176d9c..5ee5117 100644 --- a/board/innokom/innokom.c +++ b/board/innokom/innokom.c @@ -39,20 +39,28 @@ * The Innokom board has GPIO70 connected to SCLK which can be toggled * until all chips think that their current cycles are finished. */ -void i2c_init_board(void) +int i2c_init_board(void) { - int i; + int i, icr; - /* set gpio pin to output */ - GPDR(70) |= GPIO_bit(70); - for (i = 0; i < 11; i++) { + /* disable I2C controller first, otherwhise it thinks we want to */ + /* talk to the slave port... */ + icr = ICR; ICR &= ~(ICR_SCLE | ICR_IUE); + + /* set gpio pin low _before_ we change direction to output */ GPCR(70) = GPIO_bit(70); + + /* now toggle between output=low and high-impedance */ + for (i = 0; i < 20; i++) { + GPDR(70) |= GPIO_bit(70); /* output */ udelay(10); - GPSR(70) = GPIO_bit(70); + GPDR(70) &= ~GPIO_bit(70); /* input */ udelay(10); } - /* set gpio pin to input */ - GPDR(70) &= ~GPIO_bit(70); + + ICR = icr; + + return 0; } @@ -98,6 +106,9 @@ int board_init (void) /* adress of boot parameters */ gd->bd->bi_boot_params = 0xa0000100; + /* baud rate */ + gd->bd->bi_baudrate = CONFIG_BAUDRATE; + return 0; } diff --git a/board/svm_sc8xx/Makefile b/board/svm_sc8xx/Makefile new file mode 100644 index 0000000..ef173d0 --- /dev/null +++ b/board/svm_sc8xx/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 + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/svm_sc8xx/config.mk b/board/svm_sc8xx/config.mk new file mode 100644 index 0000000..4bec9cb --- /dev/null +++ b/board/svm_sc8xx/config.mk @@ -0,0 +1,24 @@ +# +# (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 +# + +TEXT_BASE = 0x40000000 diff --git a/board/svm_sc8xx/flash.c b/board/svm_sc8xx/flash.c new file mode 100644 index 0000000..8c0e229 --- /dev/null +++ b/board/svm_sc8xx/flash.c @@ -0,0 +1,801 @@ +/* + * (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> + +#ifndef CFG_ENV_ADDR +#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +#endif + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static int write_word (flash_info_t *info, ulong dest, ulong data); +#if 0 +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static void flash_get_offsets (ulong base, flash_info_t *info); +#endif +#ifdef CONFIG_BOOT_8B +static int my_in_8( unsigned char *addr); +static void my_out_8( unsigned char *addr, int val); +#endif +#ifdef CONFIG_BOOT_16B +static int my_in_be16( unsigned short *addr); +static void my_out_be16( unsigned short *addr, int val); +#endif +#ifdef CONFIG_BOOT_32B +static unsigned my_in_be32( unsigned *addr); +static void my_out_be32( unsigned *addr, int val); +#endif +/*----------------------------------------------------------------------- + */ + +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; + + size_b0=0; + size_b1=0; + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } +#ifdef CFG_DOC_BASE +#ifndef CONFIG_FEL8xx_AT + memctl->memc_or5 = (0xffff8000 | CFG_OR_TIMING_DOC ); /* 32k bytes */ + memctl->memc_br5 = CFG_DOC_BASE | 0x401; +#else + memctl->memc_or3 = (0xffff8000 | CFG_OR_TIMING_DOC ); /* 32k bytes */ + memctl->memc_br3 = CFG_DOC_BASE | 0x401; +#endif +#endif +#if defined( CONFIG_BOOT_8B) +// memctl->memc_or0 = 0xfff80ff4; /* 4MB bytes */ +// memctl->memc_br0 = 0x40000401; + size_b0 = 0x80000; /* 512 K */ + flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM040; + flash_info[0].sector_count = 8; + flash_info[0].size = 0x00080000; + /* set up sector start address table */ + for (i = 0; i < flash_info[0].sector_count; i++) + flash_info[0].start[i] = 0x40000000 + (i * 0x10000); + /* protect all sectors */ + for (i = 0; i < flash_info[0].sector_count; i++) + flash_info[0].protect[i] = 0x1; +#elif defined (CONFIG_BOOT_16B) +// memctl->memc_or0 = 0xfff80ff4; /* 4MB bytes */ +// memctl->memc_br0 = 0x40000401; + size_b0 = 0x400000; /* 4MB , assume AMD29LV320B */ + flash_info[0].flash_id = FLASH_MAN_AMD | FLASH_AM320B; + flash_info[0].sector_count = 67; + flash_info[0].size = 0x00400000; + /* set up sector start address table */ + flash_info[0].start[0] = 0x40000000 ; + flash_info[0].start[1] = 0x40000000 + 0x4000; + flash_info[0].start[2] = 0x40000000 + 0x6000; + flash_info[0].start[3] = 0x40000000 + 0x8000; + for (i = 4; i < flash_info[0].sector_count; i++) + flash_info[0].start[i] = 0x40000000 + 0x10000 + ((i-4) * 0x10000); + /* protect all sectors */ + for (i = 0; i < flash_info[0].sector_count; i++) + flash_info[0].protect[i] = 0x1; +#endif + + +#ifdef CONFIG_BOOT_32B + + /* 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); + } + + 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); + } + + /* Remap FLASH according to real size */ + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK); + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; + + /* 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 */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + &flash_info[0]); +#endif + + if (size_b1) { + memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000); + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | + BR_MS_GPCM | BR_V; + + /* 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 */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[1]); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + &flash_info[1]); +#endif + } else { + memctl->memc_br1 = 0; /* invalidate bank */ + + 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; + + +#endif /* CONFIG_BOOT_32B */ + + return (size_b0 + size_b1); +} +#if 0 +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address 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; + } + } +} +#endif +/*----------------------------------------------------------------------- + */ +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) { + 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! + */ +#if 0 +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + ulong value; + ulong base = (ulong)addr; + + /* Write auto select command: read Manufacturer ID */ + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00900090; + + 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; + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + + switch (value) { + 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 */ + } + + /* set up sector start address 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; + } + } + + /* 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]; + + *addr = 0x00F000F0; /* reset bank */ + } + + return (info->size); +} +#endif + +/*----------------------------------------------------------------------- + */ + +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,in_mid,in_did; + 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 %08lx - aborted\n", + info->flash_id); + 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 defined (CONFIG_BOOT_8B ) + my_out_8( (unsigned char * ) ((ulong)addr+0x555) , 0xaa ); + my_out_8( (unsigned char * ) ((ulong)addr+0x2aa) , 0x55 ); + my_out_8( (unsigned char * ) ((ulong)addr+0x555) , 0x90 ); + in_mid=my_in_8( (unsigned char * ) addr ); + in_did=my_in_8( (unsigned char * ) ((ulong)addr+1) ); + printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); + my_out_8( (unsigned char *)addr, 0xf0); + udelay(1); + my_out_8( (unsigned char *) ((ulong)addr+0x555),0xaa ); + my_out_8( (unsigned char *) ((ulong)addr+0x2aa),0x55 ); + my_out_8( (unsigned char *) ((ulong)addr+0x555),0x80 ); + my_out_8( (unsigned char *) ((ulong)addr+0x555),0xaa ); + my_out_8( (unsigned char *) ((ulong)addr+0x2aa),0x55 ); + /* 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]); + //addr[0] = 0x00300030; + my_out_8( (unsigned char *) ((ulong)addr),0x30 ); + l_sect = sect; + } + } +#elif defined(CONFIG_BOOT_16B ) + my_out_be16( (unsigned short * ) ((ulong)addr+ (0xaaa)) , 0xaa ); + my_out_be16( (unsigned short * ) ((ulong)addr+ (0x554)) , 0x55 ); + my_out_be16( (unsigned short * ) ((ulong)addr+ (0xaaa)) , 0x90 ); + in_mid=my_in_be16( (unsigned short * ) addr ); + in_did=my_in_be16 ( (unsigned short * ) ((ulong)addr+2) ); + printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); + my_out_be16( (unsigned short *)addr, 0xf0); + udelay(1); + my_out_be16( (unsigned short *) ((ulong)addr+ 0xaaa),0xaa ); + my_out_be16( (unsigned short *) ((ulong)addr+0x554),0x55 ); + my_out_be16( (unsigned short *) ((ulong)addr+0xaaa),0x80 ); + my_out_be16( (unsigned short *) ((ulong)addr+0xaaa),0xaa ); + my_out_be16( (unsigned short *) ((ulong)addr+0x554),0x55 ); + /* 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]); + my_out_be16( (unsigned short *) ((ulong)addr),0x30 ); + l_sect = sect; + } + } + +#elif defined(CONFIG_BOOT_32B) + my_out_be32( (unsigned * ) ((ulong)addr+0x1554) , 0xaa ); + my_out_be32( (unsigned * ) ((ulong)addr+0xaa8) , 0x55 ); + my_out_be32( (unsigned *) ((ulong)addr+0x1554) , 0x90 ); + in_mid=my_in_be32( (unsigned * ) addr ); + in_did=my_in_be32( (unsigned * ) ((ulong)addr+4) ); + printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); + my_out_be32( (unsigned *)addr, 0xf0); + udelay(1); + my_out_be32( (unsigned *) ((ulong)addr+0x1554),0xaa ); + my_out_be32( (unsigned *) ((ulong)addr+0xaa8),0x55 ); + my_out_be32( (unsigned *) ((ulong)addr+0x1554),0x80 ); + my_out_be32( (unsigned *) ((ulong)addr+0x1554),0xaa ); + my_out_be32( (unsigned *) ((ulong)addr+0xaa8),0x55 ); + /* 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]); + my_out_be32( (unsigned *) ((ulong)addr),0x00300030 ); + l_sect = sect; + } + } + +#else +# error CONFIG_BOOT_(size)B missing. +#endif + /* 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 defined (CONFIG_BOOT_8B) + while ( (my_in_8((unsigned char *)addr) & 0x80) != 0x80 ) +#elif defined(CONFIG_BOOT_16B ) + while ( (my_in_be16((unsigned short *)addr) & 0x0080) != 0x0080 ) +#elif defined(CONFIG_BOOT_32B) + while ( (my_in_be32((unsigned *)addr) & 0x00800080) != 0x00800080 ) +#else +# error CONFIG_BOOT_(size)B missing. +#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 defined (CONFIG_BOOT_8B) + my_out_8( (unsigned char *)addr, 0xf0); +#elif defined(CONFIG_BOOT_16B ) + my_out_be16( (unsigned short * ) addr , 0x00f0 ); +#elif defined(CONFIG_BOOT_32B) + my_out_be32 ( (unsigned *)addr, 0x00F000F0 ); /* reset bank */ +#else +# error CONFIG_BOOT_(size)B missing. +#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) +{ + ulong addr = (ulong)(info->start[0]); + ulong start,last; + int flag; + ulong i; + int data_short[2]; + + /* Check if Flash is (sufficiently) erased */ + if ( ((ulong) *(ulong *)dest & data) != data ) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); +#if defined(CONFIG_BOOT_8B) +#ifdef DEBUG + { + int in_mid,in_did; + my_out_8( (unsigned char * ) (addr+0x555) , 0xaa ); + my_out_8( (unsigned char * ) (addr+0x2aa) , 0x55 ); + my_out_8( (unsigned char * ) (addr+0x555) , 0x90 ); + in_mid=my_in_8( (unsigned char * ) addr ); + in_did=my_in_8( (unsigned char * ) (addr+1) ); + printf(" man ID=0x%x, dev ID=0x%x.\n",in_mid,in_did ); + my_out_8( (unsigned char *)addr, 0xf0); + udelay(1); + } +#endif + { + int data_ch[4]; + data_ch[0]=(int ) ((data>>24) & 0xff); + data_ch[1]=(int ) ((data>>16) &0xff ); + data_ch[2]=(int ) ((data >>8) & 0xff); + data_ch[3]=(int ) (data & 0xff); + for (i=0;i<4;i++ ){ + my_out_8( (unsigned char *) (addr+0x555),0xaa); + my_out_8((unsigned char *) (addr+0x2aa),0x55); + my_out_8( (unsigned char *) (addr+0x555),0xa0); + my_out_8((unsigned char *) (dest+i) ,data_ch[i]); + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + last = start; + while( ( my_in_8((unsigned char *) (dest+i)) ) != ( data_ch[i] ) ) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT ) { + return 1; + } + } + }/* for */ + } +#elif defined( CONFIG_BOOT_16B) + data_short[0]=(int) (data>>16) & 0xffff; + data_short[1]=(int ) data & 0xffff ; + for (i=0;i<2;i++ ){ + my_out_be16( (unsigned short *) ((ulong)addr+ 0xaaa),0xaa ); + my_out_be16( (unsigned short *) ((ulong)addr+ 0x554),0x55 ); + my_out_be16( (unsigned short *) ((ulong)addr+ 0xaaa),0xa0 ); + my_out_be16( (unsigned short *) (dest+(i*2)) ,data_short[i]); + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + start = get_timer (0); + last = start; + while( ( my_in_be16((unsigned short *) (dest+(i*2))) ) != ( data_short[i] ) ) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT ) { + return 1; + } + } + } +#elif defined( CONFIG_BOOT_32B) + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00A000A0; + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } +#endif + + + return (0); +} +#ifdef CONFIG_BOOT_8B +static int my_in_8 ( unsigned char *addr) +{ + int ret; + __asm__ __volatile__("lbz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} + +static void my_out_8 ( unsigned char *addr, int val) +{ + __asm__ __volatile__("stb%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif +#ifdef CONFIG_BOOT_16B +static int my_in_be16( unsigned short *addr) +{ + int ret; + __asm__ __volatile__("lhz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} +static void my_out_be16( unsigned short *addr, int val) +{ + __asm__ __volatile__("sth%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif +#ifdef CONFIG_BOOT_32B +static unsigned my_in_be32( unsigned *addr) +{ + unsigned ret; + __asm__ __volatile__("lwz%U1%X1 %0,%1; eieio" : "=r" (ret) : "m" (*addr)); + return ret; +} +static void my_out_be32( unsigned *addr, int val) +{ + __asm__ __volatile__("stw%U0%X0 %1,%0; eieio" : "=m" (*addr) : "r" (val)); +} +#endif + + + diff --git a/board/svm_sc8xx/ppcboot.lds b/board/svm_sc8xx/ppcboot.lds new file mode 100644 index 0000000..5f5e2e4 --- /dev/null +++ b/board/svm_sc8xx/ppcboot.lds @@ -0,0 +1,133 @@ +/* + * (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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + ppc/ppcstring.o (.text) + ppc/vsprintf.o (.text) + ppc/crc32.o (.text) + ppc/zlib.o (.text) + + . = env_offset; + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _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 = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff --git a/board/svm_sc8xx/ppcboot.lds.debug b/board/svm_sc8xx/ppcboot.lds.debug new file mode 100644 index 0000000..f230a6b --- /dev/null +++ b/board/svm_sc8xx/ppcboot.lds.debug @@ -0,0 +1,131 @@ +/* + * (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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + ppc/vsprintf.o (.text) + ppc/crc32.o (.text) + + . = env_offset; + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.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 = .); + + __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 = .); +} + diff --git a/board/svm_sc8xx/svm_sc8xx.c b/board/svm_sc8xx/svm_sc8xx.c new file mode 100644 index 0000000..db3162a --- /dev/null +++ b/board/svm_sc8xx/svm_sc8xx.c @@ -0,0 +1,163 @@ +/* + * (C) Copyright 2000, 2001, 2002 + * 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> + +/* ------------------------------------------------------------------------- */ +const uint sdram_table[] = +{ +/*----------------- + UPM A contents: +----------------- */ +/*--------------------------------------------------- + Read Single Beat Cycle. Offset 0 in the RAM array. +---------------------------------------------------- */ +0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00 , +0x1ff77c47, 0x1ff77c35, 0xefeabc34, 0x1fb57c35 , +/*------------------------------------------------ + Read Burst Cycle. Offset 0x8 in the RAM array. +------------------------------------------------ */ +0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00, +0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47, +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, +/*------------------------------------------------------- + Write Single Beat Cycle. Offset 0x18 in the RAM array +------------------------------------------------------- */ +0x1f27fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47 , +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff , +/*------------------------------------------------- + Write Burst Cycle. Offset 0x20 in the RAM array +------------------------------------------------- */ +0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00, +0xf0affc00, 0xe1bbbc04, 0x1ff77c47, 0xffffffff, +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff , +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff , +/*------------------------------------------------------------------------ + Periodic Timer Expired. For DRAM refresh. Offset 0x30 in the RAM array +------------------------------------------------------------------------ */ +0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04, +0xfffffc84, 0xfffffc07, 0xffffffff, 0xffffffff, +0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff , +/*----------- +* Exception: +* ----------- */ +0x7ffefc07, 0xffffffff, 0xffffffff, 0xffffffff , +}; + +/* ------------------------------------------------------------------------- */ +/* + * Check Board Identity: + * + * Test ID string (SVM8...) + * + * Return 1 for "SC8xx" type, 0 else. + */ + +int checkboard (void) +{ + unsigned char *s = getenv("serial#"); + int board_type; + + if (!s || strncmp(s, "SVM8", 4)) { + printf ("### No HW ID - assuming SVM SC8xx\n"); + return (0); + } + + board_type = 1; + + for (; *s; ++s) { + if (*s == ' ') + break; + putc (*s); + } + + putc ('\n'); + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size_b0 = 0; + + upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + memctl->memc_mptpr = CFG_MPTPR; +#if defined (CONFIG_SDRAM_16M) + memctl->memc_mamr = 0x00802114 | CFG_MxMR_PTx; + memctl->memc_mcr = 0x80002105; /* SDRAM bank 0 */ + udelay(1); + memctl->memc_mcr = 0x80002830; + udelay(1); + memctl->memc_mar = 0x00000088; + udelay(1); + memctl->memc_mcr = 0x80002106; + udelay(1); + memctl->memc_or1 = 0xff000a00; + size_b0 = 0x01000000; +#elif defined (CONFIG_SDRAM_32M) + memctl->memc_mamr = 0x00904114 | CFG_MxMR_PTx; + memctl->memc_mcr = 0x80002105; /* SDRAM bank 0 */ + udelay(1); + memctl->memc_mcr = 0x80002830; + udelay(1); + memctl->memc_mar = 0x00000088; + udelay(1); + memctl->memc_mcr = 0x80002106; + udelay(1); + memctl->memc_or1 = 0xfe000a00; + size_b0 = 0x02000000; +#elif defined (CONFIG_SDRAM_64M) + memctl->memc_mamr = 0x00a04114 | CFG_MxMR_PTx; + memctl->memc_mcr = 0x80002105; /* SDRAM bank 0 */ + udelay(1); + memctl->memc_mcr = 0x80002830; + udelay(1); + memctl->memc_mar = 0x00000088; + udelay(1); + memctl->memc_mcr = 0x80002106; + udelay(1); + memctl->memc_or1 = 0xfc000a00; + size_b0 = 0x04000000; +#else +#error SDRAM size configuration missing. +#endif + memctl->memc_br1 = 0x00000081; + udelay(200); + return (size_b0 ); +} + +#if (CONFIG_COMMANDS & CFG_CMD_DOC) +extern void doc_probe (ulong physadr); +void doc_init (void) +{ + doc_probe (CFG_DOC_BASE); +} +#endif + diff --git a/board/svm_sc8xx/u-boot.lds b/board/svm_sc8xx/u-boot.lds new file mode 100644 index 0000000..17fea2e --- /dev/null +++ b/board/svm_sc8xx/u-boot.lds @@ -0,0 +1,136 @@ +/* + * (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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + cpu/mpc8xx/traps.o (.text) + common/dlmalloc.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + lib_ppc/cache.o (.text) + lib_ppc/time.o (.text) + + . = env_offset; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _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 = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff --git a/board/svm_sc8xx/u-boot.lds.debug b/board/svm_sc8xx/u-boot.lds.debug new file mode 100644 index 0000000..22138f8 --- /dev/null +++ b/board/svm_sc8xx/u-boot.lds.debug @@ -0,0 +1,131 @@ +/* + * (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 : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + + . = env_offset; + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.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 = .); + + __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 = .); +} + diff --git a/common/Makefile b/common/Makefile index 67387ef..123871c 100644 --- a/common/Makefile +++ b/common/Makefile @@ -30,7 +30,7 @@ AOBJS = COBJS = main.o altera.o bedbug.o \ cmd_autoscript.o cmd_bedbug.o cmd_boot.o \ cmd_bootm.o cmd_cache.o cmd_console.o cmd_date.o \ - cmd_dcr.o cmd_diag.o cmd_doc.o cmd_dtt.o \ + cmd_dcr.o cmd_diag.o cmd_doc.o cmd_nand.o cmd_dtt.o \ cmd_eeprom.o cmd_elf.o cmd_fdc.o cmd_fdos.o cmd_flash.o \ cmd_fpga.o cmd_i2c.o cmd_ide.o cmd_immap.o \ cmd_jffs2.o cmd_log.o cmd_mem.o cmd_mii.o cmd_misc.o \ diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 2604e41..1c9a41d 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -153,10 +153,9 @@ int do_bdinfo ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) print_num ("boot_params", (ulong)bd->bi_boot_params); for (i=0; i<CONFIG_NR_DRAM_BANKS; ++i) { - printf ("DRAM:%02d.start = %08lX\n", - i, bd->bi_dram[i].start); - printf ("DRAM:%02d.size = %08lX\n", - i, bd->bi_dram[i].size); + print_num("DRAM bank", i); + print_num("-> start", bd->bi_dram[i].start); + print_num("-> size", bd->bi_dram[i].size); } printf ("ethaddr ="); @@ -200,7 +199,7 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) addr = simple_strtoul(argv[1], NULL, 16); - printf ("## Starting application at 0x%08lx ...\n", addr); + printf ("## Starting application at 0x%08lX ...\n", addr); /* * pass address parameter as argv[0] (aka command name), @@ -209,7 +208,7 @@ int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) rc = ((ulong (*)(int, char *[]))addr) (--argc, &argv[1]); if (rc != 0) rcode = 1; - printf ("## Application terminated, rc = 0x%lx\n", rc); + printf ("## Application terminated, rc = 0x%lX\n", rc); return rcode; } @@ -285,7 +284,7 @@ int do_load_serial (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) printf ("## S-Record download aborted\n"); rcode = 1; } else { - printf ("## Start Addr = 0x%08lx\n", addr); + printf ("## Start Addr = 0x%08lX\n", addr); load_addr = addr; } @@ -345,9 +344,9 @@ load_serial (ulong offset) memcpy ((char *)(store_addr), binbuf, binlen); } if ((store_addr) < start_addr) - start_addr = store_addr; + start_addr = store_addr; if ((store_addr + binlen - 1) > end_addr) - end_addr = store_addr + binlen - 1; + end_addr = store_addr + binlen - 1; break; case SREC_END2: case SREC_END3: @@ -606,9 +605,17 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) ulong offset = 0; ulong addr; - int i; int load_baudrate, current_baudrate; int rcode = 0; + char *s; + + /* pre-set offset from CFG_LOAD_ADDR */ + offset = CFG_LOAD_ADDR; + + /* pre-set offset from $loadaddr */ + if ((s = getenv("loadaddr")) != NULL) { + offset = simple_strtoul(s, NULL, 16); + } load_baudrate = current_baudrate = gd->baudrate; @@ -635,28 +642,19 @@ int do_load_serial_bin (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) break; } } - printf ("## Ready for binary (kermit) download ...\n"); + printf ("## Ready for binary (kermit) download " + "to 0x%08lX at %d bps...\n", + offset, + current_baudrate); addr = load_serial_bin (offset); - /* - * Gather any trailing characters (for instance, the ^D which - * is sent by 'cu' after sending a file), and give the - * box some time (100 * 1 ms) - */ - for (i=0; i<100; ++i) { - if (serial_tstc()) { - (void) serial_getc(); - } - udelay(1000); - } - if (addr == ~0) { load_addr = 0; printf ("## Binary (kermit) download aborted\n"); rcode = 1; } else { - printf ("## Start Addr = 0x%08lx\n", addr); + printf ("## Start Addr = 0x%08lX\n", addr); load_addr = addr; } diff --git a/common/cmd_nand.c b/common/cmd_nand.c new file mode 100644 index 0000000..356b592 --- /dev/null +++ b/common/cmd_nand.c @@ -0,0 +1,1545 @@ +/* + * Driver for NAND support, Rick Bronson + * borrowed heavily from: + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> + * + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <malloc.h> +#include <asm/io.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + +#include <linux/mtd/nftl.h> +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ids.h> + +/* + * Definition of the out of band configuration structure + */ +struct nand_oob_config { + int ecc_pos[6]; /* position of ECC bytes inside oob */ + int badblock_pos; /* position of bad block flag inside oob -1 = inactive */ + int eccvalid_pos; /* position of ECC valid flag inside oob -1 = inactive */ +} oob_config = { {0}, 0, 0}; + +#define NAND_DEBUG +#undef ECC_DEBUG +#undef PSYCHO_DEBUG +#undef NFTL_DEBUG + +#define CONFIG_MTD_NAND_ECC /* enable ECC */ +/* #define CONFIG_MTD_NAND_ECC_JFFS2 */ + +/* + * Function Prototypes + */ +static void nand_print(struct nand_chip *nand); +static int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf); +static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len); +static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len, + size_t * retlen, u_char *buf, u_char *ecc_code); +static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, + size_t * retlen, const u_char * buf, u_char * ecc_code); +#ifdef CONFIG_MTD_NAND_ECC +static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc); +static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code); +#endif + +static struct nand_chip nand_dev_desc[CFG_MAX_NAND_DEVICE] = {{0}}; + +/* Current NAND Device */ +static int curr_device = -1; + +/* ------------------------------------------------------------------------- */ + +int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strcmp(argv[1],"info") == 0) { + int i; + + putc ('\n'); + + for (i=0; i<CFG_MAX_NAND_DEVICE; ++i) { + if(nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) + continue; /* list only known devices */ + printf ("Device %d: ", i); + nand_print(&nand_dev_desc[i]); + } + return 0; + + } else if (strcmp(argv[1],"device") == 0) { + if ((curr_device < 0) || (curr_device >= CFG_MAX_NAND_DEVICE)) { + puts ("\nno devices available\n"); + return 1; + } + printf ("\nDevice %d: ", curr_device); + nand_print(&nand_dev_desc[curr_device]); + return 0; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strcmp(argv[1],"device") == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + printf ("\nDevice %d: ", dev); + if (dev >= CFG_MAX_NAND_DEVICE) { + puts ("unknown device\n"); + return 1; + } + nand_print(&nand_dev_desc[dev]); + /*nand_print (dev);*/ + + if (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN) { + return 1; + } + + curr_device = dev; + + puts ("... is now current device\n"); + + return 0; + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strcmp(argv[1],"read") == 0 || strcmp(argv[1],"write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong off = simple_strtoul(argv[3], NULL, 16); + ulong size = simple_strtoul(argv[4], NULL, 16); + int cmd = (strcmp(argv[1],"read") == 0); + int ret, total; + + printf ("\nNAND %s: device %d offset %ld, size %ld ... ", + cmd ? "read" : "write", curr_device, off, size); + + ret = nand_rw(nand_dev_desc + curr_device, cmd, off, size, + &total, (u_char*)addr); + + printf ("%d bytes %s: %s\n", total, cmd ? "read" : "write", + ret ? "ERROR" : "OK"); + + return ret; + } else if (strcmp(argv[1],"erase") == 0) { + ulong off = simple_strtoul(argv[2], NULL, 16); + ulong size = simple_strtoul(argv[3], NULL, 16); + int ret; + + printf ("\nNAND erase: device %d offset %ld, size %ld ... ", + curr_device, off, size); + + ret = nand_erase (nand_dev_desc + curr_device, off, size); + + printf("%s\n", ret ? "ERROR" : "OK"); + + return ret; + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + rcode = 1; + } + + return rcode; + } +} + +int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + char *ep; + int dev; + ulong cnt; + ulong addr; + ulong offset = 0; + image_header_t *hdr; + int rcode = 0; + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv ("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv ("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + case 4: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + offset = simple_strtoul(argv[3], NULL, 16); + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (!boot_device) { + puts ("\n** No boot device **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + dev = simple_strtoul(boot_device, &ep, 16); + + if ((dev >= CFG_MAX_NAND_DEVICE) || + (nand_dev_desc[dev].ChipID == NAND_ChipID_UNKNOWN)) { + printf ("\n** Device %d not available\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + printf ("\nLoading from device %d: %s at 0x%lX (offset 0x%lX)\n", + dev, nand_dev_desc[dev].name, nand_dev_desc[dev].IO_ADDR, + offset); + + if (nand_rw (nand_dev_desc + dev, 1, offset, + SECTORSIZE, NULL, (u_char *)addr)) { + printf ("** Read error on %d\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + hdr = (image_header_t *)addr; + + if (ntohl(hdr->ih_magic) == IH_MAGIC) { + + print_image_hdr (hdr); + + cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt -= SECTORSIZE; + } else { + printf ("\n** Bad Magic Number 0x%x **\n", hdr->ih_magic); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (nand_rw (nand_dev_desc + dev, 1, offset + SECTORSIZE, cnt, + NULL, (u_char *)(addr+SECTORSIZE))) { + printf ("** Read error on %d\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + /* Loading ok, update default load address */ + + load_addr = addr; + + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode = 1; + } + return rcode; +} + +static int nand_rw (struct nand_chip* nand, int cmd, + size_t start, size_t len, + size_t * retlen, u_char * buf) +{ + int noecc, ret = 0, n, total = 0; + char eccbuf[6]; + + while(len) { + /* The ECC will not be calculated correctly if + less than 512 is written or read */ + noecc = (start != (start | 0x1ff) + 1) || (len < 0x200); + if (cmd) + ret = nand_read_ecc(nand, start, len, + &n, (u_char*)buf, + noecc ? NULL : eccbuf); + else + ret = nand_write_ecc(nand, start, len, + &n, (u_char*)buf, + noecc ? NULL : eccbuf); + + if (ret) + break; + + start += n; + buf += n; + total += n; + len -= n; + } + if (retlen) + *retlen = total; + + return ret; +} + +static void nand_print(struct nand_chip *nand) + { + printf("%s at 0x%lX,\n" + "\t %d chip%s %s, size %d MB, \n" + "\t total size %ld MB, sector size %ld kB\n", + nand->name, nand->IO_ADDR, nand->numchips, + nand->numchips>1 ? "s" : "", nand->chips_name, + 1 << (nand->chipshift - 20), + nand->totlen >> 20, nand->erasesize >> 10); + + if (nand->nftl_found) { + struct NFTLrecord *nftl = &nand->nftl; + unsigned long bin_size, flash_size; + + bin_size = nftl->nb_boot_blocks * nand->erasesize; + flash_size = (nftl->nb_blocks - nftl->nb_boot_blocks) * nand->erasesize; + + printf("\t NFTL boot record:\n" + "\t Binary partition: size %ld%s\n" + "\t Flash disk partition: size %ld%s, offset 0x%lx\n", + bin_size > (1 << 20) ? bin_size >> 20 : bin_size >> 10, + bin_size > (1 << 20) ? "MB" : "kB", + flash_size > (1 << 20) ? flash_size >> 20 : flash_size >> 10, + flash_size > (1 << 20) ? "MB" : "kB", bin_size); + } else { + puts ("\t No NFTL boot record found.\n"); + } +} + +/* ------------------------------------------------------------------------- */ + +/* This function is needed to avoid calls of the __ashrdi3 function. */ +static int shr(int val, int shift) + { + return val >> shift; +} + +static int NanD_WaitReady(struct nand_chip *nand) +{ + /* This is inline, to optimise the common case, where it's ready instantly */ + int ret = 0; + NAND_WAIT_READY(nand); + + return ret; +} + +/* NanD_Command: Send a flash command to the flash chip */ + +static inline int NanD_Command(struct nand_chip *nand, unsigned char command) +{ + unsigned long nandptr = nand->IO_ADDR; + + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + NAND_CTL_SETCLE(nandptr); + + /* Send the command */ + WRITE_NAND_COMMAND(command, nandptr); + + /* Lower the CLE line */ + NAND_CTL_CLRCLE(nandptr); + + return NanD_WaitReady(nand); +} + +/* NanD_Address: Set the current address for the flash chip */ + +static int NanD_Address(struct nand_chip *nand, int numbytes, unsigned long ofs) + { + unsigned long nandptr; + int i; + + nandptr = nand->IO_ADDR; + + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + NAND_CTL_SETALE(nandptr); + + /* Send the address */ + /* Devices with 256-byte page are addressed as: + Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) + * there is no device on the market with page256 + and more than 24 bits. + Devices with 512-byte page are addressed as: + Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) + * 25-31 is sent only if the chip support it. + * bit 8 changes the read command to be sent + (NAND_CMD_READ0 or NAND_CMD_READ1). + */ + + if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) + WRITE_NAND_ADDRESS(ofs, nandptr); + + ofs = ofs >> nand->page_shift; + + if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) + for (i = 0; i < nand->pageadrlen; i++, ofs = ofs >> 8) + WRITE_NAND_ADDRESS(ofs, nandptr); + + /* Lower the ALE line */ + NAND_CTL_CLRALE(nandptr); + + /* Wait for the chip to respond */ + return NanD_WaitReady(nand); + } + +/* NanD_SelectChip: Select a given flash chip within the current floor */ + +static inline int NanD_SelectChip(struct nand_chip *nand, int chip) +{ + /* Wait for it to be ready */ + return NanD_WaitReady(nand); +} + +/* NanD_IdentChip: Identify a given NAND chip given {floor,chip} */ + +static int NanD_IdentChip(struct nand_chip *nand, int floor, int chip) +{ + int mfr, id, i; + + NAND_ENABLE_CE(nand); /* set pin low */ + /* Reset the chip */ + if (NanD_Command(nand, NAND_CMD_RESET)) { +#ifdef NAND_DEBUG + printf("NanD_Command (reset) for %d,%d returned true\n", + floor, chip); +#endif + NAND_DISABLE_CE(nand); /* set pin high */ + return 0; + } + + /* Read the NAND chip ID: 1. Send ReadID command */ + if (NanD_Command(nand, NAND_CMD_READID)) { +#ifdef NAND_DEBUG + printf("NanD_Command (ReadID) for %d,%d returned true\n", + floor, chip); +#endif + NAND_DISABLE_CE(nand); /* set pin high */ + return 0; + } + + /* Read the NAND chip ID: 2. Send address byte zero */ + NanD_Address(nand, ADDR_COLUMN, 0); + + /* Read the manufacturer and device id codes from the device */ + + mfr = READ_NAND(nand->IO_ADDR); + + id = READ_NAND(nand->IO_ADDR); + + NAND_DISABLE_CE(nand); /* set pin high */ + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + { + printf("NanD_Command (ReadID) got %d %d\n", mfr, id); + return 0; + } + + /* Check it's the same as the first chip we identified. + * M-Systems say that any given nand_chip device should only + * contain _one_ type of flash part, although that's not a + * hardware restriction. */ + if (nand->mfr) { + if (nand->mfr == mfr && nand->id == id) + return 1; /* This is another the same the first */ + else + printf("Flash chip at floor %d, chip %d is different:\n", + floor, chip); + } + + /* Print and store the manufacturer and ID codes. */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (mfr == nand_flash_ids[i].manufacture_id && + id == nand_flash_ids[i].model_id) { +#ifdef NAND_DEBUG + printf("Flash chip found:\n\t Manufacturer ID: 0x%2.2X, " + "Chip ID: 0x%2.2X (%s)\n", mfr, id, + nand_flash_ids[i].name); +#endif + if (!nand->mfr) { + nand->mfr = mfr; + nand->id = id; + nand->chipshift = + nand_flash_ids[i].chipshift; + nand->page256 = nand_flash_ids[i].page256; + if (nand->page256) { + nand->oobblock = 256; + nand->oobsize = 8; + nand->page_shift = 8; + } else { + nand->oobblock = 512; + nand->oobsize = 16; + nand->page_shift = 9; + } + nand->pageadrlen = + nand_flash_ids[i].pageadrlen; + nand->erasesize = + nand_flash_ids[i].erasesize; + nand->chips_name = + nand_flash_ids[i].name; + return 1; + } + return 0; + } + } + + +#ifdef NAND_DEBUG + /* We haven't fully identified the chip. Print as much as we know. */ + printf("Unknown flash chip found: %2.2X %2.2X\n", + id, mfr); +#endif + + return 0; +} + +/* NanD_ScanChips: Find all NAND chips present in a nand_chip, and identify them */ + +static void NanD_ScanChips(struct nand_chip *nand) +{ + int floor, chip; + int numchips[NAND_MAX_FLOORS]; + int maxchips = NAND_MAX_CHIPS; + int ret = 1; + + nand->numchips = 0; + nand->mfr = 0; + nand->id = 0; + + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0; floor < NAND_MAX_FLOORS; floor++) { + ret = 1; + numchips[floor] = 0; + for (chip = 0; chip < maxchips && ret != 0; chip++) { + + ret = NanD_IdentChip(nand, floor, chip); + if (ret) { + numchips[floor]++; + nand->numchips++; + } + } + } + + /* If there are none at all that we recognise, bail */ + if (!nand->numchips) { + puts ("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + nand->chips = malloc(sizeof(struct Nand) * nand->numchips); + if (!nand->chips) { + puts ("No memory for allocating chip info structures\n"); + return; + } + + ret = 0; + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0; floor < NAND_MAX_FLOORS; floor++) { + for (chip = 0; chip < numchips[floor]; chip++) { + nand->chips[ret].floor = floor; + nand->chips[ret].chip = chip; + nand->chips[ret].curadr = 0; + nand->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + nand->totlen = nand->numchips * (1 << nand->chipshift); + +#ifdef NAND_DEBUG + printf("%d flash chips found. Total nand_chip size: %ld MB\n", + nand->numchips, nand->totlen >> 20); +#endif +} +#ifdef CONFIG_MTD_NAND_ECC +/* we need to be fast here, 1 us per read translates to 1 second per meg */ +static void nand_fast_copy (unsigned char *source, unsigned char *dest, long cntr) + { + while (cntr > 16) + { + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + *dest++ = *source++; + cntr -= 16; + } + while (cntr > 0) + { + *dest++ = *source++; + cntr--; + } + } +#endif +/* we need to be fast here, 1 us per read translates to 1 second per meg */ +static void nand_fast_read(unsigned char *data_buf, int cntr, unsigned long nandptr) + { + while (cntr > 16) + { + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + *data_buf++ = READ_NAND(nandptr); + cntr -= 16; + } + while (cntr > 0) + { + *data_buf++ = READ_NAND(nandptr); + cntr--; + } + } + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000. + */ + +/* + * NAND read with ECC + */ +static int nand_read_ecc(struct nand_chip *nand, size_t start, size_t len, + size_t * retlen, u_char *buf, u_char *ecc_code) +{ + int col, page; + int ecc_status = 0; +#ifdef CONFIG_MTD_NAND_ECC + int j; + int ecc_failed = 0; + u_char *data_poi; + u_char ecc_calc[6]; +#endif + unsigned long nandptr = nand->IO_ADDR; + + /* Do not allow reads past end of device */ + if ((start + len) > nand->totlen) { + printf ("nand_read_ecc: Attempt read beyond end of device %x %x %x\n", (uint) start, (uint) len, (uint) nand->totlen); + *retlen = 0; + return -1; + } + + /* First we calculate the starting page */ + page = shr(start, nand->page_shift); + + /* Get raw starting column */ + col = start & (nand->oobblock - 1); + + /* Initialize return value */ + *retlen = 0; + + /* Select the NAND device */ + NAND_ENABLE_CE(nand); /* set pin low */ + + /* Loop until all data read */ + while (*retlen < len) { + + +#ifdef CONFIG_MTD_NAND_ECC + + /* Do we have this page in cache ? */ + if (nand->cache_page == page) + goto readdata; + /* Send the read command */ + NanD_Command(nand, NAND_CMD_READ0); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + /* Read in a page + oob data */ + nand_fast_read(nand->data_buf, nand->oobblock + nand->oobsize, nandptr); + + /* copy data into cache, for read out of cache and if ecc fails */ + if (nand->data_cache) + memcpy (nand->data_cache, nand->data_buf, nand->oobblock + nand->oobsize); + + /* Pick the ECC bytes out of the oob data */ + for (j = 0; j < 6; j++) + ecc_code[j] = nand->data_buf[(nand->oobblock + oob_config.ecc_pos[j])]; + + /* Calculate the ECC and verify it */ + /* If block was not written with ECC, skip ECC */ + if (oob_config.eccvalid_pos != -1 && + (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0x0f) != 0x0f) { + + nand_calculate_ecc (&nand->data_buf[0], &ecc_calc[0]); + switch (nand_correct_data (&nand->data_buf[0], &ecc_code[0], &ecc_calc[0])) { + case -1: + printf ("nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); + ecc_failed++; + break; + case 1: + case 2: /* transfer ECC corrected data to cache */ + memcpy (nand->data_cache, nand->data_buf, 256); + break; + } + } + + if (oob_config.eccvalid_pos != -1 && + nand->oobblock == 512 && (nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] & 0xf0) != 0xf0) { + + nand_calculate_ecc (&nand->data_buf[256], &ecc_calc[3]); + switch (nand_correct_data (&nand->data_buf[256], &ecc_code[3], &ecc_calc[3])) { + case -1: + printf ("nand_read_ecc: " "Failed ECC read, page 0x%08x\n", page); + ecc_failed++; + break; + case 1: + case 2: /* transfer ECC corrected data to cache */ + if (nand->data_cache) + memcpy (&nand->data_cache[256], &nand->data_buf[256], 256); + break; + } + } +readdata: + /* Read the data from ECC data buffer into return buffer */ + data_poi = (nand->data_cache) ? nand->data_cache : nand->data_buf; + data_poi += col; + if ((*retlen + (nand->oobblock - col)) >= len) { + nand_fast_copy (data_poi, buf + *retlen, len - *retlen); + *retlen = len; + } else { + nand_fast_copy (data_poi, buf + *retlen, nand->oobblock - col); + *retlen += nand->oobblock - col; + } + /* Set cache page address, invalidate, if ecc_failed */ + nand->cache_page = (nand->data_cache && !ecc_failed) ? page : -1; + + ecc_status += ecc_failed; + ecc_failed = 0; + +#else + /* Send the read command */ + NanD_Command(nand, NAND_CMD_READ0); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + /* Read the data directly into the return buffer */ + if ((*retlen + (nand->oobblock - col)) >= len) { + nand_fast_read(buf + *retlen, len - *retlen, nandptr); + *retlen = len; + /* We're done */ + continue; + } else { + nand_fast_read(buf + *retlen, nand->oobblock - col, nandptr); + *retlen += nand->oobblock - col; + } +#endif + /* For subsequent reads align to page boundary. */ + col = 0; + /* Increment page address */ + page++; + } + + /* De-select the NAND device */ + NAND_DISABLE_CE(nand); /* set pin high */ + + /* + * Return success, if no ECC failures, else -EIO + * fs driver will take care of that, because + * retlen == desired len and result == -EIO + */ + return ecc_status ? -1 : 0; +} + + +/* + * Nand_page_program function is used for write and writev ! + */ +static int nand_write_page (struct nand_chip *nand, + int page, int col, int last, u_char * ecc_code) +{ + + int i; +#ifdef CONFIG_MTD_NAND_ECC + unsigned long nandptr = nand->IO_ADDR; +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + int ecc_bytes = (nand->oobblock == 512) ? 6 : 3; +#endif +#endif + /* pad oob area */ + for (i = nand->oobblock; i < nand->oobblock + nand->oobsize; i++) + nand->data_buf[i] = 0xff; + +#ifdef CONFIG_MTD_NAND_ECC + /* Zero out the ECC array */ + for (i = 0; i < 6; i++) + ecc_code[i] = 0x00; + + /* Read back previous written data, if col > 0 */ + if (col) { + NanD_Command(nand, NAND_CMD_READ0); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + for (i = 0; i < col; i++) + nand->data_buf[i] = READ_NAND (nandptr); + } + + /* Calculate and write the ECC if we have enough data */ + if ((col < nand->eccsize) && (last >= nand->eccsize)) { + nand_calculate_ecc (&nand->data_buf[0], &(ecc_code[0])); + for (i = 0; i < 3; i++) + nand->data_buf[(nand->oobblock + oob_config.ecc_pos[i])] = ecc_code[i]; + if (oob_config.eccvalid_pos != -1) + nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] = 0xf0; + } + + /* Calculate and write the second ECC if we have enough data */ + if ((nand->oobblock == 512) && (last == nand->oobblock)) { + nand_calculate_ecc (&nand->data_buf[256], &(ecc_code[3])); + for (i = 3; i < 6; i++) + nand->data_buf[(nand->oobblock + oob_config.ecc_pos[i])] = ecc_code[i]; + if (oob_config.eccvalid_pos != -1) + nand->data_buf[nand->oobblock + oob_config.eccvalid_pos] &= 0x0f; + } +#endif + /* Prepad for partial page programming !!! */ + for (i = 0; i < col; i++) + nand->data_buf[i] = 0xff; + + /* Postpad for partial page programming !!! oob is already padded */ + for (i = last; i < nand->oobblock; i++) + nand->data_buf[i] = 0xff; + + /* Send command to begin auto page programming */ + NanD_Command(nand, NAND_CMD_SEQIN); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + + /* Write out complete page of data */ + for (i = 0; i < (nand->oobblock + nand->oobsize); i++) + WRITE_NAND(nand->data_buf[i], nand->IO_ADDR); + + /* Send command to actually program the data */ + NanD_Command(nand, NAND_CMD_PAGEPROG); + NanD_Command(nand, NAND_CMD_STATUS); + + /* See if device thinks it succeeded */ + if (READ_NAND(nand->IO_ADDR) & 0x01) { + printf ("nand_write_ecc: " "Failed write, page 0x%08x, ", page); + return -1; + } +#ifdef CONFIG_MTD_NAND_VERIFY_WRITE + /* + * The NAND device assumes that it is always writing to + * a cleanly erased page. Hence, it performs its internal + * write verification only on bits that transitioned from + * 1 to 0. The device does NOT verify the whole page on a + * byte by byte basis. It is possible that the page was + * not completely erased or the page is becoming unusable + * due to wear. The read with ECC would catch the error + * later when the ECC page check fails, but we would rather + * catch it early in the page write stage. Better to write + * no data than invalid data. + */ + + /* Send command to read back the page */ + if (col < nand->eccsize) + NanD_Command(nand, NAND_CMD_READ0); + else + NanD_Command(nand, NAND_CMD_READ1); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + + /* Loop through and verify the data */ + for (i = col; i < last; i++) { + if (nand->data_buf[i] != readb (nand->IO_ADDR)) { + printf ("nand_write_ecc: " "Failed write verify, page 0x%08x ", page); + return -1; + } + } + +#ifdef CONFIG_MTD_NAND_ECC + /* + * We also want to check that the ECC bytes wrote + * correctly for the same reasons stated above. + */ + NanD_Command(nand, NAND_CMD_READOOB); + NanD_Address(nand, ADDR_COLUMN_PAGE, (page << nand->page_shift) + col); + for (i = 0; i < nand->oobsize; i++) + nand->data_buf[i] = readb (nand->IO_ADDR); + for (i = 0; i < ecc_bytes; i++) { + if ((nand->data_buf[(oob_config.ecc_pos[i])] != ecc_code[i]) && ecc_code[i]) { + printf ("nand_write_ecc: Failed ECC write " + "verify, page 0x%08x, " "%6i bytes were succesful\n", page, i); + return -1; + } + } +#endif +#endif + return 0; +} +static int nand_write_ecc (struct nand_chip* nand, size_t to, size_t len, + size_t * retlen, const u_char * buf, u_char * ecc_code) +{ + int i, page, col, cnt, ret = 0; + + /* Do not allow write past end of device */ + if ((to + len) > nand->totlen) { + printf ("nand_write_oob: Attempt to write past end of page\n"); + return -1; + } + + /* Shift to get page */ + page = ((int) to) >> nand->page_shift; + + /* Get the starting column */ + col = to & (nand->oobblock - 1); + + /* Initialize return length value */ + *retlen = 0; + + /* Select the NAND device */ + NAND_ENABLE_CE(nand); /* set pin low */ + + /* Check the WP bit */ + NanD_Command(nand, NAND_CMD_STATUS); + if (!(READ_NAND(nand->IO_ADDR) & 0x80)) { + printf ("nand_write_ecc: Device is write protected!!!\n"); + ret = -1; + goto out; + } + + /* Loop until all data is written */ + while (*retlen < len) { + /* Invalidate cache, if we write to this page */ + if (nand->cache_page == page) + nand->cache_page = -1; + + /* Write data into buffer */ + if ((col + len) >= nand->oobblock) + for (i = col, cnt = 0; i < nand->oobblock; i++, cnt++) + nand->data_buf[i] = buf[(*retlen + cnt)]; + else + for (i = col, cnt = 0; cnt < (len - *retlen); i++, cnt++) + nand->data_buf[i] = buf[(*retlen + cnt)]; + /* We use the same function for write and writev !) */ + ret = nand_write_page (nand, page, col, i, ecc_code); + if (ret) + goto out; + + /* Next data start at page boundary */ + col = 0; + + /* Update written bytes count */ + *retlen += cnt; + + /* Increment page address */ + page++; + } + + /* Return happy */ + *retlen = len; + +out: + /* De-select the NAND device */ + NAND_DISABLE_CE(nand); /* set pin high */ + + return ret; +} + +#if 0 /* not used */ +/* Read a buffer from NanD */ +static void NanD_ReadBuf(struct nand_chip *nand, u_char * buf, int len) +{ + unsigned long nandptr; + + nandptr = nand->IO_ADDR; + + for (; len > 0; len--) + *buf++ = READ_NAND(nandptr); + +} +/* Write a buffer to NanD */ +static void NanD_WriteBuf(struct nand_chip *nand, const u_char * buf, int len) +{ + unsigned long nandptr; + int i; + + nandptr = nand->IO_ADDR; + + if (len <= 0) + return; + + for (i = 0; i < len; i++) + WRITE_NAND(buf[i], nandptr); + +} + +/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the + * various device information of the NFTL partition and Bad Unit Table. Update + * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] + * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c + */ +static int find_boot_record(struct NFTLrecord *nftl) +{ + struct nftl_uci1 h1; + struct nftl_oob oob; + unsigned int block, boot_record_count = 0; + int retlen; + u8 buf[SECTORSIZE]; + struct NFTLMediaHeader *mh = &nftl->MediaHdr; + unsigned int i; + + nftl->MediaUnit = BLOCK_NIL; + nftl->SpareMediaUnit = BLOCK_NIL; + + /* search for a valid boot record */ + for (block = 0; block < nftl->nb_blocks; block++) { + int ret; + + /* Check for ANAND header first. Then can whinge if it's found but later + checks fail */ + if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, + &retlen, buf, NULL))) { + static int warncount = 5; + + if (warncount) { + printf("Block read at 0x%x failed\n", block * nftl->EraseSize); + if (!--warncount) + puts ("Further failures for this block will not be printed\n"); + } + continue; + } + + if (retlen < 6 || memcmp(buf, "ANAND", 6)) { + /* ANAND\0 not found. Continue */ +#ifdef PSYCHO_DEBUG + printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize); +#endif + continue; + } + +#ifdef NFTL_DEBUG + printf("ANAND header found at 0x%x\n", block * nftl->EraseSize); +#endif + + /* To be safer with BIOS, also use erase mark as discriminant */ + if ((ret = nand_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, + 8, &retlen, (char *)&h1) < 0)) { +#ifdef NFTL_DEBUG + printf("ANAND header found at 0x%x, but OOB data read failed\n", + block * nftl->EraseSize); +#endif + continue; + } + + /* OK, we like it. */ + + if (boot_record_count) { + /* We've already processed one. So we just check if + this one is the same as the first one we found */ + if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) { +#ifdef NFTL_DEBUG + printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n", + nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize); +#endif + /* if (debug) Print both side by side */ + return -1; + } + if (boot_record_count == 1) + nftl->SpareMediaUnit = block; + + boot_record_count++; + continue; + } + + /* This is the first we've seen. Copy the media header structure into place */ + memcpy(mh, buf, sizeof(struct NFTLMediaHeader)); + + /* Do some sanity checks on it */ + if (mh->UnitSizeFactor != 0xff) { + puts ("Sorry, we don't support UnitSizeFactor " + "of != 1 yet.\n"); + return -1; + } + + nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); + if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { + printf ("NFTL Media Header sanity check failed:\n" + "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", + nftl->nb_boot_blocks, nftl->nb_blocks); + return -1; + } + + nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize; + if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) { + printf ("NFTL Media Header sanity check failed:\n" + "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n", + nftl->numvunits, + nftl->nb_blocks, + nftl->nb_boot_blocks); + return -1; + } + + nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); + + /* If we're not using the last sectors in the device for some reason, + reduce nb_blocks accordingly so we forget they're there */ + nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN); + + /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */ + for (i = 0; i < nftl->nb_blocks; i++) { + if ((i & (SECTORSIZE - 1)) == 0) { + /* read one sector for every SECTORSIZE of blocks */ + if ((ret = nand_read_ecc(nftl->mtd, block * nftl->EraseSize + + i + SECTORSIZE, SECTORSIZE, + &retlen, buf, (char *)&oob)) < 0) { + puts ("Read of bad sector table failed\n"); + return -1; + } + } + /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */ + if (buf[i & (SECTORSIZE - 1)] != 0xff) + nftl->ReplUnitTable[i] = BLOCK_RESERVED; + } + + nftl->MediaUnit = block; + boot_record_count++; + + } /* foreach (block) */ + + return boot_record_count?0:-1; +} +static int nand_read_oob(struct nand_chip* nand, size_t ofs, size_t len, + size_t * retlen, u_char * buf) +{ + int len256 = 0, ret; + unsigned long nandptr; + struct Nand *mychip; + + nandptr = nand->IO_ADDR; + + mychip = &nand->chips[shr(ofs, nand->chipshift)]; + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with nand_read_ecc. */ + if (nand->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + NanD_Command(nand, NAND_CMD_READOOB); + NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (nand->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + NanD_ReadBuf(nand, buf, len256); + + NanD_Command(nand, NAND_CMD_READOOB); + NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff)); + } + + NanD_ReadBuf(nand, &buf[len256], len - len256); + + *retlen = len; + /* Reading the full OOB data drops us off of the end of the page, + * causing the flash device to go into busy mode, so we need + * to wait until ready 11.4.1 and Toshiba TC58256FT nands */ + + ret = NanD_WaitReady(nand); + + return ret; + +} +static int nand_write_oob(struct nand_chip* nand, size_t ofs, size_t len, + size_t * retlen, const u_char * buf) +{ + int len256 = 0; + unsigned long nandptr = nand->IO_ADDR; + +#ifdef PSYCHO_DEBUG + printf("nand_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n", + (long)ofs, len, buf[0], buf[1], buf[2], buf[3], + buf[8], buf[9], buf[14],buf[15]); +#endif + + /* Reset the chip */ + NanD_Command(nand, NAND_CMD_RESET); + + /* issue the Read2 command to set the pointer to the Spare Data Area. */ + NanD_Command(nand, NAND_CMD_READOOB); + NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with nand_read_ecc. */ + if (nand->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + /* issue the Serial Data In command to initial the Page Program process */ + NanD_Command(nand, NAND_CMD_SEQIN); + NanD_Address(nand, ADDR_COLUMN_PAGE, ofs); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (nand->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + NanD_WriteBuf(nand, buf, len256); + + NanD_Command(nand, NAND_CMD_PAGEPROG); + NanD_Command(nand, NAND_CMD_STATUS); + /* NanD_WaitReady() is implicit in NanD_Command */ + + if (READ_NAND(nandptr) & 1) { + puts ("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return -1; + } + NanD_Command(nand, NAND_CMD_SEQIN); + NanD_Address(nand, ADDR_COLUMN_PAGE, ofs & (~0x1ff)); + } + + NanD_WriteBuf(nand, &buf[len256], len - len256); + + NanD_Command(nand, NAND_CMD_PAGEPROG); + NanD_Command(nand, NAND_CMD_STATUS); + /* NanD_WaitReady() is implicit in NanD_Command */ + + if (READ_NAND(nandptr) & 1) { + puts ("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return -1; + } + + *retlen = len; + return 0; + +} +#endif + +static int nand_erase(struct nand_chip* nand, size_t ofs, size_t len) +{ + unsigned long nandptr; + struct Nand *mychip; + + if (ofs & (nand->erasesize-1) || len & (nand->erasesize-1)) { + printf ("Offset and size must be sector aligned, erasesize = %d\n", + (int) nand->erasesize); + return -1; + } + + nandptr = nand->IO_ADDR; + + /* FIXME: Do nand in the background. Use timers or schedule_task() */ + while(len) { + mychip = &nand->chips[shr(ofs, nand->chipshift)]; + + NanD_Command(nand, NAND_CMD_ERASE1); + NanD_Address(nand, ADDR_PAGE, ofs); + NanD_Command(nand, NAND_CMD_ERASE2); + + NanD_Command(nand, NAND_CMD_STATUS); + + if (READ_NAND(nandptr) & 1) { + printf("Error erasing at 0x%lx\n", (long)ofs); + /* There was an error */ + goto callback; + } + ofs += nand->erasesize; + len -= nand->erasesize; + } + + callback: + return 0; +} + +static inline int nandcheck(unsigned long potential, unsigned long physadr) +{ + + + return 0; +} + +void nand_probe(unsigned long physadr) +{ + struct nand_chip *nand = NULL; + int i = 0, ChipID = 1; + +#ifdef CONFIG_MTD_NAND_ECC_JFFS2 + oob_config.ecc_pos[0] = NAND_JFFS2_OOB_ECCPOS0; + oob_config.ecc_pos[1] = NAND_JFFS2_OOB_ECCPOS1; + oob_config.ecc_pos[2] = NAND_JFFS2_OOB_ECCPOS2; + oob_config.ecc_pos[3] = NAND_JFFS2_OOB_ECCPOS3; + oob_config.ecc_pos[4] = NAND_JFFS2_OOB_ECCPOS4; + oob_config.ecc_pos[5] = NAND_JFFS2_OOB_ECCPOS5; + oob_config.badblock_pos = 5; + oob_config.eccvalid_pos = 4; +#else + oob_config.ecc_pos[0] = NAND_NOOB_ECCPOS0; + oob_config.ecc_pos[1] = NAND_NOOB_ECCPOS1; + oob_config.ecc_pos[2] = NAND_NOOB_ECCPOS2; + oob_config.ecc_pos[3] = NAND_NOOB_ECCPOS3; + oob_config.ecc_pos[4] = NAND_NOOB_ECCPOS4; + oob_config.ecc_pos[5] = NAND_NOOB_ECCPOS5; + oob_config.badblock_pos = NAND_NOOB_BADBPOS; + oob_config.eccvalid_pos = NAND_NOOB_ECCVPOS; +#endif + + for (i=0; i<CFG_MAX_NAND_DEVICE; i++) { + if (nand_dev_desc[i].ChipID == NAND_ChipID_UNKNOWN) { + nand = nand_dev_desc + i; + break; + } + } + + if (curr_device == -1) + curr_device = i; + + memset((char *)nand, 0, sizeof(struct nand_chip)); + + nand->cache_page = -1; /* init the cache page */ + nand->IO_ADDR = physadr; + nand->ChipID = ChipID; + NanD_ScanChips(nand); + nand->data_buf = malloc (nand->oobblock + nand->oobsize); + if (!nand->data_buf) { + puts ("Cannot allocate memory for data structures.\n"); + return; + } +} + +#ifdef CONFIG_MTD_NAND_ECC +/* + * Pre-calculated 256-way 1 byte column parity + */ +static const u_char nand_ecc_precalc_table[] = { + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a, + 0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f, + 0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c, + 0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69, + 0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03, + 0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66, + 0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65, + 0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00 +}; + + +/* + * Creates non-inverted ECC code from line parity + */ +static void nand_trans_result(u_char reg2, u_char reg3, + u_char *ecc_code) +{ + u_char a, b, i, tmp1, tmp2; + + /* Initialize variables */ + a = b = 0x80; + tmp1 = tmp2 = 0; + + /* Calculate first ECC byte */ + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */ + tmp1 |= b; + b >>= 1; + a >>= 1; + } + + /* Calculate second ECC byte */ + b = 0x80; + for (i = 0; i < 4; i++) { + if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */ + tmp2 |= b; + b >>= 1; + a >>= 1; + } + + /* Store two of the ECC bytes */ + ecc_code[0] = tmp1; + ecc_code[1] = tmp2; +} + +/* + * Calculate 3 byte ECC code for 256 byte block + */ +static void nand_calculate_ecc (const u_char *dat, u_char *ecc_code) +{ + u_char idx, reg1, reg2, reg3; + int j; + + /* Initialize variables */ + reg1 = reg2 = reg3 = 0; + ecc_code[0] = ecc_code[1] = ecc_code[2] = 0; + + /* Build up column parity */ + for(j = 0; j < 256; j++) { + + /* Get CP0 - CP5 from table */ + idx = nand_ecc_precalc_table[dat[j]]; + reg1 ^= (idx & 0x3f); + + /* All bit XOR = 1 ? */ + if (idx & 0x40) { + reg3 ^= (u_char) j; + reg2 ^= ~((u_char) j); + } + } + + /* Create non-inverted ECC code from line parity */ + nand_trans_result(reg2, reg3, ecc_code); + + /* Calculate final ECC code */ + ecc_code[0] = ~ecc_code[0]; + ecc_code[1] = ~ecc_code[1]; + ecc_code[2] = ((~reg1) << 2) | 0x03; +} + +/* + * Detect and correct a 1 bit error for 256 byte block + */ +static int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc) +{ + u_char a, b, c, d1, d2, d3, add, bit, i; + + /* Do error detection */ + d1 = calc_ecc[0] ^ read_ecc[0]; + d2 = calc_ecc[1] ^ read_ecc[1]; + d3 = calc_ecc[2] ^ read_ecc[2]; + + if ((d1 | d2 | d3) == 0) { + /* No errors */ + return 0; + } + else { + a = (d1 ^ (d1 >> 1)) & 0x55; + b = (d2 ^ (d2 >> 1)) & 0x55; + c = (d3 ^ (d3 >> 1)) & 0x54; + + /* Found and will correct single bit error in the data */ + if ((a == 0x55) && (b == 0x55) && (c == 0x54)) { + c = 0x80; + add = 0; + a = 0x80; + for (i=0; i<4; i++) { + if (d1 & c) + add |= a; + c >>= 2; + a >>= 1; + } + c = 0x80; + for (i=0; i<4; i++) { + if (d2 & c) + add |= a; + c >>= 2; + a >>= 1; + } + bit = 0; + b = 0x04; + c = 0x80; + for (i=0; i<3; i++) { + if (d3 & c) + bit |= b; + c >>= 2; + b >>= 1; + } + b = 0x01; + a = dat[add]; + a ^= (b << bit); + dat[add] = a; + return 1; + } + else { + i = 0; + while (d1) { + if (d1 & 0x01) + ++i; + d1 >>= 1; + } + while (d2) { + if (d2 & 0x01) + ++i; + d2 >>= 1; + } + while (d3) { + if (d3 & 0x01) + ++i; + d3 >>= 1; + } + if (i == 1) { + /* ECC Code Error Correction */ + read_ecc[0] = calc_ecc[0]; + read_ecc[1] = calc_ecc[1]; + read_ecc[2] = calc_ecc[2]; + return 2; + } + else { + /* Uncorrectable Error */ + return -1; + } + } + } + + /* Should never happen */ + return -1; +} +#endif +#endif /* (CONFIG_COMMANDS & CFG_CMD_NAND) */ diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c index 31abbaf..c009156 100644 --- a/common/cmd_pcmcia.c +++ b/common/cmd_pcmcia.c @@ -514,12 +514,17 @@ static int hardware_disable(int slot) /* -------------------------------------------------------------------- */ /* TQM8xxL Boards by TQ Components */ +/* SC8xx Boards by SinoVee Microsystems */ /* -------------------------------------------------------------------- */ -#if defined(CONFIG_TQM8xxL) +#if defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx) +#if defined(CONFIG_TQM8xxL) #define PCMCIA_BOARD_MSG "TQM8xxL" - +#endif +#if defined(CONFIG_SVM_SC8xx) +#define PCMCIA_BOARD_MSG "SC8xx" +#endif static int hardware_enable(int slot) { diff --git a/common/command.c b/common/command.c index 2304d7a..1008925 100644 --- a/common/command.c +++ b/common/command.c @@ -58,6 +58,7 @@ #include <cmd_mii.h> #include <cmd_dcr.h> /* 4xx DCR register access */ #include <cmd_doc.h> +#include <cmd_nand.h> #include <cmd_jffs2.h> #include <cmd_fpga.h> @@ -307,6 +308,8 @@ cmd_tbl_t cmd_tbl[] = { CMD_TBL_MTEST CMD_TBL_MUXINFO CMD_TBL_MW + CMD_TBL_NAND + CMD_TBL_NANDBOOT CMD_TBL_NEXT CMD_TBL_NM CMD_TBL_PCI diff --git a/cpu/at91rm9200/Makefile b/cpu/at91rm9200/Makefile new file mode 100644 index 0000000..0953c9f --- /dev/null +++ b/cpu/at91rm9200/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2003 +# 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$(CPU).a + +START = start.o +OBJS = serial.o interrupts.o cpu.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/at91rm9200/config.mk b/cpu/at91rm9200/config.mk new file mode 100644 index 0000000..deb7f87 --- /dev/null +++ b/cpu/at91rm9200/config.mk @@ -0,0 +1,27 @@ +# +# (C) Copyright 2002 +# Sysgo Real-Time Solutions, GmbH <www.elinos.com> +# Marius Groeger <mgroeger@sysgo.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 +# +PLATFORM_RELFLAGS += -fno-strict-aliasing -fno-common -ffixed-r8 \ + -mshort-load-bytes -msoft-float + +PLATFORM_CPPFLAGS += -mapcs-32 -march=armv4 -mtune=arm7tdmi diff --git a/cpu/at91rm9200/cpu.c b/cpu/at91rm9200/cpu.c new file mode 100644 index 0000000..f41210b --- /dev/null +++ b/cpu/at91rm9200/cpu.c @@ -0,0 +1,177 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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 + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <AT91RM9200.h> + +/* read co-processor 15, register #1 (control register) */ +static unsigned long read_p15_c1(void) +{ + unsigned long value; + + __asm__ __volatile__( + "mrc p15, 0, %0, c1, c0, 0 @ read control reg\n" + : "=r" (value) + : + : "memory"); + /*printf("p15/c1 is = %08lx\n", value); */ + return value; +} + +/* write to co-processor 15, register #1 (control register) */ +static void write_p15_c1(unsigned long value) +{ + /*printf("write %08lx to p15/c1\n", value); */ + __asm__ __volatile__( + "mcr p15, 0, %0, c1, c0, 0 @ write it back\n" + : "=r" (value) + : + : "memory"); + + read_p15_c1(); +} + +static void cp_delay(void) +{ + volatile int i; + + /* copro seems to need some delay between reading and writing */ + for (i=0; i<100; i++); +} +/* See also ARM Ref. Man. */ +#define C1_MMU (1<<0) /* mmu off/on */ +#define C1_ALIGN (1<<1) /* alignment faults off/on */ +#define C1_IDC (1<<2) /* icache and/or dcache off/on */ +#define C1_WRITE_BUFFER (1<<3) /* write buffer off/on */ +#define C1_BIG_ENDIAN (1<<7) /* big endian off/on */ +#define C1_SYS_PROT (1<<8) /* system protection */ +#define C1_ROM_PROT (1<<9) /* ROM protection */ +#define C1_HIGH_VECTORS (1<<13) /* location of vectors: low/high addresses */ + +int cpu_init(void) +{ + /* + * setup up stack if necessary + */ +#ifdef CONFIG_USE_IRQ + IRQ_STACK_START = _armboot_end + + CONFIG_STACKSIZE + CONFIG_STACKSIZE_IRQ - 4; + FIQ_STACK_START = IRQ_STACK_START + CONFIG_STACKSIZE_FIQ; + _armboot_real_end = FIQ_STACK_START + 4; +#else + _armboot_real_end = _armboot_end + CONFIG_STACKSIZE; +#endif + return 0; +} + +int cleanup_before_linux(void) +{ + /* + * this function is called just before we call linux + * it prepares the processor for linux + * + * we turn off caches etc ... + * and we set the CPU-speed to 73 MHz - see start.S for details + */ + + disable_interrupts(); + return 0; +} + +int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + +#ifdef CFG_SOFT_RESET + extern void reset_cpu(ulong addr); + + disable_interrupts(); + reset_cpu(0); +#else + AT91PS_USART us = AT91C_BASE_US1; + AT91PS_PIO pio = AT91C_BASE_PIOA; + + /*shutdown the console to avoid strange chars during reset */ + us->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); + + /* Clear PA19 to trigger the hard reset */ + pio->PIO_CODR = 0x00080000; + pio->PIO_OER = 0x00080000; + pio->PIO_PER = 0x00080000; + /* Never reached */ +#endif + return 0; +} + +void icache_enable(void) +{ + ulong reg; + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg | C1_IDC); +} + +void icache_disable(void) +{ + ulong reg; + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg & ~C1_IDC); +} + +int icache_status(void) +{ + return (read_p15_c1() & C1_IDC) != 0; + return 0; +} + +void dcache_enable(void) +{ + ulong reg; + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg | C1_IDC); +} + +void dcache_disable(void) +{ + ulong reg; + reg = read_p15_c1(); + cp_delay(); + write_p15_c1(reg & ~C1_IDC); +} + +int dcache_status(void) +{ + return (read_p15_c1() & C1_IDC) != 0; + return 0; +} diff --git a/cpu/at91rm9200/interrupts.c b/cpu/at91rm9200/interrupts.c new file mode 100644 index 0000000..a14ef81 --- /dev/null +++ b/cpu/at91rm9200/interrupts.c @@ -0,0 +1,236 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc. <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.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 <AT91RM9200.h> +#include <asm/proc-armv/ptrace.h> + +extern void reset_cpu(ulong addr); + +/* we always count down the max. */ +#define TIMER_LOAD_VAL 0xffff + +/* macro to read the 16 bit timer */ +#define READ_TIMER (tmr->TC_CV) +AT91PS_TC tmr; + + + +void enable_interrupts (void) +{ + return; +} +int disable_interrupts (void) +{ + return 0; +} + + +void bad_mode(void) +{ + panic("Resetting CPU ...\n"); + reset_cpu(0); +} + +void show_regs(struct pt_regs * regs) +{ + unsigned long flags; +const char *processor_modes[]= +{ "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , + "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" , + "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32" +}; + + flags = condition_codes(regs); + + printf("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer(regs), + regs->ARM_lr, regs->ARM_sp, + regs->ARM_ip, regs->ARM_fp); + printf("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, + regs->ARM_r8); + printf("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, + regs->ARM_r5, regs->ARM_r4); + printf("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, + regs->ARM_r1, regs->ARM_r0); + printf("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', + flags & CC_V_BIT ? 'V' : 'v'); + printf(" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled(regs) ? "on" : "off", + fast_interrupts_enabled(regs) ? "on" : "off", + processor_modes[processor_mode(regs)], + thumb_mode(regs) ? " (T)" : ""); +} + +void do_undefined_instruction(struct pt_regs *pt_regs) +{ + printf("undefined instruction\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_software_interrupt(struct pt_regs *pt_regs) +{ + printf("software interrupt\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_prefetch_abort(struct pt_regs *pt_regs) +{ + printf("prefetch abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_data_abort(struct pt_regs *pt_regs) +{ + printf("data abort\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_not_used(struct pt_regs *pt_regs) +{ + printf("not used\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_fiq(struct pt_regs *pt_regs) +{ + printf("fast interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +void do_irq(struct pt_regs *pt_regs) +{ + printf("interrupt request\n"); + show_regs(pt_regs); + bad_mode(); +} + +static ulong timestamp; +static ulong lastinc; + +int interrupt_init (void) +{ + + tmr = AT91C_BASE_TC0; + + /* enables TC1.0 clock */ + *AT91C_PMC_PCER = 1 << AT91C_ID_TC0; /* enable clock */ + + *AT91C_TCB0_BCR = 0; + *AT91C_TCB0_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_NONE | AT91C_TCB_TC2XC2S_NONE; + tmr->TC_CCR = AT91C_TC_CLKDIS; + tmr->TC_CMR = AT91C_TC_TIMER_DIV1_CLOCK; /* set to MCLK/2 */ + + tmr->TC_IDR = ~0ul; + tmr->TC_RC = TIMER_LOAD_VAL; + lastinc = TIMER_LOAD_VAL; + tmr->TC_CCR = AT91C_TC_SWTRG | AT91C_TC_CLKEN; + timestamp = 0; + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer(void) +{ + reset_timer_masked(); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked() - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay(unsigned long usec) +{ + udelay_masked(usec); +} + +void reset_timer_masked(void) +{ + /* reset time */ + lastinc = READ_TIMER; + timestamp = 0; +} + +ulong get_timer_masked(void) +{ + ulong now = READ_TIMER; + if (now >= lastinc) + { + /* normal mode */ + timestamp += now - lastinc; + } else { + /* we have an overflow ... */ + timestamp += now + TIMER_LOAD_VAL - lastinc; + } + lastinc = now; + + return timestamp; +} + +void udelay_masked(unsigned long usec) +{ + ulong tmo; + + tmo = usec / 1000; + tmo *= CFG_HZ; + tmo /= 1000; + + reset_timer_masked(); + + while(get_timer_masked() < tmo); + /*NOP*/; +} + + diff --git a/cpu/at91rm9200/serial.c b/cpu/at91rm9200/serial.c new file mode 100644 index 0000000..565cd3d --- /dev/null +++ b/cpu/at91rm9200/serial.c @@ -0,0 +1,89 @@ +/* + * (C) Copyright 2002 + * Lineo, Inc <www.lineo.com> + * Bernhard Kuhn <bkuhn@lineo.com> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * 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 <AT91RM9200.h> + +/* ggi thunder */ +AT91PS_USART us = (AT91PS_USART) AT91C_BASE_DBGU; + +void serial_setbrg(void) + { + DECLARE_GLOBAL_DATA_PTR; + int baudrate; + + if ((baudrate = gd->bd->bi_baudrate) <= 0) + baudrate = CONFIG_BAUDRATE; + us->US_BRGR = 33 /* AT91C_MASTER_CLOCK / baudrate / 16 */; /* hardcode so no __divsi3 */ + } + +int serial_init(void) + { + /* make any port initializations specific to this port */ + *AT91C_PIOA_PDR = AT91C_PA31_DTXD | AT91C_PA30_DRXD; /* PA 31 & 30 */ + *AT91C_PMC_PCER = 1 << AT91C_ID_SYS; /* enable clock */ + serial_setbrg(); + + us->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX; + us->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; + us->US_MR = ( AT91C_US_CLKS_CLOCK | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_NBSTOP_1_BIT ); + us->US_IMR = ~0ul; + return (0); + } + +void serial_putc(const char c) + { + if (c == '\n') + serial_putc('\r'); + while( (us->US_CSR & AT91C_US_TXRDY) == 0 ) + ; + us->US_THR=c; + } + +void +serial_puts (const char *s) + { + while (*s) + { + serial_putc (*s++); + } + } + +int serial_getc(void) + { + while( (us->US_CSR & AT91C_US_RXRDY) == 0 ); + return us->US_RHR; + } + +int serial_tstc(void) + { + return ((us->US_CSR & AT91C_US_RXRDY) == AT91C_US_RXRDY); + } diff --git a/cpu/at91rm9200/start.S b/cpu/at91rm9200/start.S new file mode 100644 index 0000000..9b3e7aa --- /dev/null +++ b/cpu/at91rm9200/start.S @@ -0,0 +1,347 @@ +/* + * armboot - Startup Code for ARM720 CPU-core + * + * Copyright (c) 2001 Marius Gröger <mag@sysgo.de> + * Copyright (c) 2002 Alex Züpke <azu@sysgo.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 "config.h" +#include "version.h" + + +/* + ************************************************************************* + * + * Jump vector table as in table 3.1 in [1] + * + ************************************************************************* + */ + + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + + +/* + ************************************************************************* + * + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * relocate armboot to ram + * setup stack + * jump to second stage + * + ************************************************************************* + */ + +/* + * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h) + */ +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * Note: _armboot_end_data and _armboot_end are defined + * by the (board-dependent) linker script. + * _armboot_end_data is the first usable FLASH address after armboot + */ +.globl _armboot_end_data +_armboot_end_data: + .word armboot_end_data +/* + * Note: armboot_end is defined by the (board-dependent) linker script + */ +.globl _armboot_end +_armboot_end: + .word armboot_end + +/* + * _armboot_real_end is the first usable RAM address behind armboot + * and the various stacks + */ +.globl _armboot_real_end +_armboot_real_end: + .word 0x0badc0de + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + + +/* + * the actual reset code + */ + +reset: + /* + * set the cpu to SVC32 mode + */ + mrs r0,cpsr + bic r0,r0,#0x1f + orr r0,r0,#0x13 + msr cpsr,r0 + + /* + * relocate exeception table + */ + ldr r0, =_start + ldr r1, =0x0 + mov r2, #16 +copyex: + subs r2, r2, #1 + ldr r3, [r0], #4 + str r3, [r1], #4 + bne copyex + + /* + * we do sys-critical inits only at reboot, + * not when booting from ram! + */ +#ifdef CONFIG_INIT_CRITICAL + bl cpu_init_crit +#endif + + /* set up the stack */ + ldr r0, _armboot_end + add r0, r0, #CONFIG_STACKSIZE + sub sp, r0, #12 /* leave 3 words for abort-stack */ + ldr pc,_start_armboot + +_start_armboot: .word start_armboot + +/* + ************************************************************************* + * + * CPU_init_critical registers + * + ************************************************************************* + */ + +cpu_init_crit: + # actually do nothing for now! + mov pc, lr + + + + +/* + ************************************************************************* + * + * Interrupt handling + * + ************************************************************************* + */ + +@ +@ IRQ stack frame. +@ +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 +#define I_BIT 0x80 + +/* + * use bad_save_user_regs for abort/prefetch/undef/swi ... + * use irq_save_user_regs / irq_restore_user_regs for IRQ/FIQ handling + */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + + ldr r2, _armboot_end + add r2, r2, #CONFIG_STACKSIZE + sub r2, r2, #8 + ldmia r2, {r2 - r4} @ get pc, cpsr, old_r0 + add r0, sp, #S_FRAME_SIZE @ restore sp_SVC + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} @ save sp_SVC, lr_SVC, pc, cpsr, old_r + mov r0, sp + .endm + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} @ Calling r0-r12 + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ @ Calling SP, LR + str lr, [r8, #0] @ Save calling PC + mrs r6, spsr + str r6, [r8, #4] @ Save CPSR + str r0, [r8, #8] @ Save OLD_R0 + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, _armboot_end @ setup our mode stack + add r13, r13, #CONFIG_STACKSIZE @ resides at top of normal stack + sub r13, r13, #8 + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + msr spsr_c, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + +/* + * exception handlers + */ + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + /* someone ought to write a more effiction fiq_save_user_regs */ + irq_save_user_regs + bl do_fiq + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + + .align 5 +.globl reset_cpu +reset_cpu: + mov pc, r0 diff --git a/cpu/mpc8xx/cpu_init.c b/cpu/mpc8xx/cpu_init.c index 4bd91f9..83ff66a 100644 --- a/cpu/mpc8xx/cpu_init.c +++ b/cpu/mpc8xx/cpu_init.c @@ -54,9 +54,11 @@ void cpu_init_f (volatile immap_t * immr) #endif /* CONFIG_WATCHDOG */ /* SIUMCR - contains debug pin configuration (11-6) */ - +#ifndef CONFIG_SVM_SC8xx immr->im_siu_conf.sc_siumcr |= CFG_SIUMCR; - +#else + immr->im_siu_conf.sc_siumcr = CFG_SIUMCR; +#endif /* initialize timebase status and control register (11-26) */ /* unlock TBSCRK */ diff --git a/cpu/sa1100/serial.c b/cpu/sa1100/serial.c index 68bcd1f..d3b8628 100644 --- a/cpu/sa1100/serial.c +++ b/cpu/sa1100/serial.c @@ -53,17 +53,19 @@ void serial_setbrg (void) hang (); #ifdef CONFIG_SERIAL1 + /* SA1110 uart function */ + Ser1SDCR0 |= SDCR0_SUS; + /* Wait until port is ready ... */ - while (Ser1UTSR1 & UTSR1_TBY) { - } + while(Ser1UTSR1 & UTSR1_TBY) {} /* init serial serial 1 */ Ser1UTCR3 = 0x00; Ser1UTSR0 = 0xff; - Ser1UTCR0 = (UTCR0_1StpBit | UTCR0_8BitData); + Ser1UTCR0 = ( UTCR0_1StpBit | UTCR0_8BitData ); Ser1UTCR1 = 0; - Ser1UTCR2 = (u32) reg; - Ser1UTCR3 = (UTCR3_RXE | UTCR3_TXE); + Ser1UTCR2 = (u32)reg; + Ser1UTCR3 = ( UTCR3_RXE | UTCR3_TXE ); #elif CONFIG_SERIAL3 /* Wait until port is ready ... */ while (Ser3UTSR1 & UTSR1_TBY) { diff --git a/drivers/Makefile b/drivers/Makefile index 3278cec..59d753e 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -27,7 +27,8 @@ include $(TOPDIR)/config.mk LIB = libdrivers.a -OBJS = 3c589.o 5701rls.o bcm570x.o bcm570x_autoneg.o \ +OBJS = 3c589.o 5701rls.o at91rm9200_ether.o \ + bcm570x.o bcm570x_autoneg.o \ cfb_console.o cs8900.o ct69000.o dc2114x.o \ eepro100.o i8042.o inca-ip_sw.o \ natsemi.o ns16550.o ns8382x.o ns87308.o \ diff --git a/drivers/at91rm9200_ether.c b/drivers/at91rm9200_ether.c new file mode 100644 index 0000000..1b3e87f --- /dev/null +++ b/drivers/at91rm9200_ether.c @@ -0,0 +1,251 @@ + +#include <common.h> +#include <command.h> +#include <AT91RM9200.h> +#include <net.h> + +/* ----- Ethernet Buffer definitions ----- */ + +typedef struct { + unsigned long addr,size; +} rbf_t; + +#define RBF_ADDR 0xfffffffc +#define RBF_OWNER (1<<0) +#define RBF_WRAP (1<<1) +#define RBF_BROADCAST (1<<31) +#define RBF_MULTICAST (1<<30) +#define RBF_UNICAST (1<<29) +#define RBF_EXTERNAL (1<<28) +#define RBF_UNKOWN (1<<27) +#define RBF_SIZE 0x07ff +#define RBF_LOCAL4 (1<<26) +#define RBF_LOCAL3 (1<<25) +#define RBF_LOCAL2 (1<<24) +#define RBF_LOCAL1 (1<<23) + +#define RBF_FRAMEMAX 10 +#define RBF_FRAMEMEM 0x200000 +#define RBF_FRAMELEN 0x600 + +#define RBF_FRAMEBTD RBF_FRAMEMEM +#define RBF_FRAMEBUF (RBF_FRAMEMEM + RBF_FRAMEMAX*sizeof(rbf_t)) + +/* stolen from mii.h */ +/* Generic MII registers. */ + +#define MII_BMCR 0x00 /* Basic mode control register */ +#define MII_BMSR 0x01 /* Basic mode status register */ +#define BMSR_JCD 0x0002 /* Jabber detected */ +#define BMSR_LSTATUS 0x0004 /* Link status */ +#define BMSR_10HALF 0x0800 /* Can do 10mbps, half-duplex */ +#define BMSR_100FULL 0x4000 /* Can do 100mbps, full-duplex */ +#define BMSR_10FULL 0x1000 /* Can do 10mbps, full-duplex */ +#define BMSR_100HALF 0x2000 /* Can do 100mbps, half-duplex */ + +#define MII_STS2_REG 17 /* Davicom specific */ +#define MII_MDINTR_REG 21 /* Davicom specific */ + +#ifdef CONFIG_DRIVER_ETHER + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +AT91PS_EMAC p_mac; + +int MII_ReadPhy(unsigned char addr, unsigned short *ret) + { + + p_mac->EMAC_MAN = 0x60020000 | (addr << 18); + udelay(10000); + *ret = (unsigned short)p_mac->EMAC_MAN; + return 1; + } + + +int MII_GetLinkSpeed(void) + { + unsigned short stat1, stat2; + int ret; + + if (!(ret = MII_ReadPhy(MII_BMSR, &stat1))) + return 0; + + if (stat1 & BMSR_JCD) + { +#ifdef DEBUG + printf("MII: jabber condition detected\n"); +#endif /*jabber detected re-read the register*/ + } + if (!(ret = MII_ReadPhy(MII_BMSR, &stat1))) + return 0; + if (!(stat1 & BMSR_LSTATUS)) /* link status up? */ + { + printf("MII: no Link\n"); + return 0; + } + + if (!(ret = MII_ReadPhy(MII_STS2_REG, &stat2))) + return 0; + + if ((stat1 & BMSR_100FULL) && (stat2 & 0x8000) ) + { + /* set MII for 100BaseTX and Full Duplex */ + p_mac->EMAC_CFG |= AT91C_EMAC_SPD | AT91C_EMAC_FD; +#ifdef DEBUG + printf("MII: 100BaseTX and Full Duplex detected\n"); +#endif + return 1; + } + + else + if ((stat1 & BMSR_10FULL) && (stat2 & 0x2000)) + { + /* set MII for 10BaseT and Full Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)); +#ifdef DEBUG + printf("MII: 10BaseT and Full Duplex detected\n"); +#endif + return 1; + } + else + if ((stat1 & BMSR_100HALF) && (stat2 & 0x4000)) + { + /* set MII for 100BaseTX and Half Duplex */ + p_mac->EMAC_CFG = (p_mac->EMAC_CFG & ~(AT91C_EMAC_SPD | AT91C_EMAC_FD)); +#ifdef DEBUG + printf("MII: 100BaseTX and Hall Duplex detected\n"); +#endif + return 1; + } + else + if ((stat1 & BMSR_10HALF) && (stat2 & 0x1000)) + { + /*set MII for 10BaseT and Half Duplex */ + p_mac->EMAC_CFG &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD); +#ifdef DEBUG + printf("MII: 10BaseT and Hall Duplex detected\n"); +#endif + return 1; + } + + return 0; + } + + +int MDIO_StartupPhy(void) + { + int ret; + + if(p_mac->EMAC_SR & AT91C_EMAC_LINK) + { + printf("MDIO_StartupPhy: no link\n"); + return 0; + }; + + p_mac->EMAC_CTL |= AT91C_EMAC_MPE; + + ret = MII_GetLinkSpeed(); + if (ret == 0) + { + printf("MDIO_StartupPhy: MII_GetLinkSpeed failed\n"); + ret = 0; + } + else + { + ret = 1; + } + + p_mac->EMAC_CTL &= ~AT91C_EMAC_MPE; + return ret; + + } + + +rbf_t* rbfdt; +rbf_t* rbfp; + +int eth_init( bd_t *bd ) + { + int ret; + int i; + p_mac = AT91C_BASE_EMAC; + + *AT91C_PIOA_PDR = AT91C_PA16_EMDIO | + AT91C_PA15_EMDC | AT91C_PA14_ERXER | AT91C_PA13_ERX1 | AT91C_PA12_ERX0 | + AT91C_PA11_ECRS_ECRSDV | AT91C_PA10_ETX1 | AT91C_PA9_ETX0 | AT91C_PA8_ETXEN | + AT91C_PA7_ETXCK_EREFCK; /* PIO Disable Register */ + + *AT91C_PIOB_PDR = AT91C_PB25_EF100 | + AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | + AT91C_PB15_ERX2 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; + + *AT91C_PIOB_BSR = AT91C_PB25_EF100 | + AT91C_PB19_ERXCK | AT91C_PB18_ECOL | AT91C_PB17_ERXDV | AT91C_PB16_ERX3 | + AT91C_PB15_ERX2 | AT91C_PB14_ETXER | AT91C_PB13_ETX3 | AT91C_PB12_ETX2; /* Select B Register */ + *AT91C_PMC_PCER = 1 << AT91C_ID_EMAC; /* Peripheral Clock Enable Register */ + p_mac->EMAC_CFG |= AT91C_EMAC_CSR; /* Clear statistics */ + + rbfdt=(rbf_t *)RBF_FRAMEBTD; + for(i = 0; i < RBF_FRAMEMAX; i++) + { + rbfdt[i].addr=RBF_FRAMEBUF+RBF_FRAMELEN*i; + rbfdt[i].size=0; + } + rbfdt[RBF_FRAMEMAX-1].addr|=RBF_WRAP; + rbfp=&rbfdt[0]; + + if (!(ret = MDIO_StartupPhy())) + { + printf("MAC: error during MII initialization\n"); + return 0; + } + + p_mac->EMAC_SA2L = (bd->bi_enetaddr[3] << 24) | (bd->bi_enetaddr[2] << 16) + | (bd->bi_enetaddr[1] << 8) | (bd->bi_enetaddr[0]); + p_mac->EMAC_SA2H = (bd->bi_enetaddr[5] << 8) | (bd->bi_enetaddr[4]); + + p_mac->EMAC_RBQP = (long)(&rbfdt[0]); + p_mac->EMAC_RSR &= ~(AT91C_EMAC_RSR_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA); + p_mac->EMAC_CFG = (p_mac->EMAC_CFG | AT91C_EMAC_CAF | AT91C_EMAC_NBC | AT91C_EMAC_RMII) & ~AT91C_EMAC_CLK; + p_mac->EMAC_CTL |= AT91C_EMAC_TE | AT91C_EMAC_RE ; + + return 0; + } + +int eth_send(volatile void *packet, int length) + { + while(!(p_mac->EMAC_TSR & AT91C_EMAC_BNQ)) + ; + p_mac->EMAC_TAR = (long)packet; + p_mac->EMAC_TCR = length; + while(p_mac->EMAC_TCR & 0x7ff) + ; + p_mac->EMAC_TSR |= AT91C_EMAC_COMP; + return 0; + } + +int eth_rx(void) + { + int size; + + if(!(rbfp->addr & RBF_OWNER)) + return 0; + + size=rbfp->size & RBF_SIZE; + NetReceive((volatile uchar *) (rbfp->addr & RBF_ADDR), size); + + rbfp->addr &= ~RBF_OWNER; + if(rbfp->addr & RBF_WRAP) + rbfp = &rbfdt[0]; + else + rbfp++; + + p_mac->EMAC_RSR |= AT91C_EMAC_REC; + + return size; + } + +void eth_halt( void ) + {}; +#endif +#endif diff --git a/drivers/smc91111.c b/drivers/smc91111.c index 6244b4e..652d859 100644 --- a/drivers/smc91111.c +++ b/drivers/smc91111.c @@ -493,6 +493,13 @@ static int smc_send_packet(volatile void *packet, int packet_length) SMC_SELECT_BANK( 2 ); SMC_outw( MC_ALLOC | numPages, MMU_CMD_REG ); + /* FIXME: the ALLOC_INT bit never gets set * + * so the following will always give a * + * memory allocation error. * + * same code works in armboot though * + * -ro + */ + again: try++; time_out = MEMORY_WAIT_TIME; diff --git a/examples/Makefile b/examples/Makefile index e6a3023..2897ba1 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -26,6 +26,7 @@ LOAD_ADDR = 0x40000 include $(TOPDIR)/config.mk SREC = hello_world.srec +BIN = hello_world.bin ifeq ($(CPU),mips) SREC = @@ -50,7 +51,7 @@ LIBOBJS = $(LIBAOBJS) $(LIBCOBJS) CPPFLAGS += -I.. -all: .depend $(LIB) $(SREC) +all: .depend $(LIB) $(SREC) $(BIN) ######################################################################### $(LIB): .depend $(LIBOBJS) @@ -60,6 +61,9 @@ $(LIB): .depend $(LIBOBJS) $(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e $(<:.o=) $< $(LIB) $(OBJCOPY) -O srec $(<:.o=) $@ +%.bin: %.srec + $(OBJCOPY) -O binary $< $@ + ######################################################################### .depend: Makefile $(OBJS:.o=.c) $(LIBCOBJS:.o=.c) $(LIBAOBJS:.o=.S) diff --git a/include/AT91RM9200.h b/include/AT91RM9200.h new file mode 100644 index 0000000..f65328f --- /dev/null +++ b/include/AT91RM9200.h @@ -0,0 +1,349 @@ +/* ---------------------------------------------------------------------------- */ +/* ATMEL Microcontroller Software Support - ROUSSET - */ +/* ---------------------------------------------------------------------------- */ +/* The software is delivered "AS IS" without warranty or condition of any */ +/* kind, either express, implied or statutory. This includes without */ +/* limitation any warranty or condition with respect to merchantability or */ +/* fitness for any particular purpose, or against the infringements of */ +/* intellectual property rights of others. */ +/* ---------------------------------------------------------------------------- */ +/* File Name : AT91RM9200.h */ +/* Object : AT91RM9200 definitions */ +/* Generated : AT91 SW Application Group 10/29/2002 (16:10:51) */ +#ifndef AT91RM9200_H +#define AT91RM9200_H + +typedef volatile unsigned int AT91_REG;/* Hardware register definition */ + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Timer Counter Channel Interface */ +/* ***************************************************************************** */ +typedef struct _AT91S_TC { + AT91_REG TC_CCR; /* Channel Control Register */ + AT91_REG TC_CMR; /* Channel Mode Register */ + AT91_REG Reserved0[2]; /* */ + AT91_REG TC_CV; /* Counter Value */ + AT91_REG TC_RA; /* Register A */ + AT91_REG TC_RB; /* Register B */ + AT91_REG TC_RC; /* Register C */ + AT91_REG TC_SR; /* Status Register */ + AT91_REG TC_IER; /* Interrupt Enable Register */ + AT91_REG TC_IDR; /* Interrupt Disable Register */ + AT91_REG TC_IMR; /* Interrupt Mask Register */ +} AT91S_TC, *AT91PS_TC; + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Usart */ +/* ***************************************************************************** */ +typedef struct _AT91S_USART { + AT91_REG US_CR; /* Control Register */ + AT91_REG US_MR; /* Mode Register */ + AT91_REG US_IER; /* Interrupt Enable Register */ + AT91_REG US_IDR; /* Interrupt Disable Register */ + AT91_REG US_IMR; /* Interrupt Mask Register */ + AT91_REG US_CSR; /* Channel Status Register */ + AT91_REG US_RHR; /* Receiver Holding Register */ + AT91_REG US_THR; /* Transmitter Holding Register */ + AT91_REG US_BRGR; /* Baud Rate Generator Register */ + AT91_REG US_RTOR; /* Receiver Time-out Register */ + AT91_REG US_TTGR; /* Transmitter Time-guard Register */ + AT91_REG Reserved0[5]; /* */ + AT91_REG US_FIDI; /* FI_DI_Ratio Register */ + AT91_REG US_NER; /* Nb Errors Register */ + AT91_REG US_XXR; /* XON_XOFF Register */ + AT91_REG US_IF; /* IRDA_FILTER Register */ + AT91_REG Reserved1[44]; /* */ + AT91_REG US_RPR; /* Receive Pointer Register */ + AT91_REG US_RCR; /* Receive Counter Register */ + AT91_REG US_TPR; /* Transmit Pointer Register */ + AT91_REG US_TCR; /* Transmit Counter Register */ + AT91_REG US_RNPR; /* Receive Next Pointer Register */ + AT91_REG US_RNCR; /* Receive Next Counter Register */ + AT91_REG US_TNPR; /* Transmit Next Pointer Register */ + AT91_REG US_TNCR; /* Transmit Next Counter Register */ + AT91_REG US_PTCR; /* PDC Transfer Control Register */ + AT91_REG US_PTSR; /* PDC Transfer Status Register */ +} AT91S_USART, *AT91PS_USART; + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Parallel Input Output Controler */ +/* ***************************************************************************** */ +typedef struct _AT91S_PIO { + AT91_REG PIO_PER; /* PIO Enable Register */ + AT91_REG PIO_PDR; /* PIO Disable Register */ + AT91_REG PIO_PSR; /* PIO Status Register */ + AT91_REG Reserved0[1]; /* */ + AT91_REG PIO_OER; /* Output Enable Register */ + AT91_REG PIO_ODR; /* Output Disable Registerr */ + AT91_REG PIO_OSR; /* Output Status Register */ + AT91_REG Reserved1[1]; /* */ + AT91_REG PIO_IFER; /* Input Filter Enable Register */ + AT91_REG PIO_IFDR; /* Input Filter Disable Register */ + AT91_REG PIO_IFSR; /* Input Filter Status Register */ + AT91_REG Reserved2[1]; /* */ + AT91_REG PIO_SODR; /* Set Output Data Register */ + AT91_REG PIO_CODR; /* Clear Output Data Register */ + AT91_REG PIO_ODSR; /* Output Data Status Register */ + AT91_REG PIO_PDSR; /* Pin Data Status Register */ + AT91_REG PIO_IER; /* Interrupt Enable Register */ + AT91_REG PIO_IDR; /* Interrupt Disable Register */ + AT91_REG PIO_IMR; /* Interrupt Mask Register */ + AT91_REG PIO_ISR; /* Interrupt Status Register */ + AT91_REG PIO_MDER; /* Multi-driver Enable Register */ + AT91_REG PIO_MDDR; /* Multi-driver Disable Register */ + AT91_REG PIO_MDSR; /* Multi-driver Status Register */ + AT91_REG Reserved3[1]; /* */ + AT91_REG PIO_PPUDR; /* Pull-up Disable Register */ + AT91_REG PIO_PPUER; /* Pull-up Enable Register */ + AT91_REG PIO_PPUSR; /* Pad Pull-up Status Register */ + AT91_REG Reserved4[1]; /* */ + AT91_REG PIO_ASR; /* Select A Register */ + AT91_REG PIO_BSR; /* Select B Register */ + AT91_REG PIO_ABSR; /* AB Select Status Register */ + AT91_REG Reserved5[9]; /* */ + AT91_REG PIO_OWER; /* Output Write Enable Register */ + AT91_REG PIO_OWDR; /* Output Write Disable Register */ + AT91_REG PIO_OWSR; /* Output Write Status Register */ +} AT91S_PIO, *AT91PS_PIO; + + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Debug Unit */ +/* ***************************************************************************** */ +typedef struct _AT91S_DBGU { + AT91_REG DBGU_CR; /* Control Register */ + AT91_REG DBGU_MR; /* Mode Register */ + AT91_REG DBGU_IER; /* Interrupt Enable Register */ + AT91_REG DBGU_IDR; /* Interrupt Disable Register */ + AT91_REG DBGU_IMR; /* Interrupt Mask Register */ + AT91_REG DBGU_CSR; /* Channel Status Register */ + AT91_REG DBGU_RHR; /* Receiver Holding Register */ + AT91_REG DBGU_THR; /* Transmitter Holding Register */ + AT91_REG DBGU_BRGR; /* Baud Rate Generator Register */ + AT91_REG Reserved0[7]; /* */ + AT91_REG DBGU_C1R; /* Chip ID1 Register */ + AT91_REG DBGU_C2R; /* Chip ID2 Register */ + AT91_REG DBGU_FNTR; /* Force NTRST Register */ + AT91_REG Reserved1[45]; /* */ + AT91_REG DBGU_RPR; /* Receive Pointer Register */ + AT91_REG DBGU_RCR; /* Receive Counter Register */ + AT91_REG DBGU_TPR; /* Transmit Pointer Register */ + AT91_REG DBGU_TCR; /* Transmit Counter Register */ + AT91_REG DBGU_RNPR; /* Receive Next Pointer Register */ + AT91_REG DBGU_RNCR; /* Receive Next Counter Register */ + AT91_REG DBGU_TNPR; /* Transmit Next Pointer Register */ + AT91_REG DBGU_TNCR; /* Transmit Next Counter Register */ + AT91_REG DBGU_PTCR; /* PDC Transfer Control Register */ + AT91_REG DBGU_PTSR; /* PDC Transfer Status Register */ +} AT91S_DBGU, *AT91PS_DBGU; + + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Static Memory Controller 2 Interface */ +/* ***************************************************************************** */ +typedef struct _AT91S_SMC2 { + AT91_REG SMC2_CSR[8]; /* SMC2 Chip Select Register */ +} AT91S_SMC2, *AT91PS_SMC2; + +/* ***************************************************************************** */ +/* SOFTWARE API DEFINITION FOR Ethernet MAC */ +/* ***************************************************************************** */ +typedef struct _AT91S_EMAC { + AT91_REG EMAC_CTL; /* Network Control Register */ + AT91_REG EMAC_CFG; /* Network Configuration Register */ + AT91_REG EMAC_SR; /* Network Status Register */ + AT91_REG EMAC_TAR; /* Transmit Address Register */ + AT91_REG EMAC_TCR; /* Transmit Control Register */ + AT91_REG EMAC_TSR; /* Transmit Status Register */ + AT91_REG EMAC_RBQP; /* Receive Buffer Queue Pointer */ + AT91_REG Reserved0[1]; /* */ + AT91_REG EMAC_RSR; /* Receive Status Register */ + AT91_REG EMAC_ISR; /* Interrupt Status Register */ + AT91_REG EMAC_IER; /* Interrupt Enable Register */ + AT91_REG EMAC_IDR; /* Interrupt Disable Register */ + AT91_REG EMAC_IMR; /* Interrupt Mask Register */ + AT91_REG EMAC_MAN; /* PHY Maintenance Register */ + AT91_REG Reserved1[2]; /* */ + AT91_REG EMAC_FRA; /* Frames Transmitted OK Register */ + AT91_REG EMAC_SCOL; /* Single Collision Frame Register */ + AT91_REG EMAC_MCOL; /* Multiple Collision Frame Register */ + AT91_REG EMAC_OK; /* Frames Received OK Register */ + AT91_REG EMAC_SEQE; /* Frame Check Sequence Error Register */ + AT91_REG EMAC_ALE; /* Alignment Error Register */ + AT91_REG EMAC_DTE; /* Deferred Transmission Frame Register */ + AT91_REG EMAC_LCOL; /* Late Collision Register */ + AT91_REG EMAC_ECOL; /* Excessive Collision Register */ + AT91_REG EMAC_CSE; /* Carrier Sense Error Register */ + AT91_REG EMAC_TUE; /* Transmit Underrun Error Register */ + AT91_REG EMAC_CDE; /* Code Error Register */ + AT91_REG EMAC_ELR; /* Excessive Length Error Register */ + AT91_REG EMAC_RJB; /* Receive Jabber Register */ + AT91_REG EMAC_USF; /* Undersize Frame Register */ + AT91_REG EMAC_SQEE; /* SQE Test Error Register */ + AT91_REG EMAC_DRFC; /* Discarded RX Frame Register */ + AT91_REG Reserved2[3]; /* */ + AT91_REG EMAC_HSH; /* Hash Address High[63:32] */ + AT91_REG EMAC_HSL; /* Hash Address Low[31:0] */ + AT91_REG EMAC_SA1L; /* Specific Address 1 Low, First 4 bytes */ + AT91_REG EMAC_SA1H; /* Specific Address 1 High, Last 2 bytes */ + AT91_REG EMAC_SA2L; /* Specific Address 2 Low, First 4 bytes */ + AT91_REG EMAC_SA2H; /* Specific Address 2 High, Last 2 bytes */ + AT91_REG EMAC_SA3L; /* Specific Address 3 Low, First 4 bytes */ + AT91_REG EMAC_SA3H; /* Specific Address 3 High, Last 2 bytes */ + AT91_REG EMAC_SA4L; /* Specific Address 4 Low, First 4 bytes */ + AT91_REG EMAC_SA4H; /* Specific Address 4 High, Last 2 bytesr */ +} AT91S_EMAC, *AT91PS_EMAC; + +/* -------- DBGU_IER : (DBGU Offset: 0x8) Debug Unit Interrupt Enable Register -------- */ +#define AT91C_US_RXRDY ((unsigned int) 0x1 << 0) /* (DBGU) RXRDY Interrupt */ +#define AT91C_US_TXRDY ((unsigned int) 0x1 << 1) /* (DBGU) TXRDY Interrupt */ +#define AT91C_US_ENDRX ((unsigned int) 0x1 << 3) /* (DBGU) End of Receive Transfer Interrupt */ +#define AT91C_US_ENDTX ((unsigned int) 0x1 << 4) /* (DBGU) End of Transmit Interrupt */ +#define AT91C_US_OVRE ((unsigned int) 0x1 << 5) /* (DBGU) Overrun Interrupt */ +#define AT91C_US_FRAME ((unsigned int) 0x1 << 6) /* (DBGU) Framing Error Interrupt */ +#define AT91C_US_PARE ((unsigned int) 0x1 << 7) /* (DBGU) Parity Error Interrupt */ +#define AT91C_US_TXEMPTY ((unsigned int) 0x1 << 9) /* (DBGU) TXEMPTY Interrupt */ +#define AT91C_US_TXBUFE ((unsigned int) 0x1 << 11) /* (DBGU) TXBUFE Interrupt */ +#define AT91C_US_RXBUFF ((unsigned int) 0x1 << 12) /* (DBGU) RXBUFF Interrupt */ +#define AT91C_US_COMM_TX ((unsigned int) 0x1 << 30) /* (DBGU) COMM_TX Interrupt */ +#define AT91C_US_COMM_RX ((unsigned int) 0x1 << 31) /* (DBGU) COMM_RX Interrupt */ + +/* -------- DBGU_CR : (DBGU Offset: 0x0) Debug Unit Control Register -------- */ +#define AT91C_US_RSTRX ((unsigned int) 0x1 << 2) /* (DBGU) Reset Receiver */ +#define AT91C_US_RSTTX ((unsigned int) 0x1 << 3) /* (DBGU) Reset Transmitter */ +#define AT91C_US_RXEN ((unsigned int) 0x1 << 4) /* (DBGU) Receiver Enable */ +#define AT91C_US_RXDIS ((unsigned int) 0x1 << 5) /* (DBGU) Receiver Disable */ +#define AT91C_US_TXEN ((unsigned int) 0x1 << 6) /* (DBGU) Transmitter Enable */ +#define AT91C_US_TXDIS ((unsigned int) 0x1 << 7) /* (DBGU) Transmitter Disable */ + +#define AT91C_US_CLKS_CLOCK ((unsigned int) 0x0 << 4) /* (USART) Clock */ +#define AT91C_US_CHRL_8_BITS ((unsigned int) 0x3 << 6) /* (USART) Character Length: 8 bits */ +#define AT91C_US_PAR_NONE ((unsigned int) 0x4 << 9) /* (DBGU) No Parity */ +#define AT91C_US_NBSTOP_1_BIT ((unsigned int) 0x0 << 12) /* (USART) 1 stop bit */ + +#define AT91C_PMC_PCER ((AT91_REG *) 0xFFFFFC10) /* (PMC) Peripheral Clock Enable Register */ +#define AT91C_PIOA_PDR ((AT91_REG *) 0xFFFFF404) /* (PIOA) PIO Disable Register */ +#define AT91C_PIO_PA30 ((unsigned int) 1 << 30) /* Pin Controlled by PA30 */ +#define AT91C_PIO_PC0 ((unsigned int) 1 << 0) /* Pin Controlled by PC0 */ +#define AT91C_PC0_BFCK ((unsigned int) AT91C_PIO_PC0) /* Burst Flash Clock */ +#define AT91C_PA30_DRXD ((unsigned int) AT91C_PIO_PA30) /* DBGU Debug Receive Data */ +#define AT91C_PIO_PA31 ((unsigned int) 1 << 31) /* Pin Controlled by PA31 */ +#define AT91C_PA31_DTXD ((unsigned int) AT91C_PIO_PA31) /* DBGU Debug Transmit Data */ + +#define AT91C_ID_SYS ((unsigned int) 1) /* System Peripheral */ +#define AT91C_ID_TC0 ((unsigned int) 17) /* Timer Counter 0 */ +#define AT91C_ID_EMAC ((unsigned int) 24) /* Ethernet MAC */ + +#define AT91C_PIO_PC1 ((unsigned int) 1 << 1) /* Pin Controlled by PC1 */ +#define AT91C_PC1_BFRDY_SMOE ((unsigned int) AT91C_PIO_PC1) /* Burst Flash Ready */ +#define AT91C_PIO_PC3 ((unsigned int) 1 << 3) /* Pin Controlled by PC3 */ +#define AT91C_PC3_BFBAA_SMWE ((unsigned int) AT91C_PIO_PC3) /* Burst Flash Address Advance / SmartMedia Write Enable */ +#define AT91C_PIO_PC2 ((unsigned int) 1 << 2) /* Pin Controlled by PC2 */ +#define AT91C_PC2_BFAVD ((unsigned int) AT91C_PIO_PC2) /* Burst Flash Address Valid */ +#define AT91C_PIO_PB1 ((unsigned int) 1 << 1) /* Pin Controlled by PB1 */ + +#define AT91C_TC_TIMER_DIV1_CLOCK ((unsigned int) 0x0 << 0) /* (TC) MCK/2 */ +#define AT91C_TC_TIMER_DIV2_CLOCK ((unsigned int) 0x1 << 0) /* (TC) MCK/8 */ +#define AT91C_TC_TIMER_DIV3_CLOCK ((unsigned int) 0x2 << 0) /* (TC) MCK/32 */ +#define AT91C_TC_TIMER_DIV4_CLOCK ((unsigned int) 0x3 << 0) /* (TC) MCK/128 */ +#define AT91C_TC_SLOW_CLOCK ((unsigned int) 0x4 << 0) /* (TC) SLOW CLK */ +#define AT91C_TC_XC0_CLOCK ((unsigned int) 0x5 << 0) /* (TC) XC0 */ +#define AT91C_TC_XC1_CLOCK ((unsigned int) 0x6 << 0) /* (TC) XC1 */ +#define AT91C_TC_XC2_CLOCK ((unsigned int) 0x7 << 0) /* (TC) XC2 */ +#define AT91C_TCB_TC0XC0S_NONE ((unsigned int) 0x1) /* (TCB) None signal connected to XC0 */ +#define AT91C_TCB_TC1XC1S_NONE ((unsigned int) 0x1 << 2) /* (TCB) None signal connected to XC1 */ +#define AT91C_TCB_TC2XC2S_NONE ((unsigned int) 0x1 << 4) /* (TCB) None signal connected to XC2 */ +#define AT91C_TC_CLKDIS ((unsigned int) 0x1 << 1) /* (TC) Counter Clock Disable Command */ +#define AT91C_TC_SWTRG ((unsigned int) 0x1 << 2) /* (TC) Software Trigger Command */ +#define AT91C_TC_CLKEN ((unsigned int) 0x1 << 0) /* (TC) Counter Clock Enable Command */ + +#define AT91C_EMAC_BNQ ((unsigned int) 0x1 << 4) /* (EMAC) */ +#define AT91C_EMAC_COMP ((unsigned int) 0x1 << 5) /* (EMAC) */ +#define AT91C_EMAC_REC ((unsigned int) 0x1 << 1) /* (EMAC) */ +#define AT91C_EMAC_RE ((unsigned int) 0x1 << 2) /* (EMAC) Receive enable. */ +#define AT91C_EMAC_TE ((unsigned int) 0x1 << 3) /* (EMAC) Transmit enable. */ +#define AT91C_EMAC_CLK ((unsigned int) 0x3 << 10) /* (EMAC) */ +#define AT91C_EMAC_RMII ((unsigned int) 0x1 << 13) /* (EMAC) */ +#define AT91C_EMAC_NBC ((unsigned int) 0x1 << 5) /* (EMAC) No broadcast. */ +#define AT91C_EMAC_CAF ((unsigned int) 0x1 << 4) /* (EMAC) Copy all frames. */ +#define AT91C_EMAC_BNA ((unsigned int) 0x1 << 0) /* (EMAC) */ +#define AT91C_EMAC_REC ((unsigned int) 0x1 << 1) /* (EMAC) */ +#define AT91C_EMAC_RSR_OVR ((unsigned int) 0x1 << 2) /* (EMAC) */ +#define AT91C_EMAC_CSR ((unsigned int) 0x1 << 5) /* (EMAC) Clear statistics registers. */ +#define AT91C_EMAC_SPD ((unsigned int) 0x1 << 0) /* (EMAC) Speed. */ +#define AT91C_EMAC_FD ((unsigned int) 0x1 << 1) /* (EMAC) Full duplex. */ +#define AT91C_EMAC_LINK ((unsigned int) 0x1 << 0) /* (EMAC) */ +#define AT91C_EMAC_MPE ((unsigned int) 0x1 << 4) /* (EMAC) Management port enable. */ +#define AT91C_PIO_PA16 ((unsigned int) 1 << 16) /* Pin Controlled by PA16 */ +#define AT91C_PA16_EMDIO ((unsigned int) AT91C_PIO_PA16) /* Ethernet MAC Management Data Input/Output */ +#define AT91C_PIO_PA15 ((unsigned int) 1 << 15) /* Pin Controlled by PA15 */ +#define AT91C_PA15_EMDC ((unsigned int) AT91C_PIO_PA15) /* Ethernet MAC Management Data Clock */ +#define AT91C_PIO_PA14 ((unsigned int) 1 << 14) /* Pin Controlled by PA14 */ +#define AT91C_PA14_ERXER ((unsigned int) AT91C_PIO_PA14) /* Ethernet MAC Receive Error */ +#define AT91C_PIO_PA13 ((unsigned int) 1 << 13) /* Pin Controlled by PA13 */ +#define AT91C_PA13_ERX1 ((unsigned int) AT91C_PIO_PA13) /* Ethernet MAC Receive Data 1 */ +#define AT91C_PIO_PA12 ((unsigned int) 1 << 12) /* Pin Controlled by PA12 */ +#define AT91C_PA12_ERX0 ((unsigned int) AT91C_PIO_PA12) /* Ethernet MAC Receive Data 0 */ +#define AT91C_PIO_PA11 ((unsigned int) 1 << 11) /* Pin Controlled by PA11 */ +#define AT91C_PA11_ECRS_ECRSDV ((unsigned int) AT91C_PIO_PA11) /* Ethernet MAC Carrier Sense/Carrier Sense and Data Valid */ +#define AT91C_PIO_PA10 ((unsigned int) 1 << 10) /* Pin Controlled by PA10 */ +#define AT91C_PA10_ETX1 ((unsigned int) AT91C_PIO_PA10) /* Ethernet MAC Transmit Data 1 */ +#define AT91C_PIO_PA9 ((unsigned int) 1 << 9) /* Pin Controlled by PA9 */ +#define AT91C_PA9_ETX0 ((unsigned int) AT91C_PIO_PA9) /* Ethernet MAC Transmit Data 0 */ +#define AT91C_PIO_PA8 ((unsigned int) 1 << 8) /* Pin Controlled by PA8 */ +#define AT91C_PA8_ETXEN ((unsigned int) AT91C_PIO_PA8) /* Ethernet MAC Transmit Enable */ +#define AT91C_PIO_PA7 ((unsigned int) 1 << 7) /* Pin Controlled by PA7 */ +#define AT91C_PA7_ETXCK_EREFCK ((unsigned int) AT91C_PIO_PA7) /* Ethernet MAC Transmit Clock/Reference Clock */ +#define AT91C_PIO_PB25 ((unsigned int) 1 << 25) /* Pin Controlled by PB25 */ +#define AT91C_PB25_DSR1 ((unsigned int) AT91C_PIO_PB25) /* USART 1 Data Set ready */ +#define AT91C_PB25_EF100 ((unsigned int) AT91C_PIO_PB25) /* Ethernet MAC Force 100 Mbits */ +#define AT91C_PIO_PB19 ((unsigned int) 1 << 19) /* Pin Controlled by PB19 */ +#define AT91C_PB19_DTR1 ((unsigned int) AT91C_PIO_PB19) /* USART 1 Data Terminal ready */ +#define AT91C_PB19_ERXCK ((unsigned int) AT91C_PIO_PB19) /* Ethernet MAC Receive Clock */ +#define AT91C_PIO_PB18 ((unsigned int) 1 << 18) /* Pin Controlled by PB18 */ +#define AT91C_PB18_RI1 ((unsigned int) AT91C_PIO_PB18) /* USART 1 Ring Indicator */ +#define AT91C_PB18_ECOL ((unsigned int) AT91C_PIO_PB18) /* Ethernet MAC Collision Detected */ +#define AT91C_PIO_PB17 ((unsigned int) 1 << 17) /* Pin Controlled by PB17 */ +#define AT91C_PB17_RF2 ((unsigned int) AT91C_PIO_PB17) /* SSC Receive Frame Sync 2 */ +#define AT91C_PB17_ERXDV ((unsigned int) AT91C_PIO_PB17) /* Ethernet MAC Receive Data Valid */ +#define AT91C_PIO_PB16 ((unsigned int) 1 << 16) /* Pin Controlled by PB16 */ +#define AT91C_PB16_RK2 ((unsigned int) AT91C_PIO_PB16) /* SSC Receive Clock 2 */ +#define AT91C_PB16_ERX3 ((unsigned int) AT91C_PIO_PB16) /* Ethernet MAC Receive Data 3 */ +#define AT91C_PIO_PB15 ((unsigned int) 1 << 15) /* Pin Controlled by PB15 */ +#define AT91C_PB15_RD2 ((unsigned int) AT91C_PIO_PB15) /* SSC Receive Data 2 */ +#define AT91C_PB15_ERX2 ((unsigned int) AT91C_PIO_PB15) /* Ethernet MAC Receive Data 2 */ +#define AT91C_PIO_PB14 ((unsigned int) 1 << 14) /* Pin Controlled by PB14 */ +#define AT91C_PB14_TD2 ((unsigned int) AT91C_PIO_PB14) /* SSC Transmit Data 2 */ +#define AT91C_PB14_ETXER ((unsigned int) AT91C_PIO_PB14) /* Ethernet MAC Transmikt Coding Error */ +#define AT91C_PIO_PB13 ((unsigned int) 1 << 13) /* Pin Controlled by PB13 */ +#define AT91C_PB13_TK2 ((unsigned int) AT91C_PIO_PB13) /* SSC Transmit Clock 2 */ +#define AT91C_PB13_ETX3 ((unsigned int) AT91C_PIO_PB13) /* Ethernet MAC Transmit Data 3 */ +#define AT91C_PIO_PB12 ((unsigned int) 1 << 12) /* Pin Controlled by PB12 */ +#define AT91C_PB12_TF2 ((unsigned int) AT91C_PIO_PB12) /* SSC Transmit Frame Sync 2 */ +#define AT91C_PB12_ETX2 ((unsigned int) AT91C_PIO_PB12) /* Ethernet MAC Transmit Data 2 */ + +#define AT91C_PIOB_BSR ((AT91_REG *) 0xFFFFF674) /* (PIOB) Select B Register */ +#define AT91C_BASE_EMAC ((AT91PS_EMAC) 0xFFFBC000) /* (EMAC) Base Address */ +#define AT91C_PIOB_PDR ((AT91_REG *) 0xFFFFF604) /* (PIOB) PIO Disable Register */ + +#define AT91C_EBI_CS3A_SMC_SmartMedia ((unsigned int) 0x1 << 3) /* (EBI) Chip Select 3 is assigned to the Static Memory Controller and the SmartMedia Logic is activated. */ +#define AT91C_SMC2_ACSS_STANDARD ((unsigned int) 0x0 << 16) /* (SMC2) Standard, asserted at the beginning of the access and deasserted at the end. */ +#define AT91C_SMC2_DBW_8 ((unsigned int) 0x2 << 13) /* (SMC2) 8-bit. */ +#define AT91C_SMC2_WSEN ((unsigned int) 0x1 << 7) /* (SMC2) Wait State Enable */ +#define AT91C_PIOC_ASR ((AT91_REG *) 0xFFFFF870) /* (PIOC) Select A Register */ + +#define AT91C_BASE_TC0 ((AT91PS_TC) 0xFFFA0000) /* (TC0) Base Address */ +#define AT91C_BASE_DBGU ((AT91PS_DBGU) 0xFFFFF200) /* (DBGU) Base Address */ +#define AT91C_BASE_PIOA ((AT91PS_PIO) 0xFFFFF400) /* (PIOA) Base Address */ +#define AT91C_EBI_CSA ((AT91_REG *) 0xFFFFFF60) /* (EBI) Chip Select Assignment Register */ +#define AT91C_BASE_SMC2 ((AT91PS_SMC2) 0xFFFFFF70) /* (SMC2) Base Address */ +#define AT91C_BASE_US1 ((AT91PS_USART) 0xFFFC4000) /* (US1) Base Address */ +#define AT91C_TCB0_BMR ((AT91_REG *) 0xFFFA00C4) /* (TCB0) TC Block Mode Register */ +#define AT91C_TCB0_BCR ((AT91_REG *) 0xFFFA00C0) /* (TCB0) TC Block Control Register */ +#define AT91C_PIOC_PDR ((AT91_REG *) 0xFFFFF804) /* (PIOC) PIO Disable Register */ +#define AT91C_PIOC_PER ((AT91_REG *) 0xFFFFF800) /* (PIOC) PIO Enable Register */ +#define AT91C_PIOC_ODR ((AT91_REG *) 0xFFFFF814) /* (PIOC) Output Disable Registerr */ +#define AT91C_PIOB_PER ((AT91_REG *) 0xFFFFF600) /* (PIOB) PIO Enable Register */ +#define AT91C_PIOB_ODR ((AT91_REG *) 0xFFFFF614) /* (PIOB) Output Disable Registerr */ +#define AT91C_PIOB_PDSR ((AT91_REG *) 0xFFFFF63C) /* (PIOB) Pin Data Status Register */ +#endif diff --git a/include/asm-ppc/u-boot.h b/include/asm-ppc/u-boot.h index eea9c7c..e417e0d 100644 --- a/include/asm-ppc/u-boot.h +++ b/include/asm-ppc/u-boot.h @@ -68,11 +68,11 @@ typedef struct bd_info { #if defined(CONFIG_HYMOD) hymod_conf_t bi_hymod_conf; /* hymod configuration information */ #endif -#if defined(CONFIG_EVB64260) || defined(CONFIG_PN62) +#if defined(CONFIG_EVB64260) || defined(CONFIG_PN62) || defined(CONFIG_SVM_SC8xx) /* second onboard ethernet port */ unsigned char bi_enet1addr[6]; #endif -#if defined(CONFIG_EVB64260) +#if defined(CONFIG_EVB64260) || defined(CONFIG_SVM_SC8xx) /* third onboard ethernet port */ unsigned char bi_enet2addr[6]; #endif diff --git a/include/cmd_confdefs.h b/include/cmd_confdefs.h index c462c3f..4e7ab9b 100644 --- a/include/cmd_confdefs.h +++ b/include/cmd_confdefs.h @@ -78,6 +78,7 @@ #define CFG_CMD_SPI 0x0000100000000000 /* SPI utility */ #define CFG_CMD_FDOS 0x0000200000000000 /* Floppy DOS support */ #define CFG_CMD_VFD 0x0000400000000000 /* VFD support (TRAB) */ +#define CFG_CMD_NAND 0x0000800000000000 /* NAND support */ #define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFF /* ALL commands */ @@ -106,6 +107,7 @@ CFG_CMD_JFFS2 | \ CFG_CMD_KGDB | \ CFG_CMD_MII | \ + CFG_CMD_NAND | \ CFG_CMD_PCI | \ CFG_CMD_PCMCIA | \ CFG_CMD_REGINFO | \ diff --git a/include/cmd_nand.h b/include/cmd_nand.h new file mode 100644 index 0000000..febb27d --- /dev/null +++ b/include/cmd_nand.h @@ -0,0 +1,55 @@ +/* + * 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 + */ + +/* + * NAND support + */ +#ifndef _CMD_NAND_H +#define _CMD_NAND_H + +#include <common.h> +#include <command.h> + + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +#define CMD_TBL_NAND MK_CMD_TBL_ENTRY( \ + "nand", 3, 5, 1, do_nand, \ + "nand - NAND sub-system\n", \ + "info - show available NAND devices\n" \ + "nand device [dev] - show or set current device\n" \ + "nand read addr off size\n" \ + "nand write addr off size - read/write `size'" \ + " bytes starting at offset `off'\n" \ + " to/from memory address `addr'\n" \ + "nand erase off size - erase `size' bytes of NAND from offset `off'\n" \ +), + +#define CMD_TBL_NANDBOOT MK_CMD_TBL_ENTRY( \ + "nboot", 4, 4, 1, do_nandboot, \ + "nboot - boot from NAND device\n", \ + "loadAddr dev\n" \ +), + +int do_nand (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_nandboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#else +#define CMD_TBL_NAND +#define CMD_TBL_NANDBOOT +#endif + +#endif /* _CMD_NAND_H */ diff --git a/include/commproc.h b/include/commproc.h index 5ff82b7..a7d8dbd 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -1128,6 +1128,57 @@ typedef struct scc_enet { /*** NETVIA *******************************************************/ +/* SinoVee Microsystems SC8xx series FEL8xx-AT,SC823,SC850,SC855T,SC860T */ +#if ( defined CONFIG_SVM_SC8xx ) +# ifndef CONFIG_FEC_ENET + +#define PROFF_ENET PROFF_SCC2 +#define CPM_CR_ENET CPM_CR_CH_SCC2 +#define SCC_ENET 1 + + /* Bits in parallel I/O port registers that have to be set/cleared + * * * * to configure the pins for SCC2 use. + * * * */ +#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */ +#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */ +#define PA_ENET_RCLK ((ushort)0x0400) /* PA 5 */ +#define PA_ENET_TCLK ((ushort)0x0800) /* PA 4 */ + +#define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */ + +#define PC_ENET_CLSN ((ushort)0x0040) /* PC 9 */ +#define PC_ENET_RENA ((ushort)0x0080) /* PC 8 */ +/* Control bits in the SICR to route TCLK (CLK3) and RCLK (CLK1) to + * * * * SCC2. Also, make sure GR2 (bit 16) and SC2 (bit 17) are zero. + * * * */ +#define SICR_ENET_MASK ((uint)0x0000ff00) +#define SICR_ENET_CLKRT ((uint)0x00003700) + +# else /* Use FEC for Fast Ethernet */ + +#undef SCC_ENET +#define FEC_ENET + +#define PD_MII_TXD1 ((ushort)0x1000) /* PD 3 */ +#define PD_MII_TXD2 ((ushort)0x0800) /* PD 4 */ +#define PD_MII_TXD3 ((ushort)0x0400) /* PD 5 */ +#define PD_MII_RX_DV ((ushort)0x0200) /* PD 6 */ +#define PD_MII_RX_ERR ((ushort)0x0100) /* PD 7 */ +#define PD_MII_RX_CLK ((ushort)0x0080) /* PD 8 */ +#define PD_MII_TXD0 ((ushort)0x0040) /* PD 9 */ +#define PD_MII_RXD0 ((ushort)0x0020) /* PD 10 */ +#define PD_MII_TX_ERR ((ushort)0x0010) /* PD 11 */ +#define PD_MII_MDC ((ushort)0x0008) /* PD 12 */ +#define PD_MII_RXD1 ((ushort)0x0004) /* PD 13 */ +#define PD_MII_RXD2 ((ushort)0x0002) /* PD 14 */ +#define PD_MII_RXD3 ((ushort)0x0001) /* PD 15 */ + +#define PD_MII_MASK ((ushort)0x1FFF) /* PD 3...15 */ + +# endif /* CONFIG_FEC_ENET */ +#endif /* CONFIG_SVM_SC8xx */ + + #if defined(CONFIG_NETVIA) /* Bits in parallel I/O port registers that have to be set/cleared * to configure the pins for SCC2 use. diff --git a/include/configs/at91rm9200dk.h b/include/configs/at91rm9200dk.h new file mode 100644 index 0000000..6315f0a --- /dev/null +++ b/include/configs/at91rm9200dk.h @@ -0,0 +1,153 @@ +/* + * Rick Bronson <rick@efn.org> + * + * Configuation settings for the AT91RM9200DK board. + * + * 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 + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* ARM asynchronous clock */ +#define AT91C_MAIN_CLOCK 179712000 /* from 18.432 MHz crystal (18432000 / 4 * 39) */ +#define AT91C_MASTER_CLOCK 59904000 /* peripheral clock (AT91C_MASTER_CLOCK / 3) */ + +#define CONFIG_AT91RM9200DK 1 /* on an AT91RM9200DK Board */ +#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 +/* + * Size of malloc() pool + */ +#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024) +#define CONFIG_BAUDRATE 115200 +/* + * Hardware drivers + */ + +/* + * select serial console configuration + */ +#define CONFIG_SERIAL3 1 /* we use SERIAL 3 */ + +#undef CONFIG_HWFLOW /* don't include RTS/CTS flow control support */ + +#undef CONFIG_MODEM_SUPPORT /* disable modem initialization stuff */ + +#define CONFIG_COMMANDS \ + (CONFIG_CMD_DFL | \ + CFG_CMD_DHCP | \ + CFG_CMD_NAND ) +/* CFG_CMD_EEPROM | \ might consider these + CFG_CMD_I2C | \ + CFG_CMD_USB | \ + CFG_CMD_MII | \ + CFG_CMD_SDRAM | \ */ +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define SECTORSIZE 512 + +#define ADDR_COLUMN 1 +#define ADDR_PAGE 2 +#define ADDR_COLUMN_PAGE 3 + +#define NAND_ChipID_UNKNOWN 0x00 +#define NAND_MAX_FLOORS 1 +#define NAND_MAX_CHIPS 1 + +#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */ +#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */ + +#define NAND_DISABLE_CE(nand) do { *AT91C_PIOC_SODR = AT91C_PIO_PC0;} while(0) +#define NAND_ENABLE_CE(nand) do { *AT91C_PIOC_CODR = AT91C_PIO_PC0;} while(0) + +#define NAND_WAIT_READY(nand) while (!(*AT91C_PIOC_PDSR & AT91C_PIO_PC2)) + +#define WRITE_NAND_COMMAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_CLE) = (__u8)(d); } while(0) +#define WRITE_NAND_ADDRESS(d, adr) do{ *(volatile __u8 *)((unsigned long)adr | AT91_SMART_MEDIA_ALE) = (__u8)(d); } while(0) +#define WRITE_NAND(d, adr) do{ *(volatile __u8 *)((unsigned long)adr) = (__u8)d; } while(0) +#define READ_NAND(adr) ((volatile unsigned char)(*(volatile __u8 *)(unsigned long)adr)) +/* the following are NOP's in our implementation */ +#define NAND_CTL_CLRALE(nandptr) +#define NAND_CTL_SETALE(nandptr) +#define NAND_CTL_CLRCLE(nandptr) +#define NAND_CTL_SETCLE(nandptr) + +#define CONFIG_NR_DRAM_BANKS 1 +#define PHYS_SDRAM 0x20000000 +#define PHYS_SDRAM_SIZE 0x2000000 /* 32 megs */ + +#define CFG_MEMTEST_START PHYS_SDRAM +#define CFG_MEMTEST_END CFG_MEMTEST_START + PHYS_SDRAM_SIZE - 262144 + +#define CONFIG_DRIVER_ETHER + +#define PHYS_FLASH_1 0x10000000 +#define PHYS_FLASH_SIZE 0x200000 /* 2 megs main flash */ +#define CFG_FLASH_BASE PHYS_FLASH_1 +#define CFG_MAX_FLASH_BANKS 1 +#define CFG_MAX_FLASH_SECT 40 +#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */ +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0xe000) +#define CFG_ENV_SIZE 0x2000 +#define CFG_LOAD_ADDR 0x21000000 /* default load address */ + +#define CFG_BAUDRATE_TABLE {115200 , 19200, 38400, 57600, 9600 } + +#define CFG_PROMPT "Uboot> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ + +#ifndef __ASSEMBLY__ +/*----------------------------------------------------------------------- + * Board specific extension for bd_info + * + * This structure is embedded in the global bd_info (bd_t) structure + * and can be used by the board specific code (eg board/...) + */ + +struct bd_info_ext +{ + /* helper variable for board environment handling + * + * env_crc_valid == 0 => uninitialised + * env_crc_valid > 0 => environment crc in flash is valid + * env_crc_valid < 0 => environment crc in flash is invalid + */ + int env_crc_valid; +}; +#endif + +#define CFG_HZ AT91C_MASTER_CLOCK/2 /* AT91C_TC0_CMR is implicitly set to + AT91C_TC_TIMER_DIV1_CLOCK */ + +#define CONFIG_STACKSIZE (32*1024) /* regular stack */ + +#ifdef CONFIG_USE_IRQ +#error CONFIG_USE_IRQ not supported +#endif + +#endif diff --git a/include/configs/dnp1110.h b/include/configs/dnp1110.h index 5a7642b..8594e65 100644 --- a/include/configs/dnp1110.h +++ b/include/configs/dnp1110.h @@ -76,7 +76,7 @@ #define CONFIG_NETMASK 255.255.0.0 #define CONFIG_IPADDR 172.22.2.23 #define CONFIG_SERVERIP 172.22.2.22 -#define CONFIG_BOOTFILE "elinos-dnp1110" +#define CONFIG_BOOTFILE "dnp1110" #define CONFIG_BOOTCOMMAND "tftp; bootm" #if (CONFIG_COMMANDS & CFG_CMD_KGDB) @@ -128,21 +128,23 @@ #define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ #define PHYS_FLASH_SIZE 0x01000000 /* 16 MB */ +#define PHYS_FLASH_BANK_SIZE 0x01000000 /* 32 MB Banks */ +#define PHYS_FLASH_SECT_SIZE 0x00020000 /* 256 KB sectors (x2) */ #define CFG_FLASH_BASE PHYS_FLASH_1 /*----------------------------------------------------------------------- * FLASH and environment organization */ -#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ -#define CFG_MAX_FLASH_SECT (31+8) /* max number of sectors on one chip */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 128 /* max number of sectors on one chip */ /* timeout values are in ticks */ #define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */ #define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */ #define CFG_ENV_IS_IN_FLASH 1 -#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x1C000) /* Addr of Environment Sector */ -#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0xF80000) /* Addr of Environment Sector */ +#define CFG_ENV_SIZE 0x20000 /* Total Size of Environment Sector */ #endif /* __CONFIG_H */ diff --git a/include/configs/svm_sc8xx.h b/include/configs/svm_sc8xx.h new file mode 100644 index 0000000..b46b0be --- /dev/null +++ b/include/configs/svm_sc8xx.h @@ -0,0 +1,470 @@ +/* + * (C) Copyright 2000, 2001, 2002 + * 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 + */ + +/* + * board/config.h - configuration options, board specific, + * for SinoVee Microsystems SC8xx series SBC + * http://www.fel.com.cn (Chinese) + * http://www.sinovee.com (English) + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* Custom configuration */ +/* SC823,SC850,SC860SAR, FEL8xx-AT(823/850/860) */ +/* SC85T,SC860T, FEL8xx-AT(855T/860T) */ +/*#define CONFIG_FEL8xx_AT */ +/*#define CONFIG_LCD */ +/* if core > 50MHz , un-comment CONFIG_BUS_DIV2 */ +/* #define CONFIG_50MHz */ +/* #define CONFIG_66MHz */ +/* #define CONFIG_75MHz */ +#define CONFIG_80MHz +/*#define CONFIG_100MHz */ +/* #define CONFIG_BUS_DIV2 1 */ +/* for BOOT device port size */ +/* #define CONFIG_BOOT_8B */ +#define CONFIG_BOOT_16B +/* #define CONFIG_BOOT_32B */ +/* #define CONFIG_CAN_DRIVER */ +/* #define DEBUG */ +#define CONFIG_FEC_ENET + +/* #define CONFIG_SDRAM_16M */ +#define CONFIG_SDRAM_32M +/* #define CONFIG_SDRAM_64M */ +#define CFG_RESET_ADDRESS 0xffffffff +/* + * High Level Configuration Options + * (easy to change) + */ + +/* #define CONFIG_MPC823 1 */ +/* #define CONFIG_MPC850 1 */ +#define CONFIG_MPC855 1 +/* #define CONFIG_MPC860 1 */ +/* #define CONFIG_MPC860T 1 */ + +#undef CONFIG_WATCHDOG /* watchdog */ + +#define CONFIG_SVM_SC8xx 1 /* ...on SVM SC8xx series */ + +#ifdef CONFIG_LCD /* with LCD controller ? */ +/* #define CONFIG_NEC_NL6648BC20 1 / * use NEC NL6648BC20 display */ +#endif + +#define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */ +#undef CONFIG_8xx_CONS_SMC2 +#undef CONFIG_8xx_CONS_NONE +#define CONFIG_BAUDRATE 19200 /* console baudrate = 115kbps */ +#if 0 +#define CONFIG_BOOTDELAY -1 /* autoboot disabled */ +#else +#define CONFIG_BOOTDELAY 1 /* autoboot after 5 seconds */ +#endif + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_BOARD_TYPES 1 /* support board types */ + +#define CONFIG_PREBOOT "echo;echo Welcome to U-Boot SVM port;echo;echo Type \"? or help\" to get on-line help;echo" + +#undef CONFIG_BOOTARGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfsargs=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "ramargs=setenv bootargs root=/dev/ram rw\0" \ + "addip=setenv bootargs $(bootargs) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask)" \ + ":$(hostname):$(netdev):off panic=1\0" \ + "flash_nfs=run nfsargs addip;" \ + "bootm $(kernel_addr)\0" \ + "flash_self=run ramargs addip;" \ + "bootm $(kernel_addr) $(ramdisk_addr)\0" \ + "net_nfs=tftp 0x210000 $(bootfile);run nfsargs addip;bootm\0" \ + "rootpath=/opt/sinovee/ppc8xx-linux-2.0/target\0" \ + "bootfile=pImage-sc855t\0" \ + "kernel_addr=48000000\0" \ + "ramdisk_addr=48100000\0" \ + "" +#define CONFIG_BOOTCOMMAND \ + "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ + "tftpboot 0x210000 pImage-sc855t;bootm 0x210000" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ + + +#ifdef CONFIG_LCD +# undef CONFIG_STATUS_LED /* disturbs display */ +#else +# define CONFIG_STATUS_LED 1 /* Status LED enabled */ +#endif /* CONFIG_LCD */ + +#undef CONFIG_CAN_DRIVER /* CAN Driver support disabled */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DHCP | \ + CFG_CMD_DOC | \ +/* CFG_CMD_IDE |*/ \ + CFG_CMD_DATE ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +/*----------------------------------------------------------------------- + * Internal Memory Mapped Register + */ +#define CFG_IMMR 0xFF000000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR CFG_IMMR +#define CFG_INIT_RAM_END 0x2F00 /* End of used area in DPRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0x40000000 +#define CFG_MONITOR_LEN (384 << 10) /* Reserve 192 kB for Monitor */ +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 67 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_ENV_IS_IN_FLASH 1 + +#ifdef CONFIG_BOOT_8B +#define CFG_ENV_OFFSET 0x10000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ +#elif defined (CONFIG_BOOT_16B) +#define CFG_ENV_OFFSET 0x10000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */ +#elif defined (CONFIG_BOOT_32B) +#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +#endif + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_OFFSET_REDUND (CFG_ENV_OFFSET+CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) + + +/*----------------------------------------------------------------------- + * Hardware Information Block + */ +#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */ +#define CFG_HWINFO_SIZE 0x00000040 /* size of HW Info block */ +#define CFG_HWINFO_MAGIC 0x46454C38 /* 'SVM8' */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 4 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * SYPCR - System Protection Control 11-9 + * SYPCR can only be written once after reset! + *----------------------------------------------------------------------- + * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze + */ +#if defined(CONFIG_WATCHDOG) +/*#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ + SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) +*/ +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_SWF | \ + SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) +#else +#define CFG_SYPCR 0xffffff88 +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration 11-6 + *----------------------------------------------------------------------- + * PCMCIA config., multi-function pin tri-state + */ +#ifndef CONFIG_CAN_DRIVER +/*#define CFG_SIUMCR 0x00610c00 */ +#define CFG_SIUMCR 0x00000000 +#else /* we must activate GPL5 in the SIUMCR for CAN */ +#define CFG_SIUMCR (SIUMCR_DBGC11 | SIUMCR_DBPC00 | SIUMCR_MLRC01) +#endif /* CONFIG_CAN_DRIVER */ + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control 11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freezing enabled + */ +#define CFG_TBSCR 0x0001 + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register 11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC 0x00c3 + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control 11-31 + *----------------------------------------------------------------------- + * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled + */ +#define CFG_PISCR 0x0000 + +/*----------------------------------------------------------------------- + * PLPRCR - PLL, Low-Power, and Reset Control Register 15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit + */ +#if defined (CONFIG_100MHz) +#define CFG_PLPRCR 0x06301000 +#define CONFIG_8xx_GCLK_FREQ 100000000 +#elif defined (CONFIG_80MHz) +#define CFG_PLPRCR 0x04f01000 +#define CONFIG_8xx_GCLK_FREQ 80000000 +#elif defined(CONFIG_75MHz) +#define CFG_PLPRCR 0x04a00100 +#define CONFIG_8xx_GCLK_FREQ 75000000 +#elif defined(CONFIG_66MHz) +#define CFG_PLPRCR 0x04101000 +#define CONFIG_8xx_GCLK_FREQ 66000000 +#elif defined(CONFIG_50MHz) +#define CFG_PLPRCR 0x03101000 +#define CONFIG_8xx_GCLK_FREQ 50000000 +#endif + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register 15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK SCCR_EBDF11 +#ifdef CONFIG_BUS_DIV2 +#define CFG_SCCR 0x02020000 | SCCR_RTSEL +#else /* up to 50 MHz we use a 1:1 clock */ +#define CFG_SCCR 0x02000000 | SCCR_RTSEL +#endif + +/*----------------------------------------------------------------------- + * PCMCIA stuff + *----------------------------------------------------------------------- + * + */ +#define CFG_PCMCIA_MEM_ADDR (0xE0000000) +#define CFG_PCMCIA_MEM_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_DMA_ADDR (0xE4000000) +#define CFG_PCMCIA_DMA_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_ATTRB_ADDR (0xE8000000) +#define CFG_PCMCIA_ATTRB_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_IO_ADDR (0xEC000000) +#define CFG_PCMCIA_IO_SIZE ( 64 << 20 ) + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#undef CONFIG_IDE_8xx_PCCARD /* Use IDE with PC Card Adapter */ + +#define CONFIG_IDE_8xx_DIRECT 1 /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE 1 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_BASE_ADDR 0xFE100010 +#define CFG_ATA_IDE0_OFFSET 0x0000 +/*#define CFG_ATA_IDE1_OFFSET 0x0C00 */ +#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O + */ +#define CFG_ATA_REG_OFFSET 0x0200 /* Offset for normal register accesses + */ +#define CFG_ATA_ALT_OFFSET 0x0210 /* Offset for alternate registers + */ +#define CONFIG_ATAPI +#define CFG_PIO_MODE 0 + +/*----------------------------------------------------------------------- + * + *----------------------------------------------------------------------- + * + */ +/*#define CFG_DER 0x2002000F*/ +#define CFG_DER 0x0 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0x40000000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0x60000000 /* FLASH bank #0 */ + +/* used to re-map FLASH both when starting from SRAM or FLASH: + * restrict access enough to keep SRAM working (if any) + * but not too much to meddle with FLASH accesses + */ +#define CFG_REMAP_OR_AM 0x80000000 /* OR addr mask */ +#define CFG_PRELIM_OR_AM 0xE0000000 /* OR addr mask */ + +/* + * FLASH timing: + */ +#if defined(CONFIG_100MHz) +#define CFG_OR_TIMING_FLASH 0x000002f4 +#define CFG_OR_TIMING_DOC 0x000002f4 +#define CFG_MxMR_PTx 0x61000000 +#define CFG_MPTPR 0x400 + +#elif defined(CONFIG_80MHz) +#define CFG_OR_TIMING_FLASH 0x00000ff4 +#define CFG_OR_TIMING_DOC 0x000001f4 +#define CFG_MxMR_PTx 0x4e000000 +#define CFG_MPTPR 0x400 + +#elif defined(CONFIG_75MHz) +#define CFG_OR_TIMING_FLASH 0x000008f4 +#define CFG_OR_TIMING_DOC 0x000002f4 +#define CFG_MxMR_PTx 0x49000000 +#define CFG_MPTPR 0x400 + +#elif defined(CONFIG_66MHz) +#define CFG_OR_TIMING_FLASH (OR_ACS_DIV1 | OR_TRLX | OR_CSNT_SAM | \ + OR_SCY_3_CLK | OR_EHTR | OR_BI) +/*#define CFG_OR_TIMING_FLASH 0x000001f4 */ +#define CFG_OR_TIMING_DOC 0x000003f4 +#define CFG_MxMR_PTx 0x40000000 +#define CFG_MPTPR 0x400 + +#else /* 50 MHz */ +#define CFG_OR_TIMING_FLASH 0x00000ff4 +#define CFG_OR_TIMING_DOC 0x000001f4 +#define CFG_MxMR_PTx 0x30000000 +#define CFG_MPTPR 0x400 +#endif /*CONFIG_??MHz */ + + +#if defined (CONFIG_BOOT_8B) /* 512K X 8 ,29F040 , 2MB space */ +#define CFG_OR0_PRELIM (0xffe00000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V | BR_PS_8) +#elif defined (CONFIG_BOOT_16B) /* 29lv160 X 16 , 4MB space */ +#define CFG_OR0_PRELIM (0xffc00000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V | BR_PS_16) +#elif defined( CONFIG_BOOT_32B ) /* 29lv160 X 2 X 32, 4/8/16MB , 64MB space */ +#define CFG_OR0_PRELIM (0xfc000000 | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V ) +#else +#error Boot device port size missing. +#endif + +/* + * Disk-On-Chip configuration + */ + +#define CFG_DOC_SHORT_TIMEOUT +#define CFG_MAX_DOC_DEVICE 1 /* Max number of DOC devices */ + +#define CFG_DOC_SUPPORT_2000 +#define CFG_DOC_SUPPORT_MILLENNIUM +#define CFG_DOC_BASE 0x80000000 + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/flash.h b/include/flash.h index b4c8bad..b7f13d3 100644 --- a/include/flash.h +++ b/include/flash.h @@ -105,6 +105,7 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot); #define AMD_MANUFACT 0x00010001 /* AMD manuf. ID in D23..D16, D7..D0 */ #define FUJ_MANUFACT 0x00040004 /* FUJITSU manuf. ID in D23..D16, D7..D0 */ +#define ATM_MANUFACT 0x001F001F /* ATMEL */ #define STM_MANUFACT 0x00200020 /* STM (Thomson) manuf. ID in D23.. -"- */ #define SST_MANUFACT 0x00BF00BF /* SST manuf. ID in D23..D16, D7..D0 */ #define MT_MANUFACT 0x00890089 /* MT manuf. ID in D23..D16, D7..D0 */ @@ -156,6 +157,8 @@ extern int flash_real_protect(flash_info_t *info, long sector, int prot); #define AMD_ID_DL640 0x227E227E /* 29DL640D ID (64 M, dual boot sectors)*/ #define AMD_ID_LV640U 0x22D722D7 /* 29LV640U ID (64 M, uniform sectors) */ +#define ATM_ID_BV1614 0x000000C0 /* 49BV1614 ID */ + #define FUJI_ID_29F800BA 0x22582258 /* MBM29F800BA ID (8M) */ #define FUJI_ID_29F800TA 0x22D622D6 /* MBM29F800TA ID (8M) */ diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index a3a7ec3..4425187 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -1,10 +1,11 @@ /* - * u-boot/include/linux/mtd/nand.h + * linux/include/linux/mtd/nand.h * * Copyright (c) 2000 David Woodhouse <dwmw2@mvhi.com> * Steven J. Hill <sjhill@cotw.com> + * Thomas Gleixner <gleixner@autronix.de> * - * $Id: nand.h,v 1.8 2000/10/30 17:16:17 sjhill Exp $ + * $Id: nand.h,v 1.13 2002/04/28 13:40:41 gleixner Exp $ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -23,6 +24,14 @@ * bat later if I did something naughty. * 10-11-2000 SJH Added private NAND flash structure for driver * 10-24-2000 SJH Added prototype for 'nand_scan' function + * 10-29-2001 TG changed nand_chip structure to support + * hardwarespecific function for accessing control lines + * 02-21-2002 TG added support for different read/write adress and + * ready/busy line access function + * 02-26-2002 TG added chip_delay to nand_chip structure to optimize + * command delay times for different chips + * 04-28-2002 TG OOB config defines moved from nand.c to avoid duplicate + * defines in jffs2/wbuf.c */ #ifndef __LINUX_MTD_NAND_H #define __LINUX_MTD_NAND_H @@ -42,6 +51,82 @@ #define NAND_CMD_RESET 0xff /* + * Enumeration for NAND flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING +} nand_state_t; + + +/* + * NAND Private Flash Chip Data + * + * Structure overview: + * + * IO_ADDR - address to access the 8 I/O lines of the flash device + * + * hwcontrol - hardwarespecific function for accesing control-lines + * + * dev_ready - hardwarespecific function for accesing device ready/busy line + * + * chip_lock - spinlock used to protect access to this structure + * + * wq - wait queue to sleep on if a NAND operation is in progress + * + * state - give the current state of the NAND device + * + * page_shift - number of address bits in a page (column address bits) + * + * data_buf - data buffer passed to/from MTD user modules + * + * data_cache - data cache for redundant page access and shadow for + * ECC failure + * + * ecc_code_buf - used only for holding calculated or read ECCs for + * a page read or written when ECC is in use + * + * reserved - padding to make structure fall on word boundary if + * when ECC is in use + */ +struct Nand { + char floor, chip; + unsigned long curadr; + unsigned char curmode; + /* Also some erase/write/pipeline info when we get that far */ +}; + +struct nand_chip { + int page_shift; + u_char *data_buf; + u_char *data_cache; + int cache_page; + u_char ecc_code_buf[6]; + u_char reserved[2]; + char ChipID; /* Type of DiskOnChip */ + struct Nand *chips; + int chipshift; + char* chips_name; + unsigned long erasesize; + unsigned long mfr; /* Flash IDs - only one type of flash per device */ + unsigned long id; + char* name; + struct NFTLrecord nftl; + int nftl_found; + int numchips; + char page256; + char pageadrlen; + unsigned long IO_ADDR; /* address to access the 8 I/O lines to the flash device */ + unsigned long totlen; + uint oobblock; // Size of OOB blocks (e.g. 512) + uint oobsize; // Amount of OOB data per block (e.g. 16) + uint eccsize; +}; + +/* * NAND Flash Manufacturer ID Codes */ #define NAND_MFR_TOSHIBA 0x98 @@ -84,4 +169,30 @@ struct nand_flash_dev { unsigned long erasesize; }; +/* +* Constants for oob configuration +*/ +#define NAND_NOOB_ECCPOS0 0 +#define NAND_NOOB_ECCPOS1 1 +#define NAND_NOOB_ECCPOS2 2 +#define NAND_NOOB_ECCPOS3 3 +#define NAND_NOOB_ECCPOS4 4 +#define NAND_NOOB_ECCPOS5 5 +#define NAND_NOOB_BADBPOS -1 +#define NAND_NOOB_ECCVPOS -1 + +#define NAND_JFFS2_OOB_ECCPOS0 0 +#define NAND_JFFS2_OOB_ECCPOS1 1 +#define NAND_JFFS2_OOB_ECCPOS2 2 +#define NAND_JFFS2_OOB_ECCPOS3 3 +#define NAND_JFFS2_OOB_ECCPOS4 6 +#define NAND_JFFS2_OOB_ECCPOS5 7 +#define NAND_JFFS2_OOB_BADBPOS 5 +#define NAND_JFFS2_OOB_ECCVPOS 4 + +#define NAND_JFFS2_OOB8_FSDAPOS 6 +#define NAND_JFFS2_OOB16_FSDAPOS 8 +#define NAND_JFFS2_OOB8_FSDALEN 2 +#define NAND_JFFS2_OOB16_FSDALEN 8 + #endif /* __LINUX_MTD_NAND_H */ diff --git a/include/pcmcia.h b/include/pcmcia.h index beb1c16..16653f3 100644 --- a/include/pcmcia.h +++ b/include/pcmcia.h @@ -48,7 +48,7 @@ # else # define CONFIG_PCMCIA_SLOT_B # endif -#elif defined(CONFIG_TQM8xxL) +#elif defined(CONFIG_TQM8xxL) || defined(CONFIG_SVM_SC8xx) # define CONFIG_PCMCIA_SLOT_B /* The TQM8xxL use SLOT_B */ #elif defined(CONFIG_SPD823TS) /* The SPD8xx use SLOT_B */ # define CONFIG_PCMCIA_SLOT_B diff --git a/include/status_led.h b/include/status_led.h index 369cce2..79d9fb4 100644 --- a/include/status_led.h +++ b/include/status_led.h @@ -269,6 +269,20 @@ void status_led_set (int led, int state); # define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ +#elif defined(CONFIG_SVM_SC8xx) +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00000001 +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + /************************************************************************/ #else # error Status LED configuration missing diff --git a/lib_arm/board.c b/lib_arm/board.c index 244c0b5..828c2f2 100644 --- a/lib_arm/board.c +++ b/lib_arm/board.c @@ -31,6 +31,9 @@ #include <version.h> #include <net.h> +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +void nand_init (void); +#endif const char version_string[] = U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; @@ -227,6 +230,10 @@ void start_armboot (void) mem_malloc_init (_armboot_real_end); #endif /* CONFIG_VFD */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) + nand_init(); /* go init the NAND */ +#endif + /* initialize environment */ env_relocate (); |