* Add support for IceCube board (with MGT5100 and MPC5200 CPUs)

* Add support for MGT5100 and MPC5200 processors
This commit is contained in:
wdenk
2003-07-16 21:53:01 +00:00
parent cb4dbb7bbc
commit 945af8d723
56 changed files with 6168 additions and 545 deletions

View File

@@ -85,7 +85,6 @@ int disable_interrupts (void)
#endif
void bad_mode (void)
{
panic ("Resetting CPU ...\n");

View File

@@ -41,14 +41,14 @@ void gpiosetdir(ushort mask, ushort in)
void gpiosetout(ushort mask, ushort out)
{
ushort *r_ptr, r_val;
r_ptr = (ushort *)GPIO_DATA_OUTPUT_REG; /* set pointer */
r_val = *r_ptr & ~mask; /* get previous val, clear bits we want to change */
r_val |= (out & mask); /* set specified bits in value + plus origional ones */
*r_ptr = r_val; /* write it out */
/*
*r_ptr = r_val; /* write it out */
/*
* gcc screwed this one up :(.
*
*
* *(ushort *)GPIO_DATA_OUTPUT_REG = (*(ushort *)GPIO_DATA_OUTPUT_REG & ~mask) | (out & mask);
*/

View File

@@ -31,7 +31,6 @@
*/
#include <config.h>
#include <version.h>
@@ -137,14 +136,14 @@ reset:
bic r0,r0,#0x1f
orr r0,r0,#0xd3
msr cpsr,r0
/*
* Set up 925T mode
*/
mov r1, #0x81 /* Set ARM925T configuration. */
mcr p15, 0, r1, c15, c1, 0 /* Write ARM925T configuration register. */
/*
/*
* turn off the watchdog, unlock/diable sequence
*/
mov r1, #0xF5
@@ -162,9 +161,9 @@ reset:
ldr r0, =REG_IHL2_MIR
str r1, [r0]
/*
/*
* wait for dpll to lock
*/
*/
ldr r0, =CK_DPLL1
mov r1, #0x10
strh r1, [r0]
@@ -414,7 +413,7 @@ fiq:
.globl reset_cpu
reset_cpu:
ldr r1, rstctl1 /* get clkm1 reset ctl */
mov r3, #0x0
mov r3, #0x0
strh r3, [r1] /* clear it */
mov r3, #0x8
strh r3, [r1] /* force dsp+arm reset */

45
cpu/mpc5xxx/Makefile Normal file
View File

@@ -0,0 +1,45 @@
#
# (C) Copyright 2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
include $(TOPDIR)/config.mk
LIB = lib$(CPU).a
START = start.o
ASOBJS = io.o firmware_sc_task_bestcomm.impl.o firmware_sc_task.impl.o
OBJS = traps.o cpu.o cpu_init.o speed.o interrupts.o serial.o \
loadtask.o fec.o
all: .depend $(START) $(ASOBJS) $(LIB)
$(LIB): $(OBJS)
$(AR) crv $@ $(ASOBJS) $(OBJS)
#########################################################################
.depend: Makefile $(START:.o=.S) $(OBJS:.o=.c)
$(CC) -M $(CFLAGS) $(START:.o=.S) $(ASOBJS:.o=.S) $(OBJS:.o=.c) > $@
sinclude .depend
#########################################################################

27
cpu/mpc5xxx/config.mk Normal file
View File

@@ -0,0 +1,27 @@
#
# (C) Copyright 2003
# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
#
# See file CREDITS for list of people who contributed to this
# project.
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of
# the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
# MA 02111-1307 USA
#
PLATFORM_RELFLAGS += -mrelocatable -ffixed-r14 -meabi
PLATFORM_CPPFLAGS += -DCONFIG_MPC5XXX -ffixed-r2 -ffixed-r29 \
-mstring -mcpu=603e -mmultiple

103
cpu/mpc5xxx/cpu.c Normal file
View File

@@ -0,0 +1,103 @@
/*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* CPU specific code for the MPC5xxx CPUs
*/
#include <common.h>
#include <watchdog.h>
#include <command.h>
#include <mpc5xxx.h>
#include <asm/processor.h>
int checkcpu (void)
{
DECLARE_GLOBAL_DATA_PTR;
ulong clock = gd->cpu_clk;
char buf[32];
puts ("CPU: ");
printf (CPU_ID_STR);
printf (" (JTAG ID %08lx)", *(vu_long *)MPC5XXX_CDM_JTAGID);
printf (" at %s MHz\n", strmhz (buf, clock));
return 0;
}
/* ------------------------------------------------------------------------- */
int
do_reset (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
ulong msr, addr;
*(vu_long *)MPC5XXX_CDM_SRESET &= ~(1 << 16); /* Checkstop Reset enable */
/* Interrupts and MMU off */
__asm__ __volatile__ ("mfmsr %0":"=r" (msr):);
msr &= ~(MSR_ME | MSR_EE | MSR_IR | MSR_DR);
__asm__ __volatile__ ("mtmsr %0"::"r" (msr));
/*
* Trying to execute the next instruction at a non-existing address
* should cause a machine check, resulting in reset
*/
#ifdef CFG_RESET_ADDRESS
addr = CFG_RESET_ADDRESS;
#else
/*
* note: when CFG_MONITOR_BASE points to a RAM address, CFG_MONITOR_BASE
* - sizeof (ulong) is usually a valid address. Better pick an address
* known to be invalid on your system and assign it to CFG_RESET_ADDRESS.
*/
addr = CFG_MONITOR_BASE - sizeof (ulong);
#endif
((void (*)(void)) addr) ();
return 1;
}
/* ------------------------------------------------------------------------- */
/*
* Get timebase clock frequency (like cpu_clk in Hz)
*
*/
unsigned long get_tbclk (void)
{
DECLARE_GLOBAL_DATA_PTR;
ulong tbclk;
tbclk = (gd->bus_clk + 3L) / 4L;
return (tbclk);
}
/* ------------------------------------------------------------------------- */

185
cpu/mpc5xxx/cpu_init.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <common.h>
#include <mpc5xxx.h>
#if defined(CONFIG_MGT5100)
#define START_REG(start) ((start) >> 15)
#define STOP_REG(start, size) (((start) + (size) - 1) >> 15)
#elif defined(CONFIG_MPC5200)
#define START_REG(start) ((start) >> 16)
#define STOP_REG(start, size) (((start) + (size) - 1) >> 16)
#endif
/*
* Breath some life into the CPU...
*
* Set up the memory map,
* initialize a bunch of registers.
*/
void cpu_init_f (void)
{
DECLARE_GLOBAL_DATA_PTR;
unsigned long addecr = (1 << 25); /* Boot_CS */
#if defined(CFG_RAMBOOT) && defined(CONFIG_MGT5100)
addecr |= (1 << 22); /* SDRAM enable */
#endif
/* Pointer is writable since we allocated a register for it */
gd = (gd_t *) (CFG_INIT_RAM_ADDR + CFG_GBL_DATA_OFFSET);
/* Clear initial global data */
memset ((void *) gd, 0, sizeof (gd_t));
/*
* Memory Controller: configure chip selects and enable them
*/
#if defined(CFG_BOOTCS_START) && defined(CFG_BOOTCS_SIZE)
*(vu_long *)MPC5XXX_BOOTCS_START = START_REG(CFG_BOOTCS_START);
*(vu_long *)MPC5XXX_BOOTCS_STOP = STOP_REG(CFG_BOOTCS_START,
CFG_BOOTCS_SIZE);
#endif
#if defined(CFG_BOOTCS_CFG)
*(vu_long *)MPC5XXX_BOOTCS_CFG = CFG_BOOTCS_CFG;
#endif
#if defined(CFG_CS0_START) && defined(CFG_CS0_SIZE)
*(vu_long *)MPC5XXX_CS0_START = START_REG(CFG_CS0_START);
*(vu_long *)MPC5XXX_CS0_STOP = STOP_REG(CFG_CS0_START, CFG_CS0_SIZE);
/* CS0 and BOOT_CS cannot be enabled at once. */
/* addecr |= (1 << 16); */
#endif
#if defined(CFG_CS0_CFG)
*(vu_long *)MPC5XXX_CS0_CFG = CFG_CS0_CFG;
#endif
#if defined(CFG_CS1_START) && defined(CFG_CS1_SIZE)
*(vu_long *)MPC5XXX_CS1_START = START_REG(CFG_CS1_START);
*(vu_long *)MPC5XXX_CS1_STOP = STOP_REG(CFG_CS1_START, CFG_CS1_SIZE);
addecr |= (1 << 17);
#endif
#if defined(CFG_CS1_CFG)
*(vu_long *)MPC5XXX_CS1_CFG = CFG_CS1_CFG;
#endif
#if defined(CFG_CS2_START) && defined(CFG_CS2_SIZE)
*(vu_long *)MPC5XXX_CS2_START = START_REG(CFG_CS2_START);
*(vu_long *)MPC5XXX_CS2_STOP = STOP_REG(CFG_CS2_START, CFG_CS2_SIZE);
addecr |= (1 << 18);
#endif
#if defined(CFG_CS2_CFG)
*(vu_long *)MPC5XXX_CS2_CFG = CFG_CS2_CFG;
#endif
#if defined(CFG_CS3_START) && defined(CFG_CS3_SIZE)
*(vu_long *)MPC5XXX_CS3_START = START_REG(CFG_CS3_START);
*(vu_long *)MPC5XXX_CS3_STOP = STOP_REG(CFG_CS3_START, CFG_CS3_SIZE);
addecr |= (1 << 19);
#endif
#if defined(CFG_CS3_CFG)
*(vu_long *)MPC5XXX_CS3_CFG = CFG_CS3_CFG;
#endif
#if defined(CFG_CS4_START) && defined(CFG_CS4_SIZE)
*(vu_long *)MPC5XXX_CS4_START = START_REG(CFG_CS4_START);
*(vu_long *)MPC5XXX_CS4_STOP = STOP_REG(CFG_CS4_START, CFG_CS4_SIZE);
addecr |= (1 << 20);
#endif
#if defined(CFG_CS4_CFG)
*(vu_long *)MPC5XXX_CS4_CFG = CFG_CS4_CFG;
#endif
#if defined(CFG_CS5_START) && defined(CFG_CS5_SIZE)
*(vu_long *)MPC5XXX_CS5_START = START_REG(CFG_CS5_START);
*(vu_long *)MPC5XXX_CS5_STOP = STOP_REG(CFG_CS5_START, CFG_CS5_SIZE);
addecr |= (1 << 21);
#endif
#if defined(CFG_CS5_CFG)
*(vu_long *)MPC5XXX_CS5_CFG = CFG_CS5_CFG;
#endif
#if defined(CONFIG_MPC5200)
addecr |= 1;
#if defined(CFG_CS6_START) && defined(CFG_CS6_SIZE)
*(vu_long *)MPC5XXX_CS6_START = START_REG(CFG_CS6_START);
*(vu_long *)MPC5XXX_CS6_STOP = STOP_REG(CFG_CS6_START, CFG_CS6_SIZE);
addecr |= (1 << 26);
#endif
#if defined(CFG_CS6_CFG)
*(vu_long *)MPC5XXX_CS6_CFG = CFG_CS6_CFG;
#endif
#if defined(CFG_CS7_START) && defined(CFG_CS7_SIZE)
*(vu_long *)MPC5XXX_CS7_START = START_REG(CFG_CS5_START);
*(vu_long *)MPC5XXX_CS7_STOP = STOP_REG(CFG_CS7_START, CFG_CS7_SIZE);
addecr |= (1 << 27);
#endif
#if defined(CFG_CS7_CFG)
*(vu_long *)MPC5XXX_CS7_CFG = CFG_CS7_CFG;
#endif
#if defined(CFG_CS_BURST)
*(vu_long *)MPC5XXX_CS_BURST = CFG_CS_BURST;
#endif
#if defined(CFG_CS_DEADCYCLE)
*(vu_long *)MPC5XXX_CS_DEADCYCLE = CFG_CS_DEADCYCLE;
#endif
#endif /* CONFIG_MPC5200 */
/* Enable chip selects */
*(vu_long *)MPC5XXX_ADDECR = addecr;
*(vu_long *)MPC5XXX_CS_CTRL = (1 << 24);
/* Setup pin multiplexing */
#if defined(CFG_GPS_PORT_CONFIG)
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG = CFG_GPS_PORT_CONFIG;
#endif
}
/*
* initialize higher level parts of CPU like time base and timers
*/
int cpu_init_r (void)
{
/* mask all interrupts */
#if defined(CONFIG_MGT5100)
*(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xfffffc00;
#elif defined(CONFIG_MPC5200)
*(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xffffff00;
#endif
*(vu_long *)MPC5XXX_ICTL_CRIT |= 0x0001ffff;
*(vu_long *)MPC5XXX_ICTL_EXT &= ~0x00000f00;
#if defined(CONFIG_MPC5200)
/* enable timebase */
*(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 13);
#endif
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_MPC5XXX_FEC)
/* load FEC microcode */
loadtask(0, 2);
#endif
return (0);
}

944
cpu/mpc5xxx/fec.c Normal file
View File

@@ -0,0 +1,944 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* This file is based on mpc4200fec.c,
* (C) Copyright Motorola, Inc., 2000
*/
#include <common.h>
#include <mpc5xxx.h>
#include <malloc.h>
#include <net.h>
#include <miiphy.h>
#include "sdma.h"
#include "fec.h"
#define DEBUG 0x8
#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) && \
defined(CONFIG_MPC5XXX_FEC)
#if (DEBUG & 0x60)
static void tfifo_print(mpc5xxx_fec_priv *fec);
static void rfifo_print(mpc5xxx_fec_priv *fec);
#endif /* DEBUG */
#if (DEBUG & 0x40)
static uint32 local_crc32(char *string, unsigned int crc_value, int len);
#endif
/********************************************************************/
static int mpc5xxx_fec_rbd_init(mpc5xxx_fec_priv *fec)
{
int ix;
char *data;
/*
* the receive ring is located right after the transmit one
*/
for (ix = 0; ix < FEC_RBD_NUM; ix++) {
data = (char *)malloc(FEC_MAX_PKT_SIZE);
if (data == NULL) {
printf ("RBD INIT FAILED\n");
return -1;
}
fec->rbdBase[ix].status = FEC_RBD_EMPTY;
fec->rbdBase[ix].dataLength = 0;
fec->rbdBase[ix].dataPointer = (uint32)data;
}
/*
* have the last RBD to close the ring
*/
fec->rbdBase[ix - 1].status |= FEC_RBD_WRAP;
fec->rbdIndex = 0;
return 0;
}
/********************************************************************/
static void mpc5xxx_fec_tbd_init(mpc5xxx_fec_priv *fec)
{
int ix;
for (ix = 0; ix < FEC_TBD_NUM; ix++) {
fec->tbdBase[ix].status = 0;
}
/*
* Have the last TBD to close the ring
*/
fec->tbdBase[ix - 1].status |= FEC_TBD_WRAP;
/*
* Initialize some indices
*/
fec->tbdIndex = 0;
fec->usedTbdIndex = 0;
fec->cleanTbdNum = FEC_TBD_NUM;
}
/********************************************************************/
static void mpc5xxx_fec_rbd_clean(mpc5xxx_fec_priv *fec, FEC_RBD * pRbd)
{
/*
* Reset buffer descriptor as empty
*/
if ((fec->rbdIndex) == (FEC_RBD_NUM - 1))
pRbd->status = (FEC_RBD_WRAP | FEC_RBD_EMPTY);
else
pRbd->status = FEC_RBD_EMPTY;
pRbd->dataLength = 0;
/*
* Now, we have an empty RxBD, restart the SmartDMA receive task
*/
SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
/*
* Increment BD count
*/
fec->rbdIndex = (fec->rbdIndex + 1) % FEC_RBD_NUM;
}
/********************************************************************/
static void mpc5xxx_fec_tbd_scrub(mpc5xxx_fec_priv *fec)
{
FEC_TBD *pUsedTbd;
#if (DEBUG & 0x1)
printf ("tbd_scrub: fec->cleanTbdNum = %d, fec->usedTbdIndex = %d\n",
fec->cleanTbdNum, fec->usedTbdIndex);
#endif
/*
* process all the consumed TBDs
*/
while (fec->cleanTbdNum < FEC_TBD_NUM) {
pUsedTbd = &fec->tbdBase[fec->usedTbdIndex];
if (pUsedTbd->status & FEC_TBD_READY) {
#if (DEBUG & 0x20)
printf("Cannot clean TBD %d, in use\n", fec->cleanTbdNum);
#endif
return;
}
/*
* clean this buffer descriptor
*/
if (fec->usedTbdIndex == (FEC_TBD_NUM - 1))
pUsedTbd->status = FEC_TBD_WRAP;
else
pUsedTbd->status = 0;
/*
* update some indeces for a correct handling of the TBD ring
*/
fec->cleanTbdNum++;
fec->usedTbdIndex = (fec->usedTbdIndex + 1) % FEC_TBD_NUM;
}
}
/********************************************************************/
static void mpc5xxx_fec_set_hwaddr(mpc5xxx_fec_priv *fec, char *mac)
{
uint8 currByte; /* byte for which to compute the CRC */
int byte; /* loop - counter */
int bit; /* loop - counter */
uint32 crc = 0xffffffff; /* initial value */
/*
* The algorithm used is the following:
* we loop on each of the six bytes of the provided address,
* and we compute the CRC by left-shifting the previous
* value by one position, so that each bit in the current
* byte of the address may contribute the calculation. If
* the latter and the MSB in the CRC are different, then
* the CRC value so computed is also ex-ored with the
* "polynomium generator". The current byte of the address
* is also shifted right by one bit at each iteration.
* This is because the CRC generatore in hardware is implemented
* as a shift-register with as many ex-ores as the radixes
* in the polynomium. This suggests that we represent the
* polynomiumm itself as a 32-bit constant.
*/
for (byte = 0; byte < 6; byte++) {
currByte = mac[byte];
for (bit = 0; bit < 8; bit++) {
if ((currByte & 0x01) ^ (crc & 0x01)) {
crc >>= 1;
crc = crc ^ 0xedb88320;
} else {
crc >>= 1;
}
currByte >>= 1;
}
}
crc = crc >> 26;
/*
* Set individual hash table register
*/
if (crc >= 32) {
fec->eth->iaddr1 = (1 << (crc - 32));
fec->eth->iaddr2 = 0;
} else {
fec->eth->iaddr1 = 0;
fec->eth->iaddr2 = (1 << crc);
}
/*
* Set physical address
*/
fec->eth->paddr1 = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3];
fec->eth->paddr2 = (mac[4] << 24) + (mac[5] << 16) + 0x8808;
}
/********************************************************************/
static int mpc5xxx_fec_init(struct eth_device *dev, bd_t * bis)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
const uint8 phyAddr = 0; /* Only one PHY */
#if (DEBUG & 0x1)
printf ("mpc5xxx_fec_init... Begin\n");
#endif
/*
* Initialize RxBD/TxBD rings
*/
mpc5xxx_fec_rbd_init(fec);
mpc5xxx_fec_tbd_init(fec);
/*
* Initialize GPIO pins
*/
if (fec->xcv_type == SEVENWIRE) {
/* 10MBit with 7-wire operation */
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00020000;
} else {
/* 100MBit with MD operation */
*(vu_long *)MPC5XXX_GPS_PORT_CONFIG |= 0x00050000;
}
/*
* Clear FEC-Lite interrupt event register(IEVENT)
*/
fec->eth->ievent = 0xffffffff;
/*
* Set interrupt mask register
*/
fec->eth->imask = 0x00000000;
/*
* Set FEC-Lite receive control register(R_CNTRL):
*/
if (fec->xcv_type == SEVENWIRE) {
/*
* Frame length=1518; 7-wire mode
*/
fec->eth->r_cntrl = 0x05ee0020; /*0x05ee0000;FIXME */
} else {
/*
* Frame length=1518; MII mode;
*/
fec->eth->r_cntrl = 0x05ee0024; /*0x05ee0004;FIXME */
}
if (fec->xcv_type == SEVENWIRE) {
/*
* Set FEC-Lite transmit control register(X_CNTRL):
*/
/*fec->eth->x_cntrl = 0x00000002; */ /* half-duplex, heartbeat */
fec->eth->x_cntrl = 0x00000000; /* half-duplex, heartbeat disabled */
} else {
/*fec->eth->x_cntrl = 0x00000006; */ /* full-duplex, heartbeat */
fec->eth->x_cntrl = 0x00000004; /* full-duplex, heartbeat disabled */
/*
* Set MII_SPEED = (1/(mii_speed * 2)) * System Clock(25Mhz)
* and do not drop the Preamble.
*/
fec->eth->mii_speed = (0x5 << 1); /* No MII for 7-wire mode */
}
/*
* Set Opcode/Pause Duration Register
*/
fec->eth->op_pause = 0x00010020; /*FIXME0xffff0020; */
/*
* Set Rx FIFO alarm and granularity value
*/
fec->eth->rfifo_cntrl = 0x0c000000;
fec->eth->rfifo_alarm = 0x0000030c;
#if (DEBUG & 0x22)
if (fec->eth->rfifo_status & 0x00700000 ) {
printf("mpc5xxx_fec_init() RFIFO error\n");
}
#endif
/*
* Set Tx FIFO granularity value
*/
fec->eth->tfifo_cntrl = 0x0c000000;
#if (DEBUG & 0x2)
printf("tfifo_status: 0x%08x\n", fec->eth->tfifo_status);
printf("tfifo_alarm: 0x%08x\n", fec->eth->tfifo_alarm);
#endif
/*
* Set transmit fifo watermark register(X_WMRK), default = 64
*/
fec->eth->tfifo_alarm = 0x00000080;
fec->eth->x_wmrk = 0x2;
/*
* Set individual address filter for unicast address
* and set physical address registers.
*/
mpc5xxx_fec_set_hwaddr(fec, dev->enetaddr);
/*
* Set multicast address filter
*/
fec->eth->gaddr1 = 0x00000000;
fec->eth->gaddr2 = 0x00000000;
/*
* Turn ON cheater FSM: ????
*/
fec->eth->xmit_fsm = 0x03000000;
#if defined(CONFIG_MPC5200)
/*
* Turn off COMM bus prefetch in the MGT5200 BestComm. It doesn't
* work w/ the current receive task.
*/
sdma->PtdCntrl |= 0x00000001;
#endif
/*
* Set priority of different initiators
*/
sdma->IPR0 = 7; /* always */
sdma->IPR3 = 6; /* Eth RX */
sdma->IPR4 = 5; /* Eth Tx */
/*
* Clear SmartDMA task interrupt pending bits
*/
SDMA_CLEAR_IEVENT(FEC_RECV_TASK_NO);
/*
* Set SmartDMA intMask register to enable SmartDMA task interrupts
*/
SDMA_INT_ENABLE(FEC_RECV_TASK_NO);
/*
* Initialize SmartDMA parameters stored in SRAM
*/
*(int *)FEC_TBD_BASE = (int)fec->tbdBase;
*(int *)FEC_RBD_BASE = (int)fec->rbdBase;
*(int *)FEC_TBD_NEXT = (int)fec->tbdBase;
*(int *)FEC_RBD_NEXT = (int)fec->rbdBase;
if (fec->xcv_type != SEVENWIRE) {
/*
* Initialize PHY(LXT971A):
*
* Generally, on power up, the LXT971A reads its configuration
* pins to check for forced operation, If not cofigured for
* forced operation, it uses auto-negotiation/parallel detection
* to automatically determine line operating conditions.
* If the PHY device on the other side of the link supports
* auto-negotiation, the LXT971A auto-negotiates with it
* using Fast Link Pulse(FLP) Bursts. If the PHY partner does not
* support auto-negotiation, the LXT971A automatically detects
* the presence of either link pulses(10Mbps PHY) or Idle
* symbols(100Mbps) and sets its operating conditions accordingly.
*
* When auto-negotiation is controlled by software, the following
* steps are recommended.
*
* Note:
* The physical address is dependent on hardware configuration.
*
*/
int timeout = 1;
uint16 phyStatus;
/*
* Reset PHY, then delay 300ns
*/
miiphy_write(phyAddr, 0x0, 0x8000);
udelay(1000);
if (fec->xcv_type == MII10) {
/*
* Force 10Base-T, FDX operation
*/
printf("Forcing 10 Mbps ethernet link... ");
miiphy_read(phyAddr, 0x1, &phyStatus);
/*
miiphy_write(fec, phyAddr, 0x0, 0x0100);
*/
miiphy_write(phyAddr, 0x0, 0x0180);
timeout = 20;
do { /* wait for link status to go down */
udelay(10000);
if ((timeout--) == 0) {
#if (DEBUG & 0x2)
printf("hmmm, should not have waited...");
#endif
break;
}
miiphy_read(phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf("=");
#endif
} while ((phyStatus & 0x0004)); /* !link up */
timeout = 1000;
do { /* wait for link status to come back up */
udelay(10000);
if ((timeout--) == 0) {
printf("failed. Link is down.\n");
break;
}
miiphy_read(phyAddr, 0x1, &phyStatus);
#if (DEBUG & 0x2)
printf("+");
#endif
} while (!(phyStatus & 0x0004)); /* !link up */
printf ("done.\n");
} else { /* MII100 */
/*
* Set the auto-negotiation advertisement register bits
*/
miiphy_write(phyAddr, 0x4, 0x01e1);
/*
* Set MDIO bit 0.12 = 1(&& bit 0.9=1?) to enable auto-negotiation
*/
miiphy_write(phyAddr, 0x0, 0x1200);
/*
* Wait for AN completion
*/
timeout = 5000;
do {
udelay(1000);
if ((timeout--) == 0) {
#if (DEBUG & 0x2)
printf("PHY auto neg 0 failed...\n");
#endif
return -1;
}
if (miiphy_read(phyAddr, 0x1, &phyStatus) != 0) {
#if (DEBUG & 0x2)
printf("PHY auto neg 1 failed 0x%04x...\n", phyStatus);
#endif
return -1;
}
} while ((phyStatus & 0x0020) != 0x0020);
#if (DEBUG & 0x2)
printf("PHY auto neg complete! \n");
#endif
}
}
/*
* Enable FEC-Lite controller
*/
fec->eth->ecntrl |= 0x00000006;
if (fec->xcv_type != SEVENWIRE) {
#if (DEBUG & 0x2)
uint16 phyStatus, i;
uint8 phyAddr = 0;
for (i = 0; i < 9; i++) {
miiphy_read(phyAddr, i, &phyStatus);
printf("Mii reg %d: 0x%04x\n", i, phyStatus);
}
for (i = 16; i < 21; i++) {
miiphy_read(phyAddr, i, &phyStatus);
printf("Mii reg %d: 0x%04x\n", i, phyStatus);
}
#endif
}
/*
* Enable SmartDMA receive task
*/
SDMA_TASK_ENABLE(FEC_RECV_TASK_NO);
#if (DEBUG & 0x1)
printf("mpc5xxx_fec_init... Done \n");
#endif
return 0;
}
/********************************************************************/
static void mpc5xxx_fec_halt(struct eth_device *dev)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA;
int counter = 0xffff;
#if (DEBUG & 0x2)
if (fec->xcv_type != SEVENWIRE) {
uint16 phyStatus, i;
uint8 phyAddr = 0;
for (i = 0; i < 9; i++) {
miiphy_read(phyAddr, i, &phyStatus);
printf("Mii reg %d: 0x%04x\n", i, phyStatus);
}
for (i = 16; i < 21; i++) {
miiphy_read(phyAddr, i, &phyStatus);
printf ("Mii reg %d: 0x%04x\n", i, phyStatus);
}
}
#endif
/*
* mask FEC chip interrupts
*/
fec->eth->imask = 0;
/*
* issue graceful stop command to the FEC transmitter if necessary
*/
fec->eth->x_cntrl |= 0x00000001;
/*
* wait for graceful stop to register
*/
while ((counter--) && (!(fec->eth->ievent & 0x10000000))) ;
SDMA_INT_DISABLE (FEC_RECV_TASK_NO);
/*
* Disable SmartDMA tasks
*/
SDMA_TASK_DISABLE (FEC_XMIT_TASK_NO);
SDMA_TASK_DISABLE (FEC_RECV_TASK_NO);
#if defined(CONFIG_MPC5200)
/*
* Turn on COMM bus prefetch in the MGT5200 BestComm after we're
* done. It doesn't work w/ the current receive task.
*/
sdma->PtdCntrl &= ~0x00000001;
#endif
/*
* Disable the Ethernet Controller
*/
fec->eth->ecntrl &= 0xfffffffd;
/*
* Clear FIFO status registers
*/
fec->eth->rfifo_status &= 0x00700000;
fec->eth->tfifo_status &= 0x00700000;
fec->eth->reset_cntrl = 0x01000000;
/*
* Issue a reset command to the FEC chip
*/
fec->eth->ecntrl |= 0x1;
/*
* wait at least 16 clock cycles
*/
udelay(10);
#if (DEBUG & 0x3)
printf("Ethernet task stopped\n");
#endif
}
#if (DEBUG & 0x60)
/********************************************************************/
static void tfifo_print(mpc5xxx_fec_priv *fec)
{
uint16 phyAddr = 0;
uint16 phyStatus;
if ((fec->eth->tfifo_lrf_ptr != fec->eth->tfifo_lwf_ptr)
|| (fec->eth->tfifo_rdptr != fec->eth->tfifo_wrptr)) {
miiphy_read(phyAddr, 0x1, &phyStatus);
printf("\nphyStatus: 0x%04x\n", phyStatus);
printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
printf("ievent: 0x%08x\n", fec->eth->ievent);
printf("x_status: 0x%08x\n", fec->eth->x_status);
printf("tfifo: status 0x%08x\n", fec->eth->tfifo_status);
printf(" control 0x%08x\n", fec->eth->tfifo_cntrl);
printf(" lrfp 0x%08x\n", fec->eth->tfifo_lrf_ptr);
printf(" lwfp 0x%08x\n", fec->eth->tfifo_lwf_ptr);
printf(" alarm 0x%08x\n", fec->eth->tfifo_alarm);
printf(" readptr 0x%08x\n", fec->eth->tfifo_rdptr);
printf(" writptr 0x%08x\n", fec->eth->tfifo_wrptr);
}
}
static void rfifo_print(mpc5xxx_fec_priv *fec)
{
uint16 phyAddr = 0;
uint16 phyStatus;
if ((fec->eth->rfifo_lrf_ptr != fec->eth->rfifo_lwf_ptr)
|| (fec->eth->rfifo_rdptr != fec->eth->rfifo_wrptr)) {
miiphy_read(phyAddr, 0x1, &phyStatus);
printf("\nphyStatus: 0x%04x\n", phyStatus);
printf("ecntrl: 0x%08x\n", fec->eth->ecntrl);
printf("ievent: 0x%08x\n", fec->eth->ievent);
printf("x_status: 0x%08x\n", fec->eth->x_status);
printf("rfifo: status 0x%08x\n", fec->eth->rfifo_status);
printf(" control 0x%08x\n", fec->eth->rfifo_cntrl);
printf(" lrfp 0x%08x\n", fec->eth->rfifo_lrf_ptr);
printf(" lwfp 0x%08x\n", fec->eth->rfifo_lwf_ptr);
printf(" alarm 0x%08x\n", fec->eth->rfifo_alarm);
printf(" readptr 0x%08x\n", fec->eth->rfifo_rdptr);
printf(" writptr 0x%08x\n", fec->eth->rfifo_wrptr);
}
}
#endif /* DEBUG */
/********************************************************************/
static int mpc5xxx_fec_send(struct eth_device *dev, volatile void *eth_data,
int data_length)
{
/*
* This routine transmits one frame. This routine only accepts
* 6-byte Ethernet addresses.
*/
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
FEC_TBD *pTbd;
#if (DEBUG & 0x20)
printf("tbd status: 0x%04x\n", fec->tbdBase[0].status);
tfifo_print(fec);
#endif
/*
* Clear Tx BD ring at first
*/
mpc5xxx_fec_tbd_scrub(fec);
/*
* Check for valid length of data.
*/
if ((data_length > 1500) || (data_length <= 0)) {
return -1;
}
/*
* Check the number of vacant TxBDs.
*/
if (fec->cleanTbdNum < 1) {
#if (DEBUG & 0x20)
printf("No available TxBDs ...\n");
#endif
return -1;
}
/*
* Get the first TxBD to send the mac header
*/
pTbd = &fec->tbdBase[fec->tbdIndex];
pTbd->dataLength = data_length;
pTbd->dataPointer = (uint32)eth_data;
pTbd->status |= FEC_TBD_READY;
fec->tbdIndex = (fec->tbdIndex + 1) % FEC_TBD_NUM;
#if (DEBUG & 0x100)
printf("SDMA_TASK_ENABLE, fec->tbdIndex = %d \n", fec->tbdIndex);
#endif
/*
* Kick the MII i/f
*/
if (fec->xcv_type != SEVENWIRE) {
uint16 phyStatus;
miiphy_read(0, 0x1, &phyStatus);
}
/*
* Enable SmartDMA transmit task
*/
#if (DEBUG & 0x20)
tfifo_print(fec);
#endif
SDMA_TASK_ENABLE (FEC_XMIT_TASK_NO);
#if (DEBUG & 0x20)
tfifo_print(fec);
#endif
#if (DEBUG & 0x8)
printf( "+" );
#endif
fec->cleanTbdNum -= 1;
#if (DEBUG & 0x129) && (DEBUG & 0x80000000)
printf ("smartDMA ethernet Tx task enabled\n");
#endif
/*
* wait until frame is sent .
*/
while (pTbd->status & FEC_TBD_READY) {
udelay(10);
#if (DEBUG & 0x8)
printf ("TDB status = %04x\n", pTbd->status);
#endif
}
return 0;
}
/********************************************************************/
static int mpc5xxx_fec_recv(struct eth_device *dev)
{
/*
* This command pulls one frame from the card
*/
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
FEC_RBD *pRbd = &fec->rbdBase[fec->rbdIndex];
unsigned long ievent;
int frame_length;
char *frame;
#if (DEBUG & 0x1)
printf ("mpc5xxx_fec_recv %d Start...\n", fec->rbdIndex);
#endif
#if (DEBUG & 0x8)
printf( "-" );
#endif
/*
* Check if any critical events have happened
*/
ievent = fec->eth->ievent;
fec->eth->ievent = ievent;
if (ievent & 0x20060000) {
/* BABT, Rx/Tx FIFO errors */
mpc5xxx_fec_halt(dev);
mpc5xxx_fec_init(dev, NULL);
return 0;
}
if (ievent & 0x80000000) {
/* Heartbeat error */
fec->eth->x_cntrl |= 0x00000001;
}
if (ievent & 0x10000000) {
/* Graceful stop complete */
if (fec->eth->x_cntrl & 0x00000001) {
mpc5xxx_fec_halt(dev);
fec->eth->x_cntrl &= ~0x00000001;
mpc5xxx_fec_init(dev, NULL);
}
}
/*
* Do we have data in Rx FIFO?
*/
if ((pRbd->status & FEC_RBD_EMPTY) || !(pRbd->status & FEC_RBD_LAST)){
return 0;
}
/*
* Pass the packet up only if reception was Ok
*/
if ((pRbd->dataLength <= 14) || (pRbd->status & FEC_RBD_ERR)) {
mpc5xxx_fec_rbd_clean(fec, pRbd);
#if (DEBUG & 0x8)
printf( "X0" );
#endif
return 0;
}
/*
* Get buffer address and size
*/
frame = (char *)pRbd->dataPointer;
frame_length = pRbd->dataLength;
/*
* Pass the buffer to upper layers
*/
NetReceive(frame, frame_length);
/*
* Reset buffer descriptor as empty
*/
mpc5xxx_fec_rbd_clean(fec, pRbd);
return frame_length;
}
/********************************************************************/
int mpc5xxx_fec_initialize(bd_t * bis)
{
mpc5xxx_fec_priv *fec;
struct eth_device *dev;
fec = (mpc5xxx_fec_priv *)malloc(sizeof(*fec));
dev = (struct eth_device *)malloc(sizeof(*dev));
fec->eth = (ethernet_regs *)MPC5XXX_FEC;
fec->tbdBase = (FEC_TBD *)FEC_BD_BASE;
fec->rbdBase = (FEC_RBD *)(FEC_BD_BASE + FEC_TBD_NUM * sizeof(FEC_TBD));
#ifdef CONFIG_ICECUBE
fec->xcv_type = MII100;
#endif
dev->priv = (void *)fec;
dev->iobase = MPC5XXX_FEC;
dev->init = mpc5xxx_fec_init;
dev->halt = mpc5xxx_fec_halt;
dev->send = mpc5xxx_fec_send;
dev->recv = mpc5xxx_fec_recv;
eth_register(dev);
return 1;
}
/* MII-interface related functions */
/********************************************************************/
int miiphy_read(uint8 phyAddr, uint8 regAddr, uint16 * retVal)
{
ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;
/*
* reading from any PHY's register is done by properly
* programming the FEC's MII data register.
*/
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_RD | FEC_MII_DATA_TA | phy | reg);
/*
* wait for the related interrupt
*/
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
if (timeout == 0) {
#if (DEBUG & 0x2)
printf ("Read MDIO failed...\n");
#endif
return -1;
}
/*
* clear mii interrupt bit
*/
eth->ievent = 0x00800000;
/*
* it's now safe to read the PHY's register
*/
*retVal = (uint16) eth->mii_data;
return 0;
}
/********************************************************************/
int miiphy_write(uint8 phyAddr, uint8 regAddr, uint16 data)
{
ethernet_regs *eth = (ethernet_regs *)MPC5XXX_FEC;
uint32 reg; /* convenient holder for the PHY register */
uint32 phy; /* convenient holder for the PHY */
int timeout = 0xffff;
reg = regAddr << FEC_MII_DATA_RA_SHIFT;
phy = phyAddr << FEC_MII_DATA_PA_SHIFT;
eth->mii_data = (FEC_MII_DATA_ST | FEC_MII_DATA_OP_WR |
FEC_MII_DATA_TA | phy | reg | data);
/*
* wait for the MII interrupt
*/
while ((timeout--) && (!(eth->ievent & 0x00800000))) ;
if (timeout == 0) {
#if (DEBUG & 0x2)
printf ("Write MDIO failed...\n");
#endif
return -1;
}
/*
* clear MII interrupt bit
*/
eth->ievent = 0x00800000;
return 0;
}
#if (DEBUG & 0x40)
static uint32 local_crc32(char *string, unsigned int crc_value, int len)
{
int i;
char c;
unsigned int crc, count;
/*
* crc32 algorithm
*/
/*
* crc = 0xffffffff; * The initialized value should be 0xffffffff
*/
crc = crc_value;
for (i = len; --i >= 0;) {
c = *string++;
for (count = 0; count < 8; count++) {
if ((c & 0x01) ^ (crc & 0x01)) {
crc >>= 1;
crc = crc ^ 0xedb88320;
} else {
crc >>= 1;
}
c >>= 1;
}
}
/*
* In big endian system, do byte swaping for crc value
*/
/**/ return crc;
}
#endif /* DEBUG */
#endif /* CONFIG_MPC5XXX_FEC */

