Initial revision
This commit is contained in:
parent
5b1d713721
commit
c609719b8d
242
CREDITS
Normal file
242
CREDITS
Normal file
@ -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
|
190
board/cogent/serial.c
Normal file
190
board/cogent/serial.c
Normal file
@ -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 */
|
119
board/cu824/cu824.c
Normal file
119
board/cu824/cu824.c
Normal file
@ -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);
|
||||
}
|
53
board/dnp1110/u-boot.lds
Normal file
53
board/dnp1110/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
301
board/ebony/ebony.c
Normal file
301
board/ebony/ebony.c
Normal file
@ -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) */
|
98
board/ebony/init.S
Normal file
98
board/ebony/init.S
Normal file
@ -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
|
||||
|
||||
|
1487
board/eltec/bab7xx/asm_init.S
Normal file
1487
board/eltec/bab7xx/asm_init.S
Normal file
File diff suppressed because it is too large
Load Diff
292
board/eltec/bab7xx/el_srom.c
Normal file
292
board/eltec/bab7xx/el_srom.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
129
board/eltec/bab7xx/u-boot.lds
Normal file
129
board/eltec/bab7xx/u-boot.lds
Normal file
@ -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 = .);
|
||||
}
|
877
board/eltec/elppc/asm_init.S
Normal file
877
board/eltec/elppc/asm_init.S
Normal file
@ -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
|
129
board/eltec/elppc/u-boot.lds
Normal file
129
board/eltec/elppc/u-boot.lds
Normal file
@ -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 = .);
|
||||
}
|
341
board/ep7312/flash.c
Normal file
341
board/ep7312/flash.c
Normal file
@ -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);
|
||||
}
|
53
board/ep7312/u-boot.lds
Normal file
53
board/ep7312/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
262
board/esd/common/fpga.c
Normal file
262
board/esd/common/fpga.c
Normal file
@ -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;
|
||||
}
|
202
board/esd/common/pci.c
Normal file
202
board/esd/common/pci.c
Normal file
@ -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);
|
||||
}
|
451
board/esd/cpci405/cpci405.c
Normal file
451
board/esd/cpci405/cpci405.c
Normal file
@ -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 */
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
140
board/esd/cpci440/cpci440.c
Normal file
140
board/esd/cpci440/cpci440.c
Normal file
@ -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 */
|
||||
}
|
96
board/esd/cpci440/init.S
Normal file
96
board/esd/cpci440/init.S
Normal file
@ -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
|
||||
|
||||
|
254
board/esd/pci405/pci405.c
Normal file
254
board/esd/pci405/pci405.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
225
board/evb64260/eth_addrtbl.c
Normal file
225
board/evb64260/eth_addrtbl.c
Normal file
@ -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 */
|
691
board/evb64260/pci.c
Normal file
691
board/evb64260/pci.c
Normal file
@ -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);
|
||||
}
|
629
board/evb64260/sdram_init.c
Normal file
629
board/evb64260/sdram_init.c
Normal file
@ -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;
|
||||
}
|
191
board/evb64260/serial.c
Normal file
191
board/evb64260/serial.c
Normal file
@ -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 */
|
142
board/gen860t/README
Normal file
142
board/gen860t/README
Normal file
@ -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:
|
||||
|
213
board/gen860t/beeper.c
Normal file
213
board/gen860t/beeper.c
Normal file
@ -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: */
|
644
board/gen860t/flash.c
Normal file
644
board/gen860t/flash.c
Normal file
@ -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: */
|
401
board/gen860t/fpga.c
Normal file
401
board/gen860t/fpga.c
Normal file
@ -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: */
|
299
board/gen860t/gen860t.c
Normal file
299
board/gen860t/gen860t.c
Normal file
@ -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 : */
|
276
board/gen860t/ioport.c
Normal file
276
board/gen860t/ioport.c
Normal file
@ -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: */
|
135
board/gen860t/u-boot.lds
Normal file
135
board/gen860t/u-boot.lds
Normal file
@ -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 = .);
|
||||
}
|
||||
|
365
board/impa7/flash.c
Normal file
365
board/impa7/flash.c
Normal file
@ -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);
|
||||
}
|
53
board/impa7/u-boot.lds
Normal file
53
board/impa7/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
53
board/lart/u-boot.lds
Normal file
53
board/lart/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
379
board/mbx8xx/mbx8xx.c
Normal file
379
board/mbx8xx/mbx8xx.c
Normal file
@ -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;
|
||||
}
|
131
board/ml2/serial.c
Normal file
131
board/ml2/serial.c
Normal file
@ -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 */
|
283
board/mousse/pci.c
Normal file
283
board/mousse/pci.c
Normal file
@ -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);
|
||||
}
|
606
board/mpl/common/common_util.c
Normal file
606
board/mpl/common/common_util.c
Normal file
@ -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 */
|
102
board/mpl/common/pci.c
Normal file
102
board/mpl/common/pci.c
Normal file
@ -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 */
|
192
board/mpl/common/pci_parts.h
Normal file
192
board/mpl/common/pci_parts.h
Normal file
@ -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_ */
|
||||
|
||||
|
||||
|
||||
|
||||
|
49
board/mpl/mip405/Makefile
Normal file
49
board/mpl/mip405/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
52
board/mpl/pip405/Makefile
Normal file
52
board/mpl/pip405/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
130
board/musenki/musenki.c
Normal file
130
board/musenki/musenki.c
Normal file
@ -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);
|
||||
}
|
40
board/mvs1/Makefile
Normal file
40
board/mvs1/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
40
board/netvia/Makefile
Normal file
40
board/netvia/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
374
board/netvia/netvia.c
Normal file
374
board/netvia/netvia.c
Normal file
@ -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;
|
||||
}
|
||||
|
132
board/netvia/u-boot.lds
Normal file
132
board/netvia/u-boot.lds
Normal file
@ -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 = .);
|
||||
}
|
131
board/netvia/u-boot.lds.debug
Normal file
131
board/netvia/u-boot.lds.debug
Normal file
@ -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 = .);
|
||||
}
|
||||
|
372
board/oxc/flash.c
Normal file
372
board/oxc/flash.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
237
board/oxc/oxc.c
Normal file
237
board/oxc/oxc.c
Normal file
@ -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);
|
||||
}
|
254
board/pcippc2/cpc710_init_ram.c
Normal file
254
board/pcippc2/cpc710_init_ram.c
Normal file
@ -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;
|
||||
}
|
309
board/pcippc2/cpc710_pci.c
Normal file
309
board/pcippc2/cpc710_pci.c
Normal file
@ -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);
|
||||
}
|
257
board/pcippc2/i2c.c
Normal file
257
board/pcippc2/i2c.c
Normal file
@ -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 */
|
||||
}
|
214
board/pcippc2/pcippc2.c
Normal file
214
board/pcippc2/pcippc2.c
Normal file
@ -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 */
|
164
board/pn62/cmd_pn62.c
Normal file
164
board/pn62/cmd_pn62.c
Normal file
@ -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
|
235
board/pn62/misc.c
Normal file
235
board/pn62/misc.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
216
board/pn62/pn62.c
Normal file
216
board/pn62/pn62.c
Normal file
@ -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]);
|
||||
}
|
423
board/r360mpi/r360mpi.c
Normal file
423
board/r360mpi/r360mpi.c
Normal file
@ -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;
|
||||
}
|
884
board/sacsng/clkinit.c
Normal file
884
board/sacsng/clkinit.c
Normal file
@ -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");
|
||||
}
|
218
board/sacsng/ioconfig.h
Normal file
218
board/sacsng/ioconfig.h
Normal file
@ -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 */
|
||||
}
|
||||
};
|
||||
|
127
board/sandpoint/sandpoint.c
Normal file
127
board/sandpoint/sandpoint.c
Normal file
@ -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);
|
||||
}
|
53
board/shannon/u-boot.lds
Normal file
53
board/shannon/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
440
board/siemens/CCM/ccm.c
Normal file
440
board/siemens/CCM/ccm.c
Normal file
@ -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);
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
170
board/siemens/CCM/fpga_ccm.c
Normal file
170
board/siemens/CCM/fpga_ccm.c
Normal file
@ -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;
|
||||
}
|
||||
|
104
board/siemens/SCM/fpga_scm.c
Normal file
104
board/siemens/SCM/fpga_scm.c
Normal file
@ -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;
|
||||
}
|
27
board/siemens/common/README
Normal file
27
board/siemens/common/README
Normal file
@ -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)
|
358
board/siemens/common/fpga.c
Normal file
358
board/siemens/common/fpga.c
Normal file
@ -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;
|
||||
}
|
54
board/smdk2400/u-boot.lds
Normal file
54
board/smdk2400/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
124
board/smdk2410/smdk2410.c
Normal file
124
board/smdk2410/smdk2410.c
Normal file
@ -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;
|
||||
}
|
569
board/tqm8xx/flash.c
Normal file
569
board/tqm8xx/flash.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
105
board/tqm8xx/load_sernum_ethaddr.c
Normal file
105
board/tqm8xx/load_sernum_ethaddr.c
Normal file
@ -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);
|
||||
}
|
||||
}
|
44
board/trab/README.kbd
Normal file
44
board/trab/README.kbd
Normal file
@ -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.
|
301
board/trab/trab.c
Normal file
301
board/trab/trab.c
Normal file
@ -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 */
|
63
board/trab/u-boot.lds
Normal file
63
board/trab/u-boot.lds
Normal file
@ -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 = .;
|
||||
}
|
414
board/trab/vfd.c
Normal file
414
board/trab/vfd.c
Normal file
@ -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 */
|
152
board/utx8245/utx8245.c
Normal file
152
board/utx8245/utx8245.c
Normal file
@ -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();
|
||||
}
|
||||
|
941
board/w7o/flash.c
Normal file
941
board/w7o/flash.c
Normal file
@ -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() */
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
*/
|
||||
|
380
board/w7o/fpga.c
Normal file
380
board/w7o/fpga.c
Normal file
@ -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;
|
||||
}
|
||||
|
264
board/w7o/init.S
Normal file
264
board/w7o/init.S
Normal file
@ -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() */
|
||||
|
745
board/w7o/post1.S
Normal file
745
board/w7o/post1.S
Normal file
@ -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 */
|
||||
|
109
board/w7o/post2.c
Normal file
109
board/w7o/post2.c
Normal file
@ -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() */
|
||||
|
408
board/w7o/vpd.c
Normal file
408
board/w7o/vpd.c
Normal file
@ -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() */
|
||||
|
135
board/w7o/vpd.h
Normal file
135
board/w7o/vpd.h
Normal file
@ -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_ */
|
||||
|
271
board/w7o/w7o.c
Normal file
271
board/w7o/w7o.c
Normal file
@ -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);
|
||||
}
|
||||
|
1563
common/cmd_doc.c
Normal file
1563
common/cmd_doc.c
Normal file
File diff suppressed because it is too large
Load Diff
1563
common/cmd_ide.c
Normal file
1563
common/cmd_ide.c
Normal file
File diff suppressed because it is too large
Load Diff
578
common/cmd_immap.c
Normal file
578
common/cmd_immap.c
Normal file
@ -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) */
|
179
common/cmd_jffs2.c
Normal file
179
common/cmd_jffs2.c
Normal file
@ -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 */
|
477
common/cmd_pci.c
Normal file
477
common/cmd_pci.c
Normal file
@ -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 */
|
2243
common/cmd_pcmcia.c
Normal file
2243
common/cmd_pcmcia.c
Normal file
File diff suppressed because it is too large
Load Diff
377
common/env_flash.c
Normal file
377
common/env_flash.c
Normal file
@ -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) */
|
138
common/env_nvram.c
Normal file
138
common/env_nvram.c
Normal file
@ -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 */
|
198
common/environment.c
Normal file
198
common/environment.c
Normal file
@ -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 */
|
817
common/main.c
Normal file
817
common/main.c
Normal file
@ -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
|
172
common/miiphyutil.c
Normal file
172
common/miiphyutil.c
Normal file
@ -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) */
|
416
common/soft_i2c.c
Normal file
416
common/soft_i2c.c
Normal file
@ -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 */
|
43
cpu/arm720t/Makefile
Normal file
43
cpu/arm720t/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
265
cpu/arm720t/interrupts.c
Normal file
265
cpu/arm720t/interrupts.c
Normal file
@ -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*/;
|
||||
}
|
43
cpu/arm920t/Makefile
Normal file
43
cpu/arm920t/Makefile
Normal file
@ -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
|
||||
|
||||
#########################################################################
|
304
cpu/arm920t/interrupts.c
Normal file
304
cpu/arm920t/interrupts.c
Normal file
@ -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;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user