From: wdenk Date: Wed, 18 Sep 2002 20:50:34 +0000 (+0000) Subject: * Patch by Scott McNutt, 27 Aug 2002: X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=b88f3b9646a6715a2ddc5b1e4818fe16a1e33972;p=users%2Frw%2Fppcboot.git * Patch by Scott McNutt, 27 Aug 2002: 1. PCI support added (README.ppc440 has some details). 2. SPD DRAM initialization added. 3. Support for Rev B silicon added: -Fixed ethernet (errata: requires MAL bursting disabled) -Fixed corrupted dcrs: fix strap regs & chip reset(errata) -Fixed speed related calculations (Rev B. has addl div by 2) 4. Flash initialization: added delays to prevent timing issues (band-aid) --needs more investigation, but this is in the board-specific code. 5. Fixed do_reset (changed SPRN for 440). 6. Fixed get_tbclk for 440 (used same style as 405gp). 7. Initialized all interrupt vector regs (start.S) 8. Added doc/README.ppc440 * Patch by Keith Outwater, 23 Aug 2002: Added support for generic 860T system (GEN860T). See README in board/gen860t for details. * Patch by Scott McNutt, 20 Aug 2002: initialize the 440 interrupt vector registers (IVORs) and enable the PIT. The PIT is set to interrupt every 10 msec. * Patch by Kenneth Johansson, 19 Aug 2002: add some documentation for jffs2 to make it possible to change the partition with code instead of #defines, usage of a global in jffs2_1pass.c. --- diff --git a/CHANGELOG b/CHANGELOG index f94744a..e4cef16 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -10,6 +10,34 @@ Modifications for 1.2.0: For details about the current modifications, please see README-WIP +* Patch by Scott McNutt, 27 Aug 2002: + 1. PCI support added (README.ppc440 has some details). + 2. SPD DRAM initialization added. + 3. Support for Rev B silicon added: + -Fixed ethernet (errata: requires MAL bursting disabled) + -Fixed corrupted dcrs: fix strap regs & chip reset(errata) + -Fixed speed related calculations (Rev B. has addl div by 2) + 4. Flash initialization: added delays to prevent timing + issues (band-aid) --needs more investigation, but this is + in the board-specific code. + 5. Fixed do_reset (changed SPRN for 440). + 6. Fixed get_tbclk for 440 (used same style as 405gp). + 7. Initialized all interrupt vector regs (start.S) + 8. Added doc/README.ppc440 + +* Patch by Keith Outwater, 23 Aug 2002: + Added support for generic 860T system (GEN860T). See README in + board/gen860t for details. + +* Patch by Scott McNutt, 20 Aug 2002: + initialize the 440 interrupt vector registers (IVORs) and enable + the PIT. The PIT is set to interrupt every 10 msec. + +* Patch by Kenneth Johansson, 19 Aug 2002: + add some documentation for jffs2 to make it possible to change the + partition with code instead of #defines, usage of a global in + jffs2_1pass.c. + * Add support for redundand environment, so the previous settins don't get lost in case of a power failure right during a "saveenv" command. diff --git a/CREDITS b/CREDITS index 784b6ea..2190f9b 100644 --- a/CREDITS +++ b/CREDITS @@ -183,6 +183,10 @@ N: Keith Outwater E: Keith_Outwater@mvis.com D: Support for GEN860T board +N: Keith Outwater +E: keith_outwater@mvis.com +D: Support for generic/custom MPC860T board (GEN860T) + N: Frank Panno E: fpanno@delphintech.com D: Support for Embedded Planet EP8260 Board diff --git a/MAINTAINERS b/MAINTAINERS index bf821aa..092d268 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -160,6 +160,9 @@ Jim Thompson MUSENKI MPC8245/8241 Sandpoint8245 MPC8245 +Keith Outwater or + GEN860T MPC860T + ------------------------------------------------------------------------- Unknown / orphaned boards: diff --git a/MAKEALL b/MAKEALL index aaaf0b4..fc4cea4 100755 --- a/MAKEALL +++ b/MAKEALL @@ -18,15 +18,15 @@ LIST_8xx=" \ ADS860 AMX860 c2mon CCM \ cogent_mpc8xx ESTEEM192E ETX094 FADS823 \ FADS850SAR FADS860T FLAGADM FPS850L \ - GENIETV GTH hermes IAD210 \ - ICU862_100MHz IP860 IVML24 IVML24_128 \ - IVML24_256 IVMS8 IVMS8_128 IVMS8_256 \ - LANTEC lwmon MBX MBX860T \ - MHPC MVS1 NX823 pcu_e \ - R360MPI RPXClassic RPXlite SM850 \ - SPD823TS SXNI855T TQM823L TQM823L_LCD \ - TQM850L TQM855L TQM860L TQM860L_FEC \ - TTTech \ + GEN860T GENIETV GTH hermes \ + IAD210 ICU862_100MHz IP860 IVML24 \ + IVML24_128 IVML24_256 IVMS8 IVMS8_128 \ + IVMS8_256 LANTEC lwmon MBX \ + MBX860T MHPC MVS1 NX823 \ + pcu_e R360MPI RPXClassic RPXlite \ + SM850 SPD823TS SXNI855T TQM823L \ + TQM823L_LCD TQM850L TQM855L TQM860L \ + TQM860L_FEC TTTech \ " ######################################################################### diff --git a/Makefile b/Makefile index 1e78ec4..666bf04 100644 --- a/Makefile +++ b/Makefile @@ -205,6 +205,9 @@ FADS860T_config: unconfig FLAGADM_config: unconfig @./mkconfig $(@:_config=) ppc mpc8xx flagadm +GEN860T_config: unconfig + @./mkconfig $(@:_config=) ppc mpc8xx gen860t + GENIETV_config: unconfig @./mkconfig $(@:_config=) ppc mpc8xx genietv diff --git a/board/ebony/ebony.c b/board/ebony/ebony.c index b259754..ca40ce1 100644 --- a/board/ebony/ebony.c +++ b/board/ebony/ebony.c @@ -199,3 +199,98 @@ long int fixed_sdram (void) return (128 * 1024 * 1024); /* 128 MB */ } #endif /* !defined(CONFIG_SPD_EEPROM) */ + + +/************************************************************************* + * pci_pre_init + * + * This routine is called just prior to registering the hose and gives + * the board the opportunity to check things. Returning a value of zero + * indicates that things are bad & PCI initialization should be aborted. + * + * Different boards may wish to customize the pci controller structure + * (add regions, override default access routines, etc) or perform + * certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(gd_t * gd, struct pci_controller * hose ) +{ + unsigned long strap; + + /*--------------------------------------------------------------------------+ + * The ebony board is always configured as the host & requires the + * PCI arbiter to be enabled. + *--------------------------------------------------------------------------*/ + strap = mfdcr(cpc0_strp1); + if( (strap & 0x00100000) == 0 ){ + printf("PCI: CPC0_STRP1[PAE] not set.\n"); + return 0; + } + + return 1; +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + * pci_target_init + * + * The bootstrap configuration provides default settings for the pci + * inbound map (PIM). But the bootstrap config choices are limited and + * may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init( gd_t * gd, struct pci_controller * hose ) +{ + /*--------------------------------------------------------------------------+ + * Disable everything + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0SA, 0 ); /* disable */ + out32r( PCIX0_PIM1SA, 0 ); /* disable */ + out32r( PCIX0_PIM2SA, 0 ); /* disable */ + out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */ + + /*--------------------------------------------------------------------------+ + * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 strapping + * options to not support sizes such as 128/256 MB. + *--------------------------------------------------------------------------*/ + out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE ); + out32r( PCIX0_PIM0LAH, 0 ); + out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 ); + + out32r( PCIX0_BAR0, 0 ); + + /*--------------------------------------------------------------------------+ + * Program the board's subsystem id/vendor id + *--------------------------------------------------------------------------*/ + out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); + out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID ); + + out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY ); +} +#endif /* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + + +/************************************************************************* + * is_pci_host + * + * This routine is called to determine if a pci scan should be + * performed. With various hardware environments (especially cPCI and + * PPMC) it's insufficient to depend on the state of the arbiter enable + * bit in the strap register, or generic host/adapter assumptions. + * + * Rather than hard-code a bad assumption in the general 440 code, the + * 440 pci code requires the board to decide at runtime. + * + * Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +#if defined(CONFIG_PCI) +int is_pci_host( gd_t * gd, struct pci_controller *hose) +{ + /* The ebony board is always configured as host. */ + return(1); +} +#endif /* defined(CONFIG_PCI) */ diff --git a/board/ebony/flash.c b/board/ebony/flash.c index c5b318a..a669ded 100644 --- a/board/ebony/flash.c +++ b/board/ebony/flash.c @@ -35,6 +35,14 @@ #include #include + +#undef DEBUG +#ifdef DEBUG +#define DEBUGF(x...) printf(x) +#else +#define DEBUGF(x...) +#endif /* DEBUG */ + #define BOOT_SMALL_FLASH 32 /* 00100000 */ #define FLASH_ONBD_N 2 /* 00000010 */ #define FLASH_SRAM_SEL 1 /* 00000001 */ @@ -116,9 +124,8 @@ unsigned long flash_init (void) { index += FLASH_SRAM_SEL_VAL; } -#if 0 - printf("Index: %d\n", index); -#endif + DEBUGF("\n"); + DEBUGF("FLASH: Index: %d\n", index); /* Init: no FLASHes known */ for (i=0; istart[i], - info->protect[i] ? " (RO)" : " " -#else printf (" %08lX%s%s", info->start[i], erased ? " E" : " ", info->protect[i] ? "RO " : " " -#endif ); } printf ("\n"); @@ -297,10 +298,16 @@ void flash_print_info (flash_info_t *info) ulong base = (ulong)addr; volatile FLASH_WORD_SIZE *addr2 = (FLASH_WORD_SIZE *)addr; + DEBUGF("FLASH ADDR: %08x\n", (unsigned)addr ); + /* Write auto select command: read Manufacturer ID */ + udelay(10000); addr2[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA; + udelay(1000); addr2[ADDR1] = (FLASH_WORD_SIZE)0x00550055; + udelay(1000); addr2[ADDR0] = (FLASH_WORD_SIZE)0x00900090; + udelay(1000); #ifdef CONFIG_ADCIOP value = addr2[2]; @@ -308,9 +315,8 @@ void flash_print_info (flash_info_t *info) value = addr2[0]; #endif -#if 0 - printf("\nFLASH MANUFACT: %x\n", value); -#endif + DEBUGF("FLASH MANUFACT: %x\n", value); + switch (value) { case (FLASH_WORD_SIZE)AMD_MANUFACT: info->flash_id = FLASH_MAN_AMD; @@ -335,9 +341,8 @@ void flash_print_info (flash_info_t *info) value = addr2[1]; /* device ID */ #endif -#if 0 - printf("\nFLASH DEVICEID: %x\n", value); -#endif + DEBUGF("\nFLASH DEVICEID: %x\n", value); + switch (value) { case (FLASH_WORD_SIZE)AMD_ID_F016D: info->flash_id += FLASH_AMD016; diff --git a/board/ebony/init.S b/board/ebony/init.S index d7b7515..bcb09a9 100644 --- a/board/ebony/init.S +++ b/board/ebony/init.S @@ -91,6 +91,8 @@ tlbtab: tlbentry( CFG_ISRAM_BASE, SZ_4K, 0x80000000, 0, AC_R|AC_W|AC_X ) tlbentry( CFG_ISRAM_BASE + 0x1000, SZ_4K, 0x80001000, 0, AC_R|AC_W|AC_X ) tlbentry( CFG_SDRAM_BASE, SZ_256M, 0x00000000, 0, AC_R|AC_W|AC_X|SA_G|SA_I ) + tlbentry( CFG_PCI_BASE, SZ_256M, 0x00000000, 2, AC_R|AC_W|SA_G|SA_I ) + tlbentry( CFG_PCI_MEMBASE, SZ_256M, 0x00000000, 3, AC_R|AC_W|SA_G|SA_I ) tlbtab_end diff --git a/board/gen860t/Makefile b/board/gen860t/Makefile new file mode 100644 index 0000000..21bf040 --- /dev/null +++ b/board/gen860t/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 beeper.o fpga.o ioport.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/gen860t/README b/board/gen860t/README new file mode 100644 index 0000000..e522be7 --- /dev/null +++ b/board/gen860t/README @@ -0,0 +1,142 @@ + +This directory contains board specific code for a generic MPC860T based +embedded computer, called 'GEN860T'. The design is generic in the sense that +common, readily available components are used and that the architecture of the +system is i(relatively) straightforward: + + One eight bit wide boot (FLASH) memory + 32 bit main memory using SDRAM + DOC 2000+ + Ethernet PHY + Some I2C peripheral devices: Atmel AT24C256 EEPROM, Maxim DS1337 RTC. + Some other miscellaneous peripherals + +NOTE: There are references to a XIlinx FPGA and Mil-Std 1553 databus in this +port. I guess the computer is not as generic as I first said 8) However, +these extras can be safely ignored. + +Given the GEN860T files, it should be pretty easy to reverse engineer the +hardware configuration, if that's useful to you. Hopefully, this code will +be useful to someone as a basis for a port to a new system or as a head start +on a custom design. If you end up using any of this, I would appreciate +hearing from you, especially if you discover bugs or find ways to improve the +quality of this ppcboot port. + +Here are the salient features of the system: +Clock : 33 Mhz oscillator +Processor core frequency : 66 Mhz if in 1:2:1 mode; can also run 1:1 +Bus frequency : 33 Mhz + +Main memory: + Type : SDRAM + Width : 32 bits + Size : 64 megabytes + Chip : Two Micron MT48LC16M16A2TG-7E + CS : MPC860T CS1*/UPMA + UPMA CONNECTIONS: + SDRAM A10 : GPLA0* + SDRAM CAS* : GPLA2* + SDRAM WE* : GPLA3* + SDRAM RAS* : GPLA4* + +Boot memory: + Type : FLASH + Width : 8 bits + Size : 16 megabytes + Chip : One Intel 28F128J3A (StrataFlash) + CS : MPC860T CS0*/GPCM (this is the "boot" chip select) + +EEPROM memory: + Type : Serial I2C EEPROM + Width : 8 bits + Size : 32 kibibytes + Chip : One Atmel AT25C256 + CS : 0x50 (external I2C address pins on device are tied to GND) + +Filesystem memory: + Type : NAND FLASH (Toshiba) + Width : 8 bits (i.e. interface to DOC is 8 bits) + Size : 32 megabytes + Chip : One DiskOnCHip Millenium Plus (DOC 2000+) + CS : MPC860T CS2*/GPCM + +Network support: + MAC : MPC86OT FEC (Fast Ethernet Controller) + PHY : Intel LXT971A + MII Addr: 0x0 (hardwired on the board) + MII IRQ : + +Console: + RS-232 on SMC1 (Maxim MAX3232 LVCMOS-RS232 level shifter) + +Real Time Clock: + Type : Low power, I2C interface + Chip : Maxim DS1337 + CS : Address 0x68 on I2C bus + + The MPC860T's internal RTC has a defect in Mask rev D that increases + the current drain on the KAPWR line to 10 mA. Since this is an + unreasonable amount of current draw for a RTC, and Motorola does not + plan to fix this in future mask revisions, a serial (I2C) RTC that + works has been included instead. NOTE that the DS1337 can be + configured to output a 32768 Hz clock while the main power is on. + This clock output has been routed to the MPC860T's EXTAL pin to allow + the internal RTC to be used. NOTE also that due to yet another + defect in the rev D mask, the RTC does not operate reliably when the + internal RTC divisor is set to use a 32768 Hz reference. So just use + the I2C RTC. + +Miscellaneous: + Xilinx Virtex FPGA on CS3*/GPCM. + Virtex FPGA slave SelectMap interface on cs4*/UPMB. + Mil-Std 1553 databus interface on CS5*/GPCM. + Audio sounder (beeper) with digital volume control connected to SPKROUT. + +Issues: + The DOC 2000+ returns 0x40 as its device ID when probed using the method + desxribed in the DOC datasheet. Unfortunately, the ppcboot DOC driver + does not recognize this device. As of this writing, it seems that MTD + does not support the DOC 2000+ either. + +Status: + Everything appears to work except DOC support. As of this writing, + David Woodhouse has stated on the MTD mailing list that he has no + knowledge of the DOC Millineum Plus and therfore there is no support + in MTD for this device. I wish I had known this sooner :( + +The GEN860T board specific files and configuration is based on the work +of others who have contributed to ppcboot. The copright and license notices +of these authors have been retained wherever their code has been reused. +All new code to support the GEN860T board is: + + (C) Copyright 2001-2002 + Keith Outwater (keith_outwater@mvis.com) + +and the following license applies: + +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, +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 + +Thanks to Wolfgang Denk for a great software package and to everyone +who contributed to its development. + +Keith Outwater +Sr. Staff Engineer +Microvision, Inc. + + + +vim: set ts=4 sw=4 tw=78: + diff --git a/board/gen860t/beeper.c b/board/gen860t/beeper.c new file mode 100644 index 0000000..d3a8141 --- /dev/null +++ b/board/gen860t/beeper.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2002 + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* + * Basic beeper support for the GEN860T board. The GEN860T includes + * an audio sounder driven by a Phillips TDA8551 amplifier. The + * TDA8551 features a digital volume control which uses a "trinary" + * input (high/high-Z/low) to set volume. The 860's SPKROUT pin + * drives the amplifier input. + */ + + +/* + * Initialize beeper-related hardware. Initialize timer 1 for use with + * the beeper. Use 66 Mhz internal clock with prescale of 33 to get + * 1 uS period per count. + * FIXME: we should really compute the prescale based on the reported + * core clock frequency. + */ +void +init_beeper(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_RST1 | TGCR_STP1; + immap->im_cpmtimer.cpmt_tmr1 = ((33 << TMR_PS_SHIFT) & TMR_PS_MSK) + | TMR_OM | TMR_FRR | TMR_ICLK_IN_GEN; + immap->im_cpmtimer.cpmt_tcn1 = 0; + immap->im_cpmtimer.cpmt_ter1 = 0xffff; + immap->im_cpmtimer.cpmt_tgcr |= TGCR_RST1; +} + + +/* + * Set beeper frequency. Max allowed frequency is 2.5 KHz. This limit + * is mostly arbitrary, but the beeper isn't really much good beyond this + * frequency. + */ +void +set_beeper_frequency(uint frequency) +{ +#define FREQ_LIMIT 2500 + + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + /* + * Compute timer ticks given desired frequency. The timer is set up + * to count 0.5 uS per tick and it takes two ticks per cycle (Hz). + */ + if (frequency > FREQ_LIMIT) frequency = FREQ_LIMIT; + frequency = 1000000/frequency; + immap->im_cpmtimer.cpmt_trr1 = (ushort)frequency; +} + + +/* + * Turn the beeper on + */ +void +beeper_on(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + immap->im_cpmtimer.cpmt_tgcr &= ~TGCR_STP1; +} + + +/* + * Turn the beeper off + */ +void +beeper_off(void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + immap->im_cpmtimer.cpmt_tgcr |= TGCR_STP1; +} + + +/* + * Increase or decrease the beeper volume. Volume can be set + * from off to full in 64 steps. To increase volume, the output + * pin is actively driven high, then returned to tristate. + * To decrease volume, output a low on the port pin (no need to + * change pin mode to tristate) then output a high to go back to + * tristate. + */ +void +set_beeper_volume(int steps) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + int i; + + if (steps >= 0) { + for (i = 0; i < (steps >= 64 ? 64 : steps); i++) { + immap->im_cpm.cp_pbodr &= ~(0x80000000 >> 19); + udelay(1); + immap->im_cpm.cp_pbodr |= (0x80000000 >> 19); + udelay(1); + } + } + else { + for (i = 0; i > (steps <= -64 ? -64 : steps); i--) { + immap->im_cpm.cp_pbdat &= ~(0x80000000 >> 19); + udelay(1); + immap->im_cpm.cp_pbdat |= (0x80000000 >> 19); + udelay(1); + } + } +} + + +/* + * Check the environment to see if the beeper needs beeping. + * Controlled by a sequence of the form: + * freq/delta volume/on time/off time;... where: + * freq = frequency in Hz (0 - 2500) + * delta volume = volume steps up or down (-64 <= vol <= 64) + * on time = time in mS + * off time = time in mS + * + * Return 1 on success, 0 on failure + */ +int +do_beeper(char *sequence) +{ +#define DELIMITER ';' + +int args[4]; +int i; +int val; +char *p = sequence; +char *tp; + + /* + * Parse the control sequence. This is a really simple parser + * without any real error checking. You can probably blow it + * up really easily. + */ + if (*p == '\0' || !isdigit(*p)) { + printf("%s:%d: null or invalid string (%s)\n", + __FILE__, __LINE__, p); + return 0; + } + + i = 0; + while (*p != '\0') { + while (*p != DELIMITER) { + if (i > 3) i = 0; + val = (int) simple_strtol(p, &tp, 0); + if (tp == p) { + printf("%s:%d: no digits or bad format\n", + __FILE__,__LINE__); + return 0; + } + else { + args[i] = val; + } + + i++; + if (*tp == DELIMITER) + p = tp; + else + p = ++tp; + } + p++; + + /* + * Well, we got something that has a chance of being correct + */ +#if 0 + for (i = 0; i < 4; i++) { + printf("%s:%d:arg %d = %d\n", __FILE__, __LINE__, i, args[i]); + } + printf("\n"); +#endif + + set_beeper_frequency(args[0]); + set_beeper_volume(args[1]); + beeper_on(); + udelay(1000 * args[2]); + beeper_off(); + udelay(1000 * args[3]); + } + return 1; +} + +/* vim: set ts=4 sw=4 tw=78: */ diff --git a/board/gen860t/beeper.h b/board/gen860t/beeper.h new file mode 100644 index 0000000..535ee6c --- /dev/null +++ b/board/gen860t/beeper.h @@ -0,0 +1,31 @@ +/* + * (C) Copyright 2002 + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +void init_beeper(void); +void set_beeper_frequency(uint frequency); +void beeper_on(void); +void beeper_off(void); +void set_beeper_volume(int steps); +int do_beeper(char *sequence); + +/* vim: set ts=4 tw=78 sw=4: */ diff --git a/board/gen860t/config.mk b/board/gen860t/config.mk new file mode 100644 index 0000000..7acd904 --- /dev/null +++ b/board/gen860t/config.mk @@ -0,0 +1,28 @@ +# +# (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 +# + +# +# FLASH base address for GEN860T board +# + +TEXT_BASE = 0x40000000 diff --git a/board/gen860t/flash.c b/board/gen860t/flash.c new file mode 100644 index 0000000..371d89c --- /dev/null +++ b/board/gen860t/flash.c @@ -0,0 +1,644 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvsi.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + +#if defined(CFG_ENV_IS_IN_FLASH) +# ifndef CFG_ENV_ADDR +# define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +# endif +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif +# ifndef CFG_ENV_SECT_SIZE +# define CFG_ENV_SECT_SIZE CFG_ENV_SIZE +# endif +#endif + +/* + * Use buffered writes to flash by default - they are about 32x faster than + * single byte writes. + */ +#ifndef CFG_GEN860T_FLASH_USE_WRITE_BUFFER +#define CFG_GEN860T_FLASH_USE_WRITE_BUFFER +#endif + +/* + * Max time to wait (in mS) for flash device to allocate a write buffer. + */ +#ifndef CFG_FLASH_ALLOC_BUFFER_TOUT +#define CFG_FLASH_ALLOC_BUFFER_TOUT 100 +#endif + +/* + * These functions support a single Intel StrataFlash device (28F128J3A) + * in byte mode only!. The flash routines are very basic and simple + * since there isn't really any remapping necessary. + */ + +/* + * Intel SCS (Scalable Command Set) command definitions + * (taken from 28F128J3A datasheet) + */ +#define SCS_READ_CMD 0xff +#define SCS_READ_ID_CMD 0x90 +#define SCS_QUERY_CMD 0x98 +#define SCS_READ_STATUS_CMD 0x70 +#define SCS_CLEAR_STATUS_CMD 0x50 +#define SCS_WRITE_BUF_CMD 0xe8 +#define SCS_PROGRAM_CMD 0x40 +#define SCS_BLOCK_ERASE_CMD 0x20 +#define SCS_BLOCK_ERASE_RESUME_CMD 0xd0 +#define SCS_PROGRAM_RESUME_CMD 0xd0 +#define SCS_BLOCK_ERASE_SUSPEND_CMD 0xb0 +#define SCS_SET_BLOCK_LOCK_CMD 0x60 +#define SCS_CLR_BLOCK_LOCK_CMD 0x60 + +/* + * SCS status/extended status register bit definitions + */ +#define SCS_SR7 0x80 +#define SCS_XSR7 0x80 + +/*---------------------------------------------------------------------*/ +#if 0 +#define DEBUG_FLASH +#endif + +#ifdef DEBUG_FLASH +#define PRINTF(fmt,args...) printf(fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_char *addr, flash_info_t *info); +static int write_data8 (flash_info_t *info, ulong dest, uchar data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + * Initialize the flash memory. + */ +unsigned long +flash_init (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size_b0; + int i; + + for (i= 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* + * The gen860t board only has one FLASH memory device, so the + * FLASH Bank configuration is done statically. + */ + PRINTF("\n## Get flash bank 1 size @ 0x%08x\n", FLASH_BASE0_PRELIM); + size_b0 = flash_get_size((vu_char *)FLASH_BASE0_PRELIM, &flash_info[0]); + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0: " + "ID 0x%lx, Size = 0x%08lx = %ld MB\n", + flash_info[0].flash_id,size_b0, size_b0 << 20); + } + + PRINTF("## Before remap:\n" + " BR0: 0x%08x OR0: 0x%08x\n BR1: 0x%08x OR1: 0x%08x\n", + memctl->memc_br0, memctl->memc_or0, + memctl->memc_br1, memctl->memc_or1); + + /* + * Remap FLASH according to real size + */ + memctl->memc_or0 |= (-size_b0 & 0xFFFF8000); + memctl->memc_br0 |= (CFG_FLASH_BASE & BR_BA_MSK); + + PRINTF("## After remap:\n" + " BR0: 0x%08x OR0: 0x%08x\n", memctl->memc_br0, memctl->memc_or0); + + /* + * Re-do sizing to get full correct info + */ + size_b0 = flash_get_size ((vu_char *)CFG_FLASH_BASE, &flash_info[0]); + flash_get_offsets (CFG_FLASH_BASE, &flash_info[0]); + flash_info[0].size = size_b0; + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* + * Monitor protection is 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 + /* + * Environment protection ON by default + */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + + PRINTF("## Final Flash bank size: 0x%08lx\n",size_b0); + return (size_b0); +} + + +/*----------------------------------------------------------------------- + * Fill in the FLASH offset table + */ +static void +flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_INTEL: + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base; + base += 1024 * 128; + } + return; + + default: + printf ("Don't know sector offsets for FLASH" + " type 0x%lx\n", info->flash_id); + return; + } +} + + +/*----------------------------------------------------------------------- + * Display FLASH device info + */ +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_INTEL: + printf ("Intel "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F128J3A: + printf ("28F128J3A (128Mbit = 128K x 128)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + if (info->size >= (1024 * 1024)) { + i = 20; + } else { + i = 10; + } + printf (" Size: %ld %cB in %d Sectors\n", + info->size >> i, + (i == 20) ? 'M' : 'k', + info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + + +/*----------------------------------------------------------------------- + * Get size and other information for a FLASH device. + * NOTE: The following code cannot be run from FLASH! + */ +static +ulong flash_get_size (vu_char *addr, flash_info_t *info) +{ +#define NO_FLASH 0 + + vu_char value[2]; + + /* + * Try to read the manufacturer ID + */ + addr[0] = SCS_READ_CMD; + addr[0] = SCS_READ_ID_CMD; + value[0] = addr[0]; + value[1] = addr[2]; + addr[0] = SCS_READ_CMD; + + PRINTF("Manuf. ID @ 0x%08lx: 0x%02x\n", (ulong)addr, value[0]); + switch (value[0]) { + case (INTEL_MANUFACT & 0xff): + info->flash_id = FLASH_MAN_INTEL; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (NO_FLASH); + } + + /* + * Read the device ID + */ + PRINTF("Device ID @ 0x%08lx: 0x%02x\n", (ulong)(&addr[2]), value[1]); + switch (value[1]) { + case (INTEL_ID_28F128J3A & 0xff): + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 16 * 1024 * 1024; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + return (NO_FLASH); + } + + 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; + } + return (info->size); +} + + +/*----------------------------------------------------------------------- + * Erase the specified sectors in the specified FLASH device + */ +int +flash_erase(flash_info_t *info, int s_first, int s_last) +{ + int flag, prot, sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) { + printf ("Can erase only Intel flash types - aborted\n"); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + start = get_timer (0); + last = start; + + /* + * Start erase on unprotected sectors + */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + vu_char *addr = (uchar *)(info->start[sect]); + vu_char status; + + /* + * Disable interrupts which might cause a timeout + */ + flag = disable_interrupts(); + + *addr = SCS_CLEAR_STATUS_CMD; + *addr = SCS_BLOCK_ERASE_CMD; + *addr = SCS_BLOCK_ERASE_RESUME_CMD; + + /* + * Re-enable interrupts if necessary + */ + if (flag) + enable_interrupts(); + + /* + * Wait at least 80us - let's wait 1 ms + */ + udelay (1000); + + while (((status = *addr) & SCS_SR7) != SCS_SR7) { + if ((now=get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = SCS_BLOCK_ERASE_SUSPEND_CMD; + *addr = SCS_READ_CMD; + return 1; + } + + /* + * Show that we're waiting + */ + if ((now - last) > 1000) { /* 1 second */ + putc ('.'); + last = now; + } + } + *addr = SCS_READ_CMD; + } + } + printf (" done\n"); + return 0; +} + + +#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER +/* + * Allocate a flash buffer, fill it with data and write it to the flash. + * 0 - OK + * 1 - Timeout on buffer request + * + * NOTE: After the last call to this function, WSM status needs to be checked! + */ +static int +write_flash_buffer8(flash_info_t *info_p, vu_char *src_p, vu_char *dest_p, + uint count) +{ + vu_char *block_addr_p = NULL; + vu_char *start_addr_p = NULL; + ulong blocksize = info_p->size / (ulong)info_p->sector_count; + + int i; + uint time = get_timer(0); + + PRINTF("%s:%d: src: 0x%p dest: 0x%p count: %d\n", + __FUNCTION__, __LINE__, src_p, dest_p, count); + + /* + * What block are we in? We already know that the source address is + * in the flash address range, but we also can't cross a block boundary. + * We assume that the block does not cross a boundary (we'll check before + * calling this function). + */ + for (i = 0; i < info_p->sector_count; ++i) { + if ( ((ulong)dest_p >= info_p->start[i]) && + ((ulong)dest_p < (info_p->start[i] + blocksize)) ) { + PRINTF("%s:%d: Dest addr 0x%p is in block %d @ 0x%.8lx\n", + __FUNCTION__, __LINE__, dest_p, i, info_p->start[i]); + block_addr_p = (vu_char *)info_p->start[i]; + break; + } + } + + /* + * Request a buffer + */ + *block_addr_p = SCS_WRITE_BUF_CMD; + while ((*block_addr_p & SCS_XSR7) != SCS_XSR7) { + if (get_timer(time) > CFG_FLASH_ALLOC_BUFFER_TOUT) { + PRINTF("%s:%d: Buffer allocation timeout @ 0x%p (waited %d mS)\n", + __FUNCTION__, __LINE__, block_addr_p, + CFG_FLASH_ALLOC_BUFFER_TOUT); + return 1; + } + *block_addr_p = SCS_WRITE_BUF_CMD; + } + + /* + * Fill the buffer with data + */ + start_addr_p = dest_p; + *block_addr_p = count - 1; /* flash device wants count - 1 */ + PRINTF("%s:%d: Fill buffer at block addr 0x%p\n", + __FUNCTION__, __LINE__, block_addr_p); + for (i = 0; i < count; i++) { + *start_addr_p++ = *src_p++; + } + + /* + * Flush buffer to flash + */ + *block_addr_p = SCS_PROGRAM_RESUME_CMD; +#if 1 + time = get_timer(0); + while ((*block_addr_p & SCS_SR7) != SCS_SR7) { + if (get_timer(time) > CFG_FLASH_WRITE_TOUT) { + PRINTF("%s:%d: Write timeout @ 0x%p (waited %d mS)\n", + __FUNCTION__, __LINE__, block_addr_p, CFG_FLASH_WRITE_TOUT); + return 1; + } + } + +#endif + return 0; +} +#endif + + +/*----------------------------------------------------------------------- + * 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_p, uchar *src_p, ulong addr, ulong count) +{ + int rc = 0; +#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER +#define FLASH_WRITE_BUF_SIZE 0x00000020 /* 32 bytes */ + int i; + uint bufs; + ulong buf_count; + vu_char *sp; + vu_char *dp; +#else + ulong wp; +#endif + + PRINTF("\n%s:%d: src: 0x%.8lx dest: 0x%.8lx size: %d (0x%.8lx)\n", + __FUNCTION__, __LINE__, (ulong)src_p, addr, (uint)count, count); + + if (info_p->flash_id == FLASH_UNKNOWN) { + return 4; + } + +#ifdef CFG_GEN860T_FLASH_USE_WRITE_BUFFER + sp = src_p; + dp = (uchar *)addr; + + /* + * For maximum performance, we want to align the start address to + * the beginning of a write buffer boundary (i.e. A4-A0 of the + * start address = 0). See how many bytes are required to get to a + * write-buffer-aligned address. If that number is non-zero, do + * non buffered writes of the non-aligned data. By doing non-buffered + * writes, we avoid the problem of crossing a block (sector) boundary + * with buffered writes. + */ + buf_count = FLASH_WRITE_BUF_SIZE - (addr & (FLASH_WRITE_BUF_SIZE - 1)); + if (buf_count == FLASH_WRITE_BUF_SIZE) { /* already on a boundary */ + buf_count = 0; + } + if (buf_count > count) { /* not a full buffers worth of data to write */ + buf_count = count; + } + count -= buf_count; + + PRINTF("%s:%d: Write buffer alignment count = %ld\n", + __FUNCTION__, __LINE__, buf_count); + while (buf_count-- >= 1) { + if ((rc = write_data8(info_p, (ulong)dp++, *sp++)) != 0) { + return (rc); + } + } + + PRINTF("%s:%d: count = %ld\n", __FUNCTION__, __LINE__, count); + if (count == 0) { /* all done */ + PRINTF("%s:%d: Less than 1 buffer (%d) worth of bytes\n", + __FUNCTION__, __LINE__, FLASH_WRITE_BUF_SIZE); + return (rc); + } + + /* + * Now that we are write buffer aligned, write full or partial buffers. + * The fact that we are write buffer aligned automatically avoids + * crossing a block address during a write buffer operation. + */ + bufs = count / FLASH_WRITE_BUF_SIZE; + PRINTF("%s:%d: %d (0x%x) buffers to write\n", __FUNCTION__, __LINE__, + bufs, bufs); + while (bufs >= 1) { + rc = write_flash_buffer8(info_p, sp, dp, FLASH_WRITE_BUF_SIZE); + if (rc != 0) { + PRINTF("%s:%d: ** Error writing buf %d\n", + __FUNCTION__, __LINE__, bufs); + return (rc); + } + bufs--; + sp += FLASH_WRITE_BUF_SIZE; + dp += FLASH_WRITE_BUF_SIZE; + } + + /* + * Do the leftovers + */ + i = count % FLASH_WRITE_BUF_SIZE; + PRINTF("%s:%d: %d (0x%x) leftover bytes\n", __FUNCTION__, __LINE__, i, i); + if (i > 0) { + rc = write_flash_buffer8(info_p, sp, dp, i); + } + + sp = (vu_char*)info_p->start[0]; + *sp = SCS_READ_CMD; + return (rc); + +#else + wp = addr; + while (count-- >= 1) { + if((rc = write_data8(info_p, wp++, *src_p++)) != 0) + return (rc); + } + return 0; +#endif +} + + +/*----------------------------------------------------------------------- + * Write a byte to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int +write_data8 (flash_info_t *info, ulong dest, uchar data) +{ + vu_char *addr = (vu_char *)dest; + vu_char status; + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*addr & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *addr = SCS_PROGRAM_CMD; + *addr = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + + while (((status = *addr) & SCS_SR7) != SCS_SR7) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + *addr = SCS_READ_CMD; + return (1); + } + } + *addr = SCS_READ_CMD; + return (0); +} + +/* vim: set ts=4 sw=4 tw=78: */ diff --git a/board/gen860t/fpga.c b/board/gen860t/fpga.c new file mode 100644 index 0000000..2c6e4f1 --- /dev/null +++ b/board/gen860t/fpga.c @@ -0,0 +1,401 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * Keith Outwater, keith_outwater@mvis.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Virtex2 FPGA configuration support for the GEN860T computer + */ + +#include +#include +#include +#include "fpga.h" + +#if (CONFIG_FPGA) + +#if 0 +#define GEN860T_FPGA_DEBUG +#endif + +#ifdef GEN860T_FPGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * Port bit numbers for the Selectmap controls + */ +#define FPGA_INIT_BIT_NUM 22 /* PB22 */ +#define FPGA_RESET_BIT_NUM 11 /* PC11 */ +#define FPGA_DONE_BIT_NUM 16 /* PB16 */ +#define FPGA_PROGRAM_BIT_NUM 7 /* PA7 */ + +/* Note that these are pointers to code that is in Flash. They will be + * relocated at runtime. + */ +Xilinx_Virtex2_Slave_SelectMap_fns fpga_fns = { + fpga_pre_config_fn, + fpga_pgm_fn, + fpga_init_fn, + fpga_err_fn, + fpga_done_fn, + fpga_clk_fn, + fpga_cs_fn, + fpga_wr_fn, + fpga_read_data_fn, + fpga_write_data_fn, + fpga_busy_fn, + fpga_abort_fn, + fpga_post_config_fn +}; + +Xilinx_desc fpga[CONFIG_FPGA_COUNT] = { + { Xilinx_Virtex2, + slave_selectmap, + XILINX_XC2V3000_SIZE, + (void *)&fpga_fns, + 0 + } +}; + +/* + * Display FPGA revision information + */ +void +print_fpga_revision(void) +{ + vu_long *rev_p = (vu_long *)0x60000008; + + printf("FPGA Revision 0x%.8lx" + " (Date %.2lx/%.2lx/%.2lx, Status \"%.1lx\", Version %.3lu)\n", + *rev_p, + ((*rev_p >> 28) & 0xf), + ((*rev_p >> 20) & 0xff), + ((*rev_p >> 12) & 0xff), + ((*rev_p >> 8) & 0xf), + (*rev_p & 0xff)); +} + + +/* + * Perform a simple test of the FPGA to processor interface using the FPGA's + * inverting bus test register. The great thing about doing a read/write + * test on a register that inverts it's contents is that you avoid any + * problems with bus charging. + * Return 0 on failure, 1 on success. + */ +int +test_fpga_ibtr(void) +{ + vu_long *ibtr_p = (vu_long *)0x60000010; + vu_long readback; + vu_long compare; + int i; + int j; + int k; + int pass = 1; + + static const ulong bitpattern[] = { + 0xdeadbeef, /* magic ID pattern for debug */ + 0x00000001, /* single bit */ + 0x00000003, /* two adjacent bits */ + 0x00000007, /* three adjacent bits */ + 0x0000000F, /* four adjacent bits */ + 0x00000005, /* two non-adjacent bits */ + 0x00000015, /* three non-adjacent bits */ + 0x00000055, /* four non-adjacent bits */ + 0xaaaaaaaa, /* alternating 1/0 */ + }; + + for (i = 0; i < 1024; i++) { + for (j = 0; j < 31; j++) { + for (k = 0; k < sizeof(bitpattern)/sizeof(bitpattern[0]); k++) { + *ibtr_p = compare = (bitpattern[k] << j); + readback = *ibtr_p; + if (readback != ~compare) { + printf("%s:%d: FPGA test fail: expected 0x%.8lx" + " actual 0x%.8lx\n", + __FUNCTION__, __LINE__, ~compare, readback); + pass = 0; + break; + } + } + if (!pass) break; + } + if (!pass) break; + } + if (pass) { + printf("FPGA inverting bus test passed\n"); + print_fpga_revision(); + } + else { + printf("** FPGA inverting bus test failed\n"); + } + return pass; +} + + +/* + * Set the active-low FPGA reset signal. + */ +void +fpga_reset(int assert) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + PRINTF("%s:%d: RESET ", __FUNCTION__, __LINE__); + if (assert) { + immap->im_ioport.iop_pcdat &= ~(0x8000 >> FPGA_RESET_BIT_NUM); + PRINTF("asserted\n"); + } + else { + immap->im_ioport.iop_pcdat |= (0x8000 >> FPGA_RESET_BIT_NUM); + PRINTF("deasserted\n"); + } +} + + +/* + * Initialize the SelectMap interface. We assume that the mode and the + * initial state of all of the port pins have already been set! + */ +void +fpga_selectmap_init(void) +{ + PRINTF("%s:%d: Initialize SelectMap interface\n", __FUNCTION__, __LINE__); + fpga_pgm_fn(FALSE, FALSE, 0); /* make sure program pin is inactive */ +} + + +/* + * Initialize the fpga. Return 1 on success, 0 on failure. + */ +int +gen860t_init_fpga(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int i; + + PRINTF("%s:%d: Initialize FPGA interface (relocation offset = 0x%.8lx)\n", + __FUNCTION__, __LINE__, gd->reloc_off); + fpga_init(gd->reloc_off); + fpga_selectmap_init(); + + for(i=0; i < CONFIG_FPGA_COUNT; i++) { + PRINTF("%s:%d: Adding fpga %d\n", __FUNCTION__, __LINE__, i); + fpga_add(fpga_xilinx, &fpga[i]); + } + return 1; +} + + +/* + * Set the FPGA's active-low SelectMap program line to the specified level + */ +int +fpga_pgm_fn(int assert, int flush, int cookie) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + PRINTF("%s:%d: FPGA PROGRAM ", __FUNCTION__, __LINE__); + + if (assert) { + immap->im_ioport.iop_padat &= ~(0x8000 >> FPGA_PROGRAM_BIT_NUM); + PRINTF("asserted\n"); + } + else { + immap->im_ioport.iop_padat |= (0x8000 >> FPGA_PROGRAM_BIT_NUM); + PRINTF("deasserted\n"); + } + return assert; +} + + +/* + * Test the state of the active-low FPGA INIT line. Return 1 on INIT + * asserted (low). + */ +int +fpga_init_fn(int cookie) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + PRINTF("%s:%d: INIT check... ", __FUNCTION__, __LINE__); + if(immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_INIT_BIT_NUM)) { + PRINTF("high\n"); + return 0; + } + else { + PRINTF("low\n"); + return 1; + } +} + + +/* + * Test the state of the active-high FPGA DONE pin + */ +int +fpga_done_fn(int cookie) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + PRINTF("%s:%d: DONE check... ", __FUNCTION__, __LINE__); + if (immap->im_cpm.cp_pbdat & (0x80000000 >> FPGA_DONE_BIT_NUM)) { + PRINTF("high\n"); + return FPGA_SUCCESS; + } + else { + PRINTF("low\n"); + return FPGA_FAIL; + } +} + + +/* + * Read FPGA SelectMap data. + */ +int +fpga_read_data_fn(unsigned char *data, int cookie) +{ + vu_char *p = (vu_char *)SELECTMAP_BASE; + + *data = *p; +#if 0 + PRINTF("%s: Read 0x%x into 0x%p\n", __FUNCTION__, (int)data, data); +#endif + return (int)data; +} + + +/* + * Write data to the FPGA SelectMap port + */ +int +fpga_write_data_fn(unsigned char data, int flush, int cookie) +{ + vu_char *p = (vu_char *)SELECTMAP_BASE; + +#if 0 + PRINTF("%s: Write Data 0x%x\n", __FUNCTION__, (int)data); +#endif + *p = data; + return (int)data; +} + + +/* + * Abort and FPGA operation + */ +int +fpga_abort_fn(int cookie) +{ + PRINTF("%s:%d: FPGA program sequence aborted\n", + __FUNCTION__, __LINE__); + return FPGA_FAIL; +} + + +/* + * FPGA pre-configuration function. Just make sure that + * FPGA reset is asserted to keep the FPGA from starting up after + * configuration. + */ +int +fpga_pre_config_fn(int cookie) +{ + PRINTF("%s:%d: FPGA pre-configuration\n", __FUNCTION__, __LINE__); + fpga_reset(TRUE); + return 0; +} + + +/* + * FPGA post configuration function. Blip the FPGA reset line and then see if + * the FPGA appears to be running. + */ +int +fpga_post_config_fn(int cookie) +{ + int rc; + + PRINTF("%s:%d: FPGA post configuration\n", __FUNCTION__, __LINE__); + fpga_reset(TRUE); + udelay(1000); + fpga_reset(FALSE); + udelay (1000); + + /* + * Use the FPGA,s inverting bus test register to do a simple test of the + * processor interface. + */ + rc = test_fpga_ibtr(); + return rc; +} + + +/* + * Clock, chip select and write signal assert functions and error check + * and busy functions. These are only stubs because the GEN860T selectmap + * interface handles sequencing of control signals automatically (it uses + * a memory-mapped interface to the FPGA SelectMap port). The design of + * the interface guarantees that the SelectMap port cannot be overrun so + * no busy check is needed. A configuration error is signalled by INIT + * going low during configuration, so there is no need for a separate error + * function. + */ +int +fpga_clk_fn(int assert_clk, int flush, int cookie) +{ + return assert_clk; +} + +int +fpga_cs_fn(int assert_cs, int flush, int cookie) +{ + return assert_cs; +} + +int +fpga_wr_fn(int assert_write, int flush, int cookie) +{ + return assert_write; +} + +int +fpga_err_fn(int cookie) +{ + return 0; +} + +int +fpga_busy_fn(int cookie) +{ + return 0; +} +#endif + +/* vim: set ts=4 tw=78 sw=4: */ diff --git a/board/gen860t/fpga.h b/board/gen860t/fpga.h new file mode 100644 index 0000000..01967a4 --- /dev/null +++ b/board/gen860t/fpga.h @@ -0,0 +1,45 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.com. + * Keith Outwater, keith_outwater@mvis.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * Virtex2 FPGA configuration support for the GEN860T computer + */ + +extern int gen860t_init_fpga(void); +extern int fpga_pgm_fn(int assert_pgm, int flush, int cookie); +extern int fpga_init_fn(int cookie); +extern int fpga_err_fn(int cookie); +extern int fpga_done_fn(int cookie); +extern int fpga_clk_fn(int assert_clk, int flush, int cookie); +extern int fpga_cs_fn(int assert_cs, int flush, int cookie); +extern int fpga_wr_fn(int assert_write, int flush, int cookie); +extern int fpga_read_data_fn(unsigned char *data, int cookie); +extern int fpga_write_data_fn(unsigned char data, int flush, int cookie); +extern int fpga_busy_fn(int cookie); +extern int fpga_abort_fn(int cookie ); +extern int fpga_pre_config_fn(int cookie ); +extern int fpga_post_config_fn(int cookie ); + +/* vim: set ts=4 sw=4 tw=78: */ diff --git a/board/gen860t/gen860t.c b/board/gen860t/gen860t.c new file mode 100644 index 0000000..02f82ab --- /dev/null +++ b/board/gen860t/gen860t.c @@ -0,0 +1,307 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include "beeper.h" +#include "fpga.h" +#include "ioport.h" + +#ifdef CONFIG_STATUS_LED +#include +#endif + +#if defined(CFG_CMD_MII) && defined(CONFIG_MII) +#include +#endif + +#if 0 +#define GEN860T_DEBUG +#endif + +#ifdef GEN860T_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * The following UPM init tables were generated automatically by + * Motorola's MCUINIT program. See the README file for UPM to + * SDRAM pin assignments if you want to type this data into + * MCUINIT in order to reverse engineer the waveforms. + */ + +/* + * UPM initialization tables for MICRON MT48LC16M16A2TG SDRAM devices + * (UPMA) and Virtex FPGA SelectMap interface (UPMB). + * NOTE that unused areas of the table are used to hold NOP, precharge + * and mode register set sequences. + * + */ +#define UPMA_NOP_ADDR 0x5 +#define UPMA_PRECHARGE_ADDR 0x6 +#define UPMA_MRS_ADDR 0x12 + +#define UPM_SINGLE_READ_ADDR 0x00 +#define UPM_BURST_READ_ADDR 0x08 +#define UPM_SINGLE_WRITE_ADDR 0x18 +#define UPM_BURST_WRITE_ADDR 0x20 +#define UPM_REFRESH_ADDR 0x30 + +const uint sdram_upm_table[] = { + /* single read (offset 0x00 in upm ram) */ + 0x0e0fdc04, 0x01adfc04, 0x0fbffc00, 0x1fff5c05, + 0xffffffff, 0x0fffffcd, 0x0fff0fce, 0xefcfffff, + /* burst read (offset 0x08 in upm ram) */ + 0x0f0fdc04, 0x00fdfc04, 0xf0fffc00, 0xf0fffc00, + 0xf1fffc00, 0xfffffc00, 0xfffffc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0x0ffffff4, 0x1f3d5ff4, + 0xfffffff4, 0xfffffff5, 0xffffffff, 0xffffffff, + /* single write (offset 0x18 in upm ram) */ + 0x0f0fdc04, 0x00ad3c00, 0x1fff5c05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst write (offset 0x20 in upm ram) */ + 0x0f0fdc00, 0x10fd7c00, 0xf0fffc00, 0xf0fffc00, + 0xf1fffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xfffff7ff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* refresh (offset 0x30 in upm ram) */ + 0x1ffddc84, 0xfffffc04, 0xfffffc04, 0xfffffc84, + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* exception (offset 0x3C in upm ram) */ + }; + +const uint selectmap_upm_table[] = { + /* single read (offset 0x00 in upm ram) */ + 0x88fffc06, 0x00fff404, 0x00fffc04, 0x33fffc00, + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst read (offset 0x08 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* single write (offset 0x18 in upm ram) */ + 0x88fffc04, 0x00fff400, 0x77fffc05, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* burst write (offset 0x20 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* refresh (offset 0x30 in upm ram) */ + 0xfffffc04, 0xfffffc05, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, + /* exception (offset 0x3C in upm ram) */ + 0xfffffc05, 0xffffffff, 0xffffffff, 0xffffffff +}; + + +/* + * Check board identity. Always successful (gives information only) + */ +int +checkboard(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + unsigned char *s; + unsigned char buf[64]; + int i; + + i = getenv_r("board_id", buf, sizeof(buf)); + s = (i>0) ? buf : NULL; + + if (s) { + printf("%s ", s); + } else { + printf(" "); + } + + i = getenv_r("serial#", buf, sizeof(buf)); + s = (i>0) ? buf : NULL; + + if (s) { + printf("S/N %s\n", s); + } else { + printf("S/N \n"); + } + + printf("CPU at %s MHz, ",strmhz(buf, gd->cpu_clk)); + printf("local bus at %s MHz\n", strmhz(buf, gd->bus_clk)); + return (1); +} + + +/* + * Initialize SDRAM + */ +long int +initdram(int board_type) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + upmconfig(UPMA, + (uint *)sdram_upm_table, + sizeof(sdram_upm_table) / sizeof(uint) + ); + + /* + * Setup MAMR register + */ + memctl->memc_mptpr = CFG_MPTPR_1BK_8K; + memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ + + /* + * Map CS1* to SDRAM bank + */ + memctl->memc_or1 = CFG_OR1; + memctl->memc_br1 = CFG_BR1; + + /* + * Perform SDRAM initialization sequence: + * 1. Apply at least one NOP command + * 2. 100 uS delay (JEDEC standard says 200 uS) + * 3. Issue 4 precharge commands + * 4. Perform two refresh cycles + * 5. Program mode register + * + * Program SDRAM for standard operation, sequential burst, burst length + * of 4, CAS latency of 2. + */ + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF(0) | UPMA_NOP_ADDR; + udelay(200); + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF(4) | UPMA_PRECHARGE_ADDR; + + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF(2) | UPM_REFRESH_ADDR; + + memctl->memc_mar = 0x00000088; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF(1) | UPMA_MRS_ADDR; + + memctl->memc_mar = 0x00000000; + memctl->memc_mcr = MCR_UPM_A | MCR_OP_RUN | MCR_MB_CS1 | + MCR_MLCF(0) | UPMA_NOP_ADDR; + /* + * Enable refresh + */ + memctl->memc_mamr |= MAMR_PTAE; + + return (SDRAM_SIZE); +} + + +/* + * Disk On Chip (DOC) Millenium initialization. + * The DOC lives in the CS2* space + */ +#if (CONFIG_COMMANDS & CFG_CMD_DOC) +extern void +doc_probe(ulong physadr); + +void +doc_init(void) +{ + printf("Probing at 0x%.8x: ", DOC_BASE); + doc_probe(DOC_BASE); +} +#endif + + +/* + * Miscellaneous intialization + */ +int +misc_init_r (void) +{ +#define MSB_ONE 0x80000000 + + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + /* + * Set up UPMB to handle the Virtex FPGA SelectMap interface + */ + upmconfig(UPMB, (uint *)selectmap_upm_table, + sizeof(selectmap_upm_table) / sizeof(uint)); + + memctl->memc_mbmr = 0x0; + + config_mpc8xx_ioports(immr); + +#if (CONFIG_COMMANDS & CFG_CMD_MII) + mii_init(); +#endif + +#if (CONFIG_FPGA) + gen860t_init_fpga(); +#endif + + return (0); +} + + +/* + * Final init hook before entering command loop. + */ +int +last_stage_init(void) +{ + unsigned char buf[256]; + int i; + + /* set LEDs here since status LED init code has already run */ + status_led_set(STATUS_LED_BIT1, STATUS_LED_ON); + status_led_set(STATUS_LED_BIT3, STATUS_LED_ON); + + /* + * Turn the beeper volume all the way down in case this is a warm + * boot. + */ + set_beeper_volume(-64); + init_beeper(); + + /* + * Read the environment to see what to do with the beeper + */ + i = getenv_r("beeper", buf, sizeof(buf)); + if (i > 0) { + do_beeper(buf); + } + + return 0; +} + +/* vim: set ts=4 sw=4 tw=78 : */ diff --git a/board/gen860t/ioport.c b/board/gen860t/ioport.c new file mode 100644 index 0000000..34f0917 --- /dev/null +++ b/board/gen860t/ioport.c @@ -0,0 +1,276 @@ +/* + * (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 +#include +#include +#include "ioport.h" + +#if 0 +#define IOPORT_DEBUG +#endif + +#ifdef IOPORT_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* + * The ioport configuration table. + */ +const mpc8xx_iop_conf_t iop_conf_tab[NUM_PORTS][PORT_BITS] = { + /* + * Port A configuration + * Pin Signal Type Active Initial state + * PA7 fpgaProgramLowOut Out Low High + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* No pin */ + /* PA15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA9 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 1*/ + /* PA8 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 1*/ + /* PA7 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaProgramLow */ + /* PA6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA5 */ { 1, 0, 0, 1, 0, 0, 0 }, /* grn bicolor LED 0*/ + /* PA4 */ { 1, 0, 0, 1, 0, 0, 0 }, /* red bicolor LED 0*/ + /* PA3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA2 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA1 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PA0 */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + }, + + /* + * Pin Signal Type Active Initial state + * PB14 docBusyLowIn In Low X + * PB15 gpio1Sig Out High Low + * PB16 fpgaDoneBi In High X + * PB17 swBitOkLowOut Out Low Low + * PB19 speakerVolSig Out/Hi-Z High/Low High (Hi-Z) + * PB22 fpgaInitLowBi In Low X + * PB23 batteryOkSig In High X + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* PB31 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB30 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB29 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB28 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB27 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB26 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB25 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB24 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB23 */ { 1, 0, 0, 0, 0, 0, 0 }, /* batteryOk */ + /* PB22 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaInitLowBi */ + /* PB21 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB20 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB19 */ { 1, 0, 0, 1, 1, 1, 0 }, /* speakerVol */ + /* PB18 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PB17 */ { 1, 0, 0, 1, 0, 0, 0 }, /* swBitOkLow */ + /* PB16 */ { 1, 0, 0, 0, 0, 0, 0 }, /* fpgaDone */ + /* PB15 */ { 1, 0, 0, 1, 0, 0, 0 }, /* gpio1 */ + /* PB14 */ { 1, 0, 0, 0, 0, 0, 0 } /* docBusyLow */ + }, + + /* + * Pin Signal Type Active Initial state + * PC4 i2cBus1EnSig Out High High + * PC5 i2cBus2EnSig Out High High + * PC6 gpio0Sig Out High Low + * PC8 i2cBus3EnSig Out High High + * PC10 i2cBus4EnSig Out High High + * PC11 fpgaResetLowOut Out Low High + * PC12 systemBitOkIn In High X + * PC15 selfDreqLow In Low X + */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC15 */ { 1, 0, 0, 0, 0, 0, 0 }, /* selfDreqLowIn */ + /* PC14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC12 */ { 1, 0, 0, 0, 0, 0, 0 }, /* systemBitOkIn */ + /* PC11 */ { 1, 0, 0, 1, 0, 1, 0 }, /* fpgaResetLowOut */ + /* PC10 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus4EnSig */ + /* PC9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC8 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus3EnSig */ + /* PC7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PC6 */ { 1, 0, 0, 1, 0, 1, 0 }, /* gpio0 */ + /* PC5 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus2EnSig */ + /* PC4 */ { 1, 0, 0, 1, 0, 1, 0 }, /* i2cBus1EnSig */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + }, + + /* Port D configuration */ + { /* conf ppar psor pdir podr pdat pint function */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD15 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD14 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD13 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD12 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD11 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD10 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD9 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD8 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD7 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD6 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD5 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD4 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* PD3 */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 }, /* */ + /* N/A */ { 0, 0, 0, 0, 0, 0, 0 } /* */ + } +}; + +/* + * Configure the MPC8XX I/O ports per the ioport configuration table + * (taken from ./cpu/mpc8260/cpu_init.c) + */ +void +config_mpc8xx_ioports(volatile immap_t *immr) +{ + int portnum; + + for (portnum = 0; portnum < NUM_PORTS; portnum++) { + uint pmsk = 0, ppar = 0, psor = 0, pdir = 0; + uint podr = 0, pdat = 0, pint = 0; + uint msk = 1; + mpc8xx_iop_conf_t *iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][0]; + mpc8xx_iop_conf_t *eiopc = iopc + PORT_BITS; + + /* + * For all ports except port B, ignore the two don't care entries + * in the configuration tables. + */ + if (portnum != 1) { + iopc = (mpc8xx_iop_conf_t *)&iop_conf_tab[portnum][2]; + } + + /* + * NOTE: index 0 refers to pin 17, index 17 refers to pin 0 + */ + while (iopc < eiopc) { + if (iopc->conf) { + pmsk |= msk; + if (iopc->ppar) ppar |= msk; + if (iopc->psor) psor |= msk; + if (iopc->pdir) pdir |= msk; + if (iopc->podr) podr |= msk; + if (iopc->pdat) pdat |= msk; + if (iopc->pint) pint |= msk; + } + msk <<= 1; + iopc++; + } + + PRINTF("%s:%d:\n portnum=%d ", __FUNCTION__, __LINE__, portnum); +#ifdef IOPORT_DEBUG + switch(portnum) { + case 0: printf("(A)\n"); break; + case 1: printf("(B)\n"); break; + case 2: printf("(C)\n"); break; + case 3: printf("(D)\n"); break; + default: printf("(?)\n"); break; + } +#endif + PRINTF(" ppar=0x%.8x pdir=0x%.8x podr=0x%.8x\n" + " pdat=0x%.8x psor=0x%.8x pint=0x%.8x pmsk=0x%.8x\n", + ppar, pdir, podr, pdat, psor, pint, pmsk); + + /* + * Have to handle the ioports on a port-by-port basis since there + * are three different flavors. + */ + if (pmsk != 0) { + uint tpmsk = ~pmsk; + + if (0 == portnum) { /* port A */ + immr->im_ioport.iop_papar &= tpmsk; + immr->im_ioport.iop_padat = + (immr->im_ioport.iop_padat & tpmsk) | pdat; + immr->im_ioport.iop_padir = + (immr->im_ioport.iop_padir & tpmsk) | pdir; + immr->im_ioport.iop_paodr = + (immr->im_ioport.iop_paodr & tpmsk) | podr; + immr->im_ioport.iop_papar |= ppar; + } + else if (1 == portnum) { /* port B */ + immr->im_cpm.cp_pbpar &= tpmsk; + immr->im_cpm.cp_pbdat = (immr->im_cpm.cp_pbdat & tpmsk) | pdat; + immr->im_cpm.cp_pbdir = (immr->im_cpm.cp_pbdir & tpmsk) | pdir; + immr->im_cpm.cp_pbodr = (immr->im_cpm.cp_pbodr & tpmsk) | podr; + immr->im_cpm.cp_pbpar |= ppar; + } + else if (2 == portnum) { /* port C */ + immr->im_ioport.iop_pcpar &= tpmsk; + immr->im_ioport.iop_pcdat = + (immr->im_ioport.iop_pcdat & tpmsk) | pdat; + immr->im_ioport.iop_pcdir = + (immr->im_ioport.iop_pcdir & tpmsk) | pdir; + immr->im_ioport.iop_pcint = + (immr->im_ioport.iop_pcint & tpmsk) | pint; + immr->im_ioport.iop_pcso = + (immr->im_ioport.iop_pcso & tpmsk) | psor; + immr->im_ioport.iop_pcpar |= ppar; + } + else if (3 == portnum) { /* port D */ + immr->im_ioport.iop_pdpar &= tpmsk; + immr->im_ioport.iop_pddat = + (immr->im_ioport.iop_pddat & tpmsk) | pdat; + immr->im_ioport.iop_pddir = + (immr->im_ioport.iop_pddir & tpmsk) | pdir; + immr->im_ioport.iop_pdpar |= ppar; + } + } + } + + PRINTF("%s:%d: Port A:\n papar=0x%.4x padir=0x%.4x" + " paodr=0x%.4x\n padat=0x%.4x\n", __FUNCTION__, __LINE__, + immr->im_ioport.iop_papar, immr->im_ioport.iop_padir, + immr->im_ioport.iop_paodr, immr->im_ioport.iop_padat); + PRINTF("%s:%d: Port B:\n pbpar=0x%.8x pbdir=0x%.8x" + " pbodr=0x%.8x\n pbdat=0x%.8x\n", __FUNCTION__, __LINE__, + immr->im_cpm.cp_pbpar, immr->im_cpm.cp_pbdir, + immr->im_cpm.cp_pbodr, immr->im_cpm.cp_pbdat); + PRINTF("%s:%d: Port C:\n pcpar=0x%.4x pcdir=0x%.4x" + " pcdat=0x%.4x\n pcso=0x%.4x pcint=0x%.4x\n ", + __FUNCTION__, __LINE__, immr->im_ioport.iop_pcpar, + immr->im_ioport.iop_pcdir, immr->im_ioport.iop_pcdat, + immr->im_ioport.iop_pcso, immr->im_ioport.iop_pcint); + PRINTF("%s:%d: Port D:\n pdpar=0x%.4x pddir=0x%.4x" + " pddat=0x%.4x\n", __FUNCTION__, __LINE__, + immr->im_ioport.iop_pdpar, immr->im_ioport.iop_pddir, + immr->im_ioport.iop_pddat); +} + +/* vim: set ts=4 sw=4 tw=78: */ diff --git a/board/gen860t/ioport.h b/board/gen860t/ioport.h new file mode 100644 index 0000000..34a2d7b --- /dev/null +++ b/board/gen860t/ioport.h @@ -0,0 +1,44 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#define NUM_PORTS 4 +#define PORT_BITS 18 + +/* + * This structure provides configuration information for one port pin. + * We include all fields needed to initialize any of the ioports. + */ +typedef struct { + unsigned char conf:1; /* If 1, configure this port */ + unsigned char ppar:1; /* Port Pin Assignment Register */ + unsigned char psor:1; /* Port Special Options Register */ + unsigned char pdir:1; /* Port Data Direction Register */ + unsigned char podr:1; /* Port Open Drain Register */ + unsigned char pdat:1; /* Port Data Register */ + unsigned char pint:1; /* Port Interrupt Register */ +} mpc8xx_iop_conf_t; + +extern void config_mpc8xx_ioports(volatile immap_t *immr); + +/* vim: set ts=4 tw=78 sw=4: */ diff --git a/board/gen860t/ppcboot.lds b/board/gen860t/ppcboot.lds new file mode 100644 index 0000000..054a8cc --- /dev/null +++ b/board/gen860t/ppcboot.lds @@ -0,0 +1,135 @@ +/* + * Linker command file for the GEN860T board. + * + * (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); +SECTIONS +{ + /* + * Read-only sections, merged into text segment: + */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/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/common/cmd_jffs2.c b/common/cmd_jffs2.c index b11a5fb..99271e1 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -34,39 +34,51 @@ #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) #include -#include -static void -get_part_info(struct part_info *part) +#ifndef CFG_JFFS_CUSTOM_PART + +static struct part_info part; + +struct part_info* +jffs2_part_info(int part_num) { extern flash_info_t flash_info[]; /* info for FLASH chips */ int i; + + if(part.usr_priv==(void*)1) + return ∂ + + memset(&part, 0, sizeof(part)); - memset(part, 0, sizeof(*part)); #if defined(CFG_JFFS2_FIRST_SECTOR) - part->offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; + part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR]; #else - part->offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[0]; + part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[0]; #endif /* Figure out flash partition size */ for (i = CFG_JFFS2_FIRST_BANK; i < CFG_JFFS2_NUM_BANKS+CFG_JFFS2_FIRST_BANK; i++) - part->size += flash_info[i].size; + part.size += flash_info[i].size; #if defined(CFG_JFFS2_FIRST_SECTOR) && (CFG_JFFS2_FIRST_SECTOR > 0) - part->size -= + part.size -= flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR] - flash_info[CFG_JFFS2_FIRST_BANK].start[0]; #endif /* unused in current jffs2 loader */ - part->erasesize = 0; + part.erasesize = 0; + + /* Mark the struct as ready */ + part.usr_priv=(void*)1; + + return ∂ } +#endif /* ifndef CFG_JFFS_CUSTOM_PART */ int do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info part; char *filename = "vmlinuz"; ulong offset = CFG_LOAD_ADDR; int size; @@ -78,10 +90,8 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) filename = argv[2]; } - get_part_info(&part); - printf("### JFFS2 loading '%s' to 0x%lx\n", filename, offset); - size = jffs2_1pass_load((char *)offset, &part, filename); + size = jffs2_1pass_load((char *)offset, jffs2_part_info(0), filename); if (size > 0) { printf("### JFFS2 load compleate: %d bytes loaded to 0x%lx\n", @@ -95,15 +105,13 @@ do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int do_jffs2_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info part; char *filename = "/"; int ret; if (argc == 2) filename = argv[1]; - get_part_info(&part); - ret = jffs2_1pass_ls(&part, filename); + ret = jffs2_1pass_ls(jffs2_part_info(0), filename); return (ret == 1); } @@ -111,11 +119,9 @@ do_jffs2_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) int do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) { - struct part_info part; int ret; - get_part_info(&part); - ret = jffs2_1pass_info(&part); + ret = jffs2_1pass_info(jffs2_part_info(0)); return (ret == 1); } diff --git a/common/cmd_mii.c b/common/cmd_mii.c index 6e07eb3..b5963f1 100644 --- a/common/cmd_mii.c +++ b/common/cmd_mii.c @@ -56,7 +56,7 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) int rcode = 0; #ifdef CONFIG_MPC860 - mii_init (bd); + mii_init (); #endif /* diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c index 64cdafd..d943fa9 100644 --- a/cpu/mpc8xx/fec.c +++ b/cpu/mpc8xx/fec.c @@ -563,8 +563,11 @@ static int mii_init_done = 0; * This function is a subset of eth_init **************************************************************************** */ -void mii_init (bd_t *bd) +void mii_init (void) { + DECLARE_GLOBAL_DATA_PTR; + bd_t *bd = gd->bd; + volatile immap_t *immr = (immap_t *) CFG_IMMR; volatile fec_t *fecp = &(immr->im_cpm.cp_fec); int i; diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c index 2116fab..1463426 100644 --- a/cpu/ppc4xx/405gp_enet.c +++ b/cpu/ppc4xx/405gp_enet.c @@ -298,7 +298,14 @@ int eth_init (bd_t * bis) } /* set the Mal configuration reg */ +#if defined(CONFIG_440) + /* Errata 1.12: MAL_1 -- Disable MAL bursting */ + if( get_pvr() == PVR_440GP_RB ) + mtdcr (malmcr, MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); + else +#else mtdcr (malmcr, MAL_CR_PLBB | MAL_CR_OPBBL | MAL_CR_LEA | MAL_CR_PLBLT_DEFAULT); +#endif /* Free "old" buffers */ if (alloc_tx_buf) free(alloc_tx_buf); diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c index 1c01315..efd1a91 100644 --- a/cpu/ppc4xx/405gp_pci.c +++ b/cpu/ppc4xx/405gp_pci.c @@ -72,11 +72,13 @@ #include #include #include +#if !defined(CONFIG_440) #include <405gp_pci.h> +#endif #include #include -#if defined(CONFIG_405GP) || defined(CONFIG_440) +#if defined(CONFIG_405GP) #ifdef CONFIG_PCI @@ -387,3 +389,114 @@ void pci_init(void) #endif /* CONFIG_PCI */ #endif /* CONFIG_405GP */ + +/*-----------------------------------------------------------------------------+ + * CONFIG_440 + *-----------------------------------------------------------------------------*/ +#if defined(CONFIG_440) && defined(CONFIG_PCI) + +static struct pci_controller ppc440_hose = {0}; + + +void pci_440_init(gd_t *gd, struct pci_controller *hose) +{ + int reg_num = 0; + unsigned long strap; + + /*--------------------------------------------------------------------------+ + * The PCI initialization sequence enable bit must be set ... if not abort + * pci setup since updating the bit requires chip reset. + *--------------------------------------------------------------------------*/ + strap = mfdcr(cpc0_strp1); + if( (strap & 0x00040000) == 0 ){ + printf("PCI: CPC0_STRP1[PISE] not set.\n"); + printf("PCI: Configuration aborted.\n"); + return; + } + + /*--------------------------------------------------------------------------+ + * PCI controller init + *--------------------------------------------------------------------------*/ + hose->first_busno = 0; + hose->last_busno = 0xff; + + pci_set_region(hose->regions + reg_num++, + 0x00000000, + PCIX0_IOBASE, + 0x10000, + PCI_REGION_IO); + + pci_set_region(hose->regions + reg_num++, + CFG_PCI_TARGBASE, + CFG_PCI_MEMBASE, + 0x10000000, + PCI_REGION_MEM ); + hose->region_count = reg_num; + + pci_setup_indirect(hose, PCIX0_CFGADR, PCIX0_CFGDATA); + +#if defined(CFG_PCI_PRE_INIT) + /* Let board change/modify hose & do initial checks */ + if( pci_pre_init( gd, hose ) == 0 ){ + printf("PCI: Board-specific initialization failed.\n"); + printf("PCI: Configuration aborted.\n"); + return; + } +#endif + + pci_register_hose( hose ); + + /*--------------------------------------------------------------------------+ + * PCI target init + *--------------------------------------------------------------------------*/ +#if defined(CFG_PCI_TARGET_INIT) + pci_target_init(gd, hose); /* Let board setup pci target */ +#else + out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); + out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_ID ); + out16r( PCIX0_CLS, 0x00060000 ); /* Bridge, host bridge */ +#endif + + out32r( PCIX0_BRDGOPT1, 0x10000060 ); /* PLB Rq pri highest */ + out32r( PCIX0_BRDGOPT2, in32(PCIX0_BRDGOPT2) | 1 ); /* Enable host config */ + + /*--------------------------------------------------------------------------+ + * PCI master init: default is one 256MB region for PCI memory: + * 0x3_00000000 - 0x3_0FFFFFFF ==> CFG_PCI_MEMBASE + *--------------------------------------------------------------------------*/ +#if defined(CFG_PCI_MASTER_INIT) + pci_master_init(gd, hose); /* Let board setup pci master */ +#else + out32r( PCIX0_POM0SA, 0 ); /* disable */ + out32r( PCIX0_POM1SA, 0 ); /* disable */ + out32r( PCIX0_POM2SA, 0 ); /* disable */ + out32r( PCIX0_POM0LAL, 0x00000000 ); + out32r( PCIX0_POM0LAH, 0x00000003 ); + out32r( PCIX0_POM0PCIAL, CFG_PCI_MEMBASE ); + out32r( PCIX0_POM0PCIAH, 0x00000000 ); + out32r( PCIX0_POM0SA, 0xf0000001 ); /* 256MB, enabled */ + out32r( PCIX0_STS, in32r( PCIX0_STS ) & ~0x0000fff8 ); +#endif + + /*--------------------------------------------------------------------------+ + * PCI host configuration -- we don't make any assumptions here ... the + * _board_must_indicate_ what to do -- there's just too many runtime + * scenarios in environments like cPCI, PPMC, etc. to make a determination + * based on hard-coded values or state of arbiter enable. + *--------------------------------------------------------------------------*/ + if( is_pci_host(gd, hose) ){ +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + out16r( PCIX0_CMD, in16r( PCIX0_CMD ) | PCI_COMMAND_MASTER); + hose->last_busno = pci_hose_scan(hose); + } +} + + +void pci_init(gd_t *gd) +{ + pci_440_init( gd, &ppc440_hose ); +} + +#endif /* CONFIG_440 & CONFIG_PCI */ diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c index 591d37f..d8602d3 100644 --- a/cpu/ppc4xx/cpu.c +++ b/cpu/ppc4xx/cpu.c @@ -40,6 +40,10 @@ #include +#if defined(CONFIG_440) +static int do_chip_reset( unsigned long sys0, unsigned long sys1 ); +#endif + /* ------------------------------------------------------------------------- */ int checkcpu (void) @@ -138,6 +142,13 @@ int checkcpu (void) { case PVR_440GP_RB: putc('B'); + /* See errata 1.12: CHIP_4 */ + if( ( mfdcr(cpc0_sys0) != mfdcr(cpc0_strp0) ) + ||( mfdcr(cpc0_sys1) != mfdcr(cpc0_strp1) ) ){ + puts("\n\t CPC0_SYSx DCRs corrupted. Resetting chip ...\n"); + udelay( 1000 * 1000 ); /* Give time for serial buf to clear */ + do_chip_reset( mfdcr(cpc0_strp0), mfdcr(cpc0_strp1) ); + } break; case PVR_440GP_RC: putc('C'); @@ -162,10 +173,31 @@ int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) * Initiate system reset in debug control register DBCR */ __asm__ __volatile__("lis 3, 0x3000" ::: "r3"); +#if defined(CONFIG_440) + __asm__ __volatile__("mtspr 0x134, 3"); +#else __asm__ __volatile__("mtspr 0x3f2, 3"); +#endif return 1; } +#if defined(CONFIG_440) +static +int do_chip_reset( unsigned long sys0, unsigned long sys1 ) +{ + /* Changes to cpc0_sys0 and cpc0_sys1 require chip + * reset. + */ + mtdcr( cntrl0, mfdcr(cntrl0) | 0x80000000 ); /* Set SWE */ + mtdcr( cpc0_sys0, sys0 ); + mtdcr( cpc0_sys1, sys1 ); + mtdcr( cntrl0, mfdcr(cntrl0) & ~0x80000000 ); /* Clr SWE */ + mtspr( dbcr0, 0x20000000); /* Reset the chip */ + + return 1; +} +#endif + /* * Get timebase clock frequency @@ -173,8 +205,10 @@ int do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) unsigned long get_tbclk (void) { #if defined(CONFIG_440) - /* FIXME: This should be done like 405GP */ - return(400 * 1000 * 1000 ); /* Assume 400 MHz for now */ + sys_info_t sys_info; + + get_sys_info(&sys_info); + return (sys_info.freqProcessor); #endif #if defined(CONFIG_405GP) || defined(CONFIG_405CR) diff --git a/cpu/ppc4xx/interrupts.c b/cpu/ppc4xx/interrupts.c index c9311c3..0867de4 100644 --- a/cpu/ppc4xx/interrupts.c +++ b/cpu/ppc4xx/interrupts.c @@ -158,14 +158,14 @@ int interrupt_init(void) */ #if defined(CONFIG_440) val = mfspr( tcr ); - val &= (~0x04400000); /* clear DIS & ARE */ + val &= (~0x04400000); /* clear DIS & ARE */ mtspr( tcr, val ); - mtspr( dec, 0 ); /* Prevent exception after TSR clear*/ - mtspr( decar, 0 ); /* clear reload */ - mtspr( tsr, 0x08000000 ); /* clear DEC status */ - val = gd->bd->bi_intfreq/1000; - mtspr( decar, val ); /* Set auto-reload value */ - mtspr( dec, val ); /* Set inital val */ + mtspr( dec, 0 ); /* Prevent exception after TSR clear*/ + mtspr( decar, 0 ); /* clear reload */ + mtspr( tsr, 0x08000000 ); /* clear DEC status */ + val = gd->bd->bi_intfreq/100; /* 10 msec */ + mtspr( decar, val ); /* Set auto-reload value */ + mtspr( dec, val ); /* Set inital val */ #else set_pit(gd->bd->bi_intfreq / 1000); #endif @@ -181,11 +181,9 @@ int interrupt_init(void) /* * Enable PIT */ -#if !defined(CONFIG_440) val = mfspr(tcr); val |= 0x04400000; mtspr(tcr, val); -#endif /* * Set EVPR to 0 @@ -231,7 +229,8 @@ void external_interrupt(struct pt_regs *regs) irq_vecs[vec].count++; if (irq_vecs[vec].handler != NULL) { - (*irq_vecs[vec].handler)(irq_vecs[vec].arg); /* call isr */ + /* call isr */ + (*irq_vecs[vec].handler)(irq_vecs[vec].arg); } else { mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> vec)); printf ("Masking bogus interrupt vector 0x%x\n", vec); @@ -274,7 +273,8 @@ void uic1_interrupt( void * parms) irq_vecs1[vec].count++; if (irq_vecs1[vec].handler != NULL) { - (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg); /* call isr */ + /* call isr */ + (*irq_vecs1[vec].handler)(irq_vecs1[vec].arg); } else { mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> vec)); printf ("Masking bogus interrupt vector (uic1) 0x%x\n", vec); @@ -306,14 +306,14 @@ irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) { struct irq_action *irqa = irq_vecs; int i = vec; - + #if defined(CONFIG_440) if (vec > 31) { i = vec - 32; irqa = irq_vecs1; } #endif - + if (irqa[i].handler != NULL) { printf ("Interrupt vector %d: handler 0x%x replacing 0x%x\n", vec, (uint)handler, (uint)irqa[i].handler); @@ -337,26 +337,26 @@ irq_free_handler(int vec) { struct irq_action *irqa = irq_vecs; int i = vec; - + #if defined(CONFIG_440) if (vec > 31) { irqa = irq_vecs1; i = vec - 32; } #endif - + #if 0 printf ("Free interrupt for vector %d ==> %p\n", vec, irq_vecs[vec].handler); #endif - + #if defined(CONFIG_440) if (vec > 31) mtdcr(uic1er, mfdcr(uic1er) & ~(0x80000000 >> i)); else #endif mtdcr(uicer, mfdcr(uicer) & ~(0x80000000 >> i)); - + irqa[i].handler = NULL; irqa[i].arg = NULL; } @@ -424,11 +424,11 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) for (vec=0; vec<32; vec++) { if (irq_vecs[vec].handler != NULL) { - printf("%02d %08lx %08lx %d\n", - vec, - (ulong)irq_vecs[vec].handler, - (ulong)irq_vecs[vec].arg, - irq_vecs[vec].count); + printf ("%02d %08lx %08lx %d\n", + vec, + (ulong)irq_vecs[vec].handler, + (ulong)irq_vecs[vec].arg, + irq_vecs[vec].count); } } @@ -439,9 +439,9 @@ do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) for (vec=0; vec<32; vec++) { if (irq_vecs1[vec].handler != NULL) - printf("%02d %08lx %08lx %d\n", - vec+31, (ulong)irq_vecs1[vec].handler, - (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count); + printf ("%02d %08lx %08lx %d\n", + vec+31, (ulong)irq_vecs1[vec].handler, + (ulong)irq_vecs1[vec].arg, irq_vecs1[vec].count); } printf("\n"); #endif diff --git a/cpu/ppc4xx/spd_sdram.c b/cpu/ppc4xx/spd_sdram.c index 61097c6..2bbfdd5 100644 --- a/cpu/ppc4xx/spd_sdram.c +++ b/cpu/ppc4xx/spd_sdram.c @@ -12,6 +12,10 @@ * running out of cache memory during serial/console init, then running * this code later. * + * (C) Copyright 2002 + * Jun Gu, Artesyn Technology, jung@artesyncp.com + * Support for IBM 440 based on OpenBIOS draminit.c from IBM. + * * See file CREDITS for list of people who contributed to this * project. * @@ -38,6 +42,8 @@ #ifdef CONFIG_SPD_EEPROM +#ifndef CONFIG_440 /* for 405 WALNUT board */ + #define SDRAM0_CFG_DCE 0x80000000 #define SDRAM0_CFG_SRE 0x40000000 #define SDRAM0_CFG_PME 0x20000000 @@ -437,4 +443,1311 @@ int spd_read(uint addr) return 0; } -#endif /* CONFIG_DIMM_EEPROM */ +#else /* CONFIG_440 */ + +/*----------------------------------------------------------------------------- +| Memory Controller Options 0 ++-----------------------------------------------------------------------------*/ +#define SDRAM_CFG0_DCEN 0x80000000 /* SDRAM Controller Enable */ +#define SDRAM_CFG0_MCHK_MASK 0x30000000 /* Memory data errchecking mask */ +#define SDRAM_CFG0_MCHK_NON 0x00000000 /* No ECC generation */ +#define SDRAM_CFG0_MCHK_GEN 0x20000000 /* ECC generation */ +#define SDRAM_CFG0_MCHK_CHK 0x30000000 /* ECC generation and checking */ +#define SDRAM_CFG0_RDEN 0x08000000 /* Registered DIMM enable */ +#define SDRAM_CFG0_PMUD 0x04000000 /* Page management unit */ +#define SDRAM_CFG0_DMWD_MASK 0x02000000 /* DRAM width mask */ +#define SDRAM_CFG0_DMWD_32 0x00000000 /* 32 bits */ +#define SDRAM_CFG0_DMWD_64 0x02000000 /* 64 bits */ +#define SDRAM_CFG0_UIOS_MASK 0x00C00000 /* Unused IO State */ +#define SDRAM_CFG0_PDP 0x00200000 /* Page deallocation policy */ + +/*----------------------------------------------------------------------------- +| Memory Controller Options 1 ++-----------------------------------------------------------------------------*/ +#define SDRAM_CFG1_SRE 0x80000000 /* Self-Refresh Entry */ +#define SDRAM_CFG1_PMEN 0x40000000 /* Power Management Enable */ + +/*-----------------------------------------------------------------------------+ +| SDRAM DEVPOT Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_DEVOPT_DLL 0x80000000 +#define SDRAM_DEVOPT_DS 0x40000000 + +/*-----------------------------------------------------------------------------+ +| SDRAM MCSTS Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_MCSTS_MRSC 0x80000000 +#define SDRAM_MCSTS_SRMS 0x40000000 +#define SDRAM_MCSTS_CIS 0x20000000 + +/*----------------------------------------------------------------------------- +| SDRAM Refresh Timer Register ++-----------------------------------------------------------------------------*/ +#define SDRAM_RTR_RINT_MASK 0xFFFF0000 +#define SDRAM_RTR_RINT_ENCODE(n) (((n) << 16) & SDRAM_RTR_RINT_MASK) +#define sdram_HZ_to_ns(hertz) (1000000000/(hertz)) + +/*-----------------------------------------------------------------------------+ +| SDRAM UABus Base Address Reg ++-----------------------------------------------------------------------------*/ +#define SDRAM_UABBA_UBBA_MASK 0x0000000F + +/*-----------------------------------------------------------------------------+ +| Memory Bank 0-7 configuration ++-----------------------------------------------------------------------------*/ +#define SDRAM_BXCR_SDBA_MASK 0xff800000 /* Base address */ +#define SDRAM_BXCR_SDSZ_MASK 0x000e0000 /* Size */ +#define SDRAM_BXCR_SDSZ_8 0x00020000 /* 8M */ +#define SDRAM_BXCR_SDSZ_16 0x00040000 /* 16M */ +#define SDRAM_BXCR_SDSZ_32 0x00060000 /* 32M */ +#define SDRAM_BXCR_SDSZ_64 0x00080000 /* 64M */ +#define SDRAM_BXCR_SDSZ_128 0x000a0000 /* 128M */ +#define SDRAM_BXCR_SDSZ_256 0x000c0000 /* 256M */ +#define SDRAM_BXCR_SDSZ_512 0x000e0000 /* 512M */ +#define SDRAM_BXCR_SDAM_MASK 0x0000e000 /* Addressing mode */ +#define SDRAM_BXCR_SDAM_1 0x00000000 /* Mode 1 */ +#define SDRAM_BXCR_SDAM_2 0x00002000 /* Mode 2 */ +#define SDRAM_BXCR_SDAM_3 0x00004000 /* Mode 3 */ +#define SDRAM_BXCR_SDAM_4 0x00006000 /* Mode 4 */ +#define SDRAM_BXCR_SDBE 0x00000001 /* Memory Bank Enable */ + +/*-----------------------------------------------------------------------------+ +| SDRAM TR0 Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_TR0_SDWR_MASK 0x80000000 +#define SDRAM_TR0_SDWR_2_CLK 0x00000000 +#define SDRAM_TR0_SDWR_3_CLK 0x80000000 +#define SDRAM_TR0_SDWD_MASK 0x40000000 +#define SDRAM_TR0_SDWD_0_CLK 0x00000000 +#define SDRAM_TR0_SDWD_1_CLK 0x40000000 +#define SDRAM_TR0_SDCL_MASK 0x01800000 +#define SDRAM_TR0_SDCL_2_0_CLK 0x00800000 +#define SDRAM_TR0_SDCL_2_5_CLK 0x01000000 +#define SDRAM_TR0_SDCL_3_0_CLK 0x01800000 +#define SDRAM_TR0_SDPA_MASK 0x000C0000 +#define SDRAM_TR0_SDPA_2_CLK 0x00040000 +#define SDRAM_TR0_SDPA_3_CLK 0x00080000 +#define SDRAM_TR0_SDPA_4_CLK 0x000C0000 +#define SDRAM_TR0_SDCP_MASK 0x00030000 +#define SDRAM_TR0_SDCP_2_CLK 0x00000000 +#define SDRAM_TR0_SDCP_3_CLK 0x00010000 +#define SDRAM_TR0_SDCP_4_CLK 0x00020000 +#define SDRAM_TR0_SDCP_5_CLK 0x00030000 +#define SDRAM_TR0_SDLD_MASK 0x0000C000 +#define SDRAM_TR0_SDLD_1_CLK 0x00000000 +#define SDRAM_TR0_SDLD_2_CLK 0x00004000 +#define SDRAM_TR0_SDRA_MASK 0x0000001C +#define SDRAM_TR0_SDRA_6_CLK 0x00000000 +#define SDRAM_TR0_SDRA_7_CLK 0x00000004 +#define SDRAM_TR0_SDRA_8_CLK 0x00000008 +#define SDRAM_TR0_SDRA_9_CLK 0x0000000C +#define SDRAM_TR0_SDRA_10_CLK 0x00000010 +#define SDRAM_TR0_SDRA_11_CLK 0x00000014 +#define SDRAM_TR0_SDRA_12_CLK 0x00000018 +#define SDRAM_TR0_SDRA_13_CLK 0x0000001C +#define SDRAM_TR0_SDRD_MASK 0x00000003 +#define SDRAM_TR0_SDRD_2_CLK 0x00000001 +#define SDRAM_TR0_SDRD_3_CLK 0x00000002 +#define SDRAM_TR0_SDRD_4_CLK 0x00000003 + +/*-----------------------------------------------------------------------------+ +| SDRAM TR1 Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_TR1_RDSS_MASK 0xC0000000 +#define SDRAM_TR1_RDSS_TR0 0x00000000 +#define SDRAM_TR1_RDSS_TR1 0x40000000 +#define SDRAM_TR1_RDSS_TR2 0x80000000 +#define SDRAM_TR1_RDSS_TR3 0xC0000000 +#define SDRAM_TR1_RDSL_MASK 0x00C00000 +#define SDRAM_TR1_RDSL_STAGE1 0x00000000 +#define SDRAM_TR1_RDSL_STAGE2 0x00400000 +#define SDRAM_TR1_RDSL_STAGE3 0x00800000 +#define SDRAM_TR1_RDCD_MASK 0x00000800 +#define SDRAM_TR1_RDCD_RCD_0_0 0x00000000 +#define SDRAM_TR1_RDCD_RCD_1_2 0x00000800 +#define SDRAM_TR1_RDCT_MASK 0x000001FF +#define SDRAM_TR1_RDCT_ENCODE(x) (((x) << 0) & SDRAM_TR1_RDCT_MASK) +#define SDRAM_TR1_RDCT_DECODE(x) (((x) & SDRAM_TR1_RDCT_MASK) >> 0) +#define SDRAM_TR1_RDCT_MIN 0x00000000 +#define SDRAM_TR1_RDCT_MAX 0x000001FF + +/*-----------------------------------------------------------------------------+ +| SDRAM WDDCTR Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_WDDCTR_WRCP_MASK 0xC0000000 +#define SDRAM_WDDCTR_WRCP_0DEG 0x00000000 +#define SDRAM_WDDCTR_WRCP_90DEG 0x40000000 +#define SDRAM_WDDCTR_WRCP_180DEG 0x80000000 +#define SDRAM_WDDCTR_DCD_MASK 0x000001FF + +/*-----------------------------------------------------------------------------+ +| SDRAM CLKTR Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_CLKTR_CLKP_MASK 0xC0000000 +#define SDRAM_CLKTR_CLKP_0DEG 0x00000000 +#define SDRAM_CLKTR_CLKP_90DEG 0x40000000 +#define SDRAM_CLKTR_CLKP_180DEG 0x80000000 +#define SDRAM_CLKTR_DCDT_MASK 0x000001FF + +/*-----------------------------------------------------------------------------+ +| SDRAM DLYCAL Options ++-----------------------------------------------------------------------------*/ +#define SDRAM_DLYCAL_DLCV_MASK 0x000003FC +#define SDRAM_DLYCAL_DLCV_ENCODE(x) (((x)<<2) & SDRAM_DLYCAL_DLCV_MASK) +#define SDRAM_DLYCAL_DLCV_DECODE(x) (((x) & SDRAM_DLYCAL_DLCV_MASK)>>2) + +/*-----------------------------------------------------------------------------+ +| General Definition ++-----------------------------------------------------------------------------*/ +#define DEFAULT_SPD_ADDR1 0x53 +#define DEFAULT_SPD_ADDR2 0x52 +#define ONE_BILLION 1000000000 +#define MAXBANKS 4 /* at most 4 dimm banks */ +#define MAX_SPD_BYTES 256 +#define NUMHALFCYCLES 4 +#define NUMMEMTESTS 8 +#define NUMMEMWORDS 8 +#define MAXBXCR 4 +#define TRUE 1 +#define FALSE 0 + +const unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { + {0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, + 0xFFFFFFFF, 0xFFFFFFFF}, + {0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, + 0x00000000, 0x00000000}, + {0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, + 0x55555555, 0x55555555}, + {0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, + 0xAAAAAAAA, 0xAAAAAAAA}, + {0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, + 0x5A5A5A5A, 0x5A5A5A5A}, + {0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, + 0xA5A5A5A5, 0xA5A5A5A5}, + {0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, + 0x55AA55AA, 0x55AA55AA}, + {0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, + 0xAA55AA55, 0xAA55AA55} +}; + + +unsigned char spd_read(uchar chip, uint addr); + +void get_spd_info(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void check_mem_type + (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void check_volt_type + (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void program_cfg0(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void program_cfg1(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void program_rtr (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void program_tr0 (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +void program_tr1 (void); + +void program_ecc (unsigned long num_bytes); + +unsigned +long program_bxcr(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks); + +/* + * This function is reading data from the DIMM module EEPROM over the SPD bus + * and uses that to program the sdram controller. + * + * This works on boards that has the same schematics that the IBM walnut has. + * + * BUG: Don't handle ECC memory + * BUG: A few values in the TR register is currently hardcoded + */ + +long int spd_sdram(void) { + unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS; + unsigned long dimm_populated[sizeof(iic0_dimm_addr)]; + unsigned long total_size; + unsigned long cfg0; + unsigned long mcsts; + unsigned long num_dimm_banks; /* on board dimm banks */ + + num_dimm_banks = sizeof(iic0_dimm_addr); + + /* + * Make sure I2C controller is initialized + * before continuing. + */ + i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + + /* + * Read the SPD information using I2C interface. Check to see if the + * DIMM slots are populated. + */ + get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * Check the memory type for the dimms plugged. + */ + check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * Check the voltage type for the dimms plugged. + */ + check_volt_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * program 440GP SDRAM controller options (SDRAM0_CFG0) + */ + program_cfg0(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * program 440GP SDRAM controller options (SDRAM0_CFG1) + */ + program_cfg1(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * program SDRAM refresh register (SDRAM0_RTR) + */ + program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * program SDRAM Timing Register 0 (SDRAM0_TR0) + */ + program_tr0(dimm_populated, iic0_dimm_addr, num_dimm_banks); + + /* + * program the BxCR registers to find out total sdram installed + */ + total_size = program_bxcr(dimm_populated, iic0_dimm_addr, + num_dimm_banks); + + /* + * program SDRAM Clock Timing Register (SDRAM0_CLKTR) + */ + mtsdram(mem_clktr, 0x40000000); + + /* + * delay to ensure 200 usec has elapsed + */ + udelay(400); + + /* + * enable the memory controller + */ + mfsdram(mem_cfg0, cfg0); + mtsdram(mem_cfg0, cfg0 | SDRAM_CFG0_DCEN); + + /* + * wait for SDRAM_CFG0_DC_EN to complete + */ + while(1) { + mfsdram(mem_mcsts, mcsts); + if ((mcsts & SDRAM_MCSTS_MRSC) != 0) { + break; + } + } + + /* + * program SDRAM Timing Register 1, adding some delays + */ + program_tr1(); + + /* + * if ECC is enabled, initialize parity bits + */ + + return total_size; +} + +unsigned char spd_read(uchar chip, uint addr) { + unsigned char data[2]; + + if (i2c_read(chip, addr, 1, data, 1) == 0) + return data[0]; + else + return 0; +} + +void get_spd_info(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long dimm_found; + unsigned char num_of_bytes; + unsigned char total_size; + + dimm_found = FALSE; + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + num_of_bytes = 0; + total_size = 0; + + num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); + total_size = spd_read(iic0_dimm_addr[dimm_num], 1); + + if ((num_of_bytes != 0) && (total_size != 0)) { + dimm_populated[dimm_num] = TRUE; + dimm_found = TRUE; +#if 0 + printf("DIMM slot %lu: populated\n", dimm_num); +#endif + } + else { + dimm_populated[dimm_num] = FALSE; +#if 0 + printf("DIMM slot %lu: Not populated\n", dimm_num); +#endif + } + } + + if (dimm_found == FALSE) { + printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); + hang(); + } +} + +void check_mem_type(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned char dimm_type; + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2); + switch (dimm_type) { + case 7: +#if 0 + printf("DIMM slot %lu: DDR SDRAM detected\n", dimm_num); +#endif + break; + default: + printf("ERROR: Unsupported DIMM detected in slot %lu.\n", + dimm_num); + printf("Only DDR SDRAM DIMMs are supported.\n"); + printf("Replace the DIMM module with a supported DIMM.\n\n"); + hang(); + break; + } + } + } +} + + +void check_volt_type(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long voltage_type; + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); + if (voltage_type != 0x04) { + printf("ERROR: DIMM %lu with unsupported voltage level.\n", + dimm_num); + hang(); + } + else { +#if 0 + printf("DIMM %lu voltage level supported.\n", dimm_num); +#endif + } + break; + } + } +} + +void program_cfg0(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long cfg0; + unsigned long ecc_enabled; + unsigned char ecc; + unsigned char attributes; + unsigned long data_width; + unsigned long dimm_32bit; + unsigned long dimm_64bit; + + /* + * get Memory Controller Options 0 data + */ + mfsdram(mem_cfg0, cfg0); + + /* + * clear bits + */ + cfg0 &= ~(SDRAM_CFG0_DCEN | SDRAM_CFG0_MCHK_MASK | + SDRAM_CFG0_RDEN | SDRAM_CFG0_PMUD | + SDRAM_CFG0_DMWD_MASK | + SDRAM_CFG0_UIOS_MASK | SDRAM_CFG0_PDP); + + + /* + * FIXME: assume the DDR SDRAMs in both banks are the same + */ + ecc_enabled = TRUE; + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + ecc = spd_read(iic0_dimm_addr[dimm_num], 11); + if (ecc != 0x02) { + ecc_enabled = FALSE; + } + + /* + * program Registered DIMM Enable + */ + attributes = spd_read(iic0_dimm_addr[dimm_num], 21); + if ((attributes & 0x02) != 0x00) { + cfg0 |= SDRAM_CFG0_RDEN; + } + + /* + * program DDR SDRAM Data Width + */ + data_width = + (unsigned long)spd_read(iic0_dimm_addr[dimm_num],6) + + (((unsigned long)spd_read(iic0_dimm_addr[dimm_num],7)) << 8); + if (data_width == 64 || data_width == 72) { + dimm_64bit = TRUE; + cfg0 |= SDRAM_CFG0_DMWD_64; + } + else if (data_width == 32 || data_width == 40) { + dimm_32bit = TRUE; + cfg0 |= SDRAM_CFG0_DMWD_32; + } + else { + printf("WARNING: DIMM with datawidth of %lu bits.\n", + data_width); + printf("Only DIMMs with 32 or 64 bit datawidths supported.\n"); + hang(); + } + break; + } + } + + /* + * program Memory Data Error Checking + */ + if (ecc_enabled == TRUE) { + cfg0 |= SDRAM_CFG0_MCHK_GEN; + } + else { + cfg0 |= SDRAM_CFG0_MCHK_NON; + } + + /* + * program Page Management Unit + */ + cfg0 |= SDRAM_CFG0_PMUD; + + /* + * program Memory Controller Options 0 + * Note: DCEN must be enabled after all DDR SDRAM controller + * configuration registers get initialized. + */ + mtsdram(mem_cfg0, cfg0); +} + +void program_cfg1(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long cfg1; + mfsdram(mem_cfg1, cfg1); + + /* + * Self-refresh exit, disable PM + */ + cfg1 &= ~(SDRAM_CFG1_SRE | SDRAM_CFG1_PMEN); + + /* + * program Memory Controller Options 1 + */ + mtsdram(mem_cfg1, cfg1); +} + +void program_rtr (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long bus_period_x_10; + unsigned long refresh_rate = 0; + unsigned char refresh_rate_type; + unsigned long refresh_interval; + unsigned long sdram_rtr; + PPC440_SYS_INFO sys_info; + + /* + * get the board info + */ + get_sys_info(&sys_info); + bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); + + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + refresh_rate_type = 0x7F & spd_read(iic0_dimm_addr[dimm_num], 12); + switch (refresh_rate_type) { + case 0x00: + refresh_rate = 15625; + break; + case 0x011: + refresh_rate = 15625/4; + break; + case 0x02: + refresh_rate = 15625/2; + break; + case 0x03: + refresh_rate = 15626*2; + break; + case 0x04: + refresh_rate = 15625*4; + break; + case 0x05: + refresh_rate = 15625*8; + break; + default: + printf("ERROR: DIMM %lu, unsupported refresh rate/type.\n", + dimm_num); + printf("Replace the DIMM module with a supported DIMM.\n"); + break; + } + + break; + } + } + + refresh_interval = refresh_rate * 10 / bus_period_x_10; + sdram_rtr = (refresh_interval & 0x3ff8) << 16; + + /* + * program Refresh Timer Register (SDRAM0_RTR) + */ + mtsdram(mem_rtr, sdram_rtr); +} + +void program_tr0 (unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long tr0; + unsigned char wcsbc; + unsigned char t_rp_ns; + unsigned char t_rcd_ns; + unsigned char t_ras_ns; + unsigned long t_rp_clk; + unsigned long t_ras_rcd_clk; + unsigned long t_rcd_clk; + unsigned long t_rfc_clk; + unsigned long plb_check; + unsigned char cas_bit; + unsigned long cas_index; + unsigned char cas_2_0_available; + unsigned char cas_2_5_available; + unsigned char cas_3_0_available; + unsigned long cycle_time_ns_x_10[3]; + unsigned long tcyc_3_0_ns_x_10; + unsigned long tcyc_2_5_ns_x_10; + unsigned long tcyc_2_0_ns_x_10; + unsigned long tcyc_reg; + unsigned long bus_period_x_10; + PPC440_SYS_INFO sys_info; + unsigned long residue; + + /* + * get the board info + */ + get_sys_info(&sys_info); + bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); + + /* + * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits + */ + mfsdram(mem_tr0, tr0); + tr0 &= ~(SDRAM_TR0_SDWR_MASK | SDRAM_TR0_SDWD_MASK | + SDRAM_TR0_SDCL_MASK | SDRAM_TR0_SDPA_MASK | + SDRAM_TR0_SDCP_MASK | SDRAM_TR0_SDLD_MASK | + SDRAM_TR0_SDRA_MASK | SDRAM_TR0_SDRD_MASK); + + /* + * initialization + */ + wcsbc = 0; + t_rp_ns = 0; + t_rcd_ns = 0; + t_ras_ns = 0; + cas_2_0_available = TRUE; + cas_2_5_available = TRUE; + cas_3_0_available = TRUE; + tcyc_2_0_ns_x_10 = 0; + tcyc_2_5_ns_x_10 = 0; + tcyc_3_0_ns_x_10 = 0; + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + wcsbc = spd_read(iic0_dimm_addr[dimm_num], 15); + t_rp_ns = spd_read(iic0_dimm_addr[dimm_num], 27) >> 2; + t_rcd_ns = spd_read(iic0_dimm_addr[dimm_num], 29) >> 2; + t_ras_ns = spd_read(iic0_dimm_addr[dimm_num], 30); + cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); + + for (cas_index = 0; cas_index < 3; cas_index++) { + switch (cas_index) { + case 0: + tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); + break; + case 1: + tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23); + break; + default: + tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25); + break; + } + + if ((tcyc_reg & 0x0F) >= 10) { + printf("ERROR: Tcyc incorrect for DIMM in slot %lu\n", + dimm_num); + hang(); + } + + cycle_time_ns_x_10[cas_index] = + (((tcyc_reg & 0xF0) >> 4) * 10) + (tcyc_reg & 0x0F); + } + + cas_index = 0; + + if ((cas_bit & 0x80) != 0) { + cas_index += 3; + } + else if ((cas_bit & 0x40) != 0) { + cas_index += 2; + } + else if ((cas_bit & 0x20) != 0) { + cas_index += 1; + } + + if (((cas_bit & 0x10) != 0) && (cas_index < 3)) { + tcyc_3_0_ns_x_10 = cycle_time_ns_x_10[cas_index]; + cas_index++; + } + else { + if (cas_index != 0) { + cas_index++; + } + cas_3_0_available = FALSE; + } + + if (((cas_bit & 0x08) != 0) || (cas_index < 3)) { + tcyc_2_5_ns_x_10 = cycle_time_ns_x_10[cas_index]; + cas_index++; + } + else { + if (cas_index != 0) { + cas_index++; + } + cas_2_5_available = FALSE; + } + + if (((cas_bit & 0x04) != 0) || (cas_index < 3)) { + tcyc_2_0_ns_x_10 = cycle_time_ns_x_10[cas_index]; + cas_index++; + } + else { + if (cas_index != 0) { + cas_index++; + } + cas_2_0_available = FALSE; + } + + break; + } + } + + /* + * Program SD_WR and SD_WCSBC fields + */ + tr0 |= SDRAM_TR0_SDWR_2_CLK; /* Write Recovery: 2 CLK */ + switch (wcsbc) { + case 0: + tr0 |= SDRAM_TR0_SDWD_0_CLK; + break; + default: + tr0 |= SDRAM_TR0_SDWD_1_CLK; + break; + } + + /* + * Program SD_CASL field + */ + if ((cas_2_0_available == TRUE) && + (bus_period_x_10 >= tcyc_2_0_ns_x_10)) { + tr0 |= SDRAM_TR0_SDCL_2_0_CLK; + } + else if((cas_2_5_available == TRUE) && + (bus_period_x_10 >= tcyc_2_5_ns_x_10)) { + tr0 |= SDRAM_TR0_SDCL_2_5_CLK; + } + else if((cas_3_0_available == TRUE) && + (bus_period_x_10 >= tcyc_3_0_ns_x_10)) { + tr0 |= SDRAM_TR0_SDCL_3_0_CLK; + } + else { + printf("ERROR: No supported CAS latency with the installed DIMMs.\n"); + printf("Only CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); + printf("Make sure the PLB speed is within the supported range.\n"); + hang(); + } + + /* + * Calculate Trp in clock cycles and round up if necessary + * Program SD_PTA field + */ + t_rp_clk = sys_info.freqPLB * t_rp_ns / ONE_BILLION; + plb_check = ONE_BILLION * t_rp_clk / t_rp_ns; + if (sys_info.freqPLB != plb_check) { + t_rp_clk++; + } + switch ((unsigned long)t_rp_clk) { + case 0: + case 1: + case 2: + tr0 |= SDRAM_TR0_SDPA_2_CLK; + break; + case 3: + tr0 |= SDRAM_TR0_SDPA_3_CLK; + break; + default: + tr0 |= SDRAM_TR0_SDPA_4_CLK; + break; + } + + /* + * Program SD_CTP field + */ + t_ras_rcd_clk = sys_info.freqPLB * (t_ras_ns - t_rcd_ns) / ONE_BILLION; + plb_check = ONE_BILLION * t_ras_rcd_clk / (t_ras_ns - t_rcd_ns); + if (sys_info.freqPLB != plb_check) { + t_ras_rcd_clk++; + } + switch (t_ras_rcd_clk) { + case 0: + case 1: + case 2: + tr0 |= SDRAM_TR0_SDCP_2_CLK; + break; + case 3: + tr0 |= SDRAM_TR0_SDCP_3_CLK; + break; + case 4: + tr0 |= SDRAM_TR0_SDCP_4_CLK; + break; + default: + tr0 |= SDRAM_TR0_SDCP_5_CLK; + break; + } + + /* + * Program SD_LDF field + */ + tr0 |= SDRAM_TR0_SDLD_2_CLK; + + /* + * Program SD_RFTA field + * FIXME tRFC hardcoded as 75 nanoseconds + */ + t_rfc_clk = sys_info.freqPLB / (ONE_BILLION / 75); + residue = sys_info.freqPLB % (ONE_BILLION / 75); + if (residue >= (ONE_BILLION / 150)) { + t_rfc_clk++; + } + switch (t_rfc_clk) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + tr0 |= SDRAM_TR0_SDRA_6_CLK; + break; + case 7: + tr0 |= SDRAM_TR0_SDRA_7_CLK; + break; + case 8: + tr0 |= SDRAM_TR0_SDRA_8_CLK; + break; + case 9: + tr0 |= SDRAM_TR0_SDRA_9_CLK; + break; + case 10: + tr0 |= SDRAM_TR0_SDRA_10_CLK; + break; + case 11: + tr0 |= SDRAM_TR0_SDRA_11_CLK; + break; + case 12: + tr0 |= SDRAM_TR0_SDRA_12_CLK; + break; + default: + tr0 |= SDRAM_TR0_SDRA_13_CLK; + break; + } + + /* + * Program SD_RCD field + */ + t_rcd_clk = sys_info.freqPLB * t_rcd_ns / ONE_BILLION; + plb_check = ONE_BILLION * t_rcd_clk / t_rcd_ns; + if (sys_info.freqPLB != plb_check) { + t_rcd_clk++; + } + switch (t_rcd_clk) { + case 0: + case 1: + case 2: + tr0 |= SDRAM_TR0_SDRD_2_CLK; + break; + case 3: + tr0 |= SDRAM_TR0_SDRD_3_CLK; + break; + default: + tr0 |= SDRAM_TR0_SDRD_4_CLK; + break; + } + +#if 0 + printf("tr0: %x\n", tr0); +#endif + mtsdram(mem_tr0, tr0); +} + +void program_tr1 (void) +{ + unsigned long tr0; + unsigned long tr1; + unsigned long cfg0; + unsigned long ecc_temp; + unsigned long dlycal; + unsigned long dly_val; + unsigned long i, j, k; + unsigned long bxcr_num; + unsigned long max_pass_length; + unsigned long current_pass_length; + unsigned long current_fail_length; + unsigned long current_start; + unsigned long rdclt; + unsigned long rdclt_offset; + long max_start; + long max_end; + long rdclt_average; + unsigned char window_found; + unsigned char fail_found; + unsigned char pass_found; + unsigned long * membase; + PPC440_SYS_INFO sys_info; + + /* + * get the board info + */ + get_sys_info(&sys_info); + + /* + * get SDRAM Timing Register 0 (SDRAM_TR0) and clear bits + */ + mfsdram(mem_tr1, tr1); + tr1 &= ~(SDRAM_TR1_RDSS_MASK | SDRAM_TR1_RDSL_MASK | + SDRAM_TR1_RDCD_MASK | SDRAM_TR1_RDCT_MASK); + + mfsdram(mem_tr0, tr0); + if (((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) && + (sys_info.freqPLB > 100000000)) { + tr1 |= SDRAM_TR1_RDSS_TR2; + tr1 |= SDRAM_TR1_RDSL_STAGE3; + tr1 |= SDRAM_TR1_RDCD_RCD_1_2; + } + else { + tr1 |= SDRAM_TR1_RDSS_TR1; + tr1 |= SDRAM_TR1_RDSL_STAGE2; + tr1 |= SDRAM_TR1_RDCD_RCD_0_0; + } + + /* + * save CFG0 ECC setting to a temporary variable and turn ECC off + */ + mfsdram(mem_cfg0, cfg0); + ecc_temp = cfg0 & SDRAM_CFG0_MCHK_MASK; + mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | SDRAM_CFG0_MCHK_NON); + + /* + * get the delay line calibration register value + */ + mfsdram(mem_dlycal, dlycal); + dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2; + + max_pass_length = 0; + max_start = 0; + max_end = 0; + current_pass_length = 0; + current_fail_length = 0; + current_start = 0; + rdclt_offset = 0; + window_found = FALSE; + fail_found = FALSE; + pass_found = FALSE; +#ifdef DEBUG + printf("Starting memory test "); +#endif + for (k = 0; k < NUMHALFCYCLES; k++) { + for (rdclt = 0; rdclt < dly_val; rdclt++) { + /* + * Set the timing reg for the test. + */ + mtsdram(mem_tr1, (tr1 | SDRAM_TR1_RDCT_ENCODE(rdclt))); + + for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { + mtdcr(memcfga, mem_b0cr + (bxcr_num<<2)); + if ((mfdcr(memcfgd) & SDRAM_BXCR_SDBE) == SDRAM_BXCR_SDBE) { + /* Bank is enabled */ + membase = (unsigned long*) + (mfdcr(memcfgd) & SDRAM_BXCR_SDBA_MASK); + + /* + * Run the short memory test + */ + for (i = 0; i < NUMMEMTESTS; i++) { + for (j = 0; j < NUMMEMWORDS; j++) { + membase[j] = test[i][j]; + ppcDcbf((unsigned long)&(membase[j])); + } + + for (j = 0; j < NUMMEMWORDS; j++) { + if (membase[j] != test[i][j]) { + ppcDcbf((unsigned long)&(membase[j])); + break; + } + ppcDcbf((unsigned long)&(membase[j])); + } + + if (j < NUMMEMWORDS) { + break; + } + } + + /* + * see if the rdclt value passed + */ + if (i < NUMMEMTESTS) { + break; + } + } + } + + if (bxcr_num == MAXBXCR) { + if (fail_found == TRUE) { + pass_found = TRUE; + if (current_pass_length == 0) { + current_start = rdclt_offset + rdclt; + } + + current_fail_length = 0; + current_pass_length++; + + if (current_pass_length > max_pass_length) { + max_pass_length = current_pass_length; + max_start = current_start; + max_end = rdclt_offset + rdclt; + } + } + } + else { + current_pass_length = 0; + current_fail_length++; + + if (current_fail_length >= (dly_val>>2)) { + if (fail_found == FALSE) { + fail_found = TRUE; + } + else if (pass_found == TRUE) { + window_found = TRUE; + break; + } + } + } + } +#ifdef DEBUG + printf("."); +#endif + if (window_found == TRUE) { + break; + } + + tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; + rdclt_offset += dly_val; + } +#ifdef DEBUG + printf("\n"); +#endif + + /* + * make sure we find the window + */ + if (window_found == FALSE) { + printf("ERROR: Cannot determine a common read delay.\n"); + hang(); + } + + /* + * restore the orignal ECC setting + */ + mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | ecc_temp); + + /* + * set the SDRAM TR1 RDCD value + */ + tr1 &= ~SDRAM_TR1_RDCD_MASK; + if ((tr0 & SDRAM_TR0_SDCL_MASK) == SDRAM_TR0_SDCL_2_5_CLK) { + tr1 |= SDRAM_TR1_RDCD_RCD_1_2; + } + else { + tr1 |= SDRAM_TR1_RDCD_RCD_0_0; + } + + /* + * set the SDRAM TR1 RDCLT value + */ + tr1 &= ~SDRAM_TR1_RDCT_MASK; + while (max_end >= (dly_val<<1)) { + max_end -= (dly_val<<1); + max_start -= (dly_val<<1); + } + + rdclt_average = ((max_start + max_end) >> 1); + if (rdclt_average >= 0x60) + while(1); + + if (rdclt_average < 0) { + rdclt_average = 0; + } + + if (rdclt_average >= dly_val) { + rdclt_average -= dly_val; + tr1 = tr1 ^ SDRAM_TR1_RDCD_MASK; + } + tr1 |= SDRAM_TR1_RDCT_ENCODE(rdclt_average); + +#if 0 + printf("tr1: %x\n", tr1); +#endif + /* + * program SDRAM Timing Register 1 TR1 + */ + mtsdram(mem_tr1, tr1); +} + +unsigned long program_bxcr(unsigned long* dimm_populated, + unsigned char* iic0_dimm_addr, + unsigned long num_dimm_banks) +{ + unsigned long dimm_num; + unsigned long bxcr_num; + unsigned long bank_base_addr; + unsigned long bank_size_bytes; + unsigned long cr; + unsigned long i; + unsigned long temp; + unsigned char num_row_addr; + unsigned char num_col_addr; + unsigned char num_banks; + unsigned char bank_size_id; + + + /* + * Set the BxCR regs. First, wipe out the bank config registers. + */ + for (bxcr_num = 0; bxcr_num < MAXBXCR; bxcr_num++) { + mtdcr(memcfga, mem_b0cr + (bxcr_num << 2)); + mtdcr(memcfgd, 0x00000000); + } + + /* + * reset the bank_base address + */ + bank_base_addr = CFG_SDRAM_BASE; + + for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { + if (dimm_populated[dimm_num] == TRUE) { + num_row_addr = spd_read(iic0_dimm_addr[dimm_num], 3); + num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); + num_banks = spd_read(iic0_dimm_addr[dimm_num], 5); + bank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); + + /* + * Set the SDRAM0_BxCR regs + */ + cr = 0; + bank_size_bytes = 4 * 1024 * 1024 * bank_size_id; + switch (bank_size_id) { + case 0x02: + cr |= SDRAM_BXCR_SDSZ_8; + break; + case 0x04: + cr |= SDRAM_BXCR_SDSZ_16; + break; + case 0x08: + cr |= SDRAM_BXCR_SDSZ_32; + break; + case 0x10: + cr |= SDRAM_BXCR_SDSZ_64; + break; + case 0x20: + cr |= SDRAM_BXCR_SDSZ_128; + break; + case 0x40: + cr |= SDRAM_BXCR_SDSZ_256; + break; + case 0x80: + cr |= SDRAM_BXCR_SDSZ_512; + break; + default: + printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", + dimm_num); + printf("ERROR: Unsupported value for the banksize: %d.\n", + bank_size_id); + printf("Replace the DIMM module with a supported DIMM.\n\n"); + hang(); + } + + switch (num_col_addr) { + case 0x08: + cr |= SDRAM_BXCR_SDAM_1; + break; + case 0x09: + cr |= SDRAM_BXCR_SDAM_2; + break; + case 0x0A: + cr |= SDRAM_BXCR_SDAM_3; + break; + case 0x0B: + cr |= SDRAM_BXCR_SDAM_4; + break; + default: + printf("DDR-SDRAM: DIMM %lu BxCR configuration.\n", + dimm_num); + printf("ERROR: Unsupported value for number of " + "column addresses: %d.\n", num_col_addr); + printf("Replace the DIMM module with a supported DIMM.\n\n"); + hang(); + } + + /* + * enable the bank + */ + cr |= SDRAM_BXCR_SDBE; + + /*------------------------------------------------------------------ + | This next section is hardware dependent and must be programmed + | to match the hardware. + +-----------------------------------------------------------------*/ + if (dimm_num == 0) { + for (i = 0; i < num_banks; i++) { + mtdcr(memcfga, mem_b0cr + (i << 2)); + temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK | + SDRAM_BXCR_SDSZ_MASK | + SDRAM_BXCR_SDAM_MASK | + SDRAM_BXCR_SDBE); + cr |= temp; + cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK; + mtdcr(memcfgd, cr); + bank_base_addr += bank_size_bytes; + } + } + else { + for (i = 0; i < num_banks; i++) { + mtdcr(memcfga, mem_b2cr + (i << 2)); + temp = mfdcr(memcfgd) & ~(SDRAM_BXCR_SDBA_MASK | + SDRAM_BXCR_SDSZ_MASK | + SDRAM_BXCR_SDAM_MASK | + SDRAM_BXCR_SDBE); + cr |= temp; + cr |= bank_base_addr & SDRAM_BXCR_SDBA_MASK; + mtdcr(memcfgd, cr); + bank_base_addr += bank_size_bytes; + } + } + } + } + + return(bank_base_addr); +} + +void program_ecc (unsigned long num_bytes) +{ + unsigned long bank_base_addr; + unsigned long current_address; + unsigned long end_address; + unsigned long address_increment; + unsigned long cfg0; + + /* + * get Memory Controller Options 0 data + */ + mfsdram(mem_cfg0, cfg0); + + /* + * reset the bank_base address + */ + bank_base_addr = CFG_SDRAM_BASE; + + if ((cfg0 & SDRAM_CFG0_MCHK_MASK) != SDRAM_CFG0_MCHK_NON) { + mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | + SDRAM_CFG0_MCHK_GEN); + + if ((cfg0 & SDRAM_CFG0_DMWD_MASK) == SDRAM_CFG0_DMWD_32) { + address_increment = 4; + } + else { + address_increment = 8; + } + + current_address = (unsigned long)(bank_base_addr); + end_address = (unsigned long)(bank_base_addr) + num_bytes; + + while (current_address < end_address) { + *((unsigned long*)current_address) = 0x00000000; + current_address += address_increment; + } + + mtsdram(mem_cfg0, (cfg0 & ~SDRAM_CFG0_MCHK_MASK) | + SDRAM_CFG0_MCHK_CHK); + } +} + +#endif /* CONFIG_440 */ + +#endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index ac8f835..26d2190 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -208,21 +208,21 @@ ulong get_PCI_freq (void) #elif defined(CONFIG_440) void get_sys_info (sys_info_t * sysInfo) { - unsigned long sys0; + unsigned long strp0; unsigned long temp; unsigned long m; /* Extract configured divisors */ - sys0 = mfdcr( cpc0_sys0 ); - sysInfo->pllFwdDivA = 8 - ((sys0 & PLLSYS0_FWD_DIV_A_MASK) >> 15); - sysInfo->pllFwdDivB = 8 - ((sys0 & PLLSYS0_FWD_DIV_B_MASK) >> 12); - temp = (sys0 & PLLSYS0_FB_DIV_MASK) >> 18; + strp0 = mfdcr( cpc0_strp0 ); + sysInfo->pllFwdDivA = 8 - ((strp0 & PLLSYS0_FWD_DIV_A_MASK) >> 15); + sysInfo->pllFwdDivB = 8 - ((strp0 & PLLSYS0_FWD_DIV_B_MASK) >> 12); + temp = (strp0 & PLLSYS0_FB_DIV_MASK) >> 18; sysInfo->pllFbkDiv = temp ? temp : 16; - sysInfo->pllOpbDiv = 1 + ((sys0 & PLLSYS0_OPB_DIV_MASK) >> 10); - sysInfo->pllExtBusDiv = 1 + ((sys0 & PLLSYS0_EPB_DIV_MASK) >> 8); + sysInfo->pllOpbDiv = 1 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10); + sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8); /* Calculate 'M' based on feedback source */ - if( sys0 & PLLSYS0_EXTSL_MASK ) + if( strp0 & PLLSYS0_EXTSL_MASK ) m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB; else m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA; @@ -231,6 +231,8 @@ void get_sys_info (sys_info_t * sysInfo) sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1); sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA; sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB; + if( get_pvr() == PVR_440GP_RB ) /* Rev B divs an extra 2 -- geez! */ + sysInfo->freqPLB >>= 1; sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv; sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index ab9e558..559ff3c 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -194,10 +194,36 @@ _start_440: ori r1,r1,0x6000 /* cache touch */ mtspr ccr0,r1 - /* set up interrupt vectors */ - mtspr ivpr,r0 - li r1,0x500 - mtspr ivor4,r1 + /*----------------------------------------------------------------*/ + /* Setup interrupt vectors */ + /*----------------------------------------------------------------*/ + mtspr ivpr,r0 /* Vectors start at 0x0000_0000 */ + li r1,0x0100 + mtspr ivor0,r1 /* Critical input */ + li r1,0x0200 + mtspr ivor1,r1 /* Machine check */ + li r1,0x0300 + mtspr ivor2,r1 /* Data storage */ + li r1,0x0400 + mtspr ivor3,r1 /* Instruction storage */ + li r1,0x0500 + mtspr ivor4,r1 /* External interrupt */ + li r1,0x0600 + mtspr ivor5,r1 /* Alignment */ + li r1,0x0700 + mtspr ivor6,r1 /* Program check */ + li r1,0x0800 + mtspr ivor7,r1 /* Floating point unavailable */ + li r1,0x0c00 + mtspr ivor8,r1 /* System call */ + li r1,0x1000 + mtspr ivor10,r1 /* Decrementer (PIT for 440) */ + li r1,0x1400 + mtspr ivor13,r1 /* Data TLB error */ + li r1,0x1300 + mtspr ivor14,r1 /* Instr TLB error */ + li r1,0x2000 + mtspr ivor15,r1 /* Debug */ /*----------------------------------------------------------------*/ /* Configure cache regions */ diff --git a/doc/README.JFFS2 b/doc/README.JFFS2 new file mode 100644 index 0000000..f9663c3 --- /dev/null +++ b/doc/README.JFFS2 @@ -0,0 +1,68 @@ +JFFS2 options and usage. +----------------------- + +JFFS2 in ppcboot is a read only implementation of the file system in +Linux with the same name. To use JFFS2 define CFG_CMD_JFFS2. + +The module adds three new commands. +fsload - load binary file from a file system image +fsinfo - print information about file systems +ls - list files in a directory + + +There is two ways for JFFS2 to find the disk. The default way uses +the flash_info structure to find the start of a JFFS2 disk (called +partition in the code) and you can change where the partition is with +two defines. + +CFG_JFFS2_FIRST_BANK + defined the first flash bank to use + +CFG_JFFS2_FIRST_SECTOR + defines the first sector to use + + +The second way is to define CFG_JFFS_CUSTOM_PART and implement the +jffs2_part_info(int part_num) function in your board specific files. +In this mode CFG_JFFS2_FIRST_BANK and CFG_JFFS2_FIRST_SECTOR is not +used. + +The input is a partition number starting with 0. +Return a pointer to struct part_info or NULL for error; + +Ex jffs2_part_info() for one partition. +--- +#if defined CFG_JFFS_CUSTOM_PART +#include + +static struct part_info part; + +struct part_info* +jffs2_part_info(int part_num) +{ + if(part_num==0){ + if(part.usr_priv==(void*)1) + return ∂ + + memset(&part, 0, sizeof(part)); + part.offset=(char*)0xFF800000; + part.size=1024*1024*8; + + /* Mark the struct as ready */ + part.usr_priv=(void*)1; + + return ∂ + } + return 0; +} +#endif +--- + +TODO. + + Add a new command so it's actually possible to change + partition. + + Remove the assumption that JFFS can dereference a pointer + into the disk. The current code do not work with memory holes + or hardware with a sliding window (PCMCIA). diff --git a/doc/README.Modem b/doc/README.Modem new file mode 100644 index 0000000..11142d6 --- /dev/null +++ b/doc/README.Modem @@ -0,0 +1,73 @@ +How to configure modem support in PPCBoot : + +1. Define modem initialization strings: +--------------------------------------- + +The modem initialization strings have following format: + + mdm_init1= + mdm_init2= + ... + +Turning off modem verbose responses with ATV0 or ATQ1 is not allowed; +PPCBoot analyzes only verbose (not numeric) result codes. Modem local +command echo can be turned off (ATE0). + +2. RTS/CTS hardware flow control: +--------------------------------- + +You may wish to enable RTS/CTS hardware flow control, if the board's +UART driver supports it (see CONFIG_HWFLOW compile-time flag in +config/.h). This is controlled by the 'mdm_flow_control' +environment variable: + + 'mdm_flow_control=rts/cts' - to enable RTS/CTS flow control. + 'mdm_flow_control=none ' - to disable. + + +The following are the examples using a Rockwell OEM modem +configuration: + +SAMSUNG # setenv mdm_init1 ATZ - reset the modem to + the factory defaults. +SAMSUNG # setenv mdm_init2 ATS0=1 - set modem into + answer mode. +SAMSUNG # setenv mdm_flow_control rts/cts - enable serial port + flow control +SAMSUNG # saveenv + +The example above initializes modem into answer mode to wait for the +incoming call. RTS/CTS flow control is enabled for the serial port. +(The RTS/CTS flow control is enabled by default on the modem). + + +SAMSUNG # setenv mdm_init1 ATZ +SAMSUNG # setenv mdm_init2 ATS39=0+IFC=0,0 - disable modem + RTS/CTS flow control +SAMSUNG # setenv mdm_init3 ATDT1643973 - dial out the number +SAMSUNG # setenv mdm_flow_control none +SAMSUNG # saveenv + +The example above initializes modem to dial-up connection on the +number 1643973. Flow control is disabled. + +Note that flow control must be turned both off or both on for the +board serial port and for the modem. + + +If the connection was set up successfully, the PPCBoot prompt appears +on the terminal console. If not (PPCBoot modem was configured for +originating the call and connection was not established) - the board +should be reset for another dial-up try. + + +Note on the SMDK2400 board: +--------------------------- + +Since the board serial ports does not have DTR signal wired, modem +should be told to ignore port DTR setting prior to connection to the +SMDK board, and this setting should be stored in modem NVRAM. For the +Rockwell OEM modem this can to be done with the following command: + +AT&D0&W + diff --git a/doc/README.ppc440 b/doc/README.ppc440 new file mode 100644 index 0000000..815b963 --- /dev/null +++ b/doc/README.ppc440 @@ -0,0 +1,176 @@ + PowerPC 440 + + Last Update: August 27, 2002 +======================================================================= + + +OVERVIEW +============ + +Support for the ppc440 is contained in the cpu/ppc44x directory +and enabled via the CONFIG_440 flag. It is largely based on the +405gp code. A sample board support implementation is contained +in the board/ebony directory. + +All testing was performed using the IBM Ebony board using both +Rev B and Rev C silicon. However, since the Rev B. silicon has +extensive errata, support for Rev B. is minimal (it boots and +features such as i2c, pci, tftpboot, etc. seem to work ok). +The expectation is that all new board designs will be using +Rev C or later parts -- if not, you're in for a rough ride ;-) + +The ppc440 port does a fair job of keeping "board-specific" code +out of the "cpu-specific" source. The goal of course was to +provide mechanisms for each board to customize without having +to clutter the cpu-specific source with a lot of ifdefs. Many +of these mechanisms are described in the following sections. + + +MEMORY MANAGEMENT +================= + +The ppc440 doesn't run in "real mode". The MMU must be active +at all times. Additionally, the 440 implements a 36-bit physical +memory space that gets mapped into the PowerPC 32-bit virtual +address space. So things like memory-mapped peripherals, etc must +all be mapped in. Once this is done, the 32-bit virtual address +space is then viewed as though it were physical memory. + +However, this means that memory, peripherals, etc can be configured +to appear (mostly) anywhere in the virtual address space. Each board +must define its own mappings using the tlbtab (see board/ebony/init.S). +The actual TLB setup is performed by the cpu-specific code. + +Although each board is free to define its own mappings, there are +several definitions to be aware of. These definitions may be used in +the cpu-specific code (vs. board-specific code), so you should +at least review these before deciding to make any changes ... it +will probably save you some headaches ;-) + +CFG_SDRAM_BASE - The virtual address where SDRAM is mapped (always 0) + +CFG_FLASH_BASE - The virtual address where FLASH is mapped. + +CFG_PCI_MEMBASE - The virtual address where PCI-bus memory is mapped. + This mapping provides access to PCI-bus memory. + +CFG_PERIPHERAL_BASE - The virtual address where the 440 memory-mapped + peripherals are mapped. (e.g. -- UART registers, IIC registers, etc). + +CFG_ISRAM_BASE - The virtual address where the 440 internal SRAM is + mapped. The internal SRAM is equivalent to 405gp OCM and is used + for the initial stack. + +CFG_PCI_BASE - The virtual address where the 440 PCI-x bridge config + registers are mapped. + +CFG_PCI_TARGBASE - The PCI address that is mapped to the virtual address + defined by CFG_PCI_MEMBASE. + + +UART / SERIAL +================= + +The UART port works fine when an external serial clock is provided +(like the one on the Ebony board) and when using internal clocking. +This is controlled with the CFG_EXT_SERIAL_CLOCK flag. When using +internal clocking, the "ideal baud rate" settings in the 440GP +user manual are automatically calculated. + +CONFIG_SERIAL_SOFTWARE_FIFO enables interrupt-driven serial operation. +But the last time I checked, interrupts were initialized after the +serial port causing the interrupt handler to be removed from the +handler table. This will probably be fixed soon ... or fix it +yourself and submit a patch :-) + + +DDR SDRAM CONTROLLER +==================== + +SDRAM controller intialization using Serial Presence Detect (SPD) is +now supported (thanks Jun). It is enabled by defining CONFIG_SPD_EEPROM. +The i2c eeprom addresses are controlled by the SPD_EEPROM_ADDRESS macro. + +NOTE: The SPD_EEPROM_ADDRESS macro is defined differently than for other +processors. Traditionally, it defined a single address. For the 440 it +defines an array of addresses to support multiple banks. Address order +is significant: the addresses are used in order to program the BankN +registers. For example, two banks with i2c addresses of 0x53 (bank 0) +and 0x52 (bank 1) would be defined as follows: + +#define SPD_EEPROM_ADDRESS {0x53,0x52} + + +PCI-X BRIDGE +==================== + +PCI is an area that requires lots of flexibility since every board has +its own set of constraints and configuration. This section describes the +440 implementation. + +CPC0_STRP1[PISE] -- if the PISE strap bit is not asserted, PCI init +is aborted and an indication is printed. This is NOT considered an +error -- only an indication that PCI shouldn't be initialized. This +gives you a chance to edit the i2c bootstrap eeproms using the i2c +utilities once you get to the ppcboot command prompt. NOTE: the default +440 bootstrap options (not using i2c eeprom) negates this bit. + +The cpu-specific code sets up a default pci_controller structure +that maps in a single PCI I/O space and PCI memory space. The I/O +space begins at PCI I/O address 0 and the PCI memory space is +256 MB starting at PCI address CFG_PCI_TARGBASE. After the +pci_controller structure is initialized, the cpu-specific code will +call the routine pci_pre_init() if the CFG_PCI_PRE_INIT flag is +defined. This routine is implemented by board-specific code & is where +the board can over-ride/extend the default pci_controller structure +settings and do other pre-initialization task. If pci_pre_init() +returns a value of zero, PCI initialization is aborted; otherwise the +controller structure is registered and initialization continues. + +The default PCI target configuration is minimal -- it assumes that the +strapping registers are set as necessary. Since the strapping bits +provide very limited flexibility, you may want to customize the boards +target configuration. If CFG_PCI_TARGET_INIT is defined, the cpu-specific +code will call the routine pci_target_init() which you must implement +in your board-specific code. + +Target initialization is completed by the cpu-specific code by +initializing the subsystem id and subsystem vendor id, and then ensuring +that the enable host configuration bit in the PCIX0_BRDGOPT2 is set. + +The default PCI master initialization maps in 256 MB of pci memory +starting at PCI address CFG_PCI_MEMBASE. To customize this, define +PCI_MASTER_INIT. This will call the routine pci_master_init() in your +board-specific code rather than performing the default master +initialization. + +The decision to perform PCI host configuration must often be determined +at run time. The ppc440 port differs from most other implementations in +that it requires the board to determine its host configuration at run +time rather than by using compile-time flags. This shouldn't create a +large impact on the board-specific code since the board only needs to +implement a single routine that returns a zero or non-zero value: +is_pci_host(). + +Justification for this becomes clear when considering systems running +in a cPCI environment: + +1. Arbiter strapping: Many cPCI boards provide an external arbiter (often +part of the PCI-to-PCI bridge). Even though the arbiter is external (the +arbiter strapping is negated), the CPU may still be required to perform +PCI bus configuration. + +2. Host only: PPMC boards must sample the MONARCH# signal at run-time. +Depending on the configuration of the carrier, the board must determine +if it should configure the PCI bus at run-time. In addition, access to +the MONARCH#signal is board-specific (e.g. via custom FPGA, etc). + +In any event, the is_pci_host() routine gives each board the opportunity +to decide at run-time. If your board is always configured a certain way, +then just hardcode a return of 1 or 0 as appropriate. + + + +Regards, +--Scott + diff --git a/fs/jffs2/jffs2_1pass.c b/fs/jffs2/jffs2_1pass.c index 368ce3b..d12cdbd 100644 --- a/fs/jffs2/jffs2_1pass.c +++ b/fs/jffs2/jffs2_1pass.c @@ -100,8 +100,7 @@ static char *compr_names[] = { static char spinner[] = { '|', '\\', '-', '/' }; -static struct b_lists g_1PassList; - +#define DEBUG #ifdef DEBUG # define DEBUGF(fmt,args...) printf(fmt ,##args) #else @@ -195,16 +194,19 @@ jffs2_scan_empty(u32 start_offset, struct part_info *part) } static u32 -jffs_init_1pass_list(void) +jffs_init_1pass_list(struct part_info *part) { - g_1PassList.dirListHead = g_1PassList.dirListTail = NULL; - g_1PassList.fragListHead = g_1PassList.fragListTail = NULL; - g_1PassList.dirListCount = 0; - g_1PassList.dirListMemBase = 0; - g_1PassList.fragListCount = 0; - g_1PassList.fragListMemBase = 0; - g_1PassList.partOffset = 0x0; - + if ( 0 != ( part->jffs2_priv=malloc(sizeof(struct b_lists)))){ + struct b_lists *pL =(struct b_lists *)part->jffs2_priv; + + pL->dirListHead = pL->dirListTail = NULL; + pL->fragListHead = pL->fragListTail = NULL; + pL->dirListCount = 0; + pL->dirListMemBase = 0; + pL->fragListCount = 0; + pL->fragListMemBase = 0; + pL->partOffset = 0x0; + } return 0; } @@ -668,17 +670,22 @@ jffs2_1pass_search_list_inodes(struct b_lists * pL, const char *fname, u32 pino) } unsigned char -jffs2_1pass_rescan_needed(struct part_info *part, struct b_lists *pL) +jffs2_1pass_rescan_needed(struct part_info *part) { - unsigned char ret = 0; struct b_node *b; struct jffs2_unknown_node *node; + struct b_lists *pL=(struct b_lists *)part->jffs2_priv; + if (part->jffs2_priv == 0){ + DEBUGF ("rescan: First time in use\n"); + return 1; + } // if we have no list, we need to rescan if (pL->fragListCount == 0) { DEBUGF ("rescan: fraglist zero\n"); return 1; } + // or if we are scanninga new partition if (pL->partOffset != part->offset) { DEBUGF ("rescan: different partition\n"); @@ -694,12 +701,13 @@ jffs2_1pass_rescan_needed(struct part_info *part, struct b_lists *pL) } b = b->next; } - return ret; + return 0; } static u32 -jffs2_1pass_build_lists(struct part_info * part, struct b_lists * pL) +jffs2_1pass_build_lists(struct part_info * part) { + struct b_lists *pL; struct jffs2_unknown_node *node; u32 offset; u32 max = part->size - sizeof(struct jffs2_raw_inode); @@ -716,7 +724,8 @@ jffs2_1pass_build_lists(struct part_info * part, struct b_lists * pL) // if we are building a list we need to refresh the cache. // note that since we don't free our memory, eventually this will be bad. // but we're a bootldr so what the hell. - jffs_init_1pass_list(); + jffs_init_1pass_list(part); + pL=(struct b_lists *)part->jffs2_priv; pL->partOffset = part->offset; offset = 0; printf("Scanning JFFS2 FS: "); @@ -890,15 +899,13 @@ jffs2_1pass_fill_info(struct b_lists * pL, struct b_jffs2_info * piL) static struct b_lists * jffs2_get_list(struct part_info * part, const char *who) { - struct b_lists *pl = &g_1PassList; - - if (jffs2_1pass_rescan_needed(part, pl)) { - if (!jffs2_1pass_build_lists(part, pl)) { + if (jffs2_1pass_rescan_needed(part)) { + if (!jffs2_1pass_build_lists(part)) { printf("%s: Failed to scan JFFSv2 file structure\n", who); return NULL; } } - return pl; + return (struct b_lists *)part->jffs2_priv; } @@ -969,7 +976,7 @@ u32 jffs2_1pass_info(struct part_info * part) { struct b_jffs2_info info; - struct b_lists *pl = &g_1PassList; + struct b_lists *pl; int i; if (! (pl = jffs2_get_list(part, "info"))) diff --git a/include/common.h b/include/common.h index c8dc5e7..463dfea 100644 --- a/include/common.h +++ b/include/common.h @@ -38,6 +38,9 @@ typedef volatile unsigned char vu_char; #include #include #include +#if defined(CONFIG_PCI) && defined(CONFIG_440) +#include +#endif #ifdef CONFIG_8xx #include #elif defined(CONFIG_8260) @@ -135,37 +138,29 @@ void inline setenv (char *, char *); void pci_init (void); void pciinfo (int, int); +#if defined(CONFIG_PCI) && defined(CONFIG_440) +# if defined(CFG_PCI_PRE_INIT) + int pci_pre_init (gd_t *, struct pci_controller * ); +# endif +# if defined(CFG_PCI_TARGET_INIT) + void pci_target_init (gd_t *, struct pci_controller *); +# endif +# if defined(CFG_PCI_MASTER_INIT) + void pci_master_init (gd_t *, struct pci_controller *); +# endif + int is_pci_host (gd_t *, struct pci_controller *); +#endif + int misc_init_f (void); int misc_init_r (void); /* $(BOARD)/$(BOARD).c */ void reset_phy (void); -#if defined(CONFIG_CANBT) || \ - defined(CONFIG_CCM) || \ - defined(CONFIG_CPCI405) || \ - defined(CONFIG_CPCIISER4) || \ - defined(CONFIG_DU405) || \ - defined(CONFIG_HYMOD) || \ - defined(CONFIG_IP860) || \ - defined(CONFIG_LWMON) || \ - defined(CONFIG_OCRTC) || \ - defined(CONFIG_ORSG) || \ - defined(CONFIG_PCU_E) || \ - defined(CONFIG_PCI405) || \ - defined(CONFIG_PIP405) || \ - defined(CONFIG_MIP405) || \ - defined(CONFIG_PM826) || \ - defined(CONFIG_SXNI855T) || \ - defined(CONFIG_TQM8260) || \ - defined(CONFIG_CPU86) || \ - defined(CONFIG_W7O) || \ - defined(CONFIG_WALNUT405) /* $(BOARD)/eeprom.c */ void eeprom_init (void); int eeprom_read (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); int eeprom_write (unsigned dev_addr, unsigned offset, uchar *buffer, unsigned cnt); -#endif #ifdef CONFIG_LWMON extern uchar pic_read (uchar reg); extern void pic_write (uchar reg, uchar val); @@ -336,6 +331,9 @@ uint dpram_alloc_align(uint size,uint align); void post_word_store (ulong); ulong post_word_load (void); +/* $(CPU)/.../ */ +void mii_init (void); + /* $(CPU)/.../lcd.c */ #ifdef CONFIG_LCD ulong lcd_setmem (ulong); diff --git a/include/commproc.h b/include/commproc.h index 4fbade6..fb866df 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -734,6 +734,27 @@ typedef struct scc_enet { #define SICR_ENET_CLKRT ((uint)0x00002600) #endif /* CONFIG_FPS850L */ +/*** GEN860T **********************************************************/ +#if defined(CONFIG_GEN860T) +#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_GEN860T */ + /*** GENIETV ********************************************************/ #if defined(CONFIG_GENIETV) diff --git a/include/configs/EBONY.h b/include/configs/EBONY.h index 1bb7661..b97a1f2 100644 --- a/include/configs/EBONY.h +++ b/include/configs/EBONY.h @@ -43,8 +43,10 @@ #define CFG_SDRAM_BASE 0x00000000 /* _must_ be 0 */ #define CFG_FLASH_BASE 0xff800000 /* start of FLASH */ #define CFG_MONITOR_BASE 0xfff80000 /* start of monitor */ +#define CFG_PCI_MEMBASE 0x80000000 /* mapped pci memory */ #define CFG_PERIPHERAL_BASE 0xe0000000 /* internal peripherals */ #define CFG_ISRAM_BASE 0xc0000000 /* internal SRAM */ +#define CFG_PCI_BASE 0xd0000000 /* internal PCI regs */ #define CFG_FPGA_BASE (CFG_PERIPHERAL_BASE + 0x08300000) #define CFG_NVRAM_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x08000000) @@ -59,7 +61,7 @@ #define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) #define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET -#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 192 kB for Mon */ +#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 192 kB for Mon */ #define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc*/ /*----------------------------------------------------------------------- @@ -95,6 +97,12 @@ #define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ #define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +/*----------------------------------------------------------------------- + * DDR SDRAM + *----------------------------------------------------------------------*/ +#define CONFIG_SPD_EEPROM /* Use SPD EEPROM for setup */ +#define SPD_EEPROM_ADDRESS {0x53,0x52} /* SPD i2c spd addresses */ + /*----------------------------------------------------------------------- * Environment *----------------------------------------------------------------------*/ @@ -119,6 +127,7 @@ #define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ CFG_CMD_IRQ | \ CFG_CMD_I2C | \ CFG_CMD_KGDB | \ @@ -132,8 +141,6 @@ #undef CONFIG_WATCHDOG /* watchdog disabled */ -#undef CONFIG_SPD_EEPROM /* don't use SPD EEPROM for setup */ - /* * Miscellaneous configurable options */ @@ -166,25 +173,18 @@ * PCI stuff *----------------------------------------------------------------------- */ -#if 0 -#define PCI_HOST_ADAPTER 0 /* configure ar pci adapter */ -#define PCI_HOST_FORCE 1 /* configure as pci host */ -#define PCI_HOST_AUTO 2 /* detected via arbiter enable */ - -#define CONFIG_PCI /* include pci support */ -#define CONFIG_PCI_HOST PCI_HOST_FORCE /* select pci host function */ -#define CONFIG_PCI_PNP /* do pci plug-and-play */ - /* resource configuration */ - -#define CFG_PCI_SUBSYS_VENDORID 0x0000 /* PCI Vendor ID: to-do!!! */ -#define CFG_PCI_SUBSYS_DEVICEID 0x0000 /* PCI Device ID: to-do!!! */ -#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ -#define CFG_PCI_PTM1MS 0x80000001 /* 2GB, enable hard-wired to 1 */ -#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ -#define CFG_PCI_PTM2LA 0x00000000 /* disabled */ -#define CFG_PCI_PTM2MS 0x00000000 /* disabled */ -#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ -#endif +/* General PCI */ +#define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ +#define CONFIG_PCI_SCAN_SHOW /* show pci devices on startup */ +#define CFG_PCI_TARGBASE 0x80000000 /* PCIaddr mapped to CFG_PCI_MEMBASE */ + +/* Board-specific PCI */ +#define CFG_PCI_PRE_INIT /* enable board pci_pre_init() */ +#define CFG_PCI_TARGET_INIT /* let board init pci target */ + +#define CFG_PCI_SUBSYS_VENDORID 0x1014 /* IBM */ +#define CFG_PCI_SUBSYS_DEVICEID 0xcafe /* Whatever */ /* * For booting Linux, the board info and command line data @@ -201,16 +201,6 @@ #define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ #endif - -/* Configuration Port location */ -#define CONFIG_PORT_ADDR 0xF0000500 - -/*----------------------------------------------------------------------- - * Definitions for Serial Presence Detect EEPROM address - * (to get SDRAM settings) - */ -#define SPD_EEPROM_ADDRESS 0x50 - /* * Internal Definitions * diff --git a/include/configs/GEN860T.h b/include/configs/GEN860T.h new file mode 100644 index 0000000..d35f944 --- /dev/null +++ b/include/configs/GEN860T.h @@ -0,0 +1,720 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Keith Outwater, keith_outwater@mvis.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * board/config_GEN860T.h - board specific configuration options + */ + +#ifndef __CONFIG_GEN860T_H +#define __CONFIG_H + +/* + * High Level Configuration Options + */ +#define CONFIG_MPC860 +#define CONFIG_GEN860T + +/* + * Identify the board + */ +#define CONFIG_IDENT_STRING " GEN860T" + +/* + * Don't depend on the RTC clock to determine clock frequency - + * the 860's internal rtc uses a 32.768 KHz clock which is + * generated by the DS1337 - and the DS1337 clock can be turned off. + */ +#define CONFIG_8xx_GCLK_FREQ 66600000 + +/* + * The RS-232 console port is on SMC1 + */ +#define CONFIG_8xx_CONS_SMC1 +#define CONFIG_BAUDRATE 38400 + +/* + * Set allowable console baud rates + */ +#define CFG_BAUDRATE_TABLE { 9600, \ + 19200, \ + 38400, \ + 57600, \ + 115200, \ + } + +/* + * Print console information + */ +#undef CFG_CONSOLE_INFO_QUIET + +/* + * Set the autoboot delay in seconds. A delay of -1 disables autoboot + */ +#define CONFIG_BOOTDELAY 5 + +/* + * Pass the clock frequency to the Linux kernel in units of MHz + */ +#define CONFIG_CLOCKS_IN_MHZ + +#define CONFIG_PREBOOT \ + "echo;echo" + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND \ + "bootp;" \ + "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ + "bootm" + +/* + * Turn off echo for serial download by default. Allow baud rate to be changed + * for downloads + */ +#undef CONFIG_LOADS_ECHO +#define CFG_LOADS_BAUD_CHANGE + +/* + * Set default load address for tftp network downloads + */ +#define CFG_TFTP_LOADADDR 0x01000000 + +/* + * Turn off the watchdog timer + */ +#undef CONFIG_WATCHDOG + +/* + * Do not reboot if a panic occurs + */ +#define CONFIG_PANIC_HANG + +/* + * Enable the status LED + */ +#define CONFIG_STATUS_LED + +/* + * Reset address. We pick an address such that when an instruction + * is executed at that address, a machine check exception occurs + */ +#define CFG_RESET_ADDRESS ((ulong) -1) + +/* + * BOOTP options + */ +#define CONFIG_BOOTP_MASK ( CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE \ + ) + +/* + * The GEN860T network interface uses the on-chip 10/100 FEC with + * an Intel LXT971A PHY connected to the 860T's MII. The PHY's + * MII address is hardwired on the board to zero. + */ +#define CONFIG_FEC_ENET +#define CFG_DISCOVER_PHY +#define CONFIG_MII +#define CONFIG_PHY_ADDR 0 + +/* + * Set default IP stuff just to get bootstarp entries into the + * environment so that we can autoscript the full default environment. + */ +#define CONFIG_ETHADDR 9a:52:63:15:85:25 +#define CONFIG_SERVERIP 10.0.4.200 +#define CONFIG_IPADDR 10.0.4.111 + +/* + * This board has a 32 kibibyte EEPROM (Atmel AT24C256) connected to + * the MPC860T I2C interface. + */ +#define CFG_I2C_EEPROM_ADDR 0x50 +#define CFG_EEPROM_PAGE_WRITE_BITS 6 /* 64 byte pages */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 12 /* 10 mS w/ 20% margin */ +#define CFG_I2C_EEPROM_ADDR_LEN 2 /* need 16 bit address */ +#define CFG_ENV_EEPROM_SIZE (32 * 1024) + +/* + * Man, that hardware I2C is slow! + */ +#undef CONFIG_HARD_I2C +#define CONFIG_SOFT_I2C + +/* + * Configure software I2C support (taken from IP860 BSP). + * The I2C bus is connected to the GEN860T's 'dedicated' I2C + * pins, i.e. PB26 and PB27 + */ +#define PB_SCL 0x00000020 /* PB 26 */ +#define PB_SDA 0x00000010 /* PB 27 */ + +#define I2C_INIT (immr->im_cpm.cp_pbdir |= PB_SCL) +#define I2C_ACTIVE (immr->im_cpm.cp_pbdir |= PB_SDA) +#define I2C_TRISTATE (immr->im_cpm.cp_pbdir &= ~PB_SDA) +#define I2C_READ ((immr->im_cpm.cp_pbdat & PB_SDA) != 0) +#define I2C_SDA(bit) if(bit) immr->im_cpm.cp_pbdat |= PB_SDA; \ + else immr->im_cpm.cp_pbdat &= ~PB_SDA +#define I2C_SCL(bit) if(bit) immr->im_cpm.cp_pbdat |= PB_SCL; \ + else immr->im_cpm.cp_pbdat &= ~PB_SCL +#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */ + +#define CFG_I2C_SPEED 100000 /* clock speed in Hz */ +#define CFG_I2C_SLAVE 0xFE /* I2C slave address */ + +/* + * Allow environment overwrites by anyone + */ +#define CONFIG_ENV_OVERWRITE + +/* + * The MPC860's internal RTC is horribly broken in rev D masks. Three + * internal MPC860T circuit nodes were inadvertently left floating; this + * causes KAPWR current in power down mode to be three orders of magnitude + * higher than specified in the datasheet (from 10 uA to 10 mA). No + * reasonable battery can keep that kind RTC running during powerdown for any + * length of time, so we use an external RTC on the I2C bus instead. + */ +#undef CONFIG_RTC_MPC8xx +#define CONFIG_RTC_DS1337 +#define CFG_I2C_RTC_ADDR 0x68 + +/* + * Allow partial commands to be matched to uniqueness. + */ +#define CFG_MATCH_PARTIAL_CMD + +/* + * List of available monitor commands. Use the system default list + * plus add some of the "non-standard" commands back in. + * See ./cmd_confdefs.h + */ +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DHCP | \ + CFG_CMD_I2C | \ + CFG_CMD_DOC | \ + CFG_CMD_EEPROM | \ + CFG_CMD_REGINFO | \ + CFG_CMD_IMMAP | \ + CFG_CMD_ELF | \ + CFG_CMD_DATE | \ + CFG_CMD_DATE | \ + CFG_CMD_FPGA | \ + CFG_CMD_MII | \ + CFG_CMD_BEDBUG \ + ) + +/* + * There is no IDE/PCMCIA hardware support on the board. + */ +#undef CONFIG_IDE_PCMCIA +#undef CONFIG_IDE_LED +#undef CONFIG_IDE_RESET + +/* + * Enable the call to misc_init_r() for miscellaneous platform + * dependent initialization. + */ +#define CONFIG_MISC_INIT_R + +/* + * Enable call to last_stage_init() so we can twiddle some LEDS :) + */ +#define CONFIG_LAST_STAGE_INIT + +/* + * Virtex2 FPGA configuration support + */ +#define CONFIG_FPGA_COUNT 1 +#define CONFIG_FPGA CFG_XILINX_VIRTEX2 +#define CFG_FPGA_PROG_FEEDBACK + + +/************************************************************************ + * This must be included AFTER the definition of any CONFIG_COMMANDS + */ +#include + +/* + * Verbose help from command monitor. + */ +#define CFG_LONGHELP +#define CFG_PROMPT "gen860t> " + +/* + * Use the "hush" command parser + */ +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " + +/* + * Set buffer size for console I/O + */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 +#else +#define CFG_CBSIZE 256 +#endif + +/* + * Print buffer size + */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) + +/* + * Maximum number of arguments that a command can accept + */ +#define CFG_MAXARGS 16 + +/* + * Boot argument buffer size + */ +#define CFG_BARGSIZE CFG_CBSIZE + +/* + * Default memory test range + */ +#define CFG_MEMTEST_START 0x0100000 +#define CFG_MEMTEST_END (CFG_MEMTEST_START + (128 * 1024)) + +/* + * Select the more full-featured memory test + */ +#define CFG_ALT_MEMTEST + +/* + * Default load address + */ +#define CFG_LOAD_ADDR 0x01000000 + +/* + * Set decrementer frequency (1 ms ticks) + */ +#define CFG_HZ 1000 + +/* + * Device memory map (after SDRAM remap to 0x0): + * + * CS Device Base Addr Size + * ---------------------------------------------------- + * CS0* Flash 0x40000000 64 M + * CS1* SDRAM 0x00000000 16 M + * CS2* Disk-On-Chip 0x50000000 32 K + * CS3* FPGA 0x60000000 64 M + * CS4* SelectMap 0x70000000 32 K + * CS5* Mil-Std 1553 I/F 0x80000000 32 K + * CS6* Unused + * CS7* Unused + * IMMR 860T Registers 0xfff00000 + */ + +/* + * Base addresses and block sizes + */ +#define CFG_IMMR 0xFF000000 + +#define SDRAM_BASE 0x00000000 +#define SDRAM_SIZE (64 * 1024 * 1024) + +#define FLASH_BASE 0x40000000 +#define FLASH_SIZE (16 * 1024 * 1024) + +#define DOC_BASE 0x50000000 +#define DOC_SIZE (32 * 1024) + +#define FPGA_BASE 0x60000000 +#define FPGA_SIZE (64 * 1024 * 1024) + +#define SELECTMAP_BASE 0x70000000 +#define SELECTMAP_SIZE (32 * 1024) + +#define M1553_BASE 0x80000000 +#define M1553_SIZE (64 * 1024) + +/* + * 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_INIT_DATA_SIZE 64 /* # bytes reserved for initial data*/ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_INIT_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 SDRAM_BASE + +/* + * FLASH organization + */ +#define CFG_FLASH_BASE FLASH_BASE +#define CFG_FLASH_SIZE FLASH_SIZE +#define CFG_FLASH_SECT_SIZE (128 * 1024) +#define CFG_MAX_FLASH_BANKS 1 +#define CFG_MAX_FLASH_SECT 128 + +/* + * The timeout values are for an entire chip and are in milliseconds. + * Yes I know that the write timeout is huge. Accroding to the + * datasheet a single byte takes 630 uS (round to 1 ms) max at worst + * case VCC and temp after 100K programming cycles. It works out + * to 280 minutes (might as well be forever). + */ +#define CFG_FLASH_ERASE_TOUT (CFG_MAX_FLASH_SECT * 5000) +#define CFG_FLASH_WRITE_TOUT (CFG_MAX_FLASH_SECT * 128 * 1024 * 1) + +/* + * Allow direct writes to FLASH from tftp transfers (** dangerous **) + */ +#define CFG_DIRECT_FLASH_TFTP + +/* + * Reserve memory for ppcboot. + */ +#define CFG_MAX_PPCBOOT_SECT 3 + +#if defined(DEBUG) +#define CFG_MONITOR_LEN (512 * 1024) +#else +#define CFG_MONITOR_LEN (256 * 1024) +#endif + +#define CFG_MONITOR_BASE CFG_FLASH_BASE + +/* + * Select environment placement. NOTE that ppcboot.lds must + * be edited if this is changed! + */ +#undef CFG_ENV_IS_IN_FLASH +#define CFG_ENV_IS_IN_EEPROM + +#if defined(CFG_ENV_IS_IN_EEPROM) +#define CFG_ENV_SIZE (2 * 1024) +#define CFG_ENV_OFFSET (CFG_ENV_EEPROM_SIZE - (8 * 1024)) +#else +#define CFG_ENV_SIZE (4 * 1024) +#define CFG_ENV_OFFSET (CFG_MAX_PPCBOOT_SECT * CFG_FLASH_SECT_SIZE) +#endif + +/* + * Reserve memory for malloc() + */ +#define CFG_MALLOC_LEN (128 * 1024) + +/* + * 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 * 1024 * 1024) + +/* + * 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 above value */ +#endif + +/*------------------------------------------------------------------------ + * SYPCR - System Protection Control UM 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 \ + ) +#else +#define CFG_SYPCR ( SYPCR_SWTC | \ + SYPCR_BMT | \ + SYPCR_BME | \ + SYPCR_SWF | \ + SYPCR_SWP \ + ) +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration UM 11-6 + *----------------------------------------------------------------------- + * Set debug pin mux, enable SPKROUT and GPLB5*. + */ +#define CFG_SIUMCR ( SIUMCR_DBGC11 | \ + SIUMCR_DBPC11 | \ + SIUMCR_MLRC11 | \ + SIUMCR_GB5E \ + ) + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control UM 11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freeze enabled + */ +#define CFG_TBSCR ( TBSCR_REFA | \ + TBSCR_REFB | \ + TBSCR_TBF \ + ) + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register UM 11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC ( RTCSC_SEC | \ + RTCSC_ALR | \ + RTCSC_RTF | \ + RTCSC_RTE \ + ) + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control UM 11-31 + *----------------------------------------------------------------------- + * Clear Periodic Interrupt Status, Interrupt Timer freezing enabled + */ +#define CFG_PISCR ( PISCR_PS | \ + PISCR_PITF \ + ) + +/*----------------------------------------------------------------------- + * PLPRCR - PLL, Low-Power, and Reset Control Register UM 15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit. Set MF for 1:2:1 mode. + */ +#define CFG_PLPRCR ( ((0x1 << PLPRCR_MF_SHIFT) & PLPRCR_MF_MSK) | \ + PLPRCR_SPLSS | \ + PLPRCR_TEXPS | \ + PLPRCR_TMIST \ + ) + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register UM 15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK SCCR_EBDF11 + +#define CFG_SCCR ( SCCR_TBS | /* timebase = GCLK/2 */ \ + SCCR_COM00 | /* full strength CLKOUT */ \ + SCCR_DFSYNC00 | /* SYNCLK / 1 (normal) */ \ + SCCR_DFBRG00 | /* BRGCLK / 1 (normal) */ \ + SCCR_DFNL000 | \ + SCCR_DFNH000 \ + ) + +/*----------------------------------------------------------------------- + * DER - Debug Enable Register UM 37-46 + *----------------------------------------------------------------------- + * Mask all events that can cause entry into debug mode + */ +#define CFG_DER 0 + +/* + * Initialize Memory Controller: + * + * BR0 and OR0 (FLASH memory) + */ +#define FLASH_BASE0_PRELIM FLASH_BASE + +/* + * Flash address mask + */ +#define CFG_PRELIM_OR_AM 0xfe000000 + +/* + * FLASH timing: + * 33 Mhz bus with ACS = 11, TRLX = 1, CSNT = 1, SCY = 3, EHTR = 1 + */ +#define CFG_OR_TIMING_FLASH ( OR_CSNT_SAM | \ + OR_ACS_DIV2 | \ + OR_BI | \ + OR_SCY_2_CLK | \ + OR_TRLX | \ + OR_EHTR \ + ) + +#define CFG_OR0_PRELIM ( CFG_PRELIM_OR_AM | \ + CFG_OR_TIMING_FLASH \ + ) + +#define CFG_BR0_PRELIM ( (FLASH_BASE0_PRELIM & BR_BA_MSK) | \ + BR_MS_GPCM | \ + BR_PS_8 | \ + BR_V \ + ) + +/* + * SDRAM configuration + */ +#define CFG_OR1_AM 0xfc000000 +#define CFG_OR1 ( (CFG_OR1_AM & OR_AM_MSK) | \ + OR_CSNT_SAM \ + ) + +#define CFG_BR1 ( (SDRAM_BASE & BR_BA_MSK) | \ + BR_MS_UPMA | \ + BR_PS_32 | \ + BR_V \ + ) + +/* + * Refresh rate 7.8 us (= 64 ms / 8K = 31.2 uS quad bursts) for one bank + * of 256 MBit SDRAM + */ +#define CFG_MPTPR_1BK_8K MPTPR_PTP_DIV16 + +/* + * Periodic timer for refresh @ 33 MHz system clock + */ +#define CFG_MAMR_PTA 64 + +/* + * MAMR settings for SDRAM + */ +#define CFG_MAMR_8COL ( (CFG_MAMR_PTA << MAMR_PTA_SHIFT) | \ + MAMR_PTAE | \ + MAMR_AMA_TYPE_1 | \ + MAMR_DSA_1_CYCL | \ + MAMR_G0CLA_A10 | \ + MAMR_RLFA_1X | \ + MAMR_WLFA_1X | \ + MAMR_TLFA_4X \ + ) + +/* + * CS2* configuration for Disk On Chip: + * 33 MHz bus with TRLX=1, ACS=11, CSNT=1, EBDF=1, SCY=2, EHTR=1, + * no burst. + */ +#define CFG_OR2_PRELIM ( (0xffff0000 & OR_AM_MSK) | \ + OR_CSNT_SAM | \ + OR_ACS_DIV2 | \ + OR_BI | \ + OR_SCY_2_CLK | \ + OR_TRLX | \ + OR_EHTR \ + ) + +#define CFG_BR2_PRELIM ( (DOC_BASE & BR_BA_MSK) | \ + BR_PS_8 | \ + BR_MS_GPCM | \ + BR_V \ + ) + +/* + * CS3* configuration for FPGA: + * 33 MHz bus with SCY=15, no burst. + * The FPGA uses TA and TEA to terminate bus cycles, but we + * clear SETA and set the cycle length to a large number so that + * the cycle will still complete even if there is a configuration + * error that prevents TA from asserting on FPGA accesss. + */ +#define CFG_OR3_PRELIM ( (0xfc000000 & OR_AM_MSK) | \ + OR_SCY_15_CLK | \ + OR_BI \ + ) + +#define CFG_BR3_PRELIM ( (FPGA_BASE & BR_BA_MSK) | \ + BR_PS_32 | \ + BR_MS_GPCM | \ + BR_V \ + ) +/* + * CS4* configuration for FPGA SelectMap configuration interface. + * 33 MHz bus, UPMB, no burst. Do not assert GPLB5 on falling edge + * of GCLK1_50 + */ +#define CFG_OR4_PRELIM ( (0xffff0000 & OR_AM_MSK) | \ + OR_G5LS | \ + OR_BI \ + ) + +#define CFG_BR4_PRELIM ( (SELECTMAP_BASE & BR_BA_MSK) | \ + BR_PS_8 | \ + BR_MS_UPMB | \ + BR_V \ + ) + +/* + * CS5* configuration for Mil-Std 1553 databus interface. + * 33 MHz bus, GPCM, no burst. + * The 1553 interface uses TA and TEA to terminate bus cycles, + * but we clear SETA and set the cycle length to a large number so that + * the cycle will still complete even if there is a configuration + * error that prevents TA from asserting on FPGA accesss. + */ +#define CFG_OR5_PRELIM ( (0xffff0000 & OR_AM_MSK) | \ + OR_SCY_15_CLK | \ + OR_EHTR | \ + OR_TRLX | \ + OR_CSNT_SAM | \ + OR_BI \ + ) + +#define CFG_BR5_PRELIM ( (M1553_BASE & BR_BA_MSK) | \ + BR_PS_16 | \ + BR_MS_GPCM | \ + BR_V \ + ) + +/* + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +/* + * Disk On Chip (millenium) configuration + */ +#define CFG_MAX_DOC_DEVICE 1 +#undef CFG_DOC_SUPPORT_2000 +#define CFG_DOC_SUPPORT_MILLENNIUM +#undef CFG_DOC_PASSIVE_PROBE + +/* + * FEC interrupt assignment + */ +#define FEC_INTERRUPT SIU_LEVEL1 + +/* + * Sanity checks + */ +#if defined(CONFIG_SCC1_ENET) && defined(CONFIG_FEC_ENET) +#error Both CONFIG_SCC1_ENET and CONFIG_FEC_ENET configured +#endif + +#endif /* __CONFIG_GEN860T_H */ + +/* vim: set ts=4 tw=78 ai shiftwidth=4: */ diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h index 99a843d..1799afe 100644 --- a/include/jffs2/load_kernel.h +++ b/include/jffs2/load_kernel.h @@ -37,8 +37,17 @@ struct part_info { /* Where in memory does this partition start? */ char *offset; + + /* used by jffs2 set to NULL */ + void *jffs2_priv; + + /* private filed used by user */ + void *usr_priv; }; +struct part_info* +jffs2_part_info(int part_num); + struct kernel_loader { /* Return true if there is a kernel contained at src */ diff --git a/include/ppc440.h b/include/ppc440.h index 361e3f4..0f41738 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -209,6 +209,11 @@ #define cpc0_cust0 (CNTRL_DCR_BASE+0x32) /* Customer configuration reg 0 */ #define cpc0_cust1 (CNTRL_DCR_BASE+0x33) /* Customer configuration reg 1 */ +#define cpc0_strp0 (CNTRL_DCR_BASE+0x34) /* Power-on config reg 0 (RO) */ +#define cpc0_strp1 (CNTRL_DCR_BASE+0x35) /* Power-on config reg 1 (RO) */ +#define cpc0_strp2 (CNTRL_DCR_BASE+0x36) /* Power-on config reg 2 (RO) */ +#define cpc0_strp3 (CNTRL_DCR_BASE+0x37) /* Power-on config reg 3 (RO) */ + #define cntrl0 (CNTRL_DCR_BASE+0x3b) /* Control 0 register */ #define cntrl1 (CNTRL_DCR_BASE+0x3a) /* Control 1 register */ @@ -448,6 +453,69 @@ #define MODEM_STATUS 0x06 #define SCRATCH 0x07 +/*----------------------------------------------------------------------------- +| PCI Internal Registers et. al. (accessed via plb) ++----------------------------------------------------------------------------*/ +#define PCIX0_CFGADR (CFG_PCI_BASE + 0x0ec00000) +#define PCIX0_CFGDATA (CFG_PCI_BASE + 0x0ec00004) +#define PCIX0_CFGBASE (CFG_PCI_BASE + 0x0ec80000) +#define PCIX0_IOBASE (CFG_PCI_BASE + 0x08000000) + +#define PCIX0_VENDID (PCIX0_CFGBASE + PCI_VENDOR_ID ) +#define PCIX0_DEVID (PCIX0_CFGBASE + PCI_DEVICE_ID ) +#define PCIX0_CMD (PCIX0_CFGBASE + PCI_COMMAND ) +#define PCIX0_STATUS (PCIX0_CFGBASE + PCI_STATUS ) +#define PCIX0_REVID (PCIX0_CFGBASE + PCI_REVISION_ID ) +#define PCIX0_CLS (PCIX0_CFGBASE + PCI_CLASS_CODE) +#define PCIX0_CACHELS (PCIX0_CFGBASE + PCI_CACHE_LINE_SIZE ) +#define PCIX0_LATTIM (PCIX0_CFGBASE + PCI_LATENCY_TIMER ) +#define PCIX0_HDTYPE (PCIX0_CFGBASE + PCI_HEADER_TYPE ) +#define PCIX0_BIST (PCIX0_CFGBASE + PCI_BIST ) +#define PCIX0_BAR0 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_0 ) +#define PCIX0_BAR1 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_1 ) +#define PCIX0_BAR2 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_2 ) +#define PCIX0_BAR3 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_3 ) +#define PCIX0_BAR4 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_4 ) +#define PCIX0_BAR5 (PCIX0_CFGBASE + PCI_BASE_ADDRESS_5 ) +#define PCIX0_CISPTR (PCIX0_CFGBASE + PCI_CARDBUS_CIS ) +#define PCIX0_SBSYSVID (PCIX0_CFGBASE + PCI_SUBSYSTEM_VENDOR_ID ) +#define PCIX0_SBSYSID (PCIX0_CFGBASE + PCI_SUBSYSTEM_ID ) +#define PCIX0_EROMBA (PCIX0_CFGBASE + PCI_ROM_ADDRESS ) +#define PCIX0_CAP (PCIX0_CFGBASE + PCI_CAPABILITY_LIST ) +#define PCIX0_RES0 (PCIX0_CFGBASE + 0x0035 ) +#define PCIX0_RES1 (PCIX0_CFGBASE + 0x0036 ) +#define PCIX0_RES2 (PCIX0_CFGBASE + 0x0038 ) +#define PCIX0_INTLN (PCIX0_CFGBASE + PCI_INTERRUPT_LINE ) +#define PCIX0_INTPN (PCIX0_CFGBASE + PCI_INTERRUPT_PIN ) +#define PCIX0_MINGNT (PCIX0_CFGBASE + PCI_MIN_GNT ) +#define PCIX0_MAXLTNCY (PCIX0_CFGBASE + PCI_MAX_LAT ) + +#define PCIX0_BRDGOPT1 (PCIX0_CFGBASE + 0x0040) +#define PCIX0_BRDGOPT2 (PCIX0_CFGBASE + 0x0044) + +#define PCIX0_POM0LAL (PCIX0_CFGBASE + 0x0068) +#define PCIX0_POM0LAH (PCIX0_CFGBASE + 0x006c) +#define PCIX0_POM0SA (PCIX0_CFGBASE + 0x0070) +#define PCIX0_POM0PCIAL (PCIX0_CFGBASE + 0x0074) +#define PCIX0_POM0PCIAH (PCIX0_CFGBASE + 0x0078) +#define PCIX0_POM1LAL (PCIX0_CFGBASE + 0x007c) +#define PCIX0_POM1LAH (PCIX0_CFGBASE + 0x0080) +#define PCIX0_POM1SA (PCIX0_CFGBASE + 0x0084) +#define PCIX0_POM1PCIAL (PCIX0_CFGBASE + 0x0088) +#define PCIX0_POM1PCIAH (PCIX0_CFGBASE + 0x008c) +#define PCIX0_POM2SA (PCIX0_CFGBASE + 0x0090) + +#define PCIX0_PIM0SA (PCIX0_CFGBASE + 0x0098) +#define PCIX0_PIM0LAL (PCIX0_CFGBASE + 0x009c) +#define PCIX0_PIM0LAH (PCIX0_CFGBASE + 0x00a0) +#define PCIX0_PIM1SA (PCIX0_CFGBASE + 0x00a4) +#define PCIX0_PIM1LAL (PCIX0_CFGBASE + 0x00a8) +#define PCIX0_PIM1LAH (PCIX0_CFGBASE + 0x00ac) +#define PCIX0_PIM2SA (PCIX0_CFGBASE + 0x00b0) +#define PCIX0_PIM2LAL (PCIX0_CFGBASE + 0x00b4) +#define PCIX0_PIM2LAH (PCIX0_CFGBASE + 0x00b8) + +#define PCIX0_STS (PCIX0_CFGBASE + 0x00e0) /* * Macros for accessing the indirect EBC registers diff --git a/include/status_led.h b/include/status_led.h index 1c0ebbb..7c86ae1 100644 --- a/include/status_led.h +++ b/include/status_led.h @@ -88,6 +88,30 @@ void status_led_set (int led, int state); # define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ +/***** GEN860T *********************************************************/ +#elif defined(CONFIG_GEN860T) + +# define STATUS_LED_PAR im_ioport.iop_papar +# define STATUS_LED_DIR im_ioport.iop_padir +# define STATUS_LED_ODR im_ioport.iop_paodr +# define STATUS_LED_DAT im_ioport.iop_padat + +# define STATUS_LED_BIT 0x0800 /* Red LED 0 is on PA.4 */ +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING +# define STATUS_LED_BIT1 0x0400 /* Grn LED 1 is on PA.5 */ +# define STATUS_LED_PERIOD1 (CFG_HZ / 2) +# define STATUS_LED_STATE1 STATUS_LED_BLINKING +# define STATUS_LED_BIT2 0x0080 /* Red LED 2 is on PA.8 */ +# define STATUS_LED_PERIOD2 (CFG_HZ / 2) +# define STATUS_LED_STATE2 STATUS_LED_BLINKING +# define STATUS_LED_BIT3 0x0040 /* Grn LED 3 is on PA.9 */ +# define STATUS_LED_PERIOD3 (CFG_HZ / 2) +# define STATUS_LED_STATE3 STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ +# define STATUS_LED_BOOT 0 /* Boot status on LED 1 */ + /***** IVMS8 **********************************************************/ #elif defined(CONFIG_IVMS8)