286
cpu/mpc5xxx/fec.h Normal file
View File

@@ -0,0 +1,286 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* This file is based on mpc4200fec.h
* (C) Copyright Motorola, Inc., 2000
*
* odin ethernet header file
*/
#ifndef __MPC5XXX_FEC_H
#define __MPC5XXX_FEC_H
#include <common.h>
#include <mpc5xxx.h>
#include "sdma.h"
typedef unsigned long uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef struct ethernet_register_set {
/* [10:2]addr = 00 */
/* Control and status Registers (offset 000-1FF) */
volatile uint32 fec_id; /* MBAR_ETH + 0x000 */
volatile uint32 ievent; /* MBAR_ETH + 0x004 */
volatile uint32 imask; /* MBAR_ETH + 0x008 */
volatile uint32 RES0[1]; /* MBAR_ETH + 0x00C */
volatile uint32 r_des_active; /* MBAR_ETH + 0x010 */
volatile uint32 x_des_active; /* MBAR_ETH + 0x014 */
volatile uint32 r_des_active_cl; /* MBAR_ETH + 0x018 */
volatile uint32 x_des_active_cl; /* MBAR_ETH + 0x01C */
volatile uint32 ivent_set; /* MBAR_ETH + 0x020 */
volatile uint32 ecntrl; /* MBAR_ETH + 0x024 */
volatile uint32 RES1[6]; /* MBAR_ETH + 0x028-03C */
volatile uint32 mii_data; /* MBAR_ETH + 0x040 */
volatile uint32 mii_speed; /* MBAR_ETH + 0x044 */
volatile uint32 mii_status; /* MBAR_ETH + 0x048 */
volatile uint32 RES2[5]; /* MBAR_ETH + 0x04C-05C */
volatile uint32 mib_data; /* MBAR_ETH + 0x060 */
volatile uint32 mib_control; /* MBAR_ETH + 0x064 */
volatile uint32 RES3[6]; /* MBAR_ETH + 0x068-7C */
volatile uint32 r_activate; /* MBAR_ETH + 0x080 */
volatile uint32 r_cntrl; /* MBAR_ETH + 0x084 */
volatile uint32 r_hash; /* MBAR_ETH + 0x088 */
volatile uint32 r_data; /* MBAR_ETH + 0x08C */
volatile uint32 ar_done; /* MBAR_ETH + 0x090 */
volatile uint32 r_test; /* MBAR_ETH + 0x094 */
volatile uint32 r_mib; /* MBAR_ETH + 0x098 */
volatile uint32 r_da_low; /* MBAR_ETH + 0x09C */
volatile uint32 r_da_high; /* MBAR_ETH + 0x0A0 */
volatile uint32 RES4[7]; /* MBAR_ETH + 0x0A4-0BC */
volatile uint32 x_activate; /* MBAR_ETH + 0x0C0 */
volatile uint32 x_cntrl; /* MBAR_ETH + 0x0C4 */
volatile uint32 backoff; /* MBAR_ETH + 0x0C8 */
volatile uint32 x_data; /* MBAR_ETH + 0x0CC */
volatile uint32 x_status; /* MBAR_ETH + 0x0D0 */
volatile uint32 x_mib; /* MBAR_ETH + 0x0D4 */
volatile uint32 x_test; /* MBAR_ETH + 0x0D8 */
volatile uint32 fdxfc_da1; /* MBAR_ETH + 0x0DC */
volatile uint32 fdxfc_da2; /* MBAR_ETH + 0x0E0 */
volatile uint32 paddr1; /* MBAR_ETH + 0x0E4 */
volatile uint32 paddr2; /* MBAR_ETH + 0x0E8 */
volatile uint32 op_pause; /* MBAR_ETH + 0x0EC */
volatile uint32 RES5[4]; /* MBAR_ETH + 0x0F0-0FC */
volatile uint32 instr_reg; /* MBAR_ETH + 0x100 */
volatile uint32 context_reg; /* MBAR_ETH + 0x104 */
volatile uint32 test_cntrl; /* MBAR_ETH + 0x108 */
volatile uint32 acc_reg; /* MBAR_ETH + 0x10C */
volatile uint32 ones; /* MBAR_ETH + 0x110 */
volatile uint32 zeros; /* MBAR_ETH + 0x114 */
volatile uint32 iaddr1; /* MBAR_ETH + 0x118 */
volatile uint32 iaddr2; /* MBAR_ETH + 0x11C */
volatile uint32 gaddr1; /* MBAR_ETH + 0x120 */
volatile uint32 gaddr2; /* MBAR_ETH + 0x124 */
volatile uint32 random; /* MBAR_ETH + 0x128 */
volatile uint32 rand1; /* MBAR_ETH + 0x12C */
volatile uint32 tmp; /* MBAR_ETH + 0x130 */
volatile uint32 RES6[3]; /* MBAR_ETH + 0x134-13C */
volatile uint32 fifo_id; /* MBAR_ETH + 0x140 */
volatile uint32 x_wmrk; /* MBAR_ETH + 0x144 */
volatile uint32 fcntrl; /* MBAR_ETH + 0x148 */
volatile uint32 r_bound; /* MBAR_ETH + 0x14C */
volatile uint32 r_fstart; /* MBAR_ETH + 0x150 */
volatile uint32 r_count; /* MBAR_ETH + 0x154 */
volatile uint32 r_lag; /* MBAR_ETH + 0x158 */
volatile uint32 r_read; /* MBAR_ETH + 0x15C */
volatile uint32 r_write; /* MBAR_ETH + 0x160 */
volatile uint32 x_count; /* MBAR_ETH + 0x164 */
volatile uint32 x_lag; /* MBAR_ETH + 0x168 */
volatile uint32 x_retry; /* MBAR_ETH + 0x16C */
volatile uint32 x_write; /* MBAR_ETH + 0x170 */
volatile uint32 x_read; /* MBAR_ETH + 0x174 */
volatile uint32 RES7[2]; /* MBAR_ETH + 0x178-17C */
volatile uint32 fm_cntrl; /* MBAR_ETH + 0x180 */
volatile uint32 rfifo_data; /* MBAR_ETH + 0x184 */
volatile uint32 rfifo_status; /* MBAR_ETH + 0x188 */
volatile uint32 rfifo_cntrl; /* MBAR_ETH + 0x18C */
volatile uint32 rfifo_lrf_ptr; /* MBAR_ETH + 0x190 */
volatile uint32 rfifo_lwf_ptr; /* MBAR_ETH + 0x194 */
volatile uint32 rfifo_alarm; /* MBAR_ETH + 0x198 */
volatile uint32 rfifo_rdptr; /* MBAR_ETH + 0x19C */
volatile uint32 rfifo_wrptr; /* MBAR_ETH + 0x1A0 */
volatile uint32 tfifo_data; /* MBAR_ETH + 0x1A4 */
volatile uint32 tfifo_status; /* MBAR_ETH + 0x1A8 */
volatile uint32 tfifo_cntrl; /* MBAR_ETH + 0x1AC */
volatile uint32 tfifo_lrf_ptr; /* MBAR_ETH + 0x1B0 */
volatile uint32 tfifo_lwf_ptr; /* MBAR_ETH + 0x1B4 */
volatile uint32 tfifo_alarm; /* MBAR_ETH + 0x1B8 */
volatile uint32 tfifo_rdptr; /* MBAR_ETH + 0x1BC */
volatile uint32 tfifo_wrptr; /* MBAR_ETH + 0x1C0 */
volatile uint32 reset_cntrl; /* MBAR_ETH + 0x1C4 */
volatile uint32 xmit_fsm; /* MBAR_ETH + 0x1C8 */
volatile uint32 RES8[3]; /* MBAR_ETH + 0x1CC-1D4 */
volatile uint32 rdes_data0; /* MBAR_ETH + 0x1D8 */
volatile uint32 rdes_data1; /* MBAR_ETH + 0x1DC */
volatile uint32 r_length; /* MBAR_ETH + 0x1E0 */
volatile uint32 x_length; /* MBAR_ETH + 0x1E4 */
volatile uint32 x_addr; /* MBAR_ETH + 0x1E8 */
volatile uint32 cdes_data; /* MBAR_ETH + 0x1EC */
volatile uint32 status; /* MBAR_ETH + 0x1F0 */
volatile uint32 dma_control; /* MBAR_ETH + 0x1F4 */
volatile uint32 des_cmnd; /* MBAR_ETH + 0x1F8 */
volatile uint32 data; /* MBAR_ETH + 0x1FC */
/* MIB COUNTERS (Offset 200-2FF) */
volatile uint32 rmon_t_drop; /* MBAR_ETH + 0x200 */
volatile uint32 rmon_t_packets; /* MBAR_ETH + 0x204 */
volatile uint32 rmon_t_bc_pkt; /* MBAR_ETH + 0x208 */
volatile uint32 rmon_t_mc_pkt; /* MBAR_ETH + 0x20C */
volatile uint32 rmon_t_crc_align; /* MBAR_ETH + 0x210 */
volatile uint32 rmon_t_undersize; /* MBAR_ETH + 0x214 */
volatile uint32 rmon_t_oversize; /* MBAR_ETH + 0x218 */
volatile uint32 rmon_t_frag; /* MBAR_ETH + 0x21C */
volatile uint32 rmon_t_jab; /* MBAR_ETH + 0x220 */
volatile uint32 rmon_t_col; /* MBAR_ETH + 0x224 */
volatile uint32 rmon_t_p64; /* MBAR_ETH + 0x228 */
volatile uint32 rmon_t_p65to127; /* MBAR_ETH + 0x22C */
volatile uint32 rmon_t_p128to255; /* MBAR_ETH + 0x230 */
volatile uint32 rmon_t_p256to511; /* MBAR_ETH + 0x234 */
volatile uint32 rmon_t_p512to1023; /* MBAR_ETH + 0x238 */
volatile uint32 rmon_t_p1024to2047; /* MBAR_ETH + 0x23C */
volatile uint32 rmon_t_p_gte2048; /* MBAR_ETH + 0x240 */
volatile uint32 rmon_t_octets; /* MBAR_ETH + 0x244 */
volatile uint32 ieee_t_drop; /* MBAR_ETH + 0x248 */
volatile uint32 ieee_t_frame_ok; /* MBAR_ETH + 0x24C */
volatile uint32 ieee_t_1col; /* MBAR_ETH + 0x250 */
volatile uint32 ieee_t_mcol; /* MBAR_ETH + 0x254 */
volatile uint32 ieee_t_def; /* MBAR_ETH + 0x258 */
volatile uint32 ieee_t_lcol; /* MBAR_ETH + 0x25C */
volatile uint32 ieee_t_excol; /* MBAR_ETH + 0x260 */
volatile uint32 ieee_t_macerr; /* MBAR_ETH + 0x264 */
volatile uint32 ieee_t_cserr; /* MBAR_ETH + 0x268 */
volatile uint32 ieee_t_sqe; /* MBAR_ETH + 0x26C */
volatile uint32 t_fdxfc; /* MBAR_ETH + 0x270 */
volatile uint32 ieee_t_octets_ok; /* MBAR_ETH + 0x274 */
volatile uint32 RES9[2]; /* MBAR_ETH + 0x278-27C */
volatile uint32 rmon_r_drop; /* MBAR_ETH + 0x280 */
volatile uint32 rmon_r_packets; /* MBAR_ETH + 0x284 */
volatile uint32 rmon_r_bc_pkt; /* MBAR_ETH + 0x288 */
volatile uint32 rmon_r_mc_pkt; /* MBAR_ETH + 0x28C */
volatile uint32 rmon_r_crc_align; /* MBAR_ETH + 0x290 */
volatile uint32 rmon_r_undersize; /* MBAR_ETH + 0x294 */
volatile uint32 rmon_r_oversize; /* MBAR_ETH + 0x298 */
volatile uint32 rmon_r_frag; /* MBAR_ETH + 0x29C */
volatile uint32 rmon_r_jab; /* MBAR_ETH + 0x2A0 */
volatile uint32 rmon_r_resvd_0; /* MBAR_ETH + 0x2A4 */
volatile uint32 rmon_r_p64; /* MBAR_ETH + 0x2A8 */
volatile uint32 rmon_r_p65to127; /* MBAR_ETH + 0x2AC */
volatile uint32 rmon_r_p128to255; /* MBAR_ETH + 0x2B0 */
volatile uint32 rmon_r_p256to511; /* MBAR_ETH + 0x2B4 */
volatile uint32 rmon_r_p512to1023; /* MBAR_ETH + 0x2B8 */
volatile uint32 rmon_r_p1024to2047; /* MBAR_ETH + 0x2BC */
volatile uint32 rmon_r_p_gte2048; /* MBAR_ETH + 0x2C0 */
volatile uint32 rmon_r_octets; /* MBAR_ETH + 0x2C4 */
volatile uint32 ieee_r_drop; /* MBAR_ETH + 0x2C8 */
volatile uint32 ieee_r_frame_ok; /* MBAR_ETH + 0x2CC */
volatile uint32 ieee_r_crc; /* MBAR_ETH + 0x2D0 */
volatile uint32 ieee_r_align; /* MBAR_ETH + 0x2D4 */
volatile uint32 r_macerr; /* MBAR_ETH + 0x2D8 */
volatile uint32 r_fdxfc; /* MBAR_ETH + 0x2DC */
volatile uint32 ieee_r_octets_ok; /* MBAR_ETH + 0x2E0 */
volatile uint32 RES10[6]; /* MBAR_ETH + 0x2E4-2FC */
volatile uint32 RES11[64]; /* MBAR_ETH + 0x300-3FF */
} ethernet_regs;
/* Receive & Transmit Buffer Descriptor definitions */
typedef struct BufferDescriptor {
uint16 status;
uint16 dataLength;
uint32 dataPointer;
} FEC_RBD;
typedef struct {
uint16 status;
uint16 dataLength;
uint32 dataPointer;
} FEC_TBD;
/* private structure */
typedef enum {
SEVENWIRE, /* 7-wire */
MII10, /* MII 10Mbps */
MII100 /* MII 100Mbps */
} xceiver_type;
typedef struct {
ethernet_regs *eth;
xceiver_type xcv_type; /* transceiver type */
FEC_RBD *rbdBase; /* RBD ring */
FEC_TBD *tbdBase; /* TBD ring */
uint16 rbdIndex; /* next receive BD to read */
uint16 tbdIndex; /* next transmit BD to send */
uint16 usedTbdIndex; /* next transmit BD to clean */
uint16 cleanTbdNum; /* the number of available transmit BDs */
} mpc5xxx_fec_priv;
/* Ethernet parameter area */
#define FEC_TBD_BASE (FEC_PARAM_BASE + 0x00)
#define FEC_TBD_NEXT (FEC_PARAM_BASE + 0x04)
#define FEC_RBD_BASE (FEC_PARAM_BASE + 0x08)
#define FEC_RBD_NEXT (FEC_PARAM_BASE + 0x0c)
/* BD Numer definitions */
#define FEC_TBD_NUM 48 /* The user can adjust this value */
#define FEC_RBD_NUM 32 /* The user can adjust this value */
/* packet size limit */
#define FEC_MAX_PKT_SIZE 1536
/* RBD bits definitions */
#define FEC_RBD_EMPTY 0x8000 /* Buffer is empty */
#define FEC_RBD_WRAP 0x2000 /* Last BD in ring */
#define FEC_RBD_INT 0x1000 /* Interrupt */
#define FEC_RBD_LAST 0x0800 /* Buffer is last in frame(useless) */
#define FEC_RBD_MISS 0x0100 /* Miss bit for prom mode */
#define FEC_RBD_BC 0x0080 /* The received frame is broadcast frame */
#define FEC_RBD_MC 0x0040 /* The received frame is multicast frame */
#define FEC_RBD_LG 0x0020 /* Frame length violation */
#define FEC_RBD_NO 0x0010 /* Nonoctet align frame */
#define FEC_RBD_SH 0x0008 /* Short frame */
#define FEC_RBD_CR 0x0004 /* CRC error */
#define FEC_RBD_OV 0x0002 /* Receive FIFO overrun */
#define FEC_RBD_TR 0x0001 /* Frame is truncated */
#define FEC_RBD_ERR (FEC_RBD_LG | FEC_RBD_NO | FEC_RBD_CR | \
FEC_RBD_OV | FEC_RBD_TR)
/* TBD bits definitions */
#define FEC_TBD_READY 0x8000 /* Buffer is ready */
#define FEC_TBD_WRAP 0x2000 /* Last BD in ring */
#define FEC_TBD_INT 0x1000 /* Interrupt */
#define FEC_TBD_LAST 0x0800 /* Buffer is last in frame */
#define FEC_TBD_TC 0x0400 /* Transmit the CRC */
#define FEC_TBD_ABC 0x0200 /* Append bad CRC */
/* MII-related definitios */
#define FEC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
#define FEC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
#define FEC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
#define FEC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
#define FEC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
#define FEC_MII_DATA_TA 0x00020000 /* Turnaround */
#define FEC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
#define FEC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
#define FEC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
#endif /* __MPC5XXX_FEC_H */

