diff options
208 files changed, 79197 insertions, 0 deletions
@@ -0,0 +1,242 @@ +# +# Parts of the development effort for this project have been +# sponsored by SIEMENS AG, Austria. Thanks to SIEMENS for +# supporting an Open Source project! +# +# +# This is at least a partial credits-file of individual people that +# have contributed to the U-Boot project. It is sorted by name and +# formatted to allow easy grepping and beautification by scripts. +# The fields are: name (N), email (E), web-address (W), PGP key ID +# and fingerprint (P), description (D), and snail-mail address (S). +# Thanks, +# +# Wolfgang Denk +#---------- + +N: Dr. Bruno Achauer +E: bruno@exet-ag.de +D: Support for NetBSD (both as host and target system) + +N: Swen Anderson +E: sand@peppercon.de +D: ERIC Support + +N: Guillaume Alexandre +E: guillaume.alexandre@gespac.ch +D: Add PCIPPC6 configuration + +N: Pierre Aubert +E: <p.aubert@staubli.com> +D: Support for RPXClassic board + +N: Andre Beaudin +E: <andre.beaudin@colubris.com> +D: PCMCIA, Ethernet, TFTP + +N: Jerry van Baren +E: <vanbaren@cideas.com> +D: BedBug port to 603e core (MPC82xx). Code for enhanced memory test. + +N: Raphael Bossek +E: raphael.bossek@solutions4linux.de +D: 8xxrom-0.3.0 + +N: David Brown +E: DBrown03@harris.com +D: Extensions to 8xxrom-0.3.0 + +N: Oliver Brown +E: obrown@adventnetworks.com +D: Port to the gw8260 board + +N: Jonathan De Bruyne +E: jonathan.debruyne@siemens.atea.be +D: Port to Siemens IAD210 board + +N: Conn Clark +E: clark@esteem.com +D: ESTEEM192E support + +N: Magnus Damm +E: eramdam@kieray1.p.y.ki.era.ericsson.se +D: 8xxrom + +N: Kári Davíðsson +E: kd@flaga.is +D: FLAGA DM Support + +N: Wolfgang Denk +E: wd@denx.de +D: U-Boot initial version, continuing maintenance, ARMBoot merge +W: http://www.denx.de + +N: Dan A. Dickey +E: ddickey@charter.net +D: FADS Support + +N: James F. Dougherty +E: jfd@GigabitNetworks.COM +D: Port to the MOUSSE board + +N: Dave Ellis +E: DGE@sixnetio.com +D: EEPROM Speedup, SXNI855T port + +N: Dr. Wolfgang Grandegger +E: wg@denx.de +D: Support for Interphase 4539 T1/E1/J1 PMC, PN62, CCM, SCM boards +W: www.denx.de + +N: Frank Gottschling +E: fgottschling@eltec.de +D: Support for ELTEC MHPC/BAB7xx/ELPPC boards, cfb-console, i8042, SMI LynxEM +W: www.eltec.de + +N: Marius Groeger +E: mgroeger@sysgo.de +D: MBX Support, board specific function interface, EST SBC8260 support; initial support for StrongARM (LART), ARM720TDMI (implementa A7) +W: www.elinos.com + +N: Kirk Haderlie +E: khaderlie@vividimage.com +D: Added TFTP to 8xxrom (-> 0.3.1) + +N: Chris Hallinan +E: clh@net1plus.com +D: DHCP Support + +N: Anne-Sophie Harnois +E: Anne-Sophie.Harnois@nextream.fr +D: Port to Walnut405 board + +N: Andreas Heppel +E: aheppel@sysgo.de +D: CPU Support for MPC 75x; board support for Eltec BAB750 [obsolete!] + +N: Josh Huber +E: huber@alum.wpi.edu +D: Port to the Galileo Evaluation Board, and the MPC74xx cpu series. +W: http://www.mclx.com/ + +H: Stuart Hughes +E: stuarth@lineo.com +D: Port to MPC8260ADS board + +H: Rich Ireland +E: r.ireland@computer.org +D: FPGA device configuration driver + +N: Gary Jennejohn +E: garyj@jennejohn.org, gj@denx.de +D: Support for Samsung ARM920T S3C2400X, ARM920T "TRAB" +W: www.denx.de + +N: Murray Jensen +E: Murray.Jensen@cmst.csiro.au +D: Initial 8260 support; GDB support +D: Port to Cogent+Hymod boards; Hymod Board Database +W: http://www.msa.cmst.csiro.au/ourstaff/MurrayJensen/mjj.html + +N: Yoo. Jonghoon +E: yooth@ipone.co.kr +D: Added port to the RPXlite board + +N: Brad Kemp +E: Brad.Kemp@seranoa.com +D: Port to Windriver ppmc8260 board + +N: Thomas Koeller +E: tkoeller@gmx.net +D: Port to Motorola Sandpoint 3 (MPC8240) + +N: Thomas Lange +E: thomas@corelatus.com +D: Support for GTH board; lots of PCMCIA fixes + +N: Raymond Lo +E: lo@routefree.com +D: Support for DOS partitions + +N: Dan Malek +E: dan@netx4.com +D: FADSROM, the grandfather of all of this + +N: Jay Monkman +E: jtm@smoothsmoothie.com +D: EST SBC8260 support + +N: Frank Morauf +E: frank.morauf@salzbrenner.com +D: Support for Embedded Planet RPX Super Board + +N: David Müller +E: d.mueller@elsoft.ch +D: Support for Samsung ARM920T SMDK2410 eval board + +N: Rolf Offermanns +E: rof@sysgo.de +D: Initial support for SSV-DNP1110, SMC91111 driver +W: www.elinos.com + +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 + +N: Denis Peter +E: d.peter@mpl.ch +D: Support for 4xx SCSI, floppy, CDROM, CT69000 video, ... +D: Support for PIP405 board +D: Support for MIP405 board + +N: Bill Pitts +E: wlp@mindspring.com +D: BedBug embedded debugger code + +N: Stefan Roese +E: stefan.roese@esd-electronics.com +D: IBM PPC401/403/405GP Support; Windows environment support + +N: Neil Russell +E: caret@c-side.com +D: Author of LiMon-1.4.2, which contributed some ideas + +N: Paolo Scaffardi +E: arsenio@tin.it +D: FADS823 configuration, MPC823 video support, I2C, wireless keyboard, lots more + +N: Robert Schwebel +E: r.schwebel@pengutronix.de +D: Support for csb226 board (xscale) +N: Rob Taylor +E: robt@flyingpig.com +D: Port to MBX860T and Sandpoint8240 + +N: Erik Theisen +E: etheisen@mindspring.com +D: MBX8xx and many other patches + +N: Jim Thompson +E: jim@musenki.com +D: Support for MUSENKI board + +N: David Updegraff +E: dave@cray.com +D: Port to Cray L1 board; DHCP vendor extensions + +N: Christian Vejlbo +E: christian.vejlbo@tellabs.com +D: FADS860T ethernet support + +N: Alex Zuepke +E: azu@sysgo.de +D: Overall improvements on StrongARM, ARM720TDMI; Support for Tuxscreen; initial PCMCIA support for ARM +W: www.elinos.com @@ -0,0 +1,2663 @@ +# +# (C) Copyright 2000 - 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +Summary: +======== + +This directory contains the source code for U-Boot, a monitor for +Embedded PowerPC boards, which can be installed in a boot ROM and +used to test the hardware or download and run application code. + +The development of U-Boot is closely related to Linux: some parts of +the source code originate in the Linux source tree, we still have +some header files in common, and special provision has been made to +support booting of Linux images. + +Some attention has been paid to make this software easily +configurable and extendable. For instance, all monitor commands are +implemented with the same call interface, so that it's very easy to +add new commands. Also, instead of permanently adding rarely used +code (for instance hardware test utilities) to the monitor, you can +load and run it dynamically. + + +Status: +======= + +In general, all boards for which a configuration option exists in the +Makefile have been tested to some extent and can be considered +"working". In fact, many of them are used in production systems. + +In case of problems see the CHANGELOG and CREDITS files to find out +who contributed the specific port. + +Exception from this rule: the port to the Sandpoint 8240 has not been +completed yet. + + +Where to get help: +================== + +In case you have questions about, problems with or contributions for +U-Boot you should send a message to the U-Boot mailing list at +<u-boot-users@lists.sourceforge.net>. There is also an archive of +previous traffic on the mailing list - please search the archive +before asking FAQ's. Please see +http://lists.sourceforge.net/lists/listinfo/u-boot-users/ + + +Where we come from: +=================== + +- start from 8xxrom sources +- clean up code +- make it easier to add custom boards +- make it possible to add other [PowerPC] CPUs +- extend functions, especially: + * Provide extended interface to Linux boot loader + * S-Record download + * network boot + * PCMCIA / CompactFLash / ATA disk / SCSI ... boot +- add other CPU families (starting with ARM) + + +Directory Hierarchy: +==================== + +- board Board dependend files +- common Misc architecture independend functions +- cpu CPU specific files +- disk Code for disk drive partition handling +- doc Documentation (don't expect too much) +- drivers Common used device drivers +- dtt Digital Thermometer and Thermostat drivers +- examples Example code for standalone applications, etc. +- include Header Files +- disk Harddisk interface code +- net Networking code +- ppc Files generic to PowerPC architecture +- post Power On Self Test +- post/arch Symlink to architecture specific Power On Self Test +- post/arch-ppc PowerPC architecture specific Power On Self Test +- post/cpu/mpc8260 MPC8260 CPU specific Power On Self Test +- post/cpu/mpc8xx MPC8xx CPU specific Power On Self Test +- rtc Real Time Clock drivers +- tools Tools to build S-Record or U-Boot images, etc. + +- cpu/74xx_7xx Files specific to Motorola MPC74xx and 7xx CPUs +- cpu/mpc8xx Files specific to Motorola MPC8xx CPUs +- cpu/mpc824x Files specific to Motorola MPC824x CPUs +- cpu/mpc8260 Files specific to Motorola MPC8260 CPU +- cpu/ppc4xx Files specific to IBM 4xx CPUs + +- board/RPXClassic + Files specific to RPXClassic boards +- board/RPXlite Files specific to RPXlite boards +- board/c2mon Files specific to c2mon boards +- board/cogent Files specific to Cogent boards + (need further configuration) + Files specific to CPCIISER4 boards +- board/cpu86 Files specific to CPU86 boards +- board/cray/ Files specific to boards manufactured by Cray +- board/cray/L1 Files specific to L1 boards +- board/cu824 Files specific to CU824 boards +- board/ebony Files specific to IBM Ebony board +- board/eric Files specific to ERIC boards +- board/esd/ Files specific to boards manufactured by ESD +- board/esd/adciop Files specific to ADCIOP boards +- board/esd/ar405 Files specific to AR405 boards +- board/esd/canbt Files specific to CANBT boards +- board/esd/cpci405 Files specific to CPCI405 boards +- board/esd/cpciiser4 Files specific to CPCIISER4 boards +- board/esd/common Common files for ESD boards +- board/esd/dasa_sim Files specific to DASA_SIM boards +- board/esd/du405 Files specific to DU405 boards +- board/esd/ocrtc Files specific to OCRTC boards +- board/esd/pci405 Files specific to PCI405 boards +- board/esteem192e + Files specific to ESTEEM192E boards +- board/etx094 Files specific to ETX_094 boards +- board/evb64260 + Files specific to EVB64260 boards +- board/fads Files specific to FADS boards +- board/flagadm Files specific to FLAGADM boards +- board/gen860t Files specific to GEN860T boards +- board/genietv Files specific to GENIETV boards +- board/gth Files specific to GTH boards +- board/hermes Files specific to HERMES boards +- board/hymod Files specific to HYMOD boards +- board/icu862 Files specific to ICU862 boards +- board/ip860 Files specific to IP860 boards +- board/iphase4539 + Files specific to Interphase4539 boards +- board/ivm Files specific to IVMS8/IVML24 boards +- board/lantec Files specific to LANTEC boards +- board/lwmon Files specific to LWMON boards +- board/mbx8xx Files specific to MBX boards +- board/mpc8260ads + Files specific to MMPC8260ADS boards +- board/mpl/ Files specific to boards manufactured by MPL +- board/mpl/common Common files for MPL boards +- board/mpl/pip405 Files specific to PIP405 boards +- board/mpl/mip405 Files specific to MIP405 boards +- board/musenki Files specific to MUSEKNI boards +- board/mvs1 Files specific to MVS1 boards +- board/nx823 Files specific to NX823 boards +- board/oxc Files specific to OXC boards +- board/pcippc2 Files specific to PCIPPC2/PCIPPC6 boards +- board/pm826 Files specific to PM826 boards +- board/ppmc8260 + Files specific to PPMC8260 boards +- board/rpxsuper + Files specific to RPXsuper boards +- board/rsdproto + Files specific to RSDproto boards +- board/sandpoint + Files specific to Sandpoint boards +- board/sbc8260 Files specific to SBC8260 boards +- board/sacsng Files specific to SACSng boards +- board/siemens Files specific to boards manufactured by Siemens AG +- board/siemens/CCM Files specific to CCM boards +- board/siemens/IAD210 Files specific to IAD210 boards +- board/siemens/SCM Files specific to SCM boards +- board/siemens/pcu_e Files specific to PCU_E boards +- board/sixnet Files specific to SIXNET boards +- board/spd8xx Files specific to SPD8xxTS boards +- board/tqm8260 Files specific to TQM8260 boards +- board/tqm8xx Files specific to TQM8xxL boards +- board/w7o Files specific to W7O boards +- board/walnut405 + Files specific to Walnut405 boards +- board/westel/ Files specific to boards manufactured by Westel Wireless +- board/westel/amx860 Files specific to AMX860 boards +- board/utx8245 Files specific to UTX8245 boards + +Software Configuration: +======================= + +Configuration is usually done using C preprocessor defines; the +rationale behind that is to avoid dead code whenever possible. + +There are two classes of configuration variables: + +* Configuration _OPTIONS_: + These are selectable by the user and have names beginning with + "CONFIG_". + +* Configuration _SETTINGS_: + These depend on the hardware etc. and should not be meddled with if + you don't know what you're doing; they have names beginning with + "CFG_". + +Later we will add a configuration tool - probably similar to or even +identical to what's used for the Linux kernel. Right now, we have to +do the configuration by hand, which means creating some symbolic +links and editing some configuration files. We use the TQM8xxL boards +as an example here. + + +Selection of Processor Architecture and Board Type: +--------------------------------------------------- + +For all supported boards there are ready-to-use default +configurations available; just type "make <board_name>_config". + +Example: For a TQM823L module type: + + cd u-boot + make TQM823L_config + +For the Cogent platform, you need to specify the cpu type as well; +e.g. "make cogent_mpc8xx_config". And also configure the cogent +directory according to the instructions in cogent/README. + + +Configuration Options: +---------------------- + +Configuration depends on the combination of board and CPU type; all +such information is kept in a configuration file +"include/configs/<board_name>.h". + +Example: For a TQM823L module, all configuration settings are in +"include/configs/TQM823L.h". + + +The following options need to be configured: + +- CPU Type: Define exactly one of + + PowerPC based CPUs: + ------------------- + CONFIG_MPC823, CONFIG_MPC850, CONFIG_MPC855, CONFIG_MPC860 + or CONFIG_MPC824X, CONFIG_MPC8260 + or CONFIG_IOP480 + or CONFIG_405GP + or CONFIG_440 + or CONFIG_MPC74xx + + ARM based CPUs: + --------------- + CONFIG_SA1110 + CONFIG_ARM7 + CONFIG_PXA250 + + +- Board Type: Define exactly one of + + PowerPC based boards: + --------------------- + + CONFIG_ADCIOP, CONFIG_ICU862 CONFIG_RPXsuper, + CONFIG_ADS860, CONFIG_IP860, CONFIG_SM850, + CONFIG_AMX860, CONFIG_IPHASE4539, CONFIG_SPD823TS, + CONFIG_AR405, CONFIG_IVML24, CONFIG_SXNI855T, + CONFIG_BAB7xx, CONFIG_IVML24_128, CONFIG_Sandpoint8240, + CONFIG_CANBT, CONFIG_IVML24_256, CONFIG_Sandpoint8245, + CONFIG_CCM, CONFIG_IVMS8, CONFIG_TQM823L, + CONFIG_CPCI405, CONFIG_IVMS8_128, CONFIG_TQM850L, + CONFIG_CPCI4052, CONFIG_IVMS8_256, CONFIG_TQM855L, + CONFIG_CPCIISER4, CONFIG_LANTEC, CONFIG_TQM860L, + CONFIG_CPU86, CONFIG_MBX, CONFIG_TQM8260, + CONFIG_CRAYL1, CONFIG_MBX860T, CONFIG_TTTech, + CONFIG_CU824, CONFIG_MHPC, CONFIG_UTX8245, + CONFIG_DASA_SIM, CONFIG_MIP405, CONFIG_W7OLMC, + CONFIG_DU405, CONFIG_MOUSSE, CONFIG_W7OLMG, + CONFIG_ELPPC, CONFIG_MPC8260ADS, CONFIG_WALNUT405, + CONFIG_ERIC, CONFIG_MUSENKI, CONFIG_ZUMA, + CONFIG_ESTEEM192E, CONFIG_MVS1, CONFIG_c2mon, + CONFIG_ETX094, CONFIG_NX823, CONFIG_cogent_mpc8260, + CONFIG_EVB64260, CONFIG_OCRTC, CONFIG_cogent_mpc8xx, + CONFIG_FADS823, CONFIG_ORSG, CONFIG_ep8260, + CONFIG_FADS850SAR, CONFIG_OXC, CONFIG_gw8260, + CONFIG_FADS860T, CONFIG_PCI405, CONFIG_hermes, + CONFIG_FLAGADM, CONFIG_PCIPPC2, CONFIG_hymod, + CONFIG_FPS850L, CONFIG_PCIPPC6, CONFIG_lwmon, + CONFIG_GEN860T, CONFIG_PIP405, CONFIG_pcu_e, + CONFIG_GENIETV, CONFIG_PM826, CONFIG_ppmc8260, + CONFIG_GTH, CONFIG_RPXClassic, CONFIG_rsdproto, + CONFIG_IAD210, CONFIG_RPXlite, CONFIG_sbc8260, + CONFIG_EBONY, CONFIG_sacsng + + ARM based boards: + ----------------- + + CONFIG_HHP_CRADLE, CONFIG_DNP1110, CONFIG_EP7312, + CONFIG_IMPA7, CONFIG_LART, CONFIG_LUBBOCK, + CONFIG_SHANNON, CONFIG_SMDK2400, CONFIG_SMDK2410, + CONFIG_TRAB + + +- CPU Module Type: (if CONFIG_COGENT is defined) + Define exactly one of + CONFIG_CMA286_60_OLD +--- FIXME --- not tested yet: + CONFIG_CMA286_60, CONFIG_CMA286_21, CONFIG_CMA286_60P, + CONFIG_CMA287_23, CONFIG_CMA287_50 + +- Motherboard Type: (if CONFIG_COGENT is defined) + Define exactly one of + CONFIG_CMA101, CONFIG_CMA102 + +- Motherboard I/O Modules: (if CONFIG_COGENT is defined) + Define one or more of + CONFIG_CMA302 + +- Motherboard Options: (if CONFIG_CMA101 or CONFIG_CMA102 are defined) + Define one or more of + CONFIG_LCD_HEARTBEAT - update a character position on + the lcd display every second with + a "rotator" |\-/|\-/ + +- MPC824X Family Member (if CONFIG_MPC824X is defined) + Define exactly one of + CONFIG_MPC8240, CONFIG_MPC8245 + +- 8xx CPU Options: (if using an 8xx cpu) + Define one or more of + CONFIG_8xx_GCLK_FREQ - if get_gclk_freq() can not work e.g. + no 32KHz reference PIT/RTC clock + +- Clock Interface: + CONFIG_CLOCKS_IN_MHZ + + U-Boot stores all clock information in Hz + internally. For binary compatibility with older Linux + kernels (which expect the clocks passed in the + bd_info data to be in MHz) the environment variable + "clocks_in_mhz" can be defined so that U-Boot + converts clock data to MHZ before passing it to the + Linux kernel. + + When CONFIG_CLOCKS_IN_MHZ is defined, a definition of + "clocks_in_mhz=1" is automatically included in the + default environment. + +- Console Interface: + Depending on board, define exactly one serial port + (like CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2, + CONFIG_8xx_CONS_SCC1, ...), or switch off the serial + console by defining CONFIG_8xx_CONS_NONE + + Note: if CONFIG_8xx_CONS_NONE is defined, the serial + port routines must be defined elsewhere + (i.e. serial_init(), serial_getc(), ...) + + CONFIG_CFB_CONSOLE + Enables console device for a color framebuffer. Needs following + defines (cf. smiLynxEM, i8042, board/eltec/bab7xx) + VIDEO_FB_LITTLE_ENDIAN graphic memory organisation + (default big endian) + VIDEO_HW_RECTFILL graphic chip supports + rectangle fill + (cf. smiLynxEM) + VIDEO_HW_BITBLT graphic chip supports + bit-blit (cf. smiLynxEM) + VIDEO_VISIBLE_COLS visible pixel columns + (cols=pitch) + VIDEO_VISIBLE_ROWS visible pixel rows + VIDEO_PIXEL_SIZE bytes per pixel + VIDEO_DATA_FORMAT graphic data format + (0-5, cf. cfb_console.c) + VIDEO_FB_ADRS framebuffer address + VIDEO_KBD_INIT_FCT keyboard int fct + (i.e. i8042_kbd_init()) + VIDEO_TSTC_FCT test char fct + (i.e. i8042_tstc) + VIDEO_GETC_FCT get char fct + (i.e. i8042_getc) + CONFIG_CONSOLE_CURSOR cursor drawing on/off + (requires blink timer + cf. i8042.c) + CFG_CONSOLE_BLINK_COUNT blink interval (cf. i8042.c) + CONFIG_CONSOLE_TIME display time/date info in + upper right corner + (requires CFG_CMD_DATE) + CONFIG_VIDEO_LOGO display Linux logo in + upper left corner + CONFIG_CONSOLE_EXTRA_INFO + addional board info beside + the logo + + When CONFIG_CFB_CONSOLE is defined, video console is + default i/o. Serial console can be forced with + environment 'console=serial'. + +- Console Baudrate: + CONFIG_BAUDRATE - in bps + Select one of the baudrates listed in + CFG_BAUDRATE_TABLE, see below. + +- Interrupt driven serial port input: + CONFIG_SERIAL_SOFTWARE_FIFO + + PPC405GP only. + Use an interrupt handler for receiving data on the + serial port. It also enables using hardware handshake + (RTS/CTS) and UART's built-in FIFO. Set the number of + bytes the interrupt driven input buffer should have. + + Set to 0 to disable this feature (this is the default). + This will also disable hardware handshake. + +- Boot Delay: CONFIG_BOOTDELAY - in seconds + Delay before automatically booting the default image; + set to -1 to disable autoboot. + + See doc/README.autoboot for these options that + work with CONFIG_BOOTDELAY. None are required. + CONFIG_BOOT_RETRY_TIME + CONFIG_BOOT_RETRY_MIN + CONFIG_AUTOBOOT_KEYED + CONFIG_AUTOBOOT_PROMPT + CONFIG_AUTOBOOT_DELAY_STR + CONFIG_AUTOBOOT_STOP_STR + CONFIG_AUTOBOOT_DELAY_STR2 + CONFIG_AUTOBOOT_STOP_STR2 + CONFIG_ZERO_BOOTDELAY_CHECK + CONFIG_RESET_TO_RETRY + +- Autoboot Command: + CONFIG_BOOTCOMMAND + Only needed when CONFIG_BOOTDELAY is enabled; + define a command string that is automatically executed + when no character is read on the console interface + within "Boot Delay" after reset. + + CONFIG_BOOTARGS + This can be used to pass arguments to the bootm + command. The value of CONFIG_BOOTARGS goes into the + environment value "bootargs". + + CONFIG_RAMBOOT and CONFIG_NFSBOOT + The value of these goes into the environment as + "ramboot" and "nfsboot" respectively, and can be used + as a convenience, when switching between booting from + ram and nfs. + +- Pre-Boot Commands: + CONFIG_PREBOOT + + When this option is #defined, the existence of the + environment variable "preboot" will be checked + immediately before starting the CONFIG_BOOTDELAY + countdown and/or running the auto-boot command resp. + entering interactive mode. + + This feature is especially useful when "preboot" is + automatically generated or modified. For an example + see the LWMON board specific code: here "preboot" is + modified when the user holds down a certain + combination of keys on the (special) keyboard when + booting the systems + +- Serial Download Echo Mode: + CONFIG_LOADS_ECHO + If defined to 1, all characters received during a + serial download (using the "loads" command) are + echoed back. This might be needed by some terminal + emulations (like "cu"), but may as well just take + time on others. This setting #define's the initial + value of the "loads_echo" environment variable. + +- Kgdb Serial Baudrate: (if CFG_CMD_KGDB is defined) + CONFIG_KGDB_BAUDRATE + Select one of the baudrates listed in + CFG_BAUDRATE_TABLE, see below. + +- Monitor Functions: + CONFIG_COMMANDS + Most monitor functions can be selected (or + de-selected) by adjusting the definition of + CONFIG_COMMANDS; to select individual functions, + #define CONFIG_COMMANDS by "OR"ing any of the + following values: + + #define enables commands: + ------------------------- + CFG_CMD_ASKENV * ask for env variable + CFG_CMD_BDI bdinfo + CFG_CMD_BEDBUG Include BedBug Debugger + CFG_CMD_BOOTD bootd + CFG_CMD_CACHE icache, dcache + CFG_CMD_CONSOLE coninfo + CFG_CMD_DATE * support for RTC, date/time... + CFG_CMD_DHCP DHCP support + CFG_CMD_ECHO * echo arguments + CFG_CMD_EEPROM * EEPROM read/write support + CFG_CMD_ELF bootelf, bootvx + CFG_CMD_ENV saveenv + CFG_CMD_FDC * Floppy Disk Support + CFG_CMD_FLASH flinfo, erase, protect + CFG_CMD_FPGA FPGA device initialization support + CFG_CMD_I2C * I2C serial bus support + CFG_CMD_IDE * IDE harddisk support + CFG_CMD_IMI iminfo + CFG_CMD_IMMAP * IMMR dump support + CFG_CMD_IRQ * irqinfo + CFG_CMD_KGDB * kgdb + CFG_CMD_LOADB loadb + CFG_CMD_LOADS loads + CFG_CMD_MEMORY md, mm, nm, mw, cp, cmp, crc, base, + loop, mtest + CFG_CMD_MII MII utility commands + CFG_CMD_NET bootp, tftpboot, rarpboot + CFG_CMD_PCI * pciinfo + CFG_CMD_PCMCIA * PCMCIA support + CFG_CMD_REGINFO * Register dump + CFG_CMD_RUN run command in env variable + CFG_CMD_SCSI * SCSI Support + CFG_CMD_SETGETDCR Support for DCR Register access (4xx only) + CFG_CMD_SPI * SPI serial bus support + CFG_CMD_USB * USB support + CFG_CMD_BSP * Board SPecific functions + ----------------------------------------------- + CFG_CMD_ALL all + + CFG_CMD_DFL Default configuration; at the moment + this is includes all commands, except + the ones marked with "*" in the list + above. + + If you don't define CONFIG_COMMANDS it defaults to + CFG_CMD_DFL in include/cmd_confdefs.h. A board can + override the default settings in the respective + include file. + + EXAMPLE: If you want all functions except of network + support you can write: + + #define CONFIG_COMMANDS (CFG_CMD_ALL & ~CFG_CMD_NET) + + + Note: Don't enable the "icache" and "dcache" commands + (configuration option CFG_CMD_CACHE) unless you know + what you (and your U-Boot users) are doing. Data + cache cannot be enabled on systems like the 8xx or + 8260 (where accesses to the IMMR region must be + uncached), and it cannot be disabled on all other + systems where we (mis-) use the data cache to hold an + initial stack and some data. + + + XXX - this list needs to get updated! + +- Watchdog: + CONFIG_WATCHDOG + If this variable is defined, it enables watchdog + support. There must support in the platform specific + code for a watchdog. For the 8xx and 8260 CPUs, the + SIU Watchdog feature is enabled in the SYPCR + register. + +- Real-Time Clock: + + When CFG_CMD_DATE is selected, the type of the RTC + has to be selected, too. Define exactly one of the + following options: + + CONFIG_RTC_MPC8xx - use internal RTC of MPC8xx + CONFIG_RTC_PCF8563 - use Philips PCF8563 RTC + CONFIG_RTC_MC146818 - use MC146818 RTC + CONFIG_RTC_DS1337 - use Maxim, Inc. DS1337 RTC + +- Timestamp Support: + + When CONFIG_TIMESTAMP is selected, the timestamp + (date and time) of an image is printed by image + commands like bootm or iminfo. This option is + automatically enabled when you select CFG_CMD_DATE . + +- Partition Support: + CONFIG_MAC_PARTITION and/or CONFIG_DOS_PARTITION + and/or CONFIG_ISO_PARTITION + + If IDE or SCSI support is enabled (CFG_CMD_IDE or + CFG_CMD_SCSI) you must configure support for at least + one partition type as well. + +- IDE Reset method: + CONFIG_IDE_RESET_ROUTINE + + Set this to define that instead of a reset Pin, the + routine ide_set_reset(int idereset) will be used. + +- ATAPI Support: + CONFIG_ATAPI + + Set this to enable ATAPI support. + +- SCSI Support: + At the moment only there is only support for the + SYM53C8XX SCSI controller; define + CONFIG_SCSI_SYM53C8XX to enable it. + + CFG_SCSI_MAX_LUN [8], CFG_SCSI_MAX_SCSI_ID [7] and + CFG_SCSI_MAX_DEVICE [CFG_SCSI_MAX_SCSI_ID * + CFG_SCSI_MAX_LUN] can be adjusted to define the + maximum numbers of LUNs, SCSI ID's and target + devices. + CFG_SCSI_SYM53C8XX_CCF to fix clock timing (80Mhz) + +- NETWORK Support (PCI): + CONFIG_EEPRO100 + Support for Intel 82557/82559/82559ER chips. + Optional CONFIG_EEPRO100_SROM_WRITE enables eeprom + write routine for first time initialisation. + + CONFIG_TULIP + Support for Digital 2114x chips. + Optional CONFIG_TULIP_SELECT_MEDIA for board specific + modem chip initialisation (KS8761/QS6611). + + CONFIG_NATSEMI + Support for National dp83815 chips. + + CONFIG_NS8382X + Support for National dp8382[01] gigabit chips. + +- USB Support: + At the moment only the UHCI host controller is + supported (PIP405, MIP405); define + CONFIG_USB_UHCI to enable it. + define CONFIG_USB_KEYBOARD to enable the USB Keyboard + end define CONFIG_USB_STORAGE to enable the USB + storage devices. + Note: + Supported are USB Keyboards and USB Floppy drives + (TEAC FD-05PUB). + +- Keyboard Support: + CONFIG_ISA_KEYBOARD + + Define this to enable standard (PC-Style) keyboard + support + + CONFIG_I8042_KBD + Standard PC keyboard driver with US (is default) and + GERMAN key layout (switch via environment 'keymap=de') support. + Export function i8042_kbd_init, i8042_tstc and i8042_getc + for cfb_console. Supports cursor blinking. + +- Video support: + CONFIG_VIDEO + + Define this to enable video support (for output to + video). + + CONFIG_VIDEO_CT69000 + + Enable Chips & Technologies 69000 Video chip + + CONFIG_VIDEO_SMI_LYNXEM + Enable Silicon Motion SMI 712/710/810 Video chip + Videomode are selected via environment 'videomode' with + standard LiLo mode numbers. + Following modes are supported (* is default): + + 800x600 1024x768 1280x1024 + 256 (8bit) 303* 305 307 + 65536 (16bit) 314 317 31a + 16,7 Mill (24bit) 315 318 31b + (i.e. setenv videomode 317; saveenv; reset;) + +- LCD Support: CONFIG_LCD + + Define this to enable LCD support (for output to LCD + display); also select one of the supported displays + by defining one of these: + + CONFIG_NEC_NL6648AC33: + + NEC NL6648AC33-18. Active, color, single scan. + + CONFIG_NEC_NL6648BC20 + + NEC NL6648BC20-08. 6.5", 640x480. + Active, color, single scan. + + CONFIG_SHARP_16x9 + + Sharp 320x240. Active, color, single scan. + It isn't 16x9, and I am not sure what it is. + + CONFIG_SHARP_LQ64D341 + + Sharp LQ64D341 display, 640x480. + Active, color, single scan. + + CONFIG_HLD1045 + + HLD1045 display, 640x480. + Active, color, single scan. + + CONFIG_OPTREX_BW + + Optrex CBL50840-2 NF-FW 99 22 M5 + or + Hitachi LMG6912RPFC-00T + or + Hitachi SP14Q002 + + 320x240. Black & white. + + Normally display is black on white background; define + CFG_WHITE_ON_BLACK to get it inverted. + +- Ethernet address: + CONFIG_ETHADDR + CONFIG_ETH2ADDR + CONFIG_ETH3ADDR + + Define a default value for ethernet address to use + for the respective ethernet interface, in case this + is not determined automatically. + +- IP address: + CONFIG_IPADDR + + Define a default value for the IP address to use for + the default ethernet interface, in case this is not + determined through e.g. bootp. + +- Server IP address: + CONFIG_SERVERIP + + Defines a default value for theIP address of a TFTP + server to contact when using the "tftboot" command. + +- BOOTP Recovery Mode: + CONFIG_BOOTP_RANDOM_DELAY + + If you have many targets in a network that try to + boot using BOOTP, you may want to avoid that all + systems send out BOOTP requests at precisely the same + moment (which would happen for instance at recovery + from a power failure, when all systems will try to + boot, thus flooding the BOOTP server. Defining + CONFIG_BOOTP_RANDOM_DELAY causes a random delay to be + inserted before sending out BOOTP requests. The + following delays are insterted then: + + 1st BOOTP request: delay 0 ... 1 sec + 2nd BOOTP request: delay 0 ... 2 sec + 3rd BOOTP request: delay 0 ... 4 sec + 4th and following + BOOTP requests: delay 0 ... 8 sec + +- Status LED: CONFIG_STATUS_LED + + Several configurations allow to display the current + status using a LED. For instance, the LED will blink + fast while running U-Boot code, stop blinking as + soon as a reply to a BOOTP request was received, and + start blinking slow once the Linux kernel is running + (supported by a status LED driver in the Linux + kernel). Defining CONFIG_STATUS_LED enables this + feature in U-Boot. + +- CAN Support: CONFIG_CAN_DRIVER + + Defining CONFIG_CAN_DRIVER enables CAN driver support + on those systems that support this (optional) + feature, like the TQM8xxL modules. + +- I2C Support: CONFIG_HARD_I2C | CONFIG_SOFT_I2C + + Enables I2C serial bus commands. If this is selected, + either CONFIG_HARD_I2C or CONFIG_SOFT_I2C must be defined + to include the appropriate I2C driver. + + See also: common/cmd_i2c.c for a description of the + command line interface. + + + CONFIG_HARD_I2C + + Selects the CPM hardware driver for I2C. + + CONFIG_SOFT_I2C + + Use software (aka bit-banging) driver instead of CPM + or similar hardware support for I2C. This is configured + via the following defines. + + I2C_INIT + + (Optional). Any commands necessary to enable I2C + controller or configure ports. + + I2C_PORT + + (Only for MPC8260 CPU). The I/O port to use (the code + assumes both bits are on the same port). Valid values + are 0..3 for ports A..D. + + I2C_ACTIVE + + The code necessary to make the I2C data line active + (driven). If the data line is open collector, this + define can be null. + + I2C_TRISTATE + + The code necessary to make the I2C data line tri-stated + (inactive). If the data line is open collector, this + define can be null. + + I2C_READ + + Code that returns TRUE if the I2C data line is high, + FALSE if it is low. + + I2C_SDA(bit) + + If <bit> is TRUE, sets the I2C data line high. If it + is FALSE, it clears it (low). + + I2C_SCL(bit) + + If <bit> is TRUE, sets the I2C clock line high. If it + is FALSE, it clears it (low). + + I2C_DELAY + + This delay is invoked four times per clock cycle so this + controls the rate of data transfer. The data rate thus + is 1 / (I2C_DELAY * 4). + +- SPI Support: CONFIG_SPI + + Enables SPI driver (so far only tested with + SPI EEPROM, also an instance works with Crystal A/D and + D/As on the SACSng board) + + CONFIG_SPI_X + + Enables extended (16-bit) SPI EEPROM addressing. + (symmetrical to CONFIG_I2C_X) + + CONFIG_SOFT_SPI + + Enables a software (bit-bang) SPI driver rather than + using hardware support. This is a general purpose + driver that only requires three general I/O port pins + (two outputs, one input) to function. If this is + defined, the board configuration must define several + SPI configuration items (port pins to use, etc). For + an example, see include/configs/sacsng.h. + +- FPGA Support: CONFIG_FPGA_COUNT + + Specify the number of FPGA devices to support. + + CONFIG_FPGA + + Used to specify the types of FPGA devices. For + example, + #define CONFIG_FPGA CFG_XILINX_VIRTEX2 + + CFG_FPGA_PROG_FEEDBACK + + Enable printing of hash marks during FPGA + configuration. + + CFG_FPGA_CHECK_BUSY + + Enable checks on FPGA configuration interface busy + status by the configuration function. This option + will require a board or device specific function to + be written. + + CONFIG_FPGA_DELAY + + If defined, a function that provides delays in the + FPGA configuration driver. + + CFG_FPGA_CHECK_CTRLC + + Allow Control-C to interrupt FPGA configuration + + CFG_FPGA_CHECK_ERROR + + Check for configuration errors during FPGA bitfile + loading. For example, abort during Virtex II + configuration if the INIT_B line goes low (which + indicated a CRC error). + + CFG_FPGA_WAIT_INIT + + Maximum time to wait for the INIT_B line to deassert + after PROB_B has been deasserted during a Virtex II + FPGA configuration sequence. The default time is 500 mS. + + CFG_FPGA_WAIT_BUSY + + Maximum time to wait for BUSY to deassert during + Virtex II FPGA configuration. The default is 5 mS. + + CFG_FPGA_WAIT_CONFIG + + Time to wait after FPGA configuration. The default is + 200 mS. + +- FPGA Support: CONFIG_FPGA_COUNT + + Specify the number of FPGA devices to support. + + CONFIG_FPGA + + Used to specify the types of FPGA devices. For example, + #define CONFIG_FPGA CFG_XILINX_VIRTEX2 + + CFG_FPGA_PROG_FEEDBACK + + Enable printing of hash marks during FPGA configuration. + + CFG_FPGA_CHECK_BUSY + + Enable checks on FPGA configuration interface busy + status by the configuration function. This option + will require a board or device specific function to + be written. + + CONFIG_FPGA_DELAY + + If defined, a function that provides delays in the FPGA + configuration driver. + + CFG_FPGA_CHECK_CTRLC + Allow Control-C to interrupt FPGA configuration + + CFG_FPGA_CHECK_ERROR + + Check for configuration errors during FPGA bitfile + loading. For example, abort during Virtex II + configuration if the INIT_B line goes low (which + indicated a CRC error). + + CFG_FPGA_WAIT_INIT + + Maximum time to wait for the INIT_B line to deassert + after PROB_B has been deasserted during a Virtex II + FPGA configuration sequence. The default time is 500 + mS. + + CFG_FPGA_WAIT_BUSY + + Maximum time to wait for BUSY to deassert during + Virtex II FPGA configuration. The default is 5 mS. + + CFG_FPGA_WAIT_CONFIG + + Time to wait after FPGA configuration. The default is + 200 mS. + +- Configuration Management: + CONFIG_IDENT_STRING + + If defined, this string will be added to the U-Boot + version information (U_BOOT_VERSION) + +- Vendor Parameter Protection: + + U-Boot considers the values of the environment + variables "serial#" (Board Serial Number) and + "ethaddr" (Ethernet Address) to bb parameters that + are set once by the board vendor / manufacturer, and + protects these variables from casual modification by + the user. Once set, these variables are read-only, + and write or delete attempts are rejected. You can + change this behviour: + + If CONFIG_ENV_OVERWRITE is #defined in your config + file, the write protection for vendor parameters is + completely disabled. Anybody can change or delte + these parameters. + + Alternatively, if you #define _both_ CONFIG_ETHADDR + _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default + ethernet address is installed in the environment, + which can be changed exactly ONCE by the user. [The + serial# is unaffected by this, i. e. it remains + read-only.] + +- Protected RAM: + CONFIG_PRAM + + Define this variable to enable the reservation of + "protected RAM", i. e. RAM which is not overwritten + by U-Boot. Define CONFIG_PRAM to hold the number of + kB you want to reserve for pRAM. You can overwrite + this default value by defining an environment + variable "pram" to the number of kB you want to + reserve. Note that the board info structure will + still show the full amount of RAM. If pRAM is + reserved, a new environment variable "mem" will + automatically be defined to hold the amount of + remaining RAM in a form that can be passed as boot + argument to Linux, for instance like that: + + setenv bootargs ... mem=\$(mem) + saveenv + + This way you can tell Linux not to use this memory, + either, which results in a memory region that will + not be affected by reboots. + + *WARNING* If your board configuration uses automatic + detection of the RAM size, you must make sure that + this memory test is non-destructive. So far, the + following board configurations are known to be + "pRAM-clean": + + ETX094, IVMS8, IVML24, SPD8xx, TQM8xxL, + HERMES, IP860, RPXlite, LWMON, LANTEC, + PCU_E, FLAGADM, TQM8260 + +- Error Recovery: + CONFIG_PANIC_HANG + + Define this variable to stop the system in case of a + fatal error, so that you have to reset it manually. + This is probably NOT a good idea for an embedded + system where you want to system to reboot + automatically as fast as possible, but it may be + useful during development since you can try to debug + the conditions that lead to the situation. + + CONFIG_NET_RETRY_COUNT + + This variable defines the number of retries for + network operations like ARP, RARP, TFTP, or BOOTP + before giving up the operation. If not defined, a + default value of 5 is used. + +- Command Interpreter: + CFG_HUSH_PARSER + + Define this variable to enable the "hush" shell (from + Busybox) as command line interpreter, thus enabling + powerful command line syntax like + if...then...else...fi conditionals or `&&' and '||' + constructs ("shell scripts"). + + If undefined, you get the old, much simpler behaviour + with a somewhat smaller memory footprint. + + + CFG_PROMPT_HUSH_PS2 + + This defines the secondary prompt string, which is + printed when the command interpreter needs more input + to complete a command. Usually "> ". + + Note: + + In the current implementation, the local variables + space and global environment variables space are + separated. Local variables are those you define by + simply typing like `name=value'. To access a local + variable later on, you have write `$name' or + `${name}'; variable directly by typing say `$name' at + the command prompt. + + Global environment variables are those you use + setenv/printenv to work with. To run a command stored + in such a variable, you need to use the run command, + and you must not use the '$' sign to access them. + + To store commands and special characters in a + variable, please use double quotation marks + surrounding the whole text of the variable, instead + of the backslashes before semicolons and special + symbols. + +- Default Environment + CONFIG_EXTRA_ENV_SETTINGS + + Define this to contain any number of null terminated + strings (variable = value pairs) that will be part of + the default enviroment compiled into the boot image. + For example, place something like this in your + board's config file: + + #define CONFIG_EXTRA_ENV_SETTINGS \ + "myvar1=value1\0" \ + "myvar2=value2\0" + + Warning: This method is based on knowledge about the + internal format how the environment is stored by the + U-Boot code. This is NOT an official, expoerted + interface! Although it is unlikely that this format + will change soon, there is no guarantee either. + You better know what you are doing here. + + Note: overly (ab)use of the default environment is + discouraged. Make sure to check other ways to preset + the environment like the autoscript function or the + boot command first. + +- Show boot progress + CONFIG_SHOW_BOOT_PROGRESS + + Defining this option allows to add some board- + specific code (calling a user-provided function + "show_boot_progress(int)") that enables you to show + the system's boot progress on some display (for + example, some LED's) on your board. At the moment, + the following checkpoints are implemented: + + Arg Where When + 1 common/cmd_bootm.c before attempting to boot an image + -1 common/cmd_bootm.c Image header has bad magic number + 2 common/cmd_bootm.c Image header has correct magic number + -2 common/cmd_bootm.c Image header has bad checksum + 3 common/cmd_bootm.c Image header has correct checksum + -3 common/cmd_bootm.c Image data has bad checksum + 4 common/cmd_bootm.c Image data has correct checksum + -4 common/cmd_bootm.c Image is for unsupported architecture + 5 common/cmd_bootm.c Architecture check OK + -5 common/cmd_bootm.c Wrong Image Type (not kernel, multi, standalone) + 6 common/cmd_bootm.c Image Type check OK + -6 common/cmd_bootm.c gunzip uncompression error + -7 common/cmd_bootm.c Unimplemented compression type + 7 common/cmd_bootm.c Uncompression OK + -8 common/cmd_bootm.c Wrong Image Type (not kernel, multi, standalone) + 8 common/cmd_bootm.c Image Type check OK + -9 common/cmd_bootm.c Unsupported OS (not Linux, BSD, VxWorks, QNX) + 9 common/cmd_bootm.c Start initial ramdisk verification + -10 common/cmd_bootm.c Ramdisk header has bad magic number + -11 common/cmd_bootm.c Ramdisk header has bad checksum + 10 common/cmd_bootm.c Ramdisk header is OK + -12 common/cmd_bootm.c Ramdisk data has bad checksum + 11 common/cmd_bootm.c Ramdisk data has correct checksum + 12 common/cmd_bootm.c Ramdisk verification complete, start loading + -13 common/cmd_bootm.c Wrong Image Type (not PPC Linux Ramdisk) + 13 common/cmd_bootm.c Start multifile image verification + 14 common/cmd_bootm.c No initial ramdisk, no multifile, continue. + 15 common/cmd_bootm.c All preparation done, transferring control to OS + + -1 common/cmd_doc.c Bad usage of "doc" command + -1 common/cmd_doc.c No boot device + -1 common/cmd_doc.c Unknown Chip ID on boot device + -1 common/cmd_doc.c Read Error on boot device + -1 common/cmd_doc.c Image header has bad magic number + + -1 common/cmd_ide.c Bad usage of "ide" command + -1 common/cmd_ide.c No boot device + -1 common/cmd_ide.c Unknown boot device + -1 common/cmd_ide.c Unknown partition table + -1 common/cmd_ide.c Invalid partition type + -1 common/cmd_ide.c Read Error on boot device + -1 common/cmd_ide.c Image header has bad magic number + + -1 common/cmd_nvedit.c Environment not changable, but has bad CRC + + +Modem Support: +-------------- + +[so far only for SMDK2400 board] + +- Modem support endable: + CONFIG_MODEM_SUPPORT + +- RTS/CTS Flow control enable: + CONFIG_HWFLOW + +- Modem debug support: + CONFIG_MODEM_SUPPORT_DEBUG + + Enables debugging stuff (char screen[1024], dbg()) + for modem support. Useful only with BDI2000. + +- General: + + In the target system modem support is enabled when a + specific key (key combination) is pressed during + power-on. Otherwise U-Boot will boot normally + (autoboot). The key_pressed() fuction is called from + board_init(). Currently key_pressed() is a dummy + function, returning 1 and thus enabling modem + initialization. + + If there are no modem init strings in the + environment, U-Boot proceed to autoboot; the + previous output (banner, info printfs) will be + supressed, though. + + See also: doc/README.Modem + + + + +Configuration Settings: +----------------------- + +- CFG_LONGHELP: Defined when you want long help messages included; + undefine this when you're short of memory. + +- CFG_PROMPT: This is what U-Boot prints on the console to + prompt for user input. + +- CFG_CBSIZE: Buffer size for input from the Console + +- CFG_PBSIZE: Buffer size for Console output + +- CFG_MAXARGS: max. Number of arguments accepted for monitor commands + +- CFG_BARGSIZE: Buffer size for Boot Arguments which are passed to + the application (usually a Linux kernel) when it is + booted + +- CFG_BAUDRATE_TABLE: + List of legal baudrate settings for this board. + +- CFG_CONSOLE_INFO_QUIET + Suppress display of console information at boot. + +- CFG_CONSOLE_IS_IN_ENV + If the board specific function + extern int overwrite_console (void); + returns 1, the stdin, stderr and stdout are switched to the + serial port, else the settings in the environment are used. + +- CFG_CONSOLE_OVERWRITE_ROUTINE + Enable the call to overwrite_console(). + +- CFG_CONSOLE_ENV_OVERWRITE + Enable overwrite of previous console environment settings. + +- CFG_MEMTEST_START, CFG_MEMTEST_END: + Begin and End addresses of the area used by the + simple memory test. + +- CFG_ALT_MEMTEST: + Enable an alternate, more extensive memory test. + +- CFG_TFTP_LOADADDR: + Default load address for network file downloads + +- CFG_LOADS_BAUD_CHANGE: + Enable temporary baudrate change while serial download + +- CFG_SDRAM_BASE: + Physical start address of SDRAM. _Must_ be 0 here. + +- CFG_MBIO_BASE: + Physical start address of Motherboard I/O (if using a + Cogent motherboard) + +- CFG_FLASH_BASE: + Physical start address of Flash memory. + +- CFG_MONITOR_BASE: + Physical start address of boot monitor code (set by + make config files to be same as the text base address + (TEXT_BASE) used when linking) - same as + CFG_FLASH_BASE when booting from flash. + +- CFG_MONITOR_LEN: + Size of memory reserved for monitor code + +- CFG_MALLOC_LEN: + Size of DRAM reserved for malloc() use. + +- CFG_BOOTMAPSZ: + Maximum size of memory mapped by the startup code of + the Linux kernel; all data that must be processed by + the Linux kernel (bd_info, boot arguments, eventually + initrd image) must be put below this limit. + +- CFG_MAX_FLASH_BANKS: + Max number of Flash memory banks + +- CFG_MAX_FLASH_SECT: + Max number of sectors on a Flash chip + +- CFG_FLASH_ERASE_TOUT: + Timeout for Flash erase operations (in ms) + +- CFG_FLASH_WRITE_TOUT: + Timeout for Flash write operations (in ms) + +- CFG_DIRECT_FLASH_TFTP: + + Enable TFTP transfers directly to flash memory; + without this option such a download has to be + performed in two steps: (1) download to RAM, and (2) + copy from RAM to flash. + + The two-step approach is usually more reliable, since + you can check if the download worked before you erase + the flash, but in some situations (when sytem RAM is + too limited to allow for a tempory copy of the + downloaded image) this option may be very useful. + +- CFG_FLASH_CFI: + Define if the flash driver uses extra elements in the + common flash structure for storing flash geometry + +The following definitions that deal with the placement and management +of environment data (variable area); in general, we support the +following configurations: + +- CFG_ENV_IS_IN_FLASH: + + Define this if the environment is in flash memory. + + a) The environment occupies one whole flash sector, which is + "embedded" in the text segment with the U-Boot code. This + happens usually with "bottom boot sector" or "top boot + sector" type flash chips, which have several smaller + sectors at the start or the end. For instance, such a + layout can have sector sizes of 8, 2x4, 16, Nx32 kB. In + such a case you would place the environment in one of the + 4 kB sectors - with U-Boot code before and after it. With + "top boot sector" type flash chips, you would put the + environment in one of the last sectors, leaving a gap + between U-Boot and the environment. + + - CFG_ENV_OFFSET: + + Offset of environment data (variable area) to the + beginning of flash memory; for instance, with bottom boot + type flash chips the second sector can be used: the offset + for this sector is given here. + + CFG_ENV_OFFSET is used relative to CFG_FLASH_BASE. + + - CFG_ENV_ADDR: + + This is just another way to specify the start address of + the flash sector containing the environment (instead of + CFG_ENV_OFFSET). + + - CFG_ENV_SECT_SIZE: + + Size of the sector containing the environment. + + + b) Sometimes flash chips have few, equal sized, BIG sectors. + In such a case you don't want to spend a whole sector for + the environment. + + - CFG_ENV_SIZE: + + If you use this in combination with CFG_ENV_IS_IN_FLASH + and CFG_ENV_SECT_SIZE, you can specify to use only a part + of this flash sector for the environment. This saves + memory for the RAM copy of the environment. + + It may also save flash memory if you decide to use this + when your environment is "embedded" within U-Boot code, + since then the remainder of the flash sector could be used + for U-Boot code. It should be pointed out that this is + STRONGLY DISCOURAGED from a robustness point of view: + updating the environment in flash makes it always + necessary to erase the WHOLE sector. If something goes + wrong before the contents has been restored from a copy in + RAM, your target system will be dead. + + - CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND + + These settings describe a second storage area used to hold + a redundand copy of the environment data, so that there is + a valid backup copy in case there is a power failur during + a "saveenv" operation. + +BE CAREFUL! Any changes to the flash layout, and some changes to the +source code will make it necessary to adapt <board>/u-boot.lds* +accordingly! + + +- CFG_ENV_IS_IN_NVRAM: + + Define this if you have some non-volatile memory device + (NVRAM, battery buffered SRAM) which you want to use for the + environment. + + - CFG_ENV_ADDR: + - CFG_ENV_SIZE: + + These two #defines are used to determin the memory area you + want to use for environment. It is assumed that this memory + can just be read and written to, without any special + provision. + +BE CAREFUL! The first access to the environment happens quite early +in U-Boot initalization (when we try to get the setting of for the +console baudrate). You *MUST* have mappend your NVRAM area then, or +U-Boot will hang. + +Please note that even with NVRAM we still use a copy of the +environment in RAM: we could work on NVRAM directly, but we want to +keep settings there always unmodified except somebody uses "saveenv" +to save the current settings. + + +- CFG_ENV_IS_IN_EEPROM: + + Use this if you have an EEPROM or similar serial access + device and a driver for it. + + - CFG_ENV_OFFSET: + - CFG_ENV_SIZE: + + These two #defines specify the offset and size of the + environment area within the total memory of your EEPROM. + + - CFG_I2C_EEPROM_ADDR: + If defined, specified the chip address of the EEPROM device. + The default address is zero. + + - CFG_EEPROM_PAGE_WRITE_BITS: + If defined, the number of bits used to address bytes in a + single page in the EEPROM device. A 64 byte page, for example + would require six bits. + + - CFG_EEPROM_PAGE_WRITE_DELAY_MS: + If defined, the number of milliseconds to delay between + page writes. The default is zero milliseconds. + + - CFG_I2C_EEPROM_ADDR_LEN: + The length in bytes of the EEPROM memory array address. Note + that this is NOT the chip address length! + + - CFG_EEPROM_SIZE: + The size in bytes of the EEPROM device. + + - CFG_I2C_EEPROM_ADDR: + If defined, specified the chip address of the EEPROM device. + The default address is zero. + + - CFG_EEPROM_PAGE_WRITE_BITS: + If defined, the number of bits used to address bytes in a + single page in the EEPROM device. A 64 byte page, for example + would require six bits. + + - CFG_EEPROM_PAGE_WRITE_DELAY_MS: + If defined, the number of milliseconds to delay between + page writes. The default is zero milliseconds. + + - CFG_I2C_EEPROM_ADDR_LEN: + The length in bytes of the EEPROM memory array address. Note + that this is NOT the chip address length! + + - CFG_EEPROM_SIZE: + The size in bytes of the EEPROM device. + +- CFG_SPI_INIT_OFFSET + + Defines offset to the initial SPI buffer area in DPRAM. The + area is used at an early stage (ROM part) if the environment + is configured to reside in the SPI EEPROM: We need a 520 byte + scratch DPRAM area. It is used between the two initialization + calls (spi_init_f() and spi_init_r()). A value of 0xB00 seems + to be a good choice since it makes it far enough from the + start of the data area as well as from the stack pointer. + +Please note that the environment is read-only as long as the monitor +has been relocated to RAM and a RAM copy of the environment has been +created; also, when using EEPROM you will have to use getenv_r() +until then to read environment variables. + +The environment is now protected by a CRC32 checksum. Before the +monitor is relocated into RAM, as a result of a bad CRC you will be +working with the compiled-in default environment - *silently*!!! +[This is necessary, because the first environment variable we need is +the "baudrate" setting for the console - if we have a bad CRC, we +don't have any device yet where we could complain.] + +Note: once the monitor has been relocated, then it will complain if +the default environment is used; a new CRC is computed as soon as you +use the "setenv" command to modify / delete / add any environment +variable [even when you try to delete a non-existing variable!]. + +Note2: you must edit your u-boot.lds file to reflect this +configuration. + + +Many of the options are named exactly as the corresponding Linux +kernel configuration options. The intention is to make it easier to +build a config tool - later. + +Low Level (hardware related) configuration options: + +- CFG_CACHELINE_SIZE: + Cache Line Size of the CPU. + +- CFG_DEFAULT_IMMR: + Default address of the IMMR after system reset. + Needed on some 8260 systems (MPC8260ADS and RPXsuper) + to be able to adjust the position of the IMMR + register after a reset. + +- CFG_IMMR: Physical address of the Internal Memory Mapped + Register; DO NOT CHANGE! (11-4) + [MPC8xx systems only] + +- CFG_INIT_RAM_ADDR: + + Start address of memory area tha can be used for + initial data and stack; please note that this must be + writable memory that is working WITHOUT special + initialization, i. e. you CANNOT use normal RAM which + will become available only after programming the + memory controller and running certain initialization + sequences. + + U-Boot uses the following memory types: + - MPC8xx and MPC8260: IMMR (internal memory of the CPU) + - MPC824X: data cache + - PPC4xx: data cache + +- CFG_INIT_DATA_OFFSET: + + Offset of the initial data structure in the memory + area defined by CFG_INIT_RAM_ADDR. Usually + CFG_INIT_DATA_OFFSET is chosen such that the initial + data is located at the end of the available space + (sometimes written as (CFG_INIT_RAM_END - + CFG_INIT_DATA_SIZE), and the initial stack is just + below that area (growing from (CFG_INIT_RAM_ADDR + + CFG_INIT_DATA_OFFSET) downward. + + Note: + On the MPC824X (or other systems that use the data + cache for initial memory) the address chosen for + CFG_INIT_RAM_ADDR is basically arbitrary - it must + point to an otherwise UNUSED address space between + the top of RAM and the start of the PCI space. + +- CFG_SIUMCR: SIU Module Configuration (11-6) + +- CFG_SYPCR: System Protection Control (11-9) + +- CFG_TBSCR: Time Base Status and Control (11-26) + +- CFG_PISCR: Periodic Interrupt Status and Control (11-31) + +- CFG_PLPRCR: PLL, Low-Power, and Reset Control Register (15-30) + +- CFG_SCCR: System Clock and reset Control Register (15-27) + +- CFG_OR_TIMING_SDRAM: + SDRAM timing + +- CFG_MAMR_PTA: + periodic timer for refresh + +- CFG_DER: Debug Event Register (37-47) + +- FLASH_BASE0_PRELIM, FLASH_BASE1_PRELIM, CFG_REMAP_OR_AM, + CFG_PRELIM_OR_AM, CFG_OR_TIMING_FLASH, CFG_OR0_REMAP, + CFG_OR0_PRELIM, CFG_BR0_PRELIM, CFG_OR1_REMAP, CFG_OR1_PRELIM, + CFG_BR1_PRELIM: + Memory Controller Definitions: BR0/1 and OR0/1 (FLASH) + +- SDRAM_BASE2_PRELIM, SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE, + CFG_OR_TIMING_SDRAM, CFG_OR2_PRELIM, CFG_BR2_PRELIM, + CFG_OR3_PRELIM, CFG_BR3_PRELIM: + Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM) + +- CFG_MAMR_PTA, CFG_MPTPR_2BK_4K, CFG_MPTPR_1BK_4K, CFG_MPTPR_2BK_8K, + CFG_MPTPR_1BK_8K, CFG_MAMR_8COL, CFG_MAMR_9COL: + Machine Mode Register and Memory Periodic Timer + Prescaler definitions (SDRAM timing) + +- CFG_I2C_UCODE_PATCH, CFG_I2C_DPMEM_OFFSET [0x1FC0]: + enable I2C microcode relocation patch (MPC8xx); + define relocation offset in DPRAM [DSP2] + +- CFG_SPI_UCODE_PATCH, CFG_SPI_DPMEM_OFFSET [0x1FC0]: + enable SPI microcode relocation patch (MPC8xx); + define relocation offset in DPRAM [SCC4] + +- CFG_USE_OSCCLK: + Use OSCM clock mode on MBX8xx board. Be careful, + wrong setting might damage your board. Read + doc/README.MBX before setting this variable! + +Building the Software: +====================== + +Building U-Boot has been tested in native PPC environments (on a +PowerBook G3 running LinuxPPC 2000) and in cross environments +(running RedHat 6.x and 7.x Linux on x86, Solaris 2.6 on a SPARC, and +NetBSD 1.5 on x86). + +If you are not using a native PPC environment, it is assumed that you +have the GNU cross compiling tools available in your path and named +with a prefix of "powerpc-linux-". If this is not the case, (e.g. if +you are using Monta Vista's Hard Hat Linux CDK 1.2) you must change +the definition of CROSS_COMPILE in Makefile. For HHL on a 4xx CPU, +change it to: + + CROSS_COMPILE = ppc_4xx- + + +U-Boot is intended to be simple to build. After installing the +sources you must configure U-Boot for one specific board type. This +is done by typing: + + make NAME_config + +where "NAME_config" is the name of one of the existing +configurations; the following names are supported: + + ADCIOP_config GTH_config TQM850L_config + ADS860_config IP860_config TQM855L_config + AR405_config IVML24_config TQM860L_config + CANBT_config IVMS8_config WALNUT405_config + CPCI405_config LANTEC_config cogent_common_config + CPCIISER4_config MBX_config cogent_mpc8260_config + CU824_config MBX860T_config cogent_mpc8xx_config + ESTEEM192E_config RPXlite_config hermes_config + ETX094_config RPXsuper_config hymod_config + FADS823_config SM850_config lwmon_config + FADS850SAR_config SPD823TS_config pcu_e_config + FADS860T_config SXNI855T_config rsdproto_config + FPS850L_config Sandpoint8240_config sbc8260_config + GENIETV_config TQM823L_config PIP405_config + GEN860T_config EBONY_config + +Note: for some board special configuration names may exist; check if + additional information is available from the board vendor; for + instance, the TQM8xxL systems run normally at 50 MHz and use a + SCC for 10baseT ethernet; there are also systems with 80 MHz + CPU clock, and an optional Fast Ethernet module is available + for CPU's with FEC. You can select such additional "features" + when chosing the configuration, i. e. + + make TQM860L_config + - will configure for a plain TQM860L, i. e. 50MHz, no FEC + + make TQM860L_FEC_config + - will configure for a TQM860L at 50MHz with FEC for ethernet + + make TQM860L_80MHz_config + - will configure for a TQM860L at 80 MHz, with normal 10baseT + interface + + make TQM860L_FEC_80MHz_config + - will configure for a TQM860L at 80 MHz with FEC for ethernet + + make TQM823L_LCD_config + - will configure for a TQM823L with U-Boot console on LCD + + make TQM823L_LCD_80MHz_config + - will configure for a TQM823L at 80 MHz with U-Boot console on LCD + + etc. + + + +Finally, type "make all", and you should get some working U-Boot +images ready for downlod to / installation on your system: + +- "u-boot.bin" is a raw binary image +- "u-boot" is an image in ELF binary format +- "u-boot.srec" is in Motorola S-Record format + + +Please be aware that the Makefiles assume you are using GNU make, so +for instance on NetBSD you might need to use "gmake" instead of +native "make". + + +If the system board that you have is not listed, then you will need +to port U-Boot to your hardware platform. To do this, follow these +steps: + +1. Add a new configuration option for your board to the toplevel + "Makefile", using the existing entries as examples. +2. Create a new directory to hold your board specific code. Add any + files you need. +3. If you're porting U-Boot to a new CPU, then also create a new + directory to hold your CPU specific code. Add any files you need. +4. Run "make config_name" with your new name. +5. Type "make", and you should get a working "u-boot.srec" file + to be installed on your target system. + [Of course, this last step is much harder than it sounds.] + + +Testing of U-Boot Modifications, Ports to New Hardware, etc.: +============================================================== + +If you have modified U-Boot sources (for instance added a new board +or support for new devices, a new CPU, etc.) you are expected to +provide feedback to the other developers. The feedback normally takes +the form of a "patch", i. e. a context diff against a certain (latest +official or latest in CVS) version of U-Boot sources. + +But before you submit such a patch, please verify that your modifi- +cation did not break existing code. At least make sure that *ALL* of +the supported boards compile WITHOUT ANY compiler warnings. To do so, +just run the "MAKEALL" script, which will configure and build U-Boot +for ALL supported system. Be warned, this will take a while. You can +select which (cross) compiler to use py passing a `CROSS_COMPILE' +environment variable to the script, i. e. to use the cross tools from +MontaVista's Hard Hat Linux you can type + + CROSS_COMPILE=ppc_8xx- MAKEALL + +or to build on a native PowerPC system you can type + + CROSS_COMPILE=' ' MAKEALL + +See also "U-Boot Porting Guide" below. + + + +Monitor Commands - Overview: +============================ + +go - start application at address 'addr' +run - run commands in an environment variable +bootm - boot application image from memory +bootp - boot image via network using BootP/TFTP protocol +tftpboot- boot image via network using TFTP protocol + and env variables "ipaddr" and "serverip" + (and eventually "gatewayip") +rarpboot- boot image via network using RARP/TFTP protocol +diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd' +loads - load S-Record file over serial line +loadb - load binary file over serial line (kermit mode) +md - memory display +mm - memory modify (auto-incrementing) +nm - memory modify (constant address) +mw - memory write (fill) +cp - memory copy +cmp - memory compare +crc32 - checksum calculation +imd - i2c memory display +imm - i2c memory modify (auto-incrementing) +inm - i2c memory modify (constant address) +imw - i2c memory write (fill) +icrc32 - i2c checksum calculation +iprobe - probe to discover valid I2C chip addresses +iloop - infinite loop on address range +isdram - print SDRAM configuration information +sspi - SPI utility commands +base - print or set address offset +printenv- print environment variables +setenv - set environment variables +saveenv - save environment variables to persistent storage +protect - enable or disable FLASH write protection +erase - erase FLASH memory +flinfo - print FLASH memory information +bdinfo - print Board Info structure +iminfo - print header information for application image +coninfo - print console devices and informations +ide - IDE sub-system +loop - infinite loop on address range +mtest - simple RAM test +icache - enable or disable instruction cache +dcache - enable or disable data cache +reset - Perform RESET of the CPU +echo - echo args to console +version - print monitor version +help - print online help +? - alias for 'help' + + +Monitor Commands - Detailed Description: +======================================== + +TODO. + +For now: just type "help <command>". + + +Environment Variables: +====================== + +U-Boot supports user configuration using Environment Variables which +can be made persistent by saving to Flash memory. + +Environment Variables are set using "setenv", printed using +"printenv", and saved to Flash using "saveenv". Using "setenv" +without a value can be used to delete a variable from the +environment. As long as you don't save the environment you are +working with an in-memory copy. In case the Flash area containing the +environment is erased by accident, a default environment is provided. + +Some configuration options can be set using Environment Variables: + + baudrate - see CONFIG_BAUDRATE + + bootdelay - see CONFIG_BOOTDELAY + + bootcmd - see CONFIG_BOOTCOMMAND + + bootargs - Boot arguments when booting an RTOS image + + bootfile - Name of the image to load with TFTP + + autoload - if set to "no" (any string beginning with 'n'), + "bootp" will just load perform a lookup of the + configuration from the BOOTP server, but not try to + load any image using TFTP + + autostart - if set to "yes", an image loaded using the "bootp", + "rarpboot", "tftpboot" or "diskboot" commands will + be automatically started (by internally calling + "bootm") + + initrd_high - restrict positioning of initrd images: + If this variable is not set, initrd images will be + copied to the highest possible address in RAM; this + is usually what you want since it allows for + maximum initrd size. If for some reason you want to + make sure that the initrd image is loaded below the + CFG_BOOTMAPSZ limit, you can set this environment + variable to a value of "no" or "off" or "0". + Alternatively, you can set it to a maximum upper + address to use (U-Boot will still check that it + does not overwrite the U-Boot stack and data). + + For instance, when you have a system with 16 MB + RAM, and want to reseve 4 MB from use by Linux, + you can do this by adding "mem=12M" to the value of + the "bootargs" variable. However, now you must make + sure, that the initrd image is placed in the first + 12 MB as well - this can be done with + + setenv initrd_high 00c00000 + + ipaddr - IP address; needed for tftpboot command + + loadaddr - Default load address for commands like "bootp", + "rarpboot", "tftpboot" or "diskboot" + + loads_echo - see CONFIG_LOADS_ECHO + + serverip - TFTP server IP address; needed for tftpboot command + + bootretry - see CONFIG_BOOT_RETRY_TIME + + bootdelaykey - see CONFIG_AUTOBOOT_DELAY_STR + + bootstopkey - see CONFIG_AUTOBOOT_STOP_STR + + +The following environment variables may be used and automatically +updated by the network boot commands ("bootp" and "rarpboot"), +depending the information provided by your boot server: + + bootfile - see above + dnsip - IP address of your Domain Name Server + gatewayip - IP address of the Gateway (Router) to use + hostname - Target hostname + ipaddr - see above + netmask - Subnet Mask + rootpath - Pathname of the root filesystem on the NFS server + serverip - see above + + +There are two special Environment Variables: + + serial# - contains hardware identification information such + as type string and/or serial number + ethaddr - Ethernet address + +These variables can be set only once (usually during manufacturing of +the board). U-Boot refuses to delete or overwrite these variables +once they have been set once. + + +Please note that changes to some configuration parameters may take +only effect after the next boot (yes, that's just like Windoze :-). + + +Note for Redundant Ethernet Interfaces: +======================================= + +Some boards come with redundand ethernet interfaces; U-Boot supports +such configurations and is capable of automatic selection of a +"working" interface when needed. MAC assignemnt works as follows: + +Network interfaces are numbered eth0, eth1, eth2, ... Corresponding +MAC addresses can be stored in the environment as "ethaddr" (=>eth0), +"eth1addr" (=>eth1), "eth2addr", ... + +If the network interface stores some valid MAC address (for instance +in SROM), this is used as default address if there is NO correspon- +ding setting in the environment; if the corresponding environment +variable is set, this overrides the settings in the card; that means: + +o If the SROM has a valid MAC address, and there is no address in the + environment, the SROM's address is used. + +o If there is no valid address in the SROM, and a definition in the + environment exists, then the value from the environment variable is + used. + +o If both the SROM and the environment contain a MAC address, and + both addresses are the same, this MAC address is used. + +o If both the SROM and the environment contain a MAC address, and the + addresses differ, the value from the environment is used and a + warning is printed. + +o If neither SROM nor the environment contain a MAC address, an error + is raised. + + + +Image Formats: +============== + +The "boot" commands of this monitor operate on "image" files which +can be basicly anything, preceeded by a special header; see the +definitions in include/image.h for details; basicly, the header +defines the following image properties: + +* Target Operating System (Provisions for OpenBSD, NetBSD, FreeBSD, + 4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, + LynxOS, pSOS, QNX; + Currently supported: Linux, NetBSD, VxWorks, QNX). +* Target CPU Architecture (Provisions for Alpha, ARM, Intel x86, + IA64, MIPS, MIPS, PowerPC, IBM S390, SuperH, Sparc, Sparc 64 Bit; + Currently supported: PowerPC). +* Compression Type (Provisions for uncompressed, gzip, bzip2; + Currently supported: uncompressed, gzip). +* Load Address +* Entry Point +* Image Name +* Image Timestamp + +The header is marked by a special Magic Number, and both the header +and the data portions of the image are secured against corruption by +CRC32 checksums. + + +Linux Support: +============== + +Although U-Boot should support any OS or standalone application +easily, Linux has always been in the focus during the design of +U-Boot. + +U-Boot includes many features that so far have been part of some +special "boot loader" code within the Linux kernel. Also, any +"initrd" images to be used are no longer part of one big Linux image; +instead, kernel and "initrd" are separate images. This implementation +serves serveral purposes: + +- the same features can be used for other OS or standalone + applications (for instance: using compressed images to reduce the + Flash memory footprint) + +- it becomes much easier to port new Linux kernel versions because + lots of low-level, hardware dependend stuff are done by U-Boot + +- the same Linux kernel image can now be used with different "initrd" + images; of course this also means that different kernel images can + be run with the same "initrd". This makes testing easier (you don't + have to build a new "zImage.initrd" Linux image when you just + change a file in your "initrd"). Also, a field-upgrade of the + software is easier now. + + +Linux HOWTO: +============ + +Porting Linux to U-Boot based systems: +--------------------------------------- + +U-Boot cannot save you from doing all the necessary modifications to +configure the Linux device drivers for use with your target hardware +(no, we don't intend to provide a full virtual machine interface to +Linux :-). + +But now you can ignore ALL boot loader code (in arch/ppc/mbxboot). + +Just make sure your machine specific header file (for instance +include/asm-ppc/tqm8xx.h) includes the same definition of the Board +Information structure as we define in include/u-boot.h, and make +sure that your definition of IMAP_ADDR uses the same value as your +U-Boot configuration in CFG_IMMR. + + +Configuring the Linux kernel: +----------------------------- + +No specific requirements for U-Boot. Make sure you have some root +device (initial ramdisk, NFS) for your target system. + + +Building a Linux Image: +----------------------- + +No specific requirements for U-Boot. There is no need to add a +"ramdisk.image.gz" file when building the kernel, even when you +intend to run it with initial ramdisk. + +Example: + + make TQM850L_config + make oldconfig + make dep + make zImage + +However, we don't use the 'zImage' (= 'arch/ppc/mbxboot/zvmlinux') we +build this way. The 'zImage' includes the old boot loader code which +we don't ned any more. Instead, we use the raw (compressed) Linux +kernel image in 'arch/ppc/coffboot/vmlinux.gz'. + +There is a special tool (in 'tools/mkimage') to encapsulate this +image with header information, CRC32 checksum etc. for use with +U-Boot: + +In the first form (with "-l" option) mkimage lists the information +contained in the header of an existing U-Boot image; this includes +checksum verification: + + tools/mkimage -l image + -l ==> list image header information + +The second form (with "-d" option) is used to build a U-Boot image +from a "data file" which is used as image payload: + + tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \ + -n name -d data_file image + -A ==> set architecture to 'arch' + -O ==> set operating system to 'os' + -T ==> set image type to 'type' + -C ==> set compression type 'comp' + -a ==> set load address to 'addr' (hex) + -e ==> set entry point to 'ep' (hex) + -n ==> set image name to 'name' + -d ==> use image data from 'datafile' + +Right now, all Linux kernels use the same load address (0x00000000), +but the entry point address depends on the kernel version: + +- 2.2.x kernels have the entry point at 0x0000000C, +- 2.3.x and 2.4.x kernels have the entry point at 0x00000000. + +So a typical call to build a U-Boot image would read: + + -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \ + > -A ppc -O linux -T kernel -C gzip -a 00000000 -e 0000000C \ + > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz \ + > examples/image-2.2.13-initrd + Image Name: 2.2.13 for initrd on TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327.86 kB = 0.32 MB + Load Address: 0x00000000 + Entry Point: 0x0000000c + +To verify the contents of the image (or check for corruption): + + -> tools/mkimage -l examples/image-2.2.13-initrd + Image Name: 2.2.13 for initrd on TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327.86 kB = 0.32 MB + Load Address: 0x00000000 + Entry Point: 0x0000000c + +NOTE: for embedded systems where boot time is critical you can trade +speed for memory and install an UNCOMPRESSED image instead: this +needs more space in Flash, but boots much faster since it does not +need to be uncompressed: + + -> gunzip /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz + -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \ + > -A ppc -O linux -T kernel -C none -a 00000000 -e 0000000C \ + > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux \ + > examples/image-2.2.13-initrd-uncompressed + Image Name: 2.2.13 for initrd on TQM850L + Created: Wed Jul 19 02:34:59 2000 + Image Type: PowerPC Linux Kernel Image (uncompressed) + Data Size: 792160 Bytes = 773.59 kB = 0.76 MB + Load Address: 0x00000000 + Entry Point: 0x0000000c + + +Similar you can build U-Boot images from a 'ramdisk.image.gz' file +when your kernel is intended to use an initial ramdisk: + + -> tools/mkimage -n 'Simple Ramdisk Image' \ + > -A ppc -O linux -T ramdisk -C gzip \ + > -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd + Image Name: Simple Ramdisk Image + Created: Wed Jan 12 14:01:50 2000 + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553.25 kB = 0.54 MB + Load Address: 0x00000000 + Entry Point: 0x00000000 + + +Installing a Linux Image: +------------------------- + +To downloading a U-Boot image over the serial (console) interface, +you must convert the image to S-Record format: + + objcopy -I binary -O srec examples/image examples/image.srec + +The 'objcopy' does not understand the information in the U-Boot +image header, so the resulting S-Record file will be relative to +address 0x00000000. To load it to a given address, you need to +specify the target address as 'offset' parameter with the 'loads' +command. + +Example: install the image to address 0x40100000 (which on the +TQM8xxL is in the first Flash bank): + + => erase 40100000 401FFFFF + + .......... done + Erased 8 sectors + + => loads 40100000 + ## Ready for S-Record download ... + ~>examples/image.srec + 1 2 3 4 5 6 7 8 9 10 11 12 13 ... + ... + 15989 15990 15991 15992 + [file transfer complete] + [connected] + ## Start Addr = 0x00000000 + + +You can check the success of the download using the 'iminfo' command; +this includes a checksum verification so you can be sure no data +corruption happened: + + => imi 40100000 + + ## Checking Image at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + + + +Boot Linux: +----------- + +The "bootm" command is used to boot an application that is stored in +memory (RAM or Flash). In case of a Linux kernel image, the contents +of the "bootargs" environment variable is passed to the kernel as +parameters. You can check and modify this variable using the +"printenv" and "setenv" commands: + + + => printenv bootargs + bootargs=root=/dev/ram + + => setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + + => printenv bootargs + bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + + => bootm 40020000 + ## Booting Linux kernel at 40020000 ... + Image Name: 2.2.13 for NFS on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 381681 Bytes = 372 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK + Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000 + Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2 + time_init: decrementer frequency = 187500000/60 + Calibrating delay loop... 49.77 BogoMIPS + Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000] + ... + +If you want to boot a Linux kernel with initial ram disk, you pass +the memory addreses of both the kernel and the initrd image (PPBCOOT +format!) to the "bootm" command: + + => imi 40100000 40200000 + + ## Checking Image at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + + ## Checking Image at 40200000 ... + Image Name: Simple Ramdisk Image + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553 kB = 0 MB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + + => bootm 40100000 40200000 + ## Booting Linux kernel at 40100000 ... + Image Name: 2.2.13 for initrd on TQM850L + Image Type: PowerPC Linux Kernel Image (gzip compressed) + Data Size: 335725 Bytes = 327 kB = 0 MB + Load Address: 00000000 + Entry Point: 0000000c + Verifying Checksum ... OK + Uncompressing Kernel Image ... OK + ## Loading RAMDisk Image at 40200000 ... + Image Name: Simple Ramdisk Image + Image Type: PowerPC Linux RAMDisk Image (gzip compressed) + Data Size: 566530 Bytes = 553 kB = 0 MB + Load Address: 00000000 + Entry Point: 00000000 + Verifying Checksum ... OK + Loading Ramdisk ... OK + Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000 + Boot arguments: root=/dev/ram + time_init: decrementer frequency = 187500000/60 + Calibrating delay loop... 49.77 BogoMIPS + ... + RAMDISK: Compressed image found at block 0 + VFS: Mounted root (ext2 filesystem). + + bash# + + +Standalone HOWTO: +================= + +One of the features of U-Boot is that you can dynamically load and +run "standalone" applications, which can use some resources of +U-Boot like console I/O functions or interrupt services. + +Two simple examples are included with the sources: + +"Hello World" Demo: +------------------- + +'examples/hello_world.c' contains a small "Hello World" Demo +application; it is automatically compiled when you build U-Boot. +It's configured to run at address 0x00040004, so you can play with it +like that: + + => loads + ## Ready for S-Record download ... + ~>examples/hello_world.srec + 1 2 3 4 5 6 7 8 9 10 11 ... + [file transfer complete] + [connected] + ## Start Addr = 0x00040004 + + => go 40004 Hello World! This is a test. + ## Starting application at 0x00040004 ... + Hello World + argc = 7 + argv[0] = "40004" + argv[1] = "Hello" + argv[2] = "World!" + argv[3] = "This" + argv[4] = "is" + argv[5] = "a" + argv[6] = "test." + argv[7] = "<NULL>" + Hit any key to exit ... + + ## Application terminated, rc = 0x0 + +Another example, which demonstrates how to register a CPM interrupt +handler with the U-Boot code, can be found in 'examples/timer.c'. +Here, a CPM timer is set up to generate an interrupt every second. +The interrupt service routine is trivial, just printing a '.' +character, but this is just a demo program. The application can be +controlled by the following keys: + + ? - print current values og the CPM Timer registers + b - enable interrupts and start timer + e - stop timer and disable interrupts + q - quit application + + => loads + ## Ready for S-Record download ... + ~>examples/timer.srec + 1 2 3 4 5 6 7 8 9 10 11 ... + [file transfer complete] + [connected] + ## Start Addr = 0x00040004 + + => go 40004 + ## Starting application at 0x00040004 ... + TIMERS=0xfff00980 + Using timer 1 + tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0 + +Hit 'b': + [q, b, e, ?] Set interval 1000000 us + Enabling timer +Hit '?': + [q, b, e, ?] ........ + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0 +Hit '?': + [q, b, e, ?] . + tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0 +Hit 'e': + [q, b, e, ?] ...Stopping timer +Hit 'q': + [q, b, e, ?] ## Application terminated, rc = 0x0 + + +NetBSD Notes: +============= + +Starting at version 0.9.2, U-Boot supports NetBSD both as host +(build U-Boot) and target system (boots NetBSD/mpc8xx). + +Building requires a cross environment; it is known to work on +NetBSD/i386 with the cross-powerpc-netbsd-1.3 package (you will also +need gmake since the Makefiles are not compatible with BSD make). +Note that the cross-powerpc package does not install include files; +attempting to build U-Boot will fail because <machine/ansi.h> is +missing. This file has to be installed and patched manually: + + # cd /usr/pkg/cross/powerpc-netbsd/include + # mkdir powerpc + # ln -s powerpc machine + # cp /usr/src/sys/arch/powerpc/include/ansi.h powerpc/ansi.h + # ${EDIT} powerpc/ansi.h ## must remove __va_list, _BSD_VA_LIST + +Native builds *don't* work due to incompatibilities between native +and U-Boot include files. + +Booting assumes that (the first part of) the image booted is a +stage-2 loader which in turn loads and then invokes the kernel +proper. Loader sources will eventually appear in the NetBSD source +tree (probably in sys/arc/mpc8xx/stand/u-boot_stage2/); in the +meantime, send mail to bruno@exet-ag.de and/or wd@denx.de for +details. + + +Implementation Internals: +========================= + +The following is not intended to be a complete description of every +implementation detail. However, it should help to understand the +inner workings of U-Boot and make it easier to port it to custom +hardware. + + +Initial Stack, Global Data: +--------------------------- + +The implementation of U-Boot is complicated by the fact that U-Boot +starts running out of ROM (flash memory), usually without access to +system RAM (because the memory controller is not initialized yet). +This means that we don't have writable Data or BSS segments, and BSS +is not initialized as zero. To be able to get a C environment working +at all, we have to allocate at least a minimal stack. Implementation +options for this are defined and restricted by the CPU used: Some CPU +models provide on-chip memory (like the IMMR area on MPC8xx and +MPC826x processors), on others (parts of) the data cache can be +locked as (mis-) used as memory, etc. + +It is essential to remember this, since it has some impact on the C +code for the initialization procedures: + +* Initialized global data (data segment) is read-only. Do not attempt + to write it. + +* Do not use any unitialized global data (or implicitely initialized + as zero data - BSS segment) at all - this is undefined, initiali- + zation is performed later (when relocationg to RAM). + +* Stack space is very limited. Avoid big data buffers or things like + that. + +Having only the stack as writable memory limits means we cannot use +normal global data to share information beween the code. But it +turned out that the implementation of U-Boot can be greatly +simplified by making a global data structure (gd_t) available to all +functions. We could pass a pointer to this data as argument to _all_ +functions, but this would bloat the code. Instead we use a feature of +the GCC compiler (Global Register Variables) to share the data: we +place a pointer (gd) to the global data into a register which we +reserve for this purpose. + +When chosing a register for such a purpose we are restricted by the +relevant (E)ABI specifications for the current architecture, and by +GCC's implementation. + +For PowerPC, the following registers have specific use: + R1: stack pointer + R2: TOC pointer + R3-R4: parameter passing and return values + R5-R10: parameter passing + R13: small data area pointer + R30: GOT pointer + R31: frame pointer + + (U-Boot also uses R14 as internal GOT pointer.) + + ==> U-Boot will use R29 to hold a pointer to the global data + + Note: on PPC, we could use a static initializer (since the + address of the global data structure is known at compile time), + but it turned out that reserving a register results in somewhat + smaller code - although the code savings are not that big (on + average for all boards 752 bytes for the whole U-Boot image, + 624 text + 127 data). + +On ARM, the following registers are used: + + R0: function argument word/integer result + R1-R3: function argument word + R9: GOT pointer + R10: stack limit (used only if stack checking if enabled) + R11: argument (frame) pointer + R12: temporary workspace + R13: stack pointer + R14: link register + R15: program counter + + ==> U-Boot will use R8 to hold a pointer to the global data + + + +Memory Management: +------------------ + +U-Boot runs in system state and uses physical addresses, i.e. the +MMU is not used either for address mapping nor for memory protection. + +The available memory is mapped to fixed addresses using the memory +controller. In this process, a contiguous block is formed for each +memory type (Flash, SDRAM, SRAM), even when it consists of several +physical memory banks. + +U-Boot is installed in the first 128 kB of the first Flash bank (on +TQM8xxL modules this is the range 0x40000000 ... 0x4001FFFF). After +booting and sizing and initializing DRAM, the code relocates itself +to the upper end of DRAM. Immediately below the U-Boot code some +memory is reserved for use by malloc() [see CFG_MALLOC_LEN +configuration setting]. Below that, a structure with global Board +Info data is placed, followed by the stack (growing downward). + +Additionally, some exception handler code is copied to the low 8 kB +of DRAM (0x00000000 ... 0x00001FFF). + +So a typical memory configuration with 16 MB of DRAM could look like +this: + + 0x0000 0000 Exception Vector code + : + 0x0000 1FFF + 0x0000 2000 Free for Application Use + : + : + + : + : + 0x00FB FF20 Monitor Stack (Growing downward) + 0x00FB FFAC Board Info Data and permanent copy of global data + 0x00FC 0000 Malloc Arena + : + 0x00FD FFFF + 0x00FE 0000 RAM Copy of Monitor Code + ... eventually: LCD or video framebuffer + ... eventually: pRAM (Protected RAM - unchanged by reset) + 0x00FF FFFF [End of RAM] + + +System Initialization: +---------------------- + +In the reset configuration, U-Boot starts at the reset entry point +(on most PowerPC systens at address 0x00000100). Because of the reset +configuration for CS0# this is a mirror of the onboard Flash memory. +To be able to re-map memory U-Boot then jumps to it's link address. +To be able to implement the initialization code in C, a (small!) +initial stack is set up in the internal Dual Ported RAM (in case CPUs +which provide such a feature like MPC8xx or MPC8260), or in a locked +part of the data cache. After that, U-Boot initializes the CPU core, +the caches and the SIU. + +Next, all (potentially) available memory banks are mapped using a +preliminary mapping. For example, we put them on 512 MB boundaries +(multiples of 0x20000000: SDRAM on 0x00000000 and 0x20000000, Flash +on 0x40000000 and 0x60000000, SRAM on 0x80000000). Then UPM A is +programmed for SDRAM access. Using the temporary configuration, a +simple memory test is run that determines the size of the SDRAM +banks. + +When there is more than one SDRAM bank, and the banks are of +different size, the larger is mapped first. For equal size, the first +bank (CS2#) is mapped first. The first mapping is always for address +0x00000000, with any additional banks following immediately to create +contiguous memory starting from 0. + +Then, the monitor installs itself at the upper end of the SDRAM area +and allocates memory for use by malloc() and for the global Board +Info data; also, the exception vector code is copied to the low RAM +pages, and the final stack is set up. + +Only after this relocation will you have a "normal" C environment; +until that you are restricted in several ways, mostly because you are +running from ROM, and because the code will have to be relocated to a +new address in RAM. + + +U-Boot Porting Guide: +---------------------- + +[Based on messages by Jerry Van Baren in the U-Boot-Users mailing +list, Octover 2002] + + +int main (int argc, char *argv[]) +{ + sighandler_t no_more_time; + + signal (SIGALRM, no_more_time); + alarm (PROJECT_DEADLINE - toSec (3 * WEEK)); + + if (available_money > available_manpower) { + pay consultant to port U-Boot; + return 0; + } + + Download latest U-Boot source; + + if (clueless) { + email ("Hi, I am new to U-Boot, how do I get started?"); + } + + while (learning) { + Read the README file in the top level directory; + Read http://www.denx.de/re/DPLG.html + Read the source, Luke; + } + + if (available_money > toLocalCurrency ($2500)) { + Buy a BDI2000; + } else { + Add a lot of aggravation and time; + } + + Create your own board support subdirectory; + + while (!running) { + do { + Add / modify source code; + } until (compiles); + Debug; + if (clueless) + email ("Hi, I am having problems..."); + } + Send patch file to Wolfgang; + + return 0; +} + +void no_more_time (int sig) +{ + hire_a_guru(); +} + + + +Coding Standards: +----------------- + +All contributions to U-Boot should conform to the Linux kernel +coding style; see the file "Documentation/CodingStyle" in your Linux +kernel source directory. + +Please note that U-Boot is implemented in C (and to some small parts +in Assembler); no C++ is used, so please do not use C++ style +comments (//) in your code. + +Submissions which do not conform to the standards may be returned +with a request to reformat the changes. + + +Submitting Patches: +------------------- + +Since the number of patches for U-Boot is growing, we need to +establish some rules. Submissions which do not conform to these rules +may be rejected, even when they contain important and valuable stuff. + + +When you send a patch, please include the following information with +it: + +* For bug fixes: a description of the bug and how your patch fixes + this bug. Please try to include a way of demonstrating that the + patch actually fixes something. + +* For new features: a description of the feature and your + implementation. + +* A CHANGELOG entry as plaintext (separate from the patch) + +* For major contributions, your entry to the CREDITS file + +* When you add support for a new board, don't forget to add this + board to the MAKEALL script, too. + +* If your patch adds new configuration options, don't forget to + document these in the README file. + +* The patch itself. If you are accessing the CVS repository use "cvs + update; cvs diff -puRN"; else, use "diff -purN OLD NEW". If your + version of diff does not support these options, then get the latest + version of GNU diff. + + We accept patches as plain text, MIME attachments or as uuencoded + gzipped text. + +Notes: + +* Before sending the patch, run the MAKEALL script on your patched + source tree and make sure that no errors or warnings are reported + for any of the boards. + +* Keep your modifications to the necessary minimum: A patch + containing several unrelated changes or arbitrary reformats will be + returned with a request to re-formatting / split it. + +* If you modify existing code, make sure that your new code does not + add to the memory footprint of the code ;-) Small is beautiful! + When adding new features, these should compile conditionally only + (using #ifdef), and the resulting code with the new feature + disabled must not need more memory than the old code without your + modification. diff --git a/board/cogent/serial.c b/board/cogent/serial.c new file mode 100644 index 0000000..4c20017 --- /dev/null +++ b/board/cogent/serial.c @@ -0,0 +1,190 @@ +/* + * Simple serial driver for Cogent motherboard serial ports + * for use during boot + */ + +#include <common.h> +#include <board/cogent/serial.h> + +#if (CMA_MB_CAPS & CMA_MB_CAP_SERPAR) + +#if (defined(CONFIG_8xx) && defined(CONFIG_8xx_CONS_NONE)) || \ + (defined(CONFIG_8260) && defined(CONFIG_CONS_NONE)) + +#if CONFIG_CONS_INDEX == 1 +#define CMA_MB_SERIAL_BASE CMA_MB_SERIALA_BASE +#elif CONFIG_CONS_INDEX == 2 +#define CMA_MB_SERIAL_BASE CMA_MB_SERIALB_BASE +#elif CONFIG_CONS_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2) +#define CMA_MB_SERIAL_BASE CMA_MB_SER2A_BASE +#elif CONFIG_CONS_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2) +#define CMA_MB_SERIAL_BASE CMA_MB_SER2B_BASE +#else +#error CONFIG_CONS_INDEX must be configured for Cogent motherboard serial +#endif + +int serial_init (void) +{ +/* DECLARE_GLOBAL_DATA_PTR; */ + + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE; + + cma_mb_reg_write(&mbsp->ser_ier, 0x00); /* turn off interrupts */ + serial_setbrg (); + cma_mb_reg_write(&mbsp->ser_lcr, 0x03); /* 8 data, 1 stop, no parity */ + cma_mb_reg_write(&mbsp->ser_mcr, 0x03); /* RTS/DTR */ + cma_mb_reg_write(&mbsp->ser_fcr, 0x07); /* Clear & enable FIFOs */ + + return (0); +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE; + unsigned int divisor; + unsigned char lcr; + + if ((divisor = br_to_div(gd->baudrate)) == 0) + divisor = DEFDIV; + + lcr = cma_mb_reg_read(&mbsp->ser_lcr); + cma_mb_reg_write(&mbsp->ser_lcr, lcr|0x80);/* Access baud rate(set DLAB)*/ + cma_mb_reg_write(&mbsp->ser_brl, divisor & 0xff); + cma_mb_reg_write(&mbsp->ser_brh, (divisor >> 8) & 0xff); + cma_mb_reg_write(&mbsp->ser_lcr, lcr); /* unset DLAB */ +} + +void +serial_putc(const char c) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE; + + if (c == '\n') + serial_putc('\r'); + + while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_THRE) == 0) + ; + + cma_mb_reg_write(&mbsp->ser_thr, c); +} + +void +serial_puts(const char *s) +{ + while (*s != '\0') + serial_putc(*s++); +} + +int +serial_getc(void) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE; + + while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) == 0) + ; + + return ((int)cma_mb_reg_read(&mbsp->ser_rhr) & 0x7f); +} + +int +serial_tstc(void) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_SERIAL_BASE; + + return ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) != 0); +} + +#endif /* CONS_NONE */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) && \ + defined(CONFIG_KGDB_NONE) + +#if CONFIG_KGDB_INDEX == CONFIG_CONS_INDEX +#error Console and kgdb are on the same serial port - this is not supported +#endif + +#if CONFIG_KGDB_INDEX == 1 +#define CMA_MB_KGDB_SER_BASE CMA_MB_SERIALA_BASE +#elif CONFIG_KGDB_INDEX == 2 +#define CMA_MB_KGDB_SER_BASE CMA_MB_SERIALB_BASE +#elif CONFIG_KGDB_INDEX == 3 && (CMA_MB_CAPS & CMA_MB_CAP_SER2) +#define CMA_MB_KGDB_SER_BASE CMA_MB_SER2A_BASE +#elif CONFIG_KGDB_INDEX == 4 && (CMA_MB_CAPS & CMA_MB_CAP_SER2) +#define CMA_MB_KGDB_SER_BASE CMA_MB_SER2B_BASE +#else +#error CONFIG_KGDB_INDEX must be configured for Cogent motherboard serial +#endif + +void +kgdb_serial_init(void) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE; + unsigned int divisor; + + if ((divisor = br_to_div(CONFIG_KGDB_BAUDRATE)) == 0) + divisor = DEFDIV; + + cma_mb_reg_write(&mbsp->ser_ier, 0x00); /* turn off interrupts */ + cma_mb_reg_write(&mbsp->ser_lcr, 0x80); /* Access baud rate(set DLAB)*/ + cma_mb_reg_write(&mbsp->ser_brl, divisor & 0xff); + cma_mb_reg_write(&mbsp->ser_brh, (divisor >> 8) & 0xff); + cma_mb_reg_write(&mbsp->ser_lcr, 0x03); /* 8 data, 1 stop, no parity */ + cma_mb_reg_write(&mbsp->ser_mcr, 0x03); /* RTS/DTR */ + cma_mb_reg_write(&mbsp->ser_fcr, 0x07); /* Clear & enable FIFOs */ + + printf("[on cma10x serial port B] "); +} + +void +putDebugChar(int c) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE; + + while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_THRE) == 0) + ; + + cma_mb_reg_write(&mbsp->ser_thr, c & 0xff); +} + +void +putDebugStr(const char *str) +{ + while (*str != '\0') { + if (*str == '\n') + putDebugChar('\r'); + putDebugChar(*str++); + } +} + +int +getDebugChar(void) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE; + + while ((cma_mb_reg_read(&mbsp->ser_lsr) & LSR_DR) == 0) + ; + + return ((int)cma_mb_reg_read(&mbsp->ser_rhr) & 0x7f); +} + +void +kgdb_interruptible(int yes) +{ + cma_mb_serial *mbsp = (cma_mb_serial *)CMA_MB_KGDB_SER_BASE; + + if (yes == 1) { + printf("kgdb: turning serial ints on\n"); + cma_mb_reg_write(&mbsp->ser_ier, 0xf); + } + else { + printf("kgdb: turning serial ints off\n"); + cma_mb_reg_write(&mbsp->ser_ier, 0x0); + } +} + +#endif /* KGDB && KGDB_NONE */ + +#endif /* CAPS & SERPAR */ diff --git a/board/cu824/cu824.c b/board/cu824/cu824.c new file mode 100644 index 0000000..20aaea2 --- /dev/null +++ b/board/cu824/cu824.c @@ -0,0 +1,119 @@ +/* + * (C) Copyright 2001 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <asm/processor.h> +#include <pci.h> + +#define BOARD_REV_REG 0xFE80002B + +int checkboard (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + char revision = *(volatile char *)(BOARD_REV_REG); + char buf[32]; + + puts ("Board: CU824 "); + printf("Revision %d ", revision); + printf("Local Bus at %s MHz\n", strmhz(buf, gd->bus_clk)); + + return 0; +} + +long int initdram(int board_type) +{ + int i, cnt; + volatile uchar * base = CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +} + +/* + * Initialize PCI Devices, report devices found. + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_sandpoint_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN), + pci_cfgfunc_config_device, { CFG_ETH_IOBASE, + 0, + PCI_COMMAND_IO | PCI_COMMAND_MASTER }}, + { } +}; +#endif + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_sandpoint_config_table, +#endif +}; + +void pci_init(void) +{ + pci_mpc824x_init(&hose); +} diff --git a/board/dnp1110/u-boot.lds b/board/dnp1110/u-boot.lds new file mode 100644 index 0000000..f4b0ade --- /dev/null +++ b/board/dnp1110/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/sa1100/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/ebony/ebony.c b/board/ebony/ebony.c new file mode 100644 index 0000000..723fad3 --- /dev/null +++ b/board/ebony/ebony.c @@ -0,0 +1,301 @@ +/* + * Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 + */ + + +extern long int spd_sdram (void); + +#include <common.h> +#include "ebony.h" +#include <asm/processor.h> + +#define BOOT_SMALL_FLASH 32 /* 00100000 */ +#define FLASH_ONBD_N 2 /* 00000010 */ +#define FLASH_SRAM_SEL 1 /* 00000001 */ + +long int fixed_sdram (void); + +int board_pre_init (void) +{ + uint reg; + unsigned char *fpga_base = (unsigned char *) CFG_FPGA_BASE; + unsigned char status; + + + /*-------------------------------------------------------------------- + * Setup the external bus controller/chip selects + *-------------------------------------------------------------------*/ + mtdcr (ebccfga, xbcfg); + reg = mfdcr (ebccfgd); + mtdcr (ebccfgd, reg | 0x04000000); /* Set ATC */ + + mtebc (pb1ap, 0x02815480); /* NVRAM/RTC */ + mtebc (pb1cr, 0x48018000); /* BA=0x480 1MB R/W 8-bit */ + mtebc (pb7ap, 0x01015280); /* FPGA registers */ + mtebc (pb7cr, 0x48318000); /* BA=0x483 1MB R/W 8-bit */ + + /* read FPGA_REG0 and set the bus controller */ + status = *fpga_base; + if ((status & BOOT_SMALL_FLASH) && !(status & FLASH_ONBD_N)) { + mtebc (pb0ap, 0x9b015480); /* FLASH/SRAM */ + mtebc (pb0cr, 0xfff18000); /* BAS=0xfff 1MB R/W 8-bit */ + mtebc (pb2ap, 0x9b015480); /* 4MB FLASH */ + mtebc (pb2cr, 0xff858000); /* BAS=0xff8 4MB R/W 8-bit */ + } else { + mtebc (pb0ap, 0x9b015480); /* 4MB FLASH */ + mtebc (pb0cr, 0xffc58000); /* BAS=0xffc 4MB R/W 8-bit */ + + /* set CS2 if FLASH_ONBD_N == 0 */ + if (!(status & FLASH_ONBD_N)) { + mtebc (pb2ap, 0x9b015480); /* FLASH/SRAM */ + mtebc (pb2cr, 0xff818000); /* BAS=0xff8 4MB R/W 8-bit */ + } + } + + /*-------------------------------------------------------------------- + * Setup the interrupt controller polarities, triggers, etc. + *-------------------------------------------------------------------*/ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + mtdcr (uic0er, 0x00000000); /* disable all */ + mtdcr (uic0cr, 0x00000009); /* SMI & UIC1 crit are critical */ + mtdcr (uic0pr, 0xfffffe13); /* per ref-board manual */ + mtdcr (uic0tr, 0x01c00008); /* per ref-board manual */ + mtdcr (uic0vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic0sr, 0xffffffff); /* clear all */ + + mtdcr (uic1sr, 0xffffffff); /* clear all */ + mtdcr (uic1er, 0x00000000); /* disable all */ + mtdcr (uic1cr, 0x00000000); /* all non-critical */ + mtdcr (uic1pr, 0xffffe0ff); /* per ref-board manual */ + mtdcr (uic1tr, 0x00ffc000); /* per ref-board manual */ + mtdcr (uic1vr, 0x00000001); /* int31 highest, base=0x000 */ + mtdcr (uic1sr, 0xffffffff); /* clear all */ + + return 0; +} + + + +int checkboard (void) +{ + sys_info_t sysinfo; + + get_sys_info (&sysinfo); + + printf ("Board: IBM 440GP Evaluation Board (Ebony)\n"); + printf ("\tVCO: %lu MHz\n", sysinfo.freqVCOMhz / 1000000); + printf ("\tCPU: %lu MHz\n", sysinfo.freqProcessor / 1000000); + printf ("\tPLB: %lu MHz\n", sysinfo.freqPLB / 1000000); + printf ("\tOPB: %lu MHz\n", sysinfo.freqOPB / 1000000); + printf ("\tEPB: %lu MHz\n", sysinfo.freqEPB / 1000000); + return (0); +} + + +long int initdram (int board_type) +{ + long dram_size = 0; + extern long spd_sdram (void); + +#if defined(CONFIG_SPD_EEPROM) + dram_size = spd_sdram (); +#else + dram_size = fixed_sdram (); +#endif + return dram_size; +} + + +#if defined(CFG_DRAM_TEST) +int testdram (void) +{ + uint *pstart = (uint *) 0x00000000; + uint *pend = (uint *) 0x08000000; + uint *p; + + for (p = pstart; p < pend; p++) + *p = 0xaaaaaaaa; + + for (p = pstart; p < pend; p++) { + if (*p != 0xaaaaaaaa) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + + for (p = pstart; p < pend; p++) + *p = 0x55555555; + + for (p = pstart; p < pend; p++) { + if (*p != 0x55555555) { + printf ("SDRAM test fails at: %08x\n", (uint) p); + return 1; + } + } + return 0; +} +#endif + +#if !defined(CONFIG_SPD_EEPROM) +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + * + * Assumes: 128 MB, non-ECC, non-registered + * PLB @ 133 MHz + * + ************************************************************************/ +long int fixed_sdram (void) +{ + uint reg; + + /*-------------------------------------------------------------------- + * Setup some default + *------------------------------------------------------------------*/ + mtsdram (mem_uabba, 0x00000000); /* ubba=0 (default) */ + mtsdram (mem_slio, 0x00000000); /* rdre=0 wrre=0 rarw=0 */ + mtsdram (mem_devopt, 0x00000000); /* dll=0 ds=0 (normal) */ + mtsdram (mem_wddctr, 0x00000000); /* wrcp=0 dcd=0 */ + mtsdram (mem_clktr, 0x40000000); /* clkp=1 (90 deg wr) dcdt=0 */ + + /*-------------------------------------------------------------------- + * Setup for board-specific specific mem + *------------------------------------------------------------------*/ + /* + * Following for CAS Latency = 2.5 @ 133 MHz PLB + */ + mtsdram (mem_b0cr, 0x000a4001); /* SDBA=0x000 128MB, Mode 3, enabled */ + mtsdram (mem_tr0, 0x410a4012); /* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */ + /* RA=10 RD=3 */ + mtsdram (mem_tr1, 0x8080082f); /* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */ + mtsdram (mem_rtr, 0x08200000); /* Rate 15.625 ns @ 133 MHz PLB */ + mtsdram (mem_cfg1, 0x00000000); /* Self-refresh exit, disable PM */ + udelay (400); /* Delay 200 usecs (min) */ + + /*-------------------------------------------------------------------- + * Enable the controller, then wait for DCEN to complete + *------------------------------------------------------------------*/ + mtsdram (mem_cfg0, 0x86000000); /* DCEN=1, PMUD=1, 64-bit */ + for (;;) { + mfsdram (mem_mcsts, reg); + if (reg & 0x80000000) + break; + } + + 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(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(struct pci_controller * hose ) +{ + DECLARE_GLOBAL_DATA_PTR; + + /*--------------------------------------------------------------------------+ + * 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(struct pci_controller *hose) +{ + /* The ebony board is always configured as host. */ + return(1); +} +#endif /* defined(CONFIG_PCI) */ diff --git a/board/ebony/init.S b/board/ebony/init.S new file mode 100644 index 0000000..3ae93d6 --- /dev/null +++ b/board/ebony/init.S @@ -0,0 +1,98 @@ +/* +* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl> +#include <config.h> + +/* General */ +#define TLB_VALID 0x00000200 + +/* Supported page sizes */ + +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ + +/* Some handy macros */ + +#define EPN(e) ((e) & 0xfffffc00) +#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) +#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) +#define TLB2(a) ( (a)&0x00000fbf ) + +#define tlbtab_start\ + mflr r1 ;\ + bl 0f ; + +#define tlbtab_end\ + .long 0, 0, 0 ; \ +0: mflr r0 ; \ + mtlr r1 ; \ + blr ; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ + .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + .globl tlbtab + +tlbtab: + tlbtab_start + tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) + 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/eltec/bab7xx/asm_init.S b/board/eltec/bab7xx/asm_init.S new file mode 100644 index 0000000..d739b81 --- /dev/null +++ b/board/eltec/bab7xx/asm_init.S @@ -0,0 +1,1487 @@ +/* + * (C) Copyright 2001 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.de> + * + * ELTEC BAB PPC RAM initialization + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <mpc75x.h> +#include <mpc106.h> +#include <version.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +/* + * This following contains the entry code for the initialization code + * for the MPC 106, a PCI Bridge/Memory Controller. + * Register usage: + * r0 = ramtest scratch register, toggleError loop counter + * r1 = 0xfec0 0cf8 CONFIG_ADDRESS + * r2 = 0xfee0 0cfc CONFIG_DATA + * r3 = scratch register, subroutine argument and return value, ramtest size + * r4 = scratch register, spdRead clock mask, OutHex loop count + * r5 = ramtest scratch register + * r6 = toggleError 1st value, spdRead port mask + * r7 = toggleError 2nd value, ramtest scratch register, + * spdRead scratch register (0x00) + * r8 = ramtest scratch register, spdRead scratch register (0x80) + * r9 = ramtest scratch register, toggleError loop end, OutHex digit + * r10 = ramtest scratch register, spdWriteByte parameter, + * spdReadByte return value, printf pointer to COM1 + * r11 = startType + * r12 = ramtest scratch register, spdRead data mask + * r13 = pointer to message block + * r14 = pointer to GOT + * r15 = scratch register, SPD save + * r16 = bank0 size, total memory size + * r17 = bank1 size + * r18 = bank2 size + * r19 = bank3 size + * r20 = MCCR1, MSAR1 + * r21 = MCCR3, MEAR1 + * r22 = MCCR4, MBER + * r23 = EMSAR1 + * r24 = EMEAR1 + * r25 = save link register 1st level + * r26 = save link register 2nd level + * r27 = save link register 3rd level + * r30 = pointer to GPIO for spdRead + */ + + +.globl board_asm_init +board_asm_init: +/* + * setup pointer to message block + */ + mflr r25 /* save away link register */ + bl get_lnk_reg /* r3=addr of next instruction */ + subi r4, r3, 8 /* r4=board_asm_init addr */ + addi r13, r4, (MessageBlock-board_asm_init) +/* + * dcache_disable + */ + mfspr r3, HID0 + li r4, HID0_DCE + andc r3, r3, r4 + mr r2, r3 + ori r3, r3, HID0_DCI + sync + mtspr HID0, r3 + mtspr HID0, r2 + isync + sync +/* + * icache_disable + */ + mfspr r3, HID0 + li r4, 0 + ori r4, r4, HID0_ICE + andc r3, r3, r4 + sync + mtspr HID0, r3 +/* + * invalidate caches + */ + ori r3, r3, (HID0_ICE | HID0_ICFI | HID0_DCI | HID0_DCE) + or r4, r4, r3 + isync + mtspr HID0, r4 + andc r4, r4, r3 + isync + mtspr HID0, r4 + isync +/* + * icache_enable + */ + mfspr r3, HID0 + ori r3, r3, (HID0_ICE | HID0_ICFI) + sync + mtspr HID0, r3 + + lis r1, 0xfec0 + ori r1, r1, 0x0cf8 + lis r2, 0xfee0 + ori r2, r2, 0xcfc + +#ifdef CFG_ADDRESS_MAP_A +/* + * Switch to address map A if necessary. + */ + lis r3, MPC106_REG@h + ori r3, r3, PCI_PICR1 + stwbrx r3, 0, r1 + sync + lwbrx r4, 0, r2 + sync + lis r0, PICR1_XIO_MODE@h + ori r0, r0, PICR1_XIO_MODE@l + andc r4, r4, r0 + lis r0, PICR1_ADDRESS_MAP@h + ori r0, r0, PICR1_ADDRESS_MAP@l + or r4, r4, r0 + stwbrx r4, 0, r2 + sync +#endif + +/* + * Do the init for the SIO. + */ + bl .sioInit + + addi r3, r13, (MinitLogo-MessageBlock) + bl Printf + + addi r3, r13, (Mspd01-MessageBlock) + bl Printf +/* + * Memory cofiguration using SPD information stored on the SODIMMs + */ + li r17, 0 + li r18, 0 + li r19, 0 + + li r3, 0x0002 /* get RAM type from spd for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, -1 /* error ? */ + bne noSpdError + + addi r3, r13, (Mfail-MessageBlock) + bl Printf + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x00 + b toggleError /* fail - loop forever */ + +noSpdError: + mr r15, r3 /* save r3 */ + + addi r3, r13, (Mok-MessageBlock) + bl Printf + + cmpli 0, 0, r15, 0x0001 /* FPM ? */ + beq configFPM + cmpli 0, 0, r15, 0x0002 /* EDO ? */ + beq configEDO + cmpli 0, 0, r15, 0x0004 /* SDRAM ? */ + beq configSDRAM + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x01 + b toggleError /* fail - loop forever */ + +configSDRAM: + addi r3, r13, (MsdRam-MessageBlock) + bl Printf +/* + * set the Memory Configuration Reg. 1 + */ + li r3, 0x001f /* get bank size from spd bank0/1 */ + bl spdRead + + andi. r3, r3, 0x0038 + beq SD16MB2B + + li r3, 0x0011 /* get number of internal banks */ + /* from spd for bank0/1 */ + bl spdRead + + cmpli 0, 0, r3, 0x02 + beq SD64MB2B + + cmpli 0, 0, r3, 0x04 + beq SD64MB4B + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x02 + b toggleError /* fail - loop forever */ + +SD64MB2B: + li r20, 0x0005 /* 64-Mbit SDRAM 2 banks */ + b SDRow2nd + +SD64MB4B: + li r20, 0x0000 /* 64-Mbit SDRAM 4 banks */ + b SDRow2nd + +SD16MB2B: + li r20, 0x000f /* 16-Mbit SDRAM 2 banks */ + +SDRow2nd: + li r3, 0x0102 /* get RAM type spd for bank2/3 */ + bl spdRead + + cmpli 0, 0, r3, 0x0004 + bne S2D64MB4B /* bank2/3 isn't present or no SDRAM */ + + li r3, 0x011f /* get bank size from spd bank2/3 */ + bl spdRead + + andi. r3, r3, 0x0038 + beq S2D16MB2B +/* + * set the Memory Configuration Reg. 2 + */ + li r3, 0x0111 /* get number of internal banks */ + /* from spd for bank2/3 */ + bl spdRead + + cmpli 0, 0, r3, 0x02 + beq S2D64MB2B + + cmpli 0, 0, r3, 0x04 + beq S2D64MB4B + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x03 + b toggleError /* fail - loop forever */ + +S2D64MB2B: + ori r20, r20, 0x0050 /* 64-Mbit SDRAM 2 banks */ + b S2D64MB4B + +S2D16MB2B: + ori r20, r20, 0x00f0 /* 16-Mbit SDRAM 2 banks */ + +/* + * set the Memory Configuration Reg. 3 + */ +S2D64MB4B: + lis r21, 0x8630 /* BSTOPRE = 0x80, REFREC = 6, */ + /* RDLAT = 3 */ + +/* + * set the Memory Configuration Reg. 4 + */ + lis r22, 0x2430 /* PRETOACT = 2, ACTOPRE = 4, */ + /* WCBUF = 1, RCBUF = 1 */ + ori r22, r22, 0x2220 /* SDMODE = 0x022, ACTORW = 2 */ + +/* + * get the size of bank 0-3 + */ + li r3, 0x001f /* get bank size from spd bank0/1 */ + bl spdRead + + rlwinm r16, r3, 2, 24, 29 /* calculate size in MByte */ + /* (128 MB max.) */ + + li r3, 0x0005 /* get number of banks from spd */ + /* for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, 2 /* 2 banks ? */ + bne SDRAMnobank1 + + mr r17, r16 + +SDRAMnobank1: + addi r3, r13, (Mspd23-MessageBlock) + bl Printf + + li r3, 0x0102 /* get RAM type spd for bank2/3 */ + bl spdRead + + cmpli 0, 0, r3, 0x0001 /* FPM ? */ + bne noFPM23 /* handle as EDO */ + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MfpmRam-MessageBlock) + bl Printf + b configRAMcommon +noFPM23: + cmpli 0, 0, r3, 0x0002 /* EDO ? */ + bne noEDO23 + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MedoRam-MessageBlock) + bl Printf + b configRAMcommon +noEDO23: + cmpli 0, 0, r3, 0x0004 /* SDRAM ? */ + bne noSDRAM23 + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MsdRam-MessageBlock) + bl Printf + b configSDRAM23 +noSDRAM23: + addi r3, r13, (Mna-MessageBlock) + bl Printf + b configRAMcommon /* bank2/3 isn't present or no SDRAM */ + +configSDRAM23: + li r3, 0x011f /* get bank size from spd bank2/3 */ + bl spdRead + + rlwinm r18, r3, 2, 24, 29 /* calculate size in MByte */ + /* (128 MB max.) */ + + li r3, 0x0105 /* get number of banks from */ + /* spd bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, 2 /* 2 banks ? */ + bne SDRAMnobank3 + + mr r19, r18 + +SDRAMnobank3: + b configRAMcommon + +configFPM: + addi r3, r13, (MfpmRam-MessageBlock) + bl Printf + b configEDO0 +/* + * set the Memory Configuration Reg. 1 + */ +configEDO: + addi r3, r13, (MedoRam-MessageBlock) + bl Printf +configEDO0: + lis r20, MCCR1_TYPE_EDO@h + +getSpdRowBank01: + li r3, 0x0003 /* get number of row bits from */ + /* spd from bank0/1 */ + bl spdRead + ori r20, r20, (MCCR1_BK0_9BITS | MCCR1_BK1_9BITS) + cmpli 0, 0, r3, 0x0009 /* bank0 - 9 row bits */ + beq getSpdRowBank23 + + ori r20, r20, (MCCR1_BK0_10BITS | MCCR1_BK1_10BITS) + cmpli 0, 0, r3, 0x000a /* bank0 - 10 row bits */ + beq getSpdRowBank23 + + ori r20, r20, (MCCR1_BK0_11BITS | MCCR1_BK1_11BITS) + cmpli 0, 0, r3, 0x000b /* bank0 - 11 row bits */ + beq getSpdRowBank23 + + ori r20, r20, (MCCR1_BK0_12BITS | MCCR1_BK1_12BITS) + cmpli 0, 0, r3, 0x000c /* bank0 - 12 row bits */ + beq getSpdRowBank23 + + cmpli 0, 0, r3, 0x000d /* bank0 - 13 row bits */ + beq getSpdRowBank23 + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x10 + b toggleError /* fail - loop forever */ + +getSpdRowBank23: + li r3, 0x0103 /* get number of row bits from */ + /* spd for bank2/3 */ + bl spdRead + + ori r20, r20, (MCCR1_BK2_9BITS | MCCR1_BK3_9BITS) + cmpli 0, 0, r3, 0x0009 /* bank0 - 9 row bits */ + beq writeRowBits + + ori r20, r20, (MCCR1_BK2_10BITS | MCCR1_BK3_10BITS) + cmpli 0, 0, r3, 0x000a /* bank0 - 10 row bits */ + beq writeRowBits + + ori r20, r20, (MCCR1_BK2_11BITS | MCCR1_BK3_11BITS) + cmpli 0, 0, r3, 0x000b /* bank0 - 11 row bits */ + beq writeRowBits + + ori r20, r20, (MCCR1_BK2_12BITS | MCCR1_BK3_12BITS) + +/* + * set the Memory Configuration Reg. 3 + */ +writeRowBits: + lis r21, 0x000a /* CPX = 1, RAS6P = 4 */ + ori r21, r21, 0x2293 /* CAS5 = 2, CP4 = 1, */ + /* CAS3 = 2, RCD2 = 2, RP = 3 */ +/* + * set the Memory Configuration Reg. 4 + */ + lis r22, 0x0010 /* all SDRAM parameter 0, */ + /* WCBUF flow through, */ + /* RCBUF registered */ +/* + * get the size of bank 0-3 + */ + li r3, 0x0003 /* get row bits from spd bank0/1 */ + bl spdRead + + li r16, 0 /* bank size is: */ + /* (8*2^row*2^column)/0x100000 MB */ + ori r16, r16, 0x8000 + rlwnm r16, r16, r3, 0, 31 + + li r3, 0x0004 /* get column bits from spd bank0/1 */ + bl spdRead + + rlwnm r16, r16, r3, 0, 31 + + li r3, 0x0005 /* get number of banks from */ + /* spd for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, 2 /* 2 banks ? */ + bne EDOnobank1 + + mr r17, r16 + +EDOnobank1: + addi r3, r13, (Mspd23-MessageBlock) + bl Printf + + li r3, 0x0102 /* get RAM type spd for bank2/3 */ + bl spdRead + + cmpli 0, 0, r3, 0x0001 /* FPM ? */ + bne noFPM231 /* handle as EDO */ + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MfpmRam-MessageBlock) + bl Printf + b EDObank2 +noFPM231: + cmpli 0, 0, r3, 0x0002 /* EDO ? */ + bne noEDO231 + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MedoRam-MessageBlock) + bl Printf + b EDObank2 +noEDO231: + cmpli 0, 0, r3, 0x0004 /* SDRAM ? */ + bne noSDRAM231 + addi r3, r13, (Mok-MessageBlock) + bl Printf + addi r3, r13, (MsdRam-MessageBlock) + bl Printf + b configRAMcommon +noSDRAM231: + addi r3, r13, (Mfail-MessageBlock) + bl Printf + b configRAMcommon /* bank2/3 isn't present or no SDRAM */ + +EDObank2: + li r3, 0x0103 /* get row bits from spd for bank2/3 */ + bl spdRead + + li r18, 0 /* bank size is: */ + /* (8*2^row*2^column)/0x100000 MB */ + ori r18, r18, 0x8000 + rlwnm r18, r18, r3, 0, 31 + + li r3, 0x0104 /* get column bits from spd bank2/3 */ + bl spdRead + + rlwnm r18, r18, r3, 0, 31 + + li r3, 0x0105 /* get number of banks from */ + /* spd for bank2/3 */ + bl spdRead + + cmpi 0, 0, r3, 2 /* 2 banks ? */ + bne configRAMcommon + + mr r19, r18 + +configRAMcommon: + lis r1, MPC106_REG_ADDR@h + ori r1, r1, MPC106_REG_ADDR@l + lis r2, MPC106_REG_DATA@h + ori r2, r2, MPC106_REG_DATA@l + + li r0, 0 + +/* + * If we are already running in RAM (debug mode), we should + * NOT reset the MEMGO flag. Otherwise we will stop all memory + * accesses. + */ +#ifdef IN_RAM + lis r4, MCCR1_MEMGO@h + ori r4, r4, MCCR1_MEMGO@l + or r20, r20, r4 +#endif + +/* + * set the Memory Configuration Reg. 1 + */ + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r20, r0, r2 /* write data to CONFIG_DATA */ +/* + * set the Memory Configuration Reg. 3 + */ + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MCCR3 /* register number 0xf8 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r21, r0, r2 /* write data to CONFIG_DATA */ +/* + * set the Memory Configuration Reg. 4 + */ + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MCCR4 /* register number 0xfc */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r22, r0, r2 /* write data to CONFIG_DATA */ +/* + * set the memory boundary registers for bank 0-3 + */ + li r20, 0 + li r23, 0 + li r24, 0 + subi r21, r16, 1 /* calculate end address bank0 */ + li r22, (MBER_BANK0) + + cmpi 0, 0, r17, 0 /* bank1 present ? */ + beq nobank1 + + rlwinm r3, r16, 8, 16, 23 /* calculate start address of bank1 */ + or r20, r20, r3 + add r16, r16, r17 /* add to total memory size */ + subi r3, r16, 1 /* calculate end address of bank1 */ + rlwinm r3, r3, 8, 16, 23 + or r21, r21, r3 + ori r22, r22, (MBER_BANK1) /* enable bank1 */ + b bank2 + +nobank1: + ori r23, r23, 0x0300 /* set bank1 start to unused area */ + ori r24, r24, 0x0300 /* set bank1 end to unused area */ + +bank2: + cmpi 0, 0, r18, 0 /* bank2 present ? */ + beq nobank2 + + andi. r3, r16, 0x00ff /* calculate start address of bank2 */ + andi. r4, r16, 0x0300 + rlwinm r3, r3, 16, 8, 15 + or r20, r20, r3 + rlwinm r3, r4, 8, 8, 15 + or r23, r23, r3 + add r16, r16, r18 /* add to total memory size */ + subi r3, r16, 1 /* calculate end address of bank2 */ + andi. r4, r3, 0x0300 + andi. r3, r3, 0x00ff + rlwinm r3, r3, 16, 8, 15 + or r21, r21, r3 + rlwinm r3, r4, 8, 8, 15 + or r24, r24, r3 + ori r22, r22, (MBER_BANK2) /* enable bank2 */ + b bank3 + +nobank2: + lis r3, 0x0003 + or r23, r23, r3 /* set bank2 start to unused area */ + or r24, r24, r3 /* set bank2 end to unused area */ + +bank3: + cmpi 0, 0, r19, 0 /* bank3 present ? */ + beq nobank3 + + andi. r3, r16, 0x00ff /* calculate start address of bank3 */ + andi. r4, r16, 0x0300 + rlwinm r3, r3, 24, 0, 7 + or r20, r20, r3 + rlwinm r3, r4, 16, 0, 7 + or r23, r23, r3 + add r16, r16, r19 /* add to total memory size */ + subi r3, r16, 1 /* calculate end address of bank3 */ + andi. r4, r3, 0x0300 + andi. r3, r3, 0x00ff + rlwinm r3, r3, 24, 0, 7 + or r21, r21, r3 + rlwinm r3, r4, 16, 0, 7 + or r24, r24, r3 + ori r22, r22, (MBER_BANK3) /* enable bank3 */ + b writebound + +nobank3: + lis r3, 0x0300 + or r23, r23, r3 /* set bank3 start to unused area */ + or r24, r24, r3 /* set bank3 end to unused area */ + +writebound: + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MSAR1 /* register number 0x80 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r20, r0, r2 /* write data to CONFIG_DATA */ + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MEAR1 /* register number 0x90 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r21, r0, r2 /* write data to CONFIG_DATA */ + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_EMSAR1 /* register number 0x88 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r23, r0, r2 /* write data to CONFIG_DATA */ + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_EMEAR1 /* register number 0x98 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r24, r0, r2 /* write data to CONFIG_DATA */ + +/* + * set boundaries of unused banks to unused address space + */ + lis r4, 0x0303 + ori r4, r4, 0x0303 /* bank 4-7 start and end adresses */ + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_EMSAR2 /* register number 0x8C */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r4, r0, r2 /* write data to CONFIG_DATA */ + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_EMEAR2 /* register number 0x9C */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stwbrx r4, r0, r2 /* write data to CONFIG_DATA */ + +/* + * set the Memory Configuration Reg. 2 + */ + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MCCR2 /* register number 0xf4 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + + li r3, 0x000c /* get refresh from spd for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, -1 /* error ? */ + bne common1 + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x20 + b toggleError /* fail - loop forever */ + +common1: + andi. r15, r3, 0x007f /* mask selfrefresh bit */ + li r3, 0x010c /* get refresh from spd for bank2/3 */ + bl spdRead + + cmpi 0, 0, r3, -1 /* error ? */ + beq common2 + andi. r3, r3, 0x007f /* mask selfrefresh bit */ + cmp 0, 0, r3, r15 /* find the lower */ + blt common3 + +common2: + mr r3, r15 + +common3: + li r4, 0x1010 /* refesh cycle 1028 clocks */ + /* left shifted 2 */ + cmpli 0, 0, r3, 0x0000 /* 15.6 us ? */ + beq writeRefresh + + li r4, 0x0808 /* refesh cycle 514 clocks */ + /* left shifted 2 */ + cmpli 0, 0, r3, 0x0002 /* 7.8 us ? */ + beq writeRefresh + + li r4, 0x2020 /* refesh cycle 2056 clocks */ + /* left shifted 2 */ + cmpli 0, 0, r3, 0x0003 /* 31.3 us ? */ + beq writeRefresh + + li r4, 0x4040 /* refesh cycle 4112 clocks */ + /* left shifted 2 */ + cmpli 0, 0, r3, 0x0004 /* 62.5 us ? */ + beq writeRefresh + + li r4, 0 + ori r4, r4, 0x8080 /* refesh cycle 8224 clocks */ + /* left shifted 2 */ + cmpli 0, 0, r3, 0x0005 /* 125 us ? */ + beq writeRefresh + + li r6, 0xe0 /* error codes in r6 and r7 */ + li r7, 0x21 + b toggleError /* fail - loop forever */ + +writeRefresh: + stwbrx r4, r0, r2 /* write data to CONFIG_DATA */ + +/* + * DRAM BANKS SHOULD BE ENABLED + */ + addi r3, r13, (Mactivate-MessageBlock) + bl Printf + mr r3, r16 + bl OutDec + addi r3, r13, (Mmbyte-MessageBlock) + bl Printf + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MBER /* register number 0xa0 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + stb r22, 0(r2) /* write data to CONFIG_DATA */ + li r8, 0x63 /* PGMAX = 99 */ + stb r8, 3(r2) /* write data to CONFIG_DATA */ + +/* + * DRAM SHOULD NOW BE CONFIGURED AND ENABLED + * MUST WAIT 200us BEFORE ACCESSING + */ + li r0, 0x7800 + mtctr r0 + +wait200us: + bdnz wait200us + + lis r3, MPC106_REG@h /* start building new reg number */ + ori r3, r3, MPC106_MCCR1 /* register number 0xf0 */ + stwbrx r3, r0, r1 /* write this value to CONFIG_ADDR */ + eieio /* make sure mem. access is complete */ + + lwbrx r4, r0, r2 /* load r4 from CONFIG_DATA */ + + lis r0, MCCR1_MEMGO@h /* MEMGO=1 */ + ori r0, r0, MCCR1_MEMGO@l + or r4, r4, r0 /* set the MEMGO bit */ + stwbrx r4, r0, r2 /* write mdfd data to CONFIG_DATA */ + + li r0, 0x7000 + mtctr r0 + +wait8ref: + bdnz wait8ref + + addi r3, r13, (Mok-MessageBlock) + bl Printf + + mtlr r25 + blr + +/* + * Infinite loop called in case of an error during RAM initialisation. + * error codes in r6 and r7. + */ +toggleError: + li r0, 0 + lis r9, 127 + ori r9, r9, 65535 +toggleError1: + addic r0, r0, 1 + cmpw cr1, r0, r9 + ble cr1, toggleError1 + li r0, 0 + lis r9, 127 + ori r9, r9, 65535 +toggleError2: + addic r0, r0, 1 + cmpw cr1, r0, r9 + ble cr1, toggleError2 + b toggleError + + +/****************************************************************************** + * This function performs a basic initialisation of the superio chip + * to enable basic console output and SPD access during RAM initialisation. + * + * Upon completion, SIO resource registers are mapped as follows: + * Resource Enabled Address + * UART1 Yes 3F8-3FF COM1 + * UART2 Yes 2F8-2FF COM2 + * GPIO Yes 220-227 + */ +.set SIO_LUNINDEX, 0x07 /* SIO LUN index register */ +.set SIO_CNFG1, 0x21 /* SIO configuration #1 register */ +.set SIO_PCSCI, 0x23 /* SIO PCS configuration index reg */ +.set SIO_PCSCD, 0x24 /* SIO PCS configuration data reg */ +.set SIO_ACTIVATE, 0x30 /* SIO activate register */ +.set SIO_IOBASEHI, 0x60 /* SIO I/O port base address, 15:8 */ +.set SIO_IOBASELO, 0x61 /* SIO I/O port base address, 7:0 */ +.set SIO_LUNENABLE, 0x01 /* SIO LUN enable */ + +.sioInit: + mfspr r7, 8 /* save link register */ + +.sioInit_87308: + +/* + * Get base addr of ISA I/O space + */ + lis r6, CFG_ISA_IO@h + ori r6, r6, CFG_ISA_IO@l + +/* + * Set offset to base address for config registers. + */ +#if defined(CFG_NS87308_BADDR_0x) + addi r4, r0, 0x0279 +#elif defined(CFG_NS87308_BADDR_10) + addi r4, r0, 0x015C +#elif defined(CFG_NS87308_BADDR_11) + addi r4, r0, 0x002E +#endif + add r6, r6, r4 /* add offset to base */ + or r3, r6, r6 /* make a copy */ + +/* + * PMC (LUN 8) + */ + addi r4, r0, SIO_LUNINDEX /* select PMC LUN */ + addi r5, r0, 0x8 + bl .sio_bw + addi r4, r0, SIO_IOBASEHI /* initialize PMC address to 0x460 */ + addi r5, r0, 0x04 + bl .sio_bw + addi r4, r0, SIO_IOBASELO + addi r5, r0, 0x60 + bl .sio_bw + addi r4, r0, SIO_ACTIVATE /* enable PMC */ + addi r5, r0, SIO_LUNENABLE + bl .sio_bw + + lis r8, CFG_ISA_IO@h + ori r8, r8, 0x0460 + li r9, 0x03 + stb r9, 0(r8) /* select PMC2 register */ + eieio + li r9, 0x00 + stb r9, 1(r8) /* SuperI/O clock src: 24MHz via X1 */ + eieio + +/* + * map UART1 (LUN 6) or UART2 (LUN 5) to COM1 (0x3F8) + */ + addi r4, r0, SIO_LUNINDEX /* select COM1 LUN */ + addi r5, r0, 0x6 + bl .sio_bw + + addi r4, r0, SIO_IOBASEHI /* initialize COM1 address to 0x3F8 */ + addi r5, r0, 0x03 + bl .sio_bw + + addi r4, r0, SIO_IOBASELO + addi r5, r0, 0xF8 + bl .sio_bw + + addi r4, r0, SIO_ACTIVATE /* enable COM1 */ + addi r5, r0, SIO_LUNENABLE + bl .sio_bw + +/* + * Init COM1 for polled output + */ + lis r8, CFG_ISA_IO@h + ori r8, r8, 0x03f8 + li r9, 0x00 + stb r9, 1(r8) /* int disabled */ + eieio + li r9, 0x00 + stb r9, 4(r8) /* modem ctrl */ + eieio + li r9, 0x80 + stb r9, 3(r8) /* link ctrl, bank select */ + eieio + li r9, 115200/CONFIG_BAUDRATE + stb r9, 0(r8) /* baud rate (LSB)*/ + eieio + rotrwi r9, r9, 8 + stb r9, 1(r8) /* baud rate (MSB) */ + eieio + li r9, 0x03 + stb r9, 3(r8) /* 8 data bits, 1 stop bit, */ + /* no parity */ + eieio + li r9, 0x0b + stb r9, 4(r8) /* enable the receiver and transmitter */ + eieio + +waitEmpty: + lbz r9, 5(r8) /* transmit empty */ + andi. r9, r9, 0x40 + beq waitEmpty + li r9, 0x47 + stb r9, 3(r8) /* send break, 8 data bits, */ + /* 2 stop bits, no parity */ + eieio + + lis r0, 0x0001 + mtctr r0 + +waitCOM1: + lwz r0, 5(r8) /* load from port for delay */ + bdnz waitCOM1 + +waitEmpty1: + lbz r9, 5(r8) /* transmit empty */ + andi. r9, r9, 0x40 + beq waitEmpty1 + li r9, 0x07 + stb r9, 3(r8) /* 8 data bits, 2 stop bits, */ + /* no parity */ + eieio + +/* + * GPIO (LUN 7) + */ + addi r4, r0, SIO_LUNINDEX /* select GPIO LUN */ + addi r5, r0, 0x7 + bl .sio_bw + + addi r4, r0, SIO_IOBASEHI /* initialize GPIO address to 0x220 */ + addi r5, r0, 0x02 + bl .sio_bw + + addi r4, r0, SIO_IOBASELO + addi r5, r0, 0x20 + bl .sio_bw + + addi r4, r0, SIO_ACTIVATE /* enable GPIO */ + addi r5, r0, SIO_LUNENABLE + bl .sio_bw + +.sioInit_done: + +/* + * Get base addr of ISA I/O space + */ + lis r3, CFG_ISA_IO@h + ori r3, r3, CFG_ISA_IO@l + + addi r3, r3, 0x015C /* adjust to superI/O 87308 base */ + or r6, r3, r3 /* make a copy */ +/* + * CS0 + */ + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x00 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x00 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x01 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x76 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x02 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x40 + bl .sio_bw +/* + * CS1 + */ + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x05 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x00 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x05 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x70 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x06 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x1C + bl .sio_bw +/* + * CS2 + */ + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x08 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x00 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x09 + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x71 + bl .sio_bw + addi r4, r0, SIO_PCSCI /* select PCSCIR */ + addi r5, r0, 0x0A + bl .sio_bw + addi r4, r0, SIO_PCSCD /* select PCSCDR */ + addi r5, r0, 0x1C + bl .sio_bw + + mtspr 8, r7 /* restore link register */ + bclr 20, 0 /* return to caller */ + +/* + * this function writes a register to the SIO chip + */ +.sio_bw: + stb r4, 0(r3) /* write index register with register offset */ + eieio + sync + stb r5, 1(r3) /* 1st write */ + eieio + sync + stb r5, 1(r3) /* 2nd write */ + eieio + sync + bclr 20, 0 /* return to caller */ +/* + * this function reads a register from the SIO chip + */ +.sio_br: + stb r4, 0(r3) /* write index register with register offset */ + eieio + sync + lbz r3, 1(r3) /* retrieve specified reg offset contents */ + eieio + sync + bclr 20, 0 /* return to caller */ + +/* + * Print a message to COM1 in polling mode + * r10=COM1 port, r3=(char*)string + */ +.globl Printf +Printf: + lis r10, CFG_ISA_IO@h /* COM1 port */ + ori r10, r10, 0x03f8 + +WaitChr: + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, WaitChr /* wait till empty */ + lbzx r0, r0, r3 /* get char */ + stb r0, 0(r10) /* write to transmit reg */ + eieio + addi r3, r3, 1 /* next char */ + lbzx r0, r0, r3 /* get char */ + cmpwi cr1, r0, 0 /* end of string ? */ + bne cr1, WaitChr + blr + +/* + * Print 8/4/2 digits hex value to COM1 in polling mode + * r10=COM1 port, r3=val + */ +OutHex2: + li r9, 4 /* shift reg for 2 digits */ + b OHstart +OutHex4: + li r9, 12 /* shift reg for 4 digits */ + b OHstart + .globl OutHex +OutHex: + li r9, 28 /* shift reg for 8 digits */ +OHstart: + lis r10, CFG_ISA_IO@h /* COM1 port */ + ori r10, r10, 0x03f8 +OutDig: + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDig + sraw r0, r3, r9 + clrlwi r0, r0, 28 + cmpwi cr1, r0, 9 + ble cr1, digIsNum + addic r0, r0, 55 + b nextDig +digIsNum: + addic r0, r0, 48 +nextDig: + stb r0, 0(r10) /* write to transmit reg */ + eieio + addic. r9, r9, -4 + bge OutDig + blr +/* + * Print 3 digits hdec value to COM1 in polling mode + * r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0, r6=scratch + */ +.globl OutDec +OutDec: + li r6, 10 + divwu r0, r3, r6 /* r0 = r3 / 10, r9 = r3 mod 10 */ + mullw r10, r0, r6 + subf r9, r10, r3 + + mr r3, r0 + divwu r0, r3, r6 /* r0 = r3 / 10, r8 = r3 mod 10 */ + mullw r10, r0, r6 + subf r8, r10, r3 + + mr r3, r0 + divwu r0, r3, r6 /* r0 = r3 / 10, r7 = r3 mod 10 */ + mullw r10, r0, r6 + subf r7, r10, r3 + + lis r10, CFG_ISA_IO@h /* COM1 port */ + ori r10, r10, 0x03f8 + + or. r7, r7, r7 + bne noblank1 + li r3, 0x20 + b OutDec4 + +noblank1: + addi r3, r7, 48 /* convert to ASCII */ + +OutDec4: + lbz r0, 0(r13) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec4 + stb r3, 0(r10) /* x00 to transmit */ + eieio + + or. r7, r7, r8 + beq OutDec5 + + addi r3, r8, 48 /* convert to ASCII */ +OutDec5: + lbz r0, 0(r13) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec5 + stb r3, 0(r10) /* x0 to transmit */ + eieio + + addi r3, r9, 48 /* convert to ASCII */ +OutDec6: + lbz r0, 0(r13) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec6 + stb r3, 0(r10) /* x to transmit */ + eieio + blr +/* + * Print a char to COM1 in polling mode + * r10=COM1 port, r3=char + */ +.globl OutChr +OutChr: + lis r10, CFG_ISA_IO@h /* COM1 port */ + ori r10, r10, 0x03f8 + +OutChr1: + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutChr1 /* wait till empty */ + stb r3, 0(r10) /* write to transmit reg */ + eieio + blr +/* + * Input: r3 adr to read + * Output: r3 val or -1 for error + */ +spdRead: + mfspr r26, 8 /* save link register */ + + lis r30, CFG_ISA_IO@h + ori r30, r30, 0x220 /* GPIO Port 1 */ + li r7, 0x00 + li r8, 0x100 + and. r5, r3, r8 + beq spdbank0 + li r12, 0x08 + li r4, 0x10 + li r6, 0x18 + b spdRead1 + +spdbank0: + li r12, 0x20 /* set I2C data */ + li r4, 0x40 /* set I2C clock */ + li r6, 0x60 /* set I2C clock and data */ + +spdRead1: + li r8, 0x80 + + bl spdStart /* access I2C bus as master */ + li r10, 0xa0 /* write to SPD */ + bl spdWriteByte + bl spdReadAck /* ACK returns in r10 */ + cmpw cr0, r10, r7 + bne AckErr /* r10 must be 0, if ACK received */ + mr r10, r3 /* adr to read */ + bl spdWriteByte + bl spdReadAck + cmpw cr0, r10, r7 + bne AckErr + bl spdStart + li r10, 0xa1 /* read from SPD */ + bl spdWriteByte + bl spdReadAck + cmpw cr0, r10, r7 + bne AckErr + bl spdReadByte /* return val in r10 */ + bl spdWriteAck + bl spdStop /* release I2C bus */ + mr r3, r10 + mtspr 8, r26 /* restore link register */ + blr +/* + * ACK error occurred + */ +AckErr: + bl spdStop + orc r3, r0, r0 /* return -1 */ + mtspr 8, r26 /* restore link register */ + blr + +/* + * Routines to read from RAM spd. + * r30 - GPIO Port1 address in all cases. + * r4 - clock mask for SPD + * r6 - port mask for SPD + * r12 - data mask for SPD + */ +waitSpd: + li r0, 0x1000 + mtctr r0 +wSpd: + bdnz wSpd + bclr 20, 0 /* return to caller */ + +/* + * establish START condition on I2C bus + */ +spdStart: + mfspr r27, 8 /* save link register */ + stb r6, 0(r30) /* set SDA and SCL */ + eieio + stb r6, 1(r30) /* switch GPIO to output */ + eieio + bl waitSpd + stb r4, 0(r30) /* reset SDA */ + eieio + bl waitSpd + stb r7, 0(r30) /* reset SCL */ + eieio + bl waitSpd + mtspr 8, r27 + bclr 20, 0 /* return to caller */ + +/* + * establish STOP condition on I2C bus + */ +spdStop: + mfspr r27, 8 /* save link register */ + stb r7, 0(r30) /* reset SCL and SDA */ + eieio + stb r6, 1(r30) /* switch GPIO to output */ + eieio + bl waitSpd + stb r4, 0(r30) /* set SCL */ + eieio + bl waitSpd + stb r6, 0(r30) /* set SDA and SCL */ + eieio + bl waitSpd + stb r7, 1(r30) /* switch GPIO to input */ + eieio + mtspr 8, r27 + bclr 20, 0 /* return to caller */ + +spdReadByte: + mfspr r27, 8 + stb r4, 1(r30) /* set GPIO for SCL output */ + eieio + li r9, 0x08 + li r10, 0x00 +loopRB: + stb r7, 0(r30) /* reset SDA and SCL */ + eieio + bl waitSpd + stb r4, 0(r30) /* set SCL */ + eieio + bl waitSpd + lbz r5, 0(r30) /* read from GPIO Port1 */ + rlwinm r10, r10, 1, 0, 31 + and. r5, r5, r12 + beq clearBit + ori r10, r10, 0x01 /* append _1_ */ +clearBit: + stb r7, 0(r30) /* reset SCL */ + eieio + bl waitSpd + addic. r9, r9, -1 + bne loopRB + mtspr 8, r27 + bclr 20, 0 /* return (r10) to caller */ + +/* + * spdWriteByte writes bits 24 - 31 of r10 to I2C. + * r8 contains bit mask 0x80 + */ +spdWriteByte: + mfspr r27, 8 /* save link register */ + li r9, 0x08 /* write octet */ + and. r5, r10, r8 + bne sWB1 + stb r7, 0(r30) /* set SDA to _0_ */ + eieio + b sWB2 +sWB1: + stb r12, 0(r30) /* set SDA to _1_ */ + eieio +sWB2: + stb r6, 1(r30) /* set GPIO to output */ + eieio +loopWB: + and. r5, r10, r8 + bne sWB3 + stb r7, 0(r30) /* set SDA to _0_ */ + eieio + b sWB4 +sWB3: + stb r12, 0(r30) /* set SDA to _1_ */ + eieio +sWB4: + bl waitSpd + and. r5, r10, r8 + bne sWB5 + stb r4, 0(r30) /* set SDA to _0_ and SCL */ + eieio + b sWB6 +sWB5: + stb r6, 0(r30) /* set SDA to _1_ and SCL */ + eieio +sWB6: + bl waitSpd + and. r5, r10, r8 + bne sWB7 + stb r7, 0(r30) /* set SDA to _0_ and reset SCL */ + eieio + b sWB8 +sWB7: + stb r12, 0(r30) /* set SDA to _1_ and reset SCL */ + eieio +sWB8: + bl waitSpd + rlwinm r10, r10, 1, 0, 31 /* next bit */ + addic. r9, r9, -1 + bne loopWB + mtspr 8, r27 + bclr 20, 0 /* return to caller */ + +/* + * Read ACK from SPD, return value in r10 + */ +spdReadAck: + mfspr r27, 8 /* save link register */ + stb r4, 1(r30) /* set GPIO to output */ + eieio + stb r7, 0(r30) /* reset SDA and SCL */ + eieio + bl waitSpd + stb r4, 0(r30) /* set SCL */ + eieio + bl waitSpd + lbz r10, 0(r30) /* read GPIO Port 1 and mask SDA */ + and r10, r10, r12 + bl waitSpd + stb r7, 0(r30) /* reset SDA and SCL */ + eieio + bl waitSpd + mtspr 8, r27 + bclr 20, 0 /* return (r10) to caller */ + +spdWriteAck: + mfspr r27, 8 + stb r12, 0(r30) /* set SCL */ + eieio + stb r6, 1(r30) /* set GPIO to output */ + eieio + bl waitSpd + stb r6, 0(r30) /* SDA and SCL */ + eieio + bl waitSpd + stb r12, 0(r30) /* reset SCL */ + eieio + bl waitSpd + mtspr 8, r27 + bclr 20, 0 /* return to caller */ + +get_lnk_reg: + mflr r3 /* return link reg */ + blr + +/* + * Messages for console output + */ +.globl MessageBlock +MessageBlock: +Mok: + .ascii "OK\015\012\000" +Mfail: + .ascii "FAILED\015\012\000" +Mna: + .ascii "NA\015\012\000" +MinitLogo: + .ascii "\015\012*** ELTEC Elektronik, Mainz ***\015\012" + .ascii "\015\012Initialising RAM\015\012\000" +Mspd01: + .ascii " Reading SPD of bank0/1 ..... \000" +Mspd23: + .ascii " Reading SPD of bank2/3 ..... \000" +MfpmRam: + .ascii " RAM-Type: FPM \015\012\000" +MedoRam: + .ascii " RAM-Type: EDO \015\012\000" +MsdRam: + .ascii " RAM-Type: SDRAM \015\012\000" +Mactivate: + .ascii " Activating \000" +Mmbyte: + .ascii " MB .......... \000" + .align 4 + + + + + + + + + + + + diff --git a/board/eltec/bab7xx/el_srom.c b/board/eltec/bab7xx/el_srom.c new file mode 100644 index 0000000..56abdc7 --- /dev/null +++ b/board/eltec/bab7xx/el_srom.c @@ -0,0 +1,292 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include "srom.h" + +/*----------------------------------------------------------------------------*/ +/* + * START sequence + * _ _________ + * SCLK _> \____ + * _ ____ + * SDIO _> \_________ + * : : : + */ +static void eepStart (void) +{ + out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */ + out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */ + udelay(10); + out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */ + udelay(10); + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */ + udelay(10); +} + +/*----------------------------------------------------------------------------*/ +/* + * STOP sequence + * _______ + * SCLK _____/ + * _ ___ + * SDIO _>_______/ + * : : : + */ +static void eepStop (void) +{ + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = low */ + out8(I2C_BUS_DIR, 0x60); /* set output direction for SCLK/SDIO */ + udelay(10); + out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = low */ + udelay(10); + out8(I2C_BUS_DAT, 0x60); /* SCLK = high SDIO = high */ + udelay(10); + out8(I2C_BUS_DIR, 0x00); /* reset to input direction */ +} + +/*----------------------------------------------------------------------------*/ +/* + * Read one byte from EEPROM + * ___ ___ ___ ___ ___ ___ ___ ___ + * SCLK ___/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \ + * _________________________________________________________________ + * SDIO > ^ ^ ^ ^ ^ ^ ^ ^ + * : : : : : : : : : : : : : : : : : + */ +static unsigned char eepReadByte (void) +{ + register unsigned char buf = 0x00; + register int i; + + out8(I2C_BUS_DIR, 0x40); + + for (i = 0; i < 8; i++) + { + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ + udelay(10); + out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */ + udelay(15); + buf <<= 1; + buf = (in8(I2C_BUS_DAT) & 0x20) ? (buf | 0x01) : (buf & 0xFE); + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ + udelay(10); + } + return(buf); +} + +/*----------------------------------------------------------------------------*/ +/* + * Write one byte to EEPROM + * ___ ___ ___ ___ ___ ___ ___ ___ + * SCLK __/ \___/ \___/ \___/ \___/ \___/ \___/ \___/ \__ + * _______ _______ _______ _______ _______ _______ _______ ________ + * SDIO X_______X_______X_______X_______X_______X_______X_______X________ + * : 7 : 6 : 5 : 4 : 3 : 2 : 1 : 0 + */ +static void eepWriteByte (register unsigned char buf) +{ + register int i; + + (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = data */ + out8(I2C_BUS_DIR, 0x60); + + for (i = 7; i >= 0; i--) + { + (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */ + udelay(10); + (buf & 0x80) ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK=high SDIO=data */ + udelay(15); + (buf & 0x80) ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK=low SDIO=data */ + udelay(10); + buf <<= 1; + } +} + +/*----------------------------------------------------------------------------*/ +/* + * Read data acknowledge of EEPROM + * _______ + * SCLK ____/ \___ + * _______________ + * SDIO > + * : : ^ : + */ +static int eepReadAck (void) +{ + int retval; + + out8(I2C_BUS_DIR, 0x40); + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ + udelay(10); + out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = high */ + udelay(10); + retval = (in8(I2C_BUS_DAT) & 0x20) ? ERROR : 0; + udelay(10); + out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = high */ + udelay(10); + + return(retval); +} + +/*----------------------------------------------------------------------------*/ +/* + * Write data acknowledge to EEPROM + * _______ + * SCLK ____/ \___ + * + * SDIO >_______________ + * : : : + */ +static void eepWriteAck (unsigned char ack) +{ + ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */ + out8(I2C_BUS_DIR, 0x60); + udelay(10); + ack ? out8(I2C_BUS_DAT, 0x60) : out8(I2C_BUS_DAT, 0x40); /* SCLK = high SDIO = ack */ + udelay(15); + ack ? out8(I2C_BUS_DAT, 0x20) : out8(I2C_BUS_DAT, 0x00); /* SCLK = low SDIO = ack */ + udelay(10); +} + +/*----------------------------------------------------------------------------*/ +/* + * Read bytes from EEPROM + */ +int el_srom_load (addr, buf, cnt, device, block) +unsigned char addr; +unsigned char *buf; +int cnt; +unsigned char device; +unsigned char block; +{ + register int i; + + for (i=0;i<cnt;i++) + { + eepStart(); + eepWriteByte(0xA0 | device | block); + if (eepReadAck() == ERROR) + { + eepStop(); + return(ERROR); + } + eepWriteByte(addr++); + if (eepReadAck() == ERROR) + { + eepStop(); + return(ERROR); + } + eepStart(); + + eepWriteByte(0xA1 | device | block); + if (eepReadAck() == ERROR) + { + eepStop(); + return(ERROR); + } + + *buf++ = eepReadByte(); + eepWriteAck(1); + eepStop(); + + if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */ + { + if (block == FIRST_BLOCK) + block = SECOND_BLOCK; + else + return(ERROR); + } + } + return(cnt); +} + +/*----------------------------------------------------------------------------*/ +/* + * + * Write bytes to EEPROM + * + */ +int el_srom_store (addr, buf, cnt, device, block) +unsigned char addr, *buf, device, block; +int cnt; +{ + register int i, retVal; + + for (i=0;i<cnt;i++) + { + retVal = ERROR; + do + { + eepStart(); + eepWriteByte(0xA0 | device | block); + if ((retVal = eepReadAck()) == ERROR) + eepStop(); + } while (retVal == ERROR); + + eepWriteByte(addr++); + if (eepReadAck() == ERROR) return(ERROR); + + if ((addr == 0) && (i != (cnt-1))) /* is it the same block ? */ + { + if (block == FIRST_BLOCK) + block = SECOND_BLOCK; + else + return(ERROR); + } + + eepWriteByte(*buf++); + if (eepReadAck() == ERROR) + return(ERROR); + + eepStop(); + } + return(cnt); +} + +/*----------------------------------------------------------------------------*/ +/* + * calculate checksum for ELTEC revision srom + */ +unsigned long el_srom_checksum (ptr, size) +register unsigned char *ptr; +unsigned long size; +{ + u_long f, accu = 0; + u_int i; + u_char byte; + + for (; size; size--) + { + byte = *ptr++; + for (i = 8; i; i--) + { + f = ((byte & 1) ^ (accu & 1)) ? 0x84083001 : 0; + accu >>= 1; accu ^= f; + byte >>= 1; + } + } + return(accu); +} + +/*----------------------------------------------------------------------------*/ diff --git a/board/eltec/bab7xx/u-boot.lds b/board/eltec/bab7xx/u-boot.lds new file mode 100644 index 0000000..7b10c0d --- /dev/null +++ b/board/eltec/bab7xx/u-boot.lds @@ -0,0 +1,129 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * u-boot.lds - linker script for U-Boot on the Galileo Eval Board. + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/74xx_7xx/start.o (.text) + +/* store the environment in a seperate sector in the boot flash */ +/* . = env_offset; */ +/* common/environment.o(.text) */ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/eltec/elppc/asm_init.S b/board/eltec/elppc/asm_init.S new file mode 100644 index 0000000..a5605b7 --- /dev/null +++ b/board/eltec/elppc/asm_init.S @@ -0,0 +1,877 @@ +/* + * (C) Copyright 2001 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.de> + * + * ELTEC ELPPC RAM initialization + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <version.h> +#include <mpc106.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +.globl board_asm_init +board_asm_init: + +/* + * setup pointer to message block + */ + mflr r13 /* save away link register */ + bl get_lnk_reg /* r3=addr of next instruction */ + subi r4, r3, 8 /* r4=board_asm_init addr */ + addi r29, r4, (MessageBlock-board_asm_init) + +/* + * dcache_disable + */ + mfspr r3, HID0 + li r4, HID0_DCE + andc r3, r3, r4 + mr r2, r3 + ori r3, r3, HID0_DCI + sync + mtspr HID0, r3 + mtspr HID0, r2 + isync + sync +/* + * icache_disable + */ + mfspr r3, HID0 + li r4, 0 + ori r4, r4, HID0_ICE + andc r3, r3, r4 + sync + mtspr HID0, r3 +/* + * invalidate caches + */ + ori r3, r3, (HID0_ICE | HID0_ICFI | HID0_DCI | HID0_DCE) + or r4, r4, r3 + isync + mtspr HID0, r4 + andc r4, r4, r3 + isync + mtspr HID0, r4 + isync +/* + * icache_enable + */ + mfspr r3, HID0 + ori r3, r3, (HID0_ICE | HID0_ICFI) + sync + mtspr HID0, r3 + + +/* + * setup memory controller + */ + lis r1, MPC106_REG_ADDR@h + ori r1, r1, MPC106_REG_ADDR@l + lis r2, MPC106_REG_DATA@h + ori r2, r2, MPC106_REG_DATA@l + + /* Configure PICR1 */ + lis r3, MPC106_REG@h + ori r3, r3, PCI_PICR1 + stwbrx r3, 0, r1 + addis r3, r0, 0xFF14 + ori r3, r3, 0x1CC8 + eieio + stwbrx r3, 0, r2 + + /* Configure PICR2 */ + lis r3, MPC106_REG@h + ori r3, r3, PCI_PICR2 + stwbrx r3, 0, r1 + addis r3, r0, 0x0000 + ori r3, r3, 0x0000 + eieio + stwbrx r3, 0, r2 + + /* Configure EUMBAR */ + lis r3, MPC106_REG@h + ori r3, r3, 0x0078 /* offest of EUMBAR in PCI config space */ + stwbrx r3, 0, r1 + lis r3, MPC107_EUMB_ADDR@h + eieio + stwbrx r3, 0, r2 + + /* Configure Address Map B Option Reg */ + lis r3, MPC106_REG@h + ori r3, r3, 0x00e0 /* offest of AMBOR in PCI config space */ + stwbrx r3, 0, r1 + lis r3, 0 + eieio + stwbrx r3, 0, r2 + + /* Configure I2C Controller */ + lis r14, MPC107_I2C_ADDR@h /* base of I2C controller */ + ori r14, r14, MPC107_I2C_ADDR@l + lis r3, 0x2b10 /* I2C clock = 100MHz/1024 */ + stw r3, 4(r14) + li r3, 0 /* clear arbitration */ + eieio + stw r3, 12(r14) + + /* Configure MCCR1 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR1 + stwbrx r3, 0, r1 + addis r3, r0, 0x0660 /* don't set MEMGO now ! */ + ori r3, r3, 0x0000 + eieio + stwbrx r3, 0, r2 + + /* Configure MCCR2 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR2 + stwbrx r3, 0, r1 + addis r3, r0, 0x0400 + ori r3, r3, 0x1800 + eieio + stwbrx r3, 0, r2 + + + /* Configure MCCR3 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR3 + stwbrx r3, 0, r1 + addis r3, r0, 0x0230 + ori r3, r3, 0x0000 + eieio + stwbrx r3, 0, r2 + + /* Configure MCCR4 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR4 + stwbrx r3, 0, r1 + addis r3, r0, 0x2532 + ori r3, r3, 0x2220 + eieio + stwbrx r3, 0, r2 + +/* + * configure memory interface (MICRs) + */ + addis r3, r0, 0x8000 /* ADDR_80 */ + ori r3, r3, 0x0080 /* SMEMADD1 */ + stwbrx r3, 0, r1 + addis r3, r0, 0xFFFF + ori r3, r3, 0x4000 + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_84 */ + ori r3, r3, 0x0084 /* SMEMADD2 */ + stwbrx r3, 0, r1 + addis r3, r0, 0xFFFF + ori r3, r3, 0xFFFF + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_88 */ + ori r3, r3, 0x0088 /* EXTSMEM1 */ + stwbrx r3, 0, r1 + addis r3, r0, 0x0303 + ori r3, r3, 0x0000 + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_8C */ + ori r3, r3, 0x008c /* EXTSMEM2 */ + stwbrx r3, 0, r1 + addis r3, r0, 0x0303 + ori r3, r3, 0x0303 + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_90 */ + ori r3, r3, 0x0090 /* EMEMADD1 */ + stwbrx r3, 0, r1 + addis r3, r0, 0xFFFF + ori r3, r3, 0x7F3F + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_94 */ + ori r3, r3, 0x0094 /* EMEMADD2 */ + stwbrx r3, 0, r1 + addis r3, r0, 0xFFFF + ori r3, r3, 0xFFFF + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_98 */ + ori r3, r3, 0x0098 /* EXTEMEM1 */ + stwbrx r3, 0, r1 + addis r3, r0, 0x0303 + ori r3, r3, 0x0000 + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_9C */ + ori r3, r3, 0x009c /* EXTEMEM2 */ + stwbrx r3, 0, r1 + addis r3, r0, 0x0303 + ori r3, r3, 0x0303 + eieio + stwbrx r3, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_A0 */ + ori r3, r3, 0x00a0 /* MEMBNKEN */ + stwbrx r3, 0, r1 + addis r3, r0, 0x0000 + ori r3, r3, 0x0003 + eieio + stwbrx r3, 0, r2 + +/* + * must wait at least 100us after HRESET to issue a MEMGO + */ + lis r0, 1 + mtctr r0 +memStartWait: + bdnz memStartWait + +/* + * enable RAM Operations through MCCR1 (MEMGO) + */ + lis r3, 0x8000 + ori r3, r3, 0x00f0 + stwbrx r3, r0, r1 + sync + lwbrx r3, 0, r2 + lis r0, 0x0008 + or r3, r0, r3 + stwbrx r3, 0, r2 + sync + +/* + * set LEDs first time + */ + li r3, 0x1 + lis r30, CFG_USR_LED_BASE@h + stb r3, 2(r30) + sync + +/* + * init COM1 for polled output + */ + lis r8, CFG_NS16550_COM1@h /* COM1 base address*/ + ori r8, r8, CFG_NS16550_COM1@l + li r9, 0x00 + stb r9, 1(r8) /* int disabled */ + eieio + li r9, 0x00 + stb r9, 4(r8) /* modem ctrl */ + eieio + li r9, 0x80 + stb r9, 3(r8) /* link ctrl */ + eieio + li r9, (CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE) + stb r9, 0(r8) /* baud rate (LSB)*/ + eieio + li r9, ((CFG_NS16550_CLK / 16 / CONFIG_BAUDRATE) >> 8) + stb r9, 1(r8) /* baud rate (MSB) */ + eieio + li r9, 0x07 + stb r9, 3(r8) /* 8 data bits, 2 stop bit, no parity */ + eieio + li r9, 0x0b + stb r9, 4(r8) /* enable the receiver and transmitter (modem ctrl) */ + eieio +waitEmpty: + lbz r9, 5(r8) /* transmit empty */ + andi. r9, r9, 0x40 + beq waitEmpty + li r9, 0x47 + stb r9, 3(r8) /* send break, 8 data bits, 2 stop bit, no parity */ + eieio + + lis r0, 0x0001 + mtctr r0 +waitCOM1: + lwz r0, 5(r8) /* load from port for delay */ + bdnz waitCOM1 + +waitEmpty1: + lbz r9, 5(r8) /* transmit empty */ + andi. r9, r9, 0x40 + beq waitEmpty1 + li r9, 0x07 + stb r9, 3(r8) /* 8 data bits, 2 stop bit, no parity */ + eieio + +/* + * intro message from message block + */ + addi r3, r29, (MnewLine-MessageBlock) + bl Printf + addi r3, r29, (MinitLogo-MessageBlock) + bl Printf + +/* + * memory cofiguration using SPD information stored on the SODIMMs + */ + addi r3, r29, (Mspd01-MessageBlock) + bl Printf + + li r17, 0 + + li r3, 0x0002 /* get RAM type from spd for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, -1 /* error ? */ + bne noSpdError + + addi r3, r29, (Mfail-MessageBlock) + bl Printf + + li r6, 0xe /* error codes in r6 and r7 */ + li r7, 0x0 + b toggleError /* fail - loop forever */ + +noSpdError: + mr r15, r3 /* save r3 */ + + addi r3, r29, (Mok-MessageBlock) + bl Printf + + cmpli 0, 0, r15, 0x0004 /* SDRAM ? */ + beq isSDRAM + + addi r3, r29, (MramTyp-MessageBlock) + bl Printf + + li r6, 0xd /* error codes in r6 and r7 */ + li r7, 0x0 + b toggleError /* fail - loop forever */ + +isSDRAM: + li r3, 0x0012 /* get supported CAS latencies from byte 18 */ + bl spdRead + mr r15, r3 + li r3, 0x09 + andi. r0, r15, 0x04 + bne maxCLis3 + li r3, 0x17 +maxCLis3: + andi. r0, r15, 0x02 + bne CL2 + + addi r3, r29, (MramTyp-MessageBlock) + bl Printf + + li r6, 0xc /* error codes in r6 and r7 */ + li r7, 0x0 + b toggleError /* fail - loop forever */ +CL2: + bl spdRead + cmpli 0, 0, r3, 0xa1 /* cycle time must be 10ns max. */ + blt speedOk + + addi r3, r29, (MramTyp-MessageBlock) + bl Printf + + li r6, 0xb /* error codes in r6 and r7 */ + li r7, 0x0 + b toggleError /* fail - loop forever */ +speedOk: + lis r20, 0x06e8 /* preset MCR1 value */ + + li r3, 0x0011 /* get number of internal banks from spd for bank0/1 */ + bl spdRead + + cmpli 0, 0, r3, 0x02 + beq SD_2B + cmpli 0, 0, r3, 0x04 + beq SD_4B +memConfErr: + addi r3, r29, (MramConfErr-MessageBlock) + bl Printf + + li r6, 0xa /* error codes in r6 and r7 */ + li r7, 0x0 + b toggleError /* fail - loop forever */ + +SD_2B: + li r3, 0x0003 /* get number of row bits from spd for bank0/1 */ + bl spdRead + cmpli 0, 0, r3, 0x0b + beq row11x2 + cmpli 0, 0, r3, 0x0c + beq row12x2or13x2 + cmpli 0, 0, r3, 0x0d + beq row12x2or13x2 + b memConfErr +SD_4B: + li r3, 0x0003 /* get number of row bits from spd for bank0/1 */ + bl spdRead + cmpli 0, 0, r3, 0x0b + beq row11x4or12x4 + cmpli 0, 0, r3, 0x0c + beq row11x4or12x4 + cmpli 0, 0, r3, 0x0d + beq row13x4 + b memConfErr +row12x2or13x2: + ori r20, r20, 0x05 + b row11x4or12x4 +row13x4: + ori r20, r20, 0x0a + b row11x4or12x4 +row11x2: + ori r20, r20, 0x0f +row11x4or12x4: + /* get the size of bank 0-1 */ + + li r3, 0x001f /* get bank size from spd for bank0/1 */ + bl spdRead + + rlwinm r16, r3, 2, 24, 29 /* calculate size in MByte (128 MB max.) */ + + li r3, 0x0005 /* get number of banks from spd for bank0/1 */ + bl spdRead + + cmpi 0, 0, r3, 2 /* 2 banks ? */ + bne SDRAMnobank1 + + mr r17, r16 + +SDRAMnobank1: + li r3, 0x000c /* get refresh from spd for bank0/1 */ + bl spdRead + andi. r3, r3, 0x007f /* mask selfrefresh bit */ + li r4, 0x1800 /* refesh cycle 1536 clocks left shifted 2 */ + cmpli 0, 0, r3, 0x0000 /* 15.6 us ? */ + beq writeRefresh + + li r4, 0x0c00 /* refesh cycle 768 clocks left shifted 2 */ + cmpli 0, 0, r3, 0x0002 /* 7.8 us ? */ + beq writeRefresh + + li r4, 0x3000 /* refesh cycle 3072 clocks left shifted 2 */ + cmpli 0, 0, r3, 0x0003 /* 31.3 us ? */ + beq writeRefresh + + li r4, 0x6000 /* refesh cycle 6144 clocks left shifted 2 */ + cmpli 0, 0, r3, 0x0004 /* 62.5 us ? */ + beq writeRefresh + + li r4, 0 + ori r4, r4, 0xc000 /* refesh cycle 8224 clocks left shifted 2 */ + cmpli 0, 0, r3, 0x0005 /* 125 us ? */ + beq writeRefresh + + b memConfErr + +writeRefresh: + lis r21, 0x0400 /* preset MCCR2 value */ + or r21, r21, r4 + + /* Overwrite MCCR1 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR1 + stwbrx r3, 0, r1 + eieio + stwbrx r20, 0, r2 + + /* Overwrite MCCR2 */ + lis r3, MPC106_REG@h + ori r3, r3, MPC106_MCCR2 + stwbrx r3, 0, r1 + eieio + stwbrx r21, 0, r2 + + /* set the memory boundary registers for bank 0-3 */ + li r20, 0 + lis r23, 0x0303 + lis r24, 0x0303 + subi r21, r16, 1 /* calculate end address bank0 */ + li r22, 1 + + cmpi 0, 0, r17, 0 /* bank1 present ? */ + beq nobank1 + + andi. r3, r16, 0x00ff /* calculate start address of bank1 */ + andi. r4, r16, 0x0300 + rlwinm r3, r3, 8, 16, 23 + or r20, r20, r3 + or r23, r23, r4 + + add r16, r16, r17 /* add to total memory size */ + + subi r3, r16, 1 /* calculate end address of bank1 */ + andi. r4, r3, 0x0300 + andi. r3, r3, 0x00ff + rlwinm r3, r3, 8, 16, 23 + or r21, r21, r3 + or r24, r24, r4 + + ori r22, r22, 2 /* enable bank1 */ + b bankOk +nobank1: + ori r23, r23, 0x0300 /* set bank1 start to unused area */ + ori r24, r24, 0x0300 /* set bank1 end to unused area */ +bankOk: + addi r3, r29, (Mactivate-MessageBlock) + bl Printf + mr r3, r16 + bl OutDec + addi r3, r29, (Mact0123e-MessageBlock) + bl Printf + +/* + * overwrite MSAR1, MEAR1, EMSAR1, and EMEAR1 + */ + addis r3, r0, 0x8000 /* ADDR_80 */ + ori r3, r3, 0x0080 /* MSAR1 */ + stwbrx r3, 0, r1 + eieio + stwbrx r20, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_88 */ + ori r3, r3, 0x0088 /* EMSAR1 */ + stwbrx r3, 0, r1 + eieio + stwbrx r23, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_90 */ + ori r3, r3, 0x0090 /* MEAR1 */ + stwbrx r3, 0, r1 + eieio + stwbrx r21, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_98 */ + ori r3, r3, 0x0098 /* EMEAR1 */ + stwbrx r3, 0, r1 + eieio + stwbrx r24, 0, r2 + + addis r3, r0, 0x8000 /* ADDR_A0 */ + ori r3, r3, 0x00a0 /* MBER */ + stwbrx r3, 0, r1 + eieio + stwbrx r22, 0, r2 + +/* + * delay to let SDRAM go through several initialization/refresh cycles + */ + lis r3, 3 + mtctr r3 +memStartWait_1: + bdnz memStartWait_1 + eieio + +/* + * set LEDs end + */ + li r3, 0xf + lis r30, CFG_USR_LED_BASE@h + stb r3, 2(r30) + sync + + mtlr r13 + blr /* EXIT board_asm_init ... */ + +/*----------------------------------------------------------------------------*/ +/* + * print a message to COM1 in polling mode (r10=COM1 port, r3=(char*)string) + */ + +Printf: + lis r10, CFG_NS16550_COM1@h /* COM1 base address*/ + ori r10, r10, CFG_NS16550_COM1@l +WaitChr: + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, WaitChr /* wait till empty */ + lbzx r0, r0, r3 /* get char */ + stb r0, 0(r10) /* write to transmit reg */ + eieio + addi r3, r3, 1 /* next char */ + lbzx r0, r0, r3 /* get char */ + cmpwi cr1, r0, 0 /* end of string ? */ + bne cr1, WaitChr + blr + +/* + * print a char to COM1 in polling mode (r10=COM1 port, r3=char) + */ +OutChr: + lis r10, CFG_NS16550_COM1@h /* COM1 base address*/ + ori r10, r10, CFG_NS16550_COM1@l +OutChr1: + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutChr1 /* wait till empty */ + stb r3, 0(r10) /* write to transmit reg */ + eieio + blr + +/* + * print 8/4/2 digits hex value to COM1 in polling mode (r10=COM1 port, r3=val) + */ +OutHex2: + li r9, 4 /* shift reg for 2 digits */ + b OHstart +OutHex4: + li r9, 12 /* shift reg for 4 digits */ + b OHstart +OutHex: + li r9, 28 /* shift reg for 8 digits */ +OHstart: + lis r10, CFG_NS16550_COM1@h /* COM1 base address*/ + ori r10, r10, CFG_NS16550_COM1@l +OutDig: + lbz r0, 0(r29) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDig + sraw r0, r3, r9 + clrlwi r0, r0, 28 + cmpwi cr1, r0, 9 + ble cr1, digIsNum + addic r0, r0, 55 + b nextDig +digIsNum: + addic r0, r0, 48 +nextDig: + stb r0, 0(r10) /* write to transmit reg */ + eieio + addic. r9, r9, -4 + bge OutDig + blr + +/* + * print 3 digits hdec value to COM1 in polling mode + * (r10=COM1 port, r3=val, r7=x00, r8=x0, r9=x, r0, r6=scratch) + */ +OutDec: + li r6, 10 + divwu r0, r3, r6 /* r0 = r3 / 10, r9 = r3 mod 10 */ + mullw r10, r0, r6 + subf r9, r10, r3 + mr r3, r0 + divwu r0, r3, r6 /* r0 = r3 / 10, r8 = r3 mod 10 */ + mullw r10, r0, r6 + subf r8, r10, r3 + mr r3, r0 + divwu r0, r3, r6 /* r0 = r3 / 10, r7 = r3 mod 10 */ + mullw r10, r0, r6 + subf r7, r10, r3 + lis r10, CFG_NS16550_COM1@h /* COM1 base address*/ + ori r10, r10, CFG_NS16550_COM1@l + or. r7, r7, r7 + bne noblank1 + li r3, 0x20 + b OutDec4 +noblank1: + addi r3, r7, 48 /* convert to ASCII */ +OutDec4: + lbz r0, 0(r29) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec4 + stb r3, 0(r10) /* x00 to transmit */ + eieio + or. r7, r7, r8 + beq OutDec5 + addi r3, r8, 48 /* convert to ASCII */ +OutDec5: + lbz r0, 0(r29) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec5 + stb r3, 0(r10) /* x0 to transmit */ + eieio + addi r3, r9, 48 /* convert to ASCII */ +OutDec6: + lbz r0, 0(r29) /* slow down dummy read */ + lbz r0, 5(r10) /* read link status */ + eieio + andi. r0, r0, 0x40 /* mask transmitter empty bit */ + beq cr0, OutDec6 + stb r3, 0(r10) /* x to transmit */ + eieio + blr + +/* + * hang endless loop + */ +toggleError: /* fail type in r6, r7=0xff, toggle LEDs */ + stb r7, 2(r30) /* r7 to LED */ + li r0, 0 + lis r9, 127 + ori r9, r9, 65535 +toggleError1: + addic r0, r0, 1 + cmpw cr1, r0, r9 + ble cr1, toggleError1 + stb r6, 2(r30) /* r6 to LED */ + li r0, 0 + lis r9, 127 + ori r9, r9, 65535 +toggleError2: + addic r0, r0, 1 + cmpw cr1, r0, r9 + ble cr1, toggleError2 + b toggleError + +/* + * routines to read from ram spd + */ +spdWaitIdle: + lis r0, 0x1 /* timeout for about 100us */ + mtctr r0 +iSpd: + lbz r10, 12(r14) + andi. r10, r10, 0x20 /* mask and test MBB */ + beq idle + bdnz iSpd + orc. r10, r0, r0 /* return -1 to caller */ +idle: + bclr 20, 0 /* return to caller */ + +waitSpd: + lis r0, 0x10 /* timeout for about 1.5ms */ + mtctr r0 +wSpd: + lbz r10, 12(r14) + andi. r10, r10, 0x82 + cmpli 0, 0, r10, 0x82 /* test MCF and MIF set */ + beq wend + bdnz wSpd + orc. r10, r0, r0 /* return -1 to caller */ + bclr 20, 0 /* return to caller */ + +wend: + li r10, 0 + stb r10, 12(r14) /* clear status */ + bclr 20, 0 /* return to caller */ + +/* + * spdread + * in: r3 adr to read + * out: r3 val or -1 for error + * uses r10, assumes that r14 points to I2C controller + */ +spdRead: + mfspr r25, 8 /* save link register */ + + bl spdWaitIdle + bne spdErr + + li r10, 0x80 /* start with MEN */ + stb r10, 8(r14) + eieio + + li r10, 0xb0 /* start as master */ + stb r10, 8(r14) + eieio + + li r10, 0xa0 /* write device 0xA0 */ + stb r10, 16(r14) + eieio + bl waitSpd + bne spdErr + + lbz r10, 12(r14) /* test ACK */ + andi. r10, r10, 0x01 + bne gotNoAck + + stb r3, 16(r14) /* data address */ + eieio + bl waitSpd + bne spdErr + + + li r10, 0xb4 /* switch to read - restart */ + stb r10, 8(r14) + eieio + + li r10, 0xa1 /* read device 0xA0 */ + stb r10, 16(r14) + eieio + bl waitSpd + bne spdErr + + li r10, 0xa8 /* no ACK */ + stb r10, 8(r14) + eieio + + lbz r10, 16(r14) /* trigger read next byte */ + eieio + bl waitSpd + bne spdErr + + li r10, 0x88 /* generate STOP condition */ + stb r10, 8(r14) + eieio + + lbz r3, 16(r14) /* return read byte */ + + mtspr 8, r25 /* restore link register */ + blr + +gotNoAck: + li r10, 0x80 /* generate STOP condition */ + stb r10, 8(r14) + eieio +spdErr: + orc r3, r0, r0 /* return -1 */ + mtspr 8, r25 /* restore link register */ + blr + +get_lnk_reg: + mflr r3 /* return link reg */ + blr + +MessageBlock: + +MinitLogo: + .ascii "\015\012*** ELTEC Elektronik, Mainz ***\015\012" + .ascii "\015\012Initialising RAM\015\012\000" +Mspd01: + .ascii " Reading SPD of SODIMM ...... \000" +MramTyp: + .ascii "\015\012\SDRAM with CL=2 at 100 MHz required!\015\012\000" +MramConfErr: + .ascii "\015\012\Unsupported SODIMM Configuration!\015\012\000" +Mactivate: + .ascii " Activating \000" +Mact0123e: + .ascii " MByte.\015\012\000" +Mok: + .ascii "OK \015\012\000" +Mfail: + .ascii "FAILED \015\012\000" +MnewLine: + .ascii "\015\012\000" + .align 4 diff --git a/board/eltec/elppc/u-boot.lds b/board/eltec/elppc/u-boot.lds new file mode 100644 index 0000000..7b10c0d --- /dev/null +++ b/board/eltec/elppc/u-boot.lds @@ -0,0 +1,129 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * u-boot.lds - linker script for U-Boot on the Galileo Eval Board. + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/74xx_7xx/start.o (.text) + +/* store the environment in a seperate sector in the boot flash */ +/* . = env_offset; */ +/* common/environment.o(.text) */ + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/ep7312/flash.c b/board/ep7312/flash.c new file mode 100644 index 0000000..373d238 --- /dev/null +++ b/board/ep7312/flash.c @@ -0,0 +1,341 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#define FLASH_BANK_SIZE 0x1000000 +#define MAIN_SECT_SIZE 0x20000 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + + +/*----------------------------------------------------------------------- + */ + +ulong flash_init (void) +{ + int i, j; + ulong size = 0; + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) { + ulong flashbase = 0; + + flash_info[i].flash_id = + (INTEL_MANUFACT & FLASH_VENDMASK) | + (INTEL_ID_28F128J3 & FLASH_TYPEMASK); + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CFG_MAX_FLASH_SECT; + memset (flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); + if (i == 0) + flashbase = PHYS_FLASH_1; + else + panic ("configured to many flash banks!\n"); + for (j = 0; j < flash_info[i].sector_count; j++) { + flash_info[i].start[j] = flashbase + j * MAIN_SECT_SIZE; + } + size += flash_info[i].size; + } + + /* Protect monitor and environment sectors + */ + flash_protect ( FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE + _armboot_end_data - _armboot_start, + &flash_info[0]); + + flash_protect ( FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t * info) +{ + int i; + + switch (info->flash_id & FLASH_VENDMASK) { + case (INTEL_MANUFACT & FLASH_VENDMASK): + printf ("Intel: "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case (INTEL_ID_28F128J3 & FLASH_TYPEMASK): + printf ("28F128J3 (128Mbit)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + goto Done; + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) { + if ((i % 5) == 0) { + printf ("\n "); + } + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + + Done: +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t * info, int s_first, int s_last) +{ + int flag, prot, sect; + int rc = ERR_OK; + + if (info->flash_id == FLASH_UNKNOWN) + return ERR_UNKNOWN_FLASH_TYPE; + + if ((s_first < 0) || (s_first > s_last)) { + return ERR_INVAL; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (INTEL_MANUFACT & FLASH_VENDMASK)) { + return ERR_UNKNOWN_FLASH_VENDOR; + } + + prot = 0; + for (sect = s_first; sect <= s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + flag = disable_interrupts (); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect <= s_last && !ctrlc (); sect++) { + + printf ("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + if (info->protect[sect] == 0) { /* not protected */ + vu_short *addr = (vu_short *) (info->start[sect]); + + *addr = 0x20; /* erase setup */ + *addr = 0xD0; /* erase confirm */ + + while ((*addr & 0x80) != 0x80) { + if (get_timer_masked () > CFG_FLASH_ERASE_TOUT) { + *addr = 0xB0; /* suspend erase */ + *addr = 0xFF; /* reset to read mode */ + rc = ERR_TIMOUT; + goto outahere; + } + } + + /* clear status register command */ + *addr = 0x50; + /* reset to read mode */ + *addr = 0xFF; + } + printf ("ok.\n"); + } + if (ctrlc ()) + printf ("User Interrupt!\n"); + + outahere: + + /* allow flash to settle - wait 10 ms */ + udelay_masked (10000); + + if (flag) + enable_interrupts (); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +static int write_word (flash_info_t * info, ulong dest, ushort data) +{ + vu_short *addr = (vu_short *) dest, val; + int rc = ERR_OK; + int flag; + + /* Check if Flash is (sufficiently) erased + */ + if ((*addr & data) != data) + return ERR_NOT_ERASED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + flag = disable_interrupts (); + + /* clear status register command */ + *addr = 0x50; + + /* program set-up command */ + *addr = 0x40; + + /* latch address/data */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked (); + + /* wait while polling the status register */ + while (((val = *addr) & 0x80) != 0x80) { + if (get_timer_masked () > CFG_FLASH_WRITE_TOUT) { + rc = ERR_TIMOUT; + /* suspend program command */ + *addr = 0xB0; + goto outahere; + } + } + + if (val & 0x1A) { /* check for error */ + printf ("\nFlash write error %02x at address %08lx\n", + (int) val, (unsigned long) dest); + if (val & (1 << 3)) { + printf ("Voltage range error.\n"); + rc = ERR_PROG_ERROR; + goto outahere; + } + if (val & (1 << 1)) { + printf ("Device protect error.\n"); + rc = ERR_PROTECTED; + goto outahere; + } + if (val & (1 << 4)) { + printf ("Programming error.\n"); + rc = ERR_PROG_ERROR; + goto outahere; + } + rc = ERR_PROG_ERROR; + goto outahere; + } + + outahere: + /* read array command */ + *addr = 0xFF; + + if (flag) + enable_interrupts (); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t * info, uchar * src, ulong addr, ulong cnt) +{ + ulong cp, wp; + ushort data; + int l; + int i, rc; + + wp = (addr & ~1); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i = 0, cp = wp; i < l; ++i, ++cp) { + data = (data >> 8) | (*(uchar *) cp << 8); + } + for (; i < 2 && cnt > 0; ++i) { + data = (data >> 8) | (*src++ << 8); + --cnt; + ++cp; + } + for (; cnt == 0 && i < 2; ++i, ++cp) { + data = (data >> 8) | (*(uchar *) cp << 8); + } + + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + wp += 2; + } + + /* + * handle word aligned part + */ + while (cnt >= 2) { + data = *((vu_short *) src); + if ((rc = write_word (info, wp, data)) != 0) { + return (rc); + } + src += 2; + wp += 2; + cnt -= 2; + } + + if (cnt == 0) { + return ERR_OK; + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i = 0, cp = wp; i < 2 && cnt > 0; ++i, ++cp) { + data = (data >> 8) | (*src++ << 8); + --cnt; + } + for (; i < 2; ++i, ++cp) { + data = (data >> 8) | (*(uchar *) cp << 8); + } + + return write_word (info, wp, data); +} diff --git a/board/ep7312/u-boot.lds b/board/ep7312/u-boot.lds new file mode 100644 index 0000000..0849648 --- /dev/null +++ b/board/ep7312/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm720t/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/esd/common/fpga.c b/board/esd/common/fpga.c new file mode 100644 index 0000000..666b490 --- /dev/null +++ b/board/esd/common/fpga.c @@ -0,0 +1,262 @@ +/* + * (C) Copyright 2001 + * Matthias Fuchs, esd gmbh germany, matthias.fuchs@esd-electronics.com + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <command.h> + +/* ------------------------------------------------------------------------- */ + +#ifdef FPGA_DEBUG +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif /* DEBUG */ + +#define MAX_ONES 226 + +#define IBM405GP_GPIO0_OR 0xef600700 /* GPIO Output */ +#define IBM405GP_GPIO0_TCR 0xef600704 /* GPIO Three-State Control */ +#define IBM405GP_GPIO0_ODR 0xef600718 /* GPIO Open Drain */ +#define IBM405GP_GPIO0_IR 0xef60071c /* GPIO Input */ + +#ifdef CFG_FPGA_PRG +# define FPGA_PRG CFG_FPGA_PRG /* FPGA program pin (ppc output)*/ +# define FPGA_CLK CFG_FPGA_CLK /* FPGA clk pin (ppc output) */ +# define FPGA_DATA CFG_FPGA_DATA /* FPGA data pin (ppc output) */ +# define FPGA_DONE CFG_FPGA_DONE /* FPGA done pin (ppc input) */ +# define FPGA_INIT CFG_FPGA_INIT /* FPGA init pin (ppc input) */ +#else +# define FPGA_PRG 0x04000000 /* FPGA program pin (ppc output) */ +# define FPGA_CLK 0x02000000 /* FPGA clk pin (ppc output) */ +# define FPGA_DATA 0x01000000 /* FPGA data pin (ppc output) */ +# define FPGA_DONE 0x00800000 /* FPGA done pin (ppc input) */ +# define FPGA_INIT 0x00400000 /* FPGA init pin (ppc input) */ +#endif + +#define ERROR_FPGA_PRG_INIT_LOW -1 /* Timeout after PRG* asserted */ +#define ERROR_FPGA_PRG_INIT_HIGH -2 /* Timeout after PRG* deasserted */ +#define ERROR_FPGA_PRG_DONE -3 /* Timeout after programming */ + +#define SET_FPGA(data) out32(IBM405GP_GPIO0_OR, data) + +#define FPGA_WRITE_1 { \ + SET_FPGA(FPGA_PRG | FPGA_DATA); /* set clock to 0 */ \ + SET_FPGA(FPGA_PRG | FPGA_DATA); /* set data to 1 */ \ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set clock to 1 */ \ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + +#define FPGA_WRITE_0 { \ + SET_FPGA(FPGA_PRG | FPGA_DATA); /* set clock to 0 */ \ + SET_FPGA(FPGA_PRG); /* set data to 0 */ \ + SET_FPGA(FPGA_PRG | FPGA_CLK); /* set clock to 1 */ \ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA);} /* set data to 1 */ + + +static int fpga_boot(unsigned char *fpgadata, int size) +{ + int i,index,len; + int count; +#ifdef CFG_FPGA_SPARTAN2 + int j; +#else + unsigned char b; + int bit; +#endif + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) + { + len = fpgadata[index]; + DBG("FPGA: %s\n", &(fpgadata[index+1])); + index += len+3; + } + +#ifdef CFG_FPGA_SPARTAN2 + /* search for preamble 0xFFFFFFFF */ + while (1) + { + if ((fpgadata[index] == 0xff) && (fpgadata[index+1] == 0xff) && + (fpgadata[index+2] == 0xff) && (fpgadata[index+3] == 0xff)) + break; /* preamble found */ + else + index++; + } +#else + /* search for preamble 0xFF2X */ + for (index = 0; index < size-1 ; index++) + { + if ((fpgadata[index] == 0xff) && ((fpgadata[index+1] & 0xf0) == 0x30)) + break; + } + index += 2; +#endif + + DBG("FPGA: configdata starts at position 0x%x\n",index); + DBG("FPGA: length of fpga-data %d\n", size-index); + + /* + * Setup port pins for fpga programming + */ + out32(IBM405GP_GPIO0_ODR, 0x00000000); /* no open drain pins */ + out32(IBM405GP_GPIO0_TCR, FPGA_PRG | FPGA_CLK | FPGA_DATA); /* setup for output */ + out32(IBM405GP_GPIO0_OR, FPGA_PRG | FPGA_CLK | FPGA_DATA); /* set output pins to high */ + + DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" ); + + /* + * Init fpga by asserting and deasserting PROGRAM* + */ + SET_FPGA(FPGA_CLK | FPGA_DATA); + + /* Wait for FPGA init line low */ + count = 0; + while (in32(IBM405GP_GPIO0_IR) & FPGA_INIT) + { + udelay(1000); /* wait 1ms */ + /* Check for timeout - 100us max, so use 3ms */ + if (count++ > 3) + { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_INIT_LOW; + } + } + + DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" ); + + /* deassert PROGRAM* */ + SET_FPGA(FPGA_PRG | FPGA_CLK | FPGA_DATA); + + /* Wait for FPGA end of init period . */ + count = 0; + while (!(in32(IBM405GP_GPIO0_IR) & FPGA_INIT)) + { + udelay(1000); /* wait 1ms */ + /* Check for timeout */ + if (count++ > 3) + { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_INIT_HIGH; + } + } + + DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" ); + + DBG("write configuration data into fpga\n"); + /* write configuration-data into fpga... */ + +#ifdef CFG_FPGA_SPARTAN2 + /* + * Load uncompressed image into fpga + */ + for (i=index; i<size; i++) + { + for (j=0; j<8; j++) + { + if ((fpgadata[i] & 0x80) == 0x80) + { + FPGA_WRITE_1; + } + else + { + FPGA_WRITE_0; + } + fpgadata[i] <<= 1; + } + } +#else + /* send 0xff 0x20 */ + FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; + FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; FPGA_WRITE_1; + FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_1; FPGA_WRITE_0; + FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_0; FPGA_WRITE_0; + + /* + ** Bit_DeCompression + ** Code 1 .. maxOnes : n '1's followed by '0' + ** maxOnes + 1 .. maxOnes + 1 : n - 1 '1's no '0' + ** maxOnes + 2 .. 254 : n - (maxOnes + 2) '0's followed by '1' + ** 255 : '1' + */ + + for (i=index; i<size; i++) + { + b = fpgadata[i]; + if ((b >= 1) && (b <= MAX_ONES)) + { + for(bit=0; bit<b; bit++) + { + FPGA_WRITE_1; + } + FPGA_WRITE_0; + } + else if (b == (MAX_ONES+1)) + { + for(bit=1; bit<b; bit++) + { + FPGA_WRITE_1; + } + } + else if ((b >= (MAX_ONES+2)) && (b <= 254)) + { + for(bit=0; bit<(b-(MAX_ONES+2)); bit++) + { + FPGA_WRITE_0; + } + FPGA_WRITE_1; + } + else if (b == 255) + { + FPGA_WRITE_1; + } + } +#endif + + DBG("%s, ",((in32(IBM405GP_GPIO0_IR) & FPGA_DONE) == 0) ? "NOT DONE" : "DONE" ); + DBG("%s\n",((in32(IBM405GP_GPIO0_IR) & FPGA_INIT) == 0) ? "NOT INIT" : "INIT" ); + + /* + * Check if fpga's DONE signal - correctly booted ? + */ + + /* Wait for FPGA end of programming period . */ + count = 0; + while (!(in32(IBM405GP_GPIO0_IR) & FPGA_DONE)) + { + udelay(1000); /* wait 1ms */ + /* Check for timeout */ + if (count++ > 3) + { + DBG("FPGA: Booting failed!\n"); + return ERROR_FPGA_PRG_DONE; + } + } + + DBG("FPGA: Booting successful!\n"); + return 0; +} diff --git a/board/esd/common/pci.c b/board/esd/common/pci.c new file mode 100644 index 0000000..f8f180c --- /dev/null +++ b/board/esd/common/pci.c @@ -0,0 +1,202 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> +#include <pci.h> + + +u_long pci9054_iobase; + + +#define PCI_PRIMARY_CAR (0x500000dc) /* PCI config address reg */ +#define PCI_PRIMARY_CDR (0x80000000) /* PCI config data reg */ + + +/*-----------------------------------------------------------------------------+ +| Subroutine: pci9054_read_config_dword +| Description: Read a PCI configuration register +| Inputs: +| hose PCI Controller +| dev PCI Bus+Device+Function number +| offset Configuration register number +| value Address of the configuration register value +| Return value: +| 0 Successful ++-----------------------------------------------------------------------------*/ +int pci9054_read_config_dword(struct pci_controller *hose, + pci_dev_t dev, int offset, u32* value) +{ + unsigned long conAdrVal; + unsigned long val; + + /* generate coded value for CON_ADR register */ + conAdrVal = dev | (offset & 0xfc) | 0x80000000; + + /* Load the CON_ADR (CAR) value first, then read from CON_DATA (CDR) */ + *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal; + + /* Note: *pResult comes back as -1 if machine check happened */ + val = in32r(PCI_PRIMARY_CDR); + + *value = (unsigned long) val; + + out32r(PCI_PRIMARY_CAR, 0); + + if ((*(unsigned long *)0x50000304) & 0x60000000) + { + /* clear pci master/target abort bits */ + *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304; + } + + return 0; +} + +/*-----------------------------------------------------------------------------+ +| Subroutine: pci9054_write_config_dword +| Description: Write a PCI configuration register. +| Inputs: +| hose PCI Controller +| dev PCI Bus+Device+Function number +| offset Configuration register number +| Value Configuration register value +| Return value: +| 0 Successful +| Updated for pass2 errata #6. Need to disable interrupts and clear the +| PCICFGADR reg after writing the PCICFGDATA reg. ++-----------------------------------------------------------------------------*/ +int pci9054_write_config_dword(struct pci_controller *hose, + pci_dev_t dev, int offset, u32 value) +{ + unsigned long conAdrVal; + + conAdrVal = dev | (offset & 0xfc) | 0x80000000; + + *(unsigned long *)PCI_PRIMARY_CAR = conAdrVal; + + out32r(PCI_PRIMARY_CDR, value); + + out32r(PCI_PRIMARY_CAR, 0); + + /* clear pci master/target abort bits */ + *(unsigned long *)0x50000304 = *(unsigned long *)0x50000304; + + return (0); +} + +/*----------------------------------------------------------------------- + */ + +#ifdef CONFIG_DASA_SIM +static void pci_dasa_sim_config_pci9054(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *_) +{ + unsigned int iobase; + unsigned short status = 0; + unsigned char timer; + + /* + * Configure PLX PCI9054 + */ + pci_read_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, &status); + status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + pci_write_config_word(CFG_PCI9054_DEV_FN, PCI_COMMAND, status); + + /* Check the latency timer for values >= 0x60. + */ + pci_read_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, &timer); + if (timer < 0x60) + { + pci_write_config_byte(CFG_PCI9054_DEV_FN, PCI_LATENCY_TIMER, 0x60); + } + + /* Set I/O base register. + */ + pci_write_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, CFG_PCI9054_IOBASE); + pci_read_config_dword(CFG_PCI9054_DEV_FN, PCI_BASE_ADDRESS_0, &iobase); + + pci9054_iobase = pci_mem_to_phys(CFG_PCI9054_DEV_FN, iobase & PCI_BASE_ADDRESS_MEM_MASK); + + if (pci9054_iobase == 0xffffffff) + { + printf("Error: Can not set I/O base register.\n"); + return; + } +} +#endif + +static struct pci_config_table pci9054_config_table[] = { +#ifndef CONFIG_PCI_PNP + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_BUS(CFG_ETH_DEV_FN), PCI_DEV(CFG_ETH_DEV_FN), PCI_FUNC(CFG_ETH_DEV_FN), + pci_cfgfunc_config_device, { CFG_ETH_IOBASE, + CFG_ETH_IOBASE, + PCI_COMMAND_IO | PCI_COMMAND_MASTER }}, +#ifdef CONFIG_DASA_SIM + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + PCI_BUS(CFG_PCI9054_DEV_FN), PCI_DEV(CFG_PCI9054_DEV_FN), PCI_FUNC(CFG_PCI9054_DEV_FN), + pci_dasa_sim_config_pci9054 }, +#endif +#endif + { } +}; + +static struct pci_controller pci9054_hose = { + config_table: pci9054_config_table, +}; + +void pci_init(void) +{ + struct pci_controller *hose = &pci9054_hose; + + /* + * Register the hose + */ + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* System memory space */ + pci_set_region(hose->regions + 0, + 0x00000000, 0x00000000, 0x01000000, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI Memory space */ + pci_set_region(hose->regions + 1, + 0x00000000, 0xc0000000, 0x10000000, + PCI_REGION_MEM); + + pci_set_ops(hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + pci9054_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + pci9054_write_config_dword); + + hose->region_count = 2; + + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); +} diff --git a/board/esd/cpci405/cpci405.c b/board/esd/cpci405/cpci405.c new file mode 100644 index 0000000..2dda8fa --- /dev/null +++ b/board/esd/cpci405/cpci405.c @@ -0,0 +1,451 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <command.h> +#include <cmd_boot.h> +#include <malloc.h> + +/* ------------------------------------------------------------------------- */ + +#if 0 +#define FPGA_DEBUG +#endif + +/* fpga configuration data - generated by bin2cc */ +const unsigned char fpgadata[] = +{ +#ifdef CONFIG_CPCI405_VER2 +# include "fpgadata_cpci4052.c" +#else +# include "fpgadata_cpci405.c" +#endif +}; + +/* + * include common fpga code (for esd boards) + */ +#include "../common/fpga.c" + + +/* Prototypes */ +int version2(void); +int gunzip(void *, int, unsigned char *, int *); + + +int board_pre_init (void) +{ +#ifndef CONFIG_CPCI405_VER2 + int index, len, i; + int status; +#endif + +#ifdef FPGA_DEBUG + DECLARE_GLOBAL_DATA_PTR; + + /* set up serial port with default baudrate */ + (void) get_clocks (); + gd->baudrate = CONFIG_BAUDRATE; + serial_init (); + console_init_f(); +#endif + + /* + * First pull fpga-prg pin low, to disable fpga logic (on version 2 board) + */ + out32(IBM405GP_GPIO0_ODR, 0x00000000); /* no open drain pins */ + out32(IBM405GP_GPIO0_TCR, CFG_FPGA_PRG); /* setup for output */ + out32(IBM405GP_GPIO0_OR, CFG_FPGA_PRG); /* set output pins to high */ + out32(IBM405GP_GPIO0_OR, 0); /* pull prg low */ + + /* + * Boot onboard FPGA + */ +#ifndef CONFIG_CPCI405_VER2 + if (!version2()) { + status = fpga_boot((unsigned char *)fpgadata, sizeof(fpgadata)); + if (status != 0) { + /* booting FPGA failed */ +#ifndef FPGA_DEBUG + DECLARE_GLOBAL_DATA_PTR; + + /* set up serial port with default baudrate */ + (void) get_clocks (); + gd->baudrate = CONFIG_BAUDRATE; + serial_init (); + console_init_f(); +#endif + printf("\nFPGA: Booting failed "); + switch (status) { + case ERROR_FPGA_PRG_INIT_LOW: + printf("(Timeout: INIT not low after asserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_INIT_HIGH: + printf("(Timeout: INIT not high after deasserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_DONE: + printf("(Timeout: DONE not high after programming FPGA)\n "); + break; + } + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = fpgadata[index]; + printf("FPGA: %s\n", &(fpgadata[index+1])); + index += len+3; + } + putc ('\n'); + /* delayed reboot */ + for (i=20; i>0; i--) { + printf("Rebooting in %2d seconds \r",i); + for (index=0;index<1000;index++) + udelay(1000); + } + putc ('\n'); + do_reset(NULL, 0, 0, NULL); + } + } +#endif /* !CONFIG_CPCI405_VER2 */ + + /* + * IRQ 0-15 405GP internally generated; active high; level sensitive + * IRQ 16 405GP internally generated; active low; level sensitive + * IRQ 17-24 RESERVED + * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive + * IRQ 26 (EXT IRQ 1) CAN1 (+FPGA on CPCI4052) ; active low; level sensitive + * IRQ 27 (EXT IRQ 2) PCI SLOT 0; active low; level sensitive + * IRQ 28 (EXT IRQ 3) PCI SLOT 1; active low; level sensitive + * IRQ 29 (EXT IRQ 4) PCI SLOT 2; active low; level sensitive + * IRQ 30 (EXT IRQ 5) PCI SLOT 3; active low; level sensitive + * IRQ 31 (EXT IRQ 6) COMPACT FLASH; active high; level sensitive + */ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/ + mtdcr(uicpr, 0xFFFFFF81); /* set int polarities */ + mtdcr(uictr, 0x10000000); /* set int trigger levels */ + mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + +int ctermm2(void) +{ +#ifdef CONFIG_CPCI405_VER2 + return 0; /* no, board is cpci405 */ +#else + if ((*(unsigned char *)0xf0000400 == 0x00) && + (*(unsigned char *)0xf0000401 == 0x01)) + return 0; /* no, board is cpci405 */ + else + return -1; /* yes, board is cterm-m2 */ +#endif +} + + +int cpci405_host(void) +{ + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) + return -1; /* yes, board is cpci405 host */ + else + return 0; /* no, board is cpci405 adapter */ +} + + +int version2(void) +{ + unsigned long cntrl0Reg; + unsigned long value; + + /* + * Setup GPIO pins (CS2/GPIO11 as GPIO) + */ + cntrl0Reg = mfdcr(cntrl0); + mtdcr(cntrl0, cntrl0Reg | 0x02000000); + + udelay(1000); /* wait some time before reading input */ + value = in32(IBM405GP_GPIO0_IR) & 0x00100000; /* test GPIO11 */ + + /* + * Setup GPIO pins (CS2/GPIO11 as CS again) + */ + mtdcr(cntrl0, cntrl0Reg); + + if (value) + return 0; /* no, board is version 1.x */ + else + return -1; /* yes, board is version 2.x */ +} + + +int misc_init_f (void) +{ + return 0; /* dummy implementation */ +} + + +int misc_init_r (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + bd_t *bd = gd->bd; + char * tmp; /* Temporary char pointer */ + +#ifdef CONFIG_CPCI405_VER2 + unsigned char *dst; + ulong len = sizeof(fpgadata); + int status; + int index; + int i; + unsigned long cntrl0Reg; + + /* + * On CPCI-405 version 2 the environment is saved in eeprom! + * FPGA can be gzip compressed (malloc) and booted this late. + */ + + if (version2()) { + /* + * Setup GPIO pins (CS6+CS7 as GPIO) + */ + cntrl0Reg = mfdcr(cntrl0); + mtdcr(cntrl0, cntrl0Reg | 0x00300000); + + dst = malloc(CFG_FPGA_MAX_SIZE); + if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, (int *)&len) != 0) { + printf ("GUNZIP ERROR - must RESET board to recover\n"); + do_reset (NULL, 0, 0, NULL); + } + + status = fpga_boot(dst, len); + if (status != 0) { + printf("\nFPGA: Booting failed "); + switch (status) { + case ERROR_FPGA_PRG_INIT_LOW: + printf("(Timeout: INIT not low after asserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_INIT_HIGH: + printf("(Timeout: INIT not high after deasserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_DONE: + printf("(Timeout: DONE not high after programming FPGA)\n "); + break; + } + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("FPGA: %s\n", &(dst[index+1])); + index += len+3; + } + putc ('\n'); + /* delayed reboot */ + for (i=20; i>0; i--) { + printf("Rebooting in %2d seconds \r",i); + for (index=0;index<1000;index++) + udelay(1000); + } + putc ('\n'); + do_reset(NULL, 0, 0, NULL); + } + + /* restore gpio/cs settings */ + mtdcr(cntrl0, cntrl0Reg); + + puts("FPGA: "); + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("%s ", &(dst[index+1])); + index += len+3; + } + putc ('\n'); + + free(dst); + } + else { + printf("\n*** U-Boot Version does not match Board Version!\n"); + printf("*** CPCI-405 Version 2.x detected!\n"); + printf("*** Please use correct U-Boot version (CPCI4052)!\n\n"); + } + +#else /* CONFIG_CPCI405_VER2 */ + + /* + * Generate last byte of ip-addr from code-plug @ 0xf0000400 + */ + if (ctermm2()) { + char str[32]; + unsigned char ipbyte = *(unsigned char *)0xf0000400; + + /* + * Only overwrite ip-addr with allowed values + */ + if ((ipbyte != 0x00) && (ipbyte != 0xff)) { + bd->bi_ip_addr = (bd->bi_ip_addr & 0xffffff00) | ipbyte; + sprintf(str, "%ld.%ld.%ld.%ld", + (bd->bi_ip_addr & 0xff000000) >> 24, + (bd->bi_ip_addr & 0x00ff0000) >> 16, + (bd->bi_ip_addr & 0x0000ff00) >> 8, + (bd->bi_ip_addr & 0x000000ff)); + setenv("ipaddr", str); + } + } + + if (version2()) { + printf("\n*** U-Boot Version does not match Board Version!\n"); + printf("*** CPCI-405 Board Version 1.x detected!\n"); + printf("*** Please use correct U-Boot version (CPCI405)!\n\n"); + } + +#endif /* CONFIG_CPCI405_VER2 */ + + /* + * Write ethernet addr in NVRAM for VxWorks + */ + tmp = (char *)CFG_NVRAM_BASE_ADDR + CFG_NVRAM_VXWORKS_OFFS; + memcpy( (char *)tmp, (char *)&bd->bi_enetaddr[0], 6 ); + return (0); +} + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ +#ifndef CONFIG_CPCI405_VER2 + int index; + int len; +#endif + unsigned char str[64]; + int i = getenv_r ("serial#", str, sizeof(str)); + + puts ("Board: "); + + if (i == -1) { + puts ("### No HW ID - assuming CPCI405"); + } else { + puts(str); + } + + if (version2()) + puts (" (Ver 2.x, "); + else + puts (" (Ver 1.x, "); + +#if 0 + if ((*(unsigned short *)((unsigned long)CFG_FPGA_BASE_ADDR) + CFG_FPGA_STATUS) + & CFG_FPGA_STATUS_FLASH) + puts ("FLASH Bank A, "); + else + puts ("FLASH Bank B, "); +#endif + + if (ctermm2()) { + printf("CTERM-M2 - Id=0x%02x)", *(unsigned char *)0xf0000400); + } else { + if (cpci405_host()) { + puts ("PCI Host Version)"); + } else { + puts ("PCI Adapter Version)"); + } + } + +#ifndef CONFIG_CPCI405_VER2 + puts ("\nFPGA: "); + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = fpgadata[index]; + printf("%s ", &(fpgadata[index+1])); + index += len+3; + } +#endif + + putc ('\n'); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + unsigned long val; + + mtdcr(memcfga, mem_mb0cf); + val = mfdcr(memcfgd); + +#if 0 + printf("\nmb0cf=%x\n", val); /* test-only */ + printf("strap=%x\n", mfdcr(strap)); /* test-only */ +#endif + + return (4*1024*1024 << ((val & 0x000e0000) >> 17)); +} + +/* ------------------------------------------------------------------------- */ + +int testdram (void) +{ + /* TODO: XXX XXX XXX */ + printf ("test: 16 MB - ok\n"); + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_CPCI405_VER2 +#ifdef CONFIG_IDE_RESET + +void ide_set_reset(int on) +{ + volatile unsigned short *fpga_mode = (unsigned short *)CFG_FPGA_BASE_ADDR; + + /* + * Assert or deassert CompactFlash Reset Pin + */ + if (on) { /* assert RESET */ + *fpga_mode &= ~(CFG_FPGA_MODE_CF_RESET); + } else { /* release RESET */ + *fpga_mode |= CFG_FPGA_MODE_CF_RESET; + } +} + +#endif /* CONFIG_IDE_RESET */ +#endif /* CONFIG_CPCI405_VER2 */ + +/* ------------------------------------------------------------------------- */ diff --git a/board/esd/cpci440/cpci440.c b/board/esd/cpci440/cpci440.c new file mode 100644 index 0000000..51a5edd --- /dev/null +++ b/board/esd/cpci440/cpci440.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2002 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <asm/processor.h> + + +long int fixed_sdram( void ); + +int board_pre_init (void) +{ + uint reg; + + /*-------------------------------------------------------------------- + * Setup the external bus controller/chip selects + *-------------------------------------------------------------------*/ + mtdcr( ebccfga, xbcfg ); + reg = mfdcr( ebccfgd ); + mtdcr( ebccfgd, reg | 0x04000000 ); /* Set ATC */ + + mtebc( pb0ap, 0x92015480 ); /* FLASH/SRAM */ + mtebc( pb0cr, 0xFF87A000 ); /* BAS=0xff8 8MB R/W 16-bit */ + /* test-only: other regs still missing... */ + + /*-------------------------------------------------------------------- + * Setup the interrupt controller polarities, triggers, etc. + *-------------------------------------------------------------------*/ + mtdcr( uic0sr, 0xffffffff ); /* clear all */ + mtdcr( uic0er, 0x00000000 ); /* disable all */ + mtdcr( uic0cr, 0x00000009 ); /* SMI & UIC1 crit are critical */ + mtdcr( uic0pr, 0xfffffe13 ); /* per ref-board manual */ + mtdcr( uic0tr, 0x01c00008 ); /* per ref-board manual */ + mtdcr( uic0vr, 0x00000001 ); /* int31 highest, base=0x000 */ + mtdcr( uic0sr, 0xffffffff ); /* clear all */ + + mtdcr( uic1sr, 0xffffffff ); /* clear all */ + mtdcr( uic1er, 0x00000000 ); /* disable all */ + mtdcr( uic1cr, 0x00000000 ); /* all non-critical */ + mtdcr( uic1pr, 0xffffe0ff ); /* per ref-board manual */ + mtdcr( uic1tr, 0x00ffc000 ); /* per ref-board manual */ + mtdcr( uic1vr, 0x00000001 ); /* int31 highest, base=0x000 */ + mtdcr( uic1sr, 0xffffffff ); /* clear all */ + + return 0; +} + + + +int checkboard (void) +{ + sys_info_t sysinfo; + get_sys_info(&sysinfo); + + printf("Board: esd CPCI-440\n"); + printf("\tVCO: %lu MHz\n", sysinfo.freqVCOMhz/1000000); + printf("\tCPU: %lu MHz\n", sysinfo.freqProcessor/1000000); + printf("\tPLB: %lu MHz\n", sysinfo.freqPLB/1000000); + printf("\tOPB: %lu MHz\n", sysinfo.freqOPB/1000000); + printf("\tEPB: %lu MHz\n", sysinfo.freqEPB/1000000); + return (0); +} + + +long int initdram (int board_type) +{ + long dram_size = 0; + + dram_size = fixed_sdram(); + return dram_size; +} + + +/************************************************************************* + * fixed sdram init -- doesn't use serial presence detect. + * + * Assumes: 64 MB, non-ECC, non-registered + * PLB @ 133 MHz + * + ************************************************************************/ +long int fixed_sdram( void ) +{ + uint reg; + + /*-------------------------------------------------------------------- + * Setup some default + *------------------------------------------------------------------*/ + mtsdram( mem_uabba, 0x00000000 ); /* ubba=0 (default) */ + mtsdram( mem_slio, 0x00000000 ); /* rdre=0 wrre=0 rarw=0 */ + mtsdram( mem_devopt,0x00000000 ); /* dll=0 ds=0 (normal) */ + mtsdram( mem_wddctr,0x40000000 ); /* wrcp=0 dcd=0 */ + mtsdram( mem_clktr, 0x40000000 ); /* clkp=1 (90 deg wr) dcdt=0 */ + + /*-------------------------------------------------------------------- + * Setup for board-specific specific mem + *------------------------------------------------------------------*/ + /* + * Following for CAS Latency = 2.5 @ 133 MHz PLB + */ + mtsdram( mem_b0cr, 0x00082001 );/* SDBA=0x000, 64MB, Mode 2, enabled*/ + mtsdram( mem_tr0, 0x410a4012 );/* WR=2 WD=1 CL=2.5 PA=3 CP=4 LD=2 */ + /* RA=10 RD=3 */ + mtsdram( mem_tr1, 0x8080082f );/* SS=T2 SL=STAGE 3 CD=1 CT=0x02f */ + mtsdram( mem_rtr, 0x08200000 );/* Rate 15.625 ns @ 133 MHz PLB */ + mtsdram( mem_cfg1, 0x00000000 );/* Self-refresh exit, disable PM */ + udelay( 400 ); /* Delay 200 usecs (min) */ + + /*-------------------------------------------------------------------- + * Enable the controller, then wait for DCEN to complete + *------------------------------------------------------------------*/ + mtsdram( mem_cfg0, 0x86000000 );/* DCEN=1, PMUD=1, 64-bit */ + for(;;) + { + mfsdram( mem_mcsts, reg ); + if( reg & 0x80000000 ) + break; + } + + return( 64 * 1024 * 1024 ); /* 64 MB */ +} diff --git a/board/esd/cpci440/init.S b/board/esd/cpci440/init.S new file mode 100644 index 0000000..2dab9f9 --- /dev/null +++ b/board/esd/cpci440/init.S @@ -0,0 +1,96 @@ +/* +* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 <ppc_asm.tmpl> +#include <config.h> + +/* General */ +#define TLB_VALID 0x00000200 + +/* Supported page sizes */ + +#define SZ_1K 0x00000000 +#define SZ_4K 0x00000010 +#define SZ_16K 0x00000020 +#define SZ_64K 0x00000030 +#define SZ_256K 0x00000040 +#define SZ_1M 0x00000050 +#define SZ_16M 0x00000070 +#define SZ_256M 0x00000090 + +/* Storage attributes */ +#define SA_W 0x00000800 /* Write-through */ +#define SA_I 0x00000400 /* Caching inhibited */ +#define SA_M 0x00000200 /* Memory coherence */ +#define SA_G 0x00000100 /* Guarded */ +#define SA_E 0x00000080 /* Endian */ + +/* Access control */ +#define AC_X 0x00000024 /* Execute */ +#define AC_W 0x00000012 /* Write */ +#define AC_R 0x00000009 /* Read */ + +/* Some handy macros */ + +#define EPN(e) ((e) & 0xfffffc00) +#define TLB0(epn,sz) ( (EPN((epn)) | (sz) | TLB_VALID ) ) +#define TLB1(rpn,erpn) ( ((rpn)&0xfffffc00) | (erpn) ) +#define TLB2(a) ( (a)&0x00000fbf ) + +#define tlbtab_start\ + mflr r1 ;\ + bl 0f ; + +#define tlbtab_end\ + .long 0, 0, 0 ; \ +0: mflr r0 ; \ + mtlr r1 ; \ + blr ; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ + .long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + * Pointer to the table is returned in r1 + * + *************************************************************************/ + + .section .bootpg,"ax" + .globl tlbtab + +tlbtab: + tlbtab_start + tlbentry( 0xf0000000, SZ_256M, 0xf0000000, 1, AC_R|AC_W|AC_X|SA_G|SA_I) + tlbentry( CFG_PERIPHERAL_BASE, SZ_256M, 0x40000000, 1, AC_R|AC_W|SA_G|SA_I) + 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 ) + tlbtab_end + + diff --git a/board/esd/pci405/pci405.c b/board/esd/pci405/pci405.c new file mode 100644 index 0000000..ed86c02 --- /dev/null +++ b/board/esd/pci405/pci405.c @@ -0,0 +1,254 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <command.h> +#include <cmd_boot.h> +#include <malloc.h> +#include <pci.h> +#include <405gp_pci.h> + +/* ------------------------------------------------------------------------- */ + +#if 0 +#define FPGA_DEBUG +#endif + +#define PCI_RECONFIG_MAGIC 0x07081967 + + +struct pci_config_regs { + unsigned short command; + unsigned char latency_timer; + unsigned char int_line; + unsigned long bar1; + unsigned long bar2; + unsigned long magic; +}; + + +/* fpga configuration data - generated by bin2cc */ +const unsigned char fpgadata[] = +{ +#include "fpgadata.c" +}; + +/* + * include common fpga code (for esd boards) + */ +#include "../common/fpga.c" + + +/* Prototypes */ +int gunzip(void *, int, unsigned char *, int *); + + +int board_pre_init (void) +{ + unsigned long cntrl0Reg; + + /* + * IRQ 0-15 405GP internally generated; active high; level sensitive + * IRQ 16 405GP internally generated; active low; level sensitive + * IRQ 17-24 RESERVED + * IRQ 25 (EXT IRQ 0) CAN0; active low; level sensitive + * IRQ 26 (EXT IRQ 1) CAN1; active low; level sensitive + * IRQ 27 (EXT IRQ 2) CAN2; active low; level sensitive + * IRQ 28 (EXT IRQ 3) CAN3; active low; level sensitive + * IRQ 29 (EXT IRQ 4) unused; active low; level sensitive + * IRQ 30 (EXT IRQ 5) FPGA Timestamp; active low; level sensitive + * IRQ 31 (EXT IRQ 6) PCI Reset; active low; level sensitive + */ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/ + mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */ + mtdcr(uictr, 0x10000000); /* set int trigger levels */ + mtdcr(uicvcr, 0x00000001); /* set vect base=0,INT0 highest priority*/ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + + /* + * Setup GPIO pins (IRQ4/GPIO21 as GPIO) + */ + cntrl0Reg = mfdcr(cntrl0); + mtdcr(cntrl0, cntrl0Reg | 0x00008000); + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + +int misc_init_f (void) +{ + return 0; /* dummy implementation */ +} + + +int misc_init_r (void) +{ + unsigned char *dst; + ulong len = sizeof(fpgadata); + int status; + int index; + int i; + struct pci_config_regs *pci_regs; + + /* + * On PCI-405 the environment is saved in eeprom! + * FPGA can be gzip compressed (malloc) and booted this late. + */ + + dst = malloc(CFG_FPGA_MAX_SIZE); + if (gunzip (dst, CFG_FPGA_MAX_SIZE, (uchar *)fpgadata, (int *)&len) != 0) { + printf ("GUNZIP ERROR - must RESET board to recover\n"); + do_reset (NULL, 0, 0, NULL); + } + + status = fpga_boot(dst, len); + if (status != 0) { + printf("\nFPGA: Booting failed "); + switch (status) { + case ERROR_FPGA_PRG_INIT_LOW: + printf("(Timeout: INIT not low after asserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_INIT_HIGH: + printf("(Timeout: INIT not high after deasserting PROGRAM*)\n "); + break; + case ERROR_FPGA_PRG_DONE: + printf("(Timeout: DONE not high after programming FPGA)\n "); + break; + } + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("FPGA: %s\n", &(dst[index+1])); + index += len+3; + } + putc ('\n'); + /* delayed reboot */ + for (i=20; i>0; i--) { + printf("Rebooting in %2d seconds \r",i); + for (index=0;index<1000;index++) + udelay(1000); + } + putc ('\n'); + do_reset(NULL, 0, 0, NULL); + } + + puts("FPGA: "); + + /* display infos on fpgaimage */ + index = 15; + for (i=0; i<4; i++) { + len = dst[index]; + printf("%s ", &(dst[index+1])); + index += len+3; + } + putc ('\n'); + + /* + * Rewrite pci config regs (only after soft-reset with magic set) + */ + pci_regs = (struct pci_config_regs *)0x10; + if (pci_regs->magic == PCI_RECONFIG_MAGIC) { + puts("PCI: Found magic, rewriting config regs...\n"); + pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, + pci_regs->command); + pci_write_config_byte(PCIDEVID_405GP, PCI_LATENCY_TIMER, + pci_regs->latency_timer); + pci_write_config_byte(PCIDEVID_405GP, PCI_INTERRUPT_LINE, + pci_regs->int_line); + pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, + pci_regs->bar1); + pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, + pci_regs->bar2); + } + pci_regs->magic = 0; /* clear magic again */ + +#if 0 /* test-only */ + pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &(pci_regs->command)); + pci_read_config_byte(PCIDEVID_405GP, PCI_LATENCY_TIMER, &(pci_regs->latency_timer)); + pci_read_config_byte(PCIDEVID_405GP, PCI_INTERRUPT_LINE, &(pci_regs->int_line)); + pci_read_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_1, &(pci_regs->bar1)); + pci_read_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, &(pci_regs->bar2)); + pci_regs->magic = PCI_RECONFIG_MAGIC; /* set magic */ +#endif + + free(dst); + return (0); +} + + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + unsigned char str[64]; + int i = getenv_r ("serial#", str, sizeof(str)); + + puts ("Board: "); + + if (i == -1) { + puts ("### No HW ID - assuming CPCI405"); + } else { + puts (str); + } + putc ('\n'); + + return 0; +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + unsigned long val; + + mtdcr(memcfga, mem_mb0cf); + val = mfdcr(memcfgd); + +#if 0 + printf("\nmb0cf=%x\n", val); /* test-only */ + printf("strap=%x\n", mfdcr(strap)); /* test-only */ +#endif + + return (4*1024*1024 << ((val & 0x000e0000) >> 17)); +} + +/* ------------------------------------------------------------------------- */ + +int testdram (void) +{ + /* TODO: XXX XXX XXX */ + printf ("test: 16 MB - ok\n"); + + return (0); +} + +/* ------------------------------------------------------------------------- */ diff --git a/board/evb64260/eth_addrtbl.c b/board/evb64260/eth_addrtbl.c new file mode 100644 index 0000000..ea4925a --- /dev/null +++ b/board/evb64260/eth_addrtbl.c @@ -0,0 +1,225 @@ +#include <common.h> +#include <malloc.h> +#include <galileo/gt64260R.h> +#include <galileo/core.h> +#include <asm/cache.h> +#include "eth.h" +#include "eth_addrtbl.h" + +#define TRUE 1 +#define FALSE 0 + +#define PRINTF printf + +#ifdef CONFIG_GT_USE_MAC_HASH_TABLE + +static u32 addressTableHashMode[ GAL_ETH_DEVS ] = { 0, }; +static u32 addressTableHashSize[ GAL_ETH_DEVS ] = { 0, }; +static addrTblEntry *addressTableBase[ GAL_ETH_DEVS ] = { 0, }; +static void *realAddrTableBase[ GAL_ETH_DEVS ] = { 0, }; + +static const u32 hashLength[ 2 ] = { + (0x8000), /* 8K * 4 entries */ + (0x8000/16), /* 512 * 4 entries */ +}; + +/* Initialize the address table for a port, if needed */ +unsigned int initAddressTable( u32 port, u32 hashMode, u32 hashSizeSelector) +{ + unsigned int tableBase; + + if( port < 0 || port >= GAL_ETH_DEVS ) { + printf("%s: Invalid port number %d\n", __FUNCTION__, port ); + return 0; + } + + if (hashMode > 1) { + printf("%s: Invalid Hash Mode %d\n", __FUNCTION__, port ); + return 0; + } + + if ( realAddrTableBase[port] && + ( addressTableHashSize[port] != hashSizeSelector )) { + /* we have been here before, + * but now we want a different sized table + */ + free( realAddrTableBase[port] ); + realAddrTableBase[port] = 0; + addressTableBase[port] = 0; + + } + + tableBase = (unsigned int)addressTableBase[port]; + /* we get called for every probe, so only do this once */ + if ( !tableBase ) { + int bytes = hashLength[hashSizeSelector] * sizeof(addrTblEntry); + + tableBase = (unsigned int)realAddrTableBase[port] = malloc(bytes+64); + + if(!tableBase) + { + printf("%s: alloc memory failed \n", __FUNCTION__); + return 0; + } + + /* align to octal byte */ + if(tableBase&63) tableBase=(tableBase+63) & ~63; + + addressTableHashMode[port] = hashMode; + addressTableHashSize[port] = hashSizeSelector; + addressTableBase[port] = (addrTblEntry *)tableBase; + + memset((void *)tableBase,0,bytes); + } + + return tableBase; +} + +/* + * ---------------------------------------------------------------------------- + * This function will calculate the hash function of the address. + * depends on the hash mode and hash size. + * Inputs + * macH - the 2 most significant bytes of the MAC address. + * macL - the 4 least significant bytes of the MAC address. + * hashMode - hash mode 0 or hash mode 1. + * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800) + * Outputs + * return the calculated entry. + */ +u32 +hashTableFunction( u32 macH, u32 macL, u32 HashSize, u32 hash_mode) +{ + u32 hashResult; + u32 addrH; + u32 addrL; + u32 addr0; + u32 addr1; + u32 addr2; + u32 addr3; + u32 addrHSwapped; + u32 addrLSwapped; + + + addrH = NIBBLE_SWAPPING_16_BIT( macH ); + addrL = NIBBLE_SWAPPING_32_BIT( macL ); + + addrHSwapped = FLIP_4_BITS( addrH & 0xf ) + + ((FLIP_4_BITS( (addrH >> 4) & 0xf)) << 4) + + ((FLIP_4_BITS( (addrH >> 8) & 0xf)) << 8) + + ((FLIP_4_BITS( (addrH >> 12) & 0xf)) << 12); + + addrLSwapped = FLIP_4_BITS( addrL & 0xf ) + + ((FLIP_4_BITS( (addrL >> 4) & 0xf)) << 4) + + ((FLIP_4_BITS( (addrL >> 8) & 0xf)) << 8) + + ((FLIP_4_BITS( (addrL >> 12) & 0xf)) << 12) + + ((FLIP_4_BITS( (addrL >> 16) & 0xf)) << 16) + + ((FLIP_4_BITS( (addrL >> 20) & 0xf)) << 20) + + ((FLIP_4_BITS( (addrL >> 24) & 0xf)) << 24) + + ((FLIP_4_BITS( (addrL >> 28) & 0xf)) << 28); + + addrH = addrHSwapped; + addrL = addrLSwapped; + + if( hash_mode == 0 ) { + addr0 = (addrL >> 2) & 0x03f; + addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2; + addr2 = (addrL >> 15) & 0x1ff; + addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8); + } else { + addr0 = FLIP_6_BITS( addrL & 0x03f ); + addr1 = FLIP_9_BITS( ((addrL >> 6) & 0x1ff)); + addr2 = FLIP_9_BITS( (addrL >> 15) & 0x1ff); + addr3 = FLIP_9_BITS( (((addrL >> 24) & 0x0ff) | ((addrH & 0x1) << 8))); + } + + hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3); + + if( HashSize == _8K_TABLE ) { + hashResult = hashResult & 0xffff; + } else { + hashResult = hashResult & 0x07ff; + } + + return( hashResult ); +} + + +/* + * ---------------------------------------------------------------------------- + * This function will add an entry to the address table. + * depends on the hash mode and hash size that was initialized. + * Inputs + * port - ETHERNET port number. + * macH - the 2 most significant bytes of the MAC address. + * macL - the 4 least significant bytes of the MAC address. + * skip - if 1, skip this address. + * rd - the RD field in the address table. + * Outputs + * address table entry is added. + * TRUE if success. + * FALSE if table full + */ +int +addAddressTableEntry( + u32 port, + u32 macH, + u32 macL, + u32 rd, + u32 skip ) +{ + addrTblEntry *entry; + u32 newHi; + u32 newLo; + u32 i; + + newLo = (((macH >> 4) & 0xf) << 15) + | (((macH >> 0) & 0xf) << 11) + | (((macH >> 12) & 0xf) << 7) + | (((macH >> 8) & 0xf) << 3) + | (((macL >> 20) & 0x1) << 31) + | (((macL >> 16) & 0xf) << 27) + | (((macL >> 28) & 0xf) << 23) + | (((macL >> 24) & 0xf) << 19) + | (skip << SKIP_BIT) | (rd << 2) | VALID; + + newHi = (((macL >> 4) & 0xf) << 15) + | (((macL >> 0) & 0xf) << 11) + | (((macL >> 12) & 0xf) << 7) + | (((macL >> 8) & 0xf) << 3) + | (((macL >> 21) & 0x7) << 0); + + /* + * Pick the appropriate table, start scanning for free/reusable + * entries at the index obtained by hashing the specified MAC address + */ + entry = addressTableBase[port]; + entry += hashTableFunction( macH, macL, addressTableHashSize[port], + addressTableHashMode[port] ); + for( i = 0; i < HOP_NUMBER; i++, entry++ ) { + if( !(entry->lo & VALID) /*|| (entry->lo & SKIP)*/ ) { + break; + } else { /* if same address put in same position */ + if( ((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8)) + && (entry->hi == newHi) ) + { + break; + } + } + } + + if( i == HOP_NUMBER ) { + PRINTF( "addGT64260addressTableEntry: table section is full\n" ); + return( FALSE ); + } + + /* + * Update the selected entry + */ + entry->hi = newHi; + entry->lo = newLo; + DCACHE_FLUSH_N_SYNC( (u32)entry, MAC_ENTRY_SIZE ); + return( TRUE ); +} + +#endif /* CONFIG_GT_USE_MAC_HASH_TABLE */ diff --git a/board/evb64260/pci.c b/board/evb64260/pci.c new file mode 100644 index 0000000..8e9178d --- /dev/null +++ b/board/evb64260/pci.c @@ -0,0 +1,691 @@ +/* PCI.c - PCI functions */ + +/* Copyright - Galileo technology. */ + +#include <common.h> +#include <pci.h> + +#include <galileo/pci.h> + +static const unsigned char pci_irq_swizzle[2][PCI_MAX_DEVICES] = { +#ifdef CONFIG_ZUMA_V2 + {0,0,0,0,0,0,0,29, [8 ... PCI_MAX_DEVICES-1]=0}, + {0,0,0,0,0,0,0,28, [8 ... PCI_MAX_DEVICES-1]=0} +#else /* EVB??? This is a guess */ + {0,0,0,0,0,0,0,27,27, [9 ... PCI_MAX_DEVICES-1]=0}, + {0,0,0,0,0,0,0,29,29, [9 ... PCI_MAX_DEVICES-1]=0} +#endif +}; + +static const unsigned int pci_p2p_configuration_reg[]={ + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION}; + +static const unsigned int pci_configuration_address[]={ + PCI_0CONFIGURATION_ADDRESS, PCI_1CONFIGURATION_ADDRESS}; + +static const unsigned int pci_configuration_data[]={ + PCI_0CONFIGURATION_DATA_VIRTUAL_REGISTER, + PCI_1CONFIGURATION_DATA_VIRTUAL_REGISTER}; + +static const unsigned int pci_error_cause_reg[]={ + PCI_0ERROR_CAUSE, PCI_1ERROR_CAUSE}; + +static const unsigned int pci_arbiter_control[]={ + PCI_0ARBITER_CONTROL, PCI_1ARBITER_CONTROL}; + +static const unsigned int pci_snoop_control_base_0_low[]={ + PCI_0SNOOP_CONTROL_BASE_0_LOW, PCI_1SNOOP_CONTROL_BASE_0_LOW}; +static const unsigned int pci_snoop_control_top_0[]={ + PCI_0SNOOP_CONTROL_TOP_0, PCI_1SNOOP_CONTROL_TOP_0}; + +static const unsigned int pci_access_control_base_0_low[]={ + PCI_0ACCESS_CONTROL_BASE_0_LOW, PCI_1ACCESS_CONTROL_BASE_0_LOW}; +static const unsigned int pci_access_control_top_0[]={ + PCI_0ACCESS_CONTROL_TOP_0, PCI_1ACCESS_CONTROL_TOP_0}; + +static const unsigned int pci_scs_bank_size[2][4] = { + {PCI_0SCS_0_BANK_SIZE, PCI_0SCS_1_BANK_SIZE, + PCI_0SCS_2_BANK_SIZE, PCI_0SCS_3_BANK_SIZE}, + {PCI_1SCS_0_BANK_SIZE, PCI_1SCS_1_BANK_SIZE, + PCI_1SCS_2_BANK_SIZE, PCI_1SCS_3_BANK_SIZE}}; + +static const unsigned int pci_p2p_configuration[] = { + PCI_0P2P_CONFIGURATION, PCI_1P2P_CONFIGURATION}; + +/******************************************************************** +* pciWriteConfigReg - Write to a PCI configuration register +* - Make sure the GT is configured as a master before writing +* to another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* +* +* Inputs: unsigned int regOffset: The register offset as it apears in the GT spec +* (or any other PCI device spec) +* pciDevNum: The device number needs to be addressed. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +void pciWriteConfigReg(PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum,unsigned int data) +{ + volatile unsigned int DataForAddrReg; + unsigned int functionNum; + unsigned int busNum = 0; + unsigned int addr; + + if(pciDevNum > 32) /* illegal device Number */ + return; + if(pciDevNum == SELF) /* configure our configuration space. */ + { + pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f; + busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = ( regOffset | pciDevNum | functionNum | busNum) | BIT31; + GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg); + GT_REG_READ(pci_configuration_address[host], &addr); + if (addr != DataForAddrReg) return; + GT_REG_WRITE(pci_configuration_data[host],data); +} + +/******************************************************************** +* pciReadConfigReg - Read from a PCI0 configuration register +* - Make sure the GT is configured as a master before reading +* from another device on the PCI. +* - The function takes care of Big/Little endian conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec) +* pciDevNum: The device number needs to be addressed. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|00| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciReadConfigReg (PCI_HOST host, unsigned int regOffset,unsigned int pciDevNum) +{ + volatile unsigned int DataForAddrReg; + unsigned int data; + unsigned int functionNum; + unsigned int busNum = 0; + + if(pciDevNum > 32) /* illegal device Number */ + return 0xffffffff; + if(pciDevNum == SELF) /* configure our configuration space. */ + { + pciDevNum = (GTREGREAD(pci_p2p_configuration_reg[host]) >> 24) & 0x1f; + busNum = GTREGREAD(pci_p2p_configuration_reg[host]) & 0xff0000; + } + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xfc; + DataForAddrReg = (regOffset | pciDevNum | functionNum | busNum) | BIT31 ; + GT_REG_WRITE(pci_configuration_address[host],DataForAddrReg); + GT_REG_READ(pci_configuration_address[host], &data); + if (data != DataForAddrReg) + return 0xffffffff; + GT_REG_READ(pci_configuration_data[host], &data); + return data; +} + +/******************************************************************** +* pciOverBridgeWriteConfigReg - Write to a PCI configuration register where +* the agent is placed on another Bus. For more +* information read P2P in the PCI spec. +* +* Inputs: unsigned int regOffset - The register offset as it apears in the +* GT spec (or any other PCI device spec). +* unsigned int pciDevNum - The device number needs to be addressed. +* unsigned int busNum - On which bus does the Target agent connect +* to. +* unsigned int data - data to be written. +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +* The configuration Address is configure as type-I (bits[1:0] = '01') due to +* PCI spec referring to P2P. +* +*********************************************************************/ +void pciOverBridgeWriteConfigReg(PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum,unsigned int data) +{ + unsigned int DataForReg; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if(pciDevNum == SELF) /* This board */ + { + DataForReg = ( regOffset | pciDevNum | functionNum) | BIT0; + } + else + { + DataForReg = ( regOffset | pciDevNum | functionNum | busNum) | + BIT31 | BIT0; + } + GT_REG_WRITE(pci_configuration_address[host],DataForReg); + if(pciDevNum == SELF) /* This board */ + { + GT_REG_WRITE(pci_configuration_data[host],data); + } + else /* configuration Transaction over the pci. */ + { + /* The PCI is working in LE Mode So it swap the Data. */ + GT_REG_WRITE(pci_configuration_data[host],WORD_SWAP(data)); + } +} + + +/******************************************************************** +* pciOverBridgeReadConfigReg - Read from a PCIn configuration register where +* the agent target locate on another PCI bus. +* - Make sure the GT is configured as a master +* before reading from another device on the PCI. +* - The function takes care of Big/Little endian +* conversion. +* INPUTS: regOffset: The register offset as it apears in the GT spec (or PCI +* spec). (configuration register offset.) +* pciDevNum: The device number needs to be addressed. +* busNum: the Bus number where the agent is place. +* RETURNS: data , if the data == 0xffffffff check the master abort bit in the +* cause register to make sure the data is valid +* +* Configuration Address 0xCF8: +* +* 31 30 24 23 16 15 11 10 8 7 2 0 <=bit Number +* |congif|Reserved| Bus |Device|Function|Register|01| +* |Enable| |Number|Number| Number | Number | | <=field Name +* +*********************************************************************/ +unsigned int pciOverBridgeReadConfigReg(PCI_HOST host, + unsigned int regOffset, + unsigned int pciDevNum, + unsigned int busNum) +{ + unsigned int DataForReg; + unsigned int data; + unsigned int functionNum; + + functionNum = regOffset & 0x00000700; + pciDevNum = pciDevNum << 11; + regOffset = regOffset & 0xff; + busNum = busNum << 16; + if (pciDevNum == SELF) /* This board */ + { + DataForReg = (regOffset | pciDevNum | functionNum) | BIT31 ; + } + else /* agent on another bus */ + { + DataForReg = (regOffset | pciDevNum | functionNum | busNum) | + BIT0 | BIT31 ; + } + GT_REG_WRITE(pci_configuration_address[host],DataForReg); + if (pciDevNum == SELF) /* This board */ + { + GT_REG_READ(pci_configuration_data[host], &data); + return data; + } + else /* The PCI is working in LE Mode So it swap the Data. */ + { + GT_REG_READ(pci_configuration_data[host], &data); + return WORD_SWAP(data); + } +} + +/******************************************************************** +* pciGetRegOffset - Gets the register offset for this region config. +* +* INPUT: Bus, Region - The bus and region we ask for its base address. +* OUTPUT: N/A +* RETURNS: PCI register base address +*********************************************************************/ +static unsigned int pciGetRegOffset(PCI_HOST host, PCI_REGION region) +{ + switch (host) + { + case PCI_HOST0: + switch(region) { + case PCI_IO: return PCI_0I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: return PCI_0MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: return PCI_0MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: return PCI_0MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: return PCI_0MEMORY3_LOW_DECODE_ADDRESS; + } + case PCI_HOST1: + switch(region) { + case PCI_IO: return PCI_1I_O_LOW_DECODE_ADDRESS; + case PCI_REGION0: return PCI_1MEMORY0_LOW_DECODE_ADDRESS; + case PCI_REGION1: return PCI_1MEMORY1_LOW_DECODE_ADDRESS; + case PCI_REGION2: return PCI_1MEMORY2_LOW_DECODE_ADDRESS; + case PCI_REGION3: return PCI_1MEMORY3_LOW_DECODE_ADDRESS; + } + } + return PCI_0MEMORY0_LOW_DECODE_ADDRESS; +} + +static unsigned int pciGetRemapOffset(PCI_HOST host, PCI_REGION region) +{ + switch (host) + { + case PCI_HOST0: + switch(region) { + case PCI_IO: return PCI_0I_O_ADDRESS_REMAP; + case PCI_REGION0: return PCI_0MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: return PCI_0MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: return PCI_0MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: return PCI_0MEMORY3_ADDRESS_REMAP; + } + case PCI_HOST1: + switch(region) { + case PCI_IO: return PCI_1I_O_ADDRESS_REMAP; + case PCI_REGION0: return PCI_1MEMORY0_ADDRESS_REMAP; + case PCI_REGION1: return PCI_1MEMORY1_ADDRESS_REMAP; + case PCI_REGION2: return PCI_1MEMORY2_ADDRESS_REMAP; + case PCI_REGION3: return PCI_1MEMORY3_ADDRESS_REMAP; + } + } + return PCI_0MEMORY0_ADDRESS_REMAP; +} + +bool pciMapSpace(PCI_HOST host, PCI_REGION region, unsigned int remapBase, unsigned int bankBase,unsigned int bankLength) +{ + unsigned int low=0xfff; + unsigned int high=0x0; + unsigned int regOffset=pciGetRegOffset(host, region); + unsigned int remapOffset=pciGetRemapOffset(host, region); + + if(bankLength!=0) { + low = (bankBase >> 20) & 0xfff; + high=((bankBase+bankLength)>>20)-1; + } + + GT_REG_WRITE(regOffset, low | (1<<24)); /* no swapping */ + GT_REG_WRITE(regOffset+8, high); + + if(bankLength!=0) { /* must do AFTER writing maps */ + GT_REG_WRITE(remapOffset, remapBase>>20); /* sorry, 32 bits only. + dont support upper 32 + in this driver */ + } + return true; +} + +unsigned int pciGetSpaceBase(PCI_HOST host, PCI_REGION region) +{ + unsigned int low; + unsigned int regOffset=pciGetRegOffset(host, region); + GT_REG_READ(regOffset,&low); + return (low&0xfff)<<20; +} + +unsigned int pciGetSpaceSize(PCI_HOST host, PCI_REGION region) +{ + unsigned int low,high; + unsigned int regOffset=pciGetRegOffset(host, region); + GT_REG_READ(regOffset,&low); + GT_REG_READ(regOffset+8,&high); + high&=0xfff; + low&=0xfff; + if(high<=low) return 0; + return (high+1-low)<<20; +} + +/******************************************************************** +* pciMapMemoryBank - Maps PCI_host memory bank "bank" for the slave. +* +* Inputs: base and size of PCI SCS +*********************************************************************/ +void pciMapMemoryBank(PCI_HOST host, MEMORY_BANK bank, unsigned int pciDramBase,unsigned int pciDramSize) +{ + pciDramBase = pciDramBase & 0xfffff000; + pciDramBase = pciDramBase | (pciReadConfigReg(host, + PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF) & 0x00000fff); + pciWriteConfigReg(host,PCI_SCS_0_BASE_ADDRESS + 4*bank,SELF,pciDramBase); + if(pciDramSize == 0) + pciDramSize ++; + GT_REG_WRITE(pci_scs_bank_size[host][bank], pciDramSize-1); +} + + +/******************************************************************** +* pciSetRegionFeatures - This function modifys one of the 8 regions with +* feature bits given as an input. +* - Be advised to check the spec before modifying them. +* Inputs: PCI_PROTECT_REGION region - one of the eight regions. +* unsigned int features - See file: pci.h there are defintion for those +* region features. +* unsigned int baseAddress - The region base Address. +* unsigned int topAddress - The region top Address. +* Returns: false if one of the parameters is erroneous true otherwise. +*********************************************************************/ +bool pciSetRegionFeatures(PCI_HOST host, PCI_ACCESS_REGIONS region,unsigned int features, + unsigned int baseAddress,unsigned int regionLength) +{ + unsigned int accessLow; + unsigned int accessHigh; + unsigned int accessTop = baseAddress + regionLength; + + if(regionLength == 0) /* close the region. */ + { + pciDisableAccessRegion(host, region); + return true; + } + /* base Address is store is bits [11:0] */ + accessLow = (baseAddress & 0xfff00000) >> 20; + /* All the features are update according to the defines in pci.h (to be on + the safe side we disable bits: [11:0] */ + accessLow = accessLow | (features & 0xfffff000); + /* write to the Low Access Region register */ + GT_REG_WRITE( pci_access_control_base_0_low[host] + 0x10*region,accessLow); + + accessHigh = (accessTop & 0xfff00000) >> 20; + + /* write to the High Access Region register */ + GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,accessHigh - 1); + return true; +} + +/******************************************************************** +* pciDisableAccessRegion - Disable The given Region by writing MAX size +* to its low Address and MIN size to its high Address. +* +* Inputs: PCI_ACCESS_REGIONS region - The region we to be Disabled. +* Returns: N/A. +*********************************************************************/ +void pciDisableAccessRegion(PCI_HOST host, PCI_ACCESS_REGIONS region) +{ + /* writing back the registers default values. */ + GT_REG_WRITE(pci_access_control_base_0_low[host] + 0x10*region,0x01001fff); + GT_REG_WRITE(pci_access_control_top_0[host] + 0x10*region,0); +} + +/******************************************************************** +* pciArbiterEnable - Enables PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true. +*********************************************************************/ +bool pciArbiterEnable(PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ(pci_arbiter_control[host],®Data); + GT_REG_WRITE(pci_arbiter_control[host],regData | BIT31); + return true; +} + +/******************************************************************** +* pciArbiterDisable - Disable PCI-0`s Arbitration mechanism. +* +* Inputs: N/A +* Returns: true +*********************************************************************/ +bool pciArbiterDisable(PCI_HOST host) +{ + unsigned int regData; + + GT_REG_READ(pci_arbiter_control[host],®Data); + GT_REG_WRITE(pci_arbiter_control[host],regData & 0x7fffffff); + return true; +} + +/******************************************************************** +* pciParkingDisable - Park on last option disable, with this function you can +* disable the park on last mechanism for each agent. +* disabling this option for all agents results parking +* on the internal master. +* +* Inputs: PCI_AGENT_PARK internalAgent - parking Disable for internal agent. +* PCI_AGENT_PARK externalAgent0 - parking Disable for external#0 agent. +* PCI_AGENT_PARK externalAgent1 - parking Disable for external#1 agent. +* PCI_AGENT_PARK externalAgent2 - parking Disable for external#2 agent. +* PCI_AGENT_PARK externalAgent3 - parking Disable for external#3 agent. +* PCI_AGENT_PARK externalAgent4 - parking Disable for external#4 agent. +* PCI_AGENT_PARK externalAgent5 - parking Disable for external#5 agent. +* Returns: true +*********************************************************************/ +bool pciParkingDisable(PCI_HOST host, PCI_AGENT_PARK internalAgent, + PCI_AGENT_PARK externalAgent0, + PCI_AGENT_PARK externalAgent1, + PCI_AGENT_PARK externalAgent2, + PCI_AGENT_PARK externalAgent3, + PCI_AGENT_PARK externalAgent4, + PCI_AGENT_PARK externalAgent5) +{ + unsigned int regData; + unsigned int writeData; + + GT_REG_READ(pci_arbiter_control[host],®Data); + writeData = (internalAgent << 14) + (externalAgent0 << 15) + \ + (externalAgent1 << 16) + (externalAgent2 << 17) + \ + (externalAgent3 << 18) + (externalAgent4 << 19) + \ + (externalAgent5 << 20); + regData = (regData & ~(0x7f<<14)) | writeData; + GT_REG_WRITE(pci_arbiter_control[host],regData); + return true; +} + +/******************************************************************** +* pciSetRegionSnoopMode - This function modifys one of the 4 regions which +* supports Cache Coherency in the PCI_n interface. +* Inputs: region - One of the four regions. +* snoopType - There is four optional Types: +* 1. No Snoop. +* 2. Snoop to WT region. +* 3. Snoop to WB region. +* 4. Snoop & Invalidate to WB region. +* baseAddress - Base Address of this region. +* regionLength - Region length. +* Returns: false if one of the parameters is wrong otherwise return true. +*********************************************************************/ +bool pciSetRegionSnoopMode(PCI_HOST host, PCI_SNOOP_REGION region,PCI_SNOOP_TYPE snoopType, + unsigned int baseAddress, + unsigned int regionLength) +{ + unsigned int snoopXbaseAddress; + unsigned int snoopXtopAddress; + unsigned int data; + unsigned int snoopHigh = baseAddress + regionLength; + + if( (region > PCI_SNOOP_REGION3) || (snoopType > PCI_SNOOP_WB) ) + return false; + snoopXbaseAddress = pci_snoop_control_base_0_low[host] + 0x10 * region; + snoopXtopAddress = pci_snoop_control_top_0[host] + 0x10 * region; + if(regionLength == 0) /* closing the region */ + { + GT_REG_WRITE(snoopXbaseAddress,0x0000ffff); + GT_REG_WRITE(snoopXtopAddress,0); + return true; + } + baseAddress = baseAddress & 0xfff00000; /* Granularity of 1MByte */ + data = (baseAddress >> 20) | snoopType << 12; + GT_REG_WRITE(snoopXbaseAddress,data); + snoopHigh = (snoopHigh & 0xfff00000) >> 20; + GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1); + return true; +} + +/* + * + */ + +static int gt_read_config_dword(struct pci_controller *hose, + pci_dev_t dev, + int offset, u32* value) +{ + *value = pciReadConfigReg((PCI_HOST) hose->cfg_addr, offset, PCI_DEV(dev)); + return 0; +} + +static int gt_write_config_dword(struct pci_controller *hose, + pci_dev_t dev, + int offset, u32 value) +{ + pciWriteConfigReg((PCI_HOST)hose->cfg_addr, offset, PCI_DEV(dev), value); + return 0; +} + +/* + * + */ + +static void gt_setup_ide(struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ + static const int ide_bar[]={8,4,8,4,0,0}; + u32 bar_response, bar_value; + int bar; + + for (bar=0; bar<6; bar++) + { + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, 0x0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, &bar_response); + + pciauto_region_allocate(bar_response & PCI_BASE_ADDRESS_SPACE_IO ? + hose->pci_io : hose->pci_mem, ide_bar[bar], &bar_value); + + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar*4, bar_value); + } +} + +static void gt_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char pin, irq; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + + if(pin == 1) { /* only allow INT A */ + irq = pci_irq_swizzle[(PCI_HOST)hose->cfg_addr][PCI_DEV(dev)]; + if(irq) + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); + } +} + +struct pci_config_table gt_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_STORAGE_IDE, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, gt_setup_ide}, + + { } +}; + +struct pci_controller pci0_hose = { + fixup_irq: gt_fixup_irq, + config_table: gt_config_table, +}; + +struct pci_controller pci1_hose = { + fixup_irq: gt_fixup_irq, + config_table: gt_config_table, +}; + +void +pci_init(void) +{ + unsigned int command; + + pci0_hose.first_busno = 0; + pci0_hose.last_busno = 0xff; + + /* PCI memory space */ + pci_set_region(pci0_hose.regions + 0, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_0_MEM_SPACE, + CFG_PCI0_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(pci0_hose.regions + 1, + CFG_PCI0_IO_SPACE_PCI, + CFG_PCI0_IO_SPACE, + CFG_PCI0_IO_SIZE, + PCI_REGION_IO); + + pci_set_ops(&pci0_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + + pci0_hose.region_count = 2; + + pci0_hose.cfg_addr = (unsigned int*) PCI_HOST0; + + pci_register_hose(&pci0_hose); + + pciArbiterEnable(PCI_HOST0); + pciParkingDisable(PCI_HOST0,1,1,1,1,1,1,1); + + command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command); + + pci0_hose.last_busno = pci_hose_scan(&pci0_hose); + + command = pciReadConfigReg(PCI_HOST0, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg(PCI_HOST0, PCI_COMMAND, SELF, command); + + pci1_hose.first_busno = pci0_hose.last_busno + 1; + pci1_hose.last_busno = 0xff; + + /* PCI memory space */ + pci_set_region(pci1_hose.regions + 0, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_0_MEM_SPACE, + CFG_PCI1_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(pci1_hose.regions + 1, + CFG_PCI1_IO_SPACE_PCI, + CFG_PCI1_IO_SPACE, + CFG_PCI1_IO_SIZE, + PCI_REGION_IO); + + pci_set_ops(&pci1_hose, + pci_hose_read_config_byte_via_dword, + pci_hose_read_config_word_via_dword, + gt_read_config_dword, + pci_hose_write_config_byte_via_dword, + pci_hose_write_config_word_via_dword, + gt_write_config_dword); + + pci1_hose.region_count = 2; + + pci1_hose.cfg_addr = (unsigned int*) PCI_HOST1; + + pci_register_hose(&pci1_hose); + + pciArbiterEnable(PCI_HOST1); + pciParkingDisable(PCI_HOST1,1,1,1,1,1,1,1); + + command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MASTER; + pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command); + + pci1_hose.last_busno = pci_hose_scan(&pci1_hose); + + command = pciReadConfigReg(PCI_HOST1, PCI_COMMAND, SELF); + command |= PCI_COMMAND_MEMORY; + pciWriteConfigReg(PCI_HOST1, PCI_COMMAND, SELF, command); +} diff --git a/board/evb64260/sdram_init.c b/board/evb64260/sdram_init.c new file mode 100644 index 0000000..ff98e4d --- /dev/null +++ b/board/evb64260/sdram_init.c @@ -0,0 +1,629 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* sdram_init.c - automatic memory sizing */ + +#include <common.h> +#include <74xx_7xx.h> +#include <galileo/memory.h> +#include <galileo/pci.h> +#include <galileo/gt64260R.h> +#include <net.h> + +#include "eth.h" +#include "mpsc.h" +#include "i2c.h" +#include "64260.h" + +/* #define DEBUG */ +#define MAP_PCI + +#ifdef DEBUG +#define DP(x) x +#else +#define DP(x) +#endif + +#define GB (1 << 30) + +/* structure to store the relevant information about an sdram bank */ +typedef struct sdram_info { + uchar drb_size; + uchar registered, ecc; + uchar tpar; + uchar tras_clocks; + uchar burst_len; + uchar banks, slot; + int size; /* detected size, not from I2C but from dram_size() */ +} sdram_info_t; + +#ifdef DEBUG +void dump_dimm_info(struct sdram_info *d) +{ + static const char *ecc_legend[]={""," Parity"," ECC"}; + printf("dimm%s %sDRAM: %dMibytes:\n", + ecc_legend[d->ecc], + d->registered?"R":"", + (d->size>>20)); + printf(" drb=%d tpar=%d tras=%d burstlen=%d banks=%d slot=%d\n", + d->drb_size, d->tpar, d->tras_clocks, d->burst_len, + d->banks, d->slot); +} +#endif + +static int +memory_map_bank(unsigned int bankNo, + unsigned int bankBase, + unsigned int bankLength) +{ +#ifdef DEBUG + if (bankLength > 0) { + printf("mapping bank %d at %08x - %08x\n", + bankNo, bankBase, bankBase + bankLength - 1); + } else { + printf("unmapping bank %d\n", bankNo); + } +#endif + + memoryMapBank(bankNo, bankBase, bankLength); + + return 0; +} + +#ifdef MAP_PCI +static int +memory_map_bank_pci(unsigned int bankNo, + unsigned int bankBase, + unsigned int bankLength) +{ + PCI_HOST host; + for (host=PCI_HOST0;host<=PCI_HOST1;host++) { + const int features= + PREFETCH_ENABLE | + DELAYED_READ_ENABLE | + AGGRESSIVE_PREFETCH | + READ_LINE_AGGRESSIVE_PREFETCH | + READ_MULTI_AGGRESSIVE_PREFETCH | + MAX_BURST_4 | + PCI_NO_SWAP; + + pciMapMemoryBank(host, bankNo, bankBase, bankLength); + + pciSetRegionSnoopMode(host, bankNo, PCI_SNOOP_WB, bankBase, + bankLength); + + pciSetRegionFeatures(host, bankNo, features, bankBase, bankLength); + } + return 0; +} +#endif + +/* ------------------------------------------------------------------------- */ + +/* much of this code is based on (or is) the code in the pip405 port */ +/* thanks go to the authors of said port - Josh */ + + +/* + * translate ns.ns/10 coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short +NS10to10PS(unsigned char spd_byte) +{ + unsigned short ns, ns10; + + /* isolate upper nibble */ + ns = (spd_byte >> 4) & 0x0F; + /* isolate lower nibble */ + ns10 = (spd_byte & 0x0F); + + return(ns*100 + ns10*10); +} + +/* + * translate ns coding of SPD timing values + * into 10 ps unit values + */ +static inline unsigned short +NSto10PS(unsigned char spd_byte) +{ + return(spd_byte*100); +} + +#ifdef CONFIG_ZUMA_V2 +static int +check_dimm(uchar slot, sdram_info_t *info) +{ + /* assume 2 dimms, 2 banks each 256M - we dont have an + * dimm i2c so rely on the detection routines later */ + + memset(info, 0, sizeof(*info)); + + info->slot = slot; + info->banks = 2; /* Detect later */ + info->registered = 0; + info->drb_size = 32; /* 16 - 256MBit, 32 - 512MBit + but doesn't matter, both do same + thing in setup_sdram() */ + info->tpar = 3; + info->tras_clocks = 5; + info->burst_len = 4; +#ifdef CONFIG_ECC + info->ecc = 0; /* Detect later */ +#endif /* CONFIG_ECC */ + return 0; +} + +#else /* ! CONFIG_ZUMA_V2 */ + +/* This code reads the SPD chip on the sdram and populates + * the array which is passed in with the relevant information */ +static int +check_dimm(uchar slot, sdram_info_t *info) +{ + DECLARE_GLOBAL_DATA_PTR; + uchar addr = slot == 0 ? DIMM0_I2C_ADDR : DIMM1_I2C_ADDR; + int ret; + uchar rows, cols, sdram_banks, supp_cal, width, cal_val; + ulong tmemclk; + uchar trp_clocks, trcd_clocks; + uchar data[128]; + + get_clocks (); + + tmemclk = 1000000000 / (gd->bus_clk / 100); /* in 10 ps units */ + +#ifdef CONFIG_EVB64260_750CX + if (0 != slot) { + printf("check_dimm: The EVB-64260-750CX only has 1 DIMM,"); + printf(" called with slot=%d insetad!\n", slot); + return 0; + } +#endif + DP(puts("before i2c read\n")); + + ret = i2c_read(addr, 0, 128, data, 0); + + DP(puts("after i2c read\n")); + + /* zero all the values */ + memset(info, 0, sizeof(*info)); + + if (ret) { + DP(printf("No DIMM in slot %d [err = %x]\n", slot, ret)); + return 0; + } + + /* first, do some sanity checks */ + if (data[2] != 0x4) { + printf("Not SDRAM in slot %d\n", slot); + return 0; + } + + /* get various information */ + rows = data[3]; + cols = data[4]; + info->banks = data[5]; + sdram_banks = data[17]; + width = data[13] & 0x7f; + + DP(printf("sdram_banks: %d, banks: %d\n", sdram_banks, info->banks)); + + /* check if the memory is registered */ + if (data[21] & (BIT1 | BIT4)) + info->registered = 1; + +#ifdef CONFIG_ECC + /* check for ECC/parity [0 = none, 1 = parity, 2 = ecc] */ + info->ecc = (data[11] & 2) >> 1; +#endif + + /* bit 1 is CL2, bit 2 is CL3 */ + supp_cal = (data[18] & 0x6) >> 1; + + /* compute the relevant clock values */ + trp_clocks = (NSto10PS(data[27])+(tmemclk-1)) / tmemclk; + trcd_clocks = (NSto10PS(data[29])+(tmemclk-1)) / tmemclk; + info->tras_clocks = (NSto10PS(data[30])+(tmemclk-1)) / tmemclk; + + DP(printf("trp = %d\ntrcd_clocks = %d\ntras_clocks = %d\n", + trp_clocks, trcd_clocks, info->tras_clocks)); + + /* try a CAS latency of 3 first... */ + cal_val = 0; + if (supp_cal & 3) { + if (NS10to10PS(data[9]) <= tmemclk) + cal_val = 3; + } + + /* then 2... */ + if (supp_cal & 2) { + if (NS10to10PS(data[23]) <= tmemclk) + cal_val = 2; + } + + DP(printf("cal_val = %d\n", cal_val)); + + /* bummer, did't work... */ + if (cal_val == 0) { + DP(printf("Couldn't find a good CAS latency\n")); + return 0; + } + + /* get the largest delay -- these values need to all be the same + * see Res#6 */ + info->tpar = cal_val; + if (trp_clocks > info->tpar) + info->tpar = trp_clocks; + if (trcd_clocks > info->tpar) + info->tpar = trcd_clocks; + + DP(printf("tpar set to: %d\n", info->tpar)); + +#ifdef CFG_BROKEN_CL2 + if (info->tpar == 2){ + info->tpar = 3; + DP(printf("tpar fixed-up to: %d\n", info->tpar)); + } +#endif + /* compute the module DRB size */ + info->drb_size = (((1 << (rows + cols)) * sdram_banks) * width) / _16M; + + DP(printf("drb_size set to: %d\n", info->drb_size)); + + /* find the burst len */ + info->burst_len = data[16] & 0xf; + if ((info->burst_len & 8) == 8) { + info->burst_len = 1; + } else if ((info->burst_len & 4) == 4) { + info->burst_len = 0; + } else { + return 0; + } + + info->slot = slot; + return 0; +} +#endif /* ! CONFIG_ZUMA_V2 */ + +static int +setup_sdram_common(sdram_info_t info[2]) +{ + ulong tmp; + int tpar=2, tras_clocks=5, registered=1, ecc=2; + + if(!info[0].banks && !info[1].banks) return 0; + + if(info[0].banks) { + if(info[0].tpar>tpar) tpar=info[0].tpar; + if(info[0].tras_clocks>tras_clocks) tras_clocks=info[0].tras_clocks; + if(!info[0].registered) registered=0; + if(info[0].ecc!=2) ecc=0; + } + + if(info[1].banks) { + if(info[1].tpar>tpar) tpar=info[1].tpar; + if(info[1].tras_clocks>tras_clocks) tras_clocks=info[1].tras_clocks; + if(!info[1].registered) registered=0; + if(info[1].ecc!=2) ecc=0; + } + + /* SDRAM configuration */ + tmp = GTREGREAD(SDRAM_CONFIGURATION); + + /* Turn on physical interleave if both DIMMs + * have even numbers of banks. */ + if( (info[0].banks == 0 || info[0].banks == 2) && + (info[1].banks == 0 || info[1].banks == 2) ) { + /* physical interleave on */ + tmp &= ~(1 << 15); + } else { + /* physical interleave off */ + tmp |= (1 << 15); + } + + tmp |= (registered << 17); + + /* Use buffer 1 to return read data to the CPU + * See Res #12 */ + tmp |= (1 << 26); + + GT_REG_WRITE(SDRAM_CONFIGURATION, tmp); + DP(printf("SDRAM config: %08x\n", + GTREGREAD(SDRAM_CONFIGURATION))); + + /* SDRAM timing */ + tmp = (((tpar == 3) ? 2 : 1) | + (((tpar == 3) ? 2 : 1) << 2) | + (((tpar == 3) ? 2 : 1) << 4) | + (tras_clocks << 8)); + +#ifdef CONFIG_ECC + /* Setup ECC */ + if (ecc == 2) tmp |= 1<<13; +#endif /* CONFIG_ECC */ + + GT_REG_WRITE(SDRAM_TIMING, tmp); + DP(printf("SDRAM timing: %08x (%d,%d,%d,%d)\n", + GTREGREAD(SDRAM_TIMING), tpar,tpar,tpar,tras_clocks)); + + /* SDRAM address decode register */ + /* program this with the default value */ + GT_REG_WRITE(SDRAM_ADDRESS_DECODE, 0x2); + DP(printf("SDRAM decode: %08x\n", + GTREGREAD(SDRAM_ADDRESS_DECODE))); + + return 0; +} + +/* sets up the GT properly with information passed in */ +static int +setup_sdram(sdram_info_t *info) +{ + ulong tmp, check; + ulong *addr = 0; + int i; + + /* sanity checking */ + if (! info->banks) return 0; + + /* ---------------------------- */ + /* Program the GT with the discovered data */ + + /* bank parameters */ + tmp = (0xf<<16); /* leave all virt bank pages open */ + + DP(printf("drb_size: %d\n", info->drb_size)); + switch (info->drb_size) { + case 1: + tmp |= (1 << 14); + break; + case 4: + case 8: + tmp |= (2 << 14); + break; + case 16: + case 32: + tmp |= (3 << 14); + break; + default: + printf("Error in dram size calculation\n"); + return 1; + } + + /* SDRAM bank parameters */ + /* the param registers for slot 1 (banks 2+3) are offset by 0x8 */ + GT_REG_WRITE(SDRAM_BANK0PARAMETERS + (info->slot * 0x8), tmp); + GT_REG_WRITE(SDRAM_BANK1PARAMETERS + (info->slot * 0x8), tmp); + DP(printf("SDRAM bankparam slot %d (bank %d+%d): %08lx\n", info->slot, info->slot*2, (info->slot*2)+1, tmp)); + + /* set the SDRAM configuration for each bank */ + for (i = info->slot * 2; i < ((info->slot * 2) + info->banks); i++) { + DP(printf("*** Running a MRS cycle for bank %d ***\n", i)); + + /* map the bank */ + memory_map_bank(i, 0, GB/4); + + /* set SDRAM mode */ + GT_REG_WRITE(SDRAM_OPERATION_MODE, 0x3); + check = GTREGREAD(SDRAM_OPERATION_MODE); + + /* dummy write */ + *addr = 0; + + /* wait for the command to complete */ + while ((GTREGREAD(SDRAM_OPERATION_MODE) & (1 << 31)) == 0) + ; + + /* switch back to normal operation mode */ + GT_REG_WRITE(SDRAM_OPERATION_MODE, 0); + check = GTREGREAD(SDRAM_OPERATION_MODE); + + /* unmap the bank */ + memory_map_bank(i, 0, 0); + DP(printf("*** MRS cycle for bank %d done ***\n", i)); + } + + return 0; +} + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ +static long int +dram_size(long int *base, long int maxsize) +{ + volatile long int *addr, *b=base; + long int cnt, val, save1, save2; + +#define STARTVAL (1<<20) /* start test at 1M */ + for (cnt = STARTVAL/sizeof(long); cnt < maxsize/sizeof(long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + save1=*addr; /* save contents of addr */ + save2=*b; /* save contents of base */ + + *addr=cnt; /* write cnt to addr */ + *b=0; /* put null at base */ + + /* check at base address */ + if ((*b) != 0) { + *addr=save1; /* restore *addr */ + *b=save2; /* restore *b */ + return (0); + } + val = *addr; /* read *addr */ + + *addr=save1; + *b=save2; + + if (val != cnt) { + /* fix boundary condition.. STARTVAL means zero */ + if(cnt==STARTVAL/sizeof(long)) cnt=0; + return (cnt * sizeof(long)); + } + } + return maxsize; +} + +/* ------------------------------------------------------------------------- */ + +/* U-Boot interface function to SDRAM init - this is where all the + * controlling logic happens */ +long int +initdram(int board_type) +{ + ulong checkbank[4] = { [0 ... 3] = 0 }; + int bank_no; + ulong total; + int nhr; + sdram_info_t dimm_info[2]; + + + /* first, use the SPD to get info about the SDRAM */ + + /* check the NHR bit and skip mem init if it's already done */ + nhr = get_hid0() & (1 << 16); + + if (nhr) { + printf("Skipping SDRAM setup due to NHR bit being set\n"); + } else { + /* DIMM0 */ + check_dimm(0, &dimm_info[0]); + + /* DIMM1 */ +#ifndef CONFIG_EVB64260_750CX /* EVB64260_750CX has only 1 DIMM */ + check_dimm(1, &dimm_info[1]); +#else /* CONFIG_EVB64260_750CX */ + memset(&dimm_info[1], 0, sizeof(sdram_info_t)); +#endif + + /* unmap all banks */ + memory_map_bank(0, 0, 0); + memory_map_bank(1, 0, 0); + memory_map_bank(2, 0, 0); + memory_map_bank(3, 0, 0); + + /* Now, program the GT with the correct values */ + if (setup_sdram_common(dimm_info)) { + printf("Setup common failed.\n"); + } + + if (setup_sdram(&dimm_info[0])) { + printf("Setup for DIMM1 failed.\n"); + } + + if (setup_sdram(&dimm_info[1])) { + printf("Setup for DIMM2 failed.\n"); + } + + /* set the NHR bit */ + set_hid0(get_hid0() | (1 << 16)); + } + /* next, size the SDRAM banks */ + + total = 0; + if (dimm_info[0].banks > 0) checkbank[0] = 1; + if (dimm_info[0].banks > 1) checkbank[1] = 1; + if (dimm_info[0].banks > 2) + printf("Error, SPD claims DIMM1 has >2 banks\n"); + + if (dimm_info[1].banks > 0) checkbank[2] = 1; + if (dimm_info[1].banks > 1) checkbank[3] = 1; + if (dimm_info[1].banks > 2) + printf("Error, SPD claims DIMM2 has >2 banks\n"); + + /* Generic dram sizer: works even if we don't have i2c DIMMs, + * as long as the timing settings are more or less correct */ + + /* + * pass 1: size all the banks, using first bat (0-256M) + * limitation: we only support 256M per bank due to + * us only having 1 BAT for all DRAM + */ + for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) { + /* skip over banks that are not populated */ + if (! checkbank[bank_no]) + continue; + + DP(printf("checking bank %d\n", bank_no)); + + memory_map_bank(bank_no, 0, GB/4); + checkbank[bank_no] = dram_size(NULL, GB/4); + memory_map_bank(bank_no, 0, 0); + + DP(printf("bank %d %08lx\n", bank_no, checkbank[bank_no])); + } + + /* + * pass 2: contiguously map each bank into physical address + * space. + */ + dimm_info[0].banks=dimm_info[1].banks=0; + for (bank_no = 0; bank_no < CFG_DRAM_BANKS; bank_no++) { + if(!checkbank[bank_no]) continue; + + dimm_info[bank_no/2].banks++; + dimm_info[bank_no/2].size+=checkbank[bank_no]; + + memory_map_bank(bank_no, total, checkbank[bank_no]); +#ifdef MAP_PCI + memory_map_bank_pci(bank_no, total, checkbank[bank_no]); +#endif + total += checkbank[bank_no]; + } + +#ifdef CONFIG_ECC +#ifdef CONFIG_ZUMA_V2 + /* + * We always enable ECC when bank 2 and 3 are unpopulated + * If we 2 or 3 are populated, we CAN'T support ECC. + * (Zuma boards only support ECC in banks 0 and 1; assume that + * in that configuration, ECC chips are mounted, even for stacked + * chips) + */ + if (checkbank[2]==0 && checkbank[3]==0) { + dimm_info[0].ecc=2; + GT_REG_WRITE(SDRAM_TIMING, GTREGREAD(SDRAM_TIMING) | (1 << 13)); + /* TODO: do we have to run MRS cycles again? */ + } +#endif /* CONFIG_ZUMA_V2 */ + + if (GTREGREAD(SDRAM_TIMING) & (1 << 13)) { + puts("[ECC] "); + } +#endif /* CONFIG_ECC */ + +#ifdef DEBUG + dump_dimm_info(&dimm_info[0]); + dump_dimm_info(&dimm_info[1]); +#endif + /* TODO: return at MOST 256M? */ + /* return total > GB/4 ? GB/4 : total; */ + return total; +} diff --git a/board/evb64260/serial.c b/board/evb64260/serial.c new file mode 100644 index 0000000..d9c7a15 --- /dev/null +++ b/board/evb64260/serial.c @@ -0,0 +1,191 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * 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 + */ + +/* + * serial.c - serial support for the gal ev board + */ + +/* supports both the 16650 duart and the MPSC */ + +#include <common.h> +#include <command.h> +#include <galileo/memory.h> + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) +#include <ns16550.h> +#endif + +#include "serial.h" + +#include "mpsc.h" + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) +const NS16550_t COM_PORTS[] = { (NS16550_t) CFG_NS16550_COM1, + (NS16550_t) CFG_NS16550_COM2 }; +#endif + +#ifdef CONFIG_MPSC + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; +#endif + + mpsc_init(gd->baudrate); + + /* init the DUART chans so that KGDB in the kernel can use them */ +#ifdef CFG_INIT_CHAN1 + NS16550_reinit(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit(COM_PORTS[1], clock_divisor); +#endif + return (0); +} + +void +serial_putc(const char c) +{ + if (c == '\n') + mpsc_putchar('\r'); + + mpsc_putchar(c); +} + +int +serial_getc(void) +{ + return mpsc_getchar(); +} + +int +serial_tstc(void) +{ + return mpsc_test_char(); +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + galbrg_set_baudrate(CONFIG_MPSC_PORT, gd->baudrate); +} + +#else /* ! CONFIG_MPSC */ + +int serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + (void)NS16550_init(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + (void)NS16550_init(COM_PORTS[1], clock_divisor); +#endif + + return (0); +} + +void +serial_putc(const char c) +{ + if (c == '\n') + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r'); + + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c); +} + +int +serial_getc(void) +{ + return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]); +} + +int +serial_tstc(void) +{ + return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]); +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + NS16550_reinit(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit(COM_PORTS[1], clock_divisor); +#endif +} + +#endif /* CONFIG_MPSC */ + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void +kgdb_serial_init(void) +{ +} + +void +putDebugChar (int c) +{ + serial_putc (c); +} + +void +putDebugStr (const char *str) +{ + serial_puts (str); +} + +int +getDebugChar (void) +{ + return serial_getc(); +} + +void +kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/gen860t/README b/board/gen860t/README new file mode 100644 index 0000000..761ceed --- /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 U-Boot 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 U-Boot 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 U-Boot. 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. +<keith_outwater@mvis.com> +<outwater@eskimo.com> + +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..46fe66b --- /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 <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include <linux/ctype.h> + +/* + * 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/flash.c b/board/gen860t/flash.c new file mode 100644 index 0000000..902b1b0 --- /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 <common.h> +#include <mpc8xx.h> + +#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; i<info->sector_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..2c4fbf1 --- /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 <common.h> +#include <virtex2.h> +#include <command.h> +#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/gen860t.c b/board/gen860t/gen860t.c new file mode 100644 index 0000000..16a3262 --- /dev/null +++ b/board/gen860t/gen860t.c @@ -0,0 +1,299 @@ +/* + * (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 <virtex2.h> +#include <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#include "beeper.h" +#include "fpga.h" +#include "ioport.h" + +#ifdef CONFIG_STATUS_LED +#include <status_led.h> +#endif + +#if defined(CFG_CMD_MII) && defined(CONFIG_MII) +#include <net.h> +#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("<unknown> "); + } + + i = getenv_r("serial#", buf, sizeof(buf)); + s = (i>0) ? buf : NULL; + + if (s) { + printf("S/N %s\n", s); + } else { + printf("S/N <unknown>\n"); + } + + printf("CPU at %s MHz, ",strmhz(buf, gd->cpu_clk)); + printf("local bus at %s MHz\n", strmhz(buf, gd->bus_clk)); + return (0); +} + +/* + * 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) +{ + 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..5d6524d --- /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 <common.h> +#include <mpc8xx.h> +#include <asm/8xx_immap.h> +#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/u-boot.lds b/board/gen860t/u-boot.lds new file mode 100644 index 0000000..1b53c72 --- /dev/null +++ b/board/gen860t/u-boot.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/board/impa7/flash.c b/board/impa7/flash.c new file mode 100644 index 0000000..c59ffb8 --- /dev/null +++ b/board/impa7/flash.c @@ -0,0 +1,365 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#define FLASH_BANK_SIZE 0x800000 +#define MAIN_SECT_SIZE 0x20000 +#define PARAM_SECT_SIZE 0x4000 + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; + + +/*----------------------------------------------------------------------- + */ + +ulong flash_init(void) +{ + int i, j; + ulong size = 0; + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i++) + { + ulong flashbase = 0; + flash_info[i].flash_id = + (INTEL_MANUFACT & FLASH_VENDMASK) | + (INTEL_ID_28F320B3T & FLASH_TYPEMASK); + flash_info[i].size = FLASH_BANK_SIZE; + flash_info[i].sector_count = CFG_MAX_FLASH_SECT; + memset(flash_info[i].protect, 0, CFG_MAX_FLASH_SECT); + if (i == 0) + flashbase = PHYS_FLASH_1; + else if (i == 1) + flashbase = PHYS_FLASH_2; + else + panic("configured to many flash banks!\n"); + for (j = 0; j < flash_info[i].sector_count; j++) + { + if (j <= 7) + { + flash_info[i].start[j] = flashbase + j * PARAM_SECT_SIZE; + } + else + { + flash_info[i].start[j] = flashbase + (j - 7)*MAIN_SECT_SIZE; + } + } + size += flash_info[i].size; + } + + /* Protect monitor and environment sectors + */ + flash_protect(FLAG_PROTECT_SET, + CFG_FLASH_BASE, + CFG_FLASH_BASE + _armboot_end_data - _armboot_start, + &flash_info[0]); + + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); + + return size; +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + switch (info->flash_id & FLASH_VENDMASK) + { + case (INTEL_MANUFACT & FLASH_VENDMASK): + printf("Intel: "); + break; + default: + printf("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) + { + case (INTEL_ID_28F320B3T & FLASH_TYPEMASK): + printf("28F320F3B (16Mbit)\n"); + break; + default: + printf("Unknown Chip Type\n"); + goto Done; + break; + } + + printf(" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf(" Sector Start Addresses:"); + for (i = 0; i < info->sector_count; i++) + { + if ((i % 5) == 0) + { + printf ("\n "); + } + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + printf ("\n"); + +Done: +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + int flag, prot, sect; + int rc = ERR_OK; + + if (info->flash_id == FLASH_UNKNOWN) + return ERR_UNKNOWN_FLASH_TYPE; + + if ((s_first < 0) || (s_first > s_last)) { + return ERR_INVAL; + } + + if ((info->flash_id & FLASH_VENDMASK) != + (INTEL_MANUFACT & FLASH_VENDMASK)) { + return ERR_UNKNOWN_FLASH_VENDOR; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + if (prot) + return ERR_PROTECTED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + flag = disable_interrupts(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last && !ctrlc(); sect++) { + + printf("Erasing sector %2d ... ", sect); + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + + if (info->protect[sect] == 0) { /* not protected */ + vu_long *addr = (vu_long *)(info->start[sect]); + + *addr = 0x00200020; /* erase setup */ + *addr = 0x00D000D0; /* erase confirm */ + + while ((*addr & 0x00800080) != 0x00800080) { + if (get_timer_masked() > CFG_FLASH_ERASE_TOUT) { + *addr = 0x00B000B0; /* suspend erase */ + *addr = 0x00FF00FF; /* reset to read mode */ + rc = ERR_TIMOUT; + goto outahere; + } + } + + *addr = 0x00FF00FF; /* reset to read mode */ + } + printf("ok.\n"); + } + if (ctrlc()) + printf("User Interrupt!\n"); + +outahere: + + /* allow flash to settle - wait 10 ms */ + udelay_masked(10000); + + if (flag) + enable_interrupts(); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash + */ + +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long *)dest; + ulong barf; + int rc = ERR_OK; + int flag; + + /* Check if Flash is (sufficiently) erased + */ + if ((*addr & data) != data) + return ERR_NOT_ERASED; + + /* + * Disable interrupts which might cause a timeout + * here. Remember that our exception vectors are + * at address 0 in the flash, and we don't want a + * (ticker) exception to happen while the flash + * chip is in programming mode. + */ + flag = disable_interrupts(); + + /* clear status register command */ + *addr = 0x00500050; + + /* program set-up command */ + *addr = 0x00400040; + + /* latch address/data */ + *addr = data; + + /* arm simple, non interrupt dependent timer */ + reset_timer_masked(); + + /* read status register command */ + *addr = 0x00700070; + + /* wait while polling the status register */ + while((*addr & 0x00800080) != 0x00800080) + { + if (get_timer_masked() > CFG_FLASH_WRITE_TOUT) { + rc = ERR_TIMOUT; + /* suspend program command */ + *addr = 0x00B000B0; + goto outahere; + } + + if( *addr & 0x003A003A) { /* check for error */ + barf = *addr; + if( barf & 0x003A0000) { + barf >>=16; + } else { + barf &= 0x0000003A; + } + printf("\nFlash write error %02lx at address %08lx\n", + barf, (unsigned long)dest); + if(barf & 0x0002) { + printf("Block locked, not erased.\n"); + rc = ERR_NOT_ERASED; + goto outahere; + } + if(barf & 0x0010) { + printf("Programming error.\n"); + rc = ERR_PROG_ERROR; + goto outahere; + } + if(barf & 0x0008) { + printf("Vpp Low error.\n"); + rc = ERR_PROG_ERROR; + goto outahere; + } + rc = ERR_PROG_ERROR; + goto outahere; + } + } + + +outahere: + /* read array command */ + *addr = 0x00FF00FF; + + if (flag) + enable_interrupts(); + + return rc; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int l; + int i, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data >> 8) | (*(uchar *)cp << 24); + } + for (; i<4 && cnt>0; ++i) { + data = (data >> 8) | (*src++ << 24); + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data >> 8) | (*(uchar *)cp << 24); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = *((vu_long*)src); + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + src += 4; + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return ERR_OK; + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data >> 8) | (*src++ << 24); + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data >> 8) | (*(uchar *)cp << 24); + } + + return write_word(info, wp, data); +} diff --git a/board/impa7/u-boot.lds b/board/impa7/u-boot.lds new file mode 100644 index 0000000..0849648 --- /dev/null +++ b/board/impa7/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm720t/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/lart/u-boot.lds b/board/lart/u-boot.lds new file mode 100644 index 0000000..f4b0ade --- /dev/null +++ b/board/lart/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/sa1100/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/mbx8xx/mbx8xx.c b/board/mbx8xx/mbx8xx.c new file mode 100644 index 0000000..9a9bf80 --- /dev/null +++ b/board/mbx8xx/mbx8xx.c @@ -0,0 +1,379 @@ +/* + * (C) Copyright 2000 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Board specific routines for the MBX + * + * - initialisation + * - interface to VPD data (mac address, clock speeds) + * - memory controller + * - serial io initialisation + * - ethernet io initialisation + * + * ----------------------------------------------------------------- + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <commproc.h> +#include <mpc8xx.h> +#include "dimm.h" +#include "vpd.h" +#include "csr.h" + +/* ------------------------------------------------------------------------- */ + +static const uint sdram_table_40[] = { + /* DRAM - single read. (offset 0 in upm RAM) + */ + 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x30AF0C00, + 0xF1BF4805, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* DRAM - burst read. (offset 8 in upm RAM) + */ + 0xCFAFC004, 0x0FAFC404, 0x0CAF0C04, 0x03AF0C08, + 0x0CAF0C04, 0x03AF0C08, 0x0CAF0C04, 0x03AF0C08, + 0x0CAF0C04, 0x30AF0C00, 0xF3BF4805, 0xFFFFC005, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* DRAM - single write. (offset 18 in upm RAM) + */ + 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x33FF4804, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* DRAM - burst write. (offset 20 in upm RAM) + */ + 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C, + 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C, + 0x0CFF0C00, 0x33FF4804, 0xFFFFC005, 0xFFFFC005, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* refresh (offset 30 in upm RAM) + */ + 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004, + 0x3FFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* exception. (offset 3c in upm RAM) + */ + 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, +}; + +static const uint sdram_table_50[] = { + /* DRAM - single read. (offset 0 in upm RAM) + */ + 0xCFAFC004, 0x0FAFC404, 0x0CAF8C04, 0x10AF0C04, + 0xF0AF0C00, 0xF3BF4805, 0xFFFFC005, 0xFFFFC005, + + /* DRAM - burst read. (offset 8 in upm RAM) + */ + 0xCFAFC004, 0X0FAFC404, 0X0CAF8C04, 0X00AF0C04, + /* 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C04, */ + 0X07AF0C08, 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, + 0X0CAF0C04, 0X01AF0C04, 0X0FAF0C08, 0X0CAF0C04, + /* 0X10AF0C04, 0XF0AFC000, 0XF3FF4805, 0XFFFFC005, */ + 0X10AF0C04, 0XF0AFC000, 0XF3BF4805, 0XFFFFC005, + + /* DRAM - single write. (offset 18 in upm RAM) + */ + 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x13FF4804, + 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* DRAM - burst write. (offset 20 in upm RAM) + */ + 0xCFFF0004, 0x0FFF0404, 0x0CFF0C00, 0x03FF0C0C, + 0x0CFF0C00, 0x03FF0C0C, 0x0CFF0C00, 0x03FF0C0C, + 0x0CFF0C00, 0x13FF4804, 0xFFFFC004, 0xFFFFC005, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* refresh (offset 30 in upm RAM) + */ + 0xFCFFC004, 0xC0FFC004, 0x01FFC004, 0x0FFFC004, + 0x1FFFC004, 0xFFFFC004, 0xFFFFC005, 0xFFFFC005, + 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, 0xFFFFC005, + + /* exception. (offset 3c in upm RAM) + */ + 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, 0xFFFFC007, +}; + +/* ------------------------------------------------------------------------- */ + +static unsigned int get_reffreq(void); +static unsigned int board_get_cpufreq(void); + +void mbx_init (void) +{ + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + ulong speed, refclock, plprcr, sccr; + ulong br0_32 = memctl->memc_br0 & 0x400; + + /* real-time clock status and control register */ + immr->im_sitk.sitk_rtcsck = KAPWR_KEY; + immr->im_sit.sit_rtcsc = 0x00C3; + + /* SIEL and SIMASK Registers (see MBX PRG 2-3) */ + immr->im_siu_conf.sc_simask = 0x00000000; + immr->im_siu_conf.sc_siel = 0xAAAA0000; + immr->im_siu_conf.sc_tesr = 0xFFFFFFFF; + + /* + * Prepare access to i2c bus. The MBX offers 3 devices on the i2c bus: + * 1. Vital Product Data (contains clock speeds, MAC address etc, see vpd.h) + * 2. RAM Specs (see dimm.h) + * 2. DIMM Specs (see dimm.h) + */ + vpd_init (); + + /* system clock and reset control register */ + immr->im_clkrstk.cark_sccrk = KAPWR_KEY; + sccr = immr->im_clkrst.car_sccr; + sccr &= SCCR_MASK; + sccr |= CFG_SCCR; + immr->im_clkrst.car_sccr = sccr; + + speed = board_get_cpufreq (); + refclock = get_reffreq (); + +#if ((CFG_PLPRCR & PLPRCR_MF_MSK) != 0) + plprcr = CFG_PLPRCR; +#else + plprcr = immr->im_clkrst.car_plprcr; + plprcr &= PLPRCR_MF_MSK; /* isolate MF field */ + plprcr |= CFG_PLPRCR; /* reset control bits */ +#endif + +#ifdef CFG_USE_OSCCLK /* See doc/README.MBX ! */ + plprcr |= ((speed + refclock / 2) / refclock - 1) << 20; +#endif + + immr->im_clkrstk.cark_plprcrk = KAPWR_KEY; + immr->im_clkrst.car_plprcr = plprcr; + + /* + * preliminary setup of memory controller: + * - map Flash, otherwise configuration/status + * registers won't be accessible when read + * by board_init_f. + * - map NVRAM and configuation/status registers. + * - map pci registers. + * - DON'T map ram yet, this is done in initdram(). + */ + switch (speed / 1000000) { + case 40: + memctl->memc_br0 = 0xFE000000 | br0_32 | 1; + memctl->memc_or0 = 0xFF800930; + memctl->memc_or4 = CFG_NVRAM_OR | 0x920; + memctl->memc_br4 = CFG_NVRAM_BASE | 0x401; + break; + case 50: + memctl->memc_br0 = 0xFE000000 | br0_32 | 1; + memctl->memc_or0 = 0xFF800940; + memctl->memc_or4 = CFG_NVRAM_OR | 0x930; + memctl->memc_br4 = CFG_NVRAM_BASE | 0x401; + break; + default: + hang (); + break; + } +#ifdef CONFIG_USE_PCI + memctl->memc_or5 = CFG_PCIMEM_OR; + memctl->memc_br5 = CFG_PCIMEM_BASE | 0x001; + memctl->memc_or6 = CFG_PCIBRIDGE_OR; + memctl->memc_br6 = CFG_PCIBRIDGE_BASE | 0x001; +#endif + /* + * FIXME: I do not understand why I have to call this to + * initialise the control register here before booting from + * the PCMCIA card but if I do not the Linux kernel falls + * over in a big heap. If you can answer this question I + * would like to know about it. + */ + board_ether_init(); +} + +void board_serial_init (void) +{ + MBX_CSR1 &= ~(CSR1_COM1EN | CSR1_XCVRDIS); +} + +void board_ether_init (void) +{ + MBX_CSR1 &= ~(CSR1_EAEN | CSR1_ELEN); + MBX_CSR1 |= CSR1_ETEN | CSR1_TPEN | CSR1_FDDIS; +} + +static unsigned int board_get_cpufreq (void) +{ +#ifndef CONFIG_8xx_GCLK_FREQ + vpd_packet_t *packet; + + packet = vpd_find_packet (VPD_PID_ICS); + return *((ulong *) packet->data); +#else + return((unsigned int)CONFIG_8xx_GCLK_FREQ ); +#endif /* CONFIG_8xx_GCLK_FREQ */ +} + +static unsigned int get_reffreq (void) +{ + vpd_packet_t *packet; + + packet = vpd_find_packet (VPD_PID_RCS); + return *((ulong *) packet->data); +} + +void board_get_enetaddr (uchar * addr) +{ + int i; + vpd_packet_t *packet; + + packet = vpd_find_packet (VPD_PID_EA); + for (i = 0; i < 6; i++) + addr[i] = packet->data[i]; +} + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + vpd_packet_t *packet; + int i; + const char *const fmt = + "\n *** Warning: Low Battery Status - %s Battery ***"; + + puts ("Board: "); + + packet = vpd_find_packet (VPD_PID_PID); + for (i = 0; i < packet->size; i++) { + serial_putc (packet->data[i]); + } + packet = vpd_find_packet (VPD_PID_MT); + for (i = 0; i < packet->size; i++) { + serial_putc (packet->data[i]); + } + serial_putc ('('); + packet = vpd_find_packet (VPD_PID_FAN); + for (i = 0; i < packet->size; i++) { + serial_putc (packet->data[i]); + } + serial_putc (')'); + + if (!(MBX_CSR2 & SR2_BATGD)) + printf (fmt, "On-Board"); + if (!(MBX_CSR2 & SR2_NVBATGD)) + printf (fmt, "NVRAM"); + + serial_putc ('\n'); + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +static ulong get_ramsize (dimm_t * dimm) +{ + ulong size = 0; + + if (dimm->fmt == 1 || dimm->fmt == 2 || dimm->fmt == 3 + || dimm->fmt == 4) { + size = (1 << (dimm->n_row + dimm->n_col)) * dimm->n_banks * + ((dimm->data_w_hi << 8 | dimm->data_w_lo) / 8); + } + + return size; +} + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long ram_sz = 0; + unsigned long dimm_sz = 0; + dimm_t vpd_dimm, vpd_dram; + unsigned int speed = board_get_cpufreq () / 1000000; + + if (vpd_read (0xa2, (uchar *) & vpd_dimm, sizeof (vpd_dimm), 0) > 0) { + dimm_sz = get_ramsize (&vpd_dimm); + } + if (vpd_read (0xa6, (uchar *) & vpd_dram, sizeof (vpd_dram), 0) > 0) { + ram_sz = get_ramsize (&vpd_dram); + } + + /* + * Only initialize memory controller when running from FLASH. + * When running from RAM, don't touch it. + */ + if ((ulong) initdram & 0xff000000) { + ulong dimm_bank; + ulong br0_32 = memctl->memc_br0 & 0x400; + + switch (speed) { + case 40: + upmconfig (UPMA, (uint *) sdram_table_40, + sizeof (sdram_table_40) / sizeof (uint)); + memctl->memc_mptpr = 0x0200; + memctl->memc_mamr = dimm_sz ? 0x06801000 : 0x13801000; + memctl->memc_or7 = 0xff800930; + memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1; + break; + case 50: + upmconfig (UPMA, (uint *) sdram_table_50, + sizeof (sdram_table_50) / sizeof (uint)); + memctl->memc_mptpr = 0x0200; + memctl->memc_mamr = dimm_sz ? 0x08801000 : 0x1880100; + memctl->memc_or7 = 0xff800940; + memctl->memc_br7 = 0xfc000000 | (br0_32 ^ br0_32) | 1; + break; + default: + hang (); + break; + } + + /* now map ram and dimm, largest one first */ + dimm_bank = dimm_sz / 2; + if (!dimm_sz) { + memctl->memc_or1 = ~(ram_sz - 1) | 0x400; + memctl->memc_br1 = CFG_SDRAM_BASE | 0x81; + memctl->memc_br2 = 0; + memctl->memc_br3 = 0; + } else if (ram_sz > dimm_bank) { + memctl->memc_or1 = ~(ram_sz - 1) | 0x400; + memctl->memc_br1 = CFG_SDRAM_BASE | 0x81; + memctl->memc_or2 = ~(dimm_bank - 1) | 0x400; + memctl->memc_br2 = (CFG_SDRAM_BASE + ram_sz) | 0x81; + memctl->memc_or3 = ~(dimm_bank - 1) | 0x400; + memctl->memc_br3 = (CFG_SDRAM_BASE + ram_sz + dimm_bank) \ + | 0x81; + } else { + memctl->memc_or2 = ~(dimm_bank - 1) | 0x400; + memctl->memc_br2 = CFG_SDRAM_BASE | 0x81; + memctl->memc_or3 = ~(dimm_bank - 1) | 0x400; + memctl->memc_br3 = (CFG_SDRAM_BASE + dimm_bank) | 0x81; + memctl->memc_or1 = ~(ram_sz - 1) | 0x400; + memctl->memc_br1 = (CFG_SDRAM_BASE + dimm_sz) | 0x81; + } + } + + return ram_sz + dimm_sz; +} diff --git a/board/ml2/serial.c b/board/ml2/serial.c new file mode 100644 index 0000000..dc9a8ea --- /dev/null +++ b/board/ml2/serial.c @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2002 + * Peter De Schrijver (p2@mind.be), Mind Linux Solutions, NV. + * + * 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 <asm/u-boot.h> +#include <asm/processor.h> +#include <common.h> +#include <command.h> +#include <configs/ML2.h> + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) +#include <ns16550.h> +#endif + +#if 0 +#include "serial.h" +#endif + +#if (defined CFG_INIT_CHAN1) || (defined CFG_INIT_CHAN2) +const NS16550_t COM_PORTS[] = { (NS16550_t) CFG_NS16550_COM1, + (NS16550_t) CFG_NS16550_COM2 }; +#endif + +int +serial_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + (void)NS16550_init(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + (void)NS16550_init(COM_PORTS[1], clock_divisor); +#endif + return 0; + +} + +void +serial_putc(const char c) +{ + if (c == '\n') + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], '\r'); + + NS16550_putc(COM_PORTS[CFG_DUART_CHAN], c); +} + +int +serial_getc(void) +{ + return NS16550_getc(COM_PORTS[CFG_DUART_CHAN]); +} + +int +serial_tstc(void) +{ + return NS16550_tstc(COM_PORTS[CFG_DUART_CHAN]); +} + +void +serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int clock_divisor = CFG_NS16550_CLK / 16 / gd->baudrate; + +#ifdef CFG_INIT_CHAN1 + NS16550_reinit(COM_PORTS[0], clock_divisor); +#endif +#ifdef CFG_INIT_CHAN2 + NS16550_reinit(COM_PORTS[1], clock_divisor); +#endif +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +void +kgdb_serial_init(void) +{ +} + +void +putDebugChar (int c) +{ + serial_putc (c); +} + +void +putDebugStr (const char *str) +{ + serial_puts (str); +} + +int +getDebugChar (void) +{ + return serial_getc(); +} + +void +kgdb_interruptible (int yes) +{ + return; +} +#endif /* CFG_CMD_KGDB */ diff --git a/board/mousse/pci.c b/board/mousse/pci.c new file mode 100644 index 0000000..89ca235 --- /dev/null +++ b/board/mousse/pci.c @@ -0,0 +1,283 @@ +/* + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 + * James Dougherty (jfd@cs.stanford.edu) + * + * 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 + */ + +/* + * PCI Configuration space access support for MPC824x/MPC107 PCI Bridge + */ +#include <common.h> +#include <mpc824x.h> +#include <pci.h> + +#include "mousse.h" + +/* + * Promise ATA/66 support. + */ +#define XFER_PIO_4 0x0C /* 0000|1100 */ +#define XFER_PIO_3 0x0B /* 0000|1011 */ +#define XFER_PIO_2 0x0A /* 0000|1010 */ +#define XFER_PIO_1 0x09 /* 0000|1001 */ +#define XFER_PIO_0 0x08 /* 0000|1000 */ +#define XFER_PIO_SLOW 0x00 /* 0000|0000 */ + +/* Promise Regs */ +#define REG_A 0x01 +#define REG_B 0x02 +#define REG_C 0x04 +#define REG_D 0x08 + +void +pdc202xx_decode_registers (unsigned char registers, unsigned char value) +{ + unsigned char bit = 0, bit1 = 0, bit2 = 0; + switch(registers) { + case REG_A: + bit2 = 0; + printf(" A Register "); + if (value & 0x80) printf("SYNC_IN "); + if (value & 0x40) printf("ERRDY_EN "); + if (value & 0x20) printf("IORDY_EN "); + if (value & 0x10) printf("PREFETCH_EN "); + if (value & 0x08) { printf("PA3 ");bit2 |= 0x08; } + if (value & 0x04) { printf("PA2 ");bit2 |= 0x04; } + if (value & 0x02) { printf("PA1 ");bit2 |= 0x02; } + if (value & 0x01) { printf("PA0 ");bit2 |= 0x01; } + printf("PIO(A) = %d ", bit2); + break; + case REG_B: + bit1 = 0;bit2 = 0; + printf(" B Register "); + if (value & 0x80) { printf("MB2 ");bit1 |= 0x80; } + if (value & 0x40) { printf("MB1 ");bit1 |= 0x40; } + if (value & 0x20) { printf("MB0 ");bit1 |= 0x20; } + printf("DMA(B) = %d ", bit1 >> 5); + if (value & 0x10) printf("PIO_FORCED/PB4 "); + if (value & 0x08) { printf("PB3 ");bit2 |= 0x08; } + if (value & 0x04) { printf("PB2 ");bit2 |= 0x04; } + if (value & 0x02) { printf("PB1 ");bit2 |= 0x02; } + if (value & 0x01) { printf("PB0 ");bit2 |= 0x01; } + printf("PIO(B) = %d ", bit2); + break; + case REG_C: + bit2 = 0; + printf(" C Register "); + if (value & 0x80) printf("DMARQp "); + if (value & 0x40) printf("IORDYp "); + if (value & 0x20) printf("DMAR_EN "); + if (value & 0x10) printf("DMAW_EN "); + + if (value & 0x08) { printf("MC3 ");bit2 |= 0x08; } + if (value & 0x04) { printf("MC2 ");bit2 |= 0x04; } + if (value & 0x02) { printf("MC1 ");bit2 |= 0x02; } + if (value & 0x01) { printf("MC0 ");bit2 |= 0x01; } + printf("DMA(C) = %d ", bit2); + break; + case REG_D: + printf(" D Register "); + break; + default: + return; + } + printf("\n %s ", (registers & REG_D) ? "DP" : + (registers & REG_C) ? "CP" : + (registers & REG_B) ? "BP" : + (registers & REG_A) ? "AP" : "ERROR"); + for (bit=128;bit>0;bit/=2) + printf("%s", (value & bit) ? "1" : "0"); + printf("\n"); +} + +/* + * Promise ATA/66 Support: configure Promise ATA66 card in specified mode. + */ +int +pdc202xx_tune_chipset (pci_dev_t dev, int drive, unsigned char speed) +{ + unsigned short drive_conf; + int err = 0; + unsigned char drive_pci, AP, BP, CP, DP; + unsigned char TA = 0, TB = 0; + + switch (drive) { + case 0: drive_pci = 0x60; break; + case 1: drive_pci = 0x64; break; + case 2: drive_pci = 0x68; break; + case 3: drive_pci = 0x6c; break; + default: return -1; + } + + pci_read_config_word(dev, drive_pci, &drive_conf); + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + if ((AP & 0x0F) || (BP & 0x07)) { + /* clear PIO modes of lower 8421 bits of A Register */ + pci_write_config_byte(dev, (drive_pci), AP & ~0x0F); + pci_read_config_byte(dev, (drive_pci), &AP); + + /* clear PIO modes of lower 421 bits of B Register */ + pci_write_config_byte(dev, (drive_pci)|0x01, BP & ~0x07); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + } + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + + switch(speed) { + case XFER_PIO_4: TA = 0x01; TB = 0x04; break; + case XFER_PIO_3: TA = 0x02; TB = 0x06; break; + case XFER_PIO_2: TA = 0x03; TB = 0x08; break; + case XFER_PIO_1: TA = 0x05; TB = 0x0C; break; + case XFER_PIO_0: + default: TA = 0x09; TB = 0x13; break; + } + + pci_write_config_byte(dev, (drive_pci), AP|TA); + pci_write_config_byte(dev, (drive_pci)|0x01, BP|TB); + + pci_read_config_byte(dev, (drive_pci), &AP); + pci_read_config_byte(dev, (drive_pci)|0x01, &BP); + pci_read_config_byte(dev, (drive_pci)|0x02, &CP); + pci_read_config_byte(dev, (drive_pci)|0x03, &DP); + + +#ifdef PDC202XX_DEBUG + pdc202xx_decode_registers(REG_A, AP); + pdc202xx_decode_registers(REG_B, BP); + pdc202xx_decode_registers(REG_C, CP); + pdc202xx_decode_registers(REG_D, DP); +#endif + return err; +} +/* + * Show/Init PCI devices on the specified bus number. + */ + +void pci_mousse_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned int line; + + switch(PCI_DEV(dev)) { + case 0x0d: + line = 0x00000101; + break; + + case 0x0e: + default: + line = 0x00000303; + break; + } + + pci_write_config_dword(dev, PCI_INTERRUPT_LINE, line); +} + +void pci_mousse_setup_pdc202xx(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *_) +{ + unsigned short vendorId; + unsigned int mbar0, cmd; + int bar, a; + + pci_read_config_word(dev, PCI_VENDOR_ID, &vendorId); + + if(vendorId == PCI_VENDOR_ID_PROMISE || vendorId == PCI_VENDOR_ID_CMD){ + /* PDC 202xx card is handled differently, it is a bootable + * device and needs all 5 MBAR's configured + */ + for(bar = 0; bar < 5; bar++){ + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, ~0); + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); +#ifdef DEBUG + printf(" ATA_bar[%d] = %dbytes\n", bar, + ~(mbar0 & PCI_BASE_ADDRESS_MEM_MASK) + 1); +#endif + } + + /* Program all BAR's */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, PROMISE_MBAR0); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, PROMISE_MBAR1); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_2, PROMISE_MBAR2); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_3, PROMISE_MBAR3); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_4, PROMISE_MBAR4); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_5, PROMISE_MBAR5); + + for(bar = 0; bar < 5; bar++){ + pci_read_config_dword(dev, PCI_BASE_ADDRESS_0+bar*4, &mbar0); +#ifdef DEBUG + printf(" ATA_bar[%d]@0x%x\n", bar, mbar0); +#endif + } + + /* Enable ROM Expansion base */ + pci_write_config_dword(dev, PCI_ROM_ADDRESS, PROMISE_MBAR5|1); + + /* Io enable, Memory enable, master enable */ + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd &= ~0xffff0000; + cmd |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO; + pci_write_config_dword(dev, PCI_COMMAND, cmd); + + /* Breath some life into the controller */ + for( a = 0; a < 4; a++) + pdc202xx_tune_chipset(dev, a, XFER_PIO_0); + } +} + +static struct pci_config_table pci_sandpoint_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0e, 0x00, + pci_mousse_setup_pdc202xx }, +#ifndef CONFIG_PCI_PNP + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x00, 0x0d, 0x00, + pci_cfgfunc_config_device, {PCI_ENET_IOADDR, + PCI_ENET_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_cfgfunc_config_device, {PCI_SLOT_IOADDR, + PCI_SLOT_MEMADDR, + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER}}, +#endif + { } +}; + +struct pci_controller hose = { + config_table: pci_sandpoint_config_table, + fixup_irq: pci_mousse_fixup_irq, +}; + +void pci_init(void) +{ + pci_mpc824x_init(&hose); +} diff --git a/board/mpl/common/common_util.c b/board/mpl/common/common_util.c new file mode 100644 index 0000000..60c49af --- /dev/null +++ b/board/mpl/common/common_util.c @@ -0,0 +1,606 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <video_fb.h> +#include "common_util.h" +#include <asm/processor.h> +#include <i2c.h> +#include <devices.h> +#include <pci.h> + +extern int gunzip (void *, int, unsigned char *, int *); +extern int mem_test(unsigned long start, unsigned long ramsize, int quiet); + +#define I2C_BACKUP_ADDR 0x7C00 /* 0x200 bytes for backup */ +#define IMAGE_SIZE 0x80000 + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +image_header_t header; + + + +int mpl_prg(unsigned long src,unsigned long size) +{ + unsigned long start; + flash_info_t *info; + int i,rc; + unsigned long *magic = (unsigned long *)src; + + info = &flash_info[0]; + start = 0 - size; + for(i=info->sector_count-1;i>0;i--) + { + info->protect[i] = 0; /* unprotect this sector */ + if(start>=info->start[i]) + break; + } + /* set-up flash location */ + /* now erase flash */ + if(magic[0]!=IH_MAGIC) { + printf("Bad Magic number\n"); + return -1; + } + printf("Erasing at %lx (sector %d) (start %lx)\n", + start,i,info->start[i]); + flash_erase (info, i, info->sector_count-1); + printf("flash erased, programming from 0x%lx 0x%lx Bytes\n",src,size); + if ((rc = flash_write ((uchar *)src, start, size)) != 0) { + puts ("ERROR "); + flash_perror (rc); + return (1); + } + puts ("OK programming done\n"); + return 0; +} + + +int mpl_prg_image(unsigned long ld_addr) +{ + unsigned long data,len,checksum; + image_header_t *hdr=&header; + /* Copy header so we can blank CRC field for re-calculation */ + memcpy (&header, (char *)ld_addr, sizeof(image_header_t)); + if (hdr->ih_magic != IH_MAGIC) { + printf ("Bad Magic Number\n"); + return 1; + } + print_image_hdr(hdr); + if (hdr->ih_os != IH_OS_U_BOOT) { + printf ("No U-Boot Image\n"); + return 1; + } + if (hdr->ih_type != IH_TYPE_FIRMWARE) { + printf ("No Firmware Image\n"); + return 1; + } + data = (ulong)&header; + len = sizeof(image_header_t); + checksum = hdr->ih_hcrc; + hdr->ih_hcrc = 0; + if (crc32 (0, (char *)data, len) != checksum) { + printf ("Bad Header Checksum\n"); + return 1; + } + data = ld_addr + sizeof(image_header_t); + len = hdr->ih_size; + printf ("Verifying Checksum ... "); + if (crc32 (0, (char *)data, len) != hdr->ih_dcrc) { + printf ("Bad Data CRC\n"); + return 1; + } + switch (hdr->ih_comp) { + case IH_COMP_NONE: + break; + case IH_COMP_GZIP: + printf (" Uncompressing ... "); + if (gunzip ((void *)(data+0x100000), 0x400000, + (uchar *)data, (int *)&len) != 0) { + printf ("GUNZIP ERROR\n"); + return 1; + } + data+=0x100000; + break; + default: + printf (" Unimplemented compression type %d\n", hdr->ih_comp); + return 1; + } + + printf (" OK\n"); + return(mpl_prg(data,len)); +} + + +void get_backup_values(backup_t *buf) +{ + i2c_read(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)buf,sizeof(backup_t)); +} + +void set_backup_values(int overwrite) +{ + backup_t back; + int i; + + get_backup_values(&back); + if(!overwrite) { + if(strncmp(back.signature,"MPL\0",4)==0) { + printf("Not possible to write Backup\n"); + return; + } + } + memcpy(back.signature,"MPL\0",4); + i=getenv_r("serial#",back.serial_name,16); + if(i==0) { + printf("Not possible to write Backup\n"); + return; + } + back.serial_name[16]=0; + i=getenv_r("ethaddr",back.eth_addr,20); + if(i==0) { + printf("Not possible to write Backup\n"); + return; + } + back.eth_addr[20]=0; + i2c_write(CFG_DEF_EEPROM_ADDR, I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t)); +} + +void clear_env_values(void) +{ + backup_t back; + unsigned char env_crc[4]; + + memset(&back,0xff,sizeof(backup_t)); + memset(env_crc,0x00,4); + i2c_write(CFG_DEF_EEPROM_ADDR,I2C_BACKUP_ADDR,2,(void *)&back,sizeof(backup_t)); + i2c_write(CFG_DEF_EEPROM_ADDR,CFG_ENV_OFFSET,2,(void *)env_crc,4); +} + +/* + * check crc of "older" environment + */ +int check_env_old_size(ulong oldsize) +{ + ulong crc, len, new; + unsigned off; + uchar buf[64]; + + /* read old CRC */ + eeprom_read (CFG_DEF_EEPROM_ADDR, + CFG_ENV_OFFSET, + (uchar *)&crc, sizeof(ulong)); + + new = 0; + len = oldsize; + off = sizeof(long); + len = oldsize-off; + while (len > 0) { + int n = (len > sizeof(buf)) ? sizeof(buf) : len; + + eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, buf, n); + new = crc32 (new, buf, n); + len -= n; + off += n; + } + + return (crc == new); +} + +static ulong oldsizes[] = { + 0x200, + 0x800, + 0 +}; + +void copy_old_env(ulong size) +{ + uchar name_buf[64]; + uchar value_buf[0x800]; + uchar c; + ulong len; + unsigned off; + uchar *name, *value; + + name=&name_buf[0]; + value=&value_buf[0]; + len=size; + off = sizeof(long); + while (len > off) { + eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1); + if(c != '=') { + *name++=c; + off++; + } + else { + *name++='\0'; + off++; + do { + eeprom_read (CFG_DEF_EEPROM_ADDR, CFG_ENV_OFFSET+off, &c, 1); + *value++=c; + off++; + if(c == '\0') + break; + } while(len > off); + name=&name_buf[0]; + value=&value_buf[0]; + if(strncmp(name,"baudrate",8)!=0) { + setenv(name,value); + } + + } + } +} + + +void check_env(void) +{ + unsigned char *s; + int i=0; + char buf[32]; + backup_t back; + + s=getenv("serial#"); + if(!s) { + while(oldsizes[i]) { + if(check_env_old_size(oldsizes[i])) + break; + i++; + } + if(!oldsizes[i]) { + /* no old environment has been found */ + get_backup_values (&back); + if (strncmp (back.signature, "MPL\0", 4) == 0) { + sprintf (buf, "%s", back.serial_name); + setenv ("serial#", buf); + sprintf (buf, "%s", back.eth_addr); + setenv ("ethaddr", buf); + printf ("INFO: serial# and ethaddr recovered, use saveenv\n"); + return; + } + } + else { + copy_old_env(oldsizes[i]); + printf ("INFO: old environment ajusted, use saveenv\n"); + } + } + else { + /* check if back up is set */ + get_backup_values(&back); + if(strncmp(back.signature,"MPL\0",4)!=0) { + set_backup_values(0); + } + } +} + + + +extern device_t *stdio_devices[]; +extern char *stdio_names[]; + +void show_stdio_dev(void) +{ + /* Print informations */ + printf ("In: "); + if (stdio_devices[stdin] == NULL) { + printf ("No input devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdin]->name); + } + + printf ("Out: "); + if (stdio_devices[stdout] == NULL) { + printf ("No output devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdout]->name); + } + + printf ("Err: "); + if (stdio_devices[stderr] == NULL) { + printf ("No error devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stderr]->name); + } +} + +/* ------------------------------------------------------------------------- */ + + /* switches the cs0 and the cs1 to the locations. + When boot is TRUE, the the mapping is switched + to the boot configuration, If it is FALSE, the + flash will be switched in the boot area */ + +#undef SW_CS_DBG +#ifdef SW_CS_DBG +#define SW_CS_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define SW_CS_PRINTF(fmt,args...) +#endif + + +int switch_cs(unsigned char boot) +{ + unsigned long pbcr; + mtdcr(ebccfga, pb0cr); /* get cs0 config reg */ + pbcr = mfdcr(ebccfgd); + if((pbcr&0x00002000)==0) { + /* we need only to switch if boot from MPS */ + /*printf(" MPS boot mode detected. ");*/ + /* printf("cs0 cfg: %lx\n",pbcr); */ + if(boot) { + /* switch to boot configuration */ + /* this is a 8bit boot, switch cs0 to flash location */ + SW_CS_PRINTF("switch to boot mode (MPS on High address\n"); + pbcr&=0x000FFFFF; /*mask base address of the cs0 */ + pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000); + mtdcr(ebccfga, pb0cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr); + mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */ + pbcr = mfdcr(ebccfgd); + SW_CS_PRINTF(" old cs1 cfg: %lx\n",pbcr); + pbcr&=0x000FFFFF; /*mask base address of the cs1 */ + pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs1 cfg: %lx, MPS is on High Address\n",pbcr); + } + else + { + /* map flash to boot area, */ + SW_CS_PRINTF("map Flash to boot area\n"); + pbcr&=0x000FFFFF; /*mask base address of the cs0 */ + pbcr|=(MULTI_PURPOSE_SOCKET_ADDR & 0xFFF00000); + mtdcr(ebccfga, pb0cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs0 cfg: %lx\n",pbcr); + mtdcr(ebccfga, pb1cr); /* get cs1 config reg (flash) */ + pbcr = mfdcr(ebccfgd); + SW_CS_PRINTF(" cs1 cfg: %lx\n",pbcr); + pbcr&=0x000FFFFF; /*mask base address of the cs1 */ + pbcr|=(FLASH_BASE0_PRELIM & 0xFFF00000); + mtdcr(ebccfga, pb1cr); + mtdcr(ebccfgd, pbcr); + SW_CS_PRINTF(" new cs1 cfg: %lx Flash is on High Address\n",pbcr); + } + return 1; + } + else { + SW_CS_PRINTF("Normal boot, no switching necessary\n"); + return 0; + } +} + + +int do_mplcommon(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong size,src,ld_addr; + int result; + backup_t back; + char sw; + src = MULTI_PURPOSE_SOCKET_ADDR; + size = IMAGE_SIZE; + + if (strcmp(argv[1], "flash") == 0) + { + sw = switch_cs(0); /* Switch flash to normal location */ +#if (CONFIG_COMMANDS & CFG_CMD_FDC) + if (strcmp(argv[2], "floppy") == 0) { + char *local_args[3]; + extern int do_fdcboot (cmd_tbl_t *, int, int, char *[]); + printf ("\nupdating bootloader image from floppy\n"); + local_args[0] = argv[0]; + if(argc==4) { + local_args[1] = argv[3]; + local_args[2] = NULL; + ld_addr=simple_strtoul(argv[3], NULL, 16); + result=do_fdcboot(cmdtp, 0, 2, local_args); + } + else { + local_args[1] = NULL; + ld_addr=CFG_LOAD_ADDR; + result=do_fdcboot(cmdtp, 0, 1, local_args); + } + result=mpl_prg_image(ld_addr); + switch_cs(sw); /* Switch flash back */ + return result; + } +#endif /* (CONFIG_COMMANDS & CFG_CMD_FDC) */ + if (strcmp(argv[2], "mem") == 0) { + if(argc==4) { + ld_addr=simple_strtoul(argv[3], NULL, 16); + } + else { + ld_addr=load_addr; + } + printf ("\nupdating bootloader image from memory at %lX\n",ld_addr); + result=mpl_prg_image(ld_addr); + switch_cs(sw); /* Switch flash back */ + return result; + } + if (strcmp(argv[2], "mps") == 0) { + printf ("\nupdating bootloader image from MSP\n"); + result=mpl_prg(src,size); + switch_cs(sw); /* Switch flash back */ + return result; + } + switch_cs(sw); /* Switch flash back */ + + } + if (strcmp(argv[1], "mem") == 0) + { + result=0; + if(argc==3) + { + result = (int)simple_strtol(argv[2], NULL, 16); + } + src=(unsigned long)&result; + src-=CFG_MEMTEST_START; + src-=(100*1024); /* - 100k */ + src&=0xfff00000; + size=0; + do { + size++; + printf("\n\nPass %ld\n",size); + mem_test(CFG_MEMTEST_START,src,1); + if(ctrlc()) + break; + if(result>0) + result--; + + }while(result); + return 0; + } + if (strcmp(argv[1], "clearenvvalues") == 0) + { + if (strcmp(argv[2], "yes") == 0) + { + clear_env_values(); + return 0; + } + } + if (strcmp(argv[1], "getback") == 0) { + get_backup_values(&back); + back.signature[3]=0; + back.serial_name[16]=0; + back.eth_addr[20]=0; + printf("GetBackUp: signature: %s\n",back.signature); + printf(" serial#: %s\n",back.serial_name); + printf(" ethaddr: %s\n",back.eth_addr); + return 0; + } + if (strcmp(argv[1], "setback") == 0) { + set_backup_values(1); + return 0; + } + printf("Usage:\n%s\n", cmdtp->usage); + return 1; +} + + +#if (CONFIG_COMMANDS & CFG_CMD_DOC) +extern void doc_probe(ulong physadr); +void doc_init (void) +{ + doc_probe(MULTI_PURPOSE_SOCKET_ADDR); +} +#endif + + +#ifdef CONFIG_VIDEO +/****************************************************** + * Routines to display the Board information + * to the screen (since the VGA will be initialized as last, + * we must resend the infos) + */ + +#ifdef CONFIG_CONSOLE_EXTRA_INFO +extern GraphicDevice ctfb; + +void video_get_info_str (int line_number, char *info) +{ + /* init video info strings for graphic console */ + DECLARE_GLOBAL_DATA_PTR; + PPC405_SYS_INFO sys_info; + char rev; + int i; + unsigned long pvr; + char buf[64]; + char tmp[16]; + unsigned char *s, *e, bc, sw; + switch (line_number) + { + case 2: + /* CPU and board infos */ + pvr=get_pvr(); + get_sys_info (&sys_info); + switch (pvr) { + case PVR_405GP_RB: rev='B'; break; + case PVR_405GP_RC: rev='C'; break; + case PVR_405GP_RD: rev='D'; break; + case PVR_405GP_RE: rev='E'; break; + default: rev='?'; break; + } + /* Board info */ + i=0; + s=getenv ("serial#"); +#ifdef CONFIG_PIP405 + if (!s || strncmp (s, "PIP405", 6)) { + sprintf(buf,"### No HW ID - assuming PIP405"); + } +#endif +#ifdef CONFIG_MIP405 + if (!s || strncmp (s, "MIP405", 6)) { + sprintf(buf,"### No HW ID - assuming MIP405"); + } +#endif + else { + for (e = s; *e; ++e) { + if (*e == ' ') + break; + } + for (; s < e; ++s) { + if (*s == '_') { + ++s; + break; + } + buf[i++]=*s; + } + sprintf(&buf[i]," SN "); + i+=4; + for (; s < e; ++s) { + buf[i++]=*s; + } + buf[i++]=0; + } + sprintf (info," %s PPC405GP %c %s MHz (%lu/%lu/%lu MHz)", + buf,rev, + strmhz (tmp, gd->cpu_clk), sys_info.freqPLB / 1000000, + sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, + sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000); + return; + case 3: + /* Memory Info */ + sw = switch_cs (0); + switch_cs (sw); + bc = in8 (CONFIG_PORT_ADDR); + sprintf(info, " %luMB RAM, %luMB Flash Cfg 0x%02X %s %s", + gd->bd->bi_memsize / 0x100000, + gd->bd->bi_flashsize / 0x100000, + bc, + sw ? "MPS boot" : "Flash boot", + ctfb.modeIdent); + return; + case 1: + sprintf (buf, "%s",CONFIG_IDENT_STRING); + sprintf (info, " %s", &buf[1]); + return; + } + /* no more info lines */ + *info = 0; + return; +} +#endif /* CONFIG_CONSOLE_EXTRA_INFO */ + +#endif /* CONFIG_VIDEO */ diff --git a/board/mpl/common/pci.c b/board/mpl/common/pci.c new file mode 100644 index 0000000..d1965f9 --- /dev/null +++ b/board/mpl/common/pci.c @@ -0,0 +1,102 @@ +/*-----------------------------------------------------------------------------+ +| +| This source code has been made available to you by IBM on an AS-IS +| basis. Anyone receiving this source is licensed under IBM +| copyrights to use it in any way he or she deems fit, including +| copying it, modifying it, compiling it, and redistributing it either +| with or without modifications. No license under IBM patents or +| patent applications is to be implied by the copyright license. +| +| Any user of this software should understand that IBM cannot provide +| technical support for this software and will not be responsible for +| any consequences resulting from the use of this software. +| +| Any person who transfers this source code or any derivative work +| must include the IBM copyright notice, this paragraph, and the +| preceding two paragraphs in the transferred software. +| +| COPYRIGHT I B M CORPORATION 1995 +| LICENSED MATERIAL - PROGRAM PROPERTY OF I B M ++-----------------------------------------------------------------------------*/ +/* + * Adapted for PIP405 03.07.01 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * TODO: Clean-up + */ + +#include <common.h> +#include <pci.h> +#include "isa.h" + +#ifdef CONFIG_405GP +#ifdef CONFIG_PCI + +#undef DEBUG + +#include "piix4_pci.h" +#include "pci_parts.h" + +void pci_pip405_write_regs(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry) +{ + struct pci_pip405_config_entry *table; + int i; + + table = (struct pci_pip405_config_entry*) entry->priv[0]; + + for (i=0; table[i].width; i++) + { +#ifdef DEBUG + printf("Reg 0x%02X Value 0x%08lX Width %02d written\n", + table[i].index, table[i].val, table[i].width); +#endif + + switch(table[i].width) + { + case 1: pci_hose_write_config_byte(hose, dev, table[i].index, table[i].val); break; + case 2: pci_hose_write_config_word(hose, dev, table[i].index, table[i].val); break; + case 4: pci_hose_write_config_dword(hose, dev, table[i].index, table[i].val); break; + } + } +} + + +static void pci_pip405_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char int_line = 0xff; + /* + * Write pci interrupt line register + */ + if(PCI_DEV(dev)==0) /* Device0 = PPC405 -> skip */ + return; + if(PCI_FUNC(dev)==0) + { + /* assuming all function 0 are using their INTA# Pin*/ + int_line=PCI_IRQ_VECTOR(dev); + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line); +#ifdef DEBUG + printf("Fixup IRQ: dev %d (%x) int line %d 0x%x\n", + PCI_DEV(dev),dev,int_line,int_line); +#endif + } +} + +extern void pci_405gp_init(struct pci_controller *hose); + + +static struct pci_controller hose = { + config_table: pci_pip405_config_table, + fixup_irq: pci_pip405_fixup_irq, +}; + +void pci_init(void) +{ + /*we want the ptrs to RAM not flash (ie don't use init list)*/ + hose.fixup_irq = pci_pip405_fixup_irq; + hose.config_table = pci_pip405_config_table; + pci_405gp_init(&hose); +} + +#endif /* CONFIG_PCI */ +#endif /* CONFIG_405GP */ diff --git a/board/mpl/common/pci_parts.h b/board/mpl/common/pci_parts.h new file mode 100644 index 0000000..944585f --- /dev/null +++ b/board/mpl/common/pci_parts.h @@ -0,0 +1,192 @@ + /* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ +#ifndef _PCI_PARTS_H_ +#define _PCI_PARTS_H_ + + +/* Board specific file containing: + * - PCI Memory Mapping + * - PCI IO Mapping + * - PCI Interrupt Mapping + */ + +/* PIP405 PCI INT Routing: + * IRQ0 VECTOR + * PIXX4 IDSEL = AD16 INTA# 28 (Function 2 USB is INTD# = 31) + * VGA IDSEL = AD17 INTB# 29 + * SCSI IDSEL = AD18 INTC# 30 + * PC104 IDSEL0 = AD20 INTA# 28 + * PC104 IDSEL1 = AD21 INTB# 29 + * PC104 IDSEL2 = AD22 INTC# 30 + * PC104 IDSEL3 = AD23 INTD# 31 + * + * busdevfunc = EXXX XXXX BBBB BBBB DDDD DFFF RRRR RR00 + * ^ ^ ^ ^ ^ + * 31 23 15 10 7 + * E = Enabled + * B = Bussnumber + * D = Devicenumber (Device0 = AD10) + * F = Functionnumber + * R = Registernumber + * + * Device = (busdevfunc>>11) + 10 + * Vector = devicenumber % 4 + 28 + * + */ +#define PCI_HIGHEST_ON_BOARD_ID 19 +/*#define PCI_DEV_NUMBER(x) (((x>>11) & 0x1f) + 10) */ +#define PCI_IRQ_VECTOR(x) ((PCI_DEV(x) + 10) % 4) + 28 + + + +/* PCI Device List for PIP405 */ + +/* Mapping: + * +-------------+------------+------------+--------------------------------+ + * ¦ PCI MemAddr | PCI IOAddr | Local Addr | Device / Function | + * +-------------+------------+------------+--------------------------------+ + * | 0x00000000 | | 0xA0000000 | ISA Memory (hard wired) | + * | 0x00FFFFFF | | 0xA0FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | | 0x00000000 | 0xE8000000 | ISA IO (hard wired) | + * | | 0x0000FFFF | 0xE800FFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x80000000 | | 0x80000000 | VGA Controller Memory | + * | 0x80FFFFFF | | 0x80FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + * | 0x81000000 | | 0x81000000 | SCSI Controller Memory | + * | 0x81FFFFFF | | 0x81FFFFFF | | + * +-------------+------------+------------+--------------------------------+ + */ + +struct pci_pip405_config_entry { + int index; /* address */ + unsigned long val; /* value */ + int width; /* data size */ +}; + +extern void pci_pip405_write_regs(struct pci_controller *, + pci_dev_t, + struct pci_config_table *); + +/* PIIX4 ISA Bridge Function 0 */ +static struct pci_pip405_config_entry piix4_isa_bridge_f0[] = { + {PCI_CFG_PIIX4_SERIRQ, 0xD0, 1}, /* enable Continous SERIRQ Pin */ + {PCI_CFG_PIIX4_GENCFG, 0x00010041, 4}, /* enable SERIRQs, ISA, PNP */ + {PCI_CFG_PIIX4_TOM, 0xFE, 1}, /* Top of Memory */ + {PCI_CFG_PIIX4_XBCS, 0x02C4, 2}, /* disable all peri CS */ + {PCI_CFG_PIIX4_RTCCFG, 0x21, 1}, /* enable RTC */ +#if defined(CONFIG_PIP405) + {PCI_CFG_PIIX4_MBDMA, 0x82, 1}, /* set MBDMA0 to DMA 2 */ + {PCI_CFG_PIIX4_MBDMA+1, 0x83, 1}, /* set MBDMA1 to DMA 3 */ +#endif + {PCI_CFG_PIIX4_DLC, 0x0, 1}, /* disable passive release feature */ + { } /* end of device table */ +}; + +/* PIIX4 IDE Controller Function 1 */ +static struct pci_pip405_config_entry piix4_ide_cntrl_f1[] = { + {PCI_COMMAND, 0x0001, 2}, /* enable IO access */ + {PCI_CFG_PIIX4_IDETIM, 0x80008000, 4}, /* enable Both IDE channels */ + { } /* end of device table */ +}; + +/* PIIX4 USB Controller Function 2 */ +static struct pci_pip405_config_entry piix4_usb_cntrl_f2[] = { + {PCI_INTERRUPT_LINE, 31, 1}, /* Int vector = 31 */ + {PCI_BASE_ADDRESS_4, 0x0000E001, 4}, /* Set IO Address to 0xe000 to 0xe01F */ + {PCI_LATENCY_TIMER, 0x80, 1}, /* Latency Timer 0x80 */ + {0xC0, 0x2000, 2}, /* Legacy support */ + {PCI_COMMAND, 0x0005, 2}, /* enable IO access and Master */ + { } /* end of device table */ +}; + +/* PIIX4 Power Management Function 3 */ +static struct pci_pip405_config_entry piix4_pmm_cntrl_f3[] = { + {PCI_COMMAND, 0x0001, 2}, /* enable IO access */ + {PCI_CFG_PIIX4_PMAB, 0x00004000, 4}, /* set PMBA to "valid" value */ + {PCI_CFG_PIIX4_PMMISC, 0x01, 1}, /* enable PMBA IO access */ + {PCI_CFG_PIIX4_SMBBA, 0x00005000, 4}, /* set SMBBA to "valid" value */ + { } /* end of device table */ +}; +/* PPC405 Dummy only used to prevent autosetup on this host bridge */ +static struct pci_pip405_config_entry ibm405_dummy[] = { + { } /* end of device table */ +}; + +void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry); + + +static struct pci_config_table pci_pip405_config_table[]={ + {PCI_VENDOR_ID_IBM, /* 405 dummy */ + PCI_DEVICE_ID_IBM_405GP, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 0, + pci_pip405_write_regs, {(unsigned long) ibm405_dummy}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 ISA Bridge Function 0 */ + PCI_DEVICE_ID_INTEL_82371AB_0, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 0, + pci_pip405_write_regs, {(unsigned long) piix4_isa_bridge_f0}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 IDE Controller Function 1 */ + PCI_DEVICE_ID_INTEL_82371AB, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 1, + pci_pip405_write_regs, {(unsigned long) piix4_ide_cntrl_f1}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 2 */ + PCI_DEVICE_ID_INTEL_82371AB_2, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 2, + pci_pip405_write_regs, {(unsigned long) piix4_usb_cntrl_f2}}, + + {PCI_VENDOR_ID_INTEL, /* PIIX4 USB Controller Function 3 */ + PCI_DEVICE_ID_INTEL_82371AB_3, + PCI_ANY_ID, + PCI_ANY_ID, PCI_ANY_ID, 3, + pci_pip405_write_regs, {(unsigned long) piix4_pmm_cntrl_f3}}, + + {PCI_ANY_ID, + PCI_ANY_ID, + PCI_CLASS_DISPLAY_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_405gp_setup_vga}, + + {PCI_ANY_ID, + PCI_ANY_ID, + PCI_CLASS_NOT_DEFINED_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_405gp_setup_vga}, + + { } +}; +#endif /* _PCI_PARTS_H_ */ + + + + + diff --git a/board/mpl/mip405/Makefile b/board/mpl/mip405/Makefile new file mode 100644 index 0000000..839cafe --- /dev/null +++ b/board/mpl/mip405/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o ../common/flash.o cmd_mip405.o ../common/pci.o \ + ../common/usb_uhci.o ../common/memtst.o ../common/common_util.o + +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpl/pip405/Makefile b/board/mpl/pip405/Makefile new file mode 100644 index 0000000..b6cc531 --- /dev/null +++ b/board/mpl/pip405/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2000, 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o \ + ../common/flash.o cmd_pip405.o ../common/pci.o \ + ../common/isa.o ../common/kbd.o \ + ../common/usb_uhci.o \ + ../common/memtst.o ../common/common_util.o + +SOBJS = init.o + +$(LIB): $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +clean: + rm -f $(SOBJS) $(OBJS) + +distclean: clean + rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/musenki/musenki.c b/board/musenki/musenki.c new file mode 100644 index 0000000..3b02f37 --- /dev/null +++ b/board/musenki/musenki.c @@ -0,0 +1,130 @@ +/* + * (C) Copyright 2001 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <pci.h> + +int checkboard (void) +{ + ulong busfreq = get_bus_freq(0); + char buf[32]; + + printf("Board: MUSENKI Local Bus at %s MHz\n", strmhz(buf, busfreq)); + return 0; + +} + +#if 0 /* NOT USED */ +int checkflash (void) +{ + /* TODO: XXX XXX XXX */ + printf ("## Test not implemented yet ##\n"); + + return (0); +} +#endif + +long int initdram (int board_type) +{ + int i, cnt; + volatile uchar * base= CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +} + +/* + * Initialize PCI Devices + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_sandpoint_config_table[] = { +#if 0 + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + 0x0, 0x0, 0x0, /* unknown eth0 divice */ + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + 0x0, 0x0, 0x0, /* unknown eth1 device */ + pci_cfgfunc_config_device, { PCI_ENET1_IOADDR, + PCI_ENET1_MEMADDR, + PCI_COMMAND_IO | + PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER }}, +#endif + { } +}; +#endif + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_sandpoint_config_table, +#endif +}; + +void pci_init(void) +{ + pci_mpc824x_init(&hose); +} diff --git a/board/mvs1/Makefile b/board/mvs1/Makefile new file mode 100644 index 0000000..ef173d0 --- /dev/null +++ b/board/mvs1/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/netvia/Makefile b/board/netvia/Makefile new file mode 100644 index 0000000..ef173d0 --- /dev/null +++ b/board/netvia/Makefile @@ -0,0 +1,40 @@ +# +# (C) Copyright 2000 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o + +$(LIB): .depend $(OBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/netvia/netvia.c b/board/netvia/netvia.c new file mode 100644 index 0000000..504593e --- /dev/null +++ b/board/netvia/netvia.c @@ -0,0 +1,374 @@ +/* + * (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 + */ + +/* + * Pantelis Antoniou, Intracom S.A., panto@intracom.gr + * U-Boot port on NetVia board + */ + +#include <common.h> +#include "mpc8xx.h" + +/* some sane bit macros */ +#define _BD(_b) (1U << (31-(_b))) +#define _BDR(_l, _h) (((((1U << (31-(_l))) - 1) << 1) | 1) & ~((1U << (31-(_h))) - 1)) + +#define _BW(_b) (1U << (15-(_b))) +#define _BWR(_l, _h) (((((1U << (15-(_l))) - 1) << 1) | 1) & ~((1U << (15-(_h))) - 1)) + +#define _BB(_b) (1U << (7-(_b))) +#define _BBR(_l, _h) (((((1U << (7-(_l))) - 1) << 1) | 1) & ~((1U << (7-(_h))) - 1)) + +#define _B(_b) _BD(_b) +#define _BR(_l, _h) _BDR(_l, _h) + +/* ------------------------------------------------------------------------- */ + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFFFFF + +/* ------------------------------------------------------------------------- */ + +#define CS_0000 0x00000000 +#define CS_0001 0x10000000 +#define CS_0010 0x20000000 +#define CS_0011 0x30000000 +#define CS_0100 0x40000000 +#define CS_0101 0x50000000 +#define CS_0110 0x60000000 +#define CS_0111 0x70000000 +#define CS_1000 0x80000000 +#define CS_1001 0x90000000 +#define CS_1010 0xA0000000 +#define CS_1011 0xB0000000 +#define CS_1100 0xC0000000 +#define CS_1101 0xD0000000 +#define CS_1110 0xE0000000 +#define CS_1111 0xF0000000 + +#define BS_0000 0x00000000 +#define BS_0001 0x01000000 +#define BS_0010 0x02000000 +#define BS_0011 0x03000000 +#define BS_0100 0x04000000 +#define BS_0101 0x05000000 +#define BS_0110 0x06000000 +#define BS_0111 0x07000000 +#define BS_1000 0x08000000 +#define BS_1001 0x09000000 +#define BS_1010 0x0A000000 +#define BS_1011 0x0B000000 +#define BS_1100 0x0C000000 +#define BS_1101 0x0D000000 +#define BS_1110 0x0E000000 +#define BS_1111 0x0F000000 + +#define A10_AAAA 0x00000000 +#define A10_AAA0 0x00200000 +#define A10_AAA1 0x00300000 +#define A10_000A 0x00800000 +#define A10_0000 0x00A00000 +#define A10_0001 0x00B00000 +#define A10_111A 0x00C00000 +#define A10_1110 0x00E00000 +#define A10_1111 0x00F00000 + +#define RAS_0000 0x00000000 +#define RAS_0001 0x00040000 +#define RAS_1110 0x00080000 +#define RAS_1111 0x000C0000 + +#define CAS_0000 0x00000000 +#define CAS_0001 0x00010000 +#define CAS_1110 0x00020000 +#define CAS_1111 0x00030000 + +#define WE_0000 0x00000000 +#define WE_0001 0x00004000 +#define WE_1110 0x00008000 +#define WE_1111 0x0000C000 + +#define GPL4_0000 0x00000000 +#define GPL4_0001 0x00001000 +#define GPL4_1110 0x00002000 +#define GPL4_1111 0x00003000 + +#define GPL5_0000 0x00000000 +#define GPL5_0001 0x00000400 +#define GPL5_1110 0x00000800 +#define GPL5_1111 0x00000C00 +#define LOOP 0x00000080 + +#define EXEN 0x00000040 + +#define AMX_COL 0x00000000 +#define AMX_ROW 0x00000020 +#define AMX_MAR 0x00000030 + +#define NA 0x00000008 + +#define UTA 0x00000004 + +#define TODT 0x00000002 + +#define LAST 0x00000001 + +const uint sdram_table[0x40] = { + /* RSS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0000 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, + + /* RBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_1111 | A10_0001 | RAS_1111 | CAS_0001 | WE_1111 | AMX_COL | UTA, /* READ */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0001 | BS_0001 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WSS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, + CS_0000 | BS_0001 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL | UTA, + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA | TODT | LAST, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* WBS */ + CS_0001 | BS_1111 | A10_AAAA | RAS_0001 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* ACT */ + CS_1111 | BS_1111 | A10_0000 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0001 | BS_0000 | A10_0000 | RAS_1111 | CAS_0001 | WE_0000 | AMX_COL, /* WRITE */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0000 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_1111 | BS_0001 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL | UTA, /* PALL */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | UTA | TODT | LAST, /* NOP */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, + + /* UPT */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, /* NOP */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_0001 | WE_1111 | AMX_COL | LOOP, + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL, + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | LOOP, + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | LAST, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, + + /* EXC */ + CS_0001 | BS_1111 | A10_1111 | RAS_0001 | CAS_1111 | WE_0001 | AMX_COL, + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1111 | AMX_COL | TODT | LAST, + + /* REG */ + CS_1111 | BS_1111 | A10_1111 | RAS_1111 | CAS_1111 | WE_1110 | AMX_MAR, + CS_0001 | BS_1111 | A10_0001 | RAS_0001 | CAS_0001 | WE_0001 | AMX_MAR | TODT | LAST, +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + * + * Test ETX ID string (ETX_xxx...) + * + * Return 1 always. + */ + +int checkboard(void) +{ + printf ("NETVIA\n"); + return (0); +} + +/* ------------------------------------------------------------------------- */ + +/* 0xC8 = 0b11001000 , CAS3, >> 2 = 0b00 11 0 010 */ +#define MAR_SDRAM_INIT 0x000000C8LU + +#define MCR_OP(x) ((unsigned long)((x) & 3) << (31-1)) +#define MCR_OP_MASK MCR_OP(3) + +#define MCR_UM(x) ((unsigned long)((x) & 1) << (31 - 8)) +#define MCR_UM_MASK MCR_UM(1) +#define MCR_UM_UPMA MCR_UM(0) +#define MCR_UM_UPMB MCR_UM(1) + +#define MCR_MB(x) ((unsigned long)((x) & 7) << (31 - 18)) +#define MCR_MB_MASK MCR_MB(7) +#define MCR_MB_CS(x) MCR_MB(x) + +#define MCR_MCLF(x) ((unsigned long)((x) & 15) << (31 - 23)) +#define MCR_MCLF_MASK MCR_MCLF(15) + +long int initdram(int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size; + + upmconfig(UPMA, (uint *) sdram_table, sizeof(sdram_table) / sizeof(uint)); + + /* + * Preliminary prescaler for refresh + */ + memctl->memc_mptpr = CFG_MPTPR_1BK_8K; + + memctl->memc_mar = MAR_SDRAM_INIT; /* 32-bit address to be output on the address bus if AMX = 0b11 */ + + /* + * Map controller bank 3 to the SDRAM bank at preliminary address. + */ + memctl->memc_or3 = CFG_OR3_PRELIM; + memctl->memc_br3 = CFG_BR3_PRELIM; + + memctl->memc_mamr = CFG_MAMR_9COL & ~MAMR_PTAE; /* no refresh yet */ + + udelay(200); + + /* perform SDRAM initialisation sequence */ + memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(1) | MCR_MAD(0x3C); /* precharge all */ + udelay(1); + memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(0) | MCR_MAD(0x30); /* refresh 16 times(0) */ + udelay(1); + memctl->memc_mcr = MCR_OP_RUN | MCR_UM_UPMA | MCR_MB_CS3 | MCR_MCLF(1) | MCR_MAD(0x3E); /* exception program (write mar) */ + udelay(1); + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay(1000); + + memctl->memc_mamr = CFG_MAMR_9COL; + + size = SDRAM_MAX_SIZE; + + udelay(10000); + + /* do the ram test */ + { + register unsigned long *rp; + register unsigned long v; + + /* first fill */ + for (rp = (unsigned long *)0; rp < (unsigned long *)SDRAM_MAX_SIZE; ) + *rp++ = (unsigned long)rp; + + /* now check */ + for (rp = (unsigned long *)0; rp < (unsigned long *)SDRAM_MAX_SIZE; rp++) { + if ((v = *rp) != (unsigned long)rp) { + printf("ERROR at 0x%lx (0x%lx)\n", (unsigned long)rp, v); + return -1; + } + } + + } + + return (size); +} + +/* ------------------------------------------------------------------------- */ + +int misc_init_r(void) +{ + return(0); +} + +/* ------------------------------------------------------------------------- */ + +/* bits that can have a special purpose or can be configured as inputs/outputs */ +#define PA_MASK (_BWR(4, 9) | _BWR(12, 15)) +#define PA_ODR_MASK (_BW(9) | _BW(12) | _BW(14)) +#define PA_ODR_VAL 0 +#define PA_GP_INMASK 0 +#define PA_GP_OUTMASK (_BW(5) | _BW(14) | _BW(15)) +#define PA_SP_OUTMASK 0 +#define PA_GP_OUTVAL _BW(5) +#define PA_SP_OUTVAL 0 + +#define PB_MASK (_BR(16, 19) | _BR(22, 31)) +#define PB_ODR_MASK PB_MASK +#define PB_ODR_VAL 0 +#define PB_GP_INMASK 0 +#define PB_GP_OUTMASK (_BR(16, 19) | _BR(26, 27) | _B(31)) +#define PB_SP_OUTMASK _BR(28, 30) +#define PB_SP_OUTVAL _BR(28, 30) +#define PB_GP_OUTVAL (_BR(16, 19) | _BR(26, 27) | _B(31)) + +#define PC_MASK _BWR(4, 15) +#define PC_SO_MASK (_BWR(6, 11) | _BWR(14, 15)) +#define PC_SO_VAL 0 +#define PC_INT_MASK PC_MASK +#define PC_INT_VAL 0 +#define PC_GP_INMASK (_BWR(5, 7) | _BWR(9, 10) | _BW(13)) +#define PC_GP_OUTMASK _BW(12) +#define PC_SP_OUTMASK 0 +#define PC_SP_OUTVAL _BW(12) +#define PC_GP_OUTVAL 0 + +#define PD_MASK _BWR(0, 15) +#define PD_GP_INMASK 0 +#define PD_GP_OUTMASK _BWR(3, 15) +#define PD_SP_OUTMASK 0 +#define PD_GP_OUTVAL (_BW(3) | _BW(5) | _BW(7) | _BWR(8, 15)) +#define PD_SP_OUTVAL 0 + +int board_pre_init(void) +{ + register volatile immap_t *immap = (immap_t *) CFG_IMMR; + register volatile iop8xx_t *ioport = &immap->im_ioport; + register volatile cpm8xx_t *cpm = &immap->im_cpm; + + ioport->iop_padat = (ioport->iop_padat & ~PA_MASK) | PA_SP_OUTVAL | PA_GP_OUTVAL; + ioport->iop_paodr = (ioport->iop_paodr & ~PA_ODR_MASK) | PA_ODR_VAL; + ioport->iop_padir = (ioport->iop_padir & ~PA_GP_INMASK)| PA_SP_OUTMASK | PA_GP_OUTMASK; + ioport->iop_papar = (ioport->iop_papar & ~(PA_GP_INMASK & PA_GP_OUTMASK)); + + cpm->cp_pbdat = (ioport->iop_padat & ~PB_MASK) | PB_SP_OUTVAL | PB_GP_OUTVAL; + cpm->cp_pbodr = (ioport->iop_paodr & ~PB_ODR_MASK) | PB_ODR_VAL; + cpm->cp_pbdir = (ioport->iop_padir & ~PB_GP_INMASK)| PB_SP_OUTMASK | PB_GP_OUTMASK; + cpm->cp_pbpar = (ioport->iop_papar & ~(PB_GP_INMASK & PB_GP_OUTMASK)); + + ioport->iop_pcdat = (ioport->iop_pcdat & ~PC_MASK) | PC_SP_OUTVAL | PC_GP_OUTVAL; + ioport->iop_pcdir = (ioport->iop_pcdir & ~PC_GP_INMASK)| PC_SP_OUTMASK | PC_GP_OUTMASK; + ioport->iop_pcso = (ioport->iop_pcso & ~PC_SO_MASK) | PC_SO_VAL; + ioport->iop_pcint = (ioport->iop_pcint & ~PC_INT_MASK) | PC_INT_VAL; + ioport->iop_pcpar = (ioport->iop_pcpar & ~(PC_GP_INMASK & PC_GP_OUTMASK)); + + ioport->iop_pddat = (ioport->iop_pddat & ~PD_MASK) | PD_SP_OUTVAL | PD_GP_OUTVAL; + ioport->iop_pddir = (ioport->iop_pddir & ~PD_GP_INMASK)| PD_SP_OUTMASK | PD_GP_OUTMASK; + ioport->iop_pdpar = (ioport->iop_pdpar & ~(PD_GP_INMASK & PD_GP_OUTMASK)); + + return 0; +} + diff --git a/board/netvia/u-boot.lds b/board/netvia/u-boot.lds new file mode 100644 index 0000000..e75f12c --- /dev/null +++ b/board/netvia/u-boot.lds @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + cpu/mpc8xx/start.o (.text) + cpu/mpc8xx/traps.o (.text) + common/dlmalloc.o (.text) + lib_ppc/ppcstring.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + lib_generic/zlib.o (.text) + lib_ppc/cache.o (.text) + lib_ppc/time.o (.text) + + . = env_offset; + common/environment.o (.ppcenv) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x00FF) & 0xFFFFFF00; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(256); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(256); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} diff --git a/board/netvia/u-boot.lds.debug b/board/netvia/u-boot.lds.debug new file mode 100644 index 0000000..fa494fb --- /dev/null +++ b/board/netvia/u-boot.lds.debug @@ -0,0 +1,131 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? + __DYNAMIC = 0; */ +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + . = + SIZEOF_HEADERS; + .interp : { *(.interp) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .rel.text : { *(.rel.text) } + .rela.text : { *(.rela.text) } + .rel.data : { *(.rel.data) } + .rela.data : { *(.rela.data) } + .rel.rodata : { *(.rel.rodata) } + .rela.rodata : { *(.rela.rodata) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + .init : { *(.init) } + .plt : { *(.plt) } + .text : + { + /* WARNING - the following is hand-optimized to fit within */ + /* the sector layout of our flash chips! XXX FIXME XXX */ + + cpu/mpc8xx/start.o (.text) + common/dlmalloc.o (.text) + lib_generic/vsprintf.o (.text) + lib_generic/crc32.o (.text) + + . = env_offset; + common/environment.o(.text) + + *(.text) + *(.fixup) + *(.got1) + } + _etext = .; + PROVIDE (etext = .); + .rodata : + { + *(.rodata) + *(.rodata1) + } + .fini : { *(.fini) } =0 + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + + /* Read-write section, merged into data segment: */ + . = (. + 0x0FFF) & 0xFFFFF000; + _erotext = .; + PROVIDE (erotext = .); + .reloc : + { + *(.got) + _GOT2_TABLE_ = .; + *(.got2) + _FIXUP_TABLE_ = .; + *(.fixup) + } + __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; + __fixup_entries = (. - _FIXUP_TABLE_)>>2; + + .data : + { + *(.data) + *(.data1) + *(.sdata) + *(.sdata2) + *(.dynamic) + CONSTRUCTORS + } + _edata = .; + PROVIDE (edata = .); + + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + . = ALIGN(4096); + __init_begin = .; + .text.init : { *(.text.init) } + .data.init : { *(.data.init) } + . = ALIGN(4096); + __init_end = .; + + __bss_start = .; + .bss : + { + *(.sbss) *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + _end = . ; + PROVIDE (end = .); +} + diff --git a/board/oxc/flash.c b/board/oxc/flash.c new file mode 100644 index 0000000..4f0220e --- /dev/null +++ b/board/oxc/flash.c @@ -0,0 +1,372 @@ +/* + * (C) Copyright 2000 + * Marius Groeger <mgroeger@sysgo.de> + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * Flash Routines for STM29W320DB/STM29W800D flash chips + * + *-------------------------------------------------------------------- + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ + +static ulong flash_get_size (vu_char *addr, flash_info_t *info); +static int write_byte (flash_info_t *info, ulong dest, uchar data); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + unsigned long size; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* + * We use the following trick here: since flash is cyclically + * mapped in the 0xFF800000-0xFFFFFFFF area, we detect the type + * and the size of flash using 0xFF800000 as the base address, + * and then call flash_get_size() again to fill flash_info. + */ + size = flash_get_size((vu_char *)CFG_FLASH_PRELIMBASE, &flash_info[0]); + if (size) + { + flash_get_size((vu_char *)(-size), &flash_info[0]); + } + +#if (CFG_MONITOR_BASE >= CFG_FLASH_PRELIMBASE) + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + +#if (CFG_ENV_IS_IN_FLASH == 1) && defined(CFG_ENV_ADDR) +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR + CFG_ENV_SIZE - 1, + &flash_info[0]); +#endif + + return (size); +} + +/*----------------------------------------------------------------------- + */ +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_STM: + printf ("ST "); + break; + default: + printf ("Unknown Vendor "); + break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_STM320DB: + printf ("M29W320DB (32 Mbit)\n"); + break; + case FLASH_STM800DB: + printf ("M29W800DB (8 Mbit, bottom boot block)\n"); + break; + case FLASH_STM800DT: + printf ("M29W800DT (8 Mbit, top boot block)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_char *addr, flash_info_t *info) +{ + short i; + uchar vendor, devid; + ulong base = (ulong)addr; + + /* Write auto select command: read Manufacturer ID */ + addr[0x0AAA] = 0xAA; + addr[0x0555] = 0x55; + addr[0x0AAA] = 0x90; + + udelay(1000); + + vendor = addr[0]; + devid = addr[2]; + + /* only support STM */ + if ((vendor << 16) != FLASH_MAN_STM) { + return 0; + } + + if (devid == FLASH_STM320DB) { + /* MPC8240 can address maximum 2Mb of flash, that is why the MSB + * lead is grounded and we can access only 2 first Mb */ + info->flash_id = vendor << 16 | devid; + info->sector_count = 32; + info->size = info->sector_count * 0x10000; + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + i * 0x10000; + } + } + else if (devid == FLASH_STM800DB) { + info->flash_id = vendor << 16 | devid; + info->sector_count = 19; + info->size = 0x100000; + info->start[0] = 0x0000; + info->start[1] = 0x4000; + info->start[2] = 0x6000; + info->start[3] = 0x8000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i-3) * 0x10000; + } + } + else if (devid == FLASH_STM800DT) { + info->flash_id = vendor << 16 | devid; + info->sector_count = 19; + info->size = 0x100000; + for (i = 0; i < info->sector_count-4; i++) { + info->start[i] = base + i * 0x10000; + } + info->start[i] = base + i * 0x10000; + info->start[i+1] = base + i * 0x10000 + 0x8000; + info->start[i+2] = base + i * 0x10000 + 0xa000; + info->start[i+3] = base + i * 0x10000 + 0xc000; + } + else { + return 0; + } + + /* mark all sectors as unprotected */ + for (i = 0; i < info->sector_count; i++) { + info->protect[i] = 0; + } + + /* Issue the reset command */ + if (info->flash_id != FLASH_UNKNOWN) { + addr[0] = 0xF0; /* reset bank */ + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + vu_char *addr = (vu_char *)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + prot = 0; + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0AAA] = 0xAA; + addr[0x0555] = 0x55; + addr[0x0AAA] = 0x80; + addr[0x0AAA] = 0xAA; + addr[0x0555] = 0x55; + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_char *)(info->start[sect]); + addr[0] = 0x30; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (vu_char *)(info->start[l_sect]); + while ((addr[0] & 0x80) != 0x80) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + serial_putc ('.'); + last = now; + } + } + + DONE: + /* reset to read mode */ + addr = (volatile unsigned char *)info->start[0]; + addr[0] = 0xF0; /* reset bank */ + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + int rc; + + while (cnt > 0) { + if ((rc = write_byte(info, addr, *src)) != 0) { + return (rc); + } + addr++; + src++; + cnt--; + } + + return (0); +} + +/*----------------------------------------------------------------------- + * Write a byte to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_byte (flash_info_t *info, ulong dest, uchar data) +{ + vu_char *addr = (vu_char *)(info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_char *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0AAA] = 0xAA; + addr[0x0555] = 0x55; + addr[0x0AAA] = 0xA0; + + *((vu_char *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_char *)dest) & 0x80) != (data & 0x80)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/oxc/oxc.c b/board/oxc/oxc.c new file mode 100644 index 0000000..8aced84 --- /dev/null +++ b/board/oxc/oxc.c @@ -0,0 +1,237 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <pci.h> +#include <i2c.h> + +int checkboard (void) +{ + puts ( "Board: OXC8240\n" ); + return 0; +} + +long int initdram (int board_type) +{ +#ifndef CFG_RAMBOOT + int i, cnt; + volatile uchar * base= CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +#else + /* if U-Boot starts from RAM, then suppose we have 16Mb of RAM */ + return (16 << 20); +#endif +} + +/* + * Initialize PCI Devices, report devices found. + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_oxc_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x14, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x15, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET1_IOADDR, + PCI_ENET1_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { } +}; +#endif + +static struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_oxc_config_table, +#endif +}; + +void pci_init (void) +{ + pci_mpc824x_init(&hose); +} + +int board_pre_init (void) +{ + *(volatile unsigned char *)(CFG_CPLD_RESET) = 0x89; + return 0; +} + +#ifdef CONFIG_WATCHDOG +void oxc_wdt_reset(void) +{ + *(volatile unsigned char *)(CFG_CPLD_WATCHDOG) = 0xff; +} + +void watchdog_reset(void) +{ + int re_enable = disable_interrupts(); + + oxc_wdt_reset(); + if (re_enable) + enable_interrupts(); +} +#endif + +static int oxc_get_expander(unsigned char addr, unsigned char * val) +{ + return i2c_read(addr, 0, 0, val, 1); +} + +static int oxc_set_expander(unsigned char addr, unsigned char val) +{ + return i2c_write(addr, 0, 0, &val, 1); +} + +static int expander0alive = 0; + +#ifdef CONFIG_SHOW_ACTIVITY +static int ledtoggle = 0; +static int ledstatus = 1; + +void oxc_toggle_activeled(void) +{ + ledtoggle++; +} + +void show_activity(int arg) +{ + static unsigned char led = 0; + unsigned char val; + + if (!expander0alive) return; + + if ((ledtoggle > (2 * arg)) && ledstatus) { + led ^= 0x80; + oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val); + udelay(200); + oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, (val & 0x7F) | led); + ledtoggle = 0; + } +} +#endif + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +void show_boot_progress(int arg) +{ + unsigned char val; + + if (!expander0alive) return; + + if (arg > 0 && ledstatus) { + ledstatus = 0; + oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val); + udelay(200); + oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, val | 0x80); + } else if (arg < 0) { + oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val); + udelay(200); + oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, val & 0x7F); + ledstatus = 1; + } +} +#endif + +int misc_init_r (void) +{ + /* check whether the i2c expander #0 is accessible */ + if (!oxc_set_expander(CFG_I2C_EXPANDER0_ADDR, 0x7F)) { + udelay(200); + expander0alive = 1; + } + +#ifdef CFG_OXC_GENERATE_IP + { + DECLARE_GLOBAL_DATA_PTR; + + char str[32]; + unsigned long ip = CFG_OXC_IPMASK; + bd_t *bd = gd->bd; + + if (expander0alive) { + unsigned char val; + + if (!oxc_get_expander(CFG_I2C_EXPANDER0_ADDR, &val)) { + ip = (ip & 0xffffff00) | ((val & 0x7c) >> 2); + } + } + + if ((ip & 0xff) < 3) { + /* if fail, set x.x.x.254 */ + ip = (ip & 0xffffff00) | 0xfe; + } + + bd->bi_ip_addr = ip; + sprintf(str, "%ld.%ld.%ld.%ld", + (bd->bi_ip_addr & 0xff000000) >> 24, + (bd->bi_ip_addr & 0x00ff0000) >> 16, + (bd->bi_ip_addr & 0x0000ff00) >> 8, + (bd->bi_ip_addr & 0x000000ff)); + setenv("ipaddr", str); + printf("ip: %s\n", str); + } +#endif + return (0); +} diff --git a/board/pcippc2/cpc710_init_ram.c b/board/pcippc2/cpc710_init_ram.c new file mode 100644 index 0000000..57ed8f0 --- /dev/null +++ b/board/pcippc2/cpc710_init_ram.c @@ -0,0 +1,254 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> + +#include "pcippc2.h" +#include "i2c.h" + +typedef struct cpc710_mem_org_s +{ + u8 rows; + u8 cols; + u8 banks2; + u8 org; +} cpc710_mem_org_t; + +static int cpc710_compute_mcer (u32 * mcer, + unsigned long * + size, + unsigned int sdram); +static int cpc710_eeprom_checksum (unsigned int sdram); +static u8 cpc710_eeprom_read (unsigned int sdram, + unsigned int offset); + +static u32 cpc710_mcer_mem [] = +{ + 0x000003f3, /* 18 lines, 4 Mb */ + 0x000003e3, /* 19 lines, 8 Mb */ + 0x000003c3, /* 20 lines, 16 Mb */ + 0x00000383, /* 21 lines, 32 Mb */ + 0x00000303, /* 22 lines, 64 Mb */ + 0x00000203, /* 23 lines, 128 Mb */ + 0x00000003, /* 24 lines, 256 Mb */ + 0x00000002, /* 25 lines, 512 Mb */ + 0x00000001 /* 26 lines, 1024 Mb */ +}; +static cpc710_mem_org_t cpc710_mem_org [] = +{ + { 0x0c, 0x09, 0x02, 0x00 }, /* 0000: 12/ 9/2 */ + { 0x0d, 0x09, 0x02, 0x00 }, /* 0000: 13/ 9/2 */ + { 0x0d, 0x0a, 0x02, 0x00 }, /* 0000: 13/10/2 */ + { 0x0d, 0x0b, 0x02, 0x00 }, /* 0000: 13/11/2 */ + { 0x0d, 0x0c, 0x02, 0x00 }, /* 0000: 13/12/2 */ + { 0x0e, 0x0c, 0x02, 0x00 }, /* 0000: 14/12/2 */ + { 0x0b, 0x08, 0x02, 0x01 }, /* 0001: 11/ 8/2 */ + { 0x0b, 0x09, 0x01, 0x02 }, /* 0010: 11/ 9/1 */ + { 0x0b, 0x0a, 0x01, 0x03 }, /* 0011: 11/10/1 */ + { 0x0c, 0x08, 0x02, 0x04 }, /* 0100: 12/ 8/2 */ + { 0x0c, 0x0a, 0x02, 0x05 }, /* 0101: 12/10/2 */ + { 0x0d, 0x08, 0x01, 0x06 }, /* 0110: 13/ 8/1 */ + { 0x0d, 0x08, 0x02, 0x07 }, /* 0111: 13/ 8/2 */ + { 0x0d, 0x09, 0x01, 0x08 }, /* 1000: 13/ 9/1 */ + { 0x0d, 0x0a, 0x01, 0x09 }, /* 1001: 13/10/1 */ + { 0x0b, 0x08, 0x01, 0x0a }, /* 1010: 11/ 8/1 */ + { 0x0c, 0x08, 0x01, 0x0b }, /* 1011: 12/ 8/1 */ + { 0x0c, 0x09, 0x01, 0x0c }, /* 1100: 12/ 9/1 */ + { 0x0e, 0x09, 0x02, 0x0d }, /* 1101: 14/ 9/2 */ + { 0x0e, 0x0a, 0x02, 0x0e }, /* 1110: 14/10/2 */ + { 0x0e, 0x0b, 0x02, 0x0f } /* 1111: 14/11/2 */ +}; + +unsigned long cpc710_ram_init (void) +{ + unsigned long memsize = 0; + unsigned long bank_size; + u32 mcer; + +#ifndef CFG_RAMBOOT + /* Clear memory banks + */ + out32(REG(SDRAM0, MCER0), 0); + out32(REG(SDRAM0, MCER1), 0); + out32(REG(SDRAM0, MCER2), 0); + out32(REG(SDRAM0, MCER3), 0); + out32(REG(SDRAM0, MCER4), 0); + out32(REG(SDRAM0, MCER5), 0); + out32(REG(SDRAM0, MCER6), 0); + out32(REG(SDRAM0, MCER7), 0); + iobarrier_rw(); + + /* Disable memory + */ + out32(REG(SDRAM0,MCCR), 0x13b06000); + iobarrier_rw(); +#endif + + /* Only the first memory bank is initialised now + */ + if (! cpc710_compute_mcer(& mcer, & bank_size, 0)) + { + puts("Unsupported SDRAM type !\n"); + hang(); + } + memsize += bank_size; +#ifndef CFG_RAMBOOT + /* Enable bank, zero start + */ + out32(REG(SDRAM0, MCER0), mcer | 0x80000000); + iobarrier_rw(); +#endif + +#ifndef CFG_RAMBOOT + /* Enable memory + */ + out32(REG(SDRAM0, MCCR), in32(REG(SDRAM0, MCCR)) | 0x80000000); + + /* Wait until initialisation finished + */ + while (! (in32 (REG(SDRAM0, MCCR)) & 0x20000000)) + { + iobarrier_rw(); + } + + /* Clear Memory Error Status and Address registers + */ + out32(REG(SDRAM0, MESR), 0); + out32(REG(SDRAM0, MEAR), 0); + iobarrier_rw(); + + /* ECC is not configured now + */ +#endif + + /* Memory size counter + */ + out32(REG(CPC0, RGBAN1), memsize); + + return memsize; +} + +static int cpc710_compute_mcer ( + u32 * mcer, + unsigned long * size, + unsigned int sdram) +{ + u8 rows; + u8 cols; + u8 banks2; + unsigned int lines; + u32 mc = 0; + unsigned int i; + cpc710_mem_org_t * org = 0; + + + if (! i2c_reset()) + { + puts("Can't reset I2C!\n"); + hang(); + } + + if (! cpc710_eeprom_checksum(sdram)) + { + puts("Invalid EEPROM checksum !\n"); + hang(); + } + + rows = cpc710_eeprom_read(sdram, 3); + cols = cpc710_eeprom_read(sdram, 4); + /* Can be 2 or 4 banks; divide by 2 + */ + banks2 = cpc710_eeprom_read(sdram, 17) / 2; + + lines = rows + cols + banks2; + + if (lines < 18 || lines > 26) + { + /* Unsupported configuration + */ + return 0; + } + + + mc |= cpc710_mcer_mem [lines - 18] << 6; + + for (i = 0; i < sizeof(cpc710_mem_org) / sizeof(cpc710_mem_org_t); i++) + { + cpc710_mem_org_t * corg = cpc710_mem_org + i; + + if (corg->rows == rows && corg->cols == cols && corg->banks2 == banks2) + { + org = corg; + + break; + } + } + + if (! org) + { + /* Unsupported configuration + */ + return 0; + } + + mc |= (u32) org->org << 2; + + /* Supported configuration + */ + *mcer = mc; + *size = 1l << (lines + 4); + + return 1; +} + +static int cpc710_eeprom_checksum ( + unsigned int sdram) +{ + u8 sum = 0; + unsigned int i; + + for (i = 0; i < 63; i++) + { + sum += cpc710_eeprom_read(sdram, i); + } + + return sum == cpc710_eeprom_read(sdram, 63); +} + +static u8 cpc710_eeprom_read ( + unsigned int sdram, + unsigned int offset) +{ + u8 dev = (sdram << 1) | 0xa0; + u8 data; + + if (! i2c_read_byte(& data, dev,offset)) + { + puts("I2C error !\n"); + hang(); + } + + return data; +} diff --git a/board/pcippc2/cpc710_pci.c b/board/pcippc2/cpc710_pci.c new file mode 100644 index 0000000..9975cda --- /dev/null +++ b/board/pcippc2/cpc710_pci.c @@ -0,0 +1,309 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> +#include <pci.h> + +#include "hardware.h" +#include "pcippc2.h" + +struct pci_controller local_hose, cpci_hose; + +static u32 cpc710_mapped_ram; + + /* Enable PCI retry timeouts + */ +void cpc710_pci_enable_timeout (void) +{ + out32(BRIDGE(LOCAL, CFGADDR), 0x50000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x32000000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x50000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x32000000); + iobarrier_rw(); +} + +void cpc710_pci_init (void) +{ + u32 sdram_size = pcippc2_sdram_size(); + + cpc710_mapped_ram = sdram_size < PCI_MEMORY_MAXSIZE ? + sdram_size : PCI_MEMORY_MAXSIZE; + + /* Select the local PCI + */ + out32(REG(CPC0, PCICNFR), 0x80000002); + iobarrier_rw(); + + out32(REG(CPC0, PCIBAR), BRIDGE_LOCAL_PHYS); + iobarrier_rw(); + + /* Enable PCI bridge address decoding + */ + out32(REG(CPC0, PCIENB), 0x80000000); + iobarrier_rw(); + + /* Select the CPCI bridge + */ + out32(REG(CPC0, PCICNFR), 0x80000003); + iobarrier_rw(); + + out32(REG(CPC0, PCIBAR), BRIDGE_CPCI_PHYS); + iobarrier_rw(); + + /* Enable PCI bridge address decoding + */ + out32(REG(CPC0, PCIENB), 0x80000000); + iobarrier_rw(); + + /* Disable configuration accesses + */ + out32(REG(CPC0, PCICNFR), 0x80000000); + iobarrier_rw(); + + /* Initialise the local PCI + */ + out32(BRIDGE(LOCAL, CRR), 0x7c000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PCIDG), 0x40000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PIBAR), BRIDGE_LOCAL_IO_BUS); + out32(BRIDGE(LOCAL, SIBAR), BRIDGE_LOCAL_IO_PHYS); + out32(BRIDGE(LOCAL, IOSIZE), -BRIDGE_LOCAL_IO_SIZE); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PMBAR), BRIDGE_LOCAL_MEM_BUS); + out32(BRIDGE(LOCAL, SMBAR), BRIDGE_LOCAL_MEM_PHYS); + out32(BRIDGE(LOCAL, MSIZE), -BRIDGE_LOCAL_MEM_SIZE); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PR), 0x00ffe000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, ACR), 0xfe000000); + iobarrier_rw(); + out32(BRIDGE(LOCAL, PSBAR), PCI_MEMORY_BUS >> 24); + out32(BRIDGE(LOCAL, BARPS), PCI_MEMORY_PHYS >> 24); + out32(BRIDGE(LOCAL, PSSIZE), 256 - (cpc710_mapped_ram >> 24)); + iobarrier_rw(); + + /* Initialise the CPCI bridge + */ + out32(BRIDGE(CPCI, CRR), 0x7c000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PCIDG), 0xC0000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PIBAR), BRIDGE_CPCI_IO_BUS); + out32(BRIDGE(CPCI, SIBAR), BRIDGE_CPCI_IO_PHYS); + out32(BRIDGE(CPCI, IOSIZE), -BRIDGE_CPCI_IO_SIZE); + iobarrier_rw(); + out32(BRIDGE(CPCI, PMBAR), BRIDGE_CPCI_MEM_BUS); + out32(BRIDGE(CPCI, SMBAR), BRIDGE_CPCI_MEM_PHYS); + out32(BRIDGE(CPCI, MSIZE), -BRIDGE_CPCI_MEM_SIZE); + iobarrier_rw(); + out32(BRIDGE(CPCI, PR), 0x80ffe000); + iobarrier_rw(); + out32(BRIDGE(CPCI, ACR), 0xdf000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, PSBAR), PCI_MEMORY_BUS >> 24); + out32(BRIDGE(CPCI, BARPS), PCI_MEMORY_PHYS >> 24); + out32(BRIDGE(CPCI, PSSIZE), 256 - (cpc710_mapped_ram >> 24)); + iobarrier_rw(); + + /* Local PCI + */ + + out32(BRIDGE(LOCAL, CFGADDR), 0x04000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x56010000); + iobarrier_rw(); + + out32(BRIDGE(LOCAL, CFGADDR), 0x0c000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), PCI_LATENCY_TIMER_VAL << 16); + iobarrier_rw(); + + /* Set bus and subbus numbers + */ + out32(BRIDGE(LOCAL, CFGADDR), 0x40000080); + iobarrier_rw(); + out32(BRIDGE(LOCAL, CFGDATA), 0x00000000); + iobarrier_rw(); + + out32(BRIDGE(LOCAL, CFGADDR), 0x50000080); + iobarrier_rw(); + /* PCI retry timeouts will be enabled later + */ + out32(BRIDGE(LOCAL, CFGDATA), 0x00000000); + iobarrier_rw(); + + /* CPCI + */ + + /* Set bus and subbus numbers + */ + out32(BRIDGE(CPCI, CFGADDR), 0x40000080); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x01010000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x04000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x56010000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x0c000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), PCI_LATENCY_TIMER_VAL << 16); + iobarrier_rw(); + + /* Write to the PSBAR */ + out32(BRIDGE(CPCI, CFGADDR), 0x10000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), cpu_to_le32(PCI_MEMORY_BUS)); + iobarrier_rw(); + + /* Set bus and subbus numbers + */ + out32(BRIDGE(CPCI, CFGADDR), 0x40000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x01ff0000); + iobarrier_rw(); + + out32(BRIDGE(CPCI, CFGADDR), 0x50000180); + iobarrier_rw(); + out32(BRIDGE(CPCI, CFGDATA), 0x32000000); + /* PCI retry timeouts will be enabled later + */ + out32(BRIDGE(CPCI, CFGDATA), 0x00000000); + iobarrier_rw(); + + /* Remove reset on the PCI buses + */ + out32(BRIDGE(LOCAL, CRR), 0xfc000000); + iobarrier_rw(); + out32(BRIDGE(CPCI, CRR), 0xfc000000); + iobarrier_rw(); + + local_hose.first_busno = 0; + local_hose.last_busno = 0xff; + + /* System memory space */ + pci_set_region(local_hose.regions + 0, + PCI_MEMORY_BUS, + PCI_MEMORY_PHYS, + PCI_MEMORY_MAXSIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(local_hose.regions + 1, + BRIDGE_LOCAL_MEM_BUS, + BRIDGE_LOCAL_MEM_PHYS, + BRIDGE_LOCAL_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(local_hose.regions + 2, + BRIDGE_LOCAL_IO_BUS, + BRIDGE_LOCAL_IO_PHYS, + BRIDGE_LOCAL_IO_SIZE, + PCI_REGION_IO); + + local_hose.region_count = 3; + + pci_setup_indirect(&local_hose, + BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGADDR, + BRIDGE_LOCAL_PHYS + HW_BRIDGE_CFGDATA); + + pci_register_hose(&local_hose); + + /* Initialize PCI32 bus registers */ + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_BUS_NUMBER, + local_hose.first_busno); + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + local_hose.last_busno); + + local_hose.last_busno = pci_hose_scan(&local_hose); + + /* Write out correct max subordinate bus number for local hose */ + pci_hose_write_config_byte(&local_hose, + PCI_BDF(local_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + local_hose.last_busno); + + cpci_hose.first_busno = local_hose.last_busno + 1; + cpci_hose.last_busno = 0xff; + + /* System memory space */ + pci_set_region(cpci_hose.regions + 0, + PCI_MEMORY_BUS, + PCI_MEMORY_PHYS, + PCI_MEMORY_MAXSIZE, + PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(cpci_hose.regions + 1, + BRIDGE_CPCI_MEM_BUS, + BRIDGE_CPCI_MEM_PHYS, + BRIDGE_CPCI_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(cpci_hose.regions + 2, + BRIDGE_CPCI_IO_BUS, + BRIDGE_CPCI_IO_PHYS, + BRIDGE_CPCI_IO_SIZE, + PCI_REGION_IO); + + cpci_hose.region_count = 3; + + pci_setup_indirect(&cpci_hose, + BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGADDR, + BRIDGE_CPCI_PHYS + HW_BRIDGE_CFGDATA); + + pci_register_hose(&cpci_hose); + + /* Initialize PCI64 bus registers */ + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_BUS_NUMBER, + cpci_hose.first_busno); + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + cpci_hose.last_busno); + + cpci_hose.last_busno = pci_hose_scan(&cpci_hose); + + /* Write out correct max subordinate bus number for cpci hose */ + pci_hose_write_config_byte(&cpci_hose, + PCI_BDF(cpci_hose.first_busno,0,0), + CPC710_SUB_BUS_NUMBER, + cpci_hose.last_busno); +} diff --git a/board/pcippc2/i2c.c b/board/pcippc2/i2c.c new file mode 100644 index 0000000..36b1d0f --- /dev/null +++ b/board/pcippc2/i2c.c @@ -0,0 +1,257 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <asm/io.h> + +#include "hardware.h" +#include "i2c.h" + +static void i2c_start (void); +static void i2c_stop (void); +static int i2c_write (u8 data); +static void i2c_read (u8 * data); + +static inline void i2c_port_start (void); +static inline void i2c_clock (unsigned int val); +static inline void i2c_data (unsigned int val); +static inline unsigned int + i2c_in (void); +static inline void i2c_write_bit (unsigned int val); +static inline unsigned int + i2c_read_bit (void); + +static inline void i2c_udelay (unsigned int time); + +int i2c_read_byte ( + u8 * data, + u8 dev, + u8 offset) +{ + int err = 0; + + i2c_start(); + + err = ! i2c_write(dev); + + if (! err) + { + err = ! i2c_write(offset); + } + + if (! err) + { + i2c_start(); + } + + if (! err) + { + err = ! i2c_write(dev | 0x01); + } + + if (! err) + { + i2c_read(data); + } + + i2c_stop(); + + return ! err; +} + +static inline void i2c_udelay ( + unsigned int time) +{ + int v; + + asm volatile("mtdec %0" : : "r" (time * ((CFG_BUS_CLK / 4) / 1000000))); + + do + { + asm volatile("isync; mfdec %0" : "=r" (v)); + } while (v >= 0); +} + + /* Low-level hardware access + */ + +#define BIT_GPDATA 0x80000000 +#define BIT_GPCLK 0x40000000 + +static inline void i2c_port_start (void) +{ + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~(BIT_GPCLK | BIT_GPDATA)); + out32(REG(CPC0, GPOUT), in32(REG(CPC0, GPOUT)) & ~(BIT_GPCLK | BIT_GPDATA)); + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline void i2c_clock ( + unsigned int val) +{ + if (val) + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPCLK); + } + else + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPCLK); + } + + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline void i2c_data ( + unsigned int val) +{ + if (val) + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) & ~BIT_GPDATA); + } + else + { + out32(REG(CPC0, GPDIR), in32(REG(CPC0, GPDIR)) | BIT_GPDATA); + } + + iobarrier_rw(); + + i2c_udelay(1); +} + +static inline unsigned int i2c_in (void) +{ + unsigned int val = ((in32(REG(CPC0, GPIN)) & BIT_GPDATA) != 0)?1:0; + + iobarrier_rw(); + + return val; +} + + + /* Protocol implementation + */ + +static inline void i2c_write_bit ( + unsigned int val) +{ + i2c_data(val); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); +} + +static inline unsigned int i2c_read_bit (void) +{ + unsigned int val; + + i2c_data(1); + i2c_udelay(10); + + i2c_clock(1); + i2c_udelay(10); + + val = i2c_in(); + + i2c_clock(0); + i2c_udelay(10); + + return val; +} + +unsigned int i2c_reset (void) +{ + unsigned int val; + int i; + + i2c_port_start(); + + i=0; + do { + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + val = i2c_in(); + i++; + } while ((i<9)&&(val==0)); + return (val); +} + + +static void i2c_start (void) +{ + i2c_data(1); + i2c_clock(1); + i2c_udelay(10); + i2c_data(0); + i2c_udelay(10); + i2c_clock(0); + i2c_udelay(10); +} + +static void i2c_stop (void) +{ + i2c_data(0); + i2c_udelay(10); + i2c_clock(1); + i2c_udelay(10); + i2c_data(1); + i2c_udelay(10); +} + +static int i2c_write ( + u8 data) +{ + unsigned int i; + + for (i = 0; i < 8; i++) + { + i2c_write_bit(data >> 7); + data <<= 1; + } + + return i2c_read_bit() == 0; +} + +static void i2c_read ( + u8 * data) +{ + unsigned int i; + u8 val = 0; + + for (i = 0; i < 8; i++) + { + val <<= 1; + val |= i2c_read_bit(); + } + + *data = val; + i2c_write_bit(1); /* NoAck */ +} diff --git a/board/pcippc2/pcippc2.c b/board/pcippc2/pcippc2.c new file mode 100644 index 0000000..e1b065b --- /dev/null +++ b/board/pcippc2/pcippc2.c @@ -0,0 +1,214 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <config.h> +#include <common.h> +#include <command.h> +#include <asm/io.h> +#include <linux/mtd/doc2000.h> +#include <watchdog.h> +#include <pci.h> + +#include "hardware.h" +#include "pcippc2.h" +#include "sconsole.h" +#include "fpga_serial.h" + +#if defined(CONFIG_WATCHDOG) + +static int pcippc2_wdt_init_done = 0; + +void pcippc2_wdt_init (void); + +#endif + + /* Check board identity + */ +int checkboard (void) +{ +#ifdef CONFIG_PCIPPC2 + puts ("Board: Gespac PCIPPC-2\n"); +#else + puts ("Board: Gespac PCIPPC-6\n"); +#endif + return 0; +} + + /* RAM size is stored in CPC0_RGBAN1 + */ +u32 pcippc2_sdram_size (void) +{ + return in32 (REG (CPC0, RGBAN1)); +} + +long initdram (int board_type) +{ + return cpc710_ram_init (); +} + +void do_reset (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + out32 (REG (CPC0, SPOR), 0); + iobarrier_rw (); + while (1); +} + +int board_pre_init (void) +{ + out32 (REG (CPC0, RSTR), 0xC0000000); + iobarrier_rw (); + + out32 (REG (CPC0, RSTR), 0xF0000000); + iobarrier_rw (); + + out32 (REG (CPC0, UCTL), 0x00F80000); + + out32 (REG (CPC0, SIOC0), 0x30000000); + + out32 (REG (CPC0, ABCNTL), 0x00000000); + + out32 (REG (CPC0, SESR), 0x00000000); + out32 (REG (CPC0, SEAR), 0x00000000); + + /* Detect IBM Avignon CPC710 Revision */ + if ((in32 (REG (CPC0, UCTL)) & 0x000000F0) == CPC710_TYPE_100P) + out32 (REG (CPC0, PGCHP), 0xA0000040); + else + out32 (REG (CPC0, PGCHP), 0x80800040); + + + out32 (REG (CPC0, ATAS), 0x709C2508); + + iobarrier_rw (); + + return 0; +} + +void after_reloc (ulong dest_addr) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* Jump to the main U-Boot board init code + */ + board_init_r (gd, dest_addr); +} + +int misc_init_r (void) +{ + pcippc2_fpga_init (); + +#if defined(CONFIG_WATCHDOG) + pcippc2_wdt_init (); +#endif + + fpga_serial_init (sconsole_get_baudrate ()); + + sconsole_putc = fpga_serial_putc; + sconsole_puts = fpga_serial_puts; + sconsole_getc = fpga_serial_getc; + sconsole_tstc = fpga_serial_tstc; + sconsole_setbrg = fpga_serial_setbrg; + + sconsole_flush (); + return (0); +} + +void pci_init (void) +{ + cpc710_pci_init (); + + /* FPGA requires no retry timeouts to be enabled + */ + cpc710_pci_enable_timeout (); +} + +void doc_init (void) +{ + doc_probe (pcippc2_fpga1_phys + HW_FPGA1_DOC); +} + +#if defined(CONFIG_WATCHDOG) + +void pcippc2_wdt_init (void) +{ + out16r (FPGA (WDT, PROG), 0xffff); + out8 (FPGA (WDT, CTRL), 0x1); + + pcippc2_wdt_init_done = 1; +} + +void pcippc2_wdt_done (void) +{ + out8 (FPGA (WDT, CTRL), 0x0); + + pcippc2_wdt_init_done = 0; +} + +void pcippc2_wdt_reset (void) +{ + if (pcippc2_wdt_init_done == 1) + out8 (FPGA (WDT, REFRESH), 0x56); +} + +void watchdog_reset (void) +{ + int re_enable = disable_interrupts (); + + pcippc2_wdt_reset (); + if (re_enable) + enable_interrupts (); +} + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) +int do_wd (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + switch (argc) { + case 1: + printf ("Watchdog timer status is %s\n", + pcippc2_wdt_init_done == 1 ? "on" : "off"); + + return 0; + case 2: + if (!strcmp(argv[1],"on")) { + pcippc2_wdt_init(); + printf("Watchdog timer now is on\n"); + + return 0; + + } else if (!strcmp(argv[1],"off")) { + pcippc2_wdt_done(); + printf("Watchdog timer now is off\n"); + + return 0; + + } else + break; + default: + break; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +#endif /* CFG_CMD_BSP */ +#endif /* CONFIG_WATCHDOG */ diff --git a/board/pn62/cmd_pn62.c b/board/pn62/cmd_pn62.c new file mode 100644 index 0000000..928f6c0 --- /dev/null +++ b/board/pn62/cmd_pn62.c @@ -0,0 +1,164 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/io.h> +#include <pci.h> +#include <cmd_autoscript.h> +#include <cmd_bsp.h> + +#include "pn62.h" + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + +/* + * Command led: controls the various LEDs 0..11 on the PN62 card. + */ +int do_led (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unsigned int number, function; + + if (argc != 3) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + number = simple_strtoul(argv[1], NULL, 10); + if (number > PN62_LED_MAX) + return 1; + function = simple_strtoul(argv[2], NULL, 16); + set_led (number, function); + return 0; +} + +/* + * Command loadpci: loads a image over PCI. + */ +#define CMD_MOVE_WINDOW 0x1 +#define CMD_BOOT_IMAGE 0x2 + +int do_loadpci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *s; + ulong addr = 0, count = 0; + u32 off; + int cmd, rcode = 0; + + /* pre-set load_addr */ + if ((s = getenv("loadaddr")) != NULL) { + addr = simple_strtoul(s, NULL, 16); + } + + switch (argc) { + case 1: + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + printf ("## Ready for image download ...\n"); + + show_startup_phase(12); + + while (1) { + /* Alive indicator */ + i2155x_write_scrapad(BOOT_PROTO, BOOT_PROTO_READY); + + /* Toggle status LEDs */ + cmd = (count / 200) % 4; /* downscale */ + set_led(4, cmd == 0 ? LED_1 : LED_0); + set_led(5, cmd == 1 ? LED_1 : LED_0); + set_led(6, cmd == 2 ? LED_1 : LED_0); + set_led(7, cmd == 3 ? LED_1 : LED_0); + udelay(1000); + count++; + + cmd = i2155x_read_scrapad(BOOT_CMD); + + if (cmd == BOOT_CMD_MOVE) { + off = i2155x_read_scrapad(BOOT_DATA); + off += addr; + i2155x_set_bar_base(3, off); + printf ("## BAR3 Addr moved = 0x%08x\n", off); + i2155x_write_scrapad(BOOT_CMD, ~cmd); + show_startup_phase(13); + } + else if (cmd == BOOT_CMD_BOOT) { + set_led(4, LED_1); + set_led(5, LED_1); + set_led(6, LED_1); + set_led(7, LED_1); + + i2155x_write_scrapad(BOOT_CMD, ~cmd); + show_startup_phase(14); + break; + } + + /* Abort if ctrl-c was pressed */ + if (ctrlc()) { + printf("\nAbort\n"); + return 0; + } + + } + + /* Repoint to the default shared memory */ + i2155x_set_bar_base(3, PN62_SMEM_DEFAULT); + + load_addr = addr; + printf ("## Start Addr = 0x%08lx\n", addr); + + show_startup_phase(15); + + /* Loading ok, check if we should attempt an auto-start */ + if (((s = getenv("autostart")) != NULL) && (strcmp(s,"yes") == 0)) { + char *local_args[2]; + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", + load_addr); + rcode = do_bootm (cmdtp, 0, 1, local_args); + } + +#ifdef CONFIG_AUTOSCRIPT + if (load_addr) { + char *s; + + if (((s = getenv("autoscript")) != NULL) && (strcmp(s,"yes") == 0)) { + printf("Running autoscript at addr 0x%08lX ...\n", load_addr); + rcode = autoscript (bd, load_addr); + } + } +#endif + return rcode; +} + +#endif diff --git a/board/pn62/misc.c b/board/pn62/misc.c new file mode 100644 index 0000000..4f71950 --- /dev/null +++ b/board/pn62/misc.c @@ -0,0 +1,235 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger <wg@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <asm/io.h> +#include <pci.h> + +#include "pn62.h" + +typedef struct { + pci_dev_t devno; + volatile u32 *csr; + +} i2155x_t; + +static i2155x_t i2155x = { 0, NULL }; + +static struct pci_device_id i2155x_ids[] = { + { 0x1011, 0x0046 }, /* i21554 */ + { 0x8086, 0xb555 } /* i21555 */ +}; + +int i2155x_init(void) +{ + pci_dev_t devno; + u32 val; + int i; + + /* + * Find the Intel bridge. + */ + if ((devno = pci_find_devices(i2155x_ids, 0)) < 0) { + printf("Error: Intel bridge 2155x not found!\n"); + return -1; + } + i2155x.devno = devno; + + /* + * Get auto-configured base address for CSR access. + */ + pci_read_config_dword(devno, PCI_BASE_ADDRESS_1, &val); + if (val & PCI_BASE_ADDRESS_SPACE_IO) { + val &= PCI_BASE_ADDRESS_IO_MASK; + i2155x.csr = (volatile u32 *)(_IO_BASE + val); + } else { + val &= PCI_BASE_ADDRESS_MEM_MASK; + i2155x.csr = (volatile u32 *)val; + } + + /* + * Translate downstream memory 2 (bar3) to base of shared memory. + */ + i2155x_set_bar_base(3, PN62_SMEM_DEFAULT); + + /* + * Enable memory space, I/O space and bus master bits + * in both Primary and Secondary command registers. + */ + val = PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_IO; + pci_write_config_word(devno, 0x44, val); + pci_write_config_word(devno, 0x04, val); + + /* + * Clear scratchpad registers. + */ + for (i = 0; i < (I2155X_SCRAPAD_MAX - 1); i++) { + i2155x_write_scrapad(i, 0x0); + } + + /* + * Set interrupt line for Linux. + */ + pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 3); + + return 0; +} + +/* + * Access the Scratchpad registers 0..7 of the Intel bridge. + */ +void i2155x_write_scrapad(int idx, u32 val) +{ + if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) + out_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx, val); + else + printf("i2155x_write_scrapad: invalid index\n"); +} + +u32 i2155x_read_scrapad(int idx) +{ + if (idx >= 0 && idx < I2155X_SCRAPAD_MAX) + return in_le32(i2155x.csr + (I2155X_SCRAPAD_ADDR/4) + idx); + else + printf("i2155x_read_scrapad: invalid index\n"); + return -1; +} + +void i2155x_set_bar_base(int bar, u32 base) +{ + if (bar >= 2 && bar <= 4) { + pci_write_config_dword(i2155x.devno, + I2155X_BAR2_BASE + (bar - 2) * 4, + base); + } +} + +/* + * Read Vital Product Data (VPD) from the Serial EPROM attached + * to the Intel bridge. + */ +int i2155x_read_vpd(int offset, int size, unsigned char *data) +{ + int i, n; + u16 val16; + + for (i = 0; i < size; i++) { + pci_write_config_word(i2155x.devno, I2155X_VPD_ADDR, + offset + i - I2155X_VPD_START); + for (n = 10000; n > 0; n--) { + pci_read_config_word(i2155x.devno, I2155X_VPD_ADDR, &val16); + if ((val16 & 0x8000) != 0) /* wait for completion */ + break; + udelay(100); + } + if (n == 0) { + printf("i2155x_read_vpd: TIMEOUT\n"); + return -1; + } + + pci_read_config_byte(i2155x.devno, I2155X_VPD_DATA, &data[i]); + } + + return i; +} + +static struct pci_device_id am79c95x_ids [] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, + { } +}; + + +/* + * Initialize the AMD ethernet controllers. + */ +int am79c95x_init(void) +{ + pci_dev_t devno; + int i; + + /* + * Set interrupt line for Linux. + */ + for (i = 0; i < 2; i++) { + if ((devno = pci_find_devices(am79c95x_ids, i)) < 0) + break; + pci_write_config_byte(devno, PCI_INTERRUPT_LINE, 2+i); + } + if (i < 2) + printf("Error: Only %d AMD Ethernet Controller found!\n", i); + + return 0; +} + + +void set_led(unsigned int number, unsigned int function) +{ + volatile u8 *addr; + + if ((number >= 0) && (number < PN62_LED_MAX) && + (function >= 0) && (function <= LED_LAST_FUNCTION)) { + addr = (volatile u8 *)(PN62_LED_BASE + number * 8); + out_8(addr, function&0xff); + } +} + +/* + * Show fatal error indicated by Kinght Rider(tm) effect + * in LEDS 0-7. LEDS 8-11 contain 4 bit error code. + * Note: this function will not terminate. + */ +void fatal_error(unsigned int error_code) +{ + int i, d; + + for (i = 0; i < 12; i++) { + set_led(i, LED_0); + } + + /* + * Write error code. + */ + set_led(8, (error_code & 0x01) ? LED_1 : LED_0); + set_led(9, (error_code & 0x02) ? LED_1 : LED_0); + set_led(10, (error_code & 0x04) ? LED_1 : LED_0); + set_led(11, (error_code & 0x08) ? LED_1 : LED_0); + + /* + * Yay - Knight Rider effect! + */ + while(1) { + unsigned int delay = 2000; + + for (i = 0; i < 8; i++) { + set_led(i, LED_1); + for (d = 0; d < delay; d++); + set_led(i, LED_0); + } + + for (i = 7; i > 0; i--) { + set_led(i, LED_1); + for (d = 0; d < delay; d++); + set_led(i, LED_0); + } + } +} diff --git a/board/pn62/pn62.c b/board/pn62/pn62.c new file mode 100644 index 0000000..4d87527 --- /dev/null +++ b/board/pn62/pn62.c @@ -0,0 +1,216 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger <wg@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <pci.h> + +#include "pn62.h" + + +static int get_serial_number (char *string, int size); +static int get_mac_address (int id, u8 * mac, char *string, int size); + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +void show_boot_progress (int phase) +{ + /* + * Show phases of the bootm command on the front panel + * LEDs and the scratchpad register #3 as well. We use + * blinking LEDs for logical "1". + */ + if (phase > 0) { + set_led (8, (phase & 0x1) ? LED_SLOW_CLOCK : LED_0); + set_led (9, (phase & 0x2) ? LED_SLOW_CLOCK : LED_0); + set_led (10, (phase & 0x4) ? LED_SLOW_CLOCK : LED_0); + set_led (11, (phase & 0x8) ? LED_SLOW_CLOCK : LED_0); + } + i2155x_write_scrapad (BOOT_STATUS, phase); + if (phase < 0) + i2155x_write_scrapad (BOOT_DONE, BOOT_DONE_ERROR); +} +#endif + +void show_startup_phase (int phase) +{ + /* + * Show the phase of U-Boot startup on the front panel + * LEDs and the scratchpad register #3 as well. + */ + if (phase > 0) { + set_led (8, (phase & 0x1) ? LED_1 : LED_0); + set_led (9, (phase & 0x2) ? LED_1 : LED_0); + set_led (10, (phase & 0x4) ? LED_1 : LED_0); + set_led (11, (phase & 0x8) ? LED_1 : LED_0); + } + i2155x_write_scrapad (BOOT_STATUS, phase); + if (phase < 0) + i2155x_write_scrapad (BOOT_DONE, BOOT_DONE_ERROR); +} + +int checkboard (void) +{ + show_startup_phase (1); + puts ("Board: PN62\n"); + return 0; +} + +long int initdram (int board_type) +{ + int i, cnt; + volatile uchar *base = CFG_SDRAM_BASE; + volatile ulong *addr; + ulong save[32]; + ulong val, ret = 0; + + show_startup_phase (2); + + for (i = 0, cnt = (CFG_MAX_RAM_SIZE / sizeof (long)) >> 1; cnt > 0; + cnt >>= 1) { + addr = (volatile ulong *) base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *) base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof (long); cnt <<= 1) { + addr = (volatile ulong *) base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof (long) - 1; + ulong mear1 = mpc824x_mpc107_getreg (MEAR1); + ulong emear1 = mpc824x_mpc107_getreg (EMEAR1); + + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg (MEAR1, mear1); + mpc824x_mpc107_setreg (EMEAR1, emear1); + + ret = cnt * sizeof (long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; + Done: + show_startup_phase (3); + return ret; +} + +/* + * Initialize PCI Devices. We rely on auto-configuration. + */ +#ifndef CONFIG_PCI_PNP +#error "CONFIG_PCI_PNP is not defined, please correct!" +#endif + +struct pci_controller hose = { +}; + +void pci_init (void) +{ + show_startup_phase (4); + pci_mpc824x_init (&hose); + + show_startup_phase (5); + i2155x_init (); + show_startup_phase (6); + am79c95x_init (); + show_startup_phase (7); +} + +int misc_init_r (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + char str[20]; + u8 mac[6]; + + show_startup_phase (8); + /* + * Get serial number and ethernet addresses if not already defined + * and update the board info structure and the environment. + */ + if (getenv ("serial#") == NULL && + get_serial_number (str, strlen (str)) > 0) { + setenv ("serial#", str); + } + show_startup_phase (9); + + if (getenv ("ethaddr") == NULL && + get_mac_address (0, mac, str, sizeof (str)) > 0) { + setenv ("ethaddr", str); + memcpy (gd->bd->bi_enetaddr, mac, 6); + } + show_startup_phase (10); + + if (getenv ("eth1addr") == NULL && + get_mac_address (1, mac, str, sizeof (str)) > 0) { + setenv ("eth1addr", str); + memcpy (gd->bd->bi_enet1addr, mac, 6); + } + show_startup_phase (11); + + /* Tell everybody that U-Boot is up and runnig */ + i2155x_write_scrapad (0, 0x12345678); + return (0); +} + +static int get_serial_number (char *string, int size) +{ + int i; + char c; + + if (size < I2155X_VPD_SN_SIZE) + size = I2155X_VPD_SN_SIZE; + for (i = 0; i < (size - 1); i++) { + i2155x_read_vpd (I2155X_VPD_SN_START + i, 1, &c); + if (c == '\0') + break; + string[i] = c; + } + string[i] = '\0'; /* make sure it's terminated */ + + return i; +} + +static int get_mac_address (int id, u8 * mac, char *string, int size) +{ + if (size < 6 * 3) + return -1; + + i2155x_read_vpd (I2155X_VPD_MAC0_START + 6 * id, 6, mac); + return sprintf (string, "%02x:%02x:%02x:%02x:%02x:%02x", + mac[0], mac[1], mac[2], + mac[3], mac[4], mac[5]); +} diff --git a/board/r360mpi/r360mpi.c b/board/r360mpi/r360mpi.c new file mode 100644 index 0000000..d7b8873 --- /dev/null +++ b/board/r360mpi/r360mpi.c @@ -0,0 +1,423 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <mpc8xx.h> +#include <i2c.h> + +#include <commproc.h> +#include <command.h> +#include <cmd_bsp.h> +#include <malloc.h> + +#include <linux/types.h> +#include <linux/string.h> /* for strdup */ + + +/* + * Memory Controller Using + * + * CS0 - Flash memory (0x40000000) + * CS1 - SDRAM (0x00000000} + * CS2 - + * CS3 - + * CS4 - + * CS5 - + * CS6 - PCMCIA device + * CS7 - PCMCIA device + */ + +/* ------------------------------------------------------------------------- */ + +#define _not_used_ 0xffffffff + +const uint sdram_table[]= +{ + /* single read. (offset 0 in upm RAM) */ + 0x1f07fc04, 0xeeaefc04, 0x11adfc04, 0xefbbbc00, + 0x1ff77c47, + + /* MRS initialization (offset 5) */ + + 0x1ff77c34, 0xefeabc34, 0x1fb57c35, + + /* burst read. (offset 8 in upm RAM) */ + 0x1f07fc04, 0xeeaefc04, 0x10adfc04, 0xf0affc00, + 0xf0affc00, 0xf1affc00, 0xefbbbc00, 0x1ff77c47, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* single write. (offset 18 in upm RAM) */ + 0x1f27fc04, 0xeeaebc00, 0x01b93c04, 0x1ff77c47, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* burst write. (offset 20 in upm RAM) */ + 0x1f07fc04, 0xeeaebc00, 0x10ad7c00, 0xf0affc00, + 0xf0affc00, 0xe1bbbc04, 0x1ff77c47, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* refresh. (offset 30 in upm RAM) */ + 0x1ff5fc84, 0xfffffc04, 0xfffffc04, 0xfffffc04, + 0xfffffc84, 0xfffffc07, _not_used_, _not_used_, + _not_used_, _not_used_, _not_used_, _not_used_, + + /* exception. (offset 3c in upm RAM) */ + 0x7ffffc07, _not_used_, _not_used_, _not_used_ }; + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ + +int checkboard (void) +{ + puts ("Board: R360 MPI Board\n"); + return 0; +} + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size8, size9; + long int size_b0 = 0; + unsigned long reg; + + upmconfig (UPMA, (uint *) sdram_table, + sizeof (sdram_table) / sizeof (uint)); + + /* + * Preliminary prescaler for refresh (depends on number of + * banks): This value is selected for four cycles every 62.4 us + * with two SDRAM banks or four cycles every 31.2 us with one + * bank. It will be adjusted after memory sizing. + */ + memctl->memc_mptpr = CFG_MPTPR_2BK_8K; + + memctl->memc_mar = 0x00000088; + + /* + * Map controller bank 1 to the SDRAM bank at + * preliminary address - these have to be modified after the + * SDRAM size has been determined. + */ + memctl->memc_or1 = CFG_OR1_PRELIM; + memctl->memc_br1 = CFG_BR1_PRELIM; + + memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ + + udelay (200); + + /* perform SDRAM initializsation sequence */ + + memctl->memc_mcr = 0x80002105; /* SDRAM bank 0 */ + udelay (200); + memctl->memc_mcr = 0x80002230; /* SDRAM bank 0 - execute twice */ + udelay (200); + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay (1000); + + /* + * Check Bank 0 Memory Size for re-configuration + * + * try 8 column mode + */ + size8 = dram_size (CFG_MAMR_8COL, (ulong *) SDRAM_BASE1_PRELIM, + SDRAM_MAX_SIZE); + + udelay (1000); + + /* + * try 9 column mode + */ + size9 = dram_size (CFG_MAMR_9COL, (ulong *) SDRAM_BASE1_PRELIM, + SDRAM_MAX_SIZE); + + if (size8 < size9) { /* leave configuration at 9 columns */ + size_b0 = size9; +/* debug ("SDRAM Bank 0 in 9 column mode: %ld MB\n", size >> 20); */ + } else { /* back to 8 columns */ + size_b0 = size8; + memctl->memc_mamr = CFG_MAMR_8COL; + udelay (500); +/* debug ("SDRAM Bank 0 in 8 column mode: %ld MB\n", size >> 20); */ + } + + udelay (1000); + + /* + * Adjust refresh rate depending on SDRAM type, both banks + * For types > 128 MBit leave it at the current (fast) rate + */ + if ((size_b0 < 0x02000000)) { + /* reduce to 15.6 us (62.4 us / quad) */ + memctl->memc_mptpr = CFG_MPTPR_2BK_4K; + udelay (1000); + } + + /* + * Final mapping + */ + + memctl->memc_or1 = ((-size_b0) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br1 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; + + /* adjust refresh rate depending on SDRAM type, one bank */ + reg = memctl->memc_mptpr; + reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */ + memctl->memc_mptpr = reg; + + udelay (10000); + + return (size_b0); +} + +/* ------------------------------------------------------------------------- */ + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ + +static long int dram_size (long int mamr_value, long int *base, + long int maxsize) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + memctl->memc_mamr = mamr_value; + + for (cnt = maxsize / sizeof (long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt <= maxsize / sizeof (long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + return (maxsize); +} + +/* ------------------------------------------------------------------------- */ + +void r360_pwm_write (uchar reg, uchar val) +{ + if (i2c_write (CFG_I2C_PWM_ADDR, reg, 1, &val, 1)) { + printf ("Can't write PWM register 0x%02X.\n", reg); + } +} + +/* ------------------------------------------------------------------------- */ + +/*----------------------------------------------------------------------- + * Keyboard Controller + */ + +/* Number of bytes returned from Keyboard Controller */ +#define KEYBD_KEY_MAX 20 /* maximum key number */ +#define KEYBD_DATALEN ((KEYBD_KEY_MAX + 7) / 8) /* normal key scan data */ + +static uchar kbd_addr = CFG_I2C_KBD_ADDR; + +static uchar *key_match (uchar *); + +int misc_init_r (void) +{ + uchar kbd_data[KEYBD_DATALEN]; + uchar keybd_env[2 * KEYBD_DATALEN + 1]; + uchar *str; + int i; + + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + } + setenv ("keybd", keybd_env); + + str = strdup (key_match (kbd_data)); /* decode keys */ + +#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + setenv ("preboot", str); /* set or delete definition */ +#endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } + + return (0); +} + +/*----------------------------------------------------------------------- + * Check if pressed key(s) match magic sequence, + * and return the command string associated with that key(s). + * + * If no key press was decoded, NULL is returned. + * + * Note: the first character of the argument will be overwritten with + * the "magic charcter code" of the decoded key(s), or '\0'. + * + * + * Note: the string points to static environment data and must be + * saved before you call any function that modifies the environment. + */ +#ifdef CONFIG_PREBOOT + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +static uchar *key_match (uchar * kbd_data) +{ + uchar compare[KEYBD_DATALEN]; + uchar magic[sizeof (kbd_magic_prefix) + 1]; + uchar cmd_name[sizeof (kbd_command_prefix) + 1]; + uchar key_mask; + uchar *str, *nxt, *suffix; + uchar *kbd_magic_keys; + char *cmd; + int i; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix) { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); +#if 0 + printf ("### Check magic \"%s\"\n", magic); +#endif + + memcpy(compare, kbd_data, KEYBD_DATALEN); + + for (str = getenv(magic); str != NULL; str = (*nxt) ? nxt+1 : nxt) { + uchar c; + + c = (uchar) simple_strtoul (str, (char **) (&nxt), 16); + + if (str == nxt) /* invalid character */ + break; + + if (c >= KEYBD_KEY_MAX) /* bad key number */ + goto next_magic; + + key_mask = 0x80 >> (c % 8); + + if (!(compare[c / 8] & key_mask)) /* key not pressed */ + goto next_magic; + + compare[c / 8] &= ~key_mask; + } + + for (i=0; i<KEYBD_DATALEN; i++) + if (compare[i]) /* key(s) not released */ + goto next_magic; + + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + + cmd = getenv (cmd_name); +#if 0 + printf ("### Set PREBOOT to $(%s): \"%s\"\n", + cmd_name, cmd ? cmd : "<<NULL>>"); +#endif + *kbd_data = *suffix; + return (cmd); + + next_magic:; + } +#if 0 + printf ("### Delete PREBOOT\n"); +#endif + *kbd_data = '\0'; + return (NULL); +} +#endif /* CONFIG_PREBOOT */ + +/* Read Keyboard status */ +int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + uchar kbd_data[KEYBD_DATALEN]; + uchar keybd_env[2 * KEYBD_DATALEN + 1]; + int i; + + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + + /* Read keys */ + i2c_read (kbd_addr, 0, 0, kbd_data, KEYBD_DATALEN); + + puts ("Keys:"); + for (i = 0; i < KEYBD_DATALEN; ++i) { + sprintf (keybd_env + i + i, "%02X", kbd_data[i]); + printf (" %02x", kbd_data[i]); + } + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} diff --git a/board/sacsng/clkinit.c b/board/sacsng/clkinit.c new file mode 100644 index 0000000..1e851e1 --- /dev/null +++ b/board/sacsng/clkinit.c @@ -0,0 +1,884 @@ +/* + * (C) Copyright 2002 + * Custom IDEAS, Inc. <www.cideas.com> + * Jon Diekema <diekema@cideas.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ioports.h> +#include <mpc8260.h> +#include <asm/cpm_8260.h> +#include <configs/sacsng.h> + +#include "clkinit.h" + +int Daq64xSampling = 0; + + +void Daq_BRG_Reset(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + *brg_ptr |= CPM_BRG_RST; + *brg_ptr &= ~CPM_BRG_RST; +} + +void Daq_BRG_Disable(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + *brg_ptr &= ~CPM_BRG_EN; +} + +void Daq_BRG_Enable(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + *brg_ptr |= CPM_BRG_EN; +} + +uint Daq_BRG_Get_Div16(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + if (*brg_ptr & CPM_BRG_DIV16) { + /* DIV16 active */ + return (TRUE); + } + else { + /* DIV16 inactive */ + return (FALSE); + } +} + +void Daq_BRG_Set_Div16(uint brg, uint div16) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + if (div16) { + /* DIV16 active */ + *brg_ptr |= CPM_BRG_DIV16; + } + else { + /* DIV16 inactive */ + *brg_ptr &= ~CPM_BRG_DIV16; + } +} + +uint Daq_BRG_Get_Count(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + uint brg_cnt; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + /* Get the clock divider + * + * Note: A clock divider of 0 means divide by 1, + * therefore we need to add 1 to the count. + */ + brg_cnt = (*brg_ptr & CPM_BRG_CD_MASK) >> CPM_BRG_DIV16_SHIFT; + brg_cnt++; + if (*brg_ptr & CPM_BRG_DIV16) { + brg_cnt *= 16; + } + + return (brg_cnt); +} + +void Daq_BRG_Set_Count(uint brg, uint brg_cnt) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + /* + * Note: A clock divider of 0 means divide by 1, + * therefore we need to subtract 1 from the count. + */ + if (brg_cnt > 4096) { + /* Prescale = Divide by 16 */ + *brg_ptr = (*brg_ptr & ~CPM_BRG_CD_MASK) | + (((brg_cnt / 16) - 1) << CPM_BRG_DIV16_SHIFT); + *brg_ptr |= CPM_BRG_DIV16; + } + else { + /* Prescale = Divide by 1 */ + *brg_ptr = (*brg_ptr & ~CPM_BRG_CD_MASK) | + ((brg_cnt - 1) << CPM_BRG_DIV16_SHIFT); + *brg_ptr &= ~CPM_BRG_DIV16; + } +} + +uint Daq_BRG_Get_ExtClk(uint brg) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + return ((*brg_ptr & CPM_BRG_EXTC_MASK) >> CPM_BRG_EXTC_SHIFT); +} + +char* Daq_BRG_Get_ExtClk_Description(uint brg) +{ + uint extc; + + extc = Daq_BRG_Get_ExtClk(brg); + + switch (brg + 1) { + case 1: + case 2: + case 5: + case 6: { + switch (extc) { + case 0: { + return ("BRG_INT"); + } + case 1: { + return ("CLK3"); + } + case 2: { + return ("CLK5"); + } + } + return ("??1245??"); + } + case 3: + case 4: + case 7: + case 8: { + switch (extc) { + case 0: { + return ("BRG_INT"); + } + case 1: { + return ("CLK9"); + } + case 2: { + return ("CLK15"); + } + } + return ("??3478??"); + } + } + return ("??9876??"); +} + +void Daq_BRG_Set_ExtClk(uint brg, uint extc) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + + brg_ptr = (uint *)&immr->im_brgc1; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg -= 4; + } + brg_ptr += brg; + + *brg_ptr = (*brg_ptr & ~CPM_BRG_EXTC_MASK) | + ((extc << CPM_BRG_EXTC_SHIFT) & CPM_BRG_EXTC_MASK); +} + +uint Daq_BRG_Rate(uint brg) +{ + DECLARE_GLOBAL_DATA_PTR; + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint *brg_ptr; + uint brg_cnt; + uint brg_freq = 0; + + brg_ptr = (uint *)&immr->im_brgc1; + brg_ptr += brg; + if (brg >= 5) { + brg_ptr = (uint *)&immr->im_brgc5; + brg_ptr += (brg - 4); + } + + brg_cnt = Daq_BRG_Get_Count(brg); + + switch (Daq_BRG_Get_ExtClk(brg)) { + case CPM_BRG_EXTC_CLK3: + case CPM_BRG_EXTC_CLK5: { + brg_freq = brg_cnt; + break; + } + default: { + brg_freq = (uint)BRG_INT_CLK / brg_cnt; + } + } + return (brg_freq); +} + +uint Daq_Get_SampleRate(void) + +{ + /* + * Read the BRG's to return the actual sample rate. + */ + return (Daq_BRG_Rate(MCLK_BRG) / (MCLK_DIVISOR * SCLK_DIVISOR)); +} + +uint Daq_Set_SampleRate(uint rate, uint force) + +{ + DECLARE_GLOBAL_DATA_PTR; + uint mclk_divisor; /* MCLK divisor */ + uint rate_curr; /* Current sample rate */ + + /* + * Limit the sample rate to some sensible values. + */ + if (Daq64xSampling) { + if (rate > MAX_64x_SAMPLE_RATE) { + rate = MAX_64x_SAMPLE_RATE; + } + } + else { + if (rate > MAX_128x_SAMPLE_RATE) { + rate = MAX_128x_SAMPLE_RATE; + } + } + if (rate < MIN_SAMPLE_RATE) { + rate = MIN_SAMPLE_RATE; + } + + /* Check to see if we are really changing rates */ + rate_curr = Daq_Get_SampleRate(); + if ((rate != rate_curr) || force) { + /* + * Dynamically adjust MCLK based on the new sample rate. + */ + + /* Compute the divisors */ + mclk_divisor = BRG_INT_CLK / (rate * MCLK_DIVISOR * SCLK_DIVISOR); + + /* Setup MCLK */ + Daq_BRG_Set_Count(MCLK_BRG, mclk_divisor); + + /* Setup SCLK */ +# ifdef RUN_SCLK_ON_BRG_INT + Daq_BRG_Set_Count(SCLK_BRG, mclk_divisor * MCLK_DIVISOR); +# else + Daq_BRG_Set_Count(SCLK_BRG, MCLK_DIVISOR); +# endif + +# ifdef RUN_LRCLK_ON_BRG_INT + Daq_BRG_Set_Count(LRCLK_BRG, + mclk_divisor * MCLK_DIVISOR * SCLK_DIVISOR); +# else + Daq_BRG_Set_Count(LRCLK_BRG, SCLK_DIVISOR); +# endif + + /* Read the BRG's to return the actual sample rate. */ + rate_curr = Daq_Get_SampleRate(); + } + + return (rate_curr); +} + +void Daq_Init_Clocks(int sample_rate, int sample_64x) + +{ + volatile ioport_t *iopa = ioport_addr((immap_t *)CFG_IMMR, 0 /* port A */); + + /* Save off the clocking data */ + Daq64xSampling = sample_64x; + + /* + * Limit the sample rate to some sensible values. + */ + if (Daq64xSampling) { + if (sample_rate > MAX_64x_SAMPLE_RATE) { + sample_rate = MAX_64x_SAMPLE_RATE; + } + } + else { + if (sample_rate > MAX_128x_SAMPLE_RATE) { + sample_rate = MAX_128x_SAMPLE_RATE; + } + } + if (sample_rate < MIN_SAMPLE_RATE) { + sample_rate = MIN_SAMPLE_RATE; + } + + /* + * Initialize the MCLK/SCLK/LRCLK baud rate generators. + */ + + /* Setup MCLK */ + Daq_BRG_Set_ExtClk(MCLK_BRG, CPM_BRG_EXTC_BRGCLK); + + /* Setup SCLK */ +# ifdef RUN_SCLK_ON_BRG_INT + Daq_BRG_Set_ExtClk(SCLK_BRG, CPM_BRG_EXTC_BRGCLK); +# else + Daq_BRG_Set_ExtClk(SCLK_BRG, CPM_BRG_EXTC_CLK9); +# endif + + /* Setup LRCLK */ +# ifdef RUN_LRCLK_ON_BRG_INT + Daq_BRG_Set_ExtClk(LRCLK_BRG, CPM_BRG_EXTC_BRGCLK); +# else + Daq_BRG_Set_ExtClk(LRCLK_BRG, CPM_BRG_EXTC_CLK5); +# endif + + /* Setup the BRG rates */ + Daq_Set_SampleRate(sample_rate, TRUE); + + /* Enable the clock drivers */ + iopa->pdat &= ~SLRCLK_EN_MASK; +} + +void Daq_Stop_Clocks(void) + +{ +#ifdef TIGHTEN_UP_BRG_TIMING + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + +# ifdef TIGHTEN_UP_BRG_TIMING + /* + * Reset MCLK BRG + */ +# if (MCLK_BRG == 0) + immr->im_brgc1 |= CPM_BRG_RST; + immr->im_brgc1 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 1) + immr->im_brgc2 |= CPM_BRG_RST; + immr->im_brgc2 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 2) + immr->im_brgc3 |= CPM_BRG_RST; + immr->im_brgc3 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 3) + immr->im_brgc4 |= CPM_BRG_RST; + immr->im_brgc4 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 4) + immr->im_brgc5 |= CPM_BRG_RST; + immr->im_brgc5 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 5) + immr->im_brgc6 |= CPM_BRG_RST; + immr->im_brgc6 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 6) + immr->im_brgc7 |= CPM_BRG_RST; + immr->im_brgc7 &= ~CPM_BRG_RST; +# endif +# if (MCLK_BRG == 7) + immr->im_brgc8 |= CPM_BRG_RST; + immr->im_brgc8 &= ~CPM_BRG_RST; +# endif + + /* + * Reset SCLK BRG + */ +# if (SCLK_BRG == 0) + immr->im_brgc1 |= CPM_BRG_RST; + immr->im_brgc1 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 1) + immr->im_brgc2 |= CPM_BRG_RST; + immr->im_brgc2 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 2) + immr->im_brgc3 |= CPM_BRG_RST; + immr->im_brgc3 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 3) + immr->im_brgc4 |= CPM_BRG_RST; + immr->im_brgc4 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 4) + immr->im_brgc5 |= CPM_BRG_RST; + immr->im_brgc5 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 5) + immr->im_brgc6 |= CPM_BRG_RST; + immr->im_brgc6 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 6) + immr->im_brgc7 |= CPM_BRG_RST; + immr->im_brgc7 &= ~CPM_BRG_RST; +# endif +# if (SCLK_BRG == 7) + immr->im_brgc8 |= CPM_BRG_RST; + immr->im_brgc8 &= ~CPM_BRG_RST; +# endif + + /* + * Reset LRCLK BRG + */ +# if (LRCLK_BRG == 0) + immr->im_brgc1 |= CPM_BRG_RST; + immr->im_brgc1 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 1) + immr->im_brgc2 |= CPM_BRG_RST; + immr->im_brgc2 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 2) + immr->im_brgc3 |= CPM_BRG_RST; + immr->im_brgc3 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 3) + immr->im_brgc4 |= CPM_BRG_RST; + immr->im_brgc4 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 4) + immr->im_brgc5 |= CPM_BRG_RST; + immr->im_brgc5 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 5) + immr->im_brgc6 |= CPM_BRG_RST; + immr->im_brgc6 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 6) + immr->im_brgc7 |= CPM_BRG_RST; + immr->im_brgc7 &= ~CPM_BRG_RST; +# endif +# if (LRCLK_BRG == 7) + immr->im_brgc8 |= CPM_BRG_RST; + immr->im_brgc8 &= ~CPM_BRG_RST; +# endif +# else + /* + * Reset the clocks + */ + Daq_BRG_Reset(MCLK_BRG); + Daq_BRG_Reset(SCLK_BRG); + Daq_BRG_Reset(LRCLK_BRG); +# endif +} + +void Daq_Start_Clocks(int sample_rate) + +{ +#ifdef TIGHTEN_UP_BRG_TIMING + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + uint mclk_brg; /* MCLK BRG value */ + uint sclk_brg; /* SCLK BRG value */ + uint lrclk_brg; /* LRCLK BRG value */ + uint temp_lrclk_brg; /* Temporary LRCLK BRG value */ + uint real_lrclk_brg; /* Permanent LRCLK BRG value */ + unsigned long flags; /* Interrupt flags */ + uint sclk_cnt; /* SCLK count */ + uint delay_cnt; /* Delay count */ +#endif + +# ifdef TIGHTEN_UP_BRG_TIMING + /* + * Obtain the enabled MCLK BRG value + */ +# if (MCLK_BRG == 0) + mclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 1) + mclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 2) + mclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 3) + mclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 4) + mclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 5) + mclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 6) + mclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (MCLK_BRG == 7) + mclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif + + /* + * Obtain the enabled SCLK BRG value + */ +# if (SCLK_BRG == 0) + sclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 1) + sclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 2) + sclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 3) + sclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 4) + sclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 5) + sclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 6) + sclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (SCLK_BRG == 7) + sclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif + + /* + * Obtain the enabled LRCLK BRG value + */ +# if (LRCLK_BRG == 0) + lrclk_brg = (immr->im_brgc1 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 1) + lrclk_brg = (immr->im_brgc2 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 2) + lrclk_brg = (immr->im_brgc3 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 3) + lrclk_brg = (immr->im_brgc4 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 4) + lrclk_brg = (immr->im_brgc5 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 5) + lrclk_brg = (immr->im_brgc6 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 6) + lrclk_brg = (immr->im_brgc7 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif +# if (LRCLK_BRG == 7) + lrclk_brg = (immr->im_brgc8 & ~CPM_BRG_RST) | CPM_BRG_EN; +# endif + + /* Save off the real LRCLK value */ + real_lrclk_brg = lrclk_brg; + + /* Obtain the current SCLK count */ + sclk_cnt = ((sclk_brg & 0x00001FFE) >> 1) + 1; + + /* Compute the delay as a function of SCLK count */ + delay_cnt = ((sclk_cnt / 4) - 2) * 10 + 6; + if (sample_rate == 43402) { + delay_cnt++; + } + + /* Clear out the count */ + temp_lrclk_brg = sclk_brg & ~0x00001FFE; + + /* Insert the count */ + temp_lrclk_brg |= ((delay_cnt + (sclk_cnt / 2) - 1) << 1) & 0x00001FFE; + + /* + * Enable MCLK BRG + */ +# if (MCLK_BRG == 0) + immr->im_brgc1 = mclk_brg; +# endif +# if (MCLK_BRG == 1) + immr->im_brgc2 = mclk_brg; +# endif +# if (MCLK_BRG == 2) + immr->im_brgc3 = mclk_brg; +# endif +# if (MCLK_BRG == 3) + immr->im_brgc4 = mclk_brg; +# endif +# if (MCLK_BRG == 4) + immr->im_brgc5 = mclk_brg; +# endif +# if (MCLK_BRG == 5) + immr->im_brgc6 = mclk_brg; +# endif +# if (MCLK_BRG == 6) + immr->im_brgc7 = mclk_brg; +# endif +# if (MCLK_BRG == 7) + immr->im_brgc8 = mclk_brg; +# endif + + /* + * Enable SCLK BRG + */ +# if (SCLK_BRG == 0) + immr->im_brgc1 = sclk_brg; +# endif +# if (SCLK_BRG == 1) + immr->im_brgc2 = sclk_brg; +# endif +# if (SCLK_BRG == 2) + immr->im_brgc3 = sclk_brg; +# endif +# if (SCLK_BRG == 3) + immr->im_brgc4 = sclk_brg; +# endif +# if (SCLK_BRG == 4) + immr->im_brgc5 = sclk_brg; +# endif +# if (SCLK_BRG == 5) + immr->im_brgc6 = sclk_brg; +# endif +# if (SCLK_BRG == 6) + immr->im_brgc7 = sclk_brg; +# endif +# if (SCLK_BRG == 7) + immr->im_brgc8 = sclk_brg; +# endif + + /* + * Enable LRCLK BRG (1st time - temporary) + */ +# if (LRCLK_BRG == 0) + immr->im_brgc1 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 1) + immr->im_brgc2 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 2) + immr->im_brgc3 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 3) + immr->im_brgc4 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 4) + immr->im_brgc5 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 5) + immr->im_brgc6 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 6) + immr->im_brgc7 = temp_lrclk_brg; +# endif +# if (LRCLK_BRG == 7) + immr->im_brgc8 = temp_lrclk_brg; +# endif + + /* + * Enable LRCLK BRG (2nd time - permanent) + */ +# if (LRCLK_BRG == 0) + immr->im_brgc1 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 1) + immr->im_brgc2 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 2) + immr->im_brgc3 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 3) + immr->im_brgc4 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 4) + immr->im_brgc5 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 5) + immr->im_brgc6 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 6) + immr->im_brgc7 = real_lrclk_brg; +# endif +# if (LRCLK_BRG == 7) + immr->im_brgc8 = real_lrclk_brg; +# endif +# else + /* + * Enable the clocks + */ + Daq_BRG_Enable(LRCLK_BRG); + Daq_BRG_Enable(SCLK_BRG); + Daq_BRG_Enable(MCLK_BRG); +# endif +} + +void Daq_Display_Clocks(void) + +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + uint mclk_divisor; /* Detected MCLK divisor */ + uint sclk_divisor; /* Detected SCLK divisor */ + + printf("\nBRG:\n"); + if (immr->im_brgc4 != 0) { + printf("\tbrgc4\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, MCLK\n", + immr->im_brgc4, + (uint)&(immr->im_brgc4), + Daq_BRG_Get_Count(3), + Daq_BRG_Get_ExtClk(3), + Daq_BRG_Get_ExtClk_Description(3)); + } + if (immr->im_brgc8 != 0) { + printf("\tbrgc8\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SCLK\n", + immr->im_brgc8, + (uint)&(immr->im_brgc8), + Daq_BRG_Get_Count(7), + Daq_BRG_Get_ExtClk(7), + Daq_BRG_Get_ExtClk_Description(7)); + } + if (immr->im_brgc6 != 0) { + printf("\tbrgc6\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, LRCLK\n", + immr->im_brgc6, + (uint)&(immr->im_brgc6), + Daq_BRG_Get_Count(5), + Daq_BRG_Get_ExtClk(5), + Daq_BRG_Get_ExtClk_Description(5)); + } + if (immr->im_brgc1 != 0) { + printf("\tbrgc1\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SMC1\n", + immr->im_brgc1, + (uint)&(immr->im_brgc1), + Daq_BRG_Get_Count(0), + Daq_BRG_Get_ExtClk(0), + Daq_BRG_Get_ExtClk_Description(0)); + } + if (immr->im_brgc2 != 0) { + printf("\tbrgc2\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SMC2\n", + immr->im_brgc2, + (uint)&(immr->im_brgc2), + Daq_BRG_Get_Count(1), + Daq_BRG_Get_ExtClk(1), + Daq_BRG_Get_ExtClk_Description(1)); + } + if (immr->im_brgc3 != 0) { + printf("\tbrgc3\t0x%08x @ 0x%08x, %5d count, %d extc, %8s, SCC1\n", + immr->im_brgc3, + (uint)&(immr->im_brgc3), + Daq_BRG_Get_Count(2), + Daq_BRG_Get_ExtClk(2), + Daq_BRG_Get_ExtClk_Description(2)); + } + if (immr->im_brgc5 != 0) { + printf("\tbrgc5\t0x%08x @ 0x%08x, %5d count, %d extc, %8s\n", + immr->im_brgc5, + (uint)&(immr->im_brgc5), + Daq_BRG_Get_Count(4), + Daq_BRG_Get_ExtClk(4), + Daq_BRG_Get_ExtClk_Description(4)); + } + if (immr->im_brgc7 != 0) { + printf("\tbrgc7\t0x%08x @ 0x%08x, %5d count, %d extc, %8s\n", + immr->im_brgc7, + (uint)&(immr->im_brgc7), + Daq_BRG_Get_Count(6), + Daq_BRG_Get_ExtClk(6), + Daq_BRG_Get_ExtClk_Description(6)); + } + +# ifdef RUN_SCLK_ON_BRG_INT + mclk_divisor = Daq_BRG_Rate(MCLK_BRG) / Daq_BRG_Rate(SCLK_BRG); +# else + mclk_divisor = Daq_BRG_Get_Count(SCLK_BRG); +# endif +# ifdef RUN_LRCLK_ON_BRG_INT + sclk_divisor = Daq_BRG_Rate(SCLK_BRG) / Daq_BRG_Rate(LRCLK_BRG); +# else + sclk_divisor = Daq_BRG_Get_Count(LRCLK_BRG); +# endif + + printf("\nADC/DAC Clocking (%d/%d):\n", sclk_divisor, mclk_divisor); + printf("\tMCLK %8d Hz, or %3dx SCLK, or %3dx LRCLK\n", + Daq_BRG_Rate(MCLK_BRG), + mclk_divisor, + mclk_divisor * sclk_divisor); +# ifdef RUN_SCLK_ON_BRG_INT + printf("\tSCLK %8d Hz, or %3dx LRCLK\n", + Daq_BRG_Rate(SCLK_BRG), + sclk_divisor); +# else + printf("\tSCLK %8d Hz, or %3dx LRCLK\n", + Daq_BRG_Rate(MCLK_BRG) / mclk_divisor, + sclk_divisor); +# endif +# ifdef RUN_LRCLK_ON_BRG_INT + printf("\tLRCLK %8d Hz\n", + Daq_BRG_Rate(LRCLK_BRG)); +# else +# ifdef RUN_SCLK_ON_BRG_INT + printf("\tLRCLK %8d Hz\n", + Daq_BRG_Rate(SCLK_BRG) / sclk_divisor); +# else + printf("\tLRCLK %8d Hz\n", + Daq_BRG_Rate(MCLK_BRG) / (mclk_divisor * sclk_divisor)); +# endif +# endif + printf("\n"); +} diff --git a/board/sacsng/ioconfig.h b/board/sacsng/ioconfig.h new file mode 100644 index 0000000..6857f99 --- /dev/null +++ b/board/sacsng/ioconfig.h @@ -0,0 +1,218 @@ +/* + * I/O Port configuration table + * + * If conf is 1, then that port pin will be configured at boot time + * according to the five values podr/pdir/ppar/psor/pdat for that entry + */ + +#ifdef SKIP +#undef SKIP +#endif + +#ifdef CONF +#undef CONF +#endif + +#ifdef DIN +#undef DIN +#endif + +#ifdef DOUT +#undef DOUT +#endif + +#ifdef GPIO +#undef GPIO +#endif + +#ifdef SPEC +#undef SPEC +#endif + +#ifdef ACTV +#undef ACTV +#endif + +#ifdef OPEN +#undef OPEN +#endif + +#define SKIP 0 /* SKIP over this port */ +#define CONF 1 /* CONFiguration the port */ + +#define DIN 0 /* PDIRx 0: Direction IN */ +#define DOUT 1 /* PDIRx 1: Direction OUT */ + +#define GPIO 0 /* PPARx 0: General Purpose I/O */ +#define SPEC 1 /* PPARx 1: dedicated to a peripheral function, */ + /* i.e. the port has a SPECial use. */ + +#define ACTV 0 /* PODRx 0: ACTiVely driven as an output */ +#define OPEN 1 /* PODRx 1: OPEN-drain driver */ + +const iop_conf_t iop_conf_tab[4][32] = { + + /* Port A configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PA31 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS8* */ + /* PA30 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS7* */ + /* PA29 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS6* */ + /* PA28 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS5* */ + /* PA27 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS4* */ + /* PA26 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS3* */ + /* PA25 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS2* */ + /* PA24 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* RODIS1* */ + /* PA23 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* ODIS_EN* */ + /* PA22 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* STLED2_EN* */ + /* PA21 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* STLED1_EN* */ + /* PA20 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PLED3_EN* */ + /* PA19 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PLED2_EN* */ + /* PA18 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* PLED1_EN* */ + /* PA17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PA16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* DAC_RST* */ + /* PA15 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* CH34SDATA_PU */ + /* PA14 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* CH12SDATA_PU */ + /* PA13 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SLRCLK_EN* */ + /* PA12 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4ACDC* */ + /* PA11 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4TEDS* */ + /* PA10 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_4XTDS* */ + /* PA9 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3ACDC* */ + /* PA8 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3TEDS* */ + /* PA7 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_3XTDS* */ + /* PA6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2ACDC* */ + /* PA5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2TEDS* */ + /* PA4 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_2XTDS* */ + /* PA3 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PA2 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_1ACDC* */ + /* PA1 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* MTRX_1TEDS* */ + /* PA0 */ { CONF, GPIO, 0, DOUT, ACTV, 1 } /* MTRX_1XTDS* */ + }, + + /* Port B configuration */ + { /* conf ppar psor pdir podr pdat */ + /* PB31 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TX_ER */ + /* PB30 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RX_DV */ + /* PB29 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* FCC2 MII_TX_EN */ + /* PB28 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RX_ER */ + /* PB27 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_COL */ + /* PB26 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_CRS */ + /* PB25 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD3 */ + /* PB24 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD2 */ + /* PB23 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD1 */ + /* PB22 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* FCC2 MII_TXD0 */ + /* PB21 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD0 */ + /* PB20 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD1 */ + /* PB19 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD2 */ + /* PB18 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* FCC2 MII_RXD3 */ + /* PB17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB15 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB14 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RXDC1, BSDATA_ADC12 */ + /* PB13 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB12 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RSYNCC1, LRCLK */ + /* PB11 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1TXDD1, RSDATA_DAC12 */ + /* PB10 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RXDD1, BSDATA_ADC34 */ + /* PB9 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB8 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* L1RSYNCD1, LRCLK */ + /* PB7 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PB6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* XCITE_SHDN */ + /* PB5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* TRIGGER */ + /* PB4 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* ARM */ + /* PB3 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PB2 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PB1 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PB0 */ { SKIP, GPIO, 0, DIN, ACTV, 0 } /* pin doesn't exist */ + }, + + /* Port C */ + { /* conf ppar psor pdir podr pdat */ + /* PC31 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC30 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC29 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK3, MCLK */ + /* PC28 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* TOUT2* */ +#ifdef QQQ + /* PC28 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TOUT2* */ +#endif + /* PC27 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK5, SCLK */ + /* PC26 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC25 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK7, SCLK */ + /* PC24 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC23 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK9, MCLK */ + /* PC22 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC21 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* BRGO6 (LRCLK) */ + /* PC20 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC19 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK13, MII_RXCLK */ + /* PC18 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* CLK14, MII_TXCLK */ + /* PC17 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* BRGO8 (SCLK) */ + /* PC16 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC15 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* SMC2_TX */ + /* PC14 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC13 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC12 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB3 */ + /* PC11 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC10 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* TDM_STRB4 */ + /* PC9 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN3 */ + /* PC8 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN2 */ + /* PC7 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BPDIS_IN1 */ + /* PC6 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PC5 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BTST_IN2* */ + /* PC4 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* BTST_IN1* */ + /* PC3 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* MUSH_STAT */ + /* PC2 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* OUTDRV_STAT */ + /* PC1 */ { CONF, GPIO, 0, DOUT, OPEN, 1 }, /* PHY_MDIO */ + /* PC0 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* PHY_MDC */ + }, + + /* Port D */ + { /* conf ppar psor pdir podr pdat */ + /* PD31 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* SCC1_RX */ + /* PD30 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SCC1_TX */ + /* PD29 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD28 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD27 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD26 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD25 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD24 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD23 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD22 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD21 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD20 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SPI_ADC_CS* */ + /* PD19 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* SPI_DAC_CS* */ +#if defined(CONFIG_SOFT_SPI) + /* PD18 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* SPI_CLK */ + /* PD17 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* SPI_MOSI */ + /* PD16 */ { CONF, GPIO, 0, DIN, ACTV, 0 }, /* SPI_MISO */ +#else + /* PD18 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SPI_CLK */ + /* PD17 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* SPI_MOSI */ + /* PD16 */ { CONF, SPEC, 1, DIN, ACTV, 0 }, /* SPI_MISO */ +#endif +#if defined(CONFIG_SOFT_I2C) + /* PD15 */ { CONF, GPIO, 0, DOUT, OPEN, 1 }, /* I2C_SDA */ + /* PD14 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* I2C_SCL */ +#else +#if defined(CONFIG_HARD_I2C) + /* PD15 */ { CONF, SPEC, 1, DIN, OPEN, 0 }, /* I2C_SDA */ + /* PD14 */ { CONF, SPEC, 1, DIN, OPEN, 0 }, /* I2C_SCL */ +#else /* normal I/O port pins */ + /* PD15 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* I2C_SDA */ + /* PD14 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* I2C_SCL */ +#endif +#endif + /* PD13 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB1 */ + /* PD12 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* TDM_STRB2 */ + /* PD11 */ { CONF, GPIO, 0, DOUT, ACTV, 0 }, /* N/C */ + /* PD10 */ { CONF, SPEC, 1, DOUT, ACTV, 0 }, /* BRGO4 (MCLK) */ + /* PD9 */ { CONF, SPEC, 0, DOUT, ACTV, 0 }, /* SMC1_TX */ + /* PD8 */ { CONF, SPEC, 0, DIN, ACTV, 0 }, /* SMC1_RX */ + /* PD7 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */ + /* PD6 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */ + /* PD5 */ { CONF, GPIO, 0, DOUT, ACTV, 1 }, /* N/C */ + /* PD4 */ { CONF, SPEC, 1, DOUT, ACTV, 1 }, /* SMC2_RX */ + /* PD3 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PD2 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PD1 */ { SKIP, GPIO, 0, DIN, ACTV, 0 }, /* pin doesn't exist */ + /* PD0 */ { SKIP, GPIO, 0, DIN, ACTV, 0 } /* pin doesn't exist */ + } +}; + diff --git a/board/sandpoint/sandpoint.c b/board/sandpoint/sandpoint.c new file mode 100644 index 0000000..8d385f7 --- /dev/null +++ b/board/sandpoint/sandpoint.c @@ -0,0 +1,127 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <pci.h> + +int checkboard (void) +{ + /*TODO: Check processor type */ + + puts ( "Board: Sandpoint " +#ifdef CONFIG_MPC8240 + "8240" +#endif +#ifdef CONFIG_MPC8245 + "8245" +#endif + " Unity ##Test not implemented yet##\n"); + return 0; +} + +#if 0 /* NOT USED */ +int checkflash (void) +{ + /* TODO: XXX XXX XXX */ + printf ("## Test not implemented yet ##\n"); + + return (0); +} +#endif + +long int initdram (int board_type) +{ + int i, cnt; + volatile uchar * base= CFG_SDRAM_BASE; + volatile ulong * addr; + ulong save[32]; + ulong val, ret = 0; + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt <= CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +} + +/* + * Initialize PCI Devices, report devices found. + */ +#ifndef CONFIG_PCI_PNP +static struct pci_config_table pci_sandpoint_config_table[] = { + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x0f, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0x10, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET1_IOADDR, + PCI_ENET1_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { } +}; +#endif + +struct pci_controller hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_sandpoint_config_table, +#endif +}; + +void pci_init(void) +{ + pci_mpc824x_init(&hose); +} diff --git a/board/shannon/u-boot.lds b/board/shannon/u-boot.lds new file mode 100644 index 0000000..f4b0ade --- /dev/null +++ b/board/shannon/u-boot.lds @@ -0,0 +1,53 @@ +/* + * (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_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/sa1100/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/siemens/CCM/ccm.c b/board/siemens/CCM/ccm.c new file mode 100644 index 0000000..079f38f --- /dev/null +++ b/board/siemens/CCM/ccm.c @@ -0,0 +1,440 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> +#include <commproc.h> +#include <command.h> + +/* ------------------------------------------------------------------------- */ + +static long int dram_size (long int, long int *, long int); +void can_driver_enable (void); +void can_driver_disable (void); + +int fpga_init(void); + +/* ------------------------------------------------------------------------- */ + +#define _NOT_USED_ 0xFFFFFFFF + +const uint sdram_table[] = +{ + /* + * Single Read. (Offset 0 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x11AF7C04, 0xEFBAFC00, + 0x1FF5FC47, /* last */ + /* + * SDRAM Initialization (offset 5 in UPMA RAM) + * + * This is no UPM entry point. The following definition uses + * the remaining space to establish an initialization + * sequence, which is executed by a RUN command. + * + */ + 0x1FF5FC34, 0xEFEABC34, 0x1FB57C35, /* last */ + /* + * Burst Read. (Offset 8 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEAFBC04, 0x10AF7C04, 0xF0AFFC00, + 0xF0AFFC00, 0xF1AFFC00, 0xEFBAFC00, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEABBC00, 0x01B27C04, 0x1FF5FC47, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPMA RAM) + */ + 0x1F0DFC04, 0xEEABBC00, 0x10A77C00, 0xF0AFFC00, + 0xF0AFFC00, 0xE1BAFC04, 0x1FF5FC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPMA RAM) + */ + 0x1FFD7C84, 0xFFFFFC04, 0xFFFFFC04, 0xFFFFFC04, + 0xFFFFFC84, 0xFFFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPMA RAM) + */ + 0x7FFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + +/* ------------------------------------------------------------------------- */ + + +/* + * Check Board Identity: + * + * Always return 1 (no second DRAM bank since based on TQM8xxL module) + */ + +int checkboard (void) +{ + unsigned char *s; + unsigned char buf[64]; + + s = (getenv_r ("serial#", buf, sizeof(buf)) > 0) ? buf : NULL; + + puts ("Board: Siemens CCM"); + + if (s) { + puts (" ("); + + for (; *s; ++s) { + if (*s == ' ') + break; + putc (*s); + } + putc (')'); + } + + putc ('\n'); + + return (0); +} + +/* ------------------------------------------------------------------------- */ + +/* + * If Power-On-Reset switch off the Red and Green LED: At reset, the + * data direction registers are cleared and must therefore be restored. + */ +#define RSR_CSRS 0x08000000 + +int power_on_reset(void) +{ + /* Test Reset Status Register */ + return ((volatile immap_t *)CFG_IMMR)->im_clkrst.car_rsr & RSR_CSRS ? 0:1; +} + +#define PB_LED_GREEN 0x10000 /* red LED is on PB.15 */ +#define PB_LED_RED 0x20000 /* red LED is on PB.14 */ +#define PB_LEDS (PB_LED_GREEN | PB_LED_RED); + +static void init_leds (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + + immap->im_cpm.cp_pbpar &= ~PB_LEDS; + immap->im_cpm.cp_pbodr &= ~PB_LEDS; + immap->im_cpm.cp_pbdir |= PB_LEDS; + /* Check stop reset status */ + if (power_on_reset()) { + immap->im_cpm.cp_pbdat &= ~PB_LEDS; + } +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + long int size8, size9; + long int size = 0; + unsigned long reg; + + upmconfig(UPMA, (uint *)sdram_table, sizeof(sdram_table)/sizeof(uint)); + + /* + * Preliminary prescaler for refresh (depends on number of + * banks): This value is selected for four cycles every 62.4 us + * with two SDRAM banks or four cycles every 31.2 us with one + * bank. It will be adjusted after memory sizing. + */ + memctl->memc_mptpr = CFG_MPTPR_2BK_8K; + + memctl->memc_mar = 0x00000088; + + /* + * Map controller banks 2 and 3 to the SDRAM banks 2 and 3 at + * preliminary addresses - these have to be modified after the + * SDRAM size has been determined. + */ + memctl->memc_or2 = CFG_OR2_PRELIM; + memctl->memc_br2 = CFG_BR2_PRELIM; + + memctl->memc_mamr = CFG_MAMR_8COL & (~(MAMR_PTAE)); /* no refresh yet */ + + udelay(200); + + /* perform SDRAM initializsation sequence */ + + memctl->memc_mcr = 0x80004105; /* SDRAM bank 0 */ + udelay(1); + memctl->memc_mcr = 0x80004230; /* SDRAM bank 0 - execute twice */ + udelay(1); + + memctl->memc_mamr |= MAMR_PTAE; /* enable refresh */ + + udelay (1000); + + /* + * Check Bank 0 Memory Size for re-configuration + * + * try 8 column mode + */ + size8 = dram_size (CFG_MAMR_8COL, (ulong *)SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); + + udelay (1000); + + /* + * try 9 column mode + */ + size9 = dram_size (CFG_MAMR_9COL, (ulong *)SDRAM_BASE2_PRELIM, SDRAM_MAX_SIZE); + + if (size8 < size9) { /* leave configuration at 9 columns */ + size = size9; +/* debug ("SDRAM in 9 column mode: %ld MB\n", size >> 20); */ + } else { /* back to 8 columns */ + size = size8; + memctl->memc_mamr = CFG_MAMR_8COL; + udelay(500); +/* debug ("SDRAM in 8 column mode: %ld MB\n", size >> 20); */ + } + + udelay (1000); + + /* + * Adjust refresh rate depending on SDRAM type + * For types > 128 MBit leave it at the current (fast) rate + */ + if (size < 0x02000000) { + /* reduce to 15.6 us (62.4 us / quad) */ + memctl->memc_mptpr = CFG_MPTPR_2BK_4K; + udelay(1000); + } + + /* + * Final mapping + */ + + memctl->memc_or2 = ((-size) & 0xFFFF0000) | CFG_OR_TIMING_SDRAM; + memctl->memc_br2 = (CFG_SDRAM_BASE & BR_BA_MSK) | BR_MS_UPMA | BR_V; + + + /* adjust refresh rate depending on SDRAM type, one bank */ + reg = memctl->memc_mptpr; + reg >>= 1; /* reduce to CFG_MPTPR_1BK_8K / _4K */ + memctl->memc_mptpr = reg; + + can_driver_enable (); + init_leds (); + + udelay(10000); + + return (size); +} + +/* ------------------------------------------------------------------------- */ + +/* + * Warning - both the PUMA load mode and the CAN driver use UPM B, + * so make sure only one of both is active. + */ +void can_driver_enable (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + /* Initialize MBMR */ + memctl->memc_mbmr = MAMR_GPL_B4DIS; /* GPL_B4 ouput line Disable */ + + /* Initialize UPMB for CAN: single read */ + memctl->memc_mdr = 0xFFFFC004; + memctl->memc_mcr = 0x0100 | UPMB; + + memctl->memc_mdr = 0x0FFFD004; + memctl->memc_mcr = 0x0101 | UPMB; + + memctl->memc_mdr = 0x0FFFC000; + memctl->memc_mcr = 0x0102 | UPMB; + + memctl->memc_mdr = 0x3FFFC004; + memctl->memc_mcr = 0x0103 | UPMB; + + memctl->memc_mdr = 0xFFFFDC05; + memctl->memc_mcr = 0x0104 | UPMB; + + /* Initialize UPMB for CAN: single write */ + memctl->memc_mdr = 0xFFFCC004; + memctl->memc_mcr = 0x0118 | UPMB; + + memctl->memc_mdr = 0xCFFCD004; + memctl->memc_mcr = 0x0119 | UPMB; + + memctl->memc_mdr = 0x0FFCC000; + memctl->memc_mcr = 0x011A | UPMB; + + memctl->memc_mdr = 0x7FFCC004; + memctl->memc_mcr = 0x011B | UPMB; + + memctl->memc_mdr = 0xFFFDCC05; + memctl->memc_mcr = 0x011C | UPMB; + + /* Initialize OR3 / BR3 for CAN Bus Controller */ + memctl->memc_or3 = CFG_OR3_CAN; + memctl->memc_br3 = CFG_BR3_CAN; +} + +void can_driver_disable (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + /* Reset OR3 / BR3 to disable CAN Bus Controller */ + memctl->memc_br3 = 0; + memctl->memc_or3 = 0; + + memctl->memc_mbmr = 0; +} + + +/* ------------------------------------------------------------------------- */ + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. Some (not all) hardware errors are detected: + * - short between address lines + * - short between data lines + */ + +static long int dram_size (long int mamr_value, long int *base, long int maxsize) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + memctl->memc_mamr = mamr_value; + + for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof(long)); + } + } + return (maxsize); +} + +/* ------------------------------------------------------------------------- */ + +#define ETH_CFG_BITS (CFG_PB_ETH_CFG1 | CFG_PB_ETH_CFG2 | CFG_PB_ETH_CFG3 ) + +#define ETH_ALL_BITS (ETH_CFG_BITS | CFG_PB_ETH_POWERDOWN) + +void reset_phy(void) +{ + immap_t *immr = (immap_t *)CFG_IMMR; + ulong value; + + /* Configure all needed port pins for GPIO */ +#if CFG_ETH_MDDIS_VALUE + immr->im_ioport.iop_padat |= CFG_PA_ETH_MDDIS; +#else + immr->im_ioport.iop_padat &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* Set low */ +#endif + immr->im_ioport.iop_papar &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* GPIO */ + immr->im_ioport.iop_paodr &= ~(CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET); /* active output */ + immr->im_ioport.iop_padir |= CFG_PA_ETH_MDDIS | CFG_PA_ETH_RESET; /* output */ + + immr->im_cpm.cp_pbpar &= ~(ETH_ALL_BITS); /* GPIO */ + immr->im_cpm.cp_pbodr &= ~(ETH_ALL_BITS); /* active output */ + + value = immr->im_cpm.cp_pbdat; + + /* Assert Powerdown and Reset signals */ + value |= CFG_PB_ETH_POWERDOWN; + + /* PHY configuration includes MDDIS and CFG1 ... CFG3 */ +#if CFG_ETH_CFG1_VALUE + value |= CFG_PB_ETH_CFG1; +#else + value &= ~(CFG_PB_ETH_CFG1); +#endif +#if CFG_ETH_CFG2_VALUE + value |= CFG_PB_ETH_CFG2; +#else + value &= ~(CFG_PB_ETH_CFG2); +#endif +#if CFG_ETH_CFG3_VALUE + value |= CFG_PB_ETH_CFG3; +#else + value &= ~(CFG_PB_ETH_CFG3); +#endif + + /* Drive output signals to initial state */ + immr->im_cpm.cp_pbdat = value; + immr->im_cpm.cp_pbdir |= ETH_ALL_BITS; + udelay (10000); + + /* De-assert Ethernet Powerdown */ + immr->im_cpm.cp_pbdat &= ~(CFG_PB_ETH_POWERDOWN); /* Enable PHY power */ + udelay (10000); + + /* de-assert RESET signal of PHY */ + immr->im_ioport.iop_padat |= CFG_PA_ETH_RESET; + udelay (1000); +} + + +int misc_init_r (void) +{ + fpga_init(); + return (0); +} +/* ------------------------------------------------------------------------- */ diff --git a/board/siemens/CCM/fpga_ccm.c b/board/siemens/CCM/fpga_ccm.c new file mode 100644 index 0000000..292387b --- /dev/null +++ b/board/siemens/CCM/fpga_ccm.c @@ -0,0 +1,170 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <mpc8xx.h> +#include <commproc.h> +#include <common.h> + +#include "../common/fpga.h" + +fpga_t fpga_list[] = { + { "PUMA" , PUMA_CONF_BASE , + CFG_PC_PUMA_INIT , CFG_PC_PUMA_PROG , CFG_PC_PUMA_DONE } +}; +int fpga_count = sizeof(fpga_list) / sizeof(fpga_t); + +void can_driver_enable (void); +void can_driver_disable (void); + +#define _NOT_USED_ 0xFFFFFFFF + +/* + * PUMA access using UPM B + */ +const uint puma_table[] = +{ + /* + * Single Read. (Offset 0 in UPM RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, + /* + * Precharge and MRS + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Read. (Offset 8 in UPM RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Single Write. (Offset 18 in UPM RAM) + */ + 0x0FFCF804, 0x0FFCF400, 0x3FFDFC47, /* last */ + _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Burst Write. (Offset 20 in UPM RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Refresh (Offset 30 in UPM RAM) + */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + _NOT_USED_, _NOT_USED_, _NOT_USED_, _NOT_USED_, + /* + * Exception. (Offset 3c in UPM RAM) + */ + 0x7FFFFC07, /* last */ + _NOT_USED_, _NOT_USED_, _NOT_USED_, +}; + + +ulong fpga_control (fpga_t* fpga, int cmd) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immr->im_memctl; + + switch (cmd) { + case FPGA_INIT_IS_HIGH: + immr->im_ioport.iop_pcdir &= ~fpga->init_mask; /* input */ + return (immr->im_ioport.iop_pcdat & fpga->init_mask) ? 1:0; + + case FPGA_INIT_SET_LOW: + immr->im_ioport.iop_pcdir |= fpga->init_mask; /* output */ + immr->im_ioport.iop_pcdat &= ~fpga->init_mask; + break; + + case FPGA_INIT_SET_HIGH: + immr->im_ioport.iop_pcdir |= fpga->init_mask; /* output */ + immr->im_ioport.iop_pcdat |= fpga->init_mask; + break; + + case FPGA_PROG_SET_LOW: + immr->im_ioport.iop_pcdat &= ~fpga->prog_mask; + break; + + case FPGA_PROG_SET_HIGH: + immr->im_ioport.iop_pcdat |= fpga->prog_mask; + break; + + case FPGA_DONE_IS_HIGH: + return (immr->im_ioport.iop_pcdat & fpga->done_mask) ? 1:0; + + case FPGA_READ_MODE: + /* disable FPGA in memory controller */ + memctl->memc_br4 = 0; + memctl->memc_or4 = PUMA_CONF_OR_READ; + memctl->memc_br4 = PUMA_CONF_BR_READ; + + /* (re-) enable CAN drivers */ + can_driver_enable (); + + break; + + case FPGA_LOAD_MODE: + /* disable FPGA in memory controller */ + memctl->memc_br4 = 0; + /* + * We must disable the CAN drivers first because + * they use UPM B, too. + */ + can_driver_disable (); + /* + * Configure UPMB for FPGA + */ + upmconfig(UPMB,(uint *)puma_table,sizeof(puma_table)/sizeof(uint)); + memctl->memc_or4 = PUMA_CONF_OR_LOAD; + memctl->memc_br4 = PUMA_CONF_BR_LOAD; + break; + + case FPGA_GET_ID: + return *(volatile ulong *)fpga->conf_base; + + case FPGA_INIT_PORTS: + immr->im_ioport.iop_pcpar &= ~fpga->init_mask; /* INIT I/O */ + immr->im_ioport.iop_pcso &= ~fpga->init_mask; + immr->im_ioport.iop_pcdir &= ~fpga->init_mask; + + immr->im_ioport.iop_pcpar &= ~fpga->prog_mask; /* PROG Output */ + immr->im_ioport.iop_pcso &= ~fpga->prog_mask; + immr->im_ioport.iop_pcdir |= fpga->prog_mask; + + immr->im_ioport.iop_pcpar &= ~fpga->done_mask; /* DONE Input */ + immr->im_ioport.iop_pcso &= ~fpga->done_mask; + immr->im_ioport.iop_pcdir &= ~fpga->done_mask; + + break; + + } + return 0; +} + diff --git a/board/siemens/SCM/fpga_scm.c b/board/siemens/SCM/fpga_scm.c new file mode 100644 index 0000000..3b93794 --- /dev/null +++ b/board/siemens/SCM/fpga_scm.c @@ -0,0 +1,104 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <mpc8260.h> +#include <common.h> +#include "../common/fpga.h" + +fpga_t fpga_list[] = { + { "FIOX" , CFG_FIOX_BASE , + CFG_PD_FIOX_INIT , CFG_PD_FIOX_PROG , CFG_PD_FIOX_DONE }, + { "FDOHM", CFG_FDOHM_BASE, + CFG_PD_FDOHM_INIT, CFG_PD_FDOHM_PROG, CFG_PD_FDOHM_DONE } +}; +int fpga_count = sizeof(fpga_list) / sizeof(fpga_t); + + +ulong fpga_control (fpga_t* fpga, int cmd) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + + switch (cmd) { + case FPGA_INIT_IS_HIGH: + immr->im_ioport.iop_pdird &= ~fpga->init_mask; /* input */ + return (immr->im_ioport.iop_pdatd & fpga->init_mask) ? 1:0; + + case FPGA_INIT_SET_LOW: + immr->im_ioport.iop_pdird |= fpga->init_mask; /* output */ + immr->im_ioport.iop_pdatd &= ~fpga->init_mask; + break; + + case FPGA_INIT_SET_HIGH: + immr->im_ioport.iop_pdird |= fpga->init_mask; /* output */ + immr->im_ioport.iop_pdatd |= fpga->init_mask; + break; + + case FPGA_PROG_SET_LOW: + immr->im_ioport.iop_pdatd &= ~fpga->prog_mask; + break; + + case FPGA_PROG_SET_HIGH: + immr->im_ioport.iop_pdatd |= fpga->prog_mask; + break; + + case FPGA_DONE_IS_HIGH: + return (immr->im_ioport.iop_pdatd & fpga->done_mask) ? 1:0; + + case FPGA_READ_MODE: + break; + + case FPGA_LOAD_MODE: + break; + + case FPGA_GET_ID: + if (fpga->conf_base == CFG_FIOX_BASE) { + ulong ver = *(volatile ulong *)(fpga->conf_base + 0x10); + return ((ver >> 10) & 0xf) + ((ver >> 2) & 0xf0); + } + else if (fpga->conf_base == CFG_FDOHM_BASE) { + return (*(volatile ushort *)fpga->conf_base) & 0xff; + } + else { + return *(volatile ulong *)fpga->conf_base; + } + + case FPGA_INIT_PORTS: + immr->im_ioport.iop_ppard &= ~fpga->init_mask; /* INIT I/O */ + immr->im_ioport.iop_psord &= ~fpga->init_mask; + immr->im_ioport.iop_pdird &= ~fpga->init_mask; + + immr->im_ioport.iop_ppard &= ~fpga->prog_mask; /* PROG Output */ + immr->im_ioport.iop_psord &= ~fpga->prog_mask; + immr->im_ioport.iop_pdird |= fpga->prog_mask; + + immr->im_ioport.iop_ppard &= ~fpga->done_mask; /* DONE Input */ + immr->im_ioport.iop_psord &= ~fpga->done_mask; + immr->im_ioport.iop_pdird &= ~fpga->done_mask; + + break; + + } + return 0; +} diff --git a/board/siemens/common/README b/board/siemens/common/README new file mode 100644 index 0000000..d781903 --- /dev/null +++ b/board/siemens/common/README @@ -0,0 +1,27 @@ +CCM/SCM-Ergaenzungen fuer U-Boot und Linux: +------------------------------------------- + +Es gibt nun ein gemeinsames Kommando zum Laden der FPGAs: + + => help fpga + fpga fpga status [name] - print FPGA status + fpga reset [name] - reset FPGA + fpga load [name] addr - load FPGA configuration data + +Der Name kann beim CCM-Module auch weggelassen werden. +Die Laengenangabe und damit "puma_len" ist nicht mehr +noetig: + + => fpga load puma 40600000 + FPGA load PUMA: addr 40600000: (00000005)... done + +Die MTD-Partitionierung kann nun mittels "bootargs" ueber- +geben werden: + + => printenv addmtd + addmtd=setenv bootargs $(bootargs) + mtdparts=0:256k(U-Boot)ro,768k(Kernel),-(Rest)\;1:-(myJFFS2) + +Die Portierung auf SMC ist natuerlich noch nicht getestet. + +Wolfgang Grandegger (04.06.2002) diff --git a/board/siemens/common/fpga.c b/board/siemens/common/fpga.c new file mode 100644 index 0000000..a17de5a --- /dev/null +++ b/board/siemens/common/fpga.c @@ -0,0 +1,358 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <common.h> +#include <command.h> +#include <linux/ctype.h> +#include <common.h> +#include <cmd_boot.h> +#include <cmd_bsp.h> + +#include "fpga.h" + +int power_on_reset(void); + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + + +static int fpga_get_version(fpga_t* fpga, char* name) +{ + char vname[12]; + /* + * Net-list string format: + * "vvvvvvvvddddddddn...". + * Version Date Name + * "0000000322042002PUMA" = PUMA version 3 from 22.04.2002. + */ + if (strlen(name) < (16 + strlen(fpga->name))) + goto failure; + /* Check FPGA name */ + if (strcmp(&name[16], fpga->name) != 0) + goto failure; + /* Get version number */ + memcpy(vname, name, 8); + vname[8] = '\0'; + return simple_strtoul(vname, NULL, 16); + + failure: + printf("Image name %s is invalid\n", name); + return -1; +} + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +static fpga_t* fpga_get(char* fpga_name) +{ + char name[FPGA_NAME_LEN]; + int i; + + if (strlen(fpga_name) >= FPGA_NAME_LEN) + goto failure; + for (i = 0; i < strlen(fpga_name); i++) + name[i] = toupper(fpga_name[i]); + name[i] = '\0'; + for (i = 0; i < fpga_count; i++) { + if (strcmp(name, fpga_list[i].name) == 0) + return &fpga_list[i]; + } + failure: + printf("FPGA: name %s is invalid\n", fpga_name); + return NULL; +} + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +static void fpga_status (fpga_t* fpga) +{ + /* Check state */ + if (fpga_control(fpga, FPGA_DONE_IS_HIGH)) + printf ("%s is loaded (%08lx)\n", + fpga->name, fpga_control(fpga, FPGA_GET_ID)); + else + printf ("%s is NOT loaded\n", fpga->name); +} + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +#define FPGA_RESET_TIMEOUT 100 /* = 10 ms */ + +static int fpga_reset (fpga_t* fpga) +{ + int i; + + /* Set PROG to low and wait til INIT goes low */ + fpga_control(fpga, FPGA_PROG_SET_LOW); + for (i = 0; i < FPGA_RESET_TIMEOUT; i++) { + udelay (100); + if (!fpga_control(fpga, FPGA_INIT_IS_HIGH)) + break; + } + if (i == FPGA_RESET_TIMEOUT) + goto failure; + + /* Set PROG to high and wait til INIT goes high */ + fpga_control(fpga, FPGA_PROG_SET_HIGH); + for (i = 0; i < FPGA_RESET_TIMEOUT; i++) { + udelay (100); + if (fpga_control(fpga, FPGA_INIT_IS_HIGH)) + break; + } + if (i == FPGA_RESET_TIMEOUT) + goto failure; + + return 0; + failure: + return 1; +} + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +#define FPGA_LOAD_TIMEOUT 100 /* = 10 ms */ + +static int fpga_load (fpga_t* fpga, ulong addr, int checkall) +{ + volatile uchar *fpga_addr = (volatile uchar *)fpga->conf_base; + image_header_t hdr; + ulong len, checksum; + uchar *data = (uchar *)&hdr; + char *s, msg[32]; + int verify, i; + + /* + * Check the image header and data of the net-list + */ + memcpy (&hdr, (char *)addr, sizeof(image_header_t)); + + if (hdr.ih_magic != IH_MAGIC) { + strcpy (msg, "Bad Image Magic Number"); + goto failure; + } + + len = sizeof(image_header_t); + + checksum = hdr.ih_hcrc; + hdr.ih_hcrc = 0; + + if (crc32 (0, data, len) != checksum) { + strcpy (msg, "Bad Image Header CRC"); + goto failure; + } + + data = (uchar*)(addr + sizeof(image_header_t)); + len = hdr.ih_size; + + s = getenv ("verify"); + verify = (s && (*s == 'n')) ? 0 : 1; + if (verify) { + if (crc32 (0, data, len) != hdr.ih_dcrc) { + strcpy (msg, "Bad Image Data CRC"); + goto failure; + } + } + + if (checkall && fpga_get_version(fpga, hdr.ih_name) < 0) + return 1; + + /* align length */ + if (len & 1) + ++len; + + /* + * Reset FPGA and wait for completion + */ + if (fpga_reset(fpga)) { + strcpy (msg, "Reset Timeout"); + goto failure; + } + + printf ("(%s)... ", hdr.ih_name); + /* + * Copy data to FPGA + */ + fpga_control (fpga, FPGA_LOAD_MODE); + while (len--) { + *fpga_addr = *data++; + } + fpga_control (fpga, FPGA_READ_MODE); + + /* + * Wait for completion and check error status if timeout + */ + for (i = 0; i < FPGA_LOAD_TIMEOUT; i++) { + udelay (100); + if (fpga_control (fpga, FPGA_DONE_IS_HIGH)) + break; + } + if (i == FPGA_LOAD_TIMEOUT) { + if (fpga_control(fpga, FPGA_INIT_IS_HIGH)) + strcpy(msg, "Invalid Size"); + else + strcpy(msg, "CRC Error"); + goto failure; + } + + printf("done\n"); + return 0; + + failure: + + printf("ERROR: %s\n", msg); + return 1; +} + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr = 0; + int i; + fpga_t* fpga; + + if (argc < 2) + goto failure; + + if (strncmp(argv[1], "stat", 4) == 0) { /* status */ + if (argc == 2) { + for (i = 0; i < fpga_count; i++) { + fpga_status (&fpga_list[i]); + } + } + else if (argc == 3) { + if ((fpga = fpga_get(argv[2])) == 0) + goto failure; + fpga_status (fpga); + } + else + goto failure; + } + else if (strcmp(argv[1],"load") == 0) { /* load */ + if (argc == 3 && fpga_count == 1) { + fpga = &fpga_list[0]; + } + else if (argc == 4) { + if ((fpga = fpga_get(argv[2])) == 0) + goto failure; + } + else + goto failure; + + addr = simple_strtoul(argv[argc-1], NULL, 16); + + printf ("FPGA load %s: addr %08lx: ", + fpga->name, addr); + fpga_load (fpga, addr, 1); + + } + else if (strncmp(argv[1], "rese", 4) == 0) { /* reset */ + if (argc == 2 && fpga_count == 1) { + fpga = &fpga_list[0]; + } + else if (argc == 3) { + if ((fpga = fpga_get(argv[2])) == 0) + goto failure; + } + else + goto failure; + + printf ("FPGA reset %s: ", fpga->name); + if (fpga_reset(fpga)) + printf ("ERROR: Timeout\n"); + else + printf ("done\n"); + } + else + goto failure; + + return 0; + + failure: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_BSP */ + +/* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */ + +int fpga_init (void) +{ + ulong addr; + ulong new_id, old_id = 0; + image_header_t *hdr; + fpga_t* fpga; + int do_load, i, j; + char name[16], *s; + + /* + * Port setup for FPGA control + */ + for (i = 0; i < fpga_count; i++) { + fpga_control(&fpga_list[i], FPGA_INIT_PORTS); + } + + /* + * Load FPGA(s): a new net-list is loaded if the FPGA is + * empty, Power-on-Reset or the old one is not up-to-date + */ + for (i = 0; i < fpga_count; i++) { + fpga = &fpga_list[i]; + printf ("%s: ", fpga->name); + + for (j = 0; j < strlen(fpga->name); j++) + name[j] = tolower(fpga->name[j]); + name[j] = '\0'; + sprintf(name, "%s_addr", name); + addr = 0; + if ((s = getenv(name)) != NULL) + addr = simple_strtoul(s, NULL, 16); + + if (!addr) { + printf ("env. variable %s undefined\n", name); + return 1; + } + + hdr = (image_header_t *)addr; + if ((new_id = fpga_get_version(fpga, hdr->ih_name)) == -1) + return 1; + + do_load = 1; + + if (!power_on_reset() && fpga_control(fpga, FPGA_DONE_IS_HIGH)) { + old_id = fpga_control(fpga, FPGA_GET_ID); + if (new_id == old_id) + do_load = 0; + } + + if (do_load) { + printf ("loading "); + fpga_load (fpga, addr, 0); + } else { + printf ("loaded (%08lx)\n", old_id); + } + } + + return 0; +} diff --git a/board/smdk2400/u-boot.lds b/board/smdk2400/u-boot.lds new file mode 100644 index 0000000..8c9c218 --- /dev/null +++ b/board/smdk2400/u-boot.lds @@ -0,0 +1,54 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm920t/start.o (.text) + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/smdk2410/smdk2410.c b/board/smdk2410/smdk2410.c new file mode 100644 index 0000000..7f983ef --- /dev/null +++ b/board/smdk2410/smdk2410.c @@ -0,0 +1,124 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, <d.mueller@elsoft.ch> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <s3c2410.h> + +/* ------------------------------------------------------------------------- */ + +#define FCLK_SPEED 1 + +#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */ +#define M_MDIV 0xC3 +#define M_PDIV 0x4 +#define M_SDIV 0x1 +#elif FCLK_SPEED==1 /* Fout = 202.8MHz */ +#define M_MDIV 0xA1 +#define M_PDIV 0x3 +#define M_SDIV 0x1 +#endif + +#define USB_CLOCK 1 + +#if USB_CLOCK==0 +#define U_M_MDIV 0xA1 +#define U_M_PDIV 0x3 +#define U_M_SDIV 0x1 +#elif USB_CLOCK==1 +#define U_M_MDIV 0x48 +#define U_M_PDIV 0x3 +#define U_M_SDIV 0x2 +#endif + +static inline void delay (unsigned long loops) +{ + __asm__ volatile ("1:\n" + "subs %0, %1, #1\n" + "bne 1b":"=r" (loops):"0" (loops)); +} + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + /* to reduce PLL lock time, adjust the LOCKTIME register */ + rLOCKTIME = 0xFFFFFF; + + /* configure MPLL */ + rMPLLCON = ((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV); + + /* some delay between MPLL and UPLL */ + delay (4000); + + /* configure UPLL */ + rUPLLCON = ((U_M_MDIV << 12) + (U_M_PDIV << 4) + U_M_SDIV); + + /* some delay between MPLL and UPLL */ + delay (8000); + + /* set up the I/O ports */ + rGPACON = 0x007FFFFF; + rGPBCON = 0x00044555; + rGPBUP = 0x000007FF; + rGPCCON = 0xAAAAAAAA; + rGPCUP = 0x0000FFFF; + rGPDCON = 0xAAAAAAAA; + rGPDUP = 0x0000FFFF; + rGPECON = 0xAAAAAAAA; + rGPEUP = 0x0000FFFF; + rGPFCON = 0x000055AA; + rGPFUP = 0x000000FF; + rGPGCON = 0xFF95FFBA; + rGPGUP = 0x0000FFFF; + rGPHCON = 0x002AFAAA; + rGPHUP = 0x000007FF; + + /* arch number of SMDK2410-Board */ + gd->bd->bi_arch_number = 193; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x30000100; + + icache_enable(); + dcache_enable(); + + return 0; +} + +int dram_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + + return 0; +} diff --git a/board/tqm8xx/flash.c b/board/tqm8xx/flash.c new file mode 100644 index 0000000..2f74ccc --- /dev/null +++ b/board/tqm8xx/flash.c @@ -0,0 +1,569 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> + +#ifndef CFG_ENV_ADDR +#define CFG_ENV_ADDR (CFG_FLASH_BASE + CFG_ENV_OFFSET) +#endif + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + unsigned long size_b0, size_b1; + int i; + + /* Init: no FLASHes known */ + for (i=0; i<CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Static FLASH Bank configuration here - FIXME XXX */ + + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + } + + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + + if (size_b1 > size_b0) { + printf ("## ERROR: " + "Bank 1 (0x%08lx = %ld MB) > Bank 0 (0x%08lx = %ld MB)\n", + size_b1, size_b1<<20, + size_b0, size_b0<<20 + ); + flash_info[0].flash_id = FLASH_UNKNOWN; + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[0].sector_count = -1; + flash_info[1].sector_count = -1; + flash_info[0].size = 0; + flash_info[1].size = 0; + return (0); + } + + /* Remap FLASH according to real size */ + memctl->memc_or0 = CFG_OR_TIMING_FLASH | (-size_b0 & OR_AM_MSK); + memctl->memc_br0 = (CFG_FLASH_BASE & BR_BA_MSK) | BR_MS_GPCM | BR_V; + + /* Re-do sizing to get full correct info */ + size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[0]); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + &flash_info[0]); +#endif + + if (size_b1) { + memctl->memc_or1 = CFG_OR_TIMING_FLASH | (-size_b1 & 0xFFFF8000); + memctl->memc_br1 = ((CFG_FLASH_BASE + size_b0) & BR_BA_MSK) | + BR_MS_GPCM | BR_V; + + /* Re-do sizing to get full correct info */ + size_b1 = flash_get_size((vu_long *)(CFG_FLASH_BASE + size_b0), + &flash_info[1]); + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + &flash_info[1]); +#endif + +#ifdef CFG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + &flash_info[1]); +#endif + } else { + memctl->memc_br1 = 0; /* invalidate bank */ + + flash_info[1].flash_id = FLASH_UNKNOWN; + flash_info[1].sector_count = -1; + } + + flash_info[0].size = size_b0; + flash_info[1].size = size_b1; + + return (size_b0 + size_b1); +} + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, info->sector_count); + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); + return; +} + +/*----------------------------------------------------------------------- + */ + + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + ulong value; + ulong base = (ulong)addr; + + /* Write auto select command: read Manufacturer ID */ + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00900090; + + value = addr[0]; + + switch (value) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* no or unknown flash */ + } + + value = addr[1]; /* device ID */ + + switch (value) { + case AMD_ID_LV400T: + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + case AMD_ID_LV320T: + info->flash_id += FLASH_AM320T; + info->sector_count = 71; + info->size = 0x00800000; + break; /* => 8 MB */ + + case AMD_ID_LV320B: + info->flash_id += FLASH_AM320B; + info->sector_count = 71; + info->size = 0x00800000; + break; /* => 8 MB */ + default: + info->flash_id = FLASH_UNKNOWN; + return (0); /* => no or unknown flash */ + } + + /* set up sector start address table */ + switch (value) { + case AMD_ID_LV400B: + case AMD_ID_LV800B: + case AMD_ID_LV160B: + /* set sector offsets for bottom boot block type */ + info->start[0] = base + 0x00000000; + info->start[1] = base + 0x00008000; + info->start[2] = base + 0x0000C000; + info->start[3] = base + 0x00010000; + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + (i * 0x00020000) - 0x00060000; + } + break; + case AMD_ID_LV400T: + case AMD_ID_LV800T: + case AMD_ID_LV160T: + /* set sector offsets for top boot block type */ + i = info->sector_count - 1; + info->start[i--] = base + info->size - 0x00008000; + info->start[i--] = base + info->size - 0x0000C000; + info->start[i--] = base + info->size - 0x00010000; + for (; i >= 0; i--) { + info->start[i] = base + i * 0x00020000; + } + break; + case AMD_ID_LV320B: + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base; + /* + * The first 8 sectors are 8 kB, + * all the other ones are 64 kB + */ + base += (i < 8) + ? 2 * ( 8 << 10) + : 2 * (64 << 10); + } + break; + case AMD_ID_LV320T: + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base; + /* + * The last 8 sectors are 8 kB, + * all the other ones are 64 kB + */ + base += (i < (info->sector_count - 8)) + ? 2 * (64 << 10) + : 2 * ( 8 << 10); + } + break; + default: + return (0); + break; + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr = (volatile unsigned long *)(info->start[i]); + info->protect[i] = addr[2] & 1; + } + + /* + * Prevent writes to uninitialized FLASH. + */ + if (info->flash_id != FLASH_UNKNOWN) { + addr = (volatile unsigned long *)info->start[0]; + + *addr = 0x00F000F0; /* reset bank */ + } + + return (info->size); +} + + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + vu_long *addr = (vu_long*)(info->start[0]); + int flag, prot, sect, l_sect; + ulong start, now, last; + + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + if ((info->flash_id == FLASH_UNKNOWN) || + (info->flash_id > FLASH_AMD_COMP)) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00800080; + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = (vu_long*)(info->start[sect]); + addr[0] = 0x00300030; + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = (vu_long*)(info->start[l_sect]); + while ((addr[0] & 0x00800080) != 0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + } + +DONE: + /* reset to read mode */ + addr = (volatile unsigned long *)info->start[0]; + addr[0] = 0x00F000F0; /* reset bank */ + + printf (" done\n"); + return 0; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<4 && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word(info, wp, data)); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long*)(info->start[0]); + ulong start; + int flag; + + /* Check if Flash is (sufficiently) erased */ + if ((*((vu_long *)dest) & data) != data) { + return (2); + } + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + addr[0x0555] = 0x00AA00AA; + addr[0x02AA] = 0x00550055; + addr[0x0555] = 0x00A000A0; + + *((vu_long *)dest) = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((*((vu_long *)dest) & 0x00800080) != (data & 0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + return (1); + } + } + return (0); +} + +/*----------------------------------------------------------------------- + */ diff --git a/board/tqm8xx/load_sernum_ethaddr.c b/board/tqm8xx/load_sernum_ethaddr.c new file mode 100644 index 0000000..98baf7f --- /dev/null +++ b/board/tqm8xx/load_sernum_ethaddr.c @@ -0,0 +1,105 @@ +/* + * (C) Copyright 2000, 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8xx.h> + +/*----------------------------------------------------------------------- + * Process Hardware Information Block: + * + * If we boot on a system fresh from factory, check if the Hardware + * Information Block exists and save the information it contains. + * + * The TQM8xxL / TQM82xx Hardware Information Block is defined as + * follows: + * - located in first flash bank + * - starts at offset 0x0003FFC0 + * - size 0x00000040 + * + * Internal structure: + * - sequence of ASCII character strings + * - fields separated by a single space character (0x20) + * - last field terminated by NUL character (0x00) + * - remaining space filled with NUL characters (0x00) + * + * Fields in Hardware Information Block: + * 1) Module Type + * 2) Serial Number + * 3) First MAC Address + * 4) Number of additional MAC addresses + */ + +void load_sernum_ethaddr (void) +{ + unsigned char *hwi; + unsigned char serial [CFG_HWINFO_SIZE]; + unsigned char ethaddr[CFG_HWINFO_SIZE]; + unsigned short ih, is, ie, part; + + hwi = (unsigned char *)(CFG_FLASH_BASE + CFG_HWINFO_OFFSET); + ih = is = ie = 0; + + if (*((unsigned long *)hwi) != (unsigned long)CFG_HWINFO_MAGIC) { + return; + } + + part = 1; + + /* copy serial # / MAC address */ + while ((hwi[ih] != '\0') && (ih < CFG_HWINFO_SIZE)) { + if (hwi[ih] < ' ' || hwi[ih] > '~') { /* ASCII strings! */ + return; + } + switch (part) { + default: /* Copy serial # */ + if (hwi[ih] == ' ') { + ++part; + } + serial[is++] = hwi[ih]; + break; + case 3: /* Copy MAC address */ + if (hwi[ih] == ' ') { + ++part; + break; + } + ethaddr[ie++] = hwi[ih]; + if ((ie % 3) == 2) + ethaddr[ie++] = ':'; + break; + } + ++ih; + } + serial[is] = '\0'; + if (ie && ethaddr[ie-1] == ':') + --ie; + ethaddr[ie] = '\0'; + + /* set serial# and ethaddr if not yet defined */ + if (getenv("serial#") == NULL) { + setenv ("serial#", serial); + } + + if (getenv("ethaddr") == NULL) { + setenv ("ethaddr", ethaddr); + } +} diff --git a/board/trab/README.kbd b/board/trab/README.kbd new file mode 100644 index 0000000..3db00bc --- /dev/null +++ b/board/trab/README.kbd @@ -0,0 +1,44 @@ + +The TRAB keyboard implementation is similar to that for LWMON and +R360MPI boards. The only difference concerns key naming. There are 4 +keys on TRAB: 1, 2, 3, 4. + +1) The "kbd" command provides information about the current state of + the keys. For example, + + TRAB # kbd + Keys: 1 0 1 0 + + means that keys 1 and 3 are pressed. The keyboard status is also + stored in the "keybd" environment variable. In this example we get + + keybd=1010 + +2) The "preboot" variable is set according to current environment + settings and keys pressed. This is an example: + + TRAB # setenv magic_keys XY + TRAB # setenv key_magicX 12 + TRAB # setenv key_cmdX echo ## Keys 1 + 2 pressed ##\;echo + TRAB # setenv key_magicY 13 + TRAB # setenv key_cmdY echo ## Keys 1 + 3 pressed ##\;echo + + Here "magic_keys=XY" means that the "key_magicX" and "key_magicY" + variables will be checked for a match. Each variable "key_magic*" + defines a set of keys. In the our example, if keys 1 and 3 are + pressed during reset, then "key_magicY" matches, so the "preboot" + variable will be set to the contents of "key_cmdY": + + preboot=echo ## Keys 1 + 3 pressed ##;echo + +3) The TRAB board has optional modem support. When a certain key + combination is pressed on the keyboard at power-on, the firmware + performs the necessary initialization of the modem and allows for + dial-in. The key combination is specified in the + "include/configs/trab.h" file. For example: + + #define CONFIG_MODEM_KEY_MAGIC "23" + + means that modem will be initialized if and only if both keys 2, 3 + are pressed. Note that the format of this string is similar to the + format of "key_magic*" environment variables described above. diff --git a/board/trab/trab.c b/board/trab/trab.c new file mode 100644 index 0000000..3f9b198 --- /dev/null +++ b/board/trab/trab.c @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* #define DEBUG */ + +#include <common.h> +#include <cmd_bsp.h> +#include <malloc.h> +#include <s3c2400.h> + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void); +extern void disable_putc(void); +extern int do_mdm_init; /* defined in common/main.c */ + +/* + * We need a delay of at least 500 us after turning on the VFD clock + * before we can read any useful information for the CPLD controlling + * the keyboard switches. Let's play safe and wait 5 ms. The problem + * is that timers are not available yet, so we use a manually timed + * loop. + */ +#define KBD_MDELAY 100000 /* 1000 */ +static void mdelay_no_timer (int msec) +{ + DECLARE_GLOBAL_DATA_PTR; + + int i; + int delay = msec * 3; + + for (i = 0; i < delay; i ++) gd->bd->bi_arch_number = 145; +} +#endif /* CONFIG_MODEM_SUPPORT */ + +/* + * Miscellaneous platform dependent initialisations + */ + +int board_init () +{ + DECLARE_GLOBAL_DATA_PTR; + + /* memory and cpu-speed are setup before relocation */ +#ifdef CONFIG_TRAB_50MHZ + /* change the clock to be 50 MHz 1:1:1 */ + /* MDIV:0x5c PDIV:4 SDIV:2 */ + rMPLLCON = 0x5c042; + rCLKDIVN = 0; +#else + /* change the clock to be 133 MHz 1:2:4 */ + /* MDIV:0x7d PDIV:4 SDIV:1 */ + rMPLLCON = 0x7d041; + rCLKDIVN = 3; +#endif + + /* set up the I/O ports */ + rPACON = 0x3ffff; + rPBCON = 0xaaaaaaaa; + rPBUP = 0xffff; + /* INPUT nCTS0 nRTS0 TXD[1] TXD[0] RXD[1] RXD[0] */ + /* 00, 10, 10, 10, 10, 10, 10 */ + rPFCON = (2<<0) | (2<<2) | (2<<4) | (2<<6) | (2<<8) | (2<<10); +#ifdef CONFIG_HWFLOW + /* do not pull up RXD0, RXD1, TXD0, TXD1, CTS0, RTS0 */ + rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<4) | (1<<5); +#else + /* do not pull up RXD0, RXD1, TXD0, TXD1 */ + rPFUP = (1<<0) | (1<<1) | (1<<2) | (1<<3); +#endif + rPGCON = 0x0; + rPGUP = 0x0; + rOPENCR= 0x0; + + /* arch number of SAMSUNG-Board */ + /* MACH_TYPE_SMDK2400 */ + /* XXX this isn't really correct, but keep it for now */ + gd->bd->bi_arch_number = 145; + + /* adress of boot parameters */ + gd->bd->bi_boot_params = 0x0c000100; + +#ifdef CONFIG_MODEM_SUPPORT + /* This stuff is needed to get interrupts on stop-position + * contact events. + * (Copied from the LCD initialization routine.) + */ + if (rLCDCON1 == 0) + { + rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; + rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; +#if 0 + rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + rLCDCON2 = 0x000DC000; + rLCDCON3 = 0x0051000A; + rLCDCON4 = 0x00000001; + rLCDCON5 = 0x00000440; + rLCDCON1 = 0x00000B75; + } + + mdelay_no_timer (KBD_MDELAY); + + if (key_pressed()) { + disable_putc(); /* modem doesn't understand banner etc */ + do_mdm_init = 1; + } +#endif /* CONFIG_MODEM_SUPPORT */ + + return 0; +} + +int dram_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + gd->bd->bi_dram[0].start = PHYS_SDRAM_1; + gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; + return 0; +} + +/*----------------------------------------------------------------------- + * Keyboard Controller + */ + +/* Maximum key number */ +#define KEYBD_KEY_NUM 4 + +#define KBD_DATA (((*(volatile ulong *)0x04020000) >> 16) & 0xF) + +static uchar *key_match (ulong); + +int misc_init_r (void) +{ + ulong kbd_data = KBD_DATA; + uchar keybd_env[KEYBD_KEY_NUM + 1]; + uchar *str; + int i; + + for (i = 0; i < KEYBD_KEY_NUM; ++i) { + keybd_env[i] = '0' + ((kbd_data >> i) & 1); + } + keybd_env[i] = '\0'; + debug ("** Setting keybd=\"%s\"\n", keybd_env); + setenv ("keybd", keybd_env); + + str = strdup (key_match (kbd_data)); /* decode keys */ + +#ifdef CONFIG_PREBOOT /* automatically configure "preboot" command on key match */ + debug ("** Setting preboot=\"%s\"\n", str); + setenv ("preboot", str); /* set or delete definition */ +#endif /* CONFIG_PREBOOT */ + if (str != NULL) { + free (str); + } + + return (0); +} + +#ifdef CONFIG_PREBOOT + +static uchar kbd_magic_prefix[] = "key_magic"; +static uchar kbd_command_prefix[] = "key_cmd"; + +static int compare_magic (ulong kbd_data, uchar *str) +{ + uchar key_mask; + + debug ("compare_magic: kbd: %04lx str: \"%s\"\n",kbd_data,str); + for (; *str; str++) + { + uchar c = *str - '1'; + + if (c >= KEYBD_KEY_NUM) /* bad key number */ + return -1; + + key_mask = 1 << c; + + if (!(kbd_data & key_mask)) { /* key not pressed */ + debug ( "compare_magic: " + "kbd: %04lx mask: %04lx - key not pressed\n", + kbd_data, key_mask ); + return -1; + } + + kbd_data &= ~key_mask; + } + + if (kbd_data) { /* key(s) not released */ + debug ( "compare_magic: " + "kbd: %04lx - key(s) not released\n", kbd_data); + return -1; + } + + return 0; +} + +/*----------------------------------------------------------------------- + * Check if pressed key(s) match magic sequence, + * and return the command string associated with that key(s). + * + * If no key press was decoded, NULL is returned. + * + * Note: the first character of the argument will be overwritten with + * the "magic charcter code" of the decoded key(s), or '\0'. + * + * + * Note: the string points to static environment data and must be + * saved before you call any function that modifies the environment. + */ +static uchar *key_match (ulong kbd_data) +{ + uchar magic[sizeof (kbd_magic_prefix) + 1]; + uchar cmd_name[sizeof (kbd_command_prefix) + 1]; + uchar *suffix; + uchar *kbd_magic_keys; + + /* + * The following string defines the characters that can pe appended + * to "key_magic" to form the names of environment variables that + * hold "magic" key codes, i. e. such key codes that can cause + * pre-boot actions. If the string is empty (""), then only + * "key_magic" is checked (old behaviour); the string "125" causes + * checks for "key_magic1", "key_magic2" and "key_magic5", etc. + */ + if ((kbd_magic_keys = getenv ("magic_keys")) == NULL) + kbd_magic_keys = ""; + + debug ("key_match: magic_keys=\"%s\"\n", kbd_magic_keys); + + /* loop over all magic keys; + * use '\0' suffix in case of empty string + */ + for (suffix=kbd_magic_keys; *suffix || suffix==kbd_magic_keys; ++suffix) + { + sprintf (magic, "%s%c", kbd_magic_prefix, *suffix); + + debug ("key_match: magic=\"%s\"\n", + getenv(magic) ? getenv(magic) : "<UNDEFINED>"); + + if (compare_magic(kbd_data, getenv(magic)) == 0) + { + sprintf (cmd_name, "%s%c", kbd_command_prefix, *suffix); + debug ("key_match: cmdname %s=\"%s\"\n", + cmd_name, + getenv (cmd_name) ? + getenv (cmd_name) : + "<UNDEFINED>"); + return (getenv (cmd_name)); + } + } + debug ("key_match: no match\n"); + return (NULL); +} +#endif /* CONFIG_PREBOOT */ + +/* Read Keyboard status */ +int do_kbd (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + ulong kbd_data = KBD_DATA; + uchar keybd_env[KEYBD_KEY_NUM + 1]; + int i; + + puts ("Keys:"); + for (i = 0; i < KEYBD_KEY_NUM; ++i) { + keybd_env[i] = '0' + ((kbd_data >> i) & 1); + printf (" %c", keybd_env[i]); + } + keybd_env[i] = '\0'; + putc ('\n'); + setenv ("keybd", keybd_env); + return 0; +} + +#ifdef CONFIG_MODEM_SUPPORT +static int key_pressed(void) +{ + return (compare_magic(KBD_DATA, CONFIG_MODEM_KEY_MAGIC) == 0); +} +#endif /* CONFIG_MODEM_SUPPORT */ diff --git a/board/trab/u-boot.lds b/board/trab/u-boot.lds new file mode 100644 index 0000000..59834af --- /dev/null +++ b/board/trab/u-boot.lds @@ -0,0 +1,63 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/ +OUTPUT_ARCH(arm) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + cpu/arm920t/start.o (.text) + lib_arm/_udivsi3.o (.text) + lib_arm/_umodsi3.o (.text) + lib_generic/zlib.o (.text) + lib_generic/crc32.o (.text) + lib_generic/string.o (.text) + + . = env_offset; + common/environment.o (.ppcenv) + + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .got : { *(.got) } + + armboot_end_data = .; + + . = ALIGN(4); + .bss : { *(.bss) } + + armboot_end = .; +} diff --git a/board/trab/vfd.c b/board/trab/vfd.c new file mode 100644 index 0000000..1ea483f --- /dev/null +++ b/board/trab/vfd.c @@ -0,0 +1,414 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering -- wd@denx.de + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/************************************************************************/ +/* ** DEBUG SETTINGS */ +/************************************************************************/ + +/* #define DEBUG */ + +/************************************************************************/ +/* ** HEADER FILES */ +/************************************************************************/ + +#include <config.h> +#include <common.h> +#include <version.h> +#include <stdarg.h> +#include <linux/types.h> +#include <devices.h> +#include <s3c2400.h> + +#ifdef CONFIG_VFD + +/************************************************************************/ +/* ** CONFIG STUFF -- should be moved to board config file */ +/************************************************************************/ + +/************************************************************************/ + +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + +#define ROT 0x09 +#define BLAU 0x0C +#define VIOLETT 0X0D + +ulong vfdbase; +ulong frame_buf_size; +#define frame_buf_offs 4 + +/* taken from armboot/common/vfd.c */ +ulong adr_vfd_table[112][18][2][4][2]; +unsigned char bit_vfd_table[112][18][2][4][2]; + +/* + * initialize the values for the VFD-grid-control in the framebuffer + */ +void init_grid_ctrl(void) +{ + ulong adr, grid_cycle; + unsigned int bit, display; + unsigned char temp, bit_nr; + + for (adr=vfdbase; adr<=(vfdbase+7168); adr+=4) /*clear frame buffer */ + (*(volatile ulong*)(adr))=0; + + for(display=0;display<=3;display++) + { + for(grid_cycle=0;grid_cycle<=55;grid_cycle++) + { + bit = grid_cycle*256*4+(grid_cycle+200)*4+frame_buf_offs+display; + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit-(frame_buf_size*8); + adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); + bit_nr = bit%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + temp|=(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + + if(grid_cycle<55) + bit = grid_cycle*256*4+(grid_cycle+201)*4+frame_buf_offs+display; + else + bit = grid_cycle*256*4+200*4+frame_buf_offs+display-4; /* grid nr. 0 */ + /* wrap arround if offset (see manual S3C2400) */ + if (bit>=frame_buf_size*8) + bit = bit-(frame_buf_size*8); + adr = vfdbase+(bit/32)*4+(3-(bit%32)/8); + bit_nr = bit%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + temp=(*(volatile unsigned char*)(adr)); + temp|=(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + } + } +} + +/* + *create translation table for getting easy the right position in the + *physical framebuffer for some x/y-coordinates of the VFDs + */ +void create_vfd_table(void) +{ + unsigned int vfd_table[112][18][2][4][2]; + ulong adr; + unsigned int x, y, color, display, entry, pixel, bit_nr; + + /* + * Create translation table for Noritake-T119C-VFD-specific + * organized frame-buffer. + * Created is the number of the bit in the framebuffer (the + * first transferred pixel of each frame is bit 0). + */ + for(y=0;y<=17;y++) /* Zeile */ + { + for(x=0;x<=111;x++) /* Spalten */ + { + /*Display 0 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][0][0]=((x%4)*4+y*16+(x/4)*2048); + /*Display 0 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][0][0]=((x%4)*4+y*16+(x/4)*2048+512); + if(x<=1) + { + /*Display 0 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1024); + /*Display 0 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][0][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1024); + } + else + { + /*Display 0 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+1024); + /*Display 0 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][0][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1024); + } + /*Display 1 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][1][0]=((x%4)*4+y*16+(x/4)*2048+1); + /*Display 1 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][1][0]=((x%4)*4+y*16+(x/4)*2048+512+1); + if(x<=1) + { + /*Display 1 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+1+1024); + /*Display 1 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][1][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+1+1024); + } + else + { + /*Display 1 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+1+1024); + /*Display 1 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][1][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+1+1024); + } + /*Display 2 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][2][0]=((x%4)*4+y*16+(x/4)*2048+2); + /*Display 2 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][2][0]=((x%4)*4+y*16+(x/4)*2048+512+2); + if(x<=1) + { + /*Display 2 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+2+1024); + /*Display 2 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][2][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+2+1024); + } + else + { + /*Display 2 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+2+1024); + /*Display 2 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][2][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+2+1024); + } + /*Display 3 blaue Pixel Eintrag 1 */ + vfd_table[x][y][0][3][0]=((x%4)*4+y*16+(x/4)*2048+3); + /*Display 3 rote Pixel Eintrag 1 */ + vfd_table[x][y][1][3][0]=((x%4)*4+y*16+(x/4)*2048+512+3); + if(x<=1) + { + /*Display 3 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+3+1024); + /*Display 3 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][3][1]=(((x+112)%4)*4+y*16+((x+110)/4)*2048+512+3+1024); + } + else + { + /*Display 3 blaue Pixel Eintrag 2 */ + vfd_table[x][y][0][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+3+1024); + /*Display 3 rote Pixel Eintrag 2 */ + vfd_table[x][y][1][3][1]=((x%4)*4+y*16+((x-2)/4)*2048+512+3+1024); + } + } + } + + /* + * Create translation table for Noritake-T119C-VFD-specific + * organized frame-buffer + * Create table with entries for physical byte adresses and + * bit-number within the byte + * from table with bit-numbers within the total framebuffer + */ + for(y=0;y<=17;y++) + { + for(x=0;x<=111;x++) + { + for(color=0;color<=1;color++) + { + for(display=0;display<=3;display++) + { + for(entry=0;entry<=1;entry++) + { + pixel = vfd_table[x][y][color][display][entry] + frame_buf_offs; + /* + * wrap arround if offset + * (see manual S3C2400) + */ + if (pixel>=frame_buf_size*8) + pixel = pixel-(frame_buf_size*8); + adr = vfdbase+(pixel/32)*4+(3-(pixel%32)/8); + bit_nr = pixel%8; + bit_nr = (bit_nr>3)?bit_nr-4:bit_nr+4; + adr_vfd_table[x][y][color][display][entry] = adr; + bit_vfd_table[x][y][color][display][entry] = bit_nr; + } + } + } + } + } +} + +/* + * Set/clear pixel of the VFDs + */ +void set_vfd_pixel(unsigned char x, unsigned char y, unsigned char color, unsigned char display, unsigned char value) +{ + ulong adr; + unsigned char bit_nr, temp; + + if (value!=0) + { + /* Pixel-Eintrag Nr. 1 */ + adr = adr_vfd_table[x][y][color][display][0]; + /* Pixel-Eintrag Nr. 1 */ + bit_nr = bit_vfd_table[x][y][color][display][0]; + temp=(*(volatile unsigned char*)(adr)); + temp|=1<<bit_nr; + (*(volatile unsigned char*)(adr))=temp; + + /* Pixel-Eintrag Nr. 2 */ + adr = adr_vfd_table[x][y][color][display][1]; + /* Pixel-Eintrag Nr. 2 */ + bit_nr = bit_vfd_table[x][y][color][display][1]; + temp=(*(volatile unsigned char*)(adr)); + temp|=1<<bit_nr; + (*(volatile unsigned char*)(adr))=temp; + } + else + { + /* Pixel-Eintrag Nr. 1 */ + adr = adr_vfd_table[x][y][color][display][0]; + /* Pixel-Eintrag Nr. 1 */ + bit_nr = bit_vfd_table[x][y][color][display][0]; + temp=(*(volatile unsigned char*)(adr)); + temp&=~(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + + /* Pixel-Eintrag Nr. 2 */ + adr = adr_vfd_table[x][y][color][display][1]; + /* Pixel-Eintrag Nr. 2 */ + bit_nr = bit_vfd_table[x][y][color][display][1]; + temp=(*(volatile unsigned char*)(adr)); + temp&=~(1<<bit_nr); + (*(volatile unsigned char*)(adr))=temp; + } +} + +/* + * transfer image from BMP-File + */ +void transfer_pic(int display, unsigned char *adr, int height, int width) +{ + int x, y; + unsigned char temp; + + for (; height > 0; height -= 18) + { + if (height > 18) + y = 18; + else + y = height; + for (; y > 0; y--) + { + for (x = 0; x < width; x += 2) + { + temp = *adr++; + set_vfd_pixel(x, y-1, 0, display, 0); + set_vfd_pixel(x, y-1, 1, display, 0); + if ((temp >> 4) == BLAU) + set_vfd_pixel(x, y-1, 0, display, 1); + else if ((temp >> 4) == ROT) + set_vfd_pixel(x, y-1, 1, display, 1); + else if ((temp >> 4) == VIOLETT) + { + set_vfd_pixel(x, y-1, 0, display, 1); + set_vfd_pixel(x, y-1, 1, display, 1); + } + set_vfd_pixel(x+1, y-1, 0, display, 0); + set_vfd_pixel(x+1, y-1, 1, display, 0); + if ((temp & 0x0F) == BLAU) + set_vfd_pixel(x+1, y-1, 0, display, 1); + else if ((temp & 0x0F) == ROT) + set_vfd_pixel(x+1, y-1, 1, display, 1); + else if ((temp & 0x0F) == VIOLETT) + { + set_vfd_pixel(x+1, y-1, 0, display, 1); + set_vfd_pixel(x+1, y-1, 1, display, 1); + } + } + } + display++; + if (display > 3) + display = 0; + } +} + +/* + * initialize LCD-Controller of the S3C2400 for using VFDs + */ +int drv_vfd_init(void) +{ + ulong palette; + + DECLARE_GLOBAL_DATA_PTR; + + vfdbase = gd->fb_base; + create_vfd_table(); + init_grid_ctrl(); + + /* + * Hinweis: Der Framebuffer ist um genau ein Nibble verschoben + * Das erste angezeigte Pixel wird aus dem zweiten Nibble geholt + * das letzte angezeigte Pixel wird aus dem ersten Nibble geholt + * (wrap around) + * see manual S3C2400 + */ + /* frame buffer startadr */ + rLCDSADDR1 = vfdbase >> 1; + /* frame buffer endadr */ + rLCDSADDR2 = (vfdbase + frame_buf_size) >> 1; + rLCDSADDR3 = ((256/4)); + + /* Port-Pins als LCD-Ausgang */ + rPCCON = (rPCCON & 0xFFFFFF00)| 0x000000AA; + /* Port-Pins als LCD-Ausgang */ + rPDCON = (rPDCON & 0xFFFFFF03)| 0x000000A8; +#ifdef WITH_VFRAME + /* mit VFRAME zum Messen */ + rPDCON = (rPDCON & 0xFFFFFF00)| 0x000000AA; +#endif + + rLCDCON2 = 0x000DC000; + rLCDCON3 = 0x0051000A; + rLCDCON4 = 0x00000001; + rLCDCON5 = 0x00000440; + rLCDCON1 = 0x00000B75; + + debug ("LCDSADDR1: %lX\n", rLCDSADDR1); + debug ("LCDSADDR2: %lX\n", rLCDSADDR2); + debug ("LCDSADDR3: %lX\n", rLCDSADDR3); + + for(palette=0;palette<=15;palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=palette; + for(palette=16;palette<=255;palette++) + (*(volatile unsigned int*)(PALETTE+(palette*4)))=0x00; + + return 0; +} + +/************************************************************************/ +/* ** ROM capable initialization part - needed to reserve FB memory */ +/************************************************************************/ + +/* + * This is called early in the system initialization to grab memory + * for the VFD controller. + * + * Note that this is running from ROM, so no write access to global data. + */ +ulong vfd_setmem (ulong addr) +{ + ulong size; + + /* MAGIC */ + frame_buf_size = (256*4*56)/8; + + /* Round up to nearest full page */ + size = (frame_buf_size + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); + + debug ("Reserving %ldk for VFD Framebuffer at: %08lx\n", size>>10, addr); + + return (size); +} + +#endif /* CONFIG_VFD */ diff --git a/board/utx8245/utx8245.c b/board/utx8245/utx8245.c new file mode 100644 index 0000000..249862a --- /dev/null +++ b/board/utx8245/utx8245.c @@ -0,0 +1,152 @@ +/* + * (C) Copyright 2001 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.com. + * + * (C) Copyright 2002 + * Gregory E. Allen, gallen@arlut.utexas.edu + * Matthew E. Karger, karger@arlut.utexas.edu + * Applied Research Laboratories, The University of Texas at Austin + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc824x.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> + +#define SAVE_SZ 32 + + +int checkboard(void) +{ + ulong busfreq = get_bus_freq(0); + char buf[32]; + + printf("Board: UTX8245 Local Bus at %s MHz\n", strmhz(buf, busfreq)); + return 0; +} + + +long int initdram(int board_type) +{ +#if 1 + int i, cnt; + volatile uchar *base = CFG_SDRAM_BASE; + volatile ulong *addr; + ulong save[SAVE_SZ]; + ulong val, ret = 0; + + for (i=0; i<SAVE_SZ; i++) {save[i] = 0;} /* clear table */ + + for (i=0, cnt=(CFG_MAX_RAM_SIZE / sizeof(long)) >> 1; cnt > 0; cnt >>= 1) + { + addr = (volatile ulong *)base + cnt; + save[i++] = *addr; + *addr = ~cnt; + } + + addr = (volatile ulong *)base; + save[i] = *addr; + *addr = 0; + + if (*addr != 0) + { + *addr = save[i]; + goto Done; + } + + for (cnt = 1; cnt < CFG_MAX_RAM_SIZE / sizeof(long); cnt <<= 1) + { + addr = (volatile ulong *)base + cnt; + val = *addr; + *addr = save[--i]; + if (val != ~cnt) + { + ulong new_bank0_end = cnt * sizeof(long) - 1; + ulong mear1 = mpc824x_mpc107_getreg(MEAR1); + ulong emear1 = mpc824x_mpc107_getreg(EMEAR1); + mear1 = (mear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT); + emear1 = (emear1 & 0xFFFFFF00) | + ((new_bank0_end & MICR_ADDR_MASK) >> MICR_EADDR_SHIFT); + mpc824x_mpc107_setreg(MEAR1, mear1); + mpc824x_mpc107_setreg(EMEAR1, emear1); + + ret = cnt * sizeof(long); + goto Done; + } + } + + ret = CFG_MAX_RAM_SIZE; +Done: + return ret; +#else + return (CFG_MAX_RAM_SIZE); +#endif + +} + + +/* + * Initialize PCI Devices, report devices found. + */ + +static struct pci_config_table pci_utx8245_config_table[] = { +#ifndef CONFIG_PCI_PNP + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_ENET0_IOADDR, + PCI_ENET0_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, + { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, + pci_cfgfunc_config_device, { PCI_FIREWIRE_IOADDR, + PCI_FIREWIRE_MEMADDR, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER }}, +#endif /*CONFIG_PCI_PNP*/ + { } +}; + + +static void pci_utx8245_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + if (PCI_DEV(dev) == 11) + /* assign serial interrupt line 9 (int25) to FireWire */ + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 25); + + else if (PCI_DEV(dev) == 12) + /* assign serial interrupt line 8 (int24) to Ethernet */ + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 24); +} + +static struct pci_controller utx8245_hose = { +#ifndef CONFIG_PCI_PNP + config_table: pci_utx8245_config_table, + fixup_irq: pci_utx8245_fixup_irq, + write_byte: pci_hose_write_config_byte +#endif /*CONFIG_PCI_PNP*/ +}; + +void pci_init (void) +{ + pci_mpc824x_init(&utx8245_hose); + + icache_enable(); +} + diff --git a/board/w7o/flash.c b/board/w7o/flash.c new file mode 100644 index 0000000..0048476 --- /dev/null +++ b/board/w7o/flash.c @@ -0,0 +1,941 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * Based on code by: + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> + +#include <watchdog.h> + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info); +static int write_word8(flash_info_t *info, ulong dest, ulong data); +static int write_word32 (flash_info_t *info, ulong dest, ulong data); +static void flash_get_offsets (ulong base, flash_info_t *info); + +/*----------------------------------------------------------------------- + */ + +unsigned long flash_init (void) +{ + int i; + unsigned long size_b0, base_b0; + unsigned long size_b1, base_b1; + + /* Init: no FLASHes known */ + for (i = 0; i < CFG_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + } + + /* Get Size of Boot and Main Flashes */ + size_b0 = flash_get_size((vu_long *)FLASH_BASE0_PRELIM, &flash_info[0]); + if (flash_info[0].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB\n", + size_b0, size_b0<<20); + return 0; + } + size_b1 = flash_get_size((vu_long *)FLASH_BASE1_PRELIM, &flash_info[1]); + if (flash_info[1].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank 1 - Size = 0x%08lx = %ld MB\n", + size_b1, size_b1<<20); + return 0; + } + + /* Calculate base addresses */ + base_b0 = -size_b0; + base_b1 = -size_b1; + + /* Setup offsets for Boot Flash */ + flash_get_offsets (base_b0, &flash_info[0]); + + /* Protect board level data */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b0, + flash_info[0].start[1] - 1, + &flash_info[0]); + + + /* Monitor protection ON by default */ + (void)flash_protect(FLAG_PROTECT_SET, + base_b0 + size_b0 - CFG_MONITOR_LEN, + base_b0 + size_b0 - 1, + &flash_info[0]); + + /* Protect the FPGA image */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE1_PRELIM, + FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN - 1, + &flash_info[1]); + + /* Protect the default boot image */ + (void)flash_protect(FLAG_PROTECT_SET, + FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN, + FLASH_BASE1_PRELIM + CFG_FPGA_IMAGE_LEN + 0x600000 - 1, + &flash_info[1]); + + /* Setup offsets for Main Flash */ + flash_get_offsets (FLASH_BASE1_PRELIM, &flash_info[1]); + + return (size_b0 + size_b1); +} /* end flash_init() */ + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table - FOR BOOT ROM ONLY!!! */ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) { + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + } +} /* end flash_get_offsets() */ + +/*----------------------------------------------------------------------- + */ +void flash_print_info (flash_info_t *info) +{ + int i; + int k; + int size; + int erased; + volatile unsigned long *flash; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("1 x AMD "); break; + case FLASH_MAN_STM: printf ("1 x STM "); break; + case FLASH_MAN_INTEL: printf ("2 x Intel "); break; + default: printf ("Unknown Vendor "); + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD) + printf ("AM29LV040 (4096 Kbit, uniform sector size)\n"); + else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) + printf ("M29W040B (4096 Kbit, uniform block size)\n"); + else + printf ("UNKNOWN 29x040x (4096 Kbit, uniform sector size)\n"); + break; + case FLASH_28F320J3A: + printf ("28F320J3A (32 Mbit = 128K x 32)\n"); + break; + case FLASH_28F640J3A: + printf ("28F640J3A (64 Mbit = 128K x 64)\n"); + break; + case FLASH_28F128J3A: + printf ("28F128J3A (128 Mbit = 128K x 128)\n"); + break; + default: + printf ("Unknown Chip Type\n"); + } + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) { + printf (" Size: %ld KB in %d Blocks\n", + info->size >> 10, info->sector_count); + } else { + printf (" Size: %ld KB in %d Sectors\n", + info->size >> 10, info->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + /* + * Check if whole sector is erased + */ + if (i != (info->sector_count-1)) + size = info->start[i+1] - info->start[i]; + else + size = info->start[0] + info->size - info->start[i]; + erased = 1; + flash = (volatile unsigned long *)info->start[i]; + size = size >> 2; /* divide by 4 for longword access */ + for (k=0; k<size; k++) + { + if (*flash++ != 0xffffffff) + { + erased = 0; + break; + } + } + + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s%s", + info->start[i], + erased ? " E" : " ", + info->protect[i] ? "RO " : " " + ); + } + printf ("\n"); +} /* end flash_print_info() */ + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (vu_long *addr, flash_info_t *info) +{ + short i; + ulong base = (ulong)addr; + + /* Setup default type */ + info->flash_id = FLASH_UNKNOWN; + info->sector_count =0; + info->size = 0; + + /* Test for Boot Flash */ + if (base == FLASH_BASE0_PRELIM) { + unsigned char value; + volatile unsigned char * addr2 = (unsigned char *)addr; + + /* Write auto select command: read Manufacturer ID */ + *(addr2 + 0x555) = 0xaa; + *(addr2 + 0x2aa) = 0x55; + *(addr2 + 0x555) = 0x90; + + /* Manufacture ID */ + value = *addr2; + switch (value) { + case (unsigned char)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + case (unsigned char)STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + default: + *addr2 = 0xf0; /* no or unknown flash */ + return 0; + } + + /* Device ID */ + value = *(addr2 + 1); + switch (value) { + case (unsigned char)AMD_ID_LV040B: + case (unsigned char)STM_ID_29W040B: + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512Kb */ + default: + *addr2 = 0xf0; /* => no or unknown flash */ + return 0; + } + } + else { /* MAIN Flash */ + unsigned long value; + volatile unsigned long * addr2 = (unsigned long *)addr; + + /* Write auto select command: read Manufacturer ID */ + *addr2 = 0x90909090; + + /* Manufacture ID */ + value = *addr2; + switch (value) { + case (unsigned long)INTEL_MANUFACT: + info->flash_id = FLASH_MAN_INTEL; + break; + default: + *addr2 = 0xff; /* no or unknown flash */ + return 0; + } + + /* Device ID - This shit is interleaved... */ + value = *(addr2 + 1); + switch (value) { + case (unsigned long)INTEL_ID_28F320J3A: + info->flash_id += FLASH_28F320J3A; + info->sector_count = 32; + info->size = 0x00400000 * 2; + break; /* => 2 X 4 MB */ + case (unsigned long)INTEL_ID_28F640J3A: + info->flash_id += FLASH_28F640J3A; + info->sector_count = 64; + info->size = 0x00800000 * 2; + break; /* => 2 X 8 MB */ + case (unsigned long)INTEL_ID_28F128J3A: + info->flash_id += FLASH_28F128J3A; + info->sector_count = 128; + info->size = 0x01000000 * 2; + break; /* => 2 X 16 MB */ + default: + *addr2 = 0xff; /* => no or unknown flash */ + } + } + + /* Make sure we don't exceed CFG_MAX_FLASH_SECT */ + 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; + } + + /* set up sector start address table */ + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00010000); + break; + case FLASH_28F320J3A: + case FLASH_28F640J3A: + case FLASH_28F128J3A: + for (i = 0; i < info->sector_count; i++) + info->start[i] = base + (i * 0x00020000 * 2); /* 2 Banks */ + break; + } + + /* Test for Boot Flash */ + if (base == FLASH_BASE0_PRELIM) { + volatile unsigned char *addr2; + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (AX .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile unsigned char *)(info->start[i]); + info->protect[i] = *(addr2 + 2) & 1; + } + + /* Restore read mode */ + *(unsigned char *)base = 0xF0; /* Reset NORMAL Flash */ + } + else { /* Main Flash */ + volatile unsigned long *addr2; + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (AX .. A0) = 0x02 */ + /* D0 = 1 if protected */ + addr2 = (volatile unsigned long *)(info->start[i]); + info->protect[i] = *(addr2 + 2) & 0x1; + } + + /* Restore read mode */ + *(unsigned long *)base = 0xFFFFFFFF; /* Reset Flash */ + } + + return (info->size); +} /* end flash_get_size() */ + +/*----------------------------------------------------------------------- + */ + +static int wait_for_DQ7(ulong addr, uchar cmp_val, ulong tout) +{ + int i; + + volatile uchar *vaddr = (uchar *)addr; + + /* Loop X times */ + for (i = 1; i <= (100 * tout); i++) { /* Wait up to tout ms */ + udelay(10); + /* Pause 10 us */ + + /* Check for completion */ + if ((vaddr[0] & 0x80) == (cmp_val & 0x80)) { + return 0; + } + + /* KEEP THE LUSER HAPPY - Print a dot every 1.1 seconds */ + if (!(i % 110000)) + putc('.'); + + /* Kick the dog if needed */ + WATCHDOG_RESET(); + } + + return 1; +} /* wait_for_DQ7() */ + +/*----------------------------------------------------------------------- + */ + +static int flash_erase8(flash_info_t *info, int s_first, int s_last) +{ + int tcode, rcode = 0; + volatile uchar *addr = (uchar *)(info->start[0]); + volatile uchar *sector_addr; + int flag, prot, sect; + + /* Validate arguments */ + 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; + } + + /* Check for KNOWN flash type */ + if (info->flash_id == FLASH_UNKNOWN) { + printf ("Can't erase unknown flash type - aborted\n"); + return 1; + } + + /* Check for protected sectors */ + 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 erase on unprotected sectors */ + for (sect = s_first; sect <= s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + sector_addr = (uchar *)(info->start[sect]); + + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_STM) + printf("Erasing block %p\n", sector_addr); + else + printf("Erasing sector %p\n", sector_addr); + + /* Disable interrupts which might cause Flash to timeout */ + flag = disable_interrupts(); + + *(addr + 0x555) = (uchar)0xAA; + *(addr + 0x2aa) = (uchar)0x55; + *(addr + 0x555) = (uchar)0x80; + *(addr + 0x555) = (uchar)0xAA; + *(addr + 0x2aa) = (uchar)0x55; + *sector_addr = (uchar)0x30; /* sector erase */ + + /* + * Wait for each sector to complete, it's more + * reliable. According to AMD Spec, you must + * issue all erase commands within a specified + * timeout. This has been seen to fail, especially + * if printf()s are included (for debug)!! + * Takes up to 6 seconds. + */ + tcode = wait_for_DQ7((ulong)sector_addr, 0x80, 6000); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* Make sure we didn't timeout */ + if (tcode) { + printf ("Timeout\n"); + rcode = 1; + } + } + } + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* reset to read mode */ + addr = (uchar *)info->start[0]; + *addr = (uchar)0xF0; /* reset bank */ + + printf (" done\n"); + return rcode; +} /* end flash_erase8() */ + +static int flash_erase32(flash_info_t *info, int s_first, int s_last) +{ + int flag, sect; + ulong start, now, last; + int prot = 0; + + /* Validate arguments */ + 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; + } + + /* Check for KNOWN flash type */ + if ((info->flash_id & FLASH_VENDMASK) != FLASH_MAN_INTEL) { + printf ("Can erase only Intel flash types - aborted\n"); + return 1; + } + + /* Check for protected sectors */ + 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++) { + WATCHDOG_RESET(); + if (info->protect[sect] == 0) { /* not protected */ + vu_long *addr = (vu_long *)(info->start[sect]); + unsigned long status; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *addr = 0x00500050; /* clear status register */ + *addr = 0x00200020; /* erase setup */ + *addr = 0x00D000D0; /* erase confirm */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* Wait at least 80us - let's wait 1 ms */ + udelay (1000); + + while (((status = *addr) & 0x00800080) != 0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + *addr = 0x00B000B0; /* suspend erase */ + *addr = 0x00FF00FF; /* reset to read mode */ + return 1; + } + + /* show that we're waiting */ + if ((now - last) > 990) { /* every second */ + putc ('.'); + last = now; + } + } + *addr = 0x00FF00FF; /* reset to read mode */ + } + } + printf (" done\n"); + return 0; +} /* end flash_erase32() */ + +int flash_erase(flash_info_t *info, int s_first, int s_last) +{ + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) + return flash_erase8(info, s_first, s_last); + else + return flash_erase32(info, s_first, s_last); +} /* end flash_erase() */ + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_buff8(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + ulong start; + int i, l, rc; + + start = get_timer (0); + + wp = (addr & ~3); /* get lower word + aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<4 && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word8(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + } + + /* + * handle word aligned part + */ + while (cnt >= 4) { + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word8(info, wp, data)) != 0) { + return (rc); + } + wp += 4; + cnt -= 4; + if (get_timer(start) > 1000) { /* every second */ + WATCHDOG_RESET(); + putc ('.'); + start = get_timer(0); + } + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word8(info, wp, data)); +} /* end write_buff8() */ + +#define FLASH_WIDTH 4 /* flash bus width in bytes */ +static int write_buff32 (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + ulong start; + + start = get_timer (0); + + if (info->flash_id == FLASH_UNKNOWN) { + return 4; + } + + wp = (addr & ~(FLASH_WIDTH-1)); /* get lower FLASH_WIDTH aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<FLASH_WIDTH && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<FLASH_WIDTH; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word32(info, wp, data)) != 0) { + return (rc); + } + wp += FLASH_WIDTH; + } + + /* + * handle FLASH_WIDTH aligned part + */ + while (cnt >= FLASH_WIDTH) { + data = 0; + for (i=0; i<FLASH_WIDTH; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word32(info, wp, data)) != 0) { + return (rc); + } + wp += FLASH_WIDTH; + cnt -= FLASH_WIDTH; + if (get_timer(start) > 990) { /* every second */ + putc ('.'); + start = get_timer(0); + } + } + + if (cnt == 0) { + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<FLASH_WIDTH && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<FLASH_WIDTH; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + return (write_word32(info, wp, data)); +} /* write_buff32() */ + +int write_buff(flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + int retval; + + if ((info->flash_id & FLASH_TYPEMASK) == FLASH_AM040) + retval = write_buff8(info, src, addr, cnt); + else + retval = write_buff32(info, src, addr, cnt); + + return retval; +} /* end write_buff() */ + +/*----------------------------------------------------------------------- + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ + +static int write_word8(flash_info_t *info, ulong dest, ulong data) +{ + volatile uchar *addr2 = (uchar *)(info->start[0]); + volatile uchar *dest2 = (uchar *)dest; + volatile uchar *data2 = (uchar *)&data; + int flag; + int i, tcode, rcode = 0; + + /* Check if Flash is (sufficently) erased */ + if ((*((volatile uchar *)dest) & + (uchar)data) != (uchar)data) { + return (2); + } + + for (i=0; i < (4 / sizeof(uchar)); i++) { + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + *(addr2 + 0x555) = (uchar)0xAA; + *(addr2 + 0x2aa) = (uchar)0x55; + *(addr2 + 0x555) = (uchar)0xA0; + + dest2[i] = data2[i]; + + /* Wait for write to complete, up to 1ms */ + tcode = wait_for_DQ7((ulong)&dest2[i], data2[i], 1); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* Make sure we didn't timeout */ + if (tcode) { + rcode = 1; + } + } + + return rcode; +} /* end write_word8() */ + +static int write_word32(flash_info_t *info, ulong dest, ulong data) +{ + vu_long *addr = (vu_long *)dest; + ulong 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 = 0x00400040; /* write setup */ + *addr = data; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + + while (((status = *addr) & 0x00800080) != 0x00800080) { + WATCHDOG_RESET(); + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + *addr = 0x00FF00FF; /* restore read mode */ + return (1); + } + } + + *addr = 0x00FF00FF; /* restore read mode */ + + return (0); +} /* end write_word32() */ + + +static int _flash_protect(flash_info_t *info, long sector) +{ + int i; + int flag; + ulong status; + int rcode = 0; + volatile long *addr = (unsigned long *)sector; + + switch(info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F320J3A: + case FLASH_28F640J3A: + case FLASH_28F128J3A: + /* Disable interrupts which might cause Flash to timeout */ + flag = disable_interrupts(); + + /* Issue command */ + *addr = 0x00500050L; /* Clear the status register */ + *addr = 0x00600060L; /* Set lock bit setup */ + *addr = 0x00010001L; /* Set lock bit confirm */ + + /* Wait for command completion */ + for (i = 0; i < 10; i++) { /* 75us timeout, wait 100us */ + udelay(10); + if ((*addr & 0x00800080L) == 0x00800080L) + break; + } + + /* Not successful? */ + status = *addr; + if (status != 0x00800080L) { + printf("Protect %x sector failed: %x\n", + (uint)sector, (uint)status); + rcode = 1; + } + + /* Restore read mode */ + *addr = 0x00ff00ffL; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + break; + case FLASH_AM040: /* No soft sector protection */ + break; + } + + /* Turn protection on for this sector */ + for (i = 0; i < info->sector_count; i++) { + if (info->start[i] == sector) { + info->protect[i] = 1; + break; + } + } + + return rcode; +} /* end _flash_protect() */ + +static int _flash_unprotect(flash_info_t *info, long sector) +{ + int i; + int flag; + ulong status; + int rcode = 0; + volatile long *addr = (unsigned long *)sector; + + switch(info->flash_id & FLASH_TYPEMASK) { + case FLASH_28F320J3A: + case FLASH_28F640J3A: + case FLASH_28F128J3A: + /* Disable interrupts which might cause Flash to timeout */ + flag = disable_interrupts(); + + *addr = 0x00500050L; /* Clear the status register */ + *addr = 0x00600060L; /* Clear lock bit setup */ + *addr = 0x00D000D0L; /* Clear lock bit confirm */ + + /* Wait for command completion */ + for (i = 0; i < 80 ; i++) { /* 700ms timeout, wait 800 */ + udelay(10000); /* Delay 10ms */ + if ((*addr & 0x00800080L) == 0x00800080L) + break; + } + + /* Not successful? */ + status = *addr; + if (status != 0x00800080L) { + printf("Un-protect %x sector failed: %x\n", + (uint)sector, (uint)status); + *addr = 0x00ff00ffL; + rcode = 1; + } + + /* restore read mode */ + *addr = 0x00ff00ffL; + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + break; + case FLASH_AM040: /* No soft sector protection */ + break; + } + + /* + * Fix Intel's little red wagon. Reprotect + * sectors that were protected before we undid + * protection on a specific sector. + */ + for (i = 0; i < info->sector_count; i++) { + if (info->start[i] != sector) { + if (info->protect[i]) { + if (_flash_protect(info, info->start[i])) + rcode = 1; + } + } + else /* Turn protection off for this sector */ + info->protect[i] = 0; + } + + return rcode; +} /* end _flash_unprotect() */ + + +int flash_real_protect(flash_info_t *info, long sector, int prot) +{ + int rcode; + + if (prot) + rcode = _flash_protect(info, info->start[sector]); + else + rcode = _flash_unprotect(info, info->start[sector]); + + return rcode; +} /* end flash_real_protect() */ + +/*----------------------------------------------------------------------- + */ + diff --git a/board/w7o/fpga.c b/board/w7o/fpga.c new file mode 100644 index 0000000..e84123b --- /dev/null +++ b/board/w7o/fpga.c @@ -0,0 +1,380 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com + * and + * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <config.h> +#include <common.h> +#include "w7o.h" +#include <asm/processor.h> +#include "errors.h" + +static void +fpga_img_write(unsigned long *src, unsigned long len, unsigned short *daddr) +{ + unsigned long i; + volatile unsigned long val; + volatile unsigned short *dest = daddr; /* volatile-bypass optimizer */ + + for (i = 0; i < len; i++, src++) { + val = *src; + *dest = (unsigned short)((val & 0xff000000L) >> 16); + *dest = (unsigned short)((val & 0x00ff0000L) >> 8); + *dest = (unsigned short)(val & 0x0000ff00L); + *dest = (unsigned short)((val & 0x000000ffL) << 8); + } + + /* Terminate programming with 4 C clocks */ + dest = daddr; + val = *(unsigned short *)dest; + val = *(unsigned short *)dest; + val = *(unsigned short *)dest; + val = *(unsigned short *)dest; + +} + + +int +fpgaDownload(unsigned char *saddr, + unsigned long size, + unsigned short *daddr) +{ + int i; /* index, intr disable flag */ + int start; /* timer */ + unsigned long greg, grego; /* GPIO & output register */ + unsigned long length; /* image size in words */ + unsigned long *source; /* image source addr */ + unsigned short *dest; /* destination FPGA addr */ + volatile unsigned short *ndest; /* temp dest FPGA addr */ + volatile unsigned short val; /* temp val */ + unsigned long cnfg = GPIO_XCV_CNFG; /* FPGA CNFG */ + unsigned long eirq = GPIO_XCV_IRQ; + int retval = -1; /* Function return value */ + + /* Setup some basic values */ + length = (size / 4) + 1; /* size in words, rounding UP + is OK */ + source = (unsigned long *)saddr; + dest = (unsigned short *)daddr; + + /* Get DCR output register */ + grego = in32(IBM405GP_GPIO0_OR); + + /* Reset FPGA */ + grego &= ~GPIO_XCV_PROG; /* PROG line low */ + out32(IBM405GP_GPIO0_OR, grego); + + /* Setup timeout timer */ + start = get_timer(0); + + /* Wait for FPGA init line */ + while(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_INIT) { /* Wait INIT line low */ + /* Check for timeout - 100us max, so use 3ms */ + if (get_timer(start) > 3) { + printf(" failed to start init.\n"); + log_warn(ERR_XINIT0); /* Don't halt */ + + /* Reset line stays low */ + goto done; /* I like gotos... */ + } + } + + /* Unreset FPGA */ + grego |= GPIO_XCV_PROG; /* PROG line high */ + out32(IBM405GP_GPIO0_OR, grego); + + /* Wait for FPGA end of init period . */ + while(!(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_INIT)) { /* Wait for INIT hi */ + + /* Check for timeout */ + if (get_timer(start) > 3) { + printf(" failed to exit init.\n"); + log_warn(ERR_XINIT1); + + /* Reset FPGA */ + grego &= ~GPIO_XCV_PROG; /* PROG line low */ + out32(IBM405GP_GPIO0_OR, grego); + + goto done; + } + } + + /* Now program FPGA ... */ + ndest = dest; + for (i = 0; i < CONFIG_NUM_FPGAS; i++) { + /* Toggle IRQ/GPIO */ + greg = mfdcr(CPC0_CR0); /* get chip ctrl register */ + greg |= eirq; /* toggle irq/gpio */ + mtdcr(CPC0_CR0, greg); /* ... just do it */ + + /* turn on open drain for CNFG */ + greg = in32(IBM405GP_GPIO0_ODR); /* get open drain register */ + greg |= cnfg; /* CNFG open drain */ + out32(IBM405GP_GPIO0_ODR, greg); /* .. just do it */ + + /* Turn output enable on for CNFG */ + greg = in32(IBM405GP_GPIO0_TCR); /* get tristate register */ + greg |= cnfg; /* CNFG tristate inactive */ + out32(IBM405GP_GPIO0_TCR, greg); /* ... just do it */ + + /* Setup FPGA for programming */ + grego &= ~cnfg; /* CONFIG line low */ + out32(IBM405GP_GPIO0_OR, grego); + + /* + * Program the FPGA + */ + printf("\n destination: 0x%lx ", (unsigned long)ndest); + + fpga_img_write(source, length, (unsigned short *)ndest); + + /* Done programming */ + grego |= cnfg; /* CONFIG line high */ + out32(IBM405GP_GPIO0_OR, grego); + + /* Turn output enable OFF for CNFG */ + greg = in32(IBM405GP_GPIO0_TCR); /* get tristate register */ + greg &= ~cnfg; /* CNFG tristate inactive */ + out32(IBM405GP_GPIO0_TCR, greg); /* ... just do it */ + + /* Toggle IRQ/GPIO */ + greg = mfdcr(CPC0_CR0); /* get chip ctrl register */ + greg &= ~eirq; /* toggle irq/gpio */ + mtdcr(CPC0_CR0, greg); /* ... just do it */ + + ndest = (unsigned short *)((char *)ndest + 0x00100000L); /* XXX - Next FPGA addr */ + cnfg >>= 1; /* XXX - Next */ + eirq >>= 1; + } + + /* Terminate programming with 4 C clocks */ + ndest = dest; + for (i = 0; i < CONFIG_NUM_FPGAS; i++) { + val = *ndest; + val = *ndest; + val = *ndest; + val = *ndest; + ndest = (unsigned short *)((char *)ndest + 0x00100000L); + } + + /* Setup timer */ + start = get_timer(0); + + /* Wait for FPGA end of programming period . */ + while(!(in32(IBM405GP_GPIO0_IR) & GPIO_XCV_DONE)) { /* Test DONE low */ + + /* Check for timeout */ + if (get_timer(start) > 3) { + printf(" done failed to come high.\n"); + log_warn(ERR_XDONE1); + + /* Reset FPGA */ + grego &= ~GPIO_XCV_PROG; /* PROG line low */ + out32(IBM405GP_GPIO0_OR, grego); + + goto done; + } + } + + printf("\n FPGA load succeeded\n"); + retval = 0; /* Program OK */ + +done: + return retval; +} + +/* FPGA image is stored in flash */ +extern flash_info_t flash_info[]; + +int init_fpga(void) +{ + unsigned int i,j,ptr; /* General purpose */ + unsigned char bufchar; /* General purpose character */ + unsigned char *buf; /* Start of image pointer */ + unsigned long len; /* Length of image */ + unsigned char *fn_buf; /* Start of filename string */ + unsigned int fn_len; /* Length of filename string */ + unsigned char *xcv_buf; /* Pointer to start of image */ + unsigned long xcv_len; /* Length of image */ + unsigned long crc; /* 30bit crc in image */ + unsigned long calc_crc; /* Calc'd 30bit crc */ + int retval = -1; + + /* Tell the world what we are doing */ + printf("FPGA: "); + + /* + * Get address of first sector where the FPGA + * image is stored. + */ + buf = (unsigned char *)flash_info[1].start[0]; + + /* + * Get the stored image's CRC & length. + */ + crc = *(unsigned long *)(buf+4); /* CRC is first long word */ + len = *(unsigned long *)(buf+8); /* Image len is next long */ + + /* Pedantic */ + if ((len < 0x133A4) || (len > 0x80000)) + goto bad_image; + + /* + * Get the file name pointer and length. + */ + fn_len = (*(unsigned short *)(buf+12) & 0xff); /* filename length + is next short */ + fn_buf = buf + 14; + + /* + * Get the FPGA image pointer and length length. + */ + xcv_buf = fn_buf + fn_len; /* pointer to fpga image */ + xcv_len = len - 14 - fn_len; /* fpga image length */ + + /* Check for uninitialized FLASH */ + if ((strncmp(buf, "w7o", 3)!=0) || (len > 0x0007ffffL) || (len == 0)) + goto bad_image; + + /* + * Calculate and Check the image's CRC. + */ + calc_crc = crc32(0, xcv_buf, xcv_len); + if (crc != calc_crc) { + printf("\nfailed - bad CRC\n"); + goto done; + } + + /* Output the file name */ + printf("file name : "); + for (i=0;i<fn_len;i++) { + bufchar = fn_buf[+i]; + if (bufchar<' ' || bufchar>'~') bufchar = '.'; + putc(bufchar); + } + + /* + * find rest of display data + */ + ptr = 15; /* Offset to ncd filename + length in fpga image */ + j = xcv_buf[ptr]; /* Get len of ncd filename */ + if (j > 32) goto bad_image; + ptr = ptr + j + 3; /* skip ncd filename string + + 3 bytes more bytes */ + + /* + * output target device string + */ + j = xcv_buf[ptr++] - 1; /* len of targ str less term */ + if (j > 32) goto bad_image; + printf("\n target : "); + for (i = 0; i < j; i++) { + bufchar = (xcv_buf[ptr++]); + if (bufchar<' ' || bufchar>'~') bufchar = '.'; + putc(bufchar); + } + + /* + * output compilation date string and time string + */ + ptr += 3; /* skip 2 bytes */ + printf("\n synth time : "); + j = (xcv_buf[ptr++] - 1); /* len of date str less term */ + if (j > 32) goto bad_image; + for (i = 0; i < j; i++) { + bufchar = (xcv_buf[ptr++]); + if (bufchar<' ' || bufchar>'~') bufchar = '.'; + putc(bufchar); + } + + ptr += 3; /* Skip 2 bytes */ + printf(" - "); + j = (xcv_buf[ptr++] - 1); /* slen = targ dev str len */ + if (j > 32) goto bad_image; + for (i = 0; i < j; i++) { + bufchar = (xcv_buf[ptr++]); + if (bufchar<' ' || bufchar>'~') bufchar = '.'; + putc(bufchar); + } + + /* + * output crc and length strings + */ + printf("\n len & crc : 0x%lx 0x%lx", len, crc); + + /* + * Program the FPGA. + */ + retval = fpgaDownload((unsigned char*)xcv_buf, xcv_len, + (unsigned short *)0xfd000000L); + return retval; + +bad_image: + printf("\n BAD FPGA image format @ %lx\n", flash_info[1].start[0]); + log_warn(ERR_XIMAGE); +done: + return retval; +} + +void test_fpga(unsigned short *daddr) +{ + int i; + volatile unsigned short *ndest = daddr; + + for (i = 0; i < CONFIG_NUM_FPGAS; i++) { +#if defined(CONFIG_W7OLMG) + ndest[0x7e] = 0x55aa; + if (ndest[0x7e] != 0x55aa) + log_warn(ERR_XRW1 + i); + ndest[0x7e] = 0xaa55; + if (ndest[0x7e] != 0xaa55) + log_warn(ERR_XRW1 + i); + ndest[0x7e] = 0xc318; + if (ndest[0x7e] != 0xc318) + log_warn(ERR_XRW1 + i); + +#elif defined(CONFIG_W7OLMC) + ndest[0x800] = 0x55aa; + ndest[0x801] = 0xaa55; + ndest[0x802] = 0xc318; + ndest[0x4800] = 0x55aa; + ndest[0x4801] = 0xaa55; + ndest[0x4802] = 0xc318; + if ((ndest[0x800] != 0x55aa) || + (ndest[0x801] != 0xaa55) || + (ndest[0x802] != 0xc318)) + log_warn(ERR_XRW1 + (2 * i)); /* Auto gen error code */ + if ((ndest[0x4800] != 0x55aa) || + (ndest[0x4801] != 0xaa55) || + (ndest[0x4802] != 0xc318)) + log_warn(ERR_XRW2 + (2 * i)); /* Auto gen error code */ + +#else +# error "Unknown W7O board configuration" +#endif + } + + printf(" FPGA ready\n"); + return; +} + diff --git a/board/w7o/init.S b/board/w7o/init.S new file mode 100644 index 0000000..0abf21f --- /dev/null +++ b/board/w7o/init.S @@ -0,0 +1,264 @@ +/****************************************************************************** + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + * + *****************************************************************************/ +#include <config.h> +#include <ppc4xx.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +/****************************************************************************** + * Function: ext_bus_cntlr_init + * + * Description: Configures EBC Controller and a few basic chip selects. + * + * CS0 is setup to get the Boot Flash out of the addresss range + * so that we may setup a stack. CS7 is setup so that we can + * access and reset the hardware watchdog. + * + * IMPORTANT: For pass1 this code must run from + * cache since you can not reliably change a peripheral banks + * timing register (pbxap) while running code from that bank. + * For ex., since we are running from ROM on bank 0, we can NOT + * execute the code that modifies bank 0 timings from ROM, so + * we run it from cache. + * + * Notes: Does NOT use the stack. + *****************************************************************************/ + .section ".text" + .align 2 + .globl ext_bus_cntlr_init + .type ext_bus_cntlr_init, @function +ext_bus_cntlr_init: + mflr r0 + /******************************************************************** + * Prefetch entire ext_bus_cntrl_init function into the icache. + * This is necessary because we are going to change the same CS we + * are executing from. Otherwise a CPU lockup may occur. + *******************************************************************/ + bl ..getAddr +..getAddr: + mflr r3 /* get address of ..getAddr */ + + /* Calculate number of cache lines for this function */ + addi r4, 0, (((.Lfe0 - ..getAddr) / CFG_CACHELINE_SIZE) + 2) + mtctr r4 +..ebcloop: + icbt r0, r3 /* prefetch cache line for addr in r3*/ + addi r3, r3, CFG_CACHELINE_SIZE /* move to next cache line */ + bdnz ..ebcloop /* continue for $CTR cache lines */ + + /******************************************************************** + * Delay to ensure all accesses to ROM are complete before changing + * bank 0 timings. 200usec should be enough. + * 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles. + *******************************************************************/ + addis r3, 0, 0x0 + ori r3, r3, 0xA000 /* wait 200us from reset */ + mtctr r3 +..spinlp: + bdnz ..spinlp /* spin loop */ + + /******************************************************************** + * Setup External Bus Controller (EBC). + *******************************************************************/ + addi r3, 0, epcr + mtdcr ebccfga, r3 + addis r4, 0, 0xb040 /* Device base timeout = 1024 cycles */ + ori r4, r4, 0x0 /* Drive CS with external master */ + mtdcr ebccfgd, r4 + + /******************************************************************** + * Change PCIINT signal to PerWE + *******************************************************************/ + mfdcr r4, cntrl1 + ori r4, r4, 0x4000 + mtdcr cntrl1, r4 + + /******************************************************************** + * Memory Bank 0 (Flash Bank 0) initialization + *******************************************************************/ + addi r3, 0, pb0ap + mtdcr ebccfga, r3 + addis r4, 0, CFG_W7O_EBC_PB0AP@h + ori r4, r4, CFG_W7O_EBC_PB0AP@l + mtdcr ebccfgd, r4 + + addi r3, 0, pb0cr + mtdcr ebccfga, r3 + addis r4, 0, CFG_W7O_EBC_PB0CR@h + ori r4, r4, CFG_W7O_EBC_PB0CR@l + mtdcr ebccfgd, r4 + + /******************************************************************** + * Memory Bank 7 LEDs - NEEDED BECAUSE OF HW WATCHDOG AND LEDs. + *******************************************************************/ + addi r3, 0, pb7ap + mtdcr ebccfga, r3 + addis r4, 0, CFG_W7O_EBC_PB7AP@h + ori r4, r4, CFG_W7O_EBC_PB7AP@l + mtdcr ebccfgd, r4 + + addi r3, 0, pb7cr + mtdcr ebccfga, r3 + addis r4, 0, CFG_W7O_EBC_PB7CR@h + ori r4, r4, CFG_W7O_EBC_PB7CR@l + mtdcr ebccfgd, r4 + + /* We are all done */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ +.Lfe0: .size ext_bus_cntlr_init,.Lfe0-ext_bus_cntlr_init +/* end ext_bus_cntlr_init() */ + +/****************************************************************************** + * Function: sdram_init + * + * Description: Configures SDRAM memory banks. + * + * Serial Presence Detect, "SPD," reads the SDRAM EEPROM + * via the IIC bus and then configures the SDRAM memory + * banks appropriately. If Auto Memory Configuration is + * is not used, it is assumed that a 4MB 11x8x2, non-ECC, + * SDRAM is soldered down. + * + * Notes: Expects that the stack is already setup. + *****************************************************************************/ + .section ".text" + .align 2 + .globl sdram_init + .type sdram_init, @function +sdram_init: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save link register */ + + /* + * First call spd_sdram to try to init SDRAM according to the + * contents of the SPD EEPROM. If the SPD EEPROM is blank or + * erronious, spd_sdram returns 0 in R3. + */ + bl spd_sdram + addic. r3, r3, 0 /* Check for error, save dram size */ + bne ..sdri_done /* If it worked, we're done... */ + + /******************************************************************** + * If SPD detection fails, we'll default to 4MB, 11x8x2, as this + * is the SMALLEST SDRAM size the 405 supports. We can do this + * because W7O boards have soldered on RAM, and there will always + * be some amount present. If we were using DIMMs, we should hang + * the board instead, since it doesn't have any RAM to continue + * running with. + *******************************************************************/ + + /* + * Disable memory controller to allow + * values to be changed. + */ + addi r3, 0, mem_mcopt1 + mtdcr memcfga, r3 + addis r4, 0, 0x0 + ori r4, r4, 0x0 + mtdcr memcfgd, r4 + + /* + * Set MB0CF for ext bank 0. (0-4MB) Address Mode 5 since 11x8x2 + * All other banks are disabled. + */ + addi r3, 0, mem_mb0cf + mtdcr memcfga, r3 + addis r4, 0, 0x0000 /* BA=0x0, SZ=4MB */ + ori r4, r4, 0x8001 /* Mode is 5, 11x8x2or4, BE=Enabled */ + mtdcr memcfgd, r4 + + /* Clear MB1CR,MB2CR,MB3CR to turn other banks off */ + addi r4, 0, 0 /* Zero the data reg */ + + addi r3, r3, 4 /* Point to MB1CF reg */ + mtdcr memcfga, r3 /* Set the address */ + mtdcr memcfgd, r4 /* Zero the reg */ + + addi r3, r3, 4 /* Point to MB2CF reg */ + mtdcr memcfga, r3 /* Set the address */ + mtdcr memcfgd, r4 /* Zero the reg */ + + addi r3, r3, 4 /* Point to MB3CF reg */ + mtdcr memcfga, r3 /* Set the address */ + mtdcr memcfgd, r4 /* Zero the reg */ + + /******************************************************************** + * Set the SDRAM Timing reg, SDTR1 and the refresh timer reg, RTR. + * To set the appropriate timings, we assume sdram is + * 100MHz (pc100 compliant). + *******************************************************************/ + + /* + * Set up SDTR1 + */ + addi r3, 0, mem_sdtr1 + mtdcr memcfga, r3 + addis r4, 0, 0x0086 /* SDTR1 value for 100Mhz */ + ori r4, r4, 0x400D + mtdcr memcfgd, r4 + + /* + * Set RTR + */ + addi r3, 0, mem_rtr + mtdcr memcfga, r3 + addis r4, 0, 0x05F0 /* RTR refresh val = 15.625ms@100Mhz */ + mtdcr memcfgd, r4 + + /******************************************************************** + * Delay to ensure 200usec have elapsed since reset. Assume worst + * case that the core is running 200Mhz: + * 200,000,000 (cycles/sec) X .000200 (sec) = 0x9C40 cycles + *******************************************************************/ + addis r3, 0, 0x0000 + ori r3, r3, 0xA000 /* Wait 200us from reset */ + mtctr r3 +..spinlp2: + bdnz ..spinlp2 /* spin loop */ + + /******************************************************************** + * Set memory controller options reg, MCOPT1. + *******************************************************************/ + addi r3, 0, mem_mcopt1 + mtdcr memcfga, r3 + addis r4, 0, 0x80E0 /* DC_EN=1,SRE=0,PME=0,MEMCHK=0 */ + ori r4, r4, 0x0000 /* REGEN=0,DRW=00,BRPF=01,ECCDD=1 */ + mtdcr memcfgd, r4 /* EMDULR=1 */ + +..sdri_done: + /* restore and return */ + lwz r0, +12(r1) /* Get saved link register */ + addi r1, r1, +8 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ +.Lfe1: .size sdram_init,.Lfe1-sdram_init +/* end sdram_init() */ + diff --git a/board/w7o/post1.S b/board/w7o/post1.S new file mode 100644 index 0000000..d510cca --- /dev/null +++ b/board/w7o/post1.S @@ -0,0 +1,745 @@ +/* + * (C) Copyright 2001 + * Bill Hunter, Wave 7 Optics, william.hunter@mediaone.net + * and + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 + */ +/* + * Description: + * Routine to exercise memory for the bringing up of our boards. + */ +#include <config.h> +#include <ppc4xx.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#include <watchdog.h> + +#include "errors.h" + +#define _ASMLANGUAGE + + .globl test_sdram + .globl test_led + .globl log_stat + .globl log_warn + .globl log_err + .globl temp_uart_init + .globl post_puts + .globl disp_hex + +/***************************************************** +******* Text Strings for low level printing ****** +******* In section got2 ******* +*****************************************************/ + +/* + * Define the text strings for errors and warnings. + * Switch to .data section. + */ + .section ".data" +err_str: .asciz "*** POST ERROR = " +warn_str: .asciz "*** POST WARNING = " +end_str: .asciz "\r\n" + +/* + * Enter the labels in Global Entry Table (GOT). + * Switch to .got2 section. + */ + START_GOT + GOT_ENTRY(err_str) + GOT_ENTRY(warn_str) + GOT_ENTRY(end_str) + END_GOT + +/* + * Switch back to .text section. + */ + .text + +/**************************************** + **************************************** + ******** LED register test ******** + **************************************** + ***************************************/ +test_led: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r4, +8(r1) /* save R4 */ + + WATCHDOG_RESET /* Reset the watchdog */ + + addi r3, 0, ERR_FF /* first test value is ffff */ + addi r4, r3, 0 /* save copy of pattern */ + bl set_led /* store first test value */ + bl get_led /* read it back */ + xor. r4, r4, r3 /* compare to original */ +#if defined(CONFIG_W7OLMC) + andi. r4, r4, 0x00ff /* lmc has 8 bits */ +#else + andi. r4, r4, 0xffff /* lmg has 16 bits */ +#endif + beq LED2 /* next test */ + addi r3, 0, ERR_LED /* error code = 1 */ + bl log_err /* display error and halt */ +LED2: addi r3, 0, ERR_00 /* 2nd test value is 0000 */ + addi r4, r3, 0 /* save copy of pattern */ + bl set_led /* store first test value */ + bl get_led /* read it back */ + xor. r4, r4, r3 /* compare to original */ +#if defined(CONFIG_W7OLMC) + andi. r4, r4, 0x00ff /* lmc has 8 bits */ +#else + andi. r4, r4, 0xffff /* lmg has 16 bits */ +#endif + beq LED3 /* next test */ + addi r3, 0, ERR_LED /* error code = 1 */ + bl log_err /* display error and halt */ + +LED3: /* restore stack and return */ + lwz r0, +16(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + lwz r4, +8(r1) /* restore r4 */ + addi r1, r1, +12 /* Remove frame from stack */ + blr /* Return to calling function */ + +/**************************************** + **************************************** + ******** SDRAM TESTS ******** + **************************************** + ***************************************/ +test_sdram: + /* called with mem size in r3 */ + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -16(r1) /* Save back chain and move SP */ + stw r0, +20(r1) /* Save link register */ + stmw r30, +8(r1) /* save R30,R31 */ + /* r30 is log2(mem size) */ + /* r31 is mem size */ + + /* take log2 of total mem size */ + addi r31, r3, 0 /* save total mem size */ + addi r30, 0, 0 /* clear r30 */ +l2_loop: + srwi. r31, r31, 1 /* shift right 1 */ + addi r30, r30, 1 /* count shifts */ + bne l2_loop /* loop till done */ + addi r30, r30, -1 /* correct for over count */ + addi r31, r3, 0 /* save original size */ + + /* now kick the dog and test the mem */ + WATCHDOG_RESET /* Reset the watchdog */ + bl Data_Buster /* test crossed/shorted data lines */ + addi r3, r30, 0 /* get log2(memsize) */ + addi r4, r31, 0 /* get memsize */ + bl Ghost_Buster /* test crossed/shorted addr lines */ + addi r3, r31, 0 /* get mem size */ + bl Bit_Buster /* check for bad internal bits */ + + /* restore stack and return */ + lmw r30, +8(r1) /* Restore r30, r31 */ + lwz r0, +20(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + addi r1, r1, +16 /* Remove frame from stack */ + blr /* Return to calling function */ + + +/**************************************** + ******** sdram data bus test ******** + ***************************************/ +Data_Buster: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -24(r1) /* Save back chain and move SP */ + stw r0, +28(r1) /* Save link register */ + stmw r28, 8(r1) /* save r28 - r31 on stack */ + /* r31 i/o register */ + /* r30 sdram base address */ + /* r29 5555 syndrom */ + /* r28 aaaa syndrom */ + + /* set up led register for this test */ + addi r3, 0, ERR_RAMG /* set led code to 1 */ + bl log_stat /* store test value */ + /* now test the dram data bus */ + xor r30, r30, r30 /* load r30 with base addr of sdram */ + addis r31, 0, 0x5555 /* load r31 with test value */ + ori r31, r31, 0x5555 + stw r31,0(r30) /* sto the value */ + lwz r29,0(r30) /* read it back */ + xor r29,r31,r29 /* compare it to original */ + addis r31, 0, 0xaaaa /* load r31 with test value */ + ori r31, r31, 0xaaaa + stw r31,0(r30) /* sto the value */ + lwz r28,0(r30) /* read it back */ + xor r28,r31,r28 /* compare it to original */ + or r3,r28,r29 /* or together both error terms */ + /* + * Now that we have the error bits, + * we have to decide which part they are in. + */ + bl get_idx /* r5 is now index to error */ + addi r3, r3, ERR_RAMG + cmpwi r3, ERR_RAMG /* check for errors */ + beq db_done /* skip if no errors */ + bl log_err /* log the error */ + +db_done: + lmw r28, 8(r1) /* restore r28 - r31 from stack */ + lwz r0, +28(r1) /* Get saved link register */ + addi r1, r1, +24 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + + +/**************************************************** + ******** test for address ghosting in dram ******** + ***************************************************/ + +Ghost_Buster: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -36(r1) /* Save back chain and move SP */ + stw r0, +40(r1) /* Save link register */ + stmw r25, 8(r1) /* save r25 - r31 on stack */ + /* r31 = scratch register */ + /* r30 is main referance loop counter, + 0 to 23 */ + /* r29 is ghost loop count, 0 to 22 */ + /* r28 is referance address */ + /* r27 is ghost address */ + /* r26 is log2 (mem size) = + number of byte addr bits */ + /* r25 is mem size */ + + /* save the log2(mem size) and mem size */ + addi r26, r3, 0 /* r26 is number of byte addr bits */ + addi r25, r4, 0 /* r25 is mem size in bytes */ + + /* set the leds for address ghost test */ + addi r3, 0, ERR_ADDG + bl set_led + + /* first fill memory with zeros */ + srwi r31, r25, 2 /* convert bytes to longs */ + mtctr r31 /* setup byte counter */ + addi r28, 0, 0 /* start at address at 0 */ + addi r31, 0, 0 /* data value = 0 */ +clr_loop: + stw r31, 0(r28) /* Store zero value */ + addi r28, r28, 4 /* Increment to next word */ + andi. r27, r28, 0xffff /* check for 2^16 loops */ + bne clr_skip /* if not there, then skip */ + WATCHDOG_RESET /* kick the dog every now and then */ +clr_skip: + bdnz clr_loop /* Round and round... */ + + /* now do main test */ + addi r30, 0, 0 /* start referance counter at 0 */ +outside: + /* + * Calculate the referance address + * the referance address is calculated by setting the (r30-1) + * bit of the base address + * when r30=0, the referance address is the base address. + * thus the sequence 0,1,2,4,8,..,2^(n-1) + * setting the bit is done with the following shift functions. + */ + WATCHDOG_RESET /* Reset the watchdog */ + + addi r31, 0, 1 /* r31 = 1 */ + slw r28, r31, r30 /* set bit coresponding to loop cnt */ + srwi r28, r28, 1 /* then shift it right one so */ + /* we start at location 0 */ + /* fill referance address with Fs */ + addi r31, 0, 0x00ff /* r31 = one byte of set bits */ + stb r31,0(r28) /* save ff in referance address */ + + /* ghost (inner) loop, now check all posible ghosted addresses */ + addi r29, 0, 0 /* start ghosted loop counter at 0 */ +inside: + /* + * Calculate the ghost address by flipping one + * bit of referance address. This gives the + * sequence 1,2,4,8,...,2^(n-1) + */ + addi r31, 0, 1 /* r31 = 1 */ + slw r27, r31, r29 /* set bit coresponding to loop cnt */ + xor r27, r28, r27 /* ghost address = ref addr with + bit flipped*/ + + /* now check for ghosting */ + lbz r31,0(r27) /* get content of ghost addr */ + cmpwi r31, 0 /* compare read value to 0 */ + bne Casper /* we found a ghost! */ + + /* now close ghost ( inner ) loop */ + addi r29, r29, 1 /* increment inner loop counter */ + cmpw r29, r26 /* check for last inner loop */ + blt inside /* do more inner loops */ + + /* now close referance ( outer ) loop */ + addi r31, 0, 0 /* r31 = zero */ + stb r31, 0(28) /* zero out the altered address loc. */ + /* + * Increment and check for end, count is zero based. + * With the ble, this gives us one more loops than + * address bits for sequence 0,1,2,4,8,...2^(n-1) + */ + addi r30, r30, 1 /* increment outer loop counter */ + cmpw r30, r26 /* check for last inner loop */ + ble outside /* do more outer loops */ + + /* were done, lets go home */ + b gb_done +Casper: /* we found a ghost !! */ + addi r3, 0, ERR_ADDF /* get indexed error message */ + bl log_err /* log error led error code */ +gb_done: /* pack your bags, and go home */ + lmw r25, 8(r1) /* restore r25 - r31 from stack */ + lwz r0, +40(r1) /* Get saved link register */ + addi r1, r1, +36 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + +/**************************************************** + ******** SDRAM data fill tests ********** + ***************************************************/ +Bit_Buster: + /* called with mem size in r3 */ + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -16(r1) /* Save back chain and move SP */ + stw r0, +20(r1) /* Save link register */ + stw r4, +8(r1) /* save R4 */ + stw r5, +12(r1) /* save r5 */ + + addis r5, r3, 0 /* save mem size */ + + /* Test 55555555 */ + addi r3, 0, ERR_R55G /* set up error code in case we fail */ + bl log_stat /* store test value */ + addis r4, 0, 0x5555 + ori r4, r4, 0x5555 + bl fill_test + + /* Test aaaaaaaa */ + addi r3, 0, ERR_RAAG /* set up error code in case we fail */ + bl log_stat /* store test value */ + addis r4, 0, 0xAAAA + ori r4, r4, 0xAAAA + bl fill_test + + /* Test 00000000 */ + addi r3, 0, ERR_R00G /* set up error code in case we fail */ + bl log_stat /* store test value */ + addis r4, 0, 0 + ori r4, r4, 0 + bl fill_test + + /* restore stack and return */ + lwz r5, +12(r1) /* restore r4 */ + lwz r4, +8(r1) /* restore r4 */ + lwz r0, +20(r1) /* Get saved link register */ + addi r1, r1, +16 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + + + +/**************************************************** + ******** fill test ******** + ***************************************************/ +/* tests memory by filling with value, and reading back */ +/* r5 = Size of memory in bytes */ +/* r4 = Value to write */ +/* r3 = Error code */ +fill_test: + mflr r0 /* Get link register */ + stwu r1, -32(r1) /* Save back chain and move SP */ + stw r0, +36(r1) /* Save link register */ + stmw r27, 8(r1) /* save r27 - r31 on stack */ + /* r31 - scratch register */ + /* r30 - memory address */ + mr r27, r3 + mr r28, r4 + mr r29, r5 + + WATCHDOG_RESET /* Reset the watchdog */ + + /* first fill memory with Value */ + srawi r31, r29, 2 /* convert bytes to longs */ + mtctr r31 /* setup counter */ + addi r30, 0, 0 /* Make r30 = addr 0 */ +ft_0: stw r28, 0(r30) /* Store value */ + addi r30, r30, 4 /* Increment to next word */ + andi. r31, r30, 0xffff /* check for 2^16 loops */ + bne ft_0a /* if not there, then skip */ + WATCHDOG_RESET /* kick the dog every now and then */ +ft_0a: bdnz ft_0 /* Round and round... */ + + WATCHDOG_RESET /* Reset the watchdog */ + + /* Now confirm Value is in memory */ + srawi r31, r29, 2 /* convert bytes to longs */ + mtctr r31 /* setup counter */ + addi r30, 0, 0 /* Make r30 = addr 0 */ +ft_1: lwz r31, 0(r30) /* get value from memory */ + xor. r31, r31, r28 /* Writen = Read ? */ + bne ft_err /* If bad, than halt */ + addi r30, r30, 4 /* Increment to next word */ + andi. r31, r30, 0xffff /* check for 2^16 loops*/ + bne ft_1a /* if not there, then skip */ + WATCHDOG_RESET /* kick the dog every now and then */ +ft_1a: bdnz ft_1 /* Round and round... */ + + WATCHDOG_RESET /* Reset the watchdog */ + + b fill_done /* restore and return */ + +ft_err: addi r29, r27, 0 /* save current led code */ + addi r27, r31, 0 /* get pattern in r27 */ + bl get_idx /* get index from r27 */ + add r27, r27, r29 /* add index to old led code */ + bl log_err /* output led err code, halt CPU */ + +fill_done: + lmw r27, 8(r1) /* restore r27 - r31 from stack */ + lwz r0, +36(r1) /* Get saved link register */ + addi r1, r1, +32 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + + +/**************************************************** + ******* get error index from r3 pattern ******** + ***************************************************/ +get_idx: /* r3 = (MSW(r3) !=0)*2 + + (LSW(r3) !=0) */ + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r4, +8(r1) /* save R4 */ + + andi. r4, r3, 0xffff /* check for lower bits */ + beq gi2 /* skip if no bits set */ + andis. r4, r3, 0xffff /* check for upper bits */ + beq gi3 /* skip if no bits set */ + addi r3, 0, 3 /* both upper and lower bits set */ + b gi_done +gi2: andis. r4, r3, 0xffff /* check for upper bits*/ + beq gi4 /* skip if no bits set */ + addi r3, 0, 2 /* only upper bits set */ + b gi_done +gi3: addi r3, 0, 1 /* only lower bits set */ + b gi_done +gi4: addi r3, 0, 0 /* no bits set */ +gi_done: + /* restore stack and return */ + lwz r0, +16(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + lwz r4, +8(r1) /* restore r4 */ + addi r1, r1, +12 /* Remove frame from stack */ + blr /* Return to calling function */ + +/**************************************************** + ******** set LED to R5 and hang ******** + ***************************************************/ +log_stat: /* output a led code and continue */ +set_led: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r4, +8(r1) /* save R4 */ + + addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */ +#if defined(CONFIG_W7OLMG) /* only on gateway, invert outputs */ + xori r3,r3, 0xffff /* complement led code, active low */ + sth r3, 0(r4) /* store first test value */ + xori r3,r3, 0xffff /* complement led code, active low */ +#else /* if not gateway, then don't invert */ + sth r3, 0(r4) /* store first test value */ +#endif + + /* restore stack and return */ + lwz r0, +16(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + lwz r4, +8(r1) /* restore r4 */ + addi r1, r1, +12 /* Remove frame from stack */ + blr /* Return to calling function */ + +get_led: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r4, +8(r1) /* save R4 */ + + addis r4, 0, 0xfe00 /* LED buffer is at 0xfe000000 */ + lhz r3, 0(r4) /* store first test value */ +#if defined(CONFIG_W7OLMG) /* only on gateway, invert inputs */ + xori r3,r3, 0xffff /* complement led code, active low */ +#endif + + /* restore stack and return */ + lwz r0, +16(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + lwz r4, +8(r1) /* restore r4 */ + addi r1, r1, +12 /* Remove frame from stack */ + blr /* Return to calling function */ + +log_err: /* output the error and hang the board ( for now ) */ + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r3, +8(r1) /* save a copy of error code */ + bl set_led /* set the led pattern */ + GET_GOT /* get GOT address in r14 */ + lwz r3,GOT(err_str) /* get address of string */ + bl post_puts /* output the warning string */ + lwz r3, +8(r1) /* get error code */ + addi r4, 0, 2 /* set disp length to 2 nibbles */ + bl disp_hex /* output the error code */ + lwz r3,GOT(end_str) /* get address of string */ + bl post_puts /* output the warning string */ +halt: + b halt /* hang */ + + /* restore stack and return */ + lwz r0, +16(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + addi r1, r1, +12 /* Remove frame from stack */ + blr /* Return to calling function */ + +log_warn: /* output a warning, then continue with operations */ + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -16(r1) /* Save back chain and move SP */ + stw r0, +20(r1) /* Save link register */ + stw r3, +8(r1) /* save a copy of error code */ + stw r14, +12(r1) /* save a copy of r14 (used by GOT) */ + + bl set_led /* set the led pattern */ + GET_GOT /* get GOT address in r14 */ + lwz r3,GOT(warn_str) /* get address of string */ + bl post_puts /* output the warning string */ + lwz r3, +8(r1) /* get error code */ + addi r4, 0, 2 /* set disp length to 2 nibbles */ + bl disp_hex /* output the error code */ + lwz r3,GOT(end_str) /* get address of string */ + bl post_puts /* output the warning string */ + + addis r3, 0, 64 /* has a long delay */ + mtctr r3 +log_2: + WATCHDOG_RESET /* this keeps dog from barking, */ + /* and takes time */ + bdnz log_2 /* loop till time expires */ + + /* restore stack and return */ + lwz r0, +20(r1) /* Get saved link register */ + lwz r14, +12(r1) /* restore r14 */ + mtlr r0 /* Restore link register */ + addi r1, r1, +16 /* Remove frame from stack */ + blr /* Return to calling function */ + +/******************************************************************* + * temp_uart_init + * Temporary UART initialization routine + * Sets up UART0 to run at 9600N81 off of the internal clock. + * R3-R4 are used. + ******************************************************************/ +temp_uart_init: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -8(r1) /* Save back chain and move SP */ + stw r0, +12(r1) /* Save link register */ + + addis r3, 0, 0xef60 + ori r3, r3, 0x0303 /* r3 = UART0_LCR */ + addi r4, 0, 0x83 /* n81 format, divisor regs enabled */ + stb r4, 0(r3) + + /* set baud rate to use internal clock, + baud = (200e6/16)/31/42 = 9600 */ + + addis r3, 0, 0xef60 /* Address of baud divisor reg */ + ori r3, r3, 0x0300 /* UART0_DLM */ + addi r4, 0, +42 /* uart baud divisor LSB = 93 */ + stb r4, 0(r3) /* baud = (200 /16)/14/93 */ + + addi r3, r3, 0x0001 /* uart baud divisor addr */ + addi r4, 0, 0 + stb r4, 0(r3) /* Divisor Latch MSB = 0 */ + + addis r3, 0, 0xef60 + ori r3, r3, 0x0303 /* r3 = UART0_LCR */ + addi r4, 0, 0x03 /* n81 format, tx/rx regs enabled */ + stb r4, 0(r3) + + /* output a few line feeds */ + addi r3, 0, '\n' /* load line feed */ + bl post_putc /* output the char */ + addi r3, 0, '\n' /* load line feed */ + bl post_putc /* output the char */ + + /* restore stack and return */ + lwz r0, +12(r1) /* Get saved link register */ + mtlr r0 /* Restore link register */ + addi r1, r1, +8 /* Remove frame from stack */ + blr /* Return to calling function */ + +/********************************************************************** + ** post_putc + ** outputs charactor in R3 + ** r3 returns the error code ( -1 if there is an error ) + *********************************************************************/ + +post_putc: + + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -20(r1) /* Save back chain and move SP */ + stw r0, +24(r1) /* Save link register */ + stmw r29, 8(r1) /* save r29 - r31 on stack + r31 - uart base address + r30 - delay counter + r29 - scratch reg */ + + addis r31, 0, 0xef60 /* Point to uart base */ + ori r31, r31, 0x0300 + addis r30, 0, 152 /* Load about 10,000,000 ticks. */ +pputc_lp: + lbz r29, 5(r31) /* Read Line Status Register */ + andi. r29, r29, 0x20 /* Check THRE status */ + bne thre_set /* Branch if FIFO empty */ + addic. r30, r30, -1 /* Decrement and check if empty. */ + bne pputc_lp /* Try, try again */ + addi r3, 0, -1 /* Load error code for timeout */ + b pputc_done /* Bail out with error code set */ +thre_set: + stb r3, 0(r31) /* Store character to UART */ + addi r3, 0, 0 /* clear error code */ +pputc_done: + lmw r29, 8(r1) /*restore r29 - r31 from stack */ + lwz r0, +24(r1) /* Get saved link register */ + addi r1, r1, +20 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + + +/**************************************************************** + post_puts + Accepts a null-terminated string pointed to by R3 + Outputs to the serial port until 0x00 is found. + r3 returns the error code ( -1 if there is an error ) +*****************************************************************/ +post_puts: + + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -12(r1) /* Save back chain and move SP */ + stw r0, +16(r1) /* Save link register */ + stw r31, 8(r1) /* save r31 - char pointer */ + + addi r31, r3, 0 /* move pointer to R31 */ +pputs_nxt: + lbz r3, 0(r31) /* Get next character */ + addic. r3, r3, 0 /* Check for zero */ + beq pputs_term /* bail out if zero */ + bl post_putc /* output the char */ + addic. r3, r3, 0 /* check for error */ + bne pputs_err + addi r31, r31, 1 /* point to next char */ + b pputs_nxt /* loop till term */ +pputs_err: + addi r3, 0, -1 /* set error code */ + b pputs_end /* were outa here */ +pputs_term: + addi r3, 0, 1 /* set success code */ + /* restore stack and return */ +pputs_end: + lwz r31, 8(r1) /* restore r27 - r31 from stack */ + lwz r0, +16(r1) /* Get saved link register */ + addi r1, r1, +12 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + + + +/******************************************************************** + ***** disp_hex + ***** Routine to display a hex value from a register. + ***** R3 is value to display + ***** R4 is number of nibbles to display ie 2 for byte 8 for (long)word + ***** Returns -1 in R3 if there is an error ( ie serial port hangs ) + ***** Returns 0 in R3 if no error + *******************************************************************/ +disp_hex: + /* save the return info on stack */ + mflr r0 /* Get link register */ + stwu r1, -16(r1) /* Save back chain and move SP */ + stw r0, +20(r1) /* Save link register */ + stmw r30, 8(r1) /* save r30 - r31 on stack */ + /* r31 output char */ + /* r30 uart base address */ + addi r30, 0, 8 /* Go through 8 nibbles. */ + addi r31, r3, 0 +pputh_nxt: + rlwinm r31, r31, 4, 0, 31 /* Rotate next nibble into position */ + andi. r3, r31, 0x0f /* Get nibble. */ + addi r3, r3, 0x30 /* Add zero's ASCII code. */ + cmpwi r3, 0x03a + blt pputh_out + addi r3, r3, 0x07 /* 0x27 for lower case. */ +pputh_out: + cmpw r30, r4 + bgt pputh_skip + bl post_putc + addic. r3, r3, 0 /* check for error */ + bne pputh_err +pputh_skip: + addic. r30, r30, -1 + bne pputh_nxt + xor r3, r3, r3 /* Clear error code */ + b pputh_done +pputh_err: + addi r3, 0, -1 /* set error code */ +pputh_done: + /* restore stack and return */ + lmw r30, 8(r1) /* restore r30 - r31 from stack */ + lwz r0, +20(r1) /* Get saved link register */ + addi r1, r1, +16 /* Remove frame from stack */ + mtlr r0 /* Restore link register */ + blr /* Return to calling function */ + diff --git a/board/w7o/post2.c b/board/w7o/post2.c new file mode 100644 index 0000000..271c197 --- /dev/null +++ b/board/w7o/post2.c @@ -0,0 +1,109 @@ +/* + * (C) Copyright 2001 + * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net + * and + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <config.h> +#include <rtc.h> +#include "errors.h" +#include "dtt.h" + +#if defined(CONFIG_RTC_M48T35A) +void rtctest(void) +{ + volatile uchar *tchar = (uchar*)(CFG_NVRAM_BASE_ADDR + CFG_NVRAM_SIZE - 9); + struct rtc_time tmp; + + /* set up led code for RTC tests */ + log_stat(ERR_RTCG); + + /* + * Do RTC battery test. The first write after power up + * fails if battery is low. + */ + *tchar = 0xaa; + if ((*tchar ^ 0xaa) != 0x0) log_warn(ERR_RTCBAT); + *tchar = 0x55; /* Reset test address */ + + /* + * Now lets check the validity of the values in the RTC. + */ + rtc_get(&tmp); + if ((tmp.tm_sec < 0) | (tmp.tm_sec > 59) | + (tmp.tm_min < 0) | (tmp.tm_min > 59) | + (tmp.tm_hour < 0) | (tmp.tm_hour > 23) | + (tmp.tm_mday < 1 ) | (tmp.tm_mday > 31) | + (tmp.tm_mon < 1 ) | (tmp.tm_mon > 12) | + (tmp.tm_year < 2000) | (tmp.tm_year > 2500) | + (tmp.tm_wday < 1 ) | (tmp.tm_wday > 7)) { + log_warn(ERR_RTCTIM); + rtc_reset(); + } + + /* + * Now lets do a check to see if the NV RAM is there. + */ + *tchar = 0xaa; + if ((*tchar ^ 0xaa) != 0x0) log_err(ERR_RTCVAL); + *tchar = 0x55; /* Reset test address */ + +} /* rtctest() */ +#endif /* CONFIG_RTC_M48T35A */ + + +#ifdef CONFIG_DTT_LM75 +int dtt_test(int sensor) +{ + short temp, trip, hyst; + + /* get values */ + temp = dtt_read(sensor, DTT_READ_TEMP) / 256; + trip = dtt_read(sensor, DTT_TEMP_SET) / 256; + hyst = dtt_read(sensor, DTT_TEMP_HYST) / 256; + + /* check values */ + if ((hyst != (CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS)) || + (trip != CFG_DTT_MAX_TEMP) || + (temp < CFG_DTT_LOW_TEMP) || (temp > CFG_DTT_MAX_TEMP)) + return 1; + + return 0; +} /* dtt_test() */ +#endif /* CONFIG_DTT_LM75 */ + +/*****************************************/ + +void post2(void) +{ +#if defined(CONFIG_RTC_M48T35A) + rtctest(); +#endif /* CONFIG_RTC_M48T35A */ + +#ifdef CONFIG_DTT_LM75 + log_stat(ERR_TempG); + if(dtt_test(2) != 0) log_warn(ERR_Ttest0); + if(dtt_test(4) != 0) log_warn(ERR_Ttest1); +#endif /* CONFIG_DTT_LM75 */ +} /* post2() */ + diff --git a/board/w7o/vpd.c b/board/w7o/vpd.c new file mode 100644 index 0000000..c24b127 --- /dev/null +++ b/board/w7o/vpd.c @@ -0,0 +1,408 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 + */ + +#if defined(VXWORKS) +# include <stdio.h> +# include <string.h> +# define CFG_DEF_EEPROM_ADDR 0xa0 +extern char iicReadByte( char, char ); +extern ulong_t crc32( unsigned char *, unsigned long ); +#else +#include <common.h> +#endif + +#include "vpd.h" + +/* + * vpd_reader() - reads VPD data from I2C EEPROMS. + * returns pointer to buffer or NULL. + */ +static unsigned char * +vpd_reader(unsigned char *buf, unsigned dev_addr, unsigned off, unsigned count) +{ + unsigned offset = off; /* Calculated offset */ + + /* + * The main board EEPROM contains + * SDRAM SPD in the first 128 bytes, + * so skew the offset. + */ + if (dev_addr == CFG_DEF_EEPROM_ADDR) + offset += SDRAM_SPD_DATA_SIZE; + + /* Try to read the I2C EEPROM */ +#if defined(VXWORKS) + { + int i; + for( i = 0; i < count; ++i ) { + buf[ i ] = iicReadByte( dev_addr, offset+i ); + } + } +#else + if (eeprom_read(dev_addr, offset, buf, count)) { + printf("Failed to read %d bytes from VPD EEPROM 0x%x @ 0x%x\n", + count, dev_addr, offset); + return NULL; + } +#endif + + return buf; +} /* vpd_reader() */ + + +/* + * vpd_get_packet() - returns next VPD packet or NULL. + */ +static vpd_packet_t *vpd_get_packet(vpd_packet_t *vpd_packet) +{ + vpd_packet_t *packet = vpd_packet; + + if (packet != NULL) { + if (packet->identifier == VPD_PID_TERM) + return NULL; + else + packet = (vpd_packet_t *)((char *)packet + packet->size + 2); + } + + return packet; +} /* vpd_get_packet() */ + + +/* + * vpd_find_packet() - Locates and returns the specified + * VPD packet or NULL on error. + */ +static vpd_packet_t *vpd_find_packet(vpd_t *vpd, unsigned char ident) +{ + vpd_packet_t *packet = (vpd_packet_t *)&vpd->packets; + + /* Guaranteed illegal */ + if (ident == VPD_PID_GI) + return NULL; + + /* Scan tuples looking for a match */ + while ((packet->identifier != ident) && + (packet->identifier != VPD_PID_TERM)) + packet = vpd_get_packet(packet); + + /* Did we find it? */ + if ((packet->identifier) && (packet->identifier != ident)) + return NULL; + return packet; +} + + +/* + * vpd_is_valid() - Validates contents of VPD data + * in I2C EEPROM. Returns 1 for + * success or 0 for failure. + */ +static int vpd_is_valid(unsigned dev_addr, unsigned char *buf) +{ + unsigned num_bytes; + vpd_packet_t *packet; + vpd_t *vpd = (vpd_t *)buf; + unsigned short stored_crc16, calc_crc16 = 0xffff; + + /* Check Eyecatcher */ + if (strncmp(vpd->header.eyecatcher, VPD_EYECATCHER, VPD_EYE_SIZE) != 0) { + unsigned offset = 0; + if (dev_addr == CFG_DEF_EEPROM_ADDR) + offset += SDRAM_SPD_DATA_SIZE; + printf("Error: VPD EEPROM 0x%x corrupt @ 0x%x\n", dev_addr, offset); + + return 0; + } + + /* Check Length */ + if (vpd->header.size> VPD_MAX_EEPROM_SIZE) { + printf("Error: VPD EEPROM 0x%x contains bad size 0x%x\n", + dev_addr, vpd->header.size); + return 0; + } + + /* Now find the termination packet */ + if ((packet = vpd_find_packet(vpd, VPD_PID_TERM)) == NULL) { + printf("Error: VPD EEPROM 0x%x missing termination packet\n", + dev_addr); + return 0; + } + + /* Calculate data size */ + num_bytes = (unsigned long)((unsigned char *)packet - + (unsigned char *)vpd + sizeof(vpd_packet_t)); + + /* Find stored CRC and clear it */ + if ((packet = vpd_find_packet(vpd, VPD_PID_CRC)) == NULL) { + printf("Error: VPD EEPROM 0x%x missing CRC\n", dev_addr); + return 0; + } + stored_crc16 = *((ushort *)packet->data); + *(ushort *)packet->data = 0; + + /* OK, lets calculate the CRC and check it */ +#if defined(VXWORKS) + calc_crc16 = (0xffff & crc32(buf, num_bytes)); +#else + calc_crc16 = (0xffff & crc32(0, buf, num_bytes)); +#endif + *(ushort *)packet->data = stored_crc16; /* Now restore the CRC */ + if (stored_crc16 != calc_crc16) { + printf("Error: VPD EEPROM 0x%x has bad CRC 0x%x\n", + dev_addr, stored_crc16); + return 0; + } + + return 1; +} /* vpd_is_valid() */ + + +/* + * size_ok() - Check to see if packet size matches + * size of data we want. Returns 1 for + * good match or 0 for failure. + */ +static int size_ok(vpd_packet_t *packet, unsigned long size) +{ + if (packet->size != size) { + printf("VPD Packet 0x%x corrupt.\n", packet->identifier); + return 0; + } + return 1; +} /* size_ok() */ + + +/* + * strlen_ok() - Check to see if packet size matches + * strlen of the string we want to populate. + * Returns 1 for valid length or 0 for failure. + */ +static int strlen_ok(vpd_packet_t *packet, unsigned long length) +{ + if (packet->size >= length) { + printf("VPD Packet 0x%x corrupt.\n", packet->identifier); + return 0; + } + return 1; +} /* strlen_ok() */ + + +/* + * get_vpd_data() - populates the passed VPD structure 'vpdInfo' + * with data obtained from the specified + * I2C EEPROM 'dev_addr'. Returns 0 for + * success or 1 for failure. + */ +int vpd_get_data(unsigned char dev_addr, VPD *vpdInfo) +{ + unsigned char buf[VPD_EEPROM_SIZE]; + vpd_t *vpd = (vpd_t *)buf; + vpd_packet_t *packet; + + if (vpdInfo == NULL) + return 1; + + /* + * Fill vpdInfo with 0s to blank out + * unused fields, fill vpdInfo->ethAddrs + * with all 0xffs so that other's code can + * determine how many real Ethernet addresses + * there are. OUIs starting with 0xff are + * broadcast addresses, and would never be + * permantely stored. + */ + memset((void *)vpdInfo, 0, sizeof(VPD)); + memset((void *)&vpdInfo->ethAddrs, 0xff, sizeof(vpdInfo->ethAddrs)); + vpdInfo->_devAddr = dev_addr; + + /* Read the minimum size first */ + if (vpd_reader(buf, dev_addr, 0, VPD_EEPROM_SIZE) == NULL) { + return 1; + } + + /* Check validity of VPD data */ + if (!vpd_is_valid(dev_addr, buf)) { + printf("VPD Data is INVALID!\n"); + return 1; + } + + /* + * Walk all the packets and populate + * the VPD info structure. + */ + packet = (vpd_packet_t *)&vpd->packets; + do { + switch (packet->identifier) { + case VPD_PID_GI: + printf("Error: Illegal VPD value\n"); + break; + case VPD_PID_PID: + if (strlen_ok(packet, MAX_PROD_ID)) { + strncpy(vpdInfo->productId, + packet->data, packet->size); + } + break; + case VPD_PID_REV: + if (size_ok(packet, sizeof(char))) + vpdInfo->revisionId = *packet->data; + break; + case VPD_PID_SN: + if (size_ok(packet, sizeof(unsigned long))) { + vpdInfo->serialNum = + *(unsigned long *)packet->data; + } + break; + case VPD_PID_MANID: + if (size_ok(packet, sizeof(unsigned char))) + vpdInfo->manuID = *packet->data; + break; + case VPD_PID_PCO: + if (size_ok(packet, sizeof(unsigned long))) { + vpdInfo->configOpt = + *(unsigned long *)packet->data; + } + break; + case VPD_PID_SYSCLK: + if (size_ok(packet, sizeof(unsigned long))) + vpdInfo->sysClk = *(unsigned long *)packet->data; + break; + case VPD_PID_SERCLK: + if (size_ok(packet, sizeof(unsigned long))) + vpdInfo->serClk = *(unsigned long *)packet->data; + break; + case VPD_PID_FLASH: + if (size_ok(packet, 9)) { /* XXX - hardcoded, + padding in struct */ + memcpy(&vpdInfo->flashCfg, packet->data, 9); + } + break; + case VPD_PID_ETHADDR: + memcpy(vpdInfo->ethAddrs, packet->data, packet->size); + break; + case VPD_PID_POTS: + if (size_ok(packet, sizeof(char))) + vpdInfo->numPOTS = (unsigned)*packet->data; + break; + case VPD_PID_DS1: + if (size_ok(packet, sizeof(char))) + vpdInfo->numDS1 = (unsigned)*packet->data; + case VPD_PID_GAL: + case VPD_PID_CRC: + case VPD_PID_TERM: + break; + default: + printf("Warning: Found unknown VPD packet ID 0x%x\n", + packet->identifier); + break; + } + } while ((packet = vpd_get_packet(packet))); + + return 0; +} /* end get_vpd_data() */ + + +/* + * vpd_init() - Initialize default VPD environment + */ +int vpd_init(unsigned char dev_addr) +{ + return (0); +} /* vpd_init() */ + + +/* + * vpd_print() - Pretty print the VPD data. + */ +void vpd_print(VPD *vpdInfo) +{ + const char *const sp = ""; + const char *const sfmt = "%4s%-20s: \"%s\"\n"; + const char *const cfmt = "%4s%-20s: '%c'\n"; + const char *const dfmt = "%4s%-20s: %ld\n"; + const char *const hfmt = "%4s%-20s: %08lX\n"; + const char *const dsfmt = "%4s%-20s: %d\n"; + const char *const hsfmt = "%4s%-20s: %04X\n"; + const char *const dhfmt = "%4s%-20s: %ld (%lX)\n"; + + printf("VPD read from I2C device: %02X\n", vpdInfo->_devAddr); + + if (vpdInfo->productId[0]) + printf(sfmt, sp, "Product ID", vpdInfo->productId); + else + printf(sfmt, sp, "Product ID", "UNKNOWN"); + + if (vpdInfo->revisionId) + printf(cfmt, sp, "Revision ID", vpdInfo->revisionId); + + if (vpdInfo->serialNum) + printf(dfmt, sp, "Serial Number", vpdInfo->serialNum); + + if (vpdInfo->manuID) + printf(dfmt, sp, "Manufacture ID", (long)vpdInfo->manuID); + + if (vpdInfo->configOpt) + printf(hfmt, sp, "Configuration", vpdInfo->configOpt); + + if (vpdInfo->sysClk) + printf(dhfmt, sp, "System Clock", vpdInfo->sysClk, vpdInfo->sysClk); + + if (vpdInfo->serClk) + printf(dhfmt, sp, "Serial Clock", vpdInfo->serClk, vpdInfo->serClk); + + if (vpdInfo->numPOTS) + printf(dfmt, sp, "Number of POTS lines", vpdInfo->numPOTS); + + if (vpdInfo->numDS1) + printf(dfmt, sp, "Number of DS1s", vpdInfo->numDS1); + + /* Print Ethernet Addresses */ + if (vpdInfo->ethAddrs[0][0] != 0xff) { + int i, j; + printf("%4sEtherNet Address(es): ", sp); + for (i = 0; i < MAX_ETH_ADDRS; i++) { + if (vpdInfo->ethAddrs[i][0] != 0xff) { + for (j = 0; j < 6; j++) { + printf("%02X", vpdInfo->ethAddrs[i][j]); + if (((j + 1) % 6) != 0) + printf(":"); + else + printf(" "); + } + if (((i + 1) % 3) == 0) printf("\n%24s: ", sp); + } + } + printf("\n"); + } + + if (vpdInfo->flashCfg.mfg && vpdInfo->flashCfg.dev) { + printf("Main Flash Configuration:\n"); + printf(hsfmt, sp, "Manufacture ID", vpdInfo->flashCfg.mfg); + printf(hsfmt, sp, "Device ID", vpdInfo->flashCfg.dev); + printf(dsfmt, sp, "Device Width", vpdInfo->flashCfg.devWidth); + printf(dsfmt, sp, "Num. Devices", vpdInfo->flashCfg.numDevs); + printf(dsfmt, sp, "Num. Columns", vpdInfo->flashCfg.numCols); + printf(dsfmt, sp, "Column Width", vpdInfo->flashCfg.colWidth); + printf(dsfmt, sp, "WE Data Width", vpdInfo->flashCfg.weDataWidth); + } +} /* vpd_print() */ + diff --git a/board/w7o/vpd.h b/board/w7o/vpd.h new file mode 100644 index 0000000..35bbe3e --- /dev/null +++ b/board/w7o/vpd.h @@ -0,0 +1,135 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 + */ + +#ifndef _VPD_H_ +#define _VPD_H_ + +/* + * Main Flash Configuration. + */ +typedef struct flashCfg_s { + unsigned short mfg; /* Manufacture ID */ + unsigned short dev; /* Device ID */ + unsigned char devWidth; /* Device Width */ + unsigned char numDevs; /* Number of devices */ + unsigned char numCols; /* Number of columns */ + unsigned char colWidth; /* Width of a column */ + unsigned char weDataWidth; /* Write/Erase Data Width */ +} flashCfg_t; + +/* + * Vital Product Data - VPD + */ +#define MAX_PROD_ID 15 +#define MAX_ETH_ADDRS 10 +typedef unsigned char EthAddr[6]; +typedef struct vpd { + unsigned char _devAddr; /* Device address during read */ + char productId[MAX_PROD_ID]; /* Product ID */ + char revisionId; /* Revision ID as a char */ + unsigned long serialNum; /* Serial number */ + unsigned char manuID; /* Manufact ID - byte int */ + unsigned long configOpt; /* Config Option - bit field */ + unsigned long sysClk; /* System clock in Hertz */ + unsigned long serClk; /* Ext. clock in Hertz */ + flashCfg_t flashCfg; /* Flash configuration */ + unsigned long numPOTS; /* Number of POTS lines */ + unsigned long numDS1; /* Number of DS1 circuits */ + EthAddr ethAddrs[MAX_ETH_ADDRS]; /* Ethernet MAC, 1st = craft */ +} VPD; + + +#define VPD_MAX_EEPROM_SIZE 512 /* Max size VPD EEPROM */ +#define SDRAM_SPD_DATA_SIZE 128 /* Size SPD in VPD EEPROM */ + +/* + * PIDs - Packet Identifiers + */ +#define VPD_PID_GI 0x0 /* Guaranted Illegal */ +#define VPD_PID_PID 0x1 /* Product Identifier */ +#define VPD_PID_REV 0x2 /* Product Revision */ +#define VPD_PID_SN 0x3 /* Serial Number */ +#define VPD_PID_MANID 0x4 /* Manufacture ID */ +#define VPD_PID_PCO 0x5 /* Product configuration */ +#define VPD_PID_SYSCLK 0x6 /* System Clock */ +#define VPD_PID_SERCLK 0x7 /* Ser. Clk. Speed in Hertz */ +#define VPD_PID_CRC 0x8 /* VPD CRC */ +#define VPD_PID_FLASH 0x9 /* Flash Configuration */ +#define VPD_PID_ETHADDR 0xA /* Ethernet Address(es) */ +#define VPD_PID_GAL 0xB /* Galileo Switch Config */ +#define VPD_PID_POTS 0xC /* Number of POTS Lines */ +#define VPD_PID_DS1 0xD /* Number of DS1s */ +#define VPD_PID_TERM 0xFF /* Termination packet */ + +/* + * VPD - Eyecatcher/Magic + */ +#define VPD_EYECATCHER "W7O" +#define VPD_EYE_SIZE 3 +typedef struct vpd_header { + unsigned char eyecatcher[VPD_EYE_SIZE]; /* eyecatcher - "W7O" */ + unsigned short size __attribute__((packed)); /* size of EEPROM */ +} vpd_header_t; + + +#define VPD_DATA_SIZE (VPD_MAX_EEPROM_SIZE - SDRAM_SPD_DATA_SIZE - \ + sizeof(vpd_header_t)) +typedef struct vpd_s { + vpd_header_t header; + unsigned char packets[VPD_DATA_SIZE]; +} vpd_t; + +typedef struct vpd_packet { + unsigned char identifier; + unsigned char size; + unsigned char data[1]; +} vpd_packet_t; + +/* + * VPD configOpt bit mask + */ +#define VPD_HAS_BBRAM 0x1 /* Battery backed SRAM */ +#define VPD_HAS_RTC 0x2 /* Battery backed RTC */ +#define VPD_HAS_EXT_SER_CLK 0x4 /* External serial clock */ +#define VPD_HAS_SER_TRANS_1 0x8 /* COM1 transceiver */ +#define VPD_HAS_SER_TRANS_2 0x10 /* COM2 transceiver */ +#define VPD_HAS_CRAFT_PHY 0x20 /* CRAFT Ethernet */ +#define VPD_HAS_DTT_1 0x40 /* I2C Digital therm. #1 */ +#define VPD_HAS_DTT_2 0x80 /* I2C Digital therm. #2 */ +#define VPD_HAS_1000_UP_LASER 0x100 /* GMM - 1000Mbit Uplink */ +#define VPD_HAS_70KM_UP_LASER 0x200 /* CMM - 70KM Uplink laser */ +#define VPD_HAS_2_UPLINKS 0x400 /* CMM - 2 uplink lasers */ +#define VPD_HAS_FPGA 0x800 /* Has 1 or more FPGAs */ +#define VPD_HAS_DFA 0x1000 /* CLM - Has 2 Fiber Inter. */ +#define VPD_HAS_GAL_SWITCH 0x2000 /* GMM - Has a Gal switch */ +#define VPD_HAS_POTS_LINES 0x4000 /* GMM - Has POTS lines */ +#define VPD_HAS_DS1_CHANNELS 0x8000 /* GMM - Has DS1 channels */ +#define VPD_HAS_CABLE_RETURN 0x10000 /* GBM/GBR - Cable ret. path */ + +#define VPD_EEPROM_SIZE (256 - SDRAM_SPD_DATA_SIZE) /* Size EEPROM */ + +extern int vpd_get_data(unsigned char dev_addr, VPD *vpd); +extern void vpd_print(VPD *vpdInfo); + +#endif /* _VPD_H_ */ + diff --git a/board/w7o/w7o.c b/board/w7o/w7o.c new file mode 100644 index 0000000..b404d61 --- /dev/null +++ b/board/w7o/w7o.c @@ -0,0 +1,271 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include "w7o.h" +#include <asm/processor.h> + +#include "vpd.h" +#include "errors.h" +#include <watchdog.h> + +unsigned long get_dram_size(void); + +/* + * Macros to transform values + * into environment strings. + */ +#define XMK_STR(x) #x +#define MK_STR(x) XMK_STR(x) + +/* ------------------------------------------------------------------------- */ + +int board_pre_init (void) +{ +#if defined(CONFIG_W7OLMG) + /* + * Setup GPIO pins - reset devices. + */ + out32(IBM405GP_GPIO0_ODR, 0x10000000); /* one open drain pin */ + out32(IBM405GP_GPIO0_OR, 0x3E000000); /* set output pins to default */ + out32(IBM405GP_GPIO0_TCR, 0x7f800000); /* setup for output */ + + /* + * IRQ 0-15 405GP internally generated; active high; level sensitive + * IRQ 16 405GP internally generated; active low; level sensitive + * IRQ 17-24 RESERVED + * IRQ 25 (EXT IRQ 0) XILINX; active low; level sensitive + * IRQ 26 (EXT IRQ 1) PCI INT A; active low; level sensitive + * IRQ 27 (EXT IRQ 2) PCI INT B; active low; level sensitive + * IRQ 28 (EXT IRQ 3) SAM 2; active low; level sensitive + * IRQ 29 (EXT IRQ 4) Battery Bad; active low; level sensitive + * IRQ 30 (EXT IRQ 5) Level One PHY; active low; level sensitive + * IRQ 31 (EXT IRQ 6) SAM 1; active high; level sensitive + */ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + + mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/ + mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */ + mtdcr(uictr, 0x10000000); /* set int trigger levels */ + mtdcr(uicvcr, 0x00000001); /* set vect base=0, + INT0 highest priority*/ + + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + +#elif defined(CONFIG_W7OLMC) + /* + * Setup GPIO pins + */ + out32(IBM405GP_GPIO0_ODR, 0x01800000); /* XCV Done Open Drain */ + out32(IBM405GP_GPIO0_OR, 0x03800000); /* set out pins to default */ + out32(IBM405GP_GPIO0_TCR, 0x66C00000); /* setup for output */ + + /* + * IRQ 0-15 405GP internally generated; active high; level sensitive + * IRQ 16 405GP internally generated; active low; level sensitive + * IRQ 17-24 RESERVED + * IRQ 25 (EXT IRQ 0) DBE 0; active low; level sensitive + * IRQ 26 (EXT IRQ 1) DBE 1; active low; level sensitive + * IRQ 27 (EXT IRQ 2) DBE 2; active low; level sensitive + * IRQ 28 (EXT IRQ 3) DBE Common; active low; level sensitive + * IRQ 29 (EXT IRQ 4) PCI; active low; level sensitive + * IRQ 30 (EXT IRQ 5) RCMM Reset; active low; level sensitive + * IRQ 31 (EXT IRQ 6) PHY; active high; level sensitive + */ + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + mtdcr(uicer, 0x00000000); /* disable all ints */ + + mtdcr(uiccr, 0x00000000); /* set all to be non-critical*/ + mtdcr(uicpr, 0xFFFFFF80); /* set int polarities */ + mtdcr(uictr, 0x10000000); /* set int trigger levels */ + mtdcr(uicvcr, 0x00000001); /* set vect base=0, + INT0 highest priority*/ + + mtdcr(uicsr, 0xFFFFFFFF); /* clear all ints */ + +#else /* Unknown */ +# error "Unknown W7O board configuration" +#endif + + WATCHDOG_RESET(); /* Reset the watchdog */ + temp_uart_init(); /* init the uart for debug */ + WATCHDOG_RESET(); /* Reset the watchdog */ + test_led(); /* test the LEDs */ + test_sdram(get_dram_size()); /* test the dram */ + log_stat(ERR_POST1); /* log status,post1 complete */ + return 0; +} + + +/* ------------------------------------------------------------------------- */ + +/* + * Check Board Identity: + */ +int checkboard (void) +{ + VPD vpd; + + puts ("Board: "); + + /* VPD data present in I2C EEPROM */ + if (vpd_get_data(CFG_DEF_EEPROM_ADDR, &vpd) == 0) { + /* + * Known board type. + */ + if (vpd.productId[0] && + ((strncmp(vpd.productId, "GMM", 3) == 0) || + (strncmp(vpd.productId, "CMM", 3) == 0))) { + + /* Output board information on startup */ + printf("\"%s\", revision '%c', serial# %ld, manufacturer %u\n", + vpd.productId, vpd.revisionId, vpd.serialNum, vpd.manuID); + return (0); + } + } + + puts ("### Unknown HW ID - assuming NOTHING\n"); + return (0); +} + +/* ------------------------------------------------------------------------- */ + +long int initdram (int board_type) +{ + return get_dram_size(); +} + +unsigned long get_dram_size (void) +{ + int tmp, i, regs[4]; + int size = 0; + + /* Get bank Size registers */ + mtdcr(memcfga, mem_mb0cf); /* get bank 0 config reg */ + regs[0] = mfdcr(memcfgd); + + mtdcr(memcfga, mem_mb1cf); /* get bank 1 config reg */ + regs[1] = mfdcr(memcfgd); + + mtdcr(memcfga, mem_mb2cf); /* get bank 2 config reg */ + regs[2] = mfdcr(memcfgd); + + mtdcr(memcfga, mem_mb3cf); /* get bank 3 config reg */ + regs[3] = mfdcr(memcfgd); + + /* compute the size, add each bank if enabled */ + for(i = 0; i < 4; i++) { + if (regs[i] & 0x0001) { /* if enabled, */ + tmp = ((regs[i] >> (31 - 14)) & 0x7); /* get size bits */ + tmp = 0x400000 << tmp; /* Size bits X 4MB = size */ + size += tmp; + } + } + + return size; +} + +int misc_init_f (void) +{ + return 0; +} + +static void +w7o_env_init(VPD *vpd) +{ + /* + * Read VPD + */ + if (vpd_get_data(CFG_DEF_EEPROM_ADDR, vpd) != 0) + return; + + /* + * Known board type. + */ + if (vpd->productId[0] && + ((strncmp(vpd->productId, "GMM", 3) == 0) || + (strncmp(vpd->productId, "CMM", 3) == 0))) { + char buf[30]; + char *eth; + unsigned char *serial = getenv("serial#"); + unsigned char *ethaddr = getenv("ethaddr"); + + /* Set 'serial#' envvar if serial# isn't set */ + if (!serial) { + sprintf(buf, "%s-%ld", vpd->productId, vpd->serialNum); + setenv("serial#", buf); + } + + /* Set 'ethaddr' envvar if 'ethaddr' envvar is the default */ + eth = vpd->ethAddrs[0]; + if (ethaddr && (strcmp(ethaddr, MK_STR(CONFIG_ETHADDR)) == 0)) { + /* Now setup ethaddr */ + sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x", + eth[0], eth[1], eth[2], eth[3], eth[4], eth[5]); + setenv("ethaddr", buf); + } + } +} /* w7o_env_init() */ + + +int misc_init_r (void) +{ + VPD vpd; /* VPD information */ + +#if defined(CONFIG_W7OLMG) + unsigned long greg; /* GPIO Register */ + + greg = in32(IBM405GP_GPIO0_OR); + + /* + * XXX - Unreset devices - this should be moved into VxWorks driver code + */ + greg |= 0x41800000L; /* SAM, PHY, Galileo */ + + out32(IBM405GP_GPIO0_OR, greg); /* set output pins to default */ +#endif /* CONFIG_W7OLMG */ + + /* + * Initialize W7O environment variables + */ + w7o_env_init(&vpd); + + /* + * Initialize the FPGA(s). + */ + if (init_fpga() == 0) + test_fpga((unsigned short *)CONFIG_FPGAS_BASE); + + /* More POST testing. */ + post2(); + + /* Done with hardware initialization and POST. */ + log_stat(ERR_POSTOK); + + /* Call silly, fail safe boot init routine */ + init_fsboot(); + + return (0); +} + diff --git a/common/cmd_doc.c b/common/cmd_doc.c new file mode 100644 index 0000000..37d0fbd --- /dev/null +++ b/common/cmd_doc.c @@ -0,0 +1,1563 @@ +/* + * Driver for Disk-On-Chip 2000 and Millennium + * (c) 1999 Machine Vision Holdings, Inc. + * (c) 1999, 2000 David Woodhouse <dwmw2@infradead.org> + * + * $Id: doc2000.c,v 1.46 2001/10/02 15:05:13 dwmw2 Exp $ + */ + +#include <common.h> +#include <config.h> +#include <command.h> +#include <malloc.h> +#include <asm/io.h> + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_DOC) + +#include <linux/mtd/nand.h> +#include <linux/mtd/nand_ids.h> +#include <linux/mtd/doc2000.h> +#include <linux/mtd/nftl.h> + +#ifdef CFG_DOC_SUPPORT_2000 +#define DoC_is_2000(doc) (doc->ChipID == DOC_ChipID_Doc2k) +#else +#define DoC_is_2000(doc) (0) +#endif + +#ifdef CFG_DOC_SUPPORT_MILLENNIUM +#define DoC_is_Millennium(doc) (doc->ChipID == DOC_ChipID_DocMil) +#else +#define DoC_is_Millennium(doc) (0) +#endif + +/* CFG_DOC_PASSIVE_PROBE: + In order to ensure that the BIOS checksum is correct at boot time, and + hence that the onboard BIOS extension gets executed, the DiskOnChip + goes into reset mode when it is read sequentially: all registers + return 0xff until the chip is woken up again by writing to the + DOCControl register. + + Unfortunately, this means that the probe for the DiskOnChip is unsafe, + because one of the first things it does is write to where it thinks + the DOCControl register should be - which may well be shared memory + for another device. I've had machines which lock up when this is + attempted. Hence the possibility to do a passive probe, which will fail + to detect a chip in reset mode, but is at least guaranteed not to lock + the machine. + + If you have this problem, uncomment the following line: +#define CFG_DOC_PASSIVE_PROBE +*/ + +#undef DOC_DEBUG +#undef ECC_DEBUG +#undef PSYCHO_DEBUG +#undef NFTL_DEBUG + +static struct DiskOnChip doc_dev_desc[CFG_MAX_DOC_DEVICE]; + +/* Current DOC Device */ +static int curr_device = -1; + +/* ------------------------------------------------------------------------- */ + +int do_doc (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strcmp(argv[1],"info") == 0) { + int i; + + putc ('\n'); + + for (i=0; i<CFG_MAX_DOC_DEVICE; ++i) { + if(doc_dev_desc[i].ChipID == DOC_ChipID_UNKNOWN) + continue; /* list only known devices */ + printf ("Device %d: ", i); + doc_print(&doc_dev_desc[i]); + } + return 0; + + } else if (strcmp(argv[1],"device") == 0) { + if ((curr_device < 0) || (curr_device >= CFG_MAX_DOC_DEVICE)) { + puts ("\nno devices available\n"); + return 1; + } + printf ("\nDevice %d: ", curr_device); + doc_print(&doc_dev_desc[curr_device]); + return 0; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strcmp(argv[1],"device") == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + printf ("\nDevice %d: ", dev); + if (dev >= CFG_MAX_DOC_DEVICE) { + puts ("unknown device\n"); + return 1; + } + doc_print(&doc_dev_desc[dev]); + /*doc_print (dev);*/ + + if (doc_dev_desc[dev].ChipID == DOC_ChipID_UNKNOWN) { + return 1; + } + + curr_device = dev; + + puts ("... is now current device\n"); + + return 0; + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strcmp(argv[1],"read") == 0 || strcmp(argv[1],"write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong off = simple_strtoul(argv[3], NULL, 16); + ulong size = simple_strtoul(argv[4], NULL, 16); + int cmd = (strcmp(argv[1],"read") == 0); + int ret, total; + + printf ("\nDOC %s: device %d offset %ld, size %ld ... ", + cmd ? "read" : "write", curr_device, off, size); + + ret = doc_rw(doc_dev_desc + curr_device, cmd, off, size, + &total, (u_char*)addr); + + printf ("%d bytes %s: %s\n", total, cmd ? "read" : "write", + ret ? "ERROR" : "OK"); + + return ret; + } else if (strcmp(argv[1],"erase") == 0) { + ulong off = simple_strtoul(argv[2], NULL, 16); + ulong size = simple_strtoul(argv[3], NULL, 16); + int ret; + + printf ("\nDOC erase: device %d offset %ld, size %ld ... ", + curr_device, off, size); + + ret = doc_erase (doc_dev_desc + curr_device, off, size); + + printf("%s\n", ret ? "ERROR" : "OK"); + + return ret; + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + rcode = 1; + } + + return rcode; + } +} + +int do_docboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + char *ep; + int dev; + ulong cnt; + ulong addr; + ulong offset = 0; + image_header_t *hdr; + int rcode = 0; + + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv ("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv ("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + case 4: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + offset = simple_strtoul(argv[3], NULL, 16); + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (!boot_device) { + puts ("\n** No boot device **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + dev = simple_strtoul(boot_device, &ep, 16); + + if ((dev >= CFG_MAX_DOC_DEVICE) || + (doc_dev_desc[dev].ChipID == DOC_ChipID_UNKNOWN)) { + printf ("\n** Device %d not available\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + printf ("\nLoading from device %d: %s at 0x%lX (offset 0x%lX)\n", + dev, doc_dev_desc[dev].name, doc_dev_desc[dev].physadr, + offset); + + if (doc_rw (doc_dev_desc + dev, 1, offset, + SECTORSIZE, NULL, (u_char *)addr)) { + printf ("** Read error on %d\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + hdr = (image_header_t *)addr; + + if (hdr->ih_magic == IH_MAGIC) { + + print_image_hdr (hdr); + + cnt = (hdr->ih_size + sizeof(image_header_t)); + cnt -= SECTORSIZE; + } else { + puts ("\n** Bad Magic Number **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (doc_rw (doc_dev_desc + dev, 1, offset + SECTORSIZE, cnt, + NULL, (u_char *)(addr+SECTORSIZE))) { + printf ("** Read error on %d\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + /* Loading ok, update default load address */ + + load_addr = addr; + + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode = 1; + } + return rcode; +} + +int doc_rw (struct DiskOnChip* this, int cmd, + loff_t from, size_t len, + size_t * retlen, u_char * buf) +{ + int noecc, ret = 0, n, total = 0; + char eccbuf[6]; + + while(len) { + /* The ECC will not be calculated correctly if + less than 512 is written or read */ + noecc = (from != (from | 0x1ff) + 1) || (len < 0x200); + + if (cmd) + ret = doc_read_ecc(this, from, len, + &n, (u_char*)buf, + noecc ? NULL : eccbuf); + else + ret = doc_write_ecc(this, from, len, + &n, (u_char*)buf, + noecc ? NULL : eccbuf); + + if (ret) + break; + + from += n; + buf += n; + total += n; + len -= n; + } + + if (retlen) + *retlen = total; + + return ret; +} + +void doc_print(struct DiskOnChip *this) { + printf("%s at 0x%lX,\n" + "\t %d chip%s %s, size %d MB, \n" + "\t total size %ld MB, sector size %ld kB\n", + this->name, this->physadr, this->numchips, + this->numchips>1 ? "s" : "", this->chips_name, + 1 << (this->chipshift - 20), + this->totlen >> 20, this->erasesize >> 10); + + if (this->nftl_found) { + struct NFTLrecord *nftl = &this->nftl; + unsigned long bin_size, flash_size; + + bin_size = nftl->nb_boot_blocks * this->erasesize; + flash_size = (nftl->nb_blocks - nftl->nb_boot_blocks) * this->erasesize; + + printf("\t NFTL boot record:\n" + "\t Binary partition: size %ld%s\n" + "\t Flash disk partition: size %ld%s, offset 0x%lx\n", + bin_size > (1 << 20) ? bin_size >> 20 : bin_size >> 10, + bin_size > (1 << 20) ? "MB" : "kB", + flash_size > (1 << 20) ? flash_size >> 20 : flash_size >> 10, + flash_size > (1 << 20) ? "MB" : "kB", bin_size); + } else { + puts ("\t No NFTL boot record found.\n"); + } +} + +/* ------------------------------------------------------------------------- */ + +/* This function is needed to avoid calls of the __ashrdi3 function. */ +static int shr(int val, int shift) { + return val >> shift; +} + +/* Perform the required delay cycles by reading from the appropriate register */ +static void DoC_Delay(struct DiskOnChip *doc, unsigned short cycles) +{ + volatile char dummy; + int i; + + for (i = 0; i < cycles; i++) { + if (DoC_is_Millennium(doc)) + dummy = ReadDOC(doc->virtadr, NOP); + else + dummy = ReadDOC(doc->virtadr, DOCStatus); + } + +} + +/* DOC_WaitReady: Wait for RDY line to be asserted by the flash chip */ +static int _DoC_WaitReady(struct DiskOnChip *doc) +{ + unsigned long docptr = doc->virtadr; + unsigned long start = get_timer(0); + +#ifdef PSYCHO_DEBUG + puts ("_DoC_WaitReady called for out-of-line wait\n"); +#endif + + /* Out-of-line routine to wait for chip response */ + while (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) { +#ifdef CFG_DOC_SHORT_TIMEOUT + /* it seems that after a certain time the DoC deasserts + * the CDSN_CTRL_FR_B although it is not ready... + * using a short timout solve this (timer increments every ms) */ + if (get_timer(start) > 10) { + return DOC_ETIMEOUT; + } +#else + if (get_timer(start) > 10 * 1000) { + puts ("_DoC_WaitReady timed out.\n"); + return DOC_ETIMEOUT; + } +#endif + udelay(1); + } + + return 0; +} + +static int DoC_WaitReady(struct DiskOnChip *doc) +{ + unsigned long docptr = doc->virtadr; + /* This is inline, to optimise the common case, where it's ready instantly */ + int ret = 0; + + /* 4 read form NOP register should be issued in prior to the read from CDSNControl + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 4); + + if (!(ReadDOC(docptr, CDSNControl) & CDSN_CTRL_FR_B)) + /* Call the out-of-line routine to wait */ + ret = _DoC_WaitReady(doc); + + /* issue 2 read from NOP register after reading from CDSNControl register + see Software Requirement 11.4 item 2. */ + DoC_Delay(doc, 2); + + return ret; +} + +/* DoC_Command: Send a flash command to the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static inline int DoC_Command(struct DiskOnChip *doc, unsigned char command, + unsigned char xtraflags) +{ + unsigned long docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags |= CDSN_CTRL_FLASH_IO; + + /* Assert the CLE (Command Latch Enable) line to the flash chip */ + WriteDOC(xtraflags | CDSN_CTRL_CLE | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + if (DoC_is_Millennium(doc)) + WriteDOC(command, docptr, CDSNSlowIO); + + /* Send the command */ + WriteDOC_(command, docptr, doc->ioreg); + + /* Lower the CLE line */ + WriteDOC(xtraflags | CDSN_CTRL_CE, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for the chip to respond - Software requirement 11.4.1 (extended for any command) */ + return DoC_WaitReady(doc); +} + +/* DoC_Address: Set the current address for the flash chip through the CDSN Slow IO register to + bypass the internal pipeline. Each of 4 delay cycles (read from the NOP register) is + required after writing to CDSN Control register, see Software Requirement 11.4 item 3. */ + +static int DoC_Address(struct DiskOnChip *doc, int numbytes, unsigned long ofs, + unsigned char xtraflags1, unsigned char xtraflags2) +{ + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (DoC_is_2000(doc)) + xtraflags1 |= CDSN_CTRL_FLASH_IO; + + /* Assert the ALE (Address Latch Enable) line to the flash chip */ + WriteDOC(xtraflags1 | CDSN_CTRL_ALE | CDSN_CTRL_CE, docptr, CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Send the address */ + /* Devices with 256-byte page are addressed as: + Column (bits 0-7), Page (bits 8-15, 16-23, 24-31) + * there is no device on the market with page256 + and more than 24 bits. + Devices with 512-byte page are addressed as: + Column (bits 0-7), Page (bits 9-16, 17-24, 25-31) + * 25-31 is sent only if the chip support it. + * bit 8 changes the read command to be sent + (NAND_CMD_READ0 or NAND_CMD_READ1). + */ + + if (numbytes == ADDR_COLUMN || numbytes == ADDR_COLUMN_PAGE) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); + } + + if (doc->page256) { + ofs = ofs >> 8; + } else { + ofs = ofs >> 9; + } + + if (numbytes == ADDR_PAGE || numbytes == ADDR_COLUMN_PAGE) { + for (i = 0; i < doc->pageadrlen; i++, ofs = ofs >> 8) { + if (DoC_is_Millennium(doc)) + WriteDOC(ofs & 0xff, docptr, CDSNSlowIO); + WriteDOC_(ofs & 0xff, docptr, doc->ioreg); + } + } + + DoC_Delay(doc, 2); /* Needed for some slow flash chips. mf. */ + + /* FIXME: The SlowIO's for millennium could be replaced by + a single WritePipeTerm here. mf. */ + + /* Lower the ALE line */ + WriteDOC(xtraflags1 | xtraflags2 | CDSN_CTRL_CE, docptr, + CDSNControl); + + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for the chip to respond - Software requirement 11.4.1 */ + return DoC_WaitReady(doc); +} + +/* Read a buffer from DoC, taking care of Millennium odditys */ +static void DoC_ReadBuf(struct DiskOnChip *doc, u_char * buf, int len) +{ + volatile int dummy; + int modulus = 0xffff; + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + if (DoC_is_Millennium(doc)) { + /* Read the data via the internal pipeline through CDSN IO register, + see Pipelined Read Operations 11.3 */ + dummy = ReadDOC(docptr, ReadPipeInit); + + /* Millennium should use the LastDataRead register - Pipeline Reads */ + len--; + + /* This is needed for correctly ECC calculation */ + modulus = 0xff; + } + + for (i = 0; i < len; i++) + buf[i] = ReadDOC_(docptr, doc->ioreg + (i & modulus)); + + if (DoC_is_Millennium(doc)) { + buf[i] = ReadDOC(docptr, LastDataRead); + } +} + +/* Write a buffer to DoC, taking care of Millennium odditys */ +static void DoC_WriteBuf(struct DiskOnChip *doc, const u_char * buf, int len) +{ + unsigned long docptr; + int i; + + docptr = doc->virtadr; + + if (len <= 0) + return; + + for (i = 0; i < len; i++) + WriteDOC_(buf[i], docptr, doc->ioreg + i); + + if (DoC_is_Millennium(doc)) { + WriteDOC(0x00, docptr, WritePipeTerm); + } +} + + +/* DoC_SelectChip: Select a given flash chip within the current floor */ + +static inline int DoC_SelectChip(struct DiskOnChip *doc, int chip) +{ + unsigned long docptr = doc->virtadr; + + /* Software requirement 11.4.4 before writing DeviceSelect */ + /* Deassert the CE line to eliminate glitches on the FCE# outputs */ + WriteDOC(CDSN_CTRL_WP, docptr, CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Select the individual flash chip requested */ + WriteDOC(chip, docptr, CDSNDeviceSelect); + DoC_Delay(doc, 4); + + /* Reassert the CE line */ + WriteDOC(CDSN_CTRL_CE | CDSN_CTRL_FLASH_IO | CDSN_CTRL_WP, docptr, + CDSNControl); + DoC_Delay(doc, 4); /* Software requirement 11.4.3 for Millennium */ + + /* Wait for it to be ready */ + return DoC_WaitReady(doc); +} + +/* DoC_SelectFloor: Select a given floor (bank of flash chips) */ + +static inline int DoC_SelectFloor(struct DiskOnChip *doc, int floor) +{ + unsigned long docptr = doc->virtadr; + + /* Select the floor (bank) of chips required */ + WriteDOC(floor, docptr, FloorSelect); + + /* Wait for the chip to be ready */ + return DoC_WaitReady(doc); +} + +/* DoC_IdentChip: Identify a given NAND chip given {floor,chip} */ + +static int DoC_IdentChip(struct DiskOnChip *doc, int floor, int chip) +{ + int mfr, id, i; + volatile char dummy; + + /* Page in the required floor/chip */ + DoC_SelectFloor(doc, floor); + DoC_SelectChip(doc, chip); + + /* Reset the chip */ + if (DoC_Command(doc, NAND_CMD_RESET, CDSN_CTRL_WP)) { +#ifdef DOC_DEBUG + printf("DoC_Command (reset) for %d,%d returned true\n", + floor, chip); +#endif + return 0; + } + + + /* Read the NAND chip ID: 1. Send ReadID command */ + if (DoC_Command(doc, NAND_CMD_READID, CDSN_CTRL_WP)) { +#ifdef DOC_DEBUG + printf("DoC_Command (ReadID) for %d,%d returned true\n", + floor, chip); +#endif + return 0; + } + + /* Read the NAND chip ID: 2. Send address byte zero */ + DoC_Address(doc, ADDR_COLUMN, 0, CDSN_CTRL_WP, 0); + + /* Read the manufacturer and device id codes from the device */ + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + mfr = ReadDOC_(doc->virtadr, doc->ioreg); + + /* CDSN Slow IO register see Software Requirement 11.4 item 5. */ + dummy = ReadDOC(doc->virtadr, CDSNSlowIO); + DoC_Delay(doc, 2); + id = ReadDOC_(doc->virtadr, doc->ioreg); + + /* No response - return failure */ + if (mfr == 0xff || mfr == 0) + return 0; + + /* Check it's the same as the first chip we identified. + * M-Systems say that any given DiskOnChip device should only + * contain _one_ type of flash part, although that's not a + * hardware restriction. */ + if (doc->mfr) { + if (doc->mfr == mfr && doc->id == id) + return 1; /* This is another the same the first */ + else + printf("Flash chip at floor %d, chip %d is different:\n", + floor, chip); + } + + /* Print and store the manufacturer and ID codes. */ + for (i = 0; nand_flash_ids[i].name != NULL; i++) { + if (mfr == nand_flash_ids[i].manufacture_id && + id == nand_flash_ids[i].model_id) { +#ifdef DOC_DEBUG + printf("Flash chip found: Manufacturer ID: %2.2X, " + "Chip ID: %2.2X (%s)\n", mfr, id, + nand_flash_ids[i].name); +#endif + if (!doc->mfr) { + doc->mfr = mfr; + doc->id = id; + doc->chipshift = + nand_flash_ids[i].chipshift; + doc->page256 = nand_flash_ids[i].page256; + doc->pageadrlen = + nand_flash_ids[i].pageadrlen; + doc->erasesize = + nand_flash_ids[i].erasesize; + doc->chips_name = + nand_flash_ids[i].name; + return 1; + } + return 0; + } + } + + +#ifdef DOC_DEBUG + /* We haven't fully identified the chip. Print as much as we know. */ + printf("Unknown flash chip found: %2.2X %2.2X\n", + id, mfr); +#endif + + return 0; +} + +/* DoC_ScanChips: Find all NAND chips present in a DiskOnChip, and identify them */ + +static void DoC_ScanChips(struct DiskOnChip *this) +{ + int floor, chip; + int numchips[MAX_FLOORS]; + int maxchips = MAX_CHIPS; + int ret = 1; + + this->numchips = 0; + this->mfr = 0; + this->id = 0; + + if (DoC_is_Millennium(this)) + maxchips = MAX_CHIPS_MIL; + + /* For each floor, find the number of valid chips it contains */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + ret = 1; + numchips[floor] = 0; + for (chip = 0; chip < maxchips && ret != 0; chip++) { + + ret = DoC_IdentChip(this, floor, chip); + if (ret) { + numchips[floor]++; + this->numchips++; + } + } + } + + /* If there are none at all that we recognise, bail */ + if (!this->numchips) { + puts ("No flash chips recognised.\n"); + return; + } + + /* Allocate an array to hold the information for each chip */ + this->chips = malloc(sizeof(struct Nand) * this->numchips); + if (!this->chips) { + puts ("No memory for allocating chip info structures\n"); + return; + } + + ret = 0; + + /* Fill out the chip array with {floor, chipno} for each + * detected chip in the device. */ + for (floor = 0; floor < MAX_FLOORS; floor++) { + for (chip = 0; chip < numchips[floor]; chip++) { + this->chips[ret].floor = floor; + this->chips[ret].chip = chip; + this->chips[ret].curadr = 0; + this->chips[ret].curmode = 0x50; + ret++; + } + } + + /* Calculate and print the total size of the device */ + this->totlen = this->numchips * (1 << this->chipshift); + +#ifdef DOC_DEBUG + printf("%d flash chips found. Total DiskOnChip size: %ld MB\n", + this->numchips, this->totlen >> 20); +#endif +} + +/* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the + * various device information of the NFTL partition and Bad Unit Table. Update + * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] + * is used for management of Erase Unit in other routines in nftl.c and nftlmount.c + */ +static int find_boot_record(struct NFTLrecord *nftl) +{ + struct nftl_uci1 h1; + struct nftl_oob oob; + unsigned int block, boot_record_count = 0; + int retlen; + u8 buf[SECTORSIZE]; + struct NFTLMediaHeader *mh = &nftl->MediaHdr; + unsigned int i; + + nftl->MediaUnit = BLOCK_NIL; + nftl->SpareMediaUnit = BLOCK_NIL; + + /* search for a valid boot record */ + for (block = 0; block < nftl->nb_blocks; block++) { + int ret; + + /* Check for ANAND header first. Then can whinge if it's found but later + checks fail */ + if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize, SECTORSIZE, + &retlen, buf, NULL))) { + static int warncount = 5; + + if (warncount) { + printf("Block read at 0x%x failed\n", block * nftl->EraseSize); + if (!--warncount) + puts ("Further failures for this block will not be printed\n"); + } + continue; + } + + if (retlen < 6 || memcmp(buf, "ANAND", 6)) { + /* ANAND\0 not found. Continue */ +#ifdef PSYCHO_DEBUG + printf("ANAND header not found at 0x%x\n", block * nftl->EraseSize); +#endif + continue; + } + +#ifdef NFTL_DEBUG + printf("ANAND header found at 0x%x\n", block * nftl->EraseSize); +#endif + + /* To be safer with BIOS, also use erase mark as discriminant */ + if ((ret = doc_read_oob(nftl->mtd, block * nftl->EraseSize + SECTORSIZE + 8, + 8, &retlen, (char *)&h1) < 0)) { +#ifdef NFTL_DEBUG + printf("ANAND header found at 0x%x, but OOB data read failed\n", + block * nftl->EraseSize); +#endif + continue; + } + + /* OK, we like it. */ + + if (boot_record_count) { + /* We've already processed one. So we just check if + this one is the same as the first one we found */ + if (memcmp(mh, buf, sizeof(struct NFTLMediaHeader))) { +#ifdef NFTL_DEBUG + printf("NFTL Media Headers at 0x%x and 0x%x disagree.\n", + nftl->MediaUnit * nftl->EraseSize, block * nftl->EraseSize); +#endif + /* if (debug) Print both side by side */ + return -1; + } + if (boot_record_count == 1) + nftl->SpareMediaUnit = block; + + boot_record_count++; + continue; + } + + /* This is the first we've seen. Copy the media header structure into place */ + memcpy(mh, buf, sizeof(struct NFTLMediaHeader)); + + /* Do some sanity checks on it */ + if (mh->UnitSizeFactor != 0xff) { + puts ("Sorry, we don't support UnitSizeFactor " + "of != 1 yet.\n"); + return -1; + } + + nftl->nb_boot_blocks = le16_to_cpu(mh->FirstPhysicalEUN); + if ((nftl->nb_boot_blocks + 2) >= nftl->nb_blocks) { + printf ("NFTL Media Header sanity check failed:\n" + "nb_boot_blocks (%d) + 2 > nb_blocks (%d)\n", + nftl->nb_boot_blocks, nftl->nb_blocks); + return -1; + } + + nftl->numvunits = le32_to_cpu(mh->FormattedSize) / nftl->EraseSize; + if (nftl->numvunits > (nftl->nb_blocks - nftl->nb_boot_blocks - 2)) { + printf ("NFTL Media Header sanity check failed:\n" + "numvunits (%d) > nb_blocks (%d) - nb_boot_blocks(%d) - 2\n", + nftl->numvunits, + nftl->nb_blocks, + nftl->nb_boot_blocks); + return -1; + } + + nftl->nr_sects = nftl->numvunits * (nftl->EraseSize / SECTORSIZE); + + /* If we're not using the last sectors in the device for some reason, + reduce nb_blocks accordingly so we forget they're there */ + nftl->nb_blocks = le16_to_cpu(mh->NumEraseUnits) + le16_to_cpu(mh->FirstPhysicalEUN); + + /* read the Bad Erase Unit Table and modify ReplUnitTable[] accordingly */ + for (i = 0; i < nftl->nb_blocks; i++) { + if ((i & (SECTORSIZE - 1)) == 0) { + /* read one sector for every SECTORSIZE of blocks */ + if ((ret = doc_read_ecc(nftl->mtd, block * nftl->EraseSize + + i + SECTORSIZE, SECTORSIZE, + &retlen, buf, (char *)&oob)) < 0) { + puts ("Read of bad sector table failed\n"); + return -1; + } + } + /* mark the Bad Erase Unit as RESERVED in ReplUnitTable */ + if (buf[i & (SECTORSIZE - 1)] != 0xff) + nftl->ReplUnitTable[i] = BLOCK_RESERVED; + } + + nftl->MediaUnit = block; + boot_record_count++; + + } /* foreach (block) */ + + return boot_record_count?0:-1; +} + +/* This routine is made available to other mtd code via + * inter_module_register. It must only be accessed through + * inter_module_get which will bump the use count of this module. The + * addresses passed back in mtd are valid as long as the use count of + * this module is non-zero, i.e. between inter_module_get and + * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000. + */ +static void DoC2k_init(struct DiskOnChip* this) +{ + struct NFTLrecord *nftl; + + switch (this->ChipID) { + case DOC_ChipID_Doc2k: + this->name = "DiskOnChip 2000"; + this->ioreg = DoC_2k_CDSN_IO; + break; + case DOC_ChipID_DocMil: + this->name = "DiskOnChip Millennium"; + this->ioreg = DoC_Mil_CDSN_IO; + break; + } + +#ifdef DOC_DEBUG + printf("%s found at address 0x%lX\n", this->name, + this->physadr); +#endif + + this->totlen = 0; + this->numchips = 0; + + this->curfloor = -1; + this->curchip = -1; + + /* Ident all the chips present. */ + DoC_ScanChips(this); + + nftl = &this->nftl; + + /* Get physical parameters */ + nftl->EraseSize = this->erasesize; + nftl->nb_blocks = this->totlen / this->erasesize; + nftl->mtd = this; + + if (find_boot_record(nftl) != 0) + this->nftl_found = 0; + else + this->nftl_found = 1; + + printf("%s @ 0x%lX, %ld MB\n", this->name, this->physadr, this->totlen >> 20); +} + +int doc_read_ecc(struct DiskOnChip* this, loff_t from, size_t len, + size_t * retlen, u_char * buf, u_char * eccbuf) +{ + unsigned long docptr; + struct Nand *mychip; + unsigned char syndrome[6]; + volatile char dummy; + int i, len256 = 0, ret=0; + + docptr = this->virtadr; + + /* Don't allow read past end of device */ + if (from >= this->totlen) { + puts ("Out of flash\n"); + return DOC_EINVAL; + } + + /* Don't allow a single read to cross a 512-byte block boundary */ + if (from + len > ((from | 0x1ff) + 1)) + len = ((from | 0x1ff) + 1) - from; + + /* The ECC will not be calculated correctly if less than 512 is read */ + if (len != 0x200 && eccbuf) + printf("ECC needs a full sector read (adr: %lx size %lx)\n", + (long) from, (long) len); + +#ifdef PHYCH_DEBUG + printf("DoC_Read (adr: %lx size %lx)\n", (long) from, (long) len); +#endif + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[shr(from, this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + DoC_Command(this, + (!this->page256 + && (from & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from, CDSN_CTRL_WP, + CDSN_CTRL_ECC_IO); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + } + + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && from + len > (from | 0xff) + 1) { + len256 = (from | 0xff) + 1 - from; + DoC_ReadBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_READ0, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, from + len256, + CDSN_CTRL_WP, CDSN_CTRL_ECC_IO); + } + + DoC_ReadBuf(this, &buf[len256], len - len256); + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + /* Read the ECC data through the DiskOnChip ECC logic */ + /* Note: this will work even with 2M x 8bit devices as */ + /* they have 8 bytes of OOB per 256 page. mf. */ + DoC_ReadBuf(this, eccbuf, 6); + + /* Flush the pipeline */ + if (DoC_is_Millennium(this)) { + dummy = ReadDOC(docptr, ECCConf); + dummy = ReadDOC(docptr, ECCConf); + i = ReadDOC(docptr, ECCConf); + } else { + dummy = ReadDOC(docptr, 2k_ECCStatus); + dummy = ReadDOC(docptr, 2k_ECCStatus); + i = ReadDOC(docptr, 2k_ECCStatus); + } + + /* Check the ECC Status */ + if (i & 0x80) { + int nb_errors; + /* There was an ECC error */ +#ifdef ECC_DEBUG + printf("DiskOnChip ECC Error: Read at %lx\n", (long)from); +#endif + /* Read the ECC syndrom through the DiskOnChip ECC logic. + These syndrome will be all ZERO when there is no error */ + for (i = 0; i < 6; i++) { + syndrome[i] = + ReadDOC(docptr, ECCSyndrome0 + i); + } + nb_errors = doc_decode_ecc(buf, syndrome); + +#ifdef ECC_DEBUG + printf("Errors corrected: %x\n", nb_errors); +#endif + if (nb_errors < 0) { + /* We return error, but have actually done the read. Not that + this can be told to user-space, via sys_read(), but at least + MTD-aware stuff can know about it by checking *retlen */ + printf("ECC Errors at %lx\n", (long)from); + ret = DOC_EECC; + } + } + +#ifdef PSYCHO_DEBUG + printf("ECC DATA at %lxB: %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long)from, eccbuf[0], eccbuf[1], eccbuf[2], + eccbuf[3], eccbuf[4], eccbuf[5]); +#endif + + /* disable the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr , ECCConf); + } + + /* according to 11.4.1, we need to wait for the busy line + * drop if we read to the end of the page. */ + if(0 == ((from + *retlen) & 0x1ff)) + { + DoC_WaitReady(this); + } + + return ret; +} + +int doc_write_ecc(struct DiskOnChip* this, loff_t to, size_t len, + size_t * retlen, const u_char * buf, + u_char * eccbuf) +{ + int di; /* Yes, DI is a hangover from when I was disassembling the binary driver */ + unsigned long docptr; + volatile char dummy; + int len256 = 0; + struct Nand *mychip; + + docptr = this->virtadr; + + /* Don't allow write past end of device */ + if (to >= this->totlen) { + puts ("Out of flash\n"); + return DOC_EINVAL; + } + + /* Don't allow a single write to cross a 512-byte block boundary */ + if (to + len > ((to | 0x1ff) + 1)) + len = ((to | 0x1ff) + 1) - to; + + /* The ECC will not be calculated correctly if less than 512 is written */ + if (len != 0x200 && eccbuf) + printf("ECC needs a full sector write (adr: %lx size %lx)\n", + (long) to, (long) len); + + /* printf("DoC_Write (adr: %lx size %lx)\n", (long) to, (long) len); */ + + /* Find the chip which is to be used and select it */ + mychip = &this->chips[shr(to, this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* Set device to main plane of flash */ + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); + DoC_Command(this, + (!this->page256 + && (to & 0x100)) ? NAND_CMD_READ1 : NAND_CMD_READ0, + CDSN_CTRL_WP); + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to, 0, CDSN_CTRL_ECC_IO); + + if (eccbuf) { + /* Prime the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_EN | DOC_ECC_RW, docptr, ECCConf); + } else { + /* disable the ECC engine */ + WriteDOC(DOC_ECC_RESET, docptr, ECCConf); + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + } + + /* treat crossing 256-byte sector for 2M x 8bits devices */ + if (this->page256 && to + len > (to | 0xff) + 1) { + len256 = (to | 0xff) + 1 - to; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + puts ("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return DOC_EIO; + } + + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, to + len256, 0, + CDSN_CTRL_ECC_IO); + } + + DoC_WriteBuf(this, &buf[len256], len - len256); + + if (eccbuf) { + WriteDOC(CDSN_CTRL_ECC_IO | CDSN_CTRL_CE, docptr, + CDSNControl); + + if (DoC_is_Millennium(this)) { + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + WriteDOC(0, docptr, NOP); + } else { + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + WriteDOC_(0, docptr, this->ioreg); + } + + /* Read the ECC data through the DiskOnChip ECC logic */ + for (di = 0; di < 6; di++) { + eccbuf[di] = ReadDOC(docptr, ECCSyndrome0 + di); + } + + /* Reset the ECC engine */ + WriteDOC(DOC_ECC_DIS, docptr, ECCConf); + +#ifdef PSYCHO_DEBUG + printf + ("OOB data at %lx is %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", + (long) to, eccbuf[0], eccbuf[1], eccbuf[2], eccbuf[3], + eccbuf[4], eccbuf[5]); +#endif + } + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + /* There's an implicit DoC_WaitReady() in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + puts ("Error programming flash\n"); + /* Error in programming */ + *retlen = 0; + return DOC_EIO; + } + + /* Let the caller know we completed it */ + *retlen = len; + + if (eccbuf) { + unsigned char x[8]; + size_t dummy; + int ret; + + /* Write the ECC data to flash */ + for (di=0; di<6; di++) + x[di] = eccbuf[di]; + + x[6]=0x55; + x[7]=0x55; + + ret = doc_write_oob(this, to, 8, &dummy, x); + return ret; + } + return 0; +} + +int doc_read_oob(struct DiskOnChip* this, loff_t ofs, size_t len, + size_t * retlen, u_char * buf) +{ + int len256 = 0, ret; + unsigned long docptr; + struct Nand *mychip; + + docptr = this->virtadr; + + mychip = &this->chips[shr(ofs, this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with doc_read_ecc. */ + if (this->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, CDSN_CTRL_WP, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_ReadBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), + CDSN_CTRL_WP, 0); + } + + DoC_ReadBuf(this, &buf[len256], len - len256); + + *retlen = len; + /* Reading the full OOB data drops us off of the end of the page, + * causing the flash device to go into busy mode, so we need + * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ + + ret = DoC_WaitReady(this); + + return ret; + +} + +int doc_write_oob(struct DiskOnChip* this, loff_t ofs, size_t len, + size_t * retlen, const u_char * buf) +{ + int len256 = 0; + unsigned long docptr = this->virtadr; + struct Nand *mychip = &this->chips[shr(ofs, this->chipshift)]; + volatile int dummy; + +#ifdef PSYCHO_DEBUG + printf("doc_write_oob(%lx, %d): %2.2X %2.2X %2.2X %2.2X ... %2.2X %2.2X .. %2.2X %2.2X\n", + (long)ofs, len, buf[0], buf[1], buf[2], buf[3], + buf[8], buf[9], buf[14],buf[15]); +#endif + + /* Find the chip which is to be used and select it */ + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + /* disable the ECC engine */ + WriteDOC (DOC_ECC_RESET, docptr, ECCConf); + WriteDOC (DOC_ECC_DIS, docptr, ECCConf); + + /* Reset the chip, see Software Requirement 11.4 item 1. */ + DoC_Command(this, NAND_CMD_RESET, CDSN_CTRL_WP); + + /* issue the Read2 command to set the pointer to the Spare Data Area. */ + DoC_Command(this, NAND_CMD_READOOB, CDSN_CTRL_WP); + + /* update address for 2M x 8bit devices. OOB starts on the second */ + /* page to maintain compatibility with doc_read_ecc. */ + if (this->page256) { + if (!(ofs & 0x8)) + ofs += 0x100; + else + ofs -= 0x8; + } + + /* issue the Serial Data In command to initial the Page Program process */ + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs, 0, 0); + + /* treat crossing 8-byte OOB data for 2M x 8bit devices */ + /* Note: datasheet says it should automaticaly wrap to the */ + /* next OOB block, but it didn't work here. mf. */ + if (this->page256 && ofs + len > (ofs | 0x7) + 1) { + len256 = (ofs | 0x7) + 1 - ofs; + DoC_WriteBuf(this, buf, len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); + /* DoC_WaitReady() is implicit in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + puts ("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return DOC_EIO; + } + DoC_Command(this, NAND_CMD_SEQIN, 0); + DoC_Address(this, ADDR_COLUMN_PAGE, ofs & (~0x1ff), 0, 0); + } + + DoC_WriteBuf(this, &buf[len256], len - len256); + + DoC_Command(this, NAND_CMD_PAGEPROG, 0); + DoC_Command(this, NAND_CMD_STATUS, 0); + /* DoC_WaitReady() is implicit in DoC_Command */ + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + puts ("Error programming oob data\n"); + /* There was an error */ + *retlen = 0; + return DOC_EIO; + } + + *retlen = len; + return 0; + +} + +int doc_erase(struct DiskOnChip* this, loff_t ofs, size_t len) +{ + volatile int dummy; + unsigned long docptr; + struct Nand *mychip; + + if (ofs & (this->erasesize-1) || len & (this->erasesize-1)) { + puts ("Offset and size must be sector aligned\n"); + return DOC_EINVAL; + } + + docptr = this->virtadr; + + /* FIXME: Do this in the background. Use timers or schedule_task() */ + while(len) { + mychip = &this->chips[shr(ofs, this->chipshift)]; + + if (this->curfloor != mychip->floor) { + DoC_SelectFloor(this, mychip->floor); + DoC_SelectChip(this, mychip->chip); + } else if (this->curchip != mychip->chip) { + DoC_SelectChip(this, mychip->chip); + } + this->curfloor = mychip->floor; + this->curchip = mychip->chip; + + DoC_Command(this, NAND_CMD_ERASE1, 0); + DoC_Address(this, ADDR_PAGE, ofs, 0, 0); + DoC_Command(this, NAND_CMD_ERASE2, 0); + + DoC_Command(this, NAND_CMD_STATUS, CDSN_CTRL_WP); + + dummy = ReadDOC(docptr, CDSNSlowIO); + DoC_Delay(this, 2); + + if (ReadDOC_(docptr, this->ioreg) & 1) { + printf("Error erasing at 0x%lx\n", (long)ofs); + /* There was an error */ + goto callback; + } + ofs += this->erasesize; + len -= this->erasesize; + } + + callback: + return 0; +} + +static inline int doccheck(unsigned long potential, unsigned long physadr) +{ + unsigned long window=potential; + unsigned char tmp, ChipID; +#ifndef DOC_PASSIVE_PROBE + unsigned char tmp2; +#endif + + /* Routine copied from the Linux DOC driver */ + +#ifdef CFG_DOCPROBE_55AA + /* Check for 0x55 0xAA signature at beginning of window, + this is no longer true once we remove the IPL (for Millennium */ + if (ReadDOC(window, Sig1) != 0x55 || ReadDOC(window, Sig2) != 0xaa) + return 0; +#endif /* CFG_DOCPROBE_55AA */ + +#ifndef DOC_PASSIVE_PROBE + /* It's not possible to cleanly detect the DiskOnChip - the + * bootup procedure will put the device into reset mode, and + * it's not possible to talk to it without actually writing + * to the DOCControl register. So we store the current contents + * of the DOCControl register's location, in case we later decide + * that it's not a DiskOnChip, and want to put it back how we + * found it. + */ + tmp2 = ReadDOC(window, DOCControl); + + /* Reset the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_RESET, + window, DOCControl); + + /* Enable the DiskOnChip ASIC */ + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); + WriteDOC(DOC_MODE_CLR_ERR | DOC_MODE_MDWREN | DOC_MODE_NORMAL, + window, DOCControl); +#endif /* !DOC_PASSIVE_PROBE */ + + ChipID = ReadDOC(window, ChipID); + + switch (ChipID) { + case DOC_ChipID_Doc2k: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, 2k_ECCStatus) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + case DOC_ChipID_DocMil: + /* Check the TOGGLE bit in the ECC register */ + tmp = ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT; + if ((ReadDOC(window, ECCConf) & DOC_TOGGLE_BIT) != tmp) + return ChipID; + break; + + default: +#ifndef CFG_DOCPROBE_55AA +/* + * if the ID isn't the DoC2000 or DoCMillenium ID, so we can assume + * the DOC is missing + */ +# if 0 + printf("Possible DiskOnChip with unknown ChipID %2.2X found at 0x%lx\n", + ChipID, physadr); +# endif +#endif +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register, in case it's not + * actually a DiskOnChip. + */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; + } + + puts ("DiskOnChip failed TOGGLE test, dropping.\n"); + +#ifndef DOC_PASSIVE_PROBE + /* Put back the contents of the DOCControl register: it's not a DiskOnChip */ + WriteDOC(tmp2, window, DOCControl); +#endif + return 0; +} + +void doc_probe(unsigned long physadr) +{ + struct DiskOnChip *this = NULL; + int i=0, ChipID; + + if ((ChipID = doccheck(physadr, physadr))) { + + for (i=0; i<CFG_MAX_DOC_DEVICE; i++) { + if (doc_dev_desc[i].ChipID == DOC_ChipID_UNKNOWN) { + this = doc_dev_desc + i; + break; + } + } + + if (!this) { + puts ("Cannot allocate memory for data structures.\n"); + return; + } + + if (curr_device == -1) + curr_device = i; + + memset((char *)this, 0, sizeof(struct DiskOnChip)); + + this->virtadr = physadr; + this->physadr = physadr; + this->ChipID = ChipID; + + DoC2k_init(this); + } else { + puts ("No DiskOnChip found\n"); + } +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_DOC) */ diff --git a/common/cmd_ide.c b/common/cmd_ide.c new file mode 100644 index 0000000..9cbfe1b --- /dev/null +++ b/common/cmd_ide.c @@ -0,0 +1,1563 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +/* + * IDE support + */ +#include <common.h> +#include <config.h> +#include <watchdog.h> +#include <command.h> +#include <image.h> +#include <asm/byteorder.h> +#if defined(CONFIG_IDE_8xx_DIRECT) || defined(CONFIG_IDE_PCMCIA) +# include <pcmcia.h> +#endif +#ifdef CONFIG_8xx +# include <mpc8xx.h> +#endif +#include <ide.h> +#include <ata.h> +#include <cmd_ide.h> +#include <cmd_disk.h> +#ifdef CONFIG_STATUS_LED +# include <status_led.h> +#endif + +#ifdef CONFIG_SHOW_BOOT_PROGRESS +# include <status_led.h> +# define SHOW_BOOT_PROGRESS(arg) show_boot_progress(arg) +#else +# define SHOW_BOOT_PROGRESS(arg) +#endif + + +#undef IDE_DEBUG + +#ifdef IDE_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_IDE) + +/* Timings for IDE Interface + * + * SETUP / LENGTH / HOLD - cycles valid for 50 MHz clk + * 70 165 30 PIO-Mode 0, [ns] + * 4 9 2 [Cycles] + * 50 125 20 PIO-Mode 1, [ns] + * 3 7 2 [Cycles] + * 30 100 15 PIO-Mode 2, [ns] + * 2 6 1 [Cycles] + * 30 80 10 PIO-Mode 3, [ns] + * 2 5 1 [Cycles] + * 25 70 10 PIO-Mode 4, [ns] + * 2 4 1 [Cycles] + */ + +const static pio_config_t pio_config_ns [IDE_MAX_PIO_MODE+1] = +{ + /* Setup Length Hold */ + { 70, 165, 30 }, /* PIO-Mode 0, [ns] */ + { 50, 125, 20 }, /* PIO-Mode 1, [ns] */ + { 30, 101, 15 }, /* PIO-Mode 2, [ns] */ + { 30, 80, 10 }, /* PIO-Mode 3, [ns] */ + { 25, 70, 10 }, /* PIO-Mode 4, [ns] */ +}; + +static pio_config_t pio_config_clk [IDE_MAX_PIO_MODE+1]; + +#ifndef CFG_PIO_MODE +#define CFG_PIO_MODE 0 /* use a relaxed default */ +#endif +static int pio_mode = CFG_PIO_MODE; + +/* Make clock cycles and always round up */ + +#define PCMCIA_MK_CLKS( t, T ) (( (t) * (T) + 999U ) / 1000U ) + +/* ------------------------------------------------------------------------- */ + +/* Current I/O Device */ +static int curr_device = -1; + +/* Current offset for IDE0 / IDE1 bus access */ +ulong ide_bus_offset[CFG_IDE_MAXBUS] = { +#if defined(CFG_ATA_IDE0_OFFSET) + CFG_ATA_IDE0_OFFSET, +#endif +#if defined(CFG_ATA_IDE1_OFFSET) && (CFG_IDE_MAXBUS > 1) + CFG_ATA_IDE1_OFFSET, +#endif +}; + +#define ATA_CURR_BASE(dev) (CFG_ATA_BASE_ADDR+ide_bus_offset[IDE_BUS(dev)]) + +static int ide_bus_ok[CFG_IDE_MAXBUS]; + +static block_dev_desc_t ide_dev_desc[CFG_IDE_MAXDEVICE]; +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_LED +static void ide_led (uchar led, uchar status); +#else +#define ide_led(a,b) /* dummy */ +#endif + +#ifdef CONFIG_IDE_RESET +static void ide_reset (void); +#else +#define ide_reset() /* dummy */ +#endif + +static void ide_ident (block_dev_desc_t *dev_desc); +static uchar ide_wait (int dev, ulong t); + +#define IDE_TIME_OUT 2000 /* 2 sec timeout */ + +#define ATAPI_TIME_OUT 7000 /* 7 sec timeout (5 sec seems to work...) */ + +#define IDE_SPIN_UP_TIME_OUT 5000 /* 5 sec spin-up timeout */ + +static void __inline__ outb(int dev, int port, unsigned char val); +static unsigned char __inline__ inb(int dev, int port); +static void input_swap_data(int dev, ulong *sect_buf, int words); +static void input_data(int dev, ulong *sect_buf, int words); +static void output_data(int dev, ulong *sect_buf, int words); +static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len); + + +#ifdef CONFIG_ATAPI +static void atapi_inquiry(block_dev_desc_t *dev_desc); +ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer); +#endif + + +#ifdef CONFIG_IDE_8xx_DIRECT +static void set_pcmcia_timing (int pmode); +#else +#define set_pcmcia_timing(a) /* dummy */ +#endif + +/* ------------------------------------------------------------------------- */ + +int do_ide (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; + + switch (argc) { + case 0: + case 1: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 2: + if (strncmp(argv[1],"res",3) == 0) { + puts ("\nReset IDE" +#ifdef CONFIG_IDE_8xx_DIRECT + " on PCMCIA " PCMCIA_SLOT_MSG +#endif + ": "); + + ide_init (); + return 0; + } else if (strncmp(argv[1],"inf",3) == 0) { + int i; + + putc ('\n'); + + for (i=0; i<CFG_IDE_MAXDEVICE; ++i) { + if (ide_dev_desc[i].type==DEV_TYPE_UNKNOWN) + continue; /* list only known devices */ + printf ("IDE device %d: ", i); + dev_print(&ide_dev_desc[i]); + } + return 0; + + } else if (strncmp(argv[1],"dev",3) == 0) { + if ((curr_device < 0) || (curr_device >= CFG_IDE_MAXDEVICE)) { + puts ("\nno IDE devices available\n"); + return 1; + } + printf ("\nIDE device %d: ", curr_device); + dev_print(&ide_dev_desc[curr_device]); + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev, ok; + + for (ok=0, dev=0; dev<CFG_IDE_MAXDEVICE; ++dev) { + if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) { + ++ok; + if (dev) + putc ('\n'); + print_part(&ide_dev_desc[dev]); + } + } + if (!ok) { + puts ("\nno IDE devices available\n"); + rcode ++; + } + return rcode; + } + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + case 3: + if (strncmp(argv[1],"dev",3) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + printf ("\nIDE device %d: ", dev); + if (dev >= CFG_IDE_MAXDEVICE) { + puts ("unknown device\n"); + return 1; + } + dev_print(&ide_dev_desc[dev]); + /*ide_print (dev);*/ + + if (ide_dev_desc[dev].type == DEV_TYPE_UNKNOWN) { + return 1; + } + + curr_device = dev; + + puts ("... is now current device\n"); + + return 0; + } else if (strncmp(argv[1],"part",4) == 0) { + int dev = (int)simple_strtoul(argv[2], NULL, 10); + + if (ide_dev_desc[dev].part_type!=PART_TYPE_UNKNOWN) { + print_part(&ide_dev_desc[dev]); + } else { + printf ("\nIDE device %d not available\n", dev); + rcode = 1; + } + return rcode; +#if 0 + } else if (strncmp(argv[1],"pio",4) == 0) { + int mode = (int)simple_strtoul(argv[2], NULL, 10); + + if ((mode >= 0) && (mode <= IDE_MAX_PIO_MODE)) { + puts ("\nSetting "); + pio_mode = mode; + ide_init (); + } else { + printf ("\nInvalid PIO mode %d (0 ... %d only)\n", + mode, IDE_MAX_PIO_MODE); + } + return; +#endif + } + + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + default: + /* at least 4 args */ + + if (strcmp(argv[1],"read") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + + printf ("\nIDE read: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); + + n = ide_dev_desc[curr_device].block_read (curr_device, + blk, cnt, + (ulong *)addr); + /* flush cache after read */ + flush_cache (addr, cnt*ide_dev_desc[curr_device].blksz); + + printf ("%ld blocks read: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + if (n==cnt) { + return 0; + } else { + return 1; + } + } else if (strcmp(argv[1],"write") == 0) { + ulong addr = simple_strtoul(argv[2], NULL, 16); + ulong blk = simple_strtoul(argv[3], NULL, 16); + ulong cnt = simple_strtoul(argv[4], NULL, 16); + ulong n; + + printf ("\nIDE write: device %d block # %ld, count %ld ... ", + curr_device, blk, cnt); + + n = ide_write (curr_device, blk, cnt, (ulong *)addr); + + printf ("%ld blocks written: %s\n", + n, (n==cnt) ? "OK" : "ERROR"); + if (n==cnt) { + return 0; + } else { + return 1; + } + } else { + printf ("Usage:\n%s\n", cmdtp->usage); + rcode = 1; + } + + return rcode; + } +} + +int do_diskboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *boot_device = NULL; + char *ep; + int dev, part = 0; + ulong cnt; + ulong addr; + disk_partition_t info; + image_header_t *hdr; + int rcode = 0; + + switch (argc) { + case 1: + addr = CFG_LOAD_ADDR; + boot_device = getenv ("bootdevice"); + break; + case 2: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = getenv ("bootdevice"); + break; + case 3: + addr = simple_strtoul(argv[1], NULL, 16); + boot_device = argv[2]; + break; + default: + printf ("Usage:\n%s\n", cmdtp->usage); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (!boot_device) { + puts ("\n** No boot device **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + dev = simple_strtoul(boot_device, &ep, 16); + + if (ide_dev_desc[dev].type==DEV_TYPE_UNKNOWN) { + printf ("\n** Device %d not available\n", dev); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (*ep) { + if (*ep != ':') { + puts ("\n** Invalid boot device, use `dev[:part]' **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + part = simple_strtoul(++ep, NULL, 16); + } + if (get_partition_info (&ide_dev_desc[dev], part, &info)) { + SHOW_BOOT_PROGRESS (-1); + return 1; + } + if (strncmp(info.type, BOOT_PART_TYPE, sizeof(info.type)) != 0) { + printf ("\n** Invalid partition type \"%.32s\"" + " (expect \"" BOOT_PART_TYPE "\")\n", + info.type); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + printf ("\nLoading from IDE device %d, partition %d: " + "Name: %.32s Type: %.32s\n", + dev, part, info.name, info.type); + + PRINTF ("First Block: %ld, # of blocks: %ld, Block Size: %ld\n", + info.start, info.size, info.blksz); + + if (ide_dev_desc[dev].block_read (dev, info.start, 1, (ulong *)addr) != 1) { + printf ("** Read error on %d:%d\n", dev, part); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + hdr = (image_header_t *)addr; + + if (ntohl(hdr->ih_magic) == IH_MAGIC) { + + print_image_hdr (hdr); + + cnt = (ntohl(hdr->ih_size) + sizeof(image_header_t)); + cnt += info.blksz - 1; + cnt /= info.blksz; + cnt -= 1; + } else { + printf("\n** Bad Magic Number **\n"); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + if (ide_dev_desc[dev].block_read (dev, info.start+1, cnt, + (ulong *)(addr+info.blksz)) != cnt) { + printf ("** Read error on %d:%d\n", dev, part); + SHOW_BOOT_PROGRESS (-1); + return 1; + } + + + /* Loading ok, update default load address */ + + load_addr = addr; + + /* Check if we should attempt an auto-start */ + if (((ep = getenv("autostart")) != NULL) && (strcmp(ep,"yes") == 0)) { + char *local_args[2]; + extern int do_bootm (cmd_tbl_t *, int, int, char *[]); + + local_args[0] = argv[0]; + local_args[1] = NULL; + + printf ("Automatic boot of image at addr 0x%08lX ...\n", addr); + + do_bootm (cmdtp, 0, 1, local_args); + rcode = 1; + } + return rcode; +} + +/* ------------------------------------------------------------------------- */ + +void ide_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_IDE_8xx_DIRECT + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia); +#endif + unsigned char c; + int i, bus; + +#ifdef CONFIG_IDE_8xx_PCCARD + extern int pcmcia_on (void); + + WATCHDOG_RESET(); + + /* initialize the PCMCIA IDE adapter card */ + if (pcmcia_on()) + return; + udelay (1000000); /* 1 s */ +#endif /* CONFIG_IDE_8xx_PCCARD */ + + WATCHDOG_RESET(); + + /* Initialize PIO timing tables */ + for (i=0; i <= IDE_MAX_PIO_MODE; ++i) { + pio_config_clk[i].t_setup = PCMCIA_MK_CLKS(pio_config_ns[i].t_setup, + gd->bus_clk); + pio_config_clk[i].t_length = PCMCIA_MK_CLKS(pio_config_ns[i].t_length, + gd->bus_clk); + pio_config_clk[i].t_hold = PCMCIA_MK_CLKS(pio_config_ns[i].t_hold, + gd->bus_clk); + PRINTF ("PIO Mode %d: setup=%2d ns/%d clk" + " len=%3d ns/%d clk" + " hold=%2d ns/%d clk\n", + i, + pio_config_ns[i].t_setup, pio_config_clk[i].t_setup, + pio_config_ns[i].t_length, pio_config_clk[i].t_length, + pio_config_ns[i].t_hold, pio_config_clk[i].t_hold); + } + + /* Reset the IDE just to be sure. + * Light LED's to show + */ + ide_led ((LED_IDE1 | LED_IDE2), 1); /* LED's on */ + ide_reset (); /* ATAPI Drives seems to need a proper IDE Reset */ + +#ifdef CONFIG_IDE_8xx_DIRECT + /* PCMCIA / IDE initialization for common mem space */ + pcmp->pcmc_pgcrb = 0; +#endif + + /* start in PIO mode 0 - most relaxed timings */ + pio_mode = 0; + set_pcmcia_timing (pio_mode); + + /* + * Wait for IDE to get ready. + * According to spec, this can take up to 31 seconds! + */ + for (bus=0; bus<CFG_IDE_MAXBUS; ++bus) { + int dev = bus * (CFG_IDE_MAXDEVICE / CFG_IDE_MAXBUS); + + printf ("Bus %d: ", bus); + + ide_bus_ok[bus] = 0; + + /* Select device + */ + udelay (100000); /* 100 ms */ + outb (dev, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(dev)); + udelay (100000); /* 100 ms */ + + i = 0; + do { + udelay (10000); /* 10 ms */ + + c = inb (dev, ATA_STATUS); + i++; + if (i > (ATA_RESET_TIME * 100)) { + puts ("** Timeout **\n"); + ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + return; + } + if ((i >= 100) && ((i%100)==0)) { + putc ('.'); + } + } while (c & ATA_STAT_BUSY); + + if (c & (ATA_STAT_BUSY | ATA_STAT_FAULT)) { + puts ("not available "); + PRINTF ("Status = 0x%02X ", c); +#ifndef CONFIG_ATAPI /* ATAPI Devices do not set DRDY */ + } else if ((c & ATA_STAT_READY) == 0) { + puts ("not available "); + PRINTF ("Status = 0x%02X ", c); +#endif + } else { + puts ("OK "); + ide_bus_ok[bus] = 1; + } + WATCHDOG_RESET(); + } + putc ('\n'); + + ide_led ((LED_IDE1 | LED_IDE2), 0); /* LED's off */ + + curr_device = -1; + for (i=0; i<CFG_IDE_MAXDEVICE; ++i) { +#ifdef CONFIG_IDE_LED + int led = (IDE_BUS(i) == 0) ? LED_IDE1 : LED_IDE2; +#endif + ide_dev_desc[i].if_type=IF_TYPE_IDE; + ide_dev_desc[i].dev=i; + ide_dev_desc[i].part_type=PART_TYPE_UNKNOWN; + ide_dev_desc[i].blksz=0; + ide_dev_desc[i].lba=0; + ide_dev_desc[i].block_read=ide_read; + if (!ide_bus_ok[IDE_BUS(i)]) + continue; + ide_led (led, 1); /* LED on */ + ide_ident(&ide_dev_desc[i]); + ide_led (led, 0); /* LED off */ + dev_print(&ide_dev_desc[i]); +/* ide_print (i); */ + if ((ide_dev_desc[i].lba > 0) && (ide_dev_desc[i].blksz > 0)) { + init_part (&ide_dev_desc[i]); /* initialize partition type */ + if (curr_device < 0) + curr_device = i; + } + } + WATCHDOG_RESET(); +} + +/* ------------------------------------------------------------------------- */ + +block_dev_desc_t * ide_get_dev(int dev) +{ + return ((block_dev_desc_t *)&ide_dev_desc[dev]); +} + + +#ifdef CONFIG_IDE_8xx_DIRECT + +static void +set_pcmcia_timing (int pmode) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + volatile pcmconf8xx_t *pcmp = &(immr->im_pcmcia); + ulong timings; + + PRINTF ("Set timing for PIO Mode %d\n", pmode); + + timings = PCMCIA_SHT(pio_config_clk[pmode].t_hold) + | PCMCIA_SST(pio_config_clk[pmode].t_setup) + | PCMCIA_SL (pio_config_clk[pmode].t_length) + ; + + /* IDE 0 + */ + pcmp->pcmc_pbr0 = CFG_PCMCIA_PBR0; + pcmp->pcmc_por0 = CFG_PCMCIA_POR0 +#if (CFG_PCMCIA_POR0 != 0) + | timings +#endif + ; + PRINTF ("PBR0: %08x POR0: %08x\n", pcmp->pcmc_pbr0, pcmp->pcmc_por0); + + pcmp->pcmc_pbr1 = CFG_PCMCIA_PBR1; + pcmp->pcmc_por1 = CFG_PCMCIA_POR1 +#if (CFG_PCMCIA_POR1 != 0) + | timings +#endif + ; + PRINTF ("PBR1: %08x POR1: %08x\n", pcmp->pcmc_pbr1, pcmp->pcmc_por1); + + pcmp->pcmc_pbr2 = CFG_PCMCIA_PBR2; + pcmp->pcmc_por2 = CFG_PCMCIA_POR2 +#if (CFG_PCMCIA_POR2 != 0) + | timings +#endif + ; + PRINTF ("PBR2: %08x POR2: %08x\n", pcmp->pcmc_pbr2, pcmp->pcmc_por2); + + pcmp->pcmc_pbr3 = CFG_PCMCIA_PBR3; + pcmp->pcmc_por3 = CFG_PCMCIA_POR3 +#if (CFG_PCMCIA_POR3 != 0) + | timings +#endif + ; + PRINTF ("PBR3: %08x POR3: %08x\n", pcmp->pcmc_pbr3, pcmp->pcmc_por3); + + /* IDE 1 + */ + pcmp->pcmc_pbr4 = CFG_PCMCIA_PBR4; + pcmp->pcmc_por4 = CFG_PCMCIA_POR4 +#if (CFG_PCMCIA_POR4 != 0) + | timings +#endif + ; + PRINTF ("PBR4: %08x POR4: %08x\n", pcmp->pcmc_pbr4, pcmp->pcmc_por4); + + pcmp->pcmc_pbr5 = CFG_PCMCIA_PBR5; + pcmp->pcmc_por5 = CFG_PCMCIA_POR5 +#if (CFG_PCMCIA_POR5 != 0) + | timings +#endif + ; + PRINTF ("PBR5: %08x POR5: %08x\n", pcmp->pcmc_pbr5, pcmp->pcmc_por5); + + pcmp->pcmc_pbr6 = CFG_PCMCIA_PBR6; + pcmp->pcmc_por6 = CFG_PCMCIA_POR6 +#if (CFG_PCMCIA_POR6 != 0) + | timings +#endif + ; + PRINTF ("PBR6: %08x POR6: %08x\n", pcmp->pcmc_pbr6, pcmp->pcmc_por6); + + pcmp->pcmc_pbr7 = CFG_PCMCIA_PBR7; + pcmp->pcmc_por7 = CFG_PCMCIA_POR7 +#if (CFG_PCMCIA_POR7 != 0) + | timings +#endif + ; + PRINTF ("PBR7: %08x POR7: %08x\n", pcmp->pcmc_pbr7, pcmp->pcmc_por7); + +} + +#endif /* CONFIG_IDE_8xx_DIRECT */ + +/* ------------------------------------------------------------------------- */ + +static void __inline__ +outb(int dev, int port, unsigned char val) +{ + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + *((uchar *)(ATA_CURR_BASE(dev)+port)) = val; +#if 0 + printf ("OUTB: 0x%08lx <== 0x%02x\n", ATA_CURR_BASE(dev)+port, val); +#endif +} + +static unsigned char __inline__ +inb(int dev, int port) +{ + uchar val; + /* Ensure I/O operations complete */ + __asm__ volatile("eieio"); + val = *((uchar *)(ATA_CURR_BASE(dev)+port)); +#if 0 + printf ("INB: 0x%08lx ==> 0x%02x\n", ATA_CURR_BASE(dev)+port, val); +#endif + return (val); +} + +__inline__ unsigned ld_le16(const volatile unsigned short *addr) +{ + unsigned val; + + __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r"(val) : "r"(addr), "m"(*addr)); + return val; +} + +static void +input_swap_data(int dev, ulong *sect_buf, int words) +{ + volatile ushort *pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); + ushort *dbuf = (ushort *)sect_buf; + + while (words--) { + *dbuf++ = ld_le16(pbuf); + *dbuf++ = ld_le16(pbuf); + } +} + +static void +output_data(int dev, ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + __asm__ volatile ("eieio"); + *pbuf = *dbuf++; + __asm__ volatile ("eieio"); + *pbuf = *dbuf++; + } +} + +static void +input_data(int dev, ulong *sect_buf, int words) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (words--) { + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf; + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf; + } +} + +/* ------------------------------------------------------------------------- + */ +static void ide_ident (block_dev_desc_t *dev_desc) +{ + ulong iobuf[ATA_SECTORWORDS]; + unsigned char c; + hd_driveid_t *iop = (hd_driveid_t *)iobuf; + +#if 0 + int mode, cycle_time; +#endif + int device; + device=dev_desc->dev; + printf (" Device %d: ", device); + + ide_led (DEVICE_LED(device), 1); /* LED on */ + /* Select device + */ + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + dev_desc->if_type=IF_TYPE_IDE; +#ifdef CONFIG_ATAPI + /* check signature */ + if ((inb(device,ATA_SECT_CNT)==0x01) && + (inb(device,ATA_SECT_NUM)==0x01) && + (inb(device,ATA_CYL_LOW)==0x14) && + (inb(device,ATA_CYL_HIGH)==0xEB)) { + /* ATAPI Signature found */ + dev_desc->if_type=IF_TYPE_ATAPI; + /* Start Ident Command + */ + outb (device, ATA_COMMAND, ATAPI_CMD_IDENT); + /* + * Wait for completion - ATAPI devices need more time + * to become ready + */ + c = ide_wait (device, ATAPI_TIME_OUT); + } + else +#endif + { + /* Start Ident Command + */ + outb (device, ATA_COMMAND, ATA_CMD_IDENT); + + /* Wait for completion + */ + c = ide_wait (device, IDE_TIME_OUT); + } + ide_led (DEVICE_LED(device), 0); /* LED off */ + + if (((c & ATA_STAT_DRQ) == 0) || + ((c & (ATA_STAT_FAULT|ATA_STAT_ERR)) != 0) ) { + dev_desc->type=DEV_TYPE_UNKNOWN; + return; + } + + input_swap_data (device, iobuf, ATA_SECTORWORDS); + + ident_cpy (dev_desc->revision, iop->fw_rev, sizeof(dev_desc->revision)); + ident_cpy (dev_desc->vendor, iop->model, sizeof(dev_desc->vendor)); + ident_cpy (dev_desc->product, iop->serial_no, sizeof(dev_desc->product)); + + if ((iop->config & 0x0080)==0x0080) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + +#if 0 + /* + * Drive PIO mode autoselection + */ + mode = iop->tPIO; + + printf ("tPIO = 0x%02x = %d\n",mode, mode); + if (mode > 2) { /* 2 is maximum allowed tPIO value */ + mode = 2; + PRINTF ("Override tPIO -> 2\n"); + } + if (iop->field_valid & 2) { /* drive implements ATA2? */ + PRINTF ("Drive implements ATA2\n"); + if (iop->capability & 8) { /* drive supports use_iordy? */ + cycle_time = iop->eide_pio_iordy; + } else { + cycle_time = iop->eide_pio; + } + PRINTF ("cycle time = %d\n", cycle_time); + mode = 4; + if (cycle_time > 120) mode = 3; /* 120 ns for PIO mode 4 */ + if (cycle_time > 180) mode = 2; /* 180 ns for PIO mode 3 */ + if (cycle_time > 240) mode = 1; /* 240 ns for PIO mode 4 */ + if (cycle_time > 383) mode = 0; /* 383 ns for PIO mode 4 */ + } + printf ("PIO mode to use: PIO %d\n", mode); +#endif /* 0 */ + +#ifdef CONFIG_ATAPI + if (dev_desc->if_type==IF_TYPE_ATAPI) { + atapi_inquiry(dev_desc); + return; + } +#endif /* CONFIG_ATAPI */ + + /* swap shorts */ + dev_desc->lba = (iop->lba_capacity << 16) | (iop->lba_capacity >> 16); + /* assuming HD */ + dev_desc->type=DEV_TYPE_HARDDISK; + dev_desc->blksz=ATA_BLOCKSIZE; + dev_desc->lun=0; /* just to fill something in... */ + +#if 0 /* only used to test the powersaving mode, + * if enabled, the drive goes after 5 sec + * in standby mode */ + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait (device, IDE_TIME_OUT); + outb (device, ATA_SECT_CNT, 1); + outb (device, ATA_LBA_LOW, 0); + outb (device, ATA_LBA_MID, 0); + outb (device, ATA_LBA_HIGH, 0); + outb (device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device)); + outb (device, ATA_COMMAND, 0xe3); + udelay (50); + c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ +#endif +} + + +/* ------------------------------------------------------------------------- */ + +ulong ide_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) +{ + ulong n = 0; + unsigned char c; + unsigned char pwrsave=0; /* power save */ + + PRINTF ("ide_read dev %d start %lX, blocks %lX buffer at %lX\n", + device, blknr, blkcnt, (ulong)buffer); + + ide_led (DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = ide_wait (device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf ("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + + /* first check if the drive is in Powersaving mode, if yes, + * increase the timeout value */ + outb (device, ATA_COMMAND, ATA_CMD_CHK_PWR); + udelay (50); + + c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ + + if (c & ATA_STAT_BUSY) { + printf ("IDE read: device %d not ready\n", device); + goto IDE_READ_E; + } + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + printf ("No Powersaving mode %X\n", c); + } else { + c = inb(device,ATA_SECT_CNT); + PRINTF("Powersaving %02X\n",c); + if(c==0) + pwrsave=1; + } + + + while (blkcnt-- > 0) { + + c = ide_wait (device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf ("IDE read: device %d not ready\n", device); + break; + } + + outb (device, ATA_SECT_CNT, 1); + outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + outb (device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | + ((blknr >> 24) & 0xF) ); + outb (device, ATA_COMMAND, ATA_CMD_READ); + + udelay (50); + + if(pwrsave) { + c = ide_wait (device, IDE_SPIN_UP_TIME_OUT); /* may take up to 4 sec */ + pwrsave=0; + } else { + c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ + } + + if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { + printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", + device, blknr, c); + break; + } + + input_data (device, buffer, ATA_SECTORWORDS); + (void) inb (device, ATA_STATUS); /* clear IRQ */ + + ++n; + ++blknr; + buffer += ATA_SECTORWORDS; + } +IDE_READ_E: + ide_led (DEVICE_LED(device), 0); /* LED off */ + return (n); +} + +/* ------------------------------------------------------------------------- */ + + +ulong ide_write (int device, ulong blknr, ulong blkcnt, ulong *buffer) +{ + ulong n = 0; + unsigned char c; + + ide_led (DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + while (blkcnt-- > 0) { + + c = ide_wait (device, IDE_TIME_OUT); + + if (c & ATA_STAT_BUSY) { + printf ("IDE read: device %d not ready\n", device); + goto WR_OUT; + } + + outb (device, ATA_SECT_CNT, 1); + outb (device, ATA_LBA_LOW, (blknr >> 0) & 0xFF); + outb (device, ATA_LBA_MID, (blknr >> 8) & 0xFF); + outb (device, ATA_LBA_HIGH, (blknr >> 16) & 0xFF); + outb (device, ATA_DEV_HD, ATA_LBA | + ATA_DEVICE(device) | + ((blknr >> 24) & 0xF) ); + outb (device, ATA_COMMAND, ATA_CMD_WRITE); + + udelay (50); + + c = ide_wait (device, IDE_TIME_OUT); /* can't take over 500 ms */ + + if ((c&(ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR)) != ATA_STAT_DRQ) { + printf ("Error (no IRQ) dev %d blk %ld: status 0x%02x\n", + device, blknr, c); + goto WR_OUT; + } + + output_data (device, buffer, ATA_SECTORWORDS); + c = inb (device, ATA_STATUS); /* clear IRQ */ + ++n; + ++blknr; + buffer += ATA_SECTORWORDS; + } +WR_OUT: + ide_led (DEVICE_LED(device), 0); /* LED off */ + return (n); +} + +/* ------------------------------------------------------------------------- */ + +/* + * copy src to dest, skipping leading and trailing blanks and null + * terminate the string + */ +static void ident_cpy (unsigned char *dest, unsigned char *src, unsigned int len) +{ + int start,end; + + start=0; + while (start<len) { + if (src[start]!=' ') + break; + start++; + } + end=len-1; + while (end>start) { + if (src[end]!=' ') + break; + end--; + } + for ( ; start<=end; start++) { + *dest++=src[start]; + } + *dest='\0'; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Wait until Busy bit is off, or timeout (in ms) + * Return last status + */ +static uchar ide_wait (int dev, ulong t) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + while ((c = inb(dev, ATA_STATUS)) & ATA_STAT_BUSY) { + udelay (100); + if (delay-- == 0) { + break; + } + } + return (c); +} + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_RESET +extern void ide_set_reset(int idereset); + +static void ide_reset (void) +{ +#if defined(CFG_PB_12V_ENABLE) || defined(CFG_PB_IDE_MOTOR) + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + int i; + + curr_device = -1; + for (i=0; i<CFG_IDE_MAXBUS; ++i) + ide_bus_ok[i] = 0; + for (i=0; i<CFG_IDE_MAXDEVICE; ++i) + ide_dev_desc[i].type = DEV_TYPE_UNKNOWN; + + ide_set_reset (1); /* assert reset */ + + WATCHDOG_RESET(); + +#ifdef CFG_PB_12V_ENABLE + immr->im_cpm.cp_pbdat &= ~(CFG_PB_12V_ENABLE); /* 12V Enable output OFF */ + immr->im_cpm.cp_pbpar &= ~(CFG_PB_12V_ENABLE); + immr->im_cpm.cp_pbodr &= ~(CFG_PB_12V_ENABLE); + immr->im_cpm.cp_pbdir |= CFG_PB_12V_ENABLE; + + /* wait 500 ms for the voltage to stabilize + */ + for (i=0; i<500; ++i) { + udelay (1000); + } + + immr->im_cpm.cp_pbdat |= CFG_PB_12V_ENABLE; /* 12V Enable output ON */ +#endif /* CFG_PB_12V_ENABLE */ + +#ifdef CFG_PB_IDE_MOTOR + /* configure IDE Motor voltage monitor pin as input */ + immr->im_cpm.cp_pbpar &= ~(CFG_PB_IDE_MOTOR); + immr->im_cpm.cp_pbodr &= ~(CFG_PB_IDE_MOTOR); + immr->im_cpm.cp_pbdir &= ~(CFG_PB_IDE_MOTOR); + + /* wait up to 1 s for the motor voltage to stabilize + */ + for (i=0; i<1000; ++i) { + if ((immr->im_cpm.cp_pbdat & CFG_PB_IDE_MOTOR) != 0) { + break; + } + udelay (1000); + } + + if (i == 1000) { /* Timeout */ + printf ("\nWarning: 5V for IDE Motor missing\n"); +# ifdef CONFIG_STATUS_LED +# ifdef STATUS_LED_YELLOW + status_led_set (STATUS_LED_YELLOW, STATUS_LED_ON ); +# endif +# ifdef STATUS_LED_GREEN + status_led_set (STATUS_LED_GREEN, STATUS_LED_OFF); +# endif +# endif /* CONFIG_STATUS_LED */ + } +#endif /* CFG_PB_IDE_MOTOR */ + + WATCHDOG_RESET(); + + /* de-assert RESET signal */ + ide_set_reset(0); + + /* wait 250 ms */ + for (i=0; i<250; ++i) { + udelay (1000); + } +} + +#endif /* CONFIG_IDE_RESET */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_LED + +static uchar led_buffer = 0; /* Buffer for current LED status */ + +static void ide_led (uchar led, uchar status) +{ + uchar *led_port = LED_PORT; + + if (status) { /* switch LED on */ + led_buffer |= led; + } else { /* switch LED off */ + led_buffer &= ~led; + } + + *led_port = led_buffer; +} + +#endif /* CONFIG_IDE_LED */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_ATAPI +/**************************************************************************** + * ATAPI Support + */ + + + +#undef ATAPI_DEBUG + +#ifdef ATAPI_DEBUG +#define AT_PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define AT_PRINTF(fmt,args...) +#endif + +/* since ATAPI may use commands with not 4 bytes alligned length + * we have our own transfer functions, 2 bytes alligned */ +static void +output_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (shorts--) { + __asm__ volatile ("eieio"); + *pbuf = *dbuf++; + } +} + +static void +input_data_shorts(int dev, ushort *sect_buf, int shorts) +{ + ushort *dbuf; + volatile ushort *pbuf; + + pbuf = (ushort *)(ATA_CURR_BASE(dev)+ATA_DATA_REG); + dbuf = (ushort *)sect_buf; + while (shorts--) { + __asm__ volatile ("eieio"); + *dbuf++ = *pbuf; + } +} + +/* + * Wait until (Status & mask) == res, or timeout (in ms) + * Return last status + * This is used since some ATAPI CD ROMs clears their Busy Bit first + * and then they set their DRQ Bit + */ +static uchar atapi_wait_mask (int dev, ulong t,uchar mask, uchar res) +{ + ulong delay = 10 * t; /* poll every 100 us */ + uchar c; + + c = inb(dev,ATA_DEV_CTL); /* prevents to read the status before valid */ + while (((c = inb(dev, ATA_STATUS)) & mask) + != res) { + /* break if error occurs (doesn't make sense to wait more) */ + if((c & ATA_STAT_ERR)==ATA_STAT_ERR) + break; + udelay (100); + if (delay-- == 0) { + break; + } + } + return (c); +} + +/* + * issue an atapi command + */ +unsigned char atapi_issue(int device,unsigned char* ccb,int ccblen, unsigned char * buffer,int buflen) +{ + unsigned char c,err,mask,res; + int n; + ide_led (DEVICE_LED(device), 1); /* LED on */ + + /* Select device + */ + mask = ATA_STAT_BUSY|ATA_STAT_DRQ; + res = 0; + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res); + if ((c & mask) != res) { + printf ("ATAPI_ISSUE: device %d not ready status %X\n", device,c); + err=0xFF; + goto AI_OUT; + } + /* write taskfile */ + outb (device, ATA_ERROR_REG, 0); /* no DMA, no overlaped */ + outb (device, ATA_CYL_LOW, (unsigned char)(buflen & 0xFF)); + outb (device, ATA_CYL_HIGH, (unsigned char)((buflen<<8) & 0xFF)); + outb (device, ATA_DEV_HD, ATA_LBA | ATA_DEVICE(device)); + + outb (device, ATA_COMMAND, ATAPI_CMD_PACKET); + udelay (50); + + mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR; + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res); + + if ((c & mask) != res) { /* DRQ must be 1, BSY 0 */ + printf ("ATTAPI_ISSUE: Error (no IRQ) before sending ccb dev %d status 0x%02x\n",device,c); + err=0xFF; + goto AI_OUT; + } + + output_data_shorts (device, (unsigned short *)ccb,ccblen/2); /* write command block */ + /* ATAPI Command written wait for completition */ + udelay (5000); /* device must set bsy */ + + mask = ATA_STAT_DRQ|ATA_STAT_BUSY|ATA_STAT_ERR; + /* if no data wait for DRQ = 0 BSY = 0 + * if data wait for DRQ = 1 BSY = 0 */ + res=0; + if(buflen) + res = ATA_STAT_DRQ; + c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res); + if ((c & mask) != res ) { + if (c & ATA_STAT_ERR) { + err=(inb(device,ATA_ERROR_REG))>>4; + AT_PRINTF("atapi_issue 1 returned sense key %X status %02X\n",err,c); + } else { + printf ("ATTAPI_ISSUE: (no DRQ) after sending ccb (%x) status 0x%02x\n", ccb[0],c); + err=0xFF; + } + goto AI_OUT; + } + n=inb(device, ATA_CYL_HIGH); + n<<=8; + n+=inb(device, ATA_CYL_LOW); + if(n>buflen) { + printf("ERROR, transfer bytes %d requested only %d\n",n,buflen); + err=0xff; + goto AI_OUT; + } + if((n==0)&&(buflen<0)) { + printf("ERROR, transfer bytes %d requested %d\n",n,buflen); + err=0xff; + goto AI_OUT; + } + if(n!=buflen) { + AT_PRINTF("WARNING, transfer bytes %d not equal with requested %d\n",n,buflen); + } + if(n!=0) { /* data transfer */ + AT_PRINTF("ATAPI_ISSUE: %d Bytes to transfer\n",n); + /* we transfer shorts */ + n>>=1; + /* ok now decide if it is an in or output */ + if ((inb(device, ATA_SECT_CNT)&0x02)==0) { + AT_PRINTF("Write to device\n"); + output_data_shorts(device,(unsigned short *)buffer,n); + } else { + AT_PRINTF("Read from device @ %p shorts %d\n",buffer,n); + input_data_shorts(device,(unsigned short *)buffer,n); + } + } + udelay(5000); /* seems that some CD ROMs need this... */ + mask = ATA_STAT_BUSY|ATA_STAT_ERR; + res=0; + c = atapi_wait_mask(device,ATAPI_TIME_OUT,mask,res); + if ((c & ATA_STAT_ERR) == ATA_STAT_ERR) { + err=(inb(device,ATA_ERROR_REG) >> 4); + AT_PRINTF("atapi_issue 2 returned sense key %X status %X\n",err,c); + } else { + err = 0; + } +AI_OUT: + ide_led (DEVICE_LED(device), 0); /* LED off */ + return (err); +} + +/* + * sending the command to atapi_issue. If an status other than good + * returns, an request_sense will be issued + */ + +#define ATAPI_DRIVE_NOT_READY 100 +#define ATAPI_UNIT_ATTN 10 + +unsigned char atapi_issue_autoreq (int device, + unsigned char* ccb, + int ccblen, + unsigned char *buffer, + int buflen) +{ + unsigned char sense_data[18],sense_ccb[12]; + unsigned char res,key,asc,ascq; + int notready,unitattn; + + unitattn=ATAPI_UNIT_ATTN; + notready=ATAPI_DRIVE_NOT_READY; + +retry: + res= atapi_issue(device,ccb,ccblen,buffer,buflen); + if (res==0) + return (0); /* Ok */ + + if (res==0xFF) + return (0xFF); /* error */ + + AT_PRINTF("(auto_req)atapi_issue returned sense key %X\n",res); + + memset(sense_ccb,0,sizeof(sense_ccb)); + memset(sense_data,0,sizeof(sense_data)); + sense_ccb[0]=ATAPI_CMD_REQ_SENSE; + sense_ccb[4]=18; /* allocation Legnth */ + + res=atapi_issue(device,sense_ccb,12,sense_data,18); + key=(sense_data[2]&0xF); + asc=(sense_data[12]); + ascq=(sense_data[13]); + + AT_PRINTF("ATAPI_CMD_REQ_SENSE returned %x\n",res); + AT_PRINTF(" Sense page: %02X key %02X ASC %02X ASCQ %02X\n", + sense_data[0], + key, + asc, + ascq); + + if((key==0)) + return 0; /* ok device ready */ + + if((key==6)|| (asc==0x29) || (asc==0x28)) { /* Unit Attention */ + if(unitattn-->0) { + udelay(200*1000); + goto retry; + } + printf("Unit Attention, tried %d\n",ATAPI_UNIT_ATTN); + goto error; + } + if((asc==0x4) && (ascq==0x1)) { /* not ready, but will be ready soon */ + if (notready-->0) { + udelay(200*1000); + goto retry; + } + printf("Drive not ready, tried %d times\n",ATAPI_DRIVE_NOT_READY); + goto error; + } + if(asc==0x3a) { + AT_PRINTF("Media not present\n"); + goto error; + } + printf ("ERROR: Unknown Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq); +error: + AT_PRINTF ("ERROR Sense key %02X ASC %02X ASCQ %02X\n",key,asc,ascq); + return (0xFF); +} + + + +static void atapi_inquiry(block_dev_desc_t * dev_desc) +{ + unsigned char ccb[12]; /* Command descriptor block */ + unsigned char iobuf[64]; /* temp buf */ + unsigned char c; + int device; + + device=dev_desc->dev; + dev_desc->type=DEV_TYPE_UNKNOWN; /* not yet valid */ + dev_desc->block_read=atapi_read; + + memset(ccb,0,sizeof(ccb)); + memset(iobuf,0,sizeof(iobuf)); + + ccb[0]=ATAPI_CMD_INQUIRY; + ccb[4]=40; /* allocation Legnth */ + c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,40); + + AT_PRINTF("ATAPI_CMD_INQUIRY returned %x\n",c); + if (c!=0) + return; + + /* copy device ident strings */ + ident_cpy(dev_desc->vendor,&iobuf[8],8); + ident_cpy(dev_desc->product,&iobuf[16],16); + ident_cpy(dev_desc->revision,&iobuf[32],5); + + dev_desc->lun=0; + dev_desc->lba=0; + dev_desc->blksz=0; + dev_desc->type=iobuf[0] & 0x1f; + + if ((iobuf[1]&0x80)==0x80) + dev_desc->removable = 1; + else + dev_desc->removable = 0; + + memset(ccb,0,sizeof(ccb)); + memset(iobuf,0,sizeof(iobuf)); + ccb[0]=ATAPI_CMD_START_STOP; + ccb[4]=0x03; /* start */ + + c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0); + + AT_PRINTF("ATAPI_CMD_START_STOP returned %x\n",c); + if (c!=0) + return; + + memset(ccb,0,sizeof(ccb)); + memset(iobuf,0,sizeof(iobuf)); + c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,0); + + AT_PRINTF("ATAPI_CMD_UNIT_TEST_READY returned %x\n",c); + if (c!=0) + return; + + memset(ccb,0,sizeof(ccb)); + memset(iobuf,0,sizeof(iobuf)); + ccb[0]=ATAPI_CMD_READ_CAP; + c=atapi_issue_autoreq(device,ccb,12,(unsigned char *)iobuf,8); + AT_PRINTF("ATAPI_CMD_READ_CAP returned %x\n",c); + if (c!=0) + return; + + AT_PRINTF("Read Cap: LBA %02X%02X%02X%02X blksize %02X%02X%02X%02X\n", + iobuf[0],iobuf[1],iobuf[2],iobuf[3], + iobuf[4],iobuf[5],iobuf[6],iobuf[7]); + + dev_desc->lba =((unsigned long)iobuf[0]<<24) + + ((unsigned long)iobuf[1]<<16) + + ((unsigned long)iobuf[2]<< 8) + + ((unsigned long)iobuf[3]); + dev_desc->blksz=((unsigned long)iobuf[4]<<24) + + ((unsigned long)iobuf[5]<<16) + + ((unsigned long)iobuf[6]<< 8) + + ((unsigned long)iobuf[7]); + return; +} + + +/* + * atapi_read: + * we transfer only one block per command, since the multiple DRQ per + * command is not yet implemented + */ +#define ATAPI_READ_MAX_BYTES 2048 /* we read max 2kbytes */ +#define ATAPI_READ_BLOCK_SIZE 2048 /* assuming CD part */ +#define ATAPI_READ_MAX_BLOCK ATAPI_READ_MAX_BYTES/ATAPI_READ_BLOCK_SIZE /* max blocks */ + +ulong atapi_read (int device, ulong blknr, ulong blkcnt, ulong *buffer) +{ + ulong n = 0; + unsigned char ccb[12]; /* Command descriptor block */ + ulong cnt; + + AT_PRINTF("atapi_read dev %d start %lX, blocks %lX buffer at %lX\n", + device, blknr, blkcnt, (ulong)buffer); + + do { + if (blkcnt>ATAPI_READ_MAX_BLOCK) { + cnt=ATAPI_READ_MAX_BLOCK; + } else { + cnt=blkcnt; + } + ccb[0]=ATAPI_CMD_READ_12; + ccb[1]=0; /* reserved */ + ccb[2]=(unsigned char) (blknr>>24) & 0xFF; /* MSB Block */ + ccb[3]=(unsigned char) (blknr>>16) & 0xFF; /* */ + ccb[4]=(unsigned char) (blknr>> 8) & 0xFF; + ccb[5]=(unsigned char) blknr & 0xFF; /* LSB Block */ + ccb[6]=(unsigned char) (cnt >>24) & 0xFF; /* MSB Block count */ + ccb[7]=(unsigned char) (cnt >>16) & 0xFF; + ccb[8]=(unsigned char) (cnt >> 8) & 0xFF; + ccb[9]=(unsigned char) cnt & 0xFF; /* LSB Block */ + ccb[10]=0; /* reserved */ + ccb[11]=0; /* reserved */ + + if (atapi_issue_autoreq(device,ccb,12, + (unsigned char *)buffer, + cnt*ATAPI_READ_BLOCK_SIZE) == 0xFF) { + return (n); + } + n+=cnt; + blkcnt-=cnt; + blknr+=cnt; + buffer+=cnt*(ATAPI_READ_BLOCK_SIZE/4); /* ulong blocksize in ulong */ + } while (blkcnt > 0); + return (n); +} + +/* ------------------------------------------------------------------------- */ + +#endif /* CONFIG_ATAPI */ + +#endif /* CONFIG_COMMANDS & CFG_CMD_IDE */ diff --git a/common/cmd_immap.c b/common/cmd_immap.c new file mode 100644 index 0000000..443335b --- /dev/null +++ b/common/cmd_immap.c @@ -0,0 +1,578 @@ +/* + * (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 + */ + +/* + * MPC8xx/MPC8260 Internal Memory Map Functions + */ + +#include <common.h> +#include <command.h> +#include <cmd_immap.h> + +#if (CONFIG_COMMANDS & CFG_CMD_IMMAP) && \ + (defined(CONFIG_8xx) || defined(CONFIG_8260)) + +#if defined(CONFIG_8xx) +#include <asm/8xx_immap.h> +#include <commproc.h> +#elif defined(CONFIG_8260) +#include <asm/immap_8260.h> +#include <asm/cpm_8260.h> +#include <asm/iopin_8260.h> +#endif + +static void +unimplemented ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf ("Sorry, but the '%s' command has not been implemented\n", + cmdtp->name); +} + +int +do_siuinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + +#if defined(CONFIG_8xx) + volatile sysconf8xx_t *sc = &immap->im_siu_conf; +#elif defined(CONFIG_8260) + volatile sysconf8260_t *sc = &immap->im_siu_conf; +#endif + + printf ("SIUMCR= %08x SYPCR = %08x\n", sc->sc_siumcr, sc->sc_sypcr); +#if defined(CONFIG_8xx) + printf ("SWT = %08x\n", sc->sc_swt); + printf ("SIPEND= %08x SIMASK= %08x\n", sc->sc_sipend, sc->sc_simask); + printf ("SIEL = %08x SIVEC = %08x\n", sc->sc_siel, sc->sc_sivec); + printf ("TESR = %08x SDCR = %08x\n", sc->sc_tesr, sc->sc_sdcr); +#elif defined(CONFIG_8260) + printf ("BCR = %08x\n", sc->sc_bcr); + printf ("P_ACR = %02x P_ALRH= %08x P_ALRL= %08x\n", + sc->sc_ppc_acr, sc->sc_ppc_alrh, sc->sc_ppc_alrl); + printf ("L_ACR = %02x L_ALRH= %08x L_ALRL= %08x\n", + sc->sc_lcl_acr, sc->sc_lcl_alrh, sc->sc_lcl_alrl); + printf ("PTESR1= %08x PTESR2= %08x\n", sc->sc_tescr1, sc->sc_tescr2); + printf ("LTESR1= %08x LTESR2= %08x\n", sc->sc_ltescr1, sc->sc_ltescr2); + printf ("PDTEA = %08x PDTEM = %02x\n", sc->sc_pdtea, sc->sc_pdtem); + printf ("LDTEA = %08x LDTEM = %02x\n", sc->sc_ldtea, sc->sc_ldtem); +#endif + return 0; +} + +int +do_memcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + +#if defined(CONFIG_8xx) + volatile memctl8xx_t *memctl = &immap->im_memctl; + int nbanks = 8; +#elif defined(CONFIG_8260) + volatile memctl8260_t *memctl = &immap->im_memctl; + int nbanks = 12; +#endif + volatile uint *p = &memctl->memc_br0; + int i; + + for (i = 0; i < nbanks; i++, p += 2) { + if (i < 10) { + printf ("BR%d = %08x OR%d = %08x\n", + i, p[0], i, p[1]); + } else { + printf ("BR%d = %08x OR%d = %08x\n", + i, p[0], i, p[1]); + } + } + + printf ("MAR = %08x", memctl->memc_mar); +#if defined(CONFIG_8xx) + printf (" MCR = %08x\n", memctl->memc_mcr); +#elif defined(CONFIG_8260) + printf ("\n"); +#endif + printf ("MAMR = %08x MBMR = %08x", + memctl->memc_mamr, memctl->memc_mbmr); +#if defined(CONFIG_8xx) + printf ("\nMSTAT = %04x\n", memctl->memc_mstat); +#elif defined(CONFIG_8260) + printf (" MCMR = %08x\n", memctl->memc_mcmr); +#endif + printf ("MPTPR = %04x MDR = %08x\n", + memctl->memc_mptpr, memctl->memc_mdr); +#if defined(CONFIG_8260) + printf ("PSDMR = %08x LSDMR = %08x\n", + memctl->memc_psdmr, memctl->memc_lsdmr); + printf ("PURT = %02x PSRT = %02x\n", + memctl->memc_purt, memctl->memc_psrt); + printf ("LURT = %02x LSRT = %02x\n", + memctl->memc_lurt, memctl->memc_lsrt); + printf ("IMMR = %08x\n", memctl->memc_immr); +#endif + return 0; +} + +int +do_sitinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +#ifdef CONFIG_8260 +int +do_icinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} +#endif + +int +do_carinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +static int counter; + +static void +header(void) +{ + char *data = "\ + -------------------------------- --------------------------------\ + 00000000001111111111222222222233 00000000001111111111222222222233\ + 01234567890123456789012345678901 01234567890123456789012345678901\ + -------------------------------- --------------------------------\ + "; + int i; + + if (counter % 2) + putc('\n'); + counter = 0; + + for (i = 0; i < 4; i++, data += 79) + printf("%.79s\n", data); +} + +static void binary (char *label, uint value, int nbits) +{ + uint mask = 1 << (nbits - 1); + int i, second = (counter++ % 2); + + if (second) + putc (' '); + puts (label); + for (i = 32 + 1; i != nbits; i--) + putc (' '); + + while (mask != 0) { + if (value & mask) + putc ('1'); + else + putc ('0'); + mask >>= 1; + } + + if (second) + putc ('\n'); +} + +#if defined(CONFIG_8xx) +#define PA_NBITS 16 +#define PA_NB_ODR 8 +#define PB_NBITS 18 +#define PB_NB_ODR 16 +#define PC_NBITS 12 +#define PD_NBITS 13 +#elif defined(CONFIG_8260) +#define PA_NBITS 32 +#define PA_NB_ODR 32 +#define PB_NBITS 28 +#define PB_NB_ODR 28 +#define PC_NBITS 32 +#define PD_NBITS 28 +#endif + +int +do_iopinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + +#if defined(CONFIG_8xx) + volatile iop8xx_t *iop = &immap->im_ioport; + volatile ushort *l, *r; +#elif defined(CONFIG_8260) + volatile iop8260_t *iop = &immap->im_ioport; + volatile uint *l, *r; +#endif + volatile uint *R; + + counter = 0; + header (); + + /* + * Ports A & B + */ + +#if defined(CONFIG_8xx) + l = &iop->iop_padir; + R = &immap->im_cpm.cp_pbdir; +#elif defined(CONFIG_8260) + l = &iop->iop_pdira; + R = &iop->iop_pdirb; +#endif + binary ("PA_DIR", *l++, PA_NBITS); + binary ("PB_DIR", *R++, PB_NBITS); + binary ("PA_PAR", *l++, PA_NBITS); + binary ("PB_PAR", *R++, PB_NBITS); +#if defined(CONFIG_8260) + binary ("PA_SOR", *l++, PA_NBITS); + binary ("PB_SOR", *R++, PB_NBITS); +#endif + binary ("PA_ODR", *l++, PA_NB_ODR); + binary ("PB_ODR", *R++, PB_NB_ODR); + binary ("PA_DAT", *l++, PA_NBITS); + binary ("PB_DAT", *R++, PB_NBITS); + + header (); + + /* + * Ports C & D + */ + +#if defined(CONFIG_8xx) + l = &iop->iop_pcdir; + r = &iop->iop_pddir; +#elif defined(CONFIG_8260) + l = &iop->iop_pdirc; + r = &iop->iop_pdird; +#endif + binary ("PC_DIR", *l++, PC_NBITS); + binary ("PD_DIR", *r++, PD_NBITS); + binary ("PC_PAR", *l++, PC_NBITS); + binary ("PD_PAR", *r++, PD_NBITS); +#if defined(CONFIG_8xx) + binary ("PC_SO ", *l++, PC_NBITS); + binary (" ", 0, 0); + r++; +#elif defined(CONFIG_8260) + binary ("PC_SOR", *l++, PC_NBITS); + binary ("PD_SOR", *r++, PD_NBITS); + binary ("PC_ODR", *l++, PC_NBITS); + binary ("PD_ODR", *r++, PD_NBITS); +#endif + binary ("PC_DAT", *l++, PC_NBITS); + binary ("PD_DAT", *r++, PD_NBITS); +#if defined(CONFIG_8xx) + binary ("PC_INT", *l++, PC_NBITS); +#endif + + header (); + return 0; +} + +/* + * set the io pins + * this needs a clean up for smaller tighter code + * use *uint and set the address based on cmd + port + */ +int +do_iopset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(CONFIG_8260) + uint rcode = 0; + static uint port = 0; + static uint pin = 0; + static uint value = 0; + static enum { DIR, PAR, SOR, ODR, DAT } cmd = DAT; + iopin_t iopin; + + if (argc != 5) { + printf ("iopset PORT PIN CMD VALUE\n"); + return 1; + } + port = argv[1][0] - 'A'; + if (port > 3) + port -= 0x20; + if (port > 3) + rcode = 1; + pin = simple_strtol (argv[2], NULL, 10); + if (pin > 31) + rcode = 1; + + + switch (argv[3][0]) { + case 'd': + if (argv[3][1] == 'a') + cmd = DAT; + else if (argv[3][1] == 'i') + cmd = DIR; + else + rcode = 1; + break; + case 'p': + cmd = PAR; + break; + case 'o': + cmd = ODR; + break; + case 's': + cmd = SOR; + break; + default: + printf ("iopset: unknown command %s\n", argv[3]); + rcode = 1; + } + if (argv[4][0] == '1') + value = 1; + else if (argv[4][0] == '0') + value = 0; + else + rcode = 1; + if (rcode == 0) { + iopin.port = port; + iopin.pin = pin; + switch (cmd) { + case DIR: + if (value) + iopin_set_out (&iopin); + else + iopin_set_in (&iopin); + break; + case PAR: + if (value) + iopin_set_ded (&iopin); + else + iopin_set_gen (&iopin); + break; + case SOR: + if (value) + iopin_set_opt2 (&iopin); + else + iopin_set_opt1 (&iopin); + break; + case ODR: + if (value) + iopin_set_odr (&iopin); + else + iopin_set_act (&iopin); + break; + case DAT: + if (value) + iopin_set_high (&iopin); + else + iopin_set_low (&iopin); + break; + } + + } + return rcode; +#else + unimplemented (cmdtp, flag, argc, argv); + return 0; +#endif +} + +int +do_dmainfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_fccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +static void prbrg (int n, uint val) +{ + uint extc = (val >> 14) & 3; + uint cd = (val & CPM_BRG_CD_MASK) >> 1; + uint div16 = (val & CPM_BRG_DIV16) != 0; + +#if defined(CONFIG_8xx) + DECLARE_GLOBAL_DATA_PTR; + ulong clock = gd->cpu_clk; +#elif defined(CONFIG_8260) + DECLARE_GLOBAL_DATA_PTR; + ulong clock = gd->brg_clk; +#endif + + printf ("BRG%d:", n); + + if (val & CPM_BRG_RST) + puts (" RESET"); + else + puts (" "); + + if (val & CPM_BRG_EN) + puts (" ENABLED"); + else + puts (" DISABLED"); + + printf (" EXTC=%d", extc); + + if (val & CPM_BRG_ATB) + puts (" ATB"); + else + puts (" "); + + printf (" DIVIDER=%4d", cd); + if (extc == 0 && cd != 0) { + uint baudrate; + + if (div16) + baudrate = (clock / 16) / (cd + 1); + else + baudrate = clock / (cd + 1); + + printf ("=%6d bps", baudrate); + } else { + puts (" "); + } + + if (val & CPM_BRG_DIV16) + puts (" DIV16"); + else + puts (" "); + + putc ('\n'); +} + +int +do_brginfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + +#if defined(CONFIG_8xx) + volatile cpm8xx_t *cp = &immap->im_cpm; + volatile uint *p = &cp->cp_brgc1; +#elif defined(CONFIG_8260) + volatile uint *p = &immap->im_brgc1; +#endif + int i = 1; + + while (i <= 4) + prbrg (i++, *p++); + +#if defined(CONFIG_8260) + p = &immap->im_brgc5; + while (i <= 8) + prbrg (i++, *p++); +#endif + return 0; +} + +int +do_i2cinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + +#if defined(CONFIG_8xx) + volatile i2c8xx_t *i2c = &immap->im_i2c; + volatile cpm8xx_t *cp = &immap->im_cpm; + volatile iic_t *iip = (iic_t *) & cp->cp_dparam[PROFF_IIC]; +#elif defined(CONFIG_8260) + volatile i2c8260_t *i2c = &immap->im_i2c; + volatile iic_t *iip; + uint dpaddr; + + dpaddr = *((unsigned short *) (&immap->im_dprambase[PROFF_I2C_BASE])); + if (dpaddr == 0) + iip = NULL; + else + iip = (iic_t *) & immap->im_dprambase[dpaddr]; +#endif + + printf ("I2MOD = %02x I2ADD = %02x\n", i2c->i2c_i2mod, i2c->i2c_i2add); + printf ("I2BRG = %02x I2COM = %02x\n", i2c->i2c_i2brg, i2c->i2c_i2com); + printf ("I2CER = %02x I2CMR = %02x\n", i2c->i2c_i2cer, i2c->i2c_i2cmr); + + if (iip == NULL) + printf ("i2c parameter ram not allocated\n"); + else { + printf ("RBASE = %08x TBASE = %08x\n", + iip->iic_rbase, iip->iic_tbase); + printf ("RFCR = %02x TFCR = %02x\n", + iip->iic_rfcr, iip->iic_tfcr); + printf ("MRBLR = %04x\n", iip->iic_mrblr); + printf ("RSTATE= %08x RDP = %08x\n", + iip->iic_rstate, iip->iic_rdp); + printf ("RBPTR = %04x RBC = %04x\n", + iip->iic_rbptr, iip->iic_rbc); + printf ("RXTMP = %08x\n", iip->iic_rxtmp); + printf ("TSTATE= %08x TDP = %08x\n", + iip->iic_tstate, iip->iic_tdp); + printf ("TBPTR = %04x TBC = %04x\n", + iip->iic_tbptr, iip->iic_tbc); + printf ("TXTMP = %08x\n", iip->iic_txtmp); + } + return 0; +} + +int +do_sccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_smcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_spiinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_muxinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_siinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} + +int +do_mccinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + unimplemented (cmdtp, flag, argc, argv); + return 0; +} +#endif /* CFG_CMD_IMMAP && (CONFIG_8xx || CONFIG_8260) */ diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c new file mode 100644 index 0000000..fc1d9c4 --- /dev/null +++ b/common/cmd_jffs2.c @@ -0,0 +1,179 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Boot support + */ +#include <common.h> +#include <command.h> +#include <cmd_boot.h> +#include <cmd_autoscript.h> +#include <s_record.h> +#include <net.h> + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) + +#include <jffs2/jffs2.h> +static int part_num=0; + +#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_num==0){ + + if(part.usr_priv==(void*)1) + return ∂ + + 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]; +#else + 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; + +#if defined(CFG_JFFS2_FIRST_SECTOR) && (CFG_JFFS2_FIRST_SECTOR > 0) + 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; + + /* Mark the struct as ready */ + part.usr_priv=(void*)1; + + return ∂ + } + return 0; +} +#endif /* ifndef CFG_JFFS_CUSTOM_PART */ +int +do_jffs2_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *filename = "pImage"; + ulong offset = CFG_LOAD_ADDR; + int size; + struct part_info *part; + + if (argc == 2) { + filename = argv[1]; + } + if (argc == 3) { + offset = simple_strtoul(argv[1], NULL, 16); + filename = argv[2]; + } + + if (0 != (part=jffs2_part_info(part_num))){ + + printf("### JFFS2 loading '%s' to 0x%lx\n", filename, offset); + size = jffs2_1pass_load((char *)offset, part, filename); + + if (size > 0) { + char buf[10]; + printf("### JFFS2 load complete: %d bytes loaded to 0x%lx\n", + size, offset); + sprintf(buf, "%x", size); + setenv("filesize", buf); + } else { + printf("### JFFS2 LOAD ERROR<%x> for %s!\n", size, filename); + } + + return !(size > 0); + } + printf("Active partition not valid\n"); + return 0; +} + +int +do_jffs2_ls(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + char *filename = "/"; + int ret; + struct part_info *part; + + if (argc == 2) + filename = argv[1]; + + if (0 != (part=jffs2_part_info(part_num))){ + + ret = jffs2_1pass_ls(jffs2_part_info(part_num), filename); + + return (ret == 1); + } + printf("Active partition not valid\n"); + return 0; +} + +int +do_jffs2_fsinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int ret; + struct part_info *part; + + if (0 != (part=jffs2_part_info(part_num))){ + + ret = jffs2_1pass_info(jffs2_part_info(part_num)); + + return (ret == 1); + } + printf("Active partition not valid\n"); + return 0; +} + +int +do_jffs2_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int tmp_part; + + if (argc >= 2) { + tmp_part = simple_strtoul(argv[1], NULL, 16); + }else{ + printf("Need partition number in argument list\n"); + return 0; + + } + + if (jffs2_part_info(tmp_part)){ + printf("Partiton changed to %d\n",tmp_part); + part_num=tmp_part; + return 0; + } + + printf("Partition %d is not valid partiton\n",tmp_part); + return 0; + +} +#endif /* CFG_CMD_JFFS2 */ diff --git a/common/cmd_pci.c b/common/cmd_pci.c new file mode 100644 index 0000000..22e4b9a --- /dev/null +++ b/common/cmd_pci.c @@ -0,0 +1,477 @@ +/* + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * Wolfgang Grandegger, DENX Software Engineering, wg@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 + */ + +/* + * PCI routines + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <command.h> +#include <cmd_boot.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <cmd_pci.h> +#include <pci.h> + +#if (CONFIG_COMMANDS & CFG_CMD_PCI) + +extern int cmd_get_data_size(char* arg, int default_size); + +unsigned char ShortPCIListing = 1; + +/* + * Follows routines for the output of infos about devices on PCI bus. + */ + +void pci_header_show(pci_dev_t dev); +void pci_header_show_brief(pci_dev_t dev); + +/* + * Subroutine: pciinfo + * + * Description: Show information about devices on PCI bus. + * Depending on the define CFG_SHORT_PCI_LISTING + * the output will be more or less exhaustive. + * + * Inputs: bus_no the number of the bus to be scanned. + * + * Return: None + * + */ +void pciinfo(int BusNum, int ShortPCIListing) +{ + int Device; + int Function; + unsigned char HeaderType; + unsigned short VendorID; + pci_dev_t dev; + + printf("Scanning PCI devices on bus %d\n", BusNum); + + if (ShortPCIListing) { + printf("BusDevFun VendorId DeviceId Device Class Sub-Class\n"); + printf("_____________________________________________________________\n"); + } + + for (Device = 0; Device < PCI_MAX_PCI_DEVICES; Device++) { + HeaderType = 0; + VendorID = 0; + for (Function = 0; Function < PCI_MAX_PCI_FUNCTIONS; Function++) { + /* + * If this is not a multi-function device, we skip the rest. + */ + if (Function && !(HeaderType & 0x80)) + break; + + dev = PCI_BDF(BusNum, Device, Function); + + pci_read_config_word(dev, PCI_VENDOR_ID, &VendorID); + if ((VendorID == 0xFFFF) || (VendorID == 0x0000)) + continue; + + pci_read_config_byte(dev, PCI_HEADER_TYPE, &HeaderType); + + if (ShortPCIListing) + { + printf("%02x.%02x.%02x ", BusNum, Device, Function); + pci_header_show_brief(dev); + } + else + { + printf("\nFound PCI device %02x.%02x.%02x:\n", + BusNum, Device, Function); + pci_header_show(dev); + } + } + } +} + +char* pci_classes_str(u8 class) +{ + static char *pci_classes[] = { + "Build before PCI Rev2.0", + "Mass storage controller", + "Network controller ", + "Display controller ", + "Multimedia device ", + "Memory controller ", + "Bridge device ", + "Simple comm. controller", + "Base system peripheral ", + "Input device ", + "Docking station ", + "Processor ", + "Serial bus controller ", + "Reserved entry ", + "Does not fit any class " + }; + + if (class < (sizeof pci_classes / sizeof *pci_classes)) + return pci_classes[(int) class]; + + return "??? "; +} + +/* + * Subroutine: pci_header_show_brief + * + * Description: Reads and prints the header of the + * specified PCI device in short form. + * + * Inputs: dev Bus+Device+Function number + * + * Return: None + * + */ +void pci_header_show_brief(pci_dev_t dev) +{ + u16 vendor, device; + u8 class, subclass; + + pci_read_config_word(dev, PCI_VENDOR_ID, &vendor); + pci_read_config_word(dev, PCI_DEVICE_ID, &device); + pci_read_config_byte(dev, PCI_CLASS_CODE, &class); + pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &subclass); + + printf("0x%.4x 0x%.4x %s 0x%.2x\n", + vendor, device, + pci_classes_str(class), subclass); +} + +/* + * Subroutine: PCI_Header_Show + * + * Description: Reads the header of the specified PCI device. + * + * Inputs: BusDevFunc Bus+Device+Function number + * + * Return: None + * + */ +void pci_header_show(pci_dev_t dev) +{ + u8 _byte, header_type; + u16 _word; + u32 _dword; + +#define PRINT(msg, type, reg) \ + pci_read_config_##type(dev, reg, &_##type); \ + printf(msg, _##type) + +#define PRINT2(msg, type, reg, func) \ + pci_read_config_##type(dev, reg, &_##type); \ + printf(msg, _##type, func(_##type)) + + pci_read_config_byte(dev, PCI_HEADER_TYPE, &header_type); + + PRINT (" vendor ID = 0x%.4x\n", word, PCI_VENDOR_ID); + PRINT (" device ID = 0x%.4x\n", word, PCI_DEVICE_ID); + PRINT (" command register = 0x%.4x\n", word, PCI_COMMAND); + PRINT (" status register = 0x%.4x\n", word, PCI_STATUS); + PRINT (" revision ID = 0x%.2x\n", byte, PCI_REVISION_ID); + PRINT2(" class code = 0x%.2x (%s)\n", byte, PCI_CLASS_CODE, + pci_classes_str); + PRINT (" sub class code = 0x%.2x\n", byte, PCI_CLASS_SUB_CODE); + PRINT (" programming interface = 0x%.2x\n", byte, PCI_CLASS_PROG); + PRINT (" cache line = 0x%.2x\n", byte, PCI_CACHE_LINE_SIZE); + PRINT (" latency time = 0x%.2x\n", byte, PCI_LATENCY_TIMER); + PRINT (" header type = 0x%.2x\n", byte, PCI_HEADER_TYPE); + PRINT (" BIST = 0x%.2x\n", byte, PCI_BIST); + PRINT (" base address 0 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_0); + PRINT (" base address 1 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_1); + + if (header_type & 0x01) { /* PCI-to-PCI bridge */ + PRINT (" primary bus number = 0x%.2x\n", byte, PCI_PRIMARY_BUS); + PRINT (" secondary bus number = 0x%.2x\n", byte, PCI_SECONDARY_BUS); + PRINT (" subordinate bus number = 0x%.2x\n", byte, PCI_SUBORDINATE_BUS); + PRINT (" secondary latency timer = 0x%.2x\n", byte, PCI_SEC_LATENCY_TIMER); + PRINT (" IO base = 0x%.2x\n", byte, PCI_IO_BASE); + PRINT (" IO limit = 0x%.2x\n", byte, PCI_IO_LIMIT); + PRINT (" secondary status = 0x%.4x\n", word, PCI_SEC_STATUS); + PRINT (" memory base = 0x%.4x\n", word, PCI_MEMORY_BASE); + PRINT (" memory limit = 0x%.4x\n", word, PCI_MEMORY_LIMIT); + PRINT (" prefetch memory base = 0x%.4x\n", word, PCI_PREF_MEMORY_BASE); + PRINT (" prefetch memory limit = 0x%.4x\n", word, PCI_PREF_MEMORY_LIMIT); + PRINT (" prefetch memory base upper = 0x%.8x\n", dword, PCI_PREF_BASE_UPPER32); + PRINT (" prefetch memory limit upper = 0x%.8x\n", dword, PCI_PREF_LIMIT_UPPER32); + PRINT (" IO base upper 16 bits = 0x%.4x\n", word, PCI_IO_BASE_UPPER16); + PRINT (" IO limit upper 16 bits = 0x%.4x\n", word, PCI_IO_LIMIT_UPPER16); + PRINT (" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS1); + PRINT (" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE); + PRINT (" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN); + PRINT (" bridge control = 0x%.4x\n", word, PCI_BRIDGE_CONTROL); + } else { /* PCI device */ + PRINT(" base address 2 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_2); + PRINT(" base address 3 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_3); + PRINT(" base address 4 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_4); + PRINT(" base address 5 = 0x%.8x\n", dword, PCI_BASE_ADDRESS_5); + PRINT(" cardBus CIS pointer = 0x%.8x\n", dword, PCI_CARDBUS_CIS); + PRINT(" sub system vendor ID = 0x%.4x\n", word, PCI_SUBSYSTEM_VENDOR_ID); + PRINT(" sub system ID = 0x%.4x\n", word, PCI_SUBSYSTEM_ID); + PRINT(" expansion ROM base address = 0x%.8x\n", dword, PCI_ROM_ADDRESS); + PRINT(" interrupt line = 0x%.2x\n", byte, PCI_INTERRUPT_LINE); + PRINT(" interrupt pin = 0x%.2x\n", byte, PCI_INTERRUPT_PIN); + PRINT(" min Grant = 0x%.2x\n", byte, PCI_MIN_GNT); + PRINT(" max Latency = 0x%.2x\n", byte, PCI_MAX_LAT); + } + +#undef PRINT +#undef PRINT2 +} + +/* Convert the "bus.device.function" identifier into a number. + */ +static pci_dev_t get_pci_dev(char* name) +{ + char cnum[12]; + int len, i, iold, n; + int bdfs[3] = {0,0,0}; + + len = strlen(name); + if (len > 8) + return -1; + for (i = 0, iold = 0, n = 0; i < len; i++) { + if (name[i] == '.') { + memcpy(cnum, &name[iold], i - iold); + cnum[i - iold] = '\0'; + bdfs[n++] = simple_strtoul(cnum, NULL, 16); + iold = i + 1; + } + } + strcpy(cnum, &name[iold]); + if (n == 0) + n = 1; + bdfs[n] = simple_strtoul(cnum, NULL, 16); + return PCI_BDF(bdfs[0], bdfs[1], bdfs[2]); +} + +static int pci_cfg_display(pci_dev_t bdf, ulong addr, ulong size, ulong length) +{ +#define DISP_LINE_LEN 16 + ulong i, nbytes, linebytes; + int rc = 0; + + if (length == 0) + length = 0x40 / size; /* Standard PCI configuration space */ + + /* Print the lines. + * once, and all accesses are with the specified bus width. + */ + nbytes = length * size; + do { + uint val4; + ushort val2; + u_char val1; + + printf("%08lx:", addr); + linebytes = (nbytes>DISP_LINE_LEN)?DISP_LINE_LEN:nbytes; + for (i=0; i<linebytes; i+= size) { + if (size == 4) { + pci_read_config_dword(bdf, addr, &val4); + printf(" %08x", val4); + } else if (size == 2) { + pci_read_config_word(bdf, addr, &val2); + printf(" %04x", val2); + } else { + pci_read_config_byte(bdf, addr, &val1); + printf(" %02x", val1); + } + addr += size; + } + printf("\n"); + nbytes -= linebytes; + if (ctrlc()) { + rc = 1; + break; + } + } while (nbytes > 0); + + return (rc); +} + +static int pci_cfg_write (pci_dev_t bdf, ulong addr, ulong size, ulong value) +{ + if (size == 4) { + pci_write_config_dword(bdf, addr, value); + } + else if (size == 2) { + ushort val = value & 0xffff; + pci_write_config_word(bdf, addr, val); + } + else { + u_char val = value & 0xff; + pci_write_config_byte(bdf, addr, val); + } + return 0; +} + +static int +pci_cfg_modify (pci_dev_t bdf, ulong addr, ulong size, ulong value, int incrflag) +{ + ulong i; + int nbytes; + extern char console_buffer[]; + uint val4; + ushort val2; + u_char val1; + + /* Print the address, followed by value. Then accept input for + * the next value. A non-converted value exits. + */ + do { + printf("%08lx:", addr); + if (size == 4) { + pci_read_config_dword(bdf, addr, &val4); + printf(" %08x", val4); + } + else if (size == 2) { + pci_read_config_word(bdf, addr, &val2); + printf(" %04x", val2); + } + else { + pci_read_config_byte(bdf, addr, &val1); + printf(" %02x", val1); + } + + nbytes = readline (" ? "); + if (nbytes == 0 || (nbytes == 1 && console_buffer[0] == '-')) { + /* <CR> pressed as only input, don't modify current + * location and move to next. "-" pressed will go back. + */ + if (incrflag) + addr += nbytes ? -size : size; + nbytes = 1; +#ifdef CONFIG_BOOT_RETRY_TIME + reset_cmd_timeout(); /* good enough to not time out */ +#endif + } +#ifdef CONFIG_BOOT_RETRY_TIME + else if (nbytes == -2) { + break; /* timed out, exit the command */ + } +#endif + else { + char *endp; + i = simple_strtoul(console_buffer, &endp, 16); + nbytes = endp - console_buffer; + if (nbytes) { +#ifdef CONFIG_BOOT_RETRY_TIME + /* good enough to not time out + */ + reset_cmd_timeout(); +#endif + pci_cfg_write (bdf, addr, size, i); + if (incrflag) + addr += size; + } + } + } while (nbytes); + + return 0; +} + +/* PCI Configuration Space access commands + * + * Syntax: + * pci display[.b, .w, .l] bus.device.function} [addr] [len] + * pci next[.b, .w, .l] bus.device.function [addr] + * pci modify[.b, .w, .l] bus.device.function [addr] + * pci write[.b, .w, .l] bus.device.function addr value + */ +int do_pci (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + ulong addr = 0, value = 0, size = 0; + pci_dev_t bdf = 0; + char cmd = 's'; + + if (argc > 1) + cmd = argv[1][0]; + + switch (cmd) { + case 'd': /* display */ + case 'n': /* next */ + case 'm': /* modify */ + case 'w': /* write */ + /* Check for a size specification. */ + size = cmd_get_data_size(argv[1], 4); + if (argc > 3) + addr = simple_strtoul(argv[3], NULL, 16); + if (argc > 4) + value = simple_strtoul(argv[4], NULL, 16); + case 'h': /* header */ + if (argc < 3) + goto usage; + if ((bdf = get_pci_dev(argv[2])) == -1) + return 1; + break; + default: /* scan bus */ + value = 1; /* short listing */ + bdf = 0; /* bus number */ + if (argc > 1) { + if (argv[argc-1][0] == 'l') { + value = 0; + argc--; + } + if (argc > 1) + bdf = simple_strtoul(argv[1], NULL, 16); + } + pciinfo(bdf, value); + return 0; + } + + switch (argv[1][0]) { + case 'h': /* header */ + pci_header_show(bdf); + return 0; + case 'd': /* display */ + return pci_cfg_display(bdf, addr, size, value); + case 'n': /* next */ + if (argc < 4) + goto usage; + return pci_cfg_modify(bdf, addr, size, value, 0); + case 'm': /* modify */ + if (argc < 4) + goto usage; + return pci_cfg_modify(bdf, addr, size, value, 1); + case 'w': /* write */ + if (argc < 5) + goto usage; + return pci_cfg_write(bdf, addr, size, value); + } + + return 1; + usage: + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; +} + +#endif /* (CONFIG_COMMANDS & CFG_CMD_PCI) */ + +#endif /* CONFIG_PCI */ diff --git a/common/cmd_pcmcia.c b/common/cmd_pcmcia.c new file mode 100644 index 0000000..ccf21a9 --- /dev/null +++ b/common/cmd_pcmcia.c @@ -0,0 +1,2243 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ******************************************************************** + * + * Lots of code copied from: + * + * m8xx_pcmcia.c - Linux PCMCIA socket driver for the mpc8xx series. + * (C) 1999-2000 Magnus Damm <damm@bitsmart.com> + * + * "The ExCA standard specifies that socket controllers should provide + * two IO and five memory windows per socket, which can be independently + * configured and positioned in the host address space and mapped to + * arbitrary segments of card address space. " - David A Hinds. 1999 + * + * This controller does _not_ meet the ExCA standard. + * + * m8xx pcmcia controller brief info: + * + 8 windows (attrib, mem, i/o) + * + up to two slots (SLOT_A and SLOT_B) + * + inputpins, outputpins, event and mask registers. + * - no offset register. sigh. + * + * Because of the lacking offset register we must map the whole card. + * We assign each memory window PCMCIA_MEM_WIN_SIZE address space. + * Make sure there is (PCMCIA_MEM_WIN_SIZE * PCMCIA_MEM_WIN_NO + * * PCMCIA_SOCKETS_NO) bytes at PCMCIA_MEM_WIN_BASE. + * The i/o windows are dynamically allocated at PCMCIA_IO_WIN_BASE. + * They are maximum 64KByte each... + */ + +/* #define DEBUG 1 */ + +/* + * PCMCIA support + */ +#include <common.h> +#include <command.h> +#include <config.h> +#include <pcmcia.h> +#include <cmd_pcmcia.h> +#if defined(CONFIG_IDE_8xx_PCCARD) && defined(CONFIG_8xx) +#include <mpc8xx.h> +#endif +#if defined(CONFIG_LWMON) +#include <i2c.h> +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) || \ + ((CONFIG_COMMANDS & CFG_CMD_IDE) && defined(CONFIG_IDE_8xx_PCCARD)) + +int pcmcia_on (void); + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int pcmcia_off (void); +static int hardware_disable(int slot); +#endif +static int hardware_enable (int slot); +static int voltage_set(int slot, int vcc, int vpp); +#ifdef CONFIG_IDE_8xx_PCCARD +static void print_funcid (int func); +static void print_fixed (volatile uchar *p); +static int identify (volatile uchar *p); +static int check_ide_device (void); +#endif /* CONFIG_IDE_8xx_PCCARD */ + +static u_int m8xx_get_graycode(u_int size); +#if 0 +static u_int m8xx_get_speed(u_int ns, u_int is_io); +#endif + +/* ------------------------------------------------------------------------- */ + +/* look up table for pgcrx registers */ + +static u_int *pcmcia_pgcrx[2] = { + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcra, + &((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pgcrb, +}; + +#define PCMCIA_PGCRX(slot) (*pcmcia_pgcrx[slot]) + +const char *indent = "\t "; + +/* ------------------------------------------------------------------------- */ + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) + +int do_pinit (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + int rcode = 0; + + if (argc != 2) { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + if (strcmp(argv[1],"on") == 0) { + rcode = pcmcia_on (); + } else if (strcmp(argv[1],"off") == 0) { + rcode = pcmcia_off (); + } else { + printf ("Usage: pinit {on | off}\n"); + return 1; + } + + return rcode; +} +#endif /* CFG_CMD_PCMCIA */ + +/* ------------------------------------------------------------------------- */ + +#if defined(CONFIG_LWMON) +# define CFG_PCMCIA_TIMING (PCMCIA_SHT(9) | PCMCIA_SST(3) | PCMCIA_SL(12)) +#else +# define CFG_PCMCIA_TIMING (PCMCIA_SHT(2) | PCMCIA_SST(4) | PCMCIA_SL(9)) +#endif + +int pcmcia_on (void) +{ + int i; + u_long reg, base; + pcmcia_win_t *win; + + debug ("Enable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + /* intialize the fixed memory windows */ + win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); + base = CFG_PCMCIA_MEM_ADDR; + + if((reg = m8xx_get_graycode(CFG_PCMCIA_MEM_SIZE)) == -1) { + printf ("Cannot set window size to 0x%08x\n", + CFG_PCMCIA_MEM_SIZE); + return (1); + } + + for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) { + win->br = base; + + switch (i) { +#ifdef CONFIG_IDE_8xx_PCCARD + case 0: { /* map attribute memory */ + win->or = ( PCMCIA_BSIZE_64M + | PCMCIA_PPS_8 + | PCMCIA_PRS_ATTR + | PCMCIA_SLOT_x + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } + + case 1: { /* map I/O window for data reg */ + win->or = ( PCMCIA_BSIZE_1K + | PCMCIA_PPS_16 + | PCMCIA_PRS_IO + | PCMCIA_SLOT_x + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } + + case 2: { /* map I/O window for command/ctrl reg block */ + win->or = ( PCMCIA_BSIZE_1K + | PCMCIA_PPS_8 + | PCMCIA_PRS_IO + | PCMCIA_SLOT_x + | PCMCIA_PV + | CFG_PCMCIA_TIMING ); + break; + } +#endif /* CONFIG_IDE_8xx_PCCARD */ + default: /* set to not valid */ + win->or = 0; + break; + } + + debug ("MemWin %d: PBR 0x%08lX POR %08lX\n", + i, win->br, win->or); + base += CFG_PCMCIA_MEM_SIZE; + ++win; + } + + /* turn off voltage */ + if (voltage_set(_slot_, 0, 0)) + return (1); + + /* Enable external hardware */ + if (hardware_enable(_slot_)) + return (1); + +#ifdef CONFIG_IDE_8xx_PCCARD + if (check_ide_device()) + return (1); +#endif + return (0); +} + +/* ------------------------------------------------------------------------- */ + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) + +static int pcmcia_off (void) +{ + int i; + pcmcia_win_t *win; + + printf ("Disable PCMCIA " PCMCIA_SLOT_MSG "\n"); + + /* clear interrupt state, and disable interrupts */ + ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pscr = PCMCIA_MASK(_slot_); + ((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* turn off interrupt and disable CxOE */ + PCMCIA_PGCRX(_slot_) = __MY_PCMCIA_GCRX_CXOE; + + /* turn off memory windows */ + win = (pcmcia_win_t *)(&((immap_t *)CFG_IMMR)->im_pcmcia.pcmc_pbr0); + + for (i=0; i<PCMCIA_MEM_WIN_NO; ++i) { + /* disable memory window */ + win->or = 0; + ++win; + } + + /* turn off voltage */ + voltage_set(_slot_, 0, 0); + + /* disable external hardware */ + printf ("Shutdown and Poweroff " PCMCIA_SLOT_MSG "\n"); + hardware_disable(_slot_); + return 0; +} + +#endif /* CFG_CMD_PCMCIA */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_8xx_PCCARD + +#define MAX_TUPEL_SZ 512 +#define MAX_FEATURES 4 + +static int check_ide_device (void) +{ + volatile uchar *ident = NULL; + volatile uchar *feature_p[MAX_FEATURES]; + volatile uchar *p, *start; + int n_features = 0; + uchar func_id = ~0; + uchar code, len; + ushort config_base = 0; + int found = 0; + int i; + + debug ("PCMCIA MEM: %08X\n", CFG_PCMCIA_MEM_ADDR); + + start = p = (volatile uchar *) CFG_PCMCIA_MEM_ADDR; + + while ((p - start) < MAX_TUPEL_SZ) { + + code = *p; p += 2; + + if (code == 0xFF) { /* End of chain */ + break; + } + + len = *p; p += 2; +#if defined(DEBUG) && (DEBUG > 1) + { volatile uchar *q = p; + printf ("\nTuple code %02x length %d\n\tData:", + code, len); + + for (i = 0; i < len; ++i) { + printf (" %02x", *q); + q+= 2; + } + } +#endif /* DEBUG */ + switch (code) { + case CISTPL_VERS_1: + ident = p + 4; + break; + case CISTPL_FUNCID: + /* Fix for broken SanDisk which may have 0x80 bit set */ + func_id = *p & 0x7F; + break; + case CISTPL_FUNCE: + if (n_features < MAX_FEATURES) + feature_p[n_features++] = p; + break; + case CISTPL_CONFIG: + config_base = (*(p+6) << 8) + (*(p+4)); + debug ("\n## Config_base = %04x ###\n", config_base); + default: + break; + } + p += 2 * len; + } + + found = identify (ident); + + if (func_id != ((uchar)~0)) { + print_funcid (func_id); + + if (func_id == CISTPL_FUNCID_FIXED) + found = 1; + else + return (1); /* no disk drive */ + } + + for (i=0; i<n_features; ++i) { + print_fixed (feature_p[i]); + } + + if (!found) { + printf ("unknown card type\n"); + return (1); + } + + /* set I/O area in config reg -> only valid for ARGOSY D5!!! */ + *((uchar *)(CFG_PCMCIA_MEM_ADDR + config_base)) = 1; + + return (0); +} +#endif /* CONFIG_IDE_8xx_PCCARD */ + +/* ------------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------------- */ +/* board specific stuff: */ +/* voltage_set(), hardware_enable() and hardware_disable() */ +/* ---------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------------- */ +/* RPX Boards from Embedded Planet */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_RPXCLASSIC) || defined(CONFIG_RPXLITE) + +/* The RPX boards seems to have it's bus monitor timeout set to 6*8 clocks. + * SYPCR is write once only, therefore must the slowest memory be faster + * than the bus monitor or we will get a machine check due to the bus timeout. + */ + +#define PCMCIA_BOARD_MSG "RPX CLASSIC or RPX LITE" + +#undef PCMCIA_BMT_LIMIT +#define PCMCIA_BMT_LIMIT (6*8) + +static int voltage_set(int slot, int vcc, int vpp) +{ + u_long reg = 0; + + switch(vcc) { + case 0: break; + case 33: reg |= BCSR1_PCVCTL4; break; + case 50: reg |= BCSR1_PCVCTL5; break; + default: return 1; + } + + switch(vpp) { + case 0: break; + case 33: + case 50: + if(vcc == vpp) + reg |= BCSR1_PCVCTL6; + else + return 1; + break; + case 120: + reg |= BCSR1_PCVCTL7; + default: return 1; + } + + if(vcc == 120) + return 1; + + /* first, turn off all power */ + + *((uint *)RPX_CSR_ADDR) &= ~(BCSR1_PCVCTL4 | BCSR1_PCVCTL5 + | BCSR1_PCVCTL6 | BCSR1_PCVCTL7); + + /* enable new powersettings */ + + *((uint *)RPX_CSR_ADDR) |= reg; + + return 0; +} + +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V +static int hardware_enable (int slot) +{ + return 0; /* No hardware to enable */ +} +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + return 0; /* No hardware to disable */ +} +#endif /* CFG_CMD_PCMCIA */ +#endif /* CONFIG_RPXCLASSIC */ + +/* ---------------------------------------------------------------------------- */ +/* (F)ADS Boards from Motorola */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_ADS) || defined(CONFIG_FADS) + +#ifdef CONFIG_ADS +#define PCMCIA_BOARD_MSG "ADS" +#define PCMCIA_GLITCHY_CD /* My ADS board needs this */ +#else +#define PCMCIA_BOARD_MSG "FADS" +#endif + +static int voltage_set(int slot, int vcc, int vpp) +{ + u_long reg = 0; + + switch(vpp) { + case 0: reg = 0; break; + case 50: reg = 1; break; + case 120: reg = 2; break; + default: return 1; + } + + switch(vcc) { + case 0: reg = 0; break; +#ifdef CONFIG_ADS + case 50: reg = BCSR1_PCCVCCON; break; +#endif +#ifdef CONFIG_FADS + case 33: reg = BCSR1_PCCVCC0 | BCSR1_PCCVCC1; break; + case 50: reg = BCSR1_PCCVCC1; break; +#endif + default: return 1; + } + + /* first, turn off all power */ + +#ifdef CONFIG_ADS + *((uint *)BCSR1) |= BCSR1_PCCVCCON; +#endif +#ifdef CONFIG_FADS + *((uint *)BCSR1) &= ~(BCSR1_PCCVCC0 | BCSR1_PCCVCC1); +#endif + *((uint *)BCSR1) &= ~BCSR1_PCCVPP_MASK; + + /* enable new powersettings */ + +#ifdef CONFIG_ADS + *((uint *)BCSR1) &= ~reg; +#endif +#ifdef CONFIG_FADS + *((uint *)BCSR1) |= reg; +#endif + + *((uint *)BCSR1) |= reg << 20; + + return 0; +} + +#define socket_get(_slot_) PCMCIA_SOCKET_KEY_5V + +static int hardware_enable(int slot) +{ + *((uint *)BCSR1) &= ~BCSR1_PCCEN; + return 0; +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + *((uint *)BCSR1) &= ~BCSR1_PCCEN; + return 0; +} +#endif /* CFG_CMD_PCMCIA */ + +#endif /* (F)ADS */ + +/* ---------------------------------------------------------------------------- */ +/* TQM8xxL Boards by TQ Components */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_TQM8xxL) + +#define PCMCIA_BOARD_MSG "TQM8xxL" + + +static int hardware_enable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Port C pins for + * 5 Volts Enable and 3 Volts enable + */ + immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004); + immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004); + /* remove all power */ + + immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + if ((reg & mask) == mask) { + immap->im_ioport.iop_pcdat |= 0x0004; + puts (" 5.0V card found: "); + } else { + immap->im_ioport.iop_pcdat |= 0x0002; + puts (" 3.3V card found: "); + } + immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); +#if 0 + /* VCC switch error flag, PCMCIA slot INPACK_ pin */ + cp->cp_pbdir &= ~(0x0020 | 0x0010); + cp->cp_pbpar &= ~(0x0020 | 0x0010); + udelay(500000); +#endif + udelay(1000); + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + + /* remove all power */ + immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); + + /* Configure PCMCIA General Control Register */ + PCMCIA_PGCRX(_slot_) = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(10000); + + return (0); +} +#endif /* CFG_CMD_PCMCIA */ + + + +static int voltage_set(int slot, int vcc, int vpp) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Port C pins for + * 5 Volts Enable and 3 Volts enable, + * Turn off all power + */ + debug ("PCMCIA power OFF\n"); + immap->im_ioport.iop_pcpar &= ~(0x0002 | 0x0004); + immap->im_ioport.iop_pcso &= ~(0x0002 | 0x0004); + immap->im_ioport.iop_pcdat &= ~(0x0002 | 0x0004); + + reg = 0; + switch(vcc) { + case 0: break; + case 33: reg |= 0x0002; break; + case 50: reg |= 0x0004; break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + immap->im_ioport.iop_pcdat |= reg; + immap->im_ioport.iop_pcdir |= (0x0002 | 0x0004); + if (reg) { + debug ("PCMCIA powered at %sV\n", + (reg&0x0004) ? "5.0" : "3.3"); + } else { + debug ("PCMCIA powered down\n"); + } + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +#endif /* TQM8xxL */ + + +/* ---------------------------------------------------------------------------- */ +/* LWMON Board */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_LWMON) + +#define PCMCIA_BOARD_MSG "LWMON" + +/* #define's for MAX1604 Power Switch */ +#define MAX1604_OP_SUS 0x80 +#define MAX1604_VCCBON 0x40 +#define MAX1604_VCC_35 0x20 +#define MAX1604_VCCBHIZ 0x10 +#define MAX1604_VPPBON 0x08 +#define MAX1604_VPPBPBPGM 0x04 +#define MAX1604_VPPBHIZ 0x02 +/* reserved 0x01 */ + +static int hardware_enable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + uchar val; + + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + /* Switch on PCMCIA port in PIC register 0x60 */ + reg = pic_read (0x60); + debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); + reg &= ~0x10; + /* reg |= 0x08; Vpp not needed */ + pic_write (0x60, reg); +#ifdef DEBUG + reg = pic_read (0x60); + printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); +#endif + udelay(10000); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + if ((reg & mask) == mask) { + val = 0; /* VCCB3/5 = 0 ==> use Vx = 5.0 V */ + puts (" 5.0V card found: "); + } else { + val = MAX1604_VCC_35; /* VCCB3/5 = 1 ==> use Vy = 3.3 V */ + puts (" 3.3V card found: "); + } + + /* switch VCC on */ + val |= MAX1604_OP_SUS | MAX1604_VCCBON; + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + udelay(500000); + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + uchar val; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + + /* remove all power, put output in high impedance state */ + val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ; + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + /* Configure PCMCIA General Control Register */ + PCMCIA_PGCRX(_slot_) = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + /* Switch off PCMCIA port in PIC register 0x60 */ + reg = pic_read (0x60); + debug ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); + reg |= 0x10; + reg &= ~0x08; + pic_write (0x60, reg); +#ifdef DEBUG + reg = pic_read (0x60); + printf ("[%d] PIC read: reg_60 = 0x%02x\n", __LINE__, reg); +#endif + udelay(10000); + + return (0); +} +#endif /* CFG_CMD_PCMCIA */ + + + +static int voltage_set(int slot, int vcc, int vpp) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + uchar val; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Turn off all power (switch to high impedance) + */ + debug ("PCMCIA power OFF\n"); + val = MAX1604_VCCBHIZ | MAX1604_VPPBHIZ; + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); + i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1); + + val = 0; + switch(vcc) { + case 0: break; + case 33: val = MAX1604_VCC_35; break; + case 50: break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + i2c_write (CFG_I2C_POWER_A_ADDR, 0, 0, &val, 1); + if (val) { + debug ("PCMCIA powered at %sV\n", + (val & MAX1604_VCC_35) ? "3.3" : "5.0"); + } else { + debug ("PCMCIA powered down\n"); + } + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +#endif /* LWMON */ + +/* ---------------------------------------------------------------------------- */ +/* GTH board by Corelatus AB */ +/* ---------------------------------------------------------------------------- */ +#if defined(CONFIG_GTH) + +#define PCMCIA_BOARD_MSG "GTH COMPACT FLASH" + +static int voltage_set(int slot, int vcc, int vpp) +{ /* Do nothing */ + return 0; +} + +static int hardware_enable (int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + + debug ("hardware_enable: GTH Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x98000000) { + printf (" No Card found\n"); + return (1); + } + + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return 0; +} +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + return 0; /* No hardware to disable */ +} +#endif /* CFG_CMD_PCMCIA */ +#endif /* CONFIG_GTH */ + +/* ---------------------------------------------------------------------------- */ +/* ICU862 Boards by Cambridge Broadband Ltd. */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_ICU862) + +#define PCMCIA_BOARD_MSG "ICU862" + +static void cfg_port_B (void); + +static int hardware_enable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, pipr, mask; + int i; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* Configure Port B for TPS2205 PC-Card Power-Interface Switch */ + cfg_port_B (); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + pipr = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + pipr, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + + reg = cp->cp_pbdat; + if ((pipr & mask) == mask) { + reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */ + TPS2205_VCC3); /* 3V off */ + reg &= ~(TPS2205_VCC5); /* 5V on */ + puts (" 5.0V card found: "); + } else { + reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */ + TPS2205_VCC5); /* 5V off */ + reg &= ~(TPS2205_VCC3); /* 3V on */ + puts (" 3.3V card found: "); + } + + debug ("\nPB DAT: %08x -> 3.3V %s 5.0V %s VPP_PGM %s VPP_VCC %s\n", + reg, + (reg & TPS2205_VCC3) ? "off" : "on", + (reg & TPS2205_VCC5) ? "off" : "on", + (reg & TPS2205_VPP_PGM) ? "off" : "on", + (reg & TPS2205_VPP_VCC) ? "off" : "on" ); + + cp->cp_pbdat = reg; + + /* Wait 500 ms; use this to check for over-current */ + for (i=0; i<5000; ++i) { + if ((cp->cp_pbdat & TPS2205_OC) == 0) { + printf (" *** Overcurrent - Safety shutdown ***\n"); + cp->cp_pbdat &= ~(TPS2205_SHDN); + return (1); + } + udelay (100); + } + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + + /* Shut down */ + cp->cp_pbdat &= ~(TPS2205_SHDN); + + /* Configure PCMCIA General Control Register */ + PCMCIA_PGCRX(_slot_) = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(10000); + + return (0); +} +#endif /* CFG_CMD_PCMCIA */ + + + +static int voltage_set(int slot, int vcc, int vpp) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + immap = (immap_t *)CFG_IMMR; + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Port C pins for + * 5 Volts Enable and 3 Volts enable, + * Turn all power pins to Hi-Z + */ + debug ("PCMCIA power OFF\n"); + cfg_port_B (); /* Enables switch, but all in Hi-Z */ + + reg = cp->cp_pbdat; + + switch(vcc) { + case 0: break; /* Switch off */ + case 33: reg &= ~TPS2205_VCC3; break; /* Switch on 3.3V */ + case 50: reg &= ~TPS2205_VCC5; break; /* Switch on 5.0V */ + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + cp->cp_pbdat = reg; + +#ifdef DEBUG + { + char *s; + + if ((reg & TPS2205_VCC3) == 0) { + s = "at 3.3V"; + } else if ((reg & TPS2205_VCC5) == 0) { + s = "at 5.0V"; + } else { + s = "down"; + } + printf ("PCMCIA powered %s\n", s); + } +#endif + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +static void cfg_port_B (void) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + uint reg; + + immap = (immap_t *)CFG_IMMR; + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* + * Configure Port B for TPS2205 PC-Card Power-Interface Switch + * + * Switch off all voltages, assert shutdown + */ + reg = cp->cp_pbdat; + reg |= (TPS2205_VPP_PGM | TPS2205_VPP_VCC | /* VAVPP => Hi-Z */ + TPS2205_VCC3 | TPS2205_VCC5 | /* VAVCC => Hi-Z */ + TPS2205_SHDN); /* enable switch */ + cp->cp_pbdat = reg; + + cp->cp_pbpar &= ~(TPS2205_INPUTS | TPS2205_OUTPUTS); + + reg = cp->cp_pbdir & ~(TPS2205_INPUTS); + cp->cp_pbdir = reg | TPS2205_OUTPUTS; + + debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n", + cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat); +} + +#endif /* ICU862 */ + + +/* ---------------------------------------------------------------------------- */ +/* C2MON Boards by TTTech Computertechnik AG */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_C2MON) + +#define PCMCIA_BOARD_MSG "C2MON" + +static void cfg_ports (void); + +static int hardware_enable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, pipr, mask; + ushort sreg; + int i; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* Configure Ports for TPS2211A PC-Card Power-Interface Switch */ + cfg_ports (); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On: Set VAVCC to 3.3V or 5V, set VAVPP to Hi-Z + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + pipr = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + pipr, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + + sreg = immap->im_ioport.iop_pcdat; + if ((pipr & mask) == mask) { + sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */ + TPS2211_VCCD1); /* 5V on */ + sreg &= ~(TPS2211_VCCD0); /* 3V off */ + puts (" 5.0V card found: "); + } else { + sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1 | /* VAVPP => Hi-Z */ + TPS2211_VCCD0); /* 3V on */ + sreg &= ~(TPS2211_VCCD1); /* 5V off */ + puts (" 3.3V card found: "); + } + + debug ("\nPC DAT: %04x -> 3.3V %s 5.0V %s\n", + sreg, + ( (sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) ? "on" : "off", + (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) ? "on" : "off" + ); + + immap->im_ioport.iop_pcdat = sreg; + + /* Wait 500 ms; use this to check for over-current */ + for (i=0; i<5000; ++i) { + if ((cp->cp_pbdat & TPS2211_OC) == 0) { + printf (" *** Overcurrent - Safety shutdown ***\n"); + immap->im_ioport.iop_pcdat &= ~(TPS2211_VCCD0|TPS2211_VCCD1); + return (1); + } + udelay (100); + } + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + + /* Configure PCMCIA General Control Register */ + PCMCIA_PGCRX(_slot_) = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + /* ALl voltages off / Hi-Z */ + immap->im_ioport.iop_pcdat |= (TPS2211_VPPD0 | TPS2211_VPPD1 | + TPS2211_VCCD0 | TPS2211_VCCD1 ); + + udelay(10000); + + return (0); +} +#endif /* CFG_CMD_PCMCIA */ + + + +static int voltage_set(int slot, int vcc, int vpp) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + u_long reg; + ushort sreg; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + immap = (immap_t *)CFG_IMMR; + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Port C pins for + * 5 Volts Enable and 3 Volts enable, + * Turn all power pins to Hi-Z + */ + debug ("PCMCIA power OFF\n"); + cfg_ports (); /* Enables switch, but all in Hi-Z */ + + sreg = immap->im_ioport.iop_pcdat; + sreg |= TPS2211_VPPD0 | TPS2211_VPPD1; /* VAVPP always Hi-Z */ + + switch(vcc) { + case 0: break; /* Switch off */ + case 33: sreg |= TPS2211_VCCD0; /* Switch on 3.3V */ + sreg &= ~TPS2211_VCCD1; + break; + case 50: sreg &= ~TPS2211_VCCD0; /* Switch on 5.0V */ + sreg |= TPS2211_VCCD1; + break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + immap->im_ioport.iop_pcdat = sreg; + +#ifdef DEBUG + { + char *s; + + if ((sreg & TPS2211_VCCD0) && !(sreg & TPS2211_VCCD1)) { + s = "at 3.3V"; + } else if (!(sreg & TPS2211_VCCD0) && (sreg & TPS2211_VCCD1)) { + s = "at 5.0V"; + } else { + s = "down"; + } + printf ("PCMCIA powered %s\n", s); + } +#endif + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +static void cfg_ports (void) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + ushort sreg; + + immap = (immap_t *)CFG_IMMR; + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* + * Configure Port C for TPS2211 PC-Card Power-Interface Switch + * + * Switch off all voltages, assert shutdown + */ + sreg = immap->im_ioport.iop_pcdat; + sreg |= (TPS2211_VPPD0 | TPS2211_VPPD1); /* VAVPP => Hi-Z */ + sreg &= ~(TPS2211_VCCD0 | TPS2211_VCCD1); /* 3V and 5V off */ + immap->im_ioport.iop_pcdat = sreg; + + immap->im_ioport.iop_pcpar &= ~(TPS2211_OUTPUTS); + immap->im_ioport.iop_pcdir |= TPS2211_OUTPUTS; + + debug ("Set Port C: PAR: %04x DIR: %04x DAT: %04x\n", + immap->im_ioport.iop_pcpar, + immap->im_ioport.iop_pcdir, + immap->im_ioport.iop_pcdat); + + /* + * Configure Port B for TPS2211 PC-Card Power-Interface Switch + * + * Over-Current Input only + */ + cp->cp_pbpar &= ~(TPS2211_INPUTS); + cp->cp_pbdir &= ~(TPS2211_INPUTS); + + debug ("Set Port B: PAR: %08x DIR: %08x DAT: %08x\n", + cp->cp_pbpar, cp->cp_pbdir, cp->cp_pbdat); +} + +#endif /* C2MON */ + +/* ---------------------------------------------------------------------------- + MBX board from Morotola + ---------------------------------------------------------------------------- */ + +#if defined( CONFIG_MBX ) +#include <../board/mbx8xx/csr.h> + +/* A lot of this has been taken from the RPX code in this file it works from me. + I have added the voltage selection for the MBX board. */ + +/* MBX voltage bit in control register #2 */ +#define CR2_VPP12 ((uchar)0x10) +#define CR2_VPPVDD ((uchar)0x20) +#define CR2_VDD5 ((uchar)0x40) +#define CR2_VDD3 ((uchar)0x80) + +#define PCMCIA_BOARD_MSG "MBX860" + +static int voltage_set (int slot, int vcc, int vpp) +{ + uchar reg = 0; + + debug ("voltage_set: PCMCIA_BOARD_MSG Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A' + slot, vcc / 10, vcc % 10, vpp / 10, vcc % 10); + + switch (vcc) { + case 0: + break; + case 33: + reg |= CR2_VDD3; + break; + case 50: + reg |= CR2_VDD5; + break; + default: + return 1; + } + + switch (vpp) { + case 0: + break; + case 33: + case 50: + if (vcc == vpp) { + reg |= CR2_VPPVDD; + } else { + return 1; + } + break; + case 120: + reg |= CR2_VPP12; + break; + default: + return 1; + } + + /* first, turn off all power */ + MBX_CSR2 &= ~(CR2_VDDSEL | CR2_VPPSEL); + + /* enable new powersettings */ + MBX_CSR2 |= reg; + debug ("MBX_CSR2 read = 0x%02x\n", MBX_CSR2); + + return (0); +} + +static int hardware_enable (int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", + 'A' + slot); + + udelay (10000); + + immap = (immap_t *) CFG_IMMR; + sysp = (sysconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *) (&(((immap_t *) CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *) (&(((immap_t *) CFG_IMMR)->im_cpm)); + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK (_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK (_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX (_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX (_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX (_slot_) = reg; + udelay (500); + + /* remove all power */ + voltage_set (slot, 0, 0); + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay (10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", __LINE__, __FUNCTION__, + &(pcmp->pcmc_pipr), pcmp->pcmc_pipr); + + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1 (_slot_) | PCMCIA_VS2 (_slot_); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", reg, + (reg & PCMCIA_VS1 (slot)) ? "n" : "ff", + (reg & PCMCIA_VS2 (slot)) ? "n" : "ff"); + + if ((reg & mask) == mask) { + voltage_set (_slot_, 50, 0); + printf (" 5.0V card found: "); + } else { + voltage_set (_slot_, 33, 0); + printf (" 3.3V card found: "); + } + + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX (_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX (_slot_) = reg; + + udelay (250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable (int slot) +{ + return 0; /* No hardware to disable */ +} +#endif /* CFG_CMD_PCMCIA */ +#endif /* CONFIG_MBX */ +/* ---------------------------------------------------------------------------- */ +/* R360MPI Board */ +/* ---------------------------------------------------------------------------- */ + +#if defined(CONFIG_R360MPI) + +#define PCMCIA_BOARD_MSG "R360MPI" + + +static int hardware_enable(int slot) +{ + volatile immap_t *immap; + volatile cpm8xx_t *cp; + volatile pcmconf8xx_t *pcmp; + volatile sysconf8xx_t *sysp; + uint reg, mask; + + debug ("hardware_enable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + udelay(10000); + + immap = (immap_t *)CFG_IMMR; + sysp = (sysconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_siu_conf)); + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + cp = (cpm8xx_t *)(&(((immap_t *)CFG_IMMR)->im_cpm)); + + /* + * Configure SIUMCR to enable PCMCIA port B + * (VFLS[0:1] are not used for debugging, we connect FRZ# instead) + */ + sysp->sc_siumcr &= ~SIUMCR_DBGC11; /* set DBGC to 00 */ + + /* clear interrupt state, and disable interrupts */ + pcmp->pcmc_pscr = PCMCIA_MASK(_slot_); + pcmp->pcmc_per &= ~PCMCIA_MASK(_slot_); + + /* disable interrupts & DMA */ + PCMCIA_PGCRX(_slot_) = 0; + + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Ports A, B & C pins for + * 5 Volts Enable and 3 Volts enable + */ + immap->im_ioport.iop_pcpar &= ~(0x0400); + immap->im_ioport.iop_pcso &= ~(0x0400);/* + immap->im_ioport.iop_pcdir |= 0x0400;*/ + + immap->im_ioport.iop_papar &= ~(0x0200);/* + immap->im_ioport.iop_padir |= 0x0200;*/ +#if 0 + immap->im_ioport.iop_pbpar &= ~(0xC000); + immap->im_ioport.iop_pbdir &= ~(0xC000); +#endif + /* remove all power */ + + immap->im_ioport.iop_pcdat |= 0x0400; + immap->im_ioport.iop_padat |= 0x0200; + + /* + * Make sure there is a card in the slot, then configure the interface. + */ + udelay(10000); + debug ("[%d] %s: PIPR(%p)=0x%x\n", + __LINE__,__FUNCTION__, + &(pcmp->pcmc_pipr),pcmp->pcmc_pipr); + if (pcmp->pcmc_pipr & 0x00001800) { + printf (" No Card found\n"); + return (1); + } + + /* + * Power On. + */ + mask = PCMCIA_VS1(slot) | PCMCIA_VS2(slot); + reg = pcmp->pcmc_pipr; + debug ("PIPR: 0x%x ==> VS1=o%s, VS2=o%s\n", + reg, + (reg&PCMCIA_VS1(slot))?"n":"ff", + (reg&PCMCIA_VS2(slot))?"n":"ff"); + if ((reg & mask) == mask) { + immap->im_ioport.iop_pcdat &= ~(0x4000); + puts (" 5.0V card found: "); + } else { + immap->im_ioport.iop_padat &= ~(0x0002); + puts (" 3.3V card found: "); + } + immap->im_ioport.iop_pcdir |= 0x0400; + immap->im_ioport.iop_padir |= 0x0200; +#if 0 + /* VCC switch error flag, PCMCIA slot INPACK_ pin */ + cp->cp_pbdir &= ~(0x0020 | 0x0010); + cp->cp_pbpar &= ~(0x0020 | 0x0010); + udelay(500000); +#endif + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(250000); /* some cards need >150 ms to come up :-( */ + + debug ("# hardware_enable done\n"); + + return (0); +} + + + +#if (CONFIG_COMMANDS & CFG_CMD_PCMCIA) +static int hardware_disable(int slot) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("hardware_disable: " PCMCIA_BOARD_MSG " Slot %c\n", 'A'+slot); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + + /* remove all power */ + immap->im_ioport.iop_pcdat |= 0x0400; + immap->im_ioport.iop_padat |= 0x0200; + + /* Configure PCMCIA General Control Register */ + PCMCIA_PGCRX(_slot_) = 0; + + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + + udelay(10000); + + return (0); +} +#endif /* CFG_CMD_PCMCIA */ + + + +static int voltage_set(int slot, int vcc, int vpp) +{ + volatile immap_t *immap; + volatile pcmconf8xx_t *pcmp; + u_long reg; + + debug ("voltage_set: " + PCMCIA_BOARD_MSG + " Slot %c, Vcc=%d.%d, Vpp=%d.%d\n", + 'A'+slot, vcc/10, vcc%10, vpp/10, vcc%10); + + immap = (immap_t *)CFG_IMMR; + pcmp = (pcmconf8xx_t *)(&(((immap_t *)CFG_IMMR)->im_pcmcia)); + /* + * Disable PCMCIA buffers (isolate the interface) + * and assert RESET signal + */ + debug ("Disable PCMCIA buffers and assert RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg |= __MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg |= __MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + /* + * Configure Ports A & C pins for + * 5 Volts Enable and 3 Volts enable, + * Turn off all power + */ + debug ("PCMCIA power OFF\n"); + immap->im_ioport.iop_pcpar &= ~(0x0400); + immap->im_ioport.iop_pcso &= ~(0x0400);/* + immap->im_ioport.iop_pcdir |= 0x0400;*/ + + immap->im_ioport.iop_papar &= ~(0x0200);/* + immap->im_ioport.iop_padir |= 0x0200;*/ + + immap->im_ioport.iop_pcdat |= 0x0400; + immap->im_ioport.iop_padat |= 0x0200; + + reg = 0; + switch(vcc) { + case 0: break; + case 33: reg |= 0x0200; break; + case 50: reg |= 0x0400; break; + default: goto done; + } + + /* Checking supported voltages */ + + debug ("PIPR: 0x%x --> %s\n", + pcmp->pcmc_pipr, + (pcmp->pcmc_pipr & 0x00008000) ? "only 5 V" : "can do 3.3V"); + + if (reg & 0x0200) + immap->im_ioport.iop_pcdat &= !reg; + if (reg & 0x0400) + immap->im_ioport.iop_padat &= !reg; + immap->im_ioport.iop_pcdir |= 0x0200; + immap->im_ioport.iop_padir |= 0x0400; + if (reg) { + debug ("PCMCIA powered at %sV\n", + (reg&0x0400) ? "5.0" : "3.3"); + } else { + debug ("PCMCIA powered down\n"); + } + +done: + debug ("Enable PCMCIA buffers and stop RESET\n"); + reg = PCMCIA_PGCRX(_slot_); + reg &= ~__MY_PCMCIA_GCRX_CXRESET; /* active high */ + reg &= ~__MY_PCMCIA_GCRX_CXOE; /* active low */ + PCMCIA_PGCRX(_slot_) = reg; + udelay(500); + + debug ("voltage_set: " PCMCIA_BOARD_MSG " Slot %c, DONE\n", + slot+'A'); + return (0); +} + +#endif /* R360MPI */ + + +/* ---------------------------------------------------------------------------- */ +/* End of Board Specific Stuff */ +/* ---------------------------------------------------------------------------- */ + + +/* ---------------------------------------------------------------------------- */ +/* MPC8xx Specific Stuff - should go to MPC8xx directory */ +/* ---------------------------------------------------------------------------- */ + +/* + * Search this table to see if the windowsize is + * supported... + */ + +#define M8XX_SIZES_NO 32 + +static const u_int m8xx_size_to_gray[M8XX_SIZES_NO] = +{ 0x00000001, 0x00000002, 0x00000008, 0x00000004, + 0x00000080, 0x00000040, 0x00000010, 0x00000020, + 0x00008000, 0x00004000, 0x00001000, 0x00002000, + 0x00000100, 0x00000200, 0x00000800, 0x00000400, + + 0x0fffffff, 0xffffffff, 0xffffffff, 0xffffffff, + 0x01000000, 0x02000000, 0xffffffff, 0x04000000, + 0x00010000, 0x00020000, 0x00080000, 0x00040000, + 0x00800000, 0x00400000, 0x00100000, 0x00200000 }; + + +/* ---------------------------------------------------------------------------- */ + +static u_int m8xx_get_graycode(u_int size) +{ + u_int k; + + for (k = 0; k < M8XX_SIZES_NO; k++) { + if(m8xx_size_to_gray[k] == size) + break; + } + + if((k == M8XX_SIZES_NO) || (m8xx_size_to_gray[k] == -1)) + k = -1; + + return k; +} + +/* ------------------------------------------------------------------------- */ + +#if 0 +static u_int m8xx_get_speed(u_int ns, u_int is_io) +{ + u_int reg, clocks, psst, psl, psht; + + if(!ns) { + + /* + * We get called with IO maps setup to 0ns + * if not specified by the user. + * They should be 255ns. + */ + + if(is_io) + ns = 255; + else + ns = 100; /* fast memory if 0 */ + } + + /* + * In PSST, PSL, PSHT fields we tell the controller + * timing parameters in CLKOUT clock cycles. + * CLKOUT is the same as GCLK2_50. + */ + +/* how we want to adjust the timing - in percent */ + +#define ADJ 180 /* 80 % longer accesstime - to be sure */ + + clocks = ((M8XX_BUSFREQ / 1000) * ns) / 1000; + clocks = (clocks * ADJ) / (100*1000); + + if(clocks >= PCMCIA_BMT_LIMIT) { + DEBUG(0, "Max access time limit reached\n"); + clocks = PCMCIA_BMT_LIMIT-1; + } + + psst = clocks / 7; /* setup time */ + psht = clocks / 7; /* hold time */ + psl = (clocks * 5) / 7; /* strobe length */ + + psst += clocks - (psst + psht + psl); + + reg = psst << 12; + reg |= psl << 7; + reg |= psht << 16; + + return reg; +} +#endif + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_8xx_PCCARD +static void print_funcid (int func) +{ + puts (indent); + switch (func) { + case CISTPL_FUNCID_MULTI: + puts (" Multi-Function"); + break; + case CISTPL_FUNCID_MEMORY: + puts (" Memory"); + break; + case CISTPL_FUNCID_SERIAL: + puts (" Serial Port"); + break; + case CISTPL_FUNCID_PARALLEL: + puts (" Parallel Port"); + break; + case CISTPL_FUNCID_FIXED: + puts (" Fixed Disk"); + break; + case CISTPL_FUNCID_VIDEO: + puts (" Video Adapter"); + break; + case CISTPL_FUNCID_NETWORK: + puts (" Network Adapter"); + break; + case CISTPL_FUNCID_AIMS: + puts (" AIMS Card"); + break; + case CISTPL_FUNCID_SCSI: + puts (" SCSI Adapter"); + break; + default: + puts (" Unknown"); + break; + } + puts (" Card\n"); +} +#endif /* CONFIG_IDE_8xx_PCCARD */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_8xx_PCCARD +static void print_fixed (volatile uchar *p) +{ + if (p == NULL) + return; + + puts(indent); + + switch (*p) { + case CISTPL_FUNCE_IDE_IFACE: + { uchar iface = *(p+2); + + puts ((iface == CISTPL_IDE_INTERFACE) ? " IDE" : " unknown"); + puts (" interface "); + break; + } + case CISTPL_FUNCE_IDE_MASTER: + case CISTPL_FUNCE_IDE_SLAVE: + { uchar f1 = *(p+2); + uchar f2 = *(p+4); + + puts ((f1 & CISTPL_IDE_SILICON) ? " [silicon]" : " [rotating]"); + + if (f1 & CISTPL_IDE_UNIQUE) + puts (" [unique]"); + + puts ((f1 & CISTPL_IDE_DUAL) ? " [dual]" : " [single]"); + + if (f2 & CISTPL_IDE_HAS_SLEEP) + puts (" [sleep]"); + + if (f2 & CISTPL_IDE_HAS_STANDBY) + puts (" [standby]"); + + if (f2 & CISTPL_IDE_HAS_IDLE) + puts (" [idle]"); + + if (f2 & CISTPL_IDE_LOW_POWER) + puts (" [low power]"); + + if (f2 & CISTPL_IDE_REG_INHIBIT) + puts (" [reg inhibit]"); + + if (f2 & CISTPL_IDE_HAS_INDEX) + puts (" [index]"); + + if (f2 & CISTPL_IDE_IOIS16) + puts (" [IOis16]"); + + break; + } + } + putc ('\n'); +} +#endif /* CONFIG_IDE_8xx_PCCARD */ + +/* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_IDE_8xx_PCCARD + +#define MAX_IDENT_CHARS 64 +#define MAX_IDENT_FIELDS 4 + +static uchar *known_cards[] = { + "ARGOSY PnPIDE D5", + NULL +}; + +static int identify (volatile uchar *p) +{ + uchar id_str[MAX_IDENT_CHARS]; + uchar data; + uchar *t; + uchar **card; + int i, done; + + if (p == NULL) + return (0); /* Don't know */ + + t = id_str; + done =0; + + for (i=0; i<=4 && !done; ++i, p+=2) { + while ((data = *p) != '\0') { + if (data == 0xFF) { + done = 1; + break; + } + *t++ = data; + if (t == &id_str[MAX_IDENT_CHARS-1]) { + done = 1; + break; + } + p += 2; + } + if (!done) + *t++ = ' '; + } + *t = '\0'; + while (--t > id_str) { + if (*t == ' ') + *t = '\0'; + else + break; + } + puts (id_str); + putc ('\n'); + + for (card=known_cards; *card; ++card) { + debug ("## Compare against \"%s\"\n", *card); + if (strcmp(*card, id_str) == 0) { /* found! */ + debug ("## CARD FOUND ##\n"); + return (1); + } + } + + return (0); /* don't know */ +} +#endif /* CONFIG_IDE_8xx_PCCARD */ + +/* ------------------------------------------------------------------------- */ + +#endif /* CFG_CMD_PCMCIA || (CFG_CMD_IDE && CONFIG_IDE_8xx_PCCARD) */ diff --git a/common/env_flash.c b/common/env_flash.c new file mode 100644 index 0000000..1593d2c --- /dev/null +++ b/common/env_flash.c @@ -0,0 +1,377 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* #define DEBUG */ + +#include <common.h> + +#if defined(CFG_ENV_IS_IN_FLASH) /* Environment is in Flash */ + +#include <command.h> +#include <environment.h> +#include <cmd_nvedit.h> +#include <linux/stddef.h> + +#if ((CONFIG_COMMANDS&(CFG_CMD_ENV|CFG_CMD_FLASH)) == (CFG_CMD_ENV|CFG_CMD_FLASH)) +#define CMD_SAVEENV +#elif defined(CFG_ENV_ADDR_REDUND) +#error Cannot use CFG_ENV_ADDR_REDUND without CFG_CMD_ENV & CFG_CMD_FLASH +#endif + +#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE) && \ + defined(CFG_ENV_ADDR_REDUND) +#error CFG_ENV_ADDR_REDUND should not be used when CFG_ENV_SECT_SIZE > CFG_ENV_SIZE +#endif + +#if defined(CFG_ENV_SIZE_REDUND) && (CFG_ENV_SIZE_REDUND < CFG_ENV_SIZE) +#error CFG_ENV_SIZE_REDUND should not be less then CFG_ENV_SIZE +#endif + +#ifdef CONFIG_INFERNO +# ifdef CFG_ENV_ADDR_REDUND +#error CFG_ENV_ADDR_REDUND is not implemented for CONFIG_INFERNO +# endif +#endif + +char * env_name_spec = "Flash"; + +#ifdef ENV_IS_EMBEDDED + +extern uchar environment[]; +env_t *env_ptr = (env_t *)(&environment[0]); + +#ifdef CMD_SAVEENV +/* static env_t *flash_addr = (env_t *)(&environment[0]);-broken on ARM-wd-*/ +static env_t *flash_addr = (env_t *)CFG_ENV_ADDR; +#endif + +#else /* ! ENV_IS_EMBEDDED */ + +env_t *env_ptr = (env_t *)CFG_ENV_ADDR; +#ifdef CMD_SAVEENV +static env_t *flash_addr = (env_t *)CFG_ENV_ADDR; +#endif + +#endif /* ENV_IS_EMBEDDED */ + +#ifdef CFG_ENV_ADDR_REDUND +static env_t *flash_addr_new = (env_t *)CFG_ENV_ADDR_REDUND; + +static ulong end_addr = CFG_ENV_ADDR + CFG_ENV_SIZE - 1; +static ulong end_addr_new = CFG_ENV_ADDR_REDUND + CFG_ENV_SIZE_REDUND - 1; + +static uchar active_flag = 1; +static uchar obsolete_flag = 0; +#endif + +extern uchar default_environment[]; +extern int default_environment_size; + + +uchar env_get_char_spec (int index) +{ + DECLARE_GLOBAL_DATA_PTR; + + return ( *((uchar *)(gd->env_addr + index)) ); +} + +#ifdef CFG_ENV_ADDR_REDUND + +int env_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int crc1_ok = + (crc32(0, flash_addr->data, ENV_SIZE) == flash_addr->crc); + int crc2_ok = + (crc32(0, flash_addr_new->data, ENV_SIZE) == flash_addr_new->crc); + + uchar flag1 = flash_addr->flags; + uchar flag2 = flash_addr_new->flags; + + ulong addr_default = (ulong)&default_environment[0]; + ulong addr1 = (ulong)&(flash_addr->data); + ulong addr2 = (ulong)&(flash_addr_new->data); + + if (crc1_ok && ! crc2_ok) + { + gd->env_addr = addr1; + gd->env_valid = 1; + } + else if (! crc1_ok && crc2_ok) + { + gd->env_addr = addr2; + gd->env_valid = 1; + } + else if (! crc1_ok && ! crc2_ok) + { + gd->env_addr = addr_default; + gd->env_valid = 0; + } + else if (flag1 == active_flag && flag2 == obsolete_flag) + { + gd->env_addr = addr1; + gd->env_valid = 1; + } + else if (flag1 == obsolete_flag && flag2 == active_flag) + { + gd->env_addr = addr2; + gd->env_valid = 1; + } + else if (flag1 == flag2) + { + gd->env_addr = addr1; + gd->env_valid = 2; + } + else if (flag1 == 0xFF) + { + gd->env_addr = addr1; + gd->env_valid = 2; + } + else if (flag2 == 0xFF) + { + gd->env_addr = addr2; + gd->env_valid = 2; + } + + return (0); +} + +#ifdef CMD_SAVEENV +int saveenv(void) +{ + int rc = 1; + + debug ("Protect off %08lX ... %08lX\n", + (ulong)flash_addr, end_addr); + + if (flash_sect_protect (0, (ulong)flash_addr, end_addr)) { + goto Done; + } + + debug ("Protect off %08lX ... %08lX\n", + (ulong)flash_addr_new, end_addr_new); + + if (flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new)) { + goto Done; + } + + puts ("Erasing Flash..."); + debug (" %08lX ... %08lX ...", + (ulong)flash_addr_new, end_addr_new); + + if (flash_sect_erase ((ulong)flash_addr_new, end_addr_new)) { + goto Done; + } + + puts ("Writing to Flash... "); + debug (" %08lX ... %08lX ...", + (ulong)&(flash_addr_new->data), + sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data)); + if (flash_write(env_ptr->data, + (ulong)&(flash_addr_new->data), + sizeof(env_ptr->data)) || + + flash_write((char *)&(env_ptr->crc), + (ulong)&(flash_addr_new->crc), + sizeof(env_ptr->crc)) || + + flash_write((char *)&obsolete_flag, + (ulong)&(flash_addr->flags), + sizeof(flash_addr->flags)) || + + flash_write((char *)&active_flag, + (ulong)&(flash_addr_new->flags), + sizeof(flash_addr_new->flags))) + { + flash_perror (rc); + goto Done; + } + puts ("done\n"); + + { + env_t * etmp = flash_addr; + ulong ltmp = end_addr; + + flash_addr = flash_addr_new; + flash_addr_new = etmp; + + end_addr = end_addr_new; + end_addr_new = ltmp; + } + + rc = 0; +Done: + + /* try to re-protect */ + (void) flash_sect_protect (1, (ulong)flash_addr, end_addr); + (void) flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new); + + return rc; +} +#endif /* CMD_SAVEENV */ + +#else /* ! CFG_ENV_ADDR_REDUND */ + +int env_init(void) +{ + DECLARE_GLOBAL_DATA_PTR; + + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); + gd->env_valid = 1; + } else { + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 0; + } + + return (0); +} + +#ifdef CMD_SAVEENV + +int saveenv(void) +{ + int len, rc; + ulong end_addr; + ulong flash_sect_addr; +#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE) + ulong flash_offset; + uchar env_buffer[CFG_ENV_SECT_SIZE]; +#else + uchar *env_buffer = (char *)env_ptr; +#endif /* CFG_ENV_SECT_SIZE */ + int rcode = 0; + +#if defined(CFG_ENV_SECT_SIZE) && (CFG_ENV_SECT_SIZE > CFG_ENV_SIZE) + + flash_offset = ((ulong)flash_addr) & (CFG_ENV_SECT_SIZE-1); + flash_sect_addr = ((ulong)flash_addr) & ~(CFG_ENV_SECT_SIZE-1); + + debug ( "copy old content: " + "sect_addr: %08lX env_addr: %08lX offset: %08lX\n", + flash_sect_addr, (ulong)flash_addr, flash_offset); + + /* copy old contents to temporary buffer */ + memcpy (env_buffer, (void *)flash_sect_addr, CFG_ENV_SECT_SIZE); + + /* copy current environment to temporary buffer */ + memcpy ((uchar *)((unsigned long)env_buffer + flash_offset), + env_ptr, + CFG_ENV_SIZE); + + len = CFG_ENV_SECT_SIZE; +#else + flash_sect_addr = (ulong)flash_addr; + len = CFG_ENV_SIZE; +#endif /* CFG_ENV_SECT_SIZE */ + +#ifndef CONFIG_INFERNO + end_addr = flash_sect_addr + len - 1; +#else + /* this is the last sector, and the size is hardcoded here */ + /* otherwise we will get stack problems on loading 128 KB environment */ + end_addr = flash_sect_addr + 0x20000 - 1; +#endif + + debug ("Protect off %08lX ... %08lX\n", + (ulong)flash_sect_addr, end_addr); + + if (flash_sect_protect (0, flash_sect_addr, end_addr)) + return 1; + + puts ("Erasing Flash..."); + if (flash_sect_erase (flash_sect_addr, end_addr)) + return 1; + + puts ("Writing to Flash... "); + rc = flash_write(env_buffer, flash_sect_addr, len); + if (rc != 0) { + flash_perror (rc); + rcode = 1; + } else { + puts ("done\n"); + } + + /* try to re-protect */ + (void) flash_sect_protect (1, flash_sect_addr, end_addr); + return rcode; +} + +#endif /* CMD_SAVEENV */ + +#endif /* CFG_ENV_ADDR_REDUND */ + +void env_relocate_spec (void) +{ +#if !defined(ENV_IS_EMBEDDED) || defined(CFG_ENV_ADDR_REDUND) +#ifdef CFG_ENV_ADDR_REDUND + DECLARE_GLOBAL_DATA_PTR; + + if (gd->env_addr != (ulong)&(flash_addr->data)) + { + env_t * etmp = flash_addr; + ulong ltmp = end_addr; + + flash_addr = flash_addr_new; + flash_addr_new = etmp; + + end_addr = end_addr_new; + end_addr_new = ltmp; + } + + if (flash_addr_new->flags != obsolete_flag && + crc32(0, flash_addr_new->data, ENV_SIZE) == + flash_addr_new->crc) + { + gd->env_valid = 2; + flash_sect_protect (0, (ulong)flash_addr_new, end_addr_new); + flash_write((char *)&obsolete_flag, + (ulong)&(flash_addr_new->flags), + sizeof(flash_addr_new->flags)); + flash_sect_protect (1, (ulong)flash_addr_new, end_addr_new); + } + + if (flash_addr->flags != active_flag && + (flash_addr->flags & active_flag) == active_flag) + { + gd->env_valid = 2; + flash_sect_protect (0, (ulong)flash_addr, end_addr); + flash_write((char *)&active_flag, + (ulong)&(flash_addr->flags), + sizeof(flash_addr->flags)); + flash_sect_protect (1, (ulong)flash_addr, end_addr); + } + + if (gd->env_valid == 2) + puts ("*** Warning - some problems detected " + "reading environment; recovered successfully\n\n"); +#endif /* CFG_ENV_ADDR_REDUND */ + memcpy (env_ptr, (void*)flash_addr, CFG_ENV_SIZE); +#endif /* ! ENV_IS_EMBEDDED || CFG_ENV_ADDR_REDUND */ +} + +#endif /* CFG_ENV_IS_IN_FLASH) */ diff --git a/common/env_nvram.c b/common/env_nvram.c new file mode 100644 index 0000000..fdfa4fc --- /dev/null +++ b/common/env_nvram.c @@ -0,0 +1,138 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * 09-18-2001 Andreas Heppel, Sysgo RTS GmbH <aheppel@sysgo.de> + * + * It might not be possible in all cases to use 'memcpy()' to copy + * the environment to NVRAM, as the NVRAM might not be mapped into + * the memory space. (I.e. this is the case for the BAB750). In those + * cases it might be possible to access the NVRAM using a different + * method. For example, the RTC on the BAB750 is accessible in IO + * space using its address and data registers. To enable usage of + * NVRAM in those cases I invented the functions 'nvram_read()' and + * 'nvram_write()', which will be activated upon the configuration + * #define CFG_NVRAM_ACCESS_ROUTINE. Note, that those functions are + * strongly dependent on the used HW, and must be redefined for each + * board that wants to use them. + */ + +#include <common.h> + +#ifdef CFG_ENV_IS_IN_NVRAM /* Environment is in NVRAM */ + +#include <command.h> +#include <environment.h> +#include <cmd_nvedit.h> +#include <linux/stddef.h> +#include <malloc.h> + +#ifdef CFG_NVRAM_ACCESS_ROUTINE +extern void *nvram_read(void *dest, const long src, size_t count); +extern void nvram_write(long dest, const void *src, size_t count); +env_t *env_ptr = NULL; +#else +env_t *env_ptr = (env_t *)CFG_ENV_ADDR; +#endif + +char * env_name_spec = "NVRAM"; + +extern uchar default_environment[]; +extern int default_environment_size; + +extern uchar (*env_get_char)(int); +extern uchar env_get_char_memory (int index); + + +uchar env_get_char_spec (int index) +{ +#ifdef CFG_NVRAM_ACCESS_ROUTINE + uchar c; + + nvram_read(&c, CFG_ENV_ADDR+index, 1); + + return c; +#else + DECLARE_GLOBAL_DATA_PTR; + + return *((uchar *)(gd->env_addr + index)); +#endif +} + +void env_relocate_spec (void) +{ +#if defined(CFG_NVRAM_ACCESS_ROUTINE) + nvram_read(env_ptr, CFG_ENV_ADDR, CFG_ENV_SIZE); +#else + memcpy (env_ptr, (void*)CFG_ENV_ADDR, CFG_ENV_SIZE); +#endif +} + +int saveenv (void) +{ + int rcode = 0; + +#ifdef CFG_NVRAM_ACCESS_ROUTINE + nvram_write(CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE); +#else + if (memcpy ((char *)CFG_ENV_ADDR, env_ptr, CFG_ENV_SIZE) == NULL) + rcode = 1 ; +#endif + return rcode; +} + + +/************************************************************************ + * Initialize Environment use + * + * We are still running from ROM, so data use is limited + */ +int env_init (void) +{ + DECLARE_GLOBAL_DATA_PTR; + +#if defined(CFG_NVRAM_ACCESS_ROUTINE) + ulong crc; + uchar data[ENV_SIZE]; + nvram_read (&crc, CFG_ENV_ADDR, sizeof(ulong)); + nvram_read (data, CFG_ENV_ADDR+sizeof(ulong), ENV_SIZE); + + if (crc32(0, data, ENV_SIZE) == crc) { + gd->env_addr = (ulong)CFG_ENV_ADDR + sizeof(long); +#else + if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) { + gd->env_addr = (ulong)&(env_ptr->data); +#endif + gd->env_valid = 1; + } else { + gd->env_addr = (ulong)&default_environment[0]; + gd->env_valid = 0; + } + + return (0); +} + +#endif /* CFG_ENV_IS_IN_NVRAM */ diff --git a/common/environment.c b/common/environment.c new file mode 100644 index 0000000..74bfd62 --- /dev/null +++ b/common/environment.c @@ -0,0 +1,198 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 <config.h> +#include <environment.h> + +/* + * Handle HOSTS that have prepended + * crap on symbol names, not TARGETS. + */ +#if defined(__APPLE__) +/* Leading underscore on symbols */ +# define SYM_CHAR "_" +#else /* No leading character on symbols */ +# define SYM_CHAR +#endif + +/* + * Generate embedded environment table + * inside U-Boot image, if needed. + */ +#if defined(ENV_IS_EMBEDDED) +/* + * Only put the environment in it's own section when we are building + * U-Boot proper. The host based program "tools/envcrc" does not need + * a seperate section. Note that ENV_CRC is only defined when building + * U-Boot itself. + */ +#if (defined(CONFIG_FADS) || \ + defined(CONFIG_HYMOD) || \ + defined(CONFIG_ICU862) || \ + defined(CONFIG_R360MPI) || \ + defined(CONFIG_TQM8xxL) || \ + defined(CONFIG_RRVISION) || \ + defined(CONFIG_TRAB) ) && \ + defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */ +/* XXX - This only works with GNU C */ +# define __PPCENV__ __attribute__ ((section(".ppcenv"))) +# define __PPCTEXT__ __attribute__ ((section(".text"))) + +#elif defined(USE_HOSTCC) /* Native for 'tools/envcrc' */ +# define __PPCENV__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ +# define __PPCTEXT__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ + +#else /* Environment is embedded in U-Boot's .text section */ +/* XXX - This only works with GNU C */ +# define __PPCENV__ __attribute__ ((section(".text"))) +# define __PPCTEXT__ __attribute__ ((section(".text"))) +#endif + +/* + * Macros to generate global absolutes. + */ +#define GEN_SYMNAME(str) SYM_CHAR #str +#define GEN_VALUE(str) #str +#define GEN_ABS(name, value) \ + asm (".globl " GEN_SYMNAME(name)); \ + asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) + +/* + * Macros to transform values + * into environment strings. + */ +#define XMK_STR(x) #x +#define MK_STR(x) XMK_STR(x) + +/* + * Check to see if we are building with a + * computed CRC. Otherwise define it as ~0. + */ +#if !defined(ENV_CRC) +# define ENV_CRC ~0 +#endif + +env_t environment __PPCENV__ = { + ENV_CRC, /* CRC Sum */ +#ifdef CFG_REDUNDAND_ENVIRONMENT + 1, /* Flags: valid */ +#endif + { +#if defined(CONFIG_BOOTARGS) + "bootargs=" CONFIG_BOOTARGS "\0" +#endif +#if defined(CONFIG_BOOTCOMMAND) + "bootcmd=" CONFIG_BOOTCOMMAND "\0" +#endif +#if defined(CONFIG_RAMBOOTCOMMAND) + "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_NFSBOOTCOMMAND) + "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0" +#endif +#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) + "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0" +#endif +#ifdef CONFIG_LOADS_ECHO + "loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0" +#endif +#ifdef CONFIG_ETHADDR + "ethaddr=" MK_STR(CONFIG_ETHADDR) "\0" +#endif +#ifdef CONFIG_ETH1ADDR + "eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0" +#endif +#ifdef CONFIG_ETH2ADDR + "eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0" +#endif +#ifdef CONFIG_ETHPRIME + "ethprime=" CONFIG_ETHPRIME "\0" +#endif +#ifdef CONFIG_IPADDR + "ipaddr=" MK_STR(CONFIG_IPADDR) "\0" +#endif +#ifdef CONFIG_SERVERIP + "serverip=" MK_STR(CONFIG_SERVERIP) "\0" +#endif +#ifdef CFG_AUTOLOAD + "autoload=" CFG_AUTOLOAD "\0" +#endif +#ifdef CONFIG_ROOTPATH + "rootpath=" MK_STR(CONFIG_ROOTPATH) "\0" +#endif +#ifdef CONFIG_GATEWAYIP + "gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0" +#endif +#ifdef CONFIG_NETMASK + "netmask=" MK_STR(CONFIG_NETMASK) "\0" +#endif +#ifdef CONFIG_HOSTNAME + "hostname=" MK_STR(CONFIG_HOSTNAME) "\0" +#endif +#ifdef CONFIG_BOOTFILE + "bootfile=" MK_STR(CONFIG_BOOTFILE) "\0" +#endif +#ifdef CONFIG_LOADADDR + "loadaddr=" MK_STR(CONFIG_LOADADDR) "\0" +#endif +#ifdef CONFIG_PREBOOT + "preboot=" CONFIG_PREBOOT "\0" +#endif +#ifdef CONFIG_CLOCKS_IN_MHZ + "clocks_in_mhz=" "1" "\0" +#endif +#ifdef CONFIG_EXTRA_ENV_SETTINGS + CONFIG_EXTRA_ENV_SETTINGS +#endif + "\0" /* Term. env_t.data with 2 NULLs */ + } +}; +#ifdef CFG_ENV_ADDR_REDUND +env_t redundand_environment __PPCENV__ = { + 0, /* CRC Sum: invalid */ + 0, /* Flags: invalid */ + { + "\0" + } +}; +#endif /* CFG_ENV_ADDR_REDUND */ + +/* + * These will end up in the .text section + * if the environment strings are embedded + * in the image. When this is used for + * tools/envcrc, they are placed in the + * .data/.sdata section. + * + */ +unsigned long env_size __PPCTEXT__ = sizeof(env_t); + +/* + * Add in absolutes. + */ +GEN_ABS(env_offset, CFG_ENV_OFFSET); + +#endif /* ENV_IS_EMBEDDED */ diff --git a/common/main.c b/common/main.c new file mode 100644 index 0000000..014804b --- /dev/null +++ b/common/main.c @@ -0,0 +1,817 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <cmd_nvedit.h> +#include <cmd_bootm.h> +#include <malloc.h> +#if defined(CONFIG_BOOT_RETRY_TIME) && defined(CONFIG_RESET_TO_RETRY) +#include <cmd_boot.h> /* for do_reset() prototype */ +#endif + +#ifdef CFG_HUSH_PARSER +#include <hush.h> +#endif + +#define MAX_DELAY_STOP_STR 32 + +static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen); +static int parse_line (char *, char *[]); +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) +static int abortboot(int); +#endif + +#undef DEBUG_PARSER + +char console_buffer[CFG_CBSIZE]; /* console I/O buffer */ + +static char erase_seq[] = "\b \b"; /* erase sequence */ +static char tab_seq[] = " "; /* used to expand TABs */ + +#ifdef CONFIG_BOOT_RETRY_TIME +static uint64_t endtime = 0; /* must be set, default is instant timeout */ +static int retry_time = -1; /* -1 so can call readline before main_loop */ +#endif + +#define endtick(seconds) (get_ticks() + (uint64_t)(seconds) * get_tbclk()) + +#ifndef CONFIG_BOOT_RETRY_MIN +#define CONFIG_BOOT_RETRY_MIN CONFIG_BOOT_RETRY_TIME +#endif + +#ifdef CONFIG_MODEM_SUPPORT +int do_mdm_init = 0; +extern void mdm_init(void); /* defined in board.c */ +#endif + +/*************************************************************************** + * Watch for 'delay' seconds for autoboot stop or autoboot delay string. + * returns: 0 - no key string, allow autoboot + * 1 - got key string, abort + */ +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) +# if defined(CONFIG_AUTOBOOT_KEYED) +static __inline__ int abortboot(int bootdelay) +{ + int abort = 0; + uint64_t etime = endtick(bootdelay); + struct + { + char* str; + u_int len; + int retry; + } + delaykey [] = + { + { str: getenv ("bootdelaykey"), retry: 1 }, + { str: getenv ("bootdelaykey2"), retry: 1 }, + { str: getenv ("bootstopkey"), retry: 0 }, + { str: getenv ("bootstopkey2"), retry: 0 }, + }; + + char presskey [MAX_DELAY_STOP_STR]; + u_int presskey_len = 0; + u_int presskey_max = 0; + u_int i; + +# ifdef CONFIG_AUTOBOOT_PROMPT + printf (CONFIG_AUTOBOOT_PROMPT, bootdelay); +# endif + +# ifdef CONFIG_AUTOBOOT_DELAY_STR + if (delaykey[0].str == NULL) + delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR; +# endif +# ifdef CONFIG_AUTOBOOT_DELAY_STR2 + if (delaykey[1].str == NULL) + delaykey[1].str = CONFIG_AUTOBOOT_DELAY_STR2; +# endif +# ifdef CONFIG_AUTOBOOT_STOP_STR + if (delaykey[2].str == NULL) + delaykey[2].str = CONFIG_AUTOBOOT_STOP_STR; +# endif +# ifdef CONFIG_AUTOBOOT_STOP_STR2 + if (delaykey[3].str == NULL) + delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2; +# endif + + for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { + delaykey[i].len = delaykey[i].str == NULL ? + 0 : strlen (delaykey[i].str); + delaykey[i].len = delaykey[i].len > MAX_DELAY_STOP_STR ? + MAX_DELAY_STOP_STR : delaykey[i].len; + + presskey_max = presskey_max > delaykey[i].len ? + presskey_max : delaykey[i].len; + +# if DEBUG_BOOTKEYS + printf("%s key:<%s>\n", + delaykey[i].retry ? "delay" : "stop", + delaykey[i].str ? delaykey[i].str : "NULL"); +# endif + } + + /* In order to keep up with incoming data, check timeout only + * when catch up. + */ + while (!abort && get_ticks() <= etime) { + for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) { + if (delaykey[i].len > 0 && + presskey_len >= delaykey[i].len && + memcmp (presskey + presskey_len - delaykey[i].len, + delaykey[i].str, + delaykey[i].len) == 0) { +# if DEBUG_BOOTKEYS + printf("got %skey\n", + delaykey[i].retry ? "delay" : "stop"); +# endif + +# ifdef CONFIG_BOOT_RETRY_TIME + /* don't retry auto boot */ + if (! delaykey[i].retry) + retry_time = -1; +# endif + abort = 1; + } + } + + if (tstc()) { + if (presskey_len < presskey_max) { + presskey [presskey_len ++] = getc(); + } + else { + for (i = 0; i < presskey_max - 1; i ++) + presskey [i] = presskey [i + 1]; + + presskey [i] = getc(); + } + } + } +# if DEBUG_BOOTKEYS + if (!abort) + printf("key timeout\n"); +# endif + + return abort; +} + +# else /* !defined(CONFIG_AUTOBOOT_KEYED) */ + +static __inline__ int abortboot(int bootdelay) +{ + int abort = 0; + + printf("Hit any key to stop autoboot: %2d ", bootdelay); + +#if defined CONFIG_ZERO_BOOTDELAY_CHECK + /* + * Check if key already pressed + * Don't check if bootdelay < 0 + */ + if (bootdelay >= 0) { + if (tstc()) { /* we got a key press */ + (void) getc(); /* consume input */ + printf ("\b\b\b 0\n"); + return 1; /* don't auto boot */ + } + } +#endif + + while (bootdelay > 0) { + int i; + + --bootdelay; + /* delay 100 * 10ms */ + for (i=0; !abort && i<100; ++i) { + if (tstc()) { /* we got a key press */ + abort = 1; /* don't auto boot */ + bootdelay = 0; /* no more delay */ + (void) getc(); /* consume input */ + break; + } + udelay (10000); + } + + printf ("\b\b\b%2d ", bootdelay); + } + + putc ('\n'); + + return abort; +} +# endif /* CONFIG_AUTOBOOT_KEYED */ +#endif /* CONFIG_BOOTDELAY >= 0 */ + +/****************************************************************************/ + +void main_loop (void) +{ +#ifndef CFG_HUSH_PARSER + static char lastcommand[CFG_CBSIZE] = { 0, }; + int len; + int rc = 1; + int flag; +#endif + +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + char *s; + int bootdelay; +#endif +#ifdef CONFIG_PREBOOT + char *p; +#endif + +#if defined(CONFIG_VFD) && defined(VFD_TEST_LOGO) + ulong bmp = 0; /* default bitmap */ + extern int trab_vfd (ulong bitmap); + +#ifdef CONFIG_MODEM_SUPPORT + if (do_mdm_init) + bmp = 1; /* alternate bitmap */ +#endif + trab_vfd (bmp); +#endif /* CONFIG_VFD && VFD_TEST_LOGO */ + +#ifdef CONFIG_MODEM_SUPPORT + debug ("DEBUG: main_loop: do_mdm_init=%d\n", do_mdm_init); + if (do_mdm_init) { + uchar *str = strdup(getenv("mdm_cmd")); + setenv ("preboot", str); /* set or delete definition */ + if (str != NULL) + free (str); + mdm_init(); /* wait for modem connection */ + } +#endif /* CONFIG_MODEM_SUPPORT */ + +#ifdef CFG_HUSH_PARSER + u_boot_hush_start (); +#endif + +#ifdef CONFIG_PREBOOT + if ((p = getenv ("preboot")) != NULL) { +# ifdef CONFIG_AUTOBOOT_KEYED + int prev = disable_ctrlc(1); /* disable Control C checking */ +# endif + +# ifndef CFG_HUSH_PARSER + run_command (p, 0); +# else + parse_string_outer(p, FLAG_PARSE_SEMICOLON | + FLAG_EXIT_FROM_LOOP); +# endif + +# ifdef CONFIG_AUTOBOOT_KEYED + disable_ctrlc(prev); /* restore Control C checking */ +# endif + } +#endif /* CONFIG_PREBOOT */ + +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + s = getenv ("bootdelay"); + bootdelay = s ? (int)simple_strtol(s, NULL, 10) : CONFIG_BOOTDELAY; + +#if 0 + printf ("### main_loop entered:\n\n"); +#endif + +# ifdef CONFIG_BOOT_RETRY_TIME + s = getenv ("bootretry"); + if (s != NULL) + retry_time = (int)simple_strtoul(s, NULL, 10); + else + retry_time = CONFIG_BOOT_RETRY_TIME; + if (retry_time >= 0 && retry_time < CONFIG_BOOT_RETRY_MIN) + retry_time = CONFIG_BOOT_RETRY_MIN; +# endif /* CONFIG_BOOT_RETRY_TIME */ + + s = getenv ("bootcmd"); + if (bootdelay >= 0 && s && !abortboot (bootdelay)) { +# ifdef CONFIG_AUTOBOOT_KEYED + int prev = disable_ctrlc(1); /* disable Control C checking */ +# endif + +# ifndef CFG_HUSH_PARSER + run_command (s, 0); +# else + parse_string_outer(s, FLAG_PARSE_SEMICOLON | + FLAG_EXIT_FROM_LOOP); +# endif + +# ifdef CONFIG_AUTOBOOT_KEYED + disable_ctrlc(prev); /* restore Control C checking */ +# endif + } +#endif /* CONFIG_BOOTDELAY */ + + /* + * Main Loop for Monitor Command Processing + */ +#ifdef CFG_HUSH_PARSER + parse_file_outer(); + /* This point is never reached */ + for (;;); +#else + for (;;) { +#ifdef CONFIG_BOOT_RETRY_TIME + if (rc >= 0) { + /* Saw enough of a valid command to + * restart the timeout. + */ + reset_cmd_timeout(); + } +#endif + len = readline (CFG_PROMPT); + + flag = 0; /* assume no special flags for now */ + if (len > 0) + strcpy (lastcommand, console_buffer); + else if (len == 0) + flag |= CMD_FLAG_REPEAT; +#ifdef CONFIG_BOOT_RETRY_TIME + else if (len == -2) { + /* -2 means timed out, retry autoboot + */ + printf("\nTimed out waiting for command\n"); +# ifdef CONFIG_RESET_TO_RETRY + /* Reinit board to run initialization code again */ + do_reset (NULL, 0, 0, NULL); +# else + return; /* retry autoboot */ +# endif + } +#endif + + if (len == -1) + printf ("<INTERRUPT>\n"); + else + rc = run_command (lastcommand, flag); + + if (rc <= 0) { + /* invalid command or not repeatable, forget it */ + lastcommand[0] = 0; + } + } +#endif /*CFG_HUSH_PARSER*/ +} + +/*************************************************************************** + * reset command line timeout to retry_time seconds + */ +#ifdef CONFIG_BOOT_RETRY_TIME +void reset_cmd_timeout(void) +{ + endtime = endtick(retry_time); +} +#endif + +/****************************************************************************/ + +/* + * Prompt for input and read a line. + * If CONFIG_BOOT_RETRY_TIME is defined and retry_time >= 0, + * time out when time goes past endtime (timebase time in ticks). + * Return: number of read characters + * -1 if break + * -2 if timed out + */ +int readline (const char *const prompt) +{ + char *p = console_buffer; + int n = 0; /* buffer index */ + int plen = 0; /* prompt length */ + int col; /* output column cnt */ + char c; + + /* print prompt */ + if (prompt) { + plen = strlen (prompt); + puts (prompt); + } + col = plen; + + for (;;) { +#ifdef CONFIG_BOOT_RETRY_TIME + while (!tstc()) { /* while no incoming data */ + if (retry_time >= 0 && get_ticks() > endtime) + return (-2); /* timed out */ + } +#endif + WATCHDOG_RESET(); /* Trigger watchdog, if needed */ + +#ifdef CONFIG_SHOW_ACTIVITY + while (!tstc()) { + extern void show_activity(int arg); + show_activity(0); + } +#endif + c = getc(); + + /* + * Special character handling + */ + switch (c) { + case '\r': /* Enter */ + case '\n': + *p = '\0'; + puts ("\r\n"); + return (p - console_buffer); + + case 0x03: /* ^C - break */ + console_buffer[0] = '\0'; /* discard input */ + return (-1); + + case 0x15: /* ^U - erase line */ + while (col > plen) { + puts (erase_seq); + --col; + } + p = console_buffer; + n = 0; + continue; + + case 0x17: /* ^W - erase word */ + p=delete_char(console_buffer, p, &col, &n, plen); + while ((n > 0) && (*p != ' ')) { + p=delete_char(console_buffer, p, &col, &n, plen); + } + continue; + + case 0x08: /* ^H - backspace */ + case 0x7F: /* DEL - backspace */ + p=delete_char(console_buffer, p, &col, &n, plen); + continue; + + default: + /* + * Must be a normal character then + */ + if (n < CFG_CBSIZE-2) { + if (c == '\t') { /* expand TABs */ + puts (tab_seq+(col&07)); + col += 8 - (col&07); + } else { + ++col; /* echo input */ + putc (c); + } + *p++ = c; + ++n; + } else { /* Buffer full */ + putc ('\a'); + } + } + } +} + +/****************************************************************************/ + +static char * delete_char (char *buffer, char *p, int *colp, int *np, int plen) +{ + char *s; + + if (*np == 0) { + return (p); + } + + if (*(--p) == '\t') { /* will retype the whole line */ + while (*colp > plen) { + puts (erase_seq); + (*colp)--; + } + for (s=buffer; s<p; ++s) { + if (*s == '\t') { + puts (tab_seq+((*colp) & 07)); + *colp += 8 - ((*colp) & 07); + } else { + ++(*colp); + putc (*s); + } + } + } else { + puts (erase_seq); + (*colp)--; + } + (*np)--; + return (p); +} + +/****************************************************************************/ + +int parse_line (char *line, char *argv[]) +{ + int nargs = 0; + +#ifdef DEBUG_PARSER + printf ("parse_line: \"%s\"\n", line); +#endif + while (nargs < CFG_MAXARGS) { + + /* skip any white space */ + while ((*line == ' ') || (*line == '\t')) { + ++line; + } + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; +#ifdef DEBUG_PARSER + printf ("parse_line: nargs=%d\n", nargs); +#endif + return (nargs); + } + + argv[nargs++] = line; /* begin of argument string */ + + /* find end of string */ + while (*line && (*line != ' ') && (*line != '\t')) { + ++line; + } + + if (*line == '\0') { /* end of line, no more args */ + argv[nargs] = NULL; +#ifdef DEBUG_PARSER + printf ("parse_line: nargs=%d\n", nargs); +#endif + return (nargs); + } + + *line++ = '\0'; /* terminate current arg */ + } + + printf ("** Too many args (max. %d) **\n", CFG_MAXARGS); + +#ifdef DEBUG_PARSER + printf ("parse_line: nargs=%d\n", nargs); +#endif + return (nargs); +} + +/****************************************************************************/ + +static void process_macros (const char *input, char *output) +{ + char c, prev; + const char *varname_start = NULL; + int inputcnt = strlen (input); + int outputcnt = CFG_CBSIZE; + int state = 0; /* 0 = waiting for '$' */ + /* 1 = waiting for '(' */ + /* 2 = waiting for ')' */ + +#ifdef DEBUG_PARSER + char *output_start = output; + + printf ("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input), input); +#endif + + prev = '\0'; /* previous character */ + + while (inputcnt && outputcnt) { + c = *input++; + inputcnt--; + + /* remove one level of escape characters */ + if ((c == '\\') && (prev != '\\')) { + if (inputcnt-- == 0) + break; + prev = c; + c = *input++; + } + + switch (state) { + case 0: /* Waiting for (unescaped) $ */ + if ((c == '$') && (prev != '\\')) { + state++; + } else { + *(output++) = c; + outputcnt--; + } + break; + case 1: /* Waiting for ( */ + if (c == '(') { + state++; + varname_start = input; + } else { + state = 0; + *(output++) = '$'; + outputcnt--; + + if (outputcnt) { + *(output++) = c; + outputcnt--; + } + } + break; + case 2: /* Waiting for ) */ + if (c == ')') { + int i; + char envname[CFG_CBSIZE], *envval; + int envcnt = input-varname_start-1; /* Varname # of chars */ + + /* Get the varname */ + for (i = 0; i < envcnt; i++) { + envname[i] = varname_start[i]; + } + envname[i] = 0; + + /* Get its value */ + envval = getenv (envname); + + /* Copy into the line if it exists */ + if (envval != NULL) + while ((*envval) && outputcnt) { + *(output++) = *(envval++); + outputcnt--; + } + /* Look for another '$' */ + state = 0; + } + break; + } + + prev = c; + } + + if (outputcnt) + *output = 0; + +#ifdef DEBUG_PARSER + printf ("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n", + strlen(output_start), output_start); +#endif +} + +/**************************************************************************** + * returns: + * 1 - command executed, repeatable + * 0 - command executed but not repeatable, interrupted commands are + * always considered not repeatable + * -1 - not executed (unrecognized, bootd recursion or too many args) + * (If cmd is NULL or "" or longer than CFG_CBSIZE-1 it is + * considered unrecognized) + * + * WARNING: + * + * We must create a temporary copy of the command since the command we get + * may be the result from getenv(), which returns a pointer directly to + * the environment data, which may change magicly when the command we run + * creates or modifies environment variables (like "bootp" does). + */ + +int run_command (const char *cmd, int flag) +{ + cmd_tbl_t *cmdtp; + char cmdbuf[CFG_CBSIZE]; /* working copy of cmd */ + char *token; /* start of token in cmdbuf */ + char *sep; /* end of token (separator) in cmdbuf */ + char finaltoken[CFG_CBSIZE]; + char *str = cmdbuf; + char *argv[CFG_MAXARGS + 1]; /* NULL terminated */ + int argc; + int repeatable = 1; + +#ifdef DEBUG_PARSER + printf ("[RUN_COMMAND] cmd[%p]=\"", cmd); + puts (cmd ? cmd : "NULL"); /* use puts - string may be loooong */ + puts ("\"\n"); +#endif + + clear_ctrlc(); /* forget any previous Control C */ + + if (!cmd || !*cmd) { + return -1; /* empty command */ + } + + if (strlen(cmd) >= CFG_CBSIZE) { + puts ("## Command too long!\n"); + return -1; + } + + strcpy (cmdbuf, cmd); + + /* Process separators and check for invalid + * repeatable commands + */ + +#ifdef DEBUG_PARSER + printf ("[PROCESS_SEPARATORS] %s\n", cmd); +#endif + while (*str) { + + /* + * Find separator, or string end + * Allow simple escape of ';' by writing "\;" + */ + for (sep = str; *sep; sep++) { + if ((*sep == ';') && /* separator */ + ( sep != str) && /* past string start */ + (*(sep-1) != '\\')) /* and NOT escaped */ + break; + } + + /* + * Limit the token to data between separators + */ + token = str; + if (*sep) { + str = sep + 1; /* start of command for next pass */ + *sep = '\0'; + } + else + str = sep; /* no more commands for next pass */ +#ifdef DEBUG_PARSER + printf ("token: \"%s\"\n", token); +#endif + + /* find macros in this token and replace them */ + process_macros (token, finaltoken); + + /* Extract arguments */ + argc = parse_line (finaltoken, argv); + + /* Look up command in command table */ + if ((cmdtp = find_cmd(argv[0])) == NULL) { + printf ("Unknown command '%s' - try 'help'\n", argv[0]); + return -1; /* give up after bad command */ + } + + /* found - check max args */ + if (argc > cmdtp->maxargs) { + printf ("Usage:\n%s\n", cmdtp->usage); + return -1; + } + +#if (CONFIG_COMMANDS & CFG_CMD_BOOTD) + /* avoid "bootd" recursion */ + if (cmdtp->cmd == do_bootd) { +#ifdef DEBUG_PARSER + printf ("[%s]\n", finaltoken); +#endif + if (flag & CMD_FLAG_BOOTD) { + printf ("'bootd' recursion detected\n"); + return -1; + } + else + flag |= CMD_FLAG_BOOTD; + } +#endif /* CFG_CMD_BOOTD */ + + /* OK - call function to do the command */ + if ((cmdtp->cmd) (cmdtp, flag, argc, argv) != 0) { + return (-1); + } + + repeatable &= cmdtp->repeatable; + + /* Did the user stop this? */ + if (had_ctrlc ()) + return 0; /* if stopped then not repeatable */ + } + + return repeatable; +} + +/****************************************************************************/ + +#if (CONFIG_COMMANDS & CFG_CMD_RUN) +int do_run (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]) +{ + int i; + int rcode = 1; + + if (argc < 2) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } + + for (i=1; i<argc; ++i) { +#ifndef CFG_HUSH_PARSER + if (run_command (getenv (argv[i]), flag) != -1) ++rcode; +#else + if (parse_string_outer(getenv (argv[i]), + FLAG_PARSE_SEMICOLON | FLAG_EXIT_FROM_LOOP) == 0) ++rcode; +#endif + } + return ((rcode == i) ? 0 : 1); +} +#endif diff --git a/common/miiphyutil.c b/common/miiphyutil.c new file mode 100644 index 0000000..6b2425f --- /dev/null +++ b/common/miiphyutil.c @@ -0,0 +1,172 @@ +/* + * (C) Copyright 2001 + * Gerald Van Baren, Custom IDEAS, vanbaren@cideas.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 + */ + +/* + * This provides a bit-banged interface to the ethernet MII management + * channel. + */ + +#include <common.h> +#include <miiphy.h> + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) + +/***************************************************************************** + * + * Read the OUI, manufacture's model number, and revision number. + * + * OUI: 22 bits (unsigned int) + * Model: 6 bits (unsigned char) + * Revision: 4 bits (unsigned char) + * + * Returns: + * 0 on success + */ +int miiphy_info (unsigned char addr, + unsigned int *oui, + unsigned char *model, unsigned char *rev) +{ + unsigned int reg = 0; + + /* + * Trick: we are reading two 16 registers into a 32 bit variable + * so we do a 16 read into the high order bits of the variable (big + * endian, you know), shift it down 16 bits, and the read the rest. + */ + if (miiphy_read (addr, PHY_PHYIDR2, (unsigned short *) ®) != 0) { +#ifdef DEBUG + printf ("PHY ID register 2 read failed\n"); +#endif + return (-1); + } + reg >>= 16; + +#ifdef DEBUG + printf ("PHY_PHYIDR2 @ 0x%x = 0x%04x\n", addr, reg); +#endif + if (reg == 0xFFFF) { + /* No physical device present at this address */ + return (-1); + } + + if (miiphy_read (addr, PHY_PHYIDR1, (unsigned short *) ®) != 0) { +#ifdef DEBUG + printf ("PHY ID register 1 read failed\n"); +#endif + return (-1); + } +#ifdef DEBUG + printf ("PHY_PHYIDR[1,2] @ 0x%x = 0x%08x\n", addr, reg); +#endif + *oui = ( reg >> 10); + *model = (unsigned char) ((reg >> 4) & 0x0000003F); + *rev = (unsigned char) ( reg & 0x0000000F); + return (0); +} + + +/***************************************************************************** + * + * Reset the PHY. + * Returns: + * 0 on success + */ +int miiphy_reset (unsigned char addr) +{ + unsigned short reg; + int loop_cnt; + + if (miiphy_write (addr, PHY_BMCR, 0x8000) != 0) { +#ifdef DEBUG + printf ("PHY reset failed\n"); +#endif + return (-1); + } + + /* + * Poll the control register for the reset bit to go to 0 (it is + * auto-clearing). This should happen within 0.5 seconds per the + * IEEE spec. + */ + loop_cnt = 0; + reg = 0x8000; + while (((reg & 0x8000) != 0) && (loop_cnt++ < 1000000)) { + if (miiphy_read (addr, PHY_BMCR, ®) != 0) { +# ifdef DEBUG + printf ("PHY status read failed\n"); +# endif + return (-1); + } + } + if ((reg & 0x8000) == 0) { + return (0); + } else { + printf ("PHY reset timed out\n"); + return (-1); + } + return (0); +} + + +/***************************************************************************** + * + * Determine the ethernet speed (10/100). + */ +int miiphy_speed (unsigned char addr) +{ + unsigned short reg; + + if (miiphy_read (addr, PHY_ANLPAR, ®)) { + printf ("PHY speed1 read failed, assuming 10bT\n"); + return (_10BASET); + } + + if ((reg & PHY_ANLPAR_100) != 0) { + return (_100BASET); + } else { + return (_10BASET); + } +} + + +/***************************************************************************** + * + * Determine full/half duplex. + */ +int miiphy_duplex (unsigned char addr) +{ + unsigned short reg; + + if (miiphy_read (addr, PHY_ANLPAR, ®)) { + printf ("PHY duplex read failed, assuming half duplex\n"); + return (HALF); + } + + if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) { + return (FULL); + } else { + return (HALF); + } +} + +#endif /* CONFIG_MII || (CONFIG_COMMANDS & CFG_CMD_MII) */ diff --git a/common/soft_i2c.c b/common/soft_i2c.c new file mode 100644 index 0000000..7777480 --- /dev/null +++ b/common/soft_i2c.c @@ -0,0 +1,416 @@ +/* + * (C) Copyright 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * This has been changed substantially by Gerald Van Baren, Custom IDEAS, + * vanbaren@cideas.com. It was heavily influenced by LiMon, written by + * Neil Russell. + */ + +#include <common.h> +#ifdef CONFIG_MPC8260 /* only valid for MPC8260 */ +#include <ioports.h> +#endif +#include <i2c.h> + +#if defined(CONFIG_SOFT_I2C) + +/* #define DEBUG_I2C */ + + +/*----------------------------------------------------------------------- + * Definitions + */ + +#define RETRIES 0 + + +#define I2C_ACK 0 /* PD_SDA level to ack a byte */ +#define I2C_NOACK 1 /* PD_SDA level to noack a byte */ + + +#ifdef DEBUG_I2C +#define PRINTD(fmt,args...) do { \ + DECLARE_GLOBAL_DATA_PTR; \ + if (gd->have_console) \ + printf (fmt ,##args); \ + } while (0) +#else +#define PRINTD(fmt,args...) +#endif + +/*----------------------------------------------------------------------- + * Local functions + */ +static void send_reset (void); +static void send_start (void); +static void send_stop (void); +static void send_ack (int); +static int write_byte (uchar byte); +static uchar read_byte (int); + + +/*----------------------------------------------------------------------- + * Send a reset sequence consisting of 9 clocks with the data signal high + * to clock any confused device back into an idle state. Also send a + * <stop> at the end of the sequence for belts & suspenders. + */ +static void send_reset(void) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + int j; + + I2C_ACTIVE; + I2C_SDA(1); + for(j = 0; j < 9; j++) { + I2C_SCL(0); + I2C_DELAY; + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_DELAY; + } + send_stop(); + I2C_TRISTATE; +} + +/*----------------------------------------------------------------------- + * START: High -> Low on SDA while SCL is High + */ +static void send_start(void) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + + I2C_DELAY; + I2C_SDA(1); + I2C_ACTIVE; + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_SDA(0); + I2C_DELAY; +} + +/*----------------------------------------------------------------------- + * STOP: Low -> High on SDA while SCL is High + */ +static void send_stop(void) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + + I2C_SCL(0); + I2C_DELAY; + I2C_SDA(0); + I2C_ACTIVE; + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_SDA(1); + I2C_DELAY; + I2C_TRISTATE; +} + + +/*----------------------------------------------------------------------- + * ack should be I2C_ACK or I2C_NOACK + */ +static void send_ack(int ack) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + + I2C_ACTIVE; + I2C_SCL(0); + I2C_DELAY; + + I2C_SDA(ack); + + I2C_ACTIVE; + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_DELAY; + I2C_SCL(0); + I2C_DELAY; +} + + +/*----------------------------------------------------------------------- + * Send 8 bits and look for an acknowledgement. + */ +static int write_byte(uchar data) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + int j; + int nack; + + I2C_ACTIVE; + for(j = 0; j < 8; j++) { + I2C_SCL(0); + I2C_DELAY; + I2C_SDA(data & 0x80); + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_DELAY; + + data <<= 1; + } + + /* + * Look for an <ACK>(negative logic) and return it. + */ + I2C_SCL(0); + I2C_DELAY; + I2C_SDA(1); + I2C_TRISTATE; + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + I2C_DELAY; + nack = I2C_READ; + I2C_SCL(0); + I2C_DELAY; + I2C_ACTIVE; + + return(nack); /* not a nack is an ack */ +} + + +/*----------------------------------------------------------------------- + * if ack == I2C_ACK, ACK the byte so can continue reading, else + * send I2C_NOACK to end the read. + */ +static uchar read_byte(int ack) +{ +#ifdef CONFIG_MPC8260 + volatile ioport_t *iop = ioport_addr((immap_t *)CFG_IMMR, I2C_PORT); +#endif +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + int data; + int j; + + /* + * Read 8 bits, MSB first. + */ + I2C_TRISTATE; + data = 0; + for(j = 0; j < 8; j++) { + I2C_SCL(0); + I2C_DELAY; + I2C_SCL(1); + I2C_DELAY; + data <<= 1; + data |= I2C_READ; + I2C_DELAY; + } + send_ack(ack); + + return(data); +} + +/*=====================================================================*/ +/* Public Functions */ +/*=====================================================================*/ + +/*----------------------------------------------------------------------- + * Initialization + */ +void i2c_init (int speed, int slaveaddr) +{ +#ifdef CONFIG_8xx + volatile immap_t *immr = (immap_t *)CFG_IMMR; +#endif + +#ifdef I2C_INIT + I2C_INIT; +#endif + /* + * WARNING: Do NOT save speed in a static variable: if the + * I2C routines are called before RAM is initialized (to read + * the DIMM SPD, for instance), RAM won't be usable and your + * system will crash. + */ + send_reset (); +} + +/*----------------------------------------------------------------------- + * Probe to see if a chip is present. Also good for checking for the + * completion of EEPROM writes since the chip stops responding until + * the write completes (typically 10mSec). + */ +int i2c_probe(uchar addr) +{ + int rc; + + send_start(); + rc = write_byte ((addr << 1) | 1); + send_stop(); + + return (rc ? 1 : 0); +} + +/*----------------------------------------------------------------------- + * Read bytes + */ +int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + int shift; + PRINTD("i2c_read: chip %02X addr %02X alen %d buffer %p len %d\n", + chip, addr, alen, buffer, len); + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); + + PRINTD("i2c_read: fix addr_overflow: chip %02X addr %02X\n", + chip, addr); +#endif + + /* + * Do the addressing portion of a write cycle to set the + * chip's address pointer. If the address length is zero, + * don't do the normal write cycle to set the address pointer, + * there is no address pointer in this chip. + */ + send_start(); + if(alen > 0) { + if(write_byte(chip << 1)) { /* write cycle */ + send_stop(); + PRINTD("i2c_read, no chip responded %02X\n", chip); + return(1); + } + shift = (alen-1) * 8; + while(alen-- > 0) { + if(write_byte(addr >> shift)) { + PRINTD("i2c_read, address not <ACK>ed\n"); + return(1); + } + shift -= 8; + } + send_stop(); /* reportedly some chips need a full stop */ + send_start(); + } + /* + * Send the chip address again, this time for a read cycle. + * Then read the data. On the last byte, we do a NACK instead + * of an ACK(len == 0) to terminate the read. + */ + write_byte((chip << 1) | 1); /* read cycle */ + while(len-- > 0) { + *buffer++ = read_byte(len == 0); + } + send_stop(); + return(0); +} + +/*----------------------------------------------------------------------- + * Write bytes + */ +int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + int shift, failures = 0; + + PRINTD("i2c_write: chip %02X addr %02X alen %d buffer %p len %d\n", + chip, addr, alen, buffer, len); + + send_start(); + if(write_byte(chip << 1)) { /* write cycle */ + send_stop(); + PRINTD("i2c_write, no chip responded %02X\n", chip); + return(1); + } + shift = (alen-1) * 8; + while(alen-- > 0) { + if(write_byte(addr >> shift)) { + PRINTD("i2c_write, address not <ACK>ed\n"); + return(1); + } + shift -= 8; + } + + while(len-- > 0) { + if(write_byte(*buffer++)) { + failures++; + } + } + send_stop(); + return(failures); +} + +/*----------------------------------------------------------------------- + * Read a register + */ +uchar i2c_reg_read(uchar i2c_addr, uchar reg) +{ + char buf; + + i2c_read(i2c_addr, reg, 1, &buf, 1); + + return(buf); +} + +/*----------------------------------------------------------------------- + * Write a register + */ +void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) +{ + i2c_write(i2c_addr, reg, 1, &val, 1); +} + + +#endif /* CONFIG_SOFT_I2C */ diff --git a/cpu/arm720t/Makefile b/cpu/arm720t/Makefile new file mode 100644 index 0000000..8c950da --- /dev/null +++ b/cpu/arm720t/Makefile @@ -0,0 +1,43 @@ +# +# (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$(CPU).a + +START = start.o +OBJS = serial.o interrupts.o cpu.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c new file mode 100644 index 0000000..52787fe --- /dev/null +++ b/cpu/arm720t/interrupts.c @@ -0,0 +1,265 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <clps7111.h> + +#include <asm/proc-armv/ptrace.h> + +extern void reset_cpu(ulong addr); + +/* we always count down the max. */ +#define TIMER_LOAD_VAL 0xffff + +/* macro to read the 16 bit timer */ +#define READ_TIMER (IO_TC1D & 0xffff) + +#ifdef CONFIG_USE_IRQ +/* enable IRQ/FIQ interrupts */ +void enable_interrupts (void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + : "=r" (temp) + : + : "memory"); +} + + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts (void) +{ + unsigned long old,temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0x80\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts (void) +{ + return; +} +int disable_interrupts (void) +{ + return 0; +} +#endif + + + +void bad_mode (void) +{ + panic ("Resetting CPU ...\n"); + reset_cpu (0); +} + +void show_regs (struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = + { "USER_26", "FIQ_26", "IRQ_26", "SVC_26", "UK4_26", "UK5_26", +"UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", "UK12_26", "UK13_26", + "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", "UK4_32", "UK5_32", + "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", "UK12_32", "UK13_32", + "UK14_32", "SYS_32" + }; + + flags = condition_codes (regs); + + printf ("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer (regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf ("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf (" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled (regs) ? "on" : "off", + fast_interrupts_enabled (regs) ? "on" : "off", + processor_modes[processor_mode (regs)], + thumb_mode (regs) ? " (T)" : ""); +} + +void do_undefined_instruction (struct pt_regs *pt_regs) +{ + printf ("undefined instruction\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_software_interrupt (struct pt_regs *pt_regs) +{ + printf ("software interrupt\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_prefetch_abort (struct pt_regs *pt_regs) +{ + printf ("prefetch abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_data_abort (struct pt_regs *pt_regs) +{ + printf ("data abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_not_used (struct pt_regs *pt_regs) +{ + printf ("not used\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_fiq (struct pt_regs *pt_regs) +{ + printf ("fast interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_irq (struct pt_regs *pt_regs) +{ + printf ("interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +} + +static ulong timestamp; +static ulong lastdec; + +int interrupt_init (void) +{ + /* disable all interrupts */ + IO_INTMR1 = 0; + + /* operate timer 1 in prescale mode */ + IO_SYSCON1 |= SYSCON1_TC1M; + + /* select 2kHz clock source for timer 1 */ + IO_SYSCON1 &= ~SYSCON1_TC1S; + + /* set timer 1 counter */ + lastdec = IO_TC1D = TIMER_LOAD_VAL; + timestamp = 0; + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay (unsigned long usec) +{ + ulong tmo; + + tmo = usec / 1000; + tmo *= CFG_HZ; + tmo /= 1000; + + tmo += get_timer (0); + + while (get_timer_masked () < tmo) + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; + timestamp = 0; +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + TIMER_LOAD_VAL - now; + } + lastdec = now; + + return timestamp; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + + tmo = usec / 1000; + tmo *= CFG_HZ; + tmo /= 1000; + + reset_timer_masked (); + + while (get_timer_masked () < tmo) + /*NOP*/; +} diff --git a/cpu/arm920t/Makefile b/cpu/arm920t/Makefile new file mode 100644 index 0000000..e5ec81d --- /dev/null +++ b/cpu/arm920t/Makefile @@ -0,0 +1,43 @@ +# +# (C) Copyright 2000, 2001, 2002 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(CPU).a + +START = start.o +OBJS = serial.o interrupts.o cpu.o speed.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/arm920t/interrupts.c b/cpu/arm920t/interrupts.c new file mode 100644 index 0000000..963ccbd --- /dev/null +++ b/cpu/arm920t/interrupts.c @@ -0,0 +1,304 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <arm920t.h> +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +#include <asm/proc-armv/ptrace.h> + +extern void reset_cpu(ulong addr); +int timer_load_val = 0; + +/* macro to read the 16 bit timer */ +#define READ_TIMER (rTCNTO4 & 0xffff) + +#ifdef CONFIG_USE_IRQ +/* enable IRQ interrupts */ +void enable_interrupts (void) +{ + unsigned long temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "bic %0, %0, #0x80\n" + "msr cpsr_c, %0" + : "=r" (temp) + : + : "memory"); +} + + +/* + * disable IRQ/FIQ interrupts + * returns true if interrupts had been enabled before we disabled them + */ +int disable_interrupts (void) +{ + unsigned long old,temp; + __asm__ __volatile__("mrs %0, cpsr\n" + "orr %1, %0, #0xc0\n" + "msr cpsr_c, %1" + : "=r" (old), "=r" (temp) + : + : "memory"); + return (old & 0x80) == 0; +} +#else +void enable_interrupts (void) +{ + return; +} +int disable_interrupts (void) +{ + return 0; +} +#endif + + + +void bad_mode (void) +{ + panic ("Resetting CPU ...\n"); + reset_cpu (0); +} + +void show_regs (struct pt_regs *regs) +{ + unsigned long flags; + const char *processor_modes[] = { + "USER_26", "FIQ_26", "IRQ_26", "SVC_26", + "UK4_26", "UK5_26", "UK6_26", "UK7_26", + "UK8_26", "UK9_26", "UK10_26", "UK11_26", + "UK12_26", "UK13_26", "UK14_26", "UK15_26", + "USER_32", "FIQ_32", "IRQ_32", "SVC_32", + "UK4_32", "UK5_32", "UK6_32", "ABT_32", + "UK8_32", "UK9_32", "UK10_32", "UND_32", + "UK12_32", "UK13_32", "UK14_32", "SYS_32", + }; + + flags = condition_codes (regs); + + printf ("pc : [<%08lx>] lr : [<%08lx>]\n" + "sp : %08lx ip : %08lx fp : %08lx\n", + instruction_pointer (regs), + regs->ARM_lr, regs->ARM_sp, regs->ARM_ip, regs->ARM_fp); + printf ("r10: %08lx r9 : %08lx r8 : %08lx\n", + regs->ARM_r10, regs->ARM_r9, regs->ARM_r8); + printf ("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n", + regs->ARM_r7, regs->ARM_r6, regs->ARM_r5, regs->ARM_r4); + printf ("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n", + regs->ARM_r3, regs->ARM_r2, regs->ARM_r1, regs->ARM_r0); + printf ("Flags: %c%c%c%c", + flags & CC_N_BIT ? 'N' : 'n', + flags & CC_Z_BIT ? 'Z' : 'z', + flags & CC_C_BIT ? 'C' : 'c', flags & CC_V_BIT ? 'V' : 'v'); + printf (" IRQs %s FIQs %s Mode %s%s\n", + interrupts_enabled (regs) ? "on" : "off", + fast_interrupts_enabled (regs) ? "on" : "off", + processor_modes[processor_mode (regs)], + thumb_mode (regs) ? " (T)" : ""); +} + +void do_undefined_instruction (struct pt_regs *pt_regs) +{ + printf ("undefined instruction\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_software_interrupt (struct pt_regs *pt_regs) +{ + printf ("software interrupt\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_prefetch_abort (struct pt_regs *pt_regs) +{ + printf ("prefetch abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_data_abort (struct pt_regs *pt_regs) +{ + printf ("data abort\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_not_used (struct pt_regs *pt_regs) +{ + printf ("not used\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_fiq (struct pt_regs *pt_regs) +{ + printf ("fast interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +} + +void do_irq (struct pt_regs *pt_regs) +{ + printf ("interrupt request\n"); + show_regs (pt_regs); + bad_mode (); +} + +static ulong timestamp; +static ulong lastdec; + +int interrupt_init (void) +{ + /* use PWM Timer 4 because it has no output */ + /* prescaler for Timer 4 is 16 */ + rTCFG0 = 0x0f00; + if (timer_load_val == 0) + { + /* + * for 10 ms clock period @ PCLK with 4 bit divider = 1/2 + * (default) and prescaler = 16. Should be 10390 + * @33.25MHz and 15625 @ 50 MHz + */ + timer_load_val = get_PCLK()/(2 * 16 * 100); + } + /* load value for 10 ms timeout */ + lastdec = rTCNTB4 = timer_load_val; + /* auto load, manual update of Timer 4 */ + rTCON = 0x600000; + /* auto load, start Timer 4 */ + rTCON = 0x500000; + timestamp = 0; + + return (0); +} + +/* + * timer without interrupts + */ + +void reset_timer (void) +{ + reset_timer_masked (); +} + +ulong get_timer (ulong base) +{ + return get_timer_masked () - base; +} + +void set_timer (ulong t) +{ + timestamp = t; +} + +void udelay (unsigned long usec) +{ + ulong tmo; + + tmo = usec / 1000; + tmo *= (timer_load_val * 100); + tmo /= 1000; + + tmo += get_timer (0); + + while (get_timer_masked () < tmo) + /*NOP*/; +} + +void reset_timer_masked (void) +{ + /* reset time */ + lastdec = READ_TIMER; + timestamp = 0; +} + +ulong get_timer_masked (void) +{ + ulong now = READ_TIMER; + + if (lastdec >= now) { + /* normal mode */ + timestamp += lastdec - now; + } else { + /* we have an overflow ... */ + timestamp += lastdec + timer_load_val - now; + } + lastdec = now; + + return timestamp; +} + +void udelay_masked (unsigned long usec) +{ + ulong tmo; + + tmo = usec / 1000; + tmo *= (timer_load_val * 100); + tmo /= 1000; + + reset_timer_masked (); + + while (get_timer_masked () < tmo) + /*NOP*/; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On ARM it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return get_timer(0); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On ARM it returns the number of timer ticks per second. + */ +ulong get_tbclk (void) +{ + ulong tbclk; + +#if defined(CONFIG_SMDK2400) || defined(CONFIG_TRAB) + tbclk = timer_load_val * 100; +#elif defined(CONFIG_SMDK2410) + tbclk = CFG_HZ; +#endif + + return tbclk; +} diff --git a/cpu/arm920t/serial.c b/cpu/arm920t/serial.c new file mode 100644 index 0000000..c32e73b --- /dev/null +++ b/cpu/arm920t/serial.c @@ -0,0 +1,200 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn, DENX Software Engineering, <gj@denx.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#if defined(CONFIG_S3C2400) || defined(CONFIG_TRAB) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + int i; + unsigned int reg = 0; + + /* value is calculated so : (int)(PCLK/16./baudrate) -1 */ + reg = get_PCLK() / (16 * gd->baudrate) - 1; + +#ifdef CONFIG_SERIAL1 + /* FIFO enable, Tx/Rx FIFO clear */ + rUFCON0 = 0x07; + rUMCON0 = 0x0; + /* Normal,No parity,1 stop,8 bit */ + rULCON0 = 0x3; + /* + * tx=level,rx=edge,disable timeout int.,enable rx error int., + * normal,interrupt or polling + */ + rUCON0 = 0x245; + rUBRDIV0 = reg; + +#ifdef CONFIG_HWFLOW + rUMCON0 = 0x1; /* RTS up */ +#endif + for (i = 0; i < 100; i++); +#elif CONFIG_SERIAL2 +# if defined(CONFIG_TRAB) +# #error "TRAB supports only CONFIG_SERIAL1" +# endif + /* FIFO enable, Tx/Rx FIFO clear */ + rUFCON1 = 0x06; + rUMCON1 = 0x0; + /* Normal,No parity,1 stop,8 bit */ + rULCON1 = 0x3; + /* + * tx=level,rx=edge,disable timeout int.,enable rx error int., + * normal,interrupt or polling + */ + rUCON1 = 0x245; + rUBRDIV1 = reg; + +#ifdef CONFIG_HWFLOW + rUMCON1 = 0x1; /* RTS up */ +#endif + for (i = 0; i < 100; i++); +#else +#error "Bad: you didn't configure serial ..." +#endif +} + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ +#ifdef CONFIG_SERIAL1 + while (!(rUTRSTAT0 & 0x1)); + + return rURXH0 & 0xff; +#elif CONFIG_SERIAL2 + while (!(rUTRSTAT1 & 0x1)); + + return rURXH1 & 0xff; +#endif +} + +#ifdef CONFIG_HWFLOW +static int hwflow = 0; /* turned off by default */ +int hwflow_onoff(int on) +{ + switch(on) { + case 0: + default: + break; /* return current */ + case 1: + hwflow = 1; /* turn on */ + break; + case -1: + hwflow = 0; /* turn off */ + break; + } + return hwflow; +} +#endif + +#ifdef CONFIG_MODEM_SUPPORT +static int be_quiet = 0; +void disable_putc(void) +{ + be_quiet = 1; +} + +void enable_putc(void) +{ + be_quiet = 0; +} +#endif + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ +#ifdef CONFIG_MODEM_SUPPORT + if (be_quiet) + return; +#endif + +#ifdef CONFIG_SERIAL1 + /* wait for room in the tx FIFO on SERIAL1 */ + while (!(rUTRSTAT0 & 0x2)); + +#ifdef CONFIG_HWFLOW + /* Wait for CTS up */ + while(hwflow && !(rUMSTAT0 & 0x1)) + ; +#endif + + rUTXH0 = c; +#elif CONFIG_SERIAL2 + /* wait for room in the tx FIFO on SERIAL2 */ + while (!(rUTRSTAT1 & 0x2)); + +#ifdef CONFIG_HWFLOW + /* Wait for CTS up */ + while(hwflow && !(rUMSTAT1 & 0x1)) + ; +#endif + rUTXH1 = c; +#endif + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Test whether a character is in the RX buffer + */ +int serial_tstc (void) +{ +#ifdef CONFIG_SERIAL1 + return rUTRSTAT0 & 0x1; +#elif CONFIG_SERIAL2 + return rUTRSTAT1 & 0x1; +#endif +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/cpu/arm920t/speed.c b/cpu/arm920t/speed.c new file mode 100644 index 0000000..1ee0c1a --- /dev/null +++ b/cpu/arm920t/speed.c @@ -0,0 +1,96 @@ +/* + * (C) Copyright 2001-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * David Mueller, ELSOFT AG, d.mueller@elsoft.ch + * + * 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 + */ + +/* This code should work for both the S3C2400 and the S3C2410 + * as they seem to have the same PLL and clock machinery inside. + * The different address mapping is handled by the s3c24xx.h files below. + */ + +#include <common.h> +#if defined(CONFIG_S3C2400) +#include <s3c2400.h> +#elif defined(CONFIG_S3C2410) +#include <s3c2410.h> +#endif + +#define MPLL 0 +#define UPLL 1 + +/* ------------------------------------------------------------------------- */ +/* NOTE: This describes the proper use of this file. + * + * CONFIG_PLL_INPUT_FREQ should be defined as the input frequency of the PLL. + * + * get_FCLK(), get_HCLK(), get_PCLK() and get_UCLK() return the clock of + * the specified bus in HZ. + */ +/* ------------------------------------------------------------------------- */ + +static ulong get_PLLCLK(int pllreg) +{ + ulong r, m, p, s; + + if (pllreg == MPLL) + r = rMPLLCON; + else if (pllreg == UPLL) + r = rUPLLCON; + else + hang(); + + m = ((r & 0xFF000) >> 12) + 8; + p = ((r & 0x003F0) >> 4) + 2; + s = r & 0x3; + + return((CONFIG_PLL_INPUT_FREQ * m) / (p << s)); +} + +/* return FCLK frequency */ +ulong get_FCLK(void) +{ + return(get_PLLCLK(MPLL)); +} + +/* return HCLK frequency */ +ulong get_HCLK(void) +{ + ulong clkdiv = rCLKDIVN; + + return((clkdiv & 0x2) ? get_FCLK()/2 : get_FCLK()); +} + +/* return PCLK frequency */ +ulong get_PCLK(void) +{ + ulong clkdiv = rCLKDIVN; + + return((clkdiv & 0x1) ? get_HCLK()/2 : get_HCLK()); +} + +/* return UCLK frequency */ +ulong get_UCLK(void) +{ + return(get_PLLCLK(UPLL)); +} diff --git a/cpu/mpc824x/cpu_init.c b/cpu/mpc824x/cpu_init.c new file mode 100644 index 0000000..602f65d --- /dev/null +++ b/cpu/mpc824x/cpu_init.c @@ -0,0 +1,383 @@ +/* + * (C) Copyright 2000 + * Rob Taylor. Flying Pig Systems. robt@flyingpig.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <mpc824x.h> + +#ifndef CFG_BANK0_ROW +#define CFG_BANK0_ROW 0 +#endif +#ifndef CFG_BANK1_ROW +#define CFG_BANK1_ROW 0 +#endif +#ifndef CFG_BANK2_ROW +#define CFG_BANK2_ROW 0 +#endif +#ifndef CFG_BANK3_ROW +#define CFG_BANK3_ROW 0 +#endif +#ifndef CFG_BANK4_ROW +#define CFG_BANK4_ROW 0 +#endif +#ifndef CFG_BANK5_ROW +#define CFG_BANK5_ROW 0 +#endif +#ifndef CFG_BANK6_ROW +#define CFG_BANK6_ROW 0 +#endif +#ifndef CFG_BANK7_ROW +#define CFG_BANK7_ROW 0 +#endif +#ifndef CFG_DBUS_SIZE2 +#define CFG_DBUS_SIZE2 0 +#endif + +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + */ +void +cpu_init_f (void) +{ +/* MOUSSE board is initialized in asm */ +#if !defined(CONFIG_MOUSSE) && !defined(CONFIG_BMW) + register unsigned long val; + CONFIG_WRITE_HALFWORD(PCICR, 0x06); /* Bus Master, respond to PCI memory space acesses*/ +/* CONFIG_WRITE_HALFWORD(PCISR, 0xffff); */ /*reset PCISR*/ + +#if defined(CONFIG_MUSENKI) || defined(CONFIG_PN62) +/* Why is this here, you ask? Try, just try setting 0x8000 + * in PCIACR with CONFIG_WRITE_HALFWORD() + * this one was a stumper, and we are annoyed + */ + +#define M_CONFIG_WRITE_HALFWORD( addr, data ) \ + __asm__ __volatile__( \ + " \ + stw %2,0(%0)\n \ + sync\n \ + sth %3,2(%1)\n \ + sync\n \ + " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" (CONFIG_DATA), \ + "r" (PCISWAP(addr & ~3)), "r" (PCISWAP(data << 16)) \ + ); + + M_CONFIG_WRITE_HALFWORD(PCIACR, 0x8000); +#endif + + CONFIG_WRITE_BYTE(PCLSR, 0x8); /* set PCI cache line size */ + + /* + * Note that although this bit is cleared after a hard reset, it + * must be explicitly set and then cleared by software during + * initialization in order to guarantee correct operation of the + * DLL and the SDRAM_CLK[0:3] signals (if they are used). + */ + CONFIG_READ_BYTE (AMBOR, val); + CONFIG_WRITE_BYTE(AMBOR, val & 0xDF); + CONFIG_WRITE_BYTE(AMBOR, val | 0x20); + CONFIG_WRITE_BYTE(AMBOR, val & 0xDF); + + CONFIG_READ_WORD(PICR1, val); +#if defined(CONFIG_MPC8240) + CONFIG_WRITE_WORD( PICR1, + (val & (PICR1_ADDRESS_MAP | PICR1_RCS0)) | + PIRC1_MSK | PICR1_PROC_TYPE_603E | + PICR1_FLASH_WR_EN | PICR1_MCP_EN | + PICR1_CF_DPARK | PICR1_EN_PCS | + PICR1_CF_APARK ); +#elif defined(CONFIG_MPC8245) + CONFIG_WRITE_WORD( PICR1, + (val & (PICR1_RCS0)) | + PICR1_PROC_TYPE_603E | + PICR1_FLASH_WR_EN | PICR1_MCP_EN | + PICR1_CF_DPARK | PICR1_NO_BUSW_CK | + PICR1_DEC| PICR1_CF_APARK | 0x10); /* 8245 UM says bit 4 must be set */ +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + + CONFIG_READ_WORD(PICR2, val); + val= val & ~ (PICR2_CF_SNOOP_WS_MASK | PICR2_CF_APHASE_WS_MASK); /*mask off waitstate bits*/ +#ifndef CONFIG_PN62 + val |= PICR2_CF_SNOOP_WS_1WS | PICR2_CF_APHASE_WS_1WS; /*1 wait state*/ +#endif + CONFIG_WRITE_WORD(PICR2, val); + + CONFIG_WRITE_WORD(EUMBBAR, CFG_EUMB_ADDR); +#ifndef CFG_RAMBOOT + CONFIG_WRITE_WORD(MCCR1, (CFG_ROMNAL << MCCR1_ROMNAL_SHIFT) | + (CFG_BANK0_ROW) | + (CFG_BANK1_ROW << MCCR1_BANK1ROW_SHIFT) | + (CFG_BANK2_ROW << MCCR1_BANK2ROW_SHIFT) | + (CFG_BANK3_ROW << MCCR1_BANK3ROW_SHIFT) | + (CFG_BANK4_ROW << MCCR1_BANK4ROW_SHIFT) | + (CFG_BANK5_ROW << MCCR1_BANK5ROW_SHIFT) | + (CFG_BANK6_ROW << MCCR1_BANK6ROW_SHIFT) | + (CFG_BANK7_ROW << MCCR1_BANK7ROW_SHIFT) | + (CFG_ROMFAL << MCCR1_ROMFAL_SHIFT)); +#endif + +#if defined(CFG_ASRISE) && defined(CFG_ASFALL) + CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT | + CFG_ASRISE << MCCR2_ASRISE_SHIFT | + CFG_ASFALL << MCCR2_ASFALL_SHIFT); +#else + CONFIG_WRITE_WORD(MCCR2, CFG_REFINT << MCCR2_REFINT_SHIFT); +#endif + +#if defined(CONFIG_MPC8240) + CONFIG_WRITE_WORD(MCCR3, + (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) | + (CFG_REFREC << MCCR3_REFREC_SHIFT) | + (CFG_RDLAT << MCCR3_RDLAT_SHIFT)); +#elif defined(CONFIG_MPC8245) + CONFIG_WRITE_WORD(MCCR3, + (((CFG_BSTOPRE & 0x003c) >> 2) << MCCR3_BSTOPRE2TO5_SHIFT) | + (CFG_REFREC << MCCR3_REFREC_SHIFT)); +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + +/* this is gross. We think these should all be the same, and various boards + * should define CFG_ACTORW to 0 if they don't want to set it, or even, if + * its not set, we define it to zero in this file + */ +#if defined(CONFIG_CU824) || defined(CONFIG_PN62) + CONFIG_WRITE_WORD(MCCR4, + (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | + (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | + MCCR4_BIT21 | + (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) | + ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) | + (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) | + CFG_SDMODE_BURSTLEN) << MCCR4_SDMODE_SHIFT) | + (CFG_ACTORW << MCCR4_ACTTORW_SHIFT) | + (((CFG_BSTOPRE & 0x03c0) >> 6) << MCCR4_BSTOPRE6TO9_SHIFT)); +#elif defined(CONFIG_MPC8240) + CONFIG_WRITE_WORD(MCCR4, + (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | + (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | + MCCR4_BIT21 | + (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) | + ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) | + (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) | + (CFG_SDMODE_BURSTLEN)) <<MCCR4_SDMODE_SHIFT) | + (((CFG_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT )); +#elif defined(CONFIG_MPC8245) + CONFIG_READ_WORD(MCCR1, val); + val &= MCCR1_DBUS_SIZE0; /* test for 64-bit mem bus */ + + CONFIG_WRITE_WORD(MCCR4, + (CFG_PRETOACT << MCCR4_PRETOACT_SHIFT) | + (CFG_ACTTOPRE << MCCR4_ACTTOPRE_SHIFT) | + (CFG_EXTROM ? MCCR4_EXTROM : 0) | + (CFG_REGDIMM ? MCCR4_REGDIMM : 0) | + (CFG_REGISTERD_TYPE_BUFFER ? MCCR4_REGISTERED: 0) | + ((CFG_BSTOPRE & 0x0003) <<MCCR4_BSTOPRE0TO1_SHIFT ) | + (CFG_DBUS_SIZE2 << MCCR4_DBUS_SIZE2_SHIFT) | + (((CFG_SDMODE_CAS_LAT <<4) | (CFG_SDMODE_WRAP <<3) | + (val ? 2 : 3)) << MCCR4_SDMODE_SHIFT) | + (CFG_ACTORW << MCCR4_ACTTORW_SHIFT) | + (((CFG_BSTOPRE & 0x03c0) >> 6) <<MCCR4_BSTOPRE6TO9_SHIFT )); +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif + + CONFIG_WRITE_WORD(MSAR1, + ( (CFG_BANK0_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) | + (((CFG_BANK1_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | + (((CFG_BANK2_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | + (((CFG_BANK3_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(EMSAR1, + ( (CFG_BANK0_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) | + (((CFG_BANK1_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | + (((CFG_BANK2_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | + (((CFG_BANK3_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(MSAR2, + ( (CFG_BANK4_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) | + (((CFG_BANK5_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | + (((CFG_BANK6_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | + (((CFG_BANK7_START & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(EMSAR2, + ( (CFG_BANK4_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) | + (((CFG_BANK5_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | + (((CFG_BANK6_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | + (((CFG_BANK7_START & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(MEAR1, + ( (CFG_BANK0_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) | + (((CFG_BANK1_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | + (((CFG_BANK2_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | + (((CFG_BANK3_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(EMEAR1, + ( (CFG_BANK0_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) | + (((CFG_BANK1_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | + (((CFG_BANK2_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | + (((CFG_BANK3_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(MEAR2, + ( (CFG_BANK4_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) | + (((CFG_BANK5_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 8) | + (((CFG_BANK6_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 16) | + (((CFG_BANK7_END & MICR_ADDR_MASK) >> MICR_ADDR_SHIFT) << 24)); + CONFIG_WRITE_WORD(EMEAR2, + ( (CFG_BANK4_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) | + (((CFG_BANK5_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 8) | + (((CFG_BANK6_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 16) | + (((CFG_BANK7_END & MICR_EADDR_MASK) >> MICR_EADDR_SHIFT) << 24)); + + CONFIG_WRITE_BYTE(ODCR, CFG_ODCR); +#ifdef CFG_DLL_MAX_DELAY + CONFIG_WRITE_BYTE(MIOCR1, CFG_DLL_MAX_DELAY); /* needed to make DLL lock */ +#endif +#if defined(CFG_DLL_EXTEND) && defined(CFG_PCI_HOLD_DEL) + CONFIG_WRITE_BYTE(PMCR2, CFG_DLL_EXTEND | CFG_PCI_HOLD_DEL); +#endif +#if defined(MIOCR2) && defined(CFG_SDRAM_DSCD) + CONFIG_WRITE_BYTE(MIOCR2, CFG_SDRAM_DSCD); /* change memory input */ +#endif /* setup & hold time */ + + CONFIG_WRITE_BYTE(MBER, + CFG_BANK0_ENABLE | + (CFG_BANK1_ENABLE << 1) | + (CFG_BANK2_ENABLE << 2) | + (CFG_BANK3_ENABLE << 3) | + (CFG_BANK4_ENABLE << 4) | + (CFG_BANK5_ENABLE << 5) | + (CFG_BANK6_ENABLE << 6) | + (CFG_BANK7_ENABLE << 7)); + +#ifdef CFG_PGMAX + CONFIG_WRITE_BYTE(MPMR, CFG_PGMAX); +#endif + + /* ! Wait 200us before initialize other registers */ + /*FIXME: write a decent udelay wait */ + __asm__ __volatile__( + " mtctr %0 \n \ + 0: bdnz 0b\n" + : + : "r" (0x10000)); + + CONFIG_READ_WORD(MCCR1, val); + CONFIG_WRITE_WORD(MCCR1, val | MCCR1_MEMGO); /* set memory access going */ + __asm__ __volatile__("eieio"); + +#endif /* !CONFIG_MOUSSE && !CONFIG_BMW */ +} + + +#ifdef CONFIG_MOUSSE +#ifdef INCLUDE_MPC107_REPORT +struct MPC107_s{ + unsigned int iobase; + char desc[120]; +} MPC107Regs[] ={ + {BMC_BASE+0x0, "MPC107 Vendor/Device ID"}, + {BMC_BASE+0x4, "MPC107 PCI Command/Status Register"}, + {BMC_BASE+0x8, "MPC107 Revision"}, + {BMC_BASE+0xC, "MPC107 Cache Line Size"}, + {BMC_BASE+0x10, "MPC107 LMBAR"}, + {BMC_BASE+0x14, "MPC824x PCSR"}, + {BMC_BASE+0xA8, "MPC824x PICR1"}, + {BMC_BASE+0xAC, "MPC824x PICR2"}, + {BMC_BASE+0x46, "MPC824x PACR"}, + {BMC_BASE+0x310, "MPC824x ITWR"}, + {BMC_BASE+0x300, "MPC824x OMBAR"}, + {BMC_BASE+0x308, "MPC824x OTWR"}, + {BMC_BASE+0x14, "MPC107 Peripheral Control and Status Register"}, + {BMC_BASE+0x78, "MPC107 EUMBAR"}, + {BMC_BASE+0xC0, "MPC107 Processor Bus Error Status"}, + {BMC_BASE+0xC4, "MPC107 PCI Bus Error Status"}, + {BMC_BASE+0xC8, "MPC107 Processor/PCI Error Address"}, + {BMC_BASE+0xE0, "MPC107 AMBOR Register"}, + {BMC_BASE+0xF0, "MPC107 MCCR1 Register"}, + {BMC_BASE+0xF4, "MPC107 MCCR2 Register"}, + {BMC_BASE+0xF8, "MPC107 MCCR3 Register"}, + {BMC_BASE+0xFC, "MPC107 MCCR4 Register"} +}; +#define N_MPC107_Regs (sizeof(MPC107Regs)/sizeof(MPC107Regs[0])) +#endif /* INCLUDE_MPC107_REPORT */ +#endif /* CONFIG_MOUSSE */ + +/* + * initialize higher level parts of CPU like time base and timers + */ +int cpu_init_r (void) +{ +#ifdef CONFIG_MOUSSE +#ifdef INCLUDE_MPC107_REPORT + unsigned int tmp = 0, i; +#endif + /* + * Initialize the EUMBBAR (Embedded Util Mem Block Base Addr Reg). + * This is necessary before the EPIC, DMA ctlr, I2C ctlr, etc. can + * be accessed. + */ + +#ifdef CONFIG_MPC8240 /* only on MPC8240 */ + mpc824x_mpc107_setreg (EUMBBAR, EUMBBAR_VAL); + /* MOT/SPS: Issue #10002, PCI (FD Alias enable) */ + mpc824x_mpc107_setreg (AMBOR, 0x000000C0); +#endif + + +#ifdef INCLUDE_MPC107_REPORT + /* Check MPC824x PCI Device and Vendor ID */ + while ((tmp = mpc824x_mpc107_getreg (BMC_BASE)) != 0x31057) { + printf (" MPC107: offset=0x%x, val = 0x%x\n", + BMC_BASE, + tmp); + } + + for (i = 0; i < N_MPC107_Regs; i++) { + printf (" 0x%x/%s = 0x%x\n", + MPC107Regs[i].iobase, + MPC107Regs[i].desc, + mpc824x_mpc107_getreg (MPC107Regs[i].iobase)); + } + + printf ("IBAT0L = 0x%08X\n", mfspr (IBAT0L)); + printf ("IBAT0U = 0x%08X\n", mfspr (IBAT0U)); + printf ("IBAT1L = 0x%08X\n", mfspr (IBAT1L)); + printf ("IBAT1U = 0x%08X\n", mfspr (IBAT1U)); + printf ("IBAT2L = 0x%08X\n", mfspr (IBAT2L)); + printf ("IBAT2U = 0x%08X\n", mfspr (IBAT2U)); + printf ("IBAT3L = 0x%08X\n", mfspr (IBAT3L)); + printf ("IBAT3U = 0x%08X\n", mfspr (IBAT3U)); + printf ("DBAT0L = 0x%08X\n", mfspr (DBAT0L)); + printf ("DBAT0U = 0x%08X\n", mfspr (DBAT0U)); + printf ("DBAT1L = 0x%08X\n", mfspr (DBAT1L)); + printf ("DBAT1U = 0x%08X\n", mfspr (DBAT1U)); + printf ("DBAT2L = 0x%08X\n", mfspr (DBAT2L)); + printf ("DBAT2U = 0x%08X\n", mfspr (DBAT2U)); + printf ("DBAT3L = 0x%08X\n", mfspr (DBAT3L)); + printf ("DBAT3U = 0x%08X\n", mfspr (DBAT3U)); +#endif /* INCLUDE_MPC107_REPORT */ +#endif /* CONFIG_MOUSSE */ + return (0); +} diff --git a/cpu/mpc824x/drivers/i2c/i2c1.c b/cpu/mpc824x/drivers/i2c/i2c1.c new file mode 100644 index 0000000..be6ec60 --- /dev/null +++ b/cpu/mpc824x/drivers/i2c/i2c1.c @@ -0,0 +1,1228 @@ +/************************************************************* + * + * Copyright @ Motorola, 1999 + * + ************************************************************/ +#include <common.h> + +#ifdef CONFIG_HARD_I2C +#include <i2c.h> +#include "i2c_export.h" +#include "i2c.h" + +#undef I2CDBG0 +#undef DEBUG + +/* Define a macro to use an optional application-layer print function, if + * one was passed to the I2C library during initialization. If there was + * no function pointer passed, this protects against calling it. Also define + * the global variable that holds the passed pointer. + */ +#define TIMEOUT (CFG_HZ/4) +#define PRINT if ( app_print ) app_print +static int (*app_print) (char *, ...); + +/******************* Internal to I2C Driver *****************/ +static unsigned int ByteToXmit = 0; +static unsigned int XmitByte = 0; +static unsigned char *XmitBuf = 0; +static unsigned int XmitBufEmptyStop = 0; +static unsigned int ByteToRcv = 0; +static unsigned int RcvByte = 0; +static unsigned char *RcvBuf = 0; +static unsigned int RcvBufFulStop = 0; +static unsigned int MasterRcvAddress = 0; + +/* Set by call to get_eumbbar during I2C_Initialize. + * This could be globally available to the I2C library, but there is + * an advantage to passing it as a parameter: it is already in a register + * and doesn't have to be loaded from memory. Also, that is the way the + * I2C library was already implemented and I don't want to change it without + * a more detailed analysis. + * It is being set as a global variable in I2C_Initialize to hide it from + * the DINK application layer, because it is Kahlua-specific. I think that + * get_eumbbar, load_runtime_reg, and store_runtime_reg should be defined in + * a Kahlua-specific library dealing with the embedded utilities memory block. + * Right now, get_eumbbar is defined in dink32/kahlua.s. The other two are + * defined in dink32/drivers/i2c/i2c2.s. + */ +static unsigned int Global_eumbbar = 0; + +extern unsigned int load_runtime_reg (unsigned int eumbbar, + unsigned int reg); + +extern unsigned int store_runtime_reg (unsigned int eumbbar, + unsigned int reg, unsigned int val); + +/************************** API *****************/ + +/* Application Program Interface (API) are the calls provided by the I2C + * library to upper layer applications (i.e., DINK) to access the Kahlua + * I2C bus interface. The functions and values that are part of this API + * are declared in i2c_export.h. + */ + +/* Initialize I2C unit with the following: + * driver's slave address + * interrupt enabled + * optional pointer to application layer print function + * + * These parameters may be added: + * desired clock rate + * digital filter frequency sampling rate + * + * This function must be called before I2C unit can be used. + */ +I2C_Status I2C_Initialize (unsigned char addr, + I2C_INTERRUPT_MODE en_int, + int (*p) (char *, ...)) +{ + I2CStatus status; + + /* establish the pointer, if there is one, to the application's "printf" */ + app_print = p; + + /* If this is the first call, get the embedded utilities memory block + * base address. I'm not sure what to do about error handling here: + * if a non-zero value is returned, accept it. + */ + if (Global_eumbbar == 0) + Global_eumbbar = get_eumbbar (); + if (Global_eumbbar == 0) { + PRINT ("I2C_Initialize: can't find EUMBBAR\n"); + return I2C_ERROR; + } + + /* validate the I2C address */ + if (addr & 0x80) { + PRINT ("I2C_Initialize, I2C address invalid: %d 0x%x\n", + (unsigned int) addr, (unsigned int) addr); + return I2C_ERROR; + } + + /* Call the internal I2C library function to perform work. + * Accept the default frequency sampling rate (no way to set it currently, + * via I2C_Init) and set the clock frequency to something reasonable. + */ + status = I2C_Init (Global_eumbbar, (unsigned char) 0x31, addr, en_int); + if (status != I2CSUCCESS) { + PRINT ("I2C_Initialize: error in initiation\n"); + return I2C_ERROR; + } + + /* all is well */ + return I2C_SUCCESS; +} + + +/* Perform the given I2C transaction, only MASTER_XMIT and MASTER_RCV + * are implemented. Both are only in polling mode. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_addr is the I2C address of the slave device + * data_addr is the address of the data on the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +I2C_Status I2C_do_transaction ( I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + unsigned char data_addr, + int len, + char *buffer, + I2C_STOP_MODE stop, + int retry, I2C_RESTART_MODE rsta) +{ + I2C_Status status; + unsigned char data_addr_buffer[1]; + +#if 1 +/* This is a temporary work-around. The I2C library breaks the protocol + * if it attempts to handle a data transmission in more than one + * transaction, so the data address and the actual data bytes are put + * into a single buffer before sending it to the library internal functions. + * The problem is related to being able to restart a transaction without + * sending the I2C device address or repeating the data address. It may take + * a day or two to sort it all out, so I'll have to get back to it later. + * Look at I2C_Start to see about using some status flags (I'm not sure that + * "stop" and "rsta" are enough to reflect the states, maybe so; but the logic + * in the library is insufficient) to control correct handling of the protocol. + */ + unsigned char dummy_buffer[257]; + + if (act == I2C_MASTER_XMIT) { + int i; + + if (len > 256) + return I2C_ERROR; + for (i = 1; i <= len; i++) + dummy_buffer[i] = buffer[i - 1]; + dummy_buffer[0] = data_addr; + status = I2C_do_buffer (en_int, act, i2c_addr, 1 + len, + dummy_buffer, stop, retry, rsta); + if (status != I2C_SUCCESS) { + PRINT ("I2C_do_transaction: can't perform data transfer\n"); + return I2C_ERROR; + } + return I2C_SUCCESS; + } +#endif /* end of temp work-around */ + + /* validate requested transaction type */ + if ((act != I2C_MASTER_XMIT) && (act != I2C_MASTER_RCV)) { + PRINT ("I2C_do_transaction, invalid transaction request: %d\n", + act); + return I2C_ERROR; + } + + /* range check the I2C address */ + if (i2c_addr & 0x80) { + PRINT ("I2C_do_transaction, I2C address out of range: %d 0x%x\n", + (unsigned int) i2c_addr, (unsigned int) i2c_addr); + return I2C_ERROR; + } else { + data_addr_buffer[0] = data_addr; + } + + /* + * We first have to contact the slave device and transmit the + * data address. Be careful about the STOP and restart stuff. + * We don't want to signal STOP after sending the data + * address, but this could be a continuation if the + * application didn't release the bus after the previous + * transaction, by not sending a STOP after it. + */ + status = I2C_do_buffer (en_int, I2C_MASTER_XMIT, i2c_addr, 1, + data_addr_buffer, I2C_NO_STOP, retry, rsta); + if (status != I2C_SUCCESS) { + PRINT ("I2C_do_transaction: can't send data address for read\n"); + return I2C_ERROR; + } + + /* The data transfer will be a continuation. */ + rsta = I2C_RESTART; + + /* now handle the user data */ + status = I2C_do_buffer (en_int, act, i2c_addr, len, + buffer, stop, retry, rsta); + if (status != I2C_SUCCESS) { + PRINT ("I2C_do_transaction: can't perform data transfer\n"); + return I2C_ERROR; + } + + /* all is well */ + return I2C_SUCCESS; +} + +/* This function performs the work for I2C_do_transaction. The work is + * split into this function to enable I2C_do_transaction to first transmit + * the data address to the I2C slave device without putting the data address + * into the first byte of the buffer. + * + * en_int controls interrupt/polling mode + * act is the type of transaction + * i2c_addr is the I2C address of the slave device + * len is the length of data to send or receive + * buffer is the address of the data buffer + * stop = I2C_NO_STOP, don't signal STOP at end of transaction + * I2C_STOP, signal STOP at end of transaction + * retry is the timeout retry value, currently ignored + * rsta = I2C_NO_RESTART, this is not continuation of existing transaction + * I2C_RESTART, this is a continuation of existing transaction + */ +static I2C_Status I2C_do_buffer (I2C_INTERRUPT_MODE en_int, + I2C_TRANSACTION_MODE act, + unsigned char i2c_addr, + int len, + unsigned char *buffer, + I2C_STOP_MODE stop, + int retry, I2C_RESTART_MODE rsta) +{ + I2CStatus rval; + unsigned int dev_stat; + + if (act == I2C_MASTER_RCV) { + /* set up for master-receive transaction */ + rval = I2C_get (Global_eumbbar, i2c_addr, buffer, len, stop, rsta); + } else { + /* set up for master-transmit transaction */ + rval = I2C_put (Global_eumbbar, i2c_addr, buffer, len, stop, rsta); + } + + /* validate the setup */ + if (rval != I2CSUCCESS) { + dev_stat = load_runtime_reg (Global_eumbbar, I2CSR); + PRINT ("Error(I2C_do_buffer): control phase, code(0x%08x), status(0x%08x)\n", rval, dev_stat); + I2C_Stop (Global_eumbbar); + return I2C_ERROR; + } + + if (en_int == 1) { + /* this should not happen, no interrupt handling yet */ + return I2C_SUCCESS; + } + + /* this performs the polling action, when the transfer is completed, + * the status returned from I2C_Timer_Event will be I2CBUFFFULL or + * I2CBUFFEMPTY (rcv or xmit), I2CSUCCESS or I2CADDRESS indicates the + * transaction is not yet complete, anything else is an error. + */ + while (rval == I2CSUCCESS || rval == I2CADDRESS) { + int timeval = get_timer (0); + + /* poll the device until something happens */ + do { + rval = I2C_Timer_Event (Global_eumbbar, 0); + } + while (rval == I2CNOEVENT && get_timer (timeval) < TIMEOUT); + + /* check for error condition */ + if (rval == I2CSUCCESS || + rval == I2CBUFFFULL || + rval == I2CBUFFEMPTY || + rval == I2CADDRESS) { + ; /* do nothing */ + } else { + /* report the error condition */ + dev_stat = load_runtime_reg (Global_eumbbar, I2CSR); + PRINT ("Error(I2C_do_buffer): code(0x%08x), status(0x%08x)\n", + rval, dev_stat); + return I2C_ERROR; + } + } + + /* all is well */ + return I2C_SUCCESS; +} + +/** + * Note: + * + * In all following functions, + * the caller shall pass the configured embedded utility memory + * block base, EUMBBAR. + **/ + +/*********************************************************** + * function: I2C_put + * + * description: + Send a buffer of data to the intended rcv_addr. + * If stop_flag is set, after the whole buffer + * is sent, generate a STOP signal provided that the + * receiver doesn't signal the STOP in the middle. + * I2C is the master performing transmitting. If + * no STOP signal is generated at the end of current + * transaction, the master can generate a START signal + * to another slave addr. + * + * note: this is master xmit API + *********************************************************/ +static I2CStatus I2C_put (unsigned int eumbbar, unsigned char rcv_addr, /* receiver's address */ + unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + unsigned int is_cnt) +{ /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + if (buffer_ptr == 0 || length == 0) { + return I2CERROR; + } +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_put\n", __FILE__, __LINE__); +#endif + + XmitByte = 0; + ByteToXmit = length; + XmitBuf = buffer_ptr; + XmitBufEmptyStop = stop_flag; + + RcvByte = 0; + ByteToRcv = 0; + RcvBuf = 0; + + /* we are the master, start transaction */ + return I2C_Start (eumbbar, rcv_addr, XMIT, is_cnt); +} + +/*********************************************************** + * function: I2C_get + * + * description: + * Receive a buffer of data from the desired sender_addr + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the master performing receiving. If no STOP signal + * is generated, the master can generate a START signal + * to another slave addr. + * + * note: this is master receive API + **********************************************************/ +static I2CStatus I2C_get (unsigned int eumbbar, unsigned char rcv_from, /* sender's address */ + unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag, /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ + unsigned int is_cnt) +{ /* 1 - this is a restart, don't check MBB + * 0 - this is a new start, check MBB + */ + if (buffer_ptr == 0 || length == 0) { + return I2CERROR; + } +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_get\n", __FILE__, __LINE__); +#endif + + RcvByte = 0; + ByteToRcv = length; + RcvBuf = buffer_ptr; + RcvBufFulStop = stop_flag; + + XmitByte = 0; + ByteToXmit = 0; + XmitBuf = 0; + + /* we are the master, start the transaction */ + return I2C_Start (eumbbar, rcv_from, RCV, is_cnt); + +} + +#if 0 /* turn off dead code */ +/********************************************************* + * function: I2C_write + * + * description: + * Send a buffer of data to the requiring master. + * If stop_flag is set, after the whole buffer is sent, + * generate a STOP signal provided that the requiring + * receiver doesn't signal the STOP in the middle. + * I2C is the slave performing transmitting. + * + * Note: this is slave xmit API. + * + * due to the current Kahlua design, slave transmitter + * shall not signal STOP since there is no way + * for master to detect it, causing I2C bus hung. + * + * For the above reason, the stop_flag is always + * set, i.e., 0. + * + * programmer shall use the timer on Kahlua to + * control the interval of data byte at the + * master side. + *******************************************************/ +static I2CStatus I2C_write (unsigned int eumbbar, unsigned char *buffer_ptr, /* pointer of data to be sent */ + unsigned int length, /* number of byte of in the buffer */ + unsigned int stop_flag) +{ /* 1 - signal STOP when buffer is empty + * 0 - no STOP signal when buffer is empty + */ + if (buffer_ptr == 0 || length == 0) { + return I2CERROR; + } + + XmitByte = 0; + ByteToXmit = length; + XmitBuf = buffer_ptr; + XmitBufEmptyStop = 0; /* in order to avoid bus hung, ignored the user's stop_flag */ + + RcvByte = 0; + ByteToRcv = 0; + RcvBuf = 0; + + /* we are the slave, just wait for being called, or pull */ + /* I2C_Timer_Event( eumbbar ); */ +} + +/****************************************************** + * function: I2C_read + * + * description: + * Receive a buffer of data from the sending master. + * If stop_flag is set, when the buffer is full and the + * sender does not signal STOP, generate a STOP signal. + * I2C is the slave performing receiving. + * + * note: this is slave receive API + ****************************************************/ +static I2CStatus I2C_read (unsigned int eumbbar, unsigned char *buffer_ptr, /* pointer of receiving buffer */ + unsigned int length, /* length of the receiving buffer */ + unsigned int stop_flag) +{ /* 1 - signal STOP when buffer is full + * 0 - no STOP signal when buffer is full + */ + if (buffer_ptr == 0 || length == 0) { + return I2CERROR; + } + + RcvByte = 0; + ByteToRcv = length; + RcvBuf = buffer_ptr; + RcvBufFulStop = stop_flag; + + XmitByte = 0; + ByteToXmit = 0; + XmitBuf = 0; + + /* wait for master to call us, or poll */ + /* I2C_Timer_Event( eumbbar ); */ +} +#endif /* turn off dead code */ + +/********************************************************* + * function: I2c_Timer_Event + * + * description: + * if interrupt is not used, this is the timer event handler. + * After each fixed time interval, this function can be called + * to check the I2C status and call appropriate function to + * handle the status event. + ********************************************************/ +static I2CStatus I2C_Timer_Event (unsigned int eumbbar, + I2CStatus (*handler) (unsigned int)) +{ + I2C_STAT stat; + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Timer_Event\n", __FILE__, __LINE__); +#endif + + stat = I2C_Get_Stat (eumbbar); + + if (stat.mif == 1) { + if (handler == 0) { + return I2C_ISR (eumbbar); + } else { + return (*handler) (eumbbar); + } + } + + return I2CNOEVENT; +} + + +/****************** Device I/O function *****************/ + +/****************************************************** + * function: I2C_Start + * + * description: Generate a START signal in the desired mode. + * I2C is the master. + * + * Return I2CSUCCESS if no error. + * + * note: + ****************************************************/ +static I2CStatus I2C_Start (unsigned int eumbbar, unsigned char slave_addr, /* address of the receiver */ + I2C_MODE mode, /* XMIT(1) - put (write) + * RCV(0) - get (read) + */ + unsigned int is_cnt) +{ /* 1 - this is a restart, don't check MBB + * 0 - this is a new start + */ + unsigned int tmp = 0; + I2C_STAT stat; + I2C_CTRL ctrl; + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Start addr 0x%x mode %d cnt %d\n", __FILE__, + __LINE__, slave_addr, mode, is_cnt); +#endif + + ctrl = I2C_Get_Ctrl (eumbbar); + + /* first make sure I2C has been initialized */ + if (ctrl.men == 0) { + return I2CERROR; + } + + /* next make sure bus is idle */ + stat = I2C_Get_Stat (eumbbar); + + if (is_cnt == 0 && stat.mbb == 1) { + /* sorry, we lost */ + return I2CBUSBUSY; + } else if (is_cnt == 1 && stat.mif == 1 && stat.mal == 0) { + /* sorry, we lost the bus */ + return I2CALOSS; + } + + + /* OK, I2C is enabled and we have the bus */ + + /* prepare to write the slave address */ + ctrl.msta = 1; + ctrl.mtx = 1; + ctrl.txak = 0; + ctrl.rsta = is_cnt; /* set the repeat start bit */ + I2C_Set_Ctrl (eumbbar, ctrl); + + /* write the slave address and xmit/rcv mode bit */ + tmp = load_runtime_reg (eumbbar, I2CDR); + tmp = (tmp & 0xffffff00) | + ((slave_addr & 0x007f) << 1) | + (mode == XMIT ? 0x0 : 0x1); + store_runtime_reg (eumbbar, I2CDR, tmp); + + if (mode == RCV) { + MasterRcvAddress = 1; + } else { + MasterRcvAddress = 0; + } + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Start exit\n", __FILE__, __LINE__); +#endif + + /* wait for the interrupt or poll */ + return I2CSUCCESS; +} + +/*********************************************************** + * function: I2c_Stop + * + * description: Generate a STOP signal to terminate the master + * transaction. + * return I2CSUCCESS + * + **********************************************************/ +static I2CStatus I2C_Stop (unsigned int eumbbar) +{ + I2C_CTRL ctrl; + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Stop enter\n", __FILE__, __LINE__); +#endif + + ctrl = I2C_Get_Ctrl (eumbbar); + ctrl.msta = 0; + I2C_Set_Ctrl (eumbbar, ctrl); + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Stop exit\n", __FILE__, __LINE__); +#endif + + return I2CSUCCESS; +} + +/**************************************************** + * function: I2C_Master_Xmit + * + * description: Master sends one byte of data to + * slave target + * + * return I2CSUCCESS if the byte transmitted. + * Otherwise no-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) == 0 + * I2CCR(MSTA) == 1 && I2CCR(MTX) == 1 + * + ***************************************************/ +static I2CStatus I2C_Master_Xmit (unsigned int eumbbar) +{ + unsigned int val; + + if (ByteToXmit > 0) { + + if (ByteToXmit == XmitByte) { + /* all xmitted */ + ByteToXmit = 0; + + if (XmitBufEmptyStop == 1) { + I2C_Stop (eumbbar); + } + + return I2CBUFFEMPTY; + + } +#ifdef I2CDBG0 + PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, + *(XmitBuf + XmitByte)); +#endif + + val = *(XmitBuf + XmitByte); + val &= 0x000000ff; + store_runtime_reg (eumbbar, I2CDR, val); + XmitByte++; + + return I2CSUCCESS; + + } + + return I2CBUFFEMPTY; +} + +/*********************************************** + * function: I2C_Master_Rcv + * + * description: master reads one byte data + * from slave source + * + * return I2CSUCCESS if no error + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && + * I2CCR(MSTA) == 1 && I2CCR(MTX) == 0 + * + ***********************************************/ +static I2CStatus I2C_Master_Rcv (unsigned int eumbbar) +{ + I2C_CTRL ctrl; + unsigned int val; + + if (ByteToRcv > 0) { + + if (ByteToRcv - RcvByte == 2 && RcvBufFulStop == 1) { + /* master requests more than or equal to 2 bytes + * we are reading 2nd to last byte + */ + + /* we need to set I2CCR(TXAK) to generate a STOP */ + ctrl = I2C_Get_Ctrl (eumbbar); + ctrl.txak = 1; + I2C_Set_Ctrl (eumbbar, ctrl); + + /* Kahlua will automatically generate a STOP + * next time a transaction happens + */ + + /* note: the case of master requesting one byte is + * handled in I2C_ISR + */ + } + + /* generat a STOP before reading the last byte */ + if (RcvByte + 1 == ByteToRcv && RcvBufFulStop == 1) { + I2C_Stop (eumbbar); + } + + val = load_runtime_reg (eumbbar, I2CDR); + *(RcvBuf + RcvByte) = val & 0xFF; + +#ifdef I2CDBG0 + PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, + *(RcvBuf + RcvByte)); +#endif + + RcvByte++; + + if (ByteToRcv == RcvByte) { + ByteToRcv = 0; + + return I2CBUFFFULL; + } + + return I2CSUCCESS; + } + + return I2CBUFFFULL; + +} + +/**************************************************** + * function: I2C_Slave_Xmit + * + * description: Slave sends one byte of data to + * requesting destination + * + * return SUCCESS if the byte transmitted. Otherwise + * No-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && I2CSR(RXAK) = 0 + * I2CCR(MSTA) == 0 && I2CCR(MTX) == 1 + * + ***************************************************/ +static I2CStatus I2C_Slave_Xmit (unsigned int eumbbar) +{ + unsigned int val; + + if (ByteToXmit > 0) { + + if (ByteToXmit == XmitByte) { + /* no more data to send */ + ByteToXmit = 0; + + /* + * do not toggle I2CCR(MTX). Doing so will + * cause bus-hung since current Kahlua design + * does not give master a way to detect slave + * stop. It is always a good idea for master + * to use timer to prevent the long long + * delays + */ + + return I2CBUFFEMPTY; + } +#ifdef I2CDBG + PRINT ("%s(%d): xmit 0x%02x\n", __FILE__, __LINE__, + *(XmitBuf + XmitByte)); +#endif + + val = *(XmitBuf + XmitByte); + val &= 0x000000ff; + store_runtime_reg (eumbbar, I2CDR, val); + XmitByte++; + + return I2CSUCCESS; + } + + return I2CBUFFEMPTY; +} + +/*********************************************** + * function: I2C_Slave_Rcv + * + * description: slave reads one byte data + * from master source + * + * return I2CSUCCESS if no error otherwise non-zero + * + * Note: condition must meet when this function is called: + * I2CSR(MIF) == 1 && I2CSR(MCF) == 1 && + * I2CCR(MSTA) == 0 && I2CCR(MTX) = 0 + * + ***********************************************/ +static I2CStatus I2C_Slave_Rcv (unsigned int eumbbar) +{ + unsigned int val; + I2C_CTRL ctrl; + + if (ByteToRcv > 0) { + val = load_runtime_reg (eumbbar, I2CDR); + *(RcvBuf + RcvByte) = val & 0xff; +#ifdef I2CDBG + PRINT ("%s(%d): rcv 0x%02x\n", __FILE__, __LINE__, + *(RcvBuf + RcvByte)); +#endif + RcvByte++; + + if (ByteToRcv == RcvByte) { + if (RcvBufFulStop == 1) { + /* all done */ + ctrl = I2C_Get_Ctrl (eumbbar); + ctrl.txak = 1; + I2C_Set_Ctrl (eumbbar, ctrl); + } + + ByteToRcv = 0; + return I2CBUFFFULL; + } + + return I2CSUCCESS; + } + + return I2CBUFFFULL; +} + +/****************** Device Control Function *************/ + +/********************************************************* + * function: I2C_Init + * + * description: Initialize I2C unit with desired frequency divider, + * master's listening address, with interrupt enabled + * or disabled. + * + * note: + ********************************************************/ +static I2CStatus I2C_Init (unsigned int eumbbar, unsigned char fdr, /* frequency divider */ + unsigned char slave_addr, /* driver's address used for receiving */ + unsigned int en_int) +{ /* 1 - enable I2C interrupt + * 0 - disable I2C interrup + */ + I2C_CTRL ctrl; + unsigned int tmp; + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Init enter\n", __FILE__, __LINE__); +#endif + + ctrl = I2C_Get_Ctrl (eumbbar); + /* disable the I2C module before we change everything */ + ctrl.men = 0; + I2C_Set_Ctrl (eumbbar, ctrl); + + /* set the frequency diver */ + tmp = load_runtime_reg (eumbbar, I2CFDR); + tmp = (tmp & 0xffffffc0) | (fdr & 0x3f); + store_runtime_reg (eumbbar, I2CFDR, tmp); + + /* Set our listening (slave) address */ + tmp = load_runtime_reg (eumbbar, I2CADR); + tmp = (tmp & 0xffffff01) | ((slave_addr & 0x7f) << 1); + store_runtime_reg (eumbbar, I2CADR, tmp); + + /* enable I2C with desired interrupt setting */ + ctrl.men = 1; + ctrl.mien = en_int & 0x1; + I2C_Set_Ctrl (eumbbar, ctrl); +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_Init exit\n", __FILE__, __LINE__); +#endif + + return I2CSUCCESS; + +} + +/***************************************** + * function I2c_Get_Stat + * + * description: Query I2C Status, i.e., read I2CSR + * + ****************************************/ +static I2C_STAT I2C_Get_Stat (unsigned int eumbbar) +{ + unsigned int temp; + I2C_STAT stat; + + temp = load_runtime_reg (eumbbar, I2CSR); + +#ifdef I2CDBG0 + PRINT ("%s(%d): get stat = 0x%08x\n", __FILE__, __LINE__, temp); +#endif + + stat.rsrv0 = (temp & 0xffffff00) >> 8; + stat.mcf = (temp & 0x00000080) >> 7; + stat.maas = (temp & 0x00000040) >> 6; + stat.mbb = (temp & 0x00000020) >> 5; + stat.mal = (temp & 0x00000010) >> 4; + stat.rsrv1 = (temp & 0x00000008) >> 3; + stat.srw = (temp & 0x00000004) >> 2; + stat.mif = (temp & 0x00000002) >> 1; + stat.rxak = (temp & 0x00000001); + return stat; +} + +/********************************************* + * function: I2c_Set_Ctrl + * + * description: Change I2C Control bits, + * i.e., write to I2CCR + * + ********************************************/ +static void I2C_Set_Ctrl (unsigned int eumbbar, I2C_CTRL ctrl) +{ /* new control value */ + unsigned int temp = load_runtime_reg (eumbbar, I2CCR); + + temp &= 0xffffff03; + temp |= ((ctrl.men & 0x1) << 7); + temp |= ((ctrl.mien & 0x1) << 6); + temp |= ((ctrl.msta & 0x1) << 5); + temp |= ((ctrl.mtx & 0x1) << 4); + temp |= ((ctrl.txak & 0x1) << 3); + temp |= ((ctrl.rsta & 0x1) << 2); +#ifdef I2CDBG0 + PRINT ("%s(%d): set ctrl = 0x%08x\n", __FILE__, __LINE__, temp); +#endif + store_runtime_reg (eumbbar, I2CCR, temp); + +} + +/***************************************** + * function: I2C_Get_Ctrl + * + * description: Query I2C Control bits, + * i.e., read I2CCR + *****************************************/ +static I2C_CTRL I2C_Get_Ctrl (unsigned int eumbbar) +{ + union { + I2C_CTRL ctrl; + unsigned int temp; + } s; + + s.temp = load_runtime_reg (eumbbar, I2CCR); +#ifdef I2CDBG0 + PRINT ("%s(%d): get ctrl = 0x%08x\n", __FILE__, __LINE__, s.temp); +#endif + + return s.ctrl; +} + + +/**************************************** + * function: I2C_Slave_Addr + * + * description: Process slave address phase. + * return I2CSUCCESS if no error + * + * note: Precondition for calling this function: + * I2CSR(MIF) == 1 && + * I2CSR(MAAS) == 1 + ****************************************/ +static I2CStatus I2C_Slave_Addr (unsigned int eumbbar) +{ + I2C_STAT stat = I2C_Get_Stat (eumbbar); + I2C_CTRL ctrl = I2C_Get_Ctrl (eumbbar); + + if (stat.srw == 1) { + /* we are asked to xmit */ + ctrl.mtx = 1; + I2C_Set_Ctrl (eumbbar, ctrl); /* set MTX */ + return I2C_Slave_Xmit (eumbbar); + } + + /* we are asked to receive data */ + ctrl.mtx = 0; + I2C_Set_Ctrl (eumbbar, ctrl); + (void) load_runtime_reg (eumbbar, I2CDR); /* do a fake read to start */ + + return I2CADDRESS; +} + +/*********************************************** + * function: I2C_ISR + * + * description: I2C Interrupt service routine + * + * note: Precondition: + * I2CSR(MIF) == 1 + **********************************************/ +static I2CStatus I2C_ISR (unsigned int eumbbar) +{ + I2C_STAT stat; + I2C_CTRL ctrl; + +#ifdef I2CDBG0 + PRINT ("%s(%d): I2C_ISR\n", __FILE__, __LINE__); +#endif + + stat = I2C_Get_Stat (eumbbar); + ctrl = I2C_Get_Ctrl (eumbbar); + + /* clear MIF */ + stat.mif = 0; + + /* Now let see what kind of event this is */ + if (stat.mcf == 1) { + /* transfer compete */ + + /* clear the MIF bit */ + I2C_Set_Stat (eumbbar, stat); + + if (ctrl.msta == 1) { + /* master */ + if (ctrl.mtx == 1) { + /* check if this is the address phase for master receive */ + if (MasterRcvAddress == 1) { + /* Yes, it is the address phase of master receive */ + ctrl.mtx = 0; + /* now check how much we want to receive */ + if (ByteToRcv == 1 && RcvBufFulStop == 1) { + ctrl.txak = 1; + } + + I2C_Set_Ctrl (eumbbar, ctrl); + (void) load_runtime_reg (eumbbar, I2CDR); /* fake read first */ + + MasterRcvAddress = 0; + return I2CADDRESS; + + } + + /* master xmit */ + if (stat.rxak == 0) { + /* slave has acknowledged */ + return I2C_Master_Xmit (eumbbar); + } + + /* slave has not acknowledged yet, generate a STOP */ + if (XmitBufEmptyStop == 1) { + ctrl.msta = 0; + I2C_Set_Ctrl (eumbbar, ctrl); + } + + return I2CSUCCESS; + } + + /* master receive */ + return I2C_Master_Rcv (eumbbar); + } + + /* slave */ + if (ctrl.mtx == 1) { + /* slave xmit */ + if (stat.rxak == 0) { + /* master has acknowledged */ + return I2C_Slave_Xmit (eumbbar); + } + + /* master has not acknowledged, wait for STOP */ + /* do nothing for preventing bus from hung */ + return I2CSUCCESS; + } + + /* slave rcv */ + return I2C_Slave_Rcv (eumbbar); + + } else if (stat.maas == 1) { + /* received a call from master */ + + /* clear the MIF bit */ + I2C_Set_Stat (eumbbar, stat); + + /* master is calling us, process the address phase */ + return I2C_Slave_Addr (eumbbar); + } else { + /* has to be arbitration lost */ + stat.mal = 0; + I2C_Set_Stat (eumbbar, stat); + + ctrl.msta = 0; /* return to receive mode */ + I2C_Set_Ctrl (eumbbar, ctrl); + } + + return I2CSUCCESS; + +} + +/****************************************************** + * function: I2C_Set_Stat + * + * description: modify the I2CSR + * + *****************************************************/ +static void I2C_Set_Stat (unsigned int eumbbar, I2C_STAT stat) +{ + union { + unsigned int val; + I2C_STAT stat; + } s_tmp; + union { + unsigned int val; + I2C_STAT stat; + } s; + + s.val = load_runtime_reg (eumbbar, I2CSR); + s.val &= 0xffffff08; + s_tmp.stat = stat; + s.val |= (s_tmp.val & 0xf7); + +#ifdef I2CDBG0 + PRINT ("%s(%d): set stat = 0x%08x\n", __FILE__, __LINE__, s.val); +#endif + + store_runtime_reg (eumbbar, I2CSR, s.val); + +} + +/****************************************************** + * The following are routines to glue the rest of + * U-Boot to the Sandpoint I2C driver. + *****************************************************/ + +void i2c_init (int speed, int slaveadd) +{ +#ifdef DEBUG + I2C_Initialize (0x7f, 0, (void *) printf); +#else + I2C_Initialize (0x7f, 0, 0); +#endif +} + +int i2c_probe (uchar chip) +{ + int tmp; + + /* + * Try to read the first location of the chip. The underlying + * driver doesn't appear to support sending just the chip address + * and looking for an <ACK> back. + */ + udelay(10000); + return i2c_read (chip, 0, 1, (char *)&tmp, 1); +} + +int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + I2CStatus status; + uchar xaddr[4]; + + if (alen > 0) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + + status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen, + &xaddr[4 - alen], I2C_NO_STOP, 1, + I2C_NO_RESTART); + if (status != I2C_SUCCESS) { + PRINT ("i2c_read: can't send data address for read\n"); + return 1; + } + } + + /* The data transfer will be a continuation. */ + status = I2C_do_buffer (0, I2C_MASTER_RCV, chip, len, + buffer, I2C_STOP, 1, (alen > 0 ? I2C_RESTART : + I2C_NO_RESTART)); + + if (status != I2C_SUCCESS) { + PRINT ("i2c_read: can't perform data transfer\n"); + return 1; + } + + return 0; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + I2CStatus status; + unsigned char dummy_buffer[I2C_RXTX_LEN + 2]; + int i; + + dummy_buffer[0] = addr & 0xFF; + if (alen == 2) + dummy_buffer[1] = (addr >> 8) & 0xFF; + for (i = 0; i < len; i++) + dummy_buffer[i + alen] = buffer[i]; + + status = I2C_do_buffer (0, I2C_MASTER_XMIT, chip, alen + len, + dummy_buffer, I2C_STOP, 1, I2C_NO_RESTART); + +#ifdef CFG_EEPROM_PAGE_WRITE_DELAY_MS + udelay(CFG_EEPROM_PAGE_WRITE_DELAY_MS * 1000); +#endif + if (status != I2C_SUCCESS) { + PRINT ("i2c_write: can't perform data transfer\n"); + return 1; + } + + return 0; +} + +uchar i2c_reg_read (uchar i2c_addr, uchar reg) +{ + char buf[1]; + + i2c_init (0, 0); + + i2c_read (i2c_addr, reg, 1, buf, 1); + + return (buf[0]); +} + +void i2c_reg_write (uchar i2c_addr, uchar reg, uchar val) +{ + i2c_init (0, 0); + + i2c_write (i2c_addr, reg, 1, &val, 1); +} + +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/mpc824x/pci.c b/cpu/mpc824x/pci.c new file mode 100644 index 0000000..7e3c4c3 --- /dev/null +++ b/cpu/mpc824x/pci.c @@ -0,0 +1,78 @@ +/* + * arch/ppc/kernel/mpc10x_common.c + * + * Common routines for the Motorola SPS MPC106, MPC107 and MPC8240 Host bridge, + * Mem ctlr, EPIC, etc. + * + * Author: Mark A. Greer + * mgreer@mvista.com + * + * Copyright 2001 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> +#include <mpc824x.h> + +void pci_mpc824x_init (struct pci_controller *hose) +{ + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* System memory space */ + pci_set_region(hose->regions + 0, + CHRP_PCI_MEMORY_BUS, + CHRP_PCI_MEMORY_PHYS, + CHRP_PCI_MEMORY_SIZE, + PCI_REGION_MEM | PCI_REGION_MEMORY); + + /* PCI memory space */ + pci_set_region(hose->regions + 1, + CHRP_PCI_MEM_BUS, + CHRP_PCI_MEM_PHYS, + CHRP_PCI_MEM_SIZE, + PCI_REGION_MEM); + + /* ISA/PCI memory space */ + pci_set_region(hose->regions + 2, + CHRP_ISA_MEM_BUS, + CHRP_ISA_MEM_PHYS, + CHRP_ISA_MEM_SIZE, + PCI_REGION_MEM); + + /* PCI I/O space */ + pci_set_region(hose->regions + 3, + CHRP_PCI_IO_BUS, + CHRP_PCI_IO_PHYS, + CHRP_PCI_IO_SIZE, + PCI_REGION_IO); + + /* ISA/PCI I/O space */ + pci_set_region(hose->regions + 4, + CHRP_ISA_IO_BUS, + CHRP_ISA_IO_PHYS, + CHRP_ISA_IO_SIZE, + PCI_REGION_IO); + + hose->region_count = 5; + + pci_setup_indirect(hose, + CHRP_REG_ADDR, + CHRP_REG_DATA); + + pci_register_hose(hose); + + hose->last_busno = pci_hose_scan(hose); +} + +#endif diff --git a/cpu/mpc824x/start.S b/cpu/mpc824x/start.S new file mode 100644 index 0000000..bd9706d --- /dev/null +++ b/cpu/mpc824x/start.S @@ -0,0 +1,835 @@ +/* + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000,2001,2002 Wolfgang Denk <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 + */ + +/* U-Boot - Startup Code for PowerPC based Embedded Boards + * + * + * The processor starts at 0x00000100 and the code is executed + * from flash. The code is organized to be at an other address + * in memory, but as long we don't jump around before relocating. + * board_init lies at a quite high address and when the cpu has + * jumped there, everything is ok. + * This works because the cpu gives the FLASH (CS0) the whole + * address space at startup, and board_init lies as a echo of + * the flash somewhere up there in the memorymap. + * + * board_init will change CS0 to be positioned at the correct + * address and (s)dram will be positioned at address 0 + */ +#include <config.h> +#include <mpc824x.h> +#include <version.h> + +#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */ + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#ifndef CONFIG_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + +/* We don't want the MMU yet. +*/ +#undef MSR_KERNEL +/* FP, Machine Check and Recoverable Interr. */ +#define MSR_KERNEL ( MSR_FP | MSR_ME | MSR_RI ) + +/* + * Set up GOT: Global Offset Table + * + * Use r14 to access the GOT + */ + START_GOT + GOT_ENTRY(_GOT2_TABLE_) + GOT_ENTRY(_FIXUP_TABLE_) + + GOT_ENTRY(_start) + GOT_ENTRY(_start_of_vectors) + GOT_ENTRY(_end_of_vectors) + GOT_ENTRY(transfer_to_handler) + + GOT_ENTRY(_end) + GOT_ENTRY(.bss) +#if defined(CONFIG_FADS) + GOT_ENTRY(environment) +#endif + END_GOT + +/* + * r3 - 1st arg to board_init(): IMMP pointer + * r4 - 2nd arg to board_init(): boot flag + */ + .text + .long 0x27051956 /* U-Boot Magic Number */ + .globl version_string +version_string: + .ascii U_BOOT_VERSION + .ascii " (", __DATE__, " - ", __TIME__, ")" + .ascii CONFIG_IDENT_STRING, "\0" + + . = EXC_OFF_SYS_RESET + .globl _start +_start: + li r21, BOOTFLAG_COLD /* Normal Power-On: Boot from FLASH */ + b boot_cold + + . = EXC_OFF_SYS_RESET + 0x10 + + .globl _start_warm +_start_warm: + li r21, BOOTFLAG_WARM /* Software reboot */ + b boot_warm + +boot_cold: +boot_warm: + + /* Initialize machine status; enable machine check interrupt */ + /*----------------------------------------------------------------------*/ + li r3, MSR_KERNEL /* Set FP, ME, RI flags */ + mtmsr r3 + mtspr SRR1, r3 /* Make SRR1 match MSR */ + + addis r0,0,0x0000 /* lets make sure that r0 is really 0 */ + mtspr HID0, r0 /* disable I and D caches */ + + mfspr r3, ICR /* clear Interrupt Cause Register */ + + mfmsr r3 /* turn off address translation */ + addis r4,0,0xffff + ori r4,r4,0xffcf + and r3,r3,r4 + mtmsr r3 + isync + sync /* the MMU should be off... */ + + +in_flash: +#if defined(CONFIG_BMW) + bl early_init_f /* Must be ASM: no stack yet! */ +#endif + /* + * Setup BATs - cannot be done in C since we don't have a stack yet + */ + bl setup_bats + + /* Enable MMU. + */ + mfmsr r3 + ori r3, r3, (MSR_IR | MSR_DR) + mtmsr r3 +#if !defined(CONFIG_BMW) + /* Enable and invalidate data cache. + */ + mfspr r3, HID0 + mr r2, r3 + ori r3, r3, HID0_DCE | HID0_DCI + ori r2, r2, HID0_DCE + sync + mtspr HID0, r3 + mtspr HID0, r2 + sync + + /* Allocate Initial RAM in data cache. + */ + lis r3, CFG_INIT_RAM_ADDR@h + ori r3, r3, CFG_INIT_RAM_ADDR@l + li r2, 128 + mtctr r2 +1: + dcbz r0, r3 + addi r3, r3, 32 + bdnz 1b + + /* Lock way0 in data cache. + */ + mfspr r3, 1011 + lis r2, 0xffff + ori r2, r2, 0xff1f + and r3, r3, r2 + ori r3, r3, 0x0080 + sync + mtspr 1011, r3 +#endif /* !CONFIG_BMW */ + /* + * Thisk the stack pointer *somewhere* sensible. Doesnt + * matter much where as we'll move it when we relocate + */ + lis r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@h + ori r1, r1, (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET)@l + + li r0, 0 /* Make room for stack frame header and */ + stwu r0, -4(r1) /* clear final stack frame so that */ + stwu r0, -4(r1) /* stack backtraces terminate cleanly */ + + /* let the C-code set up the rest */ + /* */ + /* Be careful to keep code relocatable ! */ + /*----------------------------------------------------------------------*/ + + GET_GOT /* initialize GOT access */ + + /* r3: IMMR */ + bl cpu_init_f /* run low-level CPU init code (from Flash) */ + + mr r3, r21 + /* r3: BOOTFLAG */ + bl board_init_f /* run 1st part of board init code (from Flash) */ + + + + .globl _start_of_vectors +_start_of_vectors: + +/* Machine check */ + STD_EXCEPTION(EXC_OFF_MACH_CHCK, MachineCheck, MachineCheckException) + +/* Data Storage exception. "Never" generated on the 860. */ + STD_EXCEPTION(EXC_OFF_DATA_STOR, DataStorage, UnknownException) + +/* Instruction Storage exception. "Never" generated on the 860. */ + STD_EXCEPTION(EXC_OFF_INS_STOR, InstStorage, UnknownException) + +/* External Interrupt exception. */ + STD_EXCEPTION(EXC_OFF_EXTERNAL, ExtInterrupt, external_interrupt) + +/* Alignment exception. */ + . = EXC_OFF_ALIGN +Alignment: + EXCEPTION_PROLOG + mfspr r4,DAR + stw r4,_DAR(r21) + mfspr r5,DSISR + stw r5,_DSISR(r21) + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_Alignment: + .long AlignmentException - _start + EXC_OFF_SYS_RESET + .long int_return - _start + EXC_OFF_SYS_RESET + +/* Program check exception */ + . = EXC_OFF_PROGRAM +ProgramCheck: + EXCEPTION_PROLOG + addi r3,r1,STACK_FRAME_OVERHEAD + li r20,MSR_KERNEL + rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */ + lwz r6,GOT(transfer_to_handler) + mtlr r6 + blrl +.L_ProgramCheck: + .long ProgramCheckException - _start + EXC_OFF_SYS_RESET + .long int_return - _start + EXC_OFF_SYS_RESET + + /* No FPU on MPC8xx. This exception is not supposed to happen. + */ + STD_EXCEPTION(EXC_OFF_FPUNAVAIL, FPUnavailable, UnknownException) + + /* I guess we could implement decrementer, and may have + * to someday for timekeeping. + */ + STD_EXCEPTION(EXC_OFF_DECR, Decrementer, timer_interrupt) + STD_EXCEPTION(0xa00, Trap_0a, UnknownException) + STD_EXCEPTION(0xb00, Trap_0b, UnknownException) + + . = 0xc00 +/* + * r0 - SYSCALL number + * r3-... arguments + */ +SystemCall: + addis r11,r0,0 /* get functions table addr */ + ori r11,r11,0 /* Note: this code is patched in trap_init */ + addis r12,r0,0 /* get number of functions */ + ori r12,r12,0 + + cmplw 0, r0, r12 + bge 1f + + rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */ + add r11,r11,r0 + lwz r11,0(r11) + + li r12,0xd00-4*3 /* save LR & SRRx */ + mflr r0 + stw r0,0(r12) + mfspr r0,SRR0 + stw r0,4(r12) + mfspr r0,SRR1 + stw r0,8(r12) + + li r12,0xc00+_back-SystemCall + mtlr r12 + mtspr SRR0,r11 + +1: SYNC + rfi + +_back: + + mfmsr r11 /* Disable interrupts */ + li r12,0 + ori r12,r12,MSR_EE + andc r11,r11,r12 + SYNC /* Some chip revs need this... */ + mtmsr r11 + SYNC + + li r12,0xd00-4*3 /* restore regs */ + lwz r11,0(r12) + mtlr r11 + lwz r11,4(r12) + mtspr SRR0,r11 + lwz r11,8(r12) + mtspr SRR1,r11 + + SYNC + rfi + + STD_EXCEPTION(EXC_OFF_TRACE, SingleStep, UnknownException) + + STD_EXCEPTION(EXC_OFF_FPUNASSIST, Trap_0e, UnknownException) + STD_EXCEPTION(EXC_OFF_PMI, Trap_0f, UnknownException) + + STD_EXCEPTION(EXC_OFF_ITME, InstructionTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_DLTME, DataLoadTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_DSTME, DataStoreTransMiss, UnknownException) + STD_EXCEPTION(EXC_OFF_IABE, InstructionBreakpoint, UnknownException) + STD_EXCEPTION(EXC_OFF_SMIE, SysManageInt, UnknownException) + STD_EXCEPTION(0x1500, Reserved5, UnknownException) + STD_EXCEPTION(0x1600, Reserved6, UnknownException) + STD_EXCEPTION(0x1700, Reserved7, UnknownException) + STD_EXCEPTION(0x1800, Reserved8, UnknownException) + STD_EXCEPTION(0x1900, Reserved9, UnknownException) + STD_EXCEPTION(0x1a00, ReservedA, UnknownException) + STD_EXCEPTION(0x1b00, ReservedB, UnknownException) + STD_EXCEPTION(0x1c00, ReservedC, UnknownException) + STD_EXCEPTION(0x1d00, ReservedD, UnknownException) + STD_EXCEPTION(0x1e00, ReservedE, UnknownException) + STD_EXCEPTION(0x1f00, ReservedF, UnknownException) + + STD_EXCEPTION(EXC_OFF_RMTE, RunModeTrace, UnknownException) + + .globl _end_of_vectors +_end_of_vectors: + + + . = 0x3000 + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ + .globl transfer_to_handler +transfer_to_handler: + stw r22,_NIP(r21) + lis r22,MSR_POW@h + andc r23,r23,r22 + stw r23,_MSR(r21) + SAVE_GPR(7, r21) + SAVE_4GPRS(8, r21) + SAVE_8GPRS(12, r21) + SAVE_8GPRS(24, r21) +#if 0 + andi. r23,r23,MSR_PR + mfspr r23,SPRG3 /* if from user, fix up tss.regs */ + beq 2f + addi r24,r1,STACK_FRAME_OVERHEAD + stw r24,PT_REGS(r23) +2: addi r2,r23,-TSS /* set r2 to current */ + tovirt(r2,r2,r23) +#endif + mflr r23 + andi. r24,r23,0x3f00 /* get vector offset */ + stw r24,TRAP(r21) + li r22,0 + stw r22,RESULT(r21) + mtspr SPRG2,r22 /* r1 is now kernel sp */ +#if 0 + addi r24,r2,TASK_STRUCT_SIZE /* check for kernel stack overflow */ + cmplw 0,r1,r2 + cmplw 1,r1,r24 + crand 1,1,4 + bgt stack_ovf /* if r2 < r1 < r2+TASK_STRUCT_SIZE */ +#endif + lwz r24,0(r23) /* virtual address of handler */ + lwz r23,4(r23) /* where to go when done */ + mtspr SRR0,r24 + ori r20,r20,0x30 /* enable IR, DR */ + mtspr SRR1,r20 + mtlr r23 + SYNC + rfi /* jump to handler, enable MMU */ + +int_return: + mfmsr r28 /* Disable interrupts */ + li r4,0 + ori r4,r4,MSR_EE + andc r28,r28,r4 + SYNC /* Some chip revs need this... */ + mtmsr r28 + SYNC + lwz r2,_CTR(r1) + lwz r0,_LINK(r1) + mtctr r2 + mtlr r0 + lwz r2,_XER(r1) + lwz r0,_CCR(r1) + mtspr XER,r2 + mtcrf 0xFF,r0 + REST_10GPRS(3, r1) + REST_10GPRS(13, r1) + REST_8GPRS(23, r1) + REST_GPR(31, r1) + lwz r2,_NIP(r1) /* Restore environment */ + lwz r0,_MSR(r1) + mtspr SRR0,r2 + mtspr SRR1,r0 + lwz r0,GPR0(r1) + lwz r2,GPR2(r1) + lwz r1,GPR1(r1) + SYNC + rfi + +/* Cache functions. +*/ + .globl icache_enable +icache_enable: + mfspr r5,HID0 /* turn on the I cache. */ + ori r5,r5,0x8800 /* Instruction cache only! */ + addis r6,0,0xFFFF + ori r6,r6,0xF7FF + and r6,r5,r6 /* clear the invalidate bit */ + sync + mtspr HID0,r5 + mtspr HID0,r6 + isync + sync + blr + + .globl icache_disable +icache_disable: + mfspr r5,HID0 + addis r6,0,0xFFFF + ori r6,r6,0x7FFF + and r5,r5,r6 + sync + mtspr HID0,r5 + isync + sync + blr + + .globl icache_status +icache_status: + mfspr r3, HID0 + srwi r3, r3, 15 /* >>15 & 1=> select bit 16 */ + andi. r3, r3, 1 + blr + + .globl dcache_enable +dcache_enable: + mfspr r5,HID0 /* turn on the D cache. */ + ori r5,r5,0x4400 /* Data cache only! */ + mfspr r4, PVR /* read PVR */ + srawi r3, r4, 16 /* shift off the least 16 bits */ + cmpi 0, 0, r3, 0xC /* Check for Max pvr */ + bne NotMax + ori r5,r5,0x0040 /* setting the DCFA bit, for Max rev 1 errata */ +NotMax: + addis r6,0,0xFFFF + ori r6,r6,0xFBFF + and r6,r5,r6 /* clear the invalidate bit */ + sync + mtspr HID0,r5 + mtspr HID0,r6 + isync + sync + blr + + .globl dcache_disable +dcache_disable: + mfspr r5,HID0 + addis r6,0,0xFFFF + ori r6,r6,0xBFFF + and r5,r5,r6 + sync + mtspr HID0,r5 + isync + sync + blr + + .globl dcache_status +dcache_status: + mfspr r3, HID0 + srwi r3, r3, 14 /* >>14 & 1=> select bit 17 */ + andi. r3, r3, 1 + blr + + .globl dc_read +dc_read: +/*TODO : who uses this, what should it do? +*/ + blr + + + .globl get_pvr +get_pvr: + mfspr r3, PVR + blr + + +/*------------------------------------------------------------------------------*/ + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ + .globl relocate_code +relocate_code: + + mr r1, r3 /* Set new stack pointer */ + mr r9, r4 /* Save copy of Global Data pointer */ + mr r10, r5 /* Save copy of Destination Address */ + + mr r3, r5 /* Destination Address */ +#ifdef DEBUG + lis r4, CFG_SDRAM_BASE@h /* Source Address */ + ori r4, r4, CFG_SDRAM_BASE@l +#else + lis r4, CFG_MONITOR_BASE@h /* Source Address */ + ori r4, r4, CFG_MONITOR_BASE@l +#endif + lis r5, CFG_MONITOR_LEN@h /* Length in Bytes */ + ori r5, r5, CFG_MONITOR_LEN@l + li r6, CFG_CACHELINE_SIZE /* Cache Line Size */ + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address + * + * Offset: + */ + sub r15, r10, r4 + + /* First our own GOT */ + add r14, r14, r15 + /* the the one used by the C code */ + add r30, r30, r15 + + /* + * Now relocate code + */ + + cmplw cr1,r3,r4 + addi r0,r5,3 + srwi. r0,r0,2 + beq cr1,4f /* In place copy is not necessary */ + beq 7f /* Protect against 0 count */ + mtctr r0 + bge cr1,2f + + la r8,-4(r4) + la r7,-4(r3) +1: lwzu r0,4(r8) + stwu r0,4(r7) + bdnz 1b + b 4f + +2: slwi r0,r0,2 + add r8,r4,r0 + add r7,r3,r0 +3: lwzu r0,-4(r8) + stwu r0,-4(r7) + bdnz 3b + +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4: cmpwi r6,0 + add r5,r3,r5 + beq 7f /* Always flush prefetch queue in any case */ + subi r0,r6,1 + andc r3,r3,r0 + mr r4,r3 +5: dcbst 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 5b + sync /* Wait for all dcbst to complete on bus */ + mr r4,r3 +6: icbi 0,r4 + add r4,r4,r6 + cmplw r4,r5 + blt 6b +7: sync /* Wait for all icbi to complete on bus */ + isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ + + addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET + mtlr r0 + blr + +in_ram: + + /* + * Relocation Function, r14 point to got2+0x8000 + * + * Adjust got2 pointers, no need to check for 0, this code + * already puts a few entries in the table. + */ + li r0,__got2_entries@sectoff@l + la r3,GOT(_GOT2_TABLE_) + lwz r11,GOT(_GOT2_TABLE_) + mtctr r0 + sub r11,r3,r11 + addi r3,r3,-4 +1: lwzu r0,4(r3) + add r0,r0,r11 + stw r0,0(r3) + bdnz 1b + + /* + * Now adjust the fixups and the pointers to the fixups + * in case we need to move ourselves again. + */ +2: li r0,__fixup_entries@sectoff@l + lwz r3,GOT(_FIXUP_TABLE_) + cmpwi r0,0 + mtctr r0 + addi r3,r3,-4 + beq 4f +3: lwzu r4,4(r3) + lwzux r0,r4,r11 + add r0,r0,r11 + stw r10,0(r3) + stw r0,0(r4) + bdnz 3b +4: +clear_bss: + /* + * Now clear BSS segment + */ + lwz r3,GOT(.bss) + lwz r4,GOT(_end) + + cmplw 0, r3, r4 + beq 6f + + li r0, 0 +5: + stw r0, 0(r3) + addi r3, r3, 4 + cmplw 0, r3, r4 + blt 5b +6: + + mr r3, r9 /* Global Data pointer */ + mr r4, r10 /* Destination Address */ + bl board_init_r + + /* Problems accessing "end" in C, so do it here */ + .globl get_endaddr +get_endaddr: + lwz r3,GOT(_end) + blr + + /* + * Copy exception vector code to low memory + * + * r3: dest_addr + * r7: source address, r8: end address, r9: target address + */ + .globl trap_init +trap_init: + lwz r7, GOT(_start) + lwz r8, GOT(_end_of_vectors) + + rlwinm r9, r7, 0, 18, 31 /* _start & 0x3FFF */ + + cmplw 0, r7, r8 + bgelr /* return if r7>=r8 - just in case */ + + mflr r4 /* save link register */ +1: + lwz r0, 0(r7) + stw r0, 0(r9) + addi r7, r7, 4 + addi r9, r9, 4 + cmplw 0, r7, r8 + bne 1b + + /* + * relocate `hdlr' and `int_return' entries + */ + li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET + li r8, Alignment - _start + EXC_OFF_SYS_RESET +2: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 2b + + li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET + bl trap_reloc + + li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET + bl trap_reloc + + li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET + li r8, SystemCall - _start + EXC_OFF_SYS_RESET +3: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 3b + + li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET + li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET +4: + bl trap_reloc + addi r7, r7, 0x100 /* next exception vector */ + cmplw 0, r7, r8 + blt 4b + + mtlr r4 /* restore link register */ + blr + + /* + * Function: relocate entries for one exception vector + */ +trap_reloc: + lwz r0, 0(r7) /* hdlr ... */ + add r0, r0, r3 /* ... += dest_addr */ + stw r0, 0(r7) + + lwz r0, 4(r7) /* int_return ... */ + add r0, r0, r3 /* ... += dest_addr */ + stw r0, 4(r7) + + blr + + /* Setup the BAT registers. + */ +setup_bats: + lis r4, CFG_IBAT0L@h + ori r4, r4, CFG_IBAT0L@l + lis r3, CFG_IBAT0U@h + ori r3, r3, CFG_IBAT0U@l + mtspr IBAT0L, r4 + mtspr IBAT0U, r3 + isync + + lis r4, CFG_DBAT0L@h + ori r4, r4, CFG_DBAT0L@l + lis r3, CFG_DBAT0U@h + ori r3, r3, CFG_DBAT0U@l + mtspr DBAT0L, r4 + mtspr DBAT0U, r3 + isync + + lis r4, CFG_IBAT1L@h + ori r4, r4, CFG_IBAT1L@l + lis r3, CFG_IBAT1U@h + ori r3, r3, CFG_IBAT1U@l + mtspr IBAT1L, r4 + mtspr IBAT1U, r3 + isync + + lis r4, CFG_DBAT1L@h + ori r4, r4, CFG_DBAT1L@l + lis r3, CFG_DBAT1U@h + ori r3, r3, CFG_DBAT1U@l + mtspr DBAT1L, r4 + mtspr DBAT1U, r3 + isync + + lis r4, CFG_IBAT2L@h + ori r4, r4, CFG_IBAT2L@l + lis r3, CFG_IBAT2U@h + ori r3, r3, CFG_IBAT2U@l + mtspr IBAT2L, r4 + mtspr IBAT2U, r3 + isync + + lis r4, CFG_DBAT2L@h + ori r4, r4, CFG_DBAT2L@l + lis r3, CFG_DBAT2U@h + ori r3, r3, CFG_DBAT2U@l + mtspr DBAT2L, r4 + mtspr DBAT2U, r3 + isync + + lis r4, CFG_IBAT3L@h + ori r4, r4, CFG_IBAT3L@l + lis r3, CFG_IBAT3U@h + ori r3, r3, CFG_IBAT3U@l + mtspr IBAT3L, r4 + mtspr IBAT3U, r3 + isync + + lis r4, CFG_DBAT3L@h + ori r4, r4, CFG_DBAT3L@l + lis r3, CFG_DBAT3U@h + ori r3, r3, CFG_DBAT3U@l + mtspr DBAT3L, r4 + mtspr DBAT3U, r3 + isync + + /* Invalidate TLBs. + * -> for (val = 0; val < 0x20000; val+=0x1000) + * -> tlbie(val); + */ + lis r3, 0 + lis r5, 2 + +1: + tlbie r3 + addi r3, r3, 0x1000 + cmp 0, 0, r3, r5 + blt 1b + + blr + + diff --git a/cpu/mpc8260/cpu_init.c b/cpu/mpc8260/cpu_init.c new file mode 100644 index 0000000..9f9369a --- /dev/null +++ b/cpu/mpc8260/cpu_init.c @@ -0,0 +1,264 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc8260.h> +#include <asm/cpm_8260.h> +#include <ioports.h> + +static void config_8260_ioports (volatile immap_t * immr) +{ + int portnum; + + for (portnum = 0; portnum < 4; portnum++) { + uint pmsk = 0, + ppar = 0, + psor = 0, + pdir = 0, + podr = 0, + pdat = 0; + iop_conf_t *iopc = (iop_conf_t *) & iop_conf_tab[portnum][0]; + iop_conf_t *eiopc = iopc + 32; + uint msk = 1; + + /* + * NOTE: + * index 0 refers to pin 31, + * index 31 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; + } + + msk <<= 1; + iopc++; + } + + if (pmsk != 0) { + volatile ioport_t *iop = ioport_addr (immr, portnum); + uint tpmsk = ~pmsk; + + /* + * the (somewhat confused) paragraph at the + * bottom of page 35-5 warns that there might + * be "unknown behaviour" when programming + * PSORx and PDIRx, if PPARx = 1, so I + * decided this meant I had to disable the + * dedicated function first, and enable it + * last. + */ + iop->ppar &= tpmsk; + iop->psor = (iop->psor & tpmsk) | psor; + iop->pdat = (iop->pdat & tpmsk) | pdat; + iop->pdir = (iop->pdir & tpmsk) | pdir; + iop->podr = (iop->podr & tpmsk) | podr; + iop->ppar |= ppar; + } + } +} + +/* + * Breath some life into the CPU... + * + * Set up the memory map, + * initialize a bunch of registers, + * initialize the UPM's + */ +void cpu_init_f (volatile immap_t * immr) +{ + DECLARE_GLOBAL_DATA_PTR; + + volatile memctl8260_t *memctl = &immr->im_memctl; + extern void m8260_cpm_reset (void); + + /* Pointer is writable since we allocated a register for it */ + gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET); + + /* Clear initial global data */ + memset ((void *) gd, 0, sizeof (gd_t)); + + /* RSR - Reset Status Register - clear all status (5-4) */ + gd->reset_status = immr->im_clkrst.car_rsr; + immr->im_clkrst.car_rsr = RSR_ALLBITS; + + /* RMR - Reset Mode Register - contains checkstop reset enable (5-5) */ + immr->im_clkrst.car_rmr = CFG_RMR; + + /* BCR - Bus Configuration Register (4-25) */ + immr->im_siu_conf.sc_bcr = CFG_BCR; + + /* SIUMCR - contains debug pin configuration (4-31) */ + immr->im_siu_conf.sc_siumcr = CFG_SIUMCR; + + config_8260_ioports (immr); + + /* initialize time counter status and control register (4-40) */ + immr->im_sit.sit_tmcntsc = CFG_TMCNTSC; + + /* initialize the PIT (4-42) */ + immr->im_sit.sit_piscr = CFG_PISCR; + +#if !defined(CONFIG_COGENT) /* done in start.S for the cogent */ + /* System clock control register (9-8) */ + immr->im_clkrst.car_sccr = CFG_SCCR; +#endif /* !CONFIG_COGENT */ + + /* + * Memory Controller: + */ + + /* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary + * addresses - these have to be modified later when FLASH size + * has been determined + */ + +#if defined(CFG_OR0_REMAP) + memctl->memc_or0 = CFG_OR0_REMAP; +#endif +#if defined(CFG_OR1_REMAP) + memctl->memc_or1 = CFG_OR1_REMAP; +#endif + + /* now restrict to preliminary range */ + memctl->memc_br0 = CFG_BR0_PRELIM; + memctl->memc_or0 = CFG_OR0_PRELIM; + +#if defined(CFG_BR1_PRELIM) && defined(CFG_OR1_PRELIM) + memctl->memc_or1 = CFG_OR1_PRELIM; + memctl->memc_br1 = CFG_BR1_PRELIM; +#endif + +#if defined(CFG_BR2_PRELIM) && defined(CFG_OR2_PRELIM) + memctl->memc_or2 = CFG_OR2_PRELIM; + memctl->memc_br2 = CFG_BR2_PRELIM; +#endif + +#if defined(CFG_BR3_PRELIM) && defined(CFG_OR3_PRELIM) + memctl->memc_or3 = CFG_OR3_PRELIM; + memctl->memc_br3 = CFG_BR3_PRELIM; +#endif + +#if defined(CFG_BR4_PRELIM) && defined(CFG_OR4_PRELIM) + memctl->memc_or4 = CFG_OR4_PRELIM; + memctl->memc_br4 = CFG_BR4_PRELIM; +#endif + +#if defined(CFG_BR5_PRELIM) && defined(CFG_OR5_PRELIM) + memctl->memc_or5 = CFG_OR5_PRELIM; + memctl->memc_br5 = CFG_BR5_PRELIM; +#endif + +#if defined(CFG_BR6_PRELIM) && defined(CFG_OR6_PRELIM) + memctl->memc_or6 = CFG_OR6_PRELIM; + memctl->memc_br6 = CFG_BR6_PRELIM; +#endif + +#if defined(CFG_BR7_PRELIM) && defined(CFG_OR7_PRELIM) + memctl->memc_or7 = CFG_OR7_PRELIM; + memctl->memc_br7 = CFG_BR7_PRELIM; +#endif + +#if defined(CFG_BR8_PRELIM) && defined(CFG_OR8_PRELIM) + memctl->memc_or8 = CFG_OR8_PRELIM; + memctl->memc_br8 = CFG_BR8_PRELIM; +#endif + +#if defined(CFG_BR9_PRELIM) && defined(CFG_OR9_PRELIM) + memctl->memc_or9 = CFG_OR9_PRELIM; + memctl->memc_br9 = CFG_BR9_PRELIM; +#endif + +#if defined(CFG_BR10_PRELIM) && defined(CFG_OR10_PRELIM) + memctl->memc_or10 = CFG_OR10_PRELIM; + memctl->memc_br10 = CFG_BR10_PRELIM; +#endif + +#if defined(CFG_BR11_PRELIM) && defined(CFG_OR11_PRELIM) + memctl->memc_or11 = CFG_OR11_PRELIM; + memctl->memc_br11 = CFG_BR11_PRELIM; +#endif + + m8260_cpm_reset (); +} + +/* + * initialize higher level parts of CPU like time base and timers + */ +int cpu_init_r (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + volatile immap_t *immr = (immap_t *) gd->bd->bi_immr_base; + + immr->im_cpm.cp_rccr = CFG_RCCR; + + return (0); +} + +/* + * print out the reason for the reset + */ +int prt_8260_rsr (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + static struct { + ulong mask; + char *desc; + } bits[] = { + { + RSR_JTRS, "JTAG"}, { + RSR_CSRS, "Check Stop"}, { + RSR_SWRS, "Software Watchdog"}, { + RSR_BMRS, "Bus Monitor"}, { + RSR_ESRS, "External Soft"}, { + RSR_EHRS, "External Hard"} + }; + static int n = sizeof bits / sizeof bits[0]; + ulong rsr = gd->reset_status; + int i; + char *sep; + + puts ("MPC8260 Reset Status:"); + + sep = " "; + for (i = 0; i < n; i++) + if (rsr & bits[i].mask) { + printf ("%s%s", sep, bits[i].desc); + sep = ", "; + } + + puts ("\n\n"); + return (0); +} diff --git a/cpu/mpc8260/i2c.c b/cpu/mpc8260/i2c.c new file mode 100644 index 0000000..8bfa2e8 --- /dev/null +++ b/cpu/mpc8260/i2c.c @@ -0,0 +1,733 @@ +/* + * (C) Copyright 2000 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if defined(CONFIG_HARD_I2C) + +#include <asm/cpm_8260.h> +#include <i2c.h> + +/* define to enable debug messages */ +#undef DEBUG_I2C + +/* uSec to wait between polls of the i2c */ +#define DELAY_US 100 +/* uSec to wait for the CPM to start processing the buffer */ +#define START_DELAY_US 1000 + +/* + * tx/rx per-byte timeout: we delay DELAY_US uSec between polls so the + * timeout will be (tx_length + rx_length) * DELAY_US * TOUT_LOOP + */ +#define TOUT_LOOP 5 + +/*----------------------------------------------------------------------- + * Set default values + */ +#ifndef CFG_I2C_SPEED +#define CFG_I2C_SPEED 50000 +#endif + +#ifndef CFG_I2C_SLAVE +#define CFG_I2C_SLAVE 0xFE +#endif +/*----------------------------------------------------------------------- + */ + +typedef void (*i2c_ecb_t)(int, int); /* error callback function */ + +/* This structure keeps track of the bd and buffer space usage. */ +typedef struct i2c_state { + int rx_idx; /* index to next free Rx BD */ + int tx_idx; /* index to next free Tx BD */ + void *rxbd; /* pointer to next free Rx BD */ + void *txbd; /* pointer to next free Tx BD */ + int tx_space; /* number of Tx bytes left */ + unsigned char *tx_buf; /* pointer to free Tx area */ + i2c_ecb_t err_cb; /* error callback function */ +} i2c_state_t; + +/* flags for i2c_send() and i2c_receive() */ +#define I2CF_ENABLE_SECONDARY 0x01 /* secondary_address is valid */ +#define I2CF_START_COND 0x02 /* tx: generate start condition */ +#define I2CF_STOP_COND 0x04 /* tx: generate stop condition */ + +/* return codes */ +#define I2CERR_NO_BUFFERS 0x01 /* no more BDs or buffer space */ +#define I2CERR_MSG_TOO_LONG 0x02 /* tried to send/receive to much data */ +#define I2CERR_TIMEOUT 0x03 /* timeout in i2c_doio() */ +#define I2CERR_QUEUE_EMPTY 0x04 /* i2c_doio called without send/receive */ + +/* error callback flags */ +#define I2CECB_RX_ERR 0x10 /* this is a receive error */ +#define I2CECB_RX_ERR_OV 0x02 /* receive overrun error */ +#define I2CECB_RX_MASK 0x0f /* mask for error bits */ +#define I2CECB_TX_ERR 0x20 /* this is a transmit error */ +#define I2CECB_TX_CL 0x01 /* transmit collision error */ +#define I2CECB_TX_UN 0x02 /* transmit underflow error */ +#define I2CECB_TX_NAK 0x04 /* transmit no ack error */ +#define I2CECB_TX_MASK 0x0f /* mask for error bits */ +#define I2CECB_TIMEOUT 0x40 /* this is a timeout error */ + +#define ERROR_I2C_NONE 0 +#define ERROR_I2C_LENGTH 1 + +#define I2C_WRITE_BIT 0x00 +#define I2C_READ_BIT 0x01 + +#define I2C_RXTX_LEN 128 /* maximum tx/rx buffer length */ + + +#define NUM_RX_BDS 4 +#define NUM_TX_BDS 4 +#define MAX_TX_SPACE 256 + +typedef struct I2C_BD +{ + unsigned short status; + unsigned short length; + unsigned char *addr; +} I2C_BD; +#define BD_I2C_TX_START 0x0400 /* special status for i2c: Start condition */ + +#define BD_I2C_TX_CL 0x0001 /* collision error */ +#define BD_I2C_TX_UN 0x0002 /* underflow error */ +#define BD_I2C_TX_NAK 0x0004 /* no acknowledge error */ +#define BD_I2C_TX_ERR (BD_I2C_TX_NAK|BD_I2C_TX_UN|BD_I2C_TX_CL) + +#define BD_I2C_RX_ERR BD_SC_OV + +#ifdef DEBUG_I2C +#define PRINTD(x) printf x +#else +#define PRINTD(x) +#endif + +/* + * Returns the best value of I2BRG to meet desired clock speed of I2C with + * input parameters (clock speed, filter, and predivider value). + * It returns computer speed value and the difference between it and desired + * speed. + */ +static inline int +i2c_roundrate(int hz, int speed, int filter, int modval, + int *brgval, int *totspeed) +{ + int moddiv = 1 << (5-(modval & 3)), brgdiv, div; + + PRINTD(("\t[I2C] trying hz=%d, speed=%d, filter=%d, modval=%d\n", + hz, speed, filter, modval)); + + div = moddiv * speed; + brgdiv = (hz + div - 1) / div; + + PRINTD(("\t\tmoddiv=%d, brgdiv=%d\n", moddiv, brgdiv)); + + *brgval = (brgdiv / 2) - 3 - (2*filter); + + if ((*brgval < 0) || (*brgval > 255)) { + PRINTD(("\t\trejected brgval=%d\n", *brgval)); + return -1; + } + + brgdiv = 2 * (*brgval + 3 + (2 * filter)); + div = moddiv * brgdiv ; + *totspeed = (hz + div - 1) / div; + + PRINTD(("\t\taccepted brgval=%d, totspeed=%d\n", *brgval, *totspeed)); + + return 0; +} + +/* + * Sets the I2C clock predivider and divider to meet required clock speed. + */ +static int i2c_setrate(int hz, int speed) +{ + immap_t *immap = (immap_t *)CFG_IMMR ; + volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c; + int brgval, + modval, /* 0-3 */ + bestspeed_diff = speed, + bestspeed_brgval=0, + bestspeed_modval=0, + bestspeed_filter=0, + totspeed, + filter = 0; /* Use this fixed value */ + + for (modval = 0; modval < 4; modval++) + { + if (i2c_roundrate (hz, speed, filter, modval, &brgval, &totspeed) == 0) + { + int diff = speed - totspeed ; + + if ((diff >= 0) && (diff < bestspeed_diff)) + { + bestspeed_diff = diff ; + bestspeed_modval = modval; + bestspeed_brgval = brgval; + bestspeed_filter = filter; + } + } + } + + PRINTD(("[I2C] Best is:\n")); + PRINTD(("[I2C] CPU=%dhz RATE=%d F=%d I2MOD=%08x I2BRG=%08x DIFF=%dhz\n", + hz, speed, + bestspeed_filter, bestspeed_modval, bestspeed_brgval, + bestspeed_diff)); + + i2c->i2c_i2mod |= ((bestspeed_modval & 3) << 1) | (bestspeed_filter << 3); + i2c->i2c_i2brg = bestspeed_brgval & 0xff; + + PRINTD(("[I2C] i2mod=%08x i2brg=%08x\n", i2c->i2c_i2mod, i2c->i2c_i2brg)); + + return 1 ; +} + +void i2c_init(int speed, int slaveadd) +{ + DECLARE_GLOBAL_DATA_PTR; + + volatile immap_t *immap = (immap_t *)CFG_IMMR ; + volatile cpm8260_t *cp = (cpm8260_t *)&immap->im_cpm; + volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c; + volatile iic_t *iip; + ulong rbase, tbase; + volatile I2C_BD *rxbd, *txbd; + uint dpaddr; + + dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])); + if (dpaddr == 0) { + /* need to allocate dual port ram */ + dpaddr = m8260_cpm_dpalloc(64 + + (NUM_RX_BDS * sizeof(I2C_BD)) + (NUM_TX_BDS * sizeof(I2C_BD)) + + MAX_TX_SPACE, 64); + *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])) = dpaddr; + } + + /* + * initialise data in dual port ram: + * + * dpaddr -> parameter ram (64 bytes) + * rbase -> rx BD (NUM_RX_BDS * sizeof(I2C_BD) bytes) + * tbase -> tx BD (NUM_TX_BDS * sizeof(I2C_BD) bytes) + * tx buffer (MAX_TX_SPACE bytes) + */ + + iip = (iic_t *)&immap->im_dprambase[dpaddr]; + memset((void*)iip, 0, sizeof(iic_t)); + + rbase = dpaddr + 64; + tbase = rbase + NUM_RX_BDS * sizeof(I2C_BD); + + /* Disable interrupts */ + i2c->i2c_i2mod = 0x00; + i2c->i2c_i2cmr = 0x00; + i2c->i2c_i2cer = 0xff; + i2c->i2c_i2add = slaveadd; + + /* + * Set the I2C BRG Clock division factor from desired i2c rate + * and current CPU rate (we assume sccr dfbgr field is 0; + * divide BRGCLK by 1) + */ + PRINTD(("[I2C] Setting rate...\n")); + i2c_setrate (gd->brg_clk, CFG_I2C_SPEED) ; + + /* Set I2C controller in master mode */ + i2c->i2c_i2com = 0x01; + + /* Initialize Tx/Rx parameters */ + iip->iic_rbase = rbase; + iip->iic_tbase = tbase; + rxbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_rbase]); + txbd = (I2C_BD *)((unsigned char *)&immap->im_dprambase[iip->iic_tbase]); + + PRINTD(("[I2C] rbase = %04x\n", iip->iic_rbase)); + PRINTD(("[I2C] tbase = %04x\n", iip->iic_tbase)); + PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd)); + PRINTD(("[I2C] txbd = %08x\n", (int)txbd)); + + /* Set big endian byte order */ + iip->iic_tfcr = 0x10; + iip->iic_rfcr = 0x10; + + /* Set maximum receive size. */ + iip->iic_mrblr = I2C_RXTX_LEN; + + cp->cp_cpcr = mk_cr_cmd(CPM_CR_I2C_PAGE, + CPM_CR_I2C_SBLOCK, + 0x00, + CPM_CR_INIT_TRX) | CPM_CR_FLG; + do { + __asm__ __volatile__ ("eieio"); + } while (cp->cp_cpcr & CPM_CR_FLG); + + /* Clear events and interrupts */ + i2c->i2c_i2cer = 0xff; + i2c->i2c_i2cmr = 0x00; +} + +static +void i2c_newio(i2c_state_t *state) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR ; + volatile iic_t *iip; + uint dpaddr; + + PRINTD(("[I2C] i2c_newio\n")); + + dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])); + iip = (iic_t *)&immap->im_dprambase[dpaddr]; + state->rx_idx = 0; + state->tx_idx = 0; + state->rxbd = (void*)&immap->im_dprambase[iip->iic_rbase]; + state->txbd = (void*)&immap->im_dprambase[iip->iic_tbase]; + state->tx_space = MAX_TX_SPACE; + state->tx_buf = (uchar*)state->txbd + NUM_TX_BDS * sizeof(I2C_BD); + state->err_cb = NULL; + + PRINTD(("[I2C] rxbd = %08x\n", (int)state->rxbd)); + PRINTD(("[I2C] txbd = %08x\n", (int)state->txbd)); + PRINTD(("[I2C] tx_buf = %08x\n", (int)state->tx_buf)); + + /* clear the buffer memory */ + memset((char *)state->tx_buf, 0, MAX_TX_SPACE); +} + +static +int i2c_send(i2c_state_t *state, + unsigned char address, + unsigned char secondary_address, + unsigned int flags, + unsigned short size, + unsigned char *dataout) +{ + volatile I2C_BD *txbd; + int i,j; + + PRINTD(("[I2C] i2c_send add=%02d sec=%02d flag=%02d size=%d\n", + address, secondary_address, flags, size)); + + /* trying to send message larger than BD */ + if (size > I2C_RXTX_LEN) + return I2CERR_MSG_TOO_LONG; + + /* no more free bds */ + if (state->tx_idx >= NUM_TX_BDS || state->tx_space < (2 + size)) + return I2CERR_NO_BUFFERS; + + txbd = (I2C_BD *)state->txbd; + txbd->addr = state->tx_buf; + + PRINTD(("[I2C] txbd = %08x\n", (int)txbd)); + + if (flags & I2CF_START_COND) + { + PRINTD(("[I2C] Formatting addresses...\n")); + if (flags & I2CF_ENABLE_SECONDARY) + { + txbd->length = size + 2; /* Length of message plus dest addresses */ + txbd->addr[0] = address << 1; + txbd->addr[1] = secondary_address; + i = 2; + } + else + { + txbd->length = size + 1; /* Length of message plus dest address */ + txbd->addr[0] = address << 1; /* Write destination address to BD */ + i = 1; + } + } + else + { + txbd->length = size; /* Length of message */ + i = 0; + } + + /* set up txbd */ + txbd->status = BD_SC_READY; + if (flags & I2CF_START_COND) + txbd->status |= BD_I2C_TX_START; + if (flags & I2CF_STOP_COND) + txbd->status |= BD_SC_LAST | BD_SC_WRAP; + + /* Copy data to send into buffer */ + PRINTD(("[I2C] copy data...\n")); + for(j = 0; j < size; i++, j++) + txbd->addr[i] = dataout[j]; + + PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n", + txbd->length, + txbd->status, + txbd->addr[0], + txbd->addr[1])); + + /* advance state */ + state->tx_buf += txbd->length; + state->tx_space -= txbd->length; + state->tx_idx++; + state->txbd = (void*)(txbd + 1); + + return 0; +} + +static +int i2c_receive(i2c_state_t *state, + unsigned char address, + unsigned char secondary_address, + unsigned int flags, + unsigned short size_to_expect, + unsigned char *datain) +{ + volatile I2C_BD *rxbd, *txbd; + + PRINTD(("[I2C] i2c_receive %02d %02d %02d\n", address, secondary_address, flags)); + + /* Expected to receive too much */ + if (size_to_expect > I2C_RXTX_LEN) + return I2CERR_MSG_TOO_LONG; + + /* no more free bds */ + if (state->tx_idx >= NUM_TX_BDS || state->rx_idx >= NUM_RX_BDS + || state->tx_space < 2) + return I2CERR_NO_BUFFERS; + + rxbd = (I2C_BD *)state->rxbd; + txbd = (I2C_BD *)state->txbd; + + PRINTD(("[I2C] rxbd = %08x\n", (int)rxbd)); + PRINTD(("[I2C] txbd = %08x\n", (int)txbd)); + + txbd->addr = state->tx_buf; + + /* set up TXBD for destination address */ + if (flags & I2CF_ENABLE_SECONDARY) + { + txbd->length = 2; + txbd->addr[0] = address << 1; /* Write data */ + txbd->addr[1] = secondary_address; /* Internal address */ + txbd->status = BD_SC_READY; + } + else + { + txbd->length = 1 + size_to_expect; + txbd->addr[0] = (address << 1) | 0x01; + txbd->status = BD_SC_READY; + memset(&txbd->addr[1], 0, txbd->length); + } + + /* set up rxbd for reception */ + rxbd->status = BD_SC_EMPTY; + rxbd->length = size_to_expect; + rxbd->addr = datain; + + txbd->status |= BD_I2C_TX_START; + if (flags & I2CF_STOP_COND) + { + txbd->status |= BD_SC_LAST | BD_SC_WRAP; + rxbd->status |= BD_SC_WRAP; + } + + PRINTD(("[I2C] txbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n", + txbd->length, + txbd->status, + txbd->addr[0], + txbd->addr[1])); + PRINTD(("[I2C] rxbd: length=0x%04x status=0x%04x addr[0]=0x%02x addr[1]=0x%02x\n", + rxbd->length, + rxbd->status, + rxbd->addr[0], + rxbd->addr[1])); + + /* advance state */ + state->tx_buf += txbd->length; + state->tx_space -= txbd->length; + state->tx_idx++; + state->txbd = (void*)(txbd + 1); + state->rx_idx++; + state->rxbd = (void*)(rxbd + 1); + + return 0; +} + + +static +int i2c_doio(i2c_state_t *state) +{ + volatile immap_t *immap = (immap_t *)CFG_IMMR ; + volatile iic_t *iip; + volatile i2c8260_t *i2c = (i2c8260_t *)&immap->im_i2c; + volatile I2C_BD *txbd, *rxbd; + int j; + int timeout; + uint dpaddr; + + PRINTD(("[I2C] i2c_doio\n")); + + timeout = TOUT_LOOP * 256; /* arbitrarily long */ + + if (state->tx_idx <= 0 && state->rx_idx <= 0) { + PRINTD(("[I2C] No I/O is queued\n")); + return I2CERR_QUEUE_EMPTY; + } + + dpaddr = *((unsigned short*)(&immap->im_dprambase[PROFF_I2C_BASE])); + iip = (iic_t *)&immap->im_dprambase[dpaddr]; + iip->iic_rbptr = iip->iic_rbase; + iip->iic_tbptr = iip->iic_tbase; + + /* Enable I2C */ + PRINTD(("[I2C] Enabling I2C...\n")); + i2c->i2c_i2mod |= 0x01; + + /* Begin transmission */ + i2c->i2c_i2com |= 0x80; + + /* Loop until transmit & receive completed */ + + txbd = ((I2C_BD*)state->txbd) - 1; + j = 0; + if (state->tx_idx > 0) { + timeout = TOUT_LOOP * txbd->length; + + PRINTD(("[I2C] Transmitting...(txbd=0x%08lx)\n", (ulong)txbd)); + udelay(START_DELAY_US); /* give it time to start */ + while((txbd->status & BD_SC_READY) && (j++ < timeout)) { + udelay(DELAY_US); + if (ctrlc()) + return (-1); + __asm__ __volatile__ ("eieio"); + } + } + + rxbd = ((I2C_BD*)state->rxbd) - 1; + j = 0; + if ((state->rx_idx > 0) && (j < timeout)) { + timeout = TOUT_LOOP * rxbd->length; + PRINTD(("[I2C] Receiving...(rxbd=0x%08lx)\n", (ulong)rxbd)); + udelay(START_DELAY_US); /* give it time to start */ + while((rxbd->status & BD_SC_EMPTY) && (j++ < timeout)) { + udelay(DELAY_US); + if (ctrlc()) + return (-1); + __asm__ __volatile__ ("eieio"); + } + } + + /* Turn off I2C */ + i2c->i2c_i2mod &= ~0x01; + + if (state->err_cb != NULL) { + int n, i, b; + + /* + * if we have an error callback function, look at the + * error bits in the bd status and pass them back + */ + + if ((n = state->tx_idx) > 0) { + for (i = 0; i < n; i++) { + txbd = ((I2C_BD*)state->txbd) - (n - i); + if ((b = txbd->status & BD_I2C_TX_ERR) != 0) + (*state->err_cb)(I2CECB_TX_ERR|b, i); + } + } + + if ((n = state->rx_idx) > 0) { + for (i = 0; i < n; i++) { + rxbd = ((I2C_BD*)state->rxbd) - (n - i); + if ((b = rxbd->status & BD_I2C_RX_ERR) != 0) + (*state->err_cb)(I2CECB_RX_ERR|b, i); + } + } + + if (j >= timeout) + (*state->err_cb)(I2CECB_TIMEOUT, 0); + } + + /* sort out errors and return appropriate good/error status */ + if(j >= timeout) + return(I2CERR_TIMEOUT); + if((txbd->status & BD_I2C_TX_ERR) != 0) + return(I2CECB_TX_ERR | (txbd->status & I2CECB_TX_MASK)); + if((rxbd->status & BD_I2C_RX_ERR) != 0) + return(I2CECB_RX_ERR | (rxbd->status & I2CECB_RX_MASK)); + + return(0); +} + +static int had_tx_nak; + +static void +i2c_test_callback(int flags, int xnum) +{ + if ((flags & I2CECB_TX_ERR) && (flags & I2CECB_TX_NAK)) + had_tx_nak = 1; +} + +int i2c_probe(uchar chip) +{ + i2c_state_t state; + int rc; + uchar buf[1]; + + i2c_newio(&state); + + state.err_cb = i2c_test_callback; + had_tx_nak = 0; + + rc = i2c_receive(&state, chip, 0, I2CF_START_COND|I2CF_STOP_COND, 1, buf); + + if (rc != 0) + return (rc); + + rc = i2c_doio(&state); + + if ((rc != 0) && (rc != I2CERR_TIMEOUT)) + return (rc); + + return (had_tx_nak); +} + + +int +i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + i2c_state_t state; + uchar xaddr[4]; + int rc; + + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address + * and the extra bits end up in the "chip address" bit slots. + * This makes a 24WC08 (1Kbyte) chip look like four 256 byte + * chips. + * + * Note that we consider the length of the address field to still + * be one byte because the extra address bits are hidden in the + * chip address. + */ + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + + i2c_newio(&state); + + rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]); + if (rc != 0) { + printf("i2c_read: i2c_send failed (%d)\n", rc); + return 1; + } + + rc = i2c_receive(&state, chip, 0, I2CF_STOP_COND, len, buffer); + if (rc != 0) { + printf("i2c_read: i2c_receive failed (%d)\n", rc); + return 1; + } + + rc = i2c_doio(&state); + if (rc != 0) { + printf("i2c_read: i2c_doio failed (%d)\n", rc); + return 1; + } + return 0; +} + +int +i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len) +{ + i2c_state_t state; + uchar xaddr[4]; + int rc; + + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of address + * and the extra bits end up in the "chip address" bit slots. + * This makes a 24WC08 (1Kbyte) chip look like four 256 byte + * chips. + * + * Note that we consider the length of the address field to still + * be one byte because the extra address bits are hidden in the + * chip address. + */ + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + + i2c_newio(&state); + + rc = i2c_send(&state, chip, 0, I2CF_START_COND, alen, &xaddr[4-alen]); + if (rc != 0) { + printf("i2c_write: first i2c_send failed (%d)\n", rc); + return 1; + } + + rc = i2c_send(&state, 0, 0, I2CF_STOP_COND, len, buffer); + if (rc != 0) { + printf("i2c_write: second i2c_send failed (%d)\n", rc); + return 1; + } + + rc = i2c_doio(&state); + if (rc != 0) { + printf("i2c_write: i2c_doio failed (%d)\n", rc); + return 1; + } + return 0; +} + +uchar +i2c_reg_read(uchar chip, uchar reg) +{ + char buf; + + i2c_read(chip, reg, 1, &buf, 1); + + return (buf); +} + +void +i2c_reg_write(uchar chip, uchar reg, uchar val) +{ + i2c_write(chip, reg, 1, &val, 1); +} + +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/mpc8xx/cpu.c b/cpu/mpc8xx/cpu.c new file mode 100644 index 0000000..b1b58b0 --- /dev/null +++ b/cpu/mpc8xx/cpu.c @@ -0,0 +1,516 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * m8xx.c + * + * CPU specific code + * + * written or collected and sometimes rewritten by + * Magnus Damm <damm@bitsmart.com> + * + * minor modifications by + * Wolfgang Denk <wd@denx.de> + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <mpc8xx.h> +#include <asm/cache.h> + +static char *cpu_warning = "\n " \ + "*** Warning: CPU Core has Silicon Bugs -- Check the Errata ***"; + +#if ((defined(CONFIG_MPC860) || defined(CONFIG_MPC855)) && \ + !defined(CONFIG_MPC862)) +# ifdef CONFIG_MPC855 +# define ID_STR "PC855" +# else +# define ID_STR "PC860" +# endif + +static int check_CPU (long clock, uint pvr, uint immr) +{ + volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000); + uint k, m; + char buf[32]; + char pre = 'X'; + char *mid = "xx"; + char *suf; + + /* the highest 16 bits should be 0x0050 for a 860 */ + + if ((pvr >> 16) != 0x0050) + return -1; + + k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + m = 0; + + switch (k) { + case 0x00020001: pre = 'p'; suf = ""; break; + case 0x00030001: suf = ""; break; + case 0x00120003: suf = "A"; break; + case 0x00130003: suf = "A3"; break; + + case 0x00200004: suf = "B"; break; + + case 0x00300004: suf = "C"; break; + case 0x00310004: suf = "C1"; m = 1; + break; + + case 0x00200064: mid = "SR"; suf = "B"; break; + case 0x00300065: mid = "SR"; suf = "C"; break; + case 0x00310065: mid = "SR"; suf = "C1"; m = 1; break; + case 0x05010000: suf = "D3"; m = 1; break; + case 0x05020000: suf = "D4"; m = 1; break; + + /* this value is not documented anywhere */ + case 0x40000000: pre = 'P'; suf = "D"; m = 1; break; + + default: suf = NULL; break; + } + + if (suf) + printf ("%c" ID_STR "%sZPnn%s", pre, mid, suf); + else + printf ("unknown M" ID_STR " (0x%08x)", k); + + printf (" at %s MHz:", strmhz (buf, clock)); + + printf (" %u kB I-Cache", checkicache () >> 10); + printf (" %u kB D-Cache", checkdcache () >> 10); + + /* lets check and see if we're running on a 860T (or P?) */ + + immap->im_cpm.cp_fec.fec_addr_low = 0x12345678; + if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) { + printf (" FEC present"); + } + + if (!m) { + puts (cpu_warning); + } + + putc ('\n'); + + return 0; +} + +#elif defined(CONFIG_MPC862) + +static int check_CPU (long clock, uint pvr, uint immr) +{ + volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000); + uint k, m; + char buf[32]; + char pre = 'X'; + char *mid = "xx"; + char *suf; + + /* the highest 16 bits should be 0x0050 for a 8xx */ + + if ((pvr >> 16) != 0x0050) + return -1; + + k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + m = 0; + + switch (k) { + + /* this value is not documented anywhere */ + case 0x06000000: mid = "P"; suf = "0"; break; + case 0x06010001: mid = "P"; suf = "A"; m = 1; break; + case 0x07000003: mid = "P"; suf = "B"; m = 1; break; + default: suf = NULL; break; + } + + if (suf) + printf ("%cPC862%sZPnn%s", pre, mid, suf); + else + printf ("unknown MPC862 (0x%08x)", k); + + printf (" at %s MHz:", strmhz (buf, clock)); + + printf (" %u kB I-Cache", checkicache () >> 10); + printf (" %u kB D-Cache", checkdcache () >> 10); + + /* lets check and see if we're running on a 862T (or P?) */ + + immap->im_cpm.cp_fec.fec_addr_low = 0x12345678; + if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) { + printf (" FEC present"); + } + + if (!m) { + puts (cpu_warning); + } + + putc ('\n'); + + return 0; +} + +#elif defined(CONFIG_MPC823) + +static int check_CPU (long clock, uint pvr, uint immr) +{ + volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000); + uint k, m; + char buf[32]; + char *suf; + + /* the highest 16 bits should be 0x0050 for a 8xx */ + + if ((pvr >> 16) != 0x0050) + return -1; + + k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + m = 0; + + switch (k) { + /* MPC823 */ + case 0x20000000: suf = "0"; break; + case 0x20010000: suf = "0.1"; break; + case 0x20020000: suf = "Z2/3"; break; + case 0x20020001: suf = "Z3"; break; + case 0x21000000: suf = "A"; break; + case 0x21010000: suf = "B"; m = 1; break; + case 0x21010001: suf = "B2"; m = 1; break; + /* MPC823E */ + case 0x24010000: suf = NULL; + puts ("PPC823EZTnnB2"); + m = 1; + break; + default: + suf = NULL; + printf ("unknown MPC823 (0x%08x)", k); + break; + } + if (suf) + printf ("PPC823ZTnn%s", suf); + + printf (" at %s MHz:", strmhz (buf, clock)); + + printf (" %u kB I-Cache", checkicache () >> 10); + printf (" %u kB D-Cache", checkdcache () >> 10); + + /* lets check and see if we're running on a 860T (or P?) */ + + immap->im_cpm.cp_fec.fec_addr_low = 0x12345678; + if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) { + puts (" FEC present"); + } + + if (!m) { + puts (cpu_warning); + } + + putc ('\n'); + + return 0; +} + +#elif defined(CONFIG_MPC850) + +static int check_CPU (long clock, uint pvr, uint immr) +{ + volatile immap_t *immap = (immap_t *) (immr & 0xFFFF0000); + uint k, m; + char buf[32]; + + /* the highest 16 bits should be 0x0050 for a 8xx */ + + if ((pvr >> 16) != 0x0050) + return -1; + + k = (immr << 16) | *((ushort *) & immap->im_cpm.cp_dparam[0xB0]); + m = 0; + + switch (k) { + case 0x20020001: + printf ("XPC850xxZT"); + break; + case 0x21000065: + printf ("XPC850xxZTA"); + break; + case 0x21010067: + printf ("XPC850xxZTB"); + m = 1; + break; + case 0x21020068: + printf ("XPC850xxZTC"); + m = 1; + break; + default: + printf ("unknown MPC850 (0x%08x)", k); + } + printf (" at %s MHz:", strmhz (buf, clock)); + + printf (" %u kB I-Cache", checkicache () >> 10); + printf (" %u kB D-Cache", checkdcache () >> 10); + + /* lets check and see if we're running on a 850T (or P?) */ + + immap->im_cpm.cp_fec.fec_addr_low = 0x12345678; + if (immap->im_cpm.cp_fec.fec_addr_low == 0x12345678) { + printf (" FEC present"); + } + + if (!m) { + puts (cpu_warning); + } + + putc ('\n'); + + return 0; +} +#else +#error CPU undefined +#endif +/* ------------------------------------------------------------------------- */ + +int checkcpu (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + ulong clock = gd->cpu_clk; + uint immr = get_immr (0); /* Return full IMMR contents */ + uint pvr = get_pvr (); + + puts ("CPU: "); + + /* 850 has PARTNUM 20 */ + /* 801 has PARTNUM 10 */ + return check_CPU (clock, pvr, immr); +} + +/* ------------------------------------------------------------------------- */ +/* L1 i-cache */ +/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB) */ +/* the 860 P (plus) has 256 sets of 16 bytes in 4 ways (= 16 kB) */ + +int checkicache (void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + u32 cacheon = rd_ic_cst () & IDC_ENABLED; + +#ifdef CONFIG_IP860 + u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */ +#else + u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */ +#endif + u32 m; + u32 lines = -1; + + wr_ic_cst (IDC_UNALL); + wr_ic_cst (IDC_INVALL); + wr_ic_cst (IDC_DISABLE); + __asm__ volatile ("isync"); + + while (!((m = rd_ic_cst ()) & IDC_CERR2)) { + wr_ic_adr (k); + wr_ic_cst (IDC_LDLCK); + __asm__ volatile ("isync"); + + lines++; + k += 0x10; /* the number of bytes in a cacheline */ + } + + wr_ic_cst (IDC_UNALL); + wr_ic_cst (IDC_INVALL); + + if (cacheon) + wr_ic_cst (IDC_ENABLE); + else + wr_ic_cst (IDC_DISABLE); + + __asm__ volatile ("isync"); + + return lines << 4; +}; + +/* ------------------------------------------------------------------------- */ +/* L1 d-cache */ +/* the standard 860 has 128 sets of 16 bytes in 2 ways (= 4 kB) */ +/* the 860 P (plus) has 256 sets of 16 bytes in 2 ways (= 8 kB) */ +/* call with cache disabled */ + +int checkdcache (void) +{ + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + u32 cacheon = rd_dc_cst () & IDC_ENABLED; + +#ifdef CONFIG_IP860 + u32 k = memctl->memc_br1 & ~0x00007fff; /* probe in flash memoryarea */ +#else + u32 k = memctl->memc_br0 & ~0x00007fff; /* probe in flash memoryarea */ +#endif + u32 m; + u32 lines = -1; + + wr_dc_cst (IDC_UNALL); + wr_dc_cst (IDC_INVALL); + wr_dc_cst (IDC_DISABLE); + + while (!((m = rd_dc_cst ()) & IDC_CERR2)) { + wr_dc_adr (k); + wr_dc_cst (IDC_LDLCK); + lines++; + k += 0x10; /* the number of bytes in a cacheline */ + } + + wr_dc_cst (IDC_UNALL); + wr_dc_cst (IDC_INVALL); + + if (cacheon) + wr_dc_cst (IDC_ENABLE); + else + wr_dc_cst (IDC_DISABLE); + + return lines << 4; +}; + +/* ------------------------------------------------------------------------- */ + +void upmconfig (uint upm, uint * table, uint size) +{ + uint i; + uint addr = 0; + volatile immap_t *immap = (immap_t *) CFG_IMMR; + volatile memctl8xx_t *memctl = &immap->im_memctl; + + for (i = 0; i < size; i++) { + memctl->memc_mdr = table[i]; /* (16-15) */ + memctl->memc_mcr = addr | upm; /* (16-16) */ + addr++; + } +} + +/* ------------------------------------------------------------------------- */ + +int do_reset (cmd_tbl_t * cmdtp, bd_t * bd, int flag, int argc, + char *argv[]) +{ + ulong msr, addr; + + volatile immap_t *immap = (immap_t *) CFG_IMMR; + + immap->im_clkrst.car_plprcr |= PLPRCR_CSR; /* Checkstop Reset enable */ + + /* Interrupts and MMU off */ + __asm__ volatile ("mtspr 81, 0"); + __asm__ volatile ("mfmsr %0":"=r" (msr)); + + msr &= ~0x1030; + __asm__ volatile ("mtmsr %0"::"r" (msr)); + + /* + * Trying to execute the next instruction at a non-existing address + * should cause a machine check, resulting in reset + */ +#ifdef CFG_RESET_ADDRESS + addr = CFG_RESET_ADDRESS; +#else + /* + * note: when CFG_MONITOR_BASE points to a RAM address, CFG_MONITOR_BASE + * - sizeof (ulong) is usually a valid address. Better pick an address + * known to be invalid on your system and assign it to CFG_RESET_ADDRESS. + * "(ulong)-1" used to be a good choice for many systems... + */ + addr = CFG_MONITOR_BASE - sizeof (ulong); +#endif + ((void (*)(void)) addr) (); + return 1; +} + +/* ------------------------------------------------------------------------- */ + +/* + * Get timebase clock frequency (like cpu_clk in Hz) + * + * See table 15-5 pp. 15-16, and SCCR[RTSEL] pp. 15-27. + */ +unsigned long get_tbclk (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + volatile immap_t *immr = (volatile immap_t *) CFG_IMMR; + ulong oscclk, factor; + + if (immr->im_clkrst.car_sccr & SCCR_TBS) { + return (gd->cpu_clk / 16); + } + + factor = (((CFG_PLPRCR) & PLPRCR_MF_MSK) >> PLPRCR_MF_SHIFT) + 1; + + oscclk = gd->cpu_clk / factor; + + if ((immr->im_clkrst.car_sccr & SCCR_RTSEL) == 0 || factor > 2) { + return (oscclk / 4); + } + return (oscclk / 16); +} + +/* ------------------------------------------------------------------------- */ + +#if defined(CONFIG_WATCHDOG) +void watchdog_reset (void) +{ + int re_enable = disable_interrupts (); + + reset_8xx_watchdog ((immap_t *) CFG_IMMR); + if (re_enable) + enable_interrupts (); +} + +void reset_8xx_watchdog (volatile immap_t * immr) +{ +# if defined(CONFIG_LWMON) + /* + * The LWMON board uses a MAX6301 Watchdog + * with the trigger pin connected to port PA.7 + * + * (The old board version used a MAX706TESA Watchdog, which + * had to be handled exactly the same.) + */ +# define WATCHDOG_BIT 0x0100 + immr->im_ioport.iop_papar &= ~(WATCHDOG_BIT); /* GPIO */ + immr->im_ioport.iop_padir |= WATCHDOG_BIT; /* Output */ + immr->im_ioport.iop_paodr &= ~(WATCHDOG_BIT); /* active output */ + + immr->im_ioport.iop_padat ^= WATCHDOG_BIT; /* Toggle WDI */ +# else + /* + * All other boards use the MPC8xx Internal Watchdog + */ + immr->im_siu_conf.sc_swsr = 0x556c; /* write magic1 */ + immr->im_siu_conf.sc_swsr = 0xaa39; /* write magic2 */ +# endif /* CONFIG_LWMON */ +} + +#endif /* CONFIG_WATCHDOG */ + +/* ------------------------------------------------------------------------- */ diff --git a/cpu/mpc8xx/fec.c b/cpu/mpc8xx/fec.c new file mode 100644 index 0000000..d43dcaa --- /dev/null +++ b/cpu/mpc8xx/fec.c @@ -0,0 +1,710 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <commproc.h> +#include <net.h> +#include <command.h> + +#undef ET_DEBUG + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(FEC_ENET) + +#ifdef CFG_DISCOVER_PHY +#include <miiphy.h> +static void mii_discover_phy(void); +#endif + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 + +#define TX_BUF_CNT 2 + +#define TOUT_LOOP 100 + +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1520 + + +static char txbuf[DBUF_LENGTH]; + +static uint rxIdx; /* index of the current RX buffer */ +static uint txIdx; /* index of the current TX buffer */ + +/* + * FEC Ethernet Tx and Rx buffer descriptors allocated at the + * immr->udata_bd address on Dual-Port RAM + * Provide for Double Buffering + */ + +typedef volatile struct CommonBufferDescriptor { + cbd_t rxbd[PKTBUFSRX]; /* Rx BD */ + cbd_t txbd[TX_BUF_CNT]; /* Tx BD */ +} RTXBD; + +static RTXBD *rtx = NULL; + +static int fec_send(struct eth_device* dev, volatile void *packet, int length); +static int fec_recv(struct eth_device* dev); +static int fec_init(struct eth_device* dev, bd_t * bd); +static void fec_halt(struct eth_device* dev); + +int fec_initialize(bd_t *bis) +{ + struct eth_device* dev; + + dev = (struct eth_device*) malloc(sizeof *dev); + + sprintf(dev->name, "FEC ETHERNET"); + dev->iobase = 0; + dev->priv = 0; + dev->init = fec_init; + dev->halt = fec_halt; + dev->send = fec_send; + dev->recv = fec_recv; + + eth_register(dev); + + return 1; +} + +static int fec_send(struct eth_device* dev, volatile void *packet, int length) +{ + int j, rc; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); + + /* section 16.9.23.3 + * Wait for ready + */ + j = 0; + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) { + udelay(1); + j++; + } + if (j>=TOUT_LOOP) { + printf("TX not ready\n"); + } + + rtx->txbd[txIdx].cbd_bufaddr = (uint)packet; + rtx->txbd[txIdx].cbd_datlen = length; + rtx->txbd[txIdx].cbd_sc |= BD_ENET_TX_READY | BD_ENET_TX_LAST; + __asm__ ("eieio"); + + /* Activate transmit Buffer Descriptor polling */ + fecp->fec_x_des_active = 0x01000000; /* Descriptor polling active */ + + j = 0; + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j<TOUT_LOOP)) { +#if defined(CONFIG_ICU862) + udelay(10); +#else + udelay(1); +#endif + j++; + } + if (j>=TOUT_LOOP) { + printf("TX timeout\n"); + } +#ifdef ET_DEBUG + printf("%s[%d] %s: cycles: %d status: %x retry cnt: %d\n", + __FILE__,__LINE__,__FUNCTION__,j,rtx->txbd[txIdx].cbd_sc, + (rtx->txbd[txIdx].cbd_sc & 0x003C)>>2); +#endif + /* return only status bits */; + rc = (rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_STATS); + + txIdx = (txIdx + 1) % TX_BUF_CNT; + + return rc; +} + +static int fec_recv(struct eth_device* dev) +{ + int length; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); + + for (;;) { + /* section 16.9.23.2 */ + if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { + length = -1; + break; /* nothing received - leave for() loop */ + } + + length = rtx->rxbd[rxIdx].cbd_datlen; + + if (rtx->rxbd[rxIdx].cbd_sc & 0x003f) { +#ifdef ET_DEBUG + printf("%s[%d] err: %x\n", + __FUNCTION__,__LINE__,rtx->rxbd[rxIdx].cbd_sc); +#endif + } else { + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[rxIdx], length - 4); + } + + /* Give the buffer back to the FEC. */ + rtx->rxbd[rxIdx].cbd_datlen = 0; + + /* wrap around buffer index when necessary */ + if ((rxIdx + 1) >= PKTBUFSRX) { + rtx->rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + rxIdx = 0; + } else { + rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; + rxIdx++; + } + + __asm__ ("eieio"); + + /* Try to fill Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ + } + + return length; +} + +/************************************************************** + * + * FEC Ethernet Initialization Routine + * + *************************************************************/ + +#define FEC_ECNTRL_PINMUX 0x00000004 +#define FEC_ECNTRL_ETHER_EN 0x00000002 +#define FEC_ECNTRL_RESET 0x00000001 + +#define FEC_RCNTRL_BC_REJ 0x00000010 +#define FEC_RCNTRL_PROM 0x00000008 +#define FEC_RCNTRL_MII_MODE 0x00000004 +#define FEC_RCNTRL_DRT 0x00000002 +#define FEC_RCNTRL_LOOP 0x00000001 + +#define FEC_TCNTRL_FDEN 0x00000004 +#define FEC_TCNTRL_HBC 0x00000002 +#define FEC_TCNTRL_GTS 0x00000001 + +#define FEC_RESET_DELAY 50 + +static int fec_init(struct eth_device* dev, bd_t * bd) +{ + + int i; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile fec_t *fecp = &(immr->im_cpm.cp_fec); + +#if defined(CONFIG_FADS) && defined(CONFIG_MPC860T) + /* configure FADS for fast (FEC) ethernet, half-duplex */ + /* The LXT970 needs about 50ms to recover from reset, so + * wait for it by discovering the PHY before leaving eth_init(). + */ + { + volatile uint *bcsr4 = (volatile uint *) BCSR4; + *bcsr4 = (*bcsr4 & ~(BCSR4_FETH_EN | BCSR4_FETHCFG1)) + | (BCSR4_FETHCFG0 | BCSR4_FETHFDE | BCSR4_FETHRST); + + /* reset the LXT970 PHY */ + *bcsr4 &= ~BCSR4_FETHRST; + udelay (10); + *bcsr4 |= BCSR4_FETHRST; + udelay (10); + } +#endif + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return 0; + } + + /* We use strictly polling mode only + */ + fecp->fec_imask = 0; + + /* Clear any pending interrupt + */ + fecp->fec_ievent = 0xffc0; + + /* No need to set the IVEC register */ + + /* Set station address + */ +#define ea eth_get_dev()->enetaddr + fecp->fec_addr_low = (ea[0] << 24) | (ea[1] << 16) | + (ea[2] << 8) | (ea[3] ) ; + fecp->fec_addr_high = (ea[4] << 8) | (ea[5] ) ; +#undef ea + + /* Clear multicast address hash table + */ + fecp->fec_hash_table_high = 0; + fecp->fec_hash_table_low = 0; + + /* Set maximum receive buffer size. + */ + fecp->fec_r_buff_size = PKT_MAXBLR_SIZE; + + /* Set maximum frame length + */ + fecp->fec_r_hash = PKT_MAXBUF_SIZE; + + /* + * Setup Buffers and Buffer Desriptors + */ + rxIdx = 0; + txIdx = 0; + + if (!rtx) { +#ifdef CFG_ALLOC_DPRAM + rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + dpram_alloc_align(sizeof(RTXBD),8)); +#else + rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_FEC_BASE); +#endif + } + /* + * Setup Receiver Buffer Descriptors (13.14.24.18) + * Settings: + * Empty, Wrap + */ + for (i = 0; i < PKTBUFSRX; i++) { + rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; + rtx->rxbd[i].cbd_datlen = 0; /* Reset */ + rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + } + rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + + /* + * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) + * Settings: + * Last, Tx CRC + */ + for (i = 0; i < TX_BUF_CNT; i++) { + rtx->txbd[i].cbd_sc = BD_ENET_TX_LAST | BD_ENET_TX_TC; + rtx->txbd[i].cbd_datlen = 0; /* Reset */ + rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]); + } + rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; + + /* Set receive and transmit descriptor base + */ + fecp->fec_r_des_start = (unsigned int) (&rtx->rxbd[0]); + fecp->fec_x_des_start = (unsigned int) (&rtx->txbd[0]); + + /* Enable MII mode + */ +#if 0 /* Full duplex mode */ + fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE; + fecp->fec_x_cntrl = FEC_TCNTRL_FDEN; +#else /* Half duplex mode */ + fecp->fec_r_cntrl = FEC_RCNTRL_MII_MODE | FEC_RCNTRL_DRT; + fecp->fec_x_cntrl = 0; +#endif + + /* Enable big endian and don't care about SDMA FC. + */ + fecp->fec_fun_code = 0x78000000; + + /* Set MII speed to 2.5 MHz or slightly below. + * According to the MPC860T (Rev. D) Fast ethernet controller user + * manual (6.2.14), + * the MII management interface clock must be less than or equal + * to 2.5 MHz. + * This MDC frequency is equal to system clock / (2 * MII_SPEED). + * Then MII_SPEED = system_clock / 2 * 2,5 Mhz. + */ + fecp->fec_mii_speed = ((bd->bi_busfreq + 4999999) / 5000000) << 1; + +#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) + /* Configure all of port D for MII. + */ + immr->im_ioport.iop_pdpar = 0x1fff; + + /* Bits moved from Rev. D onward */ + if ((get_immr (0) & 0xffff) < 0x0501) { + immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ + } else { + immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ + } +#else + /* Configure port A for MII. + */ + +#if defined(CONFIG_ICU862) && defined(CFG_DISCOVER_PHY) + + /* On the ICU862 board the MII-MDC pin is routed to PD8 pin + * of CPU, so for this board we need to configure Utopia and + * enable PD8 to MII-MDC function */ + immr->im_ioport.iop_pdpar |= 0x4080; +#endif + + /* Has Utopia been configured? */ + if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) { + /* + * YES - Use MUXED mode for UTOPIA bus. + * This frees Port A for use by MII (see 862UM table 41-6). + */ + immr->im_ioport.utmode &= ~0x80; + } else { + /* + * NO - set SPLIT mode for UTOPIA bus. + * + * This doesn't really effect UTOPIA (which isn't + * enabled anyway) but just tells the 862 + * to use port A for MII (see 862UM table 41-6). + */ + immr->im_ioport.utmode |= 0x80; + } +#endif /* !defined(CONFIG_ICU862) */ + + rxIdx = 0; + txIdx = 0; + + /* Now enable the transmit and receive processing + */ + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; + +#ifdef CFG_DISCOVER_PHY + /* wait for the PHY to wake up after reset + */ + mii_discover_phy(); +#endif + + /* And last, try to fill Rx Buffer Descriptors */ + fecp->fec_r_des_active = 0x01000000; /* Descriptor polling active */ + + return 1; +} + + + +static void fec_halt(struct eth_device* dev) +{ +#if 0 + volatile immap_t *immr = (immap_t *)CFG_IMMR; + immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); +#endif +} + +#if 0 +void restart(void) +{ + volatile immap_t *immr = (immap_t *)CFG_IMMR; + immr->im_cpm.cp_scc[SCC_ENET].scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT); +} +#endif + +#if defined(CFG_DISCOVER_PHY) || (CONFIG_COMMANDS & CFG_CMD_MII) + +static int phyaddr = -1; /* didn't find a PHY yet */ +static uint phytype; + +/* Make MII read/write commands for the FEC. +*/ + +#define mk_mii_read(ADDR, REG) (0x60020000 | ((ADDR << 23) | \ + (REG & 0x1f) << 18)) + +#define mk_mii_write(ADDR, REG, VAL) (0x50020000 | ((ADDR << 23) | \ + (REG & 0x1f) << 18) | \ + (VAL & 0xffff)) + +/* Interrupt events/masks. +*/ +#define FEC_ENET_HBERR ((uint)0x80000000) /* Heartbeat error */ +#define FEC_ENET_BABR ((uint)0x40000000) /* Babbling receiver */ +#define FEC_ENET_BABT ((uint)0x20000000) /* Babbling transmitter */ +#define FEC_ENET_GRA ((uint)0x10000000) /* Graceful stop complete */ +#define FEC_ENET_TXF ((uint)0x08000000) /* Full frame transmitted */ +#define FEC_ENET_TXB ((uint)0x04000000) /* A buffer was transmitted */ +#define FEC_ENET_RXF ((uint)0x02000000) /* Full frame received */ +#define FEC_ENET_RXB ((uint)0x01000000) /* A buffer was received */ +#define FEC_ENET_MII ((uint)0x00800000) /* MII interrupt */ +#define FEC_ENET_EBERR ((uint)0x00400000) /* SDMA bus error */ + +/* PHY identification + */ +#define PHY_ID_LXT970 0x78100000 /* LXT970 */ +#define PHY_ID_LXT971 0x001378e0 /* LXT971 and 972 */ +#define PHY_ID_82555 0x02a80150 /* Intel 82555 */ +#define PHY_ID_QS6612 0x01814400 /* QS6612 */ +#define PHY_ID_AMD79C784 0x00225610 /* AMD 79C784 */ +#define PHY_ID_LSI80225 0x0016f870 /* LSI 80225 */ +#define PHY_ID_LSI80225B 0x0016f880 /* LSI 80225/B */ + + +/* send command to phy using mii, wait for result */ +static uint +mii_send(uint mii_cmd) +{ + uint mii_reply; + volatile fec_t *ep; + + ep = &(((immap_t *)CFG_IMMR)->im_cpm.cp_fec); + + ep->fec_mii_data = mii_cmd; /* command to phy */ + + /* wait for mii complete */ + while (!(ep->fec_ievent & FEC_ENET_MII)) + ; /* spin until done */ + mii_reply = ep->fec_mii_data; /* result from phy */ + ep->fec_ievent = FEC_ENET_MII; /* clear MII complete */ +#if 0 + printf("%s[%d] %s: sent=0x%8.8x, reply=0x%8.8x\n", + __FILE__,__LINE__,__FUNCTION__,mii_cmd,mii_reply); +#endif + return (mii_reply & 0xffff); /* data read from phy */ +} +#endif /* CFG_DISCOVER_PHY || (CONFIG_COMMANDS & CFG_CMD_MII) */ + +#if defined(CFG_DISCOVER_PHY) +static void +mii_discover_phy(void) +{ +#define MAX_PHY_PASSES 11 + uint phyno; + int pass; + + phyaddr = -1; /* didn't find a PHY yet */ + for (pass = 1; pass <= MAX_PHY_PASSES && phyaddr < 0; ++pass) { + if (pass > 1) { + /* PHY may need more time to recover from reset. + * The LXT970 needs 50ms typical, no maximum is + * specified, so wait 10ms before try again. + * With 11 passes this gives it 100ms to wake up. + */ + udelay(10000); /* wait 10ms */ + } + for (phyno = 0; phyno < 32 && phyaddr < 0; ++phyno) { + phytype = mii_send(mk_mii_read(phyno, PHY_PHYIDR1)); +#ifdef ET_DEBUG + printf("PHY type 0x%x pass %d type ", phytype, pass); +#endif + if (phytype != 0xffff) { + phyaddr = phyno; + phytype <<= 16; + phytype |= mii_send(mk_mii_read(phyno, + PHY_PHYIDR2)); + +#ifdef ET_DEBUG + printf("PHY @ 0x%x pass %d type ",phyno,pass); + switch (phytype & 0xfffffff0) { + case PHY_ID_LXT970: + printf("LXT970\n"); + break; + case PHY_ID_LXT971: + printf("LXT971\n"); + break; + case PHY_ID_82555: + printf("82555\n"); + break; + case PHY_ID_QS6612: + printf("QS6612\n"); + break; + case PHY_ID_AMD79C784: + printf("AMD79C784\n"); + break; + case PHY_ID_LSI80225B: + printf("LSI L80225/B\n"); + break; + default: + printf("0x%08x\n", phytype); + break; + } +#endif + } + } + } + if (phyaddr < 0) { + printf("No PHY device found.\n"); + } +} +#endif /* CFG_DISCOVER_PHY */ + +#if (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII) + +static int mii_init_done = 0; + +/**************************************************************************** + * mii_init -- Initialize the MII for MII command without ethernet + * This function is a subset of eth_init + **************************************************************************** + */ +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; + + if (mii_init_done != 0) { + return; + } + + /* Whack a reset. + * A delay is required between a reset of the FEC block and + * initialization of other FEC registers because the reset takes + * some time to complete. If you don't delay, subsequent writes + * to FEC registers might get killed by the reset routine which is + * still in progress. + */ + + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_RESET; + for (i = 0; + (fecp->fec_ecntrl & FEC_ECNTRL_RESET) && (i < FEC_RESET_DELAY); + ++i) { + udelay (1); + } + if (i == FEC_RESET_DELAY) { + printf ("FEC_RESET_DELAY timeout\n"); + return; + } + + /* We use strictly polling mode only + */ + fecp->fec_imask = 0; + + /* Clear any pending interrupt + */ + fecp->fec_ievent = 0xffc0; + + /* Set MII speed to 2.5 MHz or slightly below. + * According to the MPC860T (Rev. D) Fast ethernet controller user + * manual (6.2.14), + * the MII management interface clock must be less than or equal + * to 2.5 MHz. + * This MDC frequency is equal to system clock / (2 * MII_SPEED). + * Then MII_SPEED = system_clock / 2 * 2,5 Mhz. + */ + fecp->fec_mii_speed = ((bd->bi_busfreq + 4999999) / 5000000) << 1; + +#if !defined(CONFIG_ICU862) && !defined(CONFIG_IAD210) + /* Configure all of port D for MII. + */ + immr->im_ioport.iop_pdpar = 0x1fff; + + /* Bits moved from Rev. D onward */ + if ((get_immr (0) & 0xffff) < 0x0501) { + immr->im_ioport.iop_pddir = 0x1c58; /* Pre rev. D */ + } else { + immr->im_ioport.iop_pddir = 0x1fff; /* Rev. D and later */ + } +#else + /* Configure port A for MII. + */ + +#if defined(CONFIG_ICU862) + + /* On the ICU862 board the MII-MDC pin is routed to PD8 pin + * of CPU, so for this board we need to configure Utopia and + * enable PD8 to MII-MDC function */ + immr->im_ioport.iop_pdpar |= 0x4080; +#endif + + /* Has Utopia been configured? */ + if (immr->im_ioport.iop_pdpar & (0x8000 >> 1)) { + /* + * YES - Use MUXED mode for UTOPIA bus. + * This frees Port A for use by MII (see 862UM table 41-6). + */ + immr->im_ioport.utmode &= ~0x80; + } else { + /* + * NO - set SPLIT mode for UTOPIA bus. + * + * This doesn't really effect UTOPIA (which isn't + * enabled anyway) but just tells the 862 + * to use port A for MII (see 862UM table 41-6). + */ + immr->im_ioport.utmode |= 0x80; + } +#endif /* !defined(CONFIG_ICU862) */ + /* Now enable the transmit and receive processing + */ + fecp->fec_ecntrl = FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN; + + mii_init_done = 1; +} +/***************************************************************************** + * Read and write a MII PHY register, routines used by MII Utilities + * + * FIXME: These routines are expected to return 0 on success, but mii_send + * does _not_ return an error code. Maybe 0xFFFF means error, i.e. + * no PHY connected... + * For now always return 0. + * FIXME: These routines only work after calling eth_init() at least once! + * Otherwise they hang in mii_send() !!! Sorry! + *****************************************************************************/ + +int miiphy_read(unsigned char addr, unsigned char reg, unsigned short *value) +{ + short rdreg; /* register working value */ + +#ifdef MII_DEBUG + printf ("miiphy_read(0x%x) @ 0x%x = ", reg, addr); +#endif + rdreg = mii_send(mk_mii_read(addr, reg)); + + *value = rdreg; + +#ifdef MII_DEBUG + printf ("0x%04x\n", *value); +#endif + + return 0; +} + +int miiphy_write(unsigned char addr, unsigned char reg, unsigned short value) +{ + short rdreg; /* register working value */ + +#ifdef MII_DEBUG + printf ("miiphy_write(0x%x) @ 0x%x = ", reg, addr); +#endif + + rdreg = mii_send(mk_mii_write(addr, reg, value)); + +#ifdef MII_DEBUG + printf ("0x%04x\n", value); +#endif + + return 0; +} +#endif /* (CONFIG_COMMANDS & CFG_CMD_MII) && !defined(CONFIG_BITBANGMII)*/ + +#endif /* CFG_CMD_NET, FEC_ENET */ diff --git a/cpu/mpc8xx/spi.c b/cpu/mpc8xx/spi.c new file mode 100644 index 0000000..f04d88e --- /dev/null +++ b/cpu/mpc8xx/spi.c @@ -0,0 +1,571 @@ +/* + * Copyright (c) 2001 Navin Boppuri / Prashant Patel + * <nboppuri@trinetcommunication.com>, + * <pmpatel@trinetcommunication.com> + * Copyright (c) 2001 Gerd Mennchen <Gerd.Mennchen@icn.siemens.de> + * Copyright (c) 2001 Wolfgang Denk, DENX Software Engineering, <wd@denx.de>. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * MPC8xx CPM SPI interface. + * + * Parts of this code are probably not portable and/or specific to + * the board which I used for the tests. Please send fixes/complaints + * to wd@denx.de + * + */ + +#include <common.h> +#include <mpc8xx.h> +#include <commproc.h> +#include <linux/ctype.h> +#include <malloc.h> +#include <post.h> +#include <net.h> + +#if (defined(CONFIG_SPI)) || (CONFIG_POST & CFG_POST_SPI) + +/* Warning: + * You cannot enable DEBUG for early system initalization, i. e. when + * this driver is used to read environment parameters like "baudrate" + * from EEPROM which are used to initialize the serial port which is + * needed to print the debug messages... + */ +#undef DEBUG + +#define SPI_EEPROM_WREN 0x06 +#define SPI_EEPROM_RDSR 0x05 +#define SPI_EEPROM_READ 0x03 +#define SPI_EEPROM_WRITE 0x02 + +/* --------------------------------------------------------------- + * Offset for initial SPI buffers in DPRAM: + * We need a 520 byte scratch DPRAM area to use at an early stage. + * It is used between the two initialization calls (spi_init_f() + * and spi_init_r()). + * The value 0xb00 makes it far enough from the start of the data + * area (as well as from the stack pointer). + * --------------------------------------------------------------- */ +#ifndef CFG_SPI_INIT_OFFSET +#define CFG_SPI_INIT_OFFSET 0xB00 +#endif + +#ifdef DEBUG + +#define DPRINT(a) printf a; +/* ----------------------------------------------- + * Helper functions to peek into tx and rx buffers + * ----------------------------------------------- */ +static const char * const hex_digit = "0123456789ABCDEF"; + +static char quickhex (int i) +{ + return hex_digit[i]; +} + +static void memdump (void *pv, int num) +{ + int i; + unsigned char *pc = (unsigned char *) pv; + + for (i = 0; i < num; i++) + printf ("%c%c ", quickhex (pc[i] >> 4), quickhex (pc[i] & 0x0f)); + printf ("\t"); + for (i = 0; i < num; i++) + printf ("%c", isprint (pc[i]) ? pc[i] : '.'); + printf ("\n"); +} +#else /* !DEBUG */ + +#define DPRINT(a) + +#endif /* DEBUG */ + +/* ------------------- + * Function prototypes + * ------------------- */ +void spi_init (void); + +ssize_t spi_read (uchar *, int, uchar *, int); +ssize_t spi_write (uchar *, int, uchar *, int); +ssize_t spi_xfer (size_t); + +/* ------------------- + * Variables + * ------------------- */ + +#define MAX_BUFFER 0x104 + +/* ---------------------------------------------------------------------- + * Initially we place the RX and TX buffers at a fixed location in DPRAM! + * ---------------------------------------------------------------------- */ +static uchar *rxbuf = + (uchar *)&((cpm8xx_t *)&((immap_t *)CFG_IMMR)->im_cpm)->cp_dpmem + [CFG_SPI_INIT_OFFSET]; +static uchar *txbuf = + (uchar *)&((cpm8xx_t *)&((immap_t *)CFG_IMMR)->im_cpm)->cp_dpmem + [CFG_SPI_INIT_OFFSET+MAX_BUFFER]; + +/* ************************************************************************** + * + * Function: spi_init_f + * + * Description: Init SPI-Controller (ROM part) + * + * return: --- + * + * *********************************************************************** */ +void spi_init_f (void) +{ + unsigned int dpaddr; + + volatile spi_t *spi; + volatile immap_t *immr; + volatile cpic8xx_t *cpi; + volatile cpm8xx_t *cp; + volatile iop8xx_t *iop; + volatile cbd_t *tbdf, *rbdf; + + immr = (immap_t *) CFG_IMMR; + cpi = (cpic8xx_t *)&immr->im_cpic; + iop = (iop8xx_t *) &immr->im_ioport; + cp = (cpm8xx_t *) &immr->im_cpm; + +#ifdef CFG_SPI_UCODE_PATCH + spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase]; +#else + spi = (spi_t *)&cp->cp_dparam[PROFF_SPI]; + /* Disable relocation */ + spi->spi_rpbase = 0; +#endif + +/* 1 */ + /* ------------------------------------------------ + * Initialize Port B SPI pins -> page 34-8 MPC860UM + * (we are only in Master Mode !) + * ------------------------------------------------ */ + + /* -------------------------------------------- + * GPIO or per. Function + * PBPAR[28] = 1 [0x00000008] -> PERI: (SPIMISO) + * PBPAR[29] = 1 [0x00000004] -> PERI: (SPIMOSI) + * PBPAR[30] = 1 [0x00000002] -> PERI: (SPICLK) + * PBPAR[31] = 0 [0x00000001] -> GPIO: (CS for PCUE/CCM-EEPROM) + * -------------------------------------------- */ + cp->cp_pbpar |= 0x0000000E; /* set bits */ + cp->cp_pbpar &= ~0x00000001; /* reset bit */ + + /* ---------------------------------------------- + * In/Out or per. Function 0/1 + * PBDIR[28] = 1 [0x00000008] -> PERI1: SPIMISO + * PBDIR[29] = 1 [0x00000004] -> PERI1: SPIMOSI + * PBDIR[30] = 1 [0x00000002] -> PERI1: SPICLK + * PBDIR[31] = 1 [0x00000001] -> GPIO OUT: CS for PCUE/CCM-EEPROM + * ---------------------------------------------- */ + cp->cp_pbdir |= 0x0000000F; + + /* ---------------------------------------------- + * open drain or active output + * PBODR[28] = 1 [0x00000008] -> open drain: SPIMISO + * PBODR[29] = 0 [0x00000004] -> active output SPIMOSI + * PBODR[30] = 0 [0x00000002] -> active output: SPICLK + * PBODR[31] = 0 [0x00000001] -> active output: GPIO OUT: CS for PCUE/CCM + * ---------------------------------------------- */ + + cp->cp_pbodr |= 0x00000008; + cp->cp_pbodr &= ~0x00000007; + + /* Initialize the parameter ram. + * We need to make sure many things are initialized to zero + */ + spi->spi_rstate = 0; + spi->spi_rdp = 0; + spi->spi_rbptr = 0; + spi->spi_rbc = 0; + spi->spi_rxtmp = 0; + spi->spi_tstate = 0; + spi->spi_tdp = 0; + spi->spi_tbptr = 0; + spi->spi_tbc = 0; + spi->spi_txtmp = 0; + + /* Allocate space for one transmit and one receive buffer + * descriptor in the DP ram + */ +#ifdef CFG_ALLOC_DPRAM + dpaddr = dpram_alloc_align (sizeof(cbd_t)*2, 8); +#else + dpaddr = CPM_SPI_BASE; +#endif + +/* 3 */ + /* Set up the SPI parameters in the parameter ram */ + spi->spi_rbase = dpaddr; + spi->spi_tbase = dpaddr + sizeof (cbd_t); + + /***********IMPORTANT******************/ + + /* + * Setting transmit and receive buffer descriptor pointers + * initially to rbase and tbase. Only the microcode patches + * documentation talks about initializing this pointer. This + * is missing from the sample I2C driver. If you dont + * initialize these pointers, the kernel hangs. + */ + spi->spi_rbptr = spi->spi_rbase; + spi->spi_tbptr = spi->spi_tbase; + +/* 4 */ +#ifdef CFG_SPI_UCODE_PATCH + /* + * Initialize required parameters if using microcode patch. + */ + spi->spi_rstate = 0; + spi->spi_tstate = 0; +#else + /* Init SPI Tx + Rx Parameters */ + while (cp->cp_cpcr & CPM_CR_FLG) + ; + cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_SPI, CPM_CR_INIT_TRX) | CPM_CR_FLG; + while (cp->cp_cpcr & CPM_CR_FLG) + ; +#endif /* CFG_SPI_UCODE_PATCH */ + +/* 5 */ + /* Set SDMA configuration register */ + immr->im_siu_conf.sc_sdcr = 0x0001; + +/* 6 */ + /* Set to big endian. */ + spi->spi_tfcr = SMC_EB; + spi->spi_rfcr = SMC_EB; + +/* 7 */ + /* Set maximum receive size. */ + spi->spi_mrblr = MAX_BUFFER; + +/* 8 + 9 */ + /* tx and rx buffer descriptors */ + tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase]; + rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase]; + + tbdf->cbd_sc &= ~BD_SC_READY; + rbdf->cbd_sc &= ~BD_SC_EMPTY; + + /* Set the bd's rx and tx buffer address pointers */ + rbdf->cbd_bufaddr = (ulong) rxbuf; + tbdf->cbd_bufaddr = (ulong) txbuf; + +/* 10 + 11 */ + cp->cp_spim = 0; /* Mask all SPI events */ + cp->cp_spie = SPI_EMASK; /* Clear all SPI events */ + + return; +} + +/* ************************************************************************** + * + * Function: spi_init_r + * + * Description: Init SPI-Controller (RAM part) - + * The malloc engine is ready and we can move our buffers to + * normal RAM + * + * return: --- + * + * *********************************************************************** */ +void spi_init_r (void) +{ + volatile cpm8xx_t *cp; + volatile spi_t *spi; + volatile immap_t *immr; + volatile cbd_t *tbdf, *rbdf; + + immr = (immap_t *) CFG_IMMR; + cp = (cpm8xx_t *) &immr->im_cpm; + +#ifdef CFG_SPI_UCODE_PATCH + spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase]; +#else + spi = (spi_t *)&cp->cp_dparam[PROFF_SPI]; + /* Disable relocation */ + spi->spi_rpbase = 0; +#endif + + /* tx and rx buffer descriptors */ + tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase]; + rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase]; + + /* Allocate memory for RX and TX buffers */ + rxbuf = (uchar *) malloc (MAX_BUFFER); + txbuf = (uchar *) malloc (MAX_BUFFER); + + rbdf->cbd_bufaddr = (ulong) rxbuf; + tbdf->cbd_bufaddr = (ulong) txbuf; + + return; +} + +/**************************************************************************** + * Function: spi_write + **************************************************************************** */ +ssize_t spi_write (uchar *addr, int alen, uchar *buffer, int len) +{ + int i; + + memset(rxbuf, 0, MAX_BUFFER); + memset(txbuf, 0, MAX_BUFFER); + *txbuf = SPI_EEPROM_WREN; /* write enable */ + spi_xfer(1); + memcpy(txbuf, addr, alen); + *txbuf = SPI_EEPROM_WRITE; /* WRITE memory array */ + memcpy(alen + txbuf, buffer, len); + spi_xfer(alen + len); + /* ignore received data */ + for (i = 0; i < 1000; i++) { + *txbuf = SPI_EEPROM_RDSR; /* read status */ + txbuf[1] = 0; + spi_xfer(2); + if (!(rxbuf[1] & 1)) { + break; + } + udelay(1000); + } + if (i >= 1000) { + printf ("*** spi_write: Time out while writing!\n"); + } + + return len; +} + +/**************************************************************************** + * Function: spi_read + **************************************************************************** */ +ssize_t spi_read (uchar *addr, int alen, uchar *buffer, int len) +{ + memset(rxbuf, 0, MAX_BUFFER); + memset(txbuf, 0, MAX_BUFFER); + memcpy(txbuf, addr, alen); + *txbuf = SPI_EEPROM_READ; /* READ memory array */ + + /* + * There is a bug in 860T (?) that cuts the last byte of input + * if we're reading into DPRAM. The solution we choose here is + * to always read len+1 bytes (we have one extra byte at the + * end of the buffer). + */ + spi_xfer(alen + len + 1); + memcpy(buffer, alen + rxbuf, len); + + return len; +} + +/**************************************************************************** + * Function: spi_xfer + **************************************************************************** */ +ssize_t spi_xfer (size_t count) +{ + volatile immap_t *immr; + volatile cpm8xx_t *cp; + volatile spi_t *spi; + cbd_t *tbdf, *rbdf; + ushort loop; + int tm; + + DPRINT (("*** spi_xfer entered ***\n")); + + immr = (immap_t *) CFG_IMMR; + cp = (cpm8xx_t *) &immr->im_cpm; + +#ifdef CFG_SPI_UCODE_PATCH + spi = (spi_t *)&cp->cp_dpmem[spi->spi_rpbase]; +#else + spi = (spi_t *)&cp->cp_dparam[PROFF_SPI]; + /* Disable relocation */ + spi->spi_rpbase = 0; +#endif + + tbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_tbase]; + rbdf = (cbd_t *) & cp->cp_dpmem[spi->spi_rbase]; + + /* Set CS for device */ + cp->cp_pbdat &= ~0x0001; + + /* Setting tx bd status and data length */ + tbdf->cbd_sc = BD_SC_READY | BD_SC_LAST | BD_SC_WRAP; + tbdf->cbd_datlen = count; + + DPRINT (("*** spi_xfer: Bytes to be xferred: %d ***\n", + tbdf->cbd_datlen)); + + /* Setting rx bd status and data length */ + rbdf->cbd_sc = BD_SC_EMPTY | BD_SC_WRAP; + rbdf->cbd_datlen = 0; /* rx length has no significance */ + + loop = cp->cp_spmode & SPMODE_LOOP; + cp->cp_spmode = /*SPMODE_DIV16 |*/ /* BRG/16 mode not used here */ + loop | + SPMODE_REV | + SPMODE_MSTR | + SPMODE_EN | + SPMODE_LEN(8) | /* 8 Bits per char */ + SPMODE_PM(0x8) ; /* medium speed */ + cp->cp_spim = 0; /* Mask all SPI events */ + cp->cp_spie = SPI_EMASK; /* Clear all SPI events */ + + /* start spi transfer */ + DPRINT (("*** spi_xfer: Performing transfer ...\n")); + cp->cp_spcom |= SPI_STR; /* Start transmit */ + + /* -------------------------------- + * Wait for SPI transmit to get out + * or time out (1 second = 1000 ms) + * -------------------------------- */ + for (tm=0; tm<1000; ++tm) { + if (cp->cp_spie & SPI_TXB) { /* Tx Buffer Empty */ + DPRINT (("*** spi_xfer: Tx buffer empty\n")); + break; + } + if ((tbdf->cbd_sc & BD_SC_READY) == 0) { + DPRINT (("*** spi_xfer: Tx BD done\n")); + break; + } + udelay (1000); + } + if (tm >= 1000) { + printf ("*** spi_xfer: Time out while xferring to/from SPI!\n"); + } + DPRINT (("*** spi_xfer: ... transfer ended\n")); + +#ifdef DEBUG + printf ("\nspi_xfer: txbuf after xfer\n"); + memdump ((void *) txbuf, 16); /* dump of txbuf before transmit */ + printf ("spi_xfer: rxbuf after xfer\n"); + memdump ((void *) rxbuf, 16); /* dump of rxbuf after transmit */ + printf ("\n"); +#endif + + /* Clear CS for device */ + cp->cp_pbdat |= 0x0001; + + return count; +} +#endif /* CONFIG_SPI || (CONFIG_POST & CFG_POST_SPI) */ + +/* + * SPI test + * + * The Serial Peripheral Interface (SPI) is tested in the local loopback mode. + * The interface is configured accordingly and several packets + * are transfered. The configurable test parameters are: + * TEST_MIN_LENGTH - minimum size of packet to transfer + * TEST_MAX_LENGTH - maximum size of packet to transfer + * TEST_NUM - number of tests + */ + +#if CONFIG_POST & CFG_POST_SPI + +#define TEST_MIN_LENGTH 1 +#define TEST_MAX_LENGTH MAX_BUFFER +#define TEST_NUM 1 + +static void packet_fill (char * packet, int length) +{ + char c = (char) length; + int i; + + for (i = 0; i < length; i++) + { + packet[i] = c++; + } +} + +static int packet_check (char * packet, int length) +{ + char c = (char) length; + int i; + + for (i = 0; i < length; i++) + { + if (packet[i] != c++) return -1; + } + + return 0; +} + +int spi_post_test (int flags) +{ + DECLARE_GLOBAL_DATA_PTR; + + int res = -1; + volatile immap_t *immr = (immap_t *) CFG_IMMR; + volatile cpm8xx_t *cp = (cpm8xx_t *) &immr->im_cpm; + int i; + int l; + + spi_init_f(); + spi_init_r(); + + cp->cp_spmode |= SPMODE_LOOP; + + for (i = 0; i < TEST_NUM; i++) + { + for (l = TEST_MIN_LENGTH; l <= TEST_MAX_LENGTH; l += 8) + { + packet_fill(txbuf, l); + + spi_xfer(l); + + if (packet_check(rxbuf, l) < 0) + { + goto Done; + } + } + } + + res = 0; + + Done: + + cp->cp_spmode &= ~SPMODE_LOOP; + + /* + * SCC2 Ethernet parameter RAM space overlaps + * the SPI parameter RAM space. So we need to restore + * the SCC2 configuration if it is used by UART or Ethernet. + */ + +#if defined(CONFIG_8xx_CONS_SCC2) + serial_init(); +#endif + +#if defined(SCC_ENET) && (SCC_ENET == 1) + eth_init(gd->bd); +#endif + + if (res != 0) + { + post_log("SPI test failed\n"); + } + + return res; +} +#endif /* CONFIG_POST & CFG_POST_SPI */ diff --git a/cpu/ppc4xx/405gp_enet.c b/cpu/ppc4xx/405gp_enet.c new file mode 100644 index 0000000..49e9e42 --- /dev/null +++ b/cpu/ppc4xx/405gp_enet.c @@ -0,0 +1,867 @@ +/*-----------------------------------------------------------------------------+ + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-----------------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------------+ + * + * File Name: enetemac.c + * + * Function: Device driver for the ethernet EMAC3 macro on the 405GP. + * + * Author: Mark Wisner + * + * Change Activity- + * + * Date Description of Change BY + * --------- --------------------- --- + * 05-May-99 Created MKW + * 27-Jun-99 Clean up JWB + * 16-Jul-99 Added MAL error recovery and better IP packet handling MKW + * 29-Jul-99 Added Full duplex support MKW + * 06-Aug-99 Changed names for Mal CR reg MKW + * 23-Aug-99 Turned off SYE when running at 10Mbs MKW + * 24-Aug-99 Marked descriptor empty after call_xlc MKW + * 07-Sep-99 Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16 MCG + * to avoid chaining maximum sized packets. Push starting + * RX descriptor address up to the next cache line boundary. + * 16-Jan-00 Added support for booting with IP of 0x0 MKW + * 15-Mar-00 Updated enetInit() to enable broadcast addresses in the + * EMAC_RXM register. JWB + * 12-Mar-01 anne-sophie.harnois@nextream.fr + * - Variables are compatible with those already defined in + * include/net.h + * - Receive buffer descriptor ring is used to send buffers + * to the user + * - Info print about send/received/handled packet number if + * INFO_405_ENET is set + * 17-Apr-01 stefan.roese@esd-electronics.com + * - MAL reset in "eth_halt" included + * - Enet speed and duplex output now in one line + * 08-May-01 stefan.roese@esd-electronics.com + * - MAL error handling added (eth_init called again) + * 13-Nov-01 stefan.roese@esd-electronics.com + * - Set IST bit in EMAC_M1 reg upon 100MBit or full duplex + * 04-Jan-02 stefan.roese@esd-electronics.com + * - Wait for PHY auto negotiation to complete added + * 06-Feb-02 stefan.roese@esd-electronics.com + * - Bug fixed in waiting for auto negotiation to complete + * 26-Feb-02 stefan.roese@esd-electronics.com + * - rx and tx buffer descriptors now allocated (no fixed address + * used anymore) + * 17-Jun-02 stefan.roese@esd-electronics.com + * - MAL error debug printf 'M' removed (rx de interrupt may + * occur upon many incoming packets with only 4 rx buffers). + *-----------------------------------------------------------------------------*/ + +#include <common.h> +#include <asm/processor.h> +#include <ppc4xx.h> +#include <commproc.h> +#include <405gp_enet.h> +#include <405_mal.h> +#include <miiphy.h> +#include <net.h> +#include <malloc.h> +#include "vecnum.h" + +#if defined(CONFIG_405GP) || defined(CONFIG_440) + +#define EMAC_RESET_TIMEOUT 1000 /* 1000 ms reset timeout */ +#define PHY_AUTONEGOTIATE_TIMEOUT 2000 /* 2000 ms autonegotiate timeout */ + +#define NUM_TX_BUFF 1 +/* AS.HARNOIS + * Use PKTBUFSRX (include/net.h) instead of setting NUM_RX_BUFF again + * These both variables are used to define the same thing! + * #define NUM_RX_BUFF 4 + */ +#define NUM_RX_BUFF PKTBUFSRX + +/* Ethernet Transmit and Receive Buffers */ +/* AS.HARNOIS + * In the same way ENET_MAX_MTU and ENET_MAX_MTU_ALIGNED are set from + * PKTSIZE and PKTSIZE_ALIGN (include/net.h) + */ +#define ENET_MAX_MTU PKTSIZE +#define ENET_MAX_MTU_ALIGNED PKTSIZE_ALIGN + +static char *txbuf_ptr; + +/* define the number of channels implemented */ +#define EMAC_RXCHL 1 +#define EMAC_TXCHL 1 + +/*-----------------------------------------------------------------------------+ + * Defines for MAL/EMAC interrupt conditions as reported in the UIC (Universal + * Interrupt Controller). + *-----------------------------------------------------------------------------*/ +#define MAL_UIC_ERR ( UIC_MAL_SERR | UIC_MAL_TXDE | UIC_MAL_RXDE) +#define MAL_UIC_DEF (UIC_MAL_RXEOB | MAL_UIC_ERR) +#define EMAC_UIC_DEF UIC_ENET + +/*-----------------------------------------------------------------------------+ + * Global variables. TX and RX descriptors and buffers. + *-----------------------------------------------------------------------------*/ +static volatile mal_desc_t *tx; +static volatile mal_desc_t *rx; +static mal_desc_t *alloc_tx_buf = NULL; +static mal_desc_t *alloc_rx_buf = NULL; + +/* IER globals */ +static unsigned long emac_ier; +static unsigned long mal_ier; + + +/* Statistic Areas */ +#define MAX_ERR_LOG 10 +struct emac_stats { + int data_len_err; + int rx_frames; + int rx; + int rx_prot_err; +}; + +static struct stats { /* Statistic Block */ + struct emac_stats emac; + int int_err; + short tx_err_log[MAX_ERR_LOG]; + short rx_err_log[MAX_ERR_LOG]; +} stats; + +static int first_init = 0; + +static int tx_err_index = 0; /* Transmit Error Index for tx_err_log */ +static int rx_err_index = 0; /* Receive Error Index for rx_err_log */ + +static int rx_slot = 0; /* MAL Receive Slot */ +static int rx_i_index = 0; /* Receive Interrupt Queue Index */ +static int rx_u_index = 0; /* Receive User Queue Index */ +static int rx_ready[NUM_RX_BUFF]; /* Receive Ready Queue */ + +static int tx_slot = 0; /* MAL Transmit Slot */ +static int tx_i_index = 0; /* Transmit Interrupt Queue Index */ +static int tx_u_index = 0; /* Transmit User Queue Index */ +static int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */ + +#undef INFO_405_ENET 1 +#ifdef INFO_405_ENET +static int packetSent = 0; +static int packetReceived = 0; +static int packetHandled = 0; +#endif + +static char emac_hwd_addr[ENET_ADDR_LENGTH]; + +static bd_t *bis_save = NULL; /* for eth_init upon mal error */ + +static int is_receiving = 0; /* sync with eth interrupt */ +static int print_speed = 1; /* print speed message upon start */ + +static void enet_rcv (unsigned long malisr); + +/*-----------------------------------------------------------------------------+ + * Prototypes and externals. + *-----------------------------------------------------------------------------*/ +void mal_err (unsigned long isr, unsigned long uic, unsigned long mal_def, + unsigned long mal_errr); +void emac_err (unsigned long isr); + + +void eth_halt (void) +{ + mtdcr (malier, 0x00000000); /* disable mal interrupts */ + out32 (EMAC_IER, 0x00000000); /* disable emac interrupts */ + + /* 1st reset MAL */ + mtdcr (malmcr, MAL_CR_MMSR); + + /* wait for reset */ + while (mfdcr (malmcr) & MAL_CR_MMSR) { + }; + + /* EMAC RESET */ + out32 (EMAC_M0, EMAC_M0_SRST); + + print_speed = 1; /* print speed message again next time */ +} + + +int eth_init (bd_t * bis) +{ + int i; + unsigned long reg; + unsigned long msr; + unsigned long speed; + unsigned long duplex; + unsigned mode_reg; + unsigned short reg_short; + + msr = mfmsr (); + mtmsr (msr & ~(MSR_EE)); /* disable interrupts */ + +#ifdef INFO_405_ENET + /* AS.HARNOIS + * We should have : + * packetHandled <= packetReceived <= packetHandled+PKTBUFSRX + * In the most cases packetHandled = packetReceived, but it + * is possible that new packets (without relationship with + * current transfer) have got the time to arrived before + * netloop calls eth_halt + */ + printf ("About preceeding transfer:\n" + "- Sent packet number %d\n" + "- Received packet number %d\n" + "- Handled packet number %d\n", + packetSent, packetReceived, packetHandled); + packetSent = 0; + packetReceived = 0; + packetHandled = 0; +#endif + + /* MAL RESET */ + mtdcr (malmcr, MAL_CR_MMSR); + /* wait for reset */ + while (mfdcr (malmcr) & MAL_CR_MMSR) { + }; + + tx_err_index = 0; /* Transmit Error Index for tx_err_log */ + rx_err_index = 0; /* Receive Error Index for rx_err_log */ + + rx_slot = 0; /* MAL Receive Slot */ + rx_i_index = 0; /* Receive Interrupt Queue Index */ + rx_u_index = 0; /* Receive User Queue Index */ + + tx_slot = 0; /* MAL Transmit Slot */ + tx_i_index = 0; /* Transmit Interrupt Queue Index */ + tx_u_index = 0; /* Transmit User Queue Index */ + +#if defined(CONFIG_440) + /* set RMII mode */ + out32 (ZMII_FER, ZMII_RMII | ZMII_MDI0); +#endif /* CONFIG_440 */ + + /* EMAC RESET */ + out32 (EMAC_M0, EMAC_M0_SRST); + + /* wait for PHY to complete auto negotiation */ + reg_short = 0; +#ifndef CONFIG_CS8952_PHY + miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, ®_short); + + /* + * Wait if PHY is able of autonegotiation and autonegotiation is not complete + */ + if ((reg_short & PHY_BMSR_AUTN_ABLE) + && !(reg_short & PHY_BMSR_AUTN_COMP)) { + puts ("Waiting for PHY auto negotiation to complete"); + i = 0; + while (!(reg_short & PHY_BMSR_AUTN_COMP)) { + if ((i++ % 100) == 0) + putc ('.'); + udelay (10000); /* 10 ms */ + miiphy_read (CONFIG_PHY_ADDR, PHY_BMSR, ®_short); + + /* + * Timeout reached ? + */ + if (i * 10 > PHY_AUTONEGOTIATE_TIMEOUT) { + puts (" TIMEOUT !\n"); + break; + } + } + puts (" done\n"); + udelay (500000); /* another 500 ms (results in faster booting) */ + } +#endif + speed = miiphy_speed (CONFIG_PHY_ADDR); + duplex = miiphy_duplex (CONFIG_PHY_ADDR); + if (print_speed) { + print_speed = 0; + printf ("ENET Speed is %d Mbps - %s duplex connection\n", + (int) speed, (duplex == HALF) ? "HALF" : "FULL"); + } + + /* 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); + if (alloc_rx_buf) free(alloc_rx_buf); + + /* + * Malloc MAL buffer desciptors, make sure they are + * aligned on cache line boundary size + * (401/403/IOP480 = 16, 405 = 32) + * and doesn't cross cache block boundaries. + */ + alloc_tx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_TX_BUFF) + + ((2 * CFG_CACHELINE_SIZE) - 2)); + if (((int)alloc_tx_buf & CACHELINE_MASK) != 0) { + tx = (mal_desc_t *)((int)alloc_tx_buf + CFG_CACHELINE_SIZE - + ((int)alloc_tx_buf & CACHELINE_MASK)); + } else { + tx = alloc_tx_buf; + } + + alloc_rx_buf = (mal_desc_t *)malloc((sizeof(mal_desc_t) * NUM_RX_BUFF) + + ((2 * CFG_CACHELINE_SIZE) - 2)); + if (((int)alloc_rx_buf & CACHELINE_MASK) != 0) { + rx = (mal_desc_t *)((int)alloc_rx_buf + CFG_CACHELINE_SIZE - + ((int)alloc_rx_buf & CACHELINE_MASK)); + } else { + rx = alloc_rx_buf; + } + + for (i = 0; i < NUM_TX_BUFF; i++) { + tx[i].ctrl = 0; + tx[i].data_len = 0; + if (first_init == 0) + txbuf_ptr = (char *) malloc (ENET_MAX_MTU_ALIGNED); + tx[i].data_ptr = txbuf_ptr; + if ((NUM_TX_BUFF - 1) == i) + tx[i].ctrl |= MAL_TX_CTRL_WRAP; + tx_run[i] = -1; +#if 0 + printf ("TX_BUFF %d @ 0x%08lx\n", i, (ulong) tx[i].data_ptr); +#endif + } + + for (i = 0; i < NUM_RX_BUFF; i++) { + rx[i].ctrl = 0; + rx[i].data_len = 0; + /* rx[i].data_ptr = (char *) &rx_buff[i]; */ + rx[i].data_ptr = (char *) NetRxPackets[i]; + if ((NUM_RX_BUFF - 1) == i) + rx[i].ctrl |= MAL_RX_CTRL_WRAP; + rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR; + rx_ready[i] = -1; +#if 0 + printf ("RX_BUFF %d @ 0x%08lx\n", i, (ulong) rx[i].data_ptr); +#endif + } + + memcpy (emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH); + + reg = 0x00000000; + + reg |= emac_hwd_addr[0]; /* set high address */ + reg = reg << 8; + reg |= emac_hwd_addr[1]; + + out32 (EMAC_IAH, reg); + + reg = 0x00000000; + reg |= emac_hwd_addr[2]; /* set low address */ + reg = reg << 8; + reg |= emac_hwd_addr[3]; + reg = reg << 8; + reg |= emac_hwd_addr[4]; + reg = reg << 8; + reg |= emac_hwd_addr[5]; + + out32 (EMAC_IAL, reg); + + /* setup MAL tx & rx channel pointers */ + mtdcr (maltxctp0r, tx); + mtdcr (malrxctp0r, rx); + + /* Reset transmit and receive channels */ + mtdcr (malrxcarr, 0x80000000); /* 2 channels */ + mtdcr (maltxcarr, 0x80000000); /* 2 channels */ + + /* Enable MAL transmit and receive channels */ + mtdcr (maltxcasr, 0x80000000); /* 1 channel */ + mtdcr (malrxcasr, 0x80000000); /* 1 channel */ + + /* set RX buffer size */ + mtdcr (malrcbs0, ENET_MAX_MTU_ALIGNED / 16); + + /* set transmit enable & receive enable */ + out32 (EMAC_M0, EMAC_M0_TXE | EMAC_M0_RXE); + + /* set receive fifo to 4k and tx fifo to 2k */ + mode_reg = EMAC_M1_RFS_4K | EMAC_M1_TX_FIFO_2K; + + /* set speed */ + if (speed == _100BASET) + mode_reg = mode_reg | EMAC_M1_MF_100MBPS | EMAC_M1_IST; + else + mode_reg = mode_reg & ~0x00C00000; /* 10 MBPS */ + if (duplex == FULL) + mode_reg = mode_reg | 0x80000000 | EMAC_M1_IST; + + out32 (EMAC_M1, mode_reg); + + /* Enable broadcast and indvidual address */ + out32 (EMAC_RXM, EMAC_RMR_BAE | EMAC_RMR_IAE + /*| EMAC_RMR_ARRP| EMAC_RMR_SFCS | EMAC_RMR_SP */ ); + + /* we probably need to set the tx mode1 reg? maybe at tx time */ + + /* set transmit request threshold register */ + out32 (EMAC_TRTR, 0x18000000); /* 256 byte threshold */ + + /* set receive low/high water mark register */ +#if defined(CONFIG_440) + /* 440GP has a 64 byte burst length */ + out32 (EMAC_RX_HI_LO_WMARK, 0x80009000); + out32 (EMAC_TXM1, 0xf8640000); +#else /* CONFIG_440 */ + /* 405s have a 16 byte burst length */ + out32 (EMAC_RX_HI_LO_WMARK, 0x0f002000); +#endif /* CONFIG_440 */ + + /* Frame gap set */ + out32 (EMAC_I_FRAME_GAP_REG, 0x00000008); + + if (first_init == 0) { + /* + * Connect interrupt service routines + */ + irq_install_handler (VECNUM_EWU0, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_MS, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_MTE, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_MRE, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_TXDE, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_RXDE, (interrupt_handler_t *) enetInt, NULL); + irq_install_handler (VECNUM_ETH0, (interrupt_handler_t *) enetInt, NULL); + } + + /* set up interrupt handler */ + /* setup interrupt controler to take interrupts from the MAL & + EMAC */ + mtdcr (uicsr, 0xffffffff); /* clear pending interrupts */ + mtdcr (uicer, mfdcr (uicer) | MAL_UIC_DEF | EMAC_UIC_DEF); + + /* set the MAL IER ??? names may change with new spec ??? */ + mal_ier = MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | MAL_IER_OPBE | + MAL_IER_PLBE; + mtdcr (malesr, 0xffffffff); /* clear pending interrupts */ + mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */ + mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */ + mtdcr (malier, mal_ier); + + /* Set EMAC IER */ + emac_ier = EMAC_ISR_PTLE | EMAC_ISR_BFCS | + EMAC_ISR_PTLE | EMAC_ISR_ORE | EMAC_ISR_IRE; + if (speed == _100BASET) + emac_ier = emac_ier | EMAC_ISR_SYE; + + out32 (EMAC_ISR, 0xffffffff); /* clear pending interrupts */ + out32 (EMAC_IER, emac_ier); + + mtmsr (msr); /* enable interrupts again */ + + bis_save = bis; + first_init = 1; + + return (0); +} + + +int eth_send (volatile void *ptr, int len) +{ + struct enet_frame *ef_ptr; + ulong time_start, time_now; + unsigned long temp_txm0; + + ef_ptr = (struct enet_frame *) ptr; + + /*-----------------------------------------------------------------------+ + * Copy in our address into the frame. + *-----------------------------------------------------------------------*/ + (void) memcpy (ef_ptr->source_addr, emac_hwd_addr, ENET_ADDR_LENGTH); + + /*-----------------------------------------------------------------------+ + * If frame is too long or too short, modify length. + *-----------------------------------------------------------------------*/ + if (len > ENET_MAX_MTU) + len = ENET_MAX_MTU; + + /* memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len); */ + memcpy ((void *) txbuf_ptr, (const void *) ptr, len); + + /*-----------------------------------------------------------------------+ + * set TX Buffer busy, and send it + *-----------------------------------------------------------------------*/ + tx[tx_slot].ctrl = (MAL_TX_CTRL_LAST | + EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) & + ~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA); + if ((NUM_TX_BUFF - 1) == tx_slot) + tx[tx_slot].ctrl |= MAL_TX_CTRL_WRAP; + + tx[tx_slot].data_len = (short) len; + tx[tx_slot].ctrl |= MAL_TX_CTRL_READY; + + __asm__ volatile ("eieio"); + out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0); +#ifdef INFO_405_ENET + packetSent++; +#endif + + /*-----------------------------------------------------------------------+ + * poll unitl the packet is sent and then make sure it is OK + *-----------------------------------------------------------------------*/ + time_start = get_timer (0); + while (1) { + temp_txm0 = in32 (EMAC_TXM0); + /* loop until either TINT turns on or 3 seconds elapse */ + if ((temp_txm0 & EMAC_TXM0_GNP0) != 0) { + /* transmit is done, so now check for errors + * If there is an error, an interrupt should + * happen when we return + */ + time_now = get_timer (0); + if ((time_now - time_start) > 3000) { + return (-1); + } + } else { + return (0); + } + } +} + + +#if defined(CONFIG_440) +/*-----------------------------------------------------------------------------+ +| EnetInt. +| EnetInt is the interrupt handler. It will determine the +| cause of the interrupt and call the apporpriate servive +| routine. ++-----------------------------------------------------------------------------*/ +int enetInt () +{ + int serviced; + int rc = -1; /* default to not us */ + unsigned long mal_isr; + unsigned long emac_isr = 0; + unsigned long mal_rx_eob; + unsigned long my_uic0msr, my_uic1msr; + + /* enter loop that stays in interrupt code until nothing to service */ + do { + serviced = 0; + + my_uic0msr = mfdcr (uic0msr); + my_uic1msr = mfdcr (uic1msr); + + if (!(my_uic0msr & UIC_MRE) + && !(my_uic1msr & (UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE))) { + /* not for us */ + return (rc); + } + + /* get and clear controller status interrupts */ + /* look at Mal and EMAC interrupts */ + if ((my_uic0msr & UIC_MRE) + || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { + /* we have a MAL interrupt */ + mal_isr = mfdcr (malesr); + /* look for mal error */ + if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) { + mal_err (mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR); + serviced = 1; + rc = 0; + } + } + if (UIC_ETH0 & my_uic1msr) { /* look for EMAC errors */ + emac_isr = in32 (EMAC_ISR); + if ((emac_ier & emac_isr) != 0) { + emac_err (emac_isr); + serviced = 1; + rc = 0; + } + } + if ((emac_ier & emac_isr) + || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { + mtdcr (uic0sr, UIC_MRE); /* Clear */ + mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + return (rc); /* we had errors so get out */ + } + + /* handle MAL RX EOB interupt from a receive */ + /* check for EOB on valid channels */ + if (my_uic0msr & UIC_MRE) { + mal_rx_eob = mfdcr (malrxeobisr); + if ((mal_rx_eob & 0x80000000) != 0) { /* call emac routine for channel 0 */ + /* clear EOB + mtdcr(malrxeobisr, mal_rx_eob); */ + enet_rcv (emac_isr); + /* indicate that we serviced an interrupt */ + serviced = 1; + rc = 0; + } + } + mtdcr (uic0sr, UIC_MRE); /* Clear */ + mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ + } while (serviced); + + return (rc); +} +#else /* CONFIG_440 */ +/*-----------------------------------------------------------------------------+ + * EnetInt. + * EnetInt is the interrupt handler. It will determine the + * cause of the interrupt and call the apporpriate servive + * routine. + *-----------------------------------------------------------------------------*/ +int enetInt () +{ + int serviced; + int rc = -1; /* default to not us */ + unsigned long mal_isr; + unsigned long emac_isr = 0; + unsigned long mal_rx_eob; + unsigned long my_uicmsr; + + /* enter loop that stays in interrupt code until nothing to service */ + do { + serviced = 0; + + my_uicmsr = mfdcr (uicmsr); + if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0) { /* not for us */ + return (rc); + } + + + /* get and clear controller status interrupts */ + /* look at Mal and EMAC interrupts */ + if ((MAL_UIC_DEF & my_uicmsr) != 0) { /* we have a MAL interrupt */ + mal_isr = mfdcr (malesr); + /* look for mal error */ + if ((my_uicmsr & MAL_UIC_ERR) != 0) { + mal_err (mal_isr, my_uicmsr, MAL_UIC_DEF, MAL_UIC_ERR); + serviced = 1; + rc = 0; + } + } + if ((EMAC_UIC_DEF & my_uicmsr) != 0) { /* look for EMAC errors */ + emac_isr = in32 (EMAC_ISR); + if ((emac_ier & emac_isr) != 0) { + emac_err (emac_isr); + serviced = 1; + rc = 0; + } + } + if (((emac_ier & emac_isr) != 0) | ((MAL_UIC_ERR & my_uicmsr) != 0)) { + mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */ + return (rc); /* we had errors so get out */ + } + + + /* handle MAL RX EOB interupt from a receive */ + /* check for EOB on valid channels */ + if ((my_uicmsr & UIC_MAL_RXEOB) != 0) { + mal_rx_eob = mfdcr (malrxeobisr); + if ((mal_rx_eob & 0x80000000) != 0) { /* call emac routine for channel 0 */ + /* clear EOB + mtdcr(malrxeobisr, mal_rx_eob); */ + enet_rcv (emac_isr); + /* indicate that we serviced an interrupt */ + serviced = 1; + rc = 0; + } + } + mtdcr (uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */ + } + while (serviced); + + return (rc); +} +#endif /* CONFIG_440 */ + +/*-----------------------------------------------------------------------------+ + * MAL Error Routine + *-----------------------------------------------------------------------------*/ +void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef, + unsigned long mal_errr) +{ + mtdcr (malesr, isr); /* clear interrupt */ + + /* clear DE interrupt */ + mtdcr (maltxdeir, 0xC0000000); + mtdcr (malrxdeir, 0x80000000); + +#if 1 /*sr */ + printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", + isr, uic, maldef, mal_errr); +#else +#if 0 + /* + * MAL error is RX DE error (out of rx buffers)! This is OK here, upon + * many incoming packets with only 4 rx buffers. + */ + printf ("M"); /* just to see something upon mal error */ +#endif +#endif /*sr */ + + eth_init (bis_save); /* start again... */ +} + +/*-----------------------------------------------------------------------------+ + * EMAC Error Routine + *-----------------------------------------------------------------------------*/ +void emac_err (unsigned long isr) +{ + printf ("EMAC error occured.... ISR = %lx\n", isr); + out32 (EMAC_ISR, isr); +} + +/*-----------------------------------------------------------------------------+ + * enet_rcv() handles the ethernet receive data + *-----------------------------------------------------------------------------*/ +static void enet_rcv (unsigned long malisr) +{ + struct enet_frame *ef_ptr; + unsigned long data_len; + unsigned long rx_eob_isr; + + int handled = 0; + int i; + int loop_count = 0; + + rx_eob_isr = mfdcr (malrxeobisr); + if ((0x80000000 >> (EMAC_RXCHL - 1)) & rx_eob_isr) { + /* clear EOB */ + mtdcr (malrxeobisr, rx_eob_isr); + + /* EMAC RX done */ + while (1) { /* do all */ + i = rx_slot; + + if ((MAL_RX_CTRL_EMPTY & rx[i].ctrl) + || (loop_count >= NUM_RX_BUFF)) + break; + loop_count++; + rx_slot++; + if (NUM_RX_BUFF == rx_slot) + rx_slot = 0; + handled++; + data_len = (unsigned long) rx[i].data_len; /* Get len */ + if (data_len) { + if (data_len > ENET_MAX_MTU) /* Check len */ + data_len = 0; + else { + if (EMAC_RX_ERRORS & rx[i].ctrl) { /* Check Errors */ + data_len = 0; + stats.rx_err_log[rx_err_index] = rx[i].ctrl; + rx_err_index++; + if (rx_err_index == MAX_ERR_LOG) + rx_err_index = 0; + } /* emac_erros */ + } /* data_len < max mtu */ + } /* if data_len */ + if (!data_len) { /* no data */ + rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */ + + stats.emac.data_len_err++; /* Error at Rx */ + } + + /* !data_len */ + /* AS.HARNOIS */ + /* Check if user has already eaten buffer */ + /* if not => ERROR */ + else if (rx_ready[rx_i_index] != -1) { + if (is_receiving) + printf ("ERROR : Receive buffers are full!\n"); + break; + } else { + stats.emac.rx_frames++; + stats.emac.rx += data_len; + ef_ptr = (struct enet_frame *) rx[i].data_ptr; +#ifdef INFO_405_ENET + packetReceived++; +#endif + /* AS.HARNOIS + * use ring buffer + */ + rx_ready[rx_i_index] = i; + rx_i_index++; + if (NUM_RX_BUFF == rx_i_index) + rx_i_index = 0; + + /* printf("X"); /|* test-only *|/ */ + + /* AS.HARNOIS + * free receive buffer only when + * buffer has been handled (eth_rx) + rx[i].ctrl |= MAL_RX_CTRL_EMPTY; + */ + } /* if data_len */ + } /* while */ + } /* if EMACK_RXCHL */ +} + + +int eth_rx (void) +{ + int length; + int user_index; + unsigned long msr; + + is_receiving = 1; /* tell driver */ + + for (;;) { + /* AS.HARNOIS + * use ring buffer and + * get index from rx buffer desciptor queue + */ + user_index = rx_ready[rx_u_index]; + if (user_index == -1) { + length = -1; + break; /* nothing received - leave for() loop */ + } + + msr = mfmsr (); + mtmsr (msr & ~(MSR_EE)); + + length = rx[user_index].data_len; + + /* Pass the packet up to the protocol layers. */ + /* NetReceive(NetRxPackets[rxIdx], length - 4); */ + /* NetReceive(NetRxPackets[i], length); */ + NetReceive (NetRxPackets[user_index], length - 4); + /* Free Recv Buffer */ + rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY; + /* Free rx buffer descriptor queue */ + rx_ready[rx_u_index] = -1; + rx_u_index++; + if (NUM_RX_BUFF == rx_u_index) + rx_u_index = 0; + +#ifdef INFO_405_ENET + packetHandled++; +#endif + + mtmsr (msr); /* Enable IRQ's */ + } + + is_receiving = 0; /* tell driver */ + + return length; +} + +#endif /* CONFIG_405GP */ diff --git a/cpu/ppc4xx/405gp_pci.c b/cpu/ppc4xx/405gp_pci.c new file mode 100644 index 0000000..1c2c59b --- /dev/null +++ b/cpu/ppc4xx/405gp_pci.c @@ -0,0 +1,502 @@ +/*-----------------------------------------------------------------------------+ + * + * This source code has been made available to you by IBM on an AS-IS + * basis. Anyone receiving this source is licensed under IBM + * copyrights to use it in any way he or she deems fit, including + * copying it, modifying it, compiling it, and redistributing it either + * with or without modifications. No license under IBM patents or + * patent applications is to be implied by the copyright license. + * + * Any user of this software should understand that IBM cannot provide + * technical support for this software and will not be responsible for + * any consequences resulting from the use of this software. + * + * Any person who transfers this source code or any derivative work + * must include the IBM copyright notice, this paragraph, and the + * preceding two paragraphs in the transferred software. + * + * COPYRIGHT I B M CORPORATION 1995 + * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M + *-----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------+ + * + * File Name: 405gp_pci.c + * + * Function: Initialization code for the 405GP PCI Configuration regs. + * + * Author: Mark Game + * + * Change Activity- + * + * Date Description of Change BY + * --------- --------------------- --- + * 09-Sep-98 Created MCG + * 02-Nov-98 Removed External arbiter selected message JWB + * 27-Nov-98 Zero out PTMBAR2 and disable in PTM2MS JWB + * 04-Jan-99 Zero out other unused PMM and PTM regs. Change bus scan MCG + * from (0 to n) to (1 to n). + * 17-May-99 Port to Walnut JWB + * 17-Jun-99 Updated for VGA support JWB + * 21-Jun-99 Updated to allow SRAM region to be a target from PCI bus JWB + * 19-Jul-99 Updated for 405GP pass 1 errata #26 (Low PCI subsequent MCG + * target latency timer values are not supported). + * Should be fixed in pass 2. + * 09-Sep-99 Removed use of PTM2 since the SRAM region no longer needs JWB + * to be a PCI target. Zero out PTMBAR2 and disable in PTM2MS. + * 10-Dec-99 Updated PCI_Write_CFG_Reg for pass2 errata #6 JWB + * 11-Jan-00 Ensure PMMxMAs disabled before setting PMMxLAs. This is not + * really required after a reset since PMMxMAs are already + * disabled but is a good practice nonetheless. JWB + * 12-Jun-01 stefan.roese@esd-electronics.com + * - PCI host/adapter handling reworked + * 09-Jul-01 stefan.roese@esd-electronics.com + * - PCI host now configures from device 0 (not 1) to max_dev, + * (host configures itself) + * - On CPCI-405 pci base address and size is generated from + * SDRAM and FLASH size (CFG regs not used anymore) + * - Some minor changes for CPCI-405-A (adapter version) + * 14-Sep-01 stefan.roese@esd-electronics.com + * - CONFIG_PCI_SCAN_SHOW added to print pci devices upon startup + * 28-Sep-01 stefan.roese@esd-electronics.com + * - Changed pci master configuration for linux compatibility + * (no need for bios_fixup() anymore) + * 26-Feb-02 stefan.roese@esd-electronics.com + * - Bug fixed in pci configuration (Andrew May) + * - Removed pci class code init for CPCI405 board + * 15-May-02 stefan.roese@esd-electronics.com + * - New vga device handling + * 29-May-02 stefan.roese@esd-electronics.com + * - PCI class code init added (if defined) + *----------------------------------------------------------------------------*/ + +#include <common.h> +#include <command.h> +#include <cmd_boot.h> +#if !defined(CONFIG_440) +#include <405gp_pci.h> +#endif +#include <asm/processor.h> +#include <pci.h> + +#if defined(CONFIG_405GP) + +#ifdef CONFIG_PCI + +/*#define DEBUG*/ + +/*-----------------------------------------------------------------------------+ + * pci_init. Initializes the 405GP PCI Configuration regs. + *-----------------------------------------------------------------------------*/ +void pci_405gp_init(struct pci_controller *hose) +{ + DECLARE_GLOBAL_DATA_PTR; + + int i, reg_num = 0; + bd_t *bd = gd->bd; + + unsigned short temp_short; + unsigned long ptmpcila[2] = {CFG_PCI_PTM1PCI, CFG_PCI_PTM2PCI}; +#if defined(CONFIG_CPCI405) + unsigned long ptmla[2] = {bd->bi_memstart, bd->bi_flashstart}; + unsigned long ptmms[2] = {~(bd->bi_memsize - 1) | 1, ~(bd->bi_flashsize - 1) | 1}; +#else + unsigned long ptmla[2] = {CFG_PCI_PTM1LA, CFG_PCI_PTM2LA}; + unsigned long ptmms[2] = {CFG_PCI_PTM1MS, CFG_PCI_PTM2MS}; +#endif +#if defined(CONFIG_PIP405) || defined (CONFIG_MIP405) + unsigned long pmmla[3] = {0x80000000, 0xA0000000, 0}; + unsigned long pmmma[3] = {0xE0000001, 0xE0000001, 0}; + unsigned long pmmpcila[3] = {0x80000000, 0x00000000, 0}; + unsigned long pmmpciha[3] = {0x00000000, 0x00000000, 0}; +#else + unsigned long pmmla[3] = {0x80000000, 0,0}; + unsigned long pmmma[3] = {0xC0000001, 0,0}; + unsigned long pmmpcila[3] = {0x80000000, 0,0}; + unsigned long pmmpciha[3] = {0x00000000, 0,0}; +#endif + + /* + * Register the hose + */ + hose->first_busno = 0; + hose->last_busno = 0xff; + + /* ISA/PCI I/O space */ + pci_set_region(hose->regions + reg_num++, + MIN_PCI_PCI_IOADDR, + MIN_PLB_PCI_IOADDR, + 0x10000, + PCI_REGION_IO); + + /* PCI I/O space */ + pci_set_region(hose->regions + reg_num++, + 0x00800000, + 0xe8800000, + 0x03800000, + PCI_REGION_IO); + + reg_num = 2; + + /* Memory spaces */ + for (i=0; i<2; i++) + if (ptmms[i] & 1) + { + if (!i) hose->pci_fb = hose->regions + reg_num; + + pci_set_region(hose->regions + reg_num++, + ptmpcila[i], ptmla[i], + ~(ptmms[i] & 0xfffff000) + 1, + PCI_REGION_MEM | + PCI_REGION_MEMORY); + } + + /* PCI memory spaces */ + for (i=0; i<3; i++) + if (pmmma[i] & 1) + { + pci_set_region(hose->regions + reg_num++, + pmmpcila[i], pmmla[i], + ~(pmmma[i] & 0xfffff000) + 1, + PCI_REGION_MEM); + } + + hose->region_count = reg_num; + + pci_setup_indirect(hose, + PCICFGADR, + PCICFGDATA); + + if (hose->pci_fb) + pciauto_region_init(hose->pci_fb); + + pci_register_hose(hose); + + /*--------------------------------------------------------------------------+ + * 405GP PCI Master configuration. + * Map one 512 MB range of PLB/processor addresses to PCI memory space. + * PLB address 0x80000000-0xBFFFFFFF ==> PCI address 0x80000000-0xBFFFFFFF + * Use byte reversed out routines to handle endianess. + *--------------------------------------------------------------------------*/ + out32r(PMM0MA, pmmma[0]); /* ensure disabled b4 setting PMM0LA */ + out32r(PMM0LA, pmmla[0]); + out32r(PMM0PCILA, pmmpcila[0]); + out32r(PMM0PCIHA, pmmpciha[0]); + out32r(PMM0MA, pmmma[0]); + + /*--------------------------------------------------------------------------+ + * PMM1 is not used. Initialize them to zero. + *--------------------------------------------------------------------------*/ + out32r(PMM1MA, pmmma[1]); /* ensure disabled b4 setting PMM2LA */ + out32r(PMM1LA, pmmla[1]); + out32r(PMM1PCILA, pmmpcila[1]); + out32r(PMM1PCIHA, pmmpciha[1]); + out32r(PMM1MA, pmmma[1]); + + /*--------------------------------------------------------------------------+ + * PMM2 is not used. Initialize them to zero. + *--------------------------------------------------------------------------*/ + out32r(PMM2MA, pmmma[2]); /* ensure disabled b4 setting PMM2LA */ + out32r(PMM2LA, pmmla[2]); + out32r(PMM2PCILA, pmmpcila[2]); + out32r(PMM2PCIHA, pmmpciha[2]); + out32r(PMM2MA, pmmma[2]); + + /*--------------------------------------------------------------------------+ + * 405GP PCI Target configuration. (PTM1) + * Note: PTM1MS is hardwire enabled but we set the enable bit anyway. + *--------------------------------------------------------------------------*/ + out32r(PTM1LA, ptmla[0]); /* insert address */ + out32r(PTM1MS, ptmms[0]); /* insert size, enable bit is 1 */ + + /*--------------------------------------------------------------------------+ + * 405GP PCI Target configuration. (PTM2) + *--------------------------------------------------------------------------*/ + out32r(PTM2LA, ptmla[1]); /* insert address */ + if (ptmms[1] == 0) + { + out32r(PTM2MS, 0x00000001); /* set enable bit */ + pci_write_config_dword(PCIDEVID_405GP, PCI_BASE_ADDRESS_2, 0x00000000); + out32r(PTM2MS, 0x00000000); /* disable */ + } + else + { + out32r(PTM2MS, ptmms[1]); /* insert size, enable bit is 1 */ + } + + /* + * Insert Subsystem Vendor and Device ID + */ + pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_VENDOR_ID, CFG_PCI_SUBSYS_VENDORID); +#ifdef CONFIG_CPCI405 + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) + pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID); + else + pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID2); +#else + pci_write_config_word(PCIDEVID_405GP, PCI_SUBSYSTEM_ID, CFG_PCI_SUBSYS_DEVICEID); +#endif + + /* + * Insert Class-code + */ +#ifdef CFG_PCI_CLASSCODE + pci_write_config_word(PCIDEVID_405GP, PCI_CLASS_SUB_CODE, CFG_PCI_CLASSCODE); +#endif /* CFG_PCI_CLASSCODE */ + + /*--------------------------------------------------------------------------+ + * If PCI speed = 66Mhz, set 66Mhz capable bit. + *--------------------------------------------------------------------------*/ + if (bd->bi_pci_busfreq >= 66000000) { + pci_read_config_word(PCIDEVID_405GP, PCI_STATUS, &temp_short); + pci_write_config_word(PCIDEVID_405GP,PCI_STATUS,(temp_short|PCI_STATUS_66MHZ)); + } + +#if (CONFIG_PCI_HOST != PCI_HOST_ADAPTER) +#if (CONFIG_PCI_HOSE == PCI_HOST_AUTO) + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) +#endif + { + /*--------------------------------------------------------------------------+ + * Write the 405GP PCI Configuration regs. + * Enable 405GP to be a master on the PCI bus (PMM). + * Enable 405GP to act as a PCI memory target (PTM). + *--------------------------------------------------------------------------*/ + pci_read_config_word(PCIDEVID_405GP, PCI_COMMAND, &temp_short); + pci_write_config_word(PCIDEVID_405GP, PCI_COMMAND, temp_short | + PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + } +#endif + + /* + * Set HCE bit (Host Configuration Enabled) + */ + pci_read_config_word(PCIDEVID_405GP, PCIBRDGOPT2, &temp_short); + pci_write_config_word(PCIDEVID_405GP, PCIBRDGOPT2, (temp_short | 0x0001)); + +#ifdef CONFIG_PCI_PNP + /*--------------------------------------------------------------------------+ + * Scan the PCI bus and configure devices found. + *--------------------------------------------------------------------------*/ +#if (CONFIG_PCI_HOST == PCI_HOST_AUTO) + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) +#endif + { +#ifdef CONFIG_PCI_SCAN_SHOW + printf("PCI: Bus Dev VenId DevId Class Int\n"); +#endif + + hose->last_busno = pci_hose_scan(hose); + } +#endif /* CONFIG_PCI_PNP */ + +} + +/* + * drivers/pci.c skips every host bridge but the 405GP since it could + * be set as an Adapter. + * + * I (Andrew May) don't know what we should do here, but I don't want + * the auto setup of a PCI device disabling what is done pci_405gp_init + * as has happened before. + */ +void pci_405gp_setup_bridge(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry) +{ +#ifdef DEBUG + printf("405gp_setup_bridge\n"); +#endif +} + +/* + * + */ + +void pci_405gp_fixup_irq(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned char int_line = 0xff; + + /* + * Write pci interrupt line register (cpci405 specific) + */ + switch (PCI_DEV(dev) & 0x03) + { + case 0: + int_line = 27 + 2; + break; + case 1: + int_line = 27 + 3; + break; + case 2: + int_line = 27 + 0; + break; + case 3: + int_line = 27 + 1; + break; + } + + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, int_line); +} + +void pci_405gp_setup_vga(struct pci_controller *hose, pci_dev_t dev, + struct pci_config_table *entry) +{ + unsigned int cmdstat = 0; + + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); + + /* always enable io space on vga boards */ + pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); + cmdstat |= PCI_COMMAND_IO; + pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat); +} + +#if !(defined(CONFIG_PIP405) || defined (CONFIG_MIP405)) + +/* + *As is these functs get called out of flash Not a horrible + *thing, but something to keep in mind. (no statics?) + */ +static struct pci_config_table pci_405gp_config_table[] = { +/*if VendID is 0 it terminates the table search (ie Walnut)*/ +#if CFG_PCI_SUBSYS_VENDORID + {CFG_PCI_SUBSYS_VENDORID, PCI_ANY_ID, PCI_CLASS_BRIDGE_HOST, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_bridge}, +#endif + {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga}, + + {PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_NOT_DEFINED_VGA, + PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, pci_405gp_setup_vga}, + + { } +}; + +static struct pci_controller hose = { + fixup_irq: pci_405gp_fixup_irq, + config_table: pci_405gp_config_table, +}; + +void pci_init(void) +{ + /*we want the ptrs to RAM not flash (ie don't use init list)*/ + hose.fixup_irq = pci_405gp_fixup_irq; + hose.config_table = pci_405gp_config_table; + pci_405gp_init(&hose); +} + +#endif + +#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 (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 (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(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(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(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(void) +{ + pci_440_init (&ppc440_hose); +} + +#endif /* CONFIG_440 & CONFIG_PCI */ diff --git a/cpu/ppc4xx/cpu.c b/cpu/ppc4xx/cpu.c new file mode 100644 index 0000000..8aaffb1 --- /dev/null +++ b/cpu/ppc4xx/cpu.c @@ -0,0 +1,253 @@ +/* + * (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 + */ + +/* + * m8xx.c + * + * CPU specific code + * + * written or collected and sometimes rewritten by + * Magnus Damm <damm@bitsmart.com> + * + * minor modifications by + * Wolfgang Denk <wd@denx.de> + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <asm/cache.h> +#include <ppc4xx.h> + + +#if defined(CONFIG_440) +static int do_chip_reset( unsigned long sys0, unsigned long sys1 ); +#endif + +/* ------------------------------------------------------------------------- */ + +int checkcpu (void) +{ +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480) || defined(CONFIG_440) + uint pvr = get_pvr(); +#endif +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_IOP480) + DECLARE_GLOBAL_DATA_PTR; + + ulong clock = gd->cpu_clk; + char buf[32]; +#endif + +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) + PPC405_SYS_INFO sys_info; + + puts ("CPU: "); + + get_sys_info(&sys_info); + +#if CONFIG_405GP + puts("IBM PowerPC 405GP"); + if (pvr == PVR_405GPR_RA) { + putc('r'); + } + puts(" Rev. "); +#endif +#if CONFIG_405CR + puts("IBM PowerPC 405CR Rev. "); +#endif + switch (pvr) { + case PVR_405GP_RB: + putc('B'); + break; + case PVR_405GP_RC: +#if CONFIG_405CR + case PVR_405CR_RC: +#endif + putc('C'); + break; + case PVR_405GP_RD: + putc('D'); + break; +#if CONFIG_405GP + case PVR_405GP_RE: + putc('E'); + break; +#endif + case PVR_405CR_RA: + case PVR_405GPR_RA: + putc('A'); + break; + case PVR_405CR_RB: + putc('B'); + break; + default: + printf("? (PVR=%08x)", pvr); + break; + } + + printf(" at %s MHz (PLB=%lu, OPB=%lu, EBC=%lu MHz)\n", strmhz(buf, clock), + sys_info.freqPLB / 1000000, + sys_info.freqPLB / sys_info.pllOpbDiv / 1000000, + sys_info.freqPLB / sys_info.pllExtBusDiv / 1000000); + +#if CONFIG_405GP + if (mfdcr(strap) & PSR_PCI_ASYNC_EN) + printf(" PCI async ext clock used, "); + else + printf(" PCI sync clock at %lu MHz, ", + sys_info.freqPLB / sys_info.pllPciDiv / 1000000); + if (mfdcr(strap) & PSR_PCI_ARBIT_EN) + printf("internal PCI arbiter enabled\n"); + else + printf("external PCI arbiter enabled\n"); +#endif + + if ((pvr | 0x00000001) == PVR_405GPR_RA) { + printf(" 16 kB I-Cache 16 kB D-Cache"); + } else { + printf(" 16 kB I-Cache 8 kB D-Cache"); + } + + +#endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */ + +#ifdef CONFIG_IOP480 + printf("PLX IOP480 (PVR=%08x)", pvr); + printf(" at %s MHz:", strmhz(buf, clock)); + printf(" %u kB I-Cache", 4); + printf(" %u kB D-Cache", 2); +#endif + +#if defined(CONFIG_440) + puts("IBM PowerPC 440 Rev. "); + switch(pvr) + { + 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'); + break; + default: + printf("UNKNOWN (PVR=%08x)", pvr); + break; + } +#endif + + printf("\n"); + + return 0; +} + + +/* ------------------------------------------------------------------------- */ + +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 + */ +unsigned long get_tbclk (void) +{ +#if defined(CONFIG_440) + + sys_info_t sys_info; + + get_sys_info(&sys_info); + return (sys_info.freqProcessor); + +#elif defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) + + PPC405_SYS_INFO sys_info; + + get_sys_info(&sys_info); + return (sys_info.freqProcessor); + +#elif defined(CONFIG_IOP480) + + return (66000000); + +#else + +# error get_tbclk() not implemented + +#endif + +} + + +#if defined(CONFIG_WATCHDOG) +void +watchdog_reset(void) +{ + int re_enable = disable_interrupts(); + reset_4xx_watchdog(); + if (re_enable) enable_interrupts(); +} + +void +reset_4xx_watchdog(void) +{ + /* + * Clear TSR(WIS) bit + */ + mtspr(tsr, 0x40000000); +} +#endif /* CONFIG_WATCHDOG */ diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c new file mode 100644 index 0000000..68af057 --- /dev/null +++ b/cpu/ppc4xx/i2c.c @@ -0,0 +1,417 @@ +/*****************************************************************************/ +/* I2C Bus interface initialisation and I2C Commands */ +/* for PPC405GP */ +/* Author : AS HARNOIS */ +/* Date : 13.Dec.00 */ +/*****************************************************************************/ + +#include <common.h> +#include <ppc4xx.h> +#if defined(CONFIG_440) +# include <440_i2c.h> +#else +# include <405gp_i2c.h> +#endif +#include <i2c.h> + +#ifdef CONFIG_HARD_I2C + +#define IIC_OK 0 +#define IIC_NOK 1 +#define IIC_NOK_LA 2 /* Lost arbitration */ +#define IIC_NOK_ICT 3 /* Incomplete transfer */ +#define IIC_NOK_XFRA 4 /* Transfer aborted */ +#define IIC_NOK_DATA 5 /* No data in buffer */ +#define IIC_NOK_TOUT 6 /* Transfer timeout */ + +#define IIC_TIMEOUT 1 /* 1 seconde */ + + +static void _i2c_bus_reset (void) +{ + int i, status; + + /* Reset status register */ + /* write 1 in SCMP and IRQA to clear these fields */ + out8 (IIC_STS, 0x0A); + + /* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */ + out8 (IIC_EXTSTS, 0x8F); + __asm__ volatile ("eieio"); + + /* + * Get current state, reset bus + * only if no transfers are pending. + */ + i = 10; + do { + /* Get status */ + status = in8 (IIC_STS); + udelay (500); /* 500us */ + i--; + } while ((status & IIC_STS_PT) && (i > 0)); + /* Soft reset controller */ + status = in8 (IIC_XTCNTLSS); + out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST)); + __asm__ volatile ("eieio"); + + /* make sure where in initial state, data hi, clock hi */ + out8 (IIC_DIRECTCNTL, 0xC); + for (i = 0; i < 10; i++) { + if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) { + /* clock until we get to known state */ + out8 (IIC_DIRECTCNTL, 0x8); /* clock lo */ + udelay (100); /* 100us */ + out8 (IIC_DIRECTCNTL, 0xC); /* clock hi */ + udelay (100); /* 100us */ + } else { + break; + } + } + /* send start condition */ + out8 (IIC_DIRECTCNTL, 0x4); + udelay (1000); /* 1ms */ + /* send stop condition */ + out8 (IIC_DIRECTCNTL, 0xC); + udelay (1000); /* 1ms */ + /* Unreset controller */ + out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST)); + udelay (1000); /* 1ms */ +} + +void i2c_init (int speed, int slaveadd) +{ + sys_info_t sysInfo; + unsigned long freqOPB; + int val, divisor; + + /* Handle possible failed I2C state */ + _i2c_bus_reset (); + + /* clear lo master address */ + out8 (IIC_LMADR, 0); + + /* clear hi master address */ + out8 (IIC_HMADR, 0); + + /* clear lo slave address */ + out8 (IIC_LSADR, 0); + + /* clear hi slave address */ + out8 (IIC_HSADR, 0); + + /* Clock divide Register */ + /* get OPB frequency */ + get_sys_info (&sysInfo); + freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv; + /* set divisor according to freqOPB */ + divisor = (freqOPB - 1) / 10000000; + if (divisor == 0) + divisor = 1; + out8 (IIC_CLKDIV, divisor); + + /* no interrupts */ + out8 (IIC_INTRMSK, 0); + + /* clear transfer count */ + out8 (IIC_XFRCNT, 0); + + /* clear extended control & stat */ + /* write 1 in SRC SRS SWC SWS to clear these fields */ + out8 (IIC_XTCNTLSS, 0xF0); + + /* Mode Control Register + Flush Slave/Master data buffer */ + out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); + __asm__ volatile ("eieio"); + + + val = in8(IIC_MDCNTL); + __asm__ volatile ("eieio"); + + /* Ignore General Call, slave transfers are ignored, + disable interrupts, exit unknown bus state, enable hold + SCL + 100kHz normaly or FastMode for 400kHz and above + */ + + val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; + if( speed >= 400000 ){ + val |= IIC_MDCNTL_FSM; + } + out8 (IIC_MDCNTL, val); + + /* clear control reg */ + out8 (IIC_CNTL, 0x00); + __asm__ volatile ("eieio"); + +} + +/* + This code tries to use the features of the 405GP i2c + controller. It will transfer up to 4 bytes in one pass + on the loop. It only does out8(lbz) to the buffer when it + is possible to do out16(lhz) transfers. + + cmd_type is 0 for write 1 for read. + + addr_len can take any value from 0-255, it is only limited + by the char, we could make it larger if needed. If it is + 0 we skip the address write cycle. + + Typical case is a Write of an addr followd by a Read. The + IBM FAQ does not cover this. On the last byte of the write + we don't set the creg CHT bit, and on the first bytes of the + read we set the RPST bit. + + It does not support address only transfers, there must be + a data part. If you want to write the address yourself, put + it in the data pointer. + + It does not support transfer to/from address 0. + + It does not check XFRCNT. +*/ +static +int i2c_transfer(unsigned char cmd_type, + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], + unsigned short data_len ) +{ + unsigned char* ptr; + int reading; + int tran,cnt; + int result; + int status; + int i; + uchar creg; + + if( data == 0 || data_len == 0 ){ + /*Don't support data transfer of no length or to address 0*/ + printf( "i2c_transfer: bad call\n" ); + return IIC_NOK; + } + if( addr && addr_len ){ + ptr = addr; + cnt = addr_len; + reading = 0; + }else{ + ptr = data; + cnt = data_len; + reading = cmd_type; + } + + /*Clear Stop Complete Bit*/ + out8(IIC_STS,IIC_STS_SCMP); + /* Check init */ + i=10; + do { + /* Get status */ + status = in8(IIC_STS); + __asm__ volatile("eieio"); + i--; + } while ((status & IIC_STS_PT) && (i>0)); + + if (status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + return(result); + } + /*flush the Master/Slave Databuffers*/ + out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); + /*need to wait 4 OPB clocks? code below should take that long*/ + + /* 7-bit adressing */ + out8(IIC_HMADR,0); + out8(IIC_LMADR, chip); + __asm__ volatile("eieio"); + + tran = 0; + result = IIC_OK; + creg = 0; + + while ( tran != cnt && (result == IIC_OK)) { + int bc,j; + + /* Control register = + Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, + Transfer is a sequence of transfers + */ + creg |= IIC_CNTL_PT; + + bc = (cnt - tran) > 4 ? 4 : + cnt - tran; + creg |= (bc-1)<<4; + /* if the real cmd type is write continue trans*/ + if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) ) + creg |= IIC_CNTL_CHT; + + if (reading) + creg |= IIC_CNTL_READ; + else { + for(j=0; j<bc; j++) { + /* Set buffer */ + out8(IIC_MDBUF,ptr[tran+j]); + __asm__ volatile("eieio"); + } + } + out8(IIC_CNTL, creg ); + __asm__ volatile("eieio"); + + /* Transfer is in progress + we have to wait for upto 5 bytes of data + 1 byte chip address+r/w bit then bc bytes + of data. + udelay(10) is 1 bit time at 100khz + Doubled for slop. 20 is too small. + */ + i=2*5*8; + do { + /* Get status */ + status = in8(IIC_STS); + __asm__ volatile("eieio"); + udelay (10); + i--; + } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) + && (i>0)); + + if (status & IIC_STS_ERR) { + result = IIC_NOK; + status = in8 (IIC_EXTSTS); + /* Lost arbitration? */ + if (status & IIC_EXTSTS_LA) + result = IIC_NOK_LA; + /* Incomplete transfer? */ + if (status & IIC_EXTSTS_ICT) + result = IIC_NOK_ICT; + /* Transfer aborted? */ + if (status & IIC_EXTSTS_XFRA) + result = IIC_NOK_XFRA; + } else if ( status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + } + /* Command is reading => get buffer */ + if ((reading) && (result == IIC_OK)) { + /* Are there data in buffer */ + if (status & IIC_STS_MDBS) { + /* + even if we have data we have to wait 4OPB clocks + for it to hit the front of the FIFO, after that + we can just read. We should check XFCNT here and + if the FIFO is full there is no need to wait. + */ + udelay (1); + for(j=0;j<bc;j++) { + ptr[tran+j] = in8(IIC_MDBUF); + __asm__ volatile("eieio"); + } + } else + result = IIC_NOK_DATA; + } + creg = 0; + tran+=bc; + if( ptr == addr && tran == cnt ) { + ptr = data; + cnt = data_len; + tran = 0; + reading = cmd_type; + if( reading ) + creg = IIC_CNTL_RPST; + } + } + return (result); +} + +int i2c_probe (uchar chip) +{ + uchar buf[1]; + + buf[0] = 0; + + /* + * What is needed is to send the chip address and verify that the + * address was <ACK>ed (i.e. there was a chip at that address which + * drove the data line low). + */ + return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0); +} + + + +int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + uchar xaddr[4]; + int ret; + + if ( alen > 4 ) { + printf ("I2C read: addr len %d not supported\n", alen); + return 1; + } + + if ( alen > 0 ) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if( alen > 0 ) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) { + printf( "I2c read: failed %d\n", ret); + return 1; + } + return 0; +} + +int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +{ + uchar xaddr[4]; + + if ( alen > 4 ) { + printf ("I2C write: addr len %d not supported\n", alen); + return 1; + + } + if ( alen > 0 ) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } + +#ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW + /* + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. + * + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. + */ + if( alen > 0 ) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); +#endif + + return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); +} + +#endif /* CONFIG_HARD_I2C */ diff --git a/cpu/ppc4xx/sdram.c b/cpu/ppc4xx/sdram.c new file mode 100644 index 0000000..d64bf96 --- /dev/null +++ b/cpu/ppc4xx/sdram.c @@ -0,0 +1,191 @@ +/* + * (C) Copyright 2002 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> +#include <pci.h> + + +#ifdef CONFIG_SDRAM_BANK0 + + +#define MAGIC0 0x00000000 +#define MAGIC1 0x11111111 +#define MAGIC2 0x22222222 +#define MAGIC3 0x33333333 +#define MAGIC4 0x44444444 + +#define ADDR_ZERO 0x00000000 +#define ADDR_400 0x00000400 +#define ADDR_08MB 0x00800000 +#define ADDR_16MB 0x01000000 +#define ADDR_32MB 0x02000000 +#define ADDR_64MB 0x04000000 + +#define mtsdram0(reg, data) mtdcr(memcfga,reg);mtdcr(memcfgd,data) + + +/*----------------------------------------------------------------------- + */ +void sdram_init(void) +{ + ulong speed; + ulong sdtr1; + ulong rtr; + + /* + * Determine SDRAM speed + */ + speed = get_bus_freq(0); /* parameter not used on ppc4xx */ + + /* + * Support for 100MHz and 133MHz SDRAM + */ + if (speed > 100000000) { + /* + * 133 MHz SDRAM + */ + sdtr1 = 0x01074015; + rtr = 0x07f00000; + } else { + /* + * default: 100 MHz SDRAM + */ + sdtr1 = 0x0086400d; + rtr = 0x05f00000; + } + + /* + * Set MB0CF for bank 0. (0-64MB) Address Mode 3 since 13x9(4) + */ + mtsdram0(mem_mb0cf, 0x00084001); + + mtsdram0(mem_sdtr1, sdtr1); + mtsdram0(mem_rtr, rtr); + + /* + * Wait for 200us + */ + udelay(200); + + /* + * Set memory controller options reg, MCOPT1. + * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst + * read/prefetch. + */ + mtsdram0(mem_mcopt1, 0x80800000); + + /* + * Wait for 10ms + */ + udelay(10000); + + /* + * Test if 64 MByte are equipped (mirror test) + */ + *(volatile ulong *)ADDR_ZERO = MAGIC0; + *(volatile ulong *)ADDR_08MB = MAGIC1; + *(volatile ulong *)ADDR_16MB = MAGIC2; + *(volatile ulong *)ADDR_32MB = MAGIC3; + + if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) && + (*(volatile ulong *)ADDR_08MB == MAGIC1) && + (*(volatile ulong *)ADDR_16MB == MAGIC2)) { + /* + * OK, 64MB detected -> all done + */ + return; + } + + /* + * Now test for 32 MByte... + */ + + /* + * Disable memory controller. + */ + mtsdram0(mem_mcopt1, 0x00000000); + + /* + * Set MB0CF for bank 0. (0-32MB) Address Mode 2 since 12x9(4) + */ + mtsdram0(mem_mb0cf, 0x00062001); + + /* + * Set memory controller options reg, MCOPT1. + * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst + * read/prefetch. + */ + mtsdram0(mem_mcopt1, 0x80800000); + + /* + * Wait for 10ms + */ + udelay(10000); + + /* + * Test if 32 MByte are equipped (mirror test) + */ + *(volatile ulong *)ADDR_ZERO = MAGIC0; + *(volatile ulong *)ADDR_400 = MAGIC1; + *(volatile ulong *)ADDR_08MB = MAGIC2; + *(volatile ulong *)ADDR_16MB = MAGIC3; + + if ((*(volatile ulong *)ADDR_ZERO == MAGIC0) && + (*(volatile ulong *)ADDR_400 == MAGIC1) && + (*(volatile ulong *)ADDR_08MB == MAGIC2)) { + /* + * OK, 32MB detected -> all done + */ + return; + } + + /* + * Setup for 16 MByte... + */ + + /* + * Disable memory controller. + */ + mtsdram0(mem_mcopt1, 0x00000000); + + /* + * Set MB0CF for bank 0. (0-16MB) Address Mode 4 since 12x8(4) + */ + mtsdram0(mem_mb0cf, 0x00046001); + + /* + * Set memory controller options reg, MCOPT1. + * Set DC_EN to '1' and BRD_PRF to '01' for 16 byte PLB Burst + * read/prefetch. + */ + mtsdram0(mem_mcopt1, 0x80800000); + + /* + * Wait for 10ms + */ + udelay(10000); +} + +#endif /* CONFIG_SDRAM_BANK0 */ diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c new file mode 100644 index 0000000..4541529 --- /dev/null +++ b/cpu/ppc4xx/speed.c @@ -0,0 +1,308 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <ppc_asm.tmpl> +#include <ppc4xx.h> +#include <asm/processor.h> + +/* ------------------------------------------------------------------------- */ + +#define ONE_BILLION 1000000000 + + +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) + +void get_sys_info (PPC405_SYS_INFO * sysInfo) +{ + unsigned long pllmr; + unsigned long sysClkPeriodPs = ONE_BILLION / (CONFIG_SYS_CLK_FREQ / 1000); + uint pvr = get_pvr(); + unsigned long psr; + unsigned long m; + + /* + * Read PLL Mode register + */ + pllmr = mfdcr (pllmd); + + /* + * Read Pin Strapping register + */ + psr = mfdcr (strap); + + /* + * Determine FWD_DIV. + */ + sysInfo->pllFwdDiv = 8 - ((pllmr & PLLMR_FWD_DIV_MASK) >> 29); + + /* + * Determine FBK_DIV. + */ + sysInfo->pllFbkDiv = ((pllmr & PLLMR_FB_DIV_MASK) >> 25); + if (sysInfo->pllFbkDiv == 0) { + sysInfo->pllFbkDiv = 16; + } + + /* + * Determine PLB_DIV. + */ + sysInfo->pllPlbDiv = ((pllmr & PLLMR_CPU_TO_PLB_MASK) >> 17) + 1; + + /* + * Determine PCI_DIV. + */ + sysInfo->pllPciDiv = ((pllmr & PLLMR_PCI_TO_PLB_MASK) >> 13) + 1; + + /* + * Determine EXTBUS_DIV. + */ + sysInfo->pllExtBusDiv = ((pllmr & PLLMR_EXB_TO_PLB_MASK) >> 11) + 2; + + /* + * Determine OPB_DIV. + */ + sysInfo->pllOpbDiv = ((pllmr & PLLMR_OPB_TO_PLB_MASK) >> 15) + 1; + + /* + * Check if PPC405GPr used (mask minor revision field) + */ + if ((pvr & 0xfffffff0) == (PVR_405GPR_RA & 0xfffffff0)) { + /* + * Determine FWD_DIV B (only PPC405GPr with new mode strapping). + */ + sysInfo->pllFwdDivB = 8 - (pllmr & PLLMR_FWDB_DIV_MASK); + + /* + * Determine factor m depending on PLL feedback clock source + */ + if (!(psr & PSR_PCI_ASYNC_EN)) { + if (psr & PSR_NEW_MODE_EN) { + /* + * sync pci clock used as feedback (new mode) + */ + m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllPciDiv; + } else { + /* + * sync pci clock used as feedback (legacy mode) + */ + m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllPciDiv; + } + } else if (psr & PSR_NEW_MODE_EN) { + if (psr & PSR_PERCLK_SYNC_MODE_EN) { + /* + * PerClk used as feedback (new mode) + */ + m = 1 * sysInfo->pllFwdDivB * 2 * sysInfo->pllExtBusDiv; + } else { + /* + * CPU clock used as feedback (new mode) + */ + m = sysInfo->pllFbkDiv * sysInfo->pllFwdDiv; + } + } else if (sysInfo->pllExtBusDiv == sysInfo->pllFbkDiv) { + /* + * PerClk used as feedback (legacy mode) + */ + m = 1 * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv * sysInfo->pllExtBusDiv; + } else { + /* + * PLB clock used as feedback (legacy mode) + */ + m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivB * sysInfo->pllPlbDiv; + } + + sysInfo->freqVCOMhz = (1000000 * m) / sysClkPeriodPs; + sysInfo->freqProcessor = (sysInfo->freqVCOMhz * 1000000) / sysInfo->pllFwdDiv; + sysInfo->freqPLB = (sysInfo->freqVCOMhz * 1000000) / + (sysInfo->pllFwdDivB * sysInfo->pllPlbDiv); + } else { + /* + * Check pllFwdDiv to see if running in bypass mode where the CPU speed + * is equal to the 405GP SYS_CLK_FREQ. If not in bypass mode, check VCO + * to make sure it is within the proper range. + * spec: VCO = SYS_CLOCK x FBKDIV x PLBDIV x FWDDIV + * Note freqVCO is calculated in Mhz to avoid errors introduced by rounding. + */ + if (sysInfo->pllFwdDiv == 1) { + sysInfo->freqProcessor = CONFIG_SYS_CLK_FREQ; + sysInfo->freqPLB = CONFIG_SYS_CLK_FREQ / sysInfo->pllPlbDiv; + } else { + sysInfo->freqVCOMhz = ( 1000000 * + sysInfo->pllFwdDiv * + sysInfo->pllFbkDiv * + sysInfo->pllPlbDiv + ) / sysClkPeriodPs; + if (sysInfo->freqVCOMhz >= VCO_MIN + && sysInfo->freqVCOMhz <= VCO_MAX) { + sysInfo->freqPLB = (ONE_BILLION / + ((sysClkPeriodPs * 10) / + sysInfo->pllFbkDiv)) * 10000; + sysInfo->freqProcessor = sysInfo->freqPLB * sysInfo->pllPlbDiv; + } else { + printf ("\nInvalid VCO frequency calculated : %ld MHz \a\n", + sysInfo->freqVCOMhz); + printf ("It must be between %d-%d MHz \a\n", + VCO_MIN, VCO_MAX); + printf ("PLL Mode reg : %8.8lx\a\n", + pllmr); + hang (); + } + } + } +} + + +/******************************************** + * get_OPB_freq + * return OPB bus freq in Hz + *********************************************/ +ulong get_OPB_freq (void) +{ + ulong val = 0; + + PPC405_SYS_INFO sys_info; + + get_sys_info (&sys_info); + val = sys_info.freqPLB / sys_info.pllOpbDiv; + + return val; +} + + +/******************************************** + * get_PCI_freq + * return PCI bus freq in Hz + *********************************************/ +ulong get_PCI_freq (void) +{ + ulong val; + PPC405_SYS_INFO sys_info; + + get_sys_info (&sys_info); + val = sys_info.freqPLB / sys_info.pllPciDiv; + return val; +} + + +#elif defined(CONFIG_440) +void get_sys_info (sys_info_t * sysInfo) +{ + unsigned long strp0; + unsigned long temp; + unsigned long m; + + /* Extract configured divisors */ + 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 + ((strp0 & PLLSYS0_OPB_DIV_MASK) >> 10); + sysInfo->pllExtBusDiv = 1 + ((strp0 & PLLSYS0_EPB_DIV_MASK) >> 8); + + /* Calculate 'M' based on feedback source */ + if( strp0 & PLLSYS0_EXTSL_MASK ) + m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB; + else + m = sysInfo->pllFbkDiv * sysInfo->pllFwdDivA; + + /* Now calculate the individual clocks */ + 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; + +} + +ulong get_OPB_freq (void) +{ + + sys_info_t sys_info; + get_sys_info (&sys_info); + return sys_info.freqOPB; +} + +#elif defined(CONFIG_405) + +void get_sys_info (sys_info_t * sysInfo) { + + sysInfo->freqVCOMhz=3125000; + sysInfo->freqProcessor=12*1000*1000; + sysInfo->freqPLB=50*1000*1000; + sysInfo->freqPCI=66*1000*1000; + +} + +#endif + +int get_clocks (void) +{ +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_440) || defined(CONFIG_405) + DECLARE_GLOBAL_DATA_PTR; + + sys_info_t sys_info; + + get_sys_info (&sys_info); + gd->cpu_clk = sys_info.freqProcessor; + gd->bus_clk = sys_info.freqPLB; + +#endif /* defined(CONFIG_405GP) || defined(CONFIG_405CR) */ + +#ifdef CONFIG_IOP480 + DECLARE_GLOBAL_DATA_PTR; + + gd->cpu_clk = 66000000; + gd->bus_clk = 66000000; +#endif + return (0); +} + + +/******************************************** + * get_bus_freq + * return PLB bus freq in Hz + *********************************************/ +ulong get_bus_freq (ulong dummy) +{ + ulong val; + +#if defined(CONFIG_405GP) || defined(CONFIG_405CR) || defined(CONFIG_405) || defined(CONFIG_440) + sys_info_t sys_info; + + get_sys_info (&sys_info); + val = sys_info.freqPLB; + +#elif defined(CONFIG_IOP480) + + val = 66; + +#else +# error get_bus_freq() not implemented +#endif + + return val; +} diff --git a/cpu/ppc4xx/vecnum.h b/cpu/ppc4xx/vecnum.h new file mode 100644 index 0000000..d493a5d --- /dev/null +++ b/cpu/ppc4xx/vecnum.h @@ -0,0 +1,100 @@ +/* +* Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.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 +*/ + +/* + * Interrupt vector number definitions to ease the + * 405 -- 440 porting pain ;-) + * + * NOTE: They're not all here yet ... update as needed. + * + */ + +#ifndef _VECNUMS_H_ +#define _VECNUMS_H_ + +#if defined(CONFIG_440) + +/* UIC 0 */ +#define VECNUM_U0 0 /* UART0 */ +#define VECNUM_U1 1 /* UART1 */ +#define VECNUM_IIC0 2 /* IIC0 */ +#define VECNUM_IIC1 3 /* IIC1 */ +#define VECNUM_PIM 4 /* PCI inbound message */ +#define VECNUM_PCRW 5 /* PCI command reg write */ +#define VECNUM_PPM 6 /* PCI power management */ +#define VECNUM_MSI0 7 /* PCI MSI level 0 */ +#define VECNUM_MSI1 8 /* PCI MSI level 0 */ +#define VECNUM_MSI2 9 /* PCI MSI level 0 */ +#define VECNUM_MTE 10 /* MAL TXEOB */ +#define VECNUM_MRE 11 /* MAL RXEOB */ +#define VECNUM_D0 12 /* DMA channel 0 */ +#define VECNUM_D1 13 /* DMA channel 1 */ +#define VECNUM_D2 14 /* DMA channel 2 */ +#define VECNUM_D3 15 /* DMA channel 3 */ +#define VECNUM_CT0 18 /* GPT compare timer 0 */ +#define VECNUM_CT1 19 /* GPT compare timer 1 */ +#define VECNUM_CT2 20 /* GPT compare timer 2 */ +#define VECNUM_CT3 21 /* GPT compare timer 3 */ +#define VECNUM_CT4 22 /* GPT compare timer 4 */ +#define VECNUM_EIR0 23 /* External interrupt 0 */ +#define VECNUM_EIR1 24 /* External interrupt 1 */ +#define VECNUM_EIR2 25 /* External interrupt 2 */ +#define VECNUM_EIR3 26 /* External interrupt 3 */ +#define VECNUM_EIR4 27 /* External interrupt 4 */ +#define VECNUM_EIR5 28 /* External interrupt 5 */ +#define VECNUM_EIR6 29 /* External interrupt 6 */ +#define VECNUM_UIC1NC 30 /* UIC1 non-critical interrupt */ +#define VECNUM_UIC1C 31 /* UIC1 critical interrupt */ + +/* UIC 1 */ +#define VECNUM_MS (32 + 0 ) /* MAL SERR */ +#define VECNUM_TXDE (32 + 1 ) /* MAL TXDE */ +#define VECNUM_RXDE (32 + 2 ) /* MAL RXDE */ +#define VECNUM_ETH0 (32 + 28) /* Ethernet 0 interrupt status */ +#define VECNUM_EWU0 (32 + 29) /* Ethernet 0 wakeup */ + +#else /* !defined(CONFIG_440) */ + +#define VECNUM_U0 0 /* UART0 */ +#define VECNUM_U1 1 /* UART1 */ +#define VECNUM_D0 5 /* DMA channel 0 */ +#define VECNUM_D1 6 /* DMA channel 1 */ +#define VECNUM_D2 7 /* DMA channel 2 */ +#define VECNUM_D3 8 /* DMA channel 3 */ +#define VECNUM_EWU0 9 /* Ethernet wakeup */ +#define VECNUM_MS 10 /* MAL SERR */ +#define VECNUM_MTE 11 /* MAL TXEOB */ +#define VECNUM_MRE 12 /* MAL RXEOB */ +#define VECNUM_TXDE 13 /* MAL TXDE */ +#define VECNUM_RXDE 14 /* MAL RXDE */ +#define VECNUM_ETH0 15 /* Ethernet interrupt status */ +#define VECNUM_EIR0 25 /* External interrupt 0 */ +#define VECNUM_EIR1 26 /* External interrupt 1 */ +#define VECNUM_EIR2 27 /* External interrupt 2 */ +#define VECNUM_EIR3 28 /* External interrupt 3 */ +#define VECNUM_EIR4 29 /* External interrupt 4 */ +#define VECNUM_EIR5 30 /* External interrupt 5 */ +#define VECNUM_EIR6 31 /* External interrupt 6 */ + +#endif /* defined(CONFIG_440) */ + +#endif /* _VECNUMS_H_ */ diff --git a/cpu/sa1100/Makefile b/cpu/sa1100/Makefile new file mode 100644 index 0000000..8c950da --- /dev/null +++ b/cpu/sa1100/Makefile @@ -0,0 +1,43 @@ +# +# (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$(CPU).a + +START = start.o +OBJS = serial.o interrupts.o cpu.o + +all: .depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(START:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/cpu/xscale/serial.c b/cpu/xscale/serial.c new file mode 100644 index 0000000..35302a7 --- /dev/null +++ b/cpu/xscale/serial.c @@ -0,0 +1,143 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, <wd@denx.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <asm/arch/pxa-regs.h> + +void serial_setbrg (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + unsigned int quot = 0; + + if (gd->baudrate == 1200) + quot = 192; + else if (gd->baudrate == 9600) + quot = 96; + else if (gd->baudrate == 19200) + quot = 48; + else if (gd->baudrate == 38400) + quot = 24; + else if (gd->baudrate == 57600) + quot = 16; + else if (gd->baudrate == 115200) + quot = 8; + else + hang (); + +#ifdef CONFIG_FFUART + + CKEN |= CKEN6_FFUART; + + FFIER = 0; /* Disable for now */ + FFFCR = 0; /* No fifos enabled */ + + /* set baud rate */ + FFLCR = LCR_WLS0 | LCR_WLS1 | LCR_DLAB; + FFDLL = quot & 0xff; + FFDLH = quot >> 8; + FFLCR = LCR_WLS0 | LCR_WLS1; + + FFIER = IER_UUE; /* Enable FFUART */ + +#elif CONFIG_STUART +#error "Bad: not implemented yet!" +#else +#error "Bad: you didn't configured serial ..." +#endif +} + + +/* + * Initialise the serial port with the given baudrate. The settings + * are always 8 data bits, no parity, 1 stop bit, no start bits. + * + */ +int serial_init (void) +{ + serial_setbrg (); + + return (0); +} + + +/* + * Output a single byte to the serial port. + */ +void serial_putc (const char c) +{ +#ifdef CONFIG_FFUART + /* wait for room in the tx FIFO on FFUART */ + while ((FFLSR & LSR_TEMT) == 0); + + FFTHR = c; +#elif CONFIG_STUART +#endif + + /* If \n, also do \r */ + if (c == '\n') + serial_putc ('\r'); +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_tstc (void) +{ +#ifdef CONFIG_FFUART + return FFLSR & LSR_DR; +#elif CONFIG_STUART +#endif +} + +/* + * Read a single byte from the serial port. Returns 1 on success, 0 + * otherwise. When the function is succesfull, the character read is + * written into its argument c. + */ +int serial_getc (void) +{ +#ifdef CONFIG_FFUART + while (!(FFLSR & LSR_DR)); + + return (char) FFRBR & 0xff; +#elif CONFIG_STUART +#endif +} + +void +serial_puts (const char *s) +{ + while (*s) { + serial_putc (*s++); + } +} diff --git a/cpu/xscale/start.S b/cpu/xscale/start.S new file mode 100644 index 0000000..f1049a8 --- /dev/null +++ b/cpu/xscale/start.S @@ -0,0 +1,412 @@ +/* + * armboot - Startup Code for XScale + * + * Copyright (C) 1998 Dan Malek <dmalek@jlc.net> + * Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se> + * Copyright (C) 2000 Wolfgang Denk <wd@denx.de> + * Copyright (c) 2001 Alex Züpke <azu@sysgo.de> + * Copyright (c) 2002 Kyle Harris <kharris@nexus-tech.net> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + + +#include <config.h> +#include <version.h> + +.globl _start +_start: b reset + ldr pc, _undefined_instruction + ldr pc, _software_interrupt + ldr pc, _prefetch_abort + ldr pc, _data_abort + ldr pc, _not_used + ldr pc, _irq + ldr pc, _fiq + +_undefined_instruction: .word undefined_instruction +_software_interrupt: .word software_interrupt +_prefetch_abort: .word prefetch_abort +_data_abort: .word data_abort +_not_used: .word not_used +_irq: .word irq +_fiq: .word fiq + + .balignl 16,0xdeadbeef + + +/* + * Startup Code (reset vector) + * + * do important init only if we don't start from memory! + * - relocate armboot to ram + * - setup stack + * - jump to second stage + */ + +/* + * CFG_MEM_END is in the board dependent config-file (configs/config_BOARD.h) + */ +_TEXT_BASE: + .word TEXT_BASE + +.globl _armboot_start +_armboot_start: + .word _start + +/* + * Note: _armboot_end_data and _armboot_end are defined + * by the (board-dependent) linker script. + * _armboot_end_data is the first usable FLASH address after armboot + */ +.globl _armboot_end_data +_armboot_end_data: + .word armboot_end_data +.globl _armboot_end +_armboot_end: + .word armboot_end + +/* + * _armboot_real_end is the first usable RAM address behind armboot + * and the various stacks + */ +.globl _armboot_real_end +_armboot_real_end: + .word 0x0badc0de + +/* + * We relocate uboot to this address (end of RAM - 128 KiB) + */ +.globl _uboot_reloc +_uboot_reloc: + .word CFG_DRAM_BASE + CFG_DRAM_SIZE - CFG_MONITOR_LEN + +#ifdef CONFIG_USE_IRQ +/* IRQ stack memory (calculated at run-time) */ +.globl IRQ_STACK_START +IRQ_STACK_START: + .word 0x0badc0de + +/* IRQ stack memory (calculated at run-time) */ +.globl FIQ_STACK_START +FIQ_STACK_START: + .word 0x0badc0de +#endif + + +/****************************************************************************/ +/* */ +/* the actual reset code */ +/* */ +/****************************************************************************/ + +reset: + mrs r0,cpsr /* set the cpu to SVC32 mode */ + bic r0,r0,#0x1f /* (superviser mode, M=10011) */ + orr r0,r0,#0x13 + msr cpsr,r0 + + bl cpu_init_crit /* we do sys-critical inits */ + +relocate: /* relocate U-Boot to RAM */ + adr r0, _start /* r0 <- current position of code */ + ldr r2, _armboot_start + ldr r3, _armboot_end + sub r2, r3, r2 /* r2 <- size of armboot */ +/* ldr r1, _uboot_reloc / * r1 <- destination address */ + ldr r1, _TEXT_BASE + add r2, r0, r2 /* r2 <- source end address */ + +copy_loop: + ldmia r0!, {r3-r10} /* copy from source address [r0] */ + stmia r1!, {r3-r10} /* copy to target address [r1] */ + cmp r0, r2 /* until source end addreee [r2] */ + ble copy_loop + + /* Set up the stack */ + ldr r0, _uboot_reloc /* upper 128 KiB: relocated uboot */ + sub r0, r0, #CFG_MALLOC_LEN /* malloc area */ + /* FIXME: bdinfo should be here */ + sub sp, r0, #12 /* leave 3 words for abort-stack */ + + ldr pc, _start_armboot + +_start_armboot: .word start_armboot + + +/****************************************************************************/ +/* */ +/* CPU_init_critical registers */ +/* */ +/* - setup important registers */ +/* - setup memory timing */ +/* */ +/****************************************************************************/ + + /* Interrupt-Controller base address */ +IC_BASE: .word 0x40d00000 +#define ICMR 0x04 + +/* Reset-Controller */ +RST_BASE: .word 0x40f00030 +#define RCSR 0x00 + + + /* Clock Manager Registers */ +CC_BASE: .word 0x41300000 +#define CCCR 0x00 +cpuspeed: .word CFG_CPUSPEED + + /* RS: ??? */ + .macro CPWAIT + mrc p15,0,r0,c2,c0,0 + mov r0,r0 + sub pc,pc,#4 + .endm + + +cpu_init_crit: + + /* mask all IRQs */ + ldr r0, IC_BASE + mov r1, #0x00 + str r1, [r0, #ICMR] + + /* set clock speed */ + ldr r0, CC_BASE + ldr r1, cpuspeed + str r1, [r0, #CCCR] + + /* + * before relocating, we have to setup RAM timing + * because memory timing is board-dependend, you will + * find a memsetup.S in your board directory. + */ + mov ip, lr + bl memsetup + mov lr, ip + + /* Memory interfaces are working. Disable MMU and enable I-cache. */ + + ldr r0, =0x2001 /* enable access to all coproc. */ + mcr p15, 0, r0, c15, c1, 0 + CPWAIT + + mcr p15, 0, r0, c7, c10, 4 /* drain the write & fill buffers */ + CPWAIT + + mcr p15, 0, r0, c7, c7, 0 /* flush Icache, Dcache and BTB */ + CPWAIT + + mcr p15, 0, r0, c8, c7, 0 /* flush instuction and data TLBs */ + CPWAIT + + /* Enable the Icache */ +/* + mrc p15, 0, r0, c1, c0, 0 + orr r0, r0, #0x1800 + mcr p15, 0, r0, c1, c0, 0 + CPWAIT +*/ + mov pc, lr + + +/****************************************************************************/ +/* */ +/* Interrupt handling */ +/* */ +/****************************************************************************/ + +/* IRQ stack frame */ + +#define S_FRAME_SIZE 72 + +#define S_OLD_R0 68 +#define S_PSR 64 +#define S_PC 60 +#define S_LR 56 +#define S_SP 52 + +#define S_IP 48 +#define S_FP 44 +#define S_R10 40 +#define S_R9 36 +#define S_R8 32 +#define S_R7 28 +#define S_R6 24 +#define S_R5 20 +#define S_R4 16 +#define S_R3 12 +#define S_R2 8 +#define S_R1 4 +#define S_R0 0 + +#define MODE_SVC 0x13 + + /* use bad_save_user_regs for abort/prefetch/undef/swi ... */ + + .macro bad_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} /* Calling r0-r12 */ + add r8, sp, #S_PC + + ldr r2, _armboot_end + add r2, r2, #CONFIG_STACKSIZE + sub r2, r2, #8 + ldmia r2, {r2 - r4} /* get pc, cpsr, old_r0 */ + add r0, sp, #S_FRAME_SIZE /* restore sp_SVC */ + + add r5, sp, #S_SP + mov r1, lr + stmia r5, {r0 - r4} /* save sp_SVC, lr_SVC, pc, cpsr, old_r */ + mov r0, sp + .endm + + + /* use irq_save_user_regs / irq_restore_user_regs for */ + /* IRQ/FIQ handling */ + + .macro irq_save_user_regs + sub sp, sp, #S_FRAME_SIZE + stmia sp, {r0 - r12} /* Calling r0-r12 */ + add r8, sp, #S_PC + stmdb r8, {sp, lr}^ /* Calling SP, LR */ + str lr, [r8, #0] /* Save calling PC */ + mrs r6, spsr + str r6, [r8, #4] /* Save CPSR */ + str r0, [r8, #8] /* Save OLD_R0 */ + mov r0, sp + .endm + + .macro irq_restore_user_regs + ldmia sp, {r0 - lr}^ @ Calling r0 - lr + mov r0, r0 + ldr lr, [sp, #S_PC] @ Get PC + add sp, sp, #S_FRAME_SIZE + subs pc, lr, #4 @ return & move spsr_svc into cpsr + .endm + + .macro get_bad_stack + ldr r13, _armboot_end @ setup our mode stack + add r13, r13, #CONFIG_STACKSIZE @ resides at top of normal stack + sub r13, r13, #8 + + str lr, [r13] @ save caller lr / spsr + mrs lr, spsr + str lr, [r13, #4] + + mov r13, #MODE_SVC @ prepare SVC-Mode + msr spsr_c, r13 + mov lr, pc + movs pc, lr + .endm + + .macro get_irq_stack @ setup IRQ stack + ldr sp, IRQ_STACK_START + .endm + + .macro get_fiq_stack @ setup FIQ stack + ldr sp, FIQ_STACK_START + .endm + + +/****************************************************************************/ +/* */ +/* exception handlers */ +/* */ +/****************************************************************************/ + + .align 5 +undefined_instruction: + get_bad_stack + bad_save_user_regs + bl do_undefined_instruction + + .align 5 +software_interrupt: + get_bad_stack + bad_save_user_regs + bl do_software_interrupt + + .align 5 +prefetch_abort: + get_bad_stack + bad_save_user_regs + bl do_prefetch_abort + + .align 5 +data_abort: + get_bad_stack + bad_save_user_regs + bl do_data_abort + + .align 5 +not_used: + get_bad_stack + bad_save_user_regs + bl do_not_used + +#ifdef CONFIG_USE_IRQ + + .align 5 +irq: + get_irq_stack + irq_save_user_regs + bl do_irq + irq_restore_user_regs + + .align 5 +fiq: + get_fiq_stack + irq_save_user_regs /* someone ought to write a more */ + bl do_fiq /* effiction fiq_save_user_regs */ + irq_restore_user_regs + +#else + + .align 5 +irq: + get_bad_stack + bad_save_user_regs + bl do_irq + + .align 5 +fiq: + get_bad_stack + bad_save_user_regs + bl do_fiq + +#endif + +/* + * FIXME How do we reset??? Watchdog timeout?? + */ + .align 5 +.globl reset_cpu +reset_cpu: + /* + ldr r0, RST_BASE + mov r1, #0x0 @ set bit 3-0 ... + str r1, [r0, #RCSR] @ ... to clear in RCSR + mov r1, #0x1 + str r1, [r0, #RCSR] @ and perform reset + */ + b reset_cpu @ silly, but repeat endlessly + diff --git a/doc/README.JFFS2 b/doc/README.JFFS2 new file mode 100644 index 0000000..0d39c46 --- /dev/null +++ b/doc/README.JFFS2 @@ -0,0 +1,68 @@ +JFFS2 options and usage. +----------------------- + +JFFS2 in U-Boot 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 <jffs2/jffs2.h> + +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..a3ba7b7 --- /dev/null +++ b/doc/README.Modem @@ -0,0 +1,73 @@ +How to configure modem support in U-Boot : + +1. Define modem initialization strings: +--------------------------------------- + +The modem initialization strings have following format: + + mdm_init1=<AT-command> + mdm_init2=<AT-command> + ... + +Turning off modem verbose responses with ATV0 or ATQ1 is not allowed; +U-Boot 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/<board>.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 U-Boot prompt appears +on the terminal console. If not (U-Boot 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.commands b/doc/README.commands new file mode 100644 index 0000000..576186e --- /dev/null +++ b/doc/README.commands @@ -0,0 +1,99 @@ +# +# The commands in this table are sorted alphabetically by the +# command name and in descending order by the command name string +# length. This is to prevent conflicts in command name parsing. +# Please ensure that new commands are added according to that rule. +# See $(TOPDIR)/common/command.c +# +######################## +# +# command length +# +######################## +askenv 8 +as 2 +autoscr 5 +base 2 +bdinfo 2 +bootelf 7 +bootm 5 +bootp 5 +bootvx 6 +bootd 4 +break 2 +brginfo 3 +carinfo 3 +chpart 6 +cmp 3 +coninfo 5 +continue 4 +cp 2 +crc32 3 +date 3 +dcache 2 +dhcp 4 +dmainfo 3 +ds 2 +dtt 3 +echo 4 +eeprom 3 +erase 3 +fccinfo 3 +fdcboot 4 +flinfo 3 +fpga 4 +fsinfo 5 +fsload 5 +getdcr 6 # IBM 4XX DCR registers +go 2 +help 1 +i2cinfo 4 +i2c 3 +icache 2 +icinfo 3 +ide 3 +iminfo 3 +iopinfo 3 +irqinfo 3 +kgdb 4 +loadb 5 +loads 5 +loop 4 +ls 2 +mccinfo 3 +md 2 +memcinfo 4 +mii 3 +mm 2 +mtest 5 +muxinfo 3 +mw 2 +next 4 +nm 2 +pciinfo 3 +pinit 4 +printenv 8 +protect 4 +rarpboot 4 +rdump 5 +reginfo 3 +reset 5 +run 3 +saveenv 4 +sccinfo 3 +scsiboot 5 +scsi 4 +siiinfo 3 +sitinfo 3 +siuinfo 3 +setdcr 6 # IBM 4XX DCR registers +setenv 6 +smcinfo 3 +spiinfo 3 +stack 5 +step 4 +tftpboot 4 +usbboot 5 +usb 4 +version 4 +? 1 diff --git a/doc/README.ebony b/doc/README.ebony new file mode 100644 index 0000000..12a0d70 --- /dev/null +++ b/doc/README.ebony @@ -0,0 +1,138 @@ + IBM Ebony Board + + Last Update: September 12, 2002 +======================================================================= + +This file contains some handy info regarding U-Boot and the IBM +Ebony evalutation board. See the README.ppc440 for additional +information. + + +SWITCH SETTINGS & JUMPERS +========================== + +Here's what I've been using successfully. If you feel inclined to +change things ... please read the docs! + +DIPSW U46 U80 +------------------------ +SW 1 off on +SW 2 on on +SW 3 on on +SW 4 off on +SW 5 on off +SW 6 on on +SW 7 on off +SW 8 on off + +J41: strapped +J42: open + +All others are factory default. + + +I2C iprobe +===================== + +The i2c utilities have been tested on both Rev B. and Rev C. and +look good. The CFG_I2C_NOPROBES macro is defined to prevent +probing the CDCV850 clock controller at address 0x69 (since reading +it causes the i2c implementation to misbehave. The output of +iprobe should look like this (assuming you are only using a single +SO-DIMM: + +=> iprobe +Valid chip addresses: 50 53 54 +Excluded chip addresses: 69 + + +GETTING OUT OF I2C TROUBLE +=========================== + +If you're like me ... you may have screwed up your bootstrap serial +eeprom ... or worse, your SPD eeprom when experimenting with the +i2c commands. If so, here are some ideas on how to get out of +trouble: + +Serial bootstrap eeprom corruption: +----------------------------------- +Power down the board and set the following straps: + +J41 - open +J42 - strapped + +This will select the default sys0 and sys1 settings (the serial +eeproms are not used). Then power up the board and fix the serial +eeprom using the imm command. Here are the values I currently +use: + +=> imd 50 0 10 +0000: bf a2 04 01 ae 94 11 00 00 00 00 00 00 00 00 00 ................ + +=> imd 54 0 10 +0000: 8f b3 24 01 4d 14 11 00 00 00 00 00 00 00 00 00 ..$.M........... + +Once you have the eeproms set correctly change the +J41/J42 straps as you desire. + +SPD eeprom corruption: +------------------------ +I've corrupted the SPD eeprom several times ... perhaps too much coffee +and not enough presence of mind ;-). By default, the ebony code uses +the SPD to initialize the DDR SDRAM control registers. So if the SPD +eeprom is corrupted, U-Boot will never get into ram. Here's how I got +out of this situation: + +0. First, _before_ playing with the i2c utilities, do an iprobe, then +use imd to capture the various device contents to a file. Some day +you may be glad you did this ... trust me :-). Otherwise try the +following: + +1. In the include/configs/EBONY.h file find the line that defines +the CONFIG_SPD_EEPROM macro and undefine it. E.g: + +#undef CONFIG_SPD_EEPROM + +This will make the code use default SDRAM control register +settings without using the SPD eeprom. + +2. Rebuild U-Boot + +3. Load the new U-Boot image and reboot ebony. + +4. Repair the SPD eeprom using the imm command. Here's the eeprom +contents that work with the default SO-DIMM that comes with the +ebony board (micron 8VDDT164AG-265A1). Note: these are probably +_not_ the factory settings ... but they work. + +=> imd 53 0 10 80 +0000: 80 08 07 0c 0a 01 40 00 04 75 75 00 80 08 00 01 ......@..uu..... +0010: 0e 04 0c 01 02 20 00 a0 75 00 00 50 3c 50 2d 20 ..... ..u..P<P- +0020: 90 90 50 50 00 00 00 00 00 41 4b 34 32 75 00 00 ..PP.....AK42u.. +0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 9c ................ +0040: 2c 00 00 00 00 00 00 00 08 38 56 44 44 54 31 36 ,........8VDDT16 +0050: 36 34 41 47 2d 32 36 35 41 31 20 01 00 01 2c 63 64AG-265A1 ...,c +0060: 22 25 ab 00 00 00 00 00 00 00 00 00 00 00 00 00 "%.............. +0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + + +PCI DOUBLE-ENUMERATION WOES +=========================== + +If you're not using PCI-X cards and are simply using 32-bit and/or +33 MHz cards via extenders and the like, you may notice that the +initial pci scan reports various devices twice ... and configuration +does not succeed (one or more devices are enumerated twice). To correct +this we replaced the 2K ohm resistor on the IDSEL line(s) with a +22 ohm resistor and the problem went away. This change hasn't broken +anything yet -- use at your own risk. + +We never tested anything other than 33 MHz/32-bit cards. If you have +the chance to do this, please let me know how things turn out :-) + + + +Regards, +--Scott +<smcnutt@artesyncp.com> + diff --git a/doc/README.ppc440 b/doc/README.ppc440 new file mode 100644 index 0000000..acb0c6f --- /dev/null +++ b/doc/README.ppc440 @@ -0,0 +1,204 @@ + PowerPC 440 + + Last Update: September 11, 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 may be 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. Most +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 :-) + + +I2C +================= + +The i2c utilities have been tested on both Rev B. and Rev C. and +look good. The iprobe command implementation has been updated to +allow for 'skipped' addresses. Some i2c slaves are write only and +cause problems when a probe (read) is performed (for example the +CDCV850 clock controller at address 0x69 on the ebony board). + +To prevent probing certain addresses you can define the +CFG_I2C_NOPROBES macro in your board-specific header file. When +defined, all specified addresses are skipped during a probe. +The addresses that are skipped will be displayed in the output +of the iprobe command. + +For example, to prevent probing address 0x69, define the macro as +follows: + +#define CFG_I2C_NOPROBES {0x69} + +Similarly, to prevent probing addresses 0x69 and 0x70, define the +macro a: + +#define CFG_I2C_NOPROBES {0x69, 0x70} + + +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 U-Boot 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 tasks. If pci_pre_init() +returns a value of zero, PCI initialization is aborted; otherwise the +controller structure is registered and initialization continues. + +The default 440GP 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 +local PCI bus configuration. + +2. Host only: PPMC boards must sample the MONARCH# signal at run-time. +Depending on the configuration of the carrier boar, the PPMC board must +determine if it should configure the PCI bus at run-time. And in most +cases, access to the MONARCH# signal is board-specific (e.g. via +board-specific FPGA registers, 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 +<smcnutt@artesyncp.com> + diff --git a/drivers/3c589.h b/drivers/3c589.h new file mode 100644 index 0000000..00e7f7c --- /dev/null +++ b/drivers/3c589.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 1993 Herb Peyerl (hpeyerl@novatel.ca) All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. 2. The name + * of the author may not be used to endorse or promote products derived from + * this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + October 2, 1994 + + Modified by: Andres Vega Garcia + + INRIA - Sophia Antipolis, France + e-mail: avega@sophia.inria.fr + finger: avega@pax.inria.fr + + */ + +/* + * Created from if_epreg.h by Fred Gray (fgray@rice.edu) to support the + * 3c590 family. + */ + +/* + * Modified by Shusuke Nisiyama <shu@athena.qe.eng.hokudai.ac.jp> + * for etherboot + * Mar. 14, 2000 +*/ + +/* + * Ethernet software status per interface. + */ + +/* + * Some global constants + */ + +#define TX_INIT_RATE 16 +#define TX_INIT_MAX_RATE 64 +#define RX_INIT_LATENCY 64 +#define RX_INIT_EARLY_THRESH 64 +#define MIN_RX_EARLY_THRESHF 16 /* not less than ether_header */ +#define MIN_RX_EARLY_THRESHL 4 + +#define EEPROMSIZE 0x40 +#define MAX_EEPROMBUSY 1000 +#define VX_LAST_TAG 0xd7 +#define VX_MAX_BOARDS 16 +#define VX_ID_PORT 0x100 + +/* + * some macros to acces long named fields + */ +#define BASE (EL_BASE_ADDR) + +/* + * Commands to read/write EEPROM trough EEPROM command register (Window 0, + * Offset 0xa) + */ +#define EEPROM_CMD_RD 0x0080 /* Read: Address required (5 bits) */ +#define EEPROM_CMD_WR 0x0040 /* Write: Address required (5 bits) */ +#define EEPROM_CMD_ERASE 0x00c0 /* Erase: Address required (5 bits) */ +#define EEPROM_CMD_EWEN 0x0030 /* Erase/Write Enable: No data required */ + +#define EEPROM_BUSY (1<<15) + +/* + * Some short functions, worth to let them be a macro + */ + +/************************************************************************** + * * + * These define the EEPROM data structure. They are used in the probe + * function to verify the existence of the adapter after having sent + * the ID_Sequence. + * + * There are others but only the ones we use are defined here. + * + **************************************************************************/ + +#define EEPROM_NODE_ADDR_0 0x0 /* Word */ +#define EEPROM_NODE_ADDR_1 0x1 /* Word */ +#define EEPROM_NODE_ADDR_2 0x2 /* Word */ +#define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ +#define EEPROM_MFG_ID 0x7 /* 0x6d50 */ +#define EEPROM_ADDR_CFG 0x8 /* Base addr */ +#define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ +#define EEPROM_OEM_ADDR_0 0xa /* Word */ +#define EEPROM_OEM_ADDR_1 0xb /* Word */ +#define EEPROM_OEM_ADDR_2 0xc /* Word */ +#define EEPROM_SOFT_INFO_2 0xf /* Software information 2 */ + +#define NO_RX_OVN_ANOMALY (1<<5) + +/************************************************************************** + * * + * These are the registers for the 3Com 3c509 and their bit patterns when * + * applicable. They have been taken out the the "EtherLink III Parallel * + * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * + * from 3com. * + * * + **************************************************************************/ + +#define VX_COMMAND 0x0e /* Write. BASE+0x0e is always a + * command reg. */ +#define VX_STATUS 0x0e /* Read. BASE+0x0e is always status + * reg. */ +#define VX_WINDOW 0x0f /* Read. BASE+0x0f is always window + * reg. */ +/* + * Window 0 registers. Setup. + */ +/* Write */ +#define VX_W0_EEPROM_DATA 0x0c +#define VX_W0_EEPROM_COMMAND 0x0a +#define VX_W0_RESOURCE_CFG 0x08 +#define VX_W0_ADDRESS_CFG 0x06 +#define VX_W0_CONFIG_CTRL 0x04 + /* Read */ +#define VX_W0_PRODUCT_ID 0x02 +#define VX_W0_MFG_ID 0x00 + + +/* + * Window 1 registers. Operating Set. + */ +/* Write */ +#define VX_W1_TX_PIO_WR_2 0x02 +#define VX_W1_TX_PIO_WR_1 0x00 +/* Read */ +#define VX_W1_FREE_TX 0x0c +#define VX_W1_TX_STATUS 0x0b /* byte */ +#define VX_W1_TIMER 0x0a /* byte */ +#define VX_W1_RX_STATUS 0x08 +#define VX_W1_RX_PIO_RD_2 0x02 +#define VX_W1_RX_PIO_RD_1 0x00 + +/* + * Window 2 registers. Station Address Setup/Read + */ +/* Read/Write */ +#define VX_W2_ADDR_5 0x05 +#define VX_W2_ADDR_4 0x04 +#define VX_W2_ADDR_3 0x03 +#define VX_W2_ADDR_2 0x02 +#define VX_W2_ADDR_1 0x01 +#define VX_W2_ADDR_0 0x00 + +/* + * Window 3 registers. FIFO Management. + */ +/* Read */ +#define VX_W3_INTERNAL_CFG 0x00 +#define VX_W3_RESET_OPT 0x08 +#define VX_W3_FREE_TX 0x0c +#define VX_W3_FREE_RX 0x0a + +/* + * Window 4 registers. Diagnostics. + */ +/* Read/Write */ +#define VX_W4_MEDIA_TYPE 0x0a +#define VX_W4_CTRLR_STATUS 0x08 +#define VX_W4_NET_DIAG 0x06 +#define VX_W4_FIFO_DIAG 0x04 +#define VX_W4_HOST_DIAG 0x02 +#define VX_W4_TX_DIAG 0x00 + +/* + * Window 5 Registers. Results and Internal status. + */ +/* Read */ +#define VX_W5_READ_0_MASK 0x0c +#define VX_W5_INTR_MASK 0x0a +#define VX_W5_RX_FILTER 0x08 +#define VX_W5_RX_EARLY_THRESH 0x06 +#define VX_W5_TX_AVAIL_THRESH 0x02 +#define VX_W5_TX_START_THRESH 0x00 + +/* + * Window 6 registers. Statistics. + */ +/* Read/Write */ +#define TX_TOTAL_OK 0x0c +#define RX_TOTAL_OK 0x0a +#define TX_DEFERRALS 0x08 +#define RX_FRAMES_OK 0x07 +#define TX_FRAMES_OK 0x06 +#define RX_OVERRUNS 0x05 +#define TX_COLLISIONS 0x04 +#define TX_AFTER_1_COLLISION 0x03 +#define TX_AFTER_X_COLLISIONS 0x02 +#define TX_NO_SQE 0x01 +#define TX_CD_LOST 0x00 + +/**************************************** + * + * Register definitions. + * + ****************************************/ + +/* + * Command register. All windows. + * + * 16 bit register. + * 15-11: 5-bit code for command to be executed. + * 10-0: 11-bit arg if any. For commands with no args; + * this can be set to anything. + */ +#define GLOBAL_RESET (unsigned short) 0x0000 /* Wait at least 1ms + * after issuing */ +#define WINDOW_SELECT (unsigned short) (0x1<<11) +#define START_TRANSCEIVER (unsigned short) (0x2<<11) /* Read ADDR_CFG reg to + * determine whether + * this is needed. If + * so; wait 800 uSec + * before using trans- + * ceiver. */ +#define RX_DISABLE (unsigned short) (0x3<<11) /* state disabled on + * power-up */ +#define RX_ENABLE (unsigned short) (0x4<<11) +#define RX_RESET (unsigned short) (0x5<<11) +#define RX_DISCARD_TOP_PACK (unsigned short) (0x8<<11) +#define TX_ENABLE (unsigned short) (0x9<<11) +#define TX_DISABLE (unsigned short) (0xa<<11) +#define TX_RESET (unsigned short) (0xb<<11) +#define REQ_INTR (unsigned short) (0xc<<11) +/* + * The following C_* acknowledge the various interrupts. Some of them don't + * do anything. See the manual. + */ +#define ACK_INTR (unsigned short) (0x6800) +# define C_INTR_LATCH (unsigned short) (ACK_INTR|0x1) +# define C_CARD_FAILURE (unsigned short) (ACK_INTR|0x2) +# define C_TX_COMPLETE (unsigned short) (ACK_INTR|0x4) +# define C_TX_AVAIL (unsigned short) (ACK_INTR|0x8) +# define C_RX_COMPLETE (unsigned short) (ACK_INTR|0x10) +# define C_RX_EARLY (unsigned short) (ACK_INTR|0x20) +# define C_INT_RQD (unsigned short) (ACK_INTR|0x40) +# define C_UPD_STATS (unsigned short) (ACK_INTR|0x80) +#define SET_INTR_MASK (unsigned short) (0xe<<11) +#define SET_RD_0_MASK (unsigned short) (0xf<<11) +#define SET_RX_FILTER (unsigned short) (0x10<<11) +# define FIL_INDIVIDUAL (unsigned short) (0x1) +# define FIL_MULTICAST (unsigned short) (0x02) +# define FIL_BRDCST (unsigned short) (0x04) +# define FIL_PROMISC (unsigned short) (0x08) +#define SET_RX_EARLY_THRESH (unsigned short) (0x11<<11) +#define SET_TX_AVAIL_THRESH (unsigned short) (0x12<<11) +#define SET_TX_START_THRESH (unsigned short) (0x13<<11) +#define STATS_ENABLE (unsigned short) (0x15<<11) +#define STATS_DISABLE (unsigned short) (0x16<<11) +#define STOP_TRANSCEIVER (unsigned short) (0x17<<11) + +/* + * Status register. All windows. + * + * 15-13: Window number(0-7). + * 12: Command_in_progress. + * 11: reserved. + * 10: reserved. + * 9: reserved. + * 8: reserved. + * 7: Update Statistics. + * 6: Interrupt Requested. + * 5: RX Early. + * 4: RX Complete. + * 3: TX Available. + * 2: TX Complete. + * 1: Adapter Failure. + * 0: Interrupt Latch. + */ +#define S_INTR_LATCH (unsigned short) (0x1) +#define S_CARD_FAILURE (unsigned short) (0x2) +#define S_TX_COMPLETE (unsigned short) (0x4) +#define S_TX_AVAIL (unsigned short) (0x8) +#define S_RX_COMPLETE (unsigned short) (0x10) +#define S_RX_EARLY (unsigned short) (0x20) +#define S_INT_RQD (unsigned short) (0x40) +#define S_UPD_STATS (unsigned short) (0x80) +#define S_COMMAND_IN_PROGRESS (unsigned short) (0x1000) + +#define VX_BUSY_WAIT while (inw(BASE + VX_STATUS) & S_COMMAND_IN_PROGRESS) + +/* Address Config. Register. + * Window 0/Port 06 + */ + +#define ACF_CONNECTOR_BITS 14 +#define ACF_CONNECTOR_UTP 0 +#define ACF_CONNECTOR_AUI 1 +#define ACF_CONNECTOR_BNC 3 + +#define INTERNAL_CONNECTOR_BITS 20 +#define INTERNAL_CONNECTOR_MASK 0x01700000 + +/* + * FIFO Registers. RX Status. + * + * 15: Incomplete or FIFO empty. + * 14: 1: Error in RX Packet 0: Incomplete or no error. + * 13-11: Type of error. + * 1000 = Overrun. + * 1011 = Run Packet Error. + * 1100 = Alignment Error. + * 1101 = CRC Error. + * 1001 = Oversize Packet Error (>1514 bytes) + * 0010 = Dribble Bits. + * (all other error codes, no errors.) + * + * 10-0: RX Bytes (0-1514) + */ +#define ERR_INCOMPLETE (unsigned short) (0x8000) +#define ERR_RX (unsigned short) (0x4000) +#define ERR_MASK (unsigned short) (0x7800) +#define ERR_OVERRUN (unsigned short) (0x4000) +#define ERR_RUNT (unsigned short) (0x5800) +#define ERR_ALIGNMENT (unsigned short) (0x6000) +#define ERR_CRC (unsigned short) (0x6800) +#define ERR_OVERSIZE (unsigned short) (0x4800) +#define ERR_DRIBBLE (unsigned short) (0x1000) + +/* + * TX Status. + * + * Reports the transmit status of a completed transmission. Writing this + * register pops the transmit completion stack. + * + * Window 1/Port 0x0b. + * + * 7: Complete + * 6: Interrupt on successful transmission requested. + * 5: Jabber Error (TP Only, TX Reset required. ) + * 4: Underrun (TX Reset required. ) + * 3: Maximum Collisions. + * 2: TX Status Overflow. + * 1-0: Undefined. + * + */ +#define TXS_COMPLETE 0x80 +#define TXS_INTR_REQ 0x40 +#define TXS_JABBER 0x20 +#define TXS_UNDERRUN 0x10 +#define TXS_MAX_COLLISION 0x8 +#define TXS_STATUS_OVERFLOW 0x4 + +#define RS_AUI (1<<5) +#define RS_BNC (1<<4) +#define RS_UTP (1<<3) +#define RS_T4 (1<<0) +#define RS_TX (1<<1) +#define RS_FX (1<<2) +#define RS_MII (1<<6) + + +/* + * FIFO Status (Window 4) + * + * Supports FIFO diagnostics + * + * Window 4/Port 0x04.1 + * + * 15: 1=RX receiving (RO). Set when a packet is being received + * into the RX FIFO. + * 14: Reserved + * 13: 1=RX underrun (RO). Generates Adapter Failure interrupt. + * Requires RX Reset or Global Reset command to recover. + * It is generated when you read past the end of a packet - + * reading past what has been received so far will give bad + * data. + * 12: 1=RX status overrun (RO). Set when there are already 8 + * packets in the RX FIFO. While this bit is set, no additional + * packets are received. Requires no action on the part of + * the host. The condition is cleared once a packet has been + * read out of the RX FIFO. + * 11: 1=RX overrun (RO). Set when the RX FIFO is full (there + * may not be an overrun packet yet). While this bit is set, + * no additional packets will be received (some additional + * bytes can still be pending between the wire and the RX + * FIFO). Requires no action on the part of the host. The + * condition is cleared once a few bytes have been read out + * from the RX FIFO. + * 10: 1=TX overrun (RO). Generates adapter failure interrupt. + * Requires TX Reset or Global Reset command to recover. + * Disables Transmitter. + * 9-8: Unassigned. + * 7-0: Built in self test bits for the RX and TX FIFO's. + */ +#define FIFOS_RX_RECEIVING (unsigned short) 0x8000 +#define FIFOS_RX_UNDERRUN (unsigned short) 0x2000 +#define FIFOS_RX_STATUS_OVERRUN (unsigned short) 0x1000 +#define FIFOS_RX_OVERRUN (unsigned short) 0x0800 +#define FIFOS_TX_OVERRUN (unsigned short) 0x0400 + +/* + * Misc defines for various things. + */ +#define TAG_ADAPTER 0xd0 +#define ACTIVATE_ADAPTER_TO_CONFIG 0xff +#define ENABLE_DRQ_IRQ 0x0001 +#define MFG_ID 0x506d /* `TCM' */ +#define PROD_ID 0x5090 +#define GO_WINDOW(x) outw(WINDOW_SELECT|(x),BASE+VX_COMMAND) +#define JABBER_GUARD_ENABLE 0x40 +#define LINKBEAT_ENABLE 0x80 +#define ENABLE_UTP (JABBER_GUARD_ENABLE | LINKBEAT_ENABLE) +#define DISABLE_UTP 0x0 +#define RX_BYTES_MASK (unsigned short) (0x07ff) +#define RX_ERROR 0x4000 +#define RX_INCOMPLETE 0x8000 +#define TX_INDICATE 1<<15 +#define is_eeprom_busy(b) (inw((b)+VX_W0_EEPROM_COMMAND)&EEPROM_BUSY) + +#define VX_IOSIZE 0x20 + +#define VX_CONNECTORS 8 + +/* + * Local variables: + * c-basic-offset: 8 + * End: + */ diff --git a/drivers/5701rls.c b/drivers/5701rls.c new file mode 100644 index 0000000..c4409e4 --- /dev/null +++ b/drivers/5701rls.c @@ -0,0 +1,46 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/* */ +/******************************************************************************/ + +#if INCLUDE_5701_AX_FIX + +#include "bcm570x_mm.h" +#include "5701rls.h" + +LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice) +{ + T3_FWIMG_INFO FwImgInfo; + + FwImgInfo.StartAddress = t3FwStartAddr; + FwImgInfo.Text.Buffer = (PLM_UINT8)t3FwText; + FwImgInfo.Text.Offset = t3FwTextAddr; + FwImgInfo.Text.Length = t3FwTextLen; + FwImgInfo.ROnlyData.Buffer = (PLM_UINT8)t3FwRodata; + FwImgInfo.ROnlyData.Offset = t3FwRodataAddr; + FwImgInfo.ROnlyData.Length = t3FwRodataLen; + FwImgInfo.Data.Buffer = (PLM_UINT8)t3FwData; + FwImgInfo.Data.Offset = t3FwDataAddr; + FwImgInfo.Data.Length = t3FwDataLen; + + if (LM_LoadFirmware(pDevice, + &FwImgInfo, + T3_RX_CPU_ID | T3_TX_CPU_ID, + T3_RX_CPU_ID) != LM_STATUS_SUCCESS) + { + return LM_STATUS_FAILURE; + } + + return LM_STATUS_SUCCESS; +} + +#endif /* INCLUDE_5701_AX_FIX */ diff --git a/drivers/5701rls.h b/drivers/5701rls.h new file mode 100644 index 0000000..30b127a --- /dev/null +++ b/drivers/5701rls.h @@ -0,0 +1,198 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ + +typedef unsigned long U32; +int t3FwReleaseMajor = 0x0; +int t3FwReleaseMinor = 0x0; +int t3FwReleaseFix = 0x0; +U32 t3FwStartAddr = 0x08000000; +U32 t3FwTextAddr = 0x08000000; +int t3FwTextLen = 0x9c0; +U32 t3FwRodataAddr = 0x080009c0; +int t3FwRodataLen = 0x60; +U32 t3FwDataAddr = 0x08000a40; +int t3FwDataLen = 0x20; +U32 t3FwSbssAddr = 0x08000a60; +int t3FwSbssLen = 0xc; +U32 t3FwBssAddr = 0x08000a70; +int t3FwBssLen = 0x10; +U32 t3FwText[(0x9c0/4) + 1] = { +0x0, +0x10000003, 0x0, 0xd, 0xd, +0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, +0x26100000, 0xe000018, 0x0, 0xd, +0x3c1d0800, 0x37bd3ffc, 0x3a0f021, 0x3c100800, +0x26100034, 0xe00021c, 0x0, 0xd, +0x0, 0x0, 0x0, 0x27bdffe0, +0x3c1cc000, 0xafbf0018, 0xaf80680c, 0xe00004c, +0x241b2105, 0x97850000, 0x97870002, 0x9782002c, +0x9783002e, 0x3c040800, 0x248409c0, 0xafa00014, +0x21400, 0x621825, 0x52c00, 0xafa30010, +0x8f860010, 0xe52825, 0xe000060, 0x24070102, +0x3c02ac00, 0x34420100, 0x3c03ac01, 0x34630100, +0xaf820490, 0x3c02ffff, 0xaf820494, 0xaf830498, +0xaf82049c, 0x24020001, 0xaf825ce0, 0xe00003f, +0xaf825d00, 0xe000140, 0x0, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x2402ffff, 0xaf825404, +0x8f835400, 0x34630400, 0xaf835400, 0xaf825404, +0x3c020800, 0x24420034, 0xaf82541c, 0x3e00008, +0xaf805400, 0x0, 0x0, 0x3c020800, +0x34423000, 0x3c030800, 0x34633000, 0x3c040800, +0x348437ff, 0x3c010800, 0xac220a64, 0x24020040, +0x3c010800, 0xac220a68, 0x3c010800, 0xac200a60, +0xac600000, 0x24630004, 0x83102b, 0x5040fffd, +0xac600000, 0x3e00008, 0x0, 0x804821, +0x8faa0010, 0x3c020800, 0x8c420a60, 0x3c040800, +0x8c840a68, 0x8fab0014, 0x24430001, 0x44102b, +0x3c010800, 0xac230a60, 0x14400003, 0x4021, +0x3c010800, 0xac200a60, 0x3c020800, 0x8c420a60, +0x3c030800, 0x8c630a64, 0x91240000, 0x21140, +0x431021, 0x481021, 0x25080001, 0xa0440000, +0x29020008, 0x1440fff4, 0x25290001, 0x3c020800, +0x8c420a60, 0x3c030800, 0x8c630a64, 0x8f84680c, +0x21140, 0x431021, 0xac440008, 0xac45000c, +0xac460010, 0xac470014, 0xac4a0018, 0x3e00008, +0xac4b001c, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x2000008, +0x0, 0xa0001e3, 0x3c0a0001, 0xa0001e3, +0x3c0a0002, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x3c0a0007, 0xa0001e3, 0x3c0a0008, 0xa0001e3, +0x3c0a0009, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x3c0a000b, 0xa0001e3, +0x3c0a000c, 0xa0001e3, 0x3c0a000d, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x3c0a000e, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x0, 0xa0001e3, +0x0, 0xa0001e3, 0x3c0a0013, 0xa0001e3, +0x3c0a0014, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x27bdffe0, +0x1821, 0x1021, 0xafbf0018, 0xafb10014, +0xafb00010, 0x3c010800, 0x220821, 0xac200a70, +0x3c010800, 0x220821, 0xac200a74, 0x3c010800, +0x220821, 0xac200a78, 0x24630001, 0x1860fff5, +0x2442000c, 0x24110001, 0x8f906810, 0x32020004, +0x14400005, 0x24040001, 0x3c020800, 0x8c420a78, +0x18400003, 0x2021, 0xe000182, 0x0, +0x32020001, 0x10400003, 0x0, 0xe000169, +0x0, 0xa000153, 0xaf915028, 0x8fbf0018, +0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0020, +0x3c050800, 0x8ca50a70, 0x3c060800, 0x8cc60a80, +0x3c070800, 0x8ce70a78, 0x27bdffe0, 0x3c040800, +0x248409d0, 0xafbf0018, 0xafa00010, 0xe000060, +0xafa00014, 0xe00017b, 0x2021, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x24020001, 0x8f836810, +0x821004, 0x21027, 0x621824, 0x3e00008, +0xaf836810, 0x27bdffd8, 0xafbf0024, 0x1080002e, +0xafb00020, 0x8f825cec, 0xafa20018, 0x8f825cec, +0x3c100800, 0x26100a78, 0xafa2001c, 0x34028000, +0xaf825cec, 0x8e020000, 0x18400016, 0x0, +0x3c020800, 0x94420a74, 0x8fa3001c, 0x221c0, +0xac830004, 0x8fa2001c, 0x3c010800, 0xe000201, +0xac220a74, 0x10400005, 0x0, 0x8e020000, +0x24420001, 0xa0001df, 0xae020000, 0x3c020800, +0x8c420a70, 0x21c02, 0x321c0, 0xa0001c5, +0xafa2001c, 0xe000201, 0x0, 0x1040001f, +0x0, 0x8e020000, 0x8fa3001c, 0x24420001, +0x3c010800, 0xac230a70, 0x3c010800, 0xac230a74, +0xa0001df, 0xae020000, 0x3c100800, 0x26100a78, +0x8e020000, 0x18400028, 0x0, 0xe000201, +0x0, 0x14400024, 0x0, 0x8e020000, +0x3c030800, 0x8c630a70, 0x2442ffff, 0xafa3001c, +0x18400006, 0xae020000, 0x31402, 0x221c0, +0x8c820004, 0x3c010800, 0xac220a70, 0x97a2001e, +0x2442ff00, 0x2c420300, 0x1440000b, 0x24024000, +0x3c040800, 0x248409dc, 0xafa00010, 0xafa00014, +0x8fa6001c, 0x24050008, 0xe000060, 0x3821, +0xa0001df, 0x0, 0xaf825cf8, 0x3c020800, +0x8c420a40, 0x8fa3001c, 0x24420001, 0xaf835cf8, +0x3c010800, 0xac220a40, 0x8fbf0024, 0x8fb00020, +0x3e00008, 0x27bd0028, 0x27bdffe0, 0x3c040800, +0x248409e8, 0x2821, 0x3021, 0x3821, +0xafbf0018, 0xafa00010, 0xe000060, 0xafa00014, +0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8f82680c, +0x8f85680c, 0x21827, 0x3182b, 0x31823, +0x431024, 0x441021, 0xa2282b, 0x10a00006, +0x0, 0x401821, 0x8f82680c, 0x43102b, +0x1440fffd, 0x0, 0x3e00008, 0x0, +0x3c040800, 0x8c840000, 0x3c030800, 0x8c630a40, +0x64102b, 0x54400002, 0x831023, 0x641023, +0x2c420008, 0x3e00008, 0x38420001, 0x27bdffe0, +0x802821, 0x3c040800, 0x24840a00, 0x3021, +0x3821, 0xafbf0018, 0xafa00010, 0xe000060, +0xafa00014, 0xa000216, 0x0, 0x8fbf0018, +0x3e00008, 0x27bd0020, 0x0, 0x27bdffe0, +0x3c1cc000, 0xafbf0018, 0xe00004c, 0xaf80680c, +0x3c040800, 0x24840a10, 0x3802821, 0x3021, +0x3821, 0xafa00010, 0xe000060, 0xafa00014, +0x2402ffff, 0xaf825404, 0x3c0200aa, 0xe000234, +0xaf825434, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0x0, 0x0, 0x0, 0x27bdffe8, +0xafb00010, 0x24100001, 0xafbf0014, 0x3c01c003, +0xac200000, 0x8f826810, 0x30422000, 0x10400003, +0x0, 0xe000246, 0x0, 0xa00023a, +0xaf905428, 0x8fbf0014, 0x8fb00010, 0x3e00008, +0x27bd0018, 0x27bdfff8, 0x8f845d0c, 0x3c0200ff, +0x3c030800, 0x8c630a50, 0x3442fff8, 0x821024, +0x1043001e, 0x3c0500ff, 0x34a5fff8, 0x3c06c003, +0x3c074000, 0x851824, 0x8c620010, 0x3c010800, +0xac230a50, 0x30420008, 0x10400005, 0x871025, +0x8cc20000, 0x24420001, 0xacc20000, 0x871025, +0xaf825d0c, 0x8fa20000, 0x24420001, 0xafa20000, +0x8fa20000, 0x8fa20000, 0x24420001, 0xafa20000, +0x8fa20000, 0x8f845d0c, 0x3c030800, 0x8c630a50, +0x851024, 0x1443ffe8, 0x851824, 0x27bd0008, +0x3e00008, 0x0, 0x0, 0x0 }; +U32 t3FwRodata[(0x60/4) + 1] = { +0x35373031, 0x726c7341, 0x0, +0x0, 0x53774576, 0x656e7430, 0x0, +0x726c7045, 0x76656e74, 0x31000000, 0x556e6b6e, +0x45766e74, 0x0, 0x0, 0x0, +0x0, 0x66617461, 0x6c457272, 0x0, +0x0, 0x4d61696e, 0x43707542, 0x0, +0x0, 0x0 }; +U32 t3FwData[(0x20/4) + 1] = { +0x0, 0x0, 0x0, +0x0, 0x0, 0x0, 0x0, +0x0, 0x0 }; diff --git a/drivers/bcm570x_autoneg.h b/drivers/bcm570x_autoneg.h new file mode 100644 index 0000000..95fcc07 --- /dev/null +++ b/drivers/bcm570x_autoneg.h @@ -0,0 +1,415 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2001 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ + + +#ifndef AUTONEG_H +#define AUTONEG_H + + + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +#define AN_LINK_TIMER_INTERVAL_US 9000 /* 10ms */ + +/* TRUE, FALSE */ +#define AN_TRUE 1 +#define AN_FALSE 0 + + + +/******************************************************************************/ +/* Main data structure for keeping track of 802.3z auto-negotation state */ +/* variables as shown in Figure 37-6 of the IEEE 802.3z specification. */ +/******************************************************************************/ + +typedef struct +{ + /* Current auto-negotiation state. */ + unsigned long State; + #define AN_STATE_UNKNOWN 0 + #define AN_STATE_AN_ENABLE 1 + #define AN_STATE_AN_RESTART_INIT 2 + #define AN_STATE_AN_RESTART 3 + #define AN_STATE_DISABLE_LINK_OK 4 + #define AN_STATE_ABILITY_DETECT_INIT 5 + #define AN_STATE_ABILITY_DETECT 6 + #define AN_STATE_ACK_DETECT_INIT 7 + #define AN_STATE_ACK_DETECT 8 + #define AN_STATE_COMPLETE_ACK_INIT 9 + #define AN_STATE_COMPLETE_ACK 10 + #define AN_STATE_IDLE_DETECT_INIT 11 + #define AN_STATE_IDLE_DETECT 12 + #define AN_STATE_LINK_OK 13 + #define AN_STATE_NEXT_PAGE_WAIT_INIT 14 + #define AN_STATE_NEXT_PAGE_WAIT 16 + + /* Link timer. */ + unsigned long LinkTime_us; + + /* Current time. */ + unsigned long CurrentTime_us; + + /* Need these values for consistency check. */ + unsigned short AbilityMatchCfg; + + /* Ability, idle, and ack match functions. */ + unsigned long AbilityMatchCnt; + char AbilityMatch; + char IdleMatch; + char AckMatch; + + /* Tx config data */ + union + { + /* The TxConfig register is arranged as follows: */ + /* */ + /* MSB LSB */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + struct + { +#ifdef BIG_ENDIAN_HOST + unsigned int D7:1; /* PS1 */ + unsigned int D6:1; /* HD */ + unsigned int D5:1; /* FD */ + unsigned int D4:1; + unsigned int D3:1; + unsigned int D2:1; + unsigned int D1:1; + unsigned int D0:1; + unsigned int D15:1; /* NP */ + unsigned int D14:1; /* ACK */ + unsigned int D13:1; /* RF2 */ + unsigned int D12:1; /* RF1 */ + unsigned int D11:1; + unsigned int D10:1; + unsigned int D9:1; + unsigned int D8:1; /* PS2 */ +#else /* BIG_ENDIAN_HOST */ + unsigned int D8:1; /* PS2 */ + unsigned int D9:1; + unsigned int D10:1; + unsigned int D11:1; + unsigned int D12:1; /* RF1 */ + unsigned int D13:1; /* RF2 */ + unsigned int D14:1; /* ACK */ + unsigned int D15:1; /* NP */ + unsigned int D0:1; + unsigned int D1:1; + unsigned int D2:1; + unsigned int D3:1; + unsigned int D4:1; + unsigned int D5:1; /* FD */ + unsigned int D6:1; /* HD */ + unsigned int D7:1; /* PS1 */ +#endif + } bits; + + unsigned short AsUSHORT; + + #define D8_PS2 bits.D8 + #define D12_RF1 bits.D12 + #define D13_RF2 bits.D13 + #define D14_ACK bits.D14 + #define D15_NP bits.D15 + #define D5_FD bits.D5 + #define D6_HD bits.D6 + #define D7_PS1 bits.D7 + } TxConfig; + + /* Rx config data */ + union + { + /* The RxConfig register is arranged as follows: */ + /* */ + /* MSB LSB */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + /* | D7| D6| D5| D4| D3| D2| D1| D0|D15|D14|D13|D12|D11|D10| D9| D8| */ + /* +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+ */ + struct + { +#ifdef BIG_ENDIAN_HOST + unsigned int D7:1; /* PS1 */ + unsigned int D6:1; /* HD */ + unsigned int D5:1; /* FD */ + unsigned int D4:1; + unsigned int D3:1; + unsigned int D2:1; + unsigned int D1:1; + unsigned int D0:1; + unsigned int D15:1; /* NP */ + unsigned int D14:1; /* ACK */ + unsigned int D13:1; /* RF2 */ + unsigned int D12:1; /* RF1 */ + unsigned int D11:1; + unsigned int D10:1; + unsigned int D9:1; + unsigned int D8:1; /* PS2 */ +#else /* BIG_ENDIAN_HOST */ + unsigned int D8:1; /* PS2 */ + unsigned int D9:1; + unsigned int D10:1; + unsigned int D11:1; + unsigned int D12:1; /* RF1 */ + unsigned int D13:1; /* RF2 */ + unsigned int D14:1; /* ACK */ + unsigned int D15:1; /* NP */ + unsigned int D0:1; + unsigned int D1:1; + unsigned int D2:1; + unsigned int D3:1; + unsigned int D4:1; + unsigned int D5:1; /* FD */ + unsigned int D6:1; /* HD */ + unsigned int D7:1; /* PS1 */ +#endif + } bits; + + unsigned short AsUSHORT; + } RxConfig; + + #define AN_CONFIG_NP 0x0080 + #define AN_CONFIG_ACK 0x0040 + #define AN_CONFIG_RF2 0x0020 + #define AN_CONFIG_RF1 0x0010 + #define AN_CONFIG_PS2 0x0001 + #define AN_CONFIG_PS1 0x8000 + #define AN_CONFIG_HD 0x4000 + #define AN_CONFIG_FD 0x2000 + + + /* Management registers. */ + + /* Control register. */ + union + { + struct + { + unsigned int an_enable:1; + unsigned int loopback:1; + unsigned int reset:1; + unsigned int restart_an:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_an_enable Mr0.bits.an_enable + #define mr_loopback Mr0.bits.loopback + #define mr_main_reset Mr0.bits.reset + #define mr_restart_an Mr0.bits.restart_an + } Mr0; + + /* Status register. */ + union + { + struct + { + unsigned int an_complete:1; + unsigned int link_ok:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_an_complete Mr1.bits.an_complete + #define mr_link_ok Mr1.bits.link_ok + } Mr1; + + /* Advertisement register. */ + union + { + struct + { + unsigned int reserved_4:5; + unsigned int full_duplex:1; + unsigned int half_duplex:1; + unsigned int sym_pause:1; + unsigned int asym_pause:1; + unsigned int reserved_11:3; + unsigned int remote_fault1:1; + unsigned int remote_fault2:1; + unsigned int reserved_14:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_adv_full_duplex Mr4.bits.full_duplex + #define mr_adv_half_duplex Mr4.bits.half_duplex + #define mr_adv_sym_pause Mr4.bits.sym_pause + #define mr_adv_asym_pause Mr4.bits.asym_pause + #define mr_adv_remote_fault1 Mr4.bits.remote_fault1 + #define mr_adv_remote_fault2 Mr4.bits.remote_fault2 + #define mr_adv_next_page Mr4.bits.next_page + } Mr4; + + /* Link partner advertisement register. */ + union + { + struct + { + unsigned int reserved_4:5; + unsigned int lp_full_duplex:1; + unsigned int lp_half_duplex:1; + unsigned int lp_sym_pause:1; + unsigned int lp_asym_pause:1; + unsigned int reserved_11:3; + unsigned int lp_remote_fault1:1; + unsigned int lp_remote_fault2:1; + unsigned int lp_ack:1; + unsigned int lp_next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_lp_adv_full_duplex Mr5.bits.lp_full_duplex + #define mr_lp_adv_half_duplex Mr5.bits.lp_half_duplex + #define mr_lp_adv_sym_pause Mr5.bits.lp_sym_pause + #define mr_lp_adv_asym_pause Mr5.bits.lp_asym_pause + #define mr_lp_adv_remote_fault1 Mr5.bits.lp_remote_fault1 + #define mr_lp_adv_remote_fault2 Mr5.bits.lp_remote_fault2 + #define mr_lp_adv_next_page Mr5.bits.lp_next_page + } Mr5; + + /* Auto-negotiation expansion register. */ + union + { + struct + { + unsigned int reserved_0:1; + unsigned int page_received:1; + unsigned int next_pageable:1; + unsigned int reserved_15:13; + } bits; + + unsigned short AsUSHORT; + } Mr6; + + /* Auto-negotiation next page transmit register. */ + union + { + struct + { + unsigned int code_field:11; + unsigned int toggle:1; + unsigned int ack2:1; + unsigned int message_page:1; + unsigned int reserved_14:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_np_tx Mr7.AsUSHORT + } Mr7; + + /* Auto-negotiation link partner ability register. */ + union + { + struct + { + unsigned int code_field:11; + unsigned int toggle:1; + unsigned int ack2:1; + unsigned int message_page:1; + unsigned int ack:1; + unsigned int next_page:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_lp_np_rx Mr8.AsUSHORT + } Mr8; + + /* Extended status register. */ + union + { + struct + { + unsigned int reserved_11:12; + unsigned int base1000_t_hd:1; + unsigned int base1000_t_fd:1; + unsigned int base1000_x_hd:1; + unsigned int base1000_x_fd:1; + } bits; + + unsigned short AsUSHORT; + } Mr15; + + /* Miscellaneous state variables. */ + union + { + struct + { + unsigned int toggle_tx:1; + unsigned int toggle_rx:1; + unsigned int np_rx:1; + unsigned int page_rx:1; + unsigned int np_loaded:1; + } bits; + + unsigned short AsUSHORT; + + #define mr_toggle_tx MrMisc.bits.toggle_tx + #define mr_toggle_rx MrMisc.bits.toggle_rx + #define mr_np_rx MrMisc.bits.np_rx + #define mr_page_rx MrMisc.bits.page_rx + #define mr_np_loaded MrMisc.bits.np_loaded + } MrMisc; + + + /* Implement specifics */ + + /* Pointer to the operating system specific data structure. */ + void *pContext; +} AN_STATE_INFO, *PAN_STATE_INFO; + + + +/******************************************************************************/ +/* Return code of Autoneg8023z. */ +/******************************************************************************/ + +typedef enum +{ + AUTONEG_STATUS_OK = 0, + AUTONEG_STATUS_DONE = 1, + AUTONEG_STATUS_TIMER_ENABLED = 2, + AUTONEG_STATUS_FAILED = 0xfffffff +} AUTONEG_STATUS, *PAUTONEG_STATUS; + + + +/******************************************************************************/ +/* Function prototypes. */ +/******************************************************************************/ + +AUTONEG_STATUS Autoneg8023z(PAN_STATE_INFO pAnInfo); +void AutonegInit(PAN_STATE_INFO pAnInfo); + + + +/******************************************************************************/ +/* The following functions are defined in the os-dependent module. */ +/******************************************************************************/ + +void MM_AnTxConfig(PAN_STATE_INFO pAnInfo); +void MM_AnTxIdle(PAN_STATE_INFO pAnInfo); +char MM_AnRxConfig(PAN_STATE_INFO pAnInfo, unsigned short *pRxConfig); + + + +#endif /* AUTONEG_H */ + diff --git a/drivers/bcm570x_debug.h b/drivers/bcm570x_debug.h new file mode 100644 index 0000000..0a688cf --- /dev/null +++ b/drivers/bcm570x_debug.h @@ -0,0 +1,111 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef DEBUG_H +#define DEBUG_H + +#ifdef VXWORKS +#include <vxWorks.h> +#endif + +/******************************************************************************/ +/* Debug macros */ +/******************************************************************************/ + +/* Code path for controlling output debug messages. */ +/* Define your code path here. */ +#define CP_INIT 0x010000 +#define CP_SEND 0x020000 +#define CP_RCV 0x040000 +#define CP_INT 0x080000 +#define CP_UINIT 0x100000 +#define CP_RESET 0x200000 + +#define CP_ALL (CP_INIT | CP_SEND | CP_RCV | CP_INT | \ + CP_RESET | CP_UINIT) + +#define CP_MASK 0xffff0000 + + +/* Debug message levels. */ +#define LV_VERBOSE 0x03 +#define LV_INFORM 0x02 +#define LV_WARN 0x01 +#define LV_FATAL 0x00 + +#define LV_MASK 0xffff + + +/* Code path and messsage level combined. These are the first argument of */ +/* the DbgMessage macro. */ +#define INIT_V (CP_INIT | LV_VERBOSE) +#define INIT_I (CP_INIT | LV_INFORM) +#define INIT_W (CP_INIT | LV_WARN) +#define SEND_V (CP_SEND | LV_VERBOSE) +#define SEND_I (CP_SEND | LV_INFORM) +#define SEND_W (CP_SEND | LV_WARN) +#define RCV_V (CP_RCV | LV_VERBOSE) +#define RCV_I (CP_RCV | LV_INFORM) +#define RCV_W (CP_RCV | LV_WARN) +#define INT_V (CP_INT | LV_VERBOSE) +#define INT_I (CP_INT | LV_INFORM) +#define INT_W (CP_INT | LV_WARN) +#define UINIT_V (CP_UINIT | LV_VERBOSE) +#define UINIT_I (CP_UINIT | LV_INFORM) +#define UINIT_W (CP_UINIT | LV_WARN) +#define RESET_V (CP_RESET | LV_VERBOSE) +#define RESET_I (CP_RESET | LV_INFORM) +#define RESET_W (CP_RESET | LV_WARN) +#define CPALL_V (CP_ALL | LV_VERBOSE) +#define CPALL_I (CP_ALL | LV_INFORM) +#define CPALL_W (CP_ALL | LV_WARN) + + +/* All code path message levels. */ +#define FATAL (CP_ALL | LV_FATAL) +#define WARN (CP_ALL | LV_WARN) +#define INFORM (CP_ALL | LV_INFORM) +#define VERBOSE (CP_ALL | LV_VERBOSE) + + +/* These constants control the message output. */ +/* Set your debug message output level and code path here. */ +#ifndef DBG_MSG_CP +#define DBG_MSG_CP CP_ALL /* Where to output messages. */ +#endif + +#ifndef DBG_MSG_LV +#define DBG_MSG_LV LV_VERBOSE /* Level of message output. */ +#endif + +/* DbgMessage macro. */ +#if DBG +#define DbgMessage(CNTRL, MESSAGE) \ + if((CNTRL & DBG_MSG_CP) && ((CNTRL & LV_MASK) <= DBG_MSG_LV)) \ + printf MESSAGE +#define DbgBreak() DbgBreakPoint() +#undef STATIC +#define STATIC +#else +#define DbgMessage(CNTRL, MESSAGE) +#define DbgBreak() +#undef STATIC +#define STATIC static +#endif /* DBG */ + + + +#endif /* DEBUG_H */ + diff --git a/drivers/bcm570x_lm.h b/drivers/bcm570x_lm.h new file mode 100644 index 0000000..79073a8 --- /dev/null +++ b/drivers/bcm570x_lm.h @@ -0,0 +1,469 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef LM_H +#define LM_H + +#include "bcm570x_queue.h" +#include "bcm570x_bits.h" + + + +/******************************************************************************/ +/* Basic types. */ +/******************************************************************************/ + +typedef char LM_CHAR, *PLM_CHAR; +typedef unsigned int LM_UINT, *PLM_UINT; +typedef unsigned char LM_UINT8, *PLM_UINT8; +typedef unsigned short LM_UINT16, *PLM_UINT16; +typedef unsigned int LM_UINT32, *PLM_UINT32; +typedef unsigned int LM_COUNTER, *PLM_COUNTER; +typedef void LM_VOID, *PLM_VOID; +typedef char LM_BOOL, *PLM_BOOL; + +/* 64bit value. */ +typedef struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT32 High; + LM_UINT32 Low; +#else /* BIG_ENDIAN_HOST */ + LM_UINT32 Low; + LM_UINT32 High; +#endif /* !BIG_ENDIAN_HOST */ +} LM_UINT64, *PLM_UINT64; + +typedef LM_UINT64 LM_PHYSICAL_ADDRESS, *PLM_PHYSICAL_ADDRESS; + +/* void LM_INC_PHYSICAL_ADDRESS(PLM_PHYSICAL_ADDRESS pAddr,LM_UINT32 IncSize) */ +#define LM_INC_PHYSICAL_ADDRESS(pAddr, IncSize) \ + { \ + LM_UINT32 OrgLow; \ + \ + OrgLow = (pAddr)->Low; \ + (pAddr)->Low += IncSize; \ + if((pAddr)->Low < OrgLow) { \ + (pAddr)->High++; /* Wrap around. */ \ + } \ + } + + +#ifndef NULL +#define NULL ((void *) 0) +#endif /* NULL */ + +#ifndef OFFSETOF +#define OFFSETOF(_s, _m) (MM_UINT_PTR(&(((_s *) 0)->_m))) +#endif /* OFFSETOF */ + + + +/******************************************************************************/ +/* Simple macros. */ +/******************************************************************************/ + +#define IS_ETH_BROADCAST(_pEthAddr) \ + (((unsigned char *) (_pEthAddr))[0] == ((unsigned char) 0xff)) + +#define IS_ETH_MULTICAST(_pEthAddr) \ + (((unsigned char *) (_pEthAddr))[0] & ((unsigned char) 0x01)) + +#define IS_ETH_ADDRESS_EQUAL(_pEtherAddr1, _pEtherAddr2) \ + ((((unsigned char *) (_pEtherAddr1))[0] == \ + ((unsigned char *) (_pEtherAddr2))[0]) && \ + (((unsigned char *) (_pEtherAddr1))[1] == \ + ((unsigned char *) (_pEtherAddr2))[1]) && \ + (((unsigned char *) (_pEtherAddr1))[2] == \ + ((unsigned char *) (_pEtherAddr2))[2]) && \ + (((unsigned char *) (_pEtherAddr1))[3] == \ + ((unsigned char *) (_pEtherAddr2))[3]) && \ + (((unsigned char *) (_pEtherAddr1))[4] == \ + ((unsigned char *) (_pEtherAddr2))[4]) && \ + (((unsigned char *) (_pEtherAddr1))[5] == \ + ((unsigned char *) (_pEtherAddr2))[5])) + +#define COPY_ETH_ADDRESS(_Src, _Dst) \ + ((unsigned char *) (_Dst))[0] = ((unsigned char *) (_Src))[0]; \ + ((unsigned char *) (_Dst))[1] = ((unsigned char *) (_Src))[1]; \ + ((unsigned char *) (_Dst))[2] = ((unsigned char *) (_Src))[2]; \ + ((unsigned char *) (_Dst))[3] = ((unsigned char *) (_Src))[3]; \ + ((unsigned char *) (_Dst))[4] = ((unsigned char *) (_Src))[4]; \ + ((unsigned char *) (_Dst))[5] = ((unsigned char *) (_Src))[5]; + + + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +#define ETHERNET_ADDRESS_SIZE 6 +#define ETHERNET_PACKET_HEADER_SIZE 14 +#define MIN_ETHERNET_PACKET_SIZE 64 /* with 4 byte crc. */ +#define MAX_ETHERNET_PACKET_SIZE 1518 /* with 4 byte crc. */ +#define MIN_ETHERNET_PACKET_SIZE_NO_CRC 60 +#define MAX_ETHERNET_PACKET_SIZE_NO_CRC 1514 +#define MAX_ETHERNET_PACKET_BUFFER_SIZE 1536 /* A nice even number. */ + +#ifndef LM_MAX_MC_TABLE_SIZE +#define LM_MAX_MC_TABLE_SIZE 32 +#endif /* LM_MAX_MC_TABLE_SIZE */ +#define LM_MC_ENTRY_SIZE (ETHERNET_ADDRESS_SIZE+1) +#define LM_MC_INSTANCE_COUNT_INDEX (LM_MC_ENTRY_SIZE-1) + + +/* Receive filter masks. */ +#define LM_ACCEPT_UNICAST 0x0001 +#define LM_ACCEPT_MULTICAST 0x0002 +#define LM_ACCEPT_ALL_MULTICAST 0x0004 +#define LM_ACCEPT_BROADCAST 0x0008 +#define LM_ACCEPT_ERROR_PACKET 0x0010 + +#define LM_PROMISCUOUS_MODE 0x10000 + + + +/******************************************************************************/ +/* PCI registers. */ +/******************************************************************************/ + +#define PCI_VENDOR_ID_REG 0x00 +#define PCI_DEVICE_ID_REG 0x02 + +#define PCI_COMMAND_REG 0x04 +#define PCI_IO_SPACE_ENABLE 0x0001 +#define PCI_MEM_SPACE_ENABLE 0x0002 +#define PCI_BUSMASTER_ENABLE 0x0004 +#define PCI_MEMORY_WRITE_INVALIDATE 0x0010 +#define PCI_PARITY_ERROR_ENABLE 0x0040 +#define PCI_SYSTEM_ERROR_ENABLE 0x0100 +#define PCI_FAST_BACK_TO_BACK_ENABLE 0x0200 + +#define PCI_STATUS_REG 0x06 +#define PCI_REV_ID_REG 0x08 + +#define PCI_CACHE_LINE_SIZE_REG 0x0c + +#define PCI_IO_BASE_ADDR_REG 0x10 +#define PCI_IO_BASE_ADDR_MASK 0xfffffff0 + +#define PCI_MEM_BASE_ADDR_LOW 0x10 +#define PCI_MEM_BASE_ADDR_HIGH 0x14 + +#define PCI_SUBSYSTEM_VENDOR_ID_REG 0x2c +#define PCI_SUBSYSTEM_ID_REG 0x2e +#define PCI_INT_LINE_REG 0x3c + +#define PCIX_CAP_REG 0x40 +#define PCIX_ENABLE_RELAXED_ORDERING BIT_17 + +/******************************************************************************/ +/* Fragment structure. */ +/******************************************************************************/ + +typedef struct { + LM_UINT32 FragSize; + LM_PHYSICAL_ADDRESS FragBuf; +} LM_FRAG, *PLM_FRAG; + +typedef struct { + /* FragCount is initialized for the caller to the maximum array size, on */ + /* return FragCount is the number of the actual fragments in the array. */ + LM_UINT32 FragCount; + + /* Total buffer size. */ + LM_UINT32 TotalSize; + + /* Fragment array buffer. */ + LM_FRAG Fragments[1]; +} LM_FRAG_LIST, *PLM_FRAG_LIST; + +#define DECLARE_FRAG_LIST_BUFFER_TYPE(_FRAG_LIST_TYPE_NAME, _MAX_FRAG_COUNT) \ + typedef struct { \ + LM_FRAG_LIST FragList; \ + LM_FRAG FragListBuffer[_MAX_FRAG_COUNT-1]; \ + } _FRAG_LIST_TYPE_NAME, *P##_FRAG_LIST_TYPE_NAME + + + +/******************************************************************************/ +/* Status codes. */ +/******************************************************************************/ + +#define LM_STATUS_SUCCESS 0 +#define LM_STATUS_FAILURE 1 + +#define LM_STATUS_INTERRUPT_ACTIVE 2 +#define LM_STATUS_INTERRUPT_NOT_ACTIVE 3 + +#define LM_STATUS_LINK_ACTIVE 4 +#define LM_STATUS_LINK_DOWN 5 +#define LM_STATUS_LINK_SETTING_MISMATCH 6 + +#define LM_STATUS_TOO_MANY_FRAGMENTS 7 +#define LM_STATUS_TRANSMIT_ABORTED 8 +#define LM_STATUS_TRANSMIT_ERROR 9 +#define LM_STATUS_RECEIVE_ABORTED 10 +#define LM_STATUS_RECEIVE_ERROR 11 +#define LM_STATUS_INVALID_PACKET_SIZE 12 +#define LM_STATUS_OUT_OF_MAP_REGISTERS 13 +#define LM_STATUS_UNKNOWN_ADAPTER 14 + +typedef LM_UINT LM_STATUS, *PLM_STATUS; + + + +/******************************************************************************/ +/* Requested media type. */ +/******************************************************************************/ + +#define LM_REQUESTED_MEDIA_TYPE_AUTO 0 +#define LM_REQUESTED_MEDIA_TYPE_BNC 1 +#define LM_REQUESTED_MEDIA_TYPE_UTP_AUTO 2 +#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS 3 +#define LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX 4 +#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS 5 +#define LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX 6 +#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS 7 +#define LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX 8 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS 9 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX 10 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS 11 +#define LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX 12 +#define LM_REQUESTED_MEDIA_TYPE_MAC_LOOPBACK 0xfffe +#define LM_REQUESTED_MEDIA_TYPE_PHY_LOOPBACK 0xffff + +typedef LM_UINT32 LM_REQUESTED_MEDIA_TYPE, *PLM_REQUESTED_MEDIA_TYPE; + + + +/******************************************************************************/ +/* Media type. */ +/******************************************************************************/ + +#define LM_MEDIA_TYPE_UNKNOWN -1 +#define LM_MEDIA_TYPE_AUTO 0 +#define LM_MEDIA_TYPE_UTP 1 +#define LM_MEDIA_TYPE_BNC 2 +#define LM_MEDIA_TYPE_AUI 3 +#define LM_MEDIA_TYPE_FIBER 4 + +typedef LM_UINT32 LM_MEDIA_TYPE, *PLM_MEDIA_TYPE; + + + +/******************************************************************************/ +/* Line speed. */ +/******************************************************************************/ + +#define LM_LINE_SPEED_UNKNOWN 0 +#define LM_LINE_SPEED_10MBPS 1 +#define LM_LINE_SPEED_100MBPS 2 +#define LM_LINE_SPEED_1000MBPS 3 + +typedef LM_UINT32 LM_LINE_SPEED, *PLM_LINE_SPEED; + + + +/******************************************************************************/ +/* Duplex mode. */ +/******************************************************************************/ + +#define LM_DUPLEX_MODE_UNKNOWN 0 +#define LM_DUPLEX_MODE_HALF 1 +#define LM_DUPLEX_MODE_FULL 2 + +typedef LM_UINT32 LM_DUPLEX_MODE, *PLM_DUPLEX_MODE; + + + +/******************************************************************************/ +/* Power state. */ +/******************************************************************************/ + +#define LM_POWER_STATE_D0 0 +#define LM_POWER_STATE_D1 1 +#define LM_POWER_STATE_D2 2 +#define LM_POWER_STATE_D3 3 + +typedef LM_UINT32 LM_POWER_STATE, *PLM_POWER_STATE; + + + +/******************************************************************************/ +/* Task offloading. */ +/******************************************************************************/ + +#define LM_TASK_OFFLOAD_NONE 0x0000 +#define LM_TASK_OFFLOAD_TX_IP_CHECKSUM 0x0001 +#define LM_TASK_OFFLOAD_RX_IP_CHECKSUM 0x0002 +#define LM_TASK_OFFLOAD_TX_TCP_CHECKSUM 0x0004 +#define LM_TASK_OFFLOAD_RX_TCP_CHECKSUM 0x0008 +#define LM_TASK_OFFLOAD_TX_UDP_CHECKSUM 0x0010 +#define LM_TASK_OFFLOAD_RX_UDP_CHECKSUM 0x0020 +#define LM_TASK_OFFLOAD_TCP_SEGMENTATION 0x0040 + +typedef LM_UINT32 LM_TASK_OFFLOAD, *PLM_TASK_OFFLOAD; + + + +/******************************************************************************/ +/* Flow control. */ +/******************************************************************************/ + +#define LM_FLOW_CONTROL_NONE 0x00 +#define LM_FLOW_CONTROL_RECEIVE_PAUSE 0x01 +#define LM_FLOW_CONTROL_TRANSMIT_PAUSE 0x02 +#define LM_FLOW_CONTROL_RX_TX_PAUSE (LM_FLOW_CONTROL_RECEIVE_PAUSE | \ + LM_FLOW_CONTROL_TRANSMIT_PAUSE) + +/* This value can be or-ed with RECEIVE_PAUSE and TRANSMIT_PAUSE. If the */ +/* auto-negotiation is disabled and the RECEIVE_PAUSE and TRANSMIT_PAUSE */ +/* bits are set, then flow control is enabled regardless of link partner's */ +/* flow control capability. */ +#define LM_FLOW_CONTROL_AUTO_PAUSE 0x80000000 + +typedef LM_UINT32 LM_FLOW_CONTROL, *PLM_FLOW_CONTROL; + + + +/******************************************************************************/ +/* Wake up mode. */ +/******************************************************************************/ + +#define LM_WAKE_UP_MODE_NONE 0 +#define LM_WAKE_UP_MODE_MAGIC_PACKET 1 +#define LM_WAKE_UP_MODE_NWUF 2 +#define LM_WAKE_UP_MODE_LINK_CHANGE 4 + +typedef LM_UINT32 LM_WAKE_UP_MODE, *PLM_WAKE_UP_MODE; + + + +/******************************************************************************/ +/* Counters. */ +/******************************************************************************/ + +#define LM_COUNTER_FRAMES_XMITTED_OK 0 +#define LM_COUNTER_FRAMES_RECEIVED_OK 1 +#define LM_COUNTER_ERRORED_TRANSMIT_COUNT 2 +#define LM_COUNTER_ERRORED_RECEIVE_COUNT 3 +#define LM_COUNTER_RCV_CRC_ERROR 4 +#define LM_COUNTER_ALIGNMENT_ERROR 5 +#define LM_COUNTER_SINGLE_COLLISION_FRAMES 6 +#define LM_COUNTER_MULTIPLE_COLLISION_FRAMES 7 +#define LM_COUNTER_FRAMES_DEFERRED 8 +#define LM_COUNTER_MAX_COLLISIONS 9 +#define LM_COUNTER_RCV_OVERRUN 10 +#define LM_COUNTER_XMIT_UNDERRUN 11 +#define LM_COUNTER_UNICAST_FRAMES_XMIT 12 +#define LM_COUNTER_MULTICAST_FRAMES_XMIT 13 +#define LM_COUNTER_BROADCAST_FRAMES_XMIT 14 +#define LM_COUNTER_UNICAST_FRAMES_RCV 15 +#define LM_COUNTER_MULTICAST_FRAMES_RCV 16 +#define LM_COUNTER_BROADCAST_FRAMES_RCV 17 + +typedef LM_UINT32 LM_COUNTER_TYPE, *PLM_COUNTER_TYPE; + + + +/******************************************************************************/ +/* Forward definition. */ +/******************************************************************************/ + +typedef struct _LM_DEVICE_BLOCK *PLM_DEVICE_BLOCK; +typedef struct _LM_PACKET *PLM_PACKET; + + + +/******************************************************************************/ +/* Function prototypes. */ +/******************************************************************************/ + +LM_STATUS LM_GetAdapterInfo(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_InitializeAdapter(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_ResetAdapter(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_DisableInterrupt(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_EnableInterrupt(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS LM_ServiceInterrupts(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetReceiveMask(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Mask); +LM_STATUS LM_Halt(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_MulticastAdd(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); +LM_STATUS LM_MulticastDel(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMcAddress); +LM_STATUS LM_MulticastClear(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetMacAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pMacAddress); +LM_STATUS LM_LoopbackAddress(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pAddress); + +LM_UINT32 LM_GetCrcCounter(PLM_DEVICE_BLOCK pDevice); + +LM_WAKE_UP_MODE LM_PMCapabilities(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_NwufAdd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, + LM_UINT8 *pByteMask, LM_UINT8 *pPattern); +LM_STATUS LM_NwufRemove(PLM_DEVICE_BLOCK pDevice, LM_UINT32 ByteMaskSize, + LM_UINT8 *pByteMask, LM_UINT8 *pPattern); +LM_STATUS LM_SetPowerState(PLM_DEVICE_BLOCK pDevice, LM_POWER_STATE PowerLevel); + +LM_VOID LM_ReadPhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, + PLM_UINT32 pData32); +LM_VOID LM_WritePhy(PLM_DEVICE_BLOCK pDevice, LM_UINT32 PhyReg, + LM_UINT32 Data32); + +LM_STATUS LM_ControlLoopBack(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Control); +LM_STATUS LM_SetupPhy(PLM_DEVICE_BLOCK pDevice); +int LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDuration); + + + +/******************************************************************************/ +/* These are the OS specific functions called by LMAC. */ +/******************************************************************************/ + +LM_STATUS MM_ReadConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT16 *pValue16); +LM_STATUS MM_WriteConfig16(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT16 Value16); +LM_STATUS MM_ReadConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT32 *pValue32); +LM_STATUS MM_WriteConfig32(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Offset, + LM_UINT32 Value32); +LM_STATUS MM_MapMemBase(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_MapIoBase(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateRxPackets(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateTxPackets(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_StartTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_CompleteTxDma(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_AllocateMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, + PLM_VOID *pMemoryBlockVirt); +LM_STATUS MM_AllocateSharedMemory(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlockSize, + PLM_VOID *pMemoryBlockVirt, PLM_PHYSICAL_ADDRESS pMemoryBlockPhy, + LM_BOOL Cached); +LM_STATUS MM_GetConfig(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_IndicateStatus(PLM_DEVICE_BLOCK pDevice, LM_STATUS Status); +LM_STATUS MM_InitializeUmPackets(PLM_DEVICE_BLOCK pDevice); +LM_STATUS MM_FreeRxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS MM_CoalesceTxBuffer(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket); +LM_STATUS LM_MbufWorkAround(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_SetLinkSpeed(PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType); + +#if INCLUDE_5703_A0_FIX +LM_STATUS LM_Load5703DmaWFirmware(PLM_DEVICE_BLOCK pDevice); +#endif + + +#endif /* LM_H */ + diff --git a/drivers/bcm570x_mm.h b/drivers/bcm570x_mm.h new file mode 100644 index 0000000..badd0d2 --- /dev/null +++ b/drivers/bcm570x_mm.h @@ -0,0 +1,160 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/******************************************************************************/ + +#ifndef MM_H +#define MM_H + +#define __raw_readl readl +#define __raw_writel writel + +#define BIG_ENDIAN_HOST 1 +#define readl(addr) (*(volatile unsigned int*)(addr)) +#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) + +/* Define memory barrier function here if needed */ +#define wmb() +#define membar() +#include <common.h> +#include <asm/types.h> +#include "bcm570x_lm.h" +#include "bcm570x_queue.h" +#include "tigon3.h" +#include <pci.h> + +#define FALSE 0 +#define TRUE 1 +#define ERROR -1 + +#if DBG +#define STATIC +#else +#define STATIC static +#endif + +extern int MM_Packet_Desc_Size; + +#define MM_PACKET_DESC_SIZE MM_Packet_Desc_Size + +DECLARE_QUEUE_TYPE(UM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT+1); + +#define MAX_MEM 16 + +/* Synch */ +typedef int mutex_t; +typedef int spinlock_t; + +/* Embedded device control */ +typedef struct _UM_DEVICE_BLOCK { + LM_DEVICE_BLOCK lm_dev; + pci_dev_t pdev; + char *name; + void *mem_list[MAX_MEM]; + dma_addr_t dma_list[MAX_MEM]; + int mem_size_list[MAX_MEM]; + int mem_list_num; + int mtu; + int index; + int opened; + int delayed_link_ind; /* Delay link status during initial load */ + int adapter_just_inited; /* the first few seconds after init. */ + int spurious_int; /* new -- unsupported */ + int timer_interval; + int adaptive_expiry; + int crc_counter_expiry; /* new -- unsupported */ + int poll_tib_expiry; /* new -- unsupported */ + int tx_full; + int tx_queued; + int line_speed; /* in Mbps, 0 if link is down */ + UM_RX_PACKET_Q rx_out_of_buf_q; + int rx_out_of_buf; + int rx_low_buf_thresh; /* changed to rx_buf_repl_thresh */ + int rx_buf_repl_panic_thresh; + int rx_buf_align; /* new -- unsupported */ + int do_global_lock; + mutex_t global_lock; + mutex_t undi_lock; + long undi_flags; + volatile int interrupt; + int tasklet_pending; + int tasklet_busy; /* new -- unsupported */ + int rx_pkt; + int tx_pkt; +#ifdef NICE_SUPPORT /* unsupported, this is a linux ioctl */ + void (*nice_rx)(void*, void* ); + void* nice_ctx; +#endif /* NICE_SUPPORT */ + int rx_adaptive_coalesce; + unsigned int rx_last_cnt; + unsigned int tx_last_cnt; + unsigned int rx_curr_coalesce_frames; + unsigned int rx_curr_coalesce_ticks; + unsigned int tx_curr_coalesce_frames; /* new -- unsupported */ +#if TIGON3_DEBUG /* new -- unsupported */ + uint tx_zc_count; + uint tx_chksum_count; + uint tx_himem_count; + uint rx_good_chksum_count; +#endif + unsigned int rx_bad_chksum_count; /* new -- unsupported */ + unsigned int rx_misc_errors; /* new -- unsupported */ +} UM_DEVICE_BLOCK, *PUM_DEVICE_BLOCK; + + +/* Physical/PCI DMA address */ +typedef union { + dma_addr_t dma_map; +} dma_map_t; + +/* Packet */ +typedef struct +_UM_PACKET { + LM_PACKET lm_packet; + void* skbuff; /* Address of packet buffer */ +} UM_PACKET, *PUM_PACKET; + +#define MM_ACQUIRE_UNDI_LOCK(_pDevice) +#define MM_RELEASE_UNDI_LOCK(_pDevice) +#define MM_ACQUIRE_INT_LOCK(_pDevice) +#define MM_RELEASE_INT_LOCK(_pDevice) +#define MM_UINT_PTR(_ptr) ((unsigned long) (_ptr)) + +/* Macro for setting 64bit address struct */ +#define set_64bit_addr(paddr, low, high) \ + (paddr)->Low = low; \ + (paddr)->High = high; + +/* Assume that PCI controller's view of host memory is same as host */ + +#define MEM_TO_PCI_PHYS(addr) (addr) + +extern void MM_SetAddr (LM_PHYSICAL_ADDRESS *paddr, dma_addr_t addr); +extern void MM_SetT3Addr(T3_64BIT_HOST_ADDR *paddr, dma_addr_t addr); +extern void MM_MapTxDma (PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, T3_64BIT_HOST_ADDR *paddr, + LM_UINT32 *len, int frag); +extern void MM_MapRxDma ( PLM_DEVICE_BLOCK pDevice, + struct _LM_PACKET *pPacket, + T3_64BIT_HOST_ADDR *paddr); + + +/* BSP needs to provide sysUsecDelay and sysSerialPrintString */ +extern void sysSerialPrintString (char *s); +#define MM_Wait(usec) udelay(usec) + +/* Define memory barrier function here if needed */ +#define wmb() + +#if 0 +#define cpu_to_le32(val) LONGSWAP(val) +#endif +#endif /* MM_H */ diff --git a/drivers/bcm570x_queue.h b/drivers/bcm570x_queue.h new file mode 100644 index 0000000..bc32ad7 --- /dev/null +++ b/drivers/bcm570x_queue.h @@ -0,0 +1,399 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* Queue functions. */ +/* void QQ_InitQueue(PQQ_CONTAINER pQueue) */ +/* char QQ_Full(PQQ_CONTAINER pQueue) */ +/* char QQ_Empty(PQQ_CONTAINER pQueue) */ +/* unsigned int QQ_GetSize(PQQ_CONTAINER pQueue) */ +/* unsigned int QQ_GetEntryCnt(PQQ_CONTAINER pQueue) */ +/* char QQ_PushHead(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ +/* char QQ_PushTail(PQQ_CONTAINER pQueue, PQQ_ENTRY pEntry) */ +/* PQQ_ENTRY QQ_PopHead(PQQ_CONTAINER pQueue) */ +/* PQQ_ENTRY QQ_PopTail(PQQ_CONTAINER pQueue) */ +/* PQQ_ENTRY QQ_GetHead(PQQ_CONTAINER pQueue, unsigned int Idx) */ +/* PQQ_ENTRY QQ_GetTail(PQQ_CONTAINER pQueue, unsigned int Idx) */ +/* */ +/* */ +/* History: */ +/* 02/25/00 Hav Khauv Initial version. */ +/******************************************************************************/ + +#ifndef BCM_QUEUE_H +#define BCM_QUEUE_H +#ifndef EMBEDDED +#define EMBEDDED 1 +#endif + +/******************************************************************************/ +/* Queue definitions. */ +/******************************************************************************/ + +/* Entry for queueing. */ +typedef void *PQQ_ENTRY; + +/* Linux Atomic Ops support */ +typedef struct { int counter; } atomic_t; + + +/* + * This combination of `inline' and `extern' has almost the effect of a + * macro. The way to use it is to put a function definition in a header + * file with these keywords, and put another copy of the definition + * (lacking `inline' and `extern') in a library file. The definition in + * the header file will cause most calls to the function to be inlined. + * If any uses of the function remain, they will refer to the single copy + * in the library. + */ +extern __inline void +atomic_set(atomic_t* entry, int val) +{ + entry->counter = val; +} +extern __inline int +atomic_read(atomic_t* entry) +{ + return entry->counter; +} +extern __inline void +atomic_inc(atomic_t* entry) +{ + if(entry) + entry->counter++; +} + +extern __inline void +atomic_dec(atomic_t* entry) +{ + if(entry) + entry->counter--; +} + +extern __inline void +atomic_sub(int a, atomic_t* entry) +{ + if(entry) + entry->counter -= a; +} +extern __inline void +atomic_add(int a, atomic_t* entry) +{ + if(entry) + entry->counter += a; +} + + +/* Queue header -- base type. */ +typedef struct { + unsigned int Head; + unsigned int Tail; + unsigned int Size; + atomic_t EntryCnt; + PQQ_ENTRY Array[1]; +} QQ_CONTAINER, *PQQ_CONTAINER; + + +/* Declare queue type macro. */ +#define DECLARE_QUEUE_TYPE(_QUEUE_TYPE, _QUEUE_SIZE) \ + \ + typedef struct { \ + QQ_CONTAINER Container; \ + PQQ_ENTRY EntryBuffer[_QUEUE_SIZE]; \ + } _QUEUE_TYPE, *P##_QUEUE_TYPE + + + +/******************************************************************************/ +/* Compilation switches. */ +/******************************************************************************/ + +#if DBG +#undef QQ_NO_OVERFLOW_CHECK +#undef QQ_NO_UNDERFLOW_CHECK +#endif /* DBG */ + +#ifdef QQ_USE_MACROS +/* notdone */ +#else + +#ifdef QQ_NO_INLINE +#define __inline +#endif /* QQ_NO_INLINE */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline void +QQ_InitQueue( +PQQ_CONTAINER pQueue, +unsigned int QueueSize) { + pQueue->Head = 0; + pQueue->Tail = 0; + pQueue->Size = QueueSize+1; + atomic_set(&pQueue->EntryCnt, 0); +} /* QQ_InitQueue */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline char +QQ_Full( +PQQ_CONTAINER pQueue) { + unsigned int NewHead; + + NewHead = (pQueue->Head + 1) % pQueue->Size; + + return(NewHead == pQueue->Tail); +} /* QQ_Full */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline char +QQ_Empty( +PQQ_CONTAINER pQueue) { + return(pQueue->Head == pQueue->Tail); +} /* QQ_Empty */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline unsigned int +QQ_GetSize( +PQQ_CONTAINER pQueue) { + return pQueue->Size; +} /* QQ_GetSize */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline unsigned int +QQ_GetEntryCnt( +PQQ_CONTAINER pQueue) { + return atomic_read(&pQueue->EntryCnt); +} /* QQ_GetEntryCnt */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +extern __inline char +QQ_PushHead( +PQQ_CONTAINER pQueue, +PQQ_ENTRY pEntry) { + unsigned int Head; + + Head = (pQueue->Head + 1) % pQueue->Size; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if(Head == pQueue->Tail) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[pQueue->Head] = pEntry; + wmb(); + pQueue->Head = Head; + atomic_inc(&pQueue->EntryCnt); + + return -1; +} /* QQ_PushHead */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* TRUE entry was added successfully. */ +/* FALSE queue is full. */ +/******************************************************************************/ +extern __inline char +QQ_PushTail( +PQQ_CONTAINER pQueue, +PQQ_ENTRY pEntry) { + unsigned int Tail; + + Tail = pQueue->Tail; + if(Tail == 0) { + Tail = pQueue->Size; + } /* if */ + Tail--; + +#if !defined(QQ_NO_OVERFLOW_CHECK) + if(Tail == pQueue->Head) { + return 0; + } /* if */ +#endif /* QQ_NO_OVERFLOW_CHECK */ + + pQueue->Array[Tail] = pEntry; + wmb(); + pQueue->Tail = Tail; + atomic_inc(&pQueue->EntryCnt); + + return -1; +} /* QQ_PushTail */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_PopHead( +PQQ_CONTAINER pQueue) { + unsigned int Head; + PQQ_ENTRY Entry; + + Head = pQueue->Head; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if(Head == pQueue->Tail) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + if(Head == 0) { + Head = pQueue->Size; + } /* if */ + Head--; + + Entry = pQueue->Array[Head]; +#ifdef EMBEDDED + membar(); +#else + mb(); +#endif + pQueue->Head = Head; + atomic_dec(&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopHead */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_PopTail( +PQQ_CONTAINER pQueue) { + unsigned int Tail; + PQQ_ENTRY Entry; + + Tail = pQueue->Tail; + +#if !defined(QQ_NO_UNDERFLOW_CHECK) + if(Tail == pQueue->Head) { + return (PQQ_ENTRY) 0; + } /* if */ +#endif /* QQ_NO_UNDERFLOW_CHECK */ + + Entry = pQueue->Array[Tail]; +#ifdef EMBEDDED + membar(); +#else + mb(); +#endif + pQueue->Tail = (Tail + 1) % pQueue->Size; + atomic_dec(&pQueue->EntryCnt); + + return Entry; +} /* QQ_PopTail */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_GetHead( + PQQ_CONTAINER pQueue, + unsigned int Idx) +{ + if(Idx >= atomic_read(&pQueue->EntryCnt)) + { + return (PQQ_ENTRY) 0; + } + + if(pQueue->Head > Idx) + { + Idx = pQueue->Head - Idx; + } + else + { + Idx = pQueue->Size - (Idx - pQueue->Head); + } + Idx--; + + return pQueue->Array[Idx]; +} + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +extern __inline PQQ_ENTRY +QQ_GetTail( + PQQ_CONTAINER pQueue, + unsigned int Idx) +{ + if(Idx >= atomic_read(&pQueue->EntryCnt)) + { + return (PQQ_ENTRY) 0; + } + + Idx += pQueue->Tail; + if(Idx >= pQueue->Size) + { + Idx = Idx - pQueue->Size; + } + + return pQueue->Array[Idx]; +} + +#endif /* QQ_USE_MACROS */ + + + +#endif /* QUEUE_H */ diff --git a/drivers/cfb_console.c b/drivers/cfb_console.c new file mode 100644 index 0000000..ee2fa9c --- /dev/null +++ b/drivers/cfb_console.c @@ -0,0 +1,912 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * cfb_console.c + * + * Color Framebuffer Console driver for 8/15/16/24/32 bits per pixel. + * + * At the moment only the 8x16 font is tested and the font fore- and + * background color is limited to black/white/gray colors. The Linux + * logo can be placed in the upper left corner and additional board + * information strings (that normaly goes to serial port) can be drawed. + * + * The console driver can use the standard PC keyboard interface (i8042) + * for character input. Character output goes to a memory mapped video + * framebuffer with little or big-endian organisation. + * With environment setting 'console=serial' the console i/o can be + * forced to serial port. + + The driver uses graphic specific defines/parameters/functions: + + (for SMI LynxE graphic chip) + + CONFIG_VIDEO_SMI_LYNXEM - use graphic driver for SMI 710,712,810 + VIDEO_FB_LITTLE_ENDIAN - framebuffer organisation default: big endian + VIDEO_HW_RECTFILL - graphic driver supports hardware rectangle fill + VIDEO_HW_BITBLT - graphic driver supports hardware bit blt + + Console Parameters are set by graphic drivers global struct: + + VIDEO_VISIBLE_COLS - x resolution + VIDEO_VISIBLE_ROWS - y resolution + VIDEO_PIXEL_SIZE - storage size in byte per pixel + VIDEO_DATA_FORMAT - graphical data format GDF + VIDEO_FB_ADRS - start of video memory + + CONFIG_I8042_KBD - AT Keyboard driver for i8042 + VIDEO_KBD_INIT_FCT - init function for keyboard + VIDEO_TSTC_FCT - keyboard_tstc function + VIDEO_GETC_FCT - keyboard_getc function + + CONFIG_CONSOLE_CURSOR - on/off drawing cursor is done with delay + loop in VIDEO_TSTC_FCT (i8042) + CFG_CONSOLE_BLINK_COUNT - value for delay loop - blink rate + CONFIG_CONSOLE_TIME - display time/date in upper right corner, + needs CFG_CMD_DATE and CONFIG_CONSOLE_CURSOR + CONFIG_VIDEO_LOGO - display Linux Logo in upper left corner + CONFIG_CONSOLE_EXTRA_INFO - display additional board information strings + that normaly goes to serial port. This define + requires a board specific function: + video_drawstring (VIDEO_INFO_X, + VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT, + info); + that fills a info buffer at i=row. + s.a: board/eltec/bab7xx. +CONFIG_VGA_AS_SINGLE_DEVICE - If set the framebuffer device will be initialised + as an output only device. The Keyboard driver + will not be set-up. This may be used, if you + have none or more than one Keyboard devices + (USB Keyboard, AT Keyboard). + +CONFIG_VIDEO_SW_CURSOR: - Draws a cursor after the last character. No + blinking is provided. Uses the macros CURSOR_SET + and CURSOR_OFF. +CONFIG_VIDEO_HW_CURSOR: - Uses the hardware cursor capability of the + graphic chip. Uses the macro CURSOR_SET. + ATTENTION: If booting an OS, the display driver + must disable the hardware register of the graphic + chip. Otherwise a blinking field is displayed +*/ + +#include <common.h> + +#ifdef CONFIG_CFB_CONSOLE + +/*****************************************************************************/ +/* Console device defines with SMI graphic */ +/* Any other graphic must change this section */ +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_SMI_LYNXEM + +#define VIDEO_FB_LITTLE_ENDIAN +#define VIDEO_HW_RECTFILL +#define VIDEO_HW_BITBLT +#endif + +/*****************************************************************************/ +/* Defines for the CT69000 driver */ +/*****************************************************************************/ +#ifdef CONFIG_VIDEO_CT69000 + +#define VIDEO_FB_LITTLE_ENDIAN +#define VIDEO_HW_RECTFILL +#define VIDEO_HW_BITBLT +#endif + +/*****************************************************************************/ +/* Include video_fb.h after definitions of VIDEO_HW_RECTFILL etc */ +/*****************************************************************************/ +#include <video_fb.h> + +/*****************************************************************************/ +/* some Macros */ +/*****************************************************************************/ +#define VIDEO_VISIBLE_COLS (pGD->winSizeX) +#define VIDEO_VISIBLE_ROWS (pGD->winSizeY) +#define VIDEO_PIXEL_SIZE (pGD->gdfBytesPP) +#define VIDEO_DATA_FORMAT (pGD->gdfIndex) +#define VIDEO_FB_ADRS (pGD->frameAdrs) + +/*****************************************************************************/ +/* Console device defines with i8042 keyboard controller */ +/* Any other keyboard controller must change this section */ +/*****************************************************************************/ + +#ifdef CONFIG_I8042_KBD +#include <i8042.h> + +#define VIDEO_KBD_INIT_FCT i8042_kbd_init() +#define VIDEO_TSTC_FCT i8042_tstc +#define VIDEO_GETC_FCT i8042_getc +#endif + +/*****************************************************************************/ +/* Console device */ +/*****************************************************************************/ + +#include <version.h> +#include <linux/types.h> +#include <devices.h> +#include <video_font.h> +#ifdef CFG_CMD_DATE +#include <rtc.h> + +#endif + +/*****************************************************************************/ +/* Cursor definition: */ +/* CONFIG_CONSOLE_CURSOR: Uses a timer function (see drivers/i8042.c) to */ +/* let the cursor blink. Uses the macros CURSOR_OFF */ +/* and CURSOR_ON. */ +/* CONFIG_VIDEO_SW_CURSOR: Draws a cursor after the last character. No */ +/* blinking is provided. Uses the macros CURSOR_SET */ +/* and CURSOR_OFF. */ +/* CONFIG_VIDEO_HW_CURSOR: Uses the hardware cursor capability of the */ +/* graphic chip. Uses the macro CURSOR_SET. */ +/* ATTENTION: If booting an OS, the display driver */ +/* must disable the hardware register of the graphic */ +/* chip. Otherwise a blinking field is displayed */ +/*****************************************************************************/ +#if !defined(CONFIG_CONSOLE_CURSOR) && \ + !defined(CONFIG_VIDEO_SW_CURSOR) && \ + !defined(CONFIG_VIDEO_HW_CURSOR) +/* no Cursor defined */ +#define CURSOR_ON +#define CURSOR_OFF +#define CURSOR_SET +#endif + +#ifdef CONFIG_CONSOLE_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +void console_cursor (int state); +#define CURSOR_ON console_cursor(1); +#define CURSOR_OFF console_cursor(0); +#define CURSOR_SET +#ifndef CONFIG_I8042_KBD +#warning Cursor drawing on/off needs timer function s.a. drivers/i8042.c +#endif +#else +#ifdef CONFIG_CONSOLE_TIME +#error CONFIG_CONSOLE_CURSOR must be defined for CONFIG_CONSOLE_TIME +#endif +#endif /* CONFIG_CONSOLE_CURSOR */ + +#ifdef CONFIG_VIDEO_SW_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +#define CURSOR_ON +#define CURSOR_OFF video_putchar(console_col * VIDEO_FONT_WIDTH,\ + console_row * VIDEO_FONT_HEIGHT, ' '); +#define CURSOR_SET video_set_cursor(); +#endif /* CONFIG_VIDEO_SW_CURSOR */ + + +#ifdef CONFIG_VIDEO_HW_CURSOR +#ifdef CURSOR_ON +#error only one of CONFIG_CONSOLE_CURSOR,CONFIG_VIDEO_SW_CURSOR,CONFIG_VIDEO_HW_CURSOR can be defined +#endif +#define CURSOR_ON +#define CURSOR_OFF +#define CURSOR_SET video_set_hw_cursor(console_col * VIDEO_FONT_WIDTH, \ + (console_row * VIDEO_FONT_HEIGHT) + VIDEO_LOGO_HEIGHT); +#endif /* CONFIG_VIDEO_HW_CURSOR */ + +#ifdef CONFIG_VIDEO_LOGO +#define LINUX_LOGO_WIDTH 80 +#define LINUX_LOGO_HEIGHT 80 +#define LINUX_LOGO_COLORS 214 +#define LINUX_LOGO_LUT_OFFSET 0x20 +#define __initdata +#include <linux_logo.h> +#define VIDEO_LOGO_WIDTH LINUX_LOGO_WIDTH +#define VIDEO_LOGO_HEIGHT LINUX_LOGO_HEIGHT + +#define VIDEO_INFO_X (VIDEO_LOGO_WIDTH) +#define VIDEO_INFO_Y (VIDEO_FONT_HEIGHT/2) +#else +#define VIDEO_LOGO_WIDTH 0 +#define VIDEO_LOGO_HEIGHT 0 +#endif + +#define VIDEO_COLS VIDEO_VISIBLE_COLS +#define VIDEO_ROWS VIDEO_VISIBLE_ROWS +#define VIDEO_SIZE (VIDEO_ROWS*VIDEO_COLS*VIDEO_PIXEL_SIZE) +#define VIDEO_PIX_BLOCKS (VIDEO_SIZE >> 2) +#define VIDEO_LINE_LEN (VIDEO_COLS*VIDEO_PIXEL_SIZE) +#define VIDEO_BURST_LEN (VIDEO_COLS/8) + +#ifdef CONFIG_VIDEO_LOGO +#define CONSOLE_ROWS ((VIDEO_ROWS - VIDEO_LOGO_HEIGHT) / VIDEO_FONT_HEIGHT) +#else +#define CONSOLE_ROWS (VIDEO_ROWS / VIDEO_FONT_HEIGHT) +#endif + +#define CONSOLE_COLS (VIDEO_COLS / VIDEO_FONT_WIDTH) +#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * VIDEO_LINE_LEN) +#define CONSOLE_ROW_FIRST (video_console_address) +#define CONSOLE_ROW_SECOND (video_console_address + CONSOLE_ROW_SIZE) +#define CONSOLE_ROW_LAST (video_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE) +#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * CONSOLE_ROWS) +#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE) + +/* Macros */ +#ifdef VIDEO_FB_LITTLE_ENDIAN +#define SWAP16(x) ((((x) & 0x00ff) << 8) | ( (x) >> 8)) +#define SWAP32(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\ + (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) ) +#define SHORTSWAP32(x) ((((x) & 0x000000ff) << 8) | (((x) & 0x0000ff00) >> 8)|\ + (((x) & 0x00ff0000) << 8) | (((x) & 0xff000000) >> 8) ) +#else +#define SWAP16(x) (x) +#define SWAP32(x) (x) +#define SHORTSWAP32(x) (x) +#endif + +#if defined(DEBUG) || defined(DEBUG_CFB_CONSOLE) +#define PRINTD(x) printf(x) +#else +#define PRINTD(x) +#endif + + +#ifdef CONFIG_CONSOLE_EXTRA_INFO +extern void video_get_info_str ( /* setup a board string: type, speed, etc. */ + int line_number, /* location to place info string beside logo */ + char *info /* buffer for info string */ + ); + +#endif + +/* Locals */ +static GraphicDevice *pGD; /* Pointer to Graphic array */ + +static void *video_fb_address; /* frame buffer address */ +static void *video_console_address; /* console buffer start address */ + +static int console_col = 0; /* cursor col */ +static int console_row = 0; /* cursor row */ + +static u32 eorx, fgx, bgx; /* color pats */ + +static const int video_font_draw_table8[] = { + 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff, + 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff, + 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff, + 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff }; + +static const int video_font_draw_table15[] = { + 0x00000000, 0x00007fff, 0x7fff0000, 0x7fff7fff }; + +static const int video_font_draw_table16[] = { + 0x00000000, 0x0000ffff, 0xffff0000, 0xffffffff }; + +static const int video_font_draw_table24[16][3] = { + { 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x0000ffff, 0xff000000 }, + { 0x00000000, 0x0000ffff, 0xffffffff }, + { 0x000000ff, 0xffff0000, 0x00000000 }, + { 0x000000ff, 0xffff0000, 0x00ffffff }, + { 0x000000ff, 0xffffffff, 0xff000000 }, + { 0x000000ff, 0xffffffff, 0xffffffff }, + { 0xffffff00, 0x00000000, 0x00000000 }, + { 0xffffff00, 0x00000000, 0x00ffffff }, + { 0xffffff00, 0x0000ffff, 0xff000000 }, + { 0xffffff00, 0x0000ffff, 0xffffffff }, + { 0xffffffff, 0xffff0000, 0x00000000 }, + { 0xffffffff, 0xffff0000, 0x00ffffff }, + { 0xffffffff, 0xffffffff, 0xff000000 }, + { 0xffffffff, 0xffffffff, 0xffffffff } }; + +static const int video_font_draw_table32[16][4] = { + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00000000, 0x00ffffff, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00000000, 0x00ffffff, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00000000, 0x00ffffff }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00000000 }, + { 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff } }; + + +/******************************************************************************/ + + +static void video_drawchars (int xx, int yy, unsigned char *s, int count) +{ + u8 *cdat, *dest, *dest0; + int rows, offset, c; + + offset = yy * VIDEO_LINE_LEN + xx * VIDEO_PIXEL_SIZE; + dest0 = video_fb_address + offset; + + switch (VIDEO_DATA_FORMAT) + { + case GDF__8BIT_INDEX: + case GDF__8BIT_332RGB: + while (count--) + { + c = *s ; + cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN) + { + u8 bits = *cdat++; + ((u32 *)dest)[0] = (video_font_draw_table8[bits >> 4] & eorx) ^ bgx; + ((u32 *)dest)[1] = (video_font_draw_table8[bits & 15] & eorx) ^ bgx; + } + dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; + s++; + } + break; + + case GDF_15BIT_555RGB: + while (count--) + { + c = *s ; + cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN) + { + u8 bits = *cdat++; + ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table15[bits >> 6] & eorx) ^ bgx); + ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table15[bits >> 4 & 3] & eorx) ^ bgx); + ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table15[bits >> 2 & 3] & eorx) ^ bgx); + ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table15[bits & 3] & eorx) ^ bgx); + } + dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; + s++ ; + } + break; + + case GDF_16BIT_565RGB: + while (count--) + { + c = *s ; + cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN) + { + u8 bits = *cdat++; + ((u32 *)dest)[0] = SHORTSWAP32((video_font_draw_table16[bits >> 6] & eorx) ^ bgx); + ((u32 *)dest)[1] = SHORTSWAP32((video_font_draw_table16[bits >> 4 & 3] & eorx) ^ bgx); + ((u32 *)dest)[2] = SHORTSWAP32((video_font_draw_table16[bits >> 2 & 3] & eorx) ^ bgx); + ((u32 *)dest)[3] = SHORTSWAP32((video_font_draw_table16[bits & 3] & eorx) ^ bgx); + } + dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; + s++ ; + } + break; + + case GDF_32BIT_X888RGB: + while (count--) + { + c = *s ; + cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN) + { + u8 bits = *cdat++; + ((u32 *)dest)[0] = SWAP32((video_font_draw_table32[bits >> 4][0] & eorx) ^ bgx); + ((u32 *)dest)[1] = SWAP32((video_font_draw_table32[bits >> 4][1] & eorx) ^ bgx); + ((u32 *)dest)[2] = SWAP32((video_font_draw_table32[bits >> 4][2] & eorx) ^ bgx); + ((u32 *)dest)[3] = SWAP32((video_font_draw_table32[bits >> 4][3] & eorx) ^ bgx); + ((u32 *)dest)[4] = SWAP32((video_font_draw_table32[bits & 15][0] & eorx) ^ bgx); + ((u32 *)dest)[5] = SWAP32((video_font_draw_table32[bits & 15][1] & eorx) ^ bgx); + ((u32 *)dest)[6] = SWAP32((video_font_draw_table32[bits & 15][2] & eorx) ^ bgx); + ((u32 *)dest)[7] = SWAP32((video_font_draw_table32[bits & 15][3] & eorx) ^ bgx); + } + dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; + s++ ; + } + break; + + case GDF_24BIT_888RGB: + while (count--) + { + c = *s ; + cdat = video_fontdata + c * VIDEO_FONT_HEIGHT; + for (rows = VIDEO_FONT_HEIGHT, dest = dest0; rows--; dest += VIDEO_LINE_LEN) + { + u8 bits = *cdat++; + ((u32 *)dest)[0] = (video_font_draw_table24[bits >> 4][0] & eorx) ^ bgx; + ((u32 *)dest)[1] = (video_font_draw_table24[bits >> 4][1] & eorx) ^ bgx; + ((u32 *)dest)[2] = (video_font_draw_table24[bits >> 4][2] & eorx) ^ bgx; + ((u32 *)dest)[3] = (video_font_draw_table24[bits & 15][0] & eorx) ^ bgx; + ((u32 *)dest)[4] = (video_font_draw_table24[bits & 15][1] & eorx) ^ bgx; + ((u32 *)dest)[5] = (video_font_draw_table24[bits & 15][2] & eorx) ^ bgx; + } + dest0 += VIDEO_FONT_WIDTH * VIDEO_PIXEL_SIZE; + s++ ; + } + break; + } +} + +/*****************************************************************************/ + +static inline void video_drawstring(int xx, int yy, unsigned char *s) +{ + video_drawchars (xx, yy, s, strlen(s)); +} + +/*****************************************************************************/ + +static void video_putchar(int xx, int yy, unsigned char c) +{ +#ifdef CONFIG_VIDEO_LOGO + video_drawchars (xx, yy + VIDEO_LOGO_HEIGHT, &c, 1); +#else + video_drawchars (xx, yy, &c, 1); +#endif +} + +/*****************************************************************************/ +#if defined(CONFIG_CONSOLE_CURSOR) || defined(CONFIG_VIDEO_SW_CURSOR) +static void video_set_cursor(void) +{ + /* swap drawing colors */ + eorx = fgx; + fgx = bgx; + bgx = eorx; + eorx = fgx ^ bgx; + /* draw cursor */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, ' '); + /* restore drawing colors */ + eorx = fgx; + fgx = bgx; + bgx = eorx; + eorx = fgx ^ bgx; +} +#endif +/*****************************************************************************/ +#ifdef CONFIG_CONSOLE_CURSOR +void console_cursor (int state) +{ + static int last_state = 0; +#ifdef CONFIG_CONSOLE_TIME + struct rtc_time tm; + char info[16]; + + /* time update only if cursor is on (faster scroll) */ + if (state) + { + rtc_get (&tm); + + sprintf(info, " %02d:%02d:%02d ", tm.tm_hour, tm.tm_min, tm.tm_sec); + video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH, + VIDEO_INFO_Y, info); + + sprintf(info, "%02d.%02d.%04d", tm.tm_mday, tm.tm_mon, tm.tm_year); + video_drawstring(VIDEO_VISIBLE_COLS-10*VIDEO_FONT_WIDTH, + VIDEO_INFO_Y+1*VIDEO_FONT_HEIGHT, info); + } +#endif + + if (state && (last_state != state)) + { + video_set_cursor(); + } + + if (!state && (last_state != state)) + { + /* clear cursor */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, ' '); + } + + last_state = state; +} +#endif + +/*****************************************************************************/ + +#ifndef VIDEO_HW_RECTFILL +static void memsetl (int *p, int c, int v) +{ + while (c--) + *(p++) = v; +} +#endif + +/*****************************************************************************/ + +#ifndef VIDEO_HW_BITBLT +static void memcpyl (int *d, int *s, int c) +{ + while (c--) + *(d++) = *(s++); +} +#endif + +/*****************************************************************************/ + +static void console_scrollup (void) +{ + /* copy up rows ignoring the first one */ + +#ifdef VIDEO_HW_BITBLT + video_hw_bitblt ( + VIDEO_PIXEL_SIZE, /* bytes per pixel */ + 0, /* source pos x */ + VIDEO_LOGO_HEIGHT + VIDEO_FONT_HEIGHT, /* source pos y */ + 0, /* dest pos x */ + VIDEO_LOGO_HEIGHT, /* dest pos y */ + VIDEO_VISIBLE_COLS, /* frame width */ + VIDEO_VISIBLE_ROWS - VIDEO_LOGO_HEIGHT - VIDEO_FONT_HEIGHT /* frame height */ + ); +#else + memcpyl (CONSOLE_ROW_FIRST, CONSOLE_ROW_SECOND, CONSOLE_SCROLL_SIZE >> 2); +#endif + + /* clear the last one */ +#ifdef VIDEO_HW_RECTFILL + video_hw_rectfill ( + VIDEO_PIXEL_SIZE, /* bytes per pixel */ + 0, /* dest pos x */ + VIDEO_VISIBLE_ROWS - VIDEO_FONT_HEIGHT, /* dest pos y */ + VIDEO_VISIBLE_COLS, /* frame width */ + VIDEO_FONT_HEIGHT, /* frame height */ + CONSOLE_BG_COL /* fill color */ + ); +#else + memsetl (CONSOLE_ROW_LAST, CONSOLE_ROW_SIZE >> 2, CONSOLE_BG_COL); +#endif +} + +/*****************************************************************************/ + +static void console_back (void) +{ + CURSOR_OFF + console_col--; + + if (console_col < 0) + { + console_col = CONSOLE_COLS - 1; + console_row--; + if (console_row < 0) + console_row = 0; + } + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, ' '); +} + +/*****************************************************************************/ + +static void console_newline (void) +{ + CURSOR_OFF + console_row++; + console_col = 0; + + /* Check if we need to scroll the terminal */ + if (console_row >= CONSOLE_ROWS) + { + /* Scroll everything up */ + console_scrollup (); + + /* Decrement row number */ + console_row--; + } +} + +/*****************************************************************************/ + +void video_putc (const char c) +{ + switch (c) + { + case 13: /* ignore */ + break; + + case '\n': /* next line */ + console_newline(); + break; + + case 9: /* tab 8 */ + CURSOR_OFF + console_col |= 0x0008; + console_col &= ~0x0007; + + if (console_col >= CONSOLE_COLS) + console_newline(); + break; + + case 8: /* backspace */ + console_back(); + break; + + default: /* draw the char */ + video_putchar (console_col * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, c); + console_col++ ; + + /* check for newline */ + if (console_col >= CONSOLE_COLS) + console_newline(); + } + CURSOR_SET +} + + + +/*****************************************************************************/ + +void video_puts (const char *s) +{ + int count = strlen(s); + + while(count--) + video_putc(*s++); +} + +/*****************************************************************************/ + +#ifdef CONFIG_VIDEO_LOGO +void logo_plot (void *screen, int width, int x, int y) +{ + int skip = (width - LINUX_LOGO_WIDTH) * VIDEO_PIXEL_SIZE, + xcount, i, + ycount = LINUX_LOGO_HEIGHT; + unsigned char + *source = linux_logo, + *dest = (unsigned char *) screen + ((y * width * VIDEO_PIXEL_SIZE) + x), + r, g, b; + + if (VIDEO_DATA_FORMAT == GDF__8BIT_INDEX) + { + for (i = 0; i < LINUX_LOGO_COLORS; i++) + { + r = (unsigned char)linux_logo_red [i]; + g = (unsigned char)linux_logo_green[i]; + b = (unsigned char)linux_logo_blue [i]; + video_set_lut (LINUX_LOGO_LUT_OFFSET + i, r, g, b); + } + } + + while (ycount--) + { + xcount = LINUX_LOGO_WIDTH; + while (xcount--) + { + r = (unsigned char)linux_logo_red [*source - LINUX_LOGO_LUT_OFFSET]; + g = (unsigned char)linux_logo_green[*source - LINUX_LOGO_LUT_OFFSET]; + b = (unsigned char)linux_logo_blue [*source - LINUX_LOGO_LUT_OFFSET]; + + switch (VIDEO_DATA_FORMAT) + { + case GDF__8BIT_INDEX: + *dest = *source; + break; + case GDF__8BIT_332RGB: + *dest = ((r>>5)<<5) | ((g>>5)<<2) | (b>>6); + break; + case GDF_15BIT_555RGB: + *(unsigned short *)dest = + SWAP16((unsigned short)(((r>>3)<<10) | ((g>>3)<<5) | (b>>3))); + break; + case GDF_16BIT_565RGB: + *(unsigned short *)dest = + SWAP16((unsigned short)(((r>>3)<<11) | ((g>>2)<<5) | (b>>3))); + break; + case GDF_32BIT_X888RGB: + *(unsigned long *)dest = + SWAP32((unsigned long)((r<<16) | (g<<8) | b)); + break; + case GDF_24BIT_888RGB: +#ifdef VIDEO_FB_LITTLE_ENDIAN + dest[0] = b; + dest[1] = g; + dest[2] = r; +#else + dest[0] = r; + dest[1] = g; + dest[2] = b; +#endif + break; + } + source++; + dest += VIDEO_PIXEL_SIZE; + } + dest += skip; + } +} + + +/*****************************************************************************/ + +static void *video_logo (void) +{ + char info[128]; + + logo_plot (video_fb_address, VIDEO_COLS, 0, 0); + + sprintf(info, " %s (%s - %s)", U_BOOT_VERSION, __DATE__, __TIME__); + video_drawstring (VIDEO_INFO_X, VIDEO_INFO_Y, info); + +#ifdef CONFIG_CONSOLE_EXTRA_INFO + { + int i, n = ((VIDEO_LOGO_HEIGHT-VIDEO_FONT_HEIGHT)/VIDEO_FONT_HEIGHT); + + for (i = 1; i < n; i++) + { + video_get_info_str (i, info); + if (*info) + video_drawstring (VIDEO_INFO_X, + VIDEO_INFO_Y + i*VIDEO_FONT_HEIGHT, info); + } + } +#endif + + return (video_fb_address + VIDEO_LOGO_HEIGHT * VIDEO_LINE_LEN); +} +#endif + + +/*****************************************************************************/ + +static int video_init(void) +{ + unsigned char color8; + + if ((pGD=video_hw_init()) == NULL) + return -1; + + video_fb_address = (void*)VIDEO_FB_ADRS; +#ifdef CONFIG_VIDEO_HW_CURSOR + video_init_hw_cursor(VIDEO_FONT_WIDTH, VIDEO_FONT_HEIGHT); +#endif + + /* Init drawing pats */ + switch (VIDEO_DATA_FORMAT) + { + case GDF__8BIT_INDEX: + video_set_lut (0x01, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL); + video_set_lut (0x00, CONSOLE_BG_COL, CONSOLE_BG_COL, CONSOLE_BG_COL); + fgx = 0x01010101; + bgx = 0x00000000; + break; + case GDF__8BIT_332RGB: + color8 = ((CONSOLE_FG_COL & 0xe0) | ((CONSOLE_FG_COL>>3) & 0x1c) | CONSOLE_FG_COL>>6); + fgx = (color8<<24) | (color8<<16) | (color8<<8) | color8; + color8 = ((CONSOLE_BG_COL & 0xe0) | ((CONSOLE_BG_COL>>3) & 0x1c) | CONSOLE_BG_COL>>6); + bgx = (color8<<24) | (color8<<16) | (color8<<8) | color8; + break; + case GDF_15BIT_555RGB: + fgx = (((CONSOLE_FG_COL>>3)<<26) | ((CONSOLE_FG_COL>>3)<<21) | ((CONSOLE_FG_COL>>3)<<16) | + ((CONSOLE_FG_COL>>3)<<10) | ((CONSOLE_FG_COL>>3)<<5) | (CONSOLE_FG_COL>>3)); + bgx = (((CONSOLE_BG_COL>>3)<<26) | ((CONSOLE_BG_COL>>3)<<21) | ((CONSOLE_BG_COL>>3)<<16) | + ((CONSOLE_BG_COL>>3)<<10) | ((CONSOLE_BG_COL>>3)<<5) | (CONSOLE_BG_COL>>3)); + break; + case GDF_16BIT_565RGB: + fgx = (((CONSOLE_FG_COL>>3)<<27) | ((CONSOLE_FG_COL>>2)<<21) | ((CONSOLE_FG_COL>>3)<<16) | + ((CONSOLE_FG_COL>>3)<<11) | ((CONSOLE_FG_COL>>2)<<5) | (CONSOLE_FG_COL>>3)); + bgx = (((CONSOLE_BG_COL>>3)<<27) | ((CONSOLE_BG_COL>>2)<<21) | ((CONSOLE_BG_COL>>3)<<16) | + ((CONSOLE_BG_COL>>3)<<11) | ((CONSOLE_BG_COL>>2)<<5) | (CONSOLE_BG_COL>>3)); + break; + case GDF_32BIT_X888RGB: + fgx = (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL; + break; + case GDF_24BIT_888RGB: + fgx = (CONSOLE_FG_COL<<24) | (CONSOLE_FG_COL<<16) | (CONSOLE_FG_COL<<8) | CONSOLE_FG_COL; + bgx = (CONSOLE_BG_COL<<24) | (CONSOLE_BG_COL<<16) | (CONSOLE_BG_COL<<8) | CONSOLE_BG_COL; + break; + } + eorx = fgx ^ bgx; + +#ifdef CONFIG_VIDEO_LOGO + /* Plot the logo and get start point of console */ + PRINTD("Video: Drawing the logo ...\n"); + video_console_address = video_logo(); +#else + video_console_address = video_fb_address; +#endif + + /* Initialize the console */ + console_col = 0; + console_row = 0; + + return 0 ; +} + + +/*****************************************************************************/ + +int drv_video_init (void) +{ + int skip_dev_init; + device_t console_dev; + char *penv; + + skip_dev_init = 0; + + /* Force console i/o to serial ? */ + if ((penv = getenv ("console")) != NULL) + if (strcmp (penv, "serial") == 0) + return 0; + + /* Init video chip - returns with framebuffer cleared */ + if (video_init() == -1) + skip_dev_init = 1; +#ifdef CONFIG_VGA_AS_SINGLE_DEVICE + /* Devices VGA and Keyboard will be assigned seperately */ + /* Init vga device */ + if (!skip_dev_init) + { + memset (&console_dev, 0, sizeof(console_dev)); + strcpy(console_dev.name, "vga"); + console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ + console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; + console_dev.putc = video_putc; /* 'putc' function */ + console_dev.puts = video_puts; /* 'puts' function */ + console_dev.tstc = NULL; /* 'tstc' function */ + console_dev.getc = NULL; /* 'getc' function */ + + if (device_register (&console_dev) == 0) + return 1; + } +#else + PRINTD("KBD: Keyboard init ...\n"); + if (VIDEO_KBD_INIT_FCT == -1) + skip_dev_init = 1; + + /* Init console device */ + if (!skip_dev_init) + { + memset (&console_dev, 0, sizeof(console_dev)); + strcpy(console_dev.name, "console"); + console_dev.ext = DEV_EXT_VIDEO; /* Video extensions */ + console_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + console_dev.putc = video_putc; /* 'putc' function */ + console_dev.puts = video_puts; /* 'puts' function */ + console_dev.tstc = VIDEO_TSTC_FCT; /* 'tstc' function */ + console_dev.getc = VIDEO_GETC_FCT; /* 'getc' function */ + + if (device_register (&console_dev) == 0) + return 1; + } +#endif /* CONFIG_VGA_AS_SINGLE_DEVICE */ + /* No console dev available */ + return 0; +} + +#endif /* CONFIG_CFB_CONSOLE */ + + + + + + + diff --git a/drivers/cs8900.c b/drivers/cs8900.c new file mode 100644 index 0000000..ecc7c13 --- /dev/null +++ b/drivers/cs8900.c @@ -0,0 +1,235 @@ +/* + * Cirrus Logic CS8900A Ethernet + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 1999 Ben Williamson <benw@pobox.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is loaded into SRAM in bootstrap mode, where it waits + * for commands on UART1 to read and write memory, jump to code etc. + * A design goal for this program is to be entirely independent of the + * target board. Anything with a CL-PS7111 or EP7211 should be able to run + * this code in bootstrap mode. All the board specifics can be handled on + * the host. + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <common.h> +#include <command.h> +#include "cs8900.h" +#include <net.h> + +#ifdef CONFIG_DRIVER_CS8900 + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + + +/* packet page register access functions */ + +#ifdef CS8900_BUS32 +/* we don't need 16 bit initialisation on 32 bit bus */ +#define get_reg_init_bus(x) get_reg((x)) +#else +static unsigned short get_reg_init_bus(int regno) +{ + /* force 16 bit busmode */ + volatile unsigned char c; + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + c = CS8900_BUS16_1; + c = CS8900_BUS16_0; + + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; +} +#endif + +static unsigned short +get_reg(int regno) +{ + CS8900_PPTR = regno; + return (unsigned short) CS8900_PDATA; +} + + +static void put_reg(int regno, unsigned short val) +{ + CS8900_PPTR = regno; + CS8900_PDATA = val; +} + +static void eth_reset(void) +{ + int tmo; + unsigned short us; + + /* reset NIC */ + put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset ); + + /* wait for 200ms */ + udelay(200000); + /* Wait until the chip is reset */ + + tmo = get_timer(0) + 1 * CFG_HZ; + while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0) + && tmo < get_timer(0)) + /*NOP*/; +} + +void cs8900_get_enetaddr (uchar *addr) +{ + int i; + /* verify chip id */ + if (get_reg_init_bus(PP_ChipID) != 0x630e) + return; + eth_reset(); + if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == + (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) { + /* Load the MAC from EEPROM */ + for (i=0; i<6/2; i++) { + unsigned int Addr; + Addr = get_reg(PP_IA+i*2); + addr[i*2] = Addr & 0xFF; + addr[i*2+1] = Addr >> 8; + } + } +} + +void eth_halt( void ) +{ + /* disable transmitter/receiver mode */ + put_reg(PP_LineCTL, 0); + + /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */ + get_reg_init_bus(PP_ChipID); +} + +int eth_init( bd_t *bd ) +{ + + /* verify chip id */ + if (get_reg_init_bus(PP_ChipID) != 0x630e) + { + printf( "CS8900 Ethernet chip not found?!\n" ); + return 0; + } + + eth_reset(); + /* set the ethernet address */ + put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8)); + put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8)); + put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8)); + + /* receive only error free packets addressed to this card */ + put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK); + + /* do not generate any interrupts on receive operations */ + put_reg(PP_RxCFG, 0); + + /* do not generate any interrupts on transmit operations */ + put_reg(PP_TxCFG, 0); + + /* do not generate any interrupts on buffer operations */ + put_reg(PP_BufCFG, 0); + + /* enable transmitter/receiver mode */ + put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx); + + return 0; +} + +/* Get a data block via Ethernet */ +extern int eth_rx(void) +{ + int i; + unsigned short rxlen; + unsigned short *addr; + unsigned short status; + + status = get_reg(PP_RER); + + if ((status & PP_RER_RxOK) == 0) + return 0; + + status = CS8900_RTDATA; /* stat */ + rxlen = CS8900_RTDATA; /* len */ + + if(rxlen > PKTSIZE_ALIGN + PKTALIGN) + printf("packet too big!\n"); + + for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- ) + *addr++ = CS8900_RTDATA; + if(rxlen & 1) + *addr++ = CS8900_RTDATA; + + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[0], rxlen); + + return rxlen; +} + +/* Send a data block via Ethernet. */ +extern int eth_send(volatile void *packet, int length) +{ + volatile unsigned short *addr; + int tmo; + unsigned short s; + +retry: + /* initiate a transmit sequence */ + CS8900_TxCMD = PP_TxCmd_TxStart_Full; + CS8900_TxLEN = length; + + /* Test to see if the chip has allocated memory for the packet */ + if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) { + /* Oops... this should not happen! */ + printf("cs: unable to send packet; retrying...\n"); + for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; ) + /*NOP*/; + eth_reset(); + goto retry; + } + + /* Write the contents of the packet */ + /* assume even number of bytes */ + for(addr = packet; length > 0; length -= 2 ) + CS8900_RTDATA = *addr++; + + /* wait for transfer to succeed */ + tmo = get_timer(0) + 5 * CFG_HZ; + while((s = get_reg(PP_TER) & ~0x1F) == 0) + { + if (get_timer(0) >= tmo) + break; + } + + /* nothing */ ; + if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) { + printf("\ntransmission error %#x\n", s); + } + + return 0; +} + +#endif /* COMMANDS & CFG_NET */ + +#endif /* CONFIG_DRIVER_CS8900 */ diff --git a/drivers/ct69000.c b/drivers/ct69000.c new file mode 100644 index 0000000..7962f74 --- /dev/null +++ b/drivers/ct69000.c @@ -0,0 +1,1484 @@ +/* + * (C) Copyright 2002 + * Denis Peter, MPL AG Switzerland + * + * 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 + */ + +/* + * ported from ctfb.c (linux kernel) for the U-Boot + * + */ + +/************************************************************************ + Get Parameters for the video mode: + Parameters can be set via the variable "videomode" in the environment. + 2 diferent ways are possible: + "videomode=301" - 301 is a hexadecimal number describing the VESA + mode. Following modes are implemented: + + Colors 640x480 800x600 1024x768 1152x864 + --------+----------------------------------- + 8 bits | 0x301 0x303 0x305 0x161 + 15 bits | 0x310 0x313 0x316 0x162 + 16 bits | 0x311 0x314 0x317 0x163 + 24 bits | 0x312 0x315 0x318 ? + --------+----------------------------------- + "videomode=bootargs" + - the parameters are parsed from the bootargs. + The format is "NAME:VALUE,NAME:VALUE" etc. + Ex.: + "bootargs=video=ctfb:x:800,y:600,depth:16,pclk:25000" + Parameters not included in the list will be taken from + the default mode, which is one of the following: + mode:0 640x480x24 + mode:1 800x600x16 + mode:2 1024x768x8 + mode:3 960x720x24 + mode:4 1152x864x16 + if "mode" is not provided within the parameter list, + mode:0 is assumed. + Following parameters are supported: + x xres = visible resolution horizontal + y yres = visible resolution vertical + pclk pixelclocks in pico sec + le left_marging time from sync to picture in pixelclocks + ri right_marging time from picture to sync in pixelclocks + up upper_margin time from sync to picture + lo lower_margin + hs hsync_len length of horizontal sync + vs vsync_len length of vertical sync + sync see FB_SYNC_* + vmode see FB_VMODE_* + depth Color depth in bits per pixel + All other parameters in the variable bootargs are ignored. + It is also possible to set the parameters direct in the + variable "videomode", or in another variable i.e. + "myvideo" and setting the variable "videomode=myvideo".. +****************************************************************************/ + +#include <common.h> + +#ifdef CONFIG_VIDEO + +#include <pci.h> +#include <video_fb.h> + +#ifdef CONFIG_VIDEO_CT69000 + +/* debug */ +#undef VGA_DEBUG +#undef VGA_DUMP_REG +#ifdef VGA_DEBUG +#define PRINTF(fmt,args...) printf (fmt ,##args) +#else +#define PRINTF(fmt,args...) +#endif + +/* Macros */ +#ifndef min +#define min( a, b ) ( ( a ) < ( b ) ) ? ( a ) : ( b ) +#endif +#ifndef max +#define max( a, b ) ( ( a ) > ( b ) ) ? ( a ) : ( b ) +#endif +#ifdef minmax +#error "term minmax already used." +#endif +#define minmax( a, x, b ) max( ( a ), min( ( x ), ( b ) ) ) +#define N_ELTS( x ) ( sizeof( x ) / sizeof( x[ 0 ] ) ) + +/* CT Register Offsets */ +#define CT_AR_O 0x3c0 /* Index and Data write port of the attribute Registers */ +#define CT_GR_O 0x3ce /* Index port of the Graphic Controller Registers */ +#define CT_SR_O 0x3c4 /* Index port of the Sequencer Controller */ +#define CT_CR_O 0x3d4 /* Index port of the CRT Controller */ +#define CT_XR_O 0x3d6 /* Extended Register index */ +#define CT_MSR_W_O 0x3c2 /* Misc. Output Register (write only) */ +#define CT_LUT_MASK_O 0x3c6 /* Color Palette Mask */ +#define CT_LUT_START_O 0x3c8 /* Color Palette Write Mode Index */ +#define CT_LUT_RGB_O 0x3c9 /* Color Palette Data Port */ +#define CT_STATUS_REG0_O 0x3c2 /* Status Register 0 (read only) */ +#define CT_STATUS_REG1_O 0x3da /* Input Status Register 1 (read only) */ + +#define CT_FP_O 0x3d0 /* Index port of the Flat panel Registers */ +#define CT_MR_O 0x3d2 /* Index Port of the Multimedia Extension */ + +/* defines for the memory mapped registers */ +#define BR00_o 0x400000 /* Source and Destination Span Register */ +#define BR01_o 0x400004 /* Pattern/Source Expansion Background Color & Transparency Key Register */ +#define BR02_o 0x400008 /* Pattern/Source Expansion Foreground Color Register */ +#define BR03_o 0x40000C /* Monochrome Source Control Register */ +#define BR04_o 0x400010 /* BitBLT Control Register */ +#define BR05_o 0x400014 /* Pattern Address Registe */ +#define BR06_o 0x400018 /* Source Address Register */ +#define BR07_o 0x40001C /* Destination Address Register */ +#define BR08_o 0x400020 /* Destination Width & Height Register */ +#define BR09_o 0x400024 /* Source Expansion Background Color & Transparency Key Register */ +#define BR0A_o 0x400028 /* Source Expansion Foreground Color Register */ + +#define CURSOR_SIZE 0x1000 /* in KByte for HW Cursor */ +#define PATTERN_ADR (pGD->dprBase + CURSOR_SIZE) /* pattern Memory after Cursor Memory */ +#define PATTERN_SIZE 8*8*4 /* 4 Bytes per Pixel 8 x 8 Pixel */ +#define ACCELMEMORY (CURSOR_SIZE + PATTERN_SIZE) /* reserved Memory for BITBlt and hw cursor */ + +/* Some Mode definitions */ +#define FB_SYNC_HOR_HIGH_ACT 1 /* horizontal sync high active */ +#define FB_SYNC_VERT_HIGH_ACT 2 /* vertical sync high active */ +#define FB_SYNC_EXT 4 /* external sync */ +#define FB_SYNC_COMP_HIGH_ACT 8 /* composite sync high active */ +#define FB_SYNC_BROADCAST 16 /* broadcast video timings */ + /* vtotal = 144d/288n/576i => PAL */ + /* vtotal = 121d/242n/484i => NTSC */ +#define FB_SYNC_ON_GREEN 32 /* sync on green */ + +#define FB_VMODE_NONINTERLACED 0 /* non interlaced */ +#define FB_VMODE_INTERLACED 1 /* interlaced */ +#define FB_VMODE_DOUBLE 2 /* double scan */ +#define FB_VMODE_MASK 255 + +#define FB_VMODE_YWRAP 256 /* ywrap instead of panning */ +#define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ +#define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ + +#define text 0 +#define fntwidth 8 + +/* table for VGA Initialization */ +typedef struct { + const unsigned char reg; + const unsigned char val; +} CT_CFG_TABLE; + +/* this table provides some basic initialisations such as Memory Clock etc */ +static CT_CFG_TABLE xreg[] = { + {0x09, 0x01}, /* CRT Controller Extensions Enable */ + {0x0A, 0x02}, /* Frame Buffer Mapping */ + {0x0B, 0x01}, /* PCI Write Burst support */ + {0x20, 0x00}, /* BitBLT Configuration */ + {0x40, 0x03}, /* Memory Access Control */ + {0x60, 0x00}, /* Video Pin Control */ + {0x61, 0x00}, /* DPMS Synch control */ + {0x62, 0x00}, /* GPIO Pin Control */ + {0x63, 0xBD}, /* GPIO Pin Data */ + {0x67, 0x00}, /* Pin Tri-State */ + {0x80, 0x80}, /* Pixel Pipeline Config 0 register */ + {0xA0, 0x00}, /* Cursor 1 Control Reg */ + {0xA1, 0x00}, /* Cursor 1 Vertical Extension Reg */ + {0xA2, 0x00}, /* Cursor 1 Base Address Low */ + {0xA3, 0x00}, /* Cursor 1 Base Address High */ + {0xA4, 0x00}, /* Cursor 1 X-Position Low */ + {0xA5, 0x00}, /* Cursor 1 X-Position High */ + {0xA6, 0x00}, /* Cursor 1 Y-Position Low */ + {0xA7, 0x00}, /* Cursor 1 Y-Position High */ + {0xA8, 0x00}, /* Cursor 2 Control Reg */ + {0xA9, 0x00}, /* Cursor 2 Vertical Extension Reg */ + {0xAA, 0x00}, /* Cursor 2 Base Address Low */ + {0xAB, 0x00}, /* Cursor 2 Base Address High */ + {0xAC, 0x00}, /* Cursor 2 X-Position Low */ + {0xAD, 0x00}, /* Cursor 2 X-Position High */ + {0xAE, 0x00}, /* Cursor 2 Y-Position Low */ + {0xAF, 0x00}, /* Cursor 2 Y-Position High */ + {0xC0, 0x7D}, /* Dot Clock 0 VCO M-Divisor */ + {0xC1, 0x07}, /* Dot Clock 0 VCO N-Divisor */ + {0xC3, 0x34}, /* Dot Clock 0 Divisor select */ + {0xC4, 0x55}, /* Dot Clock 1 VCO M-Divisor */ + {0xC5, 0x09}, /* Dot Clock 1 VCO N-Divisor */ + {0xC7, 0x24}, /* Dot Clock 1 Divisor select */ + {0xC8, 0x7D}, /* Dot Clock 2 VCO M-Divisor */ + {0xC9, 0x07}, /* Dot Clock 2 VCO N-Divisor */ + {0xCB, 0x34}, /* Dot Clock 2 Divisor select */ + {0xCC, 0x38}, /* Memory Clock 0 VCO M-Divisor */ + {0xCD, 0x03}, /* Memory Clock 0 VCO N-Divisor */ + {0xCE, 0x90}, /* Memory Clock 0 Divisor select */ + {0xCF, 0x06}, /* Clock Config */ + {0xD0, 0x0F}, /* Power Down */ + {0xD1, 0x01}, /* Power Down BitBLT */ + {0xFF, 0xFF} /* end of table */ +}; +/* Clock Config: + * ============= + * + * PD Registers: + * ------------- + * Bit2 and Bit4..6 are used for the Loop Divisor and Post Divisor. + * They are encoded as follows: + * + * +---+--------------+ + * | 2 | Loop Divisor | + * +---+--------------+ + * | 1 | 1 | + * +---+--------------+ + * | 0 | 4 | + * +---+--------------+ + * Note: The Memory Clock does not have a Loop Divisor. + * +---+---+---+--------------+ + * | 6 | 5 | 4 | Post Divisor | + * +---+---+---+--------------+ + * | 0 | 0 | 0 | 1 | + * +---+---+---+--------------+ + * | 0 | 0 | 1 | 2 | + * +---+---+---+--------------+ + * | 0 | 1 | 0 | 4 | + * +---+---+---+--------------+ + * | 0 | 1 | 1 | 8 | + * +---+---+---+--------------+ + * | 1 | 0 | 0 | 16 | + * +---+---+---+--------------+ + * | 1 | 0 | 1 | 32 | + * +---+---+---+--------------+ + * | 1 | 1 | X | reserved | + * +---+---+---+--------------+ + * + * All other bits are reserved in these registers. + * + * Clock VCO M Registers: + * ---------------------- + * These Registers contain the M Value -2. + * + * Clock VCO N Registers: + * ---------------------- + * These Registers contain the N Value -2. + * + * Formulas: + * --------- + * Fvco = (Fref * Loop Divisor * M/N), whereas 100MHz < Fvco < 220MHz + * Fout = Fvco / Post Divisor + * + * Dot Clk0 (default 25MHz): + * ------------------------- + * Fvco = 14.318 * 127 / 9 = 202.045MHz + * Fout = 202.045MHz / 8 = 25.25MHz + * Post Divisor = 8 + * Loop Divisor = 1 + * XRC0 = (M - 2) = 125 = 0x7D + * XRC1 = (N - 2) = 7 = 0x07 + * XRC3 = 0x34 + * + * Dot Clk1 (default 28MHz): + * ------------------------- + * Fvco = 14.318 * 87 / 11 = 113.24MHz + * Fout = 113.24MHz / 4 = 28.31MHz + * Post Divisor = 4 + * Loop Divisor = 1 + * XRC4 = (M - 2) = 85 = 0x55 + * XRC5 = (N - 2) = 9 = 0x09 + * XRC7 = 0x24 + * + * Dot Clk2 (variable for extended modes set to 25MHz): + * ---------------------------------------------------- + * Fvco = 14.318 * 127 / 9 = 202.045MHz + * Fout = 202.045MHz / 8 = 25.25MHz + * Post Divisor = 8 + * Loop Divisor = 1 + * XRC8 = (M - 2) = 125 = 0x7D + * XRC9 = (N - 2) = 7 = 0x07 + * XRCB = 0x34 + * + * Memory Clk for most modes >50MHz: + * ---------------------------------- + * Fvco = 14.318 * 58 / 5 = 166MHz + * Fout = 166MHz / 2 = 83MHz + * Post Divisor = 2 + * XRCC = (M - 2) = 57 = 0x38 + * XRCD = (N - 2) = 3 = 0x03 + * XRCE = 0x90 + * + * Note Bit7 enables the clock source from the VCO + * + */ + +/****************************************************************** + * Resolution Struct + ******************************************************************/ +struct ctfb_res_modes { + int xres; /* visible resolution */ + int yres; + /* Timing: All values in pixclocks, except pixclock (of course) */ + int pixclock; /* pixel clock in ps (pico seconds) */ + int left_margin; /* time from sync to picture */ + int right_margin; /* time from picture to sync */ + int upper_margin; /* time from sync to picture */ + int lower_margin; + int hsync_len; /* length of horizontal sync */ + int vsync_len; /* length of vertical sync */ + int sync; /* see FB_SYNC_* */ + int vmode; /* see FB_VMODE_* */ +}; + +/****************************************************************** + * Vesa Mode Struct + ******************************************************************/ +struct ctfb_vesa_modes { + int vesanr; /* Vesa number as in LILO (VESA Nr + 0x200} */ + int resindex; /* index to resolution struct */ + int bits_per_pixel; /* bpp */ +}; +/******************************************************************* + * Chips struct + *******************************************************************/ +struct ctfb_chips_properties { + int device_id; /* PCI Device ID */ + unsigned long max_mem; /* memory for frame buffer */ + int vld_set; /* value of VLD if bit2 in clock control is set */ + int vld_not_set; /* value of VLD if bit2 in clock control is set */ + int mn_diff; /* difference between M/N Value + mn_diff = M/N Register */ + int mn_min; /* min value of M/N Value */ + int mn_max; /* max value of M/N Value */ + int vco_min; /* VCO Min in MHz */ + int vco_max; /* VCO Max in MHz */ +}; + +static const struct ctfb_chips_properties chips[] = { + {PCI_DEVICE_ID_CT_69000, 0x200000, 1, 4, -2, 3, 257, 100, 220}, + {PCI_DEVICE_ID_CT_65555, 0x100000, 16, 4, 0, 1, 255, 48, 220}, /* NOT TESTED */ + {0, 0, 0, 0, 0, 0, 0, 0, 0} /* Terminator */ +}; + +/************************************************* + Video Modes: +Colours 640x400 640x480 800x600 1024x768 1152x864 1280x1024 1600x1200 +--------+-------------------------------------------------------------- + 4 bits | ? ? 0x302 ? ? ? ? + 8 bits | 0x300 0x301 0x303 0x305 0x161 0x307 0x31C +15 bits | ? 0x310 0x313 0x316 0x162 0x319 0x31D +16 bits | ? 0x311 0x314 0x317 0x163 0x31A 0x31E +24 bits | ? 0x312 0x315 0x318 ? 0x31B 0x31F +32 bits | ? ? ? ? 0x164 ? +*/ + +#define RES_MODE_640x480 0 +#define RES_MODE_800x600 1 +#define RES_MODE_1024x768 2 +#define RES_MODE_960_720 3 +#define RES_MODE_1152x864 4 +#define RES_MODES_COUNT 5 + +#define VESA_MODES_COUNT 15 + +static const struct ctfb_vesa_modes vesa_modes[VESA_MODES_COUNT] = { + {0x301, RES_MODE_640x480, 8}, + {0x310, RES_MODE_640x480, 15}, + {0x311, RES_MODE_640x480, 16}, + {0x312, RES_MODE_640x480, 24}, + {0x303, RES_MODE_800x600, 8}, + {0x313, RES_MODE_800x600, 15}, + {0x314, RES_MODE_800x600, 16}, + {0x315, RES_MODE_800x600, 24}, + {0x305, RES_MODE_1024x768, 8}, + {0x316, RES_MODE_1024x768, 15}, + {0x317, RES_MODE_1024x768, 16}, + {0x318, RES_MODE_1024x768, 24}, + {0x161, RES_MODE_1152x864, 8}, + {0x162, RES_MODE_1152x864, 15}, + {0x163, RES_MODE_1152x864, 16} +}; + +static const struct ctfb_res_modes res_mode_init[RES_MODES_COUNT] = { + /* x y pixclk le ri up lo hs vs s vmode */ + {640, 480, 39721, 40, 24, 32, 11, 96, 2, 0, + FB_VMODE_NONINTERLACED}, + {800, 600, 27778, 64, 24, 22, 1, 72, 2, 0, FB_VMODE_NONINTERLACED}, + {1024, 768, 15384, 168, 8, 29, 3, 144, 4, 0, + FB_VMODE_NONINTERLACED}, + {960, 720, 13100, 160, 40, 32, 8, 80, 4, 0, + FB_VMODE_NONINTERLACED}, + {1152, 864, 12004, 200, 64, 32, 16, 80, 4, 0, + FB_VMODE_NONINTERLACED} +}; + +/* + * The Graphic Device + */ +GraphicDevice ctfb; + +/******************************************************************************* +* +* Low Level Routines +*/ + +/******************************************************************************* +* +* Read CT ISA register +*/ +#ifdef VGA_DEBUG +static unsigned char +ctRead (unsigned short index) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + if (index == CT_AR_O) + /* synch the Flip Flop */ + in8 (pGD->isaBase + CT_STATUS_REG1_O); + + return (in8 (pGD->isaBase + index)); +} +#endif +/******************************************************************************* +* +* Write CT ISA register +*/ +static void +ctWrite (unsigned short index, unsigned char val) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + + out8 ((pGD->isaBase + index), val); +} + +/******************************************************************************* +* +* Read CT ISA register indexed +*/ +static unsigned char +ctRead_i (unsigned short index, char reg) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + if (index == CT_AR_O) + /* synch the Flip Flop */ + in8 (pGD->isaBase + CT_STATUS_REG1_O); + out8 ((pGD->isaBase + index), reg); + return (in8 (pGD->isaBase + index + 1)); +} + +/******************************************************************************* +* +* Write CT ISA register indexed +*/ +static void +ctWrite_i (unsigned short index, char reg, char val) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + if (index == CT_AR_O) { + /* synch the Flip Flop */ + in8 (pGD->isaBase + CT_STATUS_REG1_O); + out8 ((pGD->isaBase + index), reg); + out8 ((pGD->isaBase + index), val); + } else { + out8 ((pGD->isaBase + index), reg); + out8 ((pGD->isaBase + index + 1), val); + } +} + +/******************************************************************************* +* +* Write a table of CT ISA register +*/ +static void +ctLoadRegs (unsigned short index, CT_CFG_TABLE * regTab) +{ + while (regTab->reg != 0xFF) { + ctWrite_i (index, regTab->reg, regTab->val); + regTab++; + } +} + +/*****************************************************************************/ +static void +SetArRegs (void) +{ + int i, tmp; + + for (i = 0; i < 0x10; i++) + ctWrite_i (CT_AR_O, i, i); + if (text) + tmp = 0x04; + else + tmp = 0x41; + + ctWrite_i (CT_AR_O, 0x10, tmp); /* Mode Control Register */ + ctWrite_i (CT_AR_O, 0x11, 0x00); /* Overscan Color Register */ + ctWrite_i (CT_AR_O, 0x12, 0x0f); /* Memory Plane Enable Register */ + if (fntwidth == 9) + tmp = 0x08; + else + tmp = 0x00; + ctWrite_i (CT_AR_O, 0x13, tmp); /* Horizontal Pixel Panning */ + ctWrite_i (CT_AR_O, 0x14, 0x00); /* Color Select Register */ + ctWrite (CT_AR_O, 0x20); /* enable video */ +} + +/*****************************************************************************/ +static void +SetGrRegs (void) +{ /* Set Graphics Mode */ + int i; + + for (i = 0; i < 0x05; i++) + ctWrite_i (CT_GR_O, i, 0); + if (text) { + ctWrite_i (CT_GR_O, 0x05, 0x10); + ctWrite_i (CT_GR_O, 0x06, 0x02); + } else { + ctWrite_i (CT_GR_O, 0x05, 0x40); + ctWrite_i (CT_GR_O, 0x06, 0x05); + } + ctWrite_i (CT_GR_O, 0x07, 0x0f); + ctWrite_i (CT_GR_O, 0x08, 0xff); +} + +/*****************************************************************************/ +static void +SetSrRegs (void) +{ + int tmp = 0; + + ctWrite_i (CT_SR_O, 0x00, 0x00); /* reset */ + /*rr( sr, 0x01, tmp ); + if( fntwidth == 8 ) tmp |= 0x01; else tmp &= ~0x01; + wr( sr, 0x01, tmp ); */ + if (fntwidth == 8) + ctWrite_i (CT_SR_O, 0x01, 0x01); /* Clocking Mode Register */ + else + ctWrite_i (CT_SR_O, 0x01, 0x00); /* Clocking Mode Register */ + ctWrite_i (CT_SR_O, 0x02, 0x0f); /* Enable CPU wr access to given memory plane */ + ctWrite_i (CT_SR_O, 0x03, 0x00); /* Character Map Select Register */ + if (text) + tmp = 0x02; + else + tmp = 0x0e; + ctWrite_i (CT_SR_O, 0x04, tmp); /* Enable CPU accesses to the rest of the 256KB + total VGA memory beyond the first 64KB and set + fb mapping mode. */ + ctWrite_i (CT_SR_O, 0x00, 0x03); /* enable */ +} + +/*****************************************************************************/ +static void +SetBitsPerPixelIntoXrRegs (int bpp) +{ + unsigned int n = (bpp >> 3), tmp; /* only for 15, 8, 16, 24 bpp */ + static char md[4] = { 0x04, 0x02, 0x05, 0x06 }; /* DisplayColorMode */ + static char off[4] = { ~0x20, ~0x30, ~0x20, ~0x10 }; /* mask */ + static char on[4] = { 0x10, 0x00, 0x10, 0x20 }; /* mask */ + if (bpp == 15) + n = 0; + tmp = ctRead_i (CT_XR_O, 0x20); + tmp &= off[n]; + tmp |= on[n]; + ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */ + ctWrite_i (CT_XR_O, 0x81, md[n]); +} + +/*****************************************************************************/ +static void +SetCrRegs (struct ctfb_res_modes *var, int bits_per_pixel) +{ /* he -le- ht|0 hd -ri- hs -h- he */ + unsigned char cr[0x7a]; + int i, tmp; + unsigned int hd, hs, he, ht, hbe; /* Horizontal. */ + unsigned int vd, vs, ve, vt; /* vertical */ + unsigned int bpp, wd, dblscan, interlaced, bcast, CrtHalfLine; + unsigned int CompSyncCharClkDelay, CompSyncPixelClkDelay; + unsigned int NTSC_PAL_HorizontalPulseWidth, BlDelayCtrl; + unsigned int HorizontalEqualizationPulses; + unsigned int HorizontalSerration1Start, HorizontalSerration2Start; + + const int LineCompare = 0x3ff; + unsigned int TextScanLines = 1; /* this is in fact a vertical zoom factor */ + unsigned int RAMDAC_BlankPedestalEnable = 0; /* 1=en-, 0=disable, see XR82 */ + + hd = (var->xres) / 8; /* HDisp. */ + hs = (var->xres + var->right_margin) / 8; /* HsStrt */ + he = (var->xres + var->right_margin + var->hsync_len) / 8; /* HsEnd */ + ht = (var->left_margin + var->xres + var->right_margin + var->hsync_len) / 8; /* HTotal */ + hbe = ht - 1; /* HBlankEnable todo docu wants ht here, but it does not work */ + /* ve -up- vt|0 vd -lo- vs -v- ve */ + vd = var->yres; /* VDisplay */ + vs = var->yres + var->lower_margin; /* VSyncStart */ + ve = var->yres + var->lower_margin + var->vsync_len; /* VSyncEnd */ + vt = var->upper_margin + var->yres + var->lower_margin + var->vsync_len; /* VTotal */ + bpp = bits_per_pixel; + dblscan = (var->vmode & FB_VMODE_DOUBLE) ? 1 : 0; + interlaced = var->vmode & FB_VMODE_INTERLACED; + bcast = var->sync & FB_SYNC_BROADCAST; + CrtHalfLine = bcast ? (hd >> 1) : 0; + BlDelayCtrl = bcast ? 1 : 0; + CompSyncCharClkDelay = 0; /* 2 bit */ + CompSyncPixelClkDelay = 0; /* 3 bit */ + if (bcast) { + NTSC_PAL_HorizontalPulseWidth = 7; /*( var->hsync_len >> 1 ) + 1 */ + HorizontalEqualizationPulses = 0; /* inverse value */ + HorizontalSerration1Start = 31; /* ( ht >> 1 ) */ + HorizontalSerration2Start = 89; /* ( ht >> 1 ) */ + } else { + NTSC_PAL_HorizontalPulseWidth = 0; + /* 4 bit: hsync pulse width = ( ( CR74[4:0] - CR74[5] ) + * / 2 ) + 1 --> CR74[4:0] = 2*(hs-1) + CR74[5] */ + HorizontalEqualizationPulses = 1; /* inverse value */ + HorizontalSerration1Start = 0; /* ( ht >> 1 ) */ + HorizontalSerration2Start = 0; /* ( ht >> 1 ) */ + } + + if (bpp == 15) + bpp = 16; + wd = var->xres * bpp / 64; /* double words per line */ + if (interlaced) { /* we divide all vertical timings, exept vd */ + vs >>= 1; + ve >>= 1; + vt >>= 1; + } + memset (cr, 0, sizeof (cr)); + cr[0x00] = 0xff & (ht - 5); + cr[0x01] = hd - 1; /* soll:4f ist 59 */ + cr[0x02] = hd; + cr[0x03] = (hbe & 0x1F) | 0x80; /* hd + ht - hd */ + cr[0x04] = hs; + cr[0x05] = ((hbe & 0x20) << 2) | (he & 0x1f); + cr[0x06] = (vt - 2) & 0xFF; + cr[0x30] = (vt - 2) >> 8; + cr[0x07] = ((vt & 0x100) >> 8) + | ((vd & 0x100) >> 7) + | ((vs & 0x100) >> 6) + | ((vs & 0x100) >> 5) + | ((LineCompare & 0x100) >> 4) + | ((vt & 0x200) >> 4) + | ((vd & 0x200) >> 3) + | ((vs & 0x200) >> 2); + cr[0x08] = 0x00; + cr[0x09] = (dblscan << 7) + | ((LineCompare & 0x200) >> 3) + | ((vs & 0x200) >> 4) + | (TextScanLines - 1); + cr[0x10] = vs & 0xff; /* VSyncPulseStart */ + cr[0x32] = (vs & 0xf00) >> 8; /* VSyncPulseStart */ + cr[0x11] = (ve & 0x0f); /* | 0x20; */ + cr[0x12] = (vd - 1) & 0xff; /* LineCount */ + cr[0x31] = ((vd - 1) & 0xf00) >> 8; /* LineCount */ + cr[0x13] = wd & 0xff; + cr[0x41] = (wd & 0xf00) >> 8; + cr[0x15] = vs & 0xff; + cr[0x33] = (vs & 0xf00) >> 8; + cr[0x38] = (0x100 & (ht - 5)) >> 8; + cr[0x3C] = 0xc0 & hbe; + cr[0x16] = (vt - 1) & 0xff; /* vbe - docu wants vt here, */ + cr[0x17] = 0xe3; /* but it does not work */ + cr[0x18] = 0xff & LineCompare; + cr[0x22] = 0xff; /* todo? */ + cr[0x70] = interlaced ? (0x80 | CrtHalfLine) : 0x00; /* check:0xa6 */ + cr[0x71] = 0x80 | (RAMDAC_BlankPedestalEnable << 6) + | (BlDelayCtrl << 5) + | ((0x03 & CompSyncCharClkDelay) << 3) + | (0x07 & CompSyncPixelClkDelay); /* todo: see XR82 */ + cr[0x72] = HorizontalSerration1Start; + cr[0x73] = HorizontalSerration2Start; + cr[0x74] = (HorizontalEqualizationPulses << 5) + | NTSC_PAL_HorizontalPulseWidth; + /* todo: ct69000 has also 0x75-79 */ + /* now set the registers */ + for (i = 0; i <= 0x0d; i++) { /*CR00 .. CR0D */ + ctWrite_i (CT_CR_O, i, cr[i]); + } + for (i = 0x10; i <= 0x18; i++) { /*CR10 .. CR18 */ + ctWrite_i (CT_CR_O, i, cr[i]); + } + i = 0x22; /*CR22 */ + ctWrite_i (CT_CR_O, i, cr[i]); + for (i = 0x30; i <= 0x33; i++) { /*CR30 .. CR33 */ + ctWrite_i (CT_CR_O, i, cr[i]); + } + i = 0x38; /*CR38 */ + ctWrite_i (CT_CR_O, i, cr[i]); + i = 0x3C; /*CR3C */ + ctWrite_i (CT_CR_O, i, cr[i]); + for (i = 0x40; i <= 0x41; i++) { /*CR40 .. CR41 */ + ctWrite_i (CT_CR_O, i, cr[i]); + } + for (i = 0x70; i <= 0x74; i++) { /*CR70 .. CR74 */ + ctWrite_i (CT_CR_O, i, cr[i]); + } + tmp = ctRead_i (CT_CR_O, 0x40); + tmp &= 0x0f; + tmp |= 0x80; + ctWrite_i (CT_CR_O, 0x40, tmp); /* StartAddressEnable */ +} + +/* pixelclock control */ + +/***************************************************************************** + We have a rational number p/q and need an m/n which is very close to p/q + but has m and n within mnmin and mnmax. We have no floating point in the + kernel. We can use long long without divide. And we have time to compute... +******************************************************************************/ +static unsigned int +FindBestPQFittingMN (unsigned int p, unsigned int q, unsigned int mnmin, + unsigned int mnmax, unsigned int *pm, unsigned int *pn) +{ + /* this code is not for general purpose usable but good for our number ranges */ + unsigned int n = mnmin, m = 0; + long long int L = 0, P = p, Q = q, H = P >> 1; + long long int D = 0x7ffffffffffffffLL; + for (n = mnmin; n <= mnmax; n++) { + m = mnmin; /* p/q ~ m/n -> p*n ~ m*q -> p*n-x*q ~ 0 */ + L = P * n - m * Q; /* n * vco - m * fref should be near 0 */ + while (L > 0 && m < mnmax) { + L -= q; /* difference is greater as 0 subtract fref */ + m++; /* and increment m */ + } + /* difference is less or equal than 0 or m > maximum */ + if (m > mnmax) + break; /* no solution: if we increase n we get the same situation */ + /* L is <= 0 now */ + if (-L > H && m > mnmin) { /* if difference > the half fref */ + L += q; /* we take the situation before */ + m--; /* because its closer to 0 */ + } + L = (L < 0) ? -L : +L; /* absolute value */ + if (D < L) /* if last difference was better take next n */ + continue; + D = L; + *pm = m; + *pn = n; /* keep improved data */ + if (D == 0) + break; /* best result we can get */ + } + return (unsigned int) (0xffffffff & D); +} + +/* that is the hardware < 69000 we have to manage + +---------+ +-------------------+ +----------------------+ +--+ + | REFCLK |__|NTSC Divisor Select|__|FVCO Reference Divisor|__|÷N|__ + | 14.3MHz | |(NTSCDS) (÷1, ÷5) | |Select (RDS) (÷1, ÷4) | | | | + +---------+ +-------------------+ +----------------------+ +--+ | + ___________________________________________________________________| + | + | fvco fout + | +--------+ +------------+ +-----+ +-------------------+ +----+ + +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |---> + +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | | + | +--------+ +------------+ +-----+ | +-------------------+ +----+ + | | + | +--+ +---------------+ | + |____|÷M|___|VCO Loop Divide|__________| + | | |(VLD)(÷4, ÷16) | + +--+ +---------------+ +**************************************************************************** + that is the hardware >= 69000 we have to manage + +---------+ +--+ + | REFCLK |__|÷N|__ + | 14.3MHz | | | | + +---------+ +--+ | + __________________| + | + | fvco fout + | +--------+ +------------+ +-----+ +-------------------+ +----+ + +-| Phase |__|Charge Pump |__| VCO |_____|Post Divisor (PD) |___|CLK |---> + +-| Detect | |& Filter VCO| | | | |÷1, 2, 4, 8, 16, 32| | | + | +--------+ +------------+ +-----+ | +-------------------+ +----+ + | | + | +--+ +---------------+ | + |____|÷M|___|VCO Loop Divide|__________| + | | |(VLD)(÷1, ÷4) | + +--+ +---------------+ + + +*/ + +#define VIDEO_FREF 14318180; /* Hz */ +/*****************************************************************************/ +static int +ReadPixClckFromXrRegsBack (struct ctfb_chips_properties *param) +{ + unsigned int m, n, vld, pd, PD, fref, xr_cb, i, pixclock; + i = 0; + pixclock = -1; + fref = VIDEO_FREF; + m = ctRead_i (CT_XR_O, 0xc8); + n = ctRead_i (CT_XR_O, 0xc9); + m -= param->mn_diff; + n -= param->mn_diff; + xr_cb = ctRead_i (CT_XR_O, 0xcb); + PD = (0x70 & xr_cb) >> 4; + pd = 1; + for (i = 0; i < PD; i++) { + pd *= 2; + } + vld = (0x04 & xr_cb) ? param->vld_set : param->vld_not_set; + if (n * vld * m) { + unsigned long long p = 1000000000000LL * pd * n; + unsigned long long q = (long long) fref * vld * m; + while ((p > 0xffffffffLL) || (q > 0xffffffffLL)) { + p >>= 1; /* can't divide with long long so we scale down */ + q >>= 1; + } + pixclock = (unsigned) p / (unsigned) q; + } else + printf ("Invalid data in xr regs.\n"); + return pixclock; +} + +/*****************************************************************************/ +static void +FindAndSetPllParamIntoXrRegs (unsigned int pixelclock, + struct ctfb_chips_properties *param) +{ + unsigned int m, n, vld, pd, PD, fref, xr_cb; + unsigned int fvcomin, fvcomax, pclckmin, pclckmax, pclk; + unsigned int pfreq, fvco, new_pixclock; + + fref = VIDEO_FREF; + pd = 1; + PD = 0; + fvcomin = param->vco_min; + fvcomax = param->vco_max; /* MHz */ + pclckmin = 1000000 / fvcomax + 1; /* 4546 */ + pclckmax = 32000000 / fvcomin - 1; /* 666665 */ + pclk = minmax (pclckmin, pixelclock, pclckmax); /* ps pp */ + pfreq = 250 * (4000000000U / pclk); + fvco = pfreq; /* Hz */ + new_pixclock = 0; + while (fvco < fvcomin * 1000000) { + /* double VCO starting with the pixelclock frequency + * as long as it is lower than the minimal VCO frequency */ + fvco *= 2; + pd *= 2; + PD++; + } + /* fvco is exactly pd * pixelclock and higher than the ninmal VCO frequency */ + vld = (param->vld_set > param->vld_not_set) ? + param->vld_not_set : param->vld_set; + /* start with lower VLD (higher VLD is NOT yet implemented */ + FindBestPQFittingMN (fvco / vld, fref, param->mn_min, param->mn_max, &m, &n); /* rds = 1 */ + m += param->mn_diff; + n += param->mn_diff; + PRINTF ("VCO %d, pd %d, m %d n %d vld %d \n", fvco, pd, m, n, vld); + xr_cb = ((0x7 & PD) << 4) | (vld == param->vld_set ? 0x04 : 0); + /* All four of the registers used for dot clock 2 (XRC8 - XRCB) must be + * written, and in order from XRC8 to XRCB, before the hardware will + * update the synthesizer s settings. + */ + ctWrite_i (CT_XR_O, 0xc8, m); + ctWrite_i (CT_XR_O, 0xc9, n); /* xrca does not exist in CT69000 and CT69030 */ + ctWrite_i (CT_XR_O, 0xca, 0); /* because of a hw bug I guess, but we write */ + ctWrite_i (CT_XR_O, 0xcb, xr_cb); /* 0 to it for savety */ + new_pixclock = ReadPixClckFromXrRegsBack (param); + PRINTF ("pixelclock.set = %d, pixelclock.real = %d \n", + pixelclock, new_pixclock); +} + +/*****************************************************************************/ +static void +SetMsrRegs (struct ctfb_res_modes *mode) +{ + unsigned char h_synch_high, v_synch_high; + + h_synch_high = (mode->sync & FB_SYNC_HOR_HIGH_ACT) ? 0 : 0x40; /* horizontal Synch High active */ + v_synch_high = (mode->sync & FB_SYNC_VERT_HIGH_ACT) ? 0 : 0x80; /* vertical Synch High active */ + ctWrite (CT_MSR_W_O, (h_synch_high | v_synch_high | 0x29)); + /* upper64K==0x20, CLC2select==0x08, RAMenable==0x02!(todo), CGA==0x01 + * Selects the upper 64KB page.Bit5=1 + * CLK2 (left reserved in standard VGA) Bit3|2=1|0 + * Disables CPU access to frame buffer. Bit1=0 + * Sets the I/O address decode for ST01, FCR, and all CR registers + * to the 3Dx I/O address range (CGA emulation). Bit0=1 + */ +} + +/************************************************************************************/ +#ifdef VGA_DUMP_REG + +static void +ctDispRegs (unsigned short index, int from, int to) +{ + unsigned char status; + int i; + + for (i = from; i < to; i++) { + status = ctRead_i (index, i); + printf ("%02X: is %02X\n", i, status); + } +} + +void +video_dump_reg (void) +{ + int i; + + printf ("Extended Regs:\n"); + ctDispRegs (CT_XR_O, 0, 0xC); + ctDispRegs (CT_XR_O, 0xe, 0xf); + ctDispRegs (CT_XR_O, 0x20, 0x21); + ctDispRegs (CT_XR_O, 0x40, 0x50); + ctDispRegs (CT_XR_O, 0x60, 0x64); + ctDispRegs (CT_XR_O, 0x67, 0x68); + ctDispRegs (CT_XR_O, 0x70, 0x72); + ctDispRegs (CT_XR_O, 0x80, 0x83); + ctDispRegs (CT_XR_O, 0xA0, 0xB0); + ctDispRegs (CT_XR_O, 0xC0, 0xD3); + printf ("Sequencer Regs:\n"); + ctDispRegs (CT_SR_O, 0, 0x8); + printf ("Graphic Regs:\n"); + ctDispRegs (CT_GR_O, 0, 0x9); + printf ("CRT Regs:\n"); + ctDispRegs (CT_CR_O, 0, 0x19); + ctDispRegs (CT_CR_O, 0x22, 0x23); + ctDispRegs (CT_CR_O, 0x30, 0x34); + ctDispRegs (CT_CR_O, 0x38, 0x39); + ctDispRegs (CT_CR_O, 0x3C, 0x3D); + ctDispRegs (CT_CR_O, 0x40, 0x42); + ctDispRegs (CT_CR_O, 0x70, 0x80); + /* don't display the attributes */ +} + +#endif + +#ifdef CONFIG_VIDEO_HW_CURSOR +/*************************************************************** + * Set Hardware Cursor in Pixel + */ +void +video_set_hw_cursor (int x, int y) +{ + int sig_x = 0, sig_y = 0; + if (x < 0) { + x *= -1; + sig_x = 1; + } + if (y < 0) { + y *= -1; + sig_y = 1; + } + ctWrite_i (CT_XR_O, 0xa4, x & 0xff); + ctWrite_i (CT_XR_O, 0xa5, (x >> 8) & 0x7); + ctWrite_i (CT_XR_O, 0xa6, y & 0xff); + ctWrite_i (CT_XR_O, 0xa7, (y >> 8) & 0x7); +} + +/*************************************************************** + * Init Hardware Cursor. To know the size of the Cursor, + * we have to know the Font size. + */ +void +video_init_hw_cursor (int font_width, int font_height) +{ + unsigned char xr_80; + unsigned long *curs, pattern; + int i; + int cursor_start; + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + + cursor_start = pGD->dprBase; + xr_80 = ctRead_i (CT_XR_O, 0x80); + /* set start address */ + ctWrite_i (CT_XR_O, 0xa2, (cursor_start >> 8) & 0xf0); + ctWrite_i (CT_XR_O, 0xa3, (cursor_start >> 16) & 0x3f); + /* set cursor shape */ + curs = (unsigned long *) cursor_start; + i = 0; + while (i < 0x400) { + curs[i++] = 0xffffffff; /* AND mask */ + curs[i++] = 0xffffffff; /* AND mask */ + curs[i++] = 0; /* XOR mask */ + curs[i++] = 0; /* XOR mask */ + /* Transparent */ + } + pattern = 0xffffffff >> font_width; + i = 0; + while (i < (font_height * 2)) { + curs[i++] = pattern; /* AND mask */ + curs[i++] = pattern; /* AND mask */ + curs[i++] = 0; /* XOR mask */ + curs[i++] = 0; /* XOR mask */ + /* Cursor Color 0 */ + } + /* set blink rate */ + ctWrite_i (CT_FP_O, 0x19, 0xf); + + /* set cursors colors */ + xr_80 = ctRead_i (CT_XR_O, 0x80); + xr_80 |= 0x1; /* alternate palette select */ + ctWrite_i (CT_XR_O, 0x80, xr_80); + video_set_lut (4, CONSOLE_FG_COL, CONSOLE_FG_COL, CONSOLE_FG_COL); + /* position 4 is color 0 cursor 0 */ + xr_80 &= 0xfe; /* normal palette select */ + ctWrite_i (CT_XR_O, 0x80, xr_80); + /* cursor enable */ + ctWrite_i (CT_XR_O, 0xa0, 0x91); + xr_80 |= 0x10; /* enable hwcursor */ + ctWrite_i (CT_XR_O, 0x80, xr_80); + video_set_hw_cursor (0, 0); +} +#endif /* CONFIG_VIDEO_HW_CURSOR */ + +/*************************************************************** + * Wait for BitBlt ready + */ +static int +video_wait_bitblt (unsigned long addr) +{ + unsigned long br04; + int i = 0; + br04 = in32r (addr); + while (br04 & 0x80000000) { + udelay (1); + br04 = in32r (addr); + if (i++ > 1000000) { + printf ("ERROR Timeout %lx\n", br04); + return 1; + } + } + return 0; +} + +/*************************************************************** + * Set up BitBlt Registrs + */ +static void +SetDrawingEngine (int bits_per_pixel) +{ + unsigned long br04, br00; + unsigned char tmp; + + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + + tmp = ctRead_i (CT_XR_O, 0x20); /* BitBLT Configuration */ + tmp |= 0x02; /* reset BitBLT */ + ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */ + udelay (10); + tmp &= 0xfd; /* release reset BitBLT */ + ctWrite_i (CT_XR_O, 0x20, tmp); /* BitBLT Configuration */ + video_wait_bitblt (pGD->pciBase + BR04_o); + + /* set pattern Address */ + out32r (pGD->pciBase + BR05_o, PATTERN_ADR & 0x003ffff8); + br04 = 0; + if (bits_per_pixel == 1) { + br04 |= 0x00040000; /* monochome Pattern */ + br04 |= 0x00001000; /* monochome source */ + } + br00 = ((pGD->winSizeX * pGD->gdfBytesPP) << 16) + (pGD->winSizeX * pGD->gdfBytesPP); /* bytes per scanline */ + out32r (pGD->pciBase + BR00_o, br00); /* */ + out32r (pGD->pciBase + BR08_o, (10 << 16) + 10); /* dummy */ + out32r (pGD->pciBase + BR04_o, br04); /* write all 0 */ + out32r (pGD->pciBase + BR07_o, 0); /* destination */ + video_wait_bitblt (pGD->pciBase + BR04_o); +} + +/************************************************************************ + * Get Parameters for the video mode: + */ +/********************************************************************* + * returns the length to the next seperator + */ +static int +video_get_param_len (char *start, char sep) +{ + int i = 0; + while ((*start != 0) && (*start != sep)) { + start++; + i++; + } + return i; +} + +static int +video_search_param (char *start, char *param) +{ + int len, totallen, i; + char *p = start; + len = strlen (param); + totallen = len + strlen (start); + for (i = 0; i < totallen; i++) { + if (strncmp (p++, param, len) == 0) + return (i); + } + return -1; +} + +/*************************************************************** +* Get parameter via the environment as it is done for the +* linux kernel i.e: +* video=ctfb:x:800,xv:1280,y:600,yv:1024,depth:16,mode:0,pclk:25000, +* le:56,ri:48,up:26,lo:5,hs:152,vs:2,sync:0,vmode:0,accel:0 +* +* penv is a pointer to the environment, containing the string, or the name of +* another environment variable. It could even be the term "bootargs" +*/ + +#define GET_OPTION(name,var) \ + if(strncmp(p,name,strlen(name))==0) { \ + val_s=p+strlen(name); \ + var=simple_strtoul(val_s, NULL, 10); \ + } + +static int +video_get_params (struct ctfb_res_modes *pPar, char *penv) +{ + char *p, *s, *val_s; + int i = 0, t; + int bpp; + int mode; + /* first search for the environment containing the real param string */ + s = penv; + if ((p = getenv (s)) != NULL) { + s = p; + } + /* in case of the bootargs line, we have to start + * after "video=ctfb:" + */ + i = video_search_param (s, "video=ctfb:"); + if (i >= 0) { + s += i; + s += strlen ("video=ctfb:"); + } + /* search for mode as a default value */ + p = s; + t = 0; + mode = 0; /* default */ + while ((i = video_get_param_len (p, ',')) != 0) { + GET_OPTION ("mode:", mode) + p += i; + if (*p != 0) + p++; /* skip ',' */ + } + if (mode >= RES_MODES_COUNT) + mode = 0; + *pPar = res_mode_init[mode]; /* copy default values */ + bpp = 24 - ((mode % 3) * 8); + p = s; /* restart */ + while ((i = video_get_param_len (p, ',')) != 0) { + GET_OPTION ("x:", pPar->xres) + GET_OPTION ("y:", pPar->yres) + GET_OPTION ("le:", pPar->left_margin) + GET_OPTION ("ri:", pPar->right_margin) + GET_OPTION ("up:", pPar->upper_margin) + GET_OPTION ("lo:", pPar->lower_margin) + GET_OPTION ("hs:", pPar->hsync_len) + GET_OPTION ("vs:", pPar->vsync_len) + GET_OPTION ("sync:", pPar->sync) + GET_OPTION ("vmode:", pPar->vmode) + GET_OPTION ("pclk:", pPar->pixclock) + GET_OPTION ("depth:", bpp) + p += i; + if (*p != 0) + p++; /* skip ',' */ + } + return bpp; +} + +/**************************************************************************** +* supported Video Chips +*/ +static struct pci_device_id supported[] = { + {PCI_VENDOR_ID_CT, PCI_DEVICE_ID_CT_69000}, + {} +}; + +/******************************************************************************* +* +* Init video chip +*/ +void * +video_hw_init (void) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + unsigned short device_id; + pci_dev_t devbusfn; + int videomode; + unsigned long t1, hsynch, vsynch; + unsigned int pci_mem_base, *vm; + int tmp, i, bits_per_pixel; + char *penv; + struct ctfb_res_modes *res_mode; + struct ctfb_res_modes var_mode; + struct ctfb_chips_properties *chips_param; + /* Search for video chip */ + + if ((devbusfn = pci_find_devices (supported, 0)) < 0) { +#ifdef CONFIG_VIDEO_ONBOARD + printf ("Video: Controller not found !\n"); +#endif + return (NULL); + } + + /* PCI setup */ + pci_write_config_dword (devbusfn, PCI_COMMAND, + (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); + pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id); + pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base); + pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base); + + /* get chips params */ + for (chips_param = (struct ctfb_chips_properties *) &chips[0]; + chips_param->device_id != 0; chips_param++) { + if (chips_param->device_id == device_id) + break; + } + if (chips_param->device_id == 0) { +#ifdef CONFIG_VIDEO_ONBOARD + printf ("Video: controller 0x%X not supported\n", device_id); +#endif + return NULL; + } + /* supported Video controller found */ + printf ("Video: "); + + tmp = 0; + videomode = 0x301; + /* get video mode via environment */ + if ((penv = getenv ("videomode")) != NULL) { + /* deceide if it is a string */ + if (penv[0] <= '9') { + videomode = (int) simple_strtoul (penv, NULL, 16); + tmp = 1; + } + } else { + tmp = 1; + } + if (tmp) { + /* parameter are vesa modes */ + /* search params */ + for (i = 0; i < VESA_MODES_COUNT; i++) { + if (vesa_modes[i].vesanr == videomode) + break; + } + if (i == VESA_MODES_COUNT) { + printf ("no VESA Mode found, switching to mode 0x301 "); + i = 0; + } + res_mode = + (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i]. + resindex]; + bits_per_pixel = vesa_modes[i].bits_per_pixel; + } else { + + res_mode = (struct ctfb_res_modes *) &var_mode; + bits_per_pixel = video_get_params (res_mode, penv); + } + + /* calculate available color depth for controller memory */ + if (bits_per_pixel == 15) + tmp = 2; + else + tmp = bits_per_pixel >> 3; /* /8 */ + if (((chips_param->max_mem - + ACCELMEMORY) / (res_mode->xres * res_mode->yres)) < tmp) { + tmp = + ((chips_param->max_mem - + ACCELMEMORY) / (res_mode->xres * res_mode->yres)); + if (tmp == 0) { + printf + ("No matching videomode found .-> reduce resolution\n"); + return NULL; + } else { + printf ("Switching back to %d Bits per Pixel ", + tmp << 3); + bits_per_pixel = tmp << 3; + } + } + + /* calculate hsynch and vsynch freq (info only) */ + t1 = (res_mode->left_margin + res_mode->xres + + res_mode->right_margin + res_mode->hsync_len) / 8; + t1 *= 8; + t1 *= res_mode->pixclock; + t1 /= 1000; + hsynch = 1000000000L / t1; + t1 *= + (res_mode->upper_margin + res_mode->yres + + res_mode->lower_margin + res_mode->vsync_len); + t1 /= 1000; + vsynch = 1000000000L / t1; + + /* fill in Graphic device struct */ + sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres, + res_mode->yres, bits_per_pixel, (hsynch / 1000), + (vsynch / 1000)); + printf ("%s\n", pGD->modeIdent); + pGD->winSizeX = res_mode->xres; + pGD->winSizeY = res_mode->yres; + pGD->plnSizeX = res_mode->xres; + pGD->plnSizeY = res_mode->yres; + switch (bits_per_pixel) { + case 8: + pGD->gdfBytesPP = 1; + pGD->gdfIndex = GDF__8BIT_INDEX; + break; + case 15: + pGD->gdfBytesPP = 2; + pGD->gdfIndex = GDF_15BIT_555RGB; + break; + case 16: + pGD->gdfBytesPP = 2; + pGD->gdfIndex = GDF_16BIT_565RGB; + break; + case 24: + pGD->gdfBytesPP = 3; + pGD->gdfIndex = GDF_24BIT_888RGB; + break; + } + pGD->isaBase = CFG_ISA_IO_BASE_ADDRESS; + pGD->pciBase = pci_mem_base; + pGD->frameAdrs = pci_mem_base; + pGD->memSize = chips_param->max_mem; + /* Cursor Start Address */ + pGD->dprBase = + (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) + pci_mem_base; + if ((pGD->dprBase & 0x0fff) != 0) { + /* allign it */ + pGD->dprBase &= 0xfffff000; + pGD->dprBase += 0x00001000; + } + PRINTF ("Cursor Start %x Pattern Start %x\n", pGD->dprBase, + PATTERN_ADR); + pGD->vprBase = pci_mem_base; /* Dummy */ + pGD->cprBase = pci_mem_base; /* Dummy */ + /* set up Hardware */ + + ctWrite (CT_MSR_W_O, 0x01); + + /* set the extended Registers */ + ctLoadRegs (CT_XR_O, xreg); + /* set atribute registers */ + SetArRegs (); + /* set Graphics register */ + SetGrRegs (); + /* set sequencer */ + SetSrRegs (); + + /* set msr */ + SetMsrRegs (res_mode); + + /* set CRT Registers */ + SetCrRegs (res_mode, bits_per_pixel); + /* set color mode */ + SetBitsPerPixelIntoXrRegs (bits_per_pixel); + + /* set PLL */ + FindAndSetPllParamIntoXrRegs (res_mode->pixclock, chips_param); + + ctWrite_i (CT_SR_O, 0, 0x03); /* clear synchronous reset */ + /* Clear video memory */ + i = pGD->memSize / 4; + vm = (unsigned int *) pGD->pciBase; + while (i--) + *vm++ = 0; + SetDrawingEngine (bits_per_pixel); +#ifdef VGA_DUMP_REG + video_dump_reg (); +#endif + + return ((void *) &ctfb); +} + + /******************************************************************************* +* +* Set a RGB color in the LUT (8 bit index) +*/ +void +video_set_lut (unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) +{ + + ctWrite (CT_LUT_MASK_O, 0xff); + + ctWrite (CT_LUT_START_O, (char) index); + + ctWrite (CT_LUT_RGB_O, r); /* red */ + ctWrite (CT_LUT_RGB_O, g); /* green */ + ctWrite (CT_LUT_RGB_O, b); /* blue */ + udelay (1); + ctWrite (CT_LUT_MASK_O, 0xff); +} + +/******************************************************************************* +* +* Drawing engine fill on screen region +*/ +void +video_hw_rectfill (unsigned int bpp, /* bytes per pixel */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y, /* frame height */ + unsigned int color /* fill color */ + ) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + unsigned long *p, br04; + + video_wait_bitblt (pGD->pciBase + BR04_o); + + p = (unsigned long *) PATTERN_ADR; + dim_x *= bpp; + if (bpp == 3) + bpp++; /* 24Bit needs a 32bit pattern */ + memset (p, color, (bpp * sizeof (unsigned char) * 8 * 8)); /* 8 x 8 pattern data */ + out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */ + br04 = in32r (pGD->pciBase + BR04_o) & 0xffffff00; + br04 |= 0xF0; /* write Pattern P -> D */ + out32r (pGD->pciBase + BR04_o, br04); /* */ + out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* starts the BITBlt */ + video_wait_bitblt (pGD->pciBase + BR04_o); +} + +/******************************************************************************* +* +* Drawing engine bitblt with screen region +*/ +void +video_hw_bitblt (unsigned int bpp, /* bytes per pixel */ + unsigned int src_x, /* source pos x */ + unsigned int src_y, /* source pos y */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y /* frame height */ + ) +{ + GraphicDevice *pGD = (GraphicDevice *) & ctfb; + unsigned long br04; + + br04 = in32r (pGD->pciBase + BR04_o); + + /* to prevent data corruption due to overlap, we have to + * find out if, and how the frames overlaps */ + if (src_x < dst_x) { + /* src is more left than dest + * the frame may overlap -> start from right to left */ + br04 |= 0x00000100; /* set bit 8 */ + src_x += dim_x; + dst_x += dim_x; + } else { + br04 &= 0xfffffeff; /* clear bit 8 left to right */ + } + if (src_y < dst_y) { + /* src is higher than dst + * the frame may overlap => start from bottom */ + br04 |= 0x00000200; /* set bit 9 */ + src_y += dim_y; + dst_y += dim_y; + } else { + br04 &= 0xfffffdff; /* clear bit 9 top to bottom */ + } + dim_x *= bpp; + out32r (pGD->pciBase + BR06_o, ((pGD->winSizeX * src_y) + src_x) * pGD->gdfBytesPP); /* source */ + out32r (pGD->pciBase + BR07_o, ((pGD->winSizeX * dst_y) + dst_x) * pGD->gdfBytesPP); /* destination */ + br04 &= 0xffffff00; + br04 |= 0x000000CC; /* S -> D */ + out32r (pGD->pciBase + BR04_o, br04); /* */ + out32r (pGD->pciBase + BR08_o, (dim_y << 16) + dim_x); /* start the BITBlt */ + video_wait_bitblt (pGD->pciBase + BR04_o); +} + +#endif /* CONFIG_CT69000 */ + +#endif /* CONFIG_VIDEO */ diff --git a/drivers/dc2114x.c b/drivers/dc2114x.c new file mode 100644 index 0000000..e1147c0 --- /dev/null +++ b/drivers/dc2114x.c @@ -0,0 +1,720 @@ +/* + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_TULIP) + +#include <malloc.h> +#include <net.h> +#include <pci.h> + +#undef DEBUG +#undef DEBUG_SROM +#undef DEBUG_SROM2 + +#undef UPDATE_SROM + +/* PCI Registers. + */ +#define PCI_CFDA_PSM 0x43 + +#define CFRV_RN 0x000000f0 /* Revision Number */ + +#define WAKEUP 0x00 /* Power Saving Wakeup */ +#define SLEEP 0x80 /* Power Saving Sleep Mode */ + +#define DC2114x_BRK 0x0020 /* CFRV break between DC21142 & DC21143 */ + +/* Ethernet chip registers. + */ +#define DE4X5_BMR 0x000 /* Bus Mode Register */ +#define DE4X5_TPD 0x008 /* Transmit Poll Demand Reg */ +#define DE4X5_RRBA 0x018 /* RX Ring Base Address Reg */ +#define DE4X5_TRBA 0x020 /* TX Ring Base Address Reg */ +#define DE4X5_STS 0x028 /* Status Register */ +#define DE4X5_OMR 0x030 /* Operation Mode Register */ +#define DE4X5_SICR 0x068 /* SIA Connectivity Register */ +#define DE4X5_APROM 0x048 /* Ethernet Address PROM */ + +/* Register bits. + */ +#define BMR_SWR 0x00000001 /* Software Reset */ +#define STS_TS 0x00700000 /* Transmit Process State */ +#define STS_RS 0x000e0000 /* Receive Process State */ +#define OMR_ST 0x00002000 /* Start/Stop Transmission Command */ +#define OMR_SR 0x00000002 /* Start/Stop Receive */ +#define OMR_PS 0x00040000 /* Port Select */ +#define OMR_SDP 0x02000000 /* SD Polarity - MUST BE ASSERTED */ +#define OMR_PM 0x00000080 /* Pass All Multicast */ + +/* Descriptor bits. + */ +#define R_OWN 0x80000000 /* Own Bit */ +#define RD_RER 0x02000000 /* Receive End Of Ring */ +#define RD_LS 0x00000100 /* Last Descriptor */ +#define RD_ES 0x00008000 /* Error Summary */ +#define TD_TER 0x02000000 /* Transmit End Of Ring */ +#define T_OWN 0x80000000 /* Own Bit */ +#define TD_LS 0x40000000 /* Last Segment */ +#define TD_FS 0x20000000 /* First Segment */ +#define TD_ES 0x00008000 /* Error Summary */ +#define TD_SET 0x08000000 /* Setup Packet */ + +/* The EEPROM commands include the alway-set leading bit. */ +#define SROM_WRITE_CMD 5 +#define SROM_READ_CMD 6 +#define SROM_ERASE_CMD 7 + +#define SROM_HWADD 0x0014 /* Hardware Address offset in SROM */ +#define SROM_RD 0x00004000 /* Read from Boot ROM */ +#define EE_DATA_WRITE 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x4801 +#define EE_WRITE_1 0x4805 +#define EE_DATA_READ 0x08 /* EEPROM chip data out. */ +#define SROM_SR 0x00000800 /* Select Serial ROM when set */ + +#define DT_IN 0x00000004 /* Serial Data In */ +#define DT_CLK 0x00000002 /* Serial ROM Clock */ +#define DT_CS 0x00000001 /* Serial ROM Chip Select */ + +#define POLL_DEMAND 1 + +#define RESET_DE4X5(dev) {\ + int i;\ + i=INL(dev, DE4X5_BMR);\ + udelay(1000);\ + OUTL(dev, i | BMR_SWR, DE4X5_BMR);\ + udelay(1000);\ + OUTL(dev, i, DE4X5_BMR);\ + udelay(1000);\ + for (i=0;i<5;i++) {INL(dev, DE4X5_BMR); udelay(10000);}\ + udelay(1000);\ +} + +#define START_DE4X5(dev) {\ + s32 omr; \ + omr = INL(dev, DE4X5_OMR);\ + omr |= OMR_ST | OMR_SR;\ + OUTL(dev, omr, DE4X5_OMR); /* Enable the TX and/or RX */\ +} + +#define STOP_DE4X5(dev) {\ + s32 omr; \ + omr = INL(dev, DE4X5_OMR);\ + omr &= ~(OMR_ST|OMR_SR);\ + OUTL(dev, omr, DE4X5_OMR); /* Disable the TX and/or RX */ \ +} + +#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 1 /* Number of TX descriptors */ +#define RX_BUFF_SZ PKTSIZE_ALIGN + +#define TOUT_LOOP 1000000 + +#define SETUP_FRAME_LEN 192 +#define ETH_ALEN 6 + + +struct de4x5_desc { + volatile s32 status; + u32 des1; + u32 buf; + u32 next; +}; + +static struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring */ +static struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring */ +static int rx_new; /* RX descriptor ring pointer */ +static int tx_new; /* TX descriptor ring pointer */ + +static char rxRingSize; +static char txRingSize; + +static void sendto_srom(struct eth_device* dev, u_int command, u_long addr); +static int getfrom_srom(struct eth_device* dev, u_long addr); +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len); +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len); +static int read_srom(struct eth_device *dev, u_long ioaddr, int index); +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value); +static void update_srom(struct eth_device *dev, bd_t *bis); +#endif +static void read_hw_addr(struct eth_device* dev, bd_t * bis); +static void send_setup_frame(struct eth_device* dev, bd_t * bis); + +static int dc21x4x_init(struct eth_device* dev, bd_t* bis); +static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length); +static int dc21x4x_recv(struct eth_device* dev); +static void dc21x4x_halt(struct eth_device* dev); +#ifdef CONFIG_TULIP_SELECT_MEDIA +extern void dc21x4x_select_media(struct eth_device* dev); +#endif + +#define phys_to_bus(a) pci_phys_to_mem((pci_dev_t)dev->priv, a) + +static int INL(struct eth_device* dev, u_long addr) +{ + return le32_to_cpu(*(volatile u_long *)(addr + dev->iobase)); +} + +static void OUTL(struct eth_device* dev, int command, u_long addr) +{ + *(volatile u_long *)(addr + dev->iobase) = cpu_to_le32(command); +} + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_TULIP_FAST }, + { PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142 }, + { } +}; + +int dc21x4x_initialize(bd_t *bis) +{ + int idx=0; + int card_number = 0; + int cfrv; + unsigned char timer; + pci_dev_t devbusfn; + unsigned int iobase; + unsigned short status; + struct eth_device* dev; + + while(1) { + devbusfn = pci_find_devices(supported, idx++); + if (devbusfn == -1) { + break; + } + + /* Get the chip configuration revision register. */ + pci_read_config_dword(devbusfn, PCI_REVISION_ID, &cfrv); + + if ((cfrv & CFRV_RN) < DC2114x_BRK ) { + printf("Error: The chip is not DC21143.\n"); + continue; + } + + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + status |= +#ifdef CONFIG_TULIP_USE_IO + PCI_COMMAND_IO | +#else + PCI_COMMAND_MEMORY | +#endif + PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, status); + + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if (!(status & PCI_COMMAND_IO)) { + printf("Error: Can not enable I/O access.\n"); + continue; + } + + if (!(status & PCI_COMMAND_IO)) { + printf("Error: Can not enable I/O access.\n"); + continue; + } + + if (!(status & PCI_COMMAND_MASTER)) { + printf("Error: Can not enable Bus Mastering.\n"); + continue; + } + + /* Check the latency timer for values >= 0x60. */ + pci_read_config_byte(devbusfn, PCI_LATENCY_TIMER, &timer); + + if (timer < 0x60) { + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x60); + } + +#ifdef CONFIG_TULIP_USE_IO + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &iobase); + iobase &= PCI_BASE_ADDRESS_IO_MASK; +#else + /* read BAR for memory space access */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_1, &iobase); + iobase &= PCI_BASE_ADDRESS_MEM_MASK; +#endif + +#ifdef DEBUG + printf("dc21x4x: DEC 21142 PCI Device @0x%x\n", iobase); +#endif + + dev = (struct eth_device*) malloc(sizeof *dev); + + sprintf(dev->name, "dc21x4x#%d", card_number); +#ifdef CONFIG_TULIP_USE_IO + dev->iobase = pci_io_to_phys(devbusfn, iobase); +#else + dev->iobase = pci_mem_to_phys(devbusfn, iobase); +#endif + dev->priv = (void*) devbusfn; + dev->init = dc21x4x_init; + dev->halt = dc21x4x_halt; + dev->send = dc21x4x_send; + dev->recv = dc21x4x_recv; + + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + + udelay(10 * 1000); + + read_hw_addr(dev, bis); + + eth_register(dev); + + card_number++; + } + + return card_number; +} + +static int dc21x4x_init(struct eth_device* dev, bd_t* bis) +{ + int i; + int devbusfn = (int) dev->priv; + + /* Ensure we're not sleeping. */ + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, WAKEUP); + + RESET_DE4X5(dev); + + if ((INL(dev, DE4X5_STS) & (STS_TS | STS_RS)) != 0) { + printf("Error: Cannot reset ethernet controller.\n"); + return 0; + } + +#ifdef CONFIG_TULIP_SELECT_MEDIA + dc21x4x_select_media(dev); +#else + OUTL(dev, OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR); +#endif + + for (i = 0; i < NUM_RX_DESC; i++) { + rx_ring[i].status = cpu_to_le32(R_OWN); + rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ); + rx_ring[i].buf = cpu_to_le32(phys_to_bus((u32) NetRxPackets[i])); + rx_ring[i].next = 0; + } + + for (i=0; i < NUM_TX_DESC; i++) { + tx_ring[i].status = 0; + tx_ring[i].des1 = 0; + tx_ring[i].buf = 0; + tx_ring[i].next = 0; + } + + rxRingSize = NUM_RX_DESC; + txRingSize = NUM_TX_DESC; + + /* Write the end of list marker to the descriptor lists. */ + rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER); + tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER); + + /* Tell the adapter where the TX/RX rings are located. */ + OUTL(dev, phys_to_bus((u32) &rx_ring), DE4X5_RRBA); + OUTL(dev, phys_to_bus((u32) &tx_ring), DE4X5_TRBA); + + START_DE4X5(dev); + + tx_new = 0; + rx_new = 0; + + send_setup_frame(dev, bis); + + return 1; +} + +static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length) +{ + int status = -1; + int i; + + if (length <= 0) { + printf("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx error buffer not ready\n", dev->name); + goto Done; + } + } + + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet)); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); + tx_ring[tx_new].status = cpu_to_le32(T_OWN); + + OUTL(dev, POLL_DEMAND, DE4X5_TPD); + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf(".%s: tx buffer not ready\n", dev->name); + goto Done; + } + } + + if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) { +#if 0 /* test-only */ + printf("TX error status = 0x%08X\n", + le32_to_cpu(tx_ring[tx_new].status)); +#endif + goto Done; + } + + status = length; + + Done: + return status; +} + +static int dc21x4x_recv(struct eth_device* dev) +{ + s32 status; + int length = 0; + + for ( ; ; ) { + status = (s32)le32_to_cpu(rx_ring[rx_new].status); + + if (status & R_OWN) { + break; + } + + if (status & RD_LS) { + /* Valid frame status. + */ + if (status & RD_ES) { + + /* There was an error. + */ + printf("RX error status = 0x%08X\n", status); + } else { + /* A valid frame received. + */ + length = (le32_to_cpu(rx_ring[rx_new].status) >> 16); + + /* Pass the packet up to the protocol + * layers. + */ + NetReceive(NetRxPackets[rx_new], length - 4); + } + + /* Change buffer ownership for this frame, back + * to the adapter. + */ + rx_ring[rx_new].status = cpu_to_le32(R_OWN); + } + + /* Update entry information. + */ + rx_new = (rx_new + 1) % rxRingSize; + } + + return length; +} + +static void dc21x4x_halt(struct eth_device* dev) +{ + int devbusfn = (int) dev->priv; + + STOP_DE4X5(dev); + OUTL(dev, 0, DE4X5_SICR); + + pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP); +} + +static void send_setup_frame(struct eth_device* dev, bd_t *bis) +{ + int i; + char setup_frame[SETUP_FRAME_LEN]; + char *pa = &setup_frame[0]; + + memset(pa, 0xff, SETUP_FRAME_LEN); + + for (i = 0; i < ETH_ALEN; i++) { + *(pa + (i & 1)) = dev->enetaddr[i]; + if (i & 0x01) { + pa += 4; + } + } + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx error buffer not ready\n", dev->name); + goto Done; + } + } + + tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0])); + tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN); + tx_ring[tx_new].status = cpu_to_le32(T_OWN); + + OUTL(dev, POLL_DEMAND, DE4X5_TPD); + + for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { + if (i >= TOUT_LOOP) { + printf("%s: tx buffer not ready\n", dev->name); + goto Done; + } + } + + if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { + printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status)); + } +Done: + return; +} + +/* SROM Read and write routines. + */ + +static void +sendto_srom(struct eth_device* dev, u_int command, u_long addr) +{ + OUTL(dev, command, addr); + udelay(1); +} + +static int +getfrom_srom(struct eth_device* dev, u_long addr) +{ + s32 tmp; + + tmp = INL(dev, addr); + udelay(1); + + return tmp; +} + +/* Note: this routine returns extra data bits for size detection. */ +static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len) +{ + int i; + unsigned retval = 0; + int read_cmd = location | (SROM_READ_CMD << addr_len); + + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + +#ifdef DEBUG_SROM + printf(" EEPROM read at %d ", location); +#endif + + /* Shift the read command bits out. */ + for (i = 4 + addr_len; i >= 0; i--) { + short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr); + udelay(10); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + } + + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + +#ifdef DEBUG_SROM2 + printf(" :%X:", getfrom_srom(dev, ioaddr) & 15); +#endif + + for (i = 16; i > 0; i--) { + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + udelay(10); +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev, ioaddr) & 15); +#endif + retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + udelay(10); + } + + /* Terminate the EEPROM access. */ + sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); + +#ifdef DEBUG_SROM2 + printf(" EEPROM value at %d is %5.5x.\n", location, retval); +#endif + + return retval; +} + +/* This executes a generic EEPROM command, typically a write or write enable. + It returns the data output from the EEPROM, and thus may also be used for + reads. */ +static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len) +{ + unsigned retval = 0; + +#ifdef DEBUG_SROM + printf(" EEPROM op 0x%x: ", cmd); +#endif + + sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); + + /* Shift the command bits out. */ + do { + short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; + sendto_srom(dev,dataval, ioaddr); + udelay(10); + +#ifdef DEBUG_SROM2 + printf("%X", getfrom_srom(dev,ioaddr) & 15); +#endif + + sendto_srom(dev,dataval | DT_CLK, ioaddr); + udelay(10); + retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0); + } while (--cmd_len >= 0); + sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr); + + /* Terminate the EEPROM access. */ + sendto_srom(dev,SROM_RD | SROM_SR, ioaddr); + +#ifdef DEBUG_SROM + printf(" EEPROM result is 0x%5.5x.\n", retval); +#endif + + return retval; +} + +static int read_srom(struct eth_device *dev, u_long ioaddr, int index) +{ + int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; + + return do_eeprom_cmd(dev, ioaddr, + (((SROM_READ_CMD << ee_addr_size) | index) << 16) + | 0xffff, 3 + ee_addr_size + 16); +} + +#ifdef UPDATE_SROM +static int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value) +{ + int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; + int i; + unsigned short newval; + + udelay(10*1000); /* test-only */ + +#ifdef DEBUG_SROM + printf("ee_addr_size=%d.\n", ee_addr_size); + printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index); +#endif + + /* Enable programming modes. */ + do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size); + + /* Do the actual write. */ + do_eeprom_cmd(dev, ioaddr, + (((SROM_WRITE_CMD<<ee_addr_size)|index) << 16) | new_value, + 3 + ee_addr_size + 16); + + /* Poll for write finished. */ + sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); + for (i = 0; i < 10000; i++) /* Typical 2000 ticks */ + if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) + break; + +#ifdef DEBUG_SROM + printf(" Write finished after %d ticks.\n", i); +#endif + + /* Disable programming. */ + do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size-4)), 3 + ee_addr_size); + + /* And read the result. */ + newval = do_eeprom_cmd(dev, ioaddr, + (((SROM_READ_CMD<<ee_addr_size)|index) << 16) + | 0xffff, 3 + ee_addr_size + 16); +#ifdef DEBUG_SROM + printf(" New value at offset %d is %4.4x.\n", index, newval); +#endif + return 1; +} +#endif + +static void read_hw_addr(struct eth_device *dev, bd_t *bis) +{ + u_short tmp, *p = (short *)(&dev->enetaddr[0]); + int i, j = 0; + + for (i = 0; i < (ETH_ALEN >> 1); i++) { + tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i)); + *p = le16_to_cpu(tmp); + j += *p++; + } + + if ((j == 0) || (j == 0x2fffd)) { + memset (dev->enetaddr, 0, ETH_ALEN); +#ifdef DEBUG + printf("Warning: can't read HW address from SROM.\n"); +#endif + goto Done; + } + + return; + +Done: +#ifdef UPDATE_SROM + update_srom(dev, bis); +#endif + return; +} + +#ifdef UPDATE_SROM +static void update_srom(struct eth_device *dev, bd_t *bis) +{ + int i; + static unsigned short eeprom[0x40] = { + 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ + 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ + 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ + 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ + 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ + 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ + 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ + }; + + /* Ethernet Addr... */ + eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff); + eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff); + eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff); + + for (i=0; i<0x40; i++) + { + write_srom(dev, DE4X5_APROM, i, eeprom[i]); + } +} +#endif + +#endif diff --git a/drivers/i8042.c b/drivers/i8042.c new file mode 100644 index 0000000..ce24fc9 --- /dev/null +++ b/drivers/i8042.c @@ -0,0 +1,655 @@ +/* + * (C) Copyright 2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* i8042.c - Intel 8042 keyboard driver routines */ + +/* includes */ + +#include <common.h> + +#ifdef CONFIG_I8042_KBD + +#include <i8042.h> + +/* defines */ + +#ifdef CONFIG_CONSOLE_CURSOR +extern void console_cursor (int state); +static int blinkCount = CFG_CONSOLE_BLINK_COUNT; +static int cursor_state = 0; +#endif + +/* locals */ + +static int kbd_input = -1; /* no input yet */ +static int kbd_mapping = KBD_US; /* default US keyboard */ +static int kbd_flags = NORMAL; /* after reset */ +static int kbd_state = 0; /* unshift code */ + +static void kbd_conv_char (unsigned char scan_code); +static void kbd_led_set (void); +static void kbd_normal (unsigned char scan_code); +static void kbd_shift (unsigned char scan_code); +static void kbd_ctrl (unsigned char scan_code); +static void kbd_num (unsigned char scan_code); +static void kbd_caps (unsigned char scan_code); +static void kbd_scroll (unsigned char scan_code); +static void kbd_alt (unsigned char scan_code); +static int kbd_input_empty (void); +static int kbd_reset (void); + +static unsigned char kbd_fct_map [144] = + { /* kbd_fct_map table for scan code */ + 0, AS, AS, AS, AS, AS, AS, AS, /* scan 0- 7 */ + AS, AS, AS, AS, AS, AS, AS, AS, /* scan 8- F */ + AS, AS, AS, AS, AS, AS, AS, AS, /* scan 10-17 */ + AS, AS, AS, AS, AS, CN, AS, AS, /* scan 18-1F */ + AS, AS, AS, AS, AS, AS, AS, AS, /* scan 20-27 */ + AS, AS, SH, AS, AS, AS, AS, AS, /* scan 28-2F */ + AS, AS, AS, AS, AS, AS, SH, AS, /* scan 30-37 */ + AS, AS, CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, ES, /* scan 40-47 */ + ES, ES, ES, ES, ES, ES, ES, ES, /* scan 48-4F */ + ES, ES, ES, ES, 0, 0, AS, 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + AS, 0, 0, AS, 0, 0, AS, 0, /* scan 70-77 */ + 0, AS, 0, 0, 0, AS, 0, 0, /* scan 78-7F */ + AS, CN, AS, AS, AK, ST, EX, EX, /* enhanced */ + AS, EX, EX, AS, EX, AS, EX, EX /* enhanced */ + }; + +static unsigned char kbd_key_map [2][5][144] = + { + { /* US keyboard */ + { /* unshift code */ + 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ + '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ + 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ + '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ + 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ + '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* shift code */ + 0, 0x1b, '!', '@', '#', '$', '%', '^', /* scan 0- 7 */ + '&', '*', '(', ')', '_', '+', 0x08, '\t', /* scan 8- F */ + 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', /* scan 10-17 */ + 'O', 'P', '{', '}', '\r', CN, 'A', 'S', /* scan 18-1F */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', /* scan 20-27 */ + '"', '~', SH, '|', 'Z', 'X', 'C', 'V', /* scan 28-2F */ + 'B', 'N', 'M', '<', '>', '?', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ + '2', '3', '0', '.', 0, 0, 0, 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* control code */ + 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ + 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ + 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ + 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ + 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ + 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ + 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ + 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ + 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ + }, + { /* non numeric code */ + 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ + '7', '8', '9', '0', '-', '=', 0x08, '\t', /* scan 8- F */ + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', /* scan 10-17 */ + 'o', 'p', '[', ']', '\r', CN, 'a', 's', /* scan 18-1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* scan 20-27 */ + '\'', '`', SH, '\\', 'z', 'x', 'c', 'v', /* scan 28-2F */ + 'b', 'n', 'm', ',', '.', '/', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ + 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ + 'r', 's', 'p', 'n', 0, 0, 0, 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* right alt mode - not used in US keyboard */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 8 - F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50 -57 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ + } + }, + { /* german keyboard */ + { /* unshift code */ + 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ + '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ + 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ + 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ + 0x84, '^', SH, '#', 'y', 'x', 'c', 'v', /* scan 28-2F */ + 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ + '2', '3', '0', ',', 0, 0, '<', 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* shift code */ + 0, 0x1b, '!', '"', 0x15, '$', '%', '&', /* scan 0- 7 */ + '/', '(', ')', '=', '?', '`', 0x08, '\t', /* scan 8- F */ + 'Q', 'W', 'E', 'R', 'T', 'Z', 'U', 'I', /* scan 10-17 */ + 'O', 'P', 0x9a, '*', '\r', CN, 'A', 'S', /* scan 18-1F */ + 'D', 'F', 'G', 'H', 'J', 'K', 'L', 0x99, /* scan 20-27 */ + 0x8e, 0xf8, SH, '\'', 'Y', 'X', 'C', 'V', /* scan 28-2F */ + 'B', 'N', 'M', ';', ':', '_', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, '7', /* scan 40-47 */ + '8', '9', '-', '4', '5', '6', '+', '1', /* scan 48-4F */ + '2', '3', '0', ',', 0, 0, '>', 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* control code */ + 0xff, 0x1b, 0xff, 0x00, 0xff, 0xff, 0xff, 0xff, /* scan 0- 7 */ + 0x1e, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, '\t', /* scan 8- F */ + 0x11, 0x17, 0x05, 0x12, 0x14, 0x19, 0x15, 0x09, /* scan 10-17 */ + 0x0f, 0x10, 0x1b, 0x1d, '\r', CN, 0x01, 0x13, /* scan 18-1F */ + 0x04, 0x06, 0x07, 0x08, 0x0a, 0x0b, 0x0c, 0xff, /* scan 20-27 */ + 0xff, 0x1c, SH, 0xff, 0x1a, 0x18, 0x03, 0x16, /* scan 28-2F */ + 0x02, 0x0e, 0x0d, 0xff, 0xff, 0xff, SH, 0xff, /* scan 30-37 */ + 0xff, 0xff, CP, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38-3F */ + 0xff, 0xff, 0xff, 0xff, 0xff, NM, ST, 0xff, /* scan 40-47 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48-4F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 50-57 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58-5F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60-67 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68-6F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70-77 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 0xff, 0xff, /* extended */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ + }, + { /* non numeric code */ + 0, 0x1b, '1', '2', '3', '4', '5', '6', /* scan 0- 7 */ + '7', '8', '9', '0', 0xe1, '\'', 0x08, '\t', /* scan 8- F */ + 'q', 'w', 'e', 'r', 't', 'z', 'u', 'i', /* scan 10-17 */ + 'o', 'p', 0x81, '+', '\r', CN, 'a', 's', /* scan 18-1F */ + 'd', 'f', 'g', 'h', 'j', 'k', 'l', 0x94, /* scan 20-27 */ + 0x84, '^', SH, 0, 'y', 'x', 'c', 'v', /* scan 28-2F */ + 'b', 'n', 'm', ',', '.', '-', SH, '*', /* scan 30-37 */ + ' ', ' ', CP, 0, 0, 0, 0, 0, /* scan 38-3F */ + 0, 0, 0, 0, 0, NM, ST, 'w', /* scan 40-47 */ + 'x', 'y', 'l', 't', 'u', 'v', 'm', 'q', /* scan 48-4F */ + 'r', 's', 'p', 'n', 0, 0, '<', 0, /* scan 50-57 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 58-5F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 60-67 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 68-6F */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 70-77 */ + 0, 0, 0, 0, 0, 0, 0, 0, /* scan 78-7F */ + '\r', CN, '/', '*', ' ', ST, 'F', 'A', /* extended */ + 0, 'D', 'C', 0, 'B', 0, '@', 'P' /* extended */ + }, + { /* Right alt mode - is used in German keyboard */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 0 - 7 */ + '{', '[', ']', '}', '\\', 0xff, 0xff, 0xff, /* scan 8 - F */ + '@', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 10 -17 */ + 0xff, 0xff, 0xff, '~', 0xff, 0xff, 0xff, 0xff, /* scan 18 -1F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 20 -27 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 28 -2F */ + 0xff, 0xff, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 30 -37 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 38 -3F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 40 -47 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 48 -4F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, '|', 0xff, /* scan 50 -57 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 58 -5F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 60 -67 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 68 -6F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 70 -77 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* scan 78 -7F */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* extended */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff /* extended */ + } + } + }; + +static unsigned char ext_key_map [] = + { + 0x1c, /* keypad enter */ + 0x1d, /* right control */ + 0x35, /* keypad slash */ + 0x37, /* print screen */ + 0x38, /* right alt */ + 0x46, /* break */ + 0x47, /* editpad home */ + 0x48, /* editpad up */ + 0x49, /* editpad pgup */ + 0x4b, /* editpad left */ + 0x4d, /* editpad right */ + 0x4f, /* editpad end */ + 0x50, /* editpad dn */ + 0x51, /* editpad pgdn */ + 0x52, /* editpad ins */ + 0x53, /* editpad del */ + 0x00 /* map end */ + }; + +/******************************************************************************* + * + * i8042_kbd_init - reset keyboard and init state flags + */ +int i8042_kbd_init (void) +{ + int keymap, try; + char *penv; + + /* Init keyboard device (default US layout) */ + keymap = KBD_US; + if ((penv = getenv ("keymap")) != NULL) + { + if (strncmp (penv, "de", 3) == 0) + keymap = KBD_GER; + } + + for (try = 0; try < KBD_RESET_TRIES; try++) + { + if (kbd_reset() == 0) + { + kbd_mapping = keymap; + kbd_flags = NORMAL; + kbd_state = 0; + kbd_led_set(); + return 0; + } + } + return -1; +} + + +/******************************************************************************* + * + * i8042_tstc - test if keyboard input is available + * option: cursor blinking if called in a loop + */ +int i8042_tstc (void) +{ + unsigned char scan_code = 0; + +#ifdef CONFIG_CONSOLE_CURSOR + if (--blinkCount == 0) + { + cursor_state ^= 1; + console_cursor (cursor_state); + blinkCount = CFG_CONSOLE_BLINK_COUNT; + udelay (10); + } +#endif + + if ((in8 (I8042_STATUS_REG) & 0x01) == 0) + return 0; + else + { + scan_code = in8 (I8042_DATA_REG); + if (scan_code == 0xfa) + return 0; + + kbd_conv_char(scan_code); + + if (kbd_input != -1) + return 1; + } + return 0; +} + + +/******************************************************************************* + * + * i8042_getc - wait till keyboard input is available + * option: turn on/off cursor while waiting + */ +int i8042_getc (void) +{ + int ret_chr; + unsigned char scan_code; + + while (kbd_input == -1) + { + while ((in8 (I8042_STATUS_REG) & 0x01) == 0) + { +#ifdef CONFIG_CONSOLE_CURSOR + if (--blinkCount==0) + { + cursor_state ^= 1; + console_cursor (cursor_state); + blinkCount = CFG_CONSOLE_BLINK_COUNT; + } + udelay (10); +#endif + } + + scan_code = in8 (I8042_DATA_REG); + + if (scan_code != 0xfa) + kbd_conv_char (scan_code); + } + ret_chr = kbd_input; + kbd_input = -1; + return ret_chr; +} + + +/******************************************************************************/ + +static void kbd_conv_char (unsigned char scan_code) +{ + if (scan_code == 0xe0) + { + kbd_flags |= EXT; + return; + } + + /* if high bit of scan_code, set break flag */ + if (scan_code & 0x80) + kbd_flags |= BRK; + else + kbd_flags &= ~BRK; + + if ((scan_code == 0xe1) || (kbd_flags & E1)) + { + if (scan_code == 0xe1) + { + kbd_flags ^= BRK; /* reset the break flag */ + kbd_flags ^= E1; /* bitwise EXOR with E1 flag */ + } + return; + } + + scan_code &= 0x7f; + + if (kbd_flags & EXT) + { + int i; + + kbd_flags ^= EXT; + for (i=0; ext_key_map[i]; i++) + { + if (ext_key_map[i] == scan_code) + { + scan_code = 0x80 + i; + break; + } + } + /* not found ? */ + if (!ext_key_map[i]) + return; + } + + switch (kbd_fct_map [scan_code]) + { + case AS: kbd_normal (scan_code); + break; + case SH: kbd_shift (scan_code); + break; + case CN: kbd_ctrl (scan_code); + break; + case NM: kbd_num (scan_code); + break; + case CP: kbd_caps (scan_code); + break; + case ST: kbd_scroll (scan_code); + break; + case AK: kbd_alt (scan_code); + break; + } + return; +} + + +/******************************************************************************/ + +static void kbd_normal (unsigned char scan_code) +{ + unsigned char chr; + + if ((kbd_flags & BRK) == NORMAL) + { + chr = kbd_key_map [kbd_mapping][kbd_state][scan_code]; + if ((chr == 0xff) || (chr == 0x00)) + { + return; + } + + /* if caps lock convert upper to lower */ + if (((kbd_flags & CAPS) == CAPS) && (chr >= 'a' && chr <= 'z')) + { + chr -= 'a' - 'A'; + } + kbd_input = chr; + } +} + + +/******************************************************************************/ + +static void kbd_shift (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == BRK) + { + kbd_state = AS; + kbd_flags &= (~SHIFT); + } + else + { + kbd_state = SH; + kbd_flags |= SHIFT; + } +} + + +/******************************************************************************/ + +static void kbd_ctrl (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == BRK) + { + kbd_state = AS; + kbd_flags &= (~CTRL); + } + else + { + kbd_state = CN; + kbd_flags |= CTRL; + } +} + + +/******************************************************************************/ + +static void kbd_caps (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) + { + kbd_flags ^= CAPS; + kbd_led_set (); /* update keyboard LED */ + } +} + + +/******************************************************************************/ + +static void kbd_num (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) + { + kbd_flags ^= NUM; + kbd_state = (kbd_flags & NUM) ? AS : NM; + kbd_led_set (); /* update keyboard LED */ + } +} + + +/******************************************************************************/ + +static void kbd_scroll (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == NORMAL) + { + kbd_flags ^= STP; + kbd_led_set (); /* update keyboard LED */ + if (kbd_flags & STP) + kbd_input = 0x13; + else + kbd_input = 0x11; + } +} + +/******************************************************************************/ + +static void kbd_alt (unsigned char scan_code) +{ + if ((kbd_flags & BRK) == BRK) + { + kbd_state = AS; + kbd_flags &= (~ALT); + } + else + { + kbd_state = AK; + kbd_flags &= ALT; + } +} + + +/******************************************************************************/ + +static void kbd_led_set (void) +{ + kbd_input_empty(); + out8 (I8042_DATA_REG, 0xed); /* SET LED command */ + kbd_input_empty(); + out8 (I8042_DATA_REG, (kbd_flags & 0x7)); /* LED bits only */ +} + + +/******************************************************************************/ + +static int kbd_input_empty (void) +{ + int kbdTimeout = KBD_TIMEOUT; + + /* wait for input buf empty */ + while ((in8 (I8042_STATUS_REG) & 0x02) && kbdTimeout--) + udelay(1000); + + return kbdTimeout; +} + +/******************************************************************************/ + +static int kbd_reset (void) +{ + if (kbd_input_empty() == 0) + return -1; + + out8 (I8042_DATA_REG, 0xff); + + udelay(250000); + + if (kbd_input_empty() == 0) + return -1; + + out8 (I8042_DATA_REG, 0x60); + + if (kbd_input_empty() == 0) + return -1; + + out8 (I8042_DATA_REG, 0x45); + + + if (kbd_input_empty() == 0) + return -1; + + out8 (I8042_COMMAND_REG, 0xae); + + if (kbd_input_empty() == 0) + return -1; + + return 0; +} + +#endif /* CONFIG_I8042_KBD */ diff --git a/drivers/ns87308.c b/drivers/ns87308.c new file mode 100644 index 0000000..cf4d359 --- /dev/null +++ b/drivers/ns87308.c @@ -0,0 +1,121 @@ +/* + * (C) Copyright 2000 + * Rob Taylor, Flying Pig Systems. robt@flyingpig.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 <config.h> + +#ifdef CFG_NS87308 + +#include <ns87308.h> + +void initialise_ns87308 (void) +{ +#ifdef CFG_NS87308_PS2MOD + unsigned char data; + + /* + * Switch floppy drive to PS/2 mode. + */ + read_pnp_config(SUPOERIO_CONF1, &data); + data &= 0xFB; + write_pnp_config(SUPOERIO_CONF1, data); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_KBC1) + PNP_SET_DEVICE_BASE(LDEV_KBC1, CFG_NS87308_KBC1_BASE); + write_pnp_config(LUN_CONFIG_REG, 0); + write_pnp_config(CBASE_HIGH, 0x00); + write_pnp_config(CBASE_LOW, 0x64); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_MOUSE) + PNP_ACTIVATE_DEVICE(LDEV_MOUSE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_RTC_APC) + PNP_SET_DEVICE_BASE(LDEV_RTC_APC, CFG_NS87308_RTC_BASE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_FDC) + PNP_SET_DEVICE_BASE(LDEV_FDC, CFG_NS87308_FDC_BASE); + write_pnp_config(LUN_CONFIG_REG, 0x40); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_RARP) + PNP_SET_DEVICE_BASE(LDEV_PARP, CFG_NS87308_LPT_BASE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_UART1) + PNP_SET_DEVICE_BASE(LDEV_UART1, CFG_NS87308_UART1_BASE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_UART2) + PNP_SET_DEVICE_BASE(LDEV_UART2, CFG_NS87308_UART2_BASE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_GPIO) + PNP_SET_DEVICE_BASE(LDEV_GPIO, CFG_NS87308_GPIO_BASE); +#endif + +#if (CFG_NS87308_DEVS & CFG_NS87308_POWRMAN) +#ifndef CFG_NS87308_PWMAN_BASE + PNP_ACTIVATE_DEVICE(LDEV_POWRMAN); +#else + PNP_SET_DEVICE_BASE(LDEV_POWRMAN, CFG_NS87308_PWMAN_BASE); + + /* + * Enable all units + */ + write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER1, 0x7d); + write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_FER2, 0x87); + +#ifdef CFG_NS87308_PMC1 + write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC1, CFG_NS87308_PMC1); +#endif + +#ifdef CFG_NS87308_PMC2 + write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC2, CFG_NS87308_PMC2); +#endif + +#ifdef CFG_NS87308_PMC3 + write_pm_reg(CFG_NS87308_PWMAN_BASE, PWM_PMC3, CFG_NS87308_PMC3); +#endif +#endif +#endif + +#ifdef CFG_NS87308_CS0_BASE + PNP_PGCS_CSLINE_BASE(0, CFG_NS87308_CS0_BASE); + PNP_PGCS_CSLINE_CONF(0, CFG_NS87308_CS0_CONF); +#endif + +#ifdef CFG_NS87308_CS1_BASE + PNP_PGCS_CSLINE_BASE(1, CFG_NS87308_CS1_BASE); + PNP_PGCS_CSLINE_CONF(1, CFG_NS87308_CS1_CONF); +#endif + +#ifdef CFG_NS87308_CS2_BASE + PNP_PGCS_CSLINE_BASE(2, CFG_NS87308_CS2_BASE); + PNP_PGCS_CSLINE_CONF(2, CFG_NS87308_CS2_CONF); +#endif +} + +#endif diff --git a/drivers/pci.c b/drivers/pci.c new file mode 100644 index 0000000..52584ce --- /dev/null +++ b/drivers/pci.c @@ -0,0 +1,503 @@ +/* + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * PCI routines + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <command.h> +#include <cmd_boot.h> +#include <asm/processor.h> +#include <asm/io.h> +#include <pci.h> + +#ifdef DEBUG +#define DEBUGF(x...) printf(x) +#else +#define DEBUGF(x...) +#endif /* DEBUG */ + +/* + * + */ + +#define PCI_HOSE_OP(rw, size, type) \ +int pci_hose_##rw##_config_##size(struct pci_controller *hose, \ + pci_dev_t dev, \ + int offset, type value) \ +{ \ + return hose->rw##_##size(hose, dev, offset, value); \ +} + +PCI_HOSE_OP(read, byte, u8 *) +PCI_HOSE_OP(read, word, u16 *) +PCI_HOSE_OP(read, dword, u32 *) +PCI_HOSE_OP(write, byte, u8) +PCI_HOSE_OP(write, word, u16) +PCI_HOSE_OP(write, dword, u32) + +#define PCI_OP(rw, size, type, error_code) \ +int pci_##rw##_config_##size(pci_dev_t dev, int offset, type value) \ +{ \ + struct pci_controller *hose = pci_bus_to_hose(PCI_BUS(dev)); \ + \ + if (!hose) \ + { \ + error_code; \ + return -1; \ + } \ + \ + return pci_hose_##rw##_config_##size(hose, dev, offset, value); \ +} + +PCI_OP(read, byte, u8 *, *value = 0xff) +PCI_OP(read, word, u16 *, *value = 0xffff) +PCI_OP(read, dword, u32 *, *value = 0xffffffff) +PCI_OP(write, byte, u8, ) +PCI_OP(write, word, u16, ) +PCI_OP(write, dword, u32, ) + +#define PCI_READ_VIA_DWORD_OP(size, type, off_mask) \ +int pci_hose_read_config_##size##_via_dword(struct pci_controller *hose, \ + pci_dev_t dev, \ + int offset, type val) \ +{ \ + u32 val32; \ + \ + if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) \ + return -1; \ + \ + *val = (val32 >> ((offset & (int)off_mask) * 8)); \ + \ + return 0; \ +} + +#define PCI_WRITE_VIA_DWORD_OP(size, type, off_mask, val_mask) \ +int pci_hose_write_config_##size##_via_dword(struct pci_controller *hose, \ + pci_dev_t dev, \ + int offset, type val) \ +{ \ + u32 val32, mask, ldata; \ + \ + if (pci_hose_read_config_dword(hose, dev, offset & 0xfc, &val32) < 0) \ + return -1; \ + \ + mask = val_mask; \ + ldata = (((unsigned long)val) & mask) << ((offset & (int)off_mask) * 8);\ + mask <<= ((mask & (int)off_mask) * 8); \ + val32 = (val32 & ~mask) | ldata; \ + \ + if (pci_hose_write_config_dword(hose, dev, offset & 0xfc, val32) < 0) \ + return -1; \ + \ + return 0; \ +} + +PCI_READ_VIA_DWORD_OP(byte, u8 *, 0x03) +PCI_READ_VIA_DWORD_OP(word, u16 *, 0x02) +PCI_WRITE_VIA_DWORD_OP(byte, u8, 0x03, 0x000000ff) +PCI_WRITE_VIA_DWORD_OP(word, u16, 0x02, 0x0000ffff) + +/* + * + */ + +static struct pci_controller* hose_head = NULL; + +void pci_register_hose(struct pci_controller* hose) +{ + struct pci_controller **phose = &hose_head; + + while(*phose) + phose = &(*phose)->next; + + hose->next = NULL; + + *phose = hose; +} + +struct pci_controller* pci_bus_to_hose(int bus) +{ + struct pci_controller *hose; + + for (hose = hose_head; hose; hose = hose->next) + if (bus >= hose->first_busno && + bus <= hose->last_busno) + return hose; + + return NULL; +} + +pci_dev_t pci_find_devices(struct pci_device_id *ids, int index) +{ + struct pci_controller * hose; + u16 vendor, device; + u8 header_type; + pci_dev_t bdf; + int i, bus, found_multi = 0; + + for (hose = hose_head; hose; hose = hose->next) + { +#if CFG_SCSI_SCAN_BUS_REVERSE + for (bus = hose->last_busno; bus >= hose->first_busno; bus--) +#else + for (bus = hose->first_busno; bus <= hose->last_busno; bus++) +#endif + for (bdf = PCI_BDF(bus,0,0); +#ifdef CONFIG_ELPPC + bdf < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1); +#else + bdf < PCI_BDF(bus+1,0,0); +#endif + bdf += PCI_BDF(0,0,1)) + { + if (!PCI_FUNC(bdf)) + { + pci_read_config_byte(bdf, + PCI_HEADER_TYPE, + &header_type); + + found_multi = header_type & 0x80; + } + else + { + if (!found_multi) + continue; + } + + pci_read_config_word(bdf, + PCI_VENDOR_ID, + &vendor); + pci_read_config_word(bdf, + PCI_DEVICE_ID, + &device); + + for (i=0; ids[i].vendor != 0; i++) + if (vendor == ids[i].vendor && + device == ids[i].device) + { + if (index <= 0) + return bdf; + + index--; + } + } + } + + return (-1); +} + +pci_dev_t pci_find_device(unsigned int vendor, unsigned int device, int index) +{ + static struct pci_device_id ids[2] = {{}, {0, 0}}; + + ids[0].vendor = vendor; + ids[0].device = device; + + return pci_find_devices(ids, index); +} + +/* + * + */ + +unsigned long pci_hose_phys_to_bus(struct pci_controller* hose, + unsigned long phys_addr, + unsigned long flags) +{ + struct pci_region *res; + unsigned long bus_addr; + int i; + + if (!hose) + { + printf("pci_hose_phys_to_bus: %s\n", "invalid hose"); + goto Done; + } + + for (i=0; i<hose->region_count; i++) + { + res = &hose->regions[i]; + + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + continue; + + bus_addr = phys_addr - res->phys_start + res->bus_start; + + if (bus_addr >= res->bus_start && + bus_addr < res->bus_start + res->size) + { + return bus_addr; + } + } + + printf("pci_hose_phys_to_bus: %s\n", "invalid physical address"); + + Done: + return 0; +} + +unsigned long pci_hose_bus_to_phys(struct pci_controller* hose, + unsigned long bus_addr, + unsigned long flags) +{ + struct pci_region *res; + int i; + + if (!hose) + { + printf("pci_hose_bus_to_phys: %s\n", "invalid hose"); + goto Done; + } + + for (i=0; i<hose->region_count; i++) + { + res = &hose->regions[i]; + + if (((res->flags ^ flags) & PCI_REGION_TYPE) != 0) + continue; + + if (bus_addr >= res->bus_start && + bus_addr < res->bus_start + res->size) + { + return bus_addr - res->bus_start + res->phys_start; + } + } + + printf("pci_hose_bus_to_phys: %s\n", "invalid physical address"); + + Done: + return 0; +} + +/* + * + */ + +int pci_hose_config_device(struct pci_controller *hose, + pci_dev_t dev, + unsigned long io, + unsigned long mem, + unsigned long command) +{ + unsigned int bar_response, bar_size, bar_value, old_command; + unsigned char pin; + int bar, found_mem64; + + DEBUGF("PCI Config: I/O=0x%lx, Memory=0x%lx, Command=0x%lx\n", io, mem, command); + + pci_hose_write_config_dword(hose, dev, PCI_COMMAND, 0); + + for (bar = PCI_BASE_ADDRESS_0; bar < PCI_BASE_ADDRESS_5; bar += 4) + { + pci_hose_write_config_dword(hose, dev, bar, 0xffffffff); + pci_hose_read_config_dword(hose, dev, bar, &bar_response); + + if (!bar_response) + continue; + + found_mem64 = 0; + + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) + { + bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1; + bar_value = io; + + io = ((io - 1) | (bar_size - 1)) + 1; + } + else + { + if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; + bar_value = mem; + + mem = ((mem - 1) | (bar_size - 1)) + 1; + } + + /* Write it out and update our limit */ + pci_hose_write_config_dword(hose, dev, bar, bar_value); + + if (found_mem64) + { + bar += 4; + pci_hose_write_config_dword(hose, dev, bar, 0x00000000); + } + } + + /* Configure Cache Line Size Register */ + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + + /* Configure Latency Timer */ + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); + + /* Disable interrupt line, if device says it wants to use interrupts */ + pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_PIN, &pin); + if (pin != 0) + { + pci_hose_write_config_byte(hose, dev, PCI_INTERRUPT_LINE, 0xff); + } + + pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &old_command); + pci_hose_write_config_dword(hose, dev, PCI_COMMAND, + (old_command & 0xffff0000) | command ); + + return 0; +} + +/* + * + */ + +struct pci_config_table *pci_find_config(struct pci_controller *hose, + unsigned short class, + unsigned int vendor, + unsigned int device, + unsigned int bus, + unsigned int dev, + unsigned int func) +{ + struct pci_config_table *table; + + for (table = hose->config_table; table && table->vendor; table++) + { + if ((table->vendor == PCI_ANY_ID || table->vendor == vendor) && + (table->device == PCI_ANY_ID || table->device == device) && + (table->class == PCI_ANY_ID || table->class == class) && + (table->bus == PCI_ANY_ID || table->bus == bus) && + (table->dev == PCI_ANY_ID || table->dev == dev) && + (table->func == PCI_ANY_ID || table->func == func)) + { + return table; + } + } + + return NULL; +} + +void pci_cfgfunc_config_device(struct pci_controller *hose, + pci_dev_t dev, + struct pci_config_table *entry) +{ + pci_hose_config_device(hose, dev, entry->priv[0], entry->priv[1], entry->priv[2]); +} + +void pci_cfgfunc_do_nothing(struct pci_controller *hose, + pci_dev_t dev, struct pci_config_table *entry) +{ +} + +/* + * + */ + +extern void pciauto_config_init(struct pci_controller *hose); +extern void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev); + +int pci_hose_scan_bus(struct pci_controller *hose, int bus) +{ + unsigned int sub_bus, found_multi=0; + unsigned short vendor, device, class; + unsigned char header_type; + struct pci_config_table *cfg; + pci_dev_t dev; + + sub_bus = bus; + + for (dev = PCI_BDF(bus,0,0); + dev < PCI_BDF(bus,PCI_MAX_PCI_DEVICES-1,PCI_MAX_PCI_FUNCTIONS-1); + dev += PCI_BDF(0,0,1)) + { +#ifndef CONFIG_405GP /* don't skip host bridge on ppc405gp */ + /* Skip our host bridge */ + if ( dev == PCI_BDF(hose->first_busno,0,0) ) + continue; +#endif + + if (PCI_FUNC(dev) && !found_multi) + continue; + + pci_hose_read_config_byte(hose, dev, PCI_HEADER_TYPE, &header_type); + + pci_hose_read_config_word(hose, dev, PCI_VENDOR_ID, &vendor); + + if (vendor != 0xffff && vendor != 0x0000) + { + + if (!PCI_FUNC(dev)) + found_multi = header_type & 0x80; + + DEBUGF("PCI Scan: Found Bus %d, Device %d, Function %d\n", + PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev) ); + + pci_hose_read_config_word(hose, dev, PCI_DEVICE_ID, &device); + pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); + + cfg = pci_find_config(hose, class, vendor, device, + PCI_BUS(dev), PCI_DEV(dev), PCI_FUNC(dev)); + if (cfg) + cfg->config_device(hose, dev, cfg); +#ifdef CONFIG_PCI_PNP + else + pciauto_config_device(hose, dev); +#endif + if (hose->fixup_irq) + hose->fixup_irq(hose, dev); + +#ifdef CONFIG_PCI_SCAN_SHOW + /* Skip our host bridge */ + if ( dev != PCI_BDF(hose->first_busno,0,0) ) { + unsigned char int_line; + + pci_hose_read_config_byte(hose, dev, PCI_INTERRUPT_LINE, + &int_line); + printf(" %02x %02x %04x %04x %04x %02x\n", + PCI_BUS(dev), PCI_DEV(dev), vendor, device, class, + int_line); + } +#endif + } + } + + return sub_bus; +} + +int pci_hose_scan(struct pci_controller *hose) +{ +#ifdef CONFIG_PCI_PNP + pciauto_config_init(hose); +#endif + return pci_hose_scan_bus(hose, hose->first_busno); +} + +#endif /* CONFIG_PCI */ diff --git a/drivers/pci_auto.c b/drivers/pci_auto.c new file mode 100644 index 0000000..f665ee6 --- /dev/null +++ b/drivers/pci_auto.c @@ -0,0 +1,319 @@ +/* + * arch/ppc/kernel/pci_auto.c + * + * PCI autoconfiguration library + * + * Author: Matt Porter <mporter@mvista.com> + * + * Copyright 2000 MontaVista Software Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <common.h> + +#ifdef CONFIG_PCI + +#include <pci.h> + +#undef DEBUG +#ifdef DEBUG +#define DEBUGF(x...) printf(x) +#else +#define DEBUGF(x...) +#endif /* DEBUG */ + +#define PCIAUTO_IDE_MODE_MASK 0x05 + +/* + * + */ + +void pciauto_region_init(struct pci_region* res) +{ + res->bus_lower = res->bus_start; +} + +void pciauto_region_align(struct pci_region *res, unsigned long size) +{ + res->bus_lower = ((res->bus_lower - 1) | (size - 1)) + 1; +} + +int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar) +{ + unsigned long addr; + + if (!res) + { + DEBUGF("No resource"); + goto error; + } + + addr = ((res->bus_lower - 1) | (size - 1)) + 1; + + if (addr - res->bus_start + size > res->size) + { + DEBUGF("No room in resource"); + goto error; + } + + res->bus_lower = addr + size; + + DEBUGF("address=0x%lx", addr); + + *bar = addr; + return 0; + + error: + *bar = 0xffffffff; + return -1; +} + +/* + * + */ + +void pciauto_setup_device(struct pci_controller *hose, + pci_dev_t dev, int bars_num, + struct pci_region *mem, + struct pci_region *io) +{ + unsigned int bar_value, bar_response, bar_size; + unsigned int cmdstat = 0; + struct pci_region *bar_res; + int bar, bar_nr = 0; + int found_mem64 = 0; + + pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); + cmdstat = (cmdstat & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) | PCI_COMMAND_MASTER; + + for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_0 + (bars_num*4); bar += 4) + { + /* Tickle the BAR and get the response */ + pci_hose_write_config_dword(hose, dev, bar, 0xffffffff); + pci_hose_read_config_dword(hose, dev, bar, &bar_response); + + /* If BAR is not implemented go to the next BAR */ + if (!bar_response) + continue; + + found_mem64 = 0; + + /* Check the BAR type and set our address mask */ + if (bar_response & PCI_BASE_ADDRESS_SPACE) + { + bar_size = ~(bar_response & PCI_BASE_ADDRESS_IO_MASK) + 1; + bar_res = io; + + DEBUGF("PCI Autoconfig: BAR %d, I/O, size=0x%x, ", bar_nr, bar_size); + } + else + { + if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) + found_mem64 = 1; + + bar_size = ~(bar_response & PCI_BASE_ADDRESS_MEM_MASK) + 1; + bar_res = mem; + + DEBUGF("PCI Autoconfig: BAR %d, Mem, size=0x%x, ", bar_nr, bar_size); + } + + if (pciauto_region_allocate(bar_res, bar_size, &bar_value) == 0) + { + /* Write it out and update our limit */ + pci_hose_write_config_dword(hose, dev, bar, bar_value); + + /* + * If we are a 64-bit decoder then increment to the + * upper 32 bits of the bar and force it to locate + * in the lower 4GB of memory. + */ + if (found_mem64) + { + bar += 4; + pci_hose_write_config_dword(hose, dev, bar, 0x00000000); + } + + cmdstat |= (bar_response & PCI_BASE_ADDRESS_SPACE) ? + PCI_COMMAND_IO : PCI_COMMAND_MEMORY; + } + + DEBUGF("\n"); + + bar_nr++; + } + + pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat); + pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08); + pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80); +} + +static void pciauto_prescan_setup_bridge(struct pci_controller *hose, + pci_dev_t dev, int sub_bus) +{ + struct pci_region *pci_mem = hose->pci_mem; + struct pci_region *pci_io = hose->pci_io; + unsigned int cmdstat; + + pci_hose_read_config_dword(hose, dev, PCI_COMMAND, &cmdstat); + + /* Configure bus number registers */ + pci_hose_write_config_byte(hose, dev, PCI_PRIMARY_BUS, PCI_BUS(dev)); + pci_hose_write_config_byte(hose, dev, PCI_SECONDARY_BUS, sub_bus + 1); + pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, 0xff); + + if (pci_mem) + { + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_mem, 0x100000); + + /* Set up memory and I/O filter limits, assume 32-bit I/O space */ + pci_hose_write_config_word(hose, dev, PCI_MEMORY_BASE, + (pci_mem->bus_lower & 0xfff00000) >> 16); + + cmdstat |= PCI_COMMAND_MEMORY; + } + + if (pci_io) + { + /* Round I/O allocator to 4KB boundary */ + pciauto_region_align(pci_io, 0x1000); + + pci_hose_write_config_byte(hose, dev, PCI_IO_BASE, + (pci_io->bus_lower & 0x0000f000) >> 8); + pci_hose_write_config_word(hose, dev, PCI_IO_BASE_UPPER16, + (pci_io->bus_lower & 0xffff0000) >> 16); + + cmdstat |= PCI_COMMAND_IO; + } + + /* We don't support prefetchable memory for now, so disable */ + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_BASE, 0x1000); + pci_hose_write_config_word(hose, dev, PCI_PREF_MEMORY_LIMIT, 0x1000); + + /* Enable memory and I/O accesses, enable bus master */ + pci_hose_write_config_dword(hose, dev, PCI_COMMAND, cmdstat | PCI_COMMAND_MASTER); +} + +static void pciauto_postscan_setup_bridge(struct pci_controller *hose, + pci_dev_t dev, int sub_bus) +{ + struct pci_region *pci_mem = hose->pci_mem; + struct pci_region *pci_io = hose->pci_io; + + /* Configure bus number registers */ + pci_hose_write_config_byte(hose, dev, PCI_SUBORDINATE_BUS, sub_bus); + + if (pci_mem) + { + /* Round memory allocator to 1MB boundary */ + pciauto_region_align(pci_mem, 0x100000); + + pci_hose_write_config_word(hose, dev, PCI_MEMORY_LIMIT, + (pci_mem->bus_lower-1) >> 16); + } + + if (pci_io) + { + /* Round I/O allocator to 4KB boundary */ + pciauto_region_align(pci_io, 0x1000); + + pci_hose_write_config_byte(hose, dev, PCI_IO_LIMIT, + ((pci_io->bus_lower-1) & 0x0000f000) >> 8); + pci_hose_write_config_word(hose, dev, PCI_IO_LIMIT_UPPER16, + ((pci_io->bus_lower-1) & 0xffff0000) >> 16); + } +} + +/* + * + */ + +void pciauto_config_init(struct pci_controller *hose) +{ + int i; + + hose->pci_io = hose->pci_mem = NULL; + + for (i=0; i<hose->region_count; i++) + { + switch(hose->regions[i].flags) + { + case PCI_REGION_IO: + if (!hose->pci_io || + hose->pci_io->size < hose->regions[i].size) + hose->pci_io = hose->regions + i; + break; + case PCI_REGION_MEM: + if (!hose->pci_mem || + hose->pci_mem->size < hose->regions[i].size) + hose->pci_mem = hose->regions + i; + break; + } + } + + + + if (hose->pci_mem) + { + pciauto_region_init(hose->pci_mem); + + DEBUGF("PCI Autoconfig: Memory region: [%lx-%lx]\n", + hose->pci_mem->bus_start, + hose->pci_mem->bus_start + hose->pci_mem->size - 1); + } + + if (hose->pci_io) + { + pciauto_region_init(hose->pci_io); + + DEBUGF("PCI Autoconfig: I/O region: [%lx-%lx]\n", + hose->pci_io->bus_start, + hose->pci_io->bus_start + hose->pci_io->size - 1); + } +} + +void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev) +{ + unsigned int sub_bus; + unsigned short class; + unsigned char prg_iface; + + pci_hose_read_config_word(hose, dev, PCI_CLASS_DEVICE, &class); + + switch(class) + { + case PCI_CLASS_BRIDGE_PCI: + pciauto_setup_device(hose, dev, 2, hose->pci_mem, hose->pci_io); + + DEBUGF("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_DEV(dev)); + + pciauto_prescan_setup_bridge(hose, dev, PCI_BUS(dev)); + + sub_bus = pci_hose_scan_bus(hose, PCI_BUS(dev)+1); + + pciauto_postscan_setup_bridge(hose, dev, sub_bus); + break; + + case PCI_CLASS_STORAGE_IDE: + pci_hose_read_config_byte(hose, dev, PCI_CLASS_PROG, &prg_iface); + if (!(prg_iface & PCIAUTO_IDE_MODE_MASK)) + { + DEBUGF("PCI Autoconfig: Skipping legacy mode IDE controller\n"); + return; + } + + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); + break; + + default: + pciauto_setup_device(hose, dev, 6, hose->pci_mem, hose->pci_io); + break; + } +} + +#endif /* CONFIG_PCI */ diff --git a/drivers/pcnet.c b/drivers/pcnet.c new file mode 100644 index 0000000..f69cd2c --- /dev/null +++ b/drivers/pcnet.c @@ -0,0 +1,526 @@ +/* + * (C) Copyright 2002 Wolfgang Grandegger, wg@denx.de. + * + * This driver for AMD PCnet network controllers is derived from the + * Linux driver pcnet32.c written 1996-1999 by Thomas Bogendoerfer. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/io.h> +#include <pci.h> + +#if 0 +#define PCNET_DEBUG_LEVEL 0 /* 0=off, 1=init, 2=rx/tx */ +#endif + +#if PCNET_DEBUG_LEVEL > 0 +#define DEBUG1(fmt,args...) printf (fmt ,##args) +#if PCNET_DEBUG_LEVEL > 1 +#define DEBUG2(fmt,args...) printf (fmt ,##args) +#else +#define DEBUG2(fmt,args...) +#endif +#else +#define DEBUG1(fmt,args...) +#define DEBUG2(fmt,args...) +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_PCNET) + +#if !defined(CONF_PCNET_79C973) && defined(CONF_PCNET_79C975) +#error "Macro for PCnet chip version is not defined!" +#endif + +/* + * Set the number of Tx and Rx buffers, using Log_2(# buffers). + * Reasonable default values are 4 Tx buffers, and 16 Rx buffers. + * That translates to 2 (4 == 2^^2) and 4 (16 == 2^^4). + */ +#define PCNET_LOG_TX_BUFFERS 0 +#define PCNET_LOG_RX_BUFFERS 2 + +#define TX_RING_SIZE (1 << (PCNET_LOG_TX_BUFFERS)) +#define TX_RING_LEN_BITS ((PCNET_LOG_TX_BUFFERS) << 12) + +#define RX_RING_SIZE (1 << (PCNET_LOG_RX_BUFFERS)) +#define RX_RING_LEN_BITS ((PCNET_LOG_RX_BUFFERS) << 4) + +#define PKT_BUF_SZ 1544 + +/* The PCNET Rx and Tx ring descriptors. */ +struct pcnet_rx_head { + u32 base; + s16 buf_length; + s16 status; + u32 msg_length; + u32 reserved; +}; + +struct pcnet_tx_head { + u32 base; + s16 length; + s16 status; + u32 misc; + u32 reserved; +}; + +/* The PCNET 32-Bit initialization block, described in databook. */ +struct pcnet_init_block { + u16 mode; + u16 tlen_rlen; + u8 phys_addr[6]; + u16 reserved; + u32 filter[2]; + /* Receive and transmit ring base, along with extra bits. */ + u32 rx_ring; + u32 tx_ring; + u32 reserved2; +}; + +typedef struct pcnet_priv { + struct pcnet_rx_head rx_ring[RX_RING_SIZE]; + struct pcnet_tx_head tx_ring[TX_RING_SIZE]; + struct pcnet_init_block init_block; + /* Receive Buffer space */ + unsigned char rx_buf[RX_RING_SIZE][PKT_BUF_SZ + 4]; + int cur_rx; + int cur_tx; +} pcnet_priv_t; + +static pcnet_priv_t *lp; + +/* Offsets from base I/O address for WIO mode */ +#define PCNET_RDP 0x10 +#define PCNET_RAP 0x12 +#define PCNET_RESET 0x14 +#define PCNET_BDP 0x16 + +static u16 pcnet_read_csr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_RDP); +} + +static void pcnet_write_csr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_RDP); +} + +static u16 pcnet_read_bcr (struct eth_device *dev, int index) +{ + outw (index, dev->iobase+PCNET_RAP); + return inw (dev->iobase+PCNET_BDP); +} + +static void pcnet_write_bcr (struct eth_device *dev, int index, u16 val) +{ + outw (index, dev->iobase+PCNET_RAP); + outw (val, dev->iobase+PCNET_BDP); +} + +static void pcnet_reset (struct eth_device *dev) +{ + inw (dev->iobase+PCNET_RESET); +} + +static int pcnet_check (struct eth_device *dev) +{ + outw (88, dev->iobase+PCNET_RAP); + return (inw (dev->iobase+PCNET_RAP) == 88); +} + +static int pcnet_init( struct eth_device* dev, bd_t *bis); +static int pcnet_send (struct eth_device* dev, volatile void *packet, + int length); +static int pcnet_recv (struct eth_device* dev); +static void pcnet_halt (struct eth_device* dev); +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_num); + +#define PCI_TO_MEM(d,a) pci_phys_to_mem((pci_dev_t)d->priv, (u_long)(a)) +#define PCI_TO_MEM_LE(d,a) (u32)(cpu_to_le32(PCI_TO_MEM(d,a))) + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LANCE }, + { } +}; + + +int pcnet_initialize(bd_t *bis) +{ + pci_dev_t devbusfn; + struct eth_device* dev; + u16 command, status; + int dev_nr = 0; + + DEBUG1("\npcnet_initialize...\n"); + + for (dev_nr = 0; ; dev_nr++) { + + /* + * Find the PCnet PCI device(s). + */ + if ((devbusfn = pci_find_devices(supported, dev_nr)) < 0) { + break; + } + + /* + * Allocate and pre-fill the device structure. + */ + dev = (struct eth_device*) malloc(sizeof *dev); + dev->priv = (void *)devbusfn; + sprintf(dev->name, "pcnet#%d", dev_nr); + + /* + * Setup the PCI device. + */ + pci_read_config_dword(devbusfn, PCI_BASE_ADDRESS_0, &dev->iobase); + dev->iobase &= ~0xf; + + DEBUG1("%s: devbusfn=0x%x iobase=0x%x: ", + dev->name, devbusfn, dev->iobase); + + command = PCI_COMMAND_IO | PCI_COMMAND_MASTER; + pci_write_config_word(devbusfn, PCI_COMMAND, command); + pci_read_config_word(devbusfn, PCI_COMMAND, &status); + if ((status & command) != command) { + printf("%s: Couldn't enable IO access or Bus Mastering\n", + dev->name); + free(dev); + continue; + } + + pci_write_config_byte(devbusfn, PCI_LATENCY_TIMER, 0x40); + + /* + * Probe the PCnet chip. + */ + if (pcnet_probe(dev, bis, dev_nr) < 0) { + free(dev); + continue; + } + + /* + * Setup device structure and register the driver. + */ + dev->init = pcnet_init; + dev->halt = pcnet_halt; + dev->send = pcnet_send; + dev->recv = pcnet_recv; + + eth_register(dev); + } + + udelay(10 * 1000); + + return dev_nr; +} + +static int pcnet_probe(struct eth_device* dev, bd_t *bis, int dev_nr) +{ + int chip_version; + char *chipname; +#ifdef PCNET_HAS_PROM + int i; +#endif + + /* Reset the PCnet controller */ + pcnet_reset(dev); + + /* Check if register access is working */ + if (pcnet_read_csr(dev, 0) != 4 || !pcnet_check(dev)) { + printf("%s: CSR register access check failed\n", dev->name); + return -1; + } + + /* Identify the chip */ + chip_version = pcnet_read_csr(dev, 88) | (pcnet_read_csr(dev,89) << 16); + if ((chip_version & 0xfff) != 0x003) + return -1; + chip_version = (chip_version >> 12) & 0xffff; + switch (chip_version) { +#ifdef CONFIG_PCNET_79C973 + case 0x2625: + chipname = "PCnet/FAST III 79C973"; /* PCI */ + break; +#endif +#ifdef CONFIG_PCNET_79C975 + case 0x2627: + chipname = "PCnet/FAST III 79C975"; /* PCI */ + break; +#endif + default: + printf("%s: PCnet version %#x not supported\n", + dev->name, chip_version); + return -1; + } + + DEBUG1("AMD %s\n", chipname); + +#ifdef PCNET_HAS_PROM + /* + * In most chips, after a chip reset, the ethernet address is read from + * the station address PROM at the base address and programmed into the + * "Physical Address Registers" CSR12-14. + */ + for (i = 0; i < 3; i++) { + unsigned int val; + val = pcnet_read_csr(dev, i+12) & 0x0ffff; + /* There may be endianness issues here. */ + dev->dev_addr[2*i] = val & 0x0ff; + dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff; + } +#endif /* PCNET_HAS_PROM */ + + return 0; +} + +static int pcnet_init(struct eth_device* dev, bd_t *bis) +{ + int i, val; + u32 addr; + + DEBUG1("%s: pcnet_init...\n", dev->name); + + /* Switch pcnet to 32bit mode */ + pcnet_write_bcr (dev, 20, 2); + +#ifdef CONFIG_PN62 + /* Setup LED registers */ + val = pcnet_read_bcr (dev, 2) | 0x1000; + pcnet_write_bcr (dev, 2, val); /* enable LEDPE */ + pcnet_write_bcr (dev, 4, 0x5080); /* 100MBit */ + pcnet_write_bcr (dev, 5, 0x40c0); /* LNKSE */ + pcnet_write_bcr (dev, 6, 0x4090); /* TX Activity */ + pcnet_write_bcr (dev, 7, 0x4084); /* RX Activity */ +#endif + + /* Set/reset autoselect bit */ + val = pcnet_read_bcr (dev, 2) & ~2; + val |= 2; + pcnet_write_bcr (dev, 2, val); + + /* Enable auto negotiate, setup, disable fd */ + val = pcnet_read_bcr(dev, 32) & ~0x98; + val |= 0x20; + pcnet_write_bcr(dev, 32, val); + + /* + * We only maintain one structure because the drivers will never + * be used concurrently. In 32bit mode the RX and TX ring entries + * must be aligned on 16-byte boundaries. + */ + if (lp == NULL) { + addr = (u32)malloc(sizeof(pcnet_priv_t) + 0x10); + addr = (addr + 0xf) & ~0xf; + lp = (pcnet_priv_t *)addr; + } + + lp->init_block.mode = cpu_to_le16(0x0000); + lp->init_block.filter[0] = 0x00000000; + lp->init_block.filter[1] = 0x00000000; + + /* + * Initialize the Rx ring. + */ + lp->cur_rx = 0; + for (i = 0; i < RX_RING_SIZE; i++) { + lp->rx_ring[i].base = PCI_TO_MEM_LE(dev, lp->rx_buf[i]); + lp->rx_ring[i].buf_length = cpu_to_le16(-PKT_BUF_SZ); + lp->rx_ring[i].status = cpu_to_le16(0x8000); + DEBUG1("Rx%d: base=0x%x buf_length=0x%x status=0x%x\n", + i, lp->rx_ring[i].base, lp->rx_ring[i].buf_length, + lp->rx_ring[i].status); + } + + /* + * Initialize the Tx ring. The Tx buffer address is filled in as + * needed, but we do need to clear the upper ownership bit. + */ + lp->cur_tx = 0; + for (i = 0; i < TX_RING_SIZE; i++) { + lp->tx_ring[i].base = 0; + lp->tx_ring[i].status = 0; + } + + /* + * Setup Init Block. + */ + DEBUG1("Init block at 0x%p: MAC", &lp->init_block); + + for (i = 0; i < 6; i++) { + lp->init_block.phys_addr[i] = dev->enetaddr[i]; + DEBUG1(" %02x", lp->init_block.phys_addr[i]); + } + + lp->init_block.tlen_rlen = cpu_to_le16(TX_RING_LEN_BITS | + RX_RING_LEN_BITS); + lp->init_block.rx_ring = PCI_TO_MEM_LE(dev, lp->rx_ring); + lp->init_block.tx_ring = PCI_TO_MEM_LE(dev, lp->tx_ring); + + DEBUG1("\ntlen_rlen=0x%x rx_ring=0x%x tx_ring=0x%x\n", + lp->init_block.tlen_rlen, + lp->init_block.rx_ring, lp->init_block.tx_ring); + + /* + * Tell the controller where the Init Block is located. + */ + addr = PCI_TO_MEM(dev, &lp->init_block); + pcnet_write_csr(dev, 1, addr & 0xffff); + pcnet_write_csr(dev, 2, (addr >> 16) & 0xffff); + + pcnet_write_csr (dev, 4, 0x0915); + pcnet_write_csr (dev, 0, 0x0001); /* start */ + + /* Wait for Init Done bit */ + for (i = 10000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x0100) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller init failed\n", dev->name); + pcnet_reset (dev); + return 0; + } + + /* + * Finally start network controller operation. + */ + pcnet_write_csr (dev, 0, 0x0002); + + return 1; +} + +static int pcnet_send(struct eth_device* dev, volatile void *packet, int pkt_len) +{ + int i, status; + struct pcnet_tx_head *entry = &lp->tx_ring[lp->cur_tx]; + + DEBUG2("Tx%d: %d bytes from 0x%p ", lp->cur_tx, pkt_len, packet); + + /* Wait for completion by testing the OWN bit */ + for (i = 1000; i > 0; i--) { + status = le16_to_cpu(entry->status); + if ((status & 0x8000) == 0) + break; + udelay(100); + DEBUG2("."); + } + if (i <= 0) { + printf("%s: TIMEOUT: Tx%d failed (status = 0x%x)\n", + dev->name, lp->cur_tx, status); + pkt_len = 0; + goto failure; + } + + /* + * Setup Tx ring. Caution: the write order is important here, + * set the status with the "ownership" bits last. + */ + status = 0x8300; + entry->length = le16_to_cpu(-pkt_len); + entry->misc = 0x00000000; + entry->base = PCI_TO_MEM_LE(dev, packet); + entry->status = le16_to_cpu(status); + + /* Trigger an immediate send poll. */ + pcnet_write_csr (dev, 0, 0x0008); + + failure: + if (++lp->cur_tx >= TX_RING_SIZE) + lp->cur_tx = 0; + + DEBUG2("done\n"); + return pkt_len; +} + +static int pcnet_recv(struct eth_device* dev) +{ + struct pcnet_rx_head *entry; + int pkt_len = 0; + u16 status; + + while (1) { + entry = &lp->rx_ring[lp->cur_rx]; + /* + * If we own the next entry, it's a new packet. Send it up. + */ + if (((status = le16_to_cpu(entry->status)) & 0x8000) != 0) { + break; + } + status >>= 8; + + if (status != 0x03) { /* There was an error. */ + + printf("%s: Rx%d", dev->name, lp->cur_rx); + DEBUG1(" (status=0x%x)", status); + if (status & 0x20) printf(" Frame"); + if (status & 0x10) printf(" Overflow"); + if (status & 0x08) printf(" CRC"); + if (status & 0x04) printf(" Fifo"); + printf(" Error\n"); + entry->status &= le16_to_cpu(0x03ff); + + } else { + + pkt_len = (le32_to_cpu(entry->msg_length) & 0xfff) - 4; + if (pkt_len < 60) { + printf("%s: Rx%d: invalid packet length %d\n", + dev->name, lp->cur_rx, pkt_len); + } else { + NetReceive(lp->rx_buf[lp->cur_rx], pkt_len); + DEBUG2("Rx%d: %d bytes from 0x%p\n", + lp->cur_rx, pkt_len, lp->rx_buf[lp->cur_rx]); + } + } + entry->status |= cpu_to_le16(0x8000); + + if (++lp->cur_rx >= RX_RING_SIZE) + lp->cur_rx = 0; + } + return pkt_len; +} + +static void pcnet_halt(struct eth_device* dev) +{ + int i; + + DEBUG1("%s: pcnet_halt...\n", dev->name); + + /* Reset the PCnet controller */ + pcnet_reset (dev); + + /* Wait for Stop bit */ + for (i = 1000; i > 0; i--) { + if (pcnet_read_csr (dev, 0) & 0x4) + break; + udelay(10); + } + if (i <= 0) { + printf("%s: TIMEOUT: controller reset failed\n", dev->name); + } +} + +#endif diff --git a/drivers/smiLynxEM.c b/drivers/smiLynxEM.c new file mode 100644 index 0000000..75d5a31 --- /dev/null +++ b/drivers/smiLynxEM.c @@ -0,0 +1,1059 @@ +/* + * (C) Copyright 1997-2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * smiLynxEM.c + * + * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator + * + * modification history + * -------------------- + * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>. + * + */ + +#include <common.h> + +#if defined(CONFIG_VIDEO_SMI_LYNXEM) + +#include <pci.h> +#include <video_fb.h> + +/* + * Export Graphic Device + */ +GraphicDevice smi; + +/* + * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external + */ +#define VIDEO_MEM_SIZE 0x400000 + +/* + * Supported video modes for SMI Lynx E/EM/EM+ + */ +#define VIDEO_MODES 7 +#define DUAL_800_600 0 /* SMI710:VGA1:75Hz (pitch=1600) */ + /* VGA2:60/120Hz (pitch=1600) */ + /* SMI810:VGA1:75Hz (pitch=1600) */ + /* VGA2:75Hz (pitch=1600) */ +#define DUAL_1024_768 1 /* VGA1:75Hz VGA2:73Hz (pitch=2048) */ +#define SINGLE_800_600 2 /* VGA1:75Hz (pitch=800) */ +#define SINGLE_1024_768 3 /* VGA1:75Hz (pitch=1024) */ +#define SINGLE_1280_1024 4 /* VGA1:75Hz (pitch=1280) */ +#define TV_MODE_CCIR 5 /* VGA1:50Hz (h=720;v=576;pitch=720) */ +#define TV_MODE_EIA 6 /* VGA1:60Hz (h=720;v=484;pitch=720) */ + + +/* + * ISA mapped regs + */ +#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */ +#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */ +#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */ +#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */ +#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */ +#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */ +#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */ +#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */ +#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */ +#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */ +#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/ + + +/* + * Video processor control +*/ +typedef struct { + unsigned int control; + unsigned int colorKey; + unsigned int colorKeyMask; + unsigned int start; + unsigned short offset; + unsigned short width; + unsigned int fifoPrio; + unsigned int fifoERL; + unsigned int YUVtoRGB; +} SmiVideoProc; + +/* + * Video window control + */ +typedef struct { + unsigned short top; + unsigned short left; + unsigned short bottom; + unsigned short right; + unsigned int srcStart; + unsigned short width; + unsigned short offset; + unsigned char hStretch; + unsigned char vStretch; +} SmiVideoWin; + +/* + * Capture port control + */ +typedef struct { + unsigned int control; + unsigned short topClip; + unsigned short leftClip; + unsigned short srcHeight; + unsigned short srcWidth; + unsigned int srcBufStart1; + unsigned int srcBufStart2; + unsigned short srcOffset; + unsigned short fifoControl; +} SmiCapturePort; + + + +/* + * Register values for common video modes + */ +static char SMI_SCR[22] = { + /* all modes */ + 0x10, 0xff, 0x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0x00, 0x15, 0x90, + 0x16, 0x10, 0x17, 0x2c, 0x18, 0xb1, 0x19, 0x20, 0x1a, 0x01 +}; + +static char SMI_EXT_CRT[VIDEO_MODES][24] = { + { /* DUAL_800_600_8 */ + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, + 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00 + }, + { /* DUAL_1024_768_8 */ + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, + 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00 + }, + { /* SINGLE_800_600_8 */ + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, + 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00 + }, + { /* SINGLE_1024_768_8 */ + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, + 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00 + }, + { /* SINGLE_1280_1024_8 */ + 0x30, 0x09, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, + 0x36, 0x00, 0x3b, 0x00, 0x3c, 0x00, 0x3d, 0x00, 0x3e, 0x00, 0x3f, 0x00 + }, + { /* TV_MODE_CCIR */ + 0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x01, 0x34, 0x26, 0x35, 0x88, + 0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00 + }, + { /* TV_MODE_EIA */ + 0x30, 0x80, 0x31, 0x2b, 0x32, 0x06, 0x33, 0x00, 0x34, 0xf8, 0x35, 0x88, + 0x36, 0x02, 0x38, 0x11, 0x39, 0x11, 0x3a, 0x20, 0x3e, 0xa3, 0x3f, 0x00 + }, +}; + +static char SMI_CRTCR[VIDEO_MODES][50] = { + { /* DUAL_800_600_8 */ + 0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12, + 0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c, + 0x12, 0x57, 0x13, 0x64, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* DUAL_1024_768_8 */ + 0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e, + 0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24, + 0x12, 0xff, 0x13, 0x80, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* SINGLE_800_600_8 */ + 0x00, 0x7f, 0x01, 0x63, 0x02, 0x63, 0x03, 0x00, 0x04, 0x68, 0x05, 0x12, + 0x06, 0x6f, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x59, 0x11, 0x2c, + 0x12, 0x57, 0x13, 0x32, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* SINGLE_1024_768_8 */ + 0x00, 0x9f, 0x01, 0x7f, 0x02, 0x7f, 0x03, 0x00, 0x04, 0x82, 0x05, 0x0e, + 0x06, 0x1e, 0x07, 0xf5, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x24, + 0x12, 0xff, 0x13, 0x40, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* SINGLE_1280_1024_8 */ + 0x00, 0xce, 0x01, 0x9f, 0x02, 0x9f, 0x03, 0x00, 0x04, 0xa2, 0x05, 0x12, + 0x06, 0x2a, 0x07, 0x5a, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x01, 0x11, 0x23, + 0x12, 0xff, 0x13, 0x50, 0x14, 0x40, 0x15, 0xff, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* TV_MODE_CCIR */ + 0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10, + 0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c, + 0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, + { /* TV_MODE_EIA */ + 0x00, 0x00, 0x01, 0x59, 0x02, 0x63, 0x03, 0x00, 0x04, 0x69, 0x05, 0x10, + 0x06, 0x72, 0x07, 0xf0, 0x08, 0x00, 0x09, 0x60, 0x0a, 0x00, 0x0b, 0x00, + 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x58, 0x11, 0x2c, + 0x12, 0x57, 0x13, 0x2d, 0x14, 0x40, 0x15, 0x57, 0x16, 0x00, 0x17, 0xe3, + 0x18, 0xff + }, +}; + +static char SMI_SEQR[10] = { + 0x00, 0x03, 0x01, 0x01, 0x02, 0x0f, 0x03, 0x03, 0x04, 0x0e +}; + +static char SMI_PCR[VIDEO_MODES][8] = { + { /* DUAL_800_600_8 */ + 0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00 + }, + { /* DUAL_1024_768_8 */ + 0x20, 0x04, 0x21, 0x20, 0x22, 0x00, 0x23, 0x00 + }, + { /* SINGLE_800_600_8 */ + 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00 + }, + { /* SINGLE_1024_768_8 */ + 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00 + }, + { /* SINGLE_1280_1024_8 */ + 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00 + }, + { /* TV_MODE_CCIR */ + 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00 + }, + { /* TV_MODE_EIA */ + 0x20, 0x04, 0x21, 0x30, 0x22, 0x02, 0x23, 0x00 + }, +}; + +static char SMI_MCR[VIDEO_MODES][6] = { + { /* DUAL_800_600_8 */ + 0x60, 0x01, 0x61, 0x00, 0x62, 0x7a + }, + { /* DUAL_1024_768_8 */ + 0x60, 0x01, 0x61, 0x00, 0x62, 0x7a + }, + { /* SINGLE_800_600_8 */ + 0x60, 0x00, 0x61, 0x00, 0x62, 0x34 + }, + { /* SINGLE_1024_768_8 */ + 0x60, 0x00, 0x61, 0x00, 0x62, 0xfe + }, + { /* SINGLE_1280_1024_8 */ + 0x60, 0x00, 0x61, 0x00, 0x62, 0xfe + }, + { /* TV_MODE_CCIR */ + 0x60, 0x00, 0x61, 0x00, 0x62, 0x34 + }, + { /* TV_MODE_EIA */ + 0x60, 0x00, 0x61, 0x00, 0x62, 0x34 + }, +}; + +static char SMI_CCR[VIDEO_MODES][18] = { + { /* DUAL_800_600_8 */ + 0x65, 0x34, 0x68, 0x50, 0x69, 0x05, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15, + 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12 + }, + { /* DUAL_1024_768_8 */ + 0x65, 0x00, 0x68, 0x50, 0x69, 0x06, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b, + 0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02 + }, + { /* SINGLE_800_600_8 */ + 0x65, 0x34, 0x68, 0x40, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15, + 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12 + }, + { /* SINGLE_1024_768_8 */ + 0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x0b, + 0x6d, 0x02, 0x6e, 0x0b, 0x6f, 0x02 + }, + { /* SINGLE_1280_1024_8 */ + 0x65, 0x00, 0x68, 0x50, 0x69, 0x03, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0xd9, + 0x6d, 0x17, 0x6e, 0xd9, 0x6f, 0x17 + }, + { /* TV_MODE_CCIR */ + 0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15, + 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12 + }, + { /* TV_MODE_EIA */ + 0x65, 0x07, 0x68, 0xc0, 0x69, 0x81, 0x6a, 0x53, 0x6b, 0x15, 0x6c, 0x15, + 0x6d, 0x06, 0x6e, 0x3d, 0x6f, 0x12 + }, +}; + +static char SMI_SHVGA[VIDEO_MODES][24] = { + { /* DUAL_800_600_8 */ + 0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f, + 0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20, + }, + { /* DUAL_1024_768_8 */ + 0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e, + 0x46, 0xff, 0x47, 0x00, 0x48, 0x00, 0x49, 0x03, 0x4a, 0xe5, 0x4b, 0x20, + }, + { /* SINGLE_800_600_8 */ + 0x40, 0x7f, 0x41, 0x63, 0x42, 0x00, 0x43, 0x68, 0x44, 0x12, 0x45, 0x6f, + 0x46, 0x57, 0x47, 0x00, 0x48, 0x59, 0x49, 0x0c, 0x4a, 0xa0, 0x4b, 0x20, + }, + { /* SINGLE_1024_768_8 */ + 0x40, 0x9f, 0x41, 0x7f, 0x42, 0x00, 0x43, 0x82, 0x44, 0x0e, 0x45, 0x1e, + 0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x04, 0x4a, 0xa5, 0x4b, 0x20, + }, + { /* SINGLE_1280_1024_8 */ + 0x40, 0xce, 0x41, 0x9f, 0x42, 0x00, 0x43, 0xa2, 0x44, 0x12, 0x45, 0x2a, + 0x46, 0xff, 0x47, 0x00, 0x48, 0x01, 0x49, 0x03, 0x4a, 0x4a, 0x4b, 0x20, + }, + { /* TV_MODE_CCIR */ + 0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x38, + 0x46, 0x25, 0x47, 0x05, 0x48, 0x2a, 0x49, 0x00, 0x4a, 0x4d, 0x4b, 0x00, + }, + { /* TV_MODE_EIA */ + 0x40, 0x6d, 0x41, 0x59, 0x42, 0x00, 0x43, 0x60, 0x44, 0x09, 0x45, 0x06, + 0x46, 0xf7, 0x47, 0x05, 0x48, 0xfa, 0x49, 0x00, 0x4a, 0x41, 0x4b, 0x00, + }, +}; + + +static char SMI_GPR[VIDEO_MODES][12] = { + { /* DUAL_800_600_8 */ + 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00 + }, + { /* DUAL_1024_768_8 */ + 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00 + }, + { /* SINGLE_800_600_8 */ + 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00 + }, + { /* SINGLE_1024_768_8 */ + 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00 + }, + { /* SINGLE_1280_1024_8 */ + 0x70, 0x00, 0x71, 0xa2, 0x72, 0x0f, 0x73, 0x30, 0x74, 0x40, 0x75, 0x00 + }, + { /* TV_MODE_CCIR */ + 0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28 + }, + { /* TV_MODE_EIA */ + 0x70, 0x82, 0x71, 0x8d, 0x72, 0x0c, 0x73, 0x32, 0x74, 0x09, 0x75, 0x28 + }, +}; + +static char SMI_HCR[VIDEO_MODES][22] = { + { /* DUAL_800_600_8 */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* DUAL_1024_768_8 */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* SINGLE_800_600_8 */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* SINGLE_1024_768_8 */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* SINGLE_1280_1024_8 */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* TV_MODE_CCIR */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, + { /* TV_MODE_EIA */ + 0x80, 0xff, 0x81, 0x07, 0x82, 0x00, 0x83, 0xff, 0x84, 0xff, 0x88, 0x00, + 0x89, 0x02, 0x8a, 0x80, 0x8b, 0x01, 0x8c, 0xff, 0x8d, 0x00 + }, +}; + +static char SMI_FPR[VIDEO_MODES][88] = { + { /* DUAL_800_600_8 */ + 0x30, 0x36, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03, + 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8, + 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71, + 0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a, + 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00, + 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x44 + }, + { /* DUAL_1024_768_8 */ + 0x30, 0x3a, 0x31, 0x83, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00, + 0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, + 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x41, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x25, + 0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2, + 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00, + 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x44 + }, + { /* SINGLE_800_600_8 */ + 0x30, 0x36, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x03, + 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8, + 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x67, 0x55, 0x71, + 0x56, 0x57, 0x57, 0x59, 0x58, 0x03, 0x59, 0x00, 0x5a, 0x4a, + 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00, + 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x44 + }, + { /* SINGLE_1024_768_8 */ + 0x30, 0x3a, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00, + 0x3f, 0x00, 0x40, 0x80, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, + 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x06, 0x51, 0x68, 0x52, 0xa7, 0x53, 0x7f, 0x54, 0x83, 0x55, 0x24, + 0x56, 0xff, 0x57, 0x03, 0x58, 0x04, 0x59, 0x00, 0x5a, 0xc2, + 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00, + 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x44 + }, + { /* SINGLE_1280_1024_8 */ + 0x30, 0x3e, 0x31, 0x82, 0x32, 0x38, 0x33, 0x00, 0x34, 0x40, 0x3e, 0x00, + 0x3f, 0x00, 0x40, 0xa0, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, + 0x45, 0x42, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x11, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x08, 0x51, 0x88, 0x52, 0xd3, 0x53, 0x9f, 0x54, 0xa3, 0x55, 0x2a, + 0x56, 0xff, 0x57, 0x04, 0x58, 0x00, 0x59, 0x00, 0x5a, 0x63, + 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa8, 0x00, 0xa9, 0x00, + 0xaa, 0xdf, 0xab, 0x7f, 0xac, 0x00, 0xad, 0x41, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x44 + }, + { /* TV_MODE_CCIR */ + 0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03, + 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8, + 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73, + 0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b, + 0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05, + 0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x00 + }, + { /* TV_MODE_EIA */ + 0x30, 0x24, 0x31, 0x84, 0x32, 0x20, 0x33, 0x09, 0x34, 0xf0, 0x3e, 0x03, + 0x3f, 0xff, 0x40, 0x64, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0xc8, + 0x45, 0x02, 0x46, 0x00, 0x47, 0xfc, 0x48, 0x20, 0x49, 0x1c, 0x4a, 0x00, + 0x4b, 0xa0, 0x4c, 0x00, + 0x50, 0x04, 0x51, 0x48, 0x52, 0x83, 0x53, 0x63, 0x54, 0x68, 0x55, 0x73, + 0x56, 0x57, 0x57, 0x58, 0x58, 0x04, 0x59, 0x57, 0x5a, 0x7b, + 0xa1, 0x10, 0xa2, 0xab, 0xa3, 0x98, 0xa4, 0xc1, 0xa8, 0x8c, 0xa9, 0x05, + 0xaa, 0x17, 0xab, 0x35, 0xac, 0x41, 0xad, 0x68, 0xae, 0x00, 0xaf, 0x00, + 0xa0, 0x00 + }, +}; + +static char SMI_GCR[18] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x40, + 0x06, 0x05, 0x07, 0x0f, 0x08, 0xff +}; + +/******************************************************************************* +* +* Read SMI ISA register +*/ +static char smiRead (unsigned short index, char reg) +{ + register GraphicDevice *pGD = (GraphicDevice *)&smi; + + out8 ((pGD->isaBase + index), reg); + return (in8 (pGD->isaBase + index + 1)); +} + +/******************************************************************************* +* +* Write SMI ISA register +*/ +static void smiWrite (unsigned short index, char reg, char val) +{ + register GraphicDevice *pGD = (GraphicDevice *)&smi; + + out8 ((pGD->isaBase + index), reg); + out8 ((pGD->isaBase + index + 1), val); +} + +/******************************************************************************* +* +* Write a table of SMI ISA register +*/ +static void smiLoadRegs ( + unsigned int iReg, + unsigned int dReg, + char *regTab, + unsigned int tabSize + ) +{ + register int i; + + for (i=0; i<tabSize; i+=2) + { + out8 (iReg, regTab[i]); + out8 (dReg, regTab[i+1]); + } +} + +/******************************************************************************* +* +* Init capture port registers +*/ +static void smiInitCapturePort (void) +{ + SmiCapturePort smiCP = { 0x01400600, 0x30, 0x40, 480, 640, 0, 0, 2560, 6 }; + register GraphicDevice *pGD = (GraphicDevice *)&smi; + register SmiCapturePort *pCP = (SmiCapturePort *)&smiCP; + + out32r ((pGD->cprBase + 0x0004), ((pCP->topClip<<16) | pCP->leftClip)); + out32r ((pGD->cprBase + 0x0008), ((pCP->srcHeight<<16) | pCP->srcWidth)); + out32r ((pGD->cprBase + 0x000c), pCP->srcBufStart1/8); + out32r ((pGD->cprBase + 0x0010), pCP->srcBufStart2/8); + out32r ((pGD->cprBase + 0x0014), pCP->srcOffset/8); + out32r ((pGD->cprBase + 0x0018), pCP->fifoControl); + out32r ((pGD->cprBase + 0x0000), pCP->control); +} + + +/******************************************************************************* +* +* Init video processor registers +*/ +static void smiInitVideoProcessor (void) +{ + SmiVideoProc smiVP = { 0x100000, 0, 0, 0, 0, 1600, 0x1200543, 4, 0xededed }; + SmiVideoWin smiVW = { 0, 0, 599, 799, 0, 1600, 0, 0, 0 }; + register GraphicDevice *pGD = (GraphicDevice *)&smi; + register SmiVideoProc *pVP = (SmiVideoProc *)&smiVP; + register SmiVideoWin *pVWin = (SmiVideoWin *)&smiVW; + + pVP->width = pGD->plnSizeX * pGD->gdfBytesPP; + pVP->control |= pGD->gdfIndex << 16; + pVWin->bottom = pGD->winSizeY - 1; + pVWin->right = pGD->winSizeX - 1; + pVWin->width = pVP->width; + + /* color key */ + out32r ((pGD->vprBase + 0x0004), pVP->colorKey); + + /* color key mask */ + out32r ((pGD->vprBase + 0x0008), pVP->colorKeyMask); + + /* data src start adrs */ + out32r ((pGD->vprBase + 0x000c), pVP->start / 8); + + /* data width and offset */ + out32r ((pGD->vprBase + 0x0010), + ((pVP->offset / 8 * pGD->gdfBytesPP) << 16) | + (pGD->plnSizeX / 8 * pGD->gdfBytesPP)); + + /* video window 1 */ + out32r ((pGD->vprBase + 0x0014), + ((pVWin->top << 16) | pVWin->left)); + + out32r ((pGD->vprBase + 0x0018), + ((pVWin->bottom << 16) | pVWin->right)); + + out32r ((pGD->vprBase + 0x001c), pVWin->srcStart / 8); + + out32r ((pGD->vprBase + 0x0020), + (((pVWin->offset / 8) << 16) | (pVWin->width / 8))); + + out32r ((pGD->vprBase + 0x0024), + (((pVWin->hStretch) << 8) | pVWin->vStretch)); + + /* video window 2 */ + out32r ((pGD->vprBase + 0x0028), + ((pVWin->top << 16) | pVWin->left)); + + out32r ((pGD->vprBase + 0x002c), + ((pVWin->bottom << 16) | pVWin->right)); + + out32r ((pGD->vprBase + 0x0030), + pVWin->srcStart / 8); + + out32r ((pGD->vprBase + 0x0034), + (((pVWin->offset / 8) << 16) | (pVWin->width / 8))); + + out32r ((pGD->vprBase + 0x0038), + (((pVWin->hStretch) << 8) | pVWin->vStretch)); + + /* fifo prio control */ + out32r ((pGD->vprBase + 0x0054), pVP->fifoPrio); + + /* fifo empty request levell */ + out32r ((pGD->vprBase + 0x0058), pVP->fifoERL); + + /* conversion constant */ + out32r ((pGD->vprBase + 0x005c), pVP->YUVtoRGB); + + /* vpr control word */ + out32r ((pGD->vprBase + 0x0000), pVP->control); +} + +/****************************************************************************** + * + * Init drawing engine registers + */ +static void smiInitDrawingEngine (void) +{ + GraphicDevice *pGD = (GraphicDevice *)&smi; + unsigned int val; + + /* don't start now */ + out32r ((pGD->dprBase + 0x000c), 0x000f0000); + + /* set rop2 to copypen */ + val = 0xffff3ff0 & in32r ((pGD->dprBase + 0x000c)); + out32r ((pGD->dprBase + 0x000c), (val | 0x8000 | 0x0c)); + + /* set clip rect */ + out32r ((pGD->dprBase + 0x002c), 0); + out32r ((pGD->dprBase + 0x0030), + ((pGD->winSizeY<<16) | pGD->winSizeX * pGD->gdfBytesPP )); + + /* src row pitch */ + val = 0xffff0000 & (in32r ((pGD->dprBase + 0x0010))); + out32r ((pGD->dprBase + 0x0010), + (val | pGD->plnSizeX * pGD->gdfBytesPP)); + + /* dst row pitch */ + val = 0x0000ffff & (in32r ((pGD->dprBase + 0x0010))); + out32r ((pGD->dprBase + 0x0010), + (((pGD->plnSizeX * pGD->gdfBytesPP)<<16) | val)); + + /* window width src/dst */ + out32r ((pGD->dprBase + 0x003c), + (((pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff)<<16) | + (pGD->plnSizeX * pGD->gdfBytesPP & 0x0fff))); + out16r ((pGD->dprBase + 0x001e), 0x0000); + + /* src base adrs */ + out32r ((pGD->dprBase + 0x0040), + (((pGD->frameAdrs/8) & 0x000fffff))); + + /* dst base adrs */ + out32r ((pGD->dprBase + 0x0044), + (((pGD->frameAdrs/8) & 0x000fffff))); + + /* foreground color */ + out32r ((pGD->dprBase + 0x0014), pGD->fg); + + /* background color */ + out32r ((pGD->dprBase + 0x0018), pGD->bg); + + /* xcolor */ + out32r ((pGD->dprBase + 0x0020), 0x00ffffff); + + /* xcolor mask */ + out32r ((pGD->dprBase + 0x0024), 0x00ffffff); + + /* bit mask */ + out32r ((pGD->dprBase + 0x0028), 0x00ffffff); + + /* load mono pattern */ + out32r ((pGD->dprBase + 0x0034), 0); + out32r ((pGD->dprBase + 0x0038), 0); +} + +static struct pci_device_id supported[] = { + { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_710 }, + { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_712 }, + { PCI_VENDOR_ID_SMI, PCI_DEVICE_ID_SMI_810 }, + { } +}; + + +/******************************************************************************* +* +* Init video chip with common Linux graphic modes (lilo) +*/ +void *video_hw_init (void) +{ + GraphicDevice *pGD = (GraphicDevice *)&smi; + unsigned short device_id; + pci_dev_t devbusfn; + int videomode; + unsigned int pci_mem_base, *vm, i; + unsigned int gdfTab[] = { 1, 2, 2, 4, 3, 1 }; + char *penv; + char *gdfModes[] = + { + "8 Bit Index Color", + "15 Bit 5-5-5 RGB", + "16 Bit 5-6-5 RGB", + "32 Bit X-8-8-8 RGB", + "24 Bit 8-8-8 RGB", + "8 Bit 3-3-2 RGB" + }; + int vgaModes[16][2] = + { + {769, -1}, {771, 0x00002}, {773, 0x00003}, {775, 0x00004}, + {784, -1}, {787, 0x10002}, {790, 0x10003}, {793, 0x10004}, + {785, -1}, {788, 0x20002}, {791, 0x20003}, {794, 0x20004}, + {786, -1}, {789, 0x40002}, {792, 0x40003}, {795, 0x40004} + }; + + /* Search for video chip */ + printf("Video: "); + + if ((devbusfn = pci_find_devices(supported, 0)) < 0) + { + printf ("Controller not found !\n"); + return (NULL); + } + + /* PCI setup */ + pci_write_config_dword (devbusfn, PCI_COMMAND, (PCI_COMMAND_MEMORY | PCI_COMMAND_IO)); + pci_read_config_word (devbusfn, PCI_DEVICE_ID, &device_id); + pci_read_config_dword (devbusfn, PCI_BASE_ADDRESS_0, &pci_mem_base); + pci_mem_base = pci_mem_to_phys (devbusfn, pci_mem_base); + + /* Initialize the video controller */ + if ((penv = getenv ("videomode")) != NULL) + videomode = (int)simple_strtoul (penv, NULL, 16); + else + videomode = 0x303; /* Default 800x600 8 bit index color */ + + /* Compare with common vga mode numbers */ + for (i=0; i<16; i++) + { + if (vgaModes[i][0] == videomode) + { + if (vgaModes[i][1] == -1) + { + printf("Videomode not supported !\n"); + return (NULL); /* mode not supported */ + } + pGD->mode = vgaModes[i][1]; /* use driver int. mode number */ + break; + } + } + + /* Extract graphic data format */ + pGD->gdfIndex = (pGD->mode & 0x00070000) >> 16; + if (pGD->gdfIndex > 5) + pGD->gdfIndex = 0; + pGD->gdfBytesPP = gdfTab[pGD->gdfIndex]; + + /* Extract graphic resolution */ + pGD->mode &= 0xf; + + /* Exit for not supported resolutions */ + if (((pGD->mode==DUAL_800_600) || (pGD->mode==DUAL_1024_768)) && (pGD->gdfBytesPP > 1)) + { + printf ("Dual screen for 1BPP only !\n"); + return (NULL); + } + + if ((pGD->mode==SINGLE_1280_1024) && (pGD->gdfBytesPP==4)) + { + printf ("Out of memory !\n"); + return (NULL); + } + + /* Set graphic parameters */ + switch (pGD->mode) + { + case DUAL_800_600: + pGD->winSizeX = 800; + pGD->winSizeY = 600; + pGD->plnSizeX = 1600; + pGD->plnSizeY = 600; + sprintf (pGD->modeIdent, "Dual Screen 800x600 with %s", gdfModes[pGD->gdfIndex]); + break; + case DUAL_1024_768: + pGD->winSizeX = 1024; + pGD->winSizeY = 768; + pGD->plnSizeX = 2048; + pGD->plnSizeY = 768; + sprintf (pGD->modeIdent, "Dual Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]); + break; + case SINGLE_800_600: + pGD->winSizeX = 800; + pGD->winSizeY = 600; + pGD->plnSizeX = 800; + pGD->plnSizeY = 600; + sprintf (pGD->modeIdent, "Single Screen 800x600 with %s", gdfModes[pGD->gdfIndex]); + break; + case SINGLE_1024_768: + pGD->winSizeX = 1024; + pGD->winSizeY = 768; + pGD->plnSizeX = 1024; + pGD->plnSizeY = 768; + sprintf (pGD->modeIdent,"Single Screen 1024x768 with %s", gdfModes[pGD->gdfIndex]); + break; + case TV_MODE_CCIR: + pGD->winSizeX = 720; + pGD->winSizeY = 576; + pGD->plnSizeX = 720; + pGD->plnSizeY = 576; + sprintf (pGD->modeIdent, "TV Mode CCIR with %s", gdfModes[pGD->gdfIndex]); + break; + case TV_MODE_EIA: + pGD->winSizeX = 720; + pGD->winSizeY = 484; + pGD->plnSizeX = 720; + pGD->plnSizeY = 484; + sprintf (pGD->modeIdent, "TV Mode EIA with %s", gdfModes[pGD->gdfIndex]); + break; + case SINGLE_1280_1024: + pGD->winSizeX = 1280; + pGD->winSizeY = 1024; + pGD->plnSizeX = 1280; + pGD->plnSizeY = 1024; + sprintf (pGD->modeIdent, "Single Screen 1280x1024 with %s", gdfModes[pGD->gdfIndex]); + break; + default: + printf("Videomode not supported !\n"); + return (NULL); + } + + + pGD->isaBase = CFG_ISA_IO; + pGD->pciBase = pci_mem_base; + pGD->dprBase = (pci_mem_base + 0x400000 + 0x8000); + pGD->vprBase = (pci_mem_base + 0x400000 + 0xc000); + pGD->cprBase = (pci_mem_base + 0x400000 + 0xe000); + pGD->frameAdrs = pci_mem_base; + pGD->memSize = VIDEO_MEM_SIZE; + + /* Turn off display */ + smiWrite (0x3c4, 0x01, 0x20); + + /* Unlock ext. crt regs */ + out8 (SMI_LOCK_REG, 0x40); + + /* Set Register base to isa 3dx for 3?x regs (color mode) */ + out8 (SMI_MISC_REG, 0x2b); + + /* Unlock crt regs 0-7 */ + smiWrite (0x3d4, 0x11, 0x0e); + + /* Sytem Control Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_SCR, sizeof(SMI_SCR)); + + /* extented CRT Register */ + smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, + SMI_EXT_CRT[pGD->mode], sizeof(SMI_EXT_CRT)/VIDEO_MODES); + + /* Sequencer Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_SEQR, sizeof(SMI_SEQR)); + + /* Power Control Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_PCR[pGD->mode], sizeof(SMI_PCR)/VIDEO_MODES); + + /* Memory Control Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_MCR[pGD->mode], sizeof(SMI_MCR)/VIDEO_MODES); + + /* Clock Control Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_CCR[pGD->mode], sizeof(SMI_CCR)/VIDEO_MODES); + + /* Shadow VGA Register */ + smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, + SMI_SHVGA[pGD->mode], sizeof(SMI_SHVGA)/VIDEO_MODES); + + /* General Purpose Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_GPR[pGD->mode], sizeof(SMI_GPR)/VIDEO_MODES); + + /* Hardware Cusor Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_HCR[pGD->mode], sizeof(SMI_HCR)/VIDEO_MODES); + + /* Flat Panel Register */ + smiLoadRegs (SMI_INDX_C4, SMI_DATA_C5, + SMI_FPR[pGD->mode], sizeof(SMI_FPR)/VIDEO_MODES); + + /* CRTC Register */ + smiLoadRegs (SMI_INDX_D4, SMI_DATA_D5, + SMI_CRTCR[pGD->mode], sizeof(SMI_CRTCR)/VIDEO_MODES); + + /* Graphics Controller Register */ + smiLoadRegs (SMI_INDX_CE, SMI_DATA_CF, + SMI_GCR, sizeof(SMI_GCR)); + + /* Patch memory and refresh settings for SMI710 */ + if (device_id == PCI_DEVICE_ID_SMI_710) + { + unsigned char reg = smiRead (0x3c4, 0x62); + + /* external memory disabled */ + smiWrite (0x3c4, 0x62, (reg & 0xfb)); + /* memory clock */ + smiWrite (0x3c4, 0x6a, 0x75); + } + + /* Patch memory and refresh settings for SMI712 */ + if (device_id == PCI_DEVICE_ID_SMI_712) + { + unsigned char reg = smiRead (0x3c4, 0x62); + + /* IL runs at MCLK; 64bit bus; external memory disabled */ + smiWrite (0x3c4, 0x62, (reg | 0xc4)); + /* memory clock */ + smiWrite (0x3c4, 0x6a, 0x80); + } + + /* Patch clock settings for SMI810 */ + if (device_id == PCI_DEVICE_ID_SMI_810) + { + /* clock control */ + smiWrite (0x3c4, 0x69, 0x03); + } + + /* Video processor default setup */ + smiInitVideoProcessor (); + + /* Capture port default setup */ + smiInitCapturePort (); + + /* Drawing engine default setup */ + smiInitDrawingEngine (); + + /* Turn on display */ + smiWrite (0x3c4, 0x01, 0x01); + + /* Clear video memory */ + i = pGD->memSize/4; + vm = (unsigned int *)pGD->pciBase; + while(i--) + *vm++ = 0; + + printf("mode=%x - %s\n", videomode, pGD->modeIdent); + return ((void*)&smi); +} + +/******************************************************************************* +* +* Drawing engine fill on screen region +*/ +void video_hw_rectfill ( + unsigned int bpp, /* bytes per pixel */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y, /* frame height */ + unsigned int color /* fill color */ + ) +{ + register GraphicDevice *pGD = (GraphicDevice *)&smi; + register unsigned int control; + + dim_x *= bpp; + + out32r ((pGD->dprBase + 0x0014), color); + out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y)); + out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y)); + + control = 0x0000ffff & in32r ((pGD->dprBase + 0x000c)); + + control |= 0x80010000; + + out32r ((pGD->dprBase + 0x000c), control); + + /* Wait for drawing processor */ + do + { + out8 ((pGD->isaBase + 0x3c4), 0x16); + } while (in8 (pGD->isaBase + 0x3c5) & 0x08); +} + +/******************************************************************************* +* +* Drawing engine bitblt with screen region +*/ +void video_hw_bitblt ( + unsigned int bpp, /* bytes per pixel */ + unsigned int src_x, /* source pos x */ + unsigned int src_y, /* source pos y */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y /* frame height */ + ) +{ + register GraphicDevice *pGD = (GraphicDevice *)&smi; + register unsigned int control; + + dim_x *= bpp; + + if ((src_y<dst_y) || ((src_y==dst_y) && (src_x<dst_x))) + { + out32r ((pGD->dprBase + 0x0000), (((src_x+dim_x-1)<<16) | (src_y+dim_y-1))); + out32r ((pGD->dprBase + 0x0004), (((dst_x+dim_x-1)<<16) | (dst_y+dim_y-1))); + control = 0x88000000; + } + else + { + out32r ((pGD->dprBase + 0x0000), ((src_x<<16) | src_y)); + out32r ((pGD->dprBase + 0x0004), ((dst_x<<16) | dst_y)); + control = 0x80000000; + } + + out32r ((pGD->dprBase + 0x0008), ((dim_x<<16) | dim_y)); + control |= (0x0000ffff & in32r ((pGD->dprBase + 0x000c))); + out32r ((pGD->dprBase + 0x000c), control); + + /* Wait for drawing processor */ + do + { + out8 ((pGD->isaBase + 0x3c4), 0x16); + } while (in8 (pGD->isaBase + 0x3c5) & 0x08); +} + +/******************************************************************************* +* +* Set a RGB color in the LUT (8 bit index) +*/ +void video_set_lut ( + unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ) +{ + register GraphicDevice *pGD = (GraphicDevice *)&smi; + + out8 (SMI_LUT_MASK, 0xff); + + out8 (SMI_LUT_START, (char)index); + + out8 (SMI_LUT_RGB, r>>2); /* red */ + udelay (10); + out8 (SMI_LUT_RGB, g>>2); /* green */ + udelay (10); + out8 (SMI_LUT_RGB, b>>2); /* blue */ + udelay (10); +} + +#endif /* CONFIG_VIDEO_SMI_LYNXEM */ diff --git a/drivers/tigon3.c b/drivers/tigon3.c new file mode 100644 index 0000000..5883744 --- /dev/null +++ b/drivers/tigon3.c @@ -0,0 +1,6222 @@ +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/******************************************************************************/ +#include <common.h> +#include "bcm570x_mm.h" +#include <asm/types.h> +#if (CONFIG_COMMANDS & CFG_CMD_NET) && !defined(CONFIG_NET_MULTI) && \ + defined(CONFIG_TIGON3) +#ifdef CONFIG_BMW +#include <mpc824x.h> +#endif +#include <malloc.h> +#include <linux/byteorder/big_endian.h> + +#define EMBEDDED 1 +/******************************************************************************/ +/* Local functions. */ +/******************************************************************************/ + +LM_STATUS LM_Abort(PLM_DEVICE_BLOCK pDevice); +LM_STATUS LM_QueueRxPackets(PLM_DEVICE_BLOCK pDevice); + +static LM_STATUS LM_TranslateRequestedMediaType( + LM_REQUESTED_MEDIA_TYPE RequestedMediaType, + PLM_MEDIA_TYPE pMediaType, PLM_LINE_SPEED pLineSpeed, + PLM_DUPLEX_MODE pDuplexMode); + +static LM_STATUS LM_InitBcm540xPhy(PLM_DEVICE_BLOCK pDevice); + +__inline static LM_VOID LM_ServiceRxInterrupt(PLM_DEVICE_BLOCK pDevice); +__inline static LM_VOID LM_ServiceTxInterrupt(PLM_DEVICE_BLOCK pDevice); + +static LM_STATUS LM_ForceAutoNegBcm540xPhy(PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType); +static LM_STATUS LM_ForceAutoNeg(PLM_DEVICE_BLOCK pDevice, + LM_REQUESTED_MEDIA_TYPE RequestedMediaType); +static LM_UINT32 GetPhyAdFlowCntrlSettings(PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_SetFlowControl(PLM_DEVICE_BLOCK pDevice, + LM_UINT32 LocalPhyAd, LM_UINT32 RemotePhyAd); +#if INCLUDE_TBI_SUPPORT +STATIC LM_STATUS LM_SetupFiberPhy(PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_InitBcm800xPhy(PLM_DEVICE_BLOCK pDevice); +#endif +STATIC LM_STATUS LM_SetupCopperPhy(PLM_DEVICE_BLOCK pDevice); +STATIC PLM_ADAPTER_INFO LM_GetAdapterInfoBySsid(LM_UINT16 Svid, LM_UINT16 Ssid); +STATIC LM_STATUS LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, + LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize); +STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number); +STATIC LM_STATUS LM_ResetChip(PLM_DEVICE_BLOCK pDevice); +STATIC LM_STATUS LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket, + PT3_SND_BD pSendBd); + +/******************************************************************************/ +/* External functions. */ +/******************************************************************************/ + +LM_STATUS LM_LoadRlsFirmware(PLM_DEVICE_BLOCK pDevice); + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_UINT32 +LM_RegRdInd( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 Register) { + LM_UINT32 Value32; + +#if PCIX_TARGET_WORKAROUND + MM_ACQUIRE_UNDI_LOCK(pDevice); +#endif + MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register); + MM_ReadConfig32(pDevice, T3_PCI_REG_DATA_REG, &Value32); +#if PCIX_TARGET_WORKAROUND + MM_RELEASE_UNDI_LOCK(pDevice); +#endif + + return Value32; +} /* LM_RegRdInd */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_RegWrInd( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 Register, +LM_UINT32 Value32) { + +#if PCIX_TARGET_WORKAROUND + MM_ACQUIRE_UNDI_LOCK(pDevice); +#endif + MM_WriteConfig32(pDevice, T3_PCI_REG_ADDR_REG, Register); + MM_WriteConfig32(pDevice, T3_PCI_REG_DATA_REG, Value32); +#if PCIX_TARGET_WORKAROUND + MM_RELEASE_UNDI_LOCK(pDevice); +#endif +} /* LM_RegWrInd */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_UINT32 +LM_MemRdInd( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 MemAddr) { + LM_UINT32 Value32; + + MM_ACQUIRE_UNDI_LOCK(pDevice); +#ifdef BIG_ENDIAN_HOST + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + Value32 = REG_RD(pDevice, PciCfg.MemWindowData); + /* Value32 = REG_RD(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4]); */ +#else + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + MM_ReadConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, &Value32); +#endif + MM_RELEASE_UNDI_LOCK(pDevice); + + return Value32; +} /* LM_MemRdInd */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_MemWrInd( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 MemAddr, +LM_UINT32 Value32) { + MM_ACQUIRE_UNDI_LOCK(pDevice); +#ifdef BIG_ENDIAN_HOST + REG_WR(pDevice,PciCfg.MemWindowBaseAddr,MemAddr); + REG_WR(pDevice,uIntMem.Mbuf[(MemAddr & 0x7fff)/4],Value32); +#else + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, MemAddr); + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, Value32); +#endif + MM_RELEASE_UNDI_LOCK(pDevice); +} /* LM_MemWrInd */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_QueueRxPackets( +PLM_DEVICE_BLOCK pDevice) { + LM_STATUS Lmstatus; + PLM_PACKET pPacket; + PT3_RCV_BD pRcvBd; + LM_UINT32 StdBdAdded = 0; +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + LM_UINT32 JumboBdAdded = 0; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + Lmstatus = LM_STATUS_SUCCESS; + + pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container); + while(pPacket) { + switch(pPacket->u.Rx.RcvProdRing) { +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + case T3_JUMBO_RCV_PROD_RING: /* Jumbo Receive Ring. */ + /* Initialize the buffer descriptor. */ + pRcvBd = + &pDevice->pRxJumboBdVirt[pDevice->RxJumboProdIdx]; + pRcvBd->Flags = RCV_BD_FLAG_END | RCV_BD_FLAG_JUMBO_RING; + pRcvBd->Len = (LM_UINT16) pDevice->RxJumboBufferSize; + + /* Initialize the receive buffer pointer */ +#if 0 /* Jimmy, deleted in new */ + pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; + pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; +#endif + MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr); + + /* The opaque field may point to an offset from a fix addr. */ + pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) - + MM_UINT_PTR(pDevice->pPacketDescBase)); + + /* Update the producer index. */ + pDevice->RxJumboProdIdx = (pDevice->RxJumboProdIdx + 1) & + T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; + + JumboBdAdded++; + break; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + case T3_STD_RCV_PROD_RING: /* Standard Receive Ring. */ + /* Initialize the buffer descriptor. */ + pRcvBd = &pDevice->pRxStdBdVirt[pDevice->RxStdProdIdx]; + pRcvBd->Flags = RCV_BD_FLAG_END; + pRcvBd->Len = MAX_STD_RCV_BUFFER_SIZE; + + /* Initialize the receive buffer pointer */ +#if 0 /* Jimmy, deleted in new replaced with MM_MapRxDma */ + pRcvBd->HostAddr.Low = pPacket->u.Rx.RxBufferPhy.Low; + pRcvBd->HostAddr.High = pPacket->u.Rx.RxBufferPhy.High; +#endif + MM_MapRxDma(pDevice, pPacket, &pRcvBd->HostAddr); + + /* The opaque field may point to an offset from a fix addr. */ + pRcvBd->Opaque = (LM_UINT32) (MM_UINT_PTR(pPacket) - + MM_UINT_PTR(pDevice->pPacketDescBase)); + + /* Update the producer index. */ + pDevice->RxStdProdIdx = (pDevice->RxStdProdIdx + 1) & + T3_STD_RCV_RCB_ENTRY_COUNT_MASK; + + StdBdAdded++; + break; + + case T3_UNKNOWN_RCV_PROD_RING: + default: + Lmstatus = LM_STATUS_FAILURE; + break; + } /* switch */ + + /* Bail out if there is any error. */ + if(Lmstatus != LM_STATUS_SUCCESS) + { + break; + } + + pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container); + } /* while */ + + wmb(); + /* Update the procedure index. */ + if(StdBdAdded) + { + MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, pDevice->RxStdProdIdx); + } +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + if(JumboBdAdded) + { + MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, + pDevice->RxJumboProdIdx); + } +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + return Lmstatus; +} /* LM_QueueRxPackets */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_VOID +LM_NvramInit( + PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + /* Intialize clock period and state machine. */ + Value32 = SEEPROM_ADDR_CLK_PERD(SEEPROM_CLOCK_PERIOD) | + SEEPROM_ADDR_FSM_RESET; + REG_WR(pDevice, Grc.EepromAddr, Value32); + + for(j = 0; j < 100; j++) + { + MM_Wait(10); + } + + /* Serial eeprom access using the Grc.EepromAddr/EepromData registers. */ + Value32 = REG_RD(pDevice, Grc.LocalCtrl); + REG_WR(pDevice, Grc.LocalCtrl, Value32 | GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM); + + /* Set the 5701 compatibility mode if we are using EEPROM. */ + if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) + { + Value32 = REG_RD(pDevice, Nvram.Config1); + if((Value32 & FLASH_INTERFACE_ENABLE) == 0) + { + /* Use the new interface to read EEPROM. */ + Value32 &= ~FLASH_COMPAT_BYPASS; + + REG_WR(pDevice, Nvram.Config1, Value32); + } + } +} /* LM_NvRamInit */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_EepromRead( + PLM_DEVICE_BLOCK pDevice, + LM_UINT32 Offset, + LM_UINT32 *pData) +{ + LM_UINT32 Value32; + LM_UINT32 Addr; + LM_UINT32 Dev; + LM_UINT32 j; + + if(Offset > SEEPROM_CHIP_SIZE) + { + return LM_STATUS_FAILURE; + } + + Dev = Offset / SEEPROM_CHIP_SIZE; + Addr = Offset % SEEPROM_CHIP_SIZE; + + Value32 = REG_RD(pDevice, Grc.EepromAddr); + Value32 &= ~(SEEPROM_ADDR_ADDRESS_MASK | SEEPROM_ADDR_DEV_ID_MASK | + SEEPROM_ADDR_RW_MASK); + REG_WR(pDevice, Grc.EepromAddr, Value32 | SEEPROM_ADDR_DEV_ID(Dev) | + SEEPROM_ADDR_ADDRESS(Addr) | SEEPROM_ADDR_START | SEEPROM_ADDR_READ); + + for(j = 0; j < 1000; j++) + { + Value32 = REG_RD(pDevice, Grc.EepromAddr); + if(Value32 & SEEPROM_ADDR_COMPLETE) + { + break; + } + MM_Wait(10); + } + + if(Value32 & SEEPROM_ADDR_COMPLETE) + { + Value32 = REG_RD(pDevice, Grc.EepromData); + *pData = Value32; + + return LM_STATUS_SUCCESS; + } + + return LM_STATUS_FAILURE; +} /* LM_EepromRead */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_NvramRead( + PLM_DEVICE_BLOCK pDevice, + LM_UINT32 Offset, + LM_UINT32 *pData) +{ + LM_UINT32 Value32; + LM_STATUS Status; + LM_UINT32 j; + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Status = LM_EepromRead(pDevice, Offset, pData); + } + else + { + /* Determine if we have flash or EEPROM. */ + Value32 = REG_RD(pDevice, Nvram.Config1); + if(Value32 & FLASH_INTERFACE_ENABLE) + { + if(Value32 & FLASH_SSRAM_BUFFERRED_MODE) + { + Offset = ((Offset/BUFFERED_FLASH_PAGE_SIZE) << + BUFFERED_FLASH_PAGE_POS) + + (Offset % BUFFERED_FLASH_PAGE_SIZE); + } + } + + REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); + for (j = 0; j < 1000; j++) + { + if (REG_RD(pDevice, Nvram.SwArb) & SW_ARB_GNT1) + { + break; + } + MM_Wait(20); + } + if (j == 1000) + { + return LM_STATUS_FAILURE; + } + + /* Read from flash or EEPROM with the new 5703/02 interface. */ + REG_WR(pDevice, Nvram.Addr, Offset & NVRAM_ADDRESS_MASK); + + REG_WR(pDevice, Nvram.Cmd, NVRAM_CMD_RD | NVRAM_CMD_DO_IT | + NVRAM_CMD_FIRST | NVRAM_CMD_LAST | NVRAM_CMD_DONE); + + /* Wait for the done bit to clear. */ + for(j = 0; j < 500; j++) + { + MM_Wait(10); + + Value32 = REG_RD(pDevice, Nvram.Cmd); + if(!(Value32 & NVRAM_CMD_DONE)) + { + break; + } + } + + /* Wait for the done bit. */ + if(!(Value32 & NVRAM_CMD_DONE)) + { + for(j = 0; j < 500; j++) + { + MM_Wait(10); + + Value32 = REG_RD(pDevice, Nvram.Cmd); + if(Value32 & NVRAM_CMD_DONE) + { + MM_Wait(10); + + *pData = REG_RD(pDevice, Nvram.ReadData); + + /* Change the endianess. */ + *pData = ((*pData & 0xff) << 24)| ((*pData & 0xff00) << 8)| + ((*pData & 0xff0000) >> 8) | ((*pData >> 24) & 0xff); + + break; + } + } + } + + REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_CLR1); + if(Value32 & NVRAM_CMD_DONE) + { + Status = LM_STATUS_SUCCESS; + } + else + { + Status = LM_STATUS_FAILURE; + } + } + + return Status; +} /* LM_NvramRead */ + + +STATIC void +LM_ReadVPD(PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Vpd_arr[256/4]; + LM_UINT8 *Vpd = (LM_UINT8 *) &Vpd_arr[0]; + LM_UINT32 *Vpd_dptr = &Vpd_arr[0]; + LM_UINT32 Value32; + unsigned int j; + + /* Read PN from VPD */ + for (j = 0; j < 256; j += 4, Vpd_dptr++ ) + { + if (LM_NvramRead(pDevice, 0x100 + j, &Value32) != LM_STATUS_SUCCESS) { + printf("BCM570x: LM_ReadVPD: VPD read failed" + " (no EEPROM onboard)\n"); + return; + } + *Vpd_dptr = cpu_to_le32(Value32); + } + for (j = 0; j < 256; ) + { + unsigned int Vpd_r_len; + unsigned int Vpd_r_end; + + if ((Vpd[j] == 0x82) || (Vpd[j] == 0x91)) + { + j = j + 3 + Vpd[j + 1] + (Vpd[j + 2] << 8); + } + else if (Vpd[j] == 0x90) + { + Vpd_r_len = Vpd[j + 1] + (Vpd[j + 2] << 8); + j += 3; + Vpd_r_end = Vpd_r_len + j; + while (j < Vpd_r_end) + { + if ((Vpd[j] == 'P') && (Vpd[j + 1] == 'N')) + { + unsigned int len = Vpd[j + 2]; + + if (len <= 24) + { + memcpy(pDevice->PartNo, &Vpd[j + 3], len); + } + break; + } + else + { + if (Vpd[j + 2] == 0) + { + break; + } + j = j + Vpd[j + 2]; + } + } + break; + } + else { + break; + } + } +} + +STATIC void +LM_ReadBootCodeVersion(PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32, offset, ver_offset; + int i; + + if (LM_NvramRead(pDevice, 0x0, &Value32) != LM_STATUS_SUCCESS) + return; + if (Value32 != 0xaa559966) + return; + if (LM_NvramRead(pDevice, 0xc, &offset) != LM_STATUS_SUCCESS) + return; + + offset = ((offset & 0xff) << 24)| ((offset & 0xff00) << 8)| + ((offset & 0xff0000) >> 8) | ((offset >> 24) & 0xff); + if (LM_NvramRead(pDevice, offset, &Value32) != LM_STATUS_SUCCESS) + return; + if ((Value32 == 0x0300000e) && + (LM_NvramRead(pDevice, offset + 4, &Value32) == LM_STATUS_SUCCESS) && + (Value32 == 0)) { + + if (LM_NvramRead(pDevice, offset + 8, &ver_offset) != LM_STATUS_SUCCESS) + return; + ver_offset = ((ver_offset & 0xff0000) >> 8) | + ((ver_offset >> 24) & 0xff); + for (i = 0; i < 16; i += 4) { + if (LM_NvramRead(pDevice, offset + ver_offset + i, &Value32) != + LM_STATUS_SUCCESS) + { + return; + } + *((LM_UINT32 *) &pDevice->BootCodeVer[i]) = cpu_to_le32(Value32); + } + } + else { + char c; + + if (LM_NvramRead(pDevice, 0x94, &Value32) != LM_STATUS_SUCCESS) + return; + + i = 0; + c = ((Value32 & 0xff0000) >> 16); + + if (c < 10) { + pDevice->BootCodeVer[i++] = c + '0'; + } + else { + pDevice->BootCodeVer[i++] = (c / 10) + '0'; + pDevice->BootCodeVer[i++] = (c % 10) + '0'; + } + pDevice->BootCodeVer[i++] = '.'; + c = (Value32 & 0xff000000) >> 24; + if (c < 10) { + pDevice->BootCodeVer[i++] = c + '0'; + } + else { + pDevice->BootCodeVer[i++] = (c / 10) + '0'; + pDevice->BootCodeVer[i++] = (c % 10) + '0'; + } + pDevice->BootCodeVer[i] = 0; + } +} + +STATIC void +LM_GetBusSpeed(PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 PciState = pDevice->PciState; + LM_UINT32 ClockCtrl; + char *SpeedStr = ""; + + if (PciState & T3_PCI_STATE_32BIT_PCI_BUS) + { + strcpy(pDevice->BusSpeedStr, "32-bit "); + } + else + { + strcpy(pDevice->BusSpeedStr, "64-bit "); + } + if (PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) + { + strcat(pDevice->BusSpeedStr, "PCI "); + if (PciState & T3_PCI_STATE_HIGH_BUS_SPEED) + { + SpeedStr = "66MHz"; + } + else + { + SpeedStr = "33MHz"; + } + } + else + { + strcat(pDevice->BusSpeedStr, "PCIX "); + if (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE) + { + SpeedStr = "133MHz"; + } + else + { + ClockCtrl = REG_RD(pDevice, PciCfg.ClockCtrl) & 0x1f; + switch (ClockCtrl) + { + case 0: + SpeedStr = "33MHz"; + break; + + case 2: + SpeedStr = "50MHz"; + break; + + case 4: + SpeedStr = "66MHz"; + break; + + case 6: + SpeedStr = "100MHz"; + break; + + case 7: + SpeedStr = "133MHz"; + break; + } + } + } + strcat(pDevice->BusSpeedStr, SpeedStr); +} + +/******************************************************************************/ +/* Description: */ +/* This routine initializes default parameters and reads the PCI */ +/* configurations. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_GetAdapterInfo( +PLM_DEVICE_BLOCK pDevice) +{ + PLM_ADAPTER_INFO pAdapterInfo; + LM_UINT32 Value32; + LM_STATUS Status; + LM_UINT32 j; + LM_UINT32 EeSigFound; + LM_UINT32 EePhyTypeSerdes = 0; + LM_UINT32 EePhyLedMode = 0; + LM_UINT32 EePhyId = 0; + + /* Get Device Id and Vendor Id */ + Status = MM_ReadConfig32(pDevice, PCI_VENDOR_ID_REG, &Value32); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + pDevice->PciVendorId = (LM_UINT16) Value32; + pDevice->PciDeviceId = (LM_UINT16) (Value32 >> 16); + + /* If we are not getting the write adapter, exit. */ + if((Value32 != T3_PCI_ID_BCM5700) && + (Value32 != T3_PCI_ID_BCM5701) && + (Value32 != T3_PCI_ID_BCM5702) && + (Value32 != T3_PCI_ID_BCM5702x) && + (Value32 != T3_PCI_ID_BCM5702FE) && + (Value32 != T3_PCI_ID_BCM5703) && + (Value32 != T3_PCI_ID_BCM5703x) && + (Value32 != T3_PCI_ID_BCM5704)) + { + return LM_STATUS_FAILURE; + } + + Status = MM_ReadConfig32(pDevice, PCI_REV_ID_REG, &Value32); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + pDevice->PciRevId = (LM_UINT8) Value32; + + /* Get IRQ. */ + Status = MM_ReadConfig32(pDevice, PCI_INT_LINE_REG, &Value32); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + pDevice->Irq = (LM_UINT8) Value32; + + /* Get interrupt pin. */ + pDevice->IntPin = (LM_UINT8) (Value32 >> 8); + + /* Get chip revision id. */ + Status = MM_ReadConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, &Value32); + pDevice->ChipRevId = Value32 >> 16; + + /* Get subsystem vendor. */ + Status = MM_ReadConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, &Value32); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + pDevice->SubsystemVendorId = (LM_UINT16) Value32; + + /* Get PCI subsystem id. */ + pDevice->SubsystemId = (LM_UINT16) (Value32 >> 16); + + /* Get the cache line size. */ + MM_ReadConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, &Value32); + pDevice->CacheLineSize = (LM_UINT8) Value32; + pDevice->SavedCacheLineReg = Value32; + + if(pDevice->ChipRevId != T3_CHIP_ID_5703_A1 && + pDevice->ChipRevId != T3_CHIP_ID_5703_A2 && + pDevice->ChipRevId != T3_CHIP_ID_5704_A0) + { + pDevice->UndiFix = FALSE; + } +#if !PCIX_TARGET_WORKAROUND + pDevice->UndiFix = FALSE; +#endif + /* Map the memory base to system address space. */ + if (!pDevice->UndiFix) + { + Status = MM_MapMemBase(pDevice); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + /* Initialize the memory view pointer. */ + pDevice->pMemView = (PT3_STD_MEM_MAP) pDevice->pMappedMemBase; + } + +#if PCIX_TARGET_WORKAROUND + /* store whether we are in PCI are PCI-X mode */ + pDevice->EnablePciXFix = FALSE; + + MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32); + if((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0) + { + /* Enable PCI-X workaround only if we are running on 5700 BX. */ + if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) + { + pDevice->EnablePciXFix = TRUE; + } + } + if (pDevice->UndiFix) + { + pDevice->EnablePciXFix = TRUE; + } +#endif + /* Bx bug: due to the "byte_enable bug" in PCI-X mode, the power */ + /* management register may be clobbered which may cause the */ + /* BCM5700 to go into D3 state. While in this state, we will */ + /* not have memory mapped register access. As a workaround, we */ + /* need to restore the device to D0 state. */ + MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &Value32); + Value32 |= T3_PM_PME_ASSERTED; + Value32 &= ~T3_PM_POWER_STATE_MASK; + Value32 |= T3_PM_POWER_STATE_D0; + MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, Value32); + + /* read the current PCI command word */ + MM_ReadConfig32(pDevice, PCI_COMMAND_REG, &Value32); + + /* Make sure bus-mastering is enabled. */ + Value32 |= PCI_BUSMASTER_ENABLE; + +#if PCIX_TARGET_WORKAROUND + /* if we are in PCI-X mode, also make sure mem-mapping and SERR#/PERR# + are enabled */ + if (pDevice->EnablePciXFix == TRUE) { + Value32 |= (PCI_MEM_SPACE_ENABLE | PCI_SYSTEM_ERROR_ENABLE | + PCI_PARITY_ERROR_ENABLE); + } + if (pDevice->UndiFix) + { + Value32 &= ~PCI_MEM_SPACE_ENABLE; + } + +#endif + + if(pDevice->EnableMWI) + { + Value32 |= PCI_MEMORY_WRITE_INVALIDATE; + } + else { + Value32 &= (~PCI_MEMORY_WRITE_INVALIDATE); + } + + /* Error out if mem-mapping is NOT enabled for PCI systems */ + if (!(Value32 | PCI_MEM_SPACE_ENABLE)) + { + return LM_STATUS_FAILURE; + } + + /* save the value we are going to write into the PCI command word */ + pDevice->PciCommandStatusWords = Value32; + + Status = MM_WriteConfig32(pDevice, PCI_COMMAND_REG, Value32); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + + /* Set power state to D0. */ + LM_SetPowerState(pDevice, LM_POWER_STATE_D0); + +#ifdef BIG_ENDIAN_PCI + pDevice->MiscHostCtrl = + MISC_HOST_CTRL_MASK_PCI_INT | + MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | + MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | + MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; +#else /* No CPU Swap modes for PCI IO */ + + /* Setup the mode registers. */ + pDevice->MiscHostCtrl = + MISC_HOST_CTRL_MASK_PCI_INT | + MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP | +#ifdef BIG_ENDIAN_HOST + MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP | +#endif /* BIG_ENDIAN_HOST */ + MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS | + MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW; +#endif /* !BIG_ENDIAN_PCI */ + + /* write to PCI misc host ctr first in order to enable indirect accesses */ + MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl); + + REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl); + +#ifdef BIG_ENDIAN_PCI + Value32 = GRC_MODE_WORD_SWAP_DATA| + GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else +/* No CPU Swap modes for PCI IO */ +#ifdef BIG_ENDIAN_HOST + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; +#endif +#endif /* !BIG_ENDIAN_PCI */ + + REG_WR(pDevice, Grc.Mode, Value32); + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + REG_WR(pDevice, Grc.LocalCtrl, GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1); + } + MM_Wait(40); + + /* Enable indirect memory access */ + REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); + + if (REG_RD(pDevice, PciCfg.ClockCtrl) & T3_PCI_44MHZ_CORE_CLOCK) + { + REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_44MHZ_CORE_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK); + REG_WR(pDevice, PciCfg.ClockCtrl, T3_PCI_SELECT_ALTERNATE_CLOCK); + MM_Wait(40); /* required delay is 27usec */ + } + REG_WR(pDevice, PciCfg.ClockCtrl, 0); + REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0); + +#if PCIX_TARGET_WORKAROUND + MM_ReadConfig32(pDevice, T3_PCI_STATE_REG, &Value32); + if ((pDevice->EnablePciXFix == FALSE) && + ((Value32 & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) == 0)) + { + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B2 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B5) + { + __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x300])); + __raw_writel(0, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301])); + __raw_writel(0xffffffff, &(pDevice->pMemView->uIntMem.MemBlock32K[0x301])); + if (__raw_readl(&(pDevice->pMemView->uIntMem.MemBlock32K[0x300]))) + { + pDevice->EnablePciXFix = TRUE; + } + } + } +#endif +#if 1 + /* + * This code was at the beginning of else block below, but that's + * a bug if node address in shared memory. + */ + MM_Wait(50); + LM_NvramInit(pDevice); +#endif + /* Get the node address. First try to get in from the shared memory. */ + /* If the signature is not present, then get it from the NVRAM. */ + Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_HIGH_MAILBOX); + if((Value32 >> 16) == 0x484b) + { + + pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[1] = (LM_UINT8) Value32; + + Value32 = MEM_RD_OFFSET(pDevice, T3_MAC_ADDR_LOW_MAILBOX); + + pDevice->NodeAddress[2] = (LM_UINT8) (Value32 >> 24); + pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[5] = (LM_UINT8) Value32; + + Status = LM_STATUS_SUCCESS; + } + else + { + Status = LM_NvramRead(pDevice, 0x7c, &Value32); + if(Status == LM_STATUS_SUCCESS) + { + pDevice->NodeAddress[0] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[1] = (LM_UINT8) (Value32 >> 24); + + Status = LM_NvramRead(pDevice, 0x80, &Value32); + + pDevice->NodeAddress[2] = (LM_UINT8) Value32; + pDevice->NodeAddress[3] = (LM_UINT8) (Value32 >> 8); + pDevice->NodeAddress[4] = (LM_UINT8) (Value32 >> 16); + pDevice->NodeAddress[5] = (LM_UINT8) (Value32 >> 24); + } + } + + /* Assign a default address. */ + if(Status != LM_STATUS_SUCCESS) + { +#ifndef EMBEDDED + printk(KERN_ERR "Cannot get MAC addr from NVRAM. Using default.\n"); +#endif + pDevice->NodeAddress[0] = 0x00; pDevice->NodeAddress[1] = 0x10; + pDevice->NodeAddress[2] = 0x18; pDevice->NodeAddress[3] = 0x68; + pDevice->NodeAddress[4] = 0x61; pDevice->NodeAddress[5] = 0x76; + } + + pDevice->PermanentNodeAddress[0] = pDevice->NodeAddress[0]; + pDevice->PermanentNodeAddress[1] = pDevice->NodeAddress[1]; + pDevice->PermanentNodeAddress[2] = pDevice->NodeAddress[2]; + pDevice->PermanentNodeAddress[3] = pDevice->NodeAddress[3]; + pDevice->PermanentNodeAddress[4] = pDevice->NodeAddress[4]; + pDevice->PermanentNodeAddress[5] = pDevice->NodeAddress[5]; + + /* Initialize the default values. */ + pDevice->NoTxPseudoHdrChksum = FALSE; + pDevice->NoRxPseudoHdrChksum = FALSE; + pDevice->NicSendBd = FALSE; + pDevice->TxPacketDescCnt = DEFAULT_TX_PACKET_DESC_COUNT; + pDevice->RxStdDescCnt = DEFAULT_STD_RCV_DESC_COUNT; + pDevice->RxCoalescingTicks = DEFAULT_RX_COALESCING_TICKS; + pDevice->TxCoalescingTicks = DEFAULT_TX_COALESCING_TICKS; + pDevice->RxMaxCoalescedFrames = DEFAULT_RX_MAX_COALESCED_FRAMES; + pDevice->TxMaxCoalescedFrames = DEFAULT_TX_MAX_COALESCED_FRAMES; + pDevice->RxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; + pDevice->TxCoalescingTicksDuringInt = BAD_DEFAULT_VALUE; + pDevice->RxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; + pDevice->TxMaxCoalescedFramesDuringInt = BAD_DEFAULT_VALUE; + pDevice->StatsCoalescingTicks = DEFAULT_STATS_COALESCING_TICKS; + pDevice->EnableMWI = FALSE; + pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + pDevice->DisableAutoNeg = FALSE; + pDevice->PhyIntMode = T3_PHY_INT_MODE_AUTO; + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_AUTO; + pDevice->LedMode = LED_MODE_AUTO; + pDevice->ResetPhyOnInit = TRUE; + pDevice->DelayPciGrant = TRUE; + pDevice->UseTaggedStatus = FALSE; + pDevice->OneDmaAtOnce = BAD_DEFAULT_VALUE; + + pDevice->DmaMbufLowMark = T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO; + pDevice->RxMacMbufLowMark = T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO; + pDevice->MbufHighMark = T3_DEF_MBUF_HIGH_WMARK_JUMBO; + + pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_AUTO; + pDevice->TaskOffloadCap = LM_TASK_OFFLOAD_NONE; + pDevice->FlowControlCap = LM_FLOW_CONTROL_AUTO_PAUSE; + pDevice->EnableTbi = FALSE; +#if INCLUDE_TBI_SUPPORT + pDevice->PollTbiLink = BAD_DEFAULT_VALUE; +#endif + + switch (T3_ASIC_REV(pDevice->ChipRevId)) + { + case T3_ASIC_REV_5704: + pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; + pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE64; + break; + default: + pDevice->MbufBase = T3_NIC_MBUF_POOL_ADDR; + pDevice->MbufSize = T3_NIC_MBUF_POOL_SIZE96; + break; + } + + pDevice->LinkStatus = LM_STATUS_LINK_DOWN; + pDevice->QueueRxPackets = TRUE; + + pDevice->EnableWireSpeed = TRUE; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboDescCnt = DEFAULT_JUMBO_RCV_DESC_COUNT; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Make this is a known adapter. */ + pAdapterInfo = LM_GetAdapterInfoBySsid(pDevice->SubsystemVendorId, + pDevice->SubsystemId); + + pDevice->BondId = REG_RD(pDevice, Grc.MiscCfg) & GRC_MISC_BD_ID_MASK; + if (pDevice->BondId != GRC_MISC_BD_ID_5700 && + pDevice->BondId != GRC_MISC_BD_ID_5701 && + pDevice->BondId != GRC_MISC_BD_ID_5702FE && + pDevice->BondId != GRC_MISC_BD_ID_5703 && + pDevice->BondId != GRC_MISC_BD_ID_5703S && + pDevice->BondId != GRC_MISC_BD_ID_5704 && + pDevice->BondId != GRC_MISC_BD_ID_5704CIOBE) + { + return LM_STATUS_UNKNOWN_ADAPTER; + } + + pDevice->SplitModeEnable = SPLIT_MODE_DISABLE; + if ((pDevice->ChipRevId == T3_CHIP_ID_5704_A0) && + (pDevice->BondId == GRC_MISC_BD_ID_5704CIOBE)) + { + pDevice->SplitModeEnable = SPLIT_MODE_ENABLE; + pDevice->SplitModeMaxReq = SPLIT_MODE_5704_MAX_REQ; + } + + /* Get Eeprom info. */ + Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_SIG_ADDR); + if (Value32 == T3_NIC_DATA_SIG) + { + EeSigFound = TRUE; + Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_NIC_CFG_ADDR); + + /* Determine PHY type. */ + switch (Value32 & T3_NIC_CFG_PHY_TYPE_MASK) + { + case T3_NIC_CFG_PHY_TYPE_COPPER: + EePhyTypeSerdes = FALSE; + break; + + case T3_NIC_CFG_PHY_TYPE_FIBER: + EePhyTypeSerdes = TRUE; + break; + + default: + EePhyTypeSerdes = FALSE; + break; + } + + /* Determine PHY led mode. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + switch(Value32 & T3_NIC_CFG_LED_MODE_MASK) + { + case T3_NIC_CFG_LED_MODE_TRIPLE_SPEED: + EePhyLedMode = LED_MODE_THREE_LINK; + break; + + case T3_NIC_CFG_LED_MODE_LINK_SPEED: + EePhyLedMode = LED_MODE_LINK10; + break; + + default: + EePhyLedMode = LED_MODE_AUTO; + break; + } + } + else + { + switch(Value32 & T3_NIC_CFG_LED_MODE_MASK) + { + case T3_NIC_CFG_LED_MODE_OPEN_DRAIN: + EePhyLedMode = LED_MODE_OPEN_DRAIN; + break; + + case T3_NIC_CFG_LED_MODE_OUTPUT: + EePhyLedMode = LED_MODE_OUTPUT; + break; + + default: + EePhyLedMode = LED_MODE_AUTO; + break; + } + } + if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || + pDevice->ChipRevId == T3_CHIP_ID_5703_A2) + { + /* Enable EEPROM write protection. */ + if(Value32 & T3_NIC_EEPROM_WP) + { + pDevice->EepromWp = TRUE; + } + } + + /* Get the PHY Id. */ + Value32 = MEM_RD_OFFSET(pDevice, T3_NIC_DATA_PHY_ID_ADDR); + if (Value32) + { + EePhyId = (((Value32 & T3_NIC_PHY_ID1_MASK) >> 16) & + PHY_ID1_OUI_MASK) << 10; + + Value32 = Value32 & T3_NIC_PHY_ID2_MASK; + + EePhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | + (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK); + } + else + { + EePhyId = 0; + } + } + else + { + EeSigFound = FALSE; + } + + /* Set the PHY address. */ + pDevice->PhyAddr = PHY_DEVICE_ID; + + /* Disable auto polling. */ + pDevice->MiMode = 0xc0000; + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait(40); + + /* Get the PHY id. */ + LM_ReadPhy(pDevice, PHY_ID1_REG, &Value32); + pDevice->PhyId = (Value32 & PHY_ID1_OUI_MASK) << 10; + + LM_ReadPhy(pDevice, PHY_ID2_REG, &Value32); + pDevice->PhyId |= ((Value32 & PHY_ID2_OUI_MASK) << 16) | + (Value32 & PHY_ID2_MODEL_MASK) | (Value32 & PHY_ID2_REV_MASK); + + /* Set the EnableTbi flag to false if we have a copper PHY. */ + switch(pDevice->PhyId & PHY_ID_MASK) + { + case PHY_BCM5400_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5401_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5411_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5701_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5703_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM5704_PHY_ID: + pDevice->EnableTbi = FALSE; + break; + + case PHY_BCM8002_PHY_ID: + pDevice->EnableTbi = TRUE; + break; + + default: + + if (pAdapterInfo) + { + pDevice->PhyId = pAdapterInfo->PhyId; + pDevice->EnableTbi = pAdapterInfo->Serdes; + } + else if (EeSigFound) + { + pDevice->PhyId = EePhyId; + pDevice->EnableTbi = EePhyTypeSerdes; + } + break; + } + + /* Bail out if we don't know the copper PHY id. */ + if(UNKNOWN_PHY_ID(pDevice->PhyId) && !pDevice->EnableTbi) + { + return LM_STATUS_FAILURE; + } + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) + { + if((pDevice->SavedCacheLineReg & 0xff00) < 0x4000) + { + pDevice->SavedCacheLineReg &= 0xffff00ff; + pDevice->SavedCacheLineReg |= 0x4000; + } + } + /* Change driver parameters. */ + Status = MM_GetConfig(pDevice); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + +#if INCLUDE_5701_AX_FIX + if (pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) + { + pDevice->ResetPhyOnInit = TRUE; + } +#endif + + /* Save the current phy link status. */ + if(!pDevice->EnableTbi) + { + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + + /* If we don't have link reset the PHY. */ + if(!(Value32 & PHY_STATUS_LINK_PASS) || pDevice->ResetPhyOnInit) + { + + LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); + + for(j = 0; j < 100; j++) + { + MM_Wait(10); + + LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); + if(Value32 && !(Value32 & PHY_CTRL_PHY_RESET)) + { + MM_Wait(40); + break; + } + } + + +#if INCLUDE_5701_AX_FIX + /* 5701_AX_BX bug: only advertises 10mb speed. */ + if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) + { + + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | + PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL | + PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + Value32 = BCM540X_AN_AD_1000BASET_HALF | + BCM540X_AN_AD_1000BASET_FULL | BCM540X_CONFIG_AS_MASTER | + BCM540X_ENABLE_CONFIG_AS_MASTER; + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32); + pDevice->advertising1000 = Value32; + + LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE | + PHY_CTRL_RESTART_AUTO_NEG); + } +#endif + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) + { + LM_WritePhy(pDevice, 0x18, 0x0c00); + LM_WritePhy(pDevice, 0x17, 0x201f); + LM_WritePhy(pDevice, 0x15, 0x2aaa); + } + if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + LM_WritePhy(pDevice, 0x1c, 0x8d68); + LM_WritePhy(pDevice, 0x1c, 0x8d68); + } + /* Enable Ethernet@WireSpeed. */ + if(pDevice->EnableWireSpeed) + { + LM_WritePhy(pDevice, 0x18, 0x7007); + LM_ReadPhy(pDevice, 0x18, &Value32); + LM_WritePhy(pDevice, 0x18, Value32 | BIT_15 | BIT_4); + } + } + } + + /* Turn off tap power management. */ + if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) + { + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20); + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804); + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204); + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132); + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232); + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20); + + MM_Wait(40); + } + +#if INCLUDE_TBI_SUPPORT + pDevice->IgnoreTbiLinkChange = FALSE; + + if(pDevice->EnableTbi) + { + pDevice->WakeUpModeCap = LM_WAKE_UP_MODE_NONE; + pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; + if ((pDevice->PollTbiLink == BAD_DEFAULT_VALUE) || + pDevice->DisableAutoNeg) + { + pDevice->PollTbiLink = FALSE; + } + } + else + { + pDevice->PollTbiLink = FALSE; + } +#endif /* INCLUDE_TBI_SUPPORT */ + + /* UseTaggedStatus is only valid for 5701 and later. */ + if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->UseTaggedStatus = FALSE; + + pDevice->CoalesceMode = 0; + } + else + { + pDevice->CoalesceMode = HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT | + HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT; + } + + /* Set the status block size. */ + if(T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_AX && + T3_CHIP_REV(pDevice->ChipRevId) != T3_CHIP_REV_5700_BX) + { + pDevice->CoalesceMode |= HOST_COALESCE_32_BYTE_STATUS_MODE; + } + + /* Check the DURING_INT coalescing ticks parameters. */ + if(pDevice->UseTaggedStatus) + { + if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->RxCoalescingTicksDuringInt = + DEFAULT_RX_COALESCING_TICKS_DURING_INT; + } + + if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->TxCoalescingTicksDuringInt = + DEFAULT_TX_COALESCING_TICKS_DURING_INT; + } + + if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->RxMaxCoalescedFramesDuringInt = + DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT; + } + + if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->TxMaxCoalescedFramesDuringInt = + DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT; + } + } + else + { + if(pDevice->RxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->RxCoalescingTicksDuringInt = 0; + } + + if(pDevice->TxCoalescingTicksDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->TxCoalescingTicksDuringInt = 0; + } + + if(pDevice->RxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->RxMaxCoalescedFramesDuringInt = 0; + } + + if(pDevice->TxMaxCoalescedFramesDuringInt == BAD_DEFAULT_VALUE) + { + pDevice->TxMaxCoalescedFramesDuringInt = 0; + } + } + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + if(pDevice->RxMtu <= (MAX_STD_RCV_BUFFER_SIZE - 8 /* CRC */)) + { + pDevice->RxJumboDescCnt = 0; + if(pDevice->RxMtu <= MAX_ETHERNET_PACKET_SIZE_NO_CRC) + { + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + } + } + else + { + pDevice->RxJumboBufferSize = (pDevice->RxMtu + 8 /* CRC + VLAN */ + + COMMON_CACHE_LINE_SIZE-1) & ~COMMON_CACHE_LINE_MASK; + + if(pDevice->RxJumboBufferSize > MAX_JUMBO_RCV_BUFFER_SIZE) + { + pDevice->RxJumboBufferSize = DEFAULT_JUMBO_RCV_BUFFER_SIZE; + pDevice->RxMtu = pDevice->RxJumboBufferSize - 8 /* CRC + VLAN */; + } + pDevice->TxMtu = pDevice->RxMtu; + + } +#else + pDevice->RxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + pDevice->RxPacketDescCnt = +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboDescCnt + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + pDevice->RxStdDescCnt; + + if(pDevice->TxMtu < MAX_ETHERNET_PACKET_SIZE_NO_CRC) + { + pDevice->TxMtu = MAX_ETHERNET_PACKET_SIZE_NO_CRC; + } + + if(pDevice->TxMtu > MAX_JUMBO_TX_BUFFER_SIZE) + { + pDevice->TxMtu = MAX_JUMBO_TX_BUFFER_SIZE; + } + + /* Configure the proper ways to get link change interrupt. */ + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO) + { + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; + } + else + { + pDevice->PhyIntMode = T3_PHY_INT_MODE_LINK_READY; + } + } + else if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + /* Auto-polling does not work on 5700_AX and 5700_BX. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; + } + } + + /* Determine the method to get link change status. */ + if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_AUTO) + { + /* The link status bit in the status block does not work on 5700_AX */ + /* and 5700_BX chips. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; + } + else + { + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_BLOCK; + } + } + + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; + } + + /* Configure PHY led mode. */ + if(pDevice->LedMode == LED_MODE_AUTO) + { + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + if(pDevice->SubsystemVendorId == T3_SVID_DELL) + { + pDevice->LedMode = LED_MODE_LINK10; + } + else + { + pDevice->LedMode = LED_MODE_THREE_LINK; + + if(EeSigFound && EePhyLedMode != LED_MODE_AUTO) + { + pDevice->LedMode = EePhyLedMode; + } + } + + /* bug? 5701 in LINK10 mode does not seem to work when */ + /* PhyIntMode is LINK_READY. */ + if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 && +#if INCLUDE_TBI_SUPPORT + pDevice->EnableTbi == FALSE && +#endif + pDevice->LedMode == LED_MODE_LINK10) + { + pDevice->PhyIntMode = T3_PHY_INT_MODE_MI_INTERRUPT; + pDevice->LinkChngMode = T3_LINK_CHNG_MODE_USE_STATUS_REG; + } + + if(pDevice->EnableTbi) + { + pDevice->LedMode = LED_MODE_THREE_LINK; + } + } + else + { + if(EeSigFound && EePhyLedMode != LED_MODE_AUTO) + { + pDevice->LedMode = EePhyLedMode; + } + else + { + pDevice->LedMode = LED_MODE_OPEN_DRAIN; + } + } + } + + /* Enable OneDmaAtOnce. */ + if(pDevice->OneDmaAtOnce == BAD_DEFAULT_VALUE) + { + pDevice->OneDmaAtOnce = FALSE; + } + + if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B2) + { + pDevice->WolSpeed = WOL_SPEED_10MB; + } + else + { + pDevice->WolSpeed = WOL_SPEED_100MB; + } + + /* Offloadings. */ + pDevice->TaskToOffload = LM_TASK_OFFLOAD_NONE; + + /* Turn off task offloading on Ax. */ + if(pDevice->ChipRevId == T3_CHIP_ID_5700_B0) + { + pDevice->TaskOffloadCap &= ~(LM_TASK_OFFLOAD_TX_TCP_CHECKSUM | + LM_TASK_OFFLOAD_TX_UDP_CHECKSUM); + } + pDevice->PciState = REG_RD(pDevice, PciCfg.PciState); + LM_ReadVPD(pDevice); + LM_ReadBootCodeVersion(pDevice); + LM_GetBusSpeed(pDevice); + + return LM_STATUS_SUCCESS; +} /* LM_GetAdapterInfo */ + +STATIC PLM_ADAPTER_INFO +LM_GetAdapterInfoBySsid( + LM_UINT16 Svid, + LM_UINT16 Ssid) +{ + static LM_ADAPTER_INFO AdapterArr[] = + { + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A6, PHY_BCM5401_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A5, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700T6, PHY_BCM8002_PHY_ID, 1}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95700A9, 0, 1 }, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T1, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701T8, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A7, 0, 1}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A10, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95701A12, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax1, PHY_BCM5701_PHY_ID, 0}, + { T3_SVID_BROADCOM, T3_SSID_BROADCOM_BCM95703Ax2, PHY_BCM5701_PHY_ID, 0}, + + { T3_SVID_3COM, T3_SSID_3COM_3C996T, PHY_BCM5401_PHY_ID, 0 }, + { T3_SVID_3COM, T3_SSID_3COM_3C996BT, PHY_BCM5701_PHY_ID, 0 }, + { T3_SVID_3COM, T3_SSID_3COM_3C996SX, 0, 1 }, + { T3_SVID_3COM, T3_SSID_3COM_3C1000T, PHY_BCM5701_PHY_ID, 0 }, + { T3_SVID_3COM, T3_SSID_3COM_3C940BR01, PHY_BCM5701_PHY_ID, 0 }, + + { T3_SVID_DELL, T3_SSID_DELL_VIPER, PHY_BCM5401_PHY_ID, 0 }, + { T3_SVID_DELL, T3_SSID_DELL_JAGUAR, PHY_BCM5401_PHY_ID, 0 }, + { T3_SVID_DELL, T3_SSID_DELL_MERLOT, PHY_BCM5411_PHY_ID, 0 }, + { T3_SVID_DELL, T3_SSID_DELL_SLIM_MERLOT, PHY_BCM5411_PHY_ID, 0 }, + + { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE, PHY_BCM5701_PHY_ID, 0 }, + { T3_SVID_COMPAQ, T3_SSID_COMPAQ_BANSHEE_2, PHY_BCM5701_PHY_ID, 0 }, + { T3_SVID_COMPAQ, T3_SSID_COMPAQ_CHANGELING, 0, 1 }, + { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780, PHY_BCM5701_PHY_ID, 0 }, + { T3_SVID_COMPAQ, T3_SSID_COMPAQ_NC7780_2, PHY_BCM5701_PHY_ID, 0 }, + + }; + LM_UINT32 j; + + for(j = 0; j < sizeof(AdapterArr)/sizeof(LM_ADAPTER_INFO); j++) + { + if(AdapterArr[j].Svid == Svid && AdapterArr[j].Ssid == Ssid) + { + return &AdapterArr[j]; + } + } + + return NULL; +} + + +/******************************************************************************/ +/* Description: */ +/* This routine sets up receive/transmit buffer descriptions queues. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_InitializeAdapter( +PLM_DEVICE_BLOCK pDevice) +{ + LM_PHYSICAL_ADDRESS MemPhy; + PLM_UINT8 pMemVirt; + PLM_PACKET pPacket; + LM_STATUS Status; + LM_UINT32 Size; + LM_UINT32 j; + + /* Set power state to D0. */ + LM_SetPowerState(pDevice, LM_POWER_STATE_D0); + + /* Intialize the queues. */ + QQ_InitQueue(&pDevice->RxPacketReceivedQ.Container, + MAX_RX_PACKET_DESC_COUNT); + QQ_InitQueue(&pDevice->RxPacketFreeQ.Container, + MAX_RX_PACKET_DESC_COUNT); + + QQ_InitQueue(&pDevice->TxPacketFreeQ.Container,MAX_TX_PACKET_DESC_COUNT); + QQ_InitQueue(&pDevice->TxPacketActiveQ.Container,MAX_TX_PACKET_DESC_COUNT); + QQ_InitQueue(&pDevice->TxPacketXmittedQ.Container,MAX_TX_PACKET_DESC_COUNT); + + /* Allocate shared memory for: status block, the buffers for receive */ + /* rings -- standard, mini, jumbo, and return rings. */ + Size = T3_STATUS_BLOCK_SIZE + sizeof(T3_STATS_BLOCK) + + T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD) + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD); + + /* Memory for host based Send BD. */ + if(pDevice->NicSendBd == FALSE) + { + Size += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; + } + + /* Allocate the memory block. */ + Status = MM_AllocateSharedMemory(pDevice, Size, (PLM_VOID) &pMemVirt, &MemPhy, FALSE); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + + /* Program DMA Read/Write */ + if (pDevice->PciState & T3_PCI_STATE_NOT_PCI_X_BUS) + { + pDevice->DmaReadWriteCtrl = 0x763f000f; + } + else + { + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5704) + { + pDevice->DmaReadWriteCtrl = 0x761f0000; + } + else + { + pDevice->DmaReadWriteCtrl = 0x761b000f; + } + if(pDevice->ChipRevId == T3_CHIP_ID_5703_A1 || + pDevice->ChipRevId == T3_CHIP_ID_5703_A2) + { + pDevice->OneDmaAtOnce = TRUE; + } + } + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5703) + { + pDevice->DmaReadWriteCtrl &= 0xfffffff0; + } + + if(pDevice->OneDmaAtOnce) + { + pDevice->DmaReadWriteCtrl |= DMA_CTRL_WRITE_ONE_DMA_AT_ONCE; + } + REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); + + if (LM_DmaTest(pDevice, pMemVirt, MemPhy, 0x400) != LM_STATUS_SUCCESS) + { + return LM_STATUS_FAILURE; + } + + /* Status block. */ + pDevice->pStatusBlkVirt = (PT3_STATUS_BLOCK) pMemVirt; + pDevice->StatusBlkPhy = MemPhy; + pMemVirt += T3_STATUS_BLOCK_SIZE; + LM_INC_PHYSICAL_ADDRESS(&MemPhy, T3_STATUS_BLOCK_SIZE); + + /* Statistics block. */ + pDevice->pStatsBlkVirt = (PT3_STATS_BLOCK) pMemVirt; + pDevice->StatsBlkPhy = MemPhy; + pMemVirt += sizeof(T3_STATS_BLOCK); + LM_INC_PHYSICAL_ADDRESS(&MemPhy, sizeof(T3_STATS_BLOCK)); + + /* Receive standard BD buffer. */ + pDevice->pRxStdBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RxStdBdPhy = MemPhy; + + pMemVirt += T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS(&MemPhy, + T3_STD_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD)); + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Receive jumbo BD buffer. */ + pDevice->pRxJumboBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RxJumboBdPhy = MemPhy; + + pMemVirt += T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS(&MemPhy, + T3_JUMBO_RCV_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD)); +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Receive return BD buffer. */ + pDevice->pRcvRetBdVirt = (PT3_RCV_BD) pMemVirt; + pDevice->RcvRetBdPhy = MemPhy; + + pMemVirt += T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD); + LM_INC_PHYSICAL_ADDRESS(&MemPhy, + T3_RCV_RETURN_RCB_ENTRY_COUNT * sizeof(T3_RCV_BD)); + + /* Set up Send BD. */ + if(pDevice->NicSendBd == FALSE) + { + pDevice->pSendBdVirt = (PT3_SND_BD) pMemVirt; + pDevice->SendBdPhy = MemPhy; + + pMemVirt += sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT; + LM_INC_PHYSICAL_ADDRESS(&MemPhy, + sizeof(T3_SND_BD) * T3_SEND_RCB_ENTRY_COUNT); + } + else + { + pDevice->pSendBdVirt = (PT3_SND_BD) + pDevice->pMemView->uIntMem.First32k.BufferDesc; + pDevice->SendBdPhy.High = 0; + pDevice->SendBdPhy.Low = T3_NIC_SND_BUFFER_DESC_ADDR; + } + + /* Allocate memory for packet descriptors. */ + Size = (pDevice->RxPacketDescCnt + + pDevice->TxPacketDescCnt) * MM_PACKET_DESC_SIZE; + Status = MM_AllocateMemory(pDevice, Size, (PLM_VOID *) &pPacket); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + pDevice->pPacketDescBase = (PLM_VOID) pPacket; + + /* Create transmit packet descriptors from the memory block and add them */ + /* to the TxPacketFreeQ for each send ring. */ + for(j = 0; j < pDevice->TxPacketDescCnt; j++) + { + /* Ring index. */ + pPacket->Flags = 0; + + /* Queue the descriptor in the TxPacketFreeQ of the 'k' ring. */ + QQ_PushTail(&pDevice->TxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for(j.. */ + + /* Create receive packet descriptors from the memory block and add them */ + /* to the RxPacketFreeQ. Create the Standard packet descriptors. */ + for(j = 0; j < pDevice->RxStdDescCnt; j++) + { + /* Receive producer ring. */ + pPacket->u.Rx.RcvProdRing = T3_STD_RCV_PROD_RING; + + /* Receive buffer size. */ + pPacket->u.Rx.RxBufferSize = MAX_STD_RCV_BUFFER_SIZE; + + /* Add the descriptor to RxPacketFreeQ. */ + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for */ + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Create the Jumbo packet descriptors. */ + for(j = 0; j < pDevice->RxJumboDescCnt; j++) + { + /* Receive producer ring. */ + pPacket->u.Rx.RcvProdRing = T3_JUMBO_RCV_PROD_RING; + + /* Receive buffer size. */ + pPacket->u.Rx.RxBufferSize = pDevice->RxJumboBufferSize; + + /* Add the descriptor to RxPacketFreeQ. */ + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + + /* Get the pointer to the next descriptor. MM_PACKET_DESC_SIZE */ + /* is the total size of the packet descriptor including the */ + /* os-specific extensions in the UM_PACKET structure. */ + pPacket = (PLM_PACKET) ((PLM_UINT8) pPacket + MM_PACKET_DESC_SIZE); + } /* for */ +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Initialize the rest of the packet descriptors. */ + Status = MM_InitializeUmPackets(pDevice); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } /* if */ + + /* Default receive mask. */ + pDevice->ReceiveMask = LM_ACCEPT_MULTICAST | LM_ACCEPT_BROADCAST | + LM_ACCEPT_UNICAST; + + /* Make sure we are in the first 32k memory window or NicSendBd. */ + REG_WR(pDevice, PciCfg.MemWindowBaseAddr, 0); + + /* Initialize the hardware. */ + Status = LM_ResetAdapter(pDevice); + if(Status != LM_STATUS_SUCCESS) + { + return Status; + } + + /* We are done with initialization. */ + pDevice->InitDone = TRUE; + + return LM_STATUS_SUCCESS; +} /* LM_InitializeAdapter */ + + + +/******************************************************************************/ +/* Description: */ +/* This function Enables/Disables a given block. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_CntrlBlock( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 mask,LM_UINT32 cntrl) +{ + LM_UINT32 j,i,data; + LM_UINT32 MaxWaitCnt; + + MaxWaitCnt = 2; + j = 0; + + for(i = 0 ; i < 32; i++) + { + if(!(mask & (1 << i))) + continue; + + switch (1 << i) + { + case T3_BLOCK_DMA_RD: + data = REG_RD(pDevice, DmaRead.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~DMA_READ_MODE_ENABLE; + REG_WR(pDevice, DmaRead.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, DmaRead.Mode) & DMA_READ_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, DmaRead.Mode, data | DMA_READ_MODE_ENABLE); + break; + + case T3_BLOCK_DMA_COMP: + data = REG_RD(pDevice,DmaComp.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~DMA_COMP_MODE_ENABLE; + REG_WR(pDevice, DmaComp.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, DmaComp.Mode) & DMA_COMP_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, DmaComp.Mode, data | DMA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_RX_BD_INITIATOR: + data = REG_RD(pDevice, RcvBdIn.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_BD_IN_MODE_ENABLE; + REG_WR(pDevice, RcvBdIn.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvBdIn.Mode) & RCV_BD_IN_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvBdIn.Mode,data | RCV_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_RX_BD_COMP: + data = REG_RD(pDevice, RcvBdComp.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_BD_COMP_MODE_ENABLE; + REG_WR(pDevice, RcvBdComp.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvBdComp.Mode) & RCV_BD_COMP_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvBdComp.Mode,data | RCV_BD_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_DMA_WR: + data = REG_RD(pDevice, DmaWrite.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~DMA_WRITE_MODE_ENABLE; + REG_WR(pDevice, DmaWrite.Mode,data); + + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, DmaWrite.Mode) & DMA_WRITE_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, DmaWrite.Mode,data | DMA_WRITE_MODE_ENABLE); + break; + + case T3_BLOCK_MSI_HANDLER: + data = REG_RD(pDevice, Msi.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~MSI_MODE_ENABLE; + REG_WR(pDevice, Msi.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, Msi.Mode) & MSI_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, Msi.Mode, data |MSI_MODE_ENABLE); + break; + + case T3_BLOCK_RX_LIST_PLMT: + data = REG_RD(pDevice, RcvListPlmt.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_LIST_PLMT_MODE_ENABLE; + REG_WR(pDevice, RcvListPlmt.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvListPlmt.Mode) & RCV_LIST_PLMT_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvListPlmt.Mode,data | RCV_LIST_PLMT_MODE_ENABLE); + break; + + case T3_BLOCK_RX_LIST_SELECTOR: + data = REG_RD(pDevice, RcvListSel.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_LIST_SEL_MODE_ENABLE; + REG_WR(pDevice, RcvListSel.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvListSel.Mode) & RCV_LIST_SEL_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvListSel.Mode,data |RCV_LIST_SEL_MODE_ENABLE); + break; + + case T3_BLOCK_RX_DATA_INITIATOR: + data = REG_RD(pDevice, RcvDataBdIn.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_DATA_BD_IN_MODE_ENABLE; + REG_WR(pDevice, RcvDataBdIn.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_BD_IN_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvDataBdIn.Mode, data | RCV_DATA_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_RX_DATA_COMP: + data = REG_RD(pDevice, RcvDataComp.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~RCV_DATA_COMP_MODE_ENABLE; + REG_WR(pDevice, RcvDataComp.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, RcvDataBdIn.Mode) & RCV_DATA_COMP_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, RcvDataComp.Mode,data | RCV_DATA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_HOST_COALESING: + data = REG_RD(pDevice, HostCoalesce.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~HOST_COALESCE_ENABLE; + REG_WR(pDevice, HostCoalesce.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndBdIn.Mode) & HOST_COALESCE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, HostCoalesce.Mode, data | HOST_COALESCE_ENABLE); + break; + + case T3_BLOCK_MAC_RX_ENGINE: + if(cntrl == LM_DISABLE) + { + pDevice->RxMode &= ~RX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, MacCtrl.RxMode) & RX_MODE_ENABLE)) + { + break; + } + MM_Wait(10); + } + } + else + { + pDevice->RxMode |= RX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode); + } + break; + + case T3_BLOCK_MBUF_CLUSTER_FREE: + data = REG_RD(pDevice, MbufClusterFree.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~MBUF_CLUSTER_FREE_MODE_ENABLE; + REG_WR(pDevice, MbufClusterFree.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, MbufClusterFree.Mode) & MBUF_CLUSTER_FREE_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, MbufClusterFree.Mode, data | MBUF_CLUSTER_FREE_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_INITIATOR: + data = REG_RD(pDevice, SndBdIn.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~SND_BD_IN_MODE_ENABLE; + REG_WR(pDevice, SndBdIn.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndBdIn.Mode) & SND_BD_IN_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, SndBdIn.Mode, data | SND_BD_IN_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_COMP: + data = REG_RD(pDevice, SndBdComp.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~SND_BD_COMP_MODE_ENABLE; + REG_WR(pDevice, SndBdComp.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndBdComp.Mode) & SND_BD_COMP_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, SndBdComp.Mode, data | SND_BD_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_BD_SELECTOR: + data = REG_RD(pDevice, SndBdSel.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~SND_BD_SEL_MODE_ENABLE; + REG_WR(pDevice, SndBdSel.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndBdSel.Mode) & SND_BD_SEL_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, SndBdSel.Mode, data | SND_BD_SEL_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_DATA_INITIATOR: + data = REG_RD(pDevice, SndDataIn.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~T3_SND_DATA_IN_MODE_ENABLE; + REG_WR(pDevice, SndDataIn.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndDataIn.Mode) & T3_SND_DATA_IN_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, SndDataIn.Mode,data | T3_SND_DATA_IN_MODE_ENABLE); + break; + + case T3_BLOCK_SEND_DATA_COMP: + data = REG_RD(pDevice, SndDataComp.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~SND_DATA_COMP_MODE_ENABLE; + REG_WR(pDevice, SndDataComp.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, SndDataComp.Mode) & SND_DATA_COMP_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, SndDataComp.Mode,data | SND_DATA_COMP_MODE_ENABLE); + break; + + case T3_BLOCK_MAC_TX_ENGINE: + if(cntrl == LM_DISABLE) + { + pDevice->TxMode &= ~TX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, MacCtrl.TxMode) & TX_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + { + pDevice->TxMode |= TX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode); + } + break; + + case T3_BLOCK_MEM_ARBITOR: + data = REG_RD(pDevice, MemArbiter.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~T3_MEM_ARBITER_MODE_ENABLE; + REG_WR(pDevice, MemArbiter.Mode, data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, MemArbiter.Mode) & T3_MEM_ARBITER_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, MemArbiter.Mode,data|T3_MEM_ARBITER_MODE_ENABLE); + break; + + case T3_BLOCK_MBUF_MANAGER: + data = REG_RD(pDevice, BufMgr.Mode); + if (cntrl == LM_DISABLE) + { + data &= ~BUFMGR_MODE_ENABLE; + REG_WR(pDevice, BufMgr.Mode,data); + for(j = 0; j < MaxWaitCnt; j++) + { + if(!(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE)) + break; + MM_Wait(10); + } + } + else + REG_WR(pDevice, BufMgr.Mode,data | BUFMGR_MODE_ENABLE); + break; + + case T3_BLOCK_MAC_GLOBAL: + if(cntrl == LM_DISABLE) + { + pDevice->MacMode &= ~(MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | + MAC_MODE_ENABLE_FHDE); + } + else + { + pDevice->MacMode |= (MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | + MAC_MODE_ENABLE_FHDE); + } + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + break; + + default: + return LM_STATUS_FAILURE; + } /* switch */ + + if(j >= MaxWaitCnt) + { + return LM_STATUS_FAILURE; + } + } + + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* This function reinitializes the adapter. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_ResetAdapter( +PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT16 Value16; + LM_UINT32 j, k; + + /* Disable interrupt. */ + LM_DisableInterrupt(pDevice); + + /* May get a spurious interrupt */ + pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED; + + /* Disable transmit and receive DMA engines. Abort all pending requests. */ + if(pDevice->InitDone) + { + LM_Abort(pDevice); + } + + pDevice->ShuttingDown = FALSE; + + LM_ResetChip(pDevice); + + /* Bug: Athlon fix for B3 silicon only. This bit does not do anything */ + /* in other chip revisions. */ + if(pDevice->DelayPciGrant) + { + Value32 = REG_RD(pDevice, PciCfg.ClockCtrl); + REG_WR(pDevice, PciCfg.ClockCtrl, Value32 | BIT_31); + } + + if(pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) + { + Value32 = REG_RD(pDevice, PciCfg.PciState); + Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; + REG_WR(pDevice, PciCfg.PciState, Value32); + } + } + + /* Enable TaggedStatus mode. */ + if(pDevice->UseTaggedStatus) + { + pDevice->MiscHostCtrl |= MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE; + } + + /* Restore PCI configuration registers. */ + MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, + pDevice->SavedCacheLineReg); + MM_WriteConfig32(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, + (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId); + + /* Clear the statistics block. */ + for(j = 0x0300; j < 0x0b00; j++) + { + MEM_WR_OFFSET(pDevice, j, 0); + } + + /* Initialize the statistis Block */ + pDevice->pStatusBlkVirt->Status = 0; + pDevice->pStatusBlkVirt->RcvStdConIdx = 0; + pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; + pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; + + for(j = 0; j < 16; j++) + { + pDevice->pStatusBlkVirt->Idx[j].RcvProdIdx = 0; + pDevice->pStatusBlkVirt->Idx[j].SendConIdx = 0; + } + + for(k = 0; k < T3_STD_RCV_RCB_ENTRY_COUNT ;k++) + { + pDevice->pRxStdBdVirt[k].HostAddr.High = 0; + pDevice->pRxStdBdVirt[k].HostAddr.Low = 0; + } + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Receive jumbo BD buffer. */ + for(k = 0; k < T3_JUMBO_RCV_RCB_ENTRY_COUNT; k++) + { + pDevice->pRxJumboBdVirt[k].HostAddr.High = 0; + pDevice->pRxJumboBdVirt[k].HostAddr.Low = 0; + } +#endif + + REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, pDevice->DmaReadWriteCtrl); + + /* GRC mode control register. */ +#ifdef BIG_ENDIAN_PCI /* Jimmy, this ifdef block deleted in new code! */ + Value32 = + GRC_MODE_WORD_SWAP_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_INT_ON_MAC_ATTN | + GRC_MODE_HOST_STACK_UP; +#else + /* No CPU Swap modes for PCI IO */ + Value32 = +#ifdef BIG_ENDIAN_HOST + GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | + GRC_MODE_WORD_SWAP_DATA | +#else + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | + GRC_MODE_WORD_SWAP_DATA | +#endif + GRC_MODE_INT_ON_MAC_ATTN | + GRC_MODE_HOST_STACK_UP; +#endif /* !BIG_ENDIAN_PCI */ + + /* Configure send BD mode. */ + if(pDevice->NicSendBd == FALSE) + { + Value32 |= GRC_MODE_HOST_SEND_BDS; + } + else + { + Value32 |= GRC_MODE_4X_NIC_BASED_SEND_RINGS; + } + + /* Configure pseudo checksum mode. */ + if(pDevice->NoTxPseudoHdrChksum) + { + Value32 |= GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM; + } + + if(pDevice->NoRxPseudoHdrChksum) + { + Value32 |= GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM; + } + + REG_WR(pDevice, Grc.Mode, Value32); + + /* Setup the timer prescalar register. */ + REG_WR(pDevice, Grc.MiscCfg, 65 << 1); /* Clock is alwasy 66Mhz. */ + + /* Set up the MBUF pool base address and size. */ + REG_WR(pDevice, BufMgr.MbufPoolAddr, pDevice->MbufBase); + REG_WR(pDevice, BufMgr.MbufPoolSize, pDevice->MbufSize); + + /* Set up the DMA descriptor pool base address and size. */ + REG_WR(pDevice, BufMgr.DmaDescPoolAddr, T3_NIC_DMA_DESC_POOL_ADDR); + REG_WR(pDevice, BufMgr.DmaDescPoolSize, T3_NIC_DMA_DESC_POOL_SIZE); + + /* Configure MBUF and Threshold watermarks */ + /* Configure the DMA read MBUF low water mark. */ + if(pDevice->DmaMbufLowMark) + { + REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark, + pDevice->DmaMbufLowMark); + } + else + { + if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) + { + REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark, + T3_DEF_DMA_MBUF_LOW_WMARK); + } + else + { + REG_WR(pDevice, BufMgr.MbufReadDmaLowWaterMark, + T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO); + } + } + + /* Configure the MAC Rx MBUF low water mark. */ + if(pDevice->RxMacMbufLowMark) + { + REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark, + pDevice->RxMacMbufLowMark); + } + else + { + if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) + { + REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark, + T3_DEF_RX_MAC_MBUF_LOW_WMARK); + } + else + { + REG_WR(pDevice, BufMgr.MbufMacRxLowWaterMark, + T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO); + } + } + + /* Configure the MBUF high water mark. */ + if(pDevice->MbufHighMark) + { + REG_WR(pDevice, BufMgr.MbufHighWaterMark, pDevice->MbufHighMark); + } + else + { + if(pDevice->TxMtu < MAX_ETHERNET_PACKET_BUFFER_SIZE) + { + REG_WR(pDevice, BufMgr.MbufHighWaterMark, + T3_DEF_MBUF_HIGH_WMARK); + } + else + { + REG_WR(pDevice, BufMgr.MbufHighWaterMark, + T3_DEF_MBUF_HIGH_WMARK_JUMBO); + } + } + + REG_WR(pDevice, BufMgr.DmaLowWaterMark, T3_DEF_DMA_DESC_LOW_WMARK); + REG_WR(pDevice, BufMgr.DmaHighWaterMark, T3_DEF_DMA_DESC_HIGH_WMARK); + + /* Enable buffer manager. */ + REG_WR(pDevice, BufMgr.Mode, BUFMGR_MODE_ENABLE | BUFMGR_MODE_ATTN_ENABLE); + + for(j = 0 ;j < 2000; j++) + { + if(REG_RD(pDevice, BufMgr.Mode) & BUFMGR_MODE_ENABLE) + break; + MM_Wait(10); + } + + if(j >= 2000) + { + return LM_STATUS_FAILURE; + } + + /* Enable the FTQs. */ + REG_WR(pDevice, Ftq.Reset, 0xffffffff); + REG_WR(pDevice, Ftq.Reset, 0); + + /* Wait until FTQ is ready */ + for(j = 0; j < 2000; j++) + { + if(REG_RD(pDevice, Ftq.Reset) == 0) + break; + MM_Wait(10); + } + + if(j >= 2000) + { + return LM_STATUS_FAILURE; + } + + /* Initialize the Standard Receive RCB. */ + REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.High, + pDevice->RxStdBdPhy.High); + REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.HostRingAddr.Low, + pDevice->RxStdBdPhy.Low); + REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.u.MaxLen_Flags, + MAX_STD_RCV_BUFFER_SIZE << 16); + + /* Initialize the Jumbo Receive RCB. */ + REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.High, + pDevice->RxJumboBdPhy.High); + REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.HostRingAddr.Low, + pDevice->RxJumboBdPhy.Low); + + REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.u.MaxLen_Flags, 0); + +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Initialize the Mini Receive RCB. */ + REG_WR(pDevice, RcvDataBdIn.MiniRcvRcb.u.MaxLen_Flags, + T3_RCB_FLAG_RING_DISABLED); + + { + REG_WR(pDevice, RcvDataBdIn.StdRcvRcb.NicRingAddr, + (LM_UINT32) T3_NIC_STD_RCV_BUFFER_DESC_ADDR); + REG_WR(pDevice, RcvDataBdIn.JumboRcvRcb.NicRingAddr, + (LM_UINT32) T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR); + } + + /* Receive BD Ring replenish threshold. */ + REG_WR(pDevice, RcvBdIn.StdRcvThreshold, pDevice->RxStdDescCnt/8); +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + REG_WR(pDevice, RcvBdIn.JumboRcvThreshold, pDevice->RxJumboDescCnt/8); +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* Disable all the unused rings. */ + for(j = 0; j < T3_MAX_SEND_RCB_COUNT; j++) { + MEM_WR(pDevice, SendRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED); + } /* for */ + + /* Initialize the indices. */ + pDevice->SendProdIdx = 0; + pDevice->SendConIdx = 0; + + MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, 0); + MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, 0); + + /* Set up host or NIC based send RCB. */ + if(pDevice->NicSendBd == FALSE) + { + MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, + pDevice->SendBdPhy.High); + MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, + pDevice->SendBdPhy.Low); + + /* Set up the NIC ring address in the RCB. */ + MEM_WR(pDevice, SendRcb[0].NicRingAddr,T3_NIC_SND_BUFFER_DESC_ADDR); + + /* Setup the RCB. */ + MEM_WR(pDevice, SendRcb[0].u.MaxLen_Flags, + T3_SEND_RCB_ENTRY_COUNT << 16); + + for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) + { + pDevice->pSendBdVirt[k].HostAddr.High = 0; + pDevice->pSendBdVirt[k].HostAddr.Low = 0; + } + } + else + { + MEM_WR(pDevice, SendRcb[0].HostRingAddr.High, 0); + MEM_WR(pDevice, SendRcb[0].HostRingAddr.Low, 0); + MEM_WR(pDevice, SendRcb[0].NicRingAddr, + pDevice->SendBdPhy.Low); + + for(k = 0; k < T3_SEND_RCB_ENTRY_COUNT; k++) + { + __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.High)); + __raw_writel(0, &(pDevice->pSendBdVirt[k].HostAddr.Low)); + __raw_writel(0, &(pDevice->pSendBdVirt[k].u1.Len_Flags)); + pDevice->ShadowSendBd[k].HostAddr.High = 0; + pDevice->ShadowSendBd[k].u1.Len_Flags = 0; + } + } + atomic_set(&pDevice->SendBdLeft, T3_SEND_RCB_ENTRY_COUNT-1); + + /* Configure the receive return rings. */ + for(j = 0; j < T3_MAX_RCV_RETURN_RCB_COUNT; j++) + { + MEM_WR(pDevice, RcvRetRcb[j].u.MaxLen_Flags, T3_RCB_FLAG_RING_DISABLED); + } + + pDevice->RcvRetConIdx = 0; + + MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.High, + pDevice->RcvRetBdPhy.High); + MEM_WR(pDevice, RcvRetRcb[0].HostRingAddr.Low, + pDevice->RcvRetBdPhy.Low); + + /* Set up the NIC ring address in the RCB. */ + /* Not very clear from the spec. I am guessing that for Receive */ + /* Return Ring, NicRingAddr is not used. */ + MEM_WR(pDevice, RcvRetRcb[0].NicRingAddr, 0); + + /* Setup the RCB. */ + MEM_WR(pDevice, RcvRetRcb[0].u.MaxLen_Flags, + T3_RCV_RETURN_RCB_ENTRY_COUNT << 16); + + /* Reinitialize RX ring producer index */ + MB_REG_WR(pDevice, Mailbox.RcvStdProdIdx.Low, 0); + MB_REG_WR(pDevice, Mailbox.RcvJumboProdIdx.Low, 0); + MB_REG_WR(pDevice, Mailbox.RcvMiniProdIdx.Low, 0); + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + pDevice->RxJumboProdIdx = 0; + pDevice->RxJumboQueuedCnt = 0; +#endif + + /* Reinitialize our copy of the indices. */ + pDevice->RxStdProdIdx = 0; + pDevice->RxStdQueuedCnt = 0; + +#if T3_JUMBO_RCV_ENTRY_COUNT + pDevice->RxJumboProdIdx = 0; +#endif /* T3_JUMBO_RCV_ENTRY_COUNT */ + + /* Configure the MAC address. */ + LM_SetMacAddress(pDevice, pDevice->NodeAddress); + + /* Initialize the transmit random backoff seed. */ + Value32 = (pDevice->NodeAddress[0] + pDevice->NodeAddress[1] + + pDevice->NodeAddress[2] + pDevice->NodeAddress[3] + + pDevice->NodeAddress[4] + pDevice->NodeAddress[5]) & + MAC_TX_BACKOFF_SEED_MASK; + REG_WR(pDevice, MacCtrl.TxBackoffSeed, Value32); + + /* Receive MTU. Frames larger than the MTU is marked as oversized. */ + REG_WR(pDevice, MacCtrl.MtuSize, pDevice->RxMtu + 8); /* CRC + VLAN. */ + + /* Configure Time slot/IPG per 802.3 */ + REG_WR(pDevice, MacCtrl.TxLengths, 0x2620); + + /* + * Configure Receive Rules so that packets don't match + * Programmble rule will be queued to Return Ring 1 + */ + REG_WR(pDevice, MacCtrl.RcvRuleCfg, RX_RULE_DEFAULT_CLASS); + + /* + * Configure to have 16 Classes of Services (COS) and one + * queue per class. Bad frames are queued to RRR#1. + * And frames don't match rules are also queued to COS#1. + */ + REG_WR(pDevice, RcvListPlmt.Config, 0x181); + + /* Enable Receive Placement Statistics */ + REG_WR(pDevice, RcvListPlmt.StatsEnableMask,0xffffff); + REG_WR(pDevice, RcvListPlmt.StatsCtrl, RCV_LIST_STATS_ENABLE); + + /* Enable Send Data Initator Statistics */ + REG_WR(pDevice, SndDataIn.StatsEnableMask,0xffffff); + REG_WR(pDevice, SndDataIn.StatsCtrl, + T3_SND_DATA_IN_STATS_CTRL_ENABLE | \ + T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE); + + /* Disable the host coalescing state machine before configuring it's */ + /* parameters. */ + REG_WR(pDevice, HostCoalesce.Mode, 0); + for(j = 0; j < 2000; j++) + { + Value32 = REG_RD(pDevice, HostCoalesce.Mode); + if(!(Value32 & HOST_COALESCE_ENABLE)) + { + break; + } + MM_Wait(10); + } + + /* Host coalescing configurations. */ + REG_WR(pDevice, HostCoalesce.RxCoalescingTicks, pDevice->RxCoalescingTicks); + REG_WR(pDevice, HostCoalesce.TxCoalescingTicks, pDevice->TxCoalescingTicks); + REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFrames, + pDevice->RxMaxCoalescedFrames); + REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFrames, + pDevice->TxMaxCoalescedFrames); + REG_WR(pDevice, HostCoalesce.RxCoalescedTickDuringInt, + pDevice->RxCoalescingTicksDuringInt); + REG_WR(pDevice, HostCoalesce.TxCoalescedTickDuringInt, + pDevice->TxCoalescingTicksDuringInt); + REG_WR(pDevice, HostCoalesce.RxMaxCoalescedFramesDuringInt, + pDevice->RxMaxCoalescedFramesDuringInt); + REG_WR(pDevice, HostCoalesce.TxMaxCoalescedFramesDuringInt, + pDevice->TxMaxCoalescedFramesDuringInt); + + /* Initialize the address of the status block. The NIC will DMA */ + /* the status block to this memory which resides on the host. */ + REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.High, + pDevice->StatusBlkPhy.High); + REG_WR(pDevice, HostCoalesce.StatusBlkHostAddr.Low, + pDevice->StatusBlkPhy.Low); + + /* Initialize the address of the statistics block. The NIC will DMA */ + /* the statistics to this block of memory. */ + REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.High, + pDevice->StatsBlkPhy.High); + REG_WR(pDevice, HostCoalesce.StatsBlkHostAddr.Low, + pDevice->StatsBlkPhy.Low); + + REG_WR(pDevice, HostCoalesce.StatsCoalescingTicks, + pDevice->StatsCoalescingTicks); + + REG_WR(pDevice, HostCoalesce.StatsBlkNicAddr, 0x300); + REG_WR(pDevice, HostCoalesce.StatusBlkNicAddr,0xb00); + + /* Enable Host Coalesing state machine */ + REG_WR(pDevice, HostCoalesce.Mode, HOST_COALESCE_ENABLE | + pDevice->CoalesceMode); + + /* Enable the Receive BD Completion state machine. */ + REG_WR(pDevice, RcvBdComp.Mode, RCV_BD_COMP_MODE_ENABLE | + RCV_BD_COMP_MODE_ATTN_ENABLE); + + /* Enable the Receive List Placement state machine. */ + REG_WR(pDevice, RcvListPlmt.Mode, RCV_LIST_PLMT_MODE_ENABLE); + + /* Enable the Receive List Selector state machine. */ + REG_WR(pDevice, RcvListSel.Mode, RCV_LIST_SEL_MODE_ENABLE | + RCV_LIST_SEL_MODE_ATTN_ENABLE); + + /* Enable transmit DMA, clear statistics. */ + pDevice->MacMode = MAC_MODE_ENABLE_TX_STATISTICS | + MAC_MODE_ENABLE_RX_STATISTICS | MAC_MODE_ENABLE_TDE | + MAC_MODE_ENABLE_RDE | MAC_MODE_ENABLE_FHDE; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_CLEAR_RX_STATISTICS | MAC_MODE_CLEAR_TX_STATISTICS); + + /* GRC miscellaneous local control register. */ + pDevice->GrcLocalCtrl = GRC_MISC_LOCAL_CTRL_INT_ON_ATTN | + GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM; + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + pDevice->GrcLocalCtrl |= GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1; + } + + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); + MM_Wait(40); + + /* Reset RX counters. */ + for(j = 0; j < sizeof(LM_RX_COUNTERS); j++) + { + ((PLM_UINT8) &pDevice->RxCounters)[j] = 0; + } + + /* Reset TX counters. */ + for(j = 0; j < sizeof(LM_TX_COUNTERS); j++) + { + ((PLM_UINT8) &pDevice->TxCounters)[j] = 0; + } + + MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0); + + /* Enable the DMA Completion state machine. */ + REG_WR(pDevice, DmaComp.Mode, DMA_COMP_MODE_ENABLE); + + /* Enable the DMA Write state machine. */ + Value32 = DMA_WRITE_MODE_ENABLE | + DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE | + DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE | + DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE | + DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE | + DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE | + DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE; + REG_WR(pDevice, DmaWrite.Mode, Value32); + + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) + { + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + Value16 = REG_RD(pDevice, PciCfg.PciXCommand); + Value16 &= ~(PCIX_CMD_MAX_SPLIT_MASK | PCIX_CMD_MAX_BURST_MASK); + Value16 |= ((PCIX_CMD_MAX_BURST_CPIOB << PCIX_CMD_MAX_BURST_SHL) & + PCIX_CMD_MAX_BURST_MASK); + if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) + { + Value16 |= (pDevice->SplitModeMaxReq << PCIX_CMD_MAX_SPLIT_SHL) + & PCIX_CMD_MAX_SPLIT_MASK; + } + REG_WR(pDevice, PciCfg.PciXCommand, Value16); + } + } + + /* Enable the Read DMA state machine. */ + Value32 = DMA_READ_MODE_ENABLE | + DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE | + DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE | + DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE | + DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE | + DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE | + DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE | + DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE | + DMA_READ_MODE_LONG_READ_ATTN_ENABLE; + + if (pDevice->SplitModeEnable == SPLIT_MODE_ENABLE) + { + Value32 |= DMA_READ_MODE_SPLIT_ENABLE; + } + REG_WR(pDevice, DmaRead.Mode, Value32); + + /* Enable the Receive Data Completion state machine. */ + REG_WR(pDevice, RcvDataComp.Mode, RCV_DATA_COMP_MODE_ENABLE | + RCV_DATA_COMP_MODE_ATTN_ENABLE); + + /* Enable the Mbuf Cluster Free state machine. */ + REG_WR(pDevice, MbufClusterFree.Mode, MBUF_CLUSTER_FREE_MODE_ENABLE); + + /* Enable the Send Data Completion state machine. */ + REG_WR(pDevice, SndDataComp.Mode, SND_DATA_COMP_MODE_ENABLE); + + /* Enable the Send BD Completion state machine. */ + REG_WR(pDevice, SndBdComp.Mode, SND_BD_COMP_MODE_ENABLE | + SND_BD_COMP_MODE_ATTN_ENABLE); + + /* Enable the Receive BD Initiator state machine. */ + REG_WR(pDevice, RcvBdIn.Mode, RCV_BD_IN_MODE_ENABLE | + RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE); + + /* Enable the Receive Data and Receive BD Initiator state machine. */ + REG_WR(pDevice, RcvDataBdIn.Mode, RCV_DATA_BD_IN_MODE_ENABLE | + RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE); + + /* Enable the Send Data Initiator state machine. */ + REG_WR(pDevice, SndDataIn.Mode, T3_SND_DATA_IN_MODE_ENABLE); + + /* Enable the Send BD Initiator state machine. */ + REG_WR(pDevice, SndBdIn.Mode, SND_BD_IN_MODE_ENABLE | + SND_BD_IN_MODE_ATTN_ENABLE); + + /* Enable the Send BD Selector state machine. */ + REG_WR(pDevice, SndBdSel.Mode, SND_BD_SEL_MODE_ENABLE | + SND_BD_SEL_MODE_ATTN_ENABLE); + +#if INCLUDE_5701_AX_FIX + /* Load the firmware for the 5701_A0 workaround. */ + if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0) + { + LM_LoadRlsFirmware(pDevice); + } +#endif + + /* Enable the transmitter. */ + pDevice->TxMode = TX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode); + + /* Enable the receiver. */ + pDevice->RxMode = RX_MODE_ENABLE; + REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode); + + if (pDevice->RestoreOnWakeUp) + { + pDevice->RestoreOnWakeUp = FALSE; + pDevice->DisableAutoNeg = pDevice->WakeUpDisableAutoNeg; + pDevice->RequestedMediaType = pDevice->WakeUpRequestedMediaType; + } + + /* Disable auto polling. */ + pDevice->MiMode = 0xc0000; + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = LED_CTRL_PHY_MODE_1; + } + else + { + if(pDevice->LedMode == LED_MODE_OUTPUT) + { + Value32 = LED_CTRL_PHY_MODE_2; + } + else + { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + REG_WR(pDevice, MacCtrl.LedCtrl, Value32); + + /* Activate Link to enable MAC state machine */ + REG_WR(pDevice, MacCtrl.MiStatus, MI_STATUS_ENABLE_LINK_STATUS_ATTN); + + if (pDevice->EnableTbi) + { + REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_RESET); + MM_Wait(10); + REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode); + if (pDevice->ChipRevId == T3_CHIP_ID_5703_A1) + { + REG_WR(pDevice, MacCtrl.SerdesCfg, 0x616000); + } + } + /* Setup the phy chip. */ + LM_SetupPhy(pDevice); + + if (!pDevice->EnableTbi) { + /* Clear CRC stats */ + LM_ReadPhy(pDevice, 0x1e, &Value32); + LM_WritePhy(pDevice, 0x1e, Value32 | 0x8000); + LM_ReadPhy(pDevice, 0x14, &Value32); + } + + /* Set up the receive mask. */ + LM_SetReceiveMask(pDevice, pDevice->ReceiveMask); + + /* Queue Rx packet buffers. */ + if(pDevice->QueueRxPackets) + { + LM_QueueRxPackets(pDevice); + } + + /* Enable interrupt to the host. */ + if(pDevice->InitDone) + { + LM_EnableInterrupt(pDevice); + } + + return LM_STATUS_SUCCESS; +} /* LM_ResetAdapter */ + + +/******************************************************************************/ +/* Description: */ +/* This routine disables the adapter from generating interrupts. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_DisableInterrupt( + PLM_DEVICE_BLOCK pDevice) +{ + REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl | + MISC_HOST_CTRL_MASK_PCI_INT); + MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 1); + + return LM_STATUS_SUCCESS; +} + + + +/******************************************************************************/ +/* Description: */ +/* This routine enables the adapter to generate interrupts. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_EnableInterrupt( + PLM_DEVICE_BLOCK pDevice) +{ + REG_WR(pDevice, PciCfg.MiscHostCtrl, pDevice->MiscHostCtrl & + ~MISC_HOST_CTRL_MASK_PCI_INT); + MB_REG_WR(pDevice, Mailbox.Interrupt[0].Low, 0); + + if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_UPDATED) + { + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_SET_INT); + } + + return LM_STATUS_SUCCESS; +} + + + +/******************************************************************************/ +/* Description: */ +/* This routine puts a packet on the wire if there is a transmit DMA */ +/* descriptor available; otherwise the packet is queued for later */ +/* transmission. If the second argue is NULL, this routine will put */ +/* the queued packet on the wire if possible. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +#if 0 +LM_STATUS +LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + LM_UINT32 FragCount; + PT3_SND_BD pSendBd; + PT3_SND_BD pShadowSendBd; + LM_UINT32 Value32, Len; + LM_UINT32 Idx; + + if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) { + return LM_5700SendPacket(pDevice, pPacket); + } + + /* Update the SendBdLeft count. */ + atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Initalize the send buffer descriptors. */ + Idx = pDevice->SendProdIdx; + + pSendBd = &pDevice->pSendBdVirt[Idx]; + + /* Next producer index. */ + if (pDevice->NicSendBd == TRUE) + { + T3_64BIT_HOST_ADDR paddr; + + pShadowSendBd = &pDevice->ShadowSendBd[Idx]; + for(FragCount = 0; ; ) + { + MM_MapTxDma(pDevice, pPacket, &paddr, &Len, FragCount); + /* Initialize the pointer to the send buffer fragment. */ + if (paddr.High != pShadowSendBd->HostAddr.High) + { + __raw_writel(paddr.High, &(pSendBd->HostAddr.High)); + pShadowSendBd->HostAddr.High = paddr.High; + } + __raw_writel(paddr.Low, &(pSendBd->HostAddr.Low)); + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) + { + Value32 |= SND_BD_FLAG_END; + if (Value32 != pShadowSendBd->u1.Len_Flags) + { + __raw_writel(Value32, &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { + __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag)); + } + break; + } + else + { + if (Value32 != pShadowSendBd->u1.Len_Flags) + { + __raw_writel(Value32, &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) { + __raw_writel(pPacket->VlanTag, &(pSendBd->u2.VlanTag)); + } + } + + pSendBd++; + pShadowSendBd++; + if (Idx == 0) + { + pSendBd = &pDevice->pSendBdVirt[0]; + pShadowSendBd = &pDevice->ShadowSendBd[0]; + } + } /* for */ + + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket); + + wmb(); + MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + + } + else + { + for(FragCount = 0; ; ) + { + /* Initialize the pointer to the send buffer fragment. */ + MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount); + + pSendBd->u2.VlanTag = pPacket->VlanTag; + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) + { + pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END; + break; + } + else + { + pSendBd->u1.Len_Flags = Value32; + } + pSendBd++; + if (Idx == 0) + { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } /* for */ + + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket); + + wmb(); + MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); + + } + + /* Update the producer index. */ + pDevice->SendProdIdx = Idx; + + return LM_STATUS_SUCCESS; +} +#endif + +LM_STATUS +LM_SendPacket(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket) +{ + LM_UINT32 FragCount; + PT3_SND_BD pSendBd, pTmpSendBd, pShadowSendBd; + T3_SND_BD NicSendBdArr[MAX_FRAGMENT_COUNT]; + LM_UINT32 StartIdx, Idx; + + while (1) + { + /* Initalize the send buffer descriptors. */ + StartIdx = Idx = pDevice->SendProdIdx; + + if (pDevice->NicSendBd) + { + pTmpSendBd = pSendBd = &NicSendBdArr[0]; + } + else + { + pTmpSendBd = pSendBd = &pDevice->pSendBdVirt[Idx]; + } + + /* Next producer index. */ + for(FragCount = 0; ; ) + { + LM_UINT32 Value32, Len; + + /* Initialize the pointer to the send buffer fragment. */ + MM_MapTxDma(pDevice, pPacket, &pSendBd->HostAddr, &Len, FragCount); + + pSendBd->u2.VlanTag = pPacket->VlanTag; + + /* Setup the control flags and send buffer size. */ + Value32 = (Len << 16) | pPacket->Flags; + + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) + { + pSendBd->u1.Len_Flags = Value32 | SND_BD_FLAG_END; + break; + } + else + { + pSendBd->u1.Len_Flags = Value32; + } + pSendBd++; + if ((Idx == 0) && !pDevice->NicSendBd) + { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } /* for */ + if (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + if (LM_Test4GBoundary(pDevice, pPacket, pTmpSendBd) == + LM_STATUS_SUCCESS) + { + if (MM_CoalesceTxBuffer(pDevice, pPacket) != LM_STATUS_SUCCESS) + { + QQ_PushHead(&pDevice->TxPacketFreeQ.Container, pPacket); + return LM_STATUS_FAILURE; + } + continue; + } + } + break; + } + /* Put the packet descriptor in the ActiveQ. */ + QQ_PushTail(&pDevice->TxPacketActiveQ.Container, pPacket); + + if (pDevice->NicSendBd) + { + pSendBd = &pDevice->pSendBdVirt[StartIdx]; + pShadowSendBd = &pDevice->ShadowSendBd[StartIdx]; + + while (StartIdx != Idx) + { + LM_UINT32 Value32; + + if ((Value32 = pTmpSendBd->HostAddr.High) != + pShadowSendBd->HostAddr.High) + { + __raw_writel(Value32, &(pSendBd->HostAddr.High)); + pShadowSendBd->HostAddr.High = Value32; + } + + __raw_writel(pTmpSendBd->HostAddr.Low, &(pSendBd->HostAddr.Low)); + + if ((Value32 = pTmpSendBd->u1.Len_Flags) != + pShadowSendBd->u1.Len_Flags) + { + __raw_writel(Value32, &(pSendBd->u1.Len_Flags)); + pShadowSendBd->u1.Len_Flags = Value32; + } + + if (pPacket->Flags & SND_BD_FLAG_VLAN_TAG) + { + __raw_writel(pTmpSendBd->u2.VlanTag, &(pSendBd->u2.VlanTag)); + } + + StartIdx = (StartIdx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + if (StartIdx == 0) + pSendBd = &pDevice->pSendBdVirt[0]; + else + pSendBd++; + pTmpSendBd++; + } + wmb(); + MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + + if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) + { + MB_REG_WR(pDevice, Mailbox.SendNicProdIdx[0].Low, Idx); + } + } + else + { + wmb(); + MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); + + if(T3_CHIP_REV(pDevice->ChipRevId) == T3_CHIP_REV_5700_BX) + { + MB_REG_WR(pDevice, Mailbox.SendHostProdIdx[0].Low, Idx); + } + } + + /* Update the SendBdLeft count. */ + atomic_sub(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Update the producer index. */ + pDevice->SendProdIdx = Idx; + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS +LM_Test4GBoundary(PLM_DEVICE_BLOCK pDevice, PLM_PACKET pPacket, + PT3_SND_BD pSendBd) +{ + int FragCount; + LM_UINT32 Idx, Base, Len; + + Idx = pDevice->SendProdIdx; + for(FragCount = 0; ; ) + { + Len = pSendBd->u1.Len_Flags >> 16; + if (((Base = pSendBd->HostAddr.Low) > 0xffffdcc0) && + (pSendBd->HostAddr.High == 0) && + ((Base + 8 + Len) < Base)) + { + return LM_STATUS_SUCCESS; + } + FragCount++; + if (FragCount >= pPacket->u.Tx.FragCount) + { + break; + } + pSendBd++; + if (!pDevice->NicSendBd) + { + Idx = (Idx + 1) & T3_SEND_RCB_ENTRY_COUNT_MASK; + if (Idx == 0) + { + pSendBd = &pDevice->pSendBdVirt[0]; + } + } + } + return LM_STATUS_FAILURE; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static unsigned long +ComputeCrc32( +unsigned char *pBuffer, +unsigned long BufferSize) { + unsigned long Reg; + unsigned long Tmp; + unsigned long j, k; + + Reg = 0xffffffff; + + for(j = 0; j < BufferSize; j++) + { + Reg ^= pBuffer[j]; + + for(k = 0; k < 8; k++) + { + Tmp = Reg & 0x01; + + Reg >>= 1; + + if(Tmp) + { + Reg ^= 0xedb88320; + } + } + } + + return ~Reg; +} /* ComputeCrc32 */ + + + +/******************************************************************************/ +/* Description: */ +/* This routine sets the receive control register according to ReceiveMask */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_SetReceiveMask( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 Mask) { + LM_UINT32 ReceiveMask; + LM_UINT32 RxMode; + LM_UINT32 j, k; + + ReceiveMask = Mask; + + RxMode = pDevice->RxMode; + + if(Mask & LM_ACCEPT_UNICAST) + { + Mask &= ~LM_ACCEPT_UNICAST; + } + + if(Mask & LM_ACCEPT_MULTICAST) + { + Mask &= ~LM_ACCEPT_MULTICAST; + } + + if(Mask & LM_ACCEPT_ALL_MULTICAST) + { + Mask &= ~LM_ACCEPT_ALL_MULTICAST; + } + + if(Mask & LM_ACCEPT_BROADCAST) + { + Mask &= ~LM_ACCEPT_BROADCAST; + } + + RxMode &= ~RX_MODE_PROMISCUOUS_MODE; + if(Mask & LM_PROMISCUOUS_MODE) + { + RxMode |= RX_MODE_PROMISCUOUS_MODE; + Mask &= ~LM_PROMISCUOUS_MODE; + } + + RxMode &= ~(RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED); + if(Mask & LM_ACCEPT_ERROR_PACKET) + { + RxMode |= RX_MODE_ACCEPT_RUNTS | RX_MODE_ACCEPT_OVERSIZED; + Mask &= ~LM_ACCEPT_ERROR_PACKET; + } + + /* Make sure all the bits are valid before committing changes. */ + if(Mask) + { + return LM_STATUS_FAILURE; + } + + /* Commit the new filter. */ + pDevice->RxMode = RxMode; + REG_WR(pDevice, MacCtrl.RxMode, RxMode); + + pDevice->ReceiveMask = ReceiveMask; + + /* Set up the MC hash table. */ + if(ReceiveMask & LM_ACCEPT_ALL_MULTICAST) + { + for(k = 0; k < 4; k++) + { + REG_WR(pDevice, MacCtrl.HashReg[k], 0xffffffff); + } + } + else if(ReceiveMask & LM_ACCEPT_MULTICAST) + { + LM_UINT32 HashReg[4]; + + HashReg[0] = 0; HashReg[1] = 0; HashReg[2] = 0; HashReg[3] = 0; + for(j = 0; j < pDevice->McEntryCount; j++) + { + LM_UINT32 RegIndex; + LM_UINT32 Bitpos; + LM_UINT32 Crc32; + + Crc32 = ComputeCrc32(pDevice->McTable[j], ETHERNET_ADDRESS_SIZE); + + /* The most significant 7 bits of the CRC32 (no inversion), */ + /* are used to index into one of the possible 128 bit positions. */ + Bitpos = ~Crc32 & 0x7f; + + /* Hash register index. */ + RegIndex = (Bitpos & 0x60) >> 5; + + /* Bit to turn on within a hash register. */ + Bitpos &= 0x1f; + + /* Enable the multicast bit. */ + HashReg[RegIndex] |= (1 << Bitpos); + } + + /* REV_AX has problem with multicast filtering where it uses both */ + /* DA and SA to perform hashing. */ + for(k = 0; k < 4; k++) + { + REG_WR(pDevice, MacCtrl.HashReg[k], HashReg[k]); + } + } + else + { + /* Reject all multicast frames. */ + for(j = 0; j < 4; j++) + { + REG_WR(pDevice, MacCtrl.HashReg[j], 0); + } + } + + /* By default, Tigon3 will accept broadcast frames. We need to setup */ + if(ReceiveMask & LM_ACCEPT_BROADCAST) + { + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE & RCV_DISABLE_RULE_MASK); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE & RCV_DISABLE_RULE_MASK); + } + else + { + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE1_RULE); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE1_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE1_VALUE); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Rule, + REJECT_BROADCAST_RULE2_RULE); + REG_WR(pDevice, MacCtrl.RcvRules[RCV_RULE2_REJECT_BROADCAST_IDX].Value, + REJECT_BROADCAST_RULE2_VALUE); + } + + /* disable the rest of the rules. */ + for(j = RCV_LAST_RULE_IDX; j < 16; j++) + { + REG_WR(pDevice, MacCtrl.RcvRules[j].Rule, 0); + REG_WR(pDevice, MacCtrl.RcvRules[j].Value, 0); + } + + return LM_STATUS_SUCCESS; +} /* LM_SetReceiveMask */ + + + +/******************************************************************************/ +/* Description: */ +/* Disable the interrupt and put the transmitter and receiver engines in */ +/* an idle state. Also aborts all pending send requests and receive */ +/* buffers. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_Abort( +PLM_DEVICE_BLOCK pDevice) +{ + PLM_PACKET pPacket; + LM_UINT Idx; + + LM_DisableInterrupt(pDevice); + + /* Disable all the state machines. */ + LM_CntrlBlock(pDevice,T3_BLOCK_MAC_RX_ENGINE,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_INITIATOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_PLMT,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_LIST_SELECTOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_INITIATOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_DATA_COMP,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_RX_BD_COMP,LM_DISABLE); + + LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_SELECTOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_INITIATOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_INITIATOR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_DMA_RD,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_SEND_DATA_COMP,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_DMA_COMP,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_SEND_BD_COMP,LM_DISABLE); + + /* Clear TDE bit */ + pDevice->MacMode &= ~MAC_MODE_ENABLE_TDE; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + + LM_CntrlBlock(pDevice,T3_BLOCK_MAC_TX_ENGINE,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_HOST_COALESING,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_DMA_WR,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_CLUSTER_FREE,LM_DISABLE); + + /* Reset all FTQs */ + REG_WR(pDevice, Ftq.Reset, 0xffffffff); + REG_WR(pDevice, Ftq.Reset, 0x0); + + LM_CntrlBlock(pDevice,T3_BLOCK_MBUF_MANAGER,LM_DISABLE); + LM_CntrlBlock(pDevice,T3_BLOCK_MEM_ARBITOR,LM_DISABLE); + + MM_ACQUIRE_INT_LOCK(pDevice); + + /* Abort packets that have already queued to go out. */ + pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->TxPacketActiveQ.Container); + while(pPacket) + { + + pPacket->PacketStatus = LM_STATUS_TRANSMIT_ABORTED; + pDevice->TxCounters.TxPacketAbortedCnt++; + + atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket); + + pPacket = (PLM_PACKET) + QQ_PopHead(&pDevice->TxPacketActiveQ.Container); + } + + /* Cleanup the receive return rings. */ + LM_ServiceRxInterrupt(pDevice); + + /* Don't want to indicate rx packets in Ndis miniport shutdown context. */ + /* Doing so may cause system crash. */ + if(!pDevice->ShuttingDown) + { + /* Indicate packets to the protocol. */ + MM_IndicateTxPackets(pDevice); + + /* Indicate received packets to the protocols. */ + MM_IndicateRxPackets(pDevice); + } + else + { + /* Move the receive packet descriptors in the ReceivedQ to the */ + /* free queue. */ + for(; ;) + { + pPacket = (PLM_PACKET) QQ_PopHead( + &pDevice->RxPacketReceivedQ.Container); + if(pPacket == NULL) + { + break; + } + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + } + } + + /* Clean up the Std Receive Producer ring. */ + Idx = pDevice->pStatusBlkVirt->RcvStdConIdx; + + while(Idx != pDevice->RxStdProdIdx) { + pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) + + MM_UINT_PTR(pDevice->pRxStdBdVirt[Idx].Opaque)); + + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + + Idx = (Idx + 1) & T3_STD_RCV_RCB_ENTRY_COUNT_MASK; + } /* while */ + + /* Reinitialize our copy of the indices. */ + pDevice->RxStdProdIdx = 0; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + /* Clean up the Jumbo Receive Producer ring. */ + Idx = pDevice->pStatusBlkVirt->RcvJumboConIdx; + + while(Idx != pDevice->RxJumboProdIdx) { + pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) + + MM_UINT_PTR(pDevice->pRxJumboBdVirt[Idx].Opaque)); + + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + + Idx = (Idx + 1) & T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK; + } /* while */ + + /* Reinitialize our copy of the indices. */ + pDevice->RxJumboProdIdx = 0; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + MM_RELEASE_INT_LOCK(pDevice); + + /* Initialize the statistis Block */ + pDevice->pStatusBlkVirt->Status = 0; + pDevice->pStatusBlkVirt->RcvStdConIdx = 0; + pDevice->pStatusBlkVirt->RcvJumboConIdx = 0; + pDevice->pStatusBlkVirt->RcvMiniConIdx = 0; + + return LM_STATUS_SUCCESS; +} /* LM_Abort */ + + + +/******************************************************************************/ +/* Description: */ +/* Disable the interrupt and put the transmitter and receiver engines in */ +/* an idle state. Aborts all pending send requests and receive buffers. */ +/* Also free all the receive buffers. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_Halt( +PLM_DEVICE_BLOCK pDevice) { + PLM_PACKET pPacket; + LM_UINT32 EntryCnt; + + LM_Abort(pDevice); + + /* Get the number of entries in the queue. */ + EntryCnt = QQ_GetEntryCnt(&pDevice->RxPacketFreeQ.Container); + + /* Make sure all the packets have been accounted for. */ + for(EntryCnt = 0; EntryCnt < pDevice->RxPacketDescCnt; EntryCnt++) + { + pPacket = (PLM_PACKET) QQ_PopHead(&pDevice->RxPacketFreeQ.Container); + if (pPacket == 0) + break; + + MM_FreeRxBuffer(pDevice, pPacket); + + QQ_PushTail(&pDevice->RxPacketFreeQ.Container, pPacket); + } + + LM_ResetChip(pDevice); + + /* Restore PCI configuration registers. */ + MM_WriteConfig32(pDevice, PCI_CACHE_LINE_SIZE_REG, + pDevice->SavedCacheLineReg); + LM_RegWrInd(pDevice, PCI_SUBSYSTEM_VENDOR_ID_REG, + (pDevice->SubsystemId << 16) | pDevice->SubsystemVendorId); + + /* Reprogram the MAC address. */ + LM_SetMacAddress(pDevice, pDevice->NodeAddress); + + return LM_STATUS_SUCCESS; +} /* LM_Halt */ + + +STATIC LM_STATUS +LM_ResetChip(PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + /* Wait for access to the nvram interface before resetting. This is */ + /* a workaround to prevent EEPROM corruption. */ + if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) + { + /* Request access to the flash interface. */ + REG_WR(pDevice, Nvram.SwArb, SW_ARB_REQ_SET1); + + for(j = 0; j < 100000; j++) + { + Value32 = REG_RD(pDevice, Nvram.SwArb); + if(Value32 & SW_ARB_GNT1) + { + break; + } + MM_Wait(10); + } + } + + /* Global reset. */ + REG_WR(pDevice, Grc.MiscCfg, GRC_MISC_CFG_CORE_CLOCK_RESET); + MM_Wait(40); MM_Wait(40); MM_Wait(40); + + /* make sure we re-enable indirect accesses */ + MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, + pDevice->MiscHostCtrl); + + /* Set MAX PCI retry to zero. */ + Value32 = T3_PCI_STATE_PCI_ROM_ENABLE | T3_PCI_STATE_PCI_ROM_RETRY_ENABLE; + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) + { + Value32 |= T3_PCI_STATE_RETRY_SAME_DMA; + } + } + MM_WriteConfig32(pDevice, T3_PCI_STATE_REG, Value32); + + /* Restore PCI command register. */ + MM_WriteConfig32(pDevice, PCI_COMMAND_REG, + pDevice->PciCommandStatusWords); + + /* Disable PCI-X relaxed ordering bit. */ + MM_ReadConfig32(pDevice, PCIX_CAP_REG, &Value32); + Value32 &= ~PCIX_ENABLE_RELAXED_ORDERING; + MM_WriteConfig32(pDevice, PCIX_CAP_REG, Value32); + + /* Enable memory arbiter. */ + REG_WR(pDevice, MemArbiter.Mode, T3_MEM_ARBITER_MODE_ENABLE); + +#ifdef BIG_ENDIAN_PCI /* This from jfd */ + Value32 = GRC_MODE_WORD_SWAP_DATA| + GRC_MODE_WORD_SWAP_NON_FRAME_DATA; +#else +#ifdef BIG_ENDIAN_HOST + /* Reconfigure the mode register. */ + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | + GRC_MODE_WORD_SWAP_NON_FRAME_DATA | + GRC_MODE_BYTE_SWAP_DATA | + GRC_MODE_WORD_SWAP_DATA; +#else + /* Reconfigure the mode register. */ + Value32 = GRC_MODE_BYTE_SWAP_NON_FRAME_DATA | GRC_MODE_BYTE_SWAP_DATA; +#endif +#endif + REG_WR(pDevice, Grc.Mode, Value32); + + /* Prevent PXE from restarting. */ + MEM_WR_OFFSET(pDevice, 0x0b50, T3_MAGIC_NUM); + + if(pDevice->EnableTbi) { + pDevice->MacMode = MAC_MODE_PORT_MODE_TBI; + REG_WR(pDevice, MacCtrl.Mode, MAC_MODE_PORT_MODE_TBI); + } + else { + REG_WR(pDevice, MacCtrl.Mode, 0); + } + + /* Wait for the firmware to finish initialization. */ + for(j = 0; j < 100000; j++) + { + MM_Wait(10); + + Value32 = MEM_RD_OFFSET(pDevice, 0x0b50); + if(Value32 == ~T3_MAGIC_NUM) + { + break; + } + } + return LM_STATUS_SUCCESS; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static void +LM_ServiceTxInterrupt( +PLM_DEVICE_BLOCK pDevice) { + PLM_PACKET pPacket; + LM_UINT32 HwConIdx; + LM_UINT32 SwConIdx; + + HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; + + /* Get our copy of the consumer index. The buffer descriptors */ + /* that are in between the consumer indices are freed. */ + SwConIdx = pDevice->SendConIdx; + + /* Move the packets from the TxPacketActiveQ that are sent out to */ + /* the TxPacketXmittedQ. Packets that are sent use the */ + /* descriptors that are between SwConIdx and HwConIdx. */ + while(SwConIdx != HwConIdx) + { + /* Get the packet that was sent from the TxPacketActiveQ. */ + pPacket = (PLM_PACKET) QQ_PopHead( + &pDevice->TxPacketActiveQ.Container); + + /* Set the return status. */ + pPacket->PacketStatus = LM_STATUS_SUCCESS; + + /* Put the packet in the TxPacketXmittedQ for indication later. */ + QQ_PushTail(&pDevice->TxPacketXmittedQ.Container, pPacket); + + /* Move to the next packet's BD. */ + SwConIdx = (SwConIdx + pPacket->u.Tx.FragCount) & + T3_SEND_RCB_ENTRY_COUNT_MASK; + + /* Update the number of unused BDs. */ + atomic_add(pPacket->u.Tx.FragCount, &pDevice->SendBdLeft); + + /* Get the new updated HwConIdx. */ + HwConIdx = pDevice->pStatusBlkVirt->Idx[0].SendConIdx; + } /* while */ + + /* Save the new SwConIdx. */ + pDevice->SendConIdx = SwConIdx; + +} /* LM_ServiceTxInterrupt */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +__inline static void +LM_ServiceRxInterrupt( +PLM_DEVICE_BLOCK pDevice) { + PLM_PACKET pPacket; + PT3_RCV_BD pRcvBd; + LM_UINT32 HwRcvRetProdIdx; + LM_UINT32 SwRcvRetConIdx; + + /* Loop thru the receive return rings for received packets. */ + HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; + + SwRcvRetConIdx = pDevice->RcvRetConIdx; + while(SwRcvRetConIdx != HwRcvRetProdIdx) + { + pRcvBd = &pDevice->pRcvRetBdVirt[SwRcvRetConIdx]; + + /* Get the received packet descriptor. */ + pPacket = (PLM_PACKET) (MM_UINT_PTR(pDevice->pPacketDescBase) + + MM_UINT_PTR(pRcvBd->Opaque)); + + /* Check the error flag. */ + if(pRcvBd->ErrorFlag && + pRcvBd->ErrorFlag != RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) + { + pPacket->PacketStatus = LM_STATUS_FAILURE; + + pDevice->RxCounters.RxPacketErrCnt++; + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_BAD_CRC) + { + pDevice->RxCounters.RxErrCrcCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_COLL_DETECT) + { + pDevice->RxCounters.RxErrCollCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_LINK_LOST_DURING_PKT) + { + pDevice->RxCounters.RxErrLinkLostCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_PHY_DECODE_ERR) + { + pDevice->RxCounters.RxErrPhyDecodeCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_ODD_NIBBLED_RCVD_MII) + { + pDevice->RxCounters.RxErrOddNibbleCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_MAC_ABORT) + { + pDevice->RxCounters.RxErrMacAbortCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_LEN_LT_64) + { + pDevice->RxCounters.RxErrShortPacketCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_TRUNC_NO_RESOURCES) + { + pDevice->RxCounters.RxErrNoResourceCnt++; + } + + if(pRcvBd->ErrorFlag & RCV_BD_ERR_GIANT_FRAME_RCVD) + { + pDevice->RxCounters.RxErrLargePacketCnt++; + } + } + else + { + pPacket->PacketStatus = LM_STATUS_SUCCESS; + pPacket->PacketSize = pRcvBd->Len - 4; + + pPacket->Flags = pRcvBd->Flags; + if(pRcvBd->Flags & RCV_BD_FLAG_VLAN_TAG) + { + pPacket->VlanTag = pRcvBd->VlanTag; + } + + pPacket->u.Rx.TcpUdpChecksum = pRcvBd->TcpUdpCksum; + } + + /* Put the packet descriptor containing the received packet */ + /* buffer in the RxPacketReceivedQ for indication later. */ + QQ_PushTail(&pDevice->RxPacketReceivedQ.Container, pPacket); + + /* Go to the next buffer descriptor. */ + SwRcvRetConIdx = (SwRcvRetConIdx + 1) & + T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK; + + /* Get the updated HwRcvRetProdIdx. */ + HwRcvRetProdIdx = pDevice->pStatusBlkVirt->Idx[0].RcvProdIdx; + } /* while */ + + pDevice->RcvRetConIdx = SwRcvRetConIdx; + + /* Update the receive return ring consumer index. */ + MB_REG_WR(pDevice, Mailbox.RcvRetConIdx[0].Low, SwRcvRetConIdx); +} /* LM_ServiceRxInterrupt */ + + + +/******************************************************************************/ +/* Description: */ +/* This is the interrupt event handler routine. It acknowledges all */ +/* pending interrupts and process all pending events. */ +/* */ +/* Return: */ +/* LM_STATUS_SUCCESS */ +/******************************************************************************/ +LM_STATUS +LM_ServiceInterrupts( + PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + int ServicePhyInt = FALSE; + + /* Setup the phy chip whenever the link status changes. */ + if(pDevice->LinkChngMode == T3_LINK_CHNG_MODE_USE_STATUS_REG) + { + Value32 = REG_RD(pDevice, MacCtrl.Status); + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) + { + if (Value32 & MAC_STATUS_MI_INTERRUPT) + { + ServicePhyInt = TRUE; + } + } + else if(Value32 & MAC_STATUS_LINK_STATE_CHANGED) + { + ServicePhyInt = TRUE; + } + } + else + { + if(pDevice->pStatusBlkVirt->Status & STATUS_BLOCK_LINK_CHANGED_STATUS) + { + pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED | + (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS); + ServicePhyInt = TRUE; + } + } +#if INCLUDE_TBI_SUPPORT + if (pDevice->IgnoreTbiLinkChange == TRUE) + { + ServicePhyInt = FALSE; + } +#endif + if (ServicePhyInt == TRUE) + { + LM_SetupPhy(pDevice); + } + + /* Service receive and transmit interrupts. */ + LM_ServiceRxInterrupt(pDevice); + LM_ServiceTxInterrupt(pDevice); + + /* No spinlock for this queue since this routine is serialized. */ + if(!QQ_Empty(&pDevice->RxPacketReceivedQ.Container)) + { + /* Indicate receive packets. */ + MM_IndicateRxPackets(pDevice); + /* LM_QueueRxPackets(pDevice); */ + } + + /* No spinlock for this queue since this routine is serialized. */ + if(!QQ_Empty(&pDevice->TxPacketXmittedQ.Container)) + { + MM_IndicateTxPackets(pDevice); + } + + return LM_STATUS_SUCCESS; +} /* LM_ServiceInterrupts */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_MulticastAdd( +PLM_DEVICE_BLOCK pDevice, +PLM_UINT8 pMcAddress) { + PLM_UINT8 pEntry; + LM_UINT32 j; + + pEntry = pDevice->McTable[0]; + for(j = 0; j < pDevice->McEntryCount; j++) + { + if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress)) + { + /* Found a match, increment the instance count. */ + pEntry[LM_MC_INSTANCE_COUNT_INDEX] += 1; + + return LM_STATUS_SUCCESS; + } + + pEntry += LM_MC_ENTRY_SIZE; + } + + if(pDevice->McEntryCount >= LM_MAX_MC_TABLE_SIZE) + { + return LM_STATUS_FAILURE; + } + + pEntry = pDevice->McTable[pDevice->McEntryCount]; + + COPY_ETH_ADDRESS(pMcAddress, pEntry); + pEntry[LM_MC_INSTANCE_COUNT_INDEX] = 1; + + pDevice->McEntryCount++; + + LM_SetReceiveMask(pDevice, pDevice->ReceiveMask | LM_ACCEPT_MULTICAST); + + return LM_STATUS_SUCCESS; +} /* LM_MulticastAdd */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_MulticastDel( +PLM_DEVICE_BLOCK pDevice, +PLM_UINT8 pMcAddress) { + PLM_UINT8 pEntry; + LM_UINT32 j; + + pEntry = pDevice->McTable[0]; + for(j = 0; j < pDevice->McEntryCount; j++) + { + if(IS_ETH_ADDRESS_EQUAL(pEntry, pMcAddress)) + { + /* Found a match, decrement the instance count. */ + pEntry[LM_MC_INSTANCE_COUNT_INDEX] -= 1; + + /* No more instance left, remove the address from the table. */ + /* Move the last entry in the table to the delete slot. */ + if(pEntry[LM_MC_INSTANCE_COUNT_INDEX] == 0 && + pDevice->McEntryCount > 1) + { + + COPY_ETH_ADDRESS( + pDevice->McTable[pDevice->McEntryCount-1], pEntry); + pEntry[LM_MC_INSTANCE_COUNT_INDEX] = + pDevice->McTable[pDevice->McEntryCount-1] + [LM_MC_INSTANCE_COUNT_INDEX]; + } + pDevice->McEntryCount--; + + /* Update the receive mask if the table is empty. */ + if(pDevice->McEntryCount == 0) + { + LM_SetReceiveMask(pDevice, + pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); + } + + return LM_STATUS_SUCCESS; + } + + pEntry += LM_MC_ENTRY_SIZE; + } + + return LM_STATUS_FAILURE; +} /* LM_MulticastDel */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_MulticastClear( +PLM_DEVICE_BLOCK pDevice) { + pDevice->McEntryCount = 0; + + LM_SetReceiveMask(pDevice, pDevice->ReceiveMask & ~LM_ACCEPT_MULTICAST); + + return LM_STATUS_SUCCESS; +} /* LM_MulticastClear */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetMacAddress( + PLM_DEVICE_BLOCK pDevice, + PLM_UINT8 pMacAddress) +{ + LM_UINT32 j; + + for(j = 0; j < 4; j++) + { + REG_WR(pDevice, MacCtrl.MacAddr[j].High, + (pMacAddress[0] << 8) | pMacAddress[1]); + REG_WR(pDevice, MacCtrl.MacAddr[j].Low, + (pMacAddress[2] << 24) | (pMacAddress[3] << 16) | + (pMacAddress[4] << 8) | pMacAddress[5]); + } + + return LM_STATUS_SUCCESS; +} + + +/******************************************************************************/ +/* Description: */ +/* Sets up the default line speed, and duplex modes based on the requested */ +/* media type. */ +/* */ +/* Return: */ +/* None. */ +/******************************************************************************/ +static LM_STATUS +LM_TranslateRequestedMediaType( +LM_REQUESTED_MEDIA_TYPE RequestedMediaType, +PLM_MEDIA_TYPE pMediaType, +PLM_LINE_SPEED pLineSpeed, +PLM_DUPLEX_MODE pDuplexMode) { + *pMediaType = LM_MEDIA_TYPE_AUTO; + *pLineSpeed = LM_LINE_SPEED_UNKNOWN; + *pDuplexMode = LM_DUPLEX_MODE_UNKNOWN; + + /* determine media type */ + switch(RequestedMediaType) { + case LM_REQUESTED_MEDIA_TYPE_BNC: + *pMediaType = LM_MEDIA_TYPE_BNC; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_AUTO: + *pMediaType = LM_MEDIA_TYPE_UTP; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_10MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_100MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_UTP_1000MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_UTP; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_100MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_100MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case LM_REQUESTED_MEDIA_TYPE_FIBER_1000MBPS_FULL_DUPLEX: + *pMediaType = LM_MEDIA_TYPE_FIBER; + *pLineSpeed = LM_LINE_SPEED_1000MBPS; + *pDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + default: + break; + } /* switch */ + + return LM_STATUS_SUCCESS; +} /* LM_TranslateRequestedMediaType */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* LM_STATUS_LINK_ACTIVE */ +/* LM_STATUS_LINK_DOWN */ +/******************************************************************************/ +static LM_STATUS +LM_InitBcm540xPhy( +PLM_DEVICE_BLOCK pDevice) +{ + LM_LINE_SPEED CurrentLineSpeed; + LM_DUPLEX_MODE CurrentDuplexMode; + LM_STATUS CurrentLinkStatus; + LM_UINT32 Value32; + LM_UINT32 j; + +#if 1 /* jmb: bugfix -- moved here, out of code that sets initial pwr state */ + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x2); +#endif + if((pDevice->PhyId & PHY_ID_MASK) == PHY_BCM5401_PHY_ID) + { + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + + if(!pDevice->InitDone) + { + Value32 = 0; + } + + if(!(Value32 & PHY_STATUS_LINK_PASS)) + { + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20); + + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + for(j = 0; j < 1000; j++) + { + MM_Wait(10); + + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + if(Value32 & PHY_STATUS_LINK_PASS) + { + MM_Wait(40); + break; + } + } + + if((pDevice->PhyId & PHY_ID_REV_MASK) == PHY_BCM5401_B0_REV) + { + if(!(Value32 & PHY_STATUS_LINK_PASS) && + (pDevice->OldLineSpeed == LM_LINE_SPEED_1000MBPS)) + { + LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); + for(j = 0; j < 100; j++) + { + MM_Wait(10); + + LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); + if(!(Value32 & PHY_CTRL_PHY_RESET)) + { + MM_Wait(40); + break; + } + } + + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x0c20); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0012); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1804); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x0013); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x1204); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0132); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x8006); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0232); + + LM_WritePhy(pDevice, BCM540X_DSP_ADDRESS_REG, 0x201f); + LM_WritePhy(pDevice, BCM540X_DSP_RW_PORT, 0x0a20); + } + } + } + } + else if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) + { + /* Bug: 5701 A0, B0 TX CRC workaround. */ + LM_WritePhy(pDevice, 0x15, 0x0a75); + LM_WritePhy(pDevice, 0x1c, 0x8c68); + LM_WritePhy(pDevice, 0x1c, 0x8d68); + LM_WritePhy(pDevice, 0x1c, 0x8c68); + } + + /* Acknowledge interrupts. */ + LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, BCM540X_INT_STATUS_REG, &Value32); + + /* Configure the interrupt mask. */ + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) + { + LM_WritePhy(pDevice, BCM540X_INT_MASK_REG, ~BCM540X_INT_LINK_CHANGE); + } + + /* Configure PHY led mode. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701 || + (T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700)) + { + if(pDevice->LedMode == LED_MODE_THREE_LINK) + { + LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, + BCM540X_EXT_CTRL_LINK3_LED_MODE); + } + else + { + LM_WritePhy(pDevice, BCM540X_EXT_CTRL_REG, 0); + } + } + + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Get current link and duplex mode. */ + for(j = 0; j < 100; j++) + { + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + + if(Value32 & PHY_STATUS_LINK_PASS) + { + break; + } + MM_Wait(40); + } + + if(Value32 & PHY_STATUS_LINK_PASS) + { + + /* Determine the current line and duplex settings. */ + LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32); + for(j = 0; j < 2000; j++) + { + MM_Wait(10); + + LM_ReadPhy(pDevice, BCM540X_AUX_STATUS_REG, &Value32); + if(Value32) + { + break; + } + } + + switch(Value32 & BCM540X_AUX_SPEED_MASK) + { + case BCM540X_AUX_10BASET_HD: + CurrentLineSpeed = LM_LINE_SPEED_10MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_10BASET_FD: + CurrentLineSpeed = LM_LINE_SPEED_10MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case BCM540X_AUX_100BASETX_HD: + CurrentLineSpeed = LM_LINE_SPEED_100MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_100BASETX_FD: + CurrentLineSpeed = LM_LINE_SPEED_100MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + case BCM540X_AUX_100BASET_HD: + CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_HALF; + break; + + case BCM540X_AUX_100BASET_FD: + CurrentLineSpeed = LM_LINE_SPEED_1000MBPS; + CurrentDuplexMode = LM_DUPLEX_MODE_FULL; + break; + + default: + + CurrentLineSpeed = LM_LINE_SPEED_UNKNOWN; + CurrentDuplexMode = LM_DUPLEX_MODE_UNKNOWN; + break; + } + + /* Make sure we are in auto-neg mode. */ + for (j = 0; j < 200; j++) + { + LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); + if(Value32 && Value32 != 0x7fff) + { + break; + } + + if(Value32 == 0 && pDevice->RequestedMediaType == + LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS) + { + break; + } + + MM_Wait(10); + } + + /* Use the current line settings for "auto" mode. */ + if(pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) + { + if(Value32 & PHY_CTRL_AUTO_NEG_ENABLE) + { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + + /* We may be exiting low power mode and the link is in */ + /* 10mb. In this case, we need to restart autoneg. */ + LM_ReadPhy(pDevice, BCM540X_1000BASET_CTRL_REG, &Value32); + pDevice->advertising1000 = Value32; + /* 5702FE supports 10/100Mb only. */ + if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5703 || + pDevice->BondId != GRC_MISC_BD_ID_5702FE) + { + if(!(Value32 & (BCM540X_AN_AD_1000BASET_HALF | + BCM540X_AN_AD_1000BASET_FULL))) + { + CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH; + } + } + } + else + { + CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH; + } + } + else + { + /* Force line settings. */ + /* Use the current setting if it matches the user's requested */ + /* setting. */ + LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); + if((pDevice->LineSpeed == CurrentLineSpeed) && + (pDevice->DuplexMode == CurrentDuplexMode)) + { + if ((pDevice->DisableAutoNeg && + !(Value32 & PHY_CTRL_AUTO_NEG_ENABLE)) || + (!pDevice->DisableAutoNeg && + (Value32 & PHY_CTRL_AUTO_NEG_ENABLE))) + { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + else + { + CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH; + } + } + else + { + CurrentLinkStatus = LM_STATUS_LINK_SETTING_MISMATCH; + } + } + + /* Save line settings. */ + pDevice->LineSpeed = CurrentLineSpeed; + pDevice->DuplexMode = CurrentDuplexMode; + pDevice->MediaType = LM_MEDIA_TYPE_UTP; + } + + return CurrentLinkStatus; +} /* LM_InitBcm540xPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetFlowControl( + PLM_DEVICE_BLOCK pDevice, + LM_UINT32 LocalPhyAd, + LM_UINT32 RemotePhyAd) +{ + LM_FLOW_CONTROL FlowCap; + + /* Resolve flow control. */ + FlowCap = LM_FLOW_CONTROL_NONE; + + /* See Table 28B-3 of 802.3ab-1999 spec. */ + if(pDevice->FlowControlCap & LM_FLOW_CONTROL_AUTO_PAUSE) + { + if(LocalPhyAd & PHY_AN_AD_PAUSE_CAPABLE) + { + if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) + { + if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) + { + FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE | + LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + else if(RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE) + { + FlowCap = LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + } + else + { + if(RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) + { + FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE | + LM_FLOW_CONTROL_RECEIVE_PAUSE; + } + } + } + else if(LocalPhyAd & PHY_AN_AD_ASYM_PAUSE) + { + if((RemotePhyAd & PHY_LINK_PARTNER_PAUSE_CAPABLE) && + (RemotePhyAd & PHY_LINK_PARTNER_ASYM_PAUSE)) + { + FlowCap = LM_FLOW_CONTROL_TRANSMIT_PAUSE; + } + } + } + else + { + FlowCap = pDevice->FlowControlCap; + } + + /* Enable/disable rx PAUSE. */ + pDevice->RxMode &= ~RX_MODE_ENABLE_FLOW_CONTROL; + if(FlowCap & LM_FLOW_CONTROL_RECEIVE_PAUSE && + (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || + pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE)) + { + pDevice->FlowControl |= LM_FLOW_CONTROL_RECEIVE_PAUSE; + pDevice->RxMode |= RX_MODE_ENABLE_FLOW_CONTROL; + + } + REG_WR(pDevice, MacCtrl.RxMode, pDevice->RxMode); + + /* Enable/disable tx PAUSE. */ + pDevice->TxMode &= ~TX_MODE_ENABLE_FLOW_CONTROL; + if(FlowCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE && + (pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE || + pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) + { + pDevice->FlowControl |= LM_FLOW_CONTROL_TRANSMIT_PAUSE; + pDevice->TxMode |= TX_MODE_ENABLE_FLOW_CONTROL; + + } + REG_WR(pDevice, MacCtrl.TxMode, pDevice->TxMode); + + return LM_STATUS_SUCCESS; +} + + +#if INCLUDE_TBI_SUPPORT +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_InitBcm800xPhy( + PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + LM_UINT32 j; + + Value32 = REG_RD(pDevice, MacCtrl.Status); + + /* Reset the SERDES during init and when we have link. */ + if(!pDevice->InitDone || Value32 & MAC_STATUS_PCS_SYNCED) + { + /* Set PLL lock range. */ + LM_WritePhy(pDevice, 0x16, 0x8007); + + /* Software reset. */ + LM_WritePhy(pDevice, 0x00, 0x8000); + + /* Wait for reset to complete. */ + for(j = 0; j < 500; j++) + { + MM_Wait(10); + } + + /* Config mode; seletct PMA/Ch 1 regs. */ + LM_WritePhy(pDevice, 0x10, 0x8411); + + /* Enable auto-lock and comdet, select txclk for tx. */ + LM_WritePhy(pDevice, 0x11, 0x0a10); + + LM_WritePhy(pDevice, 0x18, 0x00a0); + LM_WritePhy(pDevice, 0x16, 0x41ff); + + /* Assert and deassert POR. */ + LM_WritePhy(pDevice, 0x13, 0x0400); + MM_Wait(40); + LM_WritePhy(pDevice, 0x13, 0x0000); + + LM_WritePhy(pDevice, 0x11, 0x0a50); + MM_Wait(40); + LM_WritePhy(pDevice, 0x11, 0x0a10); + + /* Delay for signal to stabilize. */ + for(j = 0; j < 15000; j++) + { + MM_Wait(10); + } + + /* Deselect the channel register so we can read the PHY id later. */ + LM_WritePhy(pDevice, 0x10, 0x8011); + } + + return LM_STATUS_SUCCESS; +} + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +STATIC LM_STATUS +LM_SetupFiberPhy( + PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS CurrentLinkStatus; + AUTONEG_STATUS AnStatus = 0; + LM_UINT32 Value32; + LM_UINT32 Cnt; + LM_UINT32 j, k; + + pDevice->MacMode &= ~(MAC_MODE_HALF_DUPLEX | MAC_MODE_PORT_MODE_MASK); + + /* Initialize the send_config register. */ + REG_WR(pDevice, MacCtrl.TxAutoNeg, 0); + + /* Enable TBI and full duplex mode. */ + pDevice->MacMode |= MAC_MODE_PORT_MODE_TBI; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + + /* Initialize the BCM8002 SERDES PHY. */ + switch(pDevice->PhyId & PHY_ID_MASK) + { + case PHY_BCM8002_PHY_ID: + LM_InitBcm800xPhy(pDevice); + break; + + default: + break; + } + + /* Enable link change interrupt. */ + REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); + + /* Default to link down. */ + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Get the link status. */ + Value32 = REG_RD(pDevice, MacCtrl.Status); + if(Value32 & MAC_STATUS_PCS_SYNCED) + { + if((pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO) || + (pDevice->DisableAutoNeg == FALSE)) + { + /* auto-negotiation mode. */ + /* Initialize the autoneg default capaiblities. */ + AutonegInit(&pDevice->AnInfo); + + /* Set the context pointer to point to the main device structure. */ + pDevice->AnInfo.pContext = pDevice; + + /* Setup flow control advertisement register. */ + Value32 = GetPhyAdFlowCntrlSettings(pDevice); + if(Value32 & PHY_AN_AD_PAUSE_CAPABLE) + { + pDevice->AnInfo.mr_adv_sym_pause = 1; + } + else + { + pDevice->AnInfo.mr_adv_sym_pause = 0; + } + + if(Value32 & PHY_AN_AD_ASYM_PAUSE) + { + pDevice->AnInfo.mr_adv_asym_pause = 1; + } + else + { + pDevice->AnInfo.mr_adv_asym_pause = 0; + } + + /* Try to autoneg up to six times. */ + if (pDevice->IgnoreTbiLinkChange) + { + Cnt = 1; + } + else + { + Cnt = 6; + } + for (j = 0; j < Cnt; j++) + { + REG_WR(pDevice, MacCtrl.TxAutoNeg, 0); + + Value32 = pDevice->MacMode & ~MAC_MODE_PORT_MODE_MASK; + REG_WR(pDevice, MacCtrl.Mode, Value32); + MM_Wait(20); + + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_SEND_CONFIGS); + + MM_Wait(20); + + pDevice->AnInfo.State = AN_STATE_UNKNOWN; + pDevice->AnInfo.CurrentTime_us = 0; + + REG_WR(pDevice, Grc.Timer, 0); + for(k = 0; (pDevice->AnInfo.CurrentTime_us < 75000) && + (k < 75000); k++) + { + AnStatus = Autoneg8023z(&pDevice->AnInfo); + + if((AnStatus == AUTONEG_STATUS_DONE) || + (AnStatus == AUTONEG_STATUS_FAILED)) + { + break; + } + + pDevice->AnInfo.CurrentTime_us = REG_RD(pDevice, Grc.Timer); + + } + if((AnStatus == AUTONEG_STATUS_DONE) || + (AnStatus == AUTONEG_STATUS_FAILED)) + { + break; + } + if (j >= 1) + { + if (!(REG_RD(pDevice, MacCtrl.Status) & + MAC_STATUS_PCS_SYNCED)) { + break; + } + } + } + + /* Stop sending configs. */ + MM_AnTxIdle(&pDevice->AnInfo); + + /* Resolve flow control settings. */ + if((AnStatus == AUTONEG_STATUS_DONE) && + pDevice->AnInfo.mr_an_complete && pDevice->AnInfo.mr_link_ok && + pDevice->AnInfo.mr_lp_adv_full_duplex) + { + LM_UINT32 RemotePhyAd; + LM_UINT32 LocalPhyAd; + + LocalPhyAd = 0; + if(pDevice->AnInfo.mr_adv_sym_pause) + { + LocalPhyAd |= PHY_AN_AD_PAUSE_CAPABLE; + } + + if(pDevice->AnInfo.mr_adv_asym_pause) + { + LocalPhyAd |= PHY_AN_AD_ASYM_PAUSE; + } + + RemotePhyAd = 0; + if(pDevice->AnInfo.mr_lp_adv_sym_pause) + { + RemotePhyAd |= PHY_LINK_PARTNER_PAUSE_CAPABLE; + } + + if(pDevice->AnInfo.mr_lp_adv_asym_pause) + { + RemotePhyAd |= PHY_LINK_PARTNER_ASYM_PAUSE; + } + + LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd); + + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + for (j = 0; j < 30; j++) + { + MM_Wait(20); + REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MM_Wait(20); + if ((REG_RD(pDevice, MacCtrl.Status) & + (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + if (pDevice->PollTbiLink) + { + Value32 = REG_RD(pDevice, MacCtrl.Status); + if (Value32 & MAC_STATUS_RECEIVING_CFG) + { + pDevice->IgnoreTbiLinkChange = TRUE; + } + else + { + pDevice->IgnoreTbiLinkChange = FALSE; + } + } + Value32 = REG_RD(pDevice, MacCtrl.Status); + if (CurrentLinkStatus == LM_STATUS_LINK_DOWN && + (Value32 & MAC_STATUS_PCS_SYNCED) && + ((Value32 & MAC_STATUS_RECEIVING_CFG) == 0)) + { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + } + else + { + /* We are forcing line speed. */ + pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE; + LM_SetFlowControl(pDevice, 0, 0); + + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_SEND_CONFIGS); + } + } + /* Set the link polarity bit. */ + pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + + pDevice->pStatusBlkVirt->Status = STATUS_BLOCK_UPDATED | + (pDevice->pStatusBlkVirt->Status & ~STATUS_BLOCK_LINK_CHANGED_STATUS); + + for (j = 0; j < 100; j++) + { + REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MM_Wait(5); + if ((REG_RD(pDevice, MacCtrl.Status) & + (MAC_STATUS_SYNC_CHANGED | MAC_STATUS_CFG_CHANGED)) == 0) + break; + } + + Value32 = REG_RD(pDevice, MacCtrl.Status); + if((Value32 & MAC_STATUS_PCS_SYNCED) == 0) + { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + if (pDevice->DisableAutoNeg == FALSE) + { + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode | + MAC_MODE_SEND_CONFIGS); + MM_Wait(1); + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + } + } + + /* Initialize the current link status. */ + if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) + { + pDevice->LineSpeed = LM_LINE_SPEED_1000MBPS; + pDevice->DuplexMode = LM_DUPLEX_MODE_FULL; + REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_1000MBPS_LED_ON); + } + else + { + pDevice->LineSpeed = LM_LINE_SPEED_UNKNOWN; + pDevice->DuplexMode = LM_DUPLEX_MODE_UNKNOWN; + REG_WR(pDevice, MacCtrl.LedCtrl, LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_OVERRIDE_TRAFFIC_LED); + } + + /* Indicate link status. */ + if (pDevice->LinkStatus != CurrentLinkStatus) { + pDevice->LinkStatus = CurrentLinkStatus; + MM_IndicateStatus(pDevice, CurrentLinkStatus); + } + + return LM_STATUS_SUCCESS; +} +#endif /* INCLUDE_TBI_SUPPORT */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetupCopperPhy( + PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS CurrentLinkStatus; + LM_UINT32 Value32; + + /* Assume there is not link first. */ + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + + /* Disable phy link change attention. */ + REG_WR(pDevice, MacCtrl.MacEvent, 0); + + /* Clear link change attention. */ + REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + + /* Disable auto-polling for the moment. */ + pDevice->MiMode = 0xc0000; + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait(40); + + /* Determine the requested line speed and duplex. */ + pDevice->OldLineSpeed = pDevice->LineSpeed; + LM_TranslateRequestedMediaType(pDevice->RequestedMediaType, + &pDevice->MediaType, &pDevice->LineSpeed, &pDevice->DuplexMode); + + /* Initialize the phy chip. */ + switch(pDevice->PhyId & PHY_ID_MASK) + { + case PHY_BCM5400_PHY_ID: + case PHY_BCM5401_PHY_ID: + case PHY_BCM5411_PHY_ID: + case PHY_BCM5701_PHY_ID: + case PHY_BCM5703_PHY_ID: + case PHY_BCM5704_PHY_ID: + CurrentLinkStatus = LM_InitBcm540xPhy(pDevice); + break; + + default: + break; + } + + if(CurrentLinkStatus == LM_STATUS_LINK_SETTING_MISMATCH) + { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + } + + /* Setup flow control. */ + pDevice->FlowControl = LM_FLOW_CONTROL_NONE; + if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) + { + LM_FLOW_CONTROL FlowCap; /* Flow control capability. */ + + FlowCap = LM_FLOW_CONTROL_NONE; + + if(pDevice->DuplexMode == LM_DUPLEX_MODE_FULL) + { + if(pDevice->DisableAutoNeg == FALSE || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) + { + LM_UINT32 ExpectedPhyAd; + LM_UINT32 LocalPhyAd; + LM_UINT32 RemotePhyAd; + + LM_ReadPhy(pDevice, PHY_AN_AD_REG, &LocalPhyAd); + pDevice->advertising = LocalPhyAd; + LocalPhyAd &= (PHY_AN_AD_ASYM_PAUSE | PHY_AN_AD_PAUSE_CAPABLE); + + ExpectedPhyAd = GetPhyAdFlowCntrlSettings(pDevice); + + if(LocalPhyAd != ExpectedPhyAd) + { + CurrentLinkStatus = LM_STATUS_LINK_DOWN; + } + else + { + LM_ReadPhy(pDevice, PHY_LINK_PARTNER_ABILITY_REG, + &RemotePhyAd); + + LM_SetFlowControl(pDevice, LocalPhyAd, RemotePhyAd); + } + } + else + { + pDevice->FlowControlCap &= ~LM_FLOW_CONTROL_AUTO_PAUSE; + LM_SetFlowControl(pDevice, 0, 0); + } + } + } + + if(CurrentLinkStatus == LM_STATUS_LINK_DOWN) + { + LM_ForceAutoNeg(pDevice, pDevice->RequestedMediaType); + + /* If we force line speed, we make get link right away. */ + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + if(Value32 & PHY_STATUS_LINK_PASS) + { + CurrentLinkStatus = LM_STATUS_LINK_ACTIVE; + } + } + + /* GMII interface. */ + pDevice->MacMode &= ~MAC_MODE_PORT_MODE_MASK; + if(CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) + { + if(pDevice->LineSpeed == LM_LINE_SPEED_100MBPS || + pDevice->LineSpeed == LM_LINE_SPEED_10MBPS) + { + pDevice->MacMode |= MAC_MODE_PORT_MODE_MII; + } + else + { + pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; + } + } + else { + pDevice->MacMode |= MAC_MODE_PORT_MODE_GMII; + } + + /* Set the MAC to operate in the appropriate duplex mode. */ + pDevice->MacMode &= ~MAC_MODE_HALF_DUPLEX; + if(pDevice->DuplexMode == LM_DUPLEX_MODE_HALF) + { + pDevice->MacMode |= MAC_MODE_HALF_DUPLEX; + } + + /* Set the link polarity bit. */ + pDevice->MacMode &= ~MAC_MODE_LINK_POLARITY; + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + if((pDevice->LedMode == LED_MODE_LINK10) || + (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE && + pDevice->LineSpeed == LM_LINE_SPEED_10MBPS)) + { + pDevice->MacMode |= MAC_MODE_LINK_POLARITY; + } + } + else + { + if (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) + { + pDevice->MacMode |= MAC_MODE_LINK_POLARITY; + } + + /* Set LED mode. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = LED_CTRL_PHY_MODE_1; + } + else + { + if(pDevice->LedMode == LED_MODE_OUTPUT) + { + Value32 = LED_CTRL_PHY_MODE_2; + } + else + { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + REG_WR(pDevice, MacCtrl.LedCtrl, Value32); + } + + REG_WR(pDevice, MacCtrl.Mode, pDevice->MacMode); + + /* Enable auto polling. */ + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + pDevice->MiMode |= MI_MODE_AUTO_POLLING_ENABLE; + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + } + + /* Enable phy link change attention. */ + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_MI_INTERRUPT) + { + REG_WR(pDevice, MacCtrl.MacEvent, MAC_EVENT_ENABLE_MI_INTERRUPT); + } + else + { + REG_WR(pDevice, MacCtrl.MacEvent, + MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN); + } + if ((T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) && + (CurrentLinkStatus == LM_STATUS_LINK_ACTIVE) && + (pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && + (((pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE) && + (pDevice->PciState & T3_PCI_STATE_BUS_SPEED_HIGH)) || + !(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE))) + { + MM_Wait(120); + REG_WR(pDevice, MacCtrl.Status, MAC_STATUS_SYNC_CHANGED | + MAC_STATUS_CFG_CHANGED); + MEM_WR_OFFSET(pDevice, T3_FIRMWARE_MAILBOX, + T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE); + } + + /* Indicate link status. */ + if (pDevice->LinkStatus != CurrentLinkStatus) { + pDevice->LinkStatus = CurrentLinkStatus; + MM_IndicateStatus(pDevice, CurrentLinkStatus); + } + + return LM_STATUS_SUCCESS; +} /* LM_SetupCopperPhy */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetupPhy( + PLM_DEVICE_BLOCK pDevice) +{ + LM_STATUS LmStatus; + LM_UINT32 Value32; + +#if INCLUDE_TBI_SUPPORT + if(pDevice->EnableTbi) + { + LmStatus = LM_SetupFiberPhy(pDevice); + } + else +#endif /* INCLUDE_TBI_SUPPORT */ + { + LmStatus = LM_SetupCopperPhy(pDevice); + } + if (pDevice->ChipRevId == T3_CHIP_ID_5704_A0) + { + if (!(pDevice->PciState & T3_PCI_STATE_CONVENTIONAL_PCI_MODE)) + { + Value32 = REG_RD(pDevice, PciCfg.PciState); + REG_WR(pDevice, PciCfg.PciState, + Value32 | T3_PCI_STATE_RETRY_SAME_DMA); + } + } + if ((pDevice->LineSpeed == LM_LINE_SPEED_1000MBPS) && + (pDevice->DuplexMode == LM_DUPLEX_MODE_HALF)) + { + REG_WR(pDevice, MacCtrl.TxLengths, 0x26ff); + } + else + { + REG_WR(pDevice, MacCtrl.TxLengths, 0x2620); + } + + return LmStatus; +} + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_ReadPhy( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 PhyReg, +PLM_UINT32 pData32) { + LM_UINT32 Value32; + LM_UINT32 j; + + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode & + ~MI_MODE_AUTO_POLLING_ENABLE); + MM_Wait(40); + } + + Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | + ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) | + MI_COM_CMD_READ | MI_COM_START; + + REG_WR(pDevice, MacCtrl.MiCom, Value32); + + for(j = 0; j < 20; j++) + { + MM_Wait(25); + + Value32 = REG_RD(pDevice, MacCtrl.MiCom); + + if(!(Value32 & MI_COM_BUSY)) + { + MM_Wait(5); + Value32 = REG_RD(pDevice, MacCtrl.MiCom); + Value32 &= MI_COM_PHY_DATA_MASK; + break; + } + } + + if(Value32 & MI_COM_BUSY) + { + Value32 = 0; + } + + *pData32 = Value32; + + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait(40); + } +} /* LM_ReadPhy */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_VOID +LM_WritePhy( +PLM_DEVICE_BLOCK pDevice, +LM_UINT32 PhyReg, +LM_UINT32 Data32) { + LM_UINT32 Value32; + LM_UINT32 j; + + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode & + ~MI_MODE_AUTO_POLLING_ENABLE); + MM_Wait(40); + } + + Value32 = (pDevice->PhyAddr << MI_COM_FIRST_PHY_ADDR_BIT) | + ((PhyReg & MI_COM_PHY_REG_ADDR_MASK) << MI_COM_FIRST_PHY_REG_ADDR_BIT) | + (Data32 & MI_COM_PHY_DATA_MASK) | MI_COM_CMD_WRITE | MI_COM_START; + + REG_WR(pDevice, MacCtrl.MiCom, Value32); + + for(j = 0; j < 20; j++) + { + MM_Wait(25); + + Value32 = REG_RD(pDevice, MacCtrl.MiCom); + + if(!(Value32 & MI_COM_BUSY)) + { + MM_Wait(5); + break; + } + } + + if(pDevice->PhyIntMode == T3_PHY_INT_MODE_AUTO_POLLING) + { + REG_WR(pDevice, MacCtrl.MiMode, pDevice->MiMode); + MM_Wait(40); + } +} /* LM_WritePhy */ + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS +LM_SetPowerState( +PLM_DEVICE_BLOCK pDevice, +LM_POWER_STATE PowerLevel) { + LM_UINT32 PmeSupport; + LM_UINT32 Value32; + LM_UINT32 PmCtrl; + + /* make sureindirect accesses are enabled*/ + MM_WriteConfig32(pDevice, T3_PCI_MISC_HOST_CTRL_REG, pDevice->MiscHostCtrl); + + /* Clear the PME_ASSERT bit and the power state bits. Also enable */ + /* the PME bit. */ + MM_ReadConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, &PmCtrl); + + PmCtrl |= T3_PM_PME_ASSERTED; + PmCtrl &= ~T3_PM_POWER_STATE_MASK; + + /* Set the appropriate power state. */ + if(PowerLevel == LM_POWER_STATE_D0) + { + + /* Bring the card out of low power mode. */ + PmCtrl |= T3_PM_POWER_STATE_D0; + MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); + + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl); + MM_Wait (40); +#if 0 /* Bugfix by jmb...can't call WritePhy here because pDevice not fully initialized */ + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x02); +#endif + + return LM_STATUS_SUCCESS; + } + else if(PowerLevel == LM_POWER_STATE_D1) + { + PmCtrl |= T3_PM_POWER_STATE_D1; + } + else if(PowerLevel == LM_POWER_STATE_D2) + { + PmCtrl |= T3_PM_POWER_STATE_D2; + } + else if(PowerLevel == LM_POWER_STATE_D3) + { + PmCtrl |= T3_PM_POWER_STATE_D3; + } + else + { + return LM_STATUS_FAILURE; + } + PmCtrl |= T3_PM_PME_ENABLE; + + /* Mask out all interrupts so LM_SetupPhy won't be called while we are */ + /* setting new line speed. */ + Value32 = REG_RD(pDevice, PciCfg.MiscHostCtrl); + REG_WR(pDevice, PciCfg.MiscHostCtrl, Value32 | MISC_HOST_CTRL_MASK_PCI_INT); + + if(!pDevice->RestoreOnWakeUp) + { + pDevice->RestoreOnWakeUp = TRUE; + pDevice->WakeUpDisableAutoNeg = pDevice->DisableAutoNeg; + pDevice->WakeUpRequestedMediaType = pDevice->RequestedMediaType; + } + + /* Force auto-negotiation to 10 line speed. */ + pDevice->DisableAutoNeg = FALSE; + pDevice->RequestedMediaType = LM_REQUESTED_MEDIA_TYPE_UTP_10MBPS; + LM_SetupPhy(pDevice); + + /* Put the driver in the initial state, and go through the power down */ + /* sequence. */ + LM_Halt(pDevice); + + MM_ReadConfig32(pDevice, T3_PCI_PM_CAP_REG, &PmeSupport); + + if (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE) + { + + /* Enable WOL. */ + LM_WritePhy(pDevice, BCM5401_AUX_CTRL, 0x5a); + MM_Wait(40); + + /* Set LED mode. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = LED_CTRL_PHY_MODE_1; + } + else + { + if(pDevice->LedMode == LED_MODE_OUTPUT) + { + Value32 = LED_CTRL_PHY_MODE_2; + } + else + { + Value32 = LED_CTRL_PHY_MODE_1; + } + } + + Value32 = MAC_MODE_PORT_MODE_MII; + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700) + { + if(pDevice->LedMode == LED_MODE_LINK10 || + pDevice->WolSpeed == WOL_SPEED_10MB) + { + Value32 |= MAC_MODE_LINK_POLARITY; + } + } + else + { + Value32 |= MAC_MODE_LINK_POLARITY; + } + REG_WR(pDevice, MacCtrl.Mode, Value32); + MM_Wait(40); MM_Wait(40); MM_Wait(40); + + /* Always enable magic packet wake-up if we have vaux. */ + if((PmeSupport & T3_PCI_PM_CAP_PME_D3COLD) && + (pDevice->WakeUpModeCap & LM_WAKE_UP_MODE_MAGIC_PACKET)) + { + Value32 |= MAC_MODE_DETECT_MAGIC_PACKET_ENABLE; + } + + REG_WR(pDevice, MacCtrl.Mode, Value32); + + /* Enable the receiver. */ + REG_WR(pDevice, MacCtrl.RxMode, RX_MODE_ENABLE); + } + + /* Disable tx/rx clocks, and seletect an alternate clock. */ + if(pDevice->WolSpeed == WOL_SPEED_100MB) + { + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK; + } + else + { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK; + } + REG_WR(pDevice, PciCfg.ClockCtrl, Value32); + + MM_Wait(40); + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK | T3_PCI_44MHZ_CORE_CLOCK; + } + else + { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_44MHZ_CORE_CLOCK; + } + + REG_WR(pDevice, PciCfg.ClockCtrl, Value32); + + MM_Wait(40); + + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_44MHZ_CORE_CLOCK; + } + else + { + Value32 = T3_PCI_44MHZ_CORE_CLOCK; + } + + REG_WR(pDevice, PciCfg.ClockCtrl, Value32); + } + else + { + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + Value32 = T3_PCI_DISABLE_RX_CLOCK | T3_PCI_DISABLE_TX_CLOCK | + T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_POWER_DOWN_PCI_PLL133; + } + else + { + Value32 = T3_PCI_SELECT_ALTERNATE_CLOCK | + T3_PCI_POWER_DOWN_PCI_PLL133; + } + + REG_WR(pDevice, PciCfg.ClockCtrl, Value32); + } + + MM_Wait(40); + + if(!pDevice->EepromWp && (pDevice->WakeUpModeCap != LM_WAKE_UP_MODE_NONE)) + { + /* Switch adapter to auxilliary power. */ + if(T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5700 || + T3_ASIC_REV(pDevice->ChipRevId) == T3_ASIC_REV_5701) + { + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); + MM_Wait(40); + } + else + { + /* GPIO0 = 0, GPIO1 = 1, GPIO2 = 1. */ + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); + MM_Wait(40); + + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 1. */ + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2); + MM_Wait(40); + + /* GPIO0 = 1, GPIO1 = 1, GPIO2 = 0. */ + REG_WR(pDevice, Grc.LocalCtrl, pDevice->GrcLocalCtrl | + GRC_MISC_LOCAL_CTRL_GPIO_OE0 | + GRC_MISC_LOCAL_CTRL_GPIO_OE1 | + GRC_MISC_LOCAL_CTRL_GPIO_OE2 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 | + GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1); + MM_Wait(40); + } + } + + /* Set the phy to low power mode. */ + /* Put the the hardware in low power mode. */ + MM_WriteConfig32(pDevice, T3_PCI_PM_STATUS_CTRL_REG, PmCtrl); + + return LM_STATUS_SUCCESS; +} /* LM_SetPowerState */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +static LM_UINT32 +GetPhyAdFlowCntrlSettings( + PLM_DEVICE_BLOCK pDevice) +{ + LM_UINT32 Value32; + + Value32 = 0; + + /* Auto negotiation flow control only when autonegotiation is enabled. */ + if(pDevice->DisableAutoNeg == FALSE || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_AUTO || + pDevice->RequestedMediaType == LM_REQUESTED_MEDIA_TYPE_UTP_AUTO) + { + /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */ + if((pDevice->FlowControlCap == LM_FLOW_CONTROL_AUTO_PAUSE) || + ((pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) && + (pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) + { + Value32 |= PHY_AN_AD_PAUSE_CAPABLE; + } + else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_TRANSMIT_PAUSE) + { + Value32 |= PHY_AN_AD_ASYM_PAUSE; + } + else if(pDevice->FlowControlCap & LM_FLOW_CONTROL_RECEIVE_PAUSE) + { + Value32 |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; + } + } + + return Value32; +} + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/* LM_STATUS_FAILURE */ +/* LM_STATUS_SUCCESS */ +/* */ +/******************************************************************************/ +static LM_STATUS +LM_ForceAutoNegBcm540xPhy( +PLM_DEVICE_BLOCK pDevice, +LM_REQUESTED_MEDIA_TYPE RequestedMediaType) +{ + LM_MEDIA_TYPE MediaType; + LM_LINE_SPEED LineSpeed; + LM_DUPLEX_MODE DuplexMode; + LM_UINT32 NewPhyCtrl; + LM_UINT32 Value32; + LM_UINT32 Cnt; + + /* Get the interface type, line speed, and duplex mode. */ + LM_TranslateRequestedMediaType(RequestedMediaType, &MediaType, &LineSpeed, + &DuplexMode); + + if (pDevice->RestoreOnWakeUp) + { + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + Value32 = PHY_AN_AD_10BASET_FULL | PHY_AN_AD_10BASET_HALF; + if (pDevice->WolSpeed == WOL_SPEED_100MB) + { + Value32 |= PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; + } + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } + /* Setup the auto-negotiation advertisement register. */ + else if(LineSpeed == LM_LINE_SPEED_UNKNOWN) + { + /* Setup the 10/100 Mbps auto-negotiation advertisement register. */ + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | + PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL | + PHY_AN_AD_100BASETX_FULL | PHY_AN_AD_100BASETX_HALF; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + /* Advertise 1000Mbps */ + Value32 = BCM540X_AN_AD_1000BASET_HALF | BCM540X_AN_AD_1000BASET_FULL; + +#if INCLUDE_5701_AX_FIX + /* Bug: workaround for CRC error in gigabit mode when we are in */ + /* slave mode. This will force the PHY to operate in */ + /* master mode. */ + if(pDevice->ChipRevId == T3_CHIP_ID_5701_A0 || + pDevice->ChipRevId == T3_CHIP_ID_5701_B0) + { + Value32 |= BCM540X_CONFIG_AS_MASTER | + BCM540X_ENABLE_CONFIG_AS_MASTER; + } +#endif + + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32); + pDevice->advertising1000 = Value32; + } + else + { + if(LineSpeed == LM_LINE_SPEED_1000MBPS) + { + Value32 = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + + if(DuplexMode != LM_DUPLEX_MODE_FULL) + { + Value32 = BCM540X_AN_AD_1000BASET_HALF; + } + else + { + Value32 = BCM540X_AN_AD_1000BASET_FULL; + } + + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, Value32); + pDevice->advertising1000 = Value32; + } + else if(LineSpeed == LM_LINE_SPEED_100MBPS) + { + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + + if(DuplexMode != LM_DUPLEX_MODE_FULL) + { + Value32 = PHY_AN_AD_100BASETX_HALF; + } + else + { + Value32 = PHY_AN_AD_100BASETX_FULL; + } + + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } + else if(LineSpeed == LM_LINE_SPEED_10MBPS) + { + LM_WritePhy(pDevice, BCM540X_1000BASET_CTRL_REG, 0); + pDevice->advertising1000 = 0; + + if(DuplexMode != LM_DUPLEX_MODE_FULL) + { + Value32 = PHY_AN_AD_10BASET_HALF; + } + else + { + Value32 = PHY_AN_AD_10BASET_FULL; + } + + Value32 |= PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; + Value32 |= GetPhyAdFlowCntrlSettings(pDevice); + + LM_WritePhy(pDevice, PHY_AN_AD_REG, Value32); + pDevice->advertising = Value32; + } + } + + /* Force line speed if auto-negotiation is disabled. */ + if(pDevice->DisableAutoNeg && LineSpeed != LM_LINE_SPEED_UNKNOWN) + { + /* This code path is executed only when there is link. */ + pDevice->MediaType = MediaType; + pDevice->LineSpeed = LineSpeed; + pDevice->DuplexMode = DuplexMode; + + /* Force line seepd. */ + NewPhyCtrl = 0; + switch(LineSpeed) + { + case LM_LINE_SPEED_10MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_10MBPS; + break; + case LM_LINE_SPEED_100MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_100MBPS; + break; + case LM_LINE_SPEED_1000MBPS: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; + break; + default: + NewPhyCtrl |= PHY_CTRL_SPEED_SELECT_1000MBPS; + break; + } + + if(DuplexMode == LM_DUPLEX_MODE_FULL) + { + NewPhyCtrl |= PHY_CTRL_FULL_DUPLEX_MODE; + } + + /* Don't do anything if the PHY_CTRL is already what we wanted. */ + LM_ReadPhy(pDevice, PHY_CTRL_REG, &Value32); + if(Value32 != NewPhyCtrl) + { + /* Temporary bring the link down before forcing line speed. */ + LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_LOOPBACK_MODE); + + /* Wait for link to go down. */ + for(Cnt = 0; Cnt < 15000; Cnt++) + { + MM_Wait(10); + + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + LM_ReadPhy(pDevice, PHY_STATUS_REG, &Value32); + + if(!(Value32 & PHY_STATUS_LINK_PASS)) + { + MM_Wait(40); + break; + } + } + + LM_WritePhy(pDevice, PHY_CTRL_REG, NewPhyCtrl); + MM_Wait(40); + } + } + else + { + LM_WritePhy(pDevice, PHY_CTRL_REG, PHY_CTRL_AUTO_NEG_ENABLE | + PHY_CTRL_RESTART_AUTO_NEG); + } + + return LM_STATUS_SUCCESS; +} /* LM_ForceAutoNegBcm540xPhy */ + + + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +static LM_STATUS +LM_ForceAutoNeg( +PLM_DEVICE_BLOCK pDevice, +LM_REQUESTED_MEDIA_TYPE RequestedMediaType) +{ + LM_STATUS LmStatus; + + /* Initialize the phy chip. */ + switch(pDevice->PhyId & PHY_ID_MASK) + { + case PHY_BCM5400_PHY_ID: + case PHY_BCM5401_PHY_ID: + case PHY_BCM5411_PHY_ID: + case PHY_BCM5701_PHY_ID: + case PHY_BCM5703_PHY_ID: + case PHY_BCM5704_PHY_ID: + LmStatus = LM_ForceAutoNegBcm540xPhy(pDevice, RequestedMediaType); + break; + + default: + LmStatus = LM_STATUS_FAILURE; + break; + } + + return LmStatus; +} /* LM_ForceAutoNeg */ + +/******************************************************************************/ +/* Description: */ +/* */ +/* Return: */ +/******************************************************************************/ +LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice, + PT3_FWIMG_INFO pFwImg, + LM_UINT32 LoadCpu, + LM_UINT32 StartCpu) +{ + LM_UINT32 i; + LM_UINT32 address; + + if (LoadCpu & T3_RX_CPU_ID) + { + if (LM_HaltCpu(pDevice,T3_RX_CPU_ID) != LM_STATUS_SUCCESS) + { + return LM_STATUS_FAILURE; + } + + /* First of all clear scrach pad memory */ + for (i = 0; i < T3_RX_CPU_SPAD_SIZE; i+=4) + { + LM_RegWrInd(pDevice,T3_RX_CPU_SPAD_ADDR+i,0); + } + + /* Copy code first */ + address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); + for (i = 0; i <= pFwImg->Text.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]); + } + + address = T3_RX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); + for (i = 0; i <= pFwImg->ROnlyData.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]); + } + + address = T3_RX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); + for (i= 0; i <= pFwImg->Data.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]); + } + } + + if (LoadCpu & T3_TX_CPU_ID) + { + if (LM_HaltCpu(pDevice,T3_TX_CPU_ID) != LM_STATUS_SUCCESS) + { + return LM_STATUS_FAILURE; + } + + /* First of all clear scrach pad memory */ + for (i = 0; i < T3_TX_CPU_SPAD_SIZE; i+=4) + { + LM_RegWrInd(pDevice,T3_TX_CPU_SPAD_ADDR+i,0); + } + + /* Copy code first */ + address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Text.Offset & 0xffff); + for (i= 0; i <= pFwImg->Text.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->Text.Buffer)[i/4]); + } + + address = T3_TX_CPU_SPAD_ADDR + (pFwImg->ROnlyData.Offset & 0xffff); + for (i= 0; i <= pFwImg->ROnlyData.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->ROnlyData.Buffer)[i/4]); + } + + address = T3_TX_CPU_SPAD_ADDR + (pFwImg->Data.Offset & 0xffff); + for (i= 0; i <= pFwImg->Data.Length; i+=4) + { + LM_RegWrInd(pDevice,address+i, + ((LM_UINT32 *)pFwImg->Data.Buffer)[i/4]); + } + } + + if (StartCpu & T3_RX_CPU_ID) + { + /* Start Rx CPU */ + REG_WR(pDevice,rxCpu.reg.state, 0xffffffff); + REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress); + for (i = 0 ; i < 5; i++) + { + if (pFwImg->StartAddress == REG_RD(pDevice,rxCpu.reg.PC)) + break; + + REG_WR(pDevice,rxCpu.reg.state, 0xffffffff); + REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT); + REG_WR(pDevice,rxCpu.reg.PC,pFwImg->StartAddress); + MM_Wait(1000); + } + + REG_WR(pDevice,rxCpu.reg.state, 0xffffffff); + REG_WR(pDevice,rxCpu.reg.mode, 0); + } + + if (StartCpu & T3_TX_CPU_ID) + { + /* Start Tx CPU */ + REG_WR(pDevice,txCpu.reg.state, 0xffffffff); + REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress); + for (i = 0 ; i < 5; i++) + { + if (pFwImg->StartAddress == REG_RD(pDevice,txCpu.reg.PC)) + break; + + REG_WR(pDevice,txCpu.reg.state, 0xffffffff); + REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT); + REG_WR(pDevice,txCpu.reg.PC,pFwImg->StartAddress); + MM_Wait(1000); + } + + REG_WR(pDevice,txCpu.reg.state, 0xffffffff); + REG_WR(pDevice,txCpu.reg.mode, 0); + } + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS LM_HaltCpu(PLM_DEVICE_BLOCK pDevice,LM_UINT32 cpu_number) +{ + LM_UINT32 i; + + if (cpu_number == T3_RX_CPU_ID) + { + for (i = 0 ; i < 10000; i++) + { + REG_WR(pDevice,rxCpu.reg.state, 0xffffffff); + REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT); + + if (REG_RD(pDevice,rxCpu.reg.mode) & CPU_MODE_HALT) + break; + } + + REG_WR(pDevice,rxCpu.reg.state, 0xffffffff); + REG_WR(pDevice,rxCpu.reg.mode,CPU_MODE_HALT); + MM_Wait(10); + } + else + { + for (i = 0 ; i < 10000; i++) + { + REG_WR(pDevice,txCpu.reg.state, 0xffffffff); + REG_WR(pDevice,txCpu.reg.mode,CPU_MODE_HALT); + + if (REG_RD(pDevice,txCpu.reg.mode) & CPU_MODE_HALT) + break; + } + } + + return (( i == 10000) ? LM_STATUS_FAILURE : LM_STATUS_SUCCESS); +} + + +int +LM_BlinkLED(PLM_DEVICE_BLOCK pDevice, LM_UINT32 BlinkDurationSec) +{ + LM_UINT32 Oldcfg; + int j; + int ret = 0; + + if(BlinkDurationSec == 0) + { + return 0; + } + if(BlinkDurationSec > 120) + { + BlinkDurationSec = 120; + } + + Oldcfg = REG_RD(pDevice, MacCtrl.LedCtrl); + for(j = 0; j < BlinkDurationSec * 2; j++) + { + if(j % 2) + { + /* Turn on the LEDs. */ + REG_WR(pDevice, MacCtrl.LedCtrl, + LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_1000MBPS_LED_ON | + LED_CTRL_100MBPS_LED_ON | + LED_CTRL_10MBPS_LED_ON | + LED_CTRL_OVERRIDE_TRAFFIC_LED | + LED_CTRL_BLINK_TRAFFIC_LED | + LED_CTRL_TRAFFIC_LED); + } + else + { + /* Turn off the LEDs. */ + REG_WR(pDevice, MacCtrl.LedCtrl, + LED_CTRL_OVERRIDE_LINK_LED | + LED_CTRL_OVERRIDE_TRAFFIC_LED); + } + +#ifndef EMBEDDED + current->state = TASK_INTERRUPTIBLE; + if (schedule_timeout(HZ/2) != 0) { + ret = -EINTR; + break; + } +#else + udelay(100000); /* 1s sleep */ +#endif + } + REG_WR(pDevice, MacCtrl.LedCtrl, Oldcfg); + return ret; +} + +int t3_do_dma(PLM_DEVICE_BLOCK pDevice, + LM_PHYSICAL_ADDRESS host_addr_phy, int length, + int dma_read) +{ + T3_DMA_DESC dma_desc; + int i; + LM_UINT32 dma_desc_addr; + LM_UINT32 value32; + + REG_WR(pDevice, BufMgr.Mode, 0); + REG_WR(pDevice, Ftq.Reset, 0); + + dma_desc.host_addr.High = host_addr_phy.High; + dma_desc.host_addr.Low = host_addr_phy.Low; + dma_desc.nic_mbuf = 0x2100; + dma_desc.len = length; + dma_desc.flags = 0x00000004; /* Generate Rx-CPU event */ + + if (dma_read) + { + dma_desc.cqid_sqid = (T3_QID_RX_BD_COMP << 8) | + T3_QID_DMA_HIGH_PRI_READ; + REG_WR(pDevice, DmaRead.Mode, DMA_READ_MODE_ENABLE); + } + else + { + dma_desc.cqid_sqid = (T3_QID_RX_DATA_COMP << 8) | + T3_QID_DMA_HIGH_PRI_WRITE; + REG_WR(pDevice, DmaWrite.Mode, DMA_WRITE_MODE_ENABLE); + } + + dma_desc_addr = T3_NIC_DMA_DESC_POOL_ADDR; + + /* Writing this DMA descriptor to DMA memory */ + for (i = 0; i < sizeof(T3_DMA_DESC); i += 4) + { + value32 = *((PLM_UINT32) (((PLM_UINT8) &dma_desc) + i)); + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, dma_desc_addr+i); + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_DATA_REG, cpu_to_le32(value32)); + } + MM_WriteConfig32(pDevice, T3_PCI_MEM_WIN_ADDR_REG, 0); + + if (dma_read) + REG_WR(pDevice, Ftq.DmaHighReadFtqFifoEnqueueDequeue, dma_desc_addr); + else + REG_WR(pDevice, Ftq.DmaHighWriteFtqFifoEnqueueDequeue, dma_desc_addr); + + for (i = 0; i < 40; i++) + { + if (dma_read) + value32 = REG_RD(pDevice, Ftq.RcvBdCompFtqFifoEnqueueDequeue); + else + value32 = REG_RD(pDevice, Ftq.RcvDataCompFtqFifoEnqueueDequeue); + + if ((value32 & 0xffff) == dma_desc_addr) + break; + + MM_Wait(10); + } + + return LM_STATUS_SUCCESS; +} + +STATIC LM_STATUS +LM_DmaTest(PLM_DEVICE_BLOCK pDevice, PLM_UINT8 pBufferVirt, + LM_PHYSICAL_ADDRESS BufferPhy, LM_UINT32 BufferSize) +{ + int j; + LM_UINT32 *ptr; + int dma_success = 0; + + if(T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5700 && + T3_ASIC_REV(pDevice->ChipRevId) != T3_ASIC_REV_5701) + { + return LM_STATUS_SUCCESS; + } + while (!dma_success) + { + /* Fill data with incremental patterns */ + ptr = (LM_UINT32 *)pBufferVirt; + for (j = 0; j < BufferSize/4; j++) + *ptr++ = j; + + if (t3_do_dma(pDevice,BufferPhy,BufferSize, 1) == LM_STATUS_FAILURE) + { + return LM_STATUS_FAILURE; + } + + MM_Wait(40); + ptr = (LM_UINT32 *)pBufferVirt; + /* Fill data with zero */ + for (j = 0; j < BufferSize/4; j++) + *ptr++ = 0; + + if (t3_do_dma(pDevice,BufferPhy,BufferSize, 0) == LM_STATUS_FAILURE) + { + return LM_STATUS_FAILURE; + } + + MM_Wait(40); + /* Check for data */ + ptr = (LM_UINT32 *)pBufferVirt; + for (j = 0; j < BufferSize/4; j++) + { + if (*ptr++ != j) + { + if ((pDevice->DmaReadWriteCtrl & DMA_CTRL_WRITE_BOUNDARY_MASK) + == DMA_CTRL_WRITE_BOUNDARY_DISABLE) + { + pDevice->DmaReadWriteCtrl = (pDevice->DmaReadWriteCtrl & + ~DMA_CTRL_WRITE_BOUNDARY_MASK) | + DMA_CTRL_WRITE_BOUNDARY_16; + REG_WR(pDevice, PciCfg.DmaReadWriteCtrl, + pDevice->DmaReadWriteCtrl); + break; + } + else + { + return LM_STATUS_FAILURE; + } + } + } + if (j == (BufferSize/4)) + dma_success = 1; + } + return LM_STATUS_SUCCESS; +} +#endif /* CFG_CMD_NET, !CONFIG_NET_MULTI, CONFIG_TIGON3 */ diff --git a/drivers/tigon3.h b/drivers/tigon3.h new file mode 100644 index 0000000..8d30ac9 --- /dev/null +++ b/drivers/tigon3.h @@ -0,0 +1,3469 @@ + +/******************************************************************************/ +/* */ +/* Broadcom BCM5700 Linux Network Driver, Copyright (c) 2000 Broadcom */ +/* Corporation. */ +/* All rights reserved. */ +/* */ +/* 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, located in the file LICENSE. */ +/* */ +/* History: */ +/* */ +/******************************************************************************/ + +#ifndef TIGON3_H +#define TIGON3_H + +#include "bcm570x_lm.h" +#if INCLUDE_TBI_SUPPORT +#include "bcm570x_autoneg.h" +#endif + + +/* io defines */ +#if !defined(BIG_ENDIAN_HOST) +#define readl(addr) \ + (LONGSWAP((*(volatile unsigned int *)(addr)))) +#define writel(b,addr) \ + ((*(volatile unsigned int *)(addr)) = (LONGSWAP(b))) +#else +#if 0 /* !defined(PPC603) */ +#define readl(addr) (*(volatile unsigned int*)(0xa0000000 + (unsigned long)(addr))) +#define writel(b,addr) ((*(volatile unsigned int *) ((unsigned long)(addr) + 0xa0000000)) = (b)) +#else +#if 1 +#define readl(addr) (*(volatile unsigned int*)(addr)) +#define writel(b,addr) ((*(volatile unsigned int *) (addr)) = (b)) +#else +extern int sprintf(char* buf, const char* f, ...); +static __inline unsigned int readl(void* addr){ + char buf[128]; + unsigned int tmp = (*(volatile unsigned int*)(addr)); + sprintf(buf,"%s:%s: read 0x%x from 0x%x\n",__FILE__,__LINE__,tmp,addr,0,0); + sysSerialPrintString(buf); + return tmp; +} +static __inline void writel(unsigned int b, unsigned int addr){ + char buf[128]; + ((*(volatile unsigned int *) (addr)) = (b)); + sprintf(buf,"%s:%s: write 0x%x to 0x%x\n",__FILE__,__LINE__,b,addr,0,0); + sysSerialPrintString(buf); +} +#endif +#endif /* PPC603 */ +#endif + + + + +/******************************************************************************/ +/* Constants. */ +/******************************************************************************/ + +/* Maxim number of packet descriptors used for sending packets. */ +#define MAX_TX_PACKET_DESC_COUNT 600 +#define DEFAULT_TX_PACKET_DESC_COUNT 2 + +/* Maximum number of packet descriptors used for receiving packets. */ +#if T3_JUMBO_RCB_ENTRY_COUNT +#define MAX_RX_PACKET_DESC_COUNT \ + (T3_STD_RCV_RCB_ENTRY_COUNT + T3_JUMBO_RCV_RCB_ENTRY_COUNT) +#else +#define MAX_RX_PACKET_DESC_COUNT 800 +#endif +#define DEFAULT_RX_PACKET_DESC_COUNT 2 + +/* Threshhold for double copying small tx packets. 0 will disable double */ +/* copying of small Tx packets. */ +#define DEFAULT_TX_COPY_BUFFER_SIZE 0 +#define MIN_TX_COPY_BUFFER_SIZE 64 +#define MAX_TX_COPY_BUFFER_SIZE 512 + +/* Cache line. */ +#define COMMON_CACHE_LINE_SIZE 0x20 +#define COMMON_CACHE_LINE_MASK (COMMON_CACHE_LINE_SIZE-1) + +/* Maximum number of fragment we can handle. */ +#ifndef MAX_FRAGMENT_COUNT +#define MAX_FRAGMENT_COUNT 32 +#endif + +/* B0 bug. */ +#define BCM5700_BX_MIN_FRAG_SIZE 10 +#define BCM5700_BX_MIN_FRAG_BUF_SIZE 16 /* nice aligned size. */ +#define BCM5700_BX_MIN_FRAG_BUF_SIZE_MASK (BCM5700_BX_MIN_FRAG_BUF_SIZE-1) +#define BCM5700_BX_TX_COPY_BUF_SIZE (BCM5700_BX_MIN_FRAG_BUF_SIZE * \ + MAX_FRAGMENT_COUNT) + +/* MAGIC number. */ +/* #define T3_MAGIC_NUM 'KevT' */ +#define T3_FIRMWARE_MAILBOX 0x0b50 +#define T3_MAGIC_NUM 0x4B657654 +#define T3_MAGIC_NUM_DISABLE_DMAW_ON_LINK_CHANGE 0x4861764b + +#define T3_NIC_DATA_SIG_ADDR 0x0b54 +#define T3_NIC_DATA_SIG 0x4b657654 + +#define T3_NIC_DATA_NIC_CFG_ADDR 0x0b58 +#define T3_NIC_CFG_LED_MODE_UNKNOWN BIT_NONE +#define T3_NIC_CFG_LED_MODE_TRIPLE_SPEED BIT_2 +#define T3_NIC_CFG_LED_MODE_LINK_SPEED BIT_3 +#define T3_NIC_CFG_LED_MODE_OPEN_DRAIN BIT_2 +#define T3_NIC_CFG_LED_MODE_OUTPUT BIT_3 +#define T3_NIC_CFG_LED_MODE_MASK (BIT_2 | BIT_3) +#define T3_NIC_CFG_PHY_TYPE_UNKNOWN BIT_NONE +#define T3_NIC_CFG_PHY_TYPE_COPPER BIT_4 +#define T3_NIC_CFG_PHY_TYPE_FIBER BIT_5 +#define T3_NIC_CFG_PHY_TYPE_MASK (BIT_4 | BIT_5) +#define T3_NIC_CFG_ENABLE_WOL BIT_6 +#define T3_NIC_CFG_ENABLE_ASF BIT_7 +#define T3_NIC_EEPROM_WP BIT_8 + +#define T3_NIC_DATA_PHY_ID_ADDR 0x0b74 +#define T3_NIC_PHY_ID1_MASK 0xffff0000 +#define T3_NIC_PHY_ID2_MASK 0x0000ffff + +#define T3_CMD_MAILBOX 0x0b78 +#define T3_CMD_NICDRV_ALIVE 0x01 +#define T3_CMD_NICDRV_PAUSE_FW 0x02 +#define T3_CMD_NICDRV_IPV4ADDR_CHANGE 0x03 +#define T3_CMD_NICDRV_IPV6ADDR_CHANGE 0x04 +#define T3_CMD_5703A0_FIX_DMAFW_DMAR 0x05 +#define T3_CMD_5703A0_FIX_DMAFW_DMAW 0x06 + +#define T3_CMD_LENGTH_MAILBOX 0x0b7c +#define T3_CMD_DATA_MAILBOX 0x0b80 + +#define T3_ASF_FW_STATUS_MAILBOX 0x0c00 + +#define T3_DRV_STATE_MAILBOX 0x0c04 +#define T3_DRV_STATE_START 0x01 +#define T3_DRV_STATE_UNLOAD 0x02 +#define T3_DRV_STATE_WOL 0x03 +#define T3_DRV_STATE_SUSPEND 0x04 + +#define T3_FW_RESET_TYPE_MAILBOX 0x0c08 + +#define T3_MAC_ADDR_HIGH_MAILBOX 0x0c14 +#define T3_MAC_ADDR_LOW_MAILBOX 0x0c18 + +/******************************************************************************/ +/* Hardware constants. */ +/******************************************************************************/ + +/* Number of entries in the send ring: must be 512. */ +#define T3_SEND_RCB_ENTRY_COUNT 512 +#define T3_SEND_RCB_ENTRY_COUNT_MASK (T3_SEND_RCB_ENTRY_COUNT-1) + +/* Number of send RCBs. May be 1-16 but for now, only support one. */ +#define T3_MAX_SEND_RCB_COUNT 16 + +/* Number of entries in the Standard Receive RCB. Must be 512 entries. */ +#define T3_STD_RCV_RCB_ENTRY_COUNT 512 +#define T3_STD_RCV_RCB_ENTRY_COUNT_MASK (T3_STD_RCV_RCB_ENTRY_COUNT-1) +#define DEFAULT_STD_RCV_DESC_COUNT 200 /* Must be < 512. */ +#define MAX_STD_RCV_BUFFER_SIZE 0x600 + +/* Number of entries in the Mini Receive RCB. This value can either be */ +/* 0, 1024. Currently Mini Receive RCB is disabled. */ +#ifndef T3_MINI_RCV_RCB_ENTRY_COUNT +#define T3_MINI_RCV_RCB_ENTRY_COUNT 0 +#endif /* T3_MINI_RCV_RCB_ENTRY_COUNT */ +#define T3_MINI_RCV_RCB_ENTRY_COUNT_MASK (T3_MINI_RCV_RCB_ENTRY_COUNT-1) +#define MAX_MINI_RCV_BUFFER_SIZE 512 +#define DEFAULT_MINI_RCV_BUFFER_SIZE 64 +#define DEFAULT_MINI_RCV_DESC_COUNT 100 /* Must be < 1024. */ + +/* Number of entries in the Jumbo Receive RCB. This value must 256 or 0. */ +/* Currently, Jumbo Receive RCB is disabled. */ +#ifndef T3_JUMBO_RCV_RCB_ENTRY_COUNT +#define T3_JUMBO_RCV_RCB_ENTRY_COUNT 0 +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ +#define T3_JUMBO_RCV_RCB_ENTRY_COUNT_MASK (T3_JUMBO_RCV_RCB_ENTRY_COUNT-1) + +#define MAX_JUMBO_RCV_BUFFER_SIZE (10 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_RCV_BUFFER_SIZE (4 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_RCV_DESC_COUNT 128 /* Must be < 256. */ + +#define MAX_JUMBO_TX_BUFFER_SIZE (8 * 1024) /* > 1514 */ +#define DEFAULT_JUMBO_TX_BUFFER_SIZE (4 * 1024) /* > 1514 */ + +/* Number of receive return RCBs. Maybe 1-16 but for now, only support one. */ +#define T3_MAX_RCV_RETURN_RCB_COUNT 16 + +/* Number of entries in a Receive Return ring. This value is either 1024 */ +/* or 2048. */ +#ifndef T3_RCV_RETURN_RCB_ENTRY_COUNT +#define T3_RCV_RETURN_RCB_ENTRY_COUNT 1024 +#endif /* T3_RCV_RETURN_RCB_ENTRY_COUNT */ +#define T3_RCV_RETURN_RCB_ENTRY_COUNT_MASK (T3_RCV_RETURN_RCB_ENTRY_COUNT-1) + + +/* Default coalescing parameters. */ +#define DEFAULT_RX_COALESCING_TICKS 100 +#define MAX_RX_COALESCING_TICKS 500 +#define DEFAULT_TX_COALESCING_TICKS 400 +#define MAX_TX_COALESCING_TICKS 500 +#define DEFAULT_RX_MAX_COALESCED_FRAMES 10 +#define MAX_RX_MAX_COALESCED_FRAMES 100 +#define ADAPTIVE_LO_RX_MAX_COALESCED_FRAMES 5 +#define ADAPTIVE_HI_RX_MAX_COALESCED_FRAMES 42 +#define ADAPTIVE_LO_RX_COALESCING_TICKS 50 +#define ADAPTIVE_HI_RX_COALESCING_TICKS 300 +#define ADAPTIVE_LO_PKT_THRESH 30000 +#define ADAPTIVE_HI_PKT_THRESH 74000 +#define DEFAULT_TX_MAX_COALESCED_FRAMES 40 +#define ADAPTIVE_LO_TX_MAX_COALESCED_FRAMES 25 +#define ADAPTIVE_HI_TX_MAX_COALESCED_FRAMES 75 +#define MAX_TX_MAX_COALESCED_FRAMES 100 + +#define DEFAULT_RX_COALESCING_TICKS_DURING_INT 25 +#define DEFAULT_TX_COALESCING_TICKS_DURING_INT 25 +#define DEFAULT_RX_MAX_COALESCED_FRAMES_DURING_INT 5 +#define DEFAULT_TX_MAX_COALESCED_FRAMES_DURING_INT 5 + +#define BAD_DEFAULT_VALUE 0xffffffff + +#define DEFAULT_STATS_COALESCING_TICKS 1000000 +#define MAX_STATS_COALESCING_TICKS 3600000000U + + +/* Receive BD Replenish thresholds. */ +#define DEFAULT_RCV_STD_BD_REPLENISH_THRESHOLD 4 +#define DEFAULT_RCV_JUMBO_BD_REPLENISH_THRESHOLD 4 + +#define SPLIT_MODE_DISABLE 0 +#define SPLIT_MODE_ENABLE 1 + +#define SPLIT_MODE_5704_MAX_REQ 3 + +/* Maximum physical fragment size. */ +#define MAX_FRAGMENT_SIZE (64 * 1024) + + +/* Standard view. */ +#define T3_STD_VIEW_SIZE (64 * 1024) +#define T3_FLAT_VIEW_SIZE (32 * 1024 * 1024) + + +/* Buffer descriptor base address on the NIC's memory. */ + +#define T3_NIC_SND_BUFFER_DESC_ADDR 0x4000 +#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR 0x6000 +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR 0x7000 + +#define T3_NIC_STD_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xc000 +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xd000 +#define T3_NIC_MINI_RCV_BUFFER_DESC_ADDR_EXT_MEM 0xe000 + +#define T3_NIC_SND_BUFFER_DESC_SIZE (T3_SEND_RCB_ENTRY_COUNT * \ + sizeof(T3_SND_BD) / 4) + +#define T3_NIC_STD_RCV_BUFFER_DESC_SIZE (T3_STD_RCV_RCB_ENTRY_COUNT * \ + sizeof(T3_RCV_BD) / 4) + +#define T3_NIC_JUMBO_RCV_BUFFER_DESC_SIZE (T3_JUMBO_RCV_RCB_ENTRY_COUNT * \ + sizeof(T3_EXT_RCV_BD) / 4) + + +/* MBUF pool. */ +#define T3_NIC_MBUF_POOL_ADDR 0x8000 +/* #define T3_NIC_MBUF_POOL_SIZE 0x18000 */ +#define T3_NIC_MBUF_POOL_SIZE96 0x18000 +#define T3_NIC_MBUF_POOL_SIZE64 0x10000 + + +#define T3_NIC_MBUF_POOL_ADDR_EXT_MEM 0x20000 + +/* DMA descriptor pool */ +#define T3_NIC_DMA_DESC_POOL_ADDR 0x2000 +#define T3_NIC_DMA_DESC_POOL_SIZE 0x2000 /* 8KB. */ + +#define T3_DEF_DMA_MBUF_LOW_WMARK 0x40 +#define T3_DEF_RX_MAC_MBUF_LOW_WMARK 0x20 +#define T3_DEF_MBUF_HIGH_WMARK 0x60 + +#define T3_DEF_DMA_MBUF_LOW_WMARK_JUMBO 304 +#define T3_DEF_RX_MAC_MBUF_LOW_WMARK_JUMBO 152 +#define T3_DEF_MBUF_HIGH_WMARK_JUMBO 380 + +#define T3_DEF_DMA_DESC_LOW_WMARK 5 +#define T3_DEF_DMA_DESC_HIGH_WMARK 10 + +/* Maximum size of giant TCP packet can be sent */ +#define T3_TCP_SEG_MAX_OFFLOAD_SIZE 64*1000 +#define T3_TCP_SEG_MIN_NUM_SEG 20 + +#define T3_RX_CPU_ID 0x1 +#define T3_TX_CPU_ID 0x2 +#define T3_RX_CPU_SPAD_ADDR 0x30000 +#define T3_RX_CPU_SPAD_SIZE 0x4000 +#define T3_TX_CPU_SPAD_ADDR 0x34000 +#define T3_TX_CPU_SPAD_SIZE 0x4000 + +typedef struct T3_DIR_ENTRY +{ + PLM_UINT8 Buffer; + LM_UINT32 Offset; + LM_UINT32 Length; +} T3_DIR_ENTRY,*PT3_DIR_ENTRY; + +typedef struct T3_FWIMG_INFO +{ + LM_UINT32 StartAddress; + T3_DIR_ENTRY Text; + T3_DIR_ENTRY ROnlyData; + T3_DIR_ENTRY Data; + T3_DIR_ENTRY Sbss; + T3_DIR_ENTRY Bss; +} T3_FWIMG_INFO, *PT3_FWIMG_INFO; + + + +/******************************************************************************/ +/* Tigon3 PCI Registers. */ +/******************************************************************************/ +#define T3_PCI_ID_BCM5700 0x164414e4 +#define T3_PCI_ID_BCM5701 0x164514e4 +#define T3_PCI_ID_BCM5702 0x164614e4 +#define T3_PCI_ID_BCM5702x 0x16A614e4 +#define T3_PCI_ID_BCM5703 0x164714e4 +#define T3_PCI_ID_BCM5703x 0x16A714e4 +#define T3_PCI_ID_BCM5702FE 0x164D14e4 +#define T3_PCI_ID_BCM5704 0x164814e4 + +#define T3_PCI_VENDOR_ID (T3_PCI_ID & 0xffff) +#define T3_PCI_DEVICE_ID (T3_PCI_ID >> 16) + +#define T3_PCI_MISC_HOST_CTRL_REG 0x68 + +/* The most significant 16bit of register 0x68. */ +/* ChipId:4, ChipRev:4, MetalRev:8 */ +#define T3_CHIP_ID_5700_A0 0x7000 +#define T3_CHIP_ID_5700_A1 0x7001 +#define T3_CHIP_ID_5700_B0 0x7100 +#define T3_CHIP_ID_5700_B1 0x7101 +#define T3_CHIP_ID_5700_C0 0x7200 + +#define T3_CHIP_ID_5701_A0 0x0000 +#define T3_CHIP_ID_5701_B0 0x0100 +#define T3_CHIP_ID_5701_B2 0x0102 +#define T3_CHIP_ID_5701_B5 0x0105 + +#define T3_CHIP_ID_5703_A0 0x1000 +#define T3_CHIP_ID_5703_A1 0x1001 +#define T3_CHIP_ID_5703_A2 0x1002 + +#define T3_CHIP_ID_5704_A0 0x2000 + +/* Chip Id. */ +#define T3_ASIC_REV(_ChipRevId) ((_ChipRevId) >> 12) +#define T3_ASIC_REV_5700 0x07 +#define T3_ASIC_REV_5701 0x00 +#define T3_ASIC_REV_5703 0x01 +#define T3_ASIC_REV_5704 0x02 + + +/* Chip id and revision. */ +#define T3_CHIP_REV(_ChipRevId) ((_ChipRevId) >> 8) +#define T3_CHIP_REV_5700_AX 0x70 +#define T3_CHIP_REV_5700_BX 0x71 +#define T3_CHIP_REV_5700_CX 0x72 +#define T3_CHIP_REV_5701_AX 0x00 + +/* Metal revision. */ +#define T3_METAL_REV(_ChipRevId) ((_ChipRevId) & 0xff) +#define T3_METAL_REV_A0 0x00 +#define T3_METAL_REV_A1 0x01 +#define T3_METAL_REV_B0 0x00 +#define T3_METAL_REV_B1 0x01 +#define T3_METAL_REV_B2 0x02 + +#define T3_PCI_REG_CLOCK_CTRL 0x74 + +#define T3_PCI_DISABLE_RX_CLOCK BIT_10 +#define T3_PCI_DISABLE_TX_CLOCK BIT_11 +#define T3_PCI_SELECT_ALTERNATE_CLOCK BIT_12 +#define T3_PCI_POWER_DOWN_PCI_PLL133 BIT_15 +#define T3_PCI_44MHZ_CORE_CLOCK BIT_18 + + +#define T3_PCI_REG_ADDR_REG 0x78 +#define T3_PCI_REG_DATA_REG 0x80 + +#define T3_PCI_MEM_WIN_ADDR_REG 0x7c +#define T3_PCI_MEM_WIN_DATA_REG 0x84 + +#define T3_PCI_PM_CAP_REG 0x48 + +#define T3_PCI_PM_CAP_PME_D3COLD BIT_31 +#define T3_PCI_PM_CAP_PME_D3HOT BIT_30 + +#define T3_PCI_PM_STATUS_CTRL_REG 0x4c + +#define T3_PM_POWER_STATE_MASK (BIT_0 | BIT_1) +#define T3_PM_POWER_STATE_D0 BIT_NONE +#define T3_PM_POWER_STATE_D1 BIT_0 +#define T3_PM_POWER_STATE_D2 BIT_1 +#define T3_PM_POWER_STATE_D3 (BIT_0 | BIT_1) + +#define T3_PM_PME_ENABLE BIT_8 +#define T3_PM_PME_ASSERTED BIT_15 + + +/* PCI state register. */ +#define T3_PCI_STATE_REG 0x70 + +#define T3_PCI_STATE_FORCE_RESET BIT_0 +#define T3_PCI_STATE_INT_NOT_ACTIVE BIT_1 +#define T3_PCI_STATE_CONVENTIONAL_PCI_MODE BIT_2 +#define T3_PCI_STATE_BUS_SPEED_HIGH BIT_3 +#define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 + + +/* Broadcom subsystem/subvendor IDs. */ +#define T3_SVID_BROADCOM 0x14e4 + +#define T3_SSID_BROADCOM_BCM95700A6 0x1644 +#define T3_SSID_BROADCOM_BCM95701A5 0x0001 +#define T3_SSID_BROADCOM_BCM95700T6 0x0002 /* BCM8002 */ +#define T3_SSID_BROADCOM_BCM95700A9 0x0003 /* Agilent */ +#define T3_SSID_BROADCOM_BCM95701T1 0x0005 +#define T3_SSID_BROADCOM_BCM95701T8 0x0006 +#define T3_SSID_BROADCOM_BCM95701A7 0x0007 /* Agilent */ +#define T3_SSID_BROADCOM_BCM95701A10 0x0008 +#define T3_SSID_BROADCOM_BCM95701A12 0x8008 +#define T3_SSID_BROADCOM_BCM95703Ax1 0x0009 +#define T3_SSID_BROADCOM_BCM95703Ax2 0x8009 + +/* 3COM subsystem/subvendor IDs. */ +#define T3_SVID_3COM 0x10b7 + +#define T3_SSID_3COM_3C996T 0x1000 +#define T3_SSID_3COM_3C996BT 0x1006 +#define T3_SSID_3COM_3C996CT 0x1002 +#define T3_SSID_3COM_3C997T 0x1003 +#define T3_SSID_3COM_3C1000T 0x1007 +#define T3_SSID_3COM_3C940BR01 0x1008 + +/* Fiber boards. */ +#define T3_SSID_3COM_3C996SX 0x1004 +#define T3_SSID_3COM_3C997SX 0x1005 + + +/* Dell subsystem/subvendor IDs. */ + +#define T3_SVID_DELL 0x1028 + +#define T3_SSID_DELL_VIPER 0x00d1 +#define T3_SSID_DELL_JAGUAR 0x0106 +#define T3_SSID_DELL_MERLOT 0x0109 +#define T3_SSID_DELL_SLIM_MERLOT 0x010a + +/* Compaq subsystem/subvendor IDs */ + +#define T3_SVID_COMPAQ 0x0e11 + +#define T3_SSID_COMPAQ_BANSHEE 0x007c +#define T3_SSID_COMPAQ_BANSHEE_2 0x009a +#define T3_SSID_COMPAQ_CHANGELING 0x007d +#define T3_SSID_COMPAQ_NC7780 0x0085 +#define T3_SSID_COMPAQ_NC7780_2 0x0099 + + +/******************************************************************************/ +/* MII registers. */ +/******************************************************************************/ + +/* Control register. */ +#define PHY_CTRL_REG 0x00 + +#define PHY_CTRL_SPEED_MASK (BIT_6 | BIT_13) +#define PHY_CTRL_SPEED_SELECT_10MBPS BIT_NONE +#define PHY_CTRL_SPEED_SELECT_100MBPS BIT_13 +#define PHY_CTRL_SPEED_SELECT_1000MBPS BIT_6 +#define PHY_CTRL_COLLISION_TEST_ENABLE BIT_7 +#define PHY_CTRL_FULL_DUPLEX_MODE BIT_8 +#define PHY_CTRL_RESTART_AUTO_NEG BIT_9 +#define PHY_CTRL_ISOLATE_PHY BIT_10 +#define PHY_CTRL_LOWER_POWER_MODE BIT_11 +#define PHY_CTRL_AUTO_NEG_ENABLE BIT_12 +#define PHY_CTRL_LOOPBACK_MODE BIT_14 +#define PHY_CTRL_PHY_RESET BIT_15 + + +/* Status register. */ +#define PHY_STATUS_REG 0x01 + +#define PHY_STATUS_LINK_PASS BIT_2 +#define PHY_STATUS_AUTO_NEG_COMPLETE BIT_5 + + +/* Phy Id registers. */ +#define PHY_ID1_REG 0x02 +#define PHY_ID1_OUI_MASK 0xffff + +#define PHY_ID2_REG 0x03 +#define PHY_ID2_REV_MASK 0x000f +#define PHY_ID2_MODEL_MASK 0x03f0 +#define PHY_ID2_OUI_MASK 0xfc00 + + +/* Auto-negotiation advertisement register. */ +#define PHY_AN_AD_REG 0x04 + +#define PHY_AN_AD_ASYM_PAUSE BIT_11 +#define PHY_AN_AD_PAUSE_CAPABLE BIT_10 +#define PHY_AN_AD_10BASET_HALF BIT_5 +#define PHY_AN_AD_10BASET_FULL BIT_6 +#define PHY_AN_AD_100BASETX_HALF BIT_7 +#define PHY_AN_AD_100BASETX_FULL BIT_8 +#define PHY_AN_AD_PROTOCOL_802_3_CSMA_CD 0x01 + + +/* Auto-negotiation Link Partner Ability register. */ +#define PHY_LINK_PARTNER_ABILITY_REG 0x05 + +#define PHY_LINK_PARTNER_ASYM_PAUSE BIT_11 +#define PHY_LINK_PARTNER_PAUSE_CAPABLE BIT_10 + + +/* Auto-negotiation expansion register. */ +#define PHY_AN_EXPANSION_REG 0x06 + + + +/******************************************************************************/ +/* BCM5400 and BCM5401 phy info. */ +/******************************************************************************/ + +#define PHY_DEVICE_ID 1 + +/* OUI: bit 31-10; Model#: bit 9-4; Rev# bit 3-0. */ +#define PHY_UNKNOWN_PHY 0x00000000 +#define PHY_BCM5400_PHY_ID 0x60008040 +#define PHY_BCM5401_PHY_ID 0x60008050 +#define PHY_BCM5411_PHY_ID 0x60008070 +#define PHY_BCM5701_PHY_ID 0x60008110 +#define PHY_BCM5703_PHY_ID 0x60008160 +#define PHY_BCM5704_PHY_ID 0x60008190 +#define PHY_BCM8002_PHY_ID 0x60010140 + +#define PHY_BCM5401_B0_REV 0x1 +#define PHY_BCM5401_B2_REV 0x3 +#define PHY_BCM5401_C0_REV 0x6 + +#define PHY_ID_OUI_MASK 0xfffffc00 +#define PHY_ID_MODEL_MASK 0x000003f0 +#define PHY_ID_REV_MASK 0x0000000f +#define PHY_ID_MASK (PHY_ID_OUI_MASK | \ + PHY_ID_MODEL_MASK) + + +#define UNKNOWN_PHY_ID(x) ((((x) & PHY_ID_MASK) != PHY_BCM5400_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5401_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5411_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5701_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5703_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM5704_PHY_ID) && \ + (((x) & PHY_ID_MASK) != PHY_BCM8002_PHY_ID)) + + + +/* 1000Base-T control register. */ +#define BCM540X_1000BASET_CTRL_REG 0x09 + +#define BCM540X_AN_AD_1000BASET_HALF BIT_8 +#define BCM540X_AN_AD_1000BASET_FULL BIT_9 +#define BCM540X_CONFIG_AS_MASTER BIT_11 +#define BCM540X_ENABLE_CONFIG_AS_MASTER BIT_12 + + +/* Extended control register. */ +#define BCM540X_EXT_CTRL_REG 0x10 + +#define BCM540X_EXT_CTRL_LINK3_LED_MODE BIT_1 +#define BCM540X_EXT_CTRL_TBI BIT_15 + +/* PHY extended status register. */ +#define BCM540X_EXT_STATUS_REG 0x11 + +#define BCM540X_EXT_STATUS_LINK_PASS BIT_8 + + +/* DSP Coefficient Read/Write Port. */ +#define BCM540X_DSP_RW_PORT 0x15 + + +/* DSP Coeficient Address Register. */ +#define BCM540X_DSP_ADDRESS_REG 0x17 + +#define BCM540X_DSP_TAP_NUMBER_MASK 0x00 +#define BCM540X_DSP_AGC_A 0x00 +#define BCM540X_DSP_AGC_B 0x01 +#define BCM540X_DSP_MSE_PAIR_STATUS 0x02 +#define BCM540X_DSP_SOFT_DECISION 0x03 +#define BCM540X_DSP_PHASE_REG 0x04 +#define BCM540X_DSP_SKEW 0x05 +#define BCM540X_DSP_POWER_SAVER_UPPER_BOUND 0x06 +#define BCM540X_DSP_POWER_SAVER_LOWER_BOUND 0x07 +#define BCM540X_DSP_LAST_ECHO 0x08 +#define BCM540X_DSP_FREQUENCY 0x09 +#define BCM540X_DSP_PLL_BANDWIDTH 0x0a +#define BCM540X_DSP_PLL_PHASE_OFFSET 0x0b + +#define BCM540X_DSP_FILTER_DCOFFSET (BIT_10 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT3 (BIT_8 | BIT_9 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT2 (BIT_9 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT1 (BIT_8 | BIT_11) +#define BCM540X_DSP_FILTER_FEXT0 BIT_11 +#define BCM540X_DSP_FILTER_NEXT3 (BIT_8 | BIT_9 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT2 (BIT_9 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT1 (BIT_8 | BIT_10) +#define BCM540X_DSP_FILTER_NEXT0 BIT_10 +#define BCM540X_DSP_FILTER_ECHO (BIT_8 | BIT_9) +#define BCM540X_DSP_FILTER_DFE BIT_9 +#define BCM540X_DSP_FILTER_FFE BIT_8 + +#define BCM540X_DSP_CONTROL_ALL_FILTERS BIT_12 + +#define BCM540X_DSP_SEL_CH_0 BIT_NONE +#define BCM540X_DSP_SEL_CH_1 BIT_13 +#define BCM540X_DSP_SEL_CH_2 BIT_14 +#define BCM540X_DSP_SEL_CH_3 (BIT_13 | BIT_14) + +#define BCM540X_CONTROL_ALL_CHANNELS BIT_15 + + +/* Auxilliary Control Register (Shadow Register) */ +#define BCM5401_AUX_CTRL 0x18 + +#define BCM5401_SHADOW_SEL_MASK 0x7 +#define BCM5401_SHADOW_SEL_NORMAL 0x00 +#define BCM5401_SHADOW_SEL_10BASET 0x01 +#define BCM5401_SHADOW_SEL_POWER_CONTROL 0x02 +#define BCM5401_SHADOW_SEL_IP_PHONE 0x03 +#define BCM5401_SHADOW_SEL_MISC_TEST1 0x04 +#define BCM5401_SHADOW_SEL_MISC_TEST2 0x05 +#define BCM5401_SHADOW_SEL_IP_PHONE_SEED 0x06 + + +/* Shadow register selector == '000' */ +#define BCM5401_SHDW_NORMAL_DIAG_MODE BIT_3 +#define BCM5401_SHDW_NORMAL_DISABLE_MBP BIT_4 +#define BCM5401_SHDW_NORMAL_DISABLE_LOW_PWR BIT_5 +#define BCM5401_SHDW_NORMAL_DISABLE_INV_PRF BIT_6 +#define BCM5401_SHDW_NORMAL_DISABLE_PRF BIT_7 +#define BCM5401_SHDW_NORMAL_RX_SLICING_NORMAL BIT_NONE +#define BCM5401_SHDW_NORMAL_RX_SLICING_4D BIT_8 +#define BCM5401_SHDW_NORMAL_RX_SLICING_3LVL_1D BIT_9 +#define BCM5401_SHDW_NORMAL_RX_SLICING_5LVL_1D (BIT_8 | BIT_9) +#define BCM5401_SHDW_NORMAL_TX_6DB_CODING BIT_10 +#define BCM5401_SHDW_NORMAL_ENABLE_SM_DSP_CLOCK BIT_11 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_4NS BIT_NONE +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_5NS BIT_12 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_3NS BIT_13 +#define BCM5401_SHDW_NORMAL_EDGERATE_CTRL_0NS (BIT_12 | BIT_13) +#define BCM5401_SHDW_NORMAL_EXT_PACKET_LENGTH BIT_14 +#define BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK BIT_15 + + +/* Auxilliary status summary. */ +#define BCM540X_AUX_STATUS_REG 0x19 + +#define BCM540X_AUX_LINK_PASS BIT_2 +#define BCM540X_AUX_SPEED_MASK (BIT_8 | BIT_9 | BIT_10) +#define BCM540X_AUX_10BASET_HD BIT_8 +#define BCM540X_AUX_10BASET_FD BIT_9 +#define BCM540X_AUX_100BASETX_HD (BIT_8 | BIT_9) +#define BCM540X_AUX_100BASET4 BIT_10 +#define BCM540X_AUX_100BASETX_FD (BIT_8 | BIT_10) +#define BCM540X_AUX_100BASET_HD (BIT_9 | BIT_10) +#define BCM540X_AUX_100BASET_FD (BIT_8 | BIT_9 | BIT_10) + + +/* Interrupt status. */ +#define BCM540X_INT_STATUS_REG 0x1a + +#define BCM540X_INT_LINK_CHANGE BIT_1 +#define BCM540X_INT_SPEED_CHANGE BIT_2 +#define BCM540X_INT_DUPLEX_CHANGE BIT_3 +#define BCM540X_INT_AUTO_NEG_PAGE_RX BIT_10 + + +/* Interrupt mask register. */ +#define BCM540X_INT_MASK_REG 0x1b + + + +/******************************************************************************/ +/* Register definitions. */ +/******************************************************************************/ + +typedef volatile LM_UINT8 T3_8BIT_REGISTER, *PT3_8BIT_REGISTER; +typedef volatile LM_UINT16 T3_16BIT_REGISTER, *PT3_16BIT_REGISTER; +typedef volatile LM_UINT32 T3_32BIT_REGISTER, *PT3_32BIT_REGISTER; + +typedef struct { + /* Big endian format. */ + T3_32BIT_REGISTER High; + T3_32BIT_REGISTER Low; +} T3_64BIT_REGISTER, *PT3_64BIT_REGISTER; + +typedef T3_64BIT_REGISTER T3_64BIT_HOST_ADDR, *PT3_64BIT_HOST_ADDR; + +#define T3_NUM_OF_DMA_DESC 256 +#define T3_NUM_OF_MBUF 768 + +typedef struct +{ + T3_64BIT_REGISTER host_addr; + T3_32BIT_REGISTER nic_mbuf; + T3_16BIT_REGISTER len; + T3_16BIT_REGISTER cqid_sqid; + T3_32BIT_REGISTER flags; + T3_32BIT_REGISTER opaque1; + T3_32BIT_REGISTER opaque2; + T3_32BIT_REGISTER opaque3; +}T3_DMA_DESC, *PT3_DMA_DESC; + + + +/******************************************************************************/ +/* Ring control block. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_REGISTER HostRingAddr; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + T3_16BIT_REGISTER MaxLen; + T3_16BIT_REGISTER Flags; +#else /* BIG_ENDIAN_HOST */ + T3_16BIT_REGISTER Flags; + T3_16BIT_REGISTER MaxLen; +#endif + } s; + + T3_32BIT_REGISTER MaxLen_Flags; + } u; + + T3_32BIT_REGISTER NicRingAddr; +} T3_RCB, *PT3_RCB; + +#define T3_RCB_FLAG_USE_EXT_RECV_BD BIT_0 +#define T3_RCB_FLAG_RING_DISABLED BIT_1 + + + +/******************************************************************************/ +/* Status block. */ +/******************************************************************************/ + +/* + * Size of status block is actually 0x50 bytes. Use 0x80 bytes for + * cache line alignment. + */ +#define T3_STATUS_BLOCK_SIZE 0x80 + +typedef struct { + volatile LM_UINT32 Status; + #define STATUS_BLOCK_UPDATED BIT_0 + #define STATUS_BLOCK_LINK_CHANGED_STATUS BIT_1 + #define STATUS_BLOCK_ERROR BIT_2 + + volatile LM_UINT32 StatusTag; + +#ifdef BIG_ENDIAN_HOST + volatile LM_UINT16 RcvStdConIdx; + volatile LM_UINT16 RcvJumboConIdx; + + volatile LM_UINT16 Reserved2; + volatile LM_UINT16 RcvMiniConIdx; + + struct { + volatile LM_UINT16 SendConIdx; /* Send consumer index. */ + volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ + } Idx[16]; +#else /* BIG_ENDIAN_HOST */ + volatile LM_UINT16 RcvJumboConIdx; + volatile LM_UINT16 RcvStdConIdx; + + volatile LM_UINT16 RcvMiniConIdx; + volatile LM_UINT16 Reserved2; + + struct { + volatile LM_UINT16 RcvProdIdx; /* Receive producer index. */ + volatile LM_UINT16 SendConIdx; /* Send consumer index. */ + } Idx[16]; +#endif +} T3_STATUS_BLOCK, *PT3_STATUS_BLOCK; + + + +/******************************************************************************/ +/* Receive buffer descriptors. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr; + +#ifdef BIG_ENDIAN_HOST + volatile LM_UINT16 Index; + volatile LM_UINT16 Len; + + volatile LM_UINT16 Type; + volatile LM_UINT16 Flags; + + volatile LM_UINT16 IpCksum; + volatile LM_UINT16 TcpUdpCksum; + + volatile LM_UINT16 ErrorFlag; + volatile LM_UINT16 VlanTag; +#else /* BIG_ENDIAN_HOST */ + volatile LM_UINT16 Len; + volatile LM_UINT16 Index; + + volatile LM_UINT16 Flags; + volatile LM_UINT16 Type; + + volatile LM_UINT16 TcpUdpCksum; + volatile LM_UINT16 IpCksum; + + volatile LM_UINT16 VlanTag; + volatile LM_UINT16 ErrorFlag; +#endif + + volatile LM_UINT32 Reserved; + volatile LM_UINT32 Opaque; +} T3_RCV_BD, *PT3_RCV_BD; + + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr[3]; + +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Len1; + LM_UINT16 Len2; + + LM_UINT16 Len3; + LM_UINT16 Reserved1; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 Len2; + LM_UINT16 Len1; + + LM_UINT16 Reserved1; + LM_UINT16 Len3; +#endif + + T3_RCV_BD StdRcvBd; +} T3_EXT_RCV_BD, *PT3_EXT_RCV_BD; + + +/* Error flags. */ +#define RCV_BD_ERR_BAD_CRC 0x0001 +#define RCV_BD_ERR_COLL_DETECT 0x0002 +#define RCV_BD_ERR_LINK_LOST_DURING_PKT 0x0004 +#define RCV_BD_ERR_PHY_DECODE_ERR 0x0008 +#define RCV_BD_ERR_ODD_NIBBLED_RCVD_MII 0x0010 +#define RCV_BD_ERR_MAC_ABORT 0x0020 +#define RCV_BD_ERR_LEN_LT_64 0x0040 +#define RCV_BD_ERR_TRUNC_NO_RESOURCES 0x0080 +#define RCV_BD_ERR_GIANT_FRAME_RCVD 0x0100 + + +/* Buffer descriptor flags. */ +#define RCV_BD_FLAG_END 0x0004 +#define RCV_BD_FLAG_JUMBO_RING 0x0020 +#define RCV_BD_FLAG_VLAN_TAG 0x0040 +#define RCV_BD_FLAG_FRAME_HAS_ERROR 0x0400 +#define RCV_BD_FLAG_MINI_RING 0x0800 +#define RCV_BD_FLAG_IP_CHKSUM_FIELD 0x1000 +#define RCV_BD_FLAG_TCP_UDP_CHKSUM_FIELD 0x2000 +#define RCV_BD_FLAG_TCP_PACKET 0x4000 + + + +/******************************************************************************/ +/* Send buffer descriptor. */ +/******************************************************************************/ + +typedef struct { + T3_64BIT_HOST_ADDR HostAddr; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Len; + LM_UINT16 Flags; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 Flags; + LM_UINT16 Len; +#endif + } s1; + + LM_UINT32 Len_Flags; + } u1; + + union { + struct { +#ifdef BIG_ENDIAN_HOST + LM_UINT16 Reserved; + LM_UINT16 VlanTag; +#else /* BIG_ENDIAN_HOST */ + LM_UINT16 VlanTag; + LM_UINT16 Reserved; +#endif + } s2; + + LM_UINT32 VlanTag; + } u2; +} T3_SND_BD, *PT3_SND_BD; + + +/* Send buffer descriptor flags. */ +#define SND_BD_FLAG_TCP_UDP_CKSUM 0x0001 +#define SND_BD_FLAG_IP_CKSUM 0x0002 +#define SND_BD_FLAG_END 0x0004 +#define SND_BD_FLAG_IP_FRAG 0x0008 +#define SND_BD_FLAG_IP_FRAG_END 0x0010 +#define SND_BD_FLAG_VLAN_TAG 0x0040 +#define SND_BD_FLAG_COAL_NOW 0x0080 +#define SND_BD_FLAG_CPU_PRE_DMA 0x0100 +#define SND_BD_FLAG_CPU_POST_DMA 0x0200 +#define SND_BD_FLAG_INSERT_SRC_ADDR 0x1000 +#define SND_BD_FLAG_CHOOSE_SRC_ADDR 0x6000 +#define SND_BD_FLAG_DONT_GEN_CRC 0x8000 + +/* MBUFs */ +typedef struct T3_MBUF_FRAME_DESC { +#ifdef BIG_ENDIAN_HOST + LM_UINT32 status_control; + union { + struct { + LM_UINT8 cqid; + LM_UINT8 reserved1; + LM_UINT16 length; + }s1; + LM_UINT32 word; + }u1; + union { + struct + { + LM_UINT16 ip_hdr_start; + LM_UINT16 tcp_udp_hdr_start; + }s2; + + LM_UINT32 word; + }u2; + + union { + struct { + LM_UINT16 data_start; + LM_UINT16 vlan_id; + }s3; + + LM_UINT32 word; + }u3; + + union { + struct { + LM_UINT16 ip_checksum; + LM_UINT16 tcp_udp_checksum; + }s4; + + LM_UINT32 word; + }u4; + + union { + struct { + LM_UINT16 pseudo_checksum; + LM_UINT16 checksum_status; + }s5; + + LM_UINT32 word; + }u5; + + union { + struct { + LM_UINT16 rule_match; + LM_UINT8 class; + LM_UINT8 rupt; + }s6; + + LM_UINT32 word; + }u6; + + union { + struct { + LM_UINT16 reserved2; + LM_UINT16 mbuf_num; + }s7; + + LM_UINT32 word; + }u7; + + LM_UINT32 reserved3; + LM_UINT32 reserved4; +#else + LM_UINT32 status_control; + union { + struct { + LM_UINT16 length; + LM_UINT8 reserved1; + LM_UINT8 cqid; + }s1; + LM_UINT32 word; + }u1; + union { + struct + { + LM_UINT16 tcp_udp_hdr_start; + LM_UINT16 ip_hdr_start; + }s2; + + LM_UINT32 word; + }u2; + + union { + struct { + LM_UINT16 vlan_id; + LM_UINT16 data_start; + }s3; + + LM_UINT32 word; + }u3; + + union { + struct { + LM_UINT16 tcp_udp_checksum; + LM_UINT16 ip_checksum; + }s4; + + LM_UINT32 word; + }u4; + + union { + struct { + LM_UINT16 checksum_status; + LM_UINT16 pseudo_checksum; + }s5; + + LM_UINT32 word; + }u5; + + union { + struct { + LM_UINT8 rupt; + LM_UINT8 class; + LM_UINT16 rule_match; + }s6; + + LM_UINT32 word; + }u6; + + union { + struct { + LM_UINT16 mbuf_num; + LM_UINT16 reserved2; + }s7; + + LM_UINT32 word; + }u7; + + LM_UINT32 reserved3; + LM_UINT32 reserved4; +#endif +}T3_MBUF_FRAME_DESC,*PT3_MBUF_FRAME_DESC; + +typedef struct T3_MBUF_HDR { + union { + struct { + unsigned int C:1; + unsigned int F:1; + unsigned int reserved1:7; + unsigned int next_mbuf:16; + unsigned int length:7; + }s1; + + LM_UINT32 word; + }u1; + + LM_UINT32 next_frame_ptr; +}T3_MBUF_HDR, *PT3_MBUF_HDR; + +typedef struct T3_MBUF +{ + T3_MBUF_HDR hdr; + union + { + struct { + T3_MBUF_FRAME_DESC frame_hdr; + LM_UINT32 data[20]; + }s1; + + struct { + LM_UINT32 data[30]; + }s2; + }body; +}T3_MBUF, *PT3_MBUF; + +#define T3_MBUF_BASE (T3_NIC_MBUF_POOL_ADDR >> 7) +#define T3_MBUF_END ((T3_NIC_MBUF_POOL_ADDR + T3_NIC_MBUF_POOL_SIZE) >> 7) + + + +/******************************************************************************/ +/* Statistics block. */ +/******************************************************************************/ + +typedef struct { + LM_UINT8 Reserved0[0x400-0x300]; + + /* Statistics maintained by Receive MAC. */ + T3_64BIT_REGISTER ifHCInOctets; + T3_64BIT_REGISTER Reserved1; + T3_64BIT_REGISTER etherStatsFragments; + T3_64BIT_REGISTER ifHCInUcastPkts; + T3_64BIT_REGISTER ifHCInMulticastPkts; + T3_64BIT_REGISTER ifHCInBroadcastPkts; + T3_64BIT_REGISTER dot3StatsFCSErrors; + T3_64BIT_REGISTER dot3StatsAlignmentErrors; + T3_64BIT_REGISTER xonPauseFramesReceived; + T3_64BIT_REGISTER xoffPauseFramesReceived; + T3_64BIT_REGISTER macControlFramesReceived; + T3_64BIT_REGISTER xoffStateEntered; + T3_64BIT_REGISTER dot3StatsFramesTooLong; + T3_64BIT_REGISTER etherStatsJabbers; + T3_64BIT_REGISTER etherStatsUndersizePkts; + T3_64BIT_REGISTER inRangeLengthError; + T3_64BIT_REGISTER outRangeLengthError; + T3_64BIT_REGISTER etherStatsPkts64Octets; + T3_64BIT_REGISTER etherStatsPkts65Octetsto127Octets; + T3_64BIT_REGISTER etherStatsPkts128Octetsto255Octets; + T3_64BIT_REGISTER etherStatsPkts256Octetsto511Octets; + T3_64BIT_REGISTER etherStatsPkts512Octetsto1023Octets; + T3_64BIT_REGISTER etherStatsPkts1024Octetsto1522Octets; + T3_64BIT_REGISTER etherStatsPkts1523Octetsto2047Octets; + T3_64BIT_REGISTER etherStatsPkts2048Octetsto4095Octets; + T3_64BIT_REGISTER etherStatsPkts4096Octetsto8191Octets; + T3_64BIT_REGISTER etherStatsPkts8192Octetsto9022Octets; + + T3_64BIT_REGISTER Unused1[37]; + + /* Statistics maintained by Transmit MAC. */ + T3_64BIT_REGISTER ifHCOutOctets; + T3_64BIT_REGISTER Reserved2; + T3_64BIT_REGISTER etherStatsCollisions; + T3_64BIT_REGISTER outXonSent; + T3_64BIT_REGISTER outXoffSent; + T3_64BIT_REGISTER flowControlDone; + T3_64BIT_REGISTER dot3StatsInternalMacTransmitErrors; + T3_64BIT_REGISTER dot3StatsSingleCollisionFrames; + T3_64BIT_REGISTER dot3StatsMultipleCollisionFrames; + T3_64BIT_REGISTER dot3StatsDeferredTransmissions; + T3_64BIT_REGISTER Reserved3; + T3_64BIT_REGISTER dot3StatsExcessiveCollisions; + T3_64BIT_REGISTER dot3StatsLateCollisions; + T3_64BIT_REGISTER dot3Collided2Times; + T3_64BIT_REGISTER dot3Collided3Times; + T3_64BIT_REGISTER dot3Collided4Times; + T3_64BIT_REGISTER dot3Collided5Times; + T3_64BIT_REGISTER dot3Collided6Times; + T3_64BIT_REGISTER dot3Collided7Times; + T3_64BIT_REGISTER dot3Collided8Times; + T3_64BIT_REGISTER dot3Collided9Times; + T3_64BIT_REGISTER dot3Collided10Times; + T3_64BIT_REGISTER dot3Collided11Times; + T3_64BIT_REGISTER dot3Collided12Times; + T3_64BIT_REGISTER dot3Collided13Times; + T3_64BIT_REGISTER dot3Collided14Times; + T3_64BIT_REGISTER dot3Collided15Times; + T3_64BIT_REGISTER ifHCOutUcastPkts; + T3_64BIT_REGISTER ifHCOutMulticastPkts; + T3_64BIT_REGISTER ifHCOutBroadcastPkts; + T3_64BIT_REGISTER dot3StatsCarrierSenseErrors; + T3_64BIT_REGISTER ifOutDiscards; + T3_64BIT_REGISTER ifOutErrors; + + T3_64BIT_REGISTER Unused2[31]; + + /* Statistics maintained by Receive List Placement. */ + T3_64BIT_REGISTER COSIfHCInPkts[16]; + T3_64BIT_REGISTER COSFramesDroppedDueToFilters; + T3_64BIT_REGISTER nicDmaWriteQueueFull; + T3_64BIT_REGISTER nicDmaWriteHighPriQueueFull; + T3_64BIT_REGISTER nicNoMoreRxBDs; + T3_64BIT_REGISTER ifInDiscards; + T3_64BIT_REGISTER ifInErrors; + T3_64BIT_REGISTER nicRecvThresholdHit; + + T3_64BIT_REGISTER Unused3[9]; + + /* Statistics maintained by Send Data Initiator. */ + T3_64BIT_REGISTER COSIfHCOutPkts[16]; + T3_64BIT_REGISTER nicDmaReadQueueFull; + T3_64BIT_REGISTER nicDmaReadHighPriQueueFull; + T3_64BIT_REGISTER nicSendDataCompQueueFull; + + /* Statistics maintained by Host Coalescing. */ + T3_64BIT_REGISTER nicRingSetSendProdIndex; + T3_64BIT_REGISTER nicRingStatusUpdate; + T3_64BIT_REGISTER nicInterrupts; + T3_64BIT_REGISTER nicAvoidedInterrupts; + T3_64BIT_REGISTER nicSendThresholdHit; + + LM_UINT8 Reserved4[0xb00-0x9c0]; +} T3_STATS_BLOCK, *PT3_STATS_BLOCK; + + + +/******************************************************************************/ +/* PCI configuration registers. */ +/******************************************************************************/ + +typedef struct { + T3_16BIT_REGISTER VendorId; + T3_16BIT_REGISTER DeviceId; + + T3_16BIT_REGISTER Command; + T3_16BIT_REGISTER Status; + + T3_32BIT_REGISTER ClassCodeRevId; + + T3_8BIT_REGISTER CacheLineSize; + T3_8BIT_REGISTER LatencyTimer; + T3_8BIT_REGISTER HeaderType; + T3_8BIT_REGISTER Bist; + + T3_32BIT_REGISTER MemBaseAddrLow; + T3_32BIT_REGISTER MemBaseAddrHigh; + + LM_UINT8 Unused1[20]; + + T3_16BIT_REGISTER SubsystemVendorId; + T3_16BIT_REGISTER SubsystemId; + + T3_32BIT_REGISTER RomBaseAddr; + + T3_8BIT_REGISTER PciXCapiblityPtr; + LM_UINT8 Unused2[7]; + + T3_8BIT_REGISTER IntLine; + T3_8BIT_REGISTER IntPin; + T3_8BIT_REGISTER MinGnt; + T3_8BIT_REGISTER MaxLat; + + T3_8BIT_REGISTER PciXCapabilities; + T3_8BIT_REGISTER PmCapabilityPtr; + T3_16BIT_REGISTER PciXCommand; + + T3_32BIT_REGISTER PciXStatus; + + T3_8BIT_REGISTER PmCapabilityId; + T3_8BIT_REGISTER VpdCapabilityPtr; + T3_16BIT_REGISTER PmCapabilities; + + T3_16BIT_REGISTER PmCtrlStatus; + #define PM_CTRL_PME_STATUS BIT_15 + #define PM_CTRL_PME_ENABLE BIT_8 + #define PM_CTRL_PME_POWER_STATE_D0 0 + #define PM_CTRL_PME_POWER_STATE_D1 1 + #define PM_CTRL_PME_POWER_STATE_D2 2 + #define PM_CTRL_PME_POWER_STATE_D3H 3 + + T3_8BIT_REGISTER BridgeSupportExt; + T3_8BIT_REGISTER PmData; + + T3_8BIT_REGISTER VpdCapabilityId; + T3_8BIT_REGISTER MsiCapabilityPtr; + T3_16BIT_REGISTER VpdAddrFlag; + #define VPD_FLAG_WRITE (1 << 15) + #define VPD_FLAG_RW_MASK (1 << 15) + #define VPD_FLAG_READ 0 + + + T3_32BIT_REGISTER VpdData; + + T3_8BIT_REGISTER MsiCapabilityId; + T3_8BIT_REGISTER NextCapabilityPtr; + T3_16BIT_REGISTER MsiCtrl; + #define MSI_CTRL_64BIT_CAP (1 << 7) + #define MSI_CTRL_MSG_ENABLE(x) (x << 4) + #define MSI_CTRL_MSG_CAP(x) (x << 1) + #define MSI_CTRL_ENABLE (1 << 0) + + + T3_32BIT_REGISTER MsiAddrLow; + T3_32BIT_REGISTER MsiAddrHigh; + + T3_16BIT_REGISTER MsiData; + T3_16BIT_REGISTER Unused3; + + T3_32BIT_REGISTER MiscHostCtrl; + #define MISC_HOST_CTRL_CLEAR_INT BIT_0 + #define MISC_HOST_CTRL_MASK_PCI_INT BIT_1 + #define MISC_HOST_CTRL_ENABLE_ENDIAN_BYTE_SWAP BIT_2 + #define MISC_HOST_CTRL_ENABLE_ENDIAN_WORD_SWAP BIT_3 + #define MISC_HOST_CTRL_ENABLE_PCI_STATE_REG_RW BIT_4 + #define MISC_HOST_CTRL_ENABLE_CLK_REG_RW BIT_5 + #define MISC_HOST_CTRL_ENABLE_REG_WORD_SWAP BIT_6 + #define MISC_HOST_CTRL_ENABLE_INDIRECT_ACCESS BIT_7 + #define MISC_HOST_CTRL_ENABLE_INT_MASK_MODE BIT_8 + #define MISC_HOST_CTRL_ENABLE_TAGGED_STATUS_MODE BIT_9 + + T3_32BIT_REGISTER DmaReadWriteCtrl; + #define DMA_CTRL_WRITE_BOUNDARY_MASK (BIT_11 | BIT_12 | BIT_13) + #define DMA_CTRL_WRITE_BOUNDARY_DISABLE 0 + #define DMA_CTRL_WRITE_BOUNDARY_16 BIT_11 + #define DMA_CTRL_WRITE_BOUNDARY_32 BIT_12 + #define DMA_CTRL_WRITE_BOUNDARY_64 (BIT_12 | BIT_11) + #define DMA_CTRL_WRITE_BOUNDARY_128 BIT_13 + #define DMA_CTRL_WRITE_BOUNDARY_256 (BIT_13 | BIT_11) + #define DMA_CTRL_WRITE_BOUNDARY_512 (BIT_13 | BIT_12) + #define DMA_CTRL_WRITE_BOUNDARY_1024 (BIT_13 | BIT_12 | BIT_11) + #define DMA_CTRL_WRITE_ONE_DMA_AT_ONCE BIT_14 + + + T3_32BIT_REGISTER PciState; + #define T3_PCI_STATE_FORCE_PCI_RESET BIT_0 + #define T3_PCI_STATE_INTERRUPT_NOT_ACTIVE BIT_1 + #define T3_PCI_STATE_NOT_PCI_X_BUS BIT_2 + #define T3_PCI_STATE_HIGH_BUS_SPEED BIT_3 + #define T3_PCI_STATE_32BIT_PCI_BUS BIT_4 + #define T3_PCI_STATE_PCI_ROM_ENABLE BIT_5 + #define T3_PCI_STATE_PCI_ROM_RETRY_ENABLE BIT_6 + #define T3_PCI_STATE_FLAT_VIEW BIT_8 + #define T3_PCI_STATE_RETRY_SAME_DMA BIT_13 + + T3_32BIT_REGISTER ClockCtrl; + #define T3_PCI_CLKCTRL_TXCPU_CLK_DISABLE BIT_11 + #define T3_PCI_CLKCTRL_RXCPU_CLK_DISABLE BIT_10 + #define T3_PCI_CLKCTRL_CORE_CLK_DISABLE BIT_9 + + T3_32BIT_REGISTER RegBaseAddr; + + T3_32BIT_REGISTER MemWindowBaseAddr; + +#ifdef NIC_CPU_VIEW + /* These registers are ONLY visible to NIC CPU */ + T3_32BIT_REGISTER PowerConsumed; + T3_32BIT_REGISTER PowerDissipated; +#else /* NIC_CPU_VIEW */ + T3_32BIT_REGISTER RegData; + T3_32BIT_REGISTER MemWindowData; +#endif /* !NIC_CPU_VIEW */ + + T3_32BIT_REGISTER ModeCtrl; + + T3_32BIT_REGISTER MiscCfg; + + T3_32BIT_REGISTER MiscLocalCtrl; + + T3_32BIT_REGISTER Unused4; + + /* NOTE: Big/Little-endian clarification needed. Are these register */ + /* in big or little endian formate. */ + T3_64BIT_REGISTER StdRingProdIdx; + T3_64BIT_REGISTER RcvRetRingConIdx; + T3_64BIT_REGISTER SndProdIdx; + + LM_UINT8 Unused5[80]; +} T3_PCI_CONFIGURATION, *PT3_PCI_CONFIGURATION; + +#define PCIX_CMD_MAX_SPLIT_MASK 0x0070 +#define PCIX_CMD_MAX_SPLIT_SHL 4 +#define PCIX_CMD_MAX_BURST_MASK 0x000c +#define PCIX_CMD_MAX_BURST_SHL 2 +#define PCIX_CMD_MAX_BURST_CPIOB 2 + +/******************************************************************************/ +/* Mac control registers. */ +/******************************************************************************/ + +typedef struct { + /* MAC mode control. */ + T3_32BIT_REGISTER Mode; + #define MAC_MODE_GLOBAL_RESET BIT_0 + #define MAC_MODE_HALF_DUPLEX BIT_1 + #define MAC_MODE_PORT_MODE_MASK (BIT_2 | BIT_3) + #define MAC_MODE_PORT_MODE_TBI (BIT_2 | BIT_3) + #define MAC_MODE_PORT_MODE_GMII BIT_3 + #define MAC_MODE_PORT_MODE_MII BIT_2 + #define MAC_MODE_PORT_MODE_NONE BIT_NONE + #define MAC_MODE_PORT_INTERNAL_LOOPBACK BIT_4 + #define MAC_MODE_TAGGED_MAC_CONTROL BIT_7 + #define MAC_MODE_TX_BURSTING BIT_8 + #define MAC_MODE_MAX_DEFER BIT_9 + #define MAC_MODE_LINK_POLARITY BIT_10 + #define MAC_MODE_ENABLE_RX_STATISTICS BIT_11 + #define MAC_MODE_CLEAR_RX_STATISTICS BIT_12 + #define MAC_MODE_FLUSH_RX_STATISTICS BIT_13 + #define MAC_MODE_ENABLE_TX_STATISTICS BIT_14 + #define MAC_MODE_CLEAR_TX_STATISTICS BIT_15 + #define MAC_MODE_FLUSH_TX_STATISTICS BIT_16 + #define MAC_MODE_SEND_CONFIGS BIT_17 + #define MAC_MODE_DETECT_MAGIC_PACKET_ENABLE BIT_18 + #define MAC_MODE_ACPI_POWER_ON_ENABLE BIT_19 + #define MAC_MODE_ENABLE_MIP BIT_20 + #define MAC_MODE_ENABLE_TDE BIT_21 + #define MAC_MODE_ENABLE_RDE BIT_22 + #define MAC_MODE_ENABLE_FHDE BIT_23 + + /* MAC status */ + T3_32BIT_REGISTER Status; + #define MAC_STATUS_PCS_SYNCED BIT_0 + #define MAC_STATUS_SIGNAL_DETECTED BIT_1 + #define MAC_STATUS_RECEIVING_CFG BIT_2 + #define MAC_STATUS_CFG_CHANGED BIT_3 + #define MAC_STATUS_SYNC_CHANGED BIT_4 + #define MAC_STATUS_PORT_DECODE_ERROR BIT_10 + #define MAC_STATUS_LINK_STATE_CHANGED BIT_12 + #define MAC_STATUS_MI_COMPLETION BIT_22 + #define MAC_STATUS_MI_INTERRUPT BIT_23 + #define MAC_STATUS_AP_ERROR BIT_24 + #define MAC_STATUS_ODI_ERROR BIT_25 + #define MAC_STATUS_RX_STATS_OVERRUN BIT_26 + #define MAC_STATUS_TX_STATS_OVERRUN BIT_27 + + /* Event Enable */ + T3_32BIT_REGISTER MacEvent; + #define MAC_EVENT_ENABLE_PORT_DECODE_ERR BIT_10 + #define MAC_EVENT_ENABLE_LINK_STATE_CHANGED_ATTN BIT_12 + #define MAC_EVENT_ENABLE_MI_COMPLETION BIT_22 + #define MAC_EVENT_ENABLE_MI_INTERRUPT BIT_23 + #define MAC_EVENT_ENABLE_AP_ERROR BIT_24 + #define MAC_EVENT_ENABLE_ODI_ERROR BIT_25 + #define MAC_EVENT_ENABLE_RX_STATS_OVERRUN BIT_26 + #define MAC_EVENT_ENABLE_TX_STATS_OVERRUN BIT_27 + + /* Led control. */ + T3_32BIT_REGISTER LedCtrl; + #define LED_CTRL_OVERRIDE_LINK_LED BIT_0 + #define LED_CTRL_1000MBPS_LED_ON BIT_1 + #define LED_CTRL_100MBPS_LED_ON BIT_2 + #define LED_CTRL_10MBPS_LED_ON BIT_3 + #define LED_CTRL_OVERRIDE_TRAFFIC_LED BIT_4 + #define LED_CTRL_BLINK_TRAFFIC_LED BIT_5 + #define LED_CTRL_TRAFFIC_LED BIT_6 + #define LED_CTRL_1000MBPS_LED_STATUS BIT_7 + #define LED_CTRL_100MBPS_LED_STATUS BIT_8 + #define LED_CTRL_10MBPS_LED_STATUS BIT_9 + #define LED_CTRL_TRAFFIC_LED_STATUS BIT_10 + #define LED_CTRL_MAC_MODE BIT_NONE + #define LED_CTRL_PHY_MODE_1 BIT_11 + #define LED_CTRL_PHY_MODE_2 BIT_12 + #define LED_CTRL_BLINK_RATE_MASK 0x7ff80000 + #define LED_CTRL_OVERRIDE_BLINK_PERIOD BIT_19 + #define LED_CTRL_OVERRIDE_BLINK_RATE BIT_31 + + /* MAC addresses. */ + struct { + T3_32BIT_REGISTER High; /* Upper 2 bytes. */ + T3_32BIT_REGISTER Low; /* Lower 4 bytes. */ + } MacAddr[4]; + + /* ACPI Mbuf pointer. */ + T3_32BIT_REGISTER AcpiMbufPtr; + + /* ACPI Length and Offset. */ + T3_32BIT_REGISTER AcpiLengthOffset; + #define ACPI_LENGTH_MASK 0xffff + #define ACPI_OFFSET_MASK 0x0fff0000 + #define ACPI_LENGTH(x) x + #define ACPI_OFFSET(x) ((x) << 16) + + /* Transmit random backoff. */ + T3_32BIT_REGISTER TxBackoffSeed; + #define MAC_TX_BACKOFF_SEED_MASK 0x3ff + + /* Receive MTU */ + T3_32BIT_REGISTER MtuSize; + #define MAC_RX_MTU_MASK 0xffff + + /* Gigabit PCS Test. */ + T3_32BIT_REGISTER PcsTest; + #define MAC_PCS_TEST_DATA_PATTERN_MASK 0x0fffff + #define MAC_PCS_TEST_ENABLE BIT_20 + + /* Transmit Gigabit Auto-Negotiation. */ + T3_32BIT_REGISTER TxAutoNeg; + #define MAC_AN_TX_AN_DATA_MASK 0xffff + + /* Receive Gigabit Auto-Negotiation. */ + T3_32BIT_REGISTER RxAutoNeg; + #define MAC_AN_RX_AN_DATA_MASK 0xffff + + /* MI Communication. */ + T3_32BIT_REGISTER MiCom; + #define MI_COM_CMD_MASK (BIT_26 | BIT_27) + #define MI_COM_CMD_WRITE BIT_26 + #define MI_COM_CMD_READ BIT_27 + #define MI_COM_READ_FAILED BIT_28 + #define MI_COM_START BIT_29 + #define MI_COM_BUSY BIT_29 + + #define MI_COM_PHY_ADDR_MASK 0x1f + #define MI_COM_FIRST_PHY_ADDR_BIT 21 + + #define MI_COM_PHY_REG_ADDR_MASK 0x1f + #define MI_COM_FIRST_PHY_REG_ADDR_BIT 16 + + #define MI_COM_PHY_DATA_MASK 0xffff + + /* MI Status. */ + T3_32BIT_REGISTER MiStatus; + #define MI_STATUS_ENABLE_LINK_STATUS_ATTN BIT_0 + + /* MI Mode. */ + T3_32BIT_REGISTER MiMode; + #define MI_MODE_CLOCK_SPEED_10MHZ BIT_0 + #define MI_MODE_USE_SHORT_PREAMBLE BIT_1 + #define MI_MODE_AUTO_POLLING_ENABLE BIT_4 + #define MI_MODE_CORE_CLOCK_SPEED_62MHZ BIT_15 + + /* Auto-polling status. */ + T3_32BIT_REGISTER AutoPollStatus; + #define AUTO_POLL_ERROR BIT_0 + + /* Transmit MAC mode. */ + T3_32BIT_REGISTER TxMode; + #define TX_MODE_RESET BIT_0 + #define TX_MODE_ENABLE BIT_1 + #define TX_MODE_ENABLE_FLOW_CONTROL BIT_4 + #define TX_MODE_ENABLE_BIG_BACKOFF BIT_5 + #define TX_MODE_ENABLE_LONG_PAUSE BIT_6 + + /* Transmit MAC status. */ + T3_32BIT_REGISTER TxStatus; + #define TX_STATUS_RX_CURRENTLY_XOFFED BIT_0 + #define TX_STATUS_SENT_XOFF BIT_1 + #define TX_STATUS_SENT_XON BIT_2 + #define TX_STATUS_LINK_UP BIT_3 + #define TX_STATUS_ODI_UNDERRUN BIT_4 + #define TX_STATUS_ODI_OVERRUN BIT_5 + + /* Transmit MAC length. */ + T3_32BIT_REGISTER TxLengths; + #define TX_LEN_SLOT_TIME_MASK 0xff + #define TX_LEN_IPG_MASK 0x0f00 + #define TX_LEN_IPG_CRS_MASK (BIT_12 | BIT_13) + + /* Receive MAC mode. */ + T3_32BIT_REGISTER RxMode; + #define RX_MODE_RESET BIT_0 + #define RX_MODE_ENABLE BIT_1 + #define RX_MODE_ENABLE_FLOW_CONTROL BIT_2 + #define RX_MODE_KEEP_MAC_CONTROL BIT_3 + #define RX_MODE_KEEP_PAUSE BIT_4 + #define RX_MODE_ACCEPT_OVERSIZED BIT_5 + #define RX_MODE_ACCEPT_RUNTS BIT_6 + #define RX_MODE_LENGTH_CHECK BIT_7 + #define RX_MODE_PROMISCUOUS_MODE BIT_8 + #define RX_MODE_NO_CRC_CHECK BIT_9 + #define RX_MODE_KEEP_VLAN_TAG BIT_10 + + /* Receive MAC status. */ + T3_32BIT_REGISTER RxStatus; + #define RX_STATUS_REMOTE_TRANSMITTER_XOFFED BIT_0 + #define RX_STATUS_XOFF_RECEIVED BIT_1 + #define RX_STATUS_XON_RECEIVED BIT_2 + + /* Hash registers. */ + T3_32BIT_REGISTER HashReg[4]; + + /* Receive placement rules registers. */ + struct { + T3_32BIT_REGISTER Rule; + T3_32BIT_REGISTER Value; + } RcvRules[16]; + + #define RCV_DISABLE_RULE_MASK 0x7fffffff + + #define RCV_RULE1_REJECT_BROADCAST_IDX 0x00 + #define REJECT_BROADCAST_RULE1_RULE 0xc2000000 + #define REJECT_BROADCAST_RULE1_VALUE 0xffffffff + + #define RCV_RULE2_REJECT_BROADCAST_IDX 0x01 + #define REJECT_BROADCAST_RULE2_RULE 0x86000004 + #define REJECT_BROADCAST_RULE2_VALUE 0xffffffff + +#if INCLUDE_5701_AX_FIX + #define RCV_LAST_RULE_IDX 0x04 +#else + #define RCV_LAST_RULE_IDX 0x02 +#endif + + T3_32BIT_REGISTER RcvRuleCfg; + #define RX_RULE_DEFAULT_CLASS (1 << 3) + + LM_UINT8 Reserved1[140]; + + T3_32BIT_REGISTER SerdesCfg; + T3_32BIT_REGISTER SerdesStatus; + + LM_UINT8 Reserved2[104]; + + volatile LM_UINT8 TxMacState[16]; + volatile LM_UINT8 RxMacState[20]; + + LM_UINT8 Reserved3[476]; + + T3_32BIT_REGISTER RxStats[26]; + + LM_UINT8 Reserved4[24]; + + T3_32BIT_REGISTER TxStats[28]; + + LM_UINT8 Reserved5[784]; +} T3_MAC_CONTROL, *PT3_MAC_CONTROL; + + + +/******************************************************************************/ +/* Send data initiator control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define T3_SND_DATA_IN_MODE_RESET BIT_0 + #define T3_SND_DATA_IN_MODE_ENABLE BIT_1 + #define T3_SND_DATA_IN_MODE_STATS_OFLW_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define T3_SND_DATA_IN_STATUS_STATS_OFLW_ATTN BIT_2 + + T3_32BIT_REGISTER StatsCtrl; + #define T3_SND_DATA_IN_STATS_CTRL_ENABLE BIT_0 + #define T3_SND_DATA_IN_STATS_CTRL_FASTER_UPDATE BIT_1 + #define T3_SND_DATA_IN_STATS_CTRL_CLEAR BIT_2 + #define T3_SND_DATA_IN_STATS_CTRL_FLUSH BIT_3 + #define T3_SND_DATA_IN_STATS_CTRL_FORCE_ZERO BIT_4 + + T3_32BIT_REGISTER StatsEnableMask; + T3_32BIT_REGISTER StatsIncMask; + + LM_UINT8 Reserved[108]; + + T3_32BIT_REGISTER ClassOfServCnt[16]; + T3_32BIT_REGISTER DmaReadQFullCnt; + T3_32BIT_REGISTER DmaPriorityReadQFullCnt; + T3_32BIT_REGISTER SdcQFullCnt; + + T3_32BIT_REGISTER NicRingSetSendProdIdxCnt; + T3_32BIT_REGISTER StatusUpdatedCnt; + T3_32BIT_REGISTER InterruptsCnt; + T3_32BIT_REGISTER AvoidInterruptsCnt; + T3_32BIT_REGISTER SendThresholdHitCnt; + + /* Unused space. */ + LM_UINT8 Unused[800]; +} T3_SEND_DATA_INITIATOR, *PT3_SEND_DATA_INITIATOR; + + + +/******************************************************************************/ +/* Send data completion control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define SND_DATA_COMP_MODE_RESET BIT_0 + #define SND_DATA_COMP_MODE_ENABLE BIT_1 + + /* Unused space. */ + LM_UINT8 Unused[1020]; +} T3_SEND_DATA_COMPLETION, *PT3_SEND_DATA_COMPLETION; + + + +/******************************************************************************/ +/* Send BD Ring Selector Control Registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define SND_BD_SEL_MODE_RESET BIT_0 + #define SND_BD_SEL_MODE_ENABLE BIT_1 + #define SND_BD_SEL_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define SND_BD_SEL_STATUS_ERROR_ATTN BIT_2 + + T3_32BIT_REGISTER HwDiag; + + /* Unused space. */ + LM_UINT8 Unused1[52]; + + /* Send BD Ring Selector Local NIC Send BD Consumer Index. */ + T3_32BIT_REGISTER NicSendBdSelConIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused2[896]; +} T3_SEND_BD_SELECTOR, *PT3_SEND_BD_SELECTOR; + + + +/******************************************************************************/ +/* Send BD initiator control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define SND_BD_IN_MODE_RESET BIT_0 + #define SND_BD_IN_MODE_ENABLE BIT_1 + #define SND_BD_IN_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define SND_BD_IN_STATUS_ERROR_ATTN BIT_2 + + /* Send BD initiator local NIC send BD producer index. */ + T3_32BIT_REGISTER NicSendBdInProdIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused2[952]; +} T3_SEND_BD_INITIATOR, *PT3_SEND_BD_INITIATOR; + + + +/******************************************************************************/ +/* Send BD Completion Control. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define SND_BD_COMP_MODE_RESET BIT_0 + #define SND_BD_COMP_MODE_ENABLE BIT_1 + #define SND_BD_COMP_MODE_ATTN_ENABLE BIT_2 + + /* Unused space. */ + LM_UINT8 Unused2[1020]; +} T3_SEND_BD_COMPLETION, *PT3_SEND_BD_COMPLETION; + + + +/******************************************************************************/ +/* Receive list placement control registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; + #define RCV_LIST_PLMT_MODE_RESET BIT_0 + #define RCV_LIST_PLMT_MODE_ENABLE BIT_1 + #define RCV_LIST_PLMT_MODE_CLASS0_ATTN_ENABLE BIT_2 + #define RCV_LIST_PLMT_MODE_MAPPING_OOR_ATTN_ENABLE BIT_3 + #define RCV_LIST_PLMT_MODE_STATS_OFLOW_ATTN_ENABLE BIT_4 + + /* Status. */ + T3_32BIT_REGISTER Status; + #define RCV_LIST_PLMT_STATUS_CLASS0_ATTN BIT_2 + #define RCV_LIST_PLMT_STATUS_MAPPING_ATTN BIT_3 + #define RCV_LIST_PLMT_STATUS_STATS_OFLOW_ATTN BIT_4 + + /* Receive selector list lock register. */ + T3_32BIT_REGISTER Lock; + #define RCV_LIST_SEL_LOCK_REQUEST_MASK 0xffff + #define RCV_LIST_SEL_LOCK_GRANT_MASK 0xffff0000 + + /* Selector non-empty bits. */ + T3_32BIT_REGISTER NonEmptyBits; + #define RCV_LIST_SEL_NON_EMPTY_MASK 0xffff + + /* Receive list placement configuration register. */ + T3_32BIT_REGISTER Config; + + /* Receive List Placement statistics Control. */ + T3_32BIT_REGISTER StatsCtrl; +#define RCV_LIST_STATS_ENABLE BIT_0 +#define RCV_LIST_STATS_FAST_UPDATE BIT_1 + + /* Receive List Placement statistics Enable Mask. */ + T3_32BIT_REGISTER StatsEnableMask; + + /* Receive List Placement statistics Increment Mask. */ + T3_32BIT_REGISTER StatsIncMask; + + /* Unused space. */ + LM_UINT8 Unused1[224]; + + struct { + T3_32BIT_REGISTER Head; + T3_32BIT_REGISTER Tail; + T3_32BIT_REGISTER Count; + + /* Unused space. */ + LM_UINT8 Unused[4]; + } RcvSelectorList[16]; + + /* Local statistics counter. */ + T3_32BIT_REGISTER ClassOfServCnt[16]; + + T3_32BIT_REGISTER DropDueToFilterCnt; + T3_32BIT_REGISTER DmaWriteQFullCnt; + T3_32BIT_REGISTER DmaHighPriorityWriteQFullCnt; + T3_32BIT_REGISTER NoMoreReceiveBdCnt; + T3_32BIT_REGISTER IfInDiscardsCnt; + T3_32BIT_REGISTER IfInErrorsCnt; + T3_32BIT_REGISTER RcvThresholdHitCnt; + + /* Another unused space. */ + LM_UINT8 Unused2[420]; +} T3_RCV_LIST_PLACEMENT, *PT3_RCV_LIST_PLACEMENT; + + + +/******************************************************************************/ +/* Receive Data and Receive BD Initiator Control. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; + #define RCV_DATA_BD_IN_MODE_RESET BIT_0 + #define RCV_DATA_BD_IN_MODE_ENABLE BIT_1 + #define RCV_DATA_BD_IN_MODE_JUMBO_BD_NEEDED BIT_2 + #define RCV_DATA_BD_IN_MODE_FRAME_TOO_BIG BIT_3 + #define RCV_DATA_BD_IN_MODE_INVALID_RING_SIZE BIT_4 + + /* Status. */ + T3_32BIT_REGISTER Status; + #define RCV_DATA_BD_IN_STATUS_JUMBO_BD_NEEDED BIT_2 + #define RCV_DATA_BD_IN_STATUS_FRAME_TOO_BIG BIT_3 + #define RCV_DATA_BD_IN_STATUS_INVALID_RING_SIZE BIT_4 + + /* Split frame minium size. */ + T3_32BIT_REGISTER SplitFrameMinSize; + + /* Unused space. */ + LM_UINT8 Unused1[0x2440-0x240c]; + + /* Receive RCBs. */ + T3_RCB JumboRcvRcb; + T3_RCB StdRcvRcb; + T3_RCB MiniRcvRcb; + + /* Receive Data and Receive BD Ring Initiator Local NIC Receive */ + /* BD Consumber Index. */ + T3_32BIT_REGISTER NicJumboConIdx; + T3_32BIT_REGISTER NicStdConIdx; + T3_32BIT_REGISTER NicMiniConIdx; + + /* Unused space. */ + LM_UINT8 Unused2[4]; + + /* Receive Data and Receive BD Initiator Local Receive Return ProdIdx. */ + T3_32BIT_REGISTER RcvDataBdProdIdx[16]; + + /* Receive Data and Receive BD Initiator Hardware Diagnostic. */ + T3_32BIT_REGISTER HwDiag; + + /* Unused space. */ + LM_UINT8 Unused3[828]; +} T3_RCV_DATA_BD_INITIATOR, *PT3_RCV_DATA_BD_INITIATOR; + + + +/******************************************************************************/ +/* Receive Data Completion Control Registes. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define RCV_DATA_COMP_MODE_RESET BIT_0 + #define RCV_DATA_COMP_MODE_ENABLE BIT_1 + #define RCV_DATA_COMP_MODE_ATTN_ENABLE BIT_2 + + /* Unused spaced. */ + LM_UINT8 Unused[1020]; +} T3_RCV_DATA_COMPLETION, *PT3_RCV_DATA_COMPLETION; + + + +/******************************************************************************/ +/* Receive BD Initiator Control. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define RCV_BD_IN_MODE_RESET BIT_0 + #define RCV_BD_IN_MODE_ENABLE BIT_1 + #define RCV_BD_IN_MODE_BD_IN_DIABLED_RCB_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define RCV_BD_IN_STATUS_BD_IN_DIABLED_RCB_ATTN BIT_2 + + T3_32BIT_REGISTER NicJumboRcvProdIdx; + T3_32BIT_REGISTER NicStdRcvProdIdx; + T3_32BIT_REGISTER NicMiniRcvProdIdx; + + T3_32BIT_REGISTER MiniRcvThreshold; + T3_32BIT_REGISTER StdRcvThreshold; + T3_32BIT_REGISTER JumboRcvThreshold; + + /* Unused space. */ + LM_UINT8 Unused[992]; +} T3_RCV_BD_INITIATOR, *PT3_RCV_BD_INITIATOR; + + + +/******************************************************************************/ +/* Receive BD Completion Control Registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define RCV_BD_COMP_MODE_RESET BIT_0 + #define RCV_BD_COMP_MODE_ENABLE BIT_1 + #define RCV_BD_COMP_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define RCV_BD_COMP_STATUS_ERROR_ATTN BIT_2 + + T3_32BIT_REGISTER NicJumboRcvBdProdIdx; + T3_32BIT_REGISTER NicStdRcvBdProdIdx; + T3_32BIT_REGISTER NicMiniRcvBdProdIdx; + + /* Unused space. */ + LM_UINT8 Unused[1004]; +} T3_RCV_BD_COMPLETION, *PT3_RCV_BD_COMPLETION; + + + +/******************************************************************************/ +/* Receive list selector control register. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define RCV_LIST_SEL_MODE_RESET BIT_0 + #define RCV_LIST_SEL_MODE_ENABLE BIT_1 + #define RCV_LIST_SEL_MODE_ATTN_ENABLE BIT_2 + + T3_32BIT_REGISTER Status; + #define RCV_LIST_SEL_STATUS_ERROR_ATTN BIT_2 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_RCV_LIST_SELECTOR, *PT3_RCV_LIST_SELECTOR; + + + +/******************************************************************************/ +/* Mbuf cluster free registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define MBUF_CLUSTER_FREE_MODE_RESET BIT_0 +#define MBUF_CLUSTER_FREE_MODE_ENABLE BIT_1 + + T3_32BIT_REGISTER Status; + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_MBUF_CLUSTER_FREE, *PT3_MBUF_CLUSTER_FREE; + + + +/******************************************************************************/ +/* Host coalescing control registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode. */ + T3_32BIT_REGISTER Mode; + #define HOST_COALESCE_RESET BIT_0 + #define HOST_COALESCE_ENABLE BIT_1 + #define HOST_COALESCE_ATTN BIT_2 + #define HOST_COALESCE_NOW BIT_3 + #define HOST_COALESCE_FULL_STATUS_MODE BIT_NONE + #define HOST_COALESCE_64_BYTE_STATUS_MODE BIT_7 + #define HOST_COALESCE_32_BYTE_STATUS_MODE BIT_8 + #define HOST_COALESCE_CLEAR_TICKS_ON_RX_BD_EVENT BIT_9 + #define HOST_COALESCE_CLEAR_TICKS_ON_TX_BD_EVENT BIT_10 + #define HOST_COALESCE_NO_INT_ON_COALESCE_NOW_MODE BIT_11 + #define HOST_COALESCE_NO_INT_ON_FORCE_DMAD_MODE BIT_12 + + /* Status. */ + T3_32BIT_REGISTER Status; + #define HOST_COALESCE_ERROR_ATTN BIT_2 + + /* Receive coalescing ticks. */ + T3_32BIT_REGISTER RxCoalescingTicks; + + /* Send coalescing ticks. */ + T3_32BIT_REGISTER TxCoalescingTicks; + + /* Receive max coalesced frames. */ + T3_32BIT_REGISTER RxMaxCoalescedFrames; + + /* Send max coalesced frames. */ + T3_32BIT_REGISTER TxMaxCoalescedFrames; + + /* Receive coalescing ticks during interrupt. */ + T3_32BIT_REGISTER RxCoalescedTickDuringInt; + + /* Send coalescing ticks during interrupt. */ + T3_32BIT_REGISTER TxCoalescedTickDuringInt; + + /* Receive max coalesced frames during interrupt. */ + T3_32BIT_REGISTER RxMaxCoalescedFramesDuringInt; + + /* Send max coalesced frames during interrupt. */ + T3_32BIT_REGISTER TxMaxCoalescedFramesDuringInt; + + /* Statistics tick. */ + T3_32BIT_REGISTER StatsCoalescingTicks; + + /* Unused space. */ + LM_UINT8 Unused2[4]; + + /* Statistics host address. */ + T3_64BIT_REGISTER StatsBlkHostAddr; + + /* Status block host address.*/ + T3_64BIT_REGISTER StatusBlkHostAddr; + + /* Statistics NIC address. */ + T3_32BIT_REGISTER StatsBlkNicAddr; + + /* Statust block NIC address. */ + T3_32BIT_REGISTER StatusBlkNicAddr; + + /* Flow attention registers. */ + T3_32BIT_REGISTER FlowAttn; + + /* Unused space. */ + LM_UINT8 Unused3[4]; + + T3_32BIT_REGISTER NicJumboRcvBdConIdx; + T3_32BIT_REGISTER NicStdRcvBdConIdx; + T3_32BIT_REGISTER NicMiniRcvBdConIdx; + + /* Unused space. */ + LM_UINT8 Unused4[36]; + + T3_32BIT_REGISTER NicRetProdIdx[16]; + T3_32BIT_REGISTER NicSndBdConIdx[16]; + + /* Unused space. */ + LM_UINT8 Unused5[768]; +} T3_HOST_COALESCING, *PT3_HOST_COALESCING; + + + +/******************************************************************************/ +/* Memory arbiter registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define T3_MEM_ARBITER_MODE_RESET BIT_0 +#define T3_MEM_ARBITER_MODE_ENABLE BIT_1 + + T3_32BIT_REGISTER Status; + + T3_32BIT_REGISTER ArbTrapAddrLow; + T3_32BIT_REGISTER ArbTrapAddrHigh; + + /* Unused space. */ + LM_UINT8 Unused[1008]; +} T3_MEM_ARBITER, *PT3_MEM_ARBITER; + + + +/******************************************************************************/ +/* Buffer manager control register. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define BUFMGR_MODE_RESET BIT_0 + #define BUFMGR_MODE_ENABLE BIT_1 + #define BUFMGR_MODE_ATTN_ENABLE BIT_2 + #define BUFMGR_MODE_BM_TEST BIT_3 + #define BUFMGR_MODE_MBUF_LOW_ATTN_ENABLE BIT_4 + + T3_32BIT_REGISTER Status; + #define BUFMGR_STATUS_ERROR BIT_2 + #define BUFMGR_STATUS_MBUF_LOW BIT_4 + + T3_32BIT_REGISTER MbufPoolAddr; + T3_32BIT_REGISTER MbufPoolSize; + T3_32BIT_REGISTER MbufReadDmaLowWaterMark; + T3_32BIT_REGISTER MbufMacRxLowWaterMark; + T3_32BIT_REGISTER MbufHighWaterMark; + + T3_32BIT_REGISTER RxCpuMbufAllocReq; + #define BUFMGR_MBUF_ALLOC_BIT BIT_31 + T3_32BIT_REGISTER RxCpuMbufAllocResp; + T3_32BIT_REGISTER TxCpuMbufAllocReq; + T3_32BIT_REGISTER TxCpuMbufAllocResp; + + T3_32BIT_REGISTER DmaDescPoolAddr; + T3_32BIT_REGISTER DmaDescPoolSize; + T3_32BIT_REGISTER DmaLowWaterMark; + T3_32BIT_REGISTER DmaHighWaterMark; + + T3_32BIT_REGISTER RxCpuDmaAllocReq; + T3_32BIT_REGISTER RxCpuDmaAllocResp; + T3_32BIT_REGISTER TxCpuDmaAllocReq; + T3_32BIT_REGISTER TxCpuDmaAllocResp; + + T3_32BIT_REGISTER Hwdiag[3]; + + /* Unused space. */ + LM_UINT8 Unused[936]; +} T3_BUFFER_MANAGER, *PT3_BUFFER_MANAGER; + + + +/******************************************************************************/ +/* Read DMA control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define DMA_READ_MODE_RESET BIT_0 + #define DMA_READ_MODE_ENABLE BIT_1 + #define DMA_READ_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 + #define DMA_READ_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 + #define DMA_READ_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 + #define DMA_READ_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 + #define DMA_READ_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 + #define DMA_READ_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 + #define DMA_READ_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 + #define DMA_READ_MODE_LONG_READ_ATTN_ENABLE BIT_9 + #define DMA_READ_MODE_SPLIT_ENABLE BIT_11 + #define DMA_READ_MODE_SPLIT_RESET BIT_12 + + T3_32BIT_REGISTER Status; + #define DMA_READ_STATUS_TARGET_ABORT_ATTN BIT_2 + #define DMA_READ_STATUS_MASTER_ABORT_ATTN BIT_3 + #define DMA_READ_STATUS_PARITY_ERROR_ATTN BIT_4 + #define DMA_READ_STATUS_ADDR_OVERFLOW_ATTN BIT_5 + #define DMA_READ_STATUS_FIFO_OVERRUN_ATTN BIT_6 + #define DMA_READ_STATUS_FIFO_UNDERRUN_ATTN BIT_7 + #define DMA_READ_STATUS_FIFO_OVERREAD_ATTN BIT_8 + #define DMA_READ_STATUS_LONG_READ_ATTN BIT_9 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_DMA_READ, *PT3_DMA_READ; + +typedef union T3_CPU +{ + struct + { + T3_32BIT_REGISTER mode; + #define CPU_MODE_HALT BIT_10 + #define CPU_MODE_RESET BIT_0 + T3_32BIT_REGISTER state; + T3_32BIT_REGISTER EventMask; + T3_32BIT_REGISTER reserved1[4]; + T3_32BIT_REGISTER PC; + T3_32BIT_REGISTER Instruction; + T3_32BIT_REGISTER SpadUnderflow; + T3_32BIT_REGISTER WatchdogClear; + T3_32BIT_REGISTER WatchdogVector; + T3_32BIT_REGISTER WatchdogSavedPC; + T3_32BIT_REGISTER HardwareBp; + T3_32BIT_REGISTER reserved2[3]; + T3_32BIT_REGISTER WatchdogSavedState; + T3_32BIT_REGISTER LastBrchAddr; + T3_32BIT_REGISTER SpadUnderflowSet; + T3_32BIT_REGISTER reserved3[(0x200-0x50)/4]; + T3_32BIT_REGISTER Regs[32]; + T3_32BIT_REGISTER reserved4[(0x400-0x280)/4]; + }reg; +}T3_CPU, *PT3_CPU; + +/******************************************************************************/ +/* Write DMA control registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define DMA_WRITE_MODE_RESET BIT_0 + #define DMA_WRITE_MODE_ENABLE BIT_1 + #define DMA_WRITE_MODE_TARGET_ABORT_ATTN_ENABLE BIT_2 + #define DMA_WRITE_MODE_MASTER_ABORT_ATTN_ENABLE BIT_3 + #define DMA_WRITE_MODE_PARITY_ERROR_ATTN_ENABLE BIT_4 + #define DMA_WRITE_MODE_ADDR_OVERFLOW_ATTN_ENABLE BIT_5 + #define DMA_WRITE_MODE_FIFO_OVERRUN_ATTN_ENABLE BIT_6 + #define DMA_WRITE_MODE_FIFO_UNDERRUN_ATTN_ENABLE BIT_7 + #define DMA_WRITE_MODE_FIFO_OVERREAD_ATTN_ENABLE BIT_8 + #define DMA_WRITE_MODE_LONG_READ_ATTN_ENABLE BIT_9 + + T3_32BIT_REGISTER Status; + #define DMA_WRITE_STATUS_TARGET_ABORT_ATTN BIT_2 + #define DMA_WRITE_STATUS_MASTER_ABORT_ATTN BIT_3 + #define DMA_WRITE_STATUS_PARITY_ERROR_ATTN BIT_4 + #define DMA_WRITE_STATUS_ADDR_OVERFLOW_ATTN BIT_5 + #define DMA_WRITE_STATUS_FIFO_OVERRUN_ATTN BIT_6 + #define DMA_WRITE_STATUS_FIFO_UNDERRUN_ATTN BIT_7 + #define DMA_WRITE_STATUS_FIFO_OVERREAD_ATTN BIT_8 + #define DMA_WRITE_STATUS_LONG_READ_ATTN BIT_9 + + /* Unused space. */ + LM_UINT8 Unused[1016]; +} T3_DMA_WRITE, *PT3_DMA_WRITE; + + + +/******************************************************************************/ +/* Mailbox registers. */ +/******************************************************************************/ + +typedef struct { + /* Interrupt mailbox registers. */ + T3_64BIT_REGISTER Interrupt[4]; + + /* General mailbox registers. */ + T3_64BIT_REGISTER General[8]; + + /* Reload statistics mailbox. */ + T3_64BIT_REGISTER ReloadStat; + + /* Receive BD ring producer index registers. */ + T3_64BIT_REGISTER RcvStdProdIdx; + T3_64BIT_REGISTER RcvJumboProdIdx; + T3_64BIT_REGISTER RcvMiniProdIdx; + + /* Receive return ring consumer index registers. */ + T3_64BIT_REGISTER RcvRetConIdx[16]; + + /* Send BD ring host producer index registers. */ + T3_64BIT_REGISTER SendHostProdIdx[16]; + + /* Send BD ring nic producer index registers. */ + T3_64BIT_REGISTER SendNicProdIdx[16]; +}T3_MAILBOX, *PT3_MAILBOX; + +typedef struct { + T3_MAILBOX Mailbox; + + /* Priority mailbox registers. */ + T3_32BIT_REGISTER HighPriorityEventVector; + T3_32BIT_REGISTER HighPriorityEventMask; + T3_32BIT_REGISTER LowPriorityEventVector; + T3_32BIT_REGISTER LowPriorityEventMask; + + /* Unused space. */ + LM_UINT8 Unused[496]; +} T3_GRC_MAILBOX, *PT3_GRC_MAILBOX; + + +/******************************************************************************/ +/* Flow through queues. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Reset; + + LM_UINT8 Unused[12]; + + T3_32BIT_REGISTER DmaNormalReadFtqCtrl; + T3_32BIT_REGISTER DmaNormalReadFtqFullCnt; + T3_32BIT_REGISTER DmaNormalReadFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaNormalReadFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaHighReadFtqCtrl; + T3_32BIT_REGISTER DmaHighReadFtqFullCnt; + T3_32BIT_REGISTER DmaHighReadFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaHighReadFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaCompDiscardFtqCtrl; + T3_32BIT_REGISTER DmaCompDiscardFtqFullCnt; + T3_32BIT_REGISTER DmaCompDiscardFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaCompDiscardFtqFifoWritePeek; + + T3_32BIT_REGISTER SendBdCompFtqCtrl; + T3_32BIT_REGISTER SendBdCompFtqFullCnt; + T3_32BIT_REGISTER SendBdCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendBdCompFtqFifoWritePeek; + + T3_32BIT_REGISTER SendDataInitiatorFtqCtrl; + T3_32BIT_REGISTER SendDataInitiatorFtqFullCnt; + T3_32BIT_REGISTER SendDataInitiatorFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendDataInitiatorFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaNormalWriteFtqCtrl; + T3_32BIT_REGISTER DmaNormalWriteFtqFullCnt; + T3_32BIT_REGISTER DmaNormalWriteFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaNormalWriteFtqFifoWritePeek; + + T3_32BIT_REGISTER DmaHighWriteFtqCtrl; + T3_32BIT_REGISTER DmaHighWriteFtqFullCnt; + T3_32BIT_REGISTER DmaHighWriteFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER DmaHighWriteFtqFifoWritePeek; + + T3_32BIT_REGISTER SwType1FtqCtrl; + T3_32BIT_REGISTER SwType1FtqFullCnt; + T3_32BIT_REGISTER SwType1FtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SwType1FtqFifoWritePeek; + + T3_32BIT_REGISTER SendDataCompFtqCtrl; + T3_32BIT_REGISTER SendDataCompFtqFullCnt; + T3_32BIT_REGISTER SendDataCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SendDataCompFtqFifoWritePeek; + + T3_32BIT_REGISTER HostCoalesceFtqCtrl; + T3_32BIT_REGISTER HostCoalesceFtqFullCnt; + T3_32BIT_REGISTER HostCoalesceFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER HostCoalesceFtqFifoWritePeek; + + T3_32BIT_REGISTER MacTxFtqCtrl; + T3_32BIT_REGISTER MacTxFtqFullCnt; + T3_32BIT_REGISTER MacTxFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER MacTxFtqFifoWritePeek; + + T3_32BIT_REGISTER MbufClustFreeFtqCtrl; + T3_32BIT_REGISTER MbufClustFreeFtqFullCnt; + T3_32BIT_REGISTER MbufClustFreeFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER MbufClustFreeFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvBdCompFtqCtrl; + T3_32BIT_REGISTER RcvBdCompFtqFullCnt; + T3_32BIT_REGISTER RcvBdCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvBdCompFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvListPlmtFtqCtrl; + T3_32BIT_REGISTER RcvListPlmtFtqFullCnt; + T3_32BIT_REGISTER RcvListPlmtFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvListPlmtFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvDataBdInitiatorFtqCtrl; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFullCnt; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvDataBdInitiatorFtqFifoWritePeek; + + T3_32BIT_REGISTER RcvDataCompFtqCtrl; + T3_32BIT_REGISTER RcvDataCompFtqFullCnt; + T3_32BIT_REGISTER RcvDataCompFtqFifoEnqueueDequeue; + T3_32BIT_REGISTER RcvDataCompFtqFifoWritePeek; + + T3_32BIT_REGISTER SwType2FtqCtrl; + T3_32BIT_REGISTER SwType2FtqFullCnt; + T3_32BIT_REGISTER SwType2FtqFifoEnqueueDequeue; + T3_32BIT_REGISTER SwType2FtqFifoWritePeek; + + /* Unused space. */ + LM_UINT8 Unused2[736]; +} T3_FTQ, *PT3_FTQ; + + + +/******************************************************************************/ +/* Message signaled interrupt registers. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; +#define MSI_MODE_RESET BIT_0 +#define MSI_MODE_ENABLE BIT_1 + T3_32BIT_REGISTER Status; + + T3_32BIT_REGISTER MsiFifoAccess; + + /* Unused space. */ + LM_UINT8 Unused[1012]; +} T3_MSG_SIGNALED_INT, *PT3_MSG_SIGNALED_INT; + + + +/******************************************************************************/ +/* DMA Completion registes. */ +/******************************************************************************/ + +typedef struct { + T3_32BIT_REGISTER Mode; + #define DMA_COMP_MODE_RESET BIT_0 + #define DMA_COMP_MODE_ENABLE BIT_1 + + /* Unused space. */ + LM_UINT8 Unused[1020]; +} T3_DMA_COMPLETION, *PT3_DMA_COMPLETION; + + + +/******************************************************************************/ +/* GRC registers. */ +/******************************************************************************/ + +typedef struct { + /* Mode control register. */ + T3_32BIT_REGISTER Mode; + #define GRC_MODE_UPDATE_ON_COALESCING BIT_0 + #define GRC_MODE_BYTE_SWAP_NON_FRAME_DATA BIT_1 + #define GRC_MODE_WORD_SWAP_NON_FRAME_DATA BIT_2 + #define GRC_MODE_BYTE_SWAP_DATA BIT_4 + #define GRC_MODE_WORD_SWAP_DATA BIT_5 + #define GRC_MODE_SPLIT_HEADER_MODE BIT_8 + #define GRC_MODE_NO_FRAME_CRACKING BIT_9 + #define GRC_MODE_INCLUDE_CRC BIT_10 + #define GRC_MODE_ALLOW_BAD_FRAMES BIT_11 + #define GRC_MODE_NO_INTERRUPT_ON_SENDS BIT_13 + #define GRC_MODE_NO_INTERRUPT_ON_RECEIVE BIT_14 + #define GRC_MODE_FORCE_32BIT_PCI_BUS_MODE BIT_15 + #define GRC_MODE_HOST_STACK_UP BIT_16 + #define GRC_MODE_HOST_SEND_BDS BIT_17 + #define GRC_MODE_TX_NO_PSEUDO_HEADER_CHKSUM BIT_20 + #define GRC_MODE_RX_NO_PSEUDO_HEADER_CHKSUM BIT_23 + #define GRC_MODE_INT_ON_TX_CPU_ATTN BIT_24 + #define GRC_MODE_INT_ON_RX_CPU_ATTN BIT_25 + #define GRC_MODE_INT_ON_MAC_ATTN BIT_26 + #define GRC_MODE_INT_ON_DMA_ATTN BIT_27 + #define GRC_MODE_INT_ON_FLOW_ATTN BIT_28 + #define GRC_MODE_4X_NIC_BASED_SEND_RINGS BIT_29 + #define GRC_MODE_MULTICAST_FRAME_ENABLE BIT_30 + + /* Misc configuration register. */ + T3_32BIT_REGISTER MiscCfg; + #define GRC_MISC_CFG_CORE_CLOCK_RESET BIT_0 + #define GRC_MISC_PRESCALAR_TIMER_MASK 0xfe + #define GRC_MISC_BD_ID_MASK 0x0001e000 + #define GRC_MISC_BD_ID_5700 0x0001e000 + #define GRC_MISC_BD_ID_5701 0x00000000 + #define GRC_MISC_BD_ID_5703 0x00000000 + #define GRC_MISC_BD_ID_5703S 0x00002000 + #define GRC_MISC_BD_ID_5702FE 0x00004000 + #define GRC_MISC_BD_ID_5704 0x00000000 + #define GRC_MISC_BD_ID_5704CIOBE 0x00004000 + + /* Miscellaneous local control register. */ + T3_32BIT_REGISTER LocalCtrl; + #define GRC_MISC_LOCAL_CTRL_INT_ACTIVE BIT_0 + #define GRC_MISC_LOCAL_CTRL_CLEAR_INT BIT_1 + #define GRC_MISC_LOCAL_CTRL_SET_INT BIT_2 + #define GRC_MISC_LOCAL_CTRL_INT_ON_ATTN BIT_3 + #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT0 BIT_8 + #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT1 BIT_9 + #define GRC_MISC_LOCAL_CTRL_GPIO_INPUT2 BIT_10 + #define GRC_MISC_LOCAL_CTRL_GPIO_OE0 BIT_11 + #define GRC_MISC_LOCAL_CTRL_GPIO_OE1 BIT_12 + #define GRC_MISC_LOCAL_CTRL_GPIO_OE2 BIT_13 + #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT0 BIT_14 + #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT1 BIT_15 + #define GRC_MISC_LOCAL_CTRL_GPIO_OUTPUT2 BIT_16 + #define GRC_MISC_LOCAL_CTRL_ENABLE_EXT_MEMORY BIT_17 + #define GRC_MISC_LOCAL_CTRL_BANK_SELECT BIT_21 + #define GRC_MISC_LOCAL_CTRL_SSRAM_TYPE BIT_22 + + #define GRC_MISC_MEMSIZE_256K 0 + #define GRC_MISC_MEMSIZE_512K (1 << 18) + #define GRC_MISC_MEMSIZE_1024K (2 << 18) + #define GRC_MISC_MEMSIZE_2048K (3 << 18) + #define GRC_MISC_MEMSIZE_4096K (4 << 18) + #define GRC_MISC_MEMSIZE_8192K (5 << 18) + #define GRC_MISC_MEMSIZE_16M (6 << 18) + #define GRC_MISC_LOCAL_CTRL_AUTO_SEEPROM BIT_24 + + + T3_32BIT_REGISTER Timer; + + T3_32BIT_REGISTER RxCpuEvent; + T3_32BIT_REGISTER RxTimerRef; + T3_32BIT_REGISTER RxCpuSemaphore; + T3_32BIT_REGISTER RemoteRxCpuAttn; + + T3_32BIT_REGISTER TxCpuEvent; + T3_32BIT_REGISTER TxTimerRef; + T3_32BIT_REGISTER TxCpuSemaphore; + T3_32BIT_REGISTER RemoteTxCpuAttn; + + T3_64BIT_REGISTER MemoryPowerUp; + + T3_32BIT_REGISTER EepromAddr; + #define SEEPROM_ADDR_WRITE 0 + #define SEEPROM_ADDR_READ (1 << 31) + #define SEEPROM_ADDR_RW_MASK 0x80000000 + #define SEEPROM_ADDR_COMPLETE (1 << 30) + #define SEEPROM_ADDR_FSM_RESET (1 << 29) + #define SEEPROM_ADDR_DEV_ID(x) (x << 26) + #define SEEPROM_ADDR_DEV_ID_MASK 0x1c000000 + #define SEEPROM_ADDR_START (1 << 25) + #define SEEPROM_ADDR_CLK_PERD(x) (x << 16) + #define SEEPROM_ADDR_ADDRESS(x) (x & 0xfffc) + #define SEEPROM_ADDR_ADDRESS_MASK 0x0000ffff + + #define SEEPROM_CLOCK_PERIOD 60 + #define SEEPROM_CHIP_SIZE (64 * 1024) + + T3_32BIT_REGISTER EepromData; + T3_32BIT_REGISTER EepromCtrl; + + T3_32BIT_REGISTER MdiCtrl; + T3_32BIT_REGISTER SepromDelay; + + /* Unused space. */ + LM_UINT8 Unused[948]; +} T3_GRC, *PT3_GRC; + + +/******************************************************************************/ +/* NVRAM control registers. */ +/******************************************************************************/ + +typedef struct +{ + T3_32BIT_REGISTER Cmd; + #define NVRAM_CMD_RESET BIT_0 + #define NVRAM_CMD_DONE BIT_3 + #define NVRAM_CMD_DO_IT BIT_4 + #define NVRAM_CMD_WR BIT_5 + #define NVRAM_CMD_RD BIT_NONE + #define NVRAM_CMD_ERASE BIT_6 + #define NVRAM_CMD_FIRST BIT_7 + #define NVRAM_CMD_LAST BIT_8 + + T3_32BIT_REGISTER Status; + T3_32BIT_REGISTER WriteData; + + T3_32BIT_REGISTER Addr; + #define NVRAM_ADDRESS_MASK 0xffffff + + T3_32BIT_REGISTER ReadData; + + /* Flash config 1 register. */ + T3_32BIT_REGISTER Config1; + #define FLASH_INTERFACE_ENABLE BIT_0 + #define FLASH_SSRAM_BUFFERRED_MODE BIT_1 + #define FLASH_PASS_THRU_MODE BIT_2 + #define FLASH_BIT_BANG_MODE BIT_3 + #define FLASH_COMPAT_BYPASS BIT_31 + + /* Buffered flash (Atmel: AT45DB011B) specific information */ + #define BUFFERED_FLASH_PAGE_POS 9 + #define BUFFERED_FLASH_BYTE_ADDR_MASK ((1<<BUFFERED_FLASH_PAGE_POS) - 1) + #define BUFFERED_FLASH_PAGE_SIZE 264 + #define BUFFERED_FLASH_PHY_PAGE_SIZE 512 + + T3_32BIT_REGISTER Config2; + T3_32BIT_REGISTER Config3; + T3_32BIT_REGISTER SwArb; + #define SW_ARB_REQ_SET0 BIT_0 + #define SW_ARB_REQ_SET1 BIT_1 + #define SW_ARB_REQ_SET2 BIT_2 + #define SW_ARB_REQ_SET3 BIT_3 + #define SW_ARB_REQ_CLR0 BIT_4 + #define SW_ARB_REQ_CLR1 BIT_5 + #define SW_ARB_REQ_CLR2 BIT_6 + #define SW_ARB_REQ_CLR3 BIT_7 + #define SW_ARB_GNT0 BIT_8 + #define SW_ARB_GNT1 BIT_9 + #define SW_ARB_GNT2 BIT_10 + #define SW_ARB_GNT3 BIT_11 + #define SW_ARB_REQ0 BIT_12 + #define SW_ARB_REQ1 BIT_13 + #define SW_ARB_REQ2 BIT_14 + #define SW_ARB_REQ3 BIT_15 + + /* Unused space. */ + LM_UINT8 Unused[988]; +} T3_NVRAM, *PT3_NVRAM; + + +/******************************************************************************/ +/* NIC's internal memory. */ +/******************************************************************************/ + +typedef struct { + /* Page zero for the internal CPUs. */ + LM_UINT8 PageZero[0x100]; /* 0x0000 */ + + /* Send RCBs. */ + T3_RCB SendRcb[16]; /* 0x0100 */ + + /* Receive Return RCBs. */ + T3_RCB RcvRetRcb[16]; /* 0x0200 */ + + /* Statistics block. */ + T3_STATS_BLOCK StatsBlk; /* 0x0300 */ + + /* Status block. */ + T3_STATUS_BLOCK StatusBlk; /* 0x0b00 */ + + /* Reserved for software. */ + LM_UINT8 Reserved[1200]; /* 0x0b50 */ + + /* Unmapped region. */ + LM_UINT8 Unmapped[4096]; /* 0x1000 */ + + /* DMA descriptors. */ + LM_UINT8 DmaDesc[8192]; /* 0x2000 */ + + /* Buffer descriptors. */ + LM_UINT8 BufferDesc[16384]; /* 0x4000 */ +} T3_FIRST_32K_SRAM, *PT3_FIRST_32K_SRAM; + + + +/******************************************************************************/ +/* Memory layout. */ +/******************************************************************************/ + +typedef struct { + /* PCI configuration registers. */ + T3_PCI_CONFIGURATION PciCfg; + + /* Unused. */ + LM_UINT8 Unused1[0x100]; /* 0x0100 */ + + /* Mailbox . */ + T3_MAILBOX Mailbox; /* 0x0200 */ + + /* MAC control registers. */ + T3_MAC_CONTROL MacCtrl; /* 0x0400 */ + + /* Send data initiator control registers. */ + T3_SEND_DATA_INITIATOR SndDataIn; /* 0x0c00 */ + + /* Send data completion Control registers. */ + T3_SEND_DATA_COMPLETION SndDataComp; /* 0x1000 */ + + /* Send BD ring selector. */ + T3_SEND_BD_SELECTOR SndBdSel; /* 0x1400 */ + + /* Send BD initiator control registers. */ + T3_SEND_BD_INITIATOR SndBdIn; /* 0x1800 */ + + /* Send BD completion control registers. */ + T3_SEND_BD_COMPLETION SndBdComp; /* 0x1c00 */ + + /* Receive list placement control registers. */ + T3_RCV_LIST_PLACEMENT RcvListPlmt; /* 0x2000 */ + + /* Receive Data and Receive BD Initiator Control. */ + T3_RCV_DATA_BD_INITIATOR RcvDataBdIn; /* 0x2400 */ + + /* Receive Data Completion Control */ + T3_RCV_DATA_COMPLETION RcvDataComp; /* 0x2800 */ + + /* Receive BD Initiator Control Registers. */ + T3_RCV_BD_INITIATOR RcvBdIn; /* 0x2c00 */ + + /* Receive BD Completion Control Registers. */ + T3_RCV_BD_COMPLETION RcvBdComp; /* 0x3000 */ + + /* Receive list selector control registers. */ + T3_RCV_LIST_SELECTOR RcvListSel; /* 0x3400 */ + + /* Mbuf cluster free registers. */ + T3_MBUF_CLUSTER_FREE MbufClusterFree; /* 0x3800 */ + + /* Host coalescing control registers. */ + T3_HOST_COALESCING HostCoalesce; /* 0x3c00 */ + + /* Memory arbiter control registers. */ + T3_MEM_ARBITER MemArbiter; /* 0x4000 */ + + /* Buffer manger control registers. */ + T3_BUFFER_MANAGER BufMgr; /* 0x4400 */ + + /* Read DMA control registers. */ + T3_DMA_READ DmaRead; /* 0x4800 */ + + /* Write DMA control registers. */ + T3_DMA_WRITE DmaWrite; /* 0x4c00 */ + + T3_CPU rxCpu; /* 0x5000 */ + T3_CPU txCpu; /* 0x5400 */ + + /* Mailboxes. */ + T3_GRC_MAILBOX GrcMailbox; /* 0x5800 */ + + /* Flow Through queues. */ + T3_FTQ Ftq; /* 0x5c00 */ + + /* Message signaled interrupt registes. */ + T3_MSG_SIGNALED_INT Msi; /* 0x6000 */ + + /* DMA completion registers. */ + T3_DMA_COMPLETION DmaComp; /* 0x6400 */ + + /* GRC registers. */ + T3_GRC Grc; /* 0x6800 */ + + /* Unused space. */ + LM_UINT8 Unused2[1024]; /* 0x6c00 */ + + /* NVRAM registers. */ + T3_NVRAM Nvram; /* 0x7000 */ + + /* Unused space. */ + LM_UINT8 Unused3[3072]; /* 0x7400 */ + + /* The 32k memory window into the NIC's */ + /* internal memory. The memory window is */ + /* controlled by the Memory Window Base */ + /* Address register. This register is located */ + /* in the PCI configuration space. */ + union { /* 0x8000 */ + T3_FIRST_32K_SRAM First32k; + + /* Use the memory window base address register to determine the */ + /* MBUF segment. */ + LM_UINT32 Mbuf[32768/4]; + LM_UINT32 MemBlock32K[32768/4]; + } uIntMem; +} T3_STD_MEM_MAP, *PT3_STD_MEM_MAP; + + +/******************************************************************************/ +/* Adapter info. */ +/******************************************************************************/ + +typedef struct +{ + LM_UINT16 Svid; + LM_UINT16 Ssid; + LM_UINT32 PhyId; + LM_UINT32 Serdes; /* 0 = copper PHY, 1 = Serdes */ +} LM_ADAPTER_INFO, *PLM_ADAPTER_INFO; + + +/******************************************************************************/ +/* Packet queues. */ +/******************************************************************************/ + +DECLARE_QUEUE_TYPE(LM_RX_PACKET_Q, MAX_RX_PACKET_DESC_COUNT); +DECLARE_QUEUE_TYPE(LM_TX_PACKET_Q, MAX_TX_PACKET_DESC_COUNT); + + + +/******************************************************************************/ +/* Tx counters. */ +/******************************************************************************/ + +typedef struct { + LM_COUNTER TxPacketGoodCnt; + LM_COUNTER TxBytesGoodCnt; + LM_COUNTER TxPacketAbortedCnt; + LM_COUNTER NoSendBdLeftCnt; + LM_COUNTER NoMapRegisterLeftCnt; + LM_COUNTER TooManyFragmentsCnt; + LM_COUNTER NoTxPacketDescCnt; +} LM_TX_COUNTERS, *PLM_TX_COUNTERS; + + + +/******************************************************************************/ +/* Rx counters. */ +/******************************************************************************/ + +typedef struct { + LM_COUNTER RxPacketGoodCnt; + LM_COUNTER RxBytesGoodCnt; + LM_COUNTER RxPacketErrCnt; + LM_COUNTER RxErrCrcCnt; + LM_COUNTER RxErrCollCnt; + LM_COUNTER RxErrLinkLostCnt; + LM_COUNTER RxErrPhyDecodeCnt; + LM_COUNTER RxErrOddNibbleCnt; + LM_COUNTER RxErrMacAbortCnt; + LM_COUNTER RxErrShortPacketCnt; + LM_COUNTER RxErrNoResourceCnt; + LM_COUNTER RxErrLargePacketCnt; +} LM_RX_COUNTERS, *PLM_RX_COUNTERS; + + + +/******************************************************************************/ +/* Receive producer rings. */ +/******************************************************************************/ + +typedef enum { + T3_UNKNOWN_RCV_PROD_RING = 0, + T3_STD_RCV_PROD_RING = 1, + T3_MINI_RCV_PROD_RING = 2, + T3_JUMBO_RCV_PROD_RING = 3 +} T3_RCV_PROD_RING, *PT3_RCV_PROD_RING; + + + +/******************************************************************************/ +/* Packet descriptor. */ +/******************************************************************************/ + +#define LM_PACKET_SIGNATURE_TX 0x6861766b +#define LM_PACKET_SIGNATURE_RX 0x6b766168 + +typedef struct _LM_PACKET { + /* Set in LM. */ + LM_STATUS PacketStatus; + + /* Set in LM for Rx, in UM for Tx. */ + LM_UINT32 PacketSize; + + LM_UINT16 Flags; + + LM_UINT16 VlanTag; + + union { + /* Send info. */ + struct { + /* Set up by UM. */ + LM_UINT32 FragCount; + + } Tx; + + /* Receive info. */ + struct { + /* This descriptor belongs to either Std, Mini, or Jumbo ring. */ + T3_RCV_PROD_RING RcvProdRing; + + /* Receive buffer size */ + LM_UINT32 RxBufferSize; + + /* Checksum information. */ + LM_UINT16 IpChecksum; + LM_UINT16 TcpUdpChecksum; + + } Rx; + } u; +} LM_PACKET; + + + +/******************************************************************************/ +/* Tigon3 device block. */ +/******************************************************************************/ + +typedef struct _LM_DEVICE_BLOCK { + int index; /* Device ID */ + /* Memory view. */ + PT3_STD_MEM_MAP pMemView; + + /* Base address of the block of memory in which the LM_PACKET descriptors */ + /* are allocated from. */ + PLM_VOID pPacketDescBase; + + LM_UINT32 MiscHostCtrl; + LM_UINT32 GrcLocalCtrl; + LM_UINT32 DmaReadWriteCtrl; + LM_UINT32 PciState; + + /* Rx info */ + LM_UINT32 RxStdDescCnt; + LM_UINT32 RxStdQueuedCnt; + LM_UINT32 RxStdProdIdx; + + PT3_RCV_BD pRxStdBdVirt; + LM_PHYSICAL_ADDRESS RxStdBdPhy; + + LM_UINT32 RxPacketDescCnt; + LM_RX_PACKET_Q RxPacketFreeQ; + LM_RX_PACKET_Q RxPacketReceivedQ; + + /* Receive info. */ + PT3_RCV_BD pRcvRetBdVirt; + LM_PHYSICAL_ADDRESS RcvRetBdPhy; + LM_UINT32 RcvRetConIdx; + +#if T3_JUMBO_RCV_RCB_ENTRY_COUNT + LM_UINT32 RxJumboDescCnt; + LM_UINT32 RxJumboBufferSize; + LM_UINT32 RxJumboQueuedCnt; + + LM_UINT32 RxJumboProdIdx; + + PT3_RCV_BD pRxJumboBdVirt; + LM_PHYSICAL_ADDRESS RxJumboBdPhy; +#endif /* T3_JUMBO_RCV_RCB_ENTRY_COUNT */ + + /* These values are used by the upper module to inform the protocol */ + /* of the maximum transmit/receive packet size. */ + LM_UINT32 TxMtu; /* Does not include CRC. */ + LM_UINT32 RxMtu; /* Does not include CRC. */ + + /* We need to shadow the EMAC, Rx, Tx mode registers. With B0 silicon, */ + /* we may have problems reading any MAC registers in 10mb mode. */ + LM_UINT32 MacMode; + LM_UINT32 RxMode; + LM_UINT32 TxMode; + + /* MiMode register. */ + LM_UINT32 MiMode; + + /* Host coalesce mode register. */ + LM_UINT32 CoalesceMode; + + /* Send info. */ + LM_UINT32 TxPacketDescCnt; + + /* Tx info. */ + LM_TX_PACKET_Q TxPacketFreeQ; + LM_TX_PACKET_Q TxPacketActiveQ; + LM_TX_PACKET_Q TxPacketXmittedQ; + + /* Pointers to SendBd. */ + PT3_SND_BD pSendBdVirt; + LM_PHYSICAL_ADDRESS SendBdPhy; /* Only valid for Host based Send BD. */ + + /* Send producer and consumer indices. */ + LM_UINT32 SendProdIdx; + LM_UINT32 SendConIdx; + + /* Number of BD left. */ + atomic_t SendBdLeft; + + T3_SND_BD ShadowSendBd[T3_SEND_RCB_ENTRY_COUNT]; + + /* Counters. */ + LM_RX_COUNTERS RxCounters; + LM_TX_COUNTERS TxCounters; + + /* Host coalescing parameters. */ + LM_UINT32 RxCoalescingTicks; + LM_UINT32 TxCoalescingTicks; + LM_UINT32 RxMaxCoalescedFrames; + LM_UINT32 TxMaxCoalescedFrames; + LM_UINT32 StatsCoalescingTicks; + LM_UINT32 RxCoalescingTicksDuringInt; + LM_UINT32 TxCoalescingTicksDuringInt; + LM_UINT32 RxMaxCoalescedFramesDuringInt; + LM_UINT32 TxMaxCoalescedFramesDuringInt; + + /* DMA water marks. */ + LM_UINT32 DmaMbufLowMark; + LM_UINT32 RxMacMbufLowMark; + LM_UINT32 MbufHighMark; + + /* Status block. */ + PT3_STATUS_BLOCK pStatusBlkVirt; + LM_PHYSICAL_ADDRESS StatusBlkPhy; + + /* Statistics block. */ + PT3_STATS_BLOCK pStatsBlkVirt; + LM_PHYSICAL_ADDRESS StatsBlkPhy; + + /* Current receive mask. */ + LM_UINT32 ReceiveMask; + + /* Task offload capabilities. */ + LM_TASK_OFFLOAD TaskOffloadCap; + + /* Task offload selected. */ + LM_TASK_OFFLOAD TaskToOffload; + + /* Wake up capability. */ + LM_WAKE_UP_MODE WakeUpModeCap; + + /* Wake up capability. */ + LM_WAKE_UP_MODE WakeUpMode; + + /* Flow control. */ + LM_FLOW_CONTROL FlowControlCap; + LM_FLOW_CONTROL FlowControl; + + /* Enable or disable PCI MWI. */ + LM_UINT32 EnableMWI; + + /* Enable 5701 tagged status mode. */ + LM_UINT32 UseTaggedStatus; + + /* NIC will not compute the pseudo header checksum. The driver or OS */ + /* must seed the checksum field with the pseudo checksum. */ + LM_UINT32 NoTxPseudoHdrChksum; + + /* The receive checksum in the BD does not include the pseudo checksum. */ + /* The OS or the driver must calculate the pseudo checksum and add it to */ + /* the checksum in the BD. */ + LM_UINT32 NoRxPseudoHdrChksum; + + /* Current node address. */ + LM_UINT8 NodeAddress[8]; + + /* The adapter's node address. */ + LM_UINT8 PermanentNodeAddress[8]; + + /* Adapter info. */ + LM_UINT16 BusNum; + LM_UINT8 DevNum; + LM_UINT8 FunctNum; + LM_UINT16 PciVendorId; + LM_UINT16 PciDeviceId; + LM_UINT32 BondId; + LM_UINT8 Irq; + LM_UINT8 IntPin; + LM_UINT8 CacheLineSize; + LM_UINT8 PciRevId; +#if PCIX_TARGET_WORKAROUND + LM_UINT32 EnablePciXFix; +#endif + LM_UINT32 UndiFix; /* new, jimmy */ + LM_UINT32 PciCommandStatusWords; + LM_UINT32 ChipRevId; + LM_UINT16 SubsystemVendorId; + LM_UINT16 SubsystemId; +#if 0 /* Jimmy, deleted in new driver */ + LM_UINT32 MemBaseLow; + LM_UINT32 MemBaseHigh; + LM_UINT32 MemBaseSize; +#endif + PLM_UINT8 pMappedMemBase; + + /* Saved PCI configuration registers for restoring after a reset. */ + LM_UINT32 SavedCacheLineReg; + + /* Phy info. */ + LM_UINT32 PhyAddr; + LM_UINT32 PhyId; + + /* Requested phy settings. */ + LM_REQUESTED_MEDIA_TYPE RequestedMediaType; + + /* Disable auto-negotiation. */ + LM_UINT32 DisableAutoNeg; + + /* Ways for the MAC to get link change interrupt. */ + LM_UINT32 PhyIntMode; + #define T3_PHY_INT_MODE_AUTO 0 + #define T3_PHY_INT_MODE_MI_INTERRUPT 1 + #define T3_PHY_INT_MODE_LINK_READY 2 + #define T3_PHY_INT_MODE_AUTO_POLLING 3 + + /* Ways to determine link change status. */ + LM_UINT32 LinkChngMode; + #define T3_LINK_CHNG_MODE_AUTO 0 + #define T3_LINK_CHNG_MODE_USE_STATUS_REG 1 + #define T3_LINK_CHNG_MODE_USE_STATUS_BLOCK 2 + + + /* LED mode. */ + LM_UINT32 LedMode; + + #define LED_MODE_AUTO 0 + + /* 5700/01 LED mode. */ + #define LED_MODE_THREE_LINK 1 + #define LED_MODE_LINK10 2 + + /* 5703/02/04 LED mode. */ + #define LED_MODE_OPEN_DRAIN 1 + #define LED_MODE_OUTPUT 2 + + /* WOL Speed */ + LM_UINT32 WolSpeed; + #define WOL_SPEED_10MB 1 + #define WOL_SPEED_100MB 2 + + /* Reset the PHY on initialization. */ + LM_UINT32 ResetPhyOnInit; + + LM_UINT32 RestoreOnWakeUp; + LM_REQUESTED_MEDIA_TYPE WakeUpRequestedMediaType; + LM_UINT32 WakeUpDisableAutoNeg; + + /* Current phy settings. */ + LM_MEDIA_TYPE MediaType; + LM_LINE_SPEED LineSpeed; + LM_LINE_SPEED OldLineSpeed; + LM_DUPLEX_MODE DuplexMode; + LM_STATUS LinkStatus; + LM_UINT32 advertising; /* Jimmy, new! */ + LM_UINT32 advertising1000; /* Jimmy, new! */ + + /* Multicast address list. */ + LM_UINT32 McEntryCount; + LM_UINT8 McTable[LM_MAX_MC_TABLE_SIZE][LM_MC_ENTRY_SIZE]; + + /* Use NIC or Host based send BD. */ + LM_UINT32 NicSendBd; + + /* Athlon fix. */ + LM_UINT32 DelayPciGrant; + + /* Enable OneDmaAtOnce */ + LM_UINT32 OneDmaAtOnce; + + /* Split Mode flags, Jimmy new */ + LM_UINT32 SplitModeEnable; + LM_UINT32 SplitModeMaxReq; + + /* Init flag. */ + LM_BOOL InitDone; + + /* Shutdown flag. Set by the upper module. */ + LM_BOOL ShuttingDown; + + /* Flag to determine whether to call LM_QueueRxPackets or not in */ + /* LM_ResetAdapter routine. */ + LM_BOOL QueueRxPackets; + + LM_UINT32 MbufBase; + LM_UINT32 MbufSize; + + /* TRUE if we have a SERDES PHY. */ + LM_UINT32 EnableTbi; + + /* Ethernet@WireSpeed. */ + LM_UINT32 EnableWireSpeed; + + LM_UINT32 EepromWp; + +#if INCLUDE_TBI_SUPPORT + /* Autoneg state info. */ + AN_STATE_INFO AnInfo; + LM_UINT32 PollTbiLink; + LM_UINT32 IgnoreTbiLinkChange; +#endif + char PartNo[24]; + char BootCodeVer[16]; + char BusSpeedStr[24]; /* Jimmy, new! */ + LM_UINT32 PhyCrcCount; +} LM_DEVICE_BLOCK; + + +#define T3_REG_CPU_VIEW 0xc0000000 + +#define T3_BLOCK_DMA_RD (1 << 0) +#define T3_BLOCK_DMA_COMP (1 << 1) +#define T3_BLOCK_RX_BD_INITIATOR (1 << 2) +#define T3_BLOCK_RX_BD_COMP (1 << 3) +#define T3_BLOCK_DMA_WR (1 << 4) +#define T3_BLOCK_MSI_HANDLER (1 << 5) +#define T3_BLOCK_RX_LIST_PLMT (1 << 6) +#define T3_BLOCK_RX_LIST_SELECTOR (1 << 7) +#define T3_BLOCK_RX_DATA_INITIATOR (1 << 8) +#define T3_BLOCK_RX_DATA_COMP (1 << 9) +#define T3_BLOCK_HOST_COALESING (1 << 10) +#define T3_BLOCK_MAC_RX_ENGINE (1 << 11) +#define T3_BLOCK_MBUF_CLUSTER_FREE (1 << 12) +#define T3_BLOCK_SEND_BD_INITIATOR (1 << 13) +#define T3_BLOCK_SEND_BD_COMP (1 << 14) +#define T3_BLOCK_SEND_BD_SELECTOR (1 << 15) +#define T3_BLOCK_SEND_DATA_INITIATOR (1 << 16) +#define T3_BLOCK_SEND_DATA_COMP (1 << 17) +#define T3_BLOCK_MAC_TX_ENGINE (1 << 18) +#define T3_BLOCK_MEM_ARBITOR (1 << 19) +#define T3_BLOCK_MBUF_MANAGER (1 << 20) +#define T3_BLOCK_MAC_GLOBAL (1 << 21) + +#define LM_ENABLE 1 +#define LM_DISABLE 2 + +#define RX_CPU_EVT_SW0 0 +#define RX_CPU_EVT_SW1 1 +#define RX_CPU_EVT_RLP 2 +#define RX_CPU_EVT_SW3 3 +#define RX_CPU_EVT_RLS 4 +#define RX_CPU_EVT_SW4 5 +#define RX_CPU_EVT_RX_BD_COMP 6 +#define RX_CPU_EVT_SW5 7 +#define RX_CPU_EVT_RDI 8 +#define RX_CPU_EVT_DMA_WR 9 +#define RX_CPU_EVT_DMA_RD 10 +#define RX_CPU_EVT_SWQ 11 +#define RX_CPU_EVT_SW6 12 +#define RX_CPU_EVT_RDC 13 +#define RX_CPU_EVT_SW7 14 +#define RX_CPU_EVT_HOST_COALES 15 +#define RX_CPU_EVT_SW8 16 +#define RX_CPU_EVT_HIGH_DMA_WR 17 +#define RX_CPU_EVT_HIGH_DMA_RD 18 +#define RX_CPU_EVT_SW9 19 +#define RX_CPU_EVT_DMA_ATTN 20 +#define RX_CPU_EVT_LOW_P_MBOX 21 +#define RX_CPU_EVT_HIGH_P_MBOX 22 +#define RX_CPU_EVT_SW10 23 +#define RX_CPU_EVT_TX_CPU_ATTN 24 +#define RX_CPU_EVT_MAC_ATTN 25 +#define RX_CPU_EVT_RX_CPU_ATTN 26 +#define RX_CPU_EVT_FLOW_ATTN 27 +#define RX_CPU_EVT_SW11 28 +#define RX_CPU_EVT_TIMER 29 +#define RX_CPU_EVT_SW12 30 +#define RX_CPU_EVT_SW13 31 + +/* RX-CPU event */ +#define RX_CPU_EVENT_SW_EVENT0 (1 << RX_CPU_EVT_SW0) +#define RX_CPU_EVENT_SW_EVENT1 (1 << RX_CPU_EVT_SW1) +#define RX_CPU_EVENT_RLP (1 << RX_CPU_EVT_RLP) +#define RX_CPU_EVENT_SW_EVENT3 (1 << RX_CPU_EVT_SW3) +#define RX_CPU_EVENT_RLS (1 << RX_CPU_EVT_RLS) +#define RX_CPU_EVENT_SW_EVENT4 (1 << RX_CPU_EVT_SW4) +#define RX_CPU_EVENT_RX_BD_COMP (1 << RX_CPU_EVT_RX_BD_COMP) +#define RX_CPU_EVENT_SW_EVENT5 (1 << RX_CPU_EVT_SW5) +#define RX_CPU_EVENT_RDI (1 << RX_CPU_EVT_RDI) +#define RX_CPU_EVENT_DMA_WR (1 << RX_CPU_EVT_DMA_WR) +#define RX_CPU_EVENT_DMA_RD (1 << RX_CPU_EVT_DMA_RD) +#define RX_CPU_EVENT_SWQ (1 << RX_CPU_EVT_SWQ) +#define RX_CPU_EVENT_SW_EVENT6 (1 << RX_CPU_EVT_SW6) +#define RX_CPU_EVENT_RDC (1 << RX_CPU_EVT_RDC) +#define RX_CPU_EVENT_SW_EVENT7 (1 << RX_CPU_EVT_SW7) +#define RX_CPU_EVENT_HOST_COALES (1 << RX_CPU_EVT_HOST_COALES) +#define RX_CPU_EVENT_SW_EVENT8 (1 << RX_CPU_EVT_SW8) +#define RX_CPU_EVENT_HIGH_DMA_WR (1 << RX_CPU_EVT_HIGH_DMA_WR) +#define RX_CPU_EVENT_HIGH_DMA_RD (1 << RX_CPU_EVT_HIGH_DMA_RD) +#define RX_CPU_EVENT_SW_EVENT9 (1 << RX_CPU_EVT_SW9) +#define RX_CPU_EVENT_DMA_ATTN (1 << RX_CPU_EVT_DMA_ATTN) +#define RX_CPU_EVENT_LOW_P_MBOX (1 << RX_CPU_EVT_LOW_P_MBOX) +#define RX_CPU_EVENT_HIGH_P_MBOX (1 << RX_CPU_EVT_HIGH_P_MBOX) +#define RX_CPU_EVENT_SW_EVENT10 (1 << RX_CPU_EVT_SW10) +#define RX_CPU_EVENT_TX_CPU_ATTN (1 << RX_CPU_EVT_TX_CPU_ATTN) +#define RX_CPU_EVENT_MAC_ATTN (1 << RX_CPU_EVT_MAC_ATTN) +#define RX_CPU_EVENT_RX_CPU_ATTN (1 << RX_CPU_EVT_RX_CPU_ATTN) +#define RX_CPU_EVENT_FLOW_ATTN (1 << RX_CPU_EVT_FLOW_ATTN) +#define RX_CPU_EVENT_SW_EVENT11 (1 << RX_CPU_EVT_SW11) +#define RX_CPU_EVENT_TIMER (1 << RX_CPU_EVT_TIMER) +#define RX_CPU_EVENT_SW_EVENT12 (1 << RX_CPU_EVT_SW12) +#define RX_CPU_EVENT_SW_EVENT13 (1 << RX_CPU_EVT_SW13) + +#define RX_CPU_MASK (RX_CPU_EVENT_SW_EVENT0 | \ + RX_CPU_EVENT_RLP | \ + RX_CPU_EVENT_RDI | \ + RX_CPU_EVENT_RDC) + +#define TX_CPU_EVT_SW0 0 +#define TX_CPU_EVT_SW1 1 +#define TX_CPU_EVT_SW2 2 +#define TX_CPU_EVT_SW3 3 +#define TX_CPU_EVT_TX_MAC 4 +#define TX_CPU_EVT_SW4 5 +#define TX_CPU_EVT_SBDC 6 +#define TX_CPU_EVT_SW5 7 +#define TX_CPU_EVT_SDI 8 +#define TX_CPU_EVT_DMA_WR 9 +#define TX_CPU_EVT_DMA_RD 10 +#define TX_CPU_EVT_SWQ 11 +#define TX_CPU_EVT_SW6 12 +#define TX_CPU_EVT_SDC 13 +#define TX_CPU_EVT_SW7 14 +#define TX_CPU_EVT_HOST_COALES 15 +#define TX_CPU_EVT_SW8 16 +#define TX_CPU_EVT_HIGH_DMA_WR 17 +#define TX_CPU_EVT_HIGH_DMA_RD 18 +#define TX_CPU_EVT_SW9 19 +#define TX_CPU_EVT_DMA_ATTN 20 +#define TX_CPU_EVT_LOW_P_MBOX 21 +#define TX_CPU_EVT_HIGH_P_MBOX 22 +#define TX_CPU_EVT_SW10 23 +#define TX_CPU_EVT_RX_CPU_ATTN 24 +#define TX_CPU_EVT_MAC_ATTN 25 +#define TX_CPU_EVT_TX_CPU_ATTN 26 +#define TX_CPU_EVT_FLOW_ATTN 27 +#define TX_CPU_EVT_SW11 28 +#define TX_CPU_EVT_TIMER 29 +#define TX_CPU_EVT_SW12 30 +#define TX_CPU_EVT_SW13 31 + + +/* TX-CPU event */ +#define TX_CPU_EVENT_SW_EVENT0 (1 << TX_CPU_EVT_SW0) +#define TX_CPU_EVENT_SW_EVENT1 (1 << TX_CPU_EVT_SW1) +#define TX_CPU_EVENT_SW_EVENT2 (1 << TX_CPU_EVT_SW2) +#define TX_CPU_EVENT_SW_EVENT3 (1 << TX_CPU_EVT_SW3) +#define TX_CPU_EVENT_TX_MAC (1 << TX_CPU_EVT_TX_MAC) +#define TX_CPU_EVENT_SW_EVENT4 (1 << TX_CPU_EVT_SW4) +#define TX_CPU_EVENT_SBDC (1 << TX_CPU_EVT_SBDC) +#define TX_CPU_EVENT_SW_EVENT5 (1 << TX_CPU_EVT_SW5) +#define TX_CPU_EVENT_SDI (1 << TX_CPU_EVT_SDI) +#define TX_CPU_EVENT_DMA_WR (1 << TX_CPU_EVT_DMA_WR) +#define TX_CPU_EVENT_DMA_RD (1 << TX_CPU_EVT_DMA_RD) +#define TX_CPU_EVENT_SWQ (1 << TX_CPU_EVT_SWQ) +#define TX_CPU_EVENT_SW_EVENT6 (1 << TX_CPU_EVT_SW6) +#define TX_CPU_EVENT_SDC (1 << TX_CPU_EVT_SDC) +#define TX_CPU_EVENT_SW_EVENT7 (1 << TX_CPU_EVT_SW7) +#define TX_CPU_EVENT_HOST_COALES (1 << TX_CPU_EVT_HOST_COALES) +#define TX_CPU_EVENT_SW_EVENT8 (1 << TX_CPU_EVT_SW8) +#define TX_CPU_EVENT_HIGH_DMA_WR (1 << TX_CPU_EVT_HIGH_DMA_WR) +#define TX_CPU_EVENT_HIGH_DMA_RD (1 << TX_CPU_EVT_HIGH_DMA_RD) +#define TX_CPU_EVENT_SW_EVENT9 (1 << TX_CPU_EVT_SW9) +#define TX_CPU_EVENT_DMA_ATTN (1 << TX_CPU_EVT_DMA_ATTN) +#define TX_CPU_EVENT_LOW_P_MBOX (1 << TX_CPU_EVT_LOW_P_MBOX) +#define TX_CPU_EVENT_HIGH_P_MBOX (1 << TX_CPU_EVT_HIGH_P_MBOX) +#define TX_CPU_EVENT_SW_EVENT10 (1 << TX_CPU_EVT_SW10) +#define TX_CPU_EVENT_RX_CPU_ATTN (1 << TX_CPU_EVT_RX_CPU_ATTN) +#define TX_CPU_EVENT_MAC_ATTN (1 << TX_CPU_EVT_MAC_ATTN) +#define TX_CPU_EVENT_TX_CPU_ATTN (1 << TX_CPU_EVT_TX_CPU_ATTN) +#define TX_CPU_EVENT_FLOW_ATTN (1 << TX_CPU_EVT_FLOW_ATTN) +#define TX_CPU_EVENT_SW_EVENT11 (1 << TX_CPU_EVT_SW11) +#define TX_CPU_EVENT_TIMER (1 << TX_CPU_EVT_TIMER) +#define TX_CPU_EVENT_SW_EVENT12 (1 << TX_CPU_EVT_SW12) +#define TX_CPU_EVENT_SW_EVENT13 (1 << TX_CPU_EVT_SW13) + + +#define TX_CPU_MASK (TX_CPU_EVENT_SW_EVENT0 | \ + TX_CPU_EVENT_SDI | \ + TX_CPU_EVENT_SDC) + + +#define T3_FTQ_TYPE1_UNDERFLOW_BIT (1 << 29) +#define T3_FTQ_TYPE1_PASS_BIT (1 << 30) +#define T3_FTQ_TYPE1_SKIP_BIT (1 << 31) + +#define T3_FTQ_TYPE2_UNDERFLOW_BIT (1 << 13) +#define T3_FTQ_TYPE2_PASS_BIT (1 << 14) +#define T3_FTQ_TYPE2_SKIP_BIT (1 << 15) + +#define T3_QID_DMA_READ 1 +#define T3_QID_DMA_HIGH_PRI_READ 2 +#define T3_QID_DMA_COMP_DX 3 +#define T3_QID_SEND_BD_COMP 4 +#define T3_QID_SEND_DATA_INITIATOR 5 +#define T3_QID_DMA_WRITE 6 +#define T3_QID_DMA_HIGH_PRI_WRITE 7 +#define T3_QID_SW_TYPE_1 8 +#define T3_QID_SEND_DATA_COMP 9 +#define T3_QID_HOST_COALESCING 10 +#define T3_QID_MAC_TX 11 +#define T3_QID_MBUF_CLUSTER_FREE 12 +#define T3_QID_RX_BD_COMP 13 +#define T3_QID_RX_LIST_PLM 14 +#define T3_QID_RX_DATA_BD_INITIATOR 15 +#define T3_QID_RX_DATA_COMP 16 +#define T3_QID_SW_TYPE2 17 + +LM_STATUS LM_LoadFirmware(PLM_DEVICE_BLOCK pDevice, + PT3_FWIMG_INFO pFwImg, + LM_UINT32 LoadCpu, + LM_UINT32 StartCpu); + +/******************************************************************************/ +/* NIC register read/write macros. */ +/******************************************************************************/ + +#if 0 /* Jimmy */ +/* MAC register access. */ +LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register); +LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, + LM_UINT32 Value32); + +/* MAC memory access. */ +LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr); +LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, + LM_UINT32 Value32); + +#if PCIX_TARGET_WORKAROUND + +/* use memory-mapped accesses for mailboxes and reads, UNDI accesses + for writes to all other registers */ +#define REG_RD(pDevice, OffsetName) \ + readl(&((pDevice)->pMemView->OffsetName)) + +#define REG_WR(pDevice, OffsetName, Value32) \ + (((OFFSETOF(T3_STD_MEM_MAP, OffsetName) >=0x200 ) && \ + (OFFSETOF(T3_STD_MEM_MAP, OffsetName) <0x400)) || \ + ((pDevice)->EnablePciXFix == FALSE)) ? \ + (void) writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) + +#define MB_REG_RD(pDevice, OffsetName) \ + readl(&((pDevice)->pMemView->OffsetName)) + +#define MB_REG_WR(pDevice, OffsetName, Value32) \ + writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define REG_RD_OFFSET(pDevice, Offset) \ + readl(&((LM_UINT8 *) (pDevice)->pMemView + Offset)) + +#define REG_WR_OFFSET(pDevice, Offset, Value32) \ + (((Offset >=0x200 ) && (Offset < 0x400)) || \ + ((pDevice)->EnablePciXFix == FALSE)) ? \ + (void) writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) : \ + LM_RegWrInd(pDevice, Offset, Value32) + +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#else /* normal target access path below */ + +/* Register access. */ +#define REG_RD(pDevice, OffsetName) \ + readl(&((pDevice)->pMemView->OffsetName)) +#define REG_WR(pDevice, OffsetName, Value32) \ + writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define REG_RD_OFFSET(pDevice, Offset) \ + readl(((LM_UINT8 *) (pDevice)->pMemView + Offset)) +#define REG_WR_OFFSET(pDevice, Offset, Value32) \ + writel(Value32, ((LM_UINT8 *) (pDevice)->pMemView + Offset)) + + +/* There could be problem access the memory window directly. For now, */ +/* we have to go through the PCI configuration register. */ +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#endif /* PCIX_TARGET_WORKAROUND */ + +#endif /* Jimmy, merging */ + + /* Jimmy...rest of file is new stuff! */ +/******************************************************************************/ +/* NIC register read/write macros. */ +/******************************************************************************/ + +/* MAC register access. */ +LM_UINT32 LM_RegRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register); +LM_VOID LM_RegWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 Register, + LM_UINT32 Value32); + +/* MAC memory access. */ +LM_UINT32 LM_MemRdInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr); +LM_VOID LM_MemWrInd(PLM_DEVICE_BLOCK pDevice, LM_UINT32 MemAddr, + LM_UINT32 Value32); + +#define MB_REG_WR(pDevice, OffsetName, Value32) \ + ((pDevice)->UndiFix) ? \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600, \ + Value32) : \ + (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#define MB_REG_RD(pDevice, OffsetName) \ + (((pDevice)->UndiFix) ? \ + LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)+0x5600) : \ + __raw_readl(&((pDevice)->pMemView->OffsetName))) + +#define REG_RD(pDevice, OffsetName) \ + (((pDevice)->UndiFix) ? \ + LM_RegRdInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName)) : \ + __raw_readl(&((pDevice)->pMemView->OffsetName))) + +#if PCIX_TARGET_WORKAROUND + +#define REG_WR(pDevice, OffsetName, Value32) \ + ((pDevice)->EnablePciXFix == FALSE) ? \ + (void) __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) : \ + LM_RegWrInd(pDevice, OFFSETOF(T3_STD_MEM_MAP, OffsetName), Value32) + +#else + +#define REG_WR(pDevice, OffsetName, Value32) \ + __raw_writel(Value32, &((pDevice)->pMemView->OffsetName)) + +#endif + +#define MEM_RD(pDevice, AddrName) \ + LM_MemRdInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName)) +#define MEM_WR(pDevice, AddrName, Value32) \ + LM_MemWrInd(pDevice, OFFSETOF(T3_FIRST_32K_SRAM, AddrName), Value32) + +#define MEM_RD_OFFSET(pDevice, Offset) \ + LM_MemRdInd(pDevice, Offset) +#define MEM_WR_OFFSET(pDevice, Offset, Value32) \ + LM_MemWrInd(pDevice, Offset, Value32) + +#endif /* TIGON3_H */ + diff --git a/dtt/ds1621.c b/dtt/ds1621.c new file mode 100644 index 0000000..5c25f64 --- /dev/null +++ b/dtt/ds1621.c @@ -0,0 +1,191 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 + */ + +/* + * Dallas Semiconductor's DS1621 Digital Thermometer and Thermostat. + */ + +#include <common.h> + +#ifdef CONFIG_DTT_DS1621 +#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \ + (CFG_EEPROM_PAGE_WRITE_BITS < 1) +# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_DS1621" +#endif +#include <i2c.h> +#include <dtt.h> + +/* + * Device code + */ +#define DTT_I2C_DEV_CODE 0x48 /* Dallas Semi's DS1621 */ + +int dtt_read(int sensor, int reg) +{ + int dlen; + uchar data[2]; + + /* + * Calculate sensor address and command. + * + */ + sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* Calculate addr of ds1621*/ + + /* + * Prepare to handle 2 byte result. + */ + if ((reg == DTT_READ_TEMP) || + (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) + dlen = 2; + else + dlen = 1; + + /* + * Now try to read the register. + */ + if (i2c_read(sensor, reg, 1, data, dlen) != 0) + return 1; + + /* + * Handle 2 byte result. + */ + if (dlen == 2) + return ((int)((short)data[1] + (((short)data[0]) << 8))); + + return (int)data[0]; +} /* dtt_read() */ + + +int dtt_write(int sensor, int reg, int val) +{ + int dlen; + uchar data[2]; + + /* + * Calculate sensor address and register. + * + */ + sensor = DTT_I2C_DEV_CODE + (sensor & sensor); + + /* + * Handle various data sizes. + */ + if ((reg == DTT_READ_TEMP) || + (reg == DTT_TEMP_HIGH) || (reg == DTT_TEMP_LOW)) { + dlen = 2; + data[0] = (char)((val >> 8) & 0xff); /* MSB first */ + data[1] = (char)(val & 0xff); + } + else if ((reg == DTT_WRITE_START_CONV) || (reg == DTT_WRITE_STOP_CONV)) { + dlen = 0; + data[0] = (char)0; + data[1] = (char)0; + } + else { + dlen = 1; + data[0] = (char)(val & 0xff); + } + + /* + * Write value to device. + */ + if (i2c_write(sensor, reg, 1, data, dlen) != 0) + return 1; + + return 0; +} /* dtt_write() */ + + +static int _dtt_init(int sensor) +{ + int val; + + /* + * Setup High Temp. + */ + val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; + if (dtt_write(sensor, DTT_TEMP_HIGH, val) != 0) + return 1; + udelay(50000); /* Max 50ms */ + + /* + * Setup Low Temp - hysteresis. + */ + val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80; + if (dtt_write(sensor, DTT_TEMP_LOW, val) != 0) + return 1; + udelay(50000); /* Max 50ms */ + + /* + * Setup configuraton register + * + * Clear THF & TLF, Reserved = 1, Polarity = Active Low, One Shot = YES + * + * We run in polled mode, since there isn't any way to know if this + * lousy device is ready to provide temperature readings on power up. + */ + val = 0x9; + if (dtt_write(sensor, DTT_CONFIG, val) != 0) + return 1; + udelay(50000); /* Max 50ms */ + + return 0; +} /* _dtt_init() */ + + +int dtt_init (void) +{ + int i; + unsigned char sensors[] = CONFIG_DTT_SENSORS; + + for (i = 0; i < sizeof(sensors); i++) { + if (_dtt_init(sensors[i]) != 0) + printf("DTT%d: FAILED\n", i+1); + else + printf("DTT%d: %i C\n", i+1, dtt_get_temp(sensors[i])); + } + + return (0); +} /* dtt_init() */ + + +int dtt_get_temp(int sensor) +{ + int i; + + /* + * Start a conversion, may take up to 1 second. + */ + dtt_write(sensor, DTT_WRITE_START_CONV, 0); + for (i = 0; i <= 10; i++) { + udelay(100000); + if (dtt_read(sensor, DTT_CONFIG) & 0x80) + break; + } + + return (dtt_read(sensor, DTT_READ_TEMP) / 256); +} /* dtt_get_temp() */ + + +#endif /* CONFIG_DTT_DS1621 */ + diff --git a/dtt/lm75.c b/dtt/lm75.c new file mode 100644 index 0000000..9930a8b --- /dev/null +++ b/dtt/lm75.c @@ -0,0 +1,181 @@ +/* + * (C) Copyright 2001 + * Bill Hunter, Wave 7 Optics, williamhunter@mediaone.net + * + * 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 + */ + +/* + * On Semiconductor's LM75 Temperature Sensor + */ + +#include <common.h> + +#ifdef CONFIG_DTT_LM75 +#if !defined(CFG_EEPROM_PAGE_WRITE_ENABLE) || \ + (CFG_EEPROM_PAGE_WRITE_BITS < 1) +# error "CFG_EEPROM_PAGE_WRITE_ENABLE must be defined and CFG_EEPROM_PAGE_WRITE_BITS must be greater than 1 to use CONFIG_DTT_LM75" +#endif + +#include <i2c.h> +#include <dtt.h> + + +/* + * Device code + */ +#define DTT_I2C_DEV_CODE 0x48 /* ON Semi's LM75 device */ + +int dtt_read(int sensor, int reg) +{ + int dlen; + uchar data[2]; + + /* + * Validate 'reg' param + */ + if((reg < 0) || (reg > 3)) + return -1; + + /* + * Calculate sensor address and register. + */ + sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ + + /* + * Prepare to handle 2 byte result. + */ + if ((reg == DTT_READ_TEMP) || + (reg == DTT_TEMP_HYST) || + (reg == DTT_TEMP_SET)) + dlen = 2; + else + dlen = 1; + + /* + * Now try to read the register. + */ + if (i2c_read(sensor, reg, 1, data, dlen) != 0) + return -1; + + /* + * Handle 2 byte result. + */ + if (dlen == 2) + return ((int)((short)data[1] + (((short)data[0]) << 8))); + + + return (int)data[0]; +} /* dtt_read() */ + + +int dtt_write(int sensor, int reg, int val) +{ + int dlen; + uchar data[2]; + + /* + * Validate 'reg' param + */ + if ((reg < 0) || (reg > 3)) + return 1; + + /* + * Calculate sensor address and register. + */ + sensor = DTT_I2C_DEV_CODE + (sensor & 0x07); /* calculate address of lm75 */ + + /* + * Handle 2 byte values. + */ + if ((reg == DTT_READ_TEMP) || + (reg == DTT_TEMP_HYST) || + (reg == DTT_TEMP_SET)) { + dlen = 2; + data[0] = (char)((val >> 8) & 0xff); /* MSB first */ + data[1] = (char)(val & 0xff); + } else { + dlen = 1; + data[0] = (char)(val & 0xff); + } + + /* + * Write value to register. + */ + if (i2c_write(sensor, reg, 1, data, dlen) != 0) + return 1; + + return 0; +} /* dtt_write() */ + + +static int _dtt_init(int sensor) +{ + int val; + + /* + * Setup TSET ( trip point ) register + */ + val = ((CFG_DTT_MAX_TEMP * 2) << 7) & 0xff80; /* trip */ + if (dtt_write(sensor, DTT_TEMP_SET, val) != 0) + return 1; + + /* + * Setup THYST ( untrip point ) register - Hysteresis + */ + val = (((CFG_DTT_MAX_TEMP - CFG_DTT_HYSTERESIS) * 2) << 7) & 0xff80; + if (dtt_write(sensor, DTT_TEMP_HYST, val) != 0) + return 1; + + /* + * Setup configuraton register + */ + /* config = 6 sample integration, int mode, active low, and enable */ + val = 0x18; + if (dtt_write(sensor, DTT_CONFIG, val) != 0) + return 1; + + return 0; +} /* _dtt_init() */ + + +int dtt_init (void) +{ + int i; + unsigned char sensors[] = CONFIG_DTT_SENSORS; + const char *const header = "DTT: "; + + for (i = 0; i < sizeof(sensors); i++) { + if (_dtt_init(sensors[i]) != 0) + printf("%s%d FAILED INIT\n", header, i+1); + else + printf("%s%d is %i C\n", header, i+1, + dtt_get_temp(sensors[i])); + } + + return (0); +} /* dtt_init() */ + +int dtt_get_temp(int sensor) +{ + return (dtt_read(sensor, DTT_READ_TEMP) / 256); +} /* dtt_get_temp() */ + +#endif /* CONFIG_DTT_LM75 */ + diff --git a/include/altera.h b/include/altera.h new file mode 100644 index 0000000..88f72db --- /dev/null +++ b/include/altera.h @@ -0,0 +1,73 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.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 <fpga.h> + +#ifndef _ALTERA_H_ +#define _ALTERA_H_ + +/* + * Note that this is just Altera FPGA interface boilerplate. + * There is no support for Altera devices yet. + * + * See include/xilinx.h for a working example. + */ + +/* In your board's config.h file you should define CONFIG_FPGA as such: + * #define CONFIG_FPGA (CFG_ALTERA_xxx | CFG_ALTERA_IF_xxx ) + */ + +/* Altera Model definitions */ +#define CFG_ALTERA_xxxx ( CFG_FPGA_ALTERA | CFG_FPGA_DEV( 0x1 )) +/* Add new models here */ + +/* Altera Interface definitions */ +#define CFG_ALTERA_IF_xxx CFG_FPGA_IF( 0x1 ) +/* Add new interfaces here */ + +typedef enum { /* typedef Altera_iface */ + min_altera_iface_type, /* insert all new types after this */ +/* Add new interfaces here */ + max_altera_iface_type /* insert all new types before this */ +} Altera_iface; /* end, typedef Altera_iface */ + +typedef enum { /* typedef Altera_Family */ + min_altera_type, /* insert all new types after this */ +/* Add new models here */ + max_altera_type /* insert all new types before this */ +} Altera_Family; /* end, typedef Altera_Family */ + +typedef struct { /* typedef Altera_desc */ + Altera_Family family; /* part type */ + Altera_iface iface; /* interface type */ + size_t size; /* bytes of data part can accept */ + void * base; /* base interface address */ +} Altera_desc; /* end, typedef Altera_desc */ + +extern int altera_load( Altera_desc *desc, void *image, size_t size ); +extern int altera_dump( Altera_desc *desc, void *buf, size_t bsize ); +extern int altera_info( Altera_desc *desc ); +extern int altera_reloc( Altera_desc *desc, ulong reloc_off ); + +#endif /* _ALTERA_H_ */ diff --git a/include/asm-arm/bitops.h b/include/asm-arm/bitops.h new file mode 100644 index 0000000..4733858 --- /dev/null +++ b/include/asm-arm/bitops.h @@ -0,0 +1,144 @@ +/* + * Copyright 1995, Russell King. + * Various bits and pieces copyrights include: + * Linus Torvalds (test_bit). + * + * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1). + * + * Please note that the code in this file should never be included + * from user space. Many of these are not implemented in assembler + * since they would be too costly. Also, they require priviledged + * instructions (which are not available from user mode) to ensure + * that they are atomic. + */ + +#ifndef __ASM_ARM_BITOPS_H +#define __ASM_ARM_BITOPS_H + +#ifdef __KERNEL__ + +#define smp_mb__before_clear_bit() do { } while (0) +#define smp_mb__after_clear_bit() do { } while (0) + +/* + * Function prototypes to keep gcc -Wall happy. + */ +extern void set_bit(int nr, volatile void * addr); + +static inline void __set_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] |= (1U << (nr & 7)); +} + +extern void clear_bit(int nr, volatile void * addr); + +static inline void __clear_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] &= ~(1U << (nr & 7)); +} + +extern void change_bit(int nr, volatile void * addr); + +static inline void __change_bit(int nr, volatile void *addr) +{ + ((unsigned char *) addr)[nr >> 3] ^= (1U << (nr & 7)); +} + +extern int test_and_set_bit(int nr, volatile void * addr); + +static inline int __test_and_set_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval | mask; + return oldval & mask; +} + +extern int test_and_clear_bit(int nr, volatile void * addr); + +static inline int __test_and_clear_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval & ~mask; + return oldval & mask; +} + +extern int test_and_change_bit(int nr, volatile void * addr); + +static inline int __test_and_change_bit(int nr, volatile void *addr) +{ + unsigned int mask = 1 << (nr & 7); + unsigned int oldval; + + oldval = ((unsigned char *) addr)[nr >> 3]; + ((unsigned char *) addr)[nr >> 3] = oldval ^ mask; + return oldval & mask; +} + +extern int find_first_zero_bit(void * addr, unsigned size); +extern int find_next_zero_bit(void * addr, int size, int offset); + +/* + * This routine doesn't need to be atomic. + */ +static inline int test_bit(int nr, const void * addr) +{ + return ((unsigned char *) addr)[nr >> 3] & (1U << (nr & 7)); +} + +/* + * ffz = Find First Zero in word. Undefined if no zero exists, + * so code should check against ~0UL first.. + */ +static inline unsigned long ffz(unsigned long word) +{ + int k; + + word = ~word; + k = 31; + if (word & 0x0000ffff) { k -= 16; word <<= 16; } + if (word & 0x00ff0000) { k -= 8; word <<= 8; } + if (word & 0x0f000000) { k -= 4; word <<= 4; } + if (word & 0x30000000) { k -= 2; word <<= 2; } + if (word & 0x40000000) { k -= 1; } + return k; +} + +/* + * ffs: find first bit set. This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ + +#define ffs(x) generic_ffs(x) + +/* + * hweightN: returns the hamming weight (i.e. the number + * of bits set) of a N-bit word + */ + +#define hweight32(x) generic_hweight32(x) +#define hweight16(x) generic_hweight16(x) +#define hweight8(x) generic_hweight8(x) + +#define ext2_set_bit test_and_set_bit +#define ext2_clear_bit test_and_clear_bit +#define ext2_test_bit test_bit +#define ext2_find_first_zero_bit find_first_zero_bit +#define ext2_find_next_zero_bit find_next_zero_bit + +/* Bitmap functions for the minix filesystem. */ +#define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr) +#define minix_set_bit(nr,addr) set_bit(nr,addr) +#define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr) +#define minix_test_bit(nr,addr) test_bit(nr,addr) +#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size) + +#endif /* __KERNEL__ */ + +#endif /* _ARM_BITOPS_H */ diff --git a/include/asm-arm/proc-armv/ptrace.h b/include/asm-arm/proc-armv/ptrace.h new file mode 100644 index 0000000..51708b9 --- /dev/null +++ b/include/asm-arm/proc-armv/ptrace.h @@ -0,0 +1,110 @@ +/* + * linux/include/asm-arm/proc-armv/ptrace.h + * + * Copyright (C) 1996-1999 Russell King + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ASM_PROC_PTRACE_H +#define __ASM_PROC_PTRACE_H + +#include <linux/config.h> + +#define USR26_MODE 0x00 +#define FIQ26_MODE 0x01 +#define IRQ26_MODE 0x02 +#define SVC26_MODE 0x03 +#define USR_MODE 0x10 +#define FIQ_MODE 0x11 +#define IRQ_MODE 0x12 +#define SVC_MODE 0x13 +#define ABT_MODE 0x17 +#define UND_MODE 0x1b +#define SYSTEM_MODE 0x1f +#define MODE_MASK 0x1f +#define T_BIT 0x20 +#define F_BIT 0x40 +#define I_BIT 0x80 +#define CC_V_BIT (1 << 28) +#define CC_C_BIT (1 << 29) +#define CC_Z_BIT (1 << 30) +#define CC_N_BIT (1 << 31) +#define PCMASK 0 + +#ifndef __ASSEMBLY__ + +/* this struct defines the way the registers are stored on the + stack during a system call. */ + +struct pt_regs { + long uregs[18]; +}; + +#define ARM_cpsr uregs[16] +#define ARM_pc uregs[15] +#define ARM_lr uregs[14] +#define ARM_sp uregs[13] +#define ARM_ip uregs[12] +#define ARM_fp uregs[11] +#define ARM_r10 uregs[10] +#define ARM_r9 uregs[9] +#define ARM_r8 uregs[8] +#define ARM_r7 uregs[7] +#define ARM_r6 uregs[6] +#define ARM_r5 uregs[5] +#define ARM_r4 uregs[4] +#define ARM_r3 uregs[3] +#define ARM_r2 uregs[2] +#define ARM_r1 uregs[1] +#define ARM_r0 uregs[0] +#define ARM_ORIG_r0 uregs[17] + +#ifdef __KERNEL__ + +#define user_mode(regs) \ + (((regs)->ARM_cpsr & 0xf) == 0) + +#ifdef CONFIG_ARM_THUMB +#define thumb_mode(regs) \ + (((regs)->ARM_cpsr & T_BIT)) +#else +#define thumb_mode(regs) (0) +#endif + +#define processor_mode(regs) \ + ((regs)->ARM_cpsr & MODE_MASK) + +#define interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & I_BIT)) + +#define fast_interrupts_enabled(regs) \ + (!((regs)->ARM_cpsr & F_BIT)) + +#define condition_codes(regs) \ + ((regs)->ARM_cpsr & (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT)) + +/* Are the current registers suitable for user mode? + * (used to maintain security in signal handlers) + */ +static inline int valid_user_regs(struct pt_regs *regs) +{ + if ((regs->ARM_cpsr & 0xf) == 0 && + (regs->ARM_cpsr & (F_BIT|I_BIT)) == 0) + return 1; + + /* + * Force CPSR to something logical... + */ + regs->ARM_cpsr &= (CC_V_BIT|CC_C_BIT|CC_Z_BIT|CC_N_BIT|0x10); + + return 0; +} + +#endif /* __KERNEL__ */ + +#endif /* __ASSEMBLY__ */ + +#endif + diff --git a/include/asm-arm/u-boot-arm.h b/include/asm-arm/u-boot-arm.h new file mode 100644 index 0000000..355b1e4 --- /dev/null +++ b/include/asm-arm/u-boot-arm.h @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _U_BOOT_ARM_H_ +#define _U_BOOT_ARM_H_ 1 + +/* for the following variables, see start.S */ +extern ulong _armboot_start; /* code start */ +extern ulong _armboot_end_data; /* code + data end */ +extern ulong _armboot_end; /* BSS end */ +extern ulong IRQ_STACK_START; /* top of IRQ stack */ +extern ulong FIQ_STACK_START; /* top of FIQ stack */ +extern ulong _armboot_real_end; /* first usable RAM address */ + +/* cpu/.../cpu.c */ +int cpu_init(void); +int cleanup_before_linux(void); + +/* board/.../... */ +int board_init(void); +int dram_init (void); + +/* ------------------------------------------------------------ */ +/* Here is a list of some prototypes which are incompatible to */ +/* the U-Boot implementation */ +/* To be fixed! */ +/* ------------------------------------------------------------ */ +/* common/cmd_nvedit.c */ +void setenv (char *, char *); + +/* cpu/.../interrupt.c */ +void reset_timer_masked (void); +ulong get_timer_masked (void); +void udelay_masked (unsigned long usec); + +#endif /* _U_BOOT_ARM_H_ */ diff --git a/include/asm-arm/u-boot.h b/include/asm-arm/u-boot.h new file mode 100644 index 0000000..c3b0e4a --- /dev/null +++ b/include/asm-arm/u-boot.h @@ -0,0 +1,49 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _U_BOOT_H_ +#define _U_BOOT_H_ 1 + +typedef struct bd_info { + int bi_baudrate; /* serial console baudrate */ + unsigned long bi_ip_addr; /* IP Address */ + unsigned char bi_enetaddr[6]; /* Ethernet adress */ + struct environment_s *bi_env; + ulong bi_arch_number; /* unique id for this board */ + ulong bi_boot_params; /* where this board expects params */ + struct /* RAM configuration */ + { + ulong start; + ulong size; + } bi_dram[CONFIG_NR_DRAM_BANKS]; +} bd_t; + +#define bi_env_data bi_env->data +#define bi_env_crc bi_env->crc + +#endif /* _U_BOOT_H_ */ diff --git a/include/cmd_bsp.h b/include/cmd_bsp.h new file mode 100644 index 0000000..b39d50b --- /dev/null +++ b/include/cmd_bsp.h @@ -0,0 +1,313 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _CMD_BSP_H_ +#define _CMD_BSP_H_ + +#include <common.h> +#include <command.h> + +#if (CONFIG_COMMANDS & CFG_CMD_BSP) + +/* ----- LWMON ----------------------------------------------------------------- + */ +#if defined(CONFIG_LWMON) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "pic", 3, 4, 1, do_pic, \ + "pic - read and write PIC registers\n", \ + "read reg - read PIC register `reg'\n" \ + "pic write reg val - write value `val' to PIC register `reg'\n" \ +), MK_CMD_TBL_ENTRY( \ + "kbd", 3, 1, 1, do_kbd, \ + "kbd - read keyboard status\n", \ + NULL \ +), MK_CMD_TBL_ENTRY( \ + "lsb", 3, 2, 1, do_lsb, \ + "lsb - check and set LSB switch\n", \ + "on - switch LSB on\n" \ + "lsb off - switch LSB off\n" \ + "lsb - print current setting\n" \ +), +int do_pic (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_lsb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_LWMON */ +/* ----------------------------------------------------------------------------*/ + +/* ----- PCU E ----------------------------------------------------------------- + */ +#if defined(CONFIG_PCU_E) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "puma", 4, 4, 1, do_puma, \ + "puma - access PUMA FPGA\n", \ + "status - print PUMA status\n" \ + "puma load addr len - load PUMA configuration data\n" \ +), +int do_puma (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_PCU_E */ +/* ----------------------------------------------------------------------------*/ + +/* ----- CCM/SCM --------------------------------------------------------------- + */ +#if defined(CONFIG_CCM) || defined(CONFIG_SCM) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "fpga", 4, 4, 1, do_fpga, \ + "fpga - access FPGA(s)\n", \ + "fpga status [name] - print FPGA status\n" \ + "fpga reset [name] - reset FPGA\n" \ + "fpga load [name] addr - load FPGA configuration data\n" \ +), +int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_CCM, CONFIG_SCM */ +/* ----------------------------------------------------------------------------*/ + +/* ----- PIP405 ----------------------------------------------------------------- + */ +#if defined(CONFIG_PIP405) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "pip405", 4, 6, 1, do_pip405, \ + "pip405 - PIP405 specific Cmds\n", \ + "flash mem [SrcAddr] - updates U-Boot with image in memory\n" \ + "pip405 flash floppy [SrcAddr] - updates U-Boot with image from floppy\n" \ + "pip405 flash mps - updates U-Boot with image from MPS\n" \ +), +int do_pip405 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_PIP405 */ +/* ----------------------------------------------------------------------------*/ +/* ----- MIP405 ----------------------------------------------------------------- + */ +#if defined(CONFIG_MIP405) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "mip405", 4, 6, 1, do_mip405, \ + "mip405 - MIP405 specific Cmds\n", \ + "flash mem [SrcAddr] - updates U-Boot with image in memory\n" \ + "mip405 flash mps - updates U-Boot with image from MPS\n" \ +), +int do_mip405 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_MIP405 */ +/* ----------------------------------------------------------------------------*/ + +/* ----- DASA_SIM --------------------------------------------------------------- + */ +#if defined(CONFIG_DASA_SIM) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "pci9054", 7, 3, 1, do_pci9054, \ + "pci9054 - PLX PCI9054 EEPROM access\n", \ + "pci9054 info - print EEPROM values\n" \ + "pci9054 update - updates EEPROM with default values\n" \ +), +int do_pci9054 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_DASA_SIM */ +/* ----------------------------------------------------------------------------*/ + +/* ----- HYMOD ----------------------------------------------------------------- + */ +#if defined(CONFIG_HYMOD) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "fpga", 4, 6, 1, do_fpga, \ + "fpga - FPGA sub-system\n", \ + "load [type] addr size\n" \ + " - write the configuration data at memory address `addr',\n" \ + " size `size' bytes, into the FPGA of type `type' (either\n" \ + " `main' or `mezz', default `main'). e.g.\n" \ + " `fpga load 100000 7d8f'\n" \ + " loads the main FPGA with config data at address 100000\n" \ + " HEX, size 7d8f HEX (32143 DEC) bytes\n" \ + "fpga tftp file addr\n" \ + " - transfers `file' from the tftp server into memory at\n" \ + " address `addr', then writes the entire file contents\n" \ + " into the main FPGA\n" \ + "fpga store addr\n" \ + " - read configuration data from the main FPGA (the mezz\n" \ + " FPGA is write-only), into address `addr'. There must be\n" \ + " enough memory available at `addr' to hold all the config\n"\ + " data - the size of which is determined by VC:???\n" \ + "fpga info\n" \ + " - print information about the Hymod FPGA, namely the\n" \ + " memory addresses at which the four FPGA local bus\n" \ + " address spaces appear in the physical address space\n" \ +), MK_CMD_TBL_ENTRY( \ + "eeclear", 4, 1, 0, do_eecl, \ + "eeclear - Clear the eeprom on a Hymod board \n", \ + "[type]\n" \ + " - write zeroes into the EEPROM on the board of type `type'\n"\ + " (`type' is either `main' or `mezz' - default `main')\n" \ + " Note: the EEPROM write enable jumper must be installed\n" \ +), +int do_fpga (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_eecl (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_HYMOD */ +/* ----------------------------------------------------------------------------*/ +/* CRAY405 (L1) */ +#if defined (CONFIG_CRAYL1) +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "L1cmd", 5, 4, 1, do_crayL1, \ + "L1cmd - L1 update, setup, commands \n", \ + "L1cmd update - update flash images from host\n" \ + "L1cmd boot - nfs or ramboot L1\n" \ +), +int do_crayL1 (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif /* CONFIG_CRAY405 */ +/* ----------------------------------------------------------------------------*/ + +#if defined (CONFIG_EVB64260) +/* ----- EVB64260 -------------------------------------------------------------*/ +#ifdef CONFIG_ZUMA_V2 +#define CMD_TBL_BSP ZUMA_TBL_ENTRY + +#define ZUMA_TBL_ENTRY MK_CMD_TBL_ENTRY( \ + "zinit", 5, 1, 0, do_zuma_init_pbb, \ + "zinit - init zuma pbb\n", \ + "\n" \ + " - init zuma pbb\n" \ +), MK_CMD_TBL_ENTRY( \ + "zdtest", 6, 3, 1, do_zuma_test_dma, \ + "zdtest - run dma test\n", \ + "[cmd [count]]\n" \ + " - run dma cmd (w=0,v=1,cp=2,cmp=3,wi=4,vi=5), count bytes\n" \ +), MK_CMD_TBL_ENTRY( \ + "zminit", 5, 1, 0, do_zuma_init_mbox, \ + "zminit - init zuma mbox\n", \ + "\n" \ + " - init zuma mbox\n" \ +), + +int do_zuma_init_pbb (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_zuma_test_dma (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +int do_zuma_init_mbox (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +void zuma_init_pbb(void); +int zuma_mbox_init(void); +int zuma_test_dma(int cmd, int size); +#else +#define CMD_TBL_BSP +#endif /* ZUMA_NTL */ + +#endif /* CONFIG_EVB64260 */ +/* ----------------------------------------------------------------------------*/ + +/* -----W7O--------------------------------------------------------------------*/ +#if defined(CONFIG_W7O) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "vpd", 3, 2, 1, do_vpd, \ + "vpd - Read Vital Product Data\n", \ + "[dev_addr]\n" \ + " - Read VPD Data from default address, or device address 'dev_addr'.\n" \ +), + +extern int do_vpd (cmd_tbl_t *, int, int, char *[]); + +#endif /* CONFIG_W7O */ +/* ----------------------------------------------------------------------------*/ + +/* ---- PCIPPC2 / PCIPPC6 -----------------------------------------------------*/ +#if defined(CONFIG_PCIPPC2) || defined(CONFIG_PCIPPC6) +#if defined(CONFIG_WATCHDOG) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "wd", 3, 2, 1, do_wd, \ + "wd - check and set watchdog\n", \ + "on - switch watchDog on\n" \ + "wd off - switch watchdog off\n" \ + "wd - print current status\n" \ +), + +extern int do_wd (cmd_tbl_t *, int, int, char *[]); + +#else +#define CMD_TBL_BSP +#endif /* CONFIG_WATCHDOG */ + +#endif /* CONFIG_PCIPPC2 , CONFIG_PCIPPC6 */ +/* ----------------------------------------------------------------------------*/ + +/* ----- PN62 -----------------------------------------------------------------*/ +#if defined(CONFIG_PN62) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "loadpci", 5, 2, 1, do_loadpci, \ + "loadpci - load binary file over PCI\n", \ + "[addr]\n" \ + " - load binary file over PCI to address 'addr'\n" \ +), MK_CMD_TBL_ENTRY( \ + "led" , 3, 3, 1, do_led, \ + "led - set LED 0..11 on the PN62 board\n", \ + "i fun\n" \ + " - set 'i'th LED to function 'fun'\n" \ +), + +extern int do_loadpci (cmd_tbl_t *, int, int, char *[]); +extern int do_led (cmd_tbl_t *, int, int, char *[]); +#endif /* CONFIG_PN62 */ +/* ----------------------------------------------------------------------------*/ + +/* ----- TRAB ------------------------------------------------------------------ + */ +#if defined(CONFIG_TRAB) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "kbd", 3, 1, 1, do_kbd, \ + "kbd - read keyboard status\n", \ + NULL \ +), + +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_TRAB */ +/* ----------------------------------------------------------------------------*/ + +#else +#define CMD_TBL_BSP +#endif /* CFG_CMD_BSP */ + +/* ----- R360MPI --------------------------------------------------------------- + */ +#if defined(CONFIG_R360MPI) + +#define CMD_TBL_BSP MK_CMD_TBL_ENTRY( \ + "kbd", 3, 1, 1, do_kbd, \ + "kbd - read keyboard status\n", \ + NULL \ +), + +int do_kbd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); + +#endif /* CONFIG_R360MPI */ +/* ----------------------------------------------------------------------------*/ + +#endif /* _CMD_BSP_H_ */ diff --git a/include/configs/BMW.h b/include/configs/BMW.h new file mode 100644 index 0000000..edfd68f --- /dev/null +++ b/include/configs/BMW.h @@ -0,0 +1,303 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * + * Configuration settings for the CU824 board. + * + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8245 1 +#define CONFIG_BMW 1 + +#define CONFIG_BCM570x 1 /* Use Broadcom BCM570x Ethernet Driver */ +#define CONFIG_TIGON3 1 + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 9600 +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_BOOTCOMMAND "bootm FF820000" /* autoboot command */ +#define CONFIG_BOOTDELAY 5 + +#define CFG_MAX_DOC_DEVICE 1 /* Only use Onboard TSOP-16MB device */ +#define DOC_PASSIVE_PROBE 1 +#define CFG_DOC_SUPPORT_2000 1 +#define CFG_DOC_SUPPORT_MILLENNIUM 1 +#define CFG_DOC_SHORT_TIMEOUT 1 +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_DATE | \ + CFG_CMD_DOC | \ + CFG_CMD_ELF | \ + 0 ) +#if 0 +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_DHCP | \ + CFG_CMD_PCI | CFG_CMD_DOC | CFG_CMD_DATE) + +#define CONFIG_PCI 1 +#define CONFIG_PCI_PNP 1 /* PCI plug-and-play */ +#endif + +/* This must be included AFTER the definition of CONFIG_COMMANDS (if any) + */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=>" /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ + +/* Print Buffer Size + */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) + +#define CFG_MAXARGS 8 /* Max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* Default load address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 + +#define CFG_FLASH_BASE0_PRELIM 0xFFF00000 /* FLASH bank on RCS#0 */ +#define CFG_FLASH_BASE1_PRELIM 0xFF800000 /* FLASH bank on RCS#1 */ +#define CFG_FLASH_BASE CFG_MONITOR_BASE +#define CFG_FLASH_BANKS { CFG_FLASH_BASE0_PRELIM , CFG_FLASH_BASE1_PRELIM } + +/* even though FLASHP_BASE is FF800000, with 4MB is RCS0, the + * reset vector is actually located at FFB00100, but the 8245 + * takes care of us. + */ +#define CFG_RESET_ADDRESS 0xFFF00100 + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_MONITOR_BASE TEXT_BASE + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (2048 << 10) /* Reserve 2MB for malloc() */ + +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x04000000 /* 0 ... 32 MB in DRAM */ + + /* Maximum amount of RAM. + */ +#define CFG_MAX_RAM_SIZE 0x04000000 /* 0 .. 64 MB of (S)DRAM */ + + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +#undef CFG_RAMBOOT +#else +#define CFG_RAMBOOT +#endif + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ +#define CFG_INIT_RAM_ADDR CFG_SDRAM_BASE + CFG_MONITOR_LEN +#define CFG_INIT_RAM_END 0x2F00 /* End of used area in DPRAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + * For the detail description refer to the MPC8240 user's manual. + */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ +#define CFG_HZ 1000 + +#define CFG_ETH_DEV_FN 0x7800 +#define CFG_ETH_IOBASE 0x00104000 + + /* Bit-field values for MCCR1. + */ +#define CFG_ROMNAL 0xf +#define CFG_ROMFAL 0x1f +#define CFG_DBUS_SIZE 0x3 + + /* Bit-field values for MCCR2. + */ +#define CFG_TSWAIT 0x5 /* Transaction Start Wait States timer */ +#define CFG_REFINT 0x400 /* Refresh interval FIXME: was 0t430 */ + + /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. + */ +#define CFG_BSTOPRE 0 /* FIXME: was 192 */ + + /* Bit-field values for MCCR3. + */ +#define CFG_REFREC 2 /* Refresh to activate interval */ + + /* Bit-field values for MCCR4. + */ +#define CFG_PRETOACT 2 /* Precharge to activate interval FIXME: was 2 */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval FIXME: was 5 */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latancy */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 3 /* SDMODE Burst length */ +#define CFG_ACTORW 0xa /* FIXME was 2 */ +#define CFG_REGISTERD_TYPE_BUFFER 1 + +#define CFG_PGMAX 0x0 /* how long the 8240 reatins the currently accessed page in memory FIXME: was 0x32*/ + +#define CFG_SDRAM_DSCD 0x20 /* SDRAM data in sample clock delay - note bottom 3 bits MUST be 0 */ + +/* Memory bank settings. + * Only bits 20-29 are actually used from these vales to set the + * start/end addresses. The upper two bits will always be 0, and the lower + * 20 bits will be 0x00000 for a start address, or 0xfffff for an end + * address. Refer to the MPC8240 book. + */ + +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x3ff00000 +#define CFG_BANK4_END 0x3fffffff +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x3ff00000 +#define CFG_BANK5_END 0x3fffffff +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x3ff00000 +#define CFG_BANK6_END 0x3fffffff +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x3ff00000 +#define CFG_BANK7_END 0x3fffffff +#define CFG_BANK7_ENABLE 0 + +#define CFG_ODCR 0xff + +#define CONFIG_PCI 1 /* Include PCI support */ +#undef CONFIG_PCI_PNP + +/* PCI Memory space(s) */ +#define PCI_MEM_SPACE1_START 0x80000000 +#define PCI_MEM_SPACE2_START 0xfd000000 + +/* ROM Spaces */ +#include "../board/bmw/bmw.h" + +/* BAT configuration */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L (0x70000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT1U (0x70000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/* + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 0 /* Max number of flash banks */ +#define CFG_MAX_FLASH_SECT 64 /* Max number of sectors per flash */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/* + * Warining: environment is not EMBEDDED in the U-Boot code. + * It's stored in flash separately. + */ +#define CFG_ENV_IS_IN_NVRAM 1 +#define CONFIG_ENV_OVERWRITE 1 +#define CFG_NVRAM_ACCESS_ROUTINE 1 +#define CFG_ENV_ADDR 0x7c004000 /* right at the start of NVRAM */ +#define CFG_ENV_SIZE 0x1ff0 /* Size of the Environment - 8K */ +#define CFG_ENV_OFFSET 0 /* starting right at the beginning */ + +/* + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +#endif /* __CONFIG_H */ diff --git a/include/configs/CCM.h b/include/configs/CCM.h new file mode 100644 index 0000000..0e0248d --- /dev/null +++ b/include/configs/CCM.h @@ -0,0 +1,472 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * configuration options, board specific, for Siemens Card Controller Module + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#undef CCM_80MHz /* define for 80 MHz CPU only */ + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC860 1 /* This is a MPC860 CPU ... */ +#define CONFIG_CCM 1 /* on a Card Controller Module */ + +#define CONFIG_8xx_CONS_SMC1 1 /* Console is on SMC1 */ +#undef CONFIG_8xx_CONS_SMC2 +#undef CONFIG_8xx_CONS_NONE + +/* ENVIRONMENT */ + +#define CONFIG_BAUDRATE 19200 /* console baudrate in bps */ +#define CONFIG_BOOTDELAY 2 /* autoboot after 2 seconds */ +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_IPADDR 192.168.0.42 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_GATEWAYIP 0.0.0.0 +#define CONFIG_SERVERIP 192.168.0.254 + +#define CONFIG_HOSTNAME CCM + +#define CONFIG_LOADADDR 40180000 + +#undef CONFIG_BOOTARGS + +#define CONFIG_BOOTCOMMAND "setenv bootargs " \ + "mem=$(mem) " \ + "root=/dev/ram rw ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off " \ + "wt_8xx=timeout:3600; " \ + "bootm" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ + +#define CONFIG_WATCHDOG 1 /* watchdog enabled */ + +#undef CONFIG_STATUS_LED /* Status LED disabled */ + +#define CONFIG_PRAM 512 /* reserve 512kB "protected RAM"*/ + +#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ + +#define CONFIG_SPI /* enable SPI driver */ +#define CONFIG_SPI_X /* 16 bit EEPROM addressing */ + +/* ---------------------------------------------------------------- + * Offset to initial SPI buffers in DPRAM (used if the environment + * is in the SPI EEPROM): We need a 520 byte scratch DPRAM area to + * use at an early stage. It is used between the two initialization + * calls (spi_init_f() and spi_init_r()). The value 0xB00 makes it + * far enough from the start of the data area (as well as from the + * stack pointer). + * ---------------------------------------------------------------- */ +#define CFG_SPI_INIT_OFFSET 0xB00 + +#define CFG_EEPROM_PAGE_WRITE_BITS 5 /* 32-byte page size */ + + +#define CONFIG_MAC_PARTITION /* nod used yet */ +#define CONFIG_DOS_PARTITION + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_DHCP | \ + CFG_CMD_DATE | \ + CFG_CMD_EEPROM | \ + CFG_CMD_BSP ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/*----------------------------------------------------------------------*/ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00F00000 /* 1 ... 15MB in DRAM */ + +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ + +/* Ethernet hardware configuration done using port pins */ +#define CFG_PA_ETH_RESET 0x0200 /* PA 6 */ +#define CFG_PA_ETH_MDDIS 0x4000 /* PA 1 */ +#define CFG_PB_ETH_POWERDOWN 0x00000800 /* PB 20 */ +#define CFG_PB_ETH_CFG1 0x00000400 /* PB 21 */ +#define CFG_PB_ETH_CFG2 0x00000200 /* PB 22 */ +#define CFG_PB_ETH_CFG3 0x00000100 /* PB 23 */ + +/* Ethernet settings: + * MDIO not disabled, autonegotiation, 10/100Mbps, half/full duplex + */ +#define CFG_ETH_MDDIS_VALUE 0 +#define CFG_ETH_CFG1_VALUE 1 +#define CFG_ETH_CFG2_VALUE 1 +#define CFG_ETH_CFG3_VALUE 1 + +/* PUMA configuration */ +#define CFG_PC_PUMA_PROG 0x0200 /* PC 6 */ +#define CFG_PC_PUMA_DONE 0x0008 /* PC 12 */ +#define CFG_PC_PUMA_INIT 0x0004 /* PC 13 */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +/*----------------------------------------------------------------------- + * Internal Memory Mapped Register + */ +#define CFG_IMMR 0xF0000000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR CFG_IMMR +#define CFG_INIT_RAM_END 0x2F00 /* End of used area in DPRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Address accessed to reset the board - must not be mapped/assigned + */ +#define CFG_RESET_ADDRESS 0xFEFFFFFF + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0x40000000 +#if defined(DEBUG) +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#else +#define CFG_MONITOR_LEN (192 << 10) /* Reserve 192 kB for Monitor */ +#endif +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 67 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#if 1 +/* Start port with environment in flash; switch to SPI EEPROM later */ +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +#else +/* Final version: environment in EEPROM */ +#define CFG_ENV_IS_IN_EEPROM 1 +#define CFG_ENV_OFFSET 2048 +#define CFG_ENV_SIZE 2048 +#endif + +/*----------------------------------------------------------------------- + * Hardware Information Block + */ +#define CFG_HWINFO_OFFSET 0x0003FFC0 /* offset of HW Info block */ +#define CFG_HWINFO_SIZE 0x00000040 /* size of HW Info block */ +#define CFG_HWINFO_MAGIC 0x54514D38 /* 'TQM8' */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ +#define CFG_CACHELINE_SHIFT 4 /* log base 2 of the above value */ + +/*----------------------------------------------------------------------- + * SYPCR - System Protection Control 11-9 + * SYPCR can only be written once after reset! + *----------------------------------------------------------------------- + * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze + */ +#if defined(CONFIG_WATCHDOG) +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ + SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) +#else +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP) +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration 11-6 + *----------------------------------------------------------------------- + * we must activate GPL5 in the SIUMCR for CAN + */ +#define CFG_SIUMCR (SIUMCR_DBGC11 | SIUMCR_DBPC00 | SIUMCR_MLRC01) + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control 11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freezing enabled + */ +#define CFG_TBSCR (TBSCR_REFA | TBSCR_REFB | TBSCR_TBF) + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register 11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC (RTCSC_SEC | RTCSC_ALR | RTCSC_RTF| RTCSC_RTE) + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control 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 15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit + * + * If this is a 80 MHz CPU, set PLL multiplication factor to 5 (5*16=80)! + */ +#ifdef CCM_80MHz /* for 80 MHz, we use a 16 MHz clock * 5 */ +#define CFG_PLPRCR \ + ( (5-1)<<PLPRCR_MF_SHIFT | PLPRCR_TEXPS | PLPRCR_TMIST ) +#else /* up to 50 MHz we use a 1:1 clock */ +#define CFG_PLPRCR (PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST) +#endif /* CCM_80MHz */ + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register 15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK SCCR_EBDF11 +#ifdef CCM_80MHz /* for 80 MHz, we use a 16 MHz clock * 5 */ +#define CFG_SCCR (/* SCCR_TBS | */ \ + SCCR_COM00 | SCCR_DFSYNC00 | SCCR_DFBRG00 | \ + SCCR_DFNL000 | SCCR_DFNH000 | SCCR_DFLCD000 | \ + SCCR_DFALCD00) +#else /* up to 50 MHz we use a 1:1 clock */ +#define CFG_SCCR (SCCR_TBS | \ + SCCR_COM00 | SCCR_DFSYNC00 | SCCR_DFBRG00 | \ + SCCR_DFNL000 | SCCR_DFNH000 | SCCR_DFLCD000 | \ + SCCR_DFALCD00) +#endif /* CCM_80MHz */ + +/*----------------------------------------------------------------------- + * + * Interrupt Levels + *----------------------------------------------------------------------- + */ +#define CFG_CPM_INTERRUPT 13 /* SIU_LEVEL6 */ + +/*----------------------------------------------------------------------- + * + *----------------------------------------------------------------------- + * + */ +#define CFG_DER 0 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0x40000000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0x60000000 /* FLASH bank #0 */ + +/* used to re-map FLASH both when starting from SRAM or FLASH: + * restrict access enough to keep SRAM working (if any) + * but not too much to meddle with FLASH accesses + */ +#define CFG_REMAP_OR_AM 0x80000000 /* OR addr mask */ +#define CFG_PRELIM_OR_AM 0xE0000000 /* OR addr mask */ + +/* FLASH timing: ACS = 11, TRLX = 0, CSNT = 1, SCY = 5, EHTR = 1 */ +#define CFG_OR_TIMING_FLASH (OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | \ + OR_SCY_5_CLK | OR_EHTR) + +#define CFG_OR0_REMAP (CFG_REMAP_OR_AM | CFG_OR_TIMING_FLASH) +#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH) +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_V ) + +#define CFG_OR1_REMAP CFG_OR0_REMAP +#define CFG_OR1_PRELIM CFG_OR0_PRELIM +#define CFG_BR1_PRELIM ((FLASH_BASE1_PRELIM & BR_BA_MSK) | BR_V ) + +/* + * BR2 and OR2 (SDRAM) + * + */ +#define SDRAM_BASE2_PRELIM 0x00000000 /* SDRAM bank #0 */ +#define SDRAM_BASE3_PRELIM 0x20000000 /* SDRAM bank #1 */ +#define SDRAM_MAX_SIZE 0x04000000 /* max 64 MB per bank */ + +/* SDRAM timing: Multiplexed addresses, GPL5 output to GPL5_A (don't care) */ +#define CFG_OR_TIMING_SDRAM 0x00000A00 + +#define CFG_OR2_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_SDRAM ) +#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V ) + +/* + * BR3 and OR3 (CAN Controller) + */ +#define CFG_CAN_BASE 0xC0000000 /* CAN mapped at 0xC0000000 */ +#define CFG_CAN_OR_AM 0xFFFF8000 /* 32 kB address mask */ +#define CFG_OR3_CAN (CFG_CAN_OR_AM | OR_G5LA | OR_BI) +#define CFG_BR3_CAN ((CFG_CAN_BASE & BR_BA_MSK) | \ + BR_PS_8 | BR_MS_UPMB | BR_V ) + +/* + * BR4/OR4: PUMA Config + * + * Memory controller will be used in 2 modes: + * + * - "read" mode: + * BR4: 0x10100801 OR4: 0xffff8520 + * - "load" mode (chip select on UPM B): + * BR4: 0x101004c1 OR4: 0xffff8600 + * + * Default initialization is in "read" mode + */ +#define PUMA_CONF_BASE 0x10100000 /* PUMA Config */ +#define PUMA_CONF_OR_AM 0xFFFF8000 /* 32 kB */ +#define PUMA_CONF_LOAD_TIMING (OR_ACS_DIV2 | OR_SCY_2_CLK) +#define PUMA_CONF_READ_TIMING (OR_G5LA | OR_BI | OR_SCY_2_CLK) + +#define PUMA_CONF_BR_LOAD ((PUMA_CONF_BASE & BR_BA_MSK) | \ + BR_PS_8 | BR_MS_UPMB | BR_V) +#define PUMA_CONF_OR_LOAD (PUMA_CONF_OR_AM | PUMA_CONF_LOAD_TIMING) + +#define PUMA_CONF_BR_READ ((PUMA_CONF_BASE & BR_BA_MSK) | BR_PS_16 | BR_V) +#define PUMA_CONF_OR_READ (PUMA_CONF_OR_AM | PUMA_CONF_READ_TIMING) + +#define CFG_BR4_PRELIM PUMA_CONF_BR_READ +#define CFG_OR4_PRELIM PUMA_CONF_OR_READ + +/* + * BR5/OR5: PUMA: SMA Bus 8 Bit + * BR5: 0x10200401 OR5: 0xffe0010a + */ +#define PUMA_SMA8_BASE 0x10200000 /* PUMA SMA Bus 8 Bit */ +#define PUMA_SMA8_OR_AM 0xFFE00000 /* 2 MB */ +#define PUMA_SMA8_TIMING (OR_BI | OR_SCY_0_CLK | OR_EHTR) + +#define CFG_BR5_PRELIM ((PUMA_SMA8_BASE & BR_BA_MSK) | BR_PS_8 | BR_V) +#define CFG_OR5_PRELIM (PUMA_SMA8_OR_AM | PUMA_SMA8_TIMING | OR_SETA) + +/* + * BR6/OR6: PUMA: SMA Bus 16 Bit + * BR6: 0x10600801 OR6: 0xffe0010a + */ +#define PUMA_SMA16_BASE 0x10600000 /* PUMA SMA Bus 16 Bit */ +#define PUMA_SMA16_OR_AM 0xFFE00000 /* 2 MB */ +#define PUMA_SMA16_TIMING (OR_BI | OR_SCY_0_CLK | OR_EHTR) + +#define CFG_BR6_PRELIM ((PUMA_SMA16_BASE & BR_BA_MSK) | BR_PS_16 | BR_V) +#define CFG_OR6_PRELIM (PUMA_SMA16_OR_AM | PUMA_SMA16_TIMING | OR_SETA) + +/* + * BR7/OR7: PUMA: external Flash + * BR7: 0x10a00801 OR7: 0xfe00010a + */ +#define PUMA_FLASH_BASE 0x10A00000 /* PUMA external Flash */ +#define PUMA_FLASH_OR_AM 0xFE000000 /* 32 MB */ +#define PUMA_FLASH_TIMING (OR_BI | OR_SCY_0_CLK | OR_EHTR) + +#define CFG_BR7_PRELIM ((PUMA_FLASH_BASE & BR_BA_MSK) | BR_PS_16 | BR_V) +#define CFG_OR7_PRELIM (PUMA_FLASH_OR_AM | PUMA_FLASH_TIMING | OR_SETA) + + +/* + * Memory Periodic Timer Prescaler + */ + +/* periodic timer for refresh */ +#define CFG_MAMR_PTA 97 /* start with divider for 100 MHz */ + +/* refresh rate 15.6 us (= 64 ms / 4K = 62.4 / quad bursts) for <= 128 MBit */ +#define CFG_MPTPR_2BK_4K MPTPR_PTP_DIV16 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_4K MPTPR_PTP_DIV32 /* setting for 1 bank */ + +/* refresh rate 7.8 us (= 64 ms / 8K = 31.2 / quad bursts) for 256 MBit */ +#define CFG_MPTPR_2BK_8K MPTPR_PTP_DIV8 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_8K MPTPR_PTP_DIV16 /* setting for 1 bank */ + +/* + * MAMR settings for SDRAM + */ + +/* 8 column SDRAM */ +#define CFG_MAMR_8COL ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) +/* 9 column SDRAM */ +#define CFG_MAMR_9COL ((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) + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/CPCI405.h b/include/configs/CPCI405.h new file mode 100644 index 0000000..6b98347 --- /dev/null +++ b/include/configs/CPCI405.h @@ -0,0 +1,333 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_CPCI405 1 /* ...on a CPCI405 board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#if 0 +#define CONFIG_PREBOOT \ + "crc32 f0207004 ffc 0;" \ + "if cmp 0 f0207000 1;" \ + "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;" \ + "else;echo Old CRC is bad;fi" +#endif + +#undef CONFIG_BOOTARGS +#define CONFIG_RAMBOOTCOMMAND \ + "setenv bootargs root=/dev/ram rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;" \ + "bootm ffc00000 ffca0000" +#define CONFIG_NFSBOOTCOMMAND \ + "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;" \ + "bootm ffc00000" +#define CONFIG_BOOTCOMMAND CONFIG_RAMBOOTCOMMAND + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_IDE | \ + CFG_CMD_ELF | \ + CFG_CMD_EEPROM ) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#undef CFG_HUSH_PARSER /* use "hush" command parser */ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_DEVICE_NULLDEV 1 /* include nulldev device */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_IGNORE_405_UART_ERRATA_59 /* ignore ppc405gp errata #59 */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define PCI_HOST_ADAPTER 0 /* configure as 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_AUTO /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ + /* resource configuration */ + +#define CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0405 /* PCI Device ID: CPCI-405 */ +#define CFG_PCI_SUBSYS_DEVICEID2 0x0406 /* PCI Device ID: CPCI-405-A */ +#define CFG_PCI_CLASSCODE 0x0b20 /* PCI Class Code: Processor/PPC*/ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xfc000001 /* 64MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffc00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffc00001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff + *----------------------------------------------------------------------- + */ +#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#undef CONFIG_IDE_RESET /* no reset for ide supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR 0xF0100000 +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O */ +#define CFG_ATA_REG_OFFSET 0x0000 /* Offset for normal register accesses */ +#define CFG_ATA_ALT_OFFSET 0x0000 /* Offset for alternate registers */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFD0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 196 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#if 1 /* Use NVRAM for environment variables */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */ +#define CFG_NVRAM_BASE_ADDR 0xf0200000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE (32*1024) /* NVRAM size */ +#define CFG_ENV_SIZE 0x1000 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE) /* Env */ +#define CFG_NVRAM_VXWORKS_OFFS 0x6900 /* Offset for VxWorks eth-addr */ + +#else /* Use EEPROM for environment variables */ + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x200 /* 512 bytes may be used for env vars */ + /* total size of a CAT24WC08 is 1024 bytes */ +#endif + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC08) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFC00000 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Flash Bank 1) initialization */ +#define CFG_EBC_PB1AP 0x92015480 +#define CFG_EBC_PB1CR 0xFF85A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (CAN0, 1, 2, Codeswitch) initialization */ +#define CFG_EBC_PB2AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB2CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (CompactFlash IDE) initialization */ +#define CFG_EBC_PB3AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB3CR 0xF011A000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */ + +/* Memory Bank 4 (NVRAM) initialization */ +#define CFG_EBC_PB4AP 0x01005280 /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1 */ +#define CFG_EBC_PB4CR 0xF0218000 /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 5 (Quart) initialization */ +#define CFG_EBC_PB5AP 0x04005B80 /* TWT=8,WBN=1,WBF=1,TH=5,RE=1,SOR=1*/ +#define CFG_EBC_PB5CR 0xF0318000 /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit */ + +/*----------------------------------------------------------------------- + * FPGA stuff + */ + +/* FPGA program pin configuration */ +#define CFG_FPGA_PRG 0x04000000 /* FPGA program pin (ppc output) */ +#define CFG_FPGA_CLK 0x02000000 /* FPGA clk pin (ppc output) */ +#define CFG_FPGA_DATA 0x01000000 /* FPGA data pin (ppc output) */ +#define CFG_FPGA_INIT 0x00400000 /* FPGA init pin (ppc input) */ +#define CFG_FPGA_DONE 0x00800000 /* FPGA done pin (ppc input) */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in data cache) + */ +#if 1 /* test-only */ +#define CFG_INIT_DCACHE_CS 7 /* use cs # 7 for data cache memory */ + +#define CFG_INIT_RAM_ADDR 0x40000000 /* use data cache */ +#else +#define CFG_INIT_RAM_ADDR 0x00df0000 /* inside of SDRAM */ +#endif +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/CPCI4052.h b/include/configs/CPCI4052.h new file mode 100644 index 0000000..0533827 --- /dev/null +++ b/include/configs/CPCI4052.h @@ -0,0 +1,378 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_CPCI405 1 /* ...on a CPCI405 board */ +#define CONFIG_CPCI405_VER2 1 /* ...version 2 */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#if 0 +#define CONFIG_PREBOOT \ + "crc32 f0207004 ffc 0;" \ + "if cmp 0 f0207000 1;" \ + "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;" \ + "else;echo Old CRC is bad;fi" +#endif + +#undef CONFIG_BOOTARGS +#define CONFIG_RAMBOOTCOMMAND \ + "setenv bootargs root=/dev/ram rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;" \ + "bootm ffc00000 ffca0000" +#define CONFIG_NFSBOOTCOMMAND \ + "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off;" \ + "bootm ffc00000" +#define CONFIG_BOOTCOMMAND CONFIG_RAMBOOTCOMMAND + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_RTC_M48T35A 1 /* ST Electronics M48 timekeeper */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_IDE | \ + CFG_CMD_ELF | \ + CFG_CMD_DATE | \ + CFG_CMD_JFFS2 | \ + CFG_CMD_I2C | \ + CFG_CMD_EEPROM ) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#undef CFG_HUSH_PARSER /* use "hush" command parser */ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_DEVICE_NULLDEV 1 /* include nulldev device */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_IGNORE_405_UART_ERRATA_59 /* ignore ppc405gp errata #59 */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define PCI_HOST_ADAPTER 0 /* configure as 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_AUTO /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ + /* resource configuration */ + +#define CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0405 /* PCI Device ID: CPCI-405 */ +#define CFG_PCI_SUBSYS_DEVICEID2 0x0406 /* PCI Device ID: CPCI-405-A */ +#define CFG_PCI_CLASSCODE 0x0b20 /* PCI Class Code: Processor/PPC*/ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xfc000001 /* 64MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffc00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffc00001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff + *----------------------------------------------------------------------- + */ +#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#define CONFIG_IDE_RESET 1 /* reset for ide supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR 0xF0100000 +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O */ +#define CFG_ATA_REG_OFFSET 0x0000 /* Offset for normal register accesses */ +#define CFG_ATA_ALT_OFFSET 0x0000 /* Offset for alternate registers */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFC0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#define CFG_JFFS2_FIRST_BANK 0 /* use for JFFS2 */ +#define CFG_JFFS2_NUM_BANKS 1 /* ! second bank contains U-Boot */ + +#if 0 /* Use NVRAM for environment variables */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */ +#define CFG_ENV_SIZE 0x0ff8 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-(CFG_ENV_SIZE+8)) /* Env */ + +#else /* Use EEPROM for environment variables */ + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x800 /* 2048 bytes may be used for env vars*/ + /* total size of a CAT24WC16 is 2048 bytes */ +#endif + +#define CFG_NVRAM_BASE_ADDR 0xf0200000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE (32*1024) /* NVRAM size */ +#define CFG_NVRAM_VXWORKS_OFFS 0x6900 /* Offset for VxWorks eth-addr */ + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC16) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 16384 /* For IBM 405 CPUs, older 405 ppc's */ + /* have only 8kB, 16kB is save here */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFC00000 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Flash Bank 1) initialization */ +#define CFG_EBC_PB1AP 0x92015480 +#define CFG_EBC_PB1CR 0xFF85A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (CAN0, 1) initialization */ +#define CFG_EBC_PB2AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB2CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (CompactFlash IDE) initialization */ +#define CFG_EBC_PB3AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB3CR 0xF011A000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */ + +/* Memory Bank 4 (NVRAM/RTC) initialization */ +#define CFG_EBC_PB4AP 0x01005280 /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1 */ +#define CFG_EBC_PB4CR 0xF0218000 /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 5 (optional Quart) initialization */ +#define CFG_EBC_PB5AP 0x04005B80 /* TWT=8,WBN=1,WBF=1,TH=5,RE=1,SOR=1*/ +#define CFG_EBC_PB5CR 0xF0318000 /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 6 (FPGA internal) initialization */ +#define CFG_EBC_PB6AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB6CR 0xF041A000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */ +#define CFG_FPGA_BASE_ADDR 0xF0400000 + +/*----------------------------------------------------------------------- + * FPGA stuff + */ +/* FPGA internal regs */ +#define CFG_FPGA_MODE 0x00 +#define CFG_FPGA_STATUS 0x02 +#define CFG_FPGA_TS 0x04 +#define CFG_FPGA_TS_LOW 0x06 +#define CFG_FPGA_TS_CAP0 0x10 +#define CFG_FPGA_TS_CAP0_LOW 0x12 +#define CFG_FPGA_TS_CAP1 0x14 +#define CFG_FPGA_TS_CAP1_LOW 0x16 +#define CFG_FPGA_TS_CAP2 0x18 +#define CFG_FPGA_TS_CAP2_LOW 0x1a +#define CFG_FPGA_TS_CAP3 0x1c +#define CFG_FPGA_TS_CAP3_LOW 0x1e + +/* FPGA Mode Reg */ +#define CFG_FPGA_MODE_CF_RESET 0x0001 +#define CFG_FPGA_MODE_TS_IRQ_ENABLE 0x0100 +#define CFG_FPGA_MODE_TS_IRQ_CLEAR 0x1000 +#define CFG_FPGA_MODE_TS_CLEAR 0x2000 + +/* FPGA Status Reg */ +#define CFG_FPGA_STATUS_DIP0 0x0001 +#define CFG_FPGA_STATUS_DIP1 0x0002 +#define CFG_FPGA_STATUS_DIP2 0x0004 +#define CFG_FPGA_STATUS_FLASH 0x0008 +#define CFG_FPGA_STATUS_TS_IRQ 0x1000 + +#define CFG_FPGA_SPARTAN2 1 /* using Xilinx Spartan 2 now */ +#define CFG_FPGA_MAX_SIZE 32*1024 /* 32kByte is enough for XC2S15 */ + +/* FPGA program pin configuration */ +#define CFG_FPGA_PRG 0x04000000 /* FPGA program pin (ppc output) */ +#define CFG_FPGA_CLK 0x02000000 /* FPGA clk pin (ppc output) */ +#define CFG_FPGA_DATA 0x01000000 /* FPGA data pin (ppc output) */ +#define CFG_FPGA_INIT 0x00010000 /* FPGA init pin (ppc input) */ +#define CFG_FPGA_DONE 0x00008000 /* FPGA done pin (ppc input) */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in data cache) + */ +#if 1 /* test-only */ +#define CFG_INIT_DCACHE_CS 7 /* use cs # 7 for data cache memory */ + +#define CFG_INIT_RAM_ADDR 0x40000000 /* use data cache */ +#else +#define CFG_INIT_RAM_ADDR 0x00df0000 /* inside of SDRAM */ +#endif +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/CPCIISER4.h b/include/configs/CPCIISER4.h new file mode 100644 index 0000000..6c8d7f6 --- /dev/null +++ b/include/configs/CPCIISER4.h @@ -0,0 +1,241 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_CPCIISER4 1 /* ...on a CPCIISER4 board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 25000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND "bootm fff00000" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_ELF | \ + CFG_CMD_EEPROM ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_EXT_SERIAL_CLOCK 1843200 /* use external serial clock */ + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#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_AUTO /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ + /* resource configuration */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0404 /* PCI Device ID: CPCI-ISER4 */ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xff000001 /* 16MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffe00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffe00001 /* 2MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFC0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (256 * 1024) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC08) for environment + */ +#define CONFIG_HARD_I2C /* I2C with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x300 /* 768 bytes may be used for env vars */ + /* total size of a CAT24WC08 is 1024 bytes */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFFF00000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Uart 8bit) initialization */ +#define CFG_EBC_PB1AP 0x01000480 /* TWT=2,TH=2,no Ready,BEM=0,SOR=1 */ +#define CFG_EBC_PB1CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 2 (Uart 32bit) initialization */ +#define CFG_EBC_PB2AP 0x000004c0 /* no Ready, BEM=1 */ +#define CFG_EBC_PB2CR 0xF011C000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=32bit */ + +/* Memory Bank 3 (FPGA Reset) initialization */ +#define CFG_EBC_PB3AP 0x010004C0 /* no Ready, BEM=1 */ +#define CFG_EBC_PB3CR 0xF021A000 /* BAS=0xF02,BS=1MB,BU=R/W,BW=16bit */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR 0x00df0000 /* inside of SDRAM */ +#define CFG_INIT_RAM_END 0x0f00 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/CRAYL1.h b/include/configs/CRAYL1.h new file mode 100644 index 0000000..b10d967 --- /dev/null +++ b/include/configs/CRAYL1.h @@ -0,0 +1,251 @@ +/* + * (C) Copyright 2000, 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * David Updegraff, Cray, Inc. dave@cray.com: our 405 is walnut-lite.. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#define CONFIG_CRAYL1 +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC405 family */ +#define CONFIG_SYS_CLK_FREQ 25000000 +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 1 /* PHY address; handling of ENET */ +#define CONFIG_BOARD_PRE_INIT 1 /* setup for 405gp */ +#define CONFIG_MISC_INIT_R 1 /* so that a misc_init_r() is called */ + +/* set PRAM to keep U-Boot out, mem= to keep linux out, and initrd_hi to + * keep possible initrd ramdisk decompression out. This is in k (1024 bytes) + #define CONFIG_PRAM 16 + */ +#define CONFIG_LOADADDR 0x100000 +#undef CONFIG_BOOTARGS + +/* the logic is that booting is driven by what env vars get set from DHCP. + * Normal DHCP sets things like serverip, rootpath, etc. + * if printenv + */ +#define CFG_AUTOLOAD "yes" +#define CONFIG_BOOTCOMMAND "dhcp;"\ + "setenv bootargs devfs=mount;"\ + "setenv bootargs ip=$ipaddr:$serverip:$gatewayip:$netmask:::off $bootargs;"\ + "if printenv initrd;"\ + "then;" \ + "setenv initrd_hi $mem;"\ + "tftp 1000000 $initrd;"\ + "setenv bootargs root=/dev/ram0 rw cwsroot=$serverip:$rootpath $bootargs;"\ + "bootm 100000 1000000;"\ + "else;"\ + "setenv bootargs root=/dev/nfs ro nfsroot=$serverip:$rootpath $bootargs;"\ + "bootm 100000;"\ + "fi;" + +#define CONFIG_EXTRA_ENV_SETTINGS "" + +/* + * ..during experiments.. + #define CONFIG_SERVERIP 10.0.0.1 + #define CONFIG_ETHADDR 00:40:a6:80:14:5 + */ +#define CONFIG_HARD_I2C 1 /* hardware support for i2c */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F +#define CFG_I2C_EEPROM_ADDR 0x57 +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CONFIG_IDENT_STRING "Cray L1" +#define CONFIG_ENV_OVERWRITE 1 +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ +#define CFG_HUSH_PARSER 1 +#define CFG_PROMPT_HUSH_PS2 "> " + + +#define CONFIG_COMMANDS (\ + CFG_CMD_BDI|\ + CFG_CMD_IMI|\ + CFG_CMD_FLASH|\ + CFG_CMD_MEMORY|\ + CFG_CMD_NET|\ + CFG_CMD_ENV|\ + CFG_CMD_CONSOLE|\ + CFG_CMD_ASKENV|\ + CFG_CMD_ECHO|\ + CFG_CMD_IMMAP|\ + CFG_CMD_REGINFO|\ + CFG_CMD_DHCP|\ + CFG_CMD_DATE|\ + CFG_CMD_RUN|\ + CFG_CMD_I2C|\ + CFG_CMD_EEPROM|\ + CFG_CMD_SETGETDCR) + +/* + * optional BOOTP / DHCP fields + */ +#define CONFIG_BOOTP_MASK (\ + CONFIG_BOOTP_VENDOREX|\ + CONFIG_BOOTP_SUBNETMASK|\ + CONFIG_BOOTP_GATEWAY|\ + CONFIG_BOOTP_DNS|\ + CONFIG_BOOTP_HOSTNAME|\ + CONFIG_BOOTP_BOOTFILESIZE|\ + CONFIG_BOOTP_BOOTPATH) + +/* + * bauds. Just to make it compile; in our case, I read the base_baud + * from the DCR anyway, so its kinda-tied to the above ref. clock which in turn + * drives the system clock. + */ +#define CFG_BASE_BAUD 403225 +#define CFG_BAUDRATE_TABLE \ + {300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400} + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ + + +#define CFG_LOAD_ADDR 0x100000/* where to load what we get from TFTP */ +#define CFG_TFTP_LOADADDR CFG_LOAD_ADDR +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFC00000 +#define CFG_MONITOR_BASE TEXT_BASE + +#ifndef CFG_HUSH_PARSER +#define CFG_MONITOR_LEN (128 * 1024) /* Reserve 128 kB for Monitor */ +#define CFG_ENV_OFFSET 0x3D0000 +#else +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 192 kB for Monitor */ +#define CFG_ENV_OFFSET 0x3FE000 +#endif + +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 64 /* max number of sectors on one chip */ +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/* BEG ENVIRONNEMENT FLASH: needs to be a whole FlashSector */ +#define CFG_ENV_IS_IN_FLASH 1 /* use FLASH for environment vars */ +#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x10000 /* see README - env sector total size */ + +/* Memory tests: U-Boot relocates itself to the top of Ram, so its at + * 32meg-(128k+some_malloc_space+copy-of-ENV sector).. + */ +#define CFG_SDRAM_SIZE 32 /* megs of ram */ +#define CFG_MEMTEST_START 0x2000 /* memtest works from the end of */ + /* the exception vector table */ + /* to the end of the DRAM */ + /* less monitor and malloc area */ +#define CFG_STACK_USAGE 0x10000 /* Reserve 64k for the stack usage */ +#define CFG_MEM_END_USAGE ( CFG_MONITOR_LEN \ + + CFG_MALLOC_LEN \ + + CFG_ENV_SECT_SIZE \ + + CFG_STACK_USAGE ) + +#define CFG_MEMTEST_END (CFG_SDRAM_SIZE * 1024 * 1024 - CFG_MEM_END_USAGE) +/* END ENVIRONNEMENT FLASH */ + +/*----------------------------------------------------------------------- + * Cache Configuration. Only used to ..?? clear it, I guess.. + */ +#define CFG_DCACHE_SIZE 16384 +#define CFG_CACHELINE_SIZE 32 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM CFG_FLASH_BASE /* FLASH bank #0 */ + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in OnChipMem ) + */ +#if 0 +#define CFG_INIT_RAM_ADDR 0x40000000 /* use data cache */ +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#else +#define CFG_TEMP_STACK_OCM 1 +#define CFG_OCM_DATA_ADDR 0xF0000000 +#define CFG_OCM_DATA_SIZE 0x1000 +#define CFG_INIT_RAM_ADDR CFG_OCM_DATA_ADDR /* inside of On Chip SRAM */ +#define CFG_INIT_RAM_END CFG_OCM_DATA_SIZE /* End of On Chip SRAM */ +#endif + +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Definitions for Serial Presence Detect EEPROM address + */ +#define EEPROM_WRITE_ADDRESS 0xA0 +#define EEPROM_READ_ADDRESS 0xA1 + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/CU824.h b/include/configs/CU824.h new file mode 100644 index 0000000..ed38ef6 --- /dev/null +++ b/include/configs/CU824.h @@ -0,0 +1,305 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * + * Configuration settings for the CU824 board. + * + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8240 1 +#define CONFIG_CU824 1 + + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 9600 +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_PREBOOT "echo;echo Type \"run flash_nfs\" to mount root filesystem over NFS;echo" + +#define CONFIG_BOOTCOMMAND "bootm FE020000" /* autoboot command */ +#define CONFIG_BOOTDELAY 5 + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_DHCP | \ + CFG_CMD_PCI | \ + 0/* CFG_CMD_DATE */ ) + +/* This must be included AFTER the definition of CONFIG_COMMANDS (if any) + */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ + +#if 1 +#define CFG_HUSH_PARSER 1 /* use "hush" command parser */ +#endif +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +/* Print Buffer Size + */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) + +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* Default load address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFF000000 + +#define CFG_RESET_ADDRESS 0xFFF00100 + +#define CFG_EUMB_ADDR 0xFCE00000 + +#define CFG_MONITOR_BASE TEXT_BASE + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x02000000 /* 0 ... 32 MB in DRAM */ + + /* Maximum amount of RAM. + */ +#define CFG_MAX_RAM_SIZE 0x10000000 + + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +#undef CFG_RAMBOOT +#else +#define CFG_RAMBOOT +#endif + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ + + /* Size in bytes reserved for initial data + */ +#define CFG_GBL_DATA_SIZE 128 + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +/* + * NS16550 Configuration + */ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 4 + +#define CFG_NS16550_CLK (14745600 / 2) + +#define CFG_NS16550_COM1 0xFE800080 +#define CFG_NS16550_COM2 0xFE8000C0 + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + * For the detail description refer to the MPC8240 user's manual. + */ + +#define CONFIG_SYS_CLK_FREQ 33000000 +#define CFG_HZ 1000 + + /* Bit-field values for MCCR1. + */ +#define CFG_ROMNAL 0 +#define CFG_ROMFAL 7 + + /* Bit-field values for MCCR2. + */ +#define CFG_REFINT 430 /* Refresh interval */ + + /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. + */ +#define CFG_BSTOPRE 192 + + /* Bit-field values for MCCR3. + */ +#define CFG_REFREC 2 /* Refresh to activate interval */ +#define CFG_RDLAT 3 /* Data latancy from read command */ + + /* Bit-field values for MCCR4. + */ +#define CFG_PRETOACT 2 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_SDMODE_CAS_LAT 2 /* SDMODE CAS latancy */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length */ +#define CFG_ACTORW 2 +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* Memory bank settings. + * Only bits 20-29 are actually used from these vales to set the + * start/end addresses. The upper two bits will always be 0, and the lower + * 20 bits will be 0x00000 for a start address, or 0xfffff for an end + * address. Refer to the MPC8240 book. + */ + +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x3ff00000 +#define CFG_BANK4_END 0x3fffffff +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x3ff00000 +#define CFG_BANK5_END 0x3fffffff +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x3ff00000 +#define CFG_BANK6_END 0x3fffffff +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x3ff00000 +#define CFG_BANK7_END 0x3fffffff +#define CFG_BANK7_ENABLE 0 + +#define CFG_ODCR 0xff + +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT3L (0xFC000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xFC000000 | BATU_BL_64M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* Max number of flash banks */ +#define CFG_MAX_FLASH_SECT 39 /* Max number of sectors in one bank */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + + /* Warining: environment is not EMBEDDED in the U-Boot code. + * It's stored in flash separately. + */ +#define CFG_ENV_IS_IN_FLASH 1 +#if 0 +#define CFG_ENV_ADDR 0xFF008000 +#define CFG_ENV_SIZE 0x8000 /* Size of the Environment Sector */ +#else +#define CFG_ENV_ADDR 0xFFFC0000 +#define CFG_ENV_SIZE 0x4000 /* Size of the Environment */ +#define CFG_ENV_OFFSET 0 /* starting right at the beginning */ +#define CFG_ENV_SECT_SIZE 0x40000 /* Size of the Environment Sector */ +#endif + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP + +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_TULIP +#define CONFIG_TULIP_USE_IO + +#define CFG_ETH_DEV_FN 0x7800 +#define CFG_ETH_IOBASE 0x00104000 + +#endif /* __CONFIG_H */ diff --git a/include/configs/DU405.h b/include/configs/DU405.h new file mode 100644 index 0000000..1bf40d9 --- /dev/null +++ b/include/configs/DU405.h @@ -0,0 +1,303 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_DU405 1 /* ...on a DU405 board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 25000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND "bootm fff00000" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_IDE | \ + CFG_CMD_ELF | \ + CFG_CMD_DATE | \ + CFG_CMD_EEPROM ) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_RTC_MC146818 /* BQ3285 is MC146818 compatible*/ +#define CFG_RTC_REG_BASE_ADDR 0xF0000080 /* RTC Base Address */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_EXT_SERIAL_CLOCK 11059200 /* use external serial clock */ + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#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_AUTO /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ + /* resource configuration */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0404 /* PCI Device ID: CPCI-ISER4 */ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xff000001 /* 16MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffe00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffe00001 /* 2MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff + *----------------------------------------------------------------------- + */ +#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#undef CONFIG_IDE_RESET /* no reset for ide supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*1) /* max. 1 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR 0xF0100000 +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#define CFG_ATA_DATA_OFFSET 0x0000 /* Offset for data I/O */ +#define CFG_ATA_REG_OFFSET 0x0000 /* Offset for normal register accesses */ +#define CFG_ATA_ALT_OFFSET 0x0000 /* Offset for alternate registers */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFD0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 192 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC08) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x400 /* 1024 bytes may be used for env vars */ + /* total size of a CAT24WC08 is 1024 bytes */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFC00000 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +#define FLASH0_BA 0xFFC00000 /* FLASH 0 Base Address */ +#define FLASH1_BA 0xFF800000 /* FLASH 1 Base Address */ +#define CAN_BA 0xF0000000 /* CAN Base Address */ +#define DUART_BA 0xF0300000 /* DUART Base Address */ +#define CF_BA 0xF0100000 /* CompactFlash Base Address */ +#define SRAM_BA 0xF0200000 /* SRAM Base Address */ +#define DURAG_IO_BA 0xF0400000 /* DURAG Bus IO Base Address */ +#define DURAG_MEM_BA 0xF0500000 /* DURAG Bus Mem Base Address */ + +#define FPGA_MODE_REG (DUART_BA+0x80) /* FPGA Mode Register */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR FLASH0_BA | 0x5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Flash Bank 1) initialization */ +#define CFG_EBC_PB1AP 0x92015480 +#define CFG_EBC_PB1CR FLASH1_BA | 0x5A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (CAN0) initialization */ +#define CFG_EBC_PB2AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB2CR CAN_BA | 0x18000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (DUART) initialization */ +#define CFG_EBC_PB3AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB3CR DUART_BA | 0x18000 /* BAS=0xF03,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 4 (CompactFlash IDE) initialization */ +#define CFG_EBC_PB4AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB4CR CF_BA | 0x1A000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=16bit */ + +/* Memory Bank 5 (SRAM) initialization */ +#define CFG_EBC_PB5AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB5CR SRAM_BA | 0x1A000 /* BAS=0xF02,BS=1MB,BU=R/W,BW=16bit */ + +/* Memory Bank 6 (DURAG Bus IO Space) initialization */ +#define CFG_EBC_PB6AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB6CR DURAG_IO_BA | 0x18000 /* BAS=0xF04,BS=1MB,BU=R/W,BW=8bit*/ + +/* Memory Bank 7 (DURAG Bus Mem Space) initialization */ +#define CFG_EBC_PB7AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB7CR DURAG_MEM_BA | 0x18000 /* BAS=0xF05,BS=1MB,BU=R/W,BW=8bit */ + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + +/* use on chip memory ( OCM ) for temperary stack until sdram is tested */ +#define CFG_TEMP_STACK_OCM 1 + +/* On Chip Memory location */ +#define CFG_OCM_DATA_ADDR 0xF8000000 +#define CFG_OCM_DATA_SIZE 0x1000 + +#define CFG_INIT_RAM_ADDR CFG_OCM_DATA_ADDR /* inside of SDRAM */ +#define CFG_INIT_RAM_END CFG_OCM_DATA_SIZE /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/EVB64260.h b/include/configs/EVB64260.h new file mode 100644 index 0000000..fa7e1f6 --- /dev/null +++ b/include/configs/EVB64260.h @@ -0,0 +1,428 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <asm/processor.h> + +#ifndef __ASSEMBLY__ +#include <galileo/core.h> +#endif + +#include "../board/evb64260/local.h" + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_EVB64260 1 /* this is an EVB64260 board */ +#define CFG_GT_6426x GT_64260 /* with a 64260 system controller */ + +#define CONFIG_BAUDRATE 38400 /* console baudrate = 38400 */ + +#undef CONFIG_ECC /* enable ECC support */ +/* #define CONFIG_EVB64260_750CX 1 */ /* Support the EVB-64260-750CX Board */ + +/* which initialization functions to call for this board */ +#define CONFIG_MISC_INIT_R 1 +#define CONFIG_BOARD_PRE_INIT 1 + +#ifndef CONFIG_EVB64260_750CX +#define CFG_BOARD_NAME "EVB64260" +#else +#define CFG_BOARD_NAME "EVB64260-750CX" +#endif + +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " + +/* + * The following defines let you select what serial you want to use + * for your console driver. + * + * what to do: + * to use the DUART, undef CONFIG_MPSC. If you have hacked a serial + * cable onto the second DUART channel, change the CFG_DUART port from 1 + * to 0 below. + * + * to use the MPSC, #define CONFIG_MPSC. If you have wired up another + * mpsc channel, change CONFIG_MPSC_PORT to the desired value. + */ +#define CONFIG_MPSC +#define CONFIG_MPSC_PORT 0 + +#define CONFIG_NET_MULTI /* attempt all available adapters */ + +/* define this if you want to enable GT MAC filtering */ +#define CONFIG_GT_USE_MAC_HASH_TABLE + +#undef CONFIG_ETHER_PORT_MII /* use RMII */ + +#if 1 +#define CONFIG_BOOTDELAY -1 /* autoboot disabled */ +#else +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#endif +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND \ + "bootp && " \ + "setenv bootargs root=/dev/nfs rw nfsroot=$serverip:$rootpath " \ + "ip=$ipaddr:$serverip:$gatewayip:" \ + "$netmask:$hostname:eth0:none; && " \ + "bootm" + +#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ +#undef CONFIG_ALTIVEC /* undef to disable */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) + + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_ASKENV) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x00300000 /* default load address */ + +#define CFG_HZ 1000 /* decr freq: 1ms ticks */ +#define CFG_BUS_HZ 100000000 /* 100 MHz */ +#define CFG_BUS_CLK CFG_BUS_HZ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +#ifdef CONFIG_EVB64260_750CX +#define CONFIG_750CX +#define CFG_BROKEN_CL2 +#endif + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_RAM_LOCK + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xfff00000 +#define CFG_RESET_ADDRESS 0xfff00100 +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (256 << 10) /* Reserve 256 kB for malloc */ + +/* areas to map different things with the GT in physical space */ +#define CFG_DRAM_BANKS 4 +#define CFG_DFL_GT_REGS 0x14000000 /* boot time GT_REGS */ + +/* What to put in the bats. */ +#define CFG_MISC_REGION_BASE 0xf0000000 + +/* Peripheral Device section */ +#define CFG_GT_REGS 0xf8000000 +#define CFG_DEV_BASE 0xfc000000 + +#define CFG_DEV0_SPACE CFG_DEV_BASE +#define CFG_DEV1_SPACE (CFG_DEV0_SPACE + CFG_DEV0_SIZE) +#define CFG_DEV2_SPACE (CFG_DEV1_SPACE + CFG_DEV1_SIZE) +#define CFG_DEV3_SPACE (CFG_DEV2_SPACE + CFG_DEV2_SIZE) + +#define CFG_DEV0_SIZE _8M /* evb64260 sram @ 0xfc00.0000 */ +#define CFG_DEV1_SIZE _8M /* evb64260 rtc @ 0xfc80.0000 */ +#define CFG_DEV2_SIZE _16M /* evb64260 duart @ 0xfd00.0000 */ +#define CFG_DEV3_SIZE _16M /* evb64260 flash @ 0xfe00.0000 */ + +#define CFG_DEV0_PAR 0x20205093 +#define CFG_DEV1_PAR 0xcfcfffff +#define CFG_DEV2_PAR 0xc0059bd4 +#define CFG_8BIT_BOOT_PAR 0xc00b5e7c +#define CFG_32BIT_BOOT_PAR 0xc4a8241c + /* c 4 a 8 2 4 1 c */ + /* 33 22|2222|22 22|111 1|11 11|1 1 | | */ + /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210 */ + /* 11|00|0100|10 10|100|0 00|10 0|100 0|001 1|100 */ + /* 3| 0|.... ..| 2| 4 | 0 | 4 | 8 | 3 | 4 */ + +#if 0 /* Wrong?? NTL */ +#define CFG_MPP_CONTROL_0 0x53541717 /* InitAct EOT[4] DBurst TCEn[1] */ + /* DMAAck[1:0] GNT0[1:0] */ +#else +#define CFG_MPP_CONTROL_0 0x53547777 /* InitAct EOT[4] DBurst TCEn[1] */ + /* REQ0[1:0] GNT0[1:0] */ +#endif +#define CFG_MPP_CONTROL_1 0x44009911 /* TCEn[4] TCTcnt[4] GPP[13:12] */ + /* DMAReq[4] DMAAck[4] WDNMI WDE */ +#if 0 /* Wrong?? NTL */ +#define CFG_MPP_CONTROL_2 0x40091818 /* TCTcnt[0] GPP[22:21] BClkIn */ + /* DMAAck[1:0] GNT1[1:0] */ +#else +#define CFG_MPP_CONTROL_2 0x40098888 /* TCTcnt[0] */ + /* GPP[22] (RS232IntB or PCI1Int) */ + /* GPP[21] (RS323IntA) */ + /* BClkIn */ + /* REQ1[1:0] GNT1[1:0] */ +#endif + +#if 0 /* Wrong?? NTL */ +# define CFG_MPP_CONTROL_3 0x00090066 /* GPP[31:29] BClkOut0 */ + /* GPP[27:26] Int[1:0] */ +#else +# define CFG_MPP_CONTROL_3 0x22090066 /* MREQ MGNT */ + /* GPP[29] (PCI1Int) */ + /* BClkOut0 */ + /* GPP[27] (PCI0Int) */ + /* GPP[26] (RtcInt or PCI1Int) */ + /* CPUInt[25:24] */ +#endif + +# define CFG_SERIAL_PORT_MUX 0x00000102 /* 0=hiZ 1=MPSC0 2=ETH 0 and 2 RMII */ + +#if 0 /* Wrong?? - NTL */ +# define CFG_GPP_LEVEL_CONTROL 0x000002c6 +#else +# define CFG_GPP_LEVEL_CONTROL 0x2c600000 /* 0010 1100 0110 0000 */ + /* gpp[29] */ + /* gpp[27:26] */ + /* gpp[22:21] */ + +# define CFG_SDRAM_CONFIG 0xd8e18200 /* 0x448 */ + /* idmas use buffer 1,1 + comm use buffer 0 + pci use buffer 1,1 + cpu use buffer 0 + normal load (see also ifdef HVL) + standard SDRAM (see also ifdef REG) + non staggered refresh */ + /* 31:26 25 23 20 19 18 16 */ + /* 110110 00 111 0 0 00 1 */ + /* refresh_count=0x200 + phisical interleaving disable + virtual interleaving enable */ + /* 15 14 13:0 */ + /* 1 0 0x200 */ +#endif + +#define CFG_DUART_IO CFG_DEV2_SPACE +#define CFG_DUART_CHAN 1 /* channel to use for console */ +#define CFG_INIT_CHAN1 +#define CFG_INIT_CHAN2 + +#define SRAM_BASE CFG_DEV0_SPACE +#define SRAM_SIZE 0x00100000 /* 1 MB of sram */ + + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ + +#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 */ + +/* PCI MEMORY MAP section */ +#define CFG_PCI0_MEM_BASE 0x80000000 +#define CFG_PCI0_MEM_SIZE _128M +#define CFG_PCI1_MEM_BASE 0x88000000 +#define CFG_PCI1_MEM_SIZE _128M + +#define CFG_PCI0_0_MEM_SPACE (CFG_PCI0_MEM_BASE) +#define CFG_PCI1_0_MEM_SPACE (CFG_PCI1_MEM_BASE) + + + +/* PCI I/O MAP section */ +#define CFG_PCI0_IO_BASE 0xfa000000 +#define CFG_PCI0_IO_SIZE _16M +#define CFG_PCI1_IO_BASE 0xfb000000 +#define CFG_PCI1_IO_SIZE _16M + +#define CFG_PCI0_IO_SPACE (CFG_PCI0_IO_BASE) +#define CFG_PCI0_IO_SPACE_PCI 0x00000000 +#define CFG_PCI1_IO_SPACE (CFG_PCI1_IO_BASE) +#define CFG_PCI1_IO_SPACE_PCI 0x00000000 + +/* + * NS16550 Configuration + */ +#define CFG_NS16550 + +#define CFG_NS16550_REG_SIZE -4 + +#define CFG_NS16550_CLK 3686400 + +#define CFG_NS16550_COM1 (CFG_DUART_IO + 0) +#define CFG_NS16550_COM2 (CFG_DUART_IO + 0x20) + +/*---------------------------------------------------------------------- + * Initial BAT mappings + */ + +/* NOTES: + * 1) GUARDED and WRITE_THRU not allowed in IBATS + * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT + */ + +/* SDRAM */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT0U CFG_IBAT0U + +/* init ram */ +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_RW | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U + +/* PCI0, PCI1 in one BAT */ +#define CFG_IBAT2L BATL_NO_ACCESS +#define CFG_IBAT2U CFG_DBAT2U +#define CFG_DBAT2L (CFG_PCI0_MEM_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT2U (CFG_PCI0_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* GT regs, bootrom, all the devices, PCI I/O */ +#define CFG_IBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW) +#define CFG_IBAT3U (CFG_MISC_REGION_BASE | BATU_VS | BATU_VP | BATU_BL_256M) +#define CFG_DBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT3U CFG_IBAT3U + +/* I2C speed and slave address (for compatability) defaults */ +#define CFG_I2C_SPEED 400000 +#define CFG_I2C_SLAVE 0x7F + +/* I2C addresses for the two DIMM SPD chips */ +#ifndef CONFIG_EVB64260_750CX +#define DIMM0_I2C_ADDR 0x56 +#define DIMM1_I2C_ADDR 0x54 +#else /* CONFIG_EVB64260_750CX - only has 1 DIMM */ +#define DIMM0_I2C_ADDR 0x54 +#define DIMM1_I2C_ADDR 0x54 +#endif + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8<<20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 67 /* max number of sectors on one chip */ + +#define CFG_EXTRA_FLASH_DEVICE DEVICE3 /* extra flash at device 3 */ +#define CFG_EXTRA_FLASH_WIDTH 4 /* 32 bit */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +#define CFG_FLASH_CFI 1 + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x10000 +#define CFG_ENV_ADDR (CFG_FLASH_BASE+CFG_MONITOR_LEN-CFG_ENV_SECT_SIZE) + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For all MPC74xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * L2CR setup -- make sure this is right for your board! + * look in include/mpc74xx.h for the defines used here + */ + +#define CFG_L2 + +#ifdef CONFIG_750CX +#define L2_INIT 0 +#else +#define L2_INIT (L2CR_L2SIZ_2M | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \ + L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT) +#endif + +#define L2_ENABLE (L2_INIT | L2CR_L2E) + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#define CFG_BOARD_ASM_INIT 1 + + +#endif /* __CONFIG_H */ diff --git a/include/configs/MUSENKI.h b/include/configs/MUSENKI.h new file mode 100644 index 0000000..03765a3 --- /dev/null +++ b/include/configs/MUSENKI.h @@ -0,0 +1,297 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * + * Configuration settings for the MUSENKI board. + * + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8245 1 +#define CONFIG_MUSENKI 1 + + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 9600 +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_BOOTDELAY 5 + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ + +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#undef CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ + +/* Print Buffer Size + */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) +#define CFG_MAXARGS 8 /* Max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* Default load address */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP + +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_TULIP + +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET0_MEMADDR 0x80000000 +#define PCI_ENET1_IOADDR 0x81000000 +#define PCI_ENET1_MEMADDR 0x81000000 + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 + +#define CFG_FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank on RCS#0 */ +#define CFG_FLASH_BASE1_PRELIM 0xFF000000 /* FLASH bank on RCS#1 */ +#define CFG_FLASH_BASE CFG_FLASH_BASE0_PRELIM + +/* even though FLASHP_BASE is FF800000, with 4MB is RCS0, the + * reset vector is actually located at FFB00100, but the 8245 + * takes care of us. + */ +#define CFG_RESET_ADDRESS 0xFFF00100 + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_MONITOR_BASE TEXT_BASE +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x02000000 /* 0 ... 32 MB in DRAM */ + + /* Maximum amount of RAM. + */ +#define CFG_MAX_RAM_SIZE 0x08000000 /* 0 .. 128 MB of (S)DRAM */ + + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +#undef CFG_RAMBOOT +#else +#define CFG_RAMBOOT +#endif + +/* + * NS16550 Configuration + */ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK get_bus_freq(0) + +#define CFG_NS16550_COM1 (CFG_EUMB_ADDR + 0x4500) +#define CFG_NS16550_COM2 (CFG_EUMB_ADDR + 0x4600) + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ + +/* #define CFG_MONITOR_BASE TEXT_BASE */ +/*#define CFG_GBL_DATA_SIZE 256*/ +#define CFG_GBL_DATA_SIZE 128 +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + * For the detail description refer to the MPC8240 user's manual. + */ + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ +#define CFG_HZ 1000 + + /* Bit-field values for MCCR1. + */ +#define CFG_ROMNAL 7 +#define CFG_ROMFAL 11 +#define CFG_DBUS_SIZE 0x3 + + /* Bit-field values for MCCR2. + */ +#define CFG_TSWAIT 0x5 /* Transaction Start Wait States timer */ +#define CFG_REFINT 0x400 /* Refresh interval FIXME: was 0t430 */ + + /* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4. + */ +#define CFG_BSTOPRE 121 + + /* Bit-field values for MCCR3. + */ +#define CFG_REFREC 8 /* Refresh to activate interval */ + + /* Bit-field values for MCCR4. + */ +#define CFG_PRETOACT 3 /* Precharge to activate interval FIXME: was 2 */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval FIXME: was 5 */ +#define CFG_ACTORW 3 /* FIXME was 2 */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latancy */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_REGISTERD_TYPE_BUFFER 1 +#define CFG_EXTROM 1 +#define CFG_REGDIMM 0 + +#define CFG_PGMAX 0x32 /* how long the 8240 reatins the currently accessed page in memory FIXME: was 0x32*/ + +#define CFG_SDRAM_DSCD 0x20 /* SDRAM data in sample clock delay - note bottom 3 bits MUST be 0 */ + +/* Memory bank settings. + * Only bits 20-29 are actually used from these vales to set the + * start/end addresses. The upper two bits will always be 0, and the lower + * 20 bits will be 0x00000 for a start address, or 0xfffff for an end + * address. Refer to the MPC8240 book. + */ + +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x3ff00000 +#define CFG_BANK4_END 0x3fffffff +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x3ff00000 +#define CFG_BANK5_END 0x3fffffff +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x3ff00000 +#define CFG_BANK6_END 0x3fffffff +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x3ff00000 +#define CFG_BANK7_END 0x3fffffff +#define CFG_BANK7_ENABLE 0 + +#define CFG_ODCR 0xff + +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* Max number of flash banks */ +#define CFG_MAX_FLASH_SECT 64 /* Max number of sectors per flash */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + + + /* Warining: environment is not EMBEDDED in the U-Boot code. + * It's stored in flash separately. + */ +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_ADDR 0xFFFF0000 +#define CFG_ENV_SIZE 0x00010000 /* Size of the Environment */ +#define CFG_ENV_SECT_SIZE 0x20000 /* Size of the Environment Sector */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + + +#endif /* __CONFIG_H */ diff --git a/include/configs/MVS1.h b/include/configs/MVS1.h new file mode 100644 index 0000000..d10fa8f --- /dev/null +++ b/include/configs/MVS1.h @@ -0,0 +1,406 @@ +/* + * (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 + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC823 1 /* This is a MPC823 CPU */ +#define CONFIG_MVS 1 /* ...on a MVsensor module */ +#define CONFIG_MVS_16BIT_FLASH /* ...with 16-bit flash access */ +#define CONFIG_8xx_GCLK_FREQ 50000000/* ... and a 50 MHz CPU */ + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#undef CONFIG_8xx_CONS_SMC1 /* Console is *NOT* on SMC1 */ +#define CONFIG_8xx_CONS_SMC2 1 /* Console is on SMC2 */ +#undef CONFIG_8xx_CONS_NONE +#define CONFIG_BAUDRATE 115200 /* console baudrate */ +#define CONFIG_BOOTDELAY 5 /* autoboot after this many seconds */ + +#define CONFIG_PREBOOT "echo;echo To mount root over NFS use \"run bootnet\";echo To mount root from FLASH use \"run bootflash\";echo" +#define CONFIG_BOOTARGS "root=/dev/mtdblock2 rw" +#define CONFIG_BOOTCOMMAND \ + "bootp; " \ + "setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \ + "bootm" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#undef CFG_LOADS_BAUD_CHANGE /* don't allow baudrate change */ + +#define CONFIG_WATCHDOG /* watchdog disabled/enabled */ + +#undef CONFIG_STATUS_LED /* Status LED disabled/enabled */ + +#undef CONFIG_CAN_DRIVER /* CAN Driver support disabled */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | CONFIG_BOOTP_VENDOREX ) + +#undef CONFIG_MAC_PARTITION +#undef CONFIG_DOS_PARTITION + +#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */ + +/* MVsensor uses a really minimal U-Boot ! */ +#define CONFIG_COMMANDS (CFG_CMD_LOADS | \ + CFG_CMD_LOADB | \ + CFG_CMD_IMI | \ + CFG_CMD_FLASH | \ + CFG_CMD_MEMORY | \ + CFG_CMD_NET | \ + CFG_CMD_DHCP | \ + CFG_CMD_ENV | \ + CFG_CMD_BOOTD | \ + CFG_CMD_RUN ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#undef CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#undef CFG_HUSH_PARSER /* Hush parse for U-Boot ?? */ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ +/*----------------------------------------------------------------------- + * Internal Memory Mapped Register + */ +#define CFG_IMMR 0xFFF00000 + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ +#define CFG_INIT_RAM_ADDR CFG_IMMR +#define CFG_INIT_RAM_END 0x2F00 /* End of used area in DPRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0x40000000 + +#define CFG_MONITOR_LEN (128 << 10) /* Reserve 192 kB for Monitor */ + +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 71 /* max number of sectors on one chip (for AMD320DB chip) */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_ENV_IS_IN_FLASH 1 + +/* 4MB flash - use bottom sectors of a bottom boot sector flash (16 bit access) */ +#define CFG_ENV_OFFSET 0x8000 /* Offset of Environment Sector (bottom boot sector) */ +#define CFG_ENV_SIZE 0x2000 /* Used Size of Environment Sector 8k */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 16 /* For all MPC8xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 4 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * SYPCR - System Protection Control 11-9 + * SYPCR can only be written once after reset! + *----------------------------------------------------------------------- + * Software & Bus Monitor Timer max, Bus Monitor enable, SW Watchdog freeze + */ +#if defined(CONFIG_WATCHDOG) +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | \ + SYPCR_SWE | SYPCR_SWRI| SYPCR_SWP) +#else +#define CFG_SYPCR (SYPCR_SWTC | SYPCR_BMT | SYPCR_BME | SYPCR_SWF | SYPCR_SWP) +#endif + +/*----------------------------------------------------------------------- + * SIUMCR - SIU Module Configuration 11-6 + *----------------------------------------------------------------------- + * PCMCIA config., multi-function pin tri-state + */ +#define CFG_SIUMCR (SIUMCR_DBGC00 | SIUMCR_DBPC00 | SIUMCR_MLRC01) + +/*----------------------------------------------------------------------- + * TBSCR - Time Base Status and Control 11-26 + *----------------------------------------------------------------------- + * Clear Reference Interrupt Status, Timebase freezing enabled + */ +#define CFG_TBSCR (TBSCR_REFA | TBSCR_REFB | TBSCR_TBF) + +/*----------------------------------------------------------------------- + * RTCSC - Real-Time Clock Status and Control Register 11-27 + *----------------------------------------------------------------------- + */ +#define CFG_RTCSC (RTCSC_SEC | RTCSC_ALR | RTCSC_RTF| RTCSC_RTE) + +/*----------------------------------------------------------------------- + * PISCR - Periodic Interrupt Status and Control 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 15-30 + *----------------------------------------------------------------------- + * Reset PLL lock status sticky bit, timer expired status bit and timer + * interrupt status bit + * + */ +#define CFG_PLPRCR (PLPRCR_SPLSS | PLPRCR_TEXPS | PLPRCR_TMIST) + +/*----------------------------------------------------------------------- + * SCCR - System Clock and reset Control Register 15-27 + *----------------------------------------------------------------------- + * Set clock output, timebase and RTC source and divider, + * power management and some other internal clocks + */ +#define SCCR_MASK SCCR_EBDF11 +#define CFG_SCCR (SCCR_TBS | \ + SCCR_COM00 | SCCR_DFSYNC00 | SCCR_DFBRG00 | \ + SCCR_DFNL000 | SCCR_DFNH000 | SCCR_DFLCD000 | \ + SCCR_DFALCD00) + +/*----------------------------------------------------------------------- + * PCMCIA stuff + *----------------------------------------------------------------------- + * + */ +#define CFG_PCMCIA_MEM_ADDR (0xE0000000) +#define CFG_PCMCIA_MEM_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_DMA_ADDR (0xE4000000) +#define CFG_PCMCIA_DMA_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_ATTRB_ADDR (0xE8000000) +#define CFG_PCMCIA_ATTRB_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_IO_ADDR (0xEC000000) +#define CFG_PCMCIA_IO_SIZE ( 64 << 20 ) + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#define CONFIG_IDE_PCCARD 0 /* **DON'T** Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_PCMCIA /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 0 /* max. no. of IDE buses */ +#define CFG_IDE_MAXDEVICE 0 /* max. no. of drives per IDE bus */ + + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +#define CFG_ATA_BASE_ADDR CFG_PCMCIA_MEM_ADDR + +/* Offset for data I/O */ +#define CFG_ATA_DATA_OFFSET (CFG_PCMCIA_MEM_SIZE + 0x320) + +/* Offset for normal register accesses */ +#define CFG_ATA_REG_OFFSET (2 * CFG_PCMCIA_MEM_SIZE + 0x320) + +/* Offset for alternate registers */ +#define CFG_ATA_ALT_OFFSET 0x0100 + +/*----------------------------------------------------------------------- + * + *----------------------------------------------------------------------- + * + */ +/*#define CFG_DER 0x2002000F*/ +#define CFG_DER 0 + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0x40000000 /* FLASH bank #0 */ +#undef FLASH_BASE1_PRELIM + +/* used to re-map FLASH both when starting from SRAM or FLASH: + * restrict access enough to keep SRAM working (if any) + * but not too much to meddle with FLASH accesses + */ +#define CFG_REMAP_OR_AM 0x80000000 /* OR addr mask */ +#define CFG_PRELIM_OR_AM 0xE0000000 /* OR addr mask */ + + +/* + * FLASH timing: + */ +/* 50 MHz CPU - 50 MHz bus: ACS = 00, TRLX = 1, CSNT = 1, SCY = 2, EHTR = 1 */ +#define CFG_OR_TIMING_FLASH (OR_ACS_DIV1 | OR_TRLX | OR_CSNT_SAM | \ + OR_SCY_2_CLK | OR_EHTR | OR_BI) +/* FLASH timing: ACS = 11, TRLX = 0, CSNT = 1, SCY = 5, EHTR = 1 */ +/* +#define CFG_OR_TIMING_FLASH (OR_CSNT_SAM | OR_ACS_DIV2 | OR_BI | \ + OR_SCY_5_CLK | OR_EHTR) +*/ + +#define CFG_OR0_REMAP (CFG_REMAP_OR_AM | CFG_OR_TIMING_FLASH) +#define CFG_OR0_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_FLASH) +#ifdef CONFIG_MVS_16BIT_FLASH +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_PS_16 | BR_V ) +#else +#define CFG_BR0_PRELIM ((FLASH_BASE0_PRELIM & BR_BA_MSK) | BR_PS_32 | BR_V ) +#endif + +#undef CFG_OR1_REMAP +#undef CFG_OR1_PRELIM +#undef CFG_BR1_PRELIM +/* + * BR2/3 and OR2/3 (SDRAM) + * + */ +#define SDRAM_BASE2_PRELIM 0x00000000 /* SDRAM bank #0 */ +#undef SDRAM_BASE3_PRELIM +#define SDRAM_MAX_SIZE 0x04000000 /* max 64 MB per bank */ + +/* SDRAM timing: Multiplexed addresses, GPL5 output to GPL5_A (don't care) */ +#define CFG_OR_TIMING_SDRAM 0x00000A00 + +#define CFG_OR2_PRELIM (CFG_PRELIM_OR_AM | CFG_OR_TIMING_SDRAM ) +#define CFG_BR2_PRELIM ((SDRAM_BASE2_PRELIM & BR_BA_MSK) | BR_MS_UPMA | BR_V ) + +#undef CFG_OR3_PRELIM +#undef CFG_BR3_PRELIM + + +/* + * Memory Periodic Timer Prescaler + * + * The Divider for PTA (refresh timer) configuration is based on an + * example SDRAM configuration (64 MBit, one bank). The adjustment to + * the number of chip selects (NCS) and the actually needed refresh + * rate is done by setting MPTPR. + * + * PTA is calculated from + * PTA = (gclk * Trefresh) / ((2 ^ (2 * DFBRG)) * PTP * NCS) + * + * gclk CPU clock (not bus clock!) + * Trefresh Refresh cycle * 4 (four word bursts used) + * + * 4096 Rows from SDRAM example configuration + * 1000 factor s -> ms + * 32 PTP (pre-divider from MPTPR) from SDRAM example configuration + * 4 Number of refresh cycles per period + * 64 Refresh cycle in ms per number of rows + * -------------------------------------------- + * Divider = 4096 * 32 * 1000 / (4 * 64) = 512000 + * + * 50 MHz => 50.000.000 / Divider = 98 + * 66 Mhz => 66.000.000 / Divider = 129 + * 80 Mhz => 80.000.000 / Divider = 156 + */ +#define CFG_MAMR_PTA 98 + +/* refresh rate 15.6 us (= 64 ms / 4K = 62.4 / quad bursts) for <= 128 MBit */ +#define CFG_MPTPR_2BK_4K MPTPR_PTP_DIV16 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_4K MPTPR_PTP_DIV32 /* setting for 1 bank */ + +/* refresh rate 7.8 us (= 64 ms / 8K = 31.2 / quad bursts) for 256 MBit */ +#define CFG_MPTPR_2BK_8K MPTPR_PTP_DIV8 /* setting for 2 banks */ +#define CFG_MPTPR_1BK_8K MPTPR_PTP_DIV16 /* setting for 1 bank */ + +/* + * MAMR settings for SDRAM + */ + +/* 8 column SDRAM */ +#define CFG_MAMR_8COL ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_0 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A11 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) +/* 9 column SDRAM */ +#define CFG_MAMR_9COL ((CFG_MAMR_PTA << MAMR_PTA_SHIFT) | MAMR_PTAE | \ + MAMR_AMA_TYPE_1 | MAMR_DSA_1_CYCL | MAMR_G0CLA_A7 | \ + MAMR_RLFA_1X | MAMR_WLFA_1X | MAMR_TLFA_4X) + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/OCRTC.h b/include/configs/OCRTC.h new file mode 100644 index 0000000..5971fb4 --- /dev/null +++ b/include/configs/OCRTC.h @@ -0,0 +1,298 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_OCRTC 1 /* ...on a OCRTC board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND "go fff00100" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_ASKENV | \ + CFG_CMD_ELF | \ + CFG_CMD_EEPROM ) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_IGNORE_405_UART_ERRATA_59 /* ignore ppc405gp errata #59 */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define PCI_HOST_ADAPTER 0 /* configure as 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_AUTO /* select pci host function */ +#define CONFIG_PCI_PNP /* do pci plug-and-play */ + /* resource configuration */ + +#define CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0410 /* PCI Device ID: OCRTC */ +#define CFG_PCI_CLASSCODE 0x0b20 /* PCI Class Code: Processor/PPC*/ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xfc000001 /* 64MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffc00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffc00001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFD0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 192 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#if 0 /* Use NVRAM for environment variables */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */ +#define CFG_NVRAM_BASE_ADDR 0xf0200000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE (32*1024) /* NVRAM size */ +#define CFG_ENV_SIZE 0x1000 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE) /* Env */ +#define CFG_NVRAM_VXWORKS_OFFS 0x6900 /* Offset for VxWorks eth-addr */ + +#else /* Use EEPROM for environment variables */ + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x300 /* 768 bytes may be used for env vars */ + /* total size of a CAT24WC08 is 1024 bytes */ +#endif + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC08) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFC00000 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Flash Bank 1) initialization */ +#define CFG_EBC_PB1AP 0x92015480 +#define CFG_EBC_PB1CR 0xFF85A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (PLD - FPGA-boot) initialization */ +#define CFG_EBC_PB2AP 0x02015480 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB2CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (PLD - OSL) initialization */ +#define CFG_EBC_PB3AP 0x02015480 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB3CR 0xF0118000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 4 (Spartan2 1) initialization */ +#define CFG_EBC_PB4AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB4CR 0xF209C000 /* BAS=0xF20,BS=16MB,BU=R/W,BW=32bit*/ + +/* Memory Bank 5 (Spartan2 2) initialization */ +#define CFG_EBC_PB5AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB5CR 0xF309C000 /* BAS=0xF30,BS=16MB,BU=R/W,BW=32bit*/ + +/* Memory Bank 6 (Virtex 1) initialization */ +#define CFG_EBC_PB6AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB6CR 0xF409A000 /* BAS=0xF40,BS=16MB,BU=R/W,BW=16bit*/ + +/* Memory Bank 7 (Virtex 2) initialization */ +#define CFG_EBC_PB7AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB7CR 0xF509A000 /* BAS=0xF50,BS=16MB,BU=R/W,BW=16bit*/ + + +#define CFG_ETHERNET_MAC_ADDR 0x00000000 /* Pass Ethernet MAC to VxWorks */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + +/* use on chip memory ( OCM ) for temperary stack until sdram is tested */ +#define CFG_TEMP_STACK_OCM 1 + +/* On Chip Memory location */ +#define CFG_OCM_DATA_ADDR 0xF8000000 +#define CFG_OCM_DATA_SIZE 0x1000 + +#define CFG_INIT_RAM_ADDR CFG_OCM_DATA_ADDR /* inside of SDRAM */ +#define CFG_INIT_RAM_END CFG_OCM_DATA_SIZE /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/ORSG.h b/include/configs/ORSG.h new file mode 100644 index 0000000..7c161c6 --- /dev/null +++ b/include/configs/ORSG.h @@ -0,0 +1,298 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_ORSG 1 /* ...on a ORSG board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#undef CONFIG_BOOTARGS +#define CONFIG_BOOTCOMMAND "go fff00100" + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_ASKENV | \ + CFG_CMD_ELF | \ + CFG_CMD_EEPROM ) + +#define CONFIG_MAC_PARTITION +#define CONFIG_DOS_PARTITION + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_IGNORE_405_UART_ERRATA_59 /* ignore ppc405gp errata #59 */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define PCI_HOST_ADAPTER 0 /* configure as 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_ADAPTER /* select pci adapter */ +#undef CONFIG_PCI_PNP /* no pci plug-and-play */ + /* resource configuration */ + +#undef CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0411 /* PCI Device ID: ORSG */ +#define CFG_PCI_CLASSCODE 0x0b20 /* PCI Class Code: Processor/PPC*/ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xfc000001 /* 64MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ +#define CFG_PCI_PTM2LA 0xffc00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffc00001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFD0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 192 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#if 0 /* Use NVRAM for environment variables */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */ +#define CFG_NVRAM_BASE_ADDR 0xf0200000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE (32*1024) /* NVRAM size */ +#define CFG_ENV_SIZE 0x1000 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-CFG_ENV_SIZE) /* Env */ +#define CFG_NVRAM_VXWORKS_OFFS 0x6900 /* Offset for VxWorks eth-addr */ + +#else /* Use EEPROM for environment variables */ + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x300 /* 768 bytes may be used for env vars */ + /* total size of a CAT24WC08 is 1024 bytes */ +#endif + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC08) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFF800000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0xFFC00000 /* FLASH bank #1 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (Flash Bank 1) initialization */ +#define CFG_EBC_PB1AP 0x92015480 +#define CFG_EBC_PB1CR 0xFF85A000 /* BAS=0xFF8,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 2 (PLD - FPGA-boot) initialization */ +#define CFG_EBC_PB2AP 0x02015480 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB2CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (PLD - OSL) initialization */ +#define CFG_EBC_PB3AP 0x02015480 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x0,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB3CR 0xF0118000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 4 (Spartan2 1) initialization */ +#define CFG_EBC_PB4AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB4CR 0xF209C000 /* BAS=0xF20,BS=16MB,BU=R/W,BW=32bit*/ + +/* Memory Bank 5 (Spartan2 2) initialization */ +#define CFG_EBC_PB5AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB5CR 0xF309C000 /* BAS=0xF30,BS=16MB,BU=R/W,BW=32bit*/ + +/* Memory Bank 6 (Virtex 1) initialization */ +#define CFG_EBC_PB6AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB6CR 0xF409A000 /* BAS=0xF40,BS=16MB,BU=R/W,BW=16bit*/ + +/* Memory Bank 7 (Virtex 2) initialization */ +#define CFG_EBC_PB7AP 0x02015580 /* BME=0x0,TWT=0x04,CSN=0x0,OEN=0x1 */ + /* WBN=0x1,WBF=0x1,TH=0x2,RE=0x1,SOR=0x1,BEM=0x0,PEN=0x0*/ +#define CFG_EBC_PB7CR 0xF509A000 /* BAS=0xF50,BS=16MB,BU=R/W,BW=16bit*/ + + +#define CFG_ETHERNET_MAC_ADDR 0x00000000 /* Pass Ethernet MAC to VxWorks */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + +/* use on chip memory ( OCM ) for temperary stack until sdram is tested */ +#define CFG_TEMP_STACK_OCM 1 + +/* On Chip Memory location */ +#define CFG_OCM_DATA_ADDR 0xF8000000 +#define CFG_OCM_DATA_SIZE 0x1000 + +#define CFG_INIT_RAM_ADDR CFG_OCM_DATA_ADDR /* inside of SDRAM */ +#define CFG_INIT_RAM_END CFG_OCM_DATA_SIZE /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/OXC.h b/include/configs/OXC.h new file mode 100644 index 0000000..7a60e4b --- /dev/null +++ b/include/configs/OXC.h @@ -0,0 +1,312 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8240 1 +#define CONFIG_OXC 1 + +#define CONFIG_BOARD_PRE_INIT 1 /* Call board_pre_init */ + +#define CONFIG_IDENT_STRING " [oxc] " + +#define CONFIG_WATCHDOG 1 +#define CONFIG_SHOW_ACTIVITY 1 +#define CONFIG_SHOW_BOOT_PROGRESS 1 + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 9600 +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | CFG_CMD_ELF) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP 1 /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() on init */ + +/*----------------------------------------------------------------------- + * Boot options + */ + +#define CONFIG_SERVERIP 10.0.0.1 +#define CONFIG_GATEWAYIP 10.0.0.1 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_LOADADDR 0x10000 +#define CONFIG_BOOTFILE "/mnt/ide0/p2/usr/tftp/oxc.elf" +#define CONFIG_BOOTCOMMAND "tftp 0x10000 ; bootelf 0x10000" +#define CONFIG_BOOTDELAY 10 + +#define CFG_OXC_GENERATE_IP 1 /* Generate IP automatically */ +#define CFG_OXC_IPMASK 0x0A000000 /* 10.0.0.x */ + +/*----------------------------------------------------------------------- + * PCI stuff + */ + +#define CONFIG_PCI /* include pci support */ + +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_EEPRO100 /* Ethernet Express PRO 100 */ + +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET0_MEMADDR 0x80000000 +#define PCI_ENET1_IOADDR 0x81000000 +#define PCI_ENET1_MEMADDR 0x81000000 + +/*----------------------------------------------------------------------- + * FLASH + */ + +#define CFG_FLASH_PRELIMBASE 0xFF800000 +#define CFG_FLASH_BASE (0-flash_info[0].size) + +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 32 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/*----------------------------------------------------------------------- + * RAM + */ + +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 + +#define CFG_RESET_ADDRESS 0xFFF00100 + +#define CFG_MONITOR_BASE TEXT_BASE +#define CFG_MONITOR_LEN 0x00030000 + +#if (CFG_MONITOR_BASE < CFG_FLASH_PRELIMBASE) +# define CFG_RAMBOOT 1 +#else +# undef CFG_RAMBOOT +#endif + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 + +#define CFG_GBL_DATA_SIZE 128 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x04000000 /* 0 ... 32 MB in DRAM */ + +/*----------------------------------------------------------------------- + * Memory mapping + */ + +#define CFG_CPLD_BASE 0xff000000 /* CPLD registers */ +#define CFG_CPLD_WATCHDOG (CFG_CPLD_BASE) /* Watchdog */ +#define CFG_CPLD_RESET (CFG_CPLD_BASE + 0x040000) /* Minor resets */ +#define CFG_UART_BASE (CFG_CPLD_BASE + 0x700000) /* debug UART */ + +/*----------------------------------------------------------------------- + * NS16550 Configuration + */ + +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE -4 +#define CFG_NS16550_CLK 1843200 +#define CFG_NS16550_COM1 CFG_UART_BASE + +/*----------------------------------------------------------------------- + * I2C Bus + */ + +#define CONFIG_I2C 1 /* I2C support on ... */ +#define CONFIG_HARD_I2C 1 /* ... hardware one */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F /* I2C slave address */ + +#define CFG_I2C_EXPANDER0_ADDR 0x20 /* PCF8574 expander 0 addrerr */ +#define CFG_I2C_EXPANDER1_ADDR 0x21 /* PCF8574 expander 1 addrerr */ +#define CFG_I2C_EXPANDER2_ADDR 0x26 /* PCF8574 expander 2 addrerr */ + +/*----------------------------------------------------------------------- + * Environment + */ + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_ADDR 0xFFF30000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x00010000 /* Total Size of Environment Sector */ +#define CONFIG_ENV_OVERWRITE 1 /* Allow modifying the environment */ + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ +#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER 2 + +#define CFG_EUMB_ADDR 0xFC000000 + +/* MCCR1 */ +#define CFG_ROMNAL 0 /* rom/flash next access time */ +#define CFG_ROMFAL 19 /* rom/flash access time */ + +/* MCCR2 */ +#define CFG_ASRISE 15 /* ASRISE=15 clocks */ +#define CFG_ASFALL 3 /* ASFALL=3 clocks */ +#define CFG_REFINT 1000 /* REFINT=1000 clocks */ + +/* MCCR3 */ +#define CFG_BSTOPRE 0x35c /* Burst To Precharge */ +#define CFG_REFREC 7 /* Refresh to activate interval */ +#define CFG_RDLAT 4 /* data latency from read command */ + +/* MCCR4 */ +#define CFG_PRETOACT 2 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_ACTORW 2 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latency */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 3 /* SDMODE Burst length 2=4, 3=8 */ +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* memory bank settings*/ +/* + * only bits 20-29 are actually used from these vales to set the + * start/end address the upper two bits will be 0, and the lower 20 + * bits will be set to 0x00000 for a start address, or 0xfffff for an + * end address + */ +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x00000000 +#define CFG_BANK1_END 0x00000000 +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x00000000 +#define CFG_BANK2_END 0x00000000 +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x00000000 +#define CFG_BANK3_END 0x00000000 +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x00000000 +#define CFG_BANK4_END 0x00000000 +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x00000000 +#define CFG_BANK5_END 0x00000000 +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x00000000 +#define CFG_BANK6_END 0x00000000 +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x00000000 +#define CFG_BANK7_END 0x00000000 +#define CFG_BANK7_ENABLE 0 +/* + * Memory bank enable bitmask, specifying which of the banks defined above + are actually present. MSB is for bank #7, LSB is for bank #0. + */ +#define CFG_BANK_ENABLE 0x01 + +#define CFG_ODCR 0xff /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/* SDRAM 0 - 256MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* stack in DCACHE @ 1GB (no backing mem) */ +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +/* PCI memory */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Flash, config addrs, etc */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For MPC8240 CPU */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/PCI405.h b/include/configs/PCI405.h new file mode 100644 index 0000000..3f9b8d4 --- /dev/null +++ b/include/configs/PCI405.h @@ -0,0 +1,343 @@ +/* + * (C) Copyright 2001 + * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.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.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_PCI405 1 /* ...on a PCI405 board */ + +#define CONFIG_BOARD_PRE_INIT 1 /* call board_pre_init() */ +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() on init */ + +#define CONFIG_SYS_CLK_FREQ 25000000 /* external frequency to pll */ + +#define CONFIG_BAUDRATE 9600 +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#if 0 +#define CONFIG_PREBOOT \ + "crc32 f0207004 ffc 0;" \ + "if cmp 0 f0207000 1;" \ + "then;echo Old CRC is correct;crc32 f0207004 ff4 f0207000;" \ + "else;echo Old CRC is bad;fi" +#endif + +#undef CONFIG_BOOTARGS +#if 1 +#define CONFIG_BOOTCOMMAND \ + "bootm fffc0000" +#else +#define CONFIG_BOOTCOMMAND \ + "mw.l 0 ffffffff; mw.l 4 ffffffff;" \ + "while cmp 0 4 1; do echo Waiting for Host...;done;" \ + "bootm 400000" +#endif + +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 0 /* PHY address */ + +#define CONFIG_RTC_M48T35A 1 /* ST Electronics M48 timekeeper */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_PCI | \ + CFG_CMD_IRQ | \ + CFG_CMD_ELF | \ + CFG_CMD_DATE | \ + CFG_CMD_I2C | \ + CFG_CMD_EEPROM ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +#define CONFIG_SDRAM_BANK0 1 /* init onboard SDRAM bank 0 */ + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ + +#define CFG_HUSH_PARSER /* use "hush" command parser */ +#ifdef CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_DEVICE_NULLDEV 1 /* include nulldev device */ + +#define CFG_CONSOLE_INFO_QUIET 1 /* don't print console @ startup*/ + +#define CFG_MEMTEST_START 0x0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 4 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_IGNORE_405_UART_ERRATA_59 /* ignore ppc405gp errata #59 */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x100000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check for keypress on bootdelay==0 */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define PCI_HOST_ADAPTER 0 /* configure as 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_ADAPTER /* select pci host function */ +#undef CONFIG_PCI_PNP /* no pci plug-and-play */ + /* resource configuration */ + +#define CONFIG_PCI_SCAN_SHOW /* print pci devices @ startup */ + +#define CFG_PCI_SUBSYS_VENDORID 0x12FE /* PCI Vendor ID: esd gmbh */ +#define CFG_PCI_SUBSYS_DEVICEID 0x0407 /* PCI Device ID: PCI-405 */ +#define CFG_PCI_CLASSCODE 0x0280 /* PCI Class Code: Network/Other*/ +#define CFG_PCI_PTM1LA 0x00000000 /* point to sdram */ +#define CFG_PCI_PTM1MS 0xfc000001 /* 64MB, enable hard-wired to 1 */ +#define CFG_PCI_PTM1PCI 0x00000000 /* Host: use this pci address */ + +#if 0 /* test-only */ +#define CFG_PCI_PTM2LA 0xffc00000 /* point to flash */ +#define CFG_PCI_PTM2MS 0xffc00001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ +#else +#define CFG_PCI_PTM2LA 0xef600000 /* point to internal regs */ +#define CFG_PCI_PTM2MS 0xef600001 /* 4MB, enable */ +#define CFG_PCI_PTM2PCI 0x04000000 /* Host: use this pci address */ +#endif + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFFD0000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (192 * 1024) /* Reserve 196 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +#define CFG_FLASH_WORD_SIZE unsigned short /* flash word size (width) */ +#define CFG_FLASH_ADDR0 0x5555 /* 1st address for flash config cycles */ +#define CFG_FLASH_ADDR1 0x2AAA /* 2nd address for flash config cycles */ +/* + * The following defines are added for buggy IOP480 byte interface. + * All other boards should use the standard values (CPCI405 etc.) + */ +#define CFG_FLASH_READ0 0x0000 /* 0 is standard */ +#define CFG_FLASH_READ1 0x0001 /* 1 is standard */ +#define CFG_FLASH_READ2 0x0002 /* 2 is standard */ + +#define CFG_FLASH_EMPTY_INFO /* print 'E' for empty sector on flinfo */ + +#if 0 /* Use NVRAM for environment variables */ +/*----------------------------------------------------------------------- + * NVRAM organization + */ +#define CFG_ENV_IS_IN_NVRAM 1 /* use NVRAM for environment vars */ +#define CFG_ENV_SIZE 0x0ff8 /* Size of Environment vars */ +#define CFG_ENV_ADDR \ + (CFG_NVRAM_BASE_ADDR+CFG_NVRAM_SIZE-(CFG_ENV_SIZE+8)) /* Env */ + +#else /* Use EEPROM for environment variables */ + +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x400 /* 1024 bytes may be used for env vars*/ + /* total size of a CAT24WC08 is 1024 bytes */ +#endif + +#define CFG_NVRAM_BASE_ADDR 0xf0200000 /* NVRAM base address */ +#define CFG_NVRAM_SIZE (32*1024) /* NVRAM size */ + +/*----------------------------------------------------------------------- + * I2C EEPROM (CAT24WC16) for environment + */ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x50 /* EEPROM CAT28WC08 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +/* mask of address bits that overflow into the "EEPROM chip address" */ +#define CFG_I2C_EEPROM_ADDR_OVERFLOW 0x07 +#define CFG_EEPROM_PAGE_WRITE_BITS 4 /* The Catalyst CAT24WC08 has */ + /* 16 byte page write mode using*/ + /* last 4 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + * + * BR0/1 and OR0/1 (FLASH) + */ + +#define FLASH_BASE0_PRELIM 0xFFE00000 /* FLASH bank #0 */ + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + */ + +/* Memory Bank 0 (Flash Bank 0) initialization */ +#define CFG_EBC_PB0AP 0x92015480 +#define CFG_EBC_PB0CR 0xFFC5A000 /* BAS=0xFFC,BS=4MB,BU=R/W,BW=16bit */ + +/* Memory Bank 1 (NVRAM/RTC) initialization */ +#define CFG_EBC_PB1AP 0x01005280 /* TWT=2,WBN=1,WBF=1,TH=1,SOR=1 */ +#define CFG_EBC_PB1CR 0xF0218000 /* BAS=0xF02,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 2 (CAN0, 1) initialization */ +#define CFG_EBC_PB2AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB2CR 0xF0018000 /* BAS=0xF00,BS=1MB,BU=R/W,BW=8bit */ + +/* Memory Bank 3 (FPGA internal) initialization */ +#define CFG_EBC_PB3AP 0x010053C0 /* BWT=2,WBN=1,WBF=1,TH=1,RE=1,SOR=1,BEM=1 */ +#define CFG_EBC_PB3CR 0xF041C000 /* BAS=0xF01,BS=1MB,BU=R/W,BW=32bit */ +#define CFG_FPGA_BASE_ADDR 0xF0400000 + +/*----------------------------------------------------------------------- + * FPGA stuff + */ +/* FPGA internal regs */ +#define CFG_FPGA_MODE 0x00 +#define CFG_FPGA_STATUS 0x02 +#define CFG_FPGA_TS 0x04 +#define CFG_FPGA_TS_LOW 0x06 +#define CFG_FPGA_TS_CAP0 0x10 +#define CFG_FPGA_TS_CAP0_LOW 0x12 +#define CFG_FPGA_TS_CAP1 0x14 +#define CFG_FPGA_TS_CAP1_LOW 0x16 +#define CFG_FPGA_TS_CAP2 0x18 +#define CFG_FPGA_TS_CAP2_LOW 0x1a +#define CFG_FPGA_TS_CAP3 0x1c +#define CFG_FPGA_TS_CAP3_LOW 0x1e + +/* FPGA Mode Reg */ +#define CFG_FPGA_MODE_CF_RESET 0x0001 +#define CFG_FPGA_MODE_TS_IRQ_ENABLE 0x0100 +#define CFG_FPGA_MODE_TS_IRQ_CLEAR 0x1000 +#define CFG_FPGA_MODE_TS_CLEAR 0x2000 + +/* FPGA Status Reg */ +#define CFG_FPGA_STATUS_DIP0 0x0001 +#define CFG_FPGA_STATUS_DIP1 0x0002 +#define CFG_FPGA_STATUS_DIP2 0x0004 +#define CFG_FPGA_STATUS_FLASH 0x0008 +#define CFG_FPGA_STATUS_TS_IRQ 0x1000 + +#define CFG_FPGA_SPARTAN2 1 /* using Xilinx Spartan 2 now */ +#define CFG_FPGA_MAX_SIZE 32*1024 /* 32kByte is enough for XC2S15 */ + +/* FPGA program pin configuration */ +#define CFG_FPGA_PRG 0x04000000 /* FPGA program pin (ppc output) */ +#define CFG_FPGA_CLK 0x02000000 /* FPGA clk pin (ppc output) */ +#define CFG_FPGA_DATA 0x01000000 /* FPGA data pin (ppc output) */ +#define CFG_FPGA_INIT 0x00400000 /* FPGA init pin (ppc input) */ +#define CFG_FPGA_DONE 0x00800000 /* FPGA done pin (ppc input) */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in data cache) + */ +#if 1 /* test-only */ +#define CFG_INIT_DCACHE_CS 7 /* use cs # 7 for data cache memory */ + +#define CFG_INIT_RAM_ADDR 0x40000000 /* use data cache */ +#else +#define CFG_INIT_RAM_ADDR 0x00df0000 /* inside of SDRAM */ +#endif +#define CFG_INIT_RAM_END 0x2000 /* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/PIP405.h b/include/configs/PIP405.h new file mode 100644 index 0000000..a5fc8d9 --- /dev/null +++ b/include/configs/PIP405.h @@ -0,0 +1,374 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/*********************************************************** + * High Level Configuration Options + * (easy to change) + ***********************************************************/ +#define CONFIG_405GP 1 /* This is a PPC405 CPU */ +#define CONFIG_4xx 1 /* ...member of PPC4xx family */ +#define CONFIG_PIP405 1 /* ...on a PIP405 board */ +/*********************************************************** + * Clock + ***********************************************************/ +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ + +/*********************************************************** + * Command definitions + ***********************************************************/ +#define CONFIG_COMMANDS \ + (CONFIG_CMD_DFL | \ + CFG_CMD_IDE | \ + CFG_CMD_DHCP | \ + CFG_CMD_PCI | \ + CFG_CMD_CACHE | \ + CFG_CMD_IRQ | \ + CFG_CMD_EEPROM | \ + CFG_CMD_I2C | \ + CFG_CMD_REGINFO | \ + CFG_CMD_FDC | \ + CFG_CMD_SCSI | \ + CFG_CMD_DATE | \ + CFG_CMD_ELF | \ + CFG_CMD_USB | \ + CFG_CMD_MII | \ + CFG_CMD_SDRAM | \ + CFG_CMD_DOC | \ + CFG_CMD_SAVES | \ + CFG_CMD_BSP ) +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " +/************************************************************** + * I2C Stuff: + * the PIP405 is equiped with an Atmel 24C128/256 EEPROM at address + * 0x53. + * Caution: on the same bus is the SPD (Serial Presens Detect + * EEPROM of the SDRAM + * The Atmel EEPROM uses 16Bit addressing. + ***************************************************************/ +#define CONFIG_HARD_I2C /* I2c with hardware support */ +#define CFG_I2C_SPEED 50000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#define CFG_I2C_EEPROM_ADDR 0x53 +#define CFG_I2C_EEPROM_ADDR_LEN 2 +#define CFG_ENV_IS_IN_EEPROM 1 /* use EEPROM for environment vars */ +#define CFG_ENV_OFFSET 0x000 /* environment starts at the beginning of the EEPROM */ +#define CFG_ENV_SIZE 0x800 /* 2 kBytes may be used for env vars */ + +#undef CFG_I2C_EEPROM_ADDR_OVERFLOW +#define CFG_EEPROM_PAGE_WRITE_BITS 6 /* The Atmel 24C128/256 has */ + /* 64 byte page write mode using*/ + /* last 6 bits of the address */ +#define CFG_EEPROM_PAGE_WRITE_ENABLE /* enable Page write */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ + + +/*************************************************************** + * Definitions for Serial Presence Detect EEPROM address + * (to get SDRAM settings) + ***************************************************************/ +#define SPD_EEPROM_ADDRESS 0x50 + +#define CONFIG_BOARD_PRE_INIT +/************************************************************** + * Environment definitions + **************************************************************/ +#define CONFIG_BAUDRATE 9600 /* STD Baudrate */ + + +#define CONFIG_BOOTDELAY 5 +/* autoboot (do NOT change this set environment variable "bootdelay" to -1 instead) */ +#define CONFIG_BOOT_RETRY_TIME -10 /* feature is avaiable but not enabled */ +#define CONFIG_ZERO_BOOTDELAY_CHECK /* check console even if bootdelay = 0 */ + + +#define CONFIG_BOOTCOMMAND "diskboot 200000 0:1; bootm" /* autoboot command */ +#define CONFIG_BOOTARGS "console=ttyS0,9600 root=/dev/hda5" /* boot arguments */ + +#define CONFIG_IPADDR 10.0.0.100 +#define CONFIG_SERVERIP 10.0.0.1 +#define CONFIG_PREBOOT +/*************************************************************** + * defines if the console is stored in the environment + ***************************************************************/ +#define CFG_CONSOLE_IS_IN_ENV /* stdin, stdout and stderr are in evironment */ +/*************************************************************** + * defines if an overwrite_console function exists + *************************************************************/ +#define CFG_CONSOLE_OVERWRITE_ROUTINE +#define CFG_CONSOLE_INFO_QUIET +/*************************************************************** + * defines if the overwrite_console should be stored in the + * environment + **************************************************************/ +#undef CFG_CONSOLE_ENV_OVERWRITE + +/************************************************************** + * loads config + *************************************************************/ +#define CONFIG_LOADS_ECHO 1 /* echo on for serial download */ +#define CFG_LOADS_BAUD_CHANGE 1 /* allow baudrate change */ + + +/*********************************************************** + * Miscellaneous configurable options + **********************************************************/ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0100000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0C00000 /* 1 ... 12 MB in DRAM */ + +#undef CFG_EXT_SERIAL_CLOCK /* no external serial clock used */ +#define CFG_BASE_BAUD 691200 + +/* The following table includes the supported baudrates */ +#define CFG_BAUDRATE_TABLE \ + { 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, \ + 57600, 115200, 230400, 460800, 921600 } + +#define CFG_LOAD_ADDR 0x200000 /* default load address */ +#define CFG_EXTBDINFO 1 /* To use extended board_into (bd_t) */ + +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#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 /* configure as pci-host */ +#define CONFIG_PCI_PNP /* 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 0x00000000 /* Host: use this pci address */ + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xFFF80000 +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MONITOR_LEN (512 * 1024) /* Reserve 512 kB for Monitor */ +#define CFG_MALLOC_LEN (128 * 1024) /* Reserve 128 kB for malloc() */ + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 256 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE 8192 /* For IBM 405 CPUs */ +#define CFG_CACHELINE_SIZE 32 /* ... */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Init Memory Controller: + */ + +#define FLASH_BASE0_PRELIM 0xFFC00000 /* FLASH bank #0 */ +#define FLASH_BASE1_PRELIM 0 /* FLASH bank #1 */ + +/* Configuration Port location */ +#define CONFIG_PORT_ADDR 0xF4000000 +#define MULTI_PURPOSE_SOCKET_ADDR 0xF8000000 + + + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in On Chip SRAM) + */ +#define CFG_TEMP_STACK_OCM 1 +#define CFG_OCM_DATA_ADDR 0xF0000000 +#define CFG_OCM_DATA_SIZE 0x1000 +#define CFG_INIT_RAM_ADDR CFG_OCM_DATA_ADDR /* inside of On Chip SRAM */ +#define CFG_INIT_RAM_END CFG_OCM_DATA_SIZE /* End of On Chip SRAM */ +#define CFG_GBL_DATA_SIZE 64 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +/*********************************************************************** + * External peripheral base address + ***********************************************************************/ +#define CFG_ISA_IO_BASE_ADDRESS 0xE8000000 + +/*********************************************************************** + * Last Stage Init + ***********************************************************************/ +#define CONFIG_LAST_STAGE_INIT +/************************************************************ + * Ethernet Stuff + ***********************************************************/ +#define CONFIG_MII 1 /* MII PHY management */ +#define CONFIG_PHY_ADDR 1 /* PHY address */ +#define CONFIG_CS8952_PHY 1 /* its a CS8952 PHY */ +/************************************************************ + * RTC + ***********************************************************/ +#define CONFIG_RTC_MC146818 +#undef CONFIG_WATCHDOG /* watchdog disabled */ + +/************************************************************ + * IDE/ATA stuff + ************************************************************/ +#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */ + +#define CFG_ATA_BASE_ADDR CFG_ISA_IO_BASE_ADDRESS /* base address */ +#define CFG_ATA_IDE0_OFFSET 0x01F0 /* ide0 offste */ +#define CFG_ATA_IDE1_OFFSET 0x0170 /* ide1 offset */ +#define CFG_ATA_DATA_OFFSET 0 /* data reg offset */ +#define CFG_ATA_REG_OFFSET 0 /* reg offset */ +#define CFG_ATA_ALT_OFFSET 0x200 /* alternate register offset */ + +#undef CONFIG_IDE_8xx_DIRECT /* no pcmcia interface required */ +#undef CONFIG_IDE_LED /* no led for ide supported */ +#define CONFIG_IDE_RESET /* reset for ide supported... */ +#define CONFIG_IDE_RESET_ROUTINE /* with a special reset function */ + +/************************************************************ + * ATAPI support (experimental) + ************************************************************/ +#define CONFIG_ATAPI /* enable ATAPI Support */ + +/************************************************************ + * SCSI support (experimental) only SYM53C8xx supported + ************************************************************/ +#define CONFIG_SCSI_SYM53C8XX +#define CFG_SCSI_MAX_LUN 8 /* number of supported LUNs */ +#define CFG_SCSI_MAX_SCSI_ID 7 /* maximum SCSI ID (0..6) */ +#define CFG_SCSI_MAX_DEVICE CFG_SCSI_MAX_SCSI_ID * CFG_SCSI_MAX_LUN /* maximum Target devices */ +#define CFG_SCSI_SPIN_UP_TIME 2 + +/************************************************************ + * Disk-On-Chip configuration + ************************************************************/ +#define CFG_MAX_DOC_DEVICE 1 /* Max number of DOC devices */ +#define CFG_DOC_SHORT_TIMEOUT +#define CFG_DOC_SUPPORT_2000 +#define CFG_DOC_SUPPORT_MILLENNIUM + +/************************************************************ + * DISK Partition support + ************************************************************/ +#define CONFIG_DOS_PARTITION +#define CONFIG_MAC_PARTITION +#define CONFIG_ISO_PARTITION /* Experimental */ + +/************************************************************ + * Keyboard support + ************************************************************/ +#define CONFIG_ISA_KEYBOARD + +/************************************************************ + * Video support + ************************************************************/ +#define CONFIG_VIDEO /*To enable video controller support */ +#define CONFIG_VIDEO_CT69000 +#define CONFIG_CFB_CONSOLE +#define CONFIG_VIDEO_LOGO +#define CONFIG_CONSOLE_EXTRA_INFO +#define CONFIG_VGA_AS_SINGLE_DEVICE +#define CONFIG_VIDEO_SW_CURSOR +#define CONFIG_VIDEO_ONBOARD /* Video controller is on-board */ + +/************************************************************ + * USB support + ************************************************************/ +#define CONFIG_USB_UHCI +#define CONFIG_USB_KEYBOARD +#define CONFIG_USB_STORAGE + +/* Enable needed helper functions */ +#define CFG_DEVICE_DEREGISTER /* needs device_deregister */ + +/************************************************************ + * Debug support + ************************************************************/ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ +#endif + +/************************************************************ + * Ident + ************************************************************/ +#define VERSION_TAG "released" +#define CONFIG_IDENT_STRING "\n(c) 2002 by MPL AG Switzerland, MEV-10066-001 " VERSION_TAG + + +#endif /* __CONFIG_H */ diff --git a/include/configs/PN62.h b/include/configs/PN62.h new file mode 100644 index 0000000..0750116 --- /dev/null +++ b/include/configs/PN62.h @@ -0,0 +1,301 @@ +/* + * (C) Copyright 2002 + * Wolfgang Grandegger, DENX Software Engineering, wg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8240 1 +#define CONFIG_PN62 1 + +#define CONFIG_CONS_INDEX 1 + + +#define REMOVE_COMMANDS ( CFG_CMD_AUTOSCRIPT | \ + CFG_CMD_LOADS | \ + CFG_CMD_ENV | \ + CFG_CMD_FLASH ) + +#define CONFIG_COMMANDS ( (CONFIG_CMD_DFL & ~REMOVE_COMMANDS) |\ + CFG_CMD_PCI |\ + CFG_CMD_BSP) + +#define CONFIG_BAUDRATE 19200 /* console baudrate */ + +#define CONFIG_BOOTDELAY 1 /* autoboot after n seconds */ + +#define CONFIG_CLOCKS_IN_MHZ 1 /* clocks passsed to Linux in MHz */ + +#define CONFIG_SERVERIP 10.0.0.201 +#define CONFIG_IPADDR 10.0.0.200 +#define CONFIG_ROOTPATH /opt/eldk/ppc_82xx +#define CONFIG_NETMASK 255.255.255.0 +#undef CONFIG_BOOTARGS +#if 0 +/* Boot Linux with NFS root filesystem */ +#define CONFIG_BOOTCOMMAND \ + "setenv verify y;" \ + "setenv bootargs console=ttyS0,19200 mem=31M quiet " \ + "root=/dev/nfs rw nfsroot=$(serverip):$(rootpath) " \ + "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \ + "loadp 100000; bootm" + /* "tftpboot 100000 pImage; bootm" */ +#else +/* Boot Linux with RAMdisk based filesystem (initrd, BusyBox) */ +#define CONFIG_BOOTCOMMAND \ + "setenv verify n;" \ + "setenv bootargs console=ttyS0,19200 mem=31M quiet " \ + "root=/dev/ram rw " \ + "ip=$(ipaddr):$(serverip)::$(netmask):pn62:eth0:off;" \ + "loadp 200000; bootm" +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP 1 /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +#define CONFIG_PRAM 1024 /* reserve 1 MB protected RAM */ + +#define CONFIG_MISC_INIT_R 1 /* call misc_init_r() on init */ + +#define CONFIG_SHOW_BOOT_PROGRESS 1 /* Show boot progress on LEDs */ + +/* + * PCI stuff + */ +#define CONFIG_PCI /* include pci support */ +#define CONFIG_PCI_PNP /* we need Plug 'n Play */ +#if 0 +#define CONFIG_PCI_SCAN_SHOW /* show PCI auto-scan at boot */ +#endif + +/* + * Networking stuff + */ +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_PCNET /* there are 2 AMD PCnet 79C973 */ +#define CONFIG_PCNET_79C973 + +#define _IO_BASE 0xfe000000 /* points to PCI I/O space */ + + +/* + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 + +#define CFG_RESET_ADDRESS 0xfff00100 + +#undef CFG_RAMBOOT +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE TEXT_BASE + +/*#define CFG_GBL_DATA_SIZE 256*/ +#define CFG_GBL_DATA_SIZE 128 + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + + +#define CFG_NO_FLASH 1 /* There is no FLASH memory */ + +#define CFG_ENV_IS_NOWHERE 1 /* Store ENV in memory only */ +#define CFG_ENV_OFFSET 0x00004000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x00002000 /* Total Size of Environment Sector */ + +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00004000 /* memtest works on */ +#define CFG_MEMTEST_END 0x01f00000 /* 0 ... 32 MB in DRAM */ + +/* + * Serial port configuration + */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK 1843200 + +#define CFG_NS16550_COM1 0xff800008 +#define CFG_NS16550_COM2 0xff800000 + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ +#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER 3 + +#define CFG_EUMB_ADDR 0xFCE00000 + +/* MCCR1 */ +#define CFG_ROMNAL 3 /* rom/flash next access time */ +#define CFG_ROMFAL 7 /* rom/flash access time */ + +/* MCCR2 */ +#define CFG_ASRISE 6 /* ASRISE in clocks */ +#define CFG_ASFALL 12 /* ASFALL in clocks */ +#define CFG_REFINT 5600 /* REFINT in clocks */ + +/* MCCR3 */ +#define CFG_BSTOPRE 0x3cf /* Burst To Precharge */ +#define CFG_REFREC 2 /* Refresh to activate interval */ +#define CFG_RDLAT 3 /* data latency from read command */ + +/* MCCR4 */ +#define CFG_PRETOACT 1 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 3 /* Activate to Precharge interval */ +#define CFG_ACTORW 2 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 2 /* SDMODE CAS latency */ +#define CFG_SDMODE_WRAP 0 /* SDMODE Wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length 2=4, 3=8 */ +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* Memory bank settings: + * + * only bits 20-29 are actually used from these vales to set the + * start/qend address the upper two bits will be 0, and the lower 20 + * bits will be set to 0x00000 for a start address, or 0xfffff for an + * end address + */ +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x00000000 +#define CFG_BANK1_END 0x00000000 +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x00000000 +#define CFG_BANK2_END 0x00000000 +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x00000000 +#define CFG_BANK3_END 0x00000000 +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x00000000 +#define CFG_BANK4_END 0x00000000 +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x00000000 +#define CFG_BANK5_END 0x00000000 +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x00000000 +#define CFG_BANK6_END 0x00000000 +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x00000000 +#define CFG_BANK7_END 0x00000000 +#define CFG_BANK7_ENABLE 0 + +/* + * Memory bank enable bitmask, specifying which of the banks defined above + * are actually present. MSB is for bank #7, LSB is for bank #0. + */ +#define CFG_BANK_ENABLE 0x01 + +#define CFG_ODCR 0xff /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/* SDRAM 0 - 256MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +/* PCI memory space */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Config addrs, etc */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/* + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For MPC8240 CPU */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +#endif /* __CONFIG_H */ diff --git a/include/configs/Sandpoint8240.h b/include/configs/Sandpoint8240.h new file mode 100644 index 0000000..0bef321 --- /dev/null +++ b/include/configs/Sandpoint8240.h @@ -0,0 +1,377 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8240 1 +#define CONFIG_SANDPOINT 1 + +#if 0 +#define USE_DINK32 1 +#else +#undef USE_DINK32 +#endif + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 115200 +#define CONFIG_DRAM_SPEED 100 /* MHz */ + +#define CONFIG_COMMANDS ( (CONFIG_CMD_DFL & ~CFG_CMD_AUTOSCRIPT) | \ + CFG_CMD_ELF | \ + CFG_CMD_I2C | \ + CFG_CMD_SDRAM | \ + CFG_CMD_EEPROM | \ + CFG_CMD_PCI ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP 1 /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP + +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_EEPRO100 + +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET0_MEMADDR 0x80000000 +#define PCI_ENET1_IOADDR 0x81000000 +#define PCI_ENET1_MEMADDR 0x81000000 + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 + +#define CFG_RESET_ADDRESS 0xFFF00100 + +#if defined (USE_DINK32) +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE 0x00090000 +#define CFG_RAMBOOT 1 +#define CFG_INIT_RAM_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#define CFG_INIT_RAM_END 0x10000 +#define CFG_GBL_DATA_SIZE 256 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET +#else +#undef CFG_RAMBOOT +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE TEXT_BASE + +/*#define CFG_GBL_DATA_SIZE 256*/ +#define CFG_GBL_DATA_SIZE 128 + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +#endif + +#define CFG_FLASH_BASE 0xFFF00000 +#if 0 +#define CFG_FLASH_SIZE (512 * 1024) /* sandpoint has tiny eeprom */ +#else +#define CFG_FLASH_SIZE (1024 * 1024) /* Unity has onboard 1MByte flash */ +#endif +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_OFFSET 0x00004000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x00002000 /* Total Size of Environment Sector */ + +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x04000000 /* 0 ... 32 MB in DRAM */ + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_ISA_MEM 0xFD000000 +#define CFG_ISA_IO 0xFE000000 + +#define CFG_FLASH_RANGE_BASE 0xFF000000 /* flash memory address range */ +#define CFG_FLASH_RANGE_SIZE 0x01000000 +#define FLASH_BASE0_PRELIM 0xFFF00000 /* sandpoint flash */ +#define FLASH_BASE1_PRELIM 0xFF000000 /* PMC onboard flash */ + +/* + * select i2c support configuration + * + * Supported configurations are {none, software, hardware} drivers. + * If the software driver is chosen, there are some additional + * configuration items that the driver uses to drive the port pins. + */ +#define CONFIG_HARD_I2C 1 /* To enable I2C support */ +#undef CONFIG_SOFT_I2C /* I2C bit-banged */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#ifdef CONFIG_SOFT_I2C +#error "Soft I2C is not configured properly. Please review!" +#define I2C_PORT 3 /* Port A=0, B=1, C=2, D=3 */ +#define I2C_ACTIVE (iop->pdir |= 0x00010000) +#define I2C_TRISTATE (iop->pdir &= ~0x00010000) +#define I2C_READ ((iop->pdat & 0x00010000) != 0) +#define I2C_SDA(bit) if(bit) iop->pdat |= 0x00010000; \ + else iop->pdat &= ~0x00010000 +#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00020000; \ + else iop->pdat &= ~0x00020000 +#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */ +#endif /* CONFIG_SOFT_I2C */ + + +#define CFG_I2C_EEPROM_ADDR 0x57 /* EEPROM IS24C02 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +#define CFG_EEPROM_PAGE_WRITE_BITS 3 /* write page size */ +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* takes up to 10 msec */ + + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } +#define CFG_FLASH_BANKS { FLASH_BASE0_PRELIM , FLASH_BASE1_PRELIM } + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + + +#define CFG_WINBOND_83C553 1 /*has a winbond bridge */ +#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal IDE ctrlr */ +#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */ +#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */ + +#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */ + +/* + * NS87308 Configuration + */ +#define CFG_NS87308 /* Nat Semi super-io controller on ISA bus */ + +#define CFG_NS87308_BADDR_10 1 + +#define CFG_NS87308_DEVS ( CFG_NS87308_UART1 | \ + CFG_NS87308_UART2 | \ + CFG_NS87308_POWRMAN | \ + CFG_NS87308_RTC_APC ) + +#undef CFG_NS87308_PS2MOD + +#define CFG_NS87308_CS0_BASE 0x0076 +#define CFG_NS87308_CS0_CONF 0x30 +#define CFG_NS87308_CS1_BASE 0x0075 +#define CFG_NS87308_CS1_CONF 0x30 +#define CFG_NS87308_CS2_BASE 0x0074 +#define CFG_NS87308_CS2_CONF 0x30 + +/* + * NS16550 Configuration + */ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK 1843200 + +#define CFG_NS16550_COM1 (CFG_ISA_IO + CFG_NS87308_UART1_BASE) +#define CFG_NS16550_COM2 (CFG_ISA_IO + CFG_NS87308_UART2_BASE) + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CONFIG_SYS_CLK_FREQ 33000000 /* external frequency to pll */ +#define CONFIG_PLL_PCI_TO_MEM_MULTIPLIER 2 + +#define CFG_ROMNAL 7 /*rom/flash next access time */ +#define CFG_ROMFAL 11 /*rom/flash access time */ + +#define CFG_REFINT 430 /* no of clock cycles between CBR refresh cycles */ + +/* the following are for SDRAM only*/ +#define CFG_BSTOPRE 121 /* Burst To Precharge, sets open page interval */ +#define CFG_REFREC 8 /* Refresh to activate interval */ +#define CFG_RDLAT 4 /* data latency from read command */ +#define CFG_PRETOACT 3 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_ACTORW 3 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latency */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#define CFG_SDMODE_BURSTLEN 2 /* SDMODE Burst length 2=4, 3=8 */ + +#define CFG_REGISTERD_TYPE_BUFFER 1 + +/* memory bank settings*/ +/* + * only bits 20-29 are actually used from these vales to set the + * start/end address the upper two bits will be 0, and the lower 20 + * bits will be set to 0x00000 for a start address, or 0xfffff for an + * end address + */ +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x00000000 +#define CFG_BANK4_END 0x00000000 +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x00000000 +#define CFG_BANK5_END 0x00000000 +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x00000000 +#define CFG_BANK6_END 0x00000000 +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x00000000 +#define CFG_BANK7_END 0x00000000 +#define CFG_BANK7_ENABLE 0 +/* + * Memory bank enable bitmask, specifying which of the banks defined above + are actually present. MSB is for bank #7, LSB is for bank #0. + */ +#define CFG_BANK_ENABLE 0x01 + +#define CFG_ODCR 0xff /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/* SDRAM 0 - 256MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* stack in DCACHE @ 1GB (no backing mem) */ +#if defined(USE_DINK32) +#define CFG_IBAT1L (0x40000000 | BATL_PP_00 ) +#define CFG_IBAT1U (0x40000000 | BATU_BL_128K ) +#else +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#endif + +/* PCI memory */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Flash, config addrs, etc */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 20 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For MPC8240 CPU */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +/* values according to the manual */ + +#define CONFIG_DRAM_50MHZ 1 +#define CONFIG_SDRAM_50MHZ + +#undef NR_8259_INTS +#define NR_8259_INTS 1 + + +#define CONFIG_DISK_SPINUP_TIME 1000000 + + +#endif /* __CONFIG_H */ diff --git a/include/configs/Sandpoint8245.h b/include/configs/Sandpoint8245.h new file mode 100644 index 0000000..aa45675 --- /dev/null +++ b/include/configs/Sandpoint8245.h @@ -0,0 +1,382 @@ +/* + * (C) Copyright 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8245 1 +#define CONFIG_SANDPOINT 1 + +#if 0 +#define USE_DINK32 1 +#else +#undef USE_DINK32 +#endif + +#define CONFIG_CONS_INDEX 3 /* set to '3' for on-chip DUART */ +#define CONFIG_BAUDRATE 9600 +#define CONFIG_DRAM_SPEED 100 /* MHz */ + +#define CONFIG_COMMANDS ( CONFIG_CMD_DFL | \ + CFG_CMD_ELF | \ + CFG_CMD_I2C | \ + CFG_CMD_EEPROM | \ + CFG_CMD_PCI ) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP 1 /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* default load address */ +#define CFG_HZ 1000 /* decrementer freq: 1 ms ticks */ + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP + +#define CONFIG_NET_MULTI /* Multi ethernet cards support */ + +#define CONFIG_EEPRO100 +#define CONFIG_NATSEMI +#define CONFIG_NS8382X + +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET0_MEMADDR 0x80000000 +#define PCI_ENET1_IOADDR 0x81000000 +#define PCI_ENET1_MEMADDR 0x81000000 + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 + +#define CFG_RESET_ADDRESS 0xFFF00100 + +#if defined (USE_DINK32) +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE 0x00090000 +#define CFG_RAMBOOT 1 +#define CFG_INIT_RAM_ADDR (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +#define CFG_INIT_RAM_END 0x10000 +#define CFG_GBL_DATA_SIZE 256 /* size in bytes reserved for initial data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_SP_OFFSET CFG_GBL_DATA_OFFSET +#else +#undef CFG_RAMBOOT +#define CFG_MONITOR_LEN 0x00030000 +#define CFG_MONITOR_BASE TEXT_BASE + +/*#define CFG_GBL_DATA_SIZE 256*/ +#define CFG_GBL_DATA_SIZE 128 + +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +#endif + +#define CFG_FLASH_BASE 0xFFF00000 +#if 0 +#define CFG_FLASH_SIZE (512 * 1024) /* sandpoint has tiny eeprom */ +#else +#define CFG_FLASH_SIZE (1024 * 1024) /* Unity has onboard 1MByte flash */ +#endif +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_OFFSET 0x00004000 /* Offset of Environment Sector */ +#define CFG_ENV_SIZE 0x00002000 /* Total Size of Environment Sector */ + +#define CFG_MALLOC_LEN (512 << 10) /* Reserve 512 kB for malloc() */ + +#define CFG_MEMTEST_START 0x00000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x04000000 /* 0 ... 32 MB in DRAM */ + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_ISA_MEM 0xFD000000 +#define CFG_ISA_IO 0xFE000000 + +#define CFG_FLASH_RANGE_BASE 0xFF000000 /* flash memory address range */ +#define CFG_FLASH_RANGE_SIZE 0x01000000 +#define FLASH_BASE0_PRELIM 0xFFF00000 /* sandpoint flash */ +#define FLASH_BASE1_PRELIM 0xFF000000 /* PMC onboard flash */ + +/* + * select i2c support configuration + * + * Supported configurations are {none, software, hardware} drivers. + * If the software driver is chosen, there are some additional + * configuration items that the driver uses to drive the port pins. + */ +#define CONFIG_HARD_I2C 1 /* To enable I2C support */ +#undef CONFIG_SOFT_I2C /* I2C bit-banged */ +#define CFG_I2C_SPEED 400000 /* I2C speed and slave address */ +#define CFG_I2C_SLAVE 0x7F + +#ifdef CONFIG_SOFT_I2C +#error "Soft I2C is not configured properly. Please review!" +#define I2C_PORT 3 /* Port A=0, B=1, C=2, D=3 */ +#define I2C_ACTIVE (iop->pdir |= 0x00010000) +#define I2C_TRISTATE (iop->pdir &= ~0x00010000) +#define I2C_READ ((iop->pdat & 0x00010000) != 0) +#define I2C_SDA(bit) if(bit) iop->pdat |= 0x00010000; \ + else iop->pdat &= ~0x00010000 +#define I2C_SCL(bit) if(bit) iop->pdat |= 0x00020000; \ + else iop->pdat &= ~0x00020000 +#define I2C_DELAY udelay(5) /* 1/4 I2C clock duration */ +#endif /* CONFIG_SOFT_I2C */ + +#define CFG_I2C_EEPROM_ADDR 0x57 /* EEPROM IS24C02 */ +#define CFG_I2C_EEPROM_ADDR_LEN 1 /* Bytes of address */ +#define CFG_EEPROM_PAGE_WRITE_BITS 3 +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 /* and takes up to 10 msec */ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } +#define CFG_FLASH_BANKS { FLASH_BASE0_PRELIM , FLASH_BASE1_PRELIM } + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area (in DPRAM) + */ + + +#define CFG_WINBOND_83C553 1 /*has a winbond bridge */ +#define CFG_USE_WINBOND_IDE 0 /*use winbond 83c553 internal IDE ctrlr */ +#define CFG_WINBOND_ISA_CFG_ADDR 0x80005800 /*pci-isa bridge config addr */ +#define CFG_WINBOND_IDE_CFG_ADDR 0x80005900 /*ide config addr */ + +#define CFG_IDE_MAXBUS 2 /* max. 2 IDE busses */ +#define CFG_IDE_MAXDEVICE (CFG_IDE_MAXBUS*2) /* max. 2 drives per IDE bus */ + +/* + * NS87308 Configuration + */ +#define CFG_NS87308 /* Nat Semi super-io controller on ISA bus */ + +#define CFG_NS87308_BADDR_10 1 + +#define CFG_NS87308_DEVS ( CFG_NS87308_UART1 | \ + CFG_NS87308_UART2 | \ + CFG_NS87308_POWRMAN | \ + CFG_NS87308_RTC_APC ) + +#undef CFG_NS87308_PS2MOD + +#define CFG_NS87308_CS0_BASE 0x0076 +#define CFG_NS87308_CS0_CONF 0x30 +#define CFG_NS87308_CS1_BASE 0x0075 +#define CFG_NS87308_CS1_CONF 0x30 +#define CFG_NS87308_CS2_BASE 0x0074 +#define CFG_NS87308_CS2_CONF 0x30 + +/* + * NS16550 Configuration + */ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK 1843200 + +#define CFG_NS16550_COM1 (CFG_ISA_IO + CFG_NS87308_UART1_BASE) +#define CFG_NS16550_COM2 (CFG_ISA_IO + CFG_NS87308_UART2_BASE) +#define CFG_NS16550_COM3 (CFG_EUMB_ADDR + 0x4500) +#define CFG_NS16550_COM4 (CFG_EUMB_ADDR + 0x4600) + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +#define CONFIG_SYS_CLK_FREQ 33333333 /* external frequency to pll */ + +#define CFG_ROMNAL 7 /*rom/flash next access time */ +#define CFG_ROMFAL 11 /*rom/flash access time */ + +#define CFG_REFINT 430 /* no of clock cycles between CBR refresh cycles */ + +/* the following are for SDRAM only*/ +#define CFG_BSTOPRE 121 /* Burst To Precharge, sets open page interval */ +#define CFG_REFREC 8 /* Refresh to activate interval */ +#define CFG_RDLAT 4 /* data latency from read command */ +#define CFG_PRETOACT 3 /* Precharge to activate interval */ +#define CFG_ACTTOPRE 5 /* Activate to Precharge interval */ +#define CFG_ACTORW 3 /* Activate to R/W */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latency */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type */ +#if 0 +#define CFG_SDMODE_BURSTLEN 2 /* OBSOLETE! SDMODE Burst length 2=4, 3=8 */ +#endif + +#define CFG_REGISTERD_TYPE_BUFFER 1 +#define CFG_EXTROM 1 +#define CFG_REGDIMM 0 + + +/* memory bank settings*/ +/* + * only bits 20-29 are actually used from these vales to set the + * start/end address the upper two bits will be 0, and the lower 20 + * bits will be set to 0x00000 for a start address, or 0xfffff for an + * end address + */ +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START 0x3ff00000 +#define CFG_BANK1_END 0x3fffffff +#define CFG_BANK1_ENABLE 0 +#define CFG_BANK2_START 0x3ff00000 +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x00000000 +#define CFG_BANK4_END 0x00000000 +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x00000000 +#define CFG_BANK5_END 0x00000000 +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x00000000 +#define CFG_BANK6_END 0x00000000 +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x00000000 +#define CFG_BANK7_END 0x00000000 +#define CFG_BANK7_ENABLE 0 +/* + * Memory bank enable bitmask, specifying which of the banks defined above + are actually present. MSB is for bank #7, LSB is for bank #0. + */ +#define CFG_BANK_ENABLE 0x01 + +#define CFG_ODCR 0xff /* configures line driver impedances, */ + /* see 8240 book for bit definitions */ +#define CFG_PGMAX 0x32 /* how long the 8240 retains the */ + /* currently accessed page in memory */ + /* see 8240 book for details */ + +/* SDRAM 0 - 256MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* stack in DCACHE @ 1GB (no backing mem) */ +#if defined(USE_DINK32) +#define CFG_IBAT1L (0x40000000 | BATL_PP_00 ) +#define CFG_IBAT1U (0x40000000 | BATU_BL_128K ) +#else +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#endif + +/* PCI memory */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Flash, config addrs, etc */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 2 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 20 /* max number of sectors on one chip */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For MPC8240 CPU */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +/* values according to the manual */ + +#define CONFIG_DRAM_50MHZ 1 +#define CONFIG_SDRAM_50MHZ + +#undef NR_8259_INTS +#define NR_8259_INTS 1 + + +#define CONFIG_DISK_SPINUP_TIME 1000000 + + +#endif /* __CONFIG_H */ diff --git a/include/configs/ZUMA.h b/include/configs/ZUMA.h new file mode 100644 index 0000000..4978f7e --- /dev/null +++ b/include/configs/ZUMA.h @@ -0,0 +1,380 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include <asm/processor.h> + +#define CFG_GT_6426x GT_64260 /* with a 64260 system controller */ +#define CONFIG_ETHER_PORT_MII /* use two MII ports */ +#define CONFIG_INTEL_LXT97X /* Intel LXT97X phy */ + +#ifndef __ASSEMBLY__ +#include <galileo/core.h> +#endif + +#include "../board/evb64260/local.h" + +#define CONFIG_EVB64260 1 /* this is an EVB64260 board */ +#define CONFIG_ZUMA_V2 1 /* always define this for ZUMA v2 */ + +/* #define CONFIG_ZUMA_V2_OLD 1 */ /* backwards compat for old V2 board */ + +#define CONFIG_BAUDRATE 38400 /* console baudrate = 38400 */ + +#define CONFIG_ECC /* enable ECC support */ + +#define CONFIG_750CX /* we have a 750CX/CXe (override local.h) */ + +/* which initialization functions to call for this board */ +#define CONFIG_MISC_INIT_R +#define CONFIG_BOARD_PRE_INIT +#define CFG_BOARD_ASM_INIT + +#define CFG_BOARD_NAME "Zuma APv2" + +#define CFG_HUSH_PARSER +#define CFG_PROMPT_HUSH_PS2 "> " + +/* + * The following defines let you select what serial you want to use + * for your console driver. + * + * what to do: + * to use the DUART, undef CONFIG_MPSC. If you have hacked a serial + * cable onto the second DUART channel, change the CFG_DUART port from 1 + * to 0 below. + * + * to use the MPSC, #define CONFIG_MPSC. If you have wired up another + * mpsc channel, change CONFIG_MPSC_PORT to the desired value. + */ +#define CONFIG_MPSC + +#define CONFIG_MPSC_PORT 0 + +#define CONFIG_NET_MULTI /* attempt all available adapters */ + +/* define this if you want to enable GT MAC filtering */ +#define CONFIG_GT_USE_MAC_HASH_TABLE + +#if 1 +#define CONFIG_BOOTDELAY -1 /* autoboot disabled */ +#else +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#endif +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#undef CONFIG_BOOTARGS + +#define CONFIG_BOOTCOMMAND \ + "tftpboot && " \ + "setenv bootargs root=/dev/nfs rw nfsroot=$serverip:$rootpath " \ + "ip=$ipaddr:$serverip:$gatewayip:" \ + "$netmask:$hostname:eth0:none panic=5 && bootm" + +#define CONFIG_LOADS_ECHO 0 /* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE /* allow baudrate changes */ + +#undef CONFIG_WATCHDOG /* watchdog disabled */ +#undef CONFIG_ALTIVEC /* undef to disable */ + +#define CONFIG_BOOTP_MASK (CONFIG_BOOTP_DEFAULT | \ + CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_MII /* enable MII commands */ + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_BSP | \ + CFG_CMD_JFFS2 | \ + CFG_CMD_MII | \ + CFG_CMD_DATE) + +/* Flash banks JFFS2 should use */ +#define CFG_JFFS2_FIRST_BANK 1 +#define CFG_JFFS2_NUM_BANKS 2 + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE 1024 /* Console I/O Buffer Size */ +#else +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#endif +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x00400000 /* memtest works on */ +#define CFG_MEMTEST_END 0x00C00000 /* 4 ... 12 MB in DRAM */ + +#define CFG_LOAD_ADDR 0x00300000 /* default load address */ + +#define CFG_HZ 1000 /* decr freq: 1ms ticks */ + +#define CFG_BUS_HZ 133000000 /* 133 MHz */ + +#define CFG_BUS_CLK CFG_BUS_HZ + +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200, 230400 } + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for init data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_INIT_RAM_LOCK + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_FLASH_BASE 0xfff00000 +#define CFG_RESET_ADDRESS 0xfff00100 +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_BASE CFG_FLASH_BASE +#define CFG_MALLOC_LEN (256 << 10) /* Reserve 256 kB for malloc */ + +/* areas to map different things with the GT in physical space */ +#define CFG_DRAM_BANKS 4 +#define CFG_DFL_GT_REGS 0x14000000 /* boot time GT_REGS */ + +/* What to put in the bats. */ +#define CFG_MISC_REGION_BASE 0xf0000000 + +/* Peripheral Device section */ +#define CFG_GT_REGS 0xf8000000 /* later mapped GT_REGS */ +#define CFG_DEV_BASE 0xf0000000 +#define CFG_DEV0_SIZE _64M /* zuma flash @ 0xf000.0000*/ +#define CFG_DEV1_SIZE _8M /* zuma IDE @ 0xf400.0000 */ +#define CFG_DEV2_SIZE _8M /* unused */ +#define CFG_DEV3_SIZE _8M /* unused */ + +#define CFG_DEV0_PAR 0xc498243c + /* c 4 9 8 2 4 3 c */ + /* 33 22|2222|22 22|111 1|11 11|1 1 | | */ + /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210 */ + /* 11|00|0100|10 01|100|0 00|10 0|100 0|011 1|100 */ + /* 3| 0|.... ..| 1| 4 | 0 | 4 | 8 | 7 | 4 */ + +#define CFG_DEV1_PAR 0xc01b6ac5 + /* c 0 1 b 6 a c 5 */ + /* 33 22|2222|22 22|111 1|11 11|1 1 | | */ + /* 10 98|7654|32 10|987 6|54 32|1 098|7 654|3 210 */ + /* 11|00|0000|00 01|101|1 01|10 1|010 1|100 0|101 */ + /* 3| 0|.... ..| 1| 5 | 5 | 5 | 5 | 8 | 5 */ + + + +#define CFG_8BIT_BOOT_PAR 0xc00b5e7c + +#define CFG_MPP_CONTROL_0 0x00007777 /* GPP[7:4] : REQ0[1:0] GNT0[1:0] */ +#define CFG_MPP_CONTROL_1 0x00000000 /* GPP[15:12] : GPP[11:8] */ +#define CFG_MPP_CONTROL_2 0x00008888 /* GPP[23:20] : REQ1[1:0] GNT1[1:0] */ +#define CFG_MPP_CONTROL_3 0x00000000 /* GPP[31:28] (int[3:0]) */ + /* GPP[27:24] (27 is int4, rest are GPP) */ + +#define CFG_SERIAL_PORT_MUX 0x00001101 /* 11=MPSC1/MPSC0 01=ETH, 0=only MII */ +#define CFG_GPP_LEVEL_CONTROL 0xf8000000 /* interrupt inputs: GPP[31:27] */ + +#define CFG_SDRAM_CONFIG 0xe4e18200 /* 0x448 */ + /* idmas use buffer 1,1 + comm use buffer 1 + pci use buffer 0,0 (pci1->0 pci0->0) + cpu use buffer 1 (R*18) + normal load (see also ifdef HVL) + standard SDRAM (see also ifdef REG) + non staggered refresh */ + /* 31:26 25 23 20 19 18 16 */ + /* 111001 00 111 0 0 00 1 */ + + /* refresh count=0x200 + phy interleave disable (by default, + set later by dram config..) + virt interleave enable */ + /* 15 14 13:0 */ + /* 1 0 0x200 */ + +#define CFG_DEV0_SPACE CFG_DEV_BASE +#define CFG_DEV1_SPACE (CFG_DEV0_SPACE + CFG_DEV0_SIZE) +#define CFG_DEV2_SPACE (CFG_DEV1_SPACE + CFG_DEV1_SIZE) +#define CFG_DEV3_SPACE (CFG_DEV2_SPACE + CFG_DEV2_SIZE) + +/*----------------------------------------------------------------------- + * PCI stuff + */ + +#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 */ + +/* PCI MEMORY MAP section */ +#define CFG_PCI0_MEM_BASE 0x80000000 +#define CFG_PCI0_MEM_SIZE _128M +#define CFG_PCI1_MEM_BASE 0x88000000 +#define CFG_PCI1_MEM_SIZE _128M + +#define CFG_PCI0_0_MEM_SPACE (CFG_PCI0_MEM_BASE) +#define CFG_PCI1_0_MEM_SPACE (CFG_PCI1_MEM_BASE) + +/* PCI I/O MAP section */ +#define CFG_PCI0_IO_BASE 0xfa000000 +#define CFG_PCI0_IO_SIZE _16M +#define CFG_PCI1_IO_BASE 0xfb000000 +#define CFG_PCI1_IO_SIZE _16M + +#define CFG_PCI0_IO_SPACE (CFG_PCI0_IO_BASE) +#define CFG_PCI0_IO_SPACE_PCI 0x00000000 +#define CFG_PCI1_IO_SPACE (CFG_PCI1_IO_BASE) +#define CFG_PCI1_IO_SPACE_PCI 0x00000000 + + +/*---------------------------------------------------------------------- + * Initial BAT mappings + */ + +/* NOTES: + * 1) GUARDED and WRITE_THRU not allowed in IBATS + * 2) CACHEINHIBIT and WRITETHROUGH not allowed together in same BAT + */ + +/* SDRAM */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) +#define CFG_DBAT0L (CFG_SDRAM_BASE | BATL_PP_RW | BATL_CACHEINHIBIT | BATL_GUARDEDSTORAGE) +#define CFG_DBAT0U CFG_IBAT0U + +/* init ram */ +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_RW | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U + +/* PCI0, PCI1 memory space (starting at PCI0 base, mapped in one BAT) */ +#define CFG_IBAT2L BATL_NO_ACCESS +#define CFG_IBAT2U CFG_DBAT2U +#define CFG_DBAT2L (CFG_PCI0_MEM_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT2U (CFG_PCI0_MEM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* GT regs, bootrom, all the devices, PCI I/O */ +#define CFG_IBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW) +#define CFG_IBAT3U (CFG_MISC_REGION_BASE | BATU_VS | BATU_VP | BATU_BL_256M) +#define CFG_DBAT3L (CFG_MISC_REGION_BASE | BATL_CACHEINHIBIT | BATL_PP_RW | BATL_GUARDEDSTORAGE) +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8<<20) /* Initial Memory map for Linux */ + + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS 3 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT 130 /* max number of sectors on one chip */ + +#define CFG_EXTRA_FLASH_DEVICE DEVICE0 /* extra flash at device 0 */ +#define CFG_EXTRA_FLASH_WIDTH 2 /* 16 bit */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ +#define CFG_FLASH_CFI 1 + +#define CFG_ENV_IS_IN_FLASH 1 +#define CFG_ENV_SIZE 0x1000 /* Total Size of Environment Sector */ +#define CFG_ENV_SECT_SIZE 0x10000 /* see README - env sect real size */ +#define CFG_ENV_ADDR (0xfff80000 - CFG_ENV_SECT_SIZE) + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 /* For all MPC74xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * L2CR setup -- make sure this is right for your board! + * look in include/mpc74xx.h for the defines used here + */ + +#define CFG_L2 + +#ifdef CONFIG_750CX +#define L2_INIT 0 +#else +#define L2_INIT (L2CR_L2SIZ_2M | L2CR_L2CLK_3 | L2CR_L2RAM_BURST | \ + L2CR_L2OH_5 | L2CR_L2CTL | L2CR_L2WT) +#endif + +#define L2_ENABLE (L2_INIT | L2CR_L2E) + +/*------------------------------------------------------------------------ + * Real time clock + */ +#define CONFIG_RTC_DS1302 + + +/*------------------------------------------------------------------------ + * Galileo I2C driver + */ +#define CONFIG_GT_I2C + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/shannon.h b/include/configs/shannon.h new file mode 100644 index 0000000..c281707 --- /dev/null +++ b/include/configs/shannon.h @@ -0,0 +1,218 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Alex Zuepke <azu@sysgo.de> + * + * Configuation settings for the Shannon/TuxScreen/IS2630 WebPhone Board. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * If we are developing, we might want to start armboot from ram + * so we MUST NOT initialize critical regs like mem-timing ... + */ + +/* + * we just run in non-critical mode now, because we use the Inferno-Loader to + * bring us to live + */ +#define CONFIG_INFERNO /* we are using the inferno bootldr */ +#undef CONFIG_INIT_CRITICAL /* undef for developing */ + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_SA1100 1 /* This is an SA1100 CPU */ +#define CONFIG_SHANNON 1 /* on an SHANNON/TuxScreen Board */ + +#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ + +/* + * Size of malloc() pool + */ +#define CONFIG_MALLOC_SIZE (CFG_ENV_SIZE + 128*1024) + +/* + * Hardware drivers + */ +#define CONFIG_DRIVER_3C589 1 + +/* + * select serial console configuration + */ +#define CONFIG_SERIAL3 1 /* we use SERIAL 3 */ + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE 115200 + +#if 0 /* XXX - cannot test IDE anyway, so disabled for now - wd */ +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_PCMCIA | \ + CFG_CMD_IDE) +#endif /* 0 */ + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define CONFIG_BOOTDELAY 3 +#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,115200" +#define CONFIG_NETMASK 255.255.0.0 +#define CONFIG_BOOTCOMMAND "help" + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 230400 /* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX 2 /* which serial port to use */ +#endif + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "TuxScreen # " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0xc0400000 /* memtest works on */ +#define CFG_MEMTEST_END 0xc0800000 /* 4 ... 8 MB in DRAM */ + +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ + +#define CFG_LOAD_ADDR 0xd0000000 /* default load address */ + +#define CFG_HZ 3686400 /* incrementer freq: 3.6864 MHz */ +#define CFG_CPUSPEED 0x09 /* 190 MHz for Shannon */ + + /* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_DOS_PARTITION 1 /* DOS partitiion support */ + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128*1024) /* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ +#endif + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +/* BE CAREFUL */ +#define CONFIG_NR_DRAM_BANKS 4 /* we have 4 banks of EDORAM */ +#define PHYS_SDRAM_1 0xc0000000 /* RAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x00400000 /* 4 MB */ +#define PHYS_SDRAM_2 0xc8000000 /* RAM Bank #2 */ +#define PHYS_SDRAM_2_SIZE 0x00400000 /* 4 MB */ +#define PHYS_SDRAM_3 0xd0000000 /* RAM Bank #3 */ +#define PHYS_SDRAM_3_SIZE 0x00400000 /* 4 MB */ +#define PHYS_SDRAM_4 0xd8000000 /* RAM Bank #4 */ +#define PHYS_SDRAM_4_SIZE 0x00400000 /* 4 MB */ + + +#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ +#define PHYS_FLASH_SIZE 0x00400000 /* 4 MB */ + +#define CFG_FLASH_BASE PHYS_FLASH_1 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT (31+4) /* max number of sectors on one chip */ + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */ + +#define CFG_ENV_IS_IN_FLASH 1 +#ifdef CONFIG_INFERNO +/* we take the last sector, 128 KB in size, but we only use 4 KB of it for stack reasons */ +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x003E0000) /* Addr of Environment Sector */ +#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +#else +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x1C000) /* Addr of Environment Sector */ +#define CFG_ENV_SIZE 0x4000 /* Total Size of Environment Sector */ +#endif + +/*----------------------------------------------------------------------- + * PCMCIA stuff + *----------------------------------------------------------------------- + * + */ + +/* we pick the upper one */ + +#define CONFIG_PCMCIA_SLOT_A + +#define CFG_PCMCIA_IO_ADDR (0x20000000) +#define CFG_PCMCIA_IO_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_DMA_ADDR (0x24000000) +#define CFG_PCMCIA_DMA_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_ATTRB_ADDR (0x2C000000) +#define CFG_PCMCIA_ATTRB_SIZE ( 64 << 20 ) +#define CFG_PCMCIA_MEM_ADDR (0x28000000) +#define CFG_PCMCIA_MEM_SIZE ( 64 << 20 ) + +/* in fact, MEM and ATTRB are swapped - has to be corrected soon in cmd_pcmcia or so */ + +/*----------------------------------------------------------------------- + * IDE/ATA stuff (Supports IDE harddisk on PCMCIA Adapter) + *----------------------------------------------------------------------- + */ + +#define CONFIG_IDE_PCCARD 1 /* Use IDE with PC Card Adapter */ + +#undef CONFIG_IDE_PCMCIA /* Direct IDE not supported */ +#undef CONFIG_IDE_LED /* LED for ide not supported */ +#undef CONFIG_IDE_RESET /* reset for ide not supported */ + +#define CFG_IDE_MAXBUS 1 /* max. 1 IDE bus */ +#define CFG_IDE_MAXDEVICE 1 /* max. 1 drive per IDE bus */ + +#define CFG_ATA_IDE0_OFFSET 0x0000 + +/* it's simple, all regs are in I/O space */ +#define CFG_ATA_BASE_ADDR CFG_PCMCIA_ATTRB_ADDR + +/* Offset for data I/O */ +#define CFG_ATA_DATA_OFFSET (CFG_ATA_BASE_ADDR) + +/* Offset for normal register accesses */ +#define CFG_ATA_REG_OFFSET (CFG_ATA_BASE_ADDR) + +/* Offset for alternate registers */ +#define CFG_ATA_ALT_OFFSET (CFG_ATA_BASE_ADDR) + +/*----------------------------------------------------------------------- + */ + +#endif /* __CONFIG_H */ diff --git a/include/configs/trab.h b/include/configs/trab.h new file mode 100644 index 0000000..7096767 --- /dev/null +++ b/include/configs/trab.h @@ -0,0 +1,243 @@ +/* + * (C) Copyright 2002 + * Gary Jennejohn <gj@denx.de> + * + * Configuation settings for the TRAB board. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * If we are developing, we might want to start armboot from ram + * so we MUST NOT initialize critical regs like mem-timing ... + */ +#define CONFIG_INIT_CRITICAL /* undef for developing */ + +/* + * High Level Configuration Options + * (easy to change) + */ +#define CONFIG_ARM920T 1 /* This is an arm920t CPU */ +#define CONFIG_S3C2400 1 /* in a SAMSUNG S3C2400 SoC */ +#define CONFIG_TRAB 1 /* on a TRAB Board */ +#undef CONFIG_TRAB_50MHZ /* run the CPU at 50 MHz */ + +/* input clock of PLL */ +#define CONFIG_PLL_INPUT_FREQ 12000000 /* TRAB has 12 MHz input clock */ + +#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */ + +#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGs */ +#define CONFIG_SETUP_MEMORY_TAGS 1 +#define CONFIG_INITRD_TAG 1 + +/* + * Size of malloc() pool + */ +#define CONFIG_MALLOC_SIZE (CFG_ENV_SIZE + 128*1024) + +/* + * Hardware drivers + */ +#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */ +#define CS8900_BASE 0x07000300 /* agrees with WIN CE PA */ +#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */ + +#define CONFIG_VFD 1 /* VFD linear frame buffer driver */ +#define VFD_TEST_LOGO 1 /* output a test logo to the VFDs */ + +/* + * select serial console configuration + */ +#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on TRAB */ + +#define CONFIG_HWFLOW /* include RTS/CTS flow control support */ + +#define CONFIG_MODEM_SUPPORT 1 /* enable modem initialization stuff */ + +#define CONFIG_MODEM_KEY_MAGIC "23" /* hold down these keys to enable modem */ + +/* + * The following enables modem debugging stuff. The dbg() and + * 'char screen[1024]' are used for debug printfs. Unfortunately, + * it is usable only from BDI + */ +#undef CONFIG_MODEM_SUPPORT_DEBUG + +/* allow to overwrite serial and ethaddr */ +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_BAUDRATE 115200 + +#define CONFIG_TIMESTAMP 1 /* Print timestamp info for images */ + +#ifdef CONFIG_HWFLOW +#define CONFIG_COMMANDS_ADD_HWFLOW CFG_CMD_HWFLOW +#else +#define CONFIG_COMMANDS_ADD_HWFLOW 0 +#endif + +#ifdef CONFIG_VFD +#define CONFIG_COMMANDS_ADD_VFD CFG_CMD_VFD +#else +#define CONFIG_COMMANDS_ADD_VFD 0 +#endif + +#ifndef USE_920T_MMU +#define CONFIG_COMMANDS ((CONFIG_CMD_DFL & ~CFG_CMD_CACHE) | \ + CFG_CMD_BSP | \ + CONFIG_COMMANDS_ADD_HWFLOW | \ + CONFIG_COMMANDS_ADD_VFD ) +#else +#define CONFIG_COMMANDS (CONFIG_CMD_DFL | \ + CFG_CMD_BSP | \ + CONFIG_COMMANDS_ADD_HWFLOW | \ + CONFIG_COMMANDS_ADD_VFD ) +#endif + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + + +#define CONFIG_BOOTDELAY 5 +#define CONFIG_PREBOOT "echo;echo *** booting ***;echo" +#define CONFIG_BOOTARGS "console=ttyS0" +#define CONFIG_ETHADDR 00:D0:93:00:61:11 +#define CONFIG_NETMASK 255.255.255.0 +#define CONFIG_IPADDR 192.168.3.27 +#define CONFIG_SERVERIP 192.168.3.1 +#define CONFIG_BOOTCOMMAND "run flash_nfs" +#define CONFIG_EXTRA_ENV_SETTINGS \ + "nfs_args=setenv bootargs root=/dev/nfs rw " \ + "nfsroot=$(serverip):$(rootpath)\0" \ + "rootpath=/opt/eldk/arm_920TDI\0" \ + "ram_args=setenv bootargs root=/dev/ram rw\0" \ + "add_net=setenv bootargs $(bootargs) ethaddr=$(ethaddr) " \ + "ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off\0" \ + "add_misc=setenv bootargs $(bootargs) console=ttyS0 panic=1\0" \ + "load=tftp 0xC100000 /tftpboot/TRAB/u-boot.bin\0" \ + "update=protect off 1:0-7;era 1:0-7;cp.b 0xc100000 0 $(filesize);" \ + "setenv filesize;saveenv\0" \ + "loadfile=/tftpboot/TRAB/pImage\0" \ + "loadaddr=c400000\0" \ + "net_load=tftpboot $(loadaddr) $(loadfile)\0" \ + "net_nfs=run net_load nfs_args add_net add_misc;bootm\0" \ + "kernel_addr=00040000\0" \ + "flash_nfs=run nfs_args add_net add_misc;bootm $(kernel_addr)\0" \ + "mdm_init1=ATZ\0" \ + "mdm_init2=ATS0=1\0" \ + "mdm_flow_control=rts/cts\0" + +#if 0 /* disabled for development */ +#define CONFIG_AUTOBOOT_KEYED /* Enable password protection */ +#define CONFIG_AUTOBOOT_PROMPT "\nEnter password - autoboot in %d sec...\n" +#define CONFIG_AUTOBOOT_DELAY_STR "system" /* 1st password */ +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */ +/* what's this ? it's not used anywhere */ +#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */ +#endif + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "TRAB # " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START 0x0c000000 /* memtest works on */ +#define CFG_MEMTEST_END 0x0d000000 /* 16 MB in DRAM */ + +#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */ + +#define CFG_LOAD_ADDR 0x0cf00000 /* default load address */ + +#ifdef CONFIG_TRAB_50MHZ +/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */ +/* it to wrap 100 times (total 1562500) to get 1 sec. */ +/* this should _really_ be calculated !! */ +#define CFG_HZ 1562500 +#else +/* the PWM TImer 4 uses a counter of 10390 for 10 ms, so we need */ +/* it to wrap 100 times (total 1039000) to get 1 sec. */ +/* this should _really_ be calculated !! */ +#define CFG_HZ 1039000 +#endif + +/* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_MISC_INIT_R /* have misc_init_r() function */ + +/*----------------------------------------------------------------------- + * Stack sizes + * + * The stack sizes are set up in start.S using the settings below + */ +#define CONFIG_STACKSIZE (128*1024) /* regular stack */ +#ifdef CONFIG_USE_IRQ +#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */ +#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */ +#endif + +/*----------------------------------------------------------------------- + * Physical Memory Map + */ +#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */ +#define PHYS_SDRAM_1 0x0c000000 /* SDRAM Bank #1 */ +#define PHYS_SDRAM_1_SIZE 0x01000000 /* 16 MB */ + +#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */ +#define PHYS_FLASH_SIZE 0x00800000 /* 8 MB */ + +/* The following #defines are needed to get flash environment right */ +#define CFG_MONITOR_BASE PHYS_FLASH_1 +#define CFG_MONITOR_LEN (256 << 10) + +#define CFG_FLASH_BASE PHYS_FLASH_1 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT (71) /* max number of sectors on one chip */ + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT (2*CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT (2*CFG_HZ) /* Timeout for Flash Write */ + +#define CFG_ENV_IS_IN_FLASH 1 + +/* Address and size of Primary Environment Sector */ +#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x4000) +#define CFG_ENV_SIZE 0x4000 + +/* Address and size of Redundant Environment Sector */ +#define CFG_ENV_OFFSET_REDUND (CFG_ENV_ADDR+CFG_ENV_SIZE) +#define CFG_ENV_SIZE_REDUND (CFG_ENV_SIZE) + +#endif /* __CONFIG_H */ diff --git a/include/configs/utx8245.h b/include/configs/utx8245.h new file mode 100644 index 0000000..5aec47a --- /dev/null +++ b/include/configs/utx8245.h @@ -0,0 +1,346 @@ +/* + * (C) Copyright 2001 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Gregory E. Allen, gallen@arlut.utexas.edu + * Matthew E. Karger, karger@arlut.utexas.edu + * Applied Research Laboratories, The University of Texas at Austin + * + * 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 + */ + +/* + * + * Configuration settings for the utx8245 board. + * + */ + +/* ------------------------------------------------------------------------- */ + +/* + * board/config.h - configuration options, board specific + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_MPC824X 1 +#define CONFIG_MPC8245 1 +#define CONFIG_UTX8245 1 +#define DEBUG 1 + +#define CONFIG_CONS_INDEX 1 +#define CONFIG_BAUDRATE 57600 +#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_BOOTDELAY 5 +#define CONFIG_AUTOBOOT_PROMPT "autoboot in %d seconds\n" +#define CONFIG_BOOTCOMMAND "bootm FF920000 FF800000" /* autoboot command */ +#define CONFIG_BOOTARGS "root=/dev/ram console=ttyS0,57600" /* RAMdisk */ +#define CONFIG_ETHADDR 41:52:4c:61:00:01 /* MAC address */ +#define CONFIG_SERVERIP 10.8.17.105 +#define CONFIG_ENV_OVERWRITE + +#define CONFIG_COMMANDS (CFG_CMD_DFL | CFG_CMD_BDI | CFG_CMD_PCI \ + | CFG_CMD_FLASH | CFG_CMD_MEMORY \ + | CFG_CMD_ENV | CFG_CMD_CONSOLE \ + | CFG_CMD_LOADS | CFG_CMD_LOADB \ + | CFG_CMD_IMI | CFG_CMD_CACHE \ + | CFG_CMD_RUN | CFG_CMD_ECHO \ + | CFG_CMD_REGINFO | CFG_CMD_NET\ + | CFG_CMD_DHCP) + +/* This must be included AFTER the definition of CONFIG_COMMANDS (if any) + */ +#include <cmd_confdefs.h> + + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "=> " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ + +/* Print Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16) + +#define CFG_MAXARGS 16 /* max number of command args */ +#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */ +#define CFG_LOAD_ADDR 0x00100000 /* Default load address */ + + +/*----------------------------------------------------------------------- + * PCI configuration + *----------------------------------------------------------------------- + */ +#define CONFIG_PCI /* include pci support */ +#undef CONFIG_PCI_PNP +#define CONFIG_PCI_SCAN_SHOW +#define CONFIG_NET_MULTI +#define CONFIG_EEPRO100 + +#define PCI_ENET0_IOADDR 0x80000000 +#define PCI_ENET0_MEMADDR 0x80000000 +#define PCI_FIREWIRE_IOADDR 0x81000000 +#define PCI_FIREWIRE_MEMADDR 0x81000000 + + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ +#define CFG_SDRAM_BASE 0x00000000 +#define CFG_MAX_RAM_SIZE 0x10000000 /* amount of SDRAM */ + + +/* even though FLASHP_BASE is FF800000, with 2MB on RCS0, the + * reset vector is actually located at FF800100, but the 8245 + * takes care of us. + */ +#define CFG_RESET_ADDRESS 0xFFF00100 + +#define CFG_EUMB_ADDR 0xFC000000 + +#define CFG_MONITOR_BASE TEXT_BASE + +#define CFG_MONITOR_LEN (256 << 10) /* Reserve 256 kB for Monitor */ +#define CFG_MALLOC_LEN (128 << 10) /* Reserve 128 kB for malloc() */ + +/*#define CFG_DRAM_TEST 1 */ +#define CFG_MEMTEST_START 0x00003000 /* memtest works on 0...256 MB */ +#define CFG_MEMTEST_END 0x0ff8ffa8 /* in SDRAM, skips exception */ + /* vectors and U-Boot */ + + +/*-------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + *------------------------------------------------------------------*/ +#define CFG_GBL_DATA_SIZE 128 /* Size in bytes reserved for */ + /* initial data */ +#define CFG_INIT_RAM_ADDR 0x40000000 +#define CFG_INIT_RAM_END 0x1000 +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +/*-------------------------------------------------------------------- + * NS16550 Configuration + *------------------------------------------------------------------*/ +#define CFG_NS16550 +#define CFG_NS16550_SERIAL + +#define CFG_NS16550_REG_SIZE 1 + +#define CFG_NS16550_CLK get_bus_freq(0) + +#define CFG_NS16550_COM1 (CFG_EUMB_ADDR + 0x4500) +#define CFG_NS16550_COM2 (CFG_EUMB_ADDR + 0x4600) + +/*-------------------------------------------------------------------- + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + * For the detail description refer to the MPC8240 user's manual. + *------------------------------------------------------------------*/ + +#define CONFIG_SYS_CLK_FREQ 33000000 +#define CFG_HZ 1000 + +#define CFG_ETH_DEV_FN 0x7800 +#define CFG_ETH_IOBASE 0x00104000 + + +/*-------------------------------------------------------------------- + * Memory Control Configuration Register values + * - see sec. 4.12 of MPC8245 UM + *------------------------------------------------------------------*/ + +/* MCCR1 */ +#define CFG_ROMNAL 0 +#define CFG_ROMFAL 2 /* (tacc=70ns)*mem_freq - 2 */ +#define CFG_BANK0_ROW 2 /* SDRAM bank 7-0 row address */ +#define CFG_BANK1_ROW 2 /* bit count */ +#define CFG_BANK2_ROW 0 +#define CFG_BANK3_ROW 0 +#define CFG_BANK4_ROW 0 +#define CFG_BANK5_ROW 0 +#define CFG_BANK6_ROW 0 +#define CFG_BANK7_ROW 0 + +/* MCCR2, refresh interval clock cycles */ +#define CFG_REFINT 480 /* 33 MHz SDRAM clock was 480 */ + +/* Burst To Precharge. Bits of this value go to MCCR3 and MCCR4 */ +#define CFG_BSTOPRE 1023 /* burst to precharge[0..9], */ + /* sets open page interval */ + +/* MCCR3 */ +#define CFG_REFREC 5 /* Refresh to activate interval, trc */ + +/* MCCR4 */ +#define CFG_PRETOACT 2 /* trp */ +#define CFG_ACTTOPRE 7 /* trcd + (burst length - 1) + tdrl */ +#define CFG_SDMODE_CAS_LAT 3 /* SDMODE CAS latancy */ +#define CFG_SDMODE_WRAP 0 /* SDMODE wrap type, sequential */ +#define CFG_ACTORW 2 /* trcd min */ +#define CFG_DBUS_SIZE2 1 /* set for 8-bit RCS1, clear for 32,64 */ +#define CFG_REGISTERD_TYPE_BUFFER 1 +#define CFG_EXTROM 1 +#define CFG_REGDIMM 0 + +/* calculate according to formula in sec. 6-22 of 8245 UM */ +#define CFG_PGMAX 50 /* how long the 8245 retains the */ + /* currently accessed page in memory */ + /* was 45 */ + +#define CFG_SDRAM_DSCD 0x20 /* SDRAM data in sample clock delay - note */ + /* bottom 3 bits MUST be 0 */ + +#define CFG_DLL_MAX_DELAY 0x04 +#define CFG_DLL_EXTEND 0x80 +#define CFG_PCI_HOLD_DEL 0x20 + + +/* Memory bank settings. + * Only bits 20-29 are actually used from these values to set the + * start/end addresses. The upper two bits will always be 0, and the lower + * 20 bits will be 0x00000 for a start address, or 0xfffff for an end + * address. Refer to the MPC8245 user manual. + */ + +#define CFG_BANK0_START 0x00000000 +#define CFG_BANK0_END (CFG_MAX_RAM_SIZE/2 - 1) +#define CFG_BANK0_ENABLE 1 +#define CFG_BANK1_START CFG_MAX_RAM_SIZE/2 +#define CFG_BANK1_END (CFG_MAX_RAM_SIZE - 1) +#define CFG_BANK1_ENABLE 1 +#define CFG_BANK2_START 0x3ff00000 /* not available in this design */ +#define CFG_BANK2_END 0x3fffffff +#define CFG_BANK2_ENABLE 0 +#define CFG_BANK3_START 0x3ff00000 +#define CFG_BANK3_END 0x3fffffff +#define CFG_BANK3_ENABLE 0 +#define CFG_BANK4_START 0x3ff00000 +#define CFG_BANK4_END 0x3fffffff +#define CFG_BANK4_ENABLE 0 +#define CFG_BANK5_START 0x3ff00000 +#define CFG_BANK5_END 0x3fffffff +#define CFG_BANK5_ENABLE 0 +#define CFG_BANK6_START 0x3ff00000 +#define CFG_BANK6_END 0x3fffffff +#define CFG_BANK6_ENABLE 0 +#define CFG_BANK7_START 0x3ff00000 +#define CFG_BANK7_END 0x3fffffff +#define CFG_BANK7_ENABLE 0 + +/*-------------------------------------------------------------------- + * 4.4 - Output Driver Control Register + *------------------------------------------------------------------*/ +#define CFG_ODCR 0xe5 + +/*-------------------------------------------------------------------- + * 4.8 - Error Handling Registers + *------------------------------------------------------------------*/ +#define CFG_ERRENR1 0x11 /* enable SDRAM refresh overflow error */ + +/* SDRAM 0-256 MB */ +#define CFG_IBAT0L (CFG_SDRAM_BASE | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT0U (CFG_SDRAM_BASE | BATU_BL_256M | BATU_VS | BATU_VP) + +/* stack in dcache */ +#define CFG_IBAT1L (CFG_INIT_RAM_ADDR | BATL_PP_10 | BATL_MEMCOHERENCE) +#define CFG_IBAT1U (CFG_INIT_RAM_ADDR | BATU_BL_128K | BATU_VS | BATU_VP) + +/* PCI memory */ +#define CFG_IBAT2L (0x80000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT2U (0x80000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +/* Flash, config addrs, etc. */ +#define CFG_IBAT3L (0xF0000000 | BATL_PP_10 | BATL_CACHEINHIBIT) +#define CFG_IBAT3U (0xF0000000 | BATU_BL_256M | BATU_VS | BATU_VP) + +#define CFG_DBAT0L CFG_IBAT0L +#define CFG_DBAT0U CFG_IBAT0U +#define CFG_DBAT1L CFG_IBAT1L +#define CFG_DBAT1U CFG_IBAT1U +#define CFG_DBAT2L CFG_IBAT2L +#define CFG_DBAT2U CFG_IBAT2U +#define CFG_DBAT3L CFG_IBAT3L +#define CFG_DBAT3U CFG_IBAT3U + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization (AMD AM29LV116D) + */ +#define CFG_FLASH_BASE 0xFF800000 + +#define CFG_MAX_FLASH_BANKS 1 /* Max number of flash banks */ +#define CFG_MAX_FLASH_SECT 35 /* Max number of sectors in one bank */ + +#define CFG_FLASH_ERASE_TOUT 120000 /* Timeout for Flash Erase (in ms) */ +#define CFG_FLASH_WRITE_TOUT 500 /* Timeout for Flash Write (in ms) */ + + /* Warning: environment is not EMBEDDED in the U-Boot code. + * It's stored in flash separately. + */ +#define CFG_ENV_IS_IN_FLASH 1 + +#define CFG_ENV_ADDR 0xFF9FA000 /* flash sector SA33 */ +#define CFG_ENV_SIZE 0x2000 /* Size of the Environment */ +#define CFG_ENV_OFFSET 0 /* starting right at the beginning */ +#define CFG_ENV_SECT_SIZE 0x2000 /* Size of the Environment Sector */ + + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE +#undef CFG_RAMBOOT +#else +#define CFG_RAMBOOT +#endif + + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE 32 +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +# define CFG_CACHELINE_SHIFT 5 /* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM 0x02 /* Software reboot */ + + +#endif /* __CONFIG_H */ diff --git a/include/dtt.h b/include/dtt.h new file mode 100644 index 0000000..f3d95ff --- /dev/null +++ b/include/dtt.h @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.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 + */ + +/* + * Digital Thermometers and Thermostats. + */ +#ifndef _DTT_H_ +#define _DTT_H_ + +#if defined(CONFIG_DTT_LM75) || defined(CONFIG_DTT_DS1621) +#define CONFIG_DTT /* We have a DTT */ + +#define DTT_COMMERCIAL_MAX_TEMP 70 /* 0 - +70 C */ +#define DTT_INDUSTRIAL_MAX_TEMP 85 /* -40 - +85 C */ +#define DTT_AUTOMOTIVE_MAX_TEMP 105 /* -40 - +105 C */ +#ifndef CFG_DTT_MAX_TEMP +#define CFG_DTT_MAX_TEMP DTT_COMMERCIAL_MAX_TEMP +#endif +#ifndef CFG_DTT_HYSTERESIS +#define CFG_DTT_HYSTERESIS 5 /* 5 C */ +#endif + +extern int dtt_init (void); +extern int dtt_read(int sensor, int reg); +extern int dtt_write(int sensor, int reg, int val); +extern int dtt_get_temp(int sensor); +#endif + +#if defined(CONFIG_DTT_LM75) +#define DTT_READ_TEMP 0x0 +#define DTT_CONFIG 0x1 +#define DTT_TEMP_HYST 0x2 +#define DTT_TEMP_SET 0x3 +#endif + +#if defined(CONFIG_DTT_DS1621) +#define DTT_READ_TEMP 0xAA +#define DTT_READ_COUNTER 0xA8 +#define DTT_READ_SLOPE 0xA9 +#define DTT_WRITE_START_CONV 0xEE +#define DTT_WRITE_STOP_CONV 0x22 +#define DTT_TEMP_HIGH 0xA1 +#define DTT_TEMP_LOW 0xA2 +#define DTT_CONFIG 0xAC +#endif + +#endif /* _DTT_H_ */ diff --git a/include/environment.h b/include/environment.h new file mode 100644 index 0000000..fe8465b --- /dev/null +++ b/include/environment.h @@ -0,0 +1,83 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _ENVIRONMENT_H_ +#define _ENVIRONMENT_H_ 1 + +/************************************************************************** + * + * The "environment" is stored as a list of '\0' terminated + * "name=value" strings. The end of the list is marked by a double + * '\0'. New entries are always added at the end. Deleting an entry + * shifts the remaining entries to the front. Replacing an entry is a + * combination of deleting the old value and adding the new one. + * + * The environment is preceeded by a 32 bit CRC over the data part. + * + ************************************************************************** + */ + +#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_OFFSET +# define CFG_ENV_OFFSET (CFG_ENV_ADDR - CFG_FLASH_BASE) +# endif +# if !defined(CFG_ENV_ADDR_REDUND) && defined(CFG_ENV_OFFSET_REDUND) +# define CFG_ENV_ADDR_REDUND (CFG_FLASH_BASE + CFG_ENV_OFFSET_REDUND) +# endif +# ifndef CFG_ENV_SIZE +# define CFG_ENV_SIZE CFG_ENV_SECT_SIZE +# endif +# if defined(CFG_ENV_ADDR_REDUND) && !defined(CFG_ENV_SIZE_REDUND) +# define CFG_ENV_SIZE_REDUND CFG_ENV_SIZE +# endif +# if (CFG_ENV_ADDR >= CFG_MONITOR_BASE) && \ + (CFG_ENV_ADDR+CFG_ENV_SIZE) <= (CFG_MONITOR_BASE + CFG_MONITOR_LEN) +# define ENV_IS_EMBEDDED 1 +# endif +# if defined(CFG_ENV_ADDR_REDUND) || defined(CFG_ENV_OFFSET_REDUND) +# define CFG_REDUNDAND_ENVIRONMENT 1 +# endif +#endif /* CFG_ENV_IS_IN_FLASH */ + + +#ifdef CFG_REDUNDAND_ENVIRONMENT +# define ENV_HEADER_SIZE (sizeof(unsigned long) + 1) +#else +# define ENV_HEADER_SIZE (sizeof(unsigned long)) +#endif + + +#define ENV_SIZE (CFG_ENV_SIZE - ENV_HEADER_SIZE) + +typedef struct environment_s { + unsigned long crc; /* CRC32 over data bytes */ +#ifdef CFG_REDUNDAND_ENVIRONMENT + unsigned char flags; /* active/obsolete flags */ +#endif + unsigned char data[ENV_SIZE]; /* Environment data */ +} env_t; + +#endif /* _ENVIRONMENT_H_ */ diff --git a/include/linux/byteorder/generic.h b/include/linux/byteorder/generic.h new file mode 100644 index 0000000..cff850f --- /dev/null +++ b/include/linux/byteorder/generic.h @@ -0,0 +1,180 @@ +#ifndef _LINUX_BYTEORDER_GENERIC_H +#define _LINUX_BYTEORDER_GENERIC_H + +/* + * linux/byteorder_generic.h + * Generic Byte-reordering support + * + * Francois-Rene Rideau <fare@tunes.org> 19970707 + * gathered all the good ideas from all asm-foo/byteorder.h into one file, + * cleaned them up. + * I hope it is compliant with non-GCC compilers. + * I decided to put __BYTEORDER_HAS_U64__ in byteorder.h, + * because I wasn't sure it would be ok to put it in types.h + * Upgraded it to 2.1.43 + * Francois-Rene Rideau <fare@tunes.org> 19971012 + * Upgraded it to 2.1.57 + * to please Linus T., replaced huge #ifdef's between little/big endian + * by nestedly #include'd files. + * Francois-Rene Rideau <fare@tunes.org> 19971205 + * Made it to 2.1.71; now a facelift: + * Put files under include/linux/byteorder/ + * Split swab from generic support. + * + * TODO: + * = Regular kernel maintainers could also replace all these manual + * byteswap macros that remain, disseminated among drivers, + * after some grep or the sources... + * = Linus might want to rename all these macros and files to fit his taste, + * to fit his personal naming scheme. + * = it seems that a few drivers would also appreciate + * nybble swapping support... + * = every architecture could add their byteswap macro in asm/byteorder.h + * see how some architectures already do (i386, alpha, ppc, etc) + * = cpu_to_beXX and beXX_to_cpu might some day need to be well + * distinguished throughout the kernel. This is not the case currently, + * since little endian, big endian, and pdp endian machines needn't it. + * But this might be the case for, say, a port of Linux to 20/21 bit + * architectures (and F21 Linux addict around?). + */ + +/* + * The following macros are to be defined by <asm/byteorder.h>: + * + * Conversion of long and short int between network and host format + * ntohl(__u32 x) + * ntohs(__u16 x) + * htonl(__u32 x) + * htons(__u16 x) + * It seems that some programs (which? where? or perhaps a standard? POSIX?) + * might like the above to be functions, not macros (why?). + * if that's true, then detect them, and take measures. + * Anyway, the measure is: define only ___ntohl as a macro instead, + * and in a separate file, have + * unsigned long inline ntohl(x){return ___ntohl(x);} + * + * The same for constant arguments + * __constant_ntohl(__u32 x) + * __constant_ntohs(__u16 x) + * __constant_htonl(__u32 x) + * __constant_htons(__u16 x) + * + * Conversion of XX-bit integers (16- 32- or 64-) + * between native CPU format and little/big endian format + * 64-bit stuff only defined for proper architectures + * cpu_to_[bl]eXX(__uXX x) + * [bl]eXX_to_cpu(__uXX x) + * + * The same, but takes a pointer to the value to convert + * cpu_to_[bl]eXXp(__uXX x) + * [bl]eXX_to_cpup(__uXX x) + * + * The same, but change in situ + * cpu_to_[bl]eXXs(__uXX x) + * [bl]eXX_to_cpus(__uXX x) + * + * See asm-foo/byteorder.h for examples of how to provide + * architecture-optimized versions + * + */ + + +#if defined(__KERNEL__) +/* + * inside the kernel, we can use nicknames; + * outside of it, we must avoid POSIX namespace pollution... + */ +#define cpu_to_le64 __cpu_to_le64 +#define le64_to_cpu __le64_to_cpu +#define cpu_to_le32 __cpu_to_le32 +#define le32_to_cpu __le32_to_cpu +#define cpu_to_le16 __cpu_to_le16 +#define le16_to_cpu __le16_to_cpu +#define cpu_to_be64 __cpu_to_be64 +#define be64_to_cpu __be64_to_cpu +#define cpu_to_be32 __cpu_to_be32 +#define be32_to_cpu __be32_to_cpu +#define cpu_to_be16 __cpu_to_be16 +#define be16_to_cpu __be16_to_cpu +#define cpu_to_le64p __cpu_to_le64p +#define le64_to_cpup __le64_to_cpup +#define cpu_to_le32p __cpu_to_le32p +#define le32_to_cpup __le32_to_cpup +#define cpu_to_le16p __cpu_to_le16p +#define le16_to_cpup __le16_to_cpup +#define cpu_to_be64p __cpu_to_be64p +#define be64_to_cpup __be64_to_cpup +#define cpu_to_be32p __cpu_to_be32p +#define be32_to_cpup __be32_to_cpup +#define cpu_to_be16p __cpu_to_be16p +#define be16_to_cpup __be16_to_cpup +#define cpu_to_le64s __cpu_to_le64s +#define le64_to_cpus __le64_to_cpus +#define cpu_to_le32s __cpu_to_le32s +#define le32_to_cpus __le32_to_cpus +#define cpu_to_le16s __cpu_to_le16s +#define le16_to_cpus __le16_to_cpus +#define cpu_to_be64s __cpu_to_be64s +#define be64_to_cpus __be64_to_cpus +#define cpu_to_be32s __cpu_to_be32s +#define be32_to_cpus __be32_to_cpus +#define cpu_to_be16s __cpu_to_be16s +#define be16_to_cpus __be16_to_cpus +#endif + + +/* + * Handle ntohl and suches. These have various compatibility + * issues - like we want to give the prototype even though we + * also have a macro for them in case some strange program + * wants to take the address of the thing or something.. + * + * Note that these used to return a "long" in libc5, even though + * long is often 64-bit these days.. Thus the casts. + * + * They have to be macros in order to do the constant folding + * correctly - if the argument passed into a inline function + * it is no longer constant according to gcc.. + */ + +#undef ntohl +#undef ntohs +#undef htonl +#undef htons + +/* + * Do the prototypes. Somebody might want to take the + * address or some such sick thing.. + */ +#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2) +extern __u32 ntohl(__u32); +extern __u32 htonl(__u32); +#else +extern unsigned long int ntohl(unsigned long int); +extern unsigned long int htonl(unsigned long int); +#endif +extern unsigned short int ntohs(unsigned short int); +extern unsigned short int htons(unsigned short int); + + +#if defined(__GNUC__) && (__GNUC__ >= 2) + +#define ___htonl(x) __cpu_to_be32(x) +#define ___htons(x) __cpu_to_be16(x) +#define ___ntohl(x) __be32_to_cpu(x) +#define ___ntohs(x) __be16_to_cpu(x) + +#if defined(__KERNEL__) || (defined (__GLIBC__) && __GLIBC__ >= 2) +#define htonl(x) ___htonl(x) +#define ntohl(x) ___ntohl(x) +#else +#define htonl(x) ((unsigned long)___htonl(x)) +#define ntohl(x) ((unsigned long)___ntohl(x)) +#endif +#define htons(x) ___htons(x) +#define ntohs(x) ___ntohs(x) + +#endif /* OPTIMIZE */ + + +#endif /* _LINUX_BYTEORDER_GENERIC_H */ diff --git a/include/mpc824x.h b/include/mpc824x.h new file mode 100644 index 0000000..0cd7898 --- /dev/null +++ b/include/mpc824x.h @@ -0,0 +1,575 @@ +/* + * Copyright Rob Taylor, Flying Pig Systems Ltd. 2000. + * Copyright (C) 2001, James Dougherty, jfd@cs.stanford.edu + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __MPC824X_H__ +#define __MPC824X_H__ + +#include <config.h> + +/* CPU Types */ +#define CPU_TYPE_601 0x01 /* PPC 601 CPU */ +#define CPU_TYPE_602 0x02 /* PPC 602 CPU */ +#define CPU_TYPE_603 0x03 /* PPC 603 CPU */ +#define CPU_TYPE_603E 0x06 /* PPC 603e CPU */ +#define CPU_TYPE_603P 0x07 /* PPC 603p CPU */ +#define CPU_TYPE_604 0x04 /* PPC 604 CPU */ +#define CPU_TYPE_604E 0x09 /* PPC 604e CPU */ +#define CPU_TYPE_604R 0x0a /* PPC 604r CPU */ +#define CPU_TYPE_750 0x08 /* PPC 750 CPU */ +#define CPU_TYPE_8240 0x81 /* PPC 8240 CPU */ +#define CPU_TYPE_8245 0x8081 /* PPC 8245/8241 CPU */ +#define _CACHE_ALIGN_SIZE 32 /* cache line size */ + +/* spr976 - DMISS data tlb miss address register + * spr977 - DCMP data tlb miss compare register + * spr978 - HASH1 PTEG1 address register + * spr980 - HASH2 PTEG2 address register + * IMISS - instruction tlb miss address register + * ICMP - instruction TLB mis compare register + * RPA - real page address register + * HID0 - hardware implemntation register + * HID2 - instruction address breakpoint register + */ + +/* Kahlua/MPC8240 defines */ +#define VEN_DEV_ID 0x00021057 /* Vendor and Dev. ID for MPC106 */ +#define KAHLUA_ID 0x00031057 /* Vendor & Dev Id for Kahlua's PCI */ +#define KAHLUA2_ID 0x00061057 /* 8245 is aka Kahlua-2 */ +#define BMC_BASE 0x80000000 /* Kahlua ID in PCI Memory space */ +#define CHRP_REG_ADDR 0xfec00000 /* MPC107 Config, Map B */ +#define CHRP_REG_DATA 0xfee00000 /* MPC107 Config, Map B */ +#define CHRP_ISA_MEM_PHYS 0xfd000000 +#define CHRP_ISA_MEM_BUS 0x00000000 +#define CHRP_ISA_MEM_SIZE 0x01000000 +#define CHRP_ISA_IO_PHYS 0xfe000000 +#define CHRP_ISA_IO_BUS 0x00000000 +#define CHRP_ISA_IO_SIZE 0x00800000 +#define CHRP_PCI_IO_PHYS 0xfe800000 +#define CHRP_PCI_IO_BUS 0x00800000 +#define CHRP_PCI_IO_SIZE 0x00400000 +#define CHRP_PCI_MEM_PHYS 0x80000000 +#define CHRP_PCI_MEM_BUS 0x80000000 +#define CHRP_PCI_MEM_SIZE 0x7d000000 +#define CHRP_PCI_MEMORY_PHYS 0x00000000 +#define CHRP_PCI_MEMORY_BUS 0x00000000 +#define CHRP_PCI_MEMORY_SIZE 0x40000000 +#define PREP_REG_ADDR 0x80000cf8 /* MPC107 Config, Map A */ +#define PREP_REG_DATA 0x80000cfc /* MPC107 Config, Map A */ +#define PREP_ISA_IO_PHYS 0x80000000 +#define PREP_ISA_IO_BUS 0x00000000 +#define PREP_ISA_IO_SIZE 0x00800000 +#define PREP_PCI_IO_PHYS 0x81000000 +#define PREP_PCI_IO_BUS 0x01000000 +#define PREP_PCI_IO_SIZE 0x3e800000 +#define PREP_PCI_MEM_PHYS 0xc0000000 +#define PREP_PCI_MEM_BUS 0x00000000 +#define PREP_PCI_MEM_SIZE 0x3f000000 +#define PREP_PCI_MEMORY_PHYS 0x00000000 +#define PREP_PCI_MEMORY_BUS 0x80000000 +#define PREP_PCI_MEMORY_SIZE 0x80000000 +#define MPC107_PCI_CMD 0x80000004 /* MPC107 PCI cmd reg */ +#define MPC107_PCI_STAT 0x80000006 /* MPC107 PCI status reg */ +#define PROC_INT1_ADR 0x800000a8 /* MPC107 Processor i/f cfg1 */ +#define PROC_INT2_ADR 0x800000ac /* MPC107 Processor i/f cfg2 */ +#define MEM_CONT1_ADR 0x800000f0 /* MPC107 Memory control config. 1 */ +#define MEM_CONT2_ADR 0x800000f4 /* MPC107 Memory control config. 2 */ +#define MEM_CONT3_ADR 0x800000f8 /* MPC107 Memory control config. 3 */ +#define MEM_CONT4_ADR 0x800000fc /* MPC107 Memory control config. 4 */ +#define MEM_ERREN1_ADR 0x800000c0 /* MPC107 Memory error enable 1 */ +#define MEM_START1_ADR 0x80000080 /* MPC107 Memory starting addr */ +#define MEM_START2_ADR 0x80000084 /* MPC107 Memory starting addr-lo */ +#define XMEM_START1_ADR 0x80000088 /* MPC107 Extended mem. start addr-hi*/ +#define XMEM_START2_ADR 0x8000008c /* MPC107 Extended mem. start addr-lo*/ +#define MEM_END1_ADR 0x80000090 /* MPC107 Memory ending address */ +#define MEM_END2_ADR 0x80000094 /* MPC107 Memory ending addr-lo */ +#define XMEM_END1_ADR 0x80000098 /* MPC107 Extended mem. end addrs-hi */ +#define XMEM_END2_ADR 0x8000009c /* MPC107 Extended mem. end addrs-lo*/ +#define OUT_DRV_CONT 0x80000073 /* MPC107 Output Driver Control reg */ +#define MEM_EN_ADR 0x800000a0 /* Memory bank enable */ +#define PAGE_MODE 0x800000a3 /* MPC107 Page Mode Counter/Timer */ + +/*----------------------------------------------------------------------- + * Exception offsets (PowerPC standard) + */ +#define EXC_OFF_RESERVED0 0x0000 /* Reserved */ +#define EXC_OFF_SYS_RESET 0x0100 /* System reset */ +#define EXC_OFF_MACH_CHCK 0x0200 /* Machine Check */ +#define EXC_OFF_DATA_STOR 0x0300 /* Data Storage */ +#define EXC_OFF_INS_STOR 0x0400 /* Instruction Storage */ +#define EXC_OFF_EXTERNAL 0x0500 /* External */ +#define EXC_OFF_ALIGN 0x0600 /* Alignment */ +#define EXC_OFF_PROGRAM 0x0700 /* Program */ +#define EXC_OFF_FPUNAVAIL 0x0800 /* Floating-point Unavailable */ +#define EXC_OFF_DECR 0x0900 /* Decrementer */ +#define EXC_OFF_RESERVED1 0x0A00 /* Reserved */ +#define EXC_OFF_RESERVED2 0x0B00 /* Reserved */ +#define EXC_OFF_SYS_CALL 0x0C00 /* System Call */ +#define EXC_OFF_TRACE 0x0D00 /* Trace */ +#define EXC_OFF_FPUNASSIST 0x0E00 /* Floating-point Assist */ + + /* 0x0E10 - 0x0FFF are marked reserved in The PowerPC Architecture book */ + /* these found in DINK code - may not apply to 8240*/ +#define EXC_OFF_PMI 0x0F00 /* Performance Monitoring Interrupt */ +#define EXC_OFF_VMXUI 0x0F20 /* VMX (AltiVec) Unavailable Interrupt */ + + /* 0x1000 - 0x2FFF are implementation specific */ + /* these found in DINK code - may not apply to 8240 */ +#define EXC_OFF_ITME 0x1000 /* Instruction Translation Miss Exception */ +#define EXC_OFF_DLTME 0x1100 /* Data Load Translation Miss Exception */ +#define EXC_OFF_DSTME 0x1200 /* Data Store Translation Miss Exception */ +#define EXC_OFF_IABE 0x1300 /* Instruction Addr Breakpoint Exception */ +#define EXC_OFF_SMIE 0x1400 /* System Management Interrupt Exception */ +#define EXC_OFF_JMDDI 0x1600 /* Java Mode denorm detect Interr -- WTF??*/ +#define EXC_OFF_RMTE 0x2000 /* Run Mode or Trace Exception */ + +#define MAP_A_CONFIG_ADDR_HIGH 0x8000 /* Upper half of CONFIG_ADDR for Map A */ +#define MAP_A_CONFIG_ADDR_LOW 0x0CF8 /* Lower half of CONFIG_ADDR for Map A */ +#define MAP_A_CONFIG_DATA_HIGH 0x8000 /* Upper half of CONFIG_DAT for Map A */ +#define MAP_A_CONFIG_DATA_LOW 0x0CFC /* Lower half of CONFIG_DAT for Map A */ +#define MAP_B_CONFIG_ADDR_HIGH 0xfec0 /* Upper half of CONFIG_ADDR for Map B */ +#define MAP_B_CONFIG_ADDR_LOW 0x0000 /* Lower half of CONFIG_ADDR for Map B */ +#define MAP_B_CONFIG_DATA_HIGH 0xfee0 /* Upper half of CONFIG_DAT for Map B */ +#define MAP_B_CONFIG_DATA_LOW 0x0000 /* Lower half of CONFIG_DAT for Map B */ + + +#if defined(CFG_ADDR_MAP_A) +#define CONFIG_ADDR_HIGH MAP_A_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */ +#define CONFIG_ADDR_LOW MAP_A_CONFIG_ADDR_LOW /* Lower half of CONFIG_ADDR */ +#define CONFIG_DATA_HIGH MAP_A_CONFIG_DATA_HIGH /* Upper half of CONFIG_DAT */ +#define CONFIG_DATA_LOW MAP_A_CONFIG_DATA_LOW /* Lower half of CONFIG_DAT */ +#else /* Assume Map B, default */ +#define CONFIG_ADDR_HIGH MAP_B_CONFIG_ADDR_HIGH /* Upper half of CONFIG_ADDR */ +#define CONFIG_ADDR_LOW MAP_B_CONFIG_ADDR_LOW /* Lower half of CONFIG_ADDR */ +#define CONFIG_DATA_HIGH MAP_B_CONFIG_DATA_HIGH /* Upper half of CONFIG_DAT */ +#define CONFIG_DATA_LOW MAP_B_CONFIG_DATA_LOW /* Lower half of CONFIG_DAT */ +#endif + +#define CONFIG_ADDR (CONFIG_ADDR_HIGH << 16 | CONFIG_ADDR_LOW) + +#define CONFIG_DATA (CONFIG_DATA_HIGH << 16 | CONFIG_DATA_LOW) + +/* Macros to write to config registers. addr should be a constant in all cases */ + +#define CONFIG_WRITE_BYTE( addr, data ) \ + __asm__ __volatile__( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + stb %3, %4(%2)\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \ + "b" (CONFIG_DATA), "r" (data), \ + "n" ((addr) & 3)); + +#define CONFIG_WRITE_HALFWORD( addr, data ) \ + __asm__ __volatile__( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + sthbrx %3, %4, %2\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" ((addr) & ~3), \ + "r" (CONFIG_DATA), "r" (data), \ + "b" ((addr) & 3)); + +/* this assumes it's writeing on word boundaries*/ +#define CONFIG_WRITE_WORD( addr, data ) \ + __asm__ __volatile__( \ + " stwbrx %1, 0, %0\n \ + sync\n \ + stwbrx %3, 0, %2\n \ + sync " \ + : /* no output */ \ + : "r" (CONFIG_ADDR), "r" (addr), \ + "r" (CONFIG_DATA), "r" (data)); + +/* Configuration register reads*/ + +#define CONFIG_READ_BYTE( addr, reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lbz %0, %4(%3)\n \ + sync " \ + : "=r" (reg) \ + : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \ + "b" (CONFIG_DATA), "n" ((addr) & 3)); + + +#define CONFIG_READ_HALFWORD( addr, reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lhbrx %0, %4, %3\n \ + sync " \ + : "=r" (reg) \ + : "r" ((addr) & ~3), "r" (CONFIG_ADDR), \ + "r" (CONFIG_DATA), \ + "b" ((addr) & 3)); + +/* this assumes it's reading on word boundaries*/ +#define CONFIG_READ_WORD( addr, reg ) \ + __asm__ ( \ + " stwbrx %1, 0, %2\n \ + sync\n \ + lwbrx %0, 0, %3\n \ + sync " \ + : "=r" (reg) \ + : "r" (addr), "r" (CONFIG_ADDR),\ + "r" (CONFIG_DATA)); + +/* + * configuration register 'addresses'. + * These are described in chaper 5 of the 8240 users manual. + * Where the register has an abreviation in the manual, this has + * been usaed here, otherwise a name in keeping with the norm has + * been invented. + * Note that some of these registers aren't documented in the manual. + */ + +#define PCICR 0x80000004 /* PCI Command Register */ +#define PCISR 0x80000006 /* PCI Status Register */ +#define REVID 0x80000008 /* CPU revision id */ +#define PIR 0x80000009 /* PCI Programming Interface Register */ +#define PBCCR 0x8000000b /* PCI Base Class Code Register */ +#define PCLSR 0x8000000c /* Processor Cache Line Size Register */ +#define PLTR 0x8000000d /* PCI Latancy Timer Register */ +#define PHTR 0x8000000e /* PCI Header Type Register */ +#define BISTCTRL 0x8000000f /* BIST Control */ +#define LMBAR 0x80000010 /* Local Base Addres Register */ +#define PCSRBAR 0x80000014 /* PCSR Base Address Register */ +#define ILR 0x8000003c /* PCI Interrupt Line Register */ +#define IPR 0x8000003d /* Interrupt Pin Register */ +#define MINGNT 0x8000003e /* MIN GNI */ +#define MAXLAT 0x8000003f /* MAX LAT */ +#define PCIACR 0x80000046 /* PCI Arbiter Control Register */ +#define PMCR1 0x80000070 /* Power management config. 1 */ +#define PMCR2 0x80000072 /* Power management config. 2 */ +#define ODCR 0x80000073 /* Output Driver Control Register */ +#define CLKDCR 0x80000074 /* CLK Driver Control Register */ +#if defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241) +#define MIOCR1 0x80000076 /* Miscellaneous I/O Control Register 1 */ +#define MIOCR2 0x80000077 /* Miscellaneous I/O Control Register 2 */ +#endif +#define EUMBBAR 0x80000078 /* Embedded Utilities Memory Block Base Address Register */ +#define EUMBBAR_VAL 0x80500000 /* PCI Relocation offset for EUMB region */ +#define EUMBSIZE 0x00100000 /* Size of EUMB region */ + +#define MSAR1 0x80000080 /* Memory Starting Address Register 1 */ +#define MSAR2 0x80000084 /* Memory Starting Address Register 2 */ +#define EMSAR1 0x80000088 /* Extended Memory Starting Address Register 1*/ +#define EMSAR2 0x8000008c /* Extended Memory Starting Address Register 2*/ +#define MEAR1 0x80000090 /* Memory Ending Address Register 1 */ +#define MEAR2 0x80000094 /* Memory Ending Address Register 2 */ +#define EMEAR1 0x80000098 /* Extended Memory Ending Address Register 1 */ +#define EMEAR2 0x8000009c /* Extended Memory Ending Address Register 2 */ +#define MBER 0x800000a0 /* Memory bank Enable Register*/ +#define MPMR 0x800000a3 /* Memory Page Mode Register (stores PGMAX) */ +#define PICR1 0x800000a8 /* Processor Interface Configuration Register 1 */ +#define PICR2 0x800000ac /* Processor Interface Configuration Register 2 */ +#define ECCSBECR 0x800000b8 /* ECC Single-Bit Error Counter Register */ +#define ECCSBETR 0x800000b8 /* ECC Single-Bit Error Trigger Register */ +#define ERRENR1 0x800000c0 /* Error Enableing Register 1 */ +#define ERRENR2 0x800000c4 /* Error Enableing Register 2 */ +#define ERRDR1 0x800000c1 /* Error Detection Register 1 */ +#define IPBESR 0x800000c3 /* Internal Processor Error Status Register */ +#define ERRDR2 0x800000c5 /* Error Detection Register 2 */ +#define PBESR 0x800000c7 /* PCI Bus Error Status Register */ +#define PBEAR 0x800000c8 /* Processor/PCI Bus Error Status Register */ +#define AMBOR 0x800000e0 /* Address Map B Options Register */ +#define MCCR1 0x800000f0 /* Memory Control Configuration Register 1 */ +#define MCCR2 0x800000f4 /* Memory Control Configuration Register 2 */ +#define MCCR3 0x800000f8 /* Memory Control Configuration Register 3 */ +#define MCCR4 0x800000fc /* Memory Control Configuration Register 4 */ + +/* some values for some of the above */ + +#define PICR1_CF_APARK 0x00000008 +#define PICR1_LE_MODE 0x00000020 +#define PICR1_ST_GATH_EN 0x00000040 +#if defined(CONFIG_MPC8240) +#define PICR1_EN_PCS 0x00000080 /* according to dink code, sets the 8240 to handle pci config space */ +#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241) +#define PICR1_NO_BUSW_CK 0x00000080 /* no bus width check for flash writes */ +#define PICR1_DEC 0x00000100 /* Time Base enable on 8245/8241 */ +#define ERCR1 0x800000d0 /* Extended ROM Configuration Register 1 */ +#define ERCR2 0x800000d4 /* Extended ROM Configuration Register 2 */ +#define ERCR3 0x800000d8 /* Extended ROM Configuration Register 3 */ +#define ERCR4 0x800000dc /* Extended ROM Configuration Register 4 */ +#define MIOCR1 0x80000076 /* Miscellaneous I/O Control Register 1 */ +#define MIOCR1_ADR_X 0x80000074 /* Miscellaneous I/O Control Register 1 */ +#define MIOCR1_SHIFT 2 +#define MIOCR2 0x80000077 /* Miscellaneous I/O Control Register 2 */ +#define MIOCR2_ADR_X 0x80000074 /* Miscellaneous I/O Control Register 1 */ +#define MIOCR2_SHIFT 3 +#define ODCR_ADR_X 0x80000070 /* Output Driver Control register */ +#define ODCR_SHIFT 3 +#define PMCR2_ADR 0x80000072 /* Power Mgmnt Cfg 2 register */ +#define PMCR2_ADR_X 0x80000070 +#define PMCR2_SHIFT 3 +#define PMCR1_ADR 0x80000070 /* Power Mgmnt Cfg 1 reister */ +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif +#define PICR1_CF_DPARK 0x00000200 +#define PICR1_MCP_EN 0x00000800 +#define PICR1_FLASH_WR_EN 0x00001000 +#ifdef CONFIG_MPC8240 +#define PICR1_ADDRESS_MAP 0x00010000 +#define PIRC1_MSK 0xff000000 +#endif +#define PICR1_PROC_TYPE_MSK 0x00060000 +#define PICR1_PROC_TYPE_603E 0x00040000 +#define PICR1_RCS0 0x00100000 + +#define PICR2_CF_SNOOP_WS_MASK 0x000c0000 +#define PICR2_CF_SNOOP_WS_0WS 0x00000000 +#define PICR2_CF_SNOOP_WS_1WS 0x00040000 +#define PICR2_CF_SNOOP_WS_2WS 0x00080000 +#define PICR2_CF_SNOOP_WS_3WS 0x000c0000 +#define PICR2_CF_APHASE_WS_MASK 0x0000000c +#define PICR2_CF_APHASE_WS_0WS 0x00000000 +#define PICR2_CF_APHASE_WS_1WS 0x00000004 +#define PICR2_CF_APHASE_WS_2WS 0x00000008 +#define PICR2_CF_APHASE_WS_3WS 0x0000000c + +#define MCCR1_ROMNAL_SHIFT 28 +#define MCCR1_ROMNAL_MSK 0xf0000000 +#define MCCR1_ROMFAL_SHIFT 23 +#define MCCR1_ROMFAL_MSK 0x0f800000 +#define MCCR1_DBUS_SIZE0 0x00400000 +#define MCCR1_BURST 0x00100000 +#define MCCR1_MEMGO 0x00080000 +#define MCCR1_SREN 0x00040000 +#if defined(CONFIG_MPC8240) +#define MCCR1_RAM_TYPE 0x00020000 +#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241) +#define MCCR1_SDRAM_EN 0x00020000 +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif +#define MCCR1_PCKEN 0x00010000 +#define MCCR1_BANK1ROW_SHIFT 2 +#define MCCR1_BANK2ROW_SHIFT 4 +#define MCCR1_BANK3ROW_SHIFT 6 +#define MCCR1_BANK4ROW_SHIFT 8 +#define MCCR1_BANK5ROW_SHIFT 10 +#define MCCR1_BANK6ROW_SHIFT 12 +#define MCCR1_BANK7ROW_SHIFT 14 + +#define MCCR2_TS_WAIT_TIMER_MSK 0xe0000000 +#define MCCR2_TS_WAIT_TIMER_SHIFT 29 +#define MCCR2_ASRISE_MSK 0x1e000000 +#define MCCR2_ASRISE_SHIFT 25 +#define MCCR2_ASFALL_MSK 0x01e00000 +#define MCCR2_ASFALL_SHIFT 21 + +#define MCCR2_INLINE_PAR_NOT_ECC 0x00100000 +#define MCCR2_WRITE_PARITY_CHK 0x00080000 +#define MCCR2_INLFRD_PARECC_CHK_EN 0x00040000 +#ifdef CONFIG_MPC8240 +#define MCCR2_ECC_EN 0x00020000 +#define MCCR2_EDO 0x00010000 +#endif +#define MCCR2_REFINT_MSK 0x0000fffc +#define MCCR2_REFINT_SHIFT 2 +#define MCCR2_RSV_PG 0x00000002 +#define MCCR2_PMW_PAR 0x00000001 + +#define MCCR3_BSTOPRE2TO5_MSK 0xf0000000 /*BSTOPRE[2-5]*/ +#define MCCR3_BSTOPRE2TO5_SHIFT 28 +#define MCCR3_REFREC_MSK 0x0f000000 +#define MCCR3_REFREC_SHIFT 24 +#ifdef CONFIG_MPC8240 +#define MCCR3_RDLAT_MSK 0x00f00000 +#define MCCR3_RDLAT_SHIFT 20 +#define MCCR3_CPX 0x00010000 +#define MCCR3_RAS6P_MSK 0x00078000 +#define MCCR3_RAS6P_SHIFT 15 +#define MCCR3_CAS5_MSK 0x00007000 +#define MCCR3_CAS5_SHIFT 12 +#define MCCR3_CP4_MSK 0x00000e00 +#define MCCR3_CP4_SHIFT 9 +#define MCCR3_CAS3_MSK 0x000001c0 +#define MCCR3_CAS3_SHIFT 6 +#define MCCR3_RCD2_MSK 0x00000038 +#define MCCR3_RCD2_SHIFT 3 +#define MCCR3_RP1_MSK 0x00000007 +#define MCCR3_RP1_SHIFT 0 +#endif + +#define MCCR4_PRETOACT_MSK 0xf0000000 +#define MCCR4_PRETOACT_SHIFT 28 +#define MCCR4_ACTTOPRE_MSK 0x0f000000 +#define MCCR4_ACTTOPRE_SHIFT 24 +#define MCCR4_WMODE 0x00800000 +#define MCCR4_INLINE 0x00400000 +#if defined(CONFIG_MPC8240) +#define MCCR4_BIT21 0x00200000 /* this include cos DINK code sets it- unknown function*/ +#elif defined(CONFIG_MPC8245) || defined(CONFIG_MPC8241) +#define MCCR4_EXTROM 0x00200000 /* enables Extended ROM space */ +#else +#error Specific type of MPC824x must be defined (i.e. CONFIG_MPC8240) +#endif +#define MCCR4_REGISTERED 0x00100000 +#define MCCR4_BSTOPRE0TO1_MSK 0x000c0000 /*BSTOPRE[0-1]*/ +#define MCCR4_BSTOPRE0TO1_SHIFT 18 +#define MCCR4_REGDIMM 0x00008000 +#define MCCR4_SDMODE_MSK 0x00007f00 +#define MCCR4_SDMODE_SHIFT 8 +#define MCCR4_ACTTORW_MSK 0x000000f0 +#define MCCR4_ACTTORW_SHIFT 4 +#define MCCR4_BSTOPRE6TO9_MSK 0x0000000f /*BSTOPRE[6-9]*/ +#define MCCR4_BSTOPRE6TO9_SHIFT 0 +#define MCCR4_DBUS_SIZE2_SHIFT 17 + +#define MICR_ADDR_MASK 0x0ff00000 +#define MICR_ADDR_SHIFT 20 +#define MICR_EADDR_MASK 0x30000000 +#define MICR_EADDR_SHIFT 28 + +#define BATU_BEPI_MSK 0xfffe0000 +#define BATU_BL_MSK 0x00001ffc + +#define BATU_BL_128K 0x00000000 +#define BATU_BL_256K 0x00000004 +#define BATU_BL_512K 0x0000000c +#define BATU_BL_1M 0x0000001c +#define BATU_BL_2M 0x0000003c +#define BATU_BL_4M 0x0000007c +#define BATU_BL_8M 0x000000fc +#define BATU_BL_16M 0x000001fc +#define BATU_BL_32M 0x000003fc +#define BATU_BL_64M 0x000007fc +#define BATU_BL_128M 0x00000ffc +#define BATU_BL_256M 0x00001ffc + +#define BATU_VS 0x00000002 +#define BATU_VP 0x00000001 + +#define BATL_BRPN_MSK 0xfffe0000 +#define BATL_WIMG_MSK 0x00000078 + +#define BATL_WRITETHROUGH 0x00000040 +#define BATL_CACHEINHIBIT 0x00000020 +#define BATL_MEMCOHERENCE 0x00000010 +#define BATL_GUARDEDSTORAGE 0x00000008 + +#define BATL_PP_MSK 0x00000003 +#define BATL_PP_00 0x00000000 /* No access */ +#define BATL_PP_01 0x00000001 /* Read-only */ +#define BATL_PP_10 0x00000002 /* Read-write */ +#define BATL_PP_11 0x00000003 + +/* + * I'd attempt to do defines for the PP bits, but it's use is a bit + * too complex, see the PowerPC Operating Environment Architecture + * section in the PowerPc arch book, chapter 4. + */ + +/*eumb and epic config*/ + +#define EPIC_FPR 0x00041000 +#define EPIC_GCR 0x00041020 +#define EPIC_EICR 0x00041030 +#define EPIC_EVI 0x00041080 +#define EPIC_PI 0x00041090 +#define EPIC_SVR 0x000410E0 +#define EPIC_TFRR 0x000410F0 + +/* + * Note the information for these is rather mangled in the 8240 manual. + * These are guesses. + */ + +#define EPIC_GTCCR0 0x00041100 +#define EPIC_GTCCR1 0x00041140 +#define EPIC_GTCCR2 0x00041180 +#define EPIC_GTCCR3 0x000411C0 +#define EPIC_GTBCR0 0x00041110 +#define EPIC_GTBCR1 0x00041150 +#define EPIC_GTBCR2 0x00041190 +#define EPIC_GTBCR3 0x000411D0 +#define EPIC_GTVPR0 0x00041120 +#define EPIC_GTVPR1 0x00041160 +#define EPIC_GTVPR2 0x000411a0 +#define EPIC_GTVPR3 0x000411e0 +#define EPIC_GTDR0 0x00041130 +#define EPIC_GTDR1 0x00041170 +#define EPIC_GTDR2 0x000411b0 +#define EPIC_GTDR3 0x000411f0 + +#define EPIC_IVPR0 0x00050200 +#define EPIC_IVPR1 0x00050220 +#define EPIC_IVPR2 0x00050240 +#define EPIC_IVPR3 0x00050260 +#define EPIC_IVPR4 0x00050280 + +#define EPIC_SVPR0 0x00050200 +#define EPIC_SVPR1 0x00050220 +#define EPIC_SVPR2 0x00050240 +#define EPIC_SVPR3 0x00050260 +#define EPIC_SVPR4 0x00050280 +#define EPIC_SVPR5 0x000502A0 +#define EPIC_SVPR6 0x000502C0 +#define EPIC_SVPR7 0x000502E0 +#define EPIC_SVPR8 0x00050300 +#define EPIC_SVPR9 0x00050320 +#define EPIC_SVPRa 0x00050340 +#define EPIC_SVPRb 0x00050360 +#define EPIC_SVPRc 0x00050380 +#define EPIC_SVPRd 0x000503A0 +#define EPIC_SVPRe 0x000503C0 +#define EPIC_SVPRf 0x000503E0 + +/* MPC8240 Byte Swap/PCI Support Macros */ +#define BYTE_SWAP_16_BIT(x) ( (((x) & 0x00ff) << 8) | ( (x) >> 8) ) +#define LONGSWAP(x) ((((x) & 0x000000ff) << 24) | (((x) & 0x0000ff00) << 8)|\ + (((x) & 0x00ff0000) >> 8) | (((x) & 0xff000000) >> 24) ) +#define PCISWAP(x) LONGSWAP(x) + +#ifndef __ASSEMBLY__ + +/* + * MPC107 Support + * + */ +unsigned int mpc824x_mpc107_getreg(unsigned int regNum); +void mpc824x_mpc107_setreg(unsigned int regNum, unsigned int regVal); +void mpc824x_mpc107_write8(unsigned int address, unsigned char data); +void mpc824x_mpc107_write16(unsigned int address, unsigned short data); +void mpc824x_mpc107_write32(unsigned int address, unsigned int data); +unsigned char mpc824x_mpc107_read8(unsigned int address); +unsigned short mpc824x_mpc107_read16(unsigned int address); +unsigned int mpc824x_mpc107_read32(unsigned int address); +unsigned int mpc824x_eummbar_read(unsigned int regNum); +void mpc824x_eummbar_write(unsigned int regNum, unsigned int regVal); + +#ifdef CONFIG_PCI +struct pci_controller; +void pci_cpm824x_init(struct pci_controller* hose); +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __MPC824X_H__ */ diff --git a/include/pci.h b/include/pci.h new file mode 100644 index 0000000..4875375 --- /dev/null +++ b/include/pci.h @@ -0,0 +1,475 @@ +/* + * (C) Copyright 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Andreas Heppel <aheppel@sysgo.de> + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * aloong with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _PCI_H +#define _PCI_H + +/* + * Under PCI, each device has 256 bytes of configuration address space, + * of which the first 64 bytes are standardized as follows: + */ +#define PCI_VENDOR_ID 0x00 /* 16 bits */ +#define PCI_DEVICE_ID 0x02 /* 16 bits */ +#define PCI_COMMAND 0x04 /* 16 bits */ +#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */ +#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */ +#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */ +#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */ +#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */ +#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */ +#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */ +#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */ +#define PCI_COMMAND_SERR 0x100 /* Enable SERR */ +#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */ + +#define PCI_STATUS 0x06 /* 16 bits */ +#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */ +#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */ +#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */ +#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */ +#define PCI_STATUS_PARITY 0x100 /* Detected parity error */ +#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */ +#define PCI_STATUS_DEVSEL_FAST 0x000 +#define PCI_STATUS_DEVSEL_MEDIUM 0x200 +#define PCI_STATUS_DEVSEL_SLOW 0x400 +#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */ +#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */ +#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */ +#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */ +#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */ + +#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 + revision */ +#define PCI_REVISION_ID 0x08 /* Revision ID */ +#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */ +#define PCI_CLASS_DEVICE 0x0a /* Device class */ +#define PCI_CLASS_CODE 0x0b /* Device class code */ +#define PCI_CLASS_SUB_CODE 0x0a /* Device sub-class code */ + +#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */ +#define PCI_LATENCY_TIMER 0x0d /* 8 bits */ +#define PCI_HEADER_TYPE 0x0e /* 8 bits */ +#define PCI_HEADER_TYPE_NORMAL 0 +#define PCI_HEADER_TYPE_BRIDGE 1 +#define PCI_HEADER_TYPE_CARDBUS 2 + +#define PCI_BIST 0x0f /* 8 bits */ +#define PCI_BIST_CODE_MASK 0x0f /* Return result */ +#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */ +#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */ + +/* + * Base addresses specify locations in memory or I/O space. + * Decoded size can be determined by writing a value of + * 0xffffffff to the register, and reading it back. Only + * 1 bits are decoded. + */ +#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */ +#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */ +#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ +#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */ +#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */ +#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */ +#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */ +#define PCI_BASE_ADDRESS_SPACE_IO 0x01 +#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00 +#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06 +#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */ +#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */ +#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */ +#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */ +#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL) +#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL) +/* bit 1 is reserved if address_space = 1 */ + +/* Header type 0 (normal devices) */ +#define PCI_CARDBUS_CIS 0x28 +#define PCI_SUBSYSTEM_VENDOR_ID 0x2c +#define PCI_SUBSYSTEM_ID 0x2e +#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */ +#define PCI_ROM_ADDRESS_ENABLE 0x01 +#define PCI_ROM_ADDRESS_MASK (~0x7ffUL) + +#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */ + +/* 0x35-0x3b are reserved */ +#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */ +#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */ +#define PCI_MIN_GNT 0x3e /* 8 bits */ +#define PCI_MAX_LAT 0x3f /* 8 bits */ + +/* Header type 1 (PCI-to-PCI bridges) */ +#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */ +#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */ +#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */ +#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */ +#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */ +#define PCI_IO_LIMIT 0x1d +#define PCI_IO_RANGE_TYPE_MASK 0x0f /* I/O bridging type */ +#define PCI_IO_RANGE_TYPE_16 0x00 +#define PCI_IO_RANGE_TYPE_32 0x01 +#define PCI_IO_RANGE_MASK ~0x0f +#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */ +#define PCI_MEMORY_BASE 0x20 /* Memory range behind */ +#define PCI_MEMORY_LIMIT 0x22 +#define PCI_MEMORY_RANGE_TYPE_MASK 0x0f +#define PCI_MEMORY_RANGE_MASK ~0x0f +#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */ +#define PCI_PREF_MEMORY_LIMIT 0x26 +#define PCI_PREF_RANGE_TYPE_MASK 0x0f +#define PCI_PREF_RANGE_TYPE_32 0x00 +#define PCI_PREF_RANGE_TYPE_64 0x01 +#define PCI_PREF_RANGE_MASK ~0x0f +#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */ +#define PCI_PREF_LIMIT_UPPER32 0x2c +#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */ +#define PCI_IO_LIMIT_UPPER16 0x32 +/* 0x34 same as for htype 0 */ +/* 0x35-0x3b is reserved */ +#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */ +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_BRIDGE_CONTROL 0x3e +#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */ +#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */ +#define PCI_BRIDGE_CTL_NO_ISA 0x04 /* Disable bridging of ISA ports */ +#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */ +#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */ +#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */ +#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */ + +/* Header type 2 (CardBus bridges) */ +#define PCI_CB_CAPABILITY_LIST 0x14 +/* 0x15 reserved */ +#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */ +#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */ +#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */ +#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */ +#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */ +#define PCI_CB_MEMORY_BASE_0 0x1c +#define PCI_CB_MEMORY_LIMIT_0 0x20 +#define PCI_CB_MEMORY_BASE_1 0x24 +#define PCI_CB_MEMORY_LIMIT_1 0x28 +#define PCI_CB_IO_BASE_0 0x2c +#define PCI_CB_IO_BASE_0_HI 0x2e +#define PCI_CB_IO_LIMIT_0 0x30 +#define PCI_CB_IO_LIMIT_0_HI 0x32 +#define PCI_CB_IO_BASE_1 0x34 +#define PCI_CB_IO_BASE_1_HI 0x36 +#define PCI_CB_IO_LIMIT_1 0x38 +#define PCI_CB_IO_LIMIT_1_HI 0x3a +#define PCI_CB_IO_RANGE_MASK ~0x03 +/* 0x3c-0x3d are same as for htype 0 */ +#define PCI_CB_BRIDGE_CONTROL 0x3e +#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */ +#define PCI_CB_BRIDGE_CTL_SERR 0x02 +#define PCI_CB_BRIDGE_CTL_ISA 0x04 +#define PCI_CB_BRIDGE_CTL_VGA 0x08 +#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20 +#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */ +#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */ +#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200 +#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400 +#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40 +#define PCI_CB_SUBSYSTEM_ID 0x42 +#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */ +/* 0x48-0x7f reserved */ + +/* Capability lists */ + +#define PCI_CAP_LIST_ID 0 /* Capability ID */ +#define PCI_CAP_ID_PM 0x01 /* Power Management */ +#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */ +#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */ +#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */ +#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */ +#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */ +#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */ +#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */ +#define PCI_CAP_SIZEOF 4 + +/* Power Management Registers */ + +#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */ +#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */ +#define PCI_PM_CAP_AUX_POWER 0x0010 /* Auxilliary power support */ +#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */ +#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */ +#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */ +#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */ +#define PCI_PM_CTRL 4 /* PM control and status register */ +#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */ +#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */ +#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */ +#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */ +#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */ +#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */ +#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */ +#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */ +#define PCI_PM_DATA_REGISTER 7 /* (??) */ +#define PCI_PM_SIZEOF 8 + +/* AGP registers */ + +#define PCI_AGP_VERSION 2 /* BCD version number */ +#define PCI_AGP_RFU 3 /* Rest of capability flags */ +#define PCI_AGP_STATUS 4 /* Status register */ +#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */ +#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */ +#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */ +#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */ +#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */ +#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */ +#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */ +#define PCI_AGP_COMMAND 8 /* Control register */ +#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */ +#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */ +#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */ +#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */ +#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */ +#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */ +#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 4x rate */ +#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 4x rate */ +#define PCI_AGP_SIZEOF 12 + +/* Slot Identification */ + +#define PCI_SID_ESR 2 /* Expansion Slot Register */ +#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */ +#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */ +#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */ + +/* Message Signalled Interrupts registers */ + +#define PCI_MSI_FLAGS 2 /* Various flags */ +#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */ +#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */ +#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */ +#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */ +#define PCI_MSI_RFU 3 /* Rest of capability flags */ +#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */ +#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */ +#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */ +#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */ + +#define PCI_MAX_PCI_DEVICES 32 +#define PCI_MAX_PCI_FUNCTIONS 8 + +/* Include the ID list */ + +#include <pci_ids.h> + +struct pci_region { + unsigned long bus_start; /* Start on the bus */ + unsigned long phys_start; /* Start in physical address space */ + unsigned long size; /* Size */ + unsigned long flags; /* Resource flags */ + + unsigned long bus_lower; +}; + +#define PCI_REGION_MEM 0x00000000 /* PCI memory space */ +#define PCI_REGION_IO 0x00000001 /* PCI IO space */ +#define PCI_REGION_TYPE 0x00000001 + +#define PCI_REGION_MEMORY 0x00000100 /* System memory */ +#define PCI_REGION_RO 0x00000200 /* Read-only memory */ + +extern __inline__ void pci_set_region(struct pci_region *reg, + unsigned long bus_start, + unsigned long phys_start, + unsigned long size, + unsigned long flags) { + reg->bus_start = bus_start; + reg->phys_start = phys_start; + reg->size = size; + reg->flags = flags; +} + +typedef int pci_dev_t; + +#define PCI_BUS(d) (((d) >> 16) & 0xff) +#define PCI_DEV(d) (((d) >> 11) & 0x1f) +#define PCI_FUNC(d) (((d) >> 8) & 0x7) +#define PCI_BDF(b,d,f) ((b) << 16 | (d) << 11 | (f) << 8) + +#define PCI_ANY_ID (~0) + +struct pci_device_id { + unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ +}; + +struct pci_controller; + +struct pci_config_table { + unsigned int vendor, device; /* Vendor and device ID or PCI_ANY_ID */ + unsigned int class; /* Class ID, or PCI_ANY_ID */ + unsigned int bus; /* Bus number, or PCI_ANY_ID */ + unsigned int dev; /* Device number, or PCI_ANY_ID */ + unsigned int func; /* Function number, or PCI_ANY_ID */ + + void (*config_device)(struct pci_controller* hose, pci_dev_t dev, + struct pci_config_table *); + unsigned long priv[3]; +}; + +extern void pci_cfgfunc_nothing(struct pci_controller* hose, pci_dev_t dev, + struct pci_config_table *); +extern void pci_cfgfunc_config_device(struct pci_controller* hose, pci_dev_t dev, + struct pci_config_table *); + +#define MAX_PCI_REGIONS 7 + +/* + * Structure of a PCI controller (host bridge) + */ +struct pci_controller { + struct pci_controller *next; + + int first_busno; + int last_busno; + + volatile unsigned int *cfg_addr; + volatile unsigned char *cfg_data; + + struct pci_region regions[MAX_PCI_REGIONS]; + int region_count; + + struct pci_config_table *config_table; + + void (*fixup_irq)(struct pci_controller *, pci_dev_t); + + /* Low-level architecture-dependent routines */ + int (*read_byte)(struct pci_controller*, pci_dev_t, int where, u8 *); + int (*read_word)(struct pci_controller*, pci_dev_t, int where, u16 *); + int (*read_dword)(struct pci_controller*, pci_dev_t, int where, u32 *); + int (*write_byte)(struct pci_controller*, pci_dev_t, int where, u8); + int (*write_word)(struct pci_controller*, pci_dev_t, int where, u16); + int (*write_dword)(struct pci_controller*, pci_dev_t, int where, u32); + + /* Used by auto config */ + struct pci_region *pci_mem, *pci_io; + + /* Used by ppc405 autoconfig*/ + struct pci_region *pci_fb; +}; + +extern __inline__ void pci_set_ops(struct pci_controller *hose, + int (*read_byte)(struct pci_controller*, + pci_dev_t, int where, u8 *), + int (*read_word)(struct pci_controller*, + pci_dev_t, int where, u16 *), + int (*read_dword)(struct pci_controller*, + pci_dev_t, int where, u32 *), + int (*write_byte)(struct pci_controller*, + pci_dev_t, int where, u8), + int (*write_word)(struct pci_controller*, + pci_dev_t, int where, u16), + int (*write_dword)(struct pci_controller*, + pci_dev_t, int where, u32)) { + hose->read_byte = read_byte; + hose->read_word = read_word; + hose->read_dword = read_dword; + hose->write_byte = write_byte; + hose->write_word = write_word; + hose->write_dword = write_dword; +} + +extern void pci_setup_indirect(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data); + +extern unsigned long pci_hose_bus_to_phys(struct pci_controller* hose, + unsigned long addr, unsigned long flags); +extern unsigned long pci_hose_phys_to_bus(struct pci_controller* hose, + unsigned long addr, unsigned long flags); + +#define pci_phys_to_bus(dev, addr, flags) \ + pci_hose_phys_to_bus(pci_bus_to_hose(PCI_BUS(dev)), (addr), (flags)) +#define pci_bus_to_phys(dev, addr, flags) \ + pci_hose_bus_to_phys(pci_bus_to_hose(PCI_BUS(dev)), (addr), (flags)) + +#define pci_phys_to_mem(dev, addr) pci_phys_to_bus((dev), (addr), PCI_REGION_MEM) +#define pci_mem_to_phys(dev, addr) pci_bus_to_phys((dev), (addr), PCI_REGION_MEM) +#define pci_phys_to_io(dev, addr) pci_phys_to_bus((dev), (addr), PCI_REGION_IO) +#define pci_io_to_phys(dev, addr) pci_bus_to_phys((dev), (addr), PCI_REGION_IO) + +extern int pci_hose_read_config_byte(struct pci_controller *hose, + pci_dev_t dev, int where, u8 *val); +extern int pci_hose_read_config_word(struct pci_controller *hose, + pci_dev_t dev, int where, u16 *val); +extern int pci_hose_read_config_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u32 *val); +extern int pci_hose_write_config_byte(struct pci_controller *hose, + pci_dev_t dev, int where, u8 val); +extern int pci_hose_write_config_word(struct pci_controller *hose, + pci_dev_t dev, int where, u16 val); +extern int pci_hose_write_config_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u32 val); + +extern int pci_read_config_byte(pci_dev_t dev, int where, u8 *val); +extern int pci_read_config_word(pci_dev_t dev, int where, u16 *val); +extern int pci_read_config_dword(pci_dev_t dev, int where, u32 *val); +extern int pci_write_config_byte(pci_dev_t dev, int where, u8 val); +extern int pci_write_config_word(pci_dev_t dev, int where, u16 val); +extern int pci_write_config_dword(pci_dev_t dev, int where, u32 val); + +extern int pci_hose_read_config_byte_via_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u8 *val); +extern int pci_hose_read_config_word_via_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u16 *val); +extern int pci_hose_write_config_byte_via_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u8 val); +extern int pci_hose_write_config_word_via_dword(struct pci_controller *hose, + pci_dev_t dev, int where, u16 val); + +extern void pci_register_hose(struct pci_controller* hose); +extern struct pci_controller* pci_bus_to_hose(int bus); + +extern int pci_hose_scan(struct pci_controller *hose); +extern int pci_hose_scan_bus(struct pci_controller *hose, int bus); + +extern void pciauto_region_init(struct pci_region* res); +extern void pciauto_region_align(struct pci_region *res, unsigned long size); +extern int pciauto_region_allocate(struct pci_region* res, unsigned int size, unsigned int *bar); +extern void pciauto_setup_device(struct pci_controller *hose, + pci_dev_t dev, int bars_num, + struct pci_region *mem, + struct pci_region *io); +void pciauto_config_device(struct pci_controller *hose, pci_dev_t dev); + +extern pci_dev_t pci_find_device (unsigned int vendor, unsigned int device, int index); +extern pci_dev_t pci_find_devices (struct pci_device_id *ids, int index); + +extern int pci_hose_config_device(struct pci_controller *hose, + pci_dev_t dev, + unsigned long io, + unsigned long mem, + unsigned long command); + +#ifdef CONFIG_MPC824X +extern void pci_mpc824x_init (struct pci_controller *hose); +#endif + +#endif /* _PCI_H */ diff --git a/include/smiLynxEM.h b/include/smiLynxEM.h new file mode 100644 index 0000000..cdd2f24 --- /dev/null +++ b/include/smiLynxEM.h @@ -0,0 +1,179 @@ +/* + * (C) Copyright 1997-2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * smiLynxEM.h + * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator + * + * + * modification history + * -------------------- + * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>. + */ + +#ifndef _SMI_LYNX_EM_H_ +#define _SMI_LYNX_EM_H_ + +/* + * SMI 710/712 have 4MB internal RAM; SMI 810 2MB internal + 2MB external + */ +#define VIDEO_MEM_SIZE 0x400000 + +/* + * Supported video modes for SMI Lynx E/EM/EM+ + */ +#define VIDEO_MODES 7 +#define DUAL_800_600 0 /* SMI710:VGA1:75Hz (pitch=1600) */ + /* VGA2:60/120Hz (pitch=1600) */ + /* SMI810:VGA1:75Hz (pitch=1600) */ + /* VGA2:75Hz (pitch=1600) */ +#define DUAL_1024_768 1 /* VGA1:75Hz VGA2:73Hz (pitch=2048) */ +#define SINGLE_800_600 2 /* VGA1:75Hz (pitch=800) */ +#define SINGLE_1024_768 3 /* VGA1:75Hz (pitch=1024) */ +#define SINGLE_1280_1024 4 /* VGA1:75Hz (pitch=1280) */ +#define TV_MODE_CCIR 5 /* VGA1:50Hz (h=720;v=576;pitch=720) */ +#define TV_MODE_EIA 6 /* VGA1:60Hz (h=720;v=484;pitch=720) */ + + +/* + * ISA mapped regs + */ +#define SMI_INDX_C4 (pGD->isaBase + 0x03c4) /* index reg */ +#define SMI_DATA_C5 (pGD->isaBase + 0x03c5) /* data reg */ +#define SMI_INDX_D4 (pGD->isaBase + 0x03d4) /* index reg */ +#define SMI_DATA_D5 (pGD->isaBase + 0x03d5) /* data reg */ +#define SMI_INDX_CE (pGD->isaBase + 0x03ce) /* index reg */ +#define SMI_DATA_CF (pGD->isaBase + 0x03cf) /* data reg */ +#define SMI_LOCK_REG (pGD->isaBase + 0x03c3) /* unlock/lock ext crt reg */ +#define SMI_MISC_REG (pGD->isaBase + 0x03c2) /* misc reg */ +#define SMI_LUT_MASK (pGD->isaBase + 0x03c6) /* lut mask reg */ +#define SMI_LUT_START (pGD->isaBase + 0x03c8) /* lut start index */ +#define SMI_LUT_RGB (pGD->isaBase + 0x03c9) /* lut colors auto incr.*/ + + +/* + * Video processor control + */ +typedef struct { + unsigned int control; + unsigned int colorKey; + unsigned int colorKeyMask; + unsigned int start; + unsigned short offset; + unsigned short width; + unsigned int fifoPrio; + unsigned int fifoERL; + unsigned int YUVtoRGB; +} SmiVideoProc; + +/* + * Video window control + */ +typedef struct { + unsigned short top; + unsigned short left; + unsigned short bottom; + unsigned short right; + unsigned int srcStart; + unsigned short width; + unsigned short offset; + unsigned char hStretch; + unsigned char vStretch; +} SmiVideoWin; + +/* + * Capture port control + */ +typedef struct { + unsigned int control; + unsigned short topClip; + unsigned short leftClip; + unsigned short srcHeight; + unsigned short srcWidth; + unsigned int srcBufStart1; + unsigned int srcBufStart2; + unsigned short srcOffset; + unsigned short fifoControl; +} SmiCapturePort; + + +/******************************************************************************/ +/* Export Graphic Driver Control */ +/******************************************************************************/ + +typedef struct { + unsigned int isaBase; + unsigned int pciBase; + unsigned int dprBase; + unsigned int vprBase; + unsigned int cprBase; + unsigned int frameAdrs; + unsigned int memSize; + unsigned int mode; + unsigned int gdfIndex; + unsigned int gdfBytesPP; + unsigned int fg; + unsigned int bg; + unsigned int plnSizeX; + unsigned int plnSizeY; + unsigned int winSizeX; + unsigned int winSizeY; + char modeIdent[80]; +} GraphicDevice; + +extern GraphicDevice smi; + + +/******************************************************************************/ +/* Export Graphic Functions */ +/******************************************************************************/ + +void *video_hw_init (void); /* returns GraphicDevice struct or NULL */ + +void video_hw_bitblt ( + unsigned int bpp, /* bytes per pixel */ + unsigned int src_x, /* source pos x */ + unsigned int src_y, /* source pos y */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y /* frame height */ + ); + +void video_hw_rectfill ( + unsigned int bpp, /* bytes per pixel */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y, /* frame height */ + unsigned int color /* fill color */ + ); + +void video_set_lut ( + unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ); + +#endif /*_SMI_LYNX_EM_H_ */ diff --git a/include/spartan2.h b/include/spartan2.h new file mode 100644 index 0000000..42806e3 --- /dev/null +++ b/include/spartan2.h @@ -0,0 +1,90 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.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 + * + */ + +#ifndef _SPARTAN2_H_ +#define _SPARTAN2_H_ + +#include <xilinx.h> + +extern int Spartan2_load( Xilinx_desc *desc, void *image, size_t size ); +extern int Spartan2_dump( Xilinx_desc *desc, void *buf, size_t bsize ); +extern int Spartan2_info( Xilinx_desc *desc ); +extern int Spartan2_reloc( Xilinx_desc *desc, ulong reloc_off ); + +/* Slave Parallel Implementation function table */ +typedef struct { + Xilinx_pre_fn pre; + Xilinx_pgm_fn pgm; + Xilinx_init_fn init; + Xilinx_err_fn err; + Xilinx_done_fn done; + Xilinx_clk_fn clk; + Xilinx_cs_fn cs; + Xilinx_wr_fn wr; + Xilinx_rdata_fn rdata; + Xilinx_wdata_fn wdata; + Xilinx_busy_fn busy; + Xilinx_abort_fn abort; + Xilinx_post_fn post; + int relocated; +} Xilinx_Spartan2_Slave_Parallel_fns; + +/* Slave Serial Implementation function table */ +typedef struct { + Xilinx_pgm_fn pgm; + Xilinx_clk_fn clk; + Xilinx_rdata_fn rdata; + Xilinx_wdata_fn wdata; + int relocated; +} Xilinx_Spartan2_Slave_Serial_fns; + +/* Device Image Sizes + *********************************************************************/ +/* Spartan-II (2.5V) */ +#define XILINX_XC2S15_SIZE 197728/8 +#define XILINX_XC2S30_SIZE 336800/8 +#define XILINX_XC2S50_SIZE 559232/8 +#define XILINX_XC2S100_SIZE 781248/8 +#define XILINX_XC2S150_SIZE 1040128/8 + +/* Descriptor Macros + *********************************************************************/ +/* Spartan-II devices */ +#define XILINX_XC2S15_DESC(iface, fn_table, cookie) \ +{ Xilinx_Spartan2, iface, XILINX_XC2S15_SIZE, fn_table, cookie } + +#define XILINX_XC2S30_DESC(iface, fn_table, cookie) \ +{ Xilinx_Spartan2, iface, XILINX_XC2S30_SIZE, fn_table, cookie } + +#define XILINX_XC2S50_DESC(iface, fn_table, cookie) \ +{ Xilinx_Spartan2, iface, XILINX_XC2S50_SIZE, fn_table, cookie } + +#define XILINX_XC2S100_DESC(iface, fn_table, cookie) \ +{ Xilinx_Spartan2, iface, XILINX_XC2S100_SIZE, fn_table, cookie } + +#define XILINX_XC2S150_DESC(iface, fn_table, cookie) \ +{ Xilinx_Spartan2, iface, XILINX_XC2S150_SIZE, fn_table, cookie } + +#endif /* _SPARTAN2_H_ */ + diff --git a/include/status_led.h b/include/status_led.h new file mode 100644 index 0000000..9b2de3e --- /dev/null +++ b/include/status_led.h @@ -0,0 +1,263 @@ +/* + * (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 + */ + +/* + * The purpose of this code is to signal the operational status of a + * target which usually boots over the network; while running in + * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply + * message has been received, the LED is turned off. The Linux + * kernel, once it is running, will start blinking the LED again, + * with another frequency. + */ + +#ifndef _STATUS_LED_H_ +#define _STATUS_LED_H_ + +#ifdef CONFIG_STATUS_LED + +#define STATUS_LED_OFF 0 +#define STATUS_LED_BLINKING 1 +#define STATUS_LED_ON 2 + +void status_led_tick (unsigned long timestamp); +void status_led_set (int led, int state); + +/***** TQM8xxL ********************************************************/ +#if defined(CONFIG_TQM8xxL) +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00000001 +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/***** MVS v1 **********************************************************/ +#elif (defined(CONFIG_MVS) && CONFIG_MVS < 2) +# define STATUS_LED_PAR im_ioport.iop_pdpar +# define STATUS_LED_DIR im_ioport.iop_pddir +# undef STATUS_LED_ODR +# define STATUS_LED_DAT im_ioport.iop_pddat + +# define STATUS_LED_BIT 0x00000001 +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/***** ETX_094 ********************************************************/ +#elif defined(CONFIG_ETX094) + +# define STATUS_LED_PAR im_ioport.iop_pdpar +# define STATUS_LED_DIR im_ioport.iop_pddir +# undef STATUS_LED_ODR +# define STATUS_LED_DAT im_ioport.iop_pddat + +# define STATUS_LED_BIT 0x00000001 +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 0 /* LED on for bit == 0 */ + +# 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) + +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00000010 /* LED 0 is on PB.27 */ +# define STATUS_LED_PERIOD (1 * CFG_HZ) +# define STATUS_LED_STATE STATUS_LED_OFF +# define STATUS_LED_BIT1 0x00000020 /* LED 1 is on PB.26 */ +# define STATUS_LED_PERIOD1 (1 * CFG_HZ) +# define STATUS_LED_STATE1 STATUS_LED_OFF +/* IDE LED usable for other purposes, too */ +# define STATUS_LED_BIT2 0x00000008 /* LED 2 is on PB.28 */ +# define STATUS_LED_PERIOD2 (1 * CFG_HZ) +# define STATUS_LED_STATE2 STATUS_LED_OFF + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_ILOCK_SWITCH 0x00800000 /* ILOCK switch in IRQ4 */ + +# define STATUS_ILOCK_PERIOD (CFG_HZ / 10) /* about every 100 ms */ + +# define STATUS_LED_YELLOW 0 +# define STATUS_LED_GREEN 1 +# define STATUS_LED_BOOT 2 /* IDE LED used for boot status */ + +/***** IVML24 *********************************************************/ +#elif defined(CONFIG_IVML24) + +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00000010 /* LED 0 is on PB.27 */ +# define STATUS_LED_PERIOD (1 * CFG_HZ) +# define STATUS_LED_STATE STATUS_LED_OFF +# define STATUS_LED_BIT1 0x00000020 /* LED 1 is on PB.26 */ +# define STATUS_LED_PERIOD1 (1 * CFG_HZ) +# define STATUS_LED_STATE1 STATUS_LED_OFF +/* IDE LED usable for other purposes, too */ +# define STATUS_LED_BIT2 0x00000008 /* LED 2 is on PB.28 */ +# define STATUS_LED_PERIOD2 (1 * CFG_HZ) +# define STATUS_LED_STATE2 STATUS_LED_OFF + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_ILOCK_SWITCH 0x00004000 /* ILOCK is on PB.17 */ + +# define STATUS_ILOCK_PERIOD (CFG_HZ / 10) /* about every 100 ms */ + +# define STATUS_LED_YELLOW 0 +# define STATUS_LED_GREEN 1 +# define STATUS_LED_BOOT 2 /* IDE LED used for boot status */ + +/***** LANTEC *********************************************************/ +#elif defined(CONFIG_LANTEC) + +# define STATUS_LED_PAR im_ioport.iop_pdpar +# define STATUS_LED_DIR im_ioport.iop_pddir +# undef STATUS_LED_ODR +# define STATUS_LED_DAT im_ioport.iop_pddat + +# if CONFIG_LATEC < 2 +# define STATUS_LED_BIT 0x1000 +# else +# define STATUS_LED_BIT 0x0800 +# endif +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 0 /* LED on for bit == 0 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/***** PCU E and CCM ************************************************/ +#elif (defined(CONFIG_PCU_E) || defined(CONFIG_CCM)) + +# define STATUS_LED_PAR im_cpm.cp_pbpar +# define STATUS_LED_DIR im_cpm.cp_pbdir +# define STATUS_LED_ODR im_cpm.cp_pbodr +# define STATUS_LED_DAT im_cpm.cp_pbdat + +# define STATUS_LED_BIT 0x00010000 /* green LED is on PB.15 */ +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/***** ICU862 ********************************************************/ +#elif defined(CONFIG_ICU862) + +# 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 0x4000 /* LED 0 is on PA.1 */ +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING +# define STATUS_LED_BIT1 0x1000 /* LED 1 is on PA.3 */ +# define STATUS_LED_PERIOD1 (CFG_HZ) +# define STATUS_LED_STATE1 STATUS_LED_OFF + +# define STATUS_LED_ACTIVE 1 /* LED on for bit == 1 */ + +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/***** Someone else defines these *************************************/ +#elif defined(STATUS_LED_PAR) + + /* + * ADVICE: Define in your board configuration file rather than + * filling this file up with lots of custom board stuff. + */ + +/***** NetVia ********************************************************/ +#elif defined(CONFIG_NETVIA) + +#define STATUS_LED_PAR im_ioport.iop_pdpar +#define STATUS_LED_DIR im_ioport.iop_pddir +#undef STATUS_LED_ODR +#define STATUS_LED_DAT im_ioport.iop_pddat + +# define STATUS_LED_BIT 0x0080 /* PD.8 */ +# define STATUS_LED_PERIOD (CFG_HZ / 2) +# define STATUS_LED_STATE STATUS_LED_BLINKING + +# define STATUS_LED_BIT1 0x0040 /* PD.9 */ +# define STATUS_LED_PERIOD1 (CFG_HZ / 2) +# define STATUS_LED_STATE1 STATUS_LED_OFF + +# define STATUS_LED_ACTIVE 0 /* LED on for bit == 0 */ +# define STATUS_LED_BOOT 0 /* LED 0 used for boot status */ + +/************************************************************************/ +#else +# error Status LED configuration missing +#endif +/************************************************************************/ + +#endif /* CONFIG_STATUS_LED */ + +#endif /* _STATUS_LED_H_ */ diff --git a/include/video_fb.h b/include/video_fb.h new file mode 100644 index 0000000..a9e4275 --- /dev/null +++ b/include/video_fb.h @@ -0,0 +1,115 @@ + /* + * (C) Copyright 1997-2002 ELTEC Elektronik AG + * Frank Gottschling <fgottschling@eltec.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 + */ + +/* + * smiLynxEM.h + * Silicon Motion graphic interface for sm810/sm710/sm712 accelerator + * + * + * modification history + * -------------------- + * 04-18-2002 Rewritten for U-Boot <fgottschling@eltec.de>. + */ + +#ifndef _VIDEO_FB_H_ +#define _VIDEO_FB_H_ + +#define CONSOLE_BG_COL 0x00 +#define CONSOLE_FG_COL 0xa0 + +/* + * Graphic Data Format (GDF) bits for VIDEO_DATA_FORMAT + */ +#define GDF__8BIT_INDEX 0 +#define GDF_15BIT_555RGB 1 +#define GDF_16BIT_565RGB 2 +#define GDF_32BIT_X888RGB 3 +#define GDF_24BIT_888RGB 4 +#define GDF__8BIT_332RGB 5 + +/******************************************************************************/ +/* Export Graphic Driver Control */ +/******************************************************************************/ + +typedef struct { + unsigned int isaBase; + unsigned int pciBase; + unsigned int dprBase; + unsigned int vprBase; + unsigned int cprBase; + unsigned int frameAdrs; + unsigned int memSize; + unsigned int mode; + unsigned int gdfIndex; + unsigned int gdfBytesPP; + unsigned int fg; + unsigned int bg; + unsigned int plnSizeX; + unsigned int plnSizeY; + unsigned int winSizeX; + unsigned int winSizeY; + char modeIdent[80]; +} GraphicDevice; + + +/******************************************************************************/ +/* Export Graphic Functions */ +/******************************************************************************/ + +void *video_hw_init (void); /* returns GraphicDevice struct or NULL */ + +#ifdef VIDEO_HW_BITBLT +void video_hw_bitblt ( + unsigned int bpp, /* bytes per pixel */ + unsigned int src_x, /* source pos x */ + unsigned int src_y, /* source pos y */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y /* frame height */ + ); +#endif + +#ifdef VIDEO_HW_RECTFILL +void video_hw_rectfill ( + unsigned int bpp, /* bytes per pixel */ + unsigned int dst_x, /* dest pos x */ + unsigned int dst_y, /* dest pos y */ + unsigned int dim_x, /* frame width */ + unsigned int dim_y, /* frame height */ + unsigned int color /* fill color */ + ); +#endif + +void video_set_lut ( + unsigned int index, /* color number */ + unsigned char r, /* red */ + unsigned char g, /* green */ + unsigned char b /* blue */ + ); +#ifdef CONFIG_VIDEO_HW_CURSOR +void video_set_hw_cursor(int x, int y); /* x y in pixel */ +void video_init_hw_cursor(int font_width, int font_height); +#endif + +#endif /*_VIDEO_FB_H_ */ diff --git a/include/virtex2.h b/include/virtex2.h new file mode 100644 index 0000000..f59227b --- /dev/null +++ b/include/virtex2.h @@ -0,0 +1,120 @@ +/* + * (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 + * + */ + +#ifndef _VIRTEX2_H_ +#define _VIRTEX2_H_ + +#include <xilinx.h> + +extern int Virtex2_load( Xilinx_desc *desc, void *image, size_t size ); +extern int Virtex2_dump( Xilinx_desc *desc, void *buf, size_t bsize ); +extern int Virtex2_info( Xilinx_desc *desc ); +extern int Virtex2_reloc( Xilinx_desc *desc, ulong reloc_off ); + +/* + * Slave SelectMap Implementation function table. + */ +typedef struct { + Xilinx_pre_fn pre; + Xilinx_pgm_fn pgm; + Xilinx_init_fn init; + Xilinx_err_fn err; + Xilinx_done_fn done; + Xilinx_clk_fn clk; + Xilinx_cs_fn cs; + Xilinx_wr_fn wr; + Xilinx_rdata_fn rdata; + Xilinx_wdata_fn wdata; + Xilinx_busy_fn busy; + Xilinx_abort_fn abort; + Xilinx_post_fn post; + int relocated; +} Xilinx_Virtex2_Slave_SelectMap_fns; + +/* Slave Serial Implementation function table */ +typedef struct { + Xilinx_pgm_fn pgm; + Xilinx_clk_fn clk; + Xilinx_rdata_fn rdata; + Xilinx_wdata_fn wdata; + int relocated; +} Xilinx_Virtex2_Slave_Serial_fns; + +/* Device Image Sizes (in bytes) + *********************************************************************/ +#define XILINX_XC2V40_SIZE (338208 / 8) +#define XILINX_XC2V80_SIZE (597408 / 8) +#define XILINX_XC2V250_SIZE (1591584 / 8) +#define XILINX_XC2V500_SIZE (2557857 / 8) +#define XILINX_XC2V1000_SIZE (3749408 / 8) +#define XILINX_XC2V1500_SIZE (5166240 / 8) +#define XILINX_XC2V2000_SIZE (6808352 / 8) +#define XILINX_XC2V3000_SIZE (9589408 / 8) +#define XILINX_XC2V4000_SIZE (14220192 / 8) +#define XILINX_XC2V6000_SIZE (19752096 / 8) +#define XILINX_XC2V8000_SIZE (26185120 / 8) +#define XILINX_XC2V10000_SIZE (33519264 / 8) + +/* Descriptor Macros + *********************************************************************/ +#define XILINX_XC2V40_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V40_SIZE, fn_table, cookie } + +#define XILINX_XC2V80_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V80_SIZE, fn_table, cookie } + +#define XILINX_XC2V250_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V250_SIZE, fn_table, cookie } + +#define XILINX_XC2V500_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V500_SIZE, fn_table, cookie } + +#define XILINX_XC2V1000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V1000_SIZE, fn_table, cookie } + +#define XILINX_XC2V1500_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V1500_SIZE, fn_table, cookie } + +#define XILINX_XC2V2000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V2000_SIZE, fn_table, cookie } + +#define XILINX_XC2V3000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V3000_SIZE, fn_table, cookie } + +#define XILINX_XC2V4000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V4000_SIZE, fn_table, cookie } + +#define XILINX_XC2V6000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V6000_SIZE, fn_table, cookie } + +#define XILINX_XC2V8000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V8000_SIZE, fn_table, cookie } + +#define XILINX_XC2V10000_DESC(iface, fn_table, cookie) \ +{ Xilinx_Virtex2, iface, XILINX_XC2V10000_SIZE, fn_table, cookie } + +#endif /* _VIRTEX2_H_ */ + +/* vim: set ts=4 tw=78: */ diff --git a/include/xilinx.h b/include/xilinx.h new file mode 100644 index 0000000..b87cfe2 --- /dev/null +++ b/include/xilinx.h @@ -0,0 +1,102 @@ +/* + * (C) Copyright 2002 + * Rich Ireland, Enterasys Networks, rireland@enterasys.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 <fpga.h> + +#ifndef _XILINX_H_ +#define _XILINX_H_ + +/* Xilinx Model definitions + *********************************************************************/ +#define CFG_SPARTAN2 CFG_FPGA_DEV( 0x1 ) +#define CFG_VIRTEX_E CFG_FPGA_DEV( 0x2 ) +#define CFG_VIRTEX2 CFG_FPGA_DEV( 0x4 ) +#define CFG_XILINX_SPARTAN2 (CFG_FPGA_XILINX | CFG_SPARTAN2) +#define CFG_XILINX_VIRTEX_E (CFG_FPGA_XILINX | CFG_VIRTEX_E) +#define CFG_XILINX_VIRTEX2 (CFG_FPGA_XILINX | CFG_VIRTEX2) +/* XXX - Add new models here */ + + +/* Xilinx Interface definitions + *********************************************************************/ +#define CFG_XILINX_IF_SS CFG_FPGA_IF( 0x1 ) /* slave serial */ +#define CFG_XILINX_IF_MS CFG_FPGA_IF( 0x2 ) /* master serial */ +#define CFG_XILINX_IF_SP CFG_FPGA_IF( 0x4 ) /* slave parallel */ +#define CFG_XILINX_IF_JTAG CFG_FPGA_IF( 0x8 ) /* jtag */ +#define CFG_XILINX_IF_MSM CFG_FPGA_IF( 0x10 ) /* master selectmap */ +#define CFG_XILINX_IF_SSM CFG_FPGA_IF( 0x20 ) /* slave selectmap */ + +/* Xilinx types + *********************************************************************/ +typedef enum { /* typedef Xilinx_iface */ + min_xilinx_iface_type, /* low range check value */ + slave_serial, /* serial data and external clock */ + master_serial, /* serial data w/ internal clock (not used) */ + slave_parallel, /* parallel data w/ external latch */ + jtag_mode, /* jtag/tap serial (not used ) */ + master_selectmap, /* master SelectMap (virtex2) */ + slave_selectmap, /* slave SelectMap (virtex2) */ + max_xilinx_iface_type /* insert all new types before this */ +} Xilinx_iface; /* end, typedef Xilinx_iface */ + +typedef enum { /* typedef Xilinx_Family */ + min_xilinx_type, /* low range check value */ + Xilinx_Spartan2, /* Spartan-II Family */ + Xilinx_VirtexE, /* Virtex-E Family */ + Xilinx_Virtex2, /* Virtex2 Family */ + max_xilinx_type /* insert all new types before this */ +} Xilinx_Family; /* end, typedef Xilinx_Family */ + +typedef struct { /* typedef Xilinx_desc */ + Xilinx_Family family; /* part type */ + Xilinx_iface iface; /* interface type */ + size_t size; /* bytes of data part can accept */ + void * iface_fns; /* interface function table */ + int cookie; /* implementation specific cookie */ +} Xilinx_desc; /* end, typedef Xilinx_desc */ + +/* Generic Xilinx Functions + *********************************************************************/ +extern int xilinx_load( Xilinx_desc *desc, void *image, size_t size ); +extern int xilinx_dump( Xilinx_desc *desc, void *buf, size_t bsize ); +extern int xilinx_info( Xilinx_desc *desc ); +extern int xilinx_reloc( Xilinx_desc *desc, ulong reloc_offset ); + +/* Board specific implementation specific function types + *********************************************************************/ +typedef int (*Xilinx_pgm_fn)( int assert_pgm, int flush, int cookie ); +typedef int (*Xilinx_init_fn)( int cookie ); +typedef int (*Xilinx_err_fn)( int cookie ); +typedef int (*Xilinx_done_fn)( int cookie ); +typedef int (*Xilinx_clk_fn)( int assert_clk, int flush, int cookie ); +typedef int (*Xilinx_cs_fn)( int assert_cs, int flush, int cookie ); +typedef int (*Xilinx_wr_fn)( int assert_write, int flush, int cookie ); +typedef int (*Xilinx_rdata_fn)( unsigned char *data, int cookie ); +typedef int (*Xilinx_wdata_fn)( unsigned char data, int flush, int cookie ); +typedef int (*Xilinx_busy_fn)( int cookie ); +typedef int (*Xilinx_abort_fn)( int cookie ); +typedef int (*Xilinx_pre_fn)( int cookie ); +typedef int (*Xilinx_post_fn)( int cookie ); + +#endif /* _XILINX_H_ */ diff --git a/lib_arm/_udivsi3.S b/lib_arm/_udivsi3.S new file mode 100644 index 0000000..19454c1 --- /dev/null +++ b/lib_arm/_udivsi3.S @@ -0,0 +1,77 @@ +/* # 1 "libgcc1.S" */ +@ libgcc1 routines for ARM cpu. +@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) +dividend .req r0 +divisor .req r1 +result .req r2 +curbit .req r3 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + .text + .globl __udivsi3 + .type __udivsi3 ,function + .align 0 + __udivsi3 : + cmp divisor, #0 + beq Ldiv0 + mov curbit, #1 + mov result, #0 + cmp dividend, divisor + bcc Lgot_result +Loop1: + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. + cmp divisor, #0x10000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #4 + movcc curbit, curbit, lsl #4 + bcc Loop1 +Lbignum: + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. + cmp divisor, #0x80000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #1 + movcc curbit, curbit, lsl #1 + bcc Lbignum +Loop3: + @ Test for possible subtractions, and note which bits + @ are done in the result. On the final pass, this may subtract + @ too much from the dividend, but the result will be ok, since the + @ "bit" will have been shifted out at the bottom. + cmp dividend, divisor + subcs dividend, dividend, divisor + orrcs result, result, curbit + cmp dividend, divisor, lsr #1 + subcs dividend, dividend, divisor, lsr #1 + orrcs result, result, curbit, lsr #1 + cmp dividend, divisor, lsr #2 + subcs dividend, dividend, divisor, lsr #2 + orrcs result, result, curbit, lsr #2 + cmp dividend, divisor, lsr #3 + subcs dividend, dividend, divisor, lsr #3 + orrcs result, result, curbit, lsr #3 + cmp dividend, #0 @ Early termination? + movnes curbit, curbit, lsr #4 @ No, any more bits to do? + movne divisor, divisor, lsr #4 + bne Loop3 +Lgot_result: + mov r0, result + mov pc, lr +Ldiv0: + str lr, [sp, #-4]! + bl __div0 (PLT) + mov r0, #0 @ about as wrong as it could be + ldmia sp!, {pc} + .size __udivsi3 , . - __udivsi3 +/* # 235 "libgcc1.S" */ +/* # 320 "libgcc1.S" */ +/* # 421 "libgcc1.S" */ +/* # 433 "libgcc1.S" */ +/* # 456 "libgcc1.S" */ +/* # 500 "libgcc1.S" */ +/* # 580 "libgcc1.S" */ diff --git a/lib_arm/_umodsi3.S b/lib_arm/_umodsi3.S new file mode 100644 index 0000000..899ffbf --- /dev/null +++ b/lib_arm/_umodsi3.S @@ -0,0 +1,88 @@ +/* # 1 "libgcc1.S" */ +@ libgcc1 routines for ARM cpu. +@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk) +/* # 145 "libgcc1.S" */ +dividend .req r0 +divisor .req r1 +overdone .req r2 +curbit .req r3 +ip .req r12 +sp .req r13 +lr .req r14 +pc .req r15 + .text + .globl __umodsi3 + .type __umodsi3 ,function + .align 0 + __umodsi3 : + cmp divisor, #0 + beq Ldiv0 + mov curbit, #1 + cmp dividend, divisor + movcc pc, lr +Loop1: + @ Unless the divisor is very big, shift it up in multiples of + @ four bits, since this is the amount of unwinding in the main + @ division loop. Continue shifting until the divisor is + @ larger than the dividend. + cmp divisor, #0x10000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #4 + movcc curbit, curbit, lsl #4 + bcc Loop1 +Lbignum: + @ For very big divisors, we must shift it a bit at a time, or + @ we will be in danger of overflowing. + cmp divisor, #0x80000000 + cmpcc divisor, dividend + movcc divisor, divisor, lsl #1 + movcc curbit, curbit, lsl #1 + bcc Lbignum +Loop3: + @ Test for possible subtractions. On the final pass, this may + @ subtract too much from the dividend, so keep track of which + @ subtractions are done, we can fix them up afterwards... + mov overdone, #0 + cmp dividend, divisor + subcs dividend, dividend, divisor + cmp dividend, divisor, lsr #1 + subcs dividend, dividend, divisor, lsr #1 + orrcs overdone, overdone, curbit, ror #1 + cmp dividend, divisor, lsr #2 + subcs dividend, dividend, divisor, lsr #2 + orrcs overdone, overdone, curbit, ror #2 + cmp dividend, divisor, lsr #3 + subcs dividend, dividend, divisor, lsr #3 + orrcs overdone, overdone, curbit, ror #3 + mov ip, curbit + cmp dividend, #0 @ Early termination? + movnes curbit, curbit, lsr #4 @ No, any more bits to do? + movne divisor, divisor, lsr #4 + bne Loop3 + @ Any subtractions that we should not have done will be recorded in + @ the top three bits of "overdone". Exactly which were not needed + @ are governed by the position of the bit, stored in ip. + @ If we terminated early, because dividend became zero, + @ then none of the below will match, since the bit in ip will not be + @ in the bottom nibble. + ands overdone, overdone, #0xe0000000 + moveq pc, lr @ No fixups needed + tst overdone, ip, ror #3 + addne dividend, dividend, divisor, lsr #3 + tst overdone, ip, ror #2 + addne dividend, dividend, divisor, lsr #2 + tst overdone, ip, ror #1 + addne dividend, dividend, divisor, lsr #1 + mov pc, lr +Ldiv0: + str lr, [sp, #-4]! + bl __div0 (PLT) + mov r0, #0 @ about as wrong as it could be + ldmia sp!, {pc} + .size __umodsi3 , . - __umodsi3 +/* # 320 "libgcc1.S" */ +/* # 421 "libgcc1.S" */ +/* # 433 "libgcc1.S" */ +/* # 456 "libgcc1.S" */ +/* # 500 "libgcc1.S" */ +/* # 580 "libgcc1.S" */ diff --git a/lib_arm/armlinux.c b/lib_arm/armlinux.c new file mode 100644 index 0000000..e5b8faa --- /dev/null +++ b/lib_arm/armlinux.c @@ -0,0 +1,324 @@ +/* + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <cmd_boot.h> +#include <image.h> +#include <zlib.h> +#include <asm/byteorder.h> + +#include <asm/setup.h> +#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2) +#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size)) + +#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ + defined (CONFIG_CMDLINE_TAG) || \ + defined (CONFIG_INITRD_TAG) || \ + defined (CONFIG_VFD) +static void setup_start_tag(bd_t *bd); +static void setup_memory_tags(bd_t *bd); +static void setup_commandline_tag(bd_t *bd, char *commandline); +#if 0 +static void setup_ramdisk_tag(bd_t *bd); +#endif +static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end); +static void setup_end_tag(bd_t *bd); +#if defined (CONFIG_VFD) +static void setup_videolfb_tag(gd_t *gd); +#endif + + +static struct tag *params; +#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ + +extern image_header_t header; /* from cmd_bootm.c */ + + +void do_bootm_linux(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[], + ulong addr, ulong *len_ptr, int verify) +{ + DECLARE_GLOBAL_DATA_PTR; + + ulong len = 0, checksum; + ulong initrd_start, initrd_end; + ulong data; + void (*theKernel)(int zero, int arch); + image_header_t *hdr = &header; + bd_t *bd = gd->bd; +#ifdef CONFIG_CMDLINE_TAG + char *commandline = getenv("bootargs"); +#endif + + theKernel = (void (*)(int, int))ntohl(hdr->ih_ep); + + /* + * Check if there is an initrd image + */ + if (argc >= 3) { + addr = simple_strtoul(argv[2], NULL, 16); + + printf ("## Loading Ramdisk Image at %08lx ...\n", addr); + + /* Copy header so we can blank CRC field for re-calculation */ + memcpy (&header, (char *)addr, sizeof(image_header_t)); + + if (ntohl(hdr->ih_magic) != IH_MAGIC) { + printf ("Bad Magic Number\n"); + do_reset (cmdtp, flag, argc, argv); + } + + data = (ulong)&header; + len = sizeof(image_header_t); + + checksum = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = 0; + + if (crc32 (0, (char *)data, len) != checksum) { + printf ("Bad Header Checksum\n"); + do_reset (cmdtp, flag, argc, argv); + } + + print_image_hdr (hdr); + + data = addr + sizeof(image_header_t); + len = ntohl(hdr->ih_size); + + if (verify) { + ulong csum = 0; + + printf (" Verifying Checksum ... "); + csum = crc32 (0, (char *)data, len); + if (csum != ntohl(hdr->ih_dcrc)) { + printf ("Bad Data CRC\n"); + do_reset (cmdtp, flag, argc, argv); + } + printf ("OK\n"); + } + + if ((hdr->ih_os != IH_OS_LINUX) || + (hdr->ih_arch != IH_CPU_ARM) || + (hdr->ih_type != IH_TYPE_RAMDISK) ) { + printf ("No Linux ARM Ramdisk Image\n"); + do_reset (cmdtp, flag, argc, argv); + } + + /* + * Now check if we have a multifile image + */ + } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) { + ulong tail = ntohl(len_ptr[0]) % 4; + int i; + + /* skip kernel length and terminator */ + data = (ulong)(&len_ptr[2]); + /* skip any additional image length fields */ + for (i=1; len_ptr[i]; ++i) + data += 4; + /* add kernel length, and align */ + data += ntohl(len_ptr[0]); + if (tail) { + data += 4 - tail; + } + + len = ntohl(len_ptr[1]); + + } else { + /* + * no initrd image + */ + data = 0; + } + +#ifdef DEBUG + if (!data) { + printf ("No initrd\n"); + } +#endif + + if (data) { + initrd_start = data; + initrd_end = initrd_start + len; + } else { + initrd_start = 0; + initrd_end = 0; + } + +#ifdef DEBUG + printf ("## Transferring control to Linux (at address %08lx) ...\n", + (ulong)theKernel); +#endif + +#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ + defined (CONFIG_CMDLINE_TAG) || \ + defined (CONFIG_INITRD_TAG) || \ + defined (CONFIG_VFD) + setup_start_tag(bd); +#ifdef CONFIG_SETUP_MEMORY_TAGS + setup_memory_tags(bd); +#endif +#ifdef CONFIG_CMDLINE_TAG + setup_commandline_tag(bd, commandline); +#endif +#ifdef CONFIG_INITRD_TAG + setup_initrd_tag(bd, initrd_start, initrd_end); +#endif +#if 0 + setup_ramdisk_tag(bd); +#endif +#if defined (CONFIG_VFD) + setup_videolfb_tag(gd); +#endif + setup_end_tag(bd); +#endif + + /* we assume that the kernel is in place */ + printf("\nStarting kernel ...\n\n"); + + cleanup_before_linux(); + + theKernel(0, bd->bi_arch_number); +} + + +#if defined (CONFIG_SETUP_MEMORY_TAGS) || \ + defined (CONFIG_CMDLINE_TAG) || \ + defined (CONFIG_INITRD_TAG) || \ + defined (CONFIG_VFD) +static void setup_start_tag(bd_t *bd) +{ + params = (struct tag *)bd->bi_boot_params; + + params->hdr.tag = ATAG_CORE; + params->hdr.size = tag_size(tag_core); + + params->u.core.flags = 0; + params->u.core.pagesize = 0; + params->u.core.rootdev = 0; + + params = tag_next(params); +} + + +static void setup_memory_tags(bd_t *bd) +{ + int i; + + for(i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { + params->hdr.tag = ATAG_MEM; + params->hdr.size = tag_size(tag_mem32); + + params->u.mem.start = bd->bi_dram[i].start; + params->u.mem.size = bd->bi_dram[i].size; + + params = tag_next(params); + } +} + + +static void setup_commandline_tag(bd_t *bd, char *commandline) +{ + char *p; + + /* eat leading white space */ + for(p = commandline; *p == ' '; p++) + ; + + /* skip non-existent command lines so the kernel will still + * use its default command line. + */ + if(*p == '\0') + return; + + params->hdr.tag = ATAG_CMDLINE; + params->hdr.size = (sizeof(struct tag_header) + strlen(p) + 1 + 4) >> 2; + + strcpy(params->u.cmdline.cmdline, p); + + params = tag_next(params); +} + + +#ifndef ATAG_INITRD2 +#define ATAG_INITRD2 0x54420005 +#endif +static void setup_initrd_tag(bd_t *bd, ulong initrd_start, ulong initrd_end) +{ + /* an ATAG_INITRD node tells the kernel where the compressed + * ramdisk can be found. ATAG_RDIMG is a better name, actually. + */ + params->hdr.tag = ATAG_INITRD2; + params->hdr.size = tag_size(tag_initrd); + + params->u.initrd.start = initrd_start; + params->u.initrd.size = initrd_end - initrd_start; + + params = tag_next(params); +} + + +#if 0 +static void setup_ramdisk_tag(bd_t *bd) +{ + /* an ATAG_RAMDISK node tells the kernel how large the + * decompressed ramdisk will become. + */ + params->hdr.tag = ATAG_RAMDISK; + params->hdr.size = tag_size(tag_ramdisk); + + params->u.ramdisk.start = 0; + /*params->u.ramdisk.size = RAMDISK_SIZE; */ + params->u.ramdisk.flags = 1; /* automatically load ramdisk */ + + params = tag_next(params); +} +#endif /* 0 */ + +#if defined (CONFIG_VFD) +static void setup_videolfb_tag(gd_t *gd) +{ + /* An ATAG_VIDEOLFB node tells the kernel where and how large + * the framebuffer for video was allocated (among other things). + * Note that a _physical_ address is passed ! + * + * We only use it to pass the address and size, the other entries + * in the tag_videolfb are not of interest. + */ + params->hdr.tag = ATAG_VIDEOLFB; + params->hdr.size = tag_size(tag_videolfb); + + params->u.videolfb.lfb_base = (u32)gd->fb_base; + /* 7168 = 256*4*56/8 - actually 2 pages (8192 bytes) are allocated */ + params->u.videolfb.lfb_size = 7168; + + params = tag_next(params); +} +#endif + +static void setup_end_tag(bd_t *bd) +{ + params->hdr.tag = ATAG_NONE; + params->hdr.size = 0; +} + +#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */ diff --git a/lib_arm/board.c b/lib_arm/board.c new file mode 100644 index 0000000..e58529f --- /dev/null +++ b/lib_arm/board.c @@ -0,0 +1,382 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 + * Sysgo Real-Time Solutions, GmbH <www.elinos.com> + * Marius Groeger <mgroeger@sysgo.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <devices.h> +#include <version.h> +#include <net.h> + + +const char version_string[] = + U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; + +#ifdef CONFIG_DRIVER_CS8900 +extern void cs8900_get_enetaddr (uchar * addr); +#endif + +/* + * Begin and End of memory area for malloc(), and current "brk" + */ +static ulong mem_malloc_start = 0; +static ulong mem_malloc_end = 0; +static ulong mem_malloc_brk = 0; + +static void mem_malloc_init (ulong dest_addr) +{ + mem_malloc_start = dest_addr; + mem_malloc_end = dest_addr + CONFIG_MALLOC_SIZE; + mem_malloc_brk = mem_malloc_start; + + memset ((void *) mem_malloc_start, 0, + mem_malloc_end - mem_malloc_start); +} + +void *sbrk (ptrdiff_t increment) +{ + ulong old = mem_malloc_brk; + ulong new = old + increment; + + if ((new < mem_malloc_start) || (new > mem_malloc_end)) { + return (NULL); + } + mem_malloc_brk = new; + + return ((void *) old); +} + +/************************************************************************ + * Init Utilities * + ************************************************************************ + * Some of this code should be moved into the core functions, + * or dropped completely, + * but let's get it working (again) first... + */ + +static int init_baudrate (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + uchar tmp[64]; /* long enough for environment variables */ + int i = getenv_r ("baudrate", tmp, sizeof (tmp)); + + gd->baudrate = (i > 0) + ? (int) simple_strtoul (tmp, NULL, 10) + : CONFIG_BAUDRATE; + + return (0); +} + +static int display_banner (void) +{ + + printf ("\n\n%s\n\n", version_string); + printf ("U-Boot code: %08lX -> %08lX BSS: -> %08lX\n", + _armboot_start, _armboot_end_data, _armboot_end); +#ifdef CONFIG_MODEM_SUPPORT + puts ("Modem Support enabled\n"); +#endif +#ifdef CONFIG_USE_IRQ + printf ("IRQ Stack: %08lx\n", IRQ_STACK_START); + printf ("FIQ Stack: %08lx\n", FIQ_STACK_START); +#endif + return (0); +} + +/* + * WARNING: this code looks "cleaner" than the PowerPC version, but + * has the disadvantage that you either get nothing, or everything. + * On PowerPC, you might see "DRAM: " before the system hangs - which + * gives a simple yet clear indication which part of the + * initialization if failing. + */ +static int display_dram_config (void) +{ + DECLARE_GLOBAL_DATA_PTR; + int i; + + puts ("DRAM Configuration:\n"); + + for(i=0; i<CONFIG_NR_DRAM_BANKS; i++) { + printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start); + print_size (gd->bd->bi_dram[i].size, "\n"); + } + + return (0); +} + +static void display_flash_config (ulong size) +{ + puts ("Flash: "); + print_size (size, "\n"); +} + + + +/* + * Breath some life into the board... + * + * Initialize an SMC for serial comms, and carry out some hardware + * tests. + * + * The first part of initialization is running from Flash memory; + * its main purpose is to initialize the RAM so that we + * can relocate the monitor code to RAM. + */ + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ +typedef int (init_fnc_t) (void); + +init_fnc_t *init_sequence[] = { + cpu_init, /* basic cpu dependent setup */ + board_init, /* basic board dependent setup */ + interrupt_init, /* set up exceptions */ + env_init, /* initialize environment */ + init_baudrate, /* initialze baudrate settings */ + serial_init, /* serial communications setup */ + display_banner, + dram_init, /* configure available RAM banks */ + display_dram_config, + + NULL, +}; + +void start_armboot (void) +{ + DECLARE_GLOBAL_DATA_PTR; + + ulong size; + gd_t gd_data; + bd_t bd_data; + init_fnc_t **init_fnc_ptr; +#ifdef CONFIG_VFD + unsigned long addr; +#endif + + /* Pointer is writable since we allocated a register for it */ + gd = &gd_data; + memset (gd, 0, sizeof (gd_t)); + gd->bd = &bd_data; + memset (gd->bd, 0, sizeof (bd_t)); + + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)() != 0) { + hang (); + } + } + + /* configure available FLASH banks */ + size = flash_init (); + display_flash_config (size); + +#ifdef CONFIG_VFD +#ifndef PAGE_SIZE +#define PAGE_SIZE 4096 +#endif + /* + * reserve memory for VFD display (always full pages) + */ + /* armboot_real_end is defined in the board-specific linker script */ + addr = (_armboot_real_end + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); + size = vfd_setmem (addr); + gd->fb_base = addr; + /* round to the next page boundary */ + addr += size; + addr = (addr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1); + mem_malloc_init (addr); +#else + /* armboot_real_end is defined in the board-specific linker script */ + mem_malloc_init (_armboot_real_end); +#endif /* CONFIG_VFD */ + +#ifdef CONFIG_VFD + /* must do this after the framebuffer is allocated */ + drv_vfd_init(); +#endif + /* initialize environment */ + env_relocate (); + + /* IP Address */ + bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); + + /* MAC Address */ + { + int i; + ulong reg; + char *s, *e; + uchar tmp[64]; + + i = getenv_r ("ethaddr", tmp, sizeof (tmp)); + s = (i > 0) ? tmp : NULL; + + for (reg = 0; reg < 6; ++reg) { + bd_data.bi_enetaddr[reg] = s ? simple_strtoul (s, &e, 16) : 0; + if (s) + s = (*e) ? e + 1 : e; + } + } + +#if defined(CONFIG_MISC_INIT_R) + /* miscellaneous platform dependent initialisations */ + misc_init_r (); +#endif + + /* enable exceptions */ + enable_interrupts (); + +#ifdef CONFIG_DRIVER_CS8900 + if (!getenv ("ethaddr")) { + cs8900_get_enetaddr (gd->bd->bi_enetaddr); + } +#endif + +#ifdef BOARD_POST_INIT + board_post_init (); +#endif + + /* main_loop() can return to retry autoboot, if so just run it again. */ + for (;;) { + main_loop (); + } + + /* NOTREACHED - no way out of command loop except booting */ +} + +void hang (void) +{ + puts ("### ERROR ### Please RESET the board ###\n"); + for (;;); +} + +#ifdef CONFIG_MODEM_SUPPORT +/* called from main loop (common/main.c) */ +extern void dbg(const char *fmt, ...); +int mdm_init (void) +{ + char env_str[16]; + char *init_str; + int i; + extern char console_buffer[]; + static inline void mdm_readline(char *buf, int bufsiz); + extern void enable_putc(void); + extern int hwflow_onoff(int); + + enable_putc(); /* enable serial_putc() */ + +#ifdef CONFIG_HWFLOW + init_str = getenv("mdm_flow_control"); + if (init_str && (strcmp(init_str, "rts/cts") == 0)) + hwflow_onoff (1); + else + hwflow_onoff(-1); +#endif + + for (i = 1;;i++) { + sprintf(env_str, "mdm_init%d", i); + if ((init_str = getenv(env_str)) != NULL) { + serial_puts(init_str); + serial_puts("\n"); + for(;;) { + mdm_readline(console_buffer, CFG_CBSIZE); + dbg("ini%d: [%s]", i, console_buffer); + + if ((strcmp(console_buffer, "OK") == 0) || + (strcmp(console_buffer, "ERROR") == 0)) { + dbg("ini%d: cmd done", i); + break; + } else /* in case we are originating call ... */ + if (strncmp(console_buffer, "CONNECT", 7) == 0) { + dbg("ini%d: connect", i); + return 0; + } + } + } else + break; /* no init string - stop modem init */ + + udelay(100000); + } + + udelay(100000); + + /* final stage - wait for connect */ + for(;i > 1;) { /* if 'i' > 1 - wait for connection + message from modem */ + mdm_readline(console_buffer, CFG_CBSIZE); + dbg("ini_f: [%s]", console_buffer); + if (strncmp(console_buffer, "CONNECT", 7) == 0) { + dbg("ini_f: connected"); + return 0; + } + } + + return 0; +} + +/* 'inline' - We have to do it fast */ +static inline void mdm_readline(char *buf, int bufsiz) +{ + char c; + char *p; + int n; + + n = 0; + p = buf; + for(;;) { + c = serial_getc(); + + /* dbg("(%c)", c); */ + + switch(c) { + case '\r': + break; + case '\n': + *p = '\0'; + return; + + default: + if(n++ > bufsiz) { + *p = '\0'; + return; /* sanity check */ + } + *p = c; + p++; + break; + } + } +} +#endif /* CONFIG_MODEM_SUPPORT */ diff --git a/lib_generic/string.c b/lib_generic/string.c new file mode 100644 index 0000000..1e1e2e3 --- /dev/null +++ b/lib_generic/string.c @@ -0,0 +1,574 @@ +/* + * linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in <asm-xx/string.h> + * + * These are buggy as well.. + * + * * Fri Jun 25 1999, Ingo Oeser <ioe@informatik.tu-chemnitz.de> + * - Added strsep() which will replace strtok() soon (because strsep() is + * reentrant and should be faster). Use only strsep() in new code, please. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <linux/ctype.h> +#include <malloc.h> + +#ifdef CONFIG_ARM +#undef __HAVE_ARCH_MEMCMP +#undef __HAVE_ARCH_MEMCPY +#undef __HAVE_ARCH_MEMMOVE +#undef __HAVE_ARCH_MEMSET +#undef __HAVE_ARCH_BCOPY +#undef __HAVE_ARCH_STRCAT +#undef __HAVE_ARCH_STRCHR +#undef __HAVE_ARCH_STRCMP +#undef __HAVE_ARCH_STRCPY +#undef __HAVE_ARCH_STRLEN +#undef __HAVE_ARCH_STRNCPY +#else +#define __HAVE_ARCH_MEMCMP +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_BCOPY +#define __HAVE_ARCH_STRCAT +#define __HAVE_ARCH_STRCMP +#define __HAVE_ARCH_STRCPY +#define __HAVE_ARCH_STRLEN +#define __HAVE_ARCH_STRNCPY +#endif + +#ifndef __HAVE_ARCH_STRNICMP +/** + * strnicmp - Case insensitive, length-limited string comparison + * @s1: One string + * @s2: The other string + * @len: the maximum number of characters to compare + */ +int strnicmp(const char *s1, const char *s2, size_t len) +{ + /* Yes, Virginia, it had better be unsigned */ + unsigned char c1, c2; + + c1 = 0; c2 = 0; + if (len) { + do { + c1 = *s1; c2 = *s2; + s1++; s2++; + if (!c1) + break; + if (!c2) + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (--len); + } + return (int)c1 - (int)c2; +} +#endif + +char * ___strtok; + +#ifndef __HAVE_ARCH_STRCPY +/** + * strcpy - Copy a %NUL terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + */ +char * strcpy(char * dest,const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCPY +/** + * strncpy - Copy a length-limited, %NUL-terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: The maximum number of bytes to copy + * + * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. + * However, the result is not %NUL-terminated if the source exceeds + * @count bytes. + */ +char * strncpy(char * dest,const char *src,size_t count) +{ + char *tmp = dest; + + while (count-- && (*dest++ = *src++) != '\0') + /* nothing */; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCAT +/** + * strcat - Append one %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + */ +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCAT +/** + * strncat - Append a length-limited, %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + * @count: The maximum numbers of bytes to copy + * + * Note that in contrast to strncpy, strncat ensures the result is + * terminated. + */ +char * strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) { + *dest = '\0'; + break; + } + } + } + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCMP +/** + * strcmp - Compare two strings + * @cs: One string + * @ct: Another string + */ +int strcmp(const char * cs,const char * ct) +{ + register signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRNCMP +/** + * strncmp - Compare two length-limited strings + * @cs: One string + * @ct: Another string + * @count: The maximum number of bytes to compare + */ +int strncmp(const char * cs,const char * ct,size_t count) +{ + register signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRCHR +/** + * strchr - Find the first occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_STRRCHR +/** + * strrchr - Find the last occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRLEN +/** + * strlen - Find the length of a string + * @s: The string to be sized + */ +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRNLEN +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRDUP +char * strdup(const char *s) +{ + char *new; + + if ((s == NULL) || + ((new = malloc (strlen(s) + 1)) == NULL) ) { + return NULL; + } + + strcpy (new, s); + return new; +} +#endif + +#ifndef __HAVE_ARCH_STRSPN +/** + * strspn - Calculate the length of the initial substring of @s which only + * contain letters in @accept + * @s: The string to be searched + * @accept: The string to search for + */ +size_t strspn(const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) { + if (*p == *a) + break; + } + if (*a == '\0') + return count; + ++count; + } + + return count; +} +#endif + +#ifndef __HAVE_ARCH_STRPBRK +/** + * strpbrk - Find the first occurrence of a set of characters + * @cs: The string to be searched + * @ct: The characters to search for + */ +char * strpbrk(const char * cs,const char * ct) +{ + const char *sc1,*sc2; + + for( sc1 = cs; *sc1 != '\0'; ++sc1) { + for( sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *) sc1; + } + } + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRTOK +/** + * strtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * WARNING: strtok is deprecated, use strsep instead. + */ +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} +#endif + +#ifndef __HAVE_ARCH_STRSEP +/** + * strsep - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * strsep() updates @s to point after the token, ready for the next call. + * + * It returns empty tokens, too, behaving exactly like the libc function + * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. + * Same semantics, slimmer shape. ;) + */ +char * strsep(char **s, const char *ct) +{ + char *sbegin = *s, *end; + + if (sbegin == NULL) + return NULL; + + end = strpbrk(sbegin, ct); + if (end) + *end++ = '\0'; + *s = end; + + return sbegin; +} +#endif + +#ifndef __HAVE_ARCH_MEMSET +/** + * memset - Fill a region of memory with the given value + * @s: Pointer to the start of the area. + * @c: The byte to fill the area with + * @count: The size of the area. + * + * Do not use memset() to access IO space, use memset_io() instead. + */ +void * memset(void * s,int c,size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} +#endif + +#ifndef __HAVE_ARCH_BCOPY +/** + * bcopy - Copy one area of memory to another + * @src: Where to copy from + * @dest: Where to copy to + * @count: The size of the area. + * + * Note that this is the same as memcpy(), with the arguments reversed. + * memcpy() is the standard, bcopy() is a legacy BSD function. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +char * bcopy(const char * src, char * dest, int count) +{ + char *tmp = dest; + + while (count--) + *tmp++ = *src++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCPY +/** + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +void * memcpy(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMMOVE +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCMP +/** + * memcmp - Compare two areas of memory + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + */ +int memcmp(const void * cs,const void * ct,size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} +#endif + +#ifndef __HAVE_ARCH_MEMSCAN +/** + * memscan - Find a character in an area of memory. + * @addr: The memory area + * @c: The byte to search for + * @size: The size of the area. + * + * returns the address of the first occurrence of @c, or 1 byte past + * the area if @c is not found + */ +void * memscan(void * addr, int c, size_t size) +{ + unsigned char * p = (unsigned char *) addr; + + while (size) { + if (*p == c) + return (void *) p; + p++; + size--; + } + return (void *) p; +} +#endif + +#ifndef __HAVE_ARCH_STRSTR +/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char * strstr(const char * s1,const char * s2) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *) s1; + s1++; + } + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_MEMCHR +/** + * memchr - Find a character in an area of memory. + * @s: The memory area + * @c: The byte to search for + * @n: The size of the area. + * + * returns the address of the first occurrence of @c, or %NULL + * if @c is not found + */ +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *p = s; + while (n-- != 0) { + if ((unsigned char)c == *p++) { + return (void *)(p-1); + } + } + return NULL; +} + +#endif diff --git a/net/eth.c b/net/eth.c new file mode 100644 index 0000000..3b06440 --- /dev/null +++ b/net/eth.c @@ -0,0 +1,292 @@ +/* + * (C) Copyright 2001, 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <command.h> +#include <net.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) + +#ifdef CFG_GT_6426x +extern int gt6426x_eth_initialize(bd_t *bis); +#endif + +extern int eepro100_initialize(bd_t*); +extern int natsemi_initialize(bd_t*); +extern int ns8382x_initialize(bd_t*); +extern int dc21x4x_initialize(bd_t*); +extern int pcnet_initialize(bd_t*); +extern int fec_initialize(bd_t*); +extern int scc_initialize(bd_t*); + +static struct eth_device *eth_devices, *eth_current; + +struct eth_device *eth_get_dev(void) +{ + return eth_current; +} + +int eth_get_dev_index (void) +{ + struct eth_device *dev; + int num = 0; + + if (!eth_devices) { + return (-1); + } + + for (dev = eth_devices; dev; dev = dev->next) { + if (dev == eth_current) + break; + ++num; + } + + if (dev) { + return (num); + } + + return (0); +} + +int eth_register(struct eth_device* dev) +{ + struct eth_device *d; + + if (!eth_devices) { + eth_current = eth_devices = dev; + } else { + for (d=eth_devices; d->next!=eth_devices; d=d->next); + d->next = dev; + } + + dev->state = ETH_STATE_INIT; + dev->next = eth_devices; + + return 0; +} + +int eth_initialize(bd_t *bis) +{ + unsigned char enetvar[32], env_enetaddr[6]; + int i, eth_number = 0; + char *tmp, *end; + + eth_devices = NULL; + eth_current = NULL; + +#ifdef CONFIG_EEPRO100 + eepro100_initialize(bis); +#endif +#ifdef CONFIG_TULIP + dc21x4x_initialize(bis); +#endif +#ifdef CONFIG_PCNET + pcnet_initialize(bis); +#endif +#ifdef CFG_GT_6426x + gt6426x_eth_initialize(bis); +#endif +#ifdef CONFIG_NATSEMI + natsemi_initialize(bis); +#endif +#ifdef CONFIG_NS8382X + ns8382x_initialize(bis); +#endif +#ifdef SCC_ENET + scc_initialize(bis); +#endif +#ifdef FEC_ENET + fec_initialize(bis); +#endif + + if (!eth_devices) { + puts ("No ethernet found.\n"); + } else { + struct eth_device *dev = eth_devices; + char *ethprime = getenv ("ethprime"); + + do { + if (eth_number) + puts (", "); + + printf("%s", dev->name); + + if (ethprime && strcmp (dev->name, ethprime) == 0) { + eth_current = dev; + puts (" [PRIME]"); + } + + sprintf(enetvar, eth_number ? "eth%daddr" : "ethaddr", eth_number); + tmp = getenv (enetvar); + + for (i=0; i<6; i++) { + env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0; + if (tmp) + tmp = (*end) ? end+1 : end; + } + + if (memcmp(env_enetaddr, "\0\0\0\0\0\0", 6)) { + if (memcmp(dev->enetaddr, "\0\0\0\0\0\0", 6) && + memcmp(dev->enetaddr, env_enetaddr, 6)) + { + printf("\nWarning: %s HW address don't match:\n", dev->name); + printf("Address in SROM is " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + dev->enetaddr[0], dev->enetaddr[1], + dev->enetaddr[2], dev->enetaddr[3], + dev->enetaddr[4], dev->enetaddr[5]); + printf("Address in environment is " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + env_enetaddr[0], env_enetaddr[1], + env_enetaddr[2], env_enetaddr[3], + env_enetaddr[4], env_enetaddr[5]); + } + + memcpy(dev->enetaddr, env_enetaddr, 6); + } + + eth_number++; + dev = dev->next; + } while(dev != eth_devices); + + putc ('\n'); + } + + return eth_number; +} + +void eth_set_enetaddr(int num, char *addr) { + struct eth_device *dev; + unsigned char enetaddr[6]; + char *end; + int i; + +#ifdef DEBUG + printf("eth_set_enetaddr(num=%d, addr=%s)\n", num, addr); +#endif + if (!eth_devices) + return; + + for (i=0; i<6; i++) { + enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0; + if (addr) + addr = (*end) ? end+1 : end; + } + + dev = eth_devices; + while(num-- > 0) { + dev = dev->next; + + if (dev == eth_devices) + return; + } + +#ifdef DEBUG + printf("Setting new HW address on %s\n", dev->name); + printf("New Address is " + "%02X:%02X:%02X:%02X:%02X:%02X\n", + dev->enetaddr[0], dev->enetaddr[1], + dev->enetaddr[2], dev->enetaddr[3], + dev->enetaddr[4], dev->enetaddr[5]); +#endif + + memcpy(dev->enetaddr, enetaddr, 6); +} + +int eth_init(bd_t *bis) +{ + struct eth_device* old_current; + + if (!eth_current) + return 0; + + old_current = eth_current; + do { +#ifdef DEBUG + printf("Trying %s\n", eth_current->name); +#endif + + if (eth_current->init(eth_current, bis)) { + eth_current->state = ETH_STATE_ACTIVE; + + printf("%s configured\n", eth_current->name); + return 1; + } + +#ifdef DEBUG + puts ("FAIL\n"); +#endif + + eth_try_another(0); + } while (old_current != eth_current); + + return 0; +} + +void eth_halt(void) +{ + if (!eth_current) + return; + + eth_current->halt(eth_current); + + eth_current->state = ETH_STATE_PASSIVE; +} + +int eth_send(volatile void *packet, int length) +{ + if (!eth_current) + return -1; + + return eth_current->send(eth_current, packet, length); +} + +int eth_rx(void) +{ + if (!eth_current) + return -1; + + return eth_current->recv(eth_current); +} + +void eth_try_another(int first_restart) +{ + static struct eth_device *first_failed = NULL; + + if (!eth_current) + return; + + if (first_restart) + { + first_failed = eth_current; + } + + eth_current = eth_current->next; + + if (first_failed == eth_current) + { + NetRestartWrap = 1; + } +} + +#endif diff --git a/post/cache_8xx.S b/post/cache_8xx.S new file mode 100644 index 0000000..4c1c295 --- /dev/null +++ b/post/cache_8xx.S @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2002 Wolfgang Denk <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 <config.h> + +#ifdef CONFIG_POST +#if defined(CONFIG_MPC823) || \ + defined(CONFIG_MPC850) || \ + defined(CONFIG_MPC855) || \ + defined(CONFIG_MPC860) || \ + defined(CONFIG_MPC824X) + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#if CONFIG_POST & CFG_POST_CACHE + + .text + +cache_post_dinvalidate: + lis r10, IDC_INVALL@h + mtspr DC_CST, r10 + blr + +cache_post_iinvalidate: + lis r10, IDC_INVALL@h + mtspr IC_CST, r10 + isync + blr + +cache_post_ddisable: + lis r10, IDC_DISABLE@h + mtspr DC_CST, r10 + blr + +cache_post_dwb: + lis r10, IDC_ENABLE@h + mtspr DC_CST, r10 + lis r10, DC_CFWT@h + mtspr DC_CST, r10 + blr + +cache_post_dwt: + lis r10, IDC_ENABLE@h + mtspr DC_CST, r10 + lis r10, DC_SFWT@h + mtspr DC_CST, r10 + blr + +cache_post_idisable: + lis r10, IDC_DISABLE@h + mtspr IC_CST, r10 + isync + blr + +cache_post_ienable: + lis r10, IDC_ENABLE@h + mtspr IC_CST, r10 + isync + blr + +cache_post_iunlock: + lis r10, IDC_UNALL@h + mtspr IC_CST, r10 + isync + blr + +cache_post_ilock: + mtspr IC_ADR, r3 + lis r10, IDC_LDLCK@h + mtspr IC_CST, r10 + isync + blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the negative pattern to a cached area + * read the area + * + * The negative pattern must be read at the last step + */ + .global cache_post_test1 +cache_post_test1: + mflr r0 + stw r0, 4(r1) + + stwu r3, -4(r1) + stwu r4, -4(r1) + + bl cache_post_dwb + bl cache_post_dinvalidate + + /* Write the negative pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0xff + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + /* Read the test area */ + lwz r0, 0(r1) + mtctr r0 + lwz r4, 4(r1) + subi r4, r4, 1 + li r3, 0 +1: + lbzu r0, 1(r4) + cmpli cr0, r0, 0xff + beq 2f + li r3, -1 + b 3f +2: + bdnz 1b +3: + + bl cache_post_ddisable + bl cache_post_dinvalidate + + addi r1, r1, 8 + + lwz r0, 4(r1) + mtlr r0 + blr + +/* + * turn on the data cache + * switch the data cache to write-back or write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * turn off the data cache + * write the negative pattern to the area + * turn on the data cache + * read the area + * + * The negative pattern must be read at the last step + */ + .global cache_post_test2 +cache_post_test2: + mflr r0 + stw r0, 4(r1) + + stwu r3, -4(r1) + stwu r4, -4(r1) + + bl cache_post_dwb + bl cache_post_dinvalidate + + /* Write the zero pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0 + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_ddisable + + /* Write the negative pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0xff + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_dwb + + /* Read the test area */ + lwz r0, 0(r1) + mtctr r0 + lwz r4, 4(r1) + subi r4, r4, 1 + li r3, 0 +1: + lbzu r0, 1(r4) + cmpli cr0, r0, 0xff + beq 2f + li r3, -1 + b 3f +2: + bdnz 1b +3: + + bl cache_post_ddisable + bl cache_post_dinvalidate + + addi r1, r1, 8 + + lwz r0, 4(r1) + mtlr r0 + blr + +/* + * turn on the data cache + * switch the data cache to write-through mode + * invalidate the data cache + * write the zero pattern to a cached area + * flush the data cache + * write the negative pattern to the area + * turn off the data cache + * read the area + * + * The negative pattern must be read at the last step + */ + .global cache_post_test3 +cache_post_test3: + mflr r0 + stw r0, 4(r1) + + stwu r3, -4(r1) + stwu r4, -4(r1) + + bl cache_post_ddisable + bl cache_post_dinvalidate + + /* Write the zero pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0 + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_dwt + bl cache_post_dinvalidate + + /* Write the negative pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0xff + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_ddisable + bl cache_post_dinvalidate + + /* Read the test area */ + lwz r0, 0(r1) + mtctr r0 + lwz r4, 4(r1) + subi r4, r4, 1 + li r3, 0 +1: + lbzu r0, 1(r4) + cmpli cr0, r0, 0xff + beq 2f + li r3, -1 + b 3f +2: + bdnz 1b +3: + + addi r1, r1, 8 + + lwz r0, 4(r1) + mtlr r0 + blr + +/* + * turn on the data cache + * switch the data cache to write-back mode + * invalidate the data cache + * write the negative pattern to a cached area + * flush the data cache + * write the zero pattern to the area + * invalidate the data cache + * read the area + * + * The negative pattern must be read at the last step + */ + .global cache_post_test4 +cache_post_test4: + mflr r0 + stw r0, 4(r1) + + stwu r3, -4(r1) + stwu r4, -4(r1) + + bl cache_post_ddisable + bl cache_post_dinvalidate + + /* Write the negative pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0xff + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_dwb + bl cache_post_dinvalidate + + /* Write the zero pattern to the test area */ + lwz r0, 0(r1) + mtctr r0 + li r0, 0 + lwz r3, 4(r1) + subi r3, r3, 1 +1: + stbu r0, 1(r3) + bdnz 1b + + bl cache_post_ddisable + bl cache_post_dinvalidate + + /* Read the test area */ + lwz r0, 0(r1) + mtctr r0 + lwz r4, 4(r1) + subi r4, r4, 1 + li r3, 0 +1: + lbzu r0, 1(r4) + cmpli cr0, r0, 0xff + beq 2f + li r3, -1 + b 3f +2: + bdnz 1b +3: + + addi r1, r1, 8 + + lwz r0, 4(r1) + mtlr r0 + blr + +cache_post_test5_1: + li r3, 0 +cache_post_test5_2: + li r3, -1 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed +*/ + .global cache_post_test5 +cache_post_test5: + mflr r0 + stw r0, 4(r1) + + bl cache_post_ienable + bl cache_post_iunlock + bl cache_post_iinvalidate + + /* Compute r9 = cache_post_test5_reloc */ + bl cache_post_test5_reloc +cache_post_test5_reloc: + mflr r9 + + /* Copy the test instruction to cache_post_test5_data */ + lis r3, (cache_post_test5_1 - cache_post_test5_reloc)@h + ori r3, r3, (cache_post_test5_1 - cache_post_test5_reloc)@l + add r3, r3, r9 + lis r4, (cache_post_test5_data - cache_post_test5_reloc)@h + ori r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l + add r4, r4, r9 + lwz r0, 0(r3) + stw r0, 0(r4) + + bl cache_post_iinvalidate + + /* Lock the branch instruction */ + lis r3, (cache_post_test5_data - cache_post_test5_reloc)@h + ori r3, r3, (cache_post_test5_data - cache_post_test5_reloc)@l + add r3, r3, r9 + bl cache_post_ilock + + /* Replace the test instruction */ + lis r3, (cache_post_test5_2 - cache_post_test5_reloc)@h + ori r3, r3, (cache_post_test5_2 - cache_post_test5_reloc)@l + add r3, r3, r9 + lis r4, (cache_post_test5_data - cache_post_test5_reloc)@h + ori r4, r4, (cache_post_test5_data - cache_post_test5_reloc)@l + add r4, r4, r9 + lwz r0, 0(r3) + stw r0, 0(r4) + + bl cache_post_iinvalidate + + /* Execute to the test instruction */ +cache_post_test5_data: + nop + + bl cache_post_iunlock + + lwz r0, 4(r1) + mtlr r0 + blr + +cache_post_test6_1: + li r3, -1 +cache_post_test6_2: + li r3, 0 + +/* + * turn on the instruction cache + * unlock the entire instruction cache + * invalidate the instruction cache + * lock a branch instruction in the instruction cache + * replace the branch instruction with "nop" + * jump to the branch instruction + * check that the branch instruction was executed + */ + .global cache_post_test6 +cache_post_test6: + mflr r0 + stw r0, 4(r1) + + bl cache_post_ienable + bl cache_post_iunlock + bl cache_post_iinvalidate + + /* Compute r9 = cache_post_test6_reloc */ + bl cache_post_test6_reloc +cache_post_test6_reloc: + mflr r9 + + /* Copy the test instruction to cache_post_test6_data */ + lis r3, (cache_post_test6_1 - cache_post_test6_reloc)@h + ori r3, r3, (cache_post_test6_1 - cache_post_test6_reloc)@l + add r3, r3, r9 + lis r4, (cache_post_test6_data - cache_post_test6_reloc)@h + ori r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l + add r4, r4, r9 + lwz r0, 0(r3) + stw r0, 0(r4) + + bl cache_post_iinvalidate + + /* Replace the test instruction */ + lis r3, (cache_post_test6_2 - cache_post_test6_reloc)@h + ori r3, r3, (cache_post_test6_2 - cache_post_test6_reloc)@l + add r3, r3, r9 + lis r4, (cache_post_test6_data - cache_post_test6_reloc)@h + ori r4, r4, (cache_post_test6_data - cache_post_test6_reloc)@l + add r4, r4, r9 + lwz r0, 0(r3) + stw r0, 0(r4) + + bl cache_post_iinvalidate + + /* Execute to the test instruction */ +cache_post_test6_data: + nop + + lwz r0, 4(r1) + mtlr r0 + blr + +#endif /* CONFIG_MPC823 || MPC850 || MPC855 || MPC860 || MPC824X */ +#endif /* CONFIG_POST & CFG_POST_CACHE */ +#endif /* CONFIG_POST */ diff --git a/post/cpu.c b/post/cpu.c new file mode 100644 index 0000000..6b8fc6e --- /dev/null +++ b/post/cpu.c @@ -0,0 +1,132 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#ifdef CONFIG_POST + +#include <watchdog.h> +#include <post.h> + +#if CONFIG_POST & CFG_POST_CPU + +extern int cpu_post_test_cmp (void); +extern int cpu_post_test_cmpi (void); +extern int cpu_post_test_two (void); +extern int cpu_post_test_twox (void); +extern int cpu_post_test_three (void); +extern int cpu_post_test_threex (void); +extern int cpu_post_test_threei (void); +extern int cpu_post_test_andi (void); +extern int cpu_post_test_srawi (void); +extern int cpu_post_test_rlwnm (void); +extern int cpu_post_test_rlwinm (void); +extern int cpu_post_test_rlwimi (void); +extern int cpu_post_test_store (void); +extern int cpu_post_test_load (void); +extern int cpu_post_test_cr (void); +extern int cpu_post_test_b (void); +extern int cpu_post_test_multi (void); +extern int cpu_post_test_string (void); +extern int cpu_post_test_complex (void); + +ulong cpu_post_makecr (long v) +{ + ulong cr = 0; + + if (v < 0) + cr |= 0x80000000; + if (v > 0) + cr |= 0x40000000; + if (v == 0) + cr |= 0x20000000; + + return cr; +} + +int cpu_post_test (int flags) +{ + int ic = icache_status (); + int ret = 0; + + if (ic) + icache_disable (); + + if (ret == 0) + ret = cpu_post_test_cmp (); + if (ret == 0) + ret = cpu_post_test_cmpi (); + if (ret == 0) + ret = cpu_post_test_two (); + if (ret == 0) + ret = cpu_post_test_twox (); + if (ret == 0) + ret = cpu_post_test_three (); + if (ret == 0) + ret = cpu_post_test_threex (); + if (ret == 0) + ret = cpu_post_test_threei (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_andi (); + if (ret == 0) + ret = cpu_post_test_srawi (); + if (ret == 0) + ret = cpu_post_test_rlwnm (); + if (ret == 0) + ret = cpu_post_test_rlwinm (); + if (ret == 0) + ret = cpu_post_test_rlwimi (); + if (ret == 0) + ret = cpu_post_test_store (); + if (ret == 0) + ret = cpu_post_test_load (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_cr (); + if (ret == 0) + ret = cpu_post_test_b (); + if (ret == 0) + ret = cpu_post_test_multi (); + if (ret == 0) + ret = cpu_post_test_string (); + if (ret == 0) + ret = cpu_post_test_complex (); + + if (ic) + icache_enable (); + + return ret; +} + +#endif /* CONFIG_POST & CFG_POST_CPU */ +#endif /* CONFIG_POST */ diff --git a/post/cpu/b.c b/post/cpu/b.c new file mode 100644 index 0000000..1ae22cc --- /dev/null +++ b/post/cpu/b.c @@ -0,0 +1,197 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Branch instructions: b, bl, bc + * + * The first 2 instructions (b, bl) are verified by jumping + * to a fixed address and checking whether control was transfered + * to that very point. For the bl instruction the value of the + * link register is checked as well (using mfspr). + * To verify the bc instruction various combinations of the BI/BO + * fields, the CTR and the condition register values are + * checked. The list of such combinations is pre-built and + * linked in U-Boot at build time. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); +extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, + ulong cr); + +static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, + int pjump, int dec, int link, ulong pctr, ulong cr) +{ + int ret = 0; + ulong lr = 0; + ulong ctr = pctr; + ulong jump; + + unsigned long code[] = + { + ASM_MTCR(6), + ASM_MFLR(6), + ASM_MTCTR(3), + ASM_MTLR(4), + ASM_LI(5, 1), + ASM_3O(cmd, bo, bi, 8), + ASM_LI(5, 0), + ASM_MFCTR(3), + ASM_MFLR(4), + ASM_MTLR(6), + ASM_BLR, + }; + + cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); + + if (ret == 0) + ret = pjump == jump ? 0 : -1; + if (ret == 0) + { + if (dec) + ret = pctr == ctr + 1 ? 0 : -1; + else + ret = pctr == ctr ? 0 : -1; + } + if (ret == 0) + { + if (link) + ret = lr == (ulong) code + 24 ? 0 : -1; + else + ret = lr == 0 ? 0 : -1; + } + + return ret; +} + +int cpu_post_test_b (void) +{ + int ret = 0; + unsigned int i; + + if (ret == 0) + { + ulong code[] = + { + ASM_MFLR(4), + ASM_MTLR(3), + ASM_B(4), + ASM_MFLR(3), + ASM_MTLR(4), + ASM_BLR, + }; + ulong res; + + cpu_post_exec_11 (code, &res, 0); + + ret = res == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at b1 test !\n"); + } + } + + if (ret == 0) + { + ulong code[] = + { + ASM_MFLR(4), + ASM_MTLR(3), + ASM_BL(4), + ASM_MFLR(3), + ASM_MTLR(4), + ASM_BLR, + }; + ulong res; + + cpu_post_exec_11 (code, &res, 0); + + ret = res == (ulong)code + 12 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at b2 test !\n"); + } + } + + if (ret == 0) + { + ulong cc, cd; + int cond; + ulong ctr; + int link; + + i = 0; + + for (cc = 0; cc < 4 && ret == 0; cc++) + { + for (cd = 0; cd < 4 && ret == 0; cd++) + { + for (link = 0; link <= 1 && ret == 0; link++) + { + for (cond = 0; cond <= 1 && ret == 0; cond++) + { + for (ctr = 1; ctr <= 2 && ret == 0; ctr++) + { + int dec = cd < 2; + int cr = cond ? 0x80000000 : 0x00000000; + int jumpc = cc >= 2 || + (cc == 0 && !cond) || + (cc == 1 && cond); + int jumpd = cd >= 2 || + (cd == 0 && ctr != 1) || + (cd == 1 && ctr == 1); + int jump = jumpc && jumpd; + + ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, + (cc << 3) + (cd << 1), 0, jump, dec, link, + ctr, cr); + + if (ret != 0) + { + post_log ("Error at b3 test %d !\n", i); + } + + i++; + } + } + } + } + } + } + + return ret; +} + +#endif +#endif diff --git a/post/cpu/cmp.c b/post/cpu/cmp.c new file mode 100644 index 0000000..789a24c --- /dev/null +++ b/post/cpu/cmp.c @@ -0,0 +1,133 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Integer compare instructions: cmpw, cmplw + * + * To verify these instructions the test runs them with + * different combinations of operands, reads the condition + * register value and compares it with the expected one. + * The test contains a pre-built table + * containing the description of each test case: the instruction, + * the values of the operands, the condition field to save + * the result in and the expected result. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); + +static struct cpu_post_cmp_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong cr; + ulong res; +} cpu_post_cmp_table[] = +{ + { + OP_CMPW, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPW, + 123, + 133, + 3, + 0x08 + }, + { + OP_CMPW, + 123, + -133, + 4, + 0x04 + }, + { + OP_CMPLW, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPLW, + 123, + -133, + 3, + 0x08 + }, + { + OP_CMPLW, + 123, + 113, + 4, + 0x04 + }, +}; +static unsigned int cpu_post_cmp_size = + sizeof (cpu_post_cmp_table) / sizeof (struct cpu_post_cmp_s); + +int cpu_post_test_cmp (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_cmp_size && ret == 0; i++) + { + struct cpu_post_cmp_s *test = cpu_post_cmp_table + i; + unsigned long code[] = + { + ASM_2C(test->cmd, test->cr, 3, 4), + ASM_MFCR(3), + ASM_BLR + }; + ulong res; + + cpu_post_exec_12 (code, & res, test->op1, test->op2); + + ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cmp test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/cpu/cmpi.c b/post/cpu/cmpi.c new file mode 100644 index 0000000..e0c2aaf --- /dev/null +++ b/post/cpu/cmpi.c @@ -0,0 +1,133 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Integer compare instructions: cmpwi, cmplwi + * + * To verify these instructions the test runs them with + * different combinations of operands, reads the condition + * register value and compares it with the expected one. + * The test contains a pre-built table + * containing the description of each test case: the instruction, + * the values of the operands, the condition field to save + * the result in and the expected result. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); + +static struct cpu_post_cmpi_s +{ + ulong cmd; + ulong op1; + ushort op2; + ulong cr; + ulong res; +} cpu_post_cmpi_table[] = +{ + { + OP_CMPWI, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPWI, + 123, + 133, + 3, + 0x08 + }, + { + OP_CMPWI, + 123, + -133, + 4, + 0x04 + }, + { + OP_CMPLWI, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPLWI, + 123, + -133, + 3, + 0x08 + }, + { + OP_CMPLWI, + 123, + 113, + 4, + 0x04 + }, +}; +static unsigned int cpu_post_cmpi_size = + sizeof (cpu_post_cmpi_table) / sizeof (struct cpu_post_cmpi_s); + +int cpu_post_test_cmpi (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_cmpi_size && ret == 0; i++) + { + struct cpu_post_cmpi_s *test = cpu_post_cmpi_table + i; + unsigned long code[] = + { + ASM_1IC(test->cmd, test->cr, 3, test->op2), + ASM_MFCR(3), + ASM_BLR + }; + ulong res; + + cpu_post_exec_11 (code, & res, test->op1); + + ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cmpi test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/cpu/cr.c b/post/cpu/cr.c new file mode 100644 index 0000000..8e38729 --- /dev/null +++ b/post/cpu/cr.c @@ -0,0 +1,356 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Condition register istructions: mtcr, mfcr, mcrxr, + * crand, crandc, cror, crorc, crxor, + * crnand, crnor, creqv, mcrf + * + * The mtcrf/mfcr instructions is tested by loading different + * values into the condition register (mtcrf), moving its value + * to a general-purpose register (mfcr) and comparing this value + * with the expected one. + * The mcrxr instruction is tested by loading a fixed value + * into the XER register (mtspr), moving XER value to the + * condition register (mcrxr), moving it to a general-purpose + * register (mfcr) and comparing the value of this register with + * the expected one. + * The rest of instructions is tested by loading a fixed + * value into the condition register (mtcrf), executing each + * instruction several times to modify all 4-bit condition + * fields, moving the value of the conditional register to a + * general-purpose register (mfcr) and comparing it with the + * expected one. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); +extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); + +static ulong cpu_post_cr_table1[] = +{ + 0xaaaaaaaa, + 0x55555555, +}; +static unsigned int cpu_post_cr_size1 = + sizeof (cpu_post_cr_table1) / sizeof (ulong); + +static struct cpu_post_cr_s2 { + ulong xer; + ulong cr; +} cpu_post_cr_table2[] = +{ + { + 0xa0000000, + 1 + }, + { + 0x40000000, + 5 + }, +}; +static unsigned int cpu_post_cr_size2 = + sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2); + +static struct cpu_post_cr_s3 { + ulong cr; + ulong cs; + ulong cd; + ulong res; +} cpu_post_cr_table3[] = +{ + { + 0x01234567, + 0, + 4, + 0x01230567 + }, + { + 0x01234567, + 7, + 0, + 0x71234567 + }, +}; +static unsigned int cpu_post_cr_size3 = + sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3); + +static struct cpu_post_cr_s4 { + ulong cmd; + ulong cr; + ulong op1; + ulong op2; + ulong op3; + ulong res; +} cpu_post_cr_table4[] = +{ + { + OP_CRAND, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRAND, + 0x0000ffff, + 16, + 17, + 0, + 0x8000ffff + }, + { + OP_CRANDC, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRANDC, + 0x0000ffff, + 16, + 0, + 0, + 0x8000ffff + }, + { + OP_CROR, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CROR, + 0x0000ffff, + 0, + 1, + 0, + 0x0000ffff + }, + { + OP_CRORC, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRORC, + 0x0000ffff, + 0, + 0, + 0, + 0x8000ffff + }, + { + OP_CRXOR, + 0x0000ffff, + 0, + 0, + 0, + 0x0000ffff + }, + { + OP_CRXOR, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CRNAND, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CRNAND, + 0x0000ffff, + 16, + 17, + 0, + 0x0000ffff + }, + { + OP_CRNOR, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRNOR, + 0x0000ffff, + 0, + 1, + 0, + 0x8000ffff + }, + { + OP_CREQV, + 0x0000ffff, + 0, + 0, + 0, + 0x8000ffff + }, + { + OP_CREQV, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, +}; +static unsigned int cpu_post_cr_size4 = + sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4); + +int cpu_post_test_cr (void) +{ + int ret = 0; + unsigned int i; + unsigned long cr_sav; + + asm ( "mfcr %0" : "=r" (cr_sav) : ); + + for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++) + { + ulong cr = cpu_post_cr_table1[i]; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, cr); + + ret = res == cr ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr1 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++) + { + struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i; + ulong res; + ulong xer; + + unsigned long code[] = + { + ASM_MTXER(3), + ASM_MCRXR(test->cr), + ASM_MFCR(3), + ASM_MFXER(4), + ASM_BLR, + }; + + cpu_post_exec_21x (code, &res, &xer, test->xer); + + ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ? + 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr2 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++) + { + struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_MCRF(test->cd, test->cs), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, test->cr); + + ret = res == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr3 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++) + { + struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_12F(test->cmd, test->op3, test->op1, test->op2), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, test->cr); + + ret = res == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr4 test %d !\n", i); + } + } + + asm ( "mtcr %0" : : "r" (cr_sav)); + + return ret; +} + +#endif +#endif diff --git a/post/cpu/three.c b/post/cpu/three.c new file mode 100644 index 0000000..c2d7476 --- /dev/null +++ b/post/cpu/three.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Ternary instructions instr rD,rA,rB + * + * Arithmetic instructions: add, addc, adde, subf, subfc, subfe, + * mullw, mulhw, mulhwu, divw, divwu + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_three_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong res; +} cpu_post_three_table[] = +{ + { + OP_ADD, + 100, + 200, + 300 + }, + { + OP_ADD, + 100, + -200, + -100 + }, + { + OP_ADDC, + 100, + 200, + 300 + }, + { + OP_ADDC, + 100, + -200, + -100 + }, + { + OP_ADDE, + 100, + 200, + 300 + }, + { + OP_ADDE, + 100, + -200, + -100 + }, + { + OP_SUBF, + 100, + 200, + 100 + }, + { + OP_SUBF, + 300, + 200, + -100 + }, + { + OP_SUBFC, + 100, + 200, + 100 + }, + { + OP_SUBFC, + 300, + 200, + -100 + }, + { + OP_SUBFE, + 100, + 200, + 200 + ~100 + }, + { + OP_SUBFE, + 300, + 200, + 200 + ~300 + }, + { + OP_MULLW, + 200, + 300, + 200 * 300 + }, + { + OP_MULHW, + 0x10000000, + 0x10000000, + 0x1000000 + }, + { + OP_MULHWU, + 0x80000000, + 0x80000000, + 0x40000000 + }, + { + OP_DIVW, + -20, + 5, + -4 + }, + { + OP_DIVWU, + 0x8000, + 0x200, + 0x40 + }, +}; +static unsigned int cpu_post_three_size = + sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s); + +int cpu_post_test_three (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_three_size && ret == 0; i++) + { + struct cpu_post_three_s *test = cpu_post_three_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int reg2 = (reg + 2) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12(test->cmd, reg2, reg1, reg0), + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C, + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at three test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at three test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/cpu/threei.c b/post/cpu/threei.c new file mode 100644 index 0000000..79f0178 --- /dev/null +++ b/post/cpu/threei.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Ternary instructions instr rA,rS,UIMM + * + * Logic instructions: ori, oris, xori, xoris + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_threei_s +{ + ulong cmd; + ulong op1; + ushort op2; + ulong res; +} cpu_post_threei_table[] = +{ + { + OP_ORI, + 0x80000000, + 0xffff, + 0x8000ffff + }, + { + OP_ORIS, + 0x00008000, + 0xffff, + 0xffff8000 + }, + { + OP_XORI, + 0x8000ffff, + 0xffff, + 0x80000000 + }, + { + OP_XORIS, + 0x00008000, + 0xffff, + 0xffff8000 + }, +}; +static unsigned int cpu_post_threei_size = + sizeof (cpu_post_threei_table) / sizeof (struct cpu_post_threei_s); + +int cpu_post_test_threei (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_threei_size && ret == 0; i++) + { + struct cpu_post_threei_s *test = cpu_post_threei_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11IX(test->cmd, reg1, reg0, test->op2), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op1); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threei test %d !\n", i); + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/cpu/threex.c b/post/cpu/threex.c new file mode 100644 index 0000000..2c72063 --- /dev/null +++ b/post/cpu/threex.c @@ -0,0 +1,229 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Ternary instructions instr rA,rS,rB + * + * Logic instructions: or, orc, xor, nand, nor, eqv + * Shift instructions: slw, srw, sraw + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_threex_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong res; +} cpu_post_threex_table[] = +{ + { + OP_OR, + 0x1234, + 0x5678, + 0x1234 | 0x5678 + }, + { + OP_ORC, + 0x1234, + 0x5678, + 0x1234 | ~0x5678 + }, + { + OP_XOR, + 0x1234, + 0x5678, + 0x1234 ^ 0x5678 + }, + { + OP_NAND, + 0x1234, + 0x5678, + ~(0x1234 & 0x5678) + }, + { + OP_NOR, + 0x1234, + 0x5678, + ~(0x1234 | 0x5678) + }, + { + OP_EQV, + 0x1234, + 0x5678, + ~(0x1234 ^ 0x5678) + }, + { + OP_SLW, + 0x80, + 16, + 0x800000 + }, + { + OP_SLW, + 0x80, + 32, + 0 + }, + { + OP_SRW, + 0x800000, + 16, + 0x80 + }, + { + OP_SRW, + 0x800000, + 32, + 0 + }, + { + OP_SRAW, + 0x80000000, + 3, + 0xf0000000 + }, + { + OP_SRAW, + 0x8000, + 3, + 0x1000 + }, +}; +static unsigned int cpu_post_threex_size = + sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s); + +int cpu_post_test_threex (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_threex_size && ret == 0; i++) + { + struct cpu_post_threex_s *test = cpu_post_threex_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int reg2 = (reg + 2) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12X(test->cmd, reg2, reg1, reg0), + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C, + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threex test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threex test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/cpu/two.c b/post/cpu/two.c new file mode 100644 index 0000000..6075714 --- /dev/null +++ b/post/cpu/two.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Binary instructions instr rD,rA + * + * Logic instructions: neg + * Arithmetic instructions: addme, addze, subfme, subfze + + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_two_s +{ + ulong cmd; + ulong op; + ulong res; +} cpu_post_two_table[] = +{ + { + OP_NEG, + 3, + -3 + }, + { + OP_NEG, + 5, + -5 + }, + { + OP_ADDME, + 6, + 5 + }, + { + OP_ADDZE, + 5, + 5 + }, + { + OP_SUBFME, + 6, + ~6 - 1 + }, + { + OP_SUBFZE, + 5, + ~5 + }, +}; +static unsigned int cpu_post_two_size = + sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s); + +int cpu_post_test_two (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_two_size && ret == 0; i++) + { + struct cpu_post_two_s *test = cpu_post_two_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11(test->cmd, reg1, reg0), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11(test->cmd, reg1, reg0) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at two test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at two test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/cpu/twox.c b/post/cpu/twox.c new file mode 100644 index 0000000..48d9954 --- /dev/null +++ b/post/cpu/twox.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * CPU test + * Binary instructions instr rA,rS + * + * Logic instructions: cntlzw + * Arithmetic instructions: extsb, extsh + + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_twox_s +{ + ulong cmd; + ulong op; + ulong res; +} cpu_post_twox_table[] = +{ + { + OP_EXTSB, + 3, + 3 + }, + { + OP_EXTSB, + 0xff, + -1 + }, + { + OP_EXTSH, + 3, + 3 + }, + { + OP_EXTSH, + 0xff, + 0xff + }, + { + OP_EXTSH, + 0xffff, + -1 + }, + { + OP_CNTLZW, + 0x000fffff, + 12 + }, +}; +static unsigned int cpu_post_twox_size = + sizeof (cpu_post_twox_table) / sizeof (struct cpu_post_twox_s); + +int cpu_post_test_twox (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_twox_size && ret == 0; i++) + { + struct cpu_post_twox_s *test = cpu_post_twox_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11X(test->cmd, reg1, reg0), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11X(test->cmd, reg1, reg0) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at twox test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at twox test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/ether.c b/post/ether.c new file mode 100644 index 0000000..5b42ca7 --- /dev/null +++ b/post/ether.c @@ -0,0 +1,646 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* + * Ethernet test + * + * The Serial Communication Controllers (SCC) listed in ctlr_list array below + * are tested in the loopback ethernet mode. + * The controllers are configured accordingly and several packets + * are transmitted. The configurable test parameters are: + * MIN_PACKET_LENGTH - minimum size of packet to transmit + * MAX_PACKET_LENGTH - maximum size of packet to transmit + * TEST_NUM - number of tests + */ + +#ifdef CONFIG_POST + +#include <post.h> + +#if defined(CONFIG_8xx) +#include <commproc.h> +#elif defined(CONFIG_MPC8260) +#include <asm/cpm_8260.h> +#else +#error "Apparently a bad configuration, please fix." +#endif + +#include <command.h> +#include <net.h> + +#if CONFIG_POST & CFG_POST_ETHER + +#define MIN_PACKET_LENGTH 64 +#define MAX_PACKET_LENGTH 256 +#define TEST_NUM 1 + +#define CTLR_SCC 0 + +extern void spi_init_f (void); +extern void spi_init_r (void); + +/* The list of controllers to test */ +#if defined(CONFIG_MPC823) +static int ctlr_list[][2] = { {CTLR_SCC, 1} }; +#else +static int ctlr_list[][2] = { }; +#endif + +#define CTRL_LIST_SIZE (sizeof(ctlr_list) / sizeof(ctlr_list[0])) + +static struct { + void (*init) (int index); + int (*send) (int index, volatile void *packet, int length); + int (*recv) (int index, void *packet, int length); +} ctlr_proc[1]; + +static char *ctlr_name[1] = { "SCC" }; + +static int used_by_uart[1] = { -1 }; +static int used_by_ether[1] = { -1 }; + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 + +#define TX_BUF_CNT 2 + +#define TOUT_LOOP 100 + +static char txbuf[DBUF_LENGTH]; + +static uint rxIdx; /* index of the current RX buffer */ +static uint txIdx; /* index of the current TX buffer */ + +/* + * SCC Ethernet Tx and Rx buffer descriptors allocated at the + * immr->udata_bd address on Dual-Port RAM + * Provide for Double Buffering + */ + +typedef volatile struct CommonBufferDescriptor { + cbd_t rxbd[PKTBUFSRX]; /* Rx BD */ + cbd_t txbd[TX_BUF_CNT]; /* Tx BD */ +} RTXBD; + +static RTXBD *rtx; + + /* + * SCC callbacks + */ + +static void scc_init (int scc_index) +{ + DECLARE_GLOBAL_DATA_PTR; + bd_t *bd = gd->bd; + + static int proff[] = + { PROFF_SCC1, PROFF_SCC2, PROFF_SCC3, PROFF_SCC4 }; + static unsigned int cpm_cr[] = + { CPM_CR_CH_SCC1, CPM_CR_CH_SCC2, CPM_CR_CH_SCC3, +CPM_CR_CH_SCC4 }; + + int i; + scc_enet_t *pram_ptr; + + volatile immap_t *immr = (immap_t *) CFG_IMMR; + + immr->im_cpm.cp_scc[scc_index].scc_gsmrl &= + ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT); + +#if defined(CONFIG_FADS) +#if defined(CONFIG_MPC860T) + /* The FADS860T doesn't use the MODEM_EN or DATA_VOICE signals. */ + *((uint *) BCSR4) &= ~BCSR4_ETHLOOP; + *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL; + *((uint *) BCSR1) &= ~BCSR1_ETHEN; +#else + *((uint *) BCSR4) &= ~(BCSR4_ETHLOOP | BCSR4_MODEM_EN); + *((uint *) BCSR4) |= BCSR4_TFPLDL | BCSR4_TPSQEL | BCSR4_DATA_VOICE; + *((uint *) BCSR1) &= ~BCSR1_ETHEN; +#endif +#endif + + pram_ptr = (scc_enet_t *) & (immr->im_cpm.cp_dparam[proff[scc_index]]); + + rxIdx = 0; + txIdx = 0; + +#ifdef CFG_ALLOC_DPRAM + rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + + dpram_alloc_align (sizeof (RTXBD), 8)); +#else + rtx = (RTXBD *) (immr->im_cpm.cp_dpmem + CPM_SCC_BASE); +#endif + +#if 0 + +#if (defined(PA_ENET_RXD) && defined(PA_ENET_TXD)) + /* Configure port A pins for Txd and Rxd. + */ + immr->im_ioport.iop_papar |= (PA_ENET_RXD | PA_ENET_TXD); + immr->im_ioport.iop_padir &= ~(PA_ENET_RXD | PA_ENET_TXD); + immr->im_ioport.iop_paodr &= ~PA_ENET_TXD; +#elif (defined(PB_ENET_RXD) && defined(PB_ENET_TXD)) + /* Configure port B pins for Txd and Rxd. + */ + immr->im_cpm.cp_pbpar |= (PB_ENET_RXD | PB_ENET_TXD); + immr->im_cpm.cp_pbdir &= ~(PB_ENET_RXD | PB_ENET_TXD); + immr->im_cpm.cp_pbodr &= ~PB_ENET_TXD; +#else +#error Configuration Error: exactly ONE of PA_ENET_[RT]XD, PB_ENET_[RT]XD must be defined +#endif + +#if defined(PC_ENET_LBK) + /* Configure port C pins to disable External Loopback + */ + immr->im_ioport.iop_pcpar &= ~PC_ENET_LBK; + immr->im_ioport.iop_pcdir |= PC_ENET_LBK; + immr->im_ioport.iop_pcso &= ~PC_ENET_LBK; + immr->im_ioport.iop_pcdat &= ~PC_ENET_LBK; /* Disable Loopback */ +#endif /* PC_ENET_LBK */ + + /* Configure port C pins to enable CLSN and RENA. + */ + immr->im_ioport.iop_pcpar &= ~(PC_ENET_CLSN | PC_ENET_RENA); + immr->im_ioport.iop_pcdir &= ~(PC_ENET_CLSN | PC_ENET_RENA); + immr->im_ioport.iop_pcso |= (PC_ENET_CLSN | PC_ENET_RENA); + + /* Configure port A for TCLK and RCLK. + */ + immr->im_ioport.iop_papar |= (PA_ENET_TCLK | PA_ENET_RCLK); + immr->im_ioport.iop_padir &= ~(PA_ENET_TCLK | PA_ENET_RCLK); + + /* + * Configure Serial Interface clock routing -- see section 16.7.5.3 + * First, clear all SCC bits to zero, then set the ones we want. + */ + + immr->im_cpm.cp_sicr &= ~SICR_ENET_MASK; + immr->im_cpm.cp_sicr |= SICR_ENET_CLKRT; +#else + /* + * SCC2 receive clock is BRG2 + * SCC2 transmit clock is BRG3 + */ + immr->im_cpm.cp_brgc2 = 0x0001000C; + immr->im_cpm.cp_brgc3 = 0x0001000C; + + immr->im_cpm.cp_sicr &= ~0x00003F00; + immr->im_cpm.cp_sicr |= 0x00000a00; +#endif /* 0 */ + + + /* + * Initialize SDCR -- see section 16.9.23.7 + * SDMA configuration register + */ + immr->im_siu_conf.sc_sdcr = 0x01; + + + /* + * Setup SCC Ethernet Parameter RAM + */ + + pram_ptr->sen_genscc.scc_rfcr = 0x18; /* Normal Operation and Mot byte ordering */ + pram_ptr->sen_genscc.scc_tfcr = 0x18; /* Mot byte ordering, Normal access */ + + pram_ptr->sen_genscc.scc_mrblr = DBUF_LENGTH; /* max. ET package len 1520 */ + + pram_ptr->sen_genscc.scc_rbase = (unsigned int) (&rtx->rxbd[0]); /* Set RXBD tbl start at Dual Port */ + pram_ptr->sen_genscc.scc_tbase = (unsigned int) (&rtx->txbd[0]); /* Set TXBD tbl start at Dual Port */ + + /* + * Setup Receiver Buffer Descriptors (13.14.24.18) + * Settings: + * Empty, Wrap + */ + + for (i = 0; i < PKTBUFSRX; i++) { + rtx->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; + rtx->rxbd[i].cbd_datlen = 0; /* Reset */ + rtx->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + } + + rtx->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + + /* + * Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) + * Settings: + * Add PADs to Short FRAMES, Wrap, Last, Tx CRC + */ + + for (i = 0; i < TX_BUF_CNT; i++) { + rtx->txbd[i].cbd_sc = + (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC); + rtx->txbd[i].cbd_datlen = 0; /* Reset */ + rtx->txbd[i].cbd_bufaddr = (uint) (&txbuf[0]); + } + + rtx->txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP; + + /* + * Enter Command: Initialize Rx Params for SCC + */ + + do { /* Spin until ready to issue command */ + __asm__ ("eieio"); + } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + /* Issue command */ + immr->im_cpm.cp_cpcr = + ((CPM_CR_INIT_RX << 8) | (cpm_cr[scc_index] << 4) | + CPM_CR_FLG); + do { /* Spin until command processed */ + __asm__ ("eieio"); + } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + + /* + * Ethernet Specific Parameter RAM + * see table 13-16, pg. 660, + * pg. 681 (example with suggested settings) + */ + + pram_ptr->sen_cpres = ~(0x0); /* Preset CRC */ + pram_ptr->sen_cmask = 0xdebb20e3; /* Constant Mask for CRC */ + pram_ptr->sen_crcec = 0x0; /* Error Counter CRC (unused) */ + pram_ptr->sen_alec = 0x0; /* Alignment Error Counter (unused) */ + pram_ptr->sen_disfc = 0x0; /* Discard Frame Counter (unused) */ + pram_ptr->sen_pads = 0x8888; /* Short Frame PAD Characters */ + + pram_ptr->sen_retlim = 15; /* Retry Limit Threshold */ + pram_ptr->sen_maxflr = 1518; /* MAX Frame Length Register */ + pram_ptr->sen_minflr = 64; /* MIN Frame Length Register */ + + pram_ptr->sen_maxd1 = DBUF_LENGTH; /* MAX DMA1 Length Register */ + pram_ptr->sen_maxd2 = DBUF_LENGTH; /* MAX DMA2 Length Register */ + + pram_ptr->sen_gaddr1 = 0x0; /* Group Address Filter 1 (unused) */ + pram_ptr->sen_gaddr2 = 0x0; /* Group Address Filter 2 (unused) */ + pram_ptr->sen_gaddr3 = 0x0; /* Group Address Filter 3 (unused) */ + pram_ptr->sen_gaddr4 = 0x0; /* Group Address Filter 4 (unused) */ + +#define ea bd->bi_enetaddr + pram_ptr->sen_paddrh = (ea[5] << 8) + ea[4]; + pram_ptr->sen_paddrm = (ea[3] << 8) + ea[2]; + pram_ptr->sen_paddrl = (ea[1] << 8) + ea[0]; +#undef ea + + pram_ptr->sen_pper = 0x0; /* Persistence (unused) */ + pram_ptr->sen_iaddr1 = 0x0; /* Individual Address Filter 1 (unused) */ + pram_ptr->sen_iaddr2 = 0x0; /* Individual Address Filter 2 (unused) */ + pram_ptr->sen_iaddr3 = 0x0; /* Individual Address Filter 3 (unused) */ + pram_ptr->sen_iaddr4 = 0x0; /* Individual Address Filter 4 (unused) */ + pram_ptr->sen_taddrh = 0x0; /* Tmp Address (MSB) (unused) */ + pram_ptr->sen_taddrm = 0x0; /* Tmp Address (unused) */ + pram_ptr->sen_taddrl = 0x0; /* Tmp Address (LSB) (unused) */ + + /* + * Enter Command: Initialize Tx Params for SCC + */ + + do { /* Spin until ready to issue command */ + __asm__ ("eieio"); + } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + /* Issue command */ + immr->im_cpm.cp_cpcr = + ((CPM_CR_INIT_TX << 8) | (cpm_cr[scc_index] << 4) | + CPM_CR_FLG); + do { /* Spin until command processed */ + __asm__ ("eieio"); + } while (immr->im_cpm.cp_cpcr & CPM_CR_FLG); + + /* + * Mask all Events in SCCM - we use polling mode + */ + immr->im_cpm.cp_scc[scc_index].scc_sccm = 0; + + /* + * Clear Events in SCCE -- Clear bits by writing 1's + */ + + immr->im_cpm.cp_scc[scc_index].scc_scce = ~(0x0); + + + /* + * Initialize GSMR High 32-Bits + * Settings: Normal Mode + */ + + immr->im_cpm.cp_scc[scc_index].scc_gsmrh = 0; + + /* + * Initialize GSMR Low 32-Bits, but do not Enable Transmit/Receive + * Settings: + * TCI = Invert + * TPL = 48 bits + * TPP = Repeating 10's + * LOOP = Loopback + * MODE = Ethernet + */ + + immr->im_cpm.cp_scc[scc_index].scc_gsmrl = (SCC_GSMRL_TCI | + SCC_GSMRL_TPL_48 | + SCC_GSMRL_TPP_10 | + SCC_GSMRL_DIAG_LOOP | + SCC_GSMRL_MODE_ENET); + + /* + * Initialize the DSR -- see section 13.14.4 (pg. 513) v0.4 + */ + + immr->im_cpm.cp_scc[scc_index].scc_dsr = 0xd555; + + /* + * Initialize the PSMR + * Settings: + * CRC = 32-Bit CCITT + * NIB = Begin searching for SFD 22 bits after RENA + * LPB = Loopback Enable (Needed when FDE is set) + */ + immr->im_cpm.cp_scc[scc_index].scc_psmr = SCC_PSMR_ENCRC | + SCC_PSMR_NIB22 | SCC_PSMR_LPB; + +#if 0 + /* + * Configure Ethernet TENA Signal + */ + +#if (defined(PC_ENET_TENA) && !defined(PB_ENET_TENA)) + immr->im_ioport.iop_pcpar |= PC_ENET_TENA; + immr->im_ioport.iop_pcdir &= ~PC_ENET_TENA; +#elif (defined(PB_ENET_TENA) && !defined(PC_ENET_TENA)) + immr->im_cpm.cp_pbpar |= PB_ENET_TENA; + immr->im_cpm.cp_pbdir |= PB_ENET_TENA; +#else +#error Configuration Error: exactly ONE of PB_ENET_TENA, PC_ENET_TENA must be defined +#endif + +#if defined(CONFIG_ADS) && defined(CONFIG_MPC860) + /* + * Port C is used to control the PHY,MC68160. + */ + immr->im_ioport.iop_pcdir |= + (PC_ENET_ETHLOOP | PC_ENET_TPFLDL | PC_ENET_TPSQEL); + + immr->im_ioport.iop_pcdat |= PC_ENET_TPFLDL; + immr->im_ioport.iop_pcdat &= ~(PC_ENET_ETHLOOP | PC_ENET_TPSQEL); + *((uint *) BCSR1) &= ~BCSR1_ETHEN; +#endif /* MPC860ADS */ + +#if defined(CONFIG_AMX860) + /* + * Port B is used to control the PHY,MC68160. + */ + immr->im_cpm.cp_pbdir |= + (PB_ENET_ETHLOOP | PB_ENET_TPFLDL | PB_ENET_TPSQEL); + + immr->im_cpm.cp_pbdat |= PB_ENET_TPFLDL; + immr->im_cpm.cp_pbdat &= ~(PB_ENET_ETHLOOP | PB_ENET_TPSQEL); + + immr->im_ioport.iop_pddir |= PD_ENET_ETH_EN; + immr->im_ioport.iop_pddat &= ~PD_ENET_ETH_EN; +#endif /* AMX860 */ + +#endif /* 0 */ + +#ifdef CONFIG_RPXCLASSIC + *((uchar *) BCSR0) &= ~BCSR0_ETHLPBK; + *((uchar *) BCSR0) |= (BCSR0_ETHEN | BCSR0_COLTEST | BCSR0_FULLDPLX); +#endif + +#ifdef CONFIG_RPXLITE + *((uchar *) BCSR0) |= BCSR0_ETHEN; +#endif + +#ifdef CONFIG_MBX + board_ether_init (); +#endif + + /* + * Set the ENT/ENR bits in the GSMR Low -- Enable Transmit/Receive + */ + + immr->im_cpm.cp_scc[scc_index].scc_gsmrl |= + (SCC_GSMRL_ENR | SCC_GSMRL_ENT); + + /* + * Work around transmit problem with first eth packet + */ +#if defined (CONFIG_FADS) + udelay (10000); /* wait 10 ms */ +#elif defined (CONFIG_AMX860) || defined(CONFIG_RPXCLASSIC) + udelay (100000); /* wait 100 ms */ +#endif +} + +static int scc_send (int index, volatile void *packet, int length) +{ + int i, j = 0; + + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) { + udelay (1); /* will also trigger Wd if needed */ + j++; + } + if (j >= TOUT_LOOP) + printf ("TX not ready\n"); + rtx->txbd[txIdx].cbd_bufaddr = (uint) packet; + rtx->txbd[txIdx].cbd_datlen = length; + rtx->txbd[txIdx].cbd_sc |= + (BD_ENET_TX_READY | BD_ENET_TX_LAST | BD_ENET_TX_WRAP); + while ((rtx->txbd[txIdx].cbd_sc & BD_ENET_TX_READY) && (j < TOUT_LOOP)) { + udelay (1); /* will also trigger Wd if needed */ + j++; + } + if (j >= TOUT_LOOP) + printf ("TX timeout\n"); + i = (rtx->txbd[txIdx]. + cbd_sc & BD_ENET_TX_STATS) /* return only status bits */ ; + return i; +} + +static int scc_recv (int index, void *packet, int max_length) +{ + int length = -1; + + if (rtx->rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) { + goto Done; /* nothing received */ + } + + if (!(rtx->rxbd[rxIdx].cbd_sc & 0x003f)) { + length = rtx->rxbd[rxIdx].cbd_datlen - 4; + memcpy (packet, + (void *) (NetRxPackets[rxIdx]), + length < max_length ? length : max_length); + } + + /* Give the buffer back to the SCC. */ + rtx->rxbd[rxIdx].cbd_datlen = 0; + + /* wrap around buffer index when necessary */ + if ((rxIdx + 1) >= PKTBUFSRX) { + rtx->rxbd[PKTBUFSRX - 1].cbd_sc = + (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + rxIdx = 0; + } else { + rtx->rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY; + rxIdx++; + } + + Done: + return length; +} + + /* + * Test routines + */ + +static void packet_fill (char *packet, int length) +{ + char c = (char) length; + int i; + + packet[0] = 0xFF; + packet[1] = 0xFF; + packet[2] = 0xFF; + packet[3] = 0xFF; + packet[4] = 0xFF; + packet[5] = 0xFF; + + for (i = 6; i < length; i++) { + packet[i] = c++; + } +} + +static int packet_check (char *packet, int length) +{ + char c = (char) length; + int i; + + for (i = 6; i < length; i++) { + if (packet[i] != c++) + return -1; + } + + return 0; +} + +static int test_ctlr (int ctlr, int index) +{ + int res = -1; + char packet_send[MAX_PACKET_LENGTH]; + char packet_recv[MAX_PACKET_LENGTH]; + int length; + int i; + int l; + + ctlr_proc[ctlr].init (index); + + for (i = 0; i < TEST_NUM; i++) { + for (l = MIN_PACKET_LENGTH; l <= MAX_PACKET_LENGTH; l++) { + packet_fill (packet_send, l); + + ctlr_proc[ctlr].send (index, packet_send, l); + + length = ctlr_proc[ctlr].recv (index, packet_recv, + MAX_PACKET_LENGTH); + + if (length != l || packet_check (packet_recv, length) < 0) { + goto Done; + } + } + } + + res = 0; + + Done: + +#if !defined(CONFIG_8xx_CONS_NONE) + if (used_by_uart[ctlr] == index) { + serial_init (); + } +#endif + +#if defined(SCC_ENET) + if (used_by_ether[ctlr] == index) { + DECLARE_GLOBAL_DATA_PTR; + + eth_init (gd->bd); + } +#endif + + /* + * SCC2 Ethernet parameter RAM space overlaps + * the SPI parameter RAM space. So we need to restore + * the SPI configuration after SCC2 ethernet test. + */ +#if defined(CONFIG_SPI) + if (ctlr == CTLR_SCC && index == 1) { + spi_init_f (); + spi_init_r (); + } +#endif + + if (res != 0) { + post_log ("ethernet %s%d test failed\n", ctlr_name[ctlr], + index + 1); + } + + return res; +} + +int ether_post_test (int flags) +{ + int res = 0; + int i; + +#if defined(CONFIG_8xx_CONS_SCC1) + used_by_uart[CTLR_SCC] = 0; +#elif defined(CONFIG_8xx_CONS_SCC2) + used_by_uart[CTLR_SCC] = 1; +#elif defined(CONFIG_8xx_CONS_SCC3) + used_by_uart[CTLR_SCC] = 2; +#elif defined(CONFIG_8xx_CONS_SCC4) + used_by_uart[CTLR_SCC] = 3; +#endif + +#if defined(SCC_ENET) + used_by_ether[CTLR_SCC] = SCC_ENET; +#endif + + ctlr_proc[CTLR_SCC].init = scc_init; + ctlr_proc[CTLR_SCC].send = scc_send; + ctlr_proc[CTLR_SCC].recv = scc_recv; + + for (i = 0; i < CTRL_LIST_SIZE; i++) { + if (test_ctlr (ctlr_list[i][0], ctlr_list[i][1]) != 0) { + res = -1; + } + } + + return res; +} + +#endif /* CONFIG_POST & CFG_POST_ETHER */ + +#endif /* CONFIG_POST */ diff --git a/post/memory.c b/post/memory.c new file mode 100644 index 0000000..7d55a6d --- /dev/null +++ b/post/memory.c @@ -0,0 +1,481 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* Memory test + * + * General observations: + * o The recommended test sequence is to test the data lines: if they are + * broken, nothing else will work properly. Then test the address + * lines. Finally, test the cells in the memory now that the test + * program knows that the address and data lines work properly. + * This sequence also helps isolate and identify what is faulty. + * + * o For the address line test, it is a good idea to use the base + * address of the lowest memory location, which causes a '1' bit to + * walk through a field of zeros on the address lines and the highest + * memory location, which causes a '0' bit to walk through a field of + * '1's on the address line. + * + * o Floating buses can fool memory tests if the test routine writes + * a value and then reads it back immediately. The problem is, the + * write will charge the residual capacitance on the data bus so the + * bus retains its state briefely. When the test program reads the + * value back immediately, the capacitance of the bus can allow it + * to read back what was written, even though the memory circuitry + * is broken. To avoid this, the test program should write a test + * pattern to the target location, write a different pattern elsewhere + * to charge the residual capacitance in a differnt manner, then read + * the target location back. + * + * o Always read the target location EXACTLY ONCE and save it in a local + * variable. The problem with reading the target location more than + * once is that the second and subsequent reads may work properly, + * resulting in a failed test that tells the poor technician that + * "Memory error at 00000000, wrote aaaaaaaa, read aaaaaaaa" which + * doesn't help him one bit and causes puzzled phone calls. Been there, + * done that. + * + * Data line test: + * --------------- + * This tests data lines for shorts and opens by forcing adjacent data + * to opposite states. Because the data lines could be routed in an + * arbitrary manner the must ensure test patterns ensure that every case + * is tested. By using the following series of binary patterns every + * combination of adjacent bits is test regardless of routing. + * + * ...101010101010101010101010 + * ...110011001100110011001100 + * ...111100001111000011110000 + * ...111111110000000011111111 + * + * Carrying this out, gives us six hex patterns as follows: + * + * 0xaaaaaaaaaaaaaaaa + * 0xcccccccccccccccc + * 0xf0f0f0f0f0f0f0f0 + * 0xff00ff00ff00ff00 + * 0xffff0000ffff0000 + * 0xffffffff00000000 + * + * To test for short and opens to other signals on our boards, we + * simply test with the 1's complemnt of the paterns as well, resulting + * in twelve patterns total. + * + * After writing a test pattern. a special pattern 0x0123456789ABCDEF is + * written to a different address in case the data lines are floating. + * Thus, if a byte lane fails, you will see part of the special + * pattern in that byte lane when the test runs. For example, if the + * xx__xxxxxxxxxxxx byte line fails, you will see aa23aaaaaaaaaaaa + * (for the 'a' test pattern). + * + * Address line test: + * ------------------ + * This function performs a test to verify that all the address lines + * hooked up to the RAM work properly. If there is an address line + * fault, it usually shows up as two different locations in the address + * map (related by the faulty address line) mapping to one physical + * memory storage location. The artifact that shows up is writing to + * the first location "changes" the second location. + * + * To test all address lines, we start with the given base address and + * xor the address with a '1' bit to flip one address line. For each + * test, we shift the '1' bit left to test the next address line. + * + * In the actual code, we start with address sizeof(ulong) since our + * test pattern we use is a ulong and thus, if we tried to test lower + * order address bits, it wouldn't work because our pattern would + * overwrite itself. + * + * Example for a 4 bit address space with the base at 0000: + * 0000 <- base + * 0001 <- test 1 + * 0010 <- test 2 + * 0100 <- test 3 + * 1000 <- test 4 + * Example for a 4 bit address space with the base at 0010: + * 0010 <- base + * 0011 <- test 1 + * 0000 <- (below the base address, skipped) + * 0110 <- test 2 + * 1010 <- test 3 + * + * The test locations are successively tested to make sure that they are + * not "mirrored" onto the base address due to a faulty address line. + * Note that the base and each test location are related by one address + * line flipped. Note that the base address need not be all zeros. + * + * Memory tests 1-4: + * ----------------- + * These tests verify RAM using sequential writes and reads + * to/from RAM. There are several test cases that use different patterns to + * verify RAM. Each test case fills a region of RAM with one pattern and + * then reads the region back and compares its contents with the pattern. + * The following patterns are used: + * + * 1a) zero pattern (0x00000000) + * 1b) negative pattern (0xffffffff) + * 1c) checkerboard pattern (0x55555555) + * 1d) checkerboard pattern (0xaaaaaaaa) + * 2) bit-flip pattern ((1 << (offset % 32)) + * 3) address pattern (offset) + * 4) address pattern (~offset) + * + * Being run in normal mode, the test verifies only small 4Kb + * regions of RAM around each 1Mb boundary. For example, for 64Mb + * RAM the following areas are verified: 0x00000000-0x00000800, + * 0x000ff800-0x00100800, 0x001ff800-0x00200800, ..., 0x03fff800- + * 0x04000000. If the test is run in power-fail mode, it verifies + * the whole RAM. + */ + +#ifdef CONFIG_POST + +#include <post.h> +#include <watchdog.h> + +#if CONFIG_POST & CFG_POST_MEMORY + +/* + * Define INJECT_*_ERRORS for testing error detection in the presence of + * _good_ hardware. + */ +#undef INJECT_DATA_ERRORS +#undef INJECT_ADDRESS_ERRORS + +#ifdef INJECT_DATA_ERRORS +#warning "Injecting data line errors for testing purposes" +#endif + +#ifdef INJECT_ADDRESS_ERRORS +#warning "Injecting address line errors for testing purposes" +#endif + + +/* + * This function performs a double word move from the data at + * the source pointer to the location at the destination pointer. + * This is helpful for testing memory on processors which have a 64 bit + * wide data bus. + * + * On those PowerPC with FPU, use assembly and a floating point move: + * this does a 64 bit move. + * + * For other processors, let the compiler generate the best code it can. + */ +static void move64(unsigned long long *src, unsigned long long *dest) +{ +#if defined(CONFIG_MPC8260) || defined(CONFIG_MPC824X) + asm ("lfd 0, 0(3)\n\t" /* fpr0 = *scr */ + "stfd 0, 0(4)" /* *dest = fpr0 */ + : : : "fr0" ); /* Clobbers fr0 */ + return; +#else + *dest = *src; +#endif +} + +/* + * This is 64 bit wide test patterns. Note that they reside in ROM + * (which presumably works) and the tests write them to RAM which may + * not work. + * + * The "otherpattern" is written to drive the data bus to values other + * than the test pattern. This is for detecting floating bus lines. + * + */ +const static unsigned long long pattern[] = { + 0xaaaaaaaaaaaaaaaa, + 0xcccccccccccccccc, + 0xf0f0f0f0f0f0f0f0, + 0xff00ff00ff00ff00, + 0xffff0000ffff0000, + 0xffffffff00000000, + 0x00000000ffffffff, + 0x0000ffff0000ffff, + 0x00ff00ff00ff00ff, + 0x0f0f0f0f0f0f0f0f, + 0x3333333333333333, + 0x5555555555555555}; +const unsigned long long otherpattern = 0x0123456789abcdef; + + +static int memory_post_dataline(unsigned long long * pmem) +{ + unsigned long long temp64; + int num_patterns = sizeof(pattern)/ sizeof(pattern[0]); + int i; + unsigned int hi, lo, pathi, patlo; + int ret = 0; + + for ( i = 0; i < num_patterns; i++) { + move64((unsigned long long *)&(pattern[i]), pmem++); + /* + * Put a different pattern on the data lines: otherwise they + * may float long enough to read back what we wrote. + */ + move64((unsigned long long *)&otherpattern, pmem--); + move64(pmem, &temp64); + +#ifdef INJECT_DATA_ERRORS + temp64 ^= 0x00008000; +#endif + + if (temp64 != pattern[i]){ + pathi = (pattern[i]>>32) & 0xffffffff; + patlo = pattern[i] & 0xffffffff; + + hi = (temp64>>32) & 0xffffffff; + lo = temp64 & 0xffffffff; + + post_log ("Memory (date line) error at %08x, " + "wrote %08x%08x, read %08x%08x !\n", + pmem, pathi, patlo, hi, lo); + ret = -1; + } + } + return ret; +} + +static int memory_post_addrline(ulong *testaddr, ulong *base, ulong size) +{ + ulong *target; + ulong *end; + ulong readback; + ulong xor; + int ret = 0; + + end = base + size; + xor = 0; + for(xor = sizeof(ulong); xor > 0; xor <<= 1) { + target = (ulong *)((ulong)testaddr ^ xor); + if((target >= base) && (target < end)) { + *testaddr = ~*target; + readback = *target; + +#ifdef INJECT_ADDRESS_ERRORS + if(xor == 0x00008000) { + readback = *testaddr; + } +#endif + if(readback == *testaddr) { + post_log ("Memory (address line) error at %08x<->%08x, " + "XOR value %08x !\n", + testaddr, target, xor); + ret = -1; + } + } + } + return ret; +} + +static int memory_post_test1 (unsigned long start, + unsigned long size, + unsigned long val) +{ + unsigned long i; + ulong *mem = (ulong *) start; + ulong readback; + int ret = 0; + + for (i = 0; i < size / sizeof (ulong); i++) { + mem[i] = val; + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + readback = mem[i]; + if (readback != val) { + post_log ("Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, val, readback); + + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + return ret; +} + +static int memory_post_test2 (unsigned long start, unsigned long size) +{ + unsigned long i; + ulong *mem = (ulong *) start; + ulong readback; + int ret = 0; + + for (i = 0; i < size / sizeof (ulong); i++) { + mem[i] = 1 << (i % 32); + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + readback = mem[i]; + if (readback != (1 << (i % 32))) { + post_log ("Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, 1 << (i % 32), readback); + + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + return ret; +} + +static int memory_post_test3 (unsigned long start, unsigned long size) +{ + unsigned long i; + ulong *mem = (ulong *) start; + ulong readback; + int ret = 0; + + for (i = 0; i < size / sizeof (ulong); i++) { + mem[i] = i; + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + readback = mem[i]; + if (readback != i) { + post_log ("Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, i, readback); + + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + return ret; +} + +static int memory_post_test4 (unsigned long start, unsigned long size) +{ + unsigned long i; + ulong *mem = (ulong *) start; + ulong readback; + int ret = 0; + + for (i = 0; i < size / sizeof (ulong); i++) { + mem[i] = ~i; + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + for (i = 0; i < size / sizeof (ulong) && ret == 0; i++) { + readback = mem[i]; + if (readback != ~i) { + post_log ("Memory error at %08x, " + "wrote %08x, read %08x !\n", + mem + i, ~i, readback); + + ret = -1; + break; + } + if (i % 1024 == 0) + WATCHDOG_RESET (); + } + + return ret; +} + +static int memory_post_tests (unsigned long start, unsigned long size) +{ + int ret = 0; + + if (ret == 0) + ret = memory_post_dataline ((long long *)start); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_addrline ((long *)start, (long *)start, size); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_addrline ((long *)(start + size - 8), + (long *)start, size); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test1 (start, size, 0x00000000); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test1 (start, size, 0xffffffff); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test1 (start, size, 0x55555555); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test1 (start, size, 0xaaaaaaaa); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test2 (start, size); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test3 (start, size); + WATCHDOG_RESET (); + if (ret == 0) + ret = memory_post_test4 (start, size); + WATCHDOG_RESET (); + + return ret; +} + +int memory_post_test (int flags) +{ + int ret = 0; + DECLARE_GLOBAL_DATA_PTR; + bd_t *bd = gd->bd; + unsigned long memsize = (bd->bi_memsize >= 256 << 20 ? + 256 << 20 : bd->bi_memsize) - (1 << 20); + + + if (flags & POST_POWERFAIL) { + ret = memory_post_tests (CFG_SDRAM_BASE, memsize); + } else { /* POST_POWERNORMAL */ + + unsigned long i; + + for (i = 0; i < (memsize >> 20) && ret == 0; i++) { + if (ret == 0) + ret = memory_post_tests (i << 20, 0x800); + if (ret == 0) + ret = memory_post_tests ((i << 20) + 0xff800, 0x800); + } + } + + return ret; +} + +#endif /* CONFIG_POST & CFG_POST_MEMORY */ +#endif /* CONFIG_POST */ diff --git a/rtc/ds1556.c b/rtc/ds1556.c new file mode 100644 index 0000000..dd9ea5e --- /dev/null +++ b/rtc/ds1556.c @@ -0,0 +1,206 @@ +/* + * (C) Copyright 2002 + * ARIO Data Networks, Inc. dchiu@ariodata.com + * + * modified for DS1556: + * Frank Panno <fpanno@delphintech.com>, Delphin Technology AG + * + * Based on MontaVista DS1743 code and U-Boot mc146818 code + * + * 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 + */ + +/* + * Date & Time support for the DS1556 RTC + */ + +/*#define RTC_DEBUG */ + +#include <common.h> +#include <command.h> +#include <rtc.h> + + +#if defined(CONFIG_RTC_DS1556) && (CONFIG_COMMANDS & CFG_CMD_DATE) + +static uchar rtc_read( unsigned int addr ); +static void rtc_write( unsigned int addr, uchar val); +static uchar bin2bcd (unsigned int n); +static unsigned bcd2bin(uchar c); + +#define RTC_BASE ( CFG_NVRAM_SIZE + CFG_NVRAM_BASE_ADDR ) + +#define RTC_YEAR ( RTC_BASE + 0xf ) +#define RTC_MONTH ( RTC_BASE + 0xe ) +#define RTC_DAY_OF_MONTH ( RTC_BASE + 0xd ) +#define RTC_DAY_OF_WEEK ( RTC_BASE + 0xc ) +#define RTC_HOURS ( RTC_BASE + 0xb ) +#define RTC_MINUTES ( RTC_BASE + 0xa ) +#define RTC_SECONDS ( RTC_BASE + 0x9 ) +#define RTC_CENTURY ( RTC_BASE + 0x8 ) + +#define RTC_CONTROLA RTC_CENTURY +#define RTC_CONTROLB RTC_SECONDS +#define RTC_CONTROLC RTC_BASE + +#define RTC_CA_WRITE 0x80 +#define RTC_CA_READ 0x40 + +#define RTC_CB_OSC_DISABLE 0x80 + +#define RTC_CC_BATTERY_FLAG 0x10 +#define RTC_CC_FREQ_TEST 0x40 + +/* ------------------------------------------------------------------------- */ + +void rtc_get( struct rtc_time *tmp ) +{ + uchar sec, min, hour; + uchar mday, wday, mon, year; + + int century; + + uchar reg_a; + + reg_a = rtc_read( RTC_CONTROLA ); + /* lock clock registers for read */ + rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_READ )); + + sec = rtc_read( RTC_SECONDS ); + min = rtc_read( RTC_MINUTES ); + hour = rtc_read( RTC_HOURS ); + mday = rtc_read( RTC_DAY_OF_MONTH ); + wday = rtc_read( RTC_DAY_OF_WEEK ); + mon = rtc_read( RTC_MONTH ); + year = rtc_read( RTC_YEAR ); + century = rtc_read( RTC_CENTURY ); + + /* unlock clock registers after read */ + rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_READ )); + +#ifdef RTC_DEBUG + printf( "Get RTC year: %02x mon/cent: %02x mon: %02x mday: %02x wday: %02x " + "hr: %02x min: %02x sec: %02x\n", + year, century, mon, mday, wday, + hour, min, sec ); +#endif + tmp->tm_sec = bcd2bin( sec & 0x7F ); + tmp->tm_min = bcd2bin( min & 0x7F ); + tmp->tm_hour = bcd2bin( hour & 0x3F ); + tmp->tm_mday = bcd2bin( mday & 0x3F ); + tmp->tm_mon = bcd2bin( mon & 0x1F ); + tmp->tm_wday = bcd2bin( wday & 0x07 ); + + /* glue year from century and year in century */ + tmp->tm_year = bcd2bin( year ) + + ( bcd2bin( century & 0x3F ) * 100 ); + + tmp->tm_yday = 0; + tmp->tm_isdst= 0; +#ifdef RTC_DEBUG + printf( "Get DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec ); +#endif +} + +void rtc_set( struct rtc_time *tmp ) +{ + uchar reg_a; +#ifdef RTC_DEBUG + printf( "Set DATE: %4d-%02d-%02d (wday=%d) TIME: %2d:%02d:%02d\n", + tmp->tm_year, tmp->tm_mon, tmp->tm_mday, tmp->tm_wday, + tmp->tm_hour, tmp->tm_min, tmp->tm_sec); +#endif + /* lock clock registers for write */ + reg_a = rtc_read( RTC_CONTROLA ); + rtc_write( RTC_CONTROLA, ( reg_a | RTC_CA_WRITE )); + + rtc_write( RTC_MONTH, bin2bcd( tmp->tm_mon )); + + rtc_write( RTC_DAY_OF_WEEK, bin2bcd( tmp->tm_wday )); + rtc_write( RTC_DAY_OF_MONTH, bin2bcd( tmp->tm_mday )); + rtc_write( RTC_HOURS, bin2bcd( tmp->tm_hour )); + rtc_write( RTC_MINUTES, bin2bcd( tmp->tm_min )); + rtc_write( RTC_SECONDS, bin2bcd( tmp->tm_sec )); + + /* break year up into century and year in century */ + rtc_write( RTC_YEAR, bin2bcd( tmp->tm_year % 100 )); + rtc_write( RTC_CENTURY, bin2bcd( tmp->tm_year / 100 )); + + /* unlock clock registers after read */ + rtc_write( RTC_CONTROLA, ( reg_a & ~RTC_CA_WRITE )); +} + +void rtc_reset (void) +{ + uchar reg_a, reg_b, reg_c; + + reg_a = rtc_read( RTC_CONTROLA ); + reg_b = rtc_read( RTC_CONTROLB ); + + if ( reg_b & RTC_CB_OSC_DISABLE ) + { + printf( "real-time-clock was stopped. Now starting...\n" ); + reg_a |= RTC_CA_WRITE; + reg_b &= ~RTC_CB_OSC_DISABLE; + + rtc_write( RTC_CONTROLA, reg_a ); + rtc_write( RTC_CONTROLB, reg_b ); + } + + /* make sure read/write clock register bits are cleared */ + reg_a &= ~( RTC_CA_WRITE | RTC_CA_READ ); + rtc_write( RTC_CONTROLA, reg_a ); + + reg_c = rtc_read( RTC_CONTROLC ); + if (( reg_c & RTC_CC_BATTERY_FLAG ) == 0 ) + printf( "RTC battery low. Clock setting may not be reliable.\n" ); +} + +/* ------------------------------------------------------------------------- */ + +static uchar rtc_read( unsigned int addr ) +{ + uchar val = *(volatile unsigned char*)(addr); +#ifdef RTC_DEBUG + printf( "rtc_read: %x:%x\n", addr, val ); +#endif + return( val ); +} + +static void rtc_write( unsigned int addr, uchar val ) +{ +#ifdef RTC_DEBUG + printf( "rtc_write: %x:%x\n", addr, val ); +#endif + *(volatile unsigned char*)(addr) = val; +} + +static unsigned bcd2bin (uchar n) +{ + return ((((n >> 4) & 0x0F) * 10) + (n & 0x0F)); +} + +static unsigned char bin2bcd (unsigned int n) +{ + return (((n / 10) << 4) | (n % 10)); +} + +#endif /* CONFIG_RTC_DS1556 && CFG_CMD_DATE */ |