Initial revision

This commit is contained in:
wdenk 2002-11-03 00:24:07 +00:00
parent 5b1d713721
commit c609719b8d
208 changed files with 79197 additions and 0 deletions

242
CREDITS Normal file
View 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

2663
README Normal file

File diff suppressed because it is too large Load Diff

190
board/cogent/serial.c Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

View 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);
}
/*----------------------------------------------------------------------------*/

View 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 = .);
}

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
/* ------------------------------------------------------------------------- */

View 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
View 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],&regData);
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],&regData);
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],&regData);
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}

View 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
View 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 */

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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 = .);
}

View 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
View 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
View 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);
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);
}
/* ------------------------------------------------------------------------- */

View 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;
}

View 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;
}

View 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
View 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
View 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
View 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
View 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);
}
/*-----------------------------------------------------------------------
*/

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff

1563
common/cmd_ide.c Normal file

File diff suppressed because it is too large Load Diff

578
common/cmd_immap.c Normal file
View 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
View 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 &part;
memset(&part, 0, sizeof(part));
#if defined(CFG_JFFS2_FIRST_SECTOR)
part.offset = (unsigned char *) flash_info[CFG_JFFS2_FIRST_BANK].start[CFG_JFFS2_FIRST_SECTOR];
#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 &part;
}
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
View 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

File diff suppressed because it is too large Load Diff

377
common/env_flash.c Normal file
View 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
View 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
View 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
View 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
View 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 *) &reg) != 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 *) &reg) != 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, &reg) != 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, &reg)) {
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, &reg)) {
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
View 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
View 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
View 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
View 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
View 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