View File

@@ -0,0 +1,364 @@
/*
* Copyright (C) 2001, Software Center, Motorola China.
*
* This file contains microcode for the FEC controller of the MGT5100 CPU.
*/
#include <config.h>
#if defined(CONFIG_MGT5100)
/* sas/sccg, gas target */
.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
.section smartdmaTaskTable,"aw",@progbits /* Task tables */
.globl taskTable
taskTable:
.globl scEthernetRecv_Entry
scEthernetRecv_Entry: /* Task 0 */
.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
.long scEthernetRecv_TDT - taskTable + 0x000000a4
.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
.long 0x00000000
.long 0x00000000
.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
.long 0xf0000000
.globl scEthernetXmit_Entry
scEthernetXmit_Entry: /* Task 1 */
.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
.long scEthernetXmit_TDT - taskTable + 0x000000d0
.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
.long 0x00000000
.long 0x00000000
.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
.long 0xf0000000
.globl scEthernetRecv_TDT
scEthernetRecv_TDT: /* Task 0 Descriptor Table */
.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x010c504c /* 0020: DRD2B1: var4 = EU1(); EU1(var1,var12) */
.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x018c504e /* 0030: DRD2B1: var6 = EU1(); EU1(var1,var14) */
.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x020c504f /* 0038: DRD2B1: var8 = EU1(); EU1(var1,var15) */
.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x080c504c /* 00A0: DRD2B1: idx0 = EU1(); EU1(var1,var12) */
.long 0x000001f8 /* 00A4(:0): NOP */
.globl scEthernetXmit_TDT
scEthernetXmit_TDT: /* Task 1 Descriptor Table */
.long 0x80014800 /* 0000: LCDEXT: idx0 = 0xf0004800; ; */
.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x024c504d /* 0020: DRD2B1: var9 = EU1(); EU1(var1,var13) */
.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x010c504e /* 0034: DRD2B1: var4 = EU1(); EU1(var1,var14) */
.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x014c504f /* 003C: DRD2B1: var5 = EU1(); EU1(var1,var15) */
.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x028c5050 /* 0044: DRD2B1: var10 = EU1(); EU1(var1,var16) */
.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x018c5051 /* 004C: DRD2B1: var6 = EU1(); EU1(var1,var17) */
.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x01cc50a1 /* 0058: DRD2B1: var7 = EU1(); EU1(var2,idx1) */
.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x60000100 /* 0088: DRD2A: EU0=0 EU1=1 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x0c4c5c4d /* 008C: DRD2B1: *idx1 = EU1(); EU1(*idx1,var13) */
.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x080c504d /* 00CC: DRD2B1: idx0 = EU1(); EU1(var1,var13) */
.long 0x000001f8 /* 00D0(:0): NOP */
.align 8
.globl scEthernetRecv_VarTab
scEthernetRecv_VarTab: /* Task 0 Variable Table */
.long 0x00000000 /* var[0] */
.long 0x00000000 /* var[1] */
.long 0x00000000 /* var[2] */
.long 0x00000000 /* var[3] */
.long 0x00000000 /* var[4] */
.long 0x00000000 /* var[5] */
.long 0x00000000 /* var[6] */
.long 0x00000000 /* var[7] */
.long 0x00000000 /* var[8] */
.long 0xf0004800 /* var[9] */
.long 0x00000008 /* var[10] */
.long 0x0000000c /* var[11] */
.long 0x80000000 /* var[12] */
.long 0x00000000 /* var[13] */
.long 0x10000000 /* var[14] */
.long 0x20000000 /* var[15] */
.long 0x000005e4 /* var[16] */
.long 0x0000000e /* var[17] */
.long 0x000005e0 /* var[18] */
.long 0x00000004 /* var[19] */
.long 0x00000000 /* var[20] */
.long 0x00000000 /* var[21] */
.long 0x00000000 /* var[22] */
.long 0x00000000 /* var[23] */
.long 0x00000000 /* inc[0] */
.long 0x60000000 /* inc[1] */
.long 0x20000001 /* inc[2] */
.long 0x80000000 /* inc[3] */
.long 0x40000000 /* inc[4] */
.long 0x00000000 /* inc[5] */
.long 0x00000000 /* inc[6] */
.long 0x00000000 /* inc[7] */
.align 8
.globl scEthernetXmit_VarTab
scEthernetXmit_VarTab: /* Task 1 Variable Table */
.long 0x00000000 /* var[0] */
.long 0x00000000 /* var[1] */
.long 0x00000000 /* var[2] */
.long 0x00000000 /* var[3] */
.long 0x00000000 /* var[4] */
.long 0x00000000 /* var[5] */
.long 0x00000000 /* var[6] */
.long 0x00000000 /* var[7] */
.long 0x00000000 /* var[8] */
.long 0x00000000 /* var[9] */
.long 0x00000000 /* var[10] */
.long 0xf0004800 /* var[11] */
.long 0x00000000 /* var[12] */
.long 0x80000000 /* var[13] */
.long 0x10000000 /* var[14] */
.long 0x08000000 /* var[15] */
.long 0x20000000 /* var[16] */
.long 0x0000ffff /* var[17] */
.long 0xffffffff /* var[18] */
.long 0x00000008 /* var[19] */
.long 0x00000000 /* var[20] */
.long 0x00000000 /* var[21] */
.long 0x00000000 /* var[22] */
.long 0x00000000 /* var[23] */
.long 0x00000000 /* inc[0] */
.long 0x60000000 /* inc[1] */
.long 0x40000000 /* inc[2] */
.long 0x4000ffff /* inc[3] */
.long 0xe0000001 /* inc[4] */
.long 0x80000000 /* inc[5] */
.long 0x00000000 /* inc[6] */
.long 0x00000000 /* inc[7] */
.align 8
.globl scEthernetRecv_FDT
scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x05800000 /* and(), EU# 1 */
.long 0x05400000 /* andn(), EU# 1 */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.align 8
.globl scEthernetXmit_FDT
scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x05800000 /* and(), EU# 1 */
.long 0x05400000 /* andn(), EU# 1 */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.align 8
.globl scEthernetRecv_CSave
scEthernetRecv_CSave: /* Task 0 context save space */
.space 256, 0x0
.align 8
.globl scEthernetXmit_CSave
scEthernetXmit_CSave: /* Task 1 context save space */
.space 256, 0x0
#endif /* CONFIG_MGT5100 */

