diff options
author | wdenk <wdenk> | 2003-07-16 21:53:01 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2003-07-16 21:53:01 +0000 |
commit | 945af8d723a29e9b6289d84250745ed0dc16fc81 (patch) | |
tree | 6798d0b717c05b01742df0c410038c702b8a1979 /cpu/mpc5xxx | |
parent | cb4dbb7bbc271f988e14ec353a5e86d7f10e1da0 (diff) |
* Add support for IceCube board (with MGT5100 and MPC5200 CPUs)U-Boot-0_4_4
* Add support for MGT5100 and MPC5200 processors
Diffstat (limited to 'cpu/mpc5xxx')
-rw-r--r-- | cpu/mpc5xxx/Makefile | 45 | ||||
-rw-r--r-- | cpu/mpc5xxx/config.mk | 27 | ||||
-rw-r--r-- | cpu/mpc5xxx/cpu.c | 103 | ||||
-rw-r--r-- | cpu/mpc5xxx/cpu_init.c | 185 | ||||
-rw-r--r-- | cpu/mpc5xxx/fec.c | 944 | ||||
-rw-r--r-- | cpu/mpc5xxx/fec.h | 286 | ||||
-rw-r--r-- | cpu/mpc5xxx/firmware_sc_task.impl.S | 364 | ||||
-rw-r--r-- | cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S | 363 | ||||
-rw-r--r-- | cpu/mpc5xxx/interrupts.c | 180 | ||||
-rw-r--r-- | cpu/mpc5xxx/io.S | 128 | ||||
-rw-r--r-- | cpu/mpc5xxx/loadtask.c | 76 | ||||
-rw-r--r-- | cpu/mpc5xxx/sdma.h | 93 | ||||
-rw-r--r-- | cpu/mpc5xxx/serial.c | 165 | ||||
-rw-r--r-- | cpu/mpc5xxx/speed.c | 93 | ||||
-rw-r--r-- | cpu/mpc5xxx/start.S | 817 | ||||
-rw-r--r-- | cpu/mpc5xxx/traps.c | 246 |
16 files changed, 4115 insertions, 0 deletions
diff --git a/cpu/mpc5xxx/Makefile b/cpu/mpc5xxx/Makefile new file mode 100644 index 00000000000..2688ee62b57 --- /dev/null +++ b/cpu/mpc5xxx/Makefile @@ -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 + +######################################################################### diff --git a/cpu/mpc5xxx/config.mk b/cpu/mpc5xxx/config.mk new file mode 100644 index 00000000000..f84b098cae2 --- /dev/null +++ b/cpu/mpc5xxx/config.mk @@ -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 diff --git a/cpu/mpc5xxx/cpu.c b/cpu/mpc5xxx/cpu.c new file mode 100644 index 00000000000..7d95d2f9c3f --- /dev/null +++ b/cpu/mpc5xxx/cpu.c @@ -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); +} + +/* ------------------------------------------------------------------------- */ diff --git a/cpu/mpc5xxx/cpu_init.c b/cpu/mpc5xxx/cpu_init.c new file mode 100644 index 00000000000..7322027e8b2 --- /dev/null +++ b/cpu/mpc5xxx/cpu_init.c @@ -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); +} diff --git a/cpu/mpc5xxx/fec.c b/cpu/mpc5xxx/fec.c new file mode 100644 index 00000000000..b8e2560cf7c --- /dev/null +++ b/cpu/mpc5xxx/fec.c @@ -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 */ diff --git a/cpu/mpc5xxx/fec.h b/cpu/mpc5xxx/fec.h new file mode 100644 index 00000000000..81756a5f6ac --- /dev/null +++ b/cpu/mpc5xxx/fec.h @@ -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 */ diff --git a/cpu/mpc5xxx/firmware_sc_task.impl.S b/cpu/mpc5xxx/firmware_sc_task.impl.S new file mode 100644 index 00000000000..b668ee5cf8d --- /dev/null +++ b/cpu/mpc5xxx/firmware_sc_task.impl.S @@ -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 */ diff --git a/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S b/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S new file mode 100644 index 00000000000..1d83fe26d99 --- /dev/null +++ b/cpu/mpc5xxx/firmware_sc_task_bestcomm.impl.S @@ -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 */ diff --git a/cpu/mpc5xxx/interrupts.c b/cpu/mpc5xxx/interrupts.c new file mode 100644 index 00000000000..5aa43880bb7 --- /dev/null +++ b/cpu/mpc5xxx/interrupts.c @@ -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"); +} diff --git a/cpu/mpc5xxx/io.S b/cpu/mpc5xxx/io.S new file mode 100644 index 00000000000..2178a267634 --- /dev/null +++ b/cpu/mpc5xxx/io.S @@ -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 diff --git a/cpu/mpc5xxx/loadtask.c b/cpu/mpc5xxx/loadtask.c new file mode 100644 index 00000000000..47e7b596a6f --- /dev/null +++ b/cpu/mpc5xxx/loadtask.c @@ -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"); +} diff --git a/cpu/mpc5xxx/sdma.h b/cpu/mpc5xxx/sdma.h new file mode 100644 index 00000000000..8b740e4e6e2 --- /dev/null +++ b/cpu/mpc5xxx/sdma.h @@ -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 */ diff --git a/cpu/mpc5xxx/serial.c b/cpu/mpc5xxx/serial.c new file mode 100644 index 00000000000..54ecf5be17b --- /dev/null +++ b/cpu/mpc5xxx/serial.c @@ -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 */ diff --git a/cpu/mpc5xxx/speed.c b/cpu/mpc5xxx/speed.c new file mode 100644 index 00000000000..cb27779a229 --- /dev/null +++ b/cpu/mpc5xxx/speed.c @@ -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); +} + +/* ------------------------------------------------------------------------- */ diff --git a/cpu/mpc5xxx/start.S b/cpu/mpc5xxx/start.S new file mode 100644 index 00000000000..41454423ca0 --- /dev/null +++ b/cpu/mpc5xxx/start.S @@ -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 diff --git a/cpu/mpc5xxx/traps.c b/cpu/mpc5xxx/traps.c new file mode 100644 index 00000000000..5d433945230 --- /dev/null +++ b/cpu/mpc5xxx/traps.c @@ -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; +} |