View File

@@ -0,0 +1,363 @@
/*
* Copyright (C) 2001, Software Center, Motorola China.
*
* This file contains microcode for the FEC controller of the MPC5200 CPU.
*/
#include <config.h>
#if defined(CONFIG_MPC5200)
/* sas/sccg, gas target */
.section smartdmaInitData,"aw",@progbits /* Initialized data for task variables */
.section smartdmaTaskTable,"aw",@progbits /* Task tables */
.align 9
.globl taskTable
taskTable:
.globl scEthernetRecv_Entry
scEthernetRecv_Entry: /* Task 0 */
.long scEthernetRecv_TDT - taskTable /* Task 0 Descriptor Table */
.long scEthernetRecv_TDT - taskTable + 0x000000a4
.long scEthernetRecv_VarTab - taskTable /* Task 0 Variable Table */
.long scEthernetRecv_FDT - taskTable + 0x03 /* Task 0 Function Descriptor Table & Flags */
.long 0x00000000
.long 0x00000000
.long scEthernetRecv_CSave - taskTable /* Task 0 context save space */
.long 0xf0000000
.globl scEthernetXmit_Entry
scEthernetXmit_Entry: /* Task 1 */
.long scEthernetXmit_TDT - taskTable /* Task 1 Descriptor Table */
.long scEthernetXmit_TDT - taskTable + 0x000000d0
.long scEthernetXmit_VarTab - taskTable /* Task 1 Variable Table */
.long scEthernetXmit_FDT - taskTable + 0x03 /* Task 1 Function Descriptor Table & Flags */
.long 0x00000000
.long 0x00000000
.long scEthernetXmit_CSave - taskTable /* Task 1 context save space */
.long 0xf0000000
.globl scEthernetRecv_TDT
scEthernetRecv_TDT: /* Task 0 Descriptor Table */
.long 0xc4c50000 /* 0000: LCDEXT: idx0 = var9 + var10; idx0 once var0; idx0 += inc0 */
.long 0x84c5e000 /* 0004: LCD: idx1 = var9 + var11; ; idx1 += inc0 */
.long 0x10001f08 /* 0008: DRD1A: var7 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x10000380 /* 000C: DRD1A: var0 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f88 /* 0010: DRD1A: var3 = *idx1; FN=0 init=0 WS=0 RS=0 */
.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x010cf04c /* 0020: DRD2B1: var4 = EU3(); EU3(var1,var12) */
.long 0x82180349 /* 0024: LCD: idx0 = var4; idx0 != var13; idx0 += inc1 */
.long 0x81c68004 /* 0028: LCD: idx1 = var3 + var13 + 4; idx1 once var0; idx1 += inc0 */
.long 0x70000000 /* 002C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x018cf04e /* 0030: DRD2B1: var6 = EU3(); EU3(var1,var14) */
.long 0x70000000 /* 0034: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x020cf04f /* 0038: DRD2B1: var8 = EU3(); EU3(var1,var15) */
.long 0x00000b88 /* 003C: DRD1A: var2 = *idx1; FN=0 init=0 WS=0 RS=0 */
.long 0x8000d184 /* 0040: LCDEXT: idx1 = 0xf0003184; ; */
.long 0xc6990452 /* 0044: LCDEXT: idx2 = var13; idx2 < var17; idx2 += inc2 */
.long 0x81486010 /* 0048: LCD: idx3 = var2 + var16; ; idx3 += inc2 */
.long 0x006acf88 /* 004C: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
.long 0x8000d184 /* 0050: LCDEXT: idx1 = 0xf0003184; ; */
.long 0x86810492 /* 0054: LCD: idx2 = var13, idx3 = var2; idx2 < var18; idx2 += inc2, idx3 += inc2 */
.long 0x006acf88 /* 0058: DRD1A: *idx3 = *idx1; FN=0 init=3 WS=1 RS=1 */
.long 0x8000d184 /* 005C: LCDEXT: idx1 = 0xf0003184; ; */
.long 0x868184d2 /* 0060: LCD: idx2 = var13, idx3 = var3; idx2 < var19; idx2 += inc2, idx3 += inc2 */
.long 0x000acf88 /* 0064: DRD1A: *idx3 = *idx1; FN=0 init=0 WS=1 RS=1 */
.long 0xc318839b /* 0068: LCDEXT: idx1 = var6; idx1 == var14; idx1 += inc3 */
.long 0x80190000 /* 006C: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
.long 0x04008468 /* 0070: DRD1A: idx1 = var13; FN=0 INT init=0 WS=0 RS=0 */
.long 0xc4038358 /* 0074: LCDEXT: idx1 = var8, idx2 = var7; idx1 == var13; idx1 += inc3, idx2 += inc0 */
.long 0x81c50000 /* 0078: LCD: idx3 = var3 + var10; idx3 once var0; idx3 += inc0 */
.long 0x1000cb18 /* 007C: DRD1A: *idx2 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f18 /* 0080: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
.long 0xc4188364 /* 0084: LCDEXT: idx1 = var8; idx1 > var13; idx1 += inc4 */
.long 0x83990000 /* 0088: LCD: idx2 = var7; idx2 once var0; idx2 += inc0 */
.long 0x10000c00 /* 008C: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x0000c800 /* 0090: DRD1A: *idx2 = var0; FN=0 init=0 WS=0 RS=0 */
.long 0x81988000 /* 0094: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x10000788 /* 0098: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 009C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x080cf04c /* 00A0: DRD2B1: idx0 = EU3(); EU3(var1,var12) */
.long 0x000001f8 /* 00A4(:0): NOP */
.globl scEthernetXmit_TDT
scEthernetXmit_TDT: /* Task 1 Descriptor Table */
.long 0x80024800 /* 0000: LCDEXT: idx0 = 0xf0008800; ; */
.long 0x85c60004 /* 0004: LCD: idx1 = var11 + var12 + 4; idx1 once var0; idx1 += inc0 */
.long 0x10002308 /* 0008: DRD1A: var8 = idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x10000f88 /* 000C: DRD1A: var3 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000380 /* 0010: DRD1A: var0 = *idx0; FN=0 init=0 WS=0 RS=0 */
.long 0x81980000 /* 0014: LCD: idx0 = var3; idx0 once var0; idx0 += inc0 */
.long 0x10000780 /* 0018: DRD1A: var1 = *idx0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 001C: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x024cf04d /* 0020: DRD2B1: var9 = EU3(); EU3(var1,var13) */
.long 0x84980309 /* 0024: LCD: idx0 = var9; idx0 != var12; idx0 += inc1 */
.long 0xc0004003 /* 0028: LCDEXT: idx1 = 0x00000003; ; */
.long 0x81c60004 /* 002C: LCD: idx2 = var3 + var12 + 4; idx2 once var0; idx2 += inc0 */
.long 0x70000000 /* 0030: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x010cf04e /* 0034: DRD2B1: var4 = EU3(); EU3(var1,var14) */
.long 0x70000000 /* 0038: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x014cf04f /* 003C: DRD2B1: var5 = EU3(); EU3(var1,var15) */
.long 0x70000000 /* 0040: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x028cf050 /* 0044: DRD2B1: var10 = EU3(); EU3(var1,var16) */
.long 0x70000000 /* 0048: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT MORE init=0 WS=0 RS=0 */
.long 0x018cf051 /* 004C: DRD2B1: var6 = EU3(); EU3(var1,var17) */
.long 0x10000b90 /* 0050: DRD1A: var2 = *idx2; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 0054: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x01ccf0a1 /* 0058: DRD2B1: var7 = EU3(); EU3(var2,idx1) */
.long 0xc2988312 /* 005C: LCDEXT: idx1 = var5; idx1 > var12; idx1 += inc2 */
.long 0x83490000 /* 0060: LCD: idx2 = var6 + var18; idx2 once var0; idx2 += inc0 */
.long 0x00001b10 /* 0064: DRD1A: var6 = idx2; FN=0 init=0 WS=0 RS=0 */
.long 0x8000d1a4 /* 0068: LCDEXT: idx1 = 0xf00031a4; ; */
.long 0x8301031c /* 006C: LCD: idx2 = var6, idx3 = var2; idx2 > var12; idx2 += inc3, idx3 += inc4 */
.long 0x008ac798 /* 0070: DRD1A: *idx1 = *idx3; FN=0 init=4 WS=1 RS=1 */
.long 0x8000d1a4 /* 0074: LCDEXT: idx1 = 0xf00031a4; ; */
.long 0xc1430000 /* 0078: LCDEXT: idx2 = var2 + var6; idx2 once var0; idx2 += inc0 */
.long 0x82998312 /* 007C: LCD: idx3 = var5; idx3 > var12; idx3 += inc2 */
.long 0x088ac790 /* 0080: DRD1A: *idx1 = *idx2; FN=0 TFD init=4 WS=1 RS=1 */
.long 0x81988000 /* 0084: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x60000001 /* 0088: DRD2A: EU0=0 EU1=0 EU2=0 EU3=1 EXT init=0 WS=0 RS=0 */
.long 0x0c4cfc4d /* 008C: DRD2B1: *idx1 = EU3(); EU3(*idx1,var13) */
.long 0xc21883ad /* 0090: LCDEXT: idx1 = var4; idx1 == var14; idx1 += inc5 */
.long 0x80190000 /* 0094: LCD: idx2 = var0; idx2 once var0; idx2 += inc0 */
.long 0x04008460 /* 0098: DRD1A: idx1 = var12; FN=0 INT init=0 WS=0 RS=0 */
.long 0xc4052305 /* 009C: LCDEXT: idx1 = var8, idx2 = var10; idx2 == var12; idx1 += inc0, idx2 += inc5 */
.long 0x81c98000 /* 00A0: LCD: idx3 = var3 + var19; idx3 once var0; idx3 += inc0 */
.long 0x1000c718 /* 00A4: DRD1A: *idx1 = idx3; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00000f18 /* 00A8: DRD1A: var3 = idx3; FN=0 init=0 WS=0 RS=0 */
.long 0xc4188000 /* 00AC: LCDEXT: idx1 = var8; idx1 once var0; idx1 += inc0 */
.long 0x85190312 /* 00B0: LCD: idx2 = var10; idx2 > var12; idx2 += inc2 */
.long 0x10000c00 /* 00B4: DRD1A: var3 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x1000c400 /* 00B8: DRD1A: *idx1 = var0; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x00008860 /* 00BC: DRD1A: idx2 = var12; FN=0 init=0 WS=0 RS=0 */
.long 0x81988000 /* 00C0: LCD: idx1 = var3; idx1 once var0; idx1 += inc0 */
.long 0x10000788 /* 00C4: DRD1A: var1 = *idx1; FN=0 MORE init=0 WS=0 RS=0 */
.long 0x60000000 /* 00C8: DRD2A: EU0=0 EU1=0 EU2=0 EU3=0 EXT init=0 WS=0 RS=0 */
.long 0x080cf04d /* 00CC: DRD2B1: idx0 = EU3(); EU3(var1,var13) */
.long 0x000001f8 /* 00D0(:0): NOP */
.align 8
.globl scEthernetRecv_VarTab
scEthernetRecv_VarTab: /* Task 0 Variable Table */
.long 0x00000000 /* var[0] */
.long 0x00000000 /* var[1] */
.long 0x00000000 /* var[2] */
.long 0x00000000 /* var[3] */
.long 0x00000000 /* var[4] */
.long 0x00000000 /* var[5] */
.long 0x00000000 /* var[6] */
.long 0x00000000 /* var[7] */
.long 0x00000000 /* var[8] */
.long 0xf0008800 /* var[9] */
.long 0x00000008 /* var[10] */
.long 0x0000000c /* var[11] */
.long 0x80000000 /* var[12] */
.long 0x00000000 /* var[13] */
.long 0x10000000 /* var[14] */
.long 0x20000000 /* var[15] */
.long 0x000005e4 /* var[16] */
.long 0x0000000e /* var[17] */
.long 0x000005e0 /* var[18] */
.long 0x00000004 /* var[19] */
.long 0x00000000 /* var[20] */
.long 0x00000000 /* var[21] */
.long 0x00000000 /* var[22] */
.long 0x00000000 /* var[23] */
.long 0x00000000 /* inc[0] */
.long 0x60000000 /* inc[1] */
.long 0x20000001 /* inc[2] */
.long 0x80000000 /* inc[3] */
.long 0x40000000 /* inc[4] */
.long 0x00000000 /* inc[5] */
.long 0x00000000 /* inc[6] */
.long 0x00000000 /* inc[7] */
.align 8
.globl scEthernetXmit_VarTab
scEthernetXmit_VarTab: /* Task 1 Variable Table */
.long 0x00000000 /* var[0] */
.long 0x00000000 /* var[1] */
.long 0x00000000 /* var[2] */
.long 0x00000000 /* var[3] */
.long 0x00000000 /* var[4] */
.long 0x00000000 /* var[5] */
.long 0x00000000 /* var[6] */
.long 0x00000000 /* var[7] */
.long 0x00000000 /* var[8] */
.long 0x00000000 /* var[9] */
.long 0x00000000 /* var[10] */
.long 0xf0008800 /* var[11] */
.long 0x00000000 /* var[12] */
.long 0x80000000 /* var[13] */
.long 0x10000000 /* var[14] */
.long 0x08000000 /* var[15] */
.long 0x20000000 /* var[16] */
.long 0x0000ffff /* var[17] */
.long 0xffffffff /* var[18] */
.long 0x00000008 /* var[19] */
.long 0x00000000 /* var[20] */
.long 0x00000000 /* var[21] */
.long 0x00000000 /* var[22] */
.long 0x00000000 /* var[23] */
.long 0x00000000 /* inc[0] */
.long 0x60000000 /* inc[1] */
.long 0x40000000 /* inc[2] */
.long 0x4000ffff /* inc[3] */
.long 0xe0000001 /* inc[4] */
.long 0x80000000 /* inc[5] */
.long 0x00000000 /* inc[6] */
.long 0x00000000 /* inc[7] */
.align 8
.globl scEthernetRecv_FDT
scEthernetRecv_FDT: /* Task 0 Function Descriptor Table */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x21800000 /* and(), EU# 3 */
.long 0x21400000 /* andn(), EU# 3 */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.align 8
.globl scEthernetXmit_FDT
scEthernetXmit_FDT: /* Task 1 Function Descriptor Table */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x21800000 /* and(), EU# 3 */
.long 0x21400000 /* andn(), EU# 3 */
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.long 0x00000000
.globl scEthernetRecv_CSave
scEthernetRecv_CSave: /* Task 0 context save space */
.space 128, 0x0
.globl scEthernetXmit_CSave
scEthernetXmit_CSave: /* Task 1 context save space */
.space 128, 0x0
#endif /* CONFIG_MPC5200 */

180
cpu/mpc5xxx/interrupts.c Normal file
View File

@@ -0,0 +1,180 @@
/*
* (C) Copyright -2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* (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
*/
/*
* interrupts.c - just enough support for the decrementer/timer
*/
#include <common.h>
#include <asm/processor.h>
#include <command.h>
/****************************************************************************/
unsigned decrementer_count; /* count value for 1e6/HZ microseconds */
/****************************************************************************/
static __inline__ unsigned long
get_msr(void)
{
unsigned long msr;
asm volatile("mfmsr %0" : "=r" (msr) :);
return msr;
}
static __inline__ void
set_msr(unsigned long msr)
{
asm volatile("mtmsr %0" : : "r" (msr));
}
static __inline__ unsigned long
get_dec(void)
{
unsigned long val;
asm volatile("mfdec %0" : "=r" (val) :);
return val;
}
static __inline__ void
set_dec(unsigned long val)
{
asm volatile("mtdec %0" : : "r" (val));
}
void
enable_interrupts(void)
{
set_msr (get_msr() | MSR_EE);
}
/* returns flag if MSR_EE was set before */
int
disable_interrupts(void)
{
ulong msr = get_msr();
set_msr (msr & ~MSR_EE);
return ((msr & MSR_EE) != 0);
}
/****************************************************************************/
int interrupt_init(void)
{
decrementer_count = get_tbclk() / CFG_HZ;
#ifdef DEBUG
puts("interrupt_init: setting actual decremter\n");
#endif
set_dec (get_tbclk() / CFG_HZ);
#ifdef DEBUG
printf("interrupt_init: enabling interrupts (msr = %08lx)\n",
get_msr());
#endif
set_msr (get_msr() | MSR_EE);
#ifdef DEBUG
printf("interrupt_init: done. (msr = %08lx)\n", get_msr());
#endif
return (0);
}
/****************************************************************************/
/*
* Handle external interrupts
*/
void
external_interrupt(struct pt_regs *regs)
{
puts("external_interrupt (oops!)\n");
}
volatile ulong timestamp = 0;
/*
* timer_interrupt - gets called when the decrementer overflows,
* with interrupts disabled.
* Trivial implementation - no need to be really accurate.
*/
void
timer_interrupt(struct pt_regs *regs)
{
set_dec(decrementer_count);
timestamp++;
}
/****************************************************************************/
void
reset_timer(void)
{
timestamp = 0;
}
ulong
get_timer(ulong base)
{
return (timestamp - base);
}
void
set_timer(ulong t)
{
timestamp = t;
}
/****************************************************************************/
/*
* Install and free a interrupt handler.
*/
void
irq_install_handler(int vec, interrupt_handler_t *handler, void *arg)
{
}
void
irq_free_handler(int vec)
{
}
/****************************************************************************/
void
do_irqinfo(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
puts("IRQ related functions are unimplemented currently.\n");
}

128
cpu/mpc5xxx/io.S Normal file
View File

@@ -0,0 +1,128 @@
/*
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
* Copyright (C) 2001 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
* Andreas Heppel <aheppel@sysgo.de>
* Copyright (C) 2003 Wolfgang Denk <wd@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <config.h>
#include <ppc_asm.tmpl>
/* ------------------------------------------------------------------------------- */
/* Function: in8 */
/* Description: Input 8 bits */
/* ------------------------------------------------------------------------------- */
.globl in8
in8:
lbz r3,0(r3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: in16 */
/* Description: Input 16 bits */
/* ------------------------------------------------------------------------------- */
.globl in16
in16:
lhz r3,0(r3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: in16r */
/* Description: Input 16 bits and byte reverse */
/* ------------------------------------------------------------------------------- */
.globl in16r
in16r:
lhbrx r3,0,r3
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: in32 */
/* Description: Input 32 bits */
/* ------------------------------------------------------------------------------- */
.globl in32
in32:
lwz 3,0(3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: in32r */
/* Description: Input 32 bits and byte reverse */
/* ------------------------------------------------------------------------------- */
.globl in32r
in32r:
lwbrx r3,0,r3
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: out8 */
/* Description: Output 8 bits */
/* ------------------------------------------------------------------------------- */
.globl out8
out8:
stb r4,0(r3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: out16 */
/* Description: Output 16 bits */
/* ------------------------------------------------------------------------------- */
.globl out16
out16:
sth r4,0(r3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: out16r */
/* Description: Byte reverse and output 16 bits */
/* ------------------------------------------------------------------------------- */
.globl out16r
out16r:
sthbrx r4,0,r3
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: out32 */
/* Description: Output 32 bits */
/* ------------------------------------------------------------------------------- */
.globl out32
out32:
stw r4,0(r3)
sync
blr
/* ------------------------------------------------------------------------------- */
/* Function: out32r */
/* Description: Byte reverse and output 32 bits */
/* ------------------------------------------------------------------------------- */
.globl out32r
out32r:
stwbrx r4,0,r3
sync
blr

76
cpu/mpc5xxx/loadtask.c Normal file
View File

@@ -0,0 +1,76 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* This file is based on code
* (C) Copyright Motorola, Inc., 2000
*/
#include <common.h>
#include <mpc5xxx.h>
/* BestComm/SmartComm microcode */
extern int taskTable;
void loadtask(int basetask, int tasks)
{
int *sram = (int *)MPC5XXX_SRAM;
int *task_org = &taskTable;
unsigned int start, offset, end;
int i;
#ifdef DEBUG
printf("basetask = %d, tasks = %d\n", basetask, tasks);
printf("task_org = 0x%08x\n", (unsigned int)task_org);
#endif
/* setup TaskBAR register */
*(vu_long *)MPC5XXX_SDMA = MPC5XXX_SRAM;
/* relocate task table entries */
offset = (unsigned int)sram;
for (i = basetask; i < basetask + tasks; i++) {
sram[i * 8 + 0] = task_org[i * 8 + 0] + offset;
sram[i * 8 + 1] = task_org[i * 8 + 1] + offset;
sram[i * 8 + 2] = task_org[i * 8 + 2] + offset;
sram[i * 8 + 3] = task_org[i * 8 + 3] + offset;
sram[i * 8 + 4] = task_org[i * 8 + 4];
sram[i * 8 + 5] = task_org[i * 8 + 5];
sram[i * 8 + 6] = task_org[i * 8 + 6] + offset;
sram[i * 8 + 7] = task_org[i * 8 + 7];
}
/* relocate task descriptors */
start = (sram[basetask * 8] - (unsigned int)sram);
end = (sram[(basetask + tasks - 1) * 8 + 1] - (unsigned int)sram);
#ifdef DEBUG
printf ("TDT start = 0x%08x, end = 0x%08x\n", start, end);
#endif
start /= 4;
end /= 4;
for (i = start; i <= end; i++) {
sram[i] = task_org[i];
}
/* relocate variables */
start = (sram[basetask * 8 + 2] - (unsigned int)sram);
end = (sram[(basetask + tasks - 1) * 8 + 2] + 256 - (unsigned int)sram);
start /= 4;
end /= 4;
for (i = start; i < end; i++) {
sram[i] = task_org[i];
}
/* relocate function decriptors */
start = ((sram[basetask * 8 + 3] & 0xfffffffc) - (unsigned int)sram);
end = ((sram[(basetask + tasks - 1) * 8 + 3] & 0xfffffffc) + 256 - (unsigned int)sram);
start /= 4;
end /= 4;
for (i = start; i < end; i++) {
sram[i] = task_org[i];
}
asm volatile ("sync");
}

93
cpu/mpc5xxx/sdma.h Normal file
View File

@@ -0,0 +1,93 @@
/*
* (C) Copyright 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* This file is based on code
* (C) Copyright Motorola, Inc., 2000
*
* odin smartdma header file
*/
#ifndef __MPC5XXX_SDMA_H
#define __MPC5XXX_SDMA_H
#include <common.h>
#include <mpc5xxx.h>
/* Task number assignment */
#define FEC_RECV_TASK_NO 0
#define FEC_XMIT_TASK_NO 1
/*---------------------------------------------------------------------*/
/* Stuff for Ethernet Tx/Rx tasks */
/*---------------------------------------------------------------------*/
/* Layout of Ethernet controller Parameter SRAM area:
----------------------------------------------------------------
0x00: TBD_BASE, base address of TX BD ring
0x04: TBD_NEXT, address of next TX BD to be processed
0x08: RBD_BASE, base address of RX BD ring
0x0C: RBD_NEXT, address of next RX BD to be processed
---------------------------------------------------------------
ALL PARAMETERS ARE ALL LONGWORDS (FOUR BYTES EACH).
*/
/* base address of SRAM area to store parameters used by Ethernet tasks */
#define FEC_PARAM_BASE (MPC5XXX_SRAM + 0x0800)
/* base address of SRAM area for buffer descriptors */
#define FEC_BD_BASE (MPC5XXX_SRAM + 0x0820)
/*---------------------------------------------------------------------*/
/* common shortcuts used by driver C code */
/*---------------------------------------------------------------------*/
/* Disable SmartDMA task */
#define SDMA_TASK_DISABLE(tasknum) \
{ \
volatile ushort *tcr = (ushort *)(MPC5XXX_SDMA + 0x0000001c + 2 * tasknum); \
*tcr = (*tcr) & (~0x8000); \
}
/* Enable SmartDMA task */
#define SDMA_TASK_ENABLE(tasknum) \
{ \
volatile ushort *tcr = (ushort *) (MPC5XXX_SDMA + 0x0000001c + 2 * tasknum); \
*tcr = (*tcr) | 0x8000; \
}
/* Enable interrupt */
#define SDMA_INT_ENABLE(tasknum) \
{ \
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
sdma->IntMask &= ~(1 << tasknum); \
}
/* Disable interrupt */
#define SDMA_INT_DISABLE(tasknum) \
{ \
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
sdma->IntMask |= (1 << tasknum); \
}
/* Clear interrupt pending bits */
#define SDMA_CLEAR_IEVENT(tasknum) \
{ \
struct mpc5xxx_sdma *sdma = (struct mpc5xxx_sdma *)MPC5XXX_SDMA; \
sdma->IntPend = (1 << tasknum); \
}
/* get interupt pending bit of a task */
#define SDMA_GET_PENDINGBIT(tasknum) \
((*(vu_long *)(MPC5XXX_SDMA + 0x14)) & (1<<(tasknum)))
/* get interupt mask bit of a task */
#define SDMA_GET_MASKBIT(tasknum) \
((*(vu_long *)(MPC5XXX_SDMA + 0x18)) & (1<<(tasknum)))
#endif /* __MPC5XXX_SDMA_H */

165
cpu/mpc5xxx/serial.c Normal file
View File

@@ -0,0 +1,165 @@
/*
* (C) Copyright 2000 - 2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*
* Hacked for MPC8260 by Murray.Jensen@cmst.csiro.au, 19-Oct-00, with
* changes based on the file arch/ppc/mbxboot/m8260_tty.c from the
* Linux/PPC sources (m8260_tty.c had no copyright info in it).
*/
/*
* Minimal serial functions needed to use one of the PSC ports
* as serial console interface.
*/
#include <common.h>
#include <mpc5xxx.h>
#if defined(CONFIG_PSC_CONSOLE)
#if CONFIG_PSC_CONSOLE == 1
#define PSC_BASE MPC5XXX_PSC1
#elif CONFIG_PSC_CONSOLE == 2
#define PSC_BASE MPC5XXX_PSC2
#elif CONFIG_PSC_CONSOLE == 3
#define PSC_BASE MPC5XXX_PSC3
#elif defined(CONFIG_MGT5100)
#error CONFIG_PSC_CONSOLE must be in 1, 2 or 3
#elif CONFIG_PSC_CONSOLE == 4
#define PSC_BASE MPC5XXX_PSC4
#elif CONFIG_PSC_CONSOLE == 5
#define PSC_BASE MPC5XXX_PSC5
#elif CONFIG_PSC_CONSOLE == 6
#define PSC_BASE MPC5XXX_PSC6
#else
#error CONFIG_PSC_CONSOLE must be in 1 ... 6
#endif
int serial_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
unsigned long baseclk;
int div;
/* reset PSC */
psc->command = PSC_SEL_MODE_REG_1;
/* select clock sources */
#if defined(CONFIG_MGT5100)
psc->psc_clock_select = 0xdd00;
baseclk = CFG_MPC5XXX_CLKIN / 32;
#elif defined(CONFIG_MPC5200)
psc->psc_clock_select = 0;
baseclk = gd->ipb_clk / 32;
#endif
/* switch to UART mode */
psc->sicr = 0;
/* configure parity, bit length and so on */
#if defined(CONFIG_MGT5100)
psc->mode = PSC_MODE_ERR | PSC_MODE_8_BITS | PSC_MODE_PARNONE;
#elif defined(CONFIG_MPC5200)
psc->mode = PSC_MODE_8_BITS | PSC_MODE_PARNONE;
#endif
psc->mode = PSC_MODE_ONE_STOP;
/* set up UART divisor */
div = baseclk / gd->baudrate;
psc->ctur = div >> 8;
psc->ctlr = div & 0xff;
/* disable all interrupts */
psc->psc_imr = 0;
/* reset and enable Rx/Tx */
psc->command = PSC_RST_RX;
psc->command = PSC_RST_TX;
psc->command = PSC_RX_ENABLE | PSC_TX_ENABLE;
return (0);
}
void
serial_putc(const char c)
{
volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
if (c == '\n')
serial_putc('\r');
/* Wait for last character to go. */
while (!(psc->psc_status & PSC_SR_TXEMP))
;
psc->psc_buffer_8 = c;
}
void
serial_puts (const char *s)
{
while (*s) {
serial_putc (*s++);
}
}
int
serial_getc(void)
{
volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
/* Wait for a character to arrive. */
while (!(psc->psc_status & PSC_SR_RXRDY))
;
return psc->psc_buffer_8;
}
int
serial_tstc(void)
{
volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
return (psc->psc_status & PSC_SR_RXRDY);
}
void
serial_setbrg(void)
{
DECLARE_GLOBAL_DATA_PTR;
volatile struct mpc5xxx_psc *psc = (struct mpc5xxx_psc *)PSC_BASE;
unsigned long baseclk, div;
#if defined(CONFIG_MGT5100)
baseclk = CFG_MPC5XXX_CLKIN / 32;
#elif defined(CONFIG_MPC5200)
baseclk = gd->ipb_clk / 32;
#endif
/* set up UART divisor */
div = baseclk / gd->baudrate;
psc->ctur = div >> 8;
psc->ctlr = div & 0xff;
}
#endif /* CONFIG_PSC_CONSOLE */

93
cpu/mpc5xxx/speed.c Normal file
View File

@@ -0,0 +1,93 @@
/*
* (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 <mpc5xxx.h>
#include <asm/processor.h>
/* ------------------------------------------------------------------------- */
/* Bus-to-Core Multipliers */
static int bus2core[] = {
0, 0, 0, 10, 20, 20, 25, 45,
30, 55, 40, 50, 0, 60, 35, 0,
30, 25, 65, 10, 70, 20, 75, 45,
0, 55, 40, 50, 80, 60, 35, 0
};
/* ------------------------------------------------------------------------- */
/*
*
*/
int get_clocks (void)
{
DECLARE_GLOBAL_DATA_PTR;
ulong val, vco;
#if !defined(CFG_MPC5XXX_CLKIN)
#error clock measuring not implemented yet - define CFG_MPC5XXX_CLKIN
#endif
val = *(vu_long *)MPC5XXX_CDM_PORCFG;
if (val & (1 << 6)) {
vco = CFG_MPC5XXX_CLKIN * 12;
} else {
vco = CFG_MPC5XXX_CLKIN * 16;
}
if (val & (1 << 5)) {
gd->bus_clk = vco / 8;
} else {
gd->bus_clk = vco / 4;
}
gd->cpu_clk = gd->bus_clk * bus2core[val & 0x1f] / 10;
val = *(vu_long *)MPC5XXX_CDM_CFG;
if (val & (1 << 8)) {
gd->ipb_clk = gd->bus_clk / 2;
} else {
gd->ipb_clk = gd->bus_clk;
}
switch (val & 3) {
case 0: gd->pci_clk = gd->ipb_clk; break;
case 1: gd->pci_clk = gd->ipb_clk / 2; break;
default: gd->pci_clk = gd->bus_clk / 4; break;
}
return (0);
}
int prt_mpc5xxx_clks (void)
{
DECLARE_GLOBAL_DATA_PTR;
printf(" Bus %ld MHz, IPB %ld MHz, PCI %ld MHz\n",
gd->bus_clk / 1000000, gd->ipb_clk / 1000000,
gd->pci_clk / 1000000);
return (0);
}
/* ------------------------------------------------------------------------- */

817
cpu/mpc5xxx/start.S Normal file
View File

@@ -0,0 +1,817 @@
/*
* Copyright (C) 1998 Dan Malek <dmalek@jlc.net>
* Copyright (C) 1999 Magnus Damm <kieraypc01.p.y.kie.era.ericsson.se>
* Copyright (C) 2000 - 2003 Wolfgang Denk <wd@denx.de>
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* U-Boot - Startup Code for MPC5xxx CPUs
*/
#include <config.h>
#include <mpc5xxx.h>
#include <version.h>
#define CONFIG_MPC5XXX 1 /* needed for Linux kernel header files */
#define _LINUX_CONFIG_H 1 /* avoid reading Linux autoconf.h file */
#include <ppc_asm.tmpl>
#include <ppc_defs.h>
#include <asm/cache.h>
#include <asm/mmu.h>
#ifndef CONFIG_IDENT_STRING
#define CONFIG_IDENT_STRING ""
#endif
/* We don't want the MMU yet.
*/
#undef MSR_KERNEL
/* Floating Point enable, Machine Check and Recoverable Interr. */
#ifdef DEBUG
#define MSR_KERNEL (MSR_FP|MSR_RI)
#else
#define MSR_KERNEL (MSR_FP|MSR_ME|MSR_RI)
#endif
/*
* Set up GOT: Global Offset Table
*
* Use r14 to access the GOT
*/
START_GOT
GOT_ENTRY(_GOT2_TABLE_)
GOT_ENTRY(_FIXUP_TABLE_)
GOT_ENTRY(_start)
GOT_ENTRY(_start_of_vectors)
GOT_ENTRY(_end_of_vectors)
GOT_ENTRY(transfer_to_handler)
GOT_ENTRY(__init_end)
GOT_ENTRY(_end)
GOT_ENTRY(__bss_start)
END_GOT
/*
* Version string
*/
.data
.globl version_string
version_string:
.ascii U_BOOT_VERSION
.ascii " (", __DATE__, " - ", __TIME__, ")"
.ascii CONFIG_IDENT_STRING, "\0"
/*
* Exception vectors
*/
.text
. = EXC_OFF_SYS_RESET
.globl _start
_start:
li r21, BOOTFLAG_COLD /* Normal Power-On */
nop
b boot_cold
. = EXC_OFF_SYS_RESET + 0x10
.globl _start_warm
_start_warm:
li r21, BOOTFLAG_WARM /* Software reboot */
b boot_warm
boot_cold:
boot_warm:
mfmsr r5 /* save msr contents */
#if defined(CFG_DEFAULT_MBAR)
lis r3, CFG_MBAR@h
ori r3, r3, CFG_MBAR@l
#if defined(CONFIG_MPC5200)
rlwinm r3, r3, 16, 16, 31
#endif
#if defined(CONFIG_MGT5100)
rlwinm r3, r3, 17, 15, 31
#endif
lis r4, CFG_DEFAULT_MBAR@h
stw r3, 0(r4)
#endif /* CFG_DEFAULT_MBAR */
/* Initialise the MPC5xxx processor core */
/*--------------------------------------------------------------*/
bl init_5xxx_core
/* initialize some things that are hard to access from C */
/*--------------------------------------------------------------*/
/* set up stack in on-chip SRAM */
lis r3, CFG_INIT_RAM_ADDR@h
ori r3, r3, CFG_INIT_RAM_ADDR@l
ori r1, r3, CFG_INIT_SP_OFFSET
li r0, 0 /* Make room for stack frame header and */
stwu r0, -4(r1) /* clear final stack frame so that */
stwu r0, -4(r1) /* stack backtraces terminate cleanly */
/* let the C-code set up the rest */
/* */
/* Be careful to keep code relocatable ! */
/*--------------------------------------------------------------*/
GET_GOT /* initialize GOT access */
/* r3: IMMR */
bl cpu_init_f /* run low-level CPU init code (in Flash)*/
mr r3, r21
/* r3: BOOTFLAG */
bl board_init_f /* run 1st part of board init code (in Flash)*/
/*
* Vector Table
*/
.globl _start_of_vectors
_start_of_vectors:
/* Machine check */
STD_EXCEPTION(0x200, MachineCheck, MachineCheckException)
/* Data Storage exception. */
STD_EXCEPTION(0x300, DataStorage, UnknownException)
/* Instruction Storage exception. */
STD_EXCEPTION(0x400, InstStorage, UnknownException)
/* External Interrupt exception. */
STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt)
/* Alignment exception. */
. = 0x600
Alignment:
EXCEPTION_PROLOG
mfspr r4,DAR
stw r4,_DAR(r21)
mfspr r5,DSISR
stw r5,_DSISR(r21)
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
lwz r6,GOT(transfer_to_handler)
mtlr r6
blrl
.L_Alignment:
.long AlignmentException - _start + EXC_OFF_SYS_RESET
.long int_return - _start + EXC_OFF_SYS_RESET
/* Program check exception */
. = 0x700
ProgramCheck:
EXCEPTION_PROLOG
addi r3,r1,STACK_FRAME_OVERHEAD
li r20,MSR_KERNEL
rlwimi r20,r23,0,16,16 /* copy EE bit from saved MSR */
rlwimi r20,r23,0,25,25 /* copy IP bit from saved MSR */
lwz r6,GOT(transfer_to_handler)
mtlr r6
blrl
.L_ProgramCheck:
.long ProgramCheckException - _start + EXC_OFF_SYS_RESET
.long int_return - _start + EXC_OFF_SYS_RESET
STD_EXCEPTION(0x800, FPUnavailable, UnknownException)
/* I guess we could implement decrementer, and may have
* to someday for timekeeping.
*/
STD_EXCEPTION(0x900, Decrementer, timer_interrupt)
STD_EXCEPTION(0xa00, Trap_0a, UnknownException)
STD_EXCEPTION(0xb00, Trap_0b, UnknownException)
. = 0xc00
/*
* r0 - SYSCALL number
* r3-... arguments
*/
SystemCall:
addis r11,r0,0 /* get functions table addr */
ori r11,r11,0 /* Note: this code is patched in trap_init */
addis r12,r0,0 /* get number of functions */
ori r12,r12,0
cmplw 0, r0, r12
bge 1f
rlwinm r0,r0,2,0,31 /* fn_addr = fn_tbl[r0] */
add r11,r11,r0
lwz r11,0(r11)
li r20,0xd00-4 /* Get stack pointer */
lwz r12,0(r20)
subi r12,r12,12 /* Adjust stack pointer */
li r0,0xc00+_end_back-SystemCall
cmplw 0, r0, r12 /* Check stack overflow */
bgt 1f
stw r12,0(r20)
mflr r0
stw r0,0(r12)
mfspr r0,SRR0
stw r0,4(r12)
mfspr r0,SRR1
stw r0,8(r12)
li r12,0xc00+_back-SystemCall
mtlr r12
mtspr SRR0,r11
1: SYNC
rfi
_back:
mfmsr r11 /* Disable interrupts */
li r12,0
ori r12,r12,MSR_EE
andc r11,r11,r12
SYNC /* Some chip revs need this... */
mtmsr r11
SYNC
li r12,0xd00-4 /* restore regs */
lwz r12,0(r12)
lwz r11,0(r12)
mtlr r11
lwz r11,4(r12)
mtspr SRR0,r11
lwz r11,8(r12)
mtspr SRR1,r11
addi r12,r12,12 /* Adjust stack pointer */
li r20,0xd00-4
stw r12,0(r20)
SYNC
rfi
_end_back:
STD_EXCEPTION(0xd00, SingleStep, UnknownException)
STD_EXCEPTION(0xe00, Trap_0e, UnknownException)
STD_EXCEPTION(0xf00, Trap_0f, UnknownException)
STD_EXCEPTION(0x1000, InstructionTLBMiss, UnknownException)
STD_EXCEPTION(0x1100, DataLoadTLBMiss, UnknownException)
STD_EXCEPTION(0x1200, DataStoreTLBMiss, UnknownException)
#ifdef DEBUG
. = 0x1300
/*
* This exception occurs when the program counter matches the
* Instruction Address Breakpoint Register (IABR).
*
* I want the cpu to halt if this occurs so I can hunt around
* with the debugger and look at things.
*
* When DEBUG is defined, both machine check enable (in the MSR)
* and checkstop reset enable (in the reset mode register) are
* turned off and so a checkstop condition will result in the cpu
* halting.
*
* I force the cpu into a checkstop condition by putting an illegal
* instruction here (at least this is the theory).
*
* well - that didnt work, so just do an infinite loop!
*/
1: b 1b
#else
STD_EXCEPTION(0x1300, InstructionBreakpoint, DebugException)
#endif
STD_EXCEPTION(0x1400, SMI, UnknownException)
STD_EXCEPTION(0x1500, Trap_15, UnknownException)
STD_EXCEPTION(0x1600, Trap_16, UnknownException)
STD_EXCEPTION(0x1700, Trap_17, UnknownException)
STD_EXCEPTION(0x1800, Trap_18, UnknownException)
STD_EXCEPTION(0x1900, Trap_19, UnknownException)
STD_EXCEPTION(0x1a00, Trap_1a, UnknownException)
STD_EXCEPTION(0x1b00, Trap_1b, UnknownException)
STD_EXCEPTION(0x1c00, Trap_1c, UnknownException)
STD_EXCEPTION(0x1d00, Trap_1d, UnknownException)
STD_EXCEPTION(0x1e00, Trap_1e, UnknownException)
STD_EXCEPTION(0x1f00, Trap_1f, UnknownException)
STD_EXCEPTION(0x2000, Trap_20, UnknownException)
STD_EXCEPTION(0x2100, Trap_21, UnknownException)
STD_EXCEPTION(0x2200, Trap_22, UnknownException)
STD_EXCEPTION(0x2300, Trap_23, UnknownException)
STD_EXCEPTION(0x2400, Trap_24, UnknownException)
STD_EXCEPTION(0x2500, Trap_25, UnknownException)
STD_EXCEPTION(0x2600, Trap_26, UnknownException)
STD_EXCEPTION(0x2700, Trap_27, UnknownException)
STD_EXCEPTION(0x2800, Trap_28, UnknownException)
STD_EXCEPTION(0x2900, Trap_29, UnknownException)
STD_EXCEPTION(0x2a00, Trap_2a, UnknownException)
STD_EXCEPTION(0x2b00, Trap_2b, UnknownException)
STD_EXCEPTION(0x2c00, Trap_2c, UnknownException)
STD_EXCEPTION(0x2d00, Trap_2d, UnknownException)
STD_EXCEPTION(0x2e00, Trap_2e, UnknownException)
STD_EXCEPTION(0x2f00, Trap_2f, UnknownException)
.globl _end_of_vectors
_end_of_vectors:
. = 0x3000
/*
* This code finishes saving the registers to the exception frame
* and jumps to the appropriate handler for the exception.
* Register r21 is pointer into trap frame, r1 has new stack pointer.
*/
.globl transfer_to_handler
transfer_to_handler:
stw r22,_NIP(r21)
lis r22,MSR_POW@h
andc r23,r23,r22
stw r23,_MSR(r21)
SAVE_GPR(7, r21)
SAVE_4GPRS(8, r21)
SAVE_8GPRS(12, r21)
SAVE_8GPRS(24, r21)
mflr r23
andi. r24,r23,0x3f00 /* get vector offset */
stw r24,TRAP(r21)
li r22,0
stw r22,RESULT(r21)
lwz r24,0(r23) /* virtual address of handler */
lwz r23,4(r23) /* where to go when done */
mtspr SRR0,r24
mtspr SRR1,r20
mtlr r23
SYNC
rfi /* jump to handler, enable MMU */
int_return:
mfmsr r28 /* Disable interrupts */
li r4,0
ori r4,r4,MSR_EE
andc r28,r28,r4
SYNC /* Some chip revs need this... */
mtmsr r28
SYNC
lwz r2,_CTR(r1)
lwz r0,_LINK(r1)
mtctr r2
mtlr r0
lwz r2,_XER(r1)
lwz r0,_CCR(r1)
mtspr XER,r2
mtcrf 0xFF,r0
REST_10GPRS(3, r1)
REST_10GPRS(13, r1)
REST_8GPRS(23, r1)
REST_GPR(31, r1)
lwz r2,_NIP(r1) /* Restore environment */
lwz r0,_MSR(r1)
mtspr SRR0,r2
mtspr SRR1,r0
lwz r0,GPR0(r1)
lwz r2,GPR2(r1)
lwz r1,GPR1(r1)
SYNC
rfi
/*
* This code initialises the MPC5xxx processor core
* (conforms to PowerPC 603e spec)
* Note: expects original MSR contents to be in r5.
*/
.globl init_5xx_core
init_5xxx_core:
/* Initialize machine status; enable machine check interrupt */
/*--------------------------------------------------------------*/
li r3, MSR_KERNEL /* Set ME and RI flags */
rlwimi r3, r5, 0, 25, 25 /* preserve IP bit set by HRCW */
#ifdef DEBUG
rlwimi r3, r5, 0, 21, 22 /* debugger might set SE & BE bits */
#endif
SYNC /* Some chip revs need this... */
mtmsr r3
SYNC
mtspr SRR1, r3 /* Make SRR1 match MSR */
/* Initialize the Hardware Implementation-dependent Registers */
/* HID0 also contains cache control */
/*--------------------------------------------------------------*/
lis r3, CFG_HID0_INIT@h
ori r3, r3, CFG_HID0_INIT@l
SYNC
mtspr HID0, r3
lis r3, CFG_HID0_FINAL@h
ori r3, r3, CFG_HID0_FINAL@l
SYNC
mtspr HID0, r3
/* clear all BAT's */
/*--------------------------------------------------------------*/
li r0, 0
mtspr DBAT0U, r0
mtspr DBAT0L, r0
mtspr DBAT1U, r0
mtspr DBAT1L, r0
mtspr DBAT2U, r0
mtspr DBAT2L, r0
mtspr DBAT3U, r0
mtspr DBAT3L, r0
mtspr IBAT0U, r0
mtspr IBAT0L, r0
mtspr IBAT1U, r0
mtspr IBAT1L, r0
mtspr IBAT2U, r0
mtspr IBAT2L, r0
mtspr IBAT3U, r0
mtspr IBAT3L, r0
SYNC
/* invalidate all tlb's */
/* */
/* From the 603e User Manual: "The 603e provides the ability to */
/* invalidate a TLB entry. The TLB Invalidate Entry (tlbie) */
/* instruction invalidates the TLB entry indexed by the EA, and */
/* operates on both the instruction and data TLBs simultaneously*/
/* invalidating four TLB entries (both sets in each TLB). The */
/* index corresponds to bits 15-19 of the EA. To invalidate all */
/* entries within both TLBs, 32 tlbie instructions should be */
/* issued, incrementing this field by one each time." */
/* */
/* "Note that the tlbia instruction is not implemented on the */
/* 603e." */
/* */
/* bits 15-19 correspond to addresses 0x00000000 to 0x0001F000 */
/* incrementing by 0x1000 each time. The code below is sort of */
/* based on code in "flush_tlbs" from arch/ppc/kernel/head.S */
/* */
/*--------------------------------------------------------------*/
li r3, 32
mtctr r3
li r3, 0
1: tlbie r3
addi r3, r3, 0x1000
bdnz 1b
SYNC
/* Done! */
/*--------------------------------------------------------------*/
blr
/* Cache functions.
*
* Note: requires that all cache bits in
* HID0 are in the low half word.
*/
.globl icache_enable
icache_enable:
mfspr r3, HID0
ori r3, r3, HID0_ICE
lis r4, 0
ori r4, r4, HID0_ILOCK
andc r3, r3, r4
ori r4, r3, HID0_ICFI
isync
mtspr HID0, r4 /* sets enable and invalidate, clears lock */
isync
mtspr HID0, r3 /* clears invalidate */
blr
.globl icache_disable
icache_disable:
mfspr r3, HID0
lis r4, 0
ori r4, r4, HID0_ICE|HID0_ILOCK
andc r3, r3, r4
ori r4, r3, HID0_ICFI
isync
mtspr HID0, r4 /* sets invalidate, clears enable and lock */
isync
mtspr HID0, r3 /* clears invalidate */
blr
.globl icache_status
icache_status:
mfspr r3, HID0
rlwinm r3, r3, HID0_ICE_BITPOS + 1, 31, 31
blr
.globl dcache_enable
dcache_enable:
mfspr r3, HID0
ori r3, r3, HID0_DCE
lis r4, 0
ori r4, r4, HID0_DLOCK
andc r3, r3, r4
ori r4, r3, HID0_DCI
sync
mtspr HID0, r4 /* sets enable and invalidate, clears lock */
sync
mtspr HID0, r3 /* clears invalidate */
blr
.globl dcache_disable
dcache_disable:
mfspr r3, HID0
lis r4, 0
ori r4, r4, HID0_DCE|HID0_DLOCK
andc r3, r3, r4
ori r4, r3, HID0_DCI
sync
mtspr HID0, r4 /* sets invalidate, clears enable and lock */
sync
mtspr HID0, r3 /* clears invalidate */
blr
.globl dcache_status
dcache_status:
mfspr r3, HID0
rlwinm r3, r3, HID0_DCE_BITPOS + 1, 31, 31
blr
.globl get_pvr
get_pvr:
mfspr r3, PVR
blr
/*------------------------------------------------------------------------------*/
/*
* void relocate_code (addr_sp, gd, addr_moni)
*
* This "function" does not return, instead it continues in RAM
* after relocating the monitor code.
*
* r3 = dest
* r4 = src
* r5 = length in bytes
* r6 = cachelinesize
*/
.globl relocate_code
relocate_code:
mr r1, r3 /* Set new stack pointer */
mr r9, r4 /* Save copy of Global Data pointer */
mr r10, r5 /* Save copy of Destination Address */
mr r3, r5 /* Destination Address */
lis r4, CFG_MONITOR_BASE@h /* Source Address */
ori r4, r4, CFG_MONITOR_BASE@l
lwz r5, GOT(__init_end)
sub r5, r5, r4
li r6, CFG_CACHELINE_SIZE /* Cache Line Size */
/*
* Fix GOT pointer:
*
* New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address
*
* Offset:
*/
sub r15, r10, r4
/* First our own GOT */
add r14, r14, r15
/* then the one used by the C code */
add r30, r30, r15
/*
* Now relocate code
*/
cmplw cr1,r3,r4
addi r0,r5,3
srwi. r0,r0,2
beq cr1,4f /* In place copy is not necessary */
beq 7f /* Protect against 0 count */
mtctr r0
bge cr1,2f
la r8,-4(r4)
la r7,-4(r3)
1: lwzu r0,4(r8)
stwu r0,4(r7)
bdnz 1b
b 4f
2: slwi r0,r0,2
add r8,r4,r0
add r7,r3,r0
3: lwzu r0,-4(r8)
stwu r0,-4(r7)
bdnz 3b
/*
* Now flush the cache: note that we must start from a cache aligned
* address. Otherwise we might miss one cache line.
*/
4: cmpwi r6,0
add r5,r3,r5
beq 7f /* Always flush prefetch queue in any case */
subi r0,r6,1
andc r3,r3,r0
mfspr r7,HID0 /* don't do dcbst if dcache is disabled */
rlwinm r7,r7,HID0_DCE_BITPOS+1,31,31
cmpwi r7,0
beq 9f
mr r4,r3
5: dcbst 0,r4
add r4,r4,r6
cmplw r4,r5
blt 5b
sync /* Wait for all dcbst to complete on bus */
9: mfspr r7,HID0 /* don't do icbi if icache is disabled */
rlwinm r7,r7,HID0_ICE_BITPOS+1,31,31
cmpwi r7,0
beq 7f
mr r4,r3
6: icbi 0,r4
add r4,r4,r6
cmplw r4,r5
blt 6b
7: sync /* Wait for all icbi to complete on bus */
isync
/*
* We are done. Do not return, instead branch to second part of board
* initialization, now running from RAM.
*/
addi r0, r10, in_ram - _start + EXC_OFF_SYS_RESET
mtlr r0
blr
in_ram:
/*
* Relocation Function, r14 point to got2+0x8000
*
* Adjust got2 pointers, no need to check for 0, this code
* already puts a few entries in the table.
*/
li r0,__got2_entries@sectoff@l
la r3,GOT(_GOT2_TABLE_)
lwz r11,GOT(_GOT2_TABLE_)
mtctr r0
sub r11,r3,r11
addi r3,r3,-4
1: lwzu r0,4(r3)
add r0,r0,r11
stw r0,0(r3)
bdnz 1b
/*
* Now adjust the fixups and the pointers to the fixups
* in case we need to move ourselves again.
*/
2: li r0,__fixup_entries@sectoff@l
lwz r3,GOT(_FIXUP_TABLE_)
cmpwi r0,0
mtctr r0
addi r3,r3,-4
beq 4f
3: lwzu r4,4(r3)
lwzux r0,r4,r11
add r0,r0,r11
stw r10,0(r3)
stw r0,0(r4)
bdnz 3b
4:
clear_bss:
/*
* Now clear BSS segment
*/
lwz r3,GOT(__bss_start)
lwz r4,GOT(_end)
cmplw 0, r3, r4
beq 6f
li r0, 0
5:
stw r0, 0(r3)
addi r3, r3, 4
cmplw 0, r3, r4
bne 5b
6:
mr r3, r9 /* Global Data pointer */
mr r4, r10 /* Destination Address */
bl board_init_r
/*
* Copy exception vector code to low memory
*
* r3: dest_addr
* r7: source address, r8: end address, r9: target address
*/
.globl trap_init
trap_init:
lwz r7, GOT(_start)
lwz r8, GOT(_end_of_vectors)
li r9, 0x100 /* reset vector always at 0x100 */
cmplw 0, r7, r8
bgelr /* return if r7>=r8 - just in case */
mflr r4 /* save link register */
1:
lwz r0, 0(r7)
stw r0, 0(r9)
addi r7, r7, 4
addi r9, r9, 4
cmplw 0, r7, r8
bne 1b
/*
* relocate `hdlr' and `int_return' entries
*/
li r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET
li r8, Alignment - _start + EXC_OFF_SYS_RESET
2:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 2b
li r7, .L_Alignment - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET
bl trap_reloc
li r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET
li r8, SystemCall - _start + EXC_OFF_SYS_RESET
3:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 3b
li r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET
li r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET
4:
bl trap_reloc
addi r7, r7, 0x100 /* next exception vector */
cmplw 0, r7, r8
blt 4b
mfmsr r3 /* now that the vectors have */
lis r7, MSR_IP@h /* relocated into low memory */
ori r7, r7, MSR_IP@l /* MSR[IP] can be turned off */
andc r3, r3, r7 /* (if it was on) */
SYNC /* Some chip revs need this... */
mtmsr r3
SYNC
mtlr r4 /* restore link register */
blr
/*
* Function: relocate entries for one exception vector
*/
trap_reloc:
lwz r0, 0(r7) /* hdlr ... */
add r0, r0, r3 /* ... += dest_addr */
stw r0, 0(r7)
lwz r0, 4(r7) /* int_return ... */
add r0, r0, r3 /* ... += dest_addr */
stw r0, 4(r7)
blr

246
cpu/mpc5xxx/traps.c Normal file
View File

@@ -0,0 +1,246 @@
/*
* linux/arch/ppc/kernel/traps.c
*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Modified by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras (paulus@cs.anu.edu.au)
*
* (C) Copyright 2000-2003
* Wolfgang Denk, DENX Software Engineering, wd@denx.de.
*
* See file CREDITS for list of people who contributed to this
* project.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
/*
* This file handles the architecture-dependent parts of hardware exceptions
*/
#include <common.h>
#include <command.h>
#include <asm/processor.h>
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
int (*debugger_exception_handler)(struct pt_regs *) = 0;
#endif
/* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table(unsigned long);
/* THIS NEEDS CHANGING to use the board info structure.
*/
#define END_OF_MEM 0x02000000
/*
* Trap & Exception support
*/
void
print_backtrace(unsigned long *sp)
{
int cnt = 0;
unsigned long i;
printf("Call backtrace: ");
while (sp) {
if ((uint)sp > END_OF_MEM)
break;
i = sp[1];
if (cnt++ % 7 == 0)
printf("\n");
printf("%08lX ", i);
if (cnt > 32) break;
sp = (unsigned long *)*sp;
}
printf("\n");
}
void show_regs(struct pt_regs * regs)
{
int i;
printf("NIP: %08lX XER: %08lX LR: %08lX REGS: %p TRAP: %04lx DAR: %08lX\n",
regs->nip, regs->xer, regs->link, regs, regs->trap, regs->dar);
printf("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n",
regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0,
regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0,
regs->msr&MSR_IR ? 1 : 0,
regs->msr&MSR_DR ? 1 : 0);
printf("\n");
for (i = 0; i < 32; i++) {
if ((i % 8) == 0)
{
printf("GPR%02d: ", i);
}
printf("%08lX ", regs->gpr[i]);
if ((i % 8) == 7)
{
printf("\n");
}
}
}
void
_exception(int signr, struct pt_regs *regs)
{
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Exception in kernel pc %lx signal %d",regs->nip,signr);
}
void
MachineCheckException(struct pt_regs *regs)
{
unsigned long fixup;
/* Probing PCI using config cycles cause this exception
* when a device is not present. Catch it and return to
* the PCI exception handler.
*/
if ((fixup = search_exception_table(regs->nip)) != 0) {
regs->nip = fixup;
return;
}
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
printf("Machine check in kernel mode.\n");
printf("Caused by (from msr): ");
printf("regs %p ",regs);
switch( regs->msr & 0x0000F000)
{
case (1<<12) :
printf("Machine check signal - probably due to mm fault\n"
"with mmu off\n");
break;
case (1<<13) :
printf("Transfer error ack signal\n");
break;
case (1<<14) :
printf("Data parity signal\n");
break;
case (1<<15) :
printf("Address parity signal\n");
break;
default:
printf("Unknown values in msr\n");
}
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("machine check");
}
void
AlignmentException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Alignment Exception");
}
void
ProgramCheckException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Program Check Exception");
}
void
SoftEmuException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
show_regs(regs);
print_backtrace((unsigned long *)regs->gpr[1]);
panic("Software Emulation Exception");
}
void
UnknownException(struct pt_regs *regs)
{
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
if (debugger_exception_handler && (*debugger_exception_handler)(regs))
return;
#endif
printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
regs->nip, regs->msr, regs->trap);
_exception(0, regs);
}
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
extern void do_bedbug_breakpoint(struct pt_regs *);
#endif
void
DebugException(struct pt_regs *regs)
{
printf("Debugger trap at @ %lx\n", regs->nip );
show_regs(regs);
#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
do_bedbug_breakpoint( regs );
#endif
}
/* Probe an address by reading. If not present, return -1, otherwise
* return 0.
*/
int
addr_probe(uint *addr)
{
#if 0
int retval;
__asm__ __volatile__( \
"1: lwz %0,0(%1)\n" \
" eieio\n" \
" li %0,0\n" \
"2:\n" \
".section .fixup,\"ax\"\n" \
"3: li %0,-1\n" \
" b 2b\n" \
".section __ex_table,\"a\"\n" \
" .align 2\n" \
" .long 1b,3b\n" \
".text" \
: "=r" (retval) : "r"(addr));
return (retval);
#endif
return 0;
}

View File

@@ -684,15 +684,15 @@ static int video_mode_generate (void)
ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);
ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
ADDENTRY (3, 3, 0, 3, 1, 0, HBP +(VIDEO_COLS * 2) + 72 , 1, 0);
/*
* Odd field
*/
/*
* Odd field
*/
ADDENTRY (0, 3, 0, 3, 1, 0, 2, 0, 0);
ADDENTRY (0, 0, 0, 3, 1, 0, HPW, 0, 0);
ADDENTRY (3, 0, 0, 3, 1, 0, HBP + (VIDEO_COLS * 2) + 72, 0, 0);
@@ -710,7 +710,7 @@ static int video_mode_generate (void)
ADDENTRY (0, 3, 0, 3, 1, 0, VID_R , 1, 0);
ADDENTRY (0, 3, 0, 3, 1, 0, HPW-1, 0, 0);
ADDENTRY (3, 3, 0, 3, 1, 0, HBP, 0, 0);
ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
ADDENTRY (3, 3, 0, 3, 0, 0, VIDEO_COLS*2, 0, 0);
ADDENTRY (3, 3, 0, 3, 1, 0, 72, 1, 1);
ADDENTRY (0, 3, 0, 3, 1, 0, 51, 1, 0);