summaryrefslogtreecommitdiffstats
path: root/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'cpu')
-rw-r--r--cpu/74xx_7xx/traps.c234
-rw-r--r--cpu/mpc824x/drivers/epic/epic1.c513
-rw-r--r--cpu/mpc824x/traps.c205
-rw-r--r--cpu/mpc8260/ether_fcc.c347
-rw-r--r--cpu/mpc8260/traps.c246
-rw-r--r--cpu/mpc8xx/traps.c245
-rw-r--r--cpu/mpc8xx/upatch.c102
-rw-r--r--cpu/ppc4xx/miiphy.c182
-rw-r--r--cpu/ppc4xx/traps.c291
9 files changed, 2365 insertions, 0 deletions
diff --git a/cpu/74xx_7xx/traps.c b/cpu/74xx_7xx/traps.c
new file mode 100644
index 0000000000..26db097402
--- /dev/null
+++ b/cpu/74xx_7xx/traps.c
@@ -0,0 +1,234 @@
+/*
+ * 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
+ * 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);
+}
+
+/* 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;
+}
diff --git a/cpu/mpc824x/drivers/epic/epic1.c b/cpu/mpc824x/drivers/epic/epic1.c
new file mode 100644
index 0000000000..362e12970d
--- /dev/null
+++ b/cpu/mpc824x/drivers/epic/epic1.c
@@ -0,0 +1,513 @@
+/**************************************************
+ *
+ * copyright @ motorola, 1999
+ *
+ *************************************************/
+#include <mpc824x.h>
+#include <common.h>
+#include "epic.h"
+
+
+#define PRINT(format, args...) printf(format , ## args)
+
+typedef void (*VOIDFUNCPTR) (void); /* ptr to function returning void */
+struct SrcVecTable SrcVecTable[MAXVEC] = /* Addr/Vector cross-reference tbl */
+ {
+ { EPIC_EX_INT0_VEC_REG, "External Direct/Serial Source 0"},
+ { EPIC_EX_INT1_VEC_REG, "External Direct/Serial Source 1"},
+ { EPIC_EX_INT2_VEC_REG, "External Direct/Serial Source 2"},
+ { EPIC_EX_INT3_VEC_REG, "External Direct/Serial Source 3"},
+ { EPIC_EX_INT4_VEC_REG, "External Direct/Serial Source 4"},
+
+ { EPIC_SR_INT5_VEC_REG, "External Serial Source 5"},
+ { EPIC_SR_INT6_VEC_REG, "External Serial Source 6"},
+ { EPIC_SR_INT7_VEC_REG, "External Serial Source 7"},
+ { EPIC_SR_INT8_VEC_REG, "External Serial Source 8"},
+ { EPIC_SR_INT9_VEC_REG, "External Serial Source 9"},
+ { EPIC_SR_INT10_VEC_REG, "External Serial Source 10"},
+ { EPIC_SR_INT11_VEC_REG, "External Serial Source 11"},
+ { EPIC_SR_INT12_VEC_REG, "External Serial Source 12"},
+ { EPIC_SR_INT13_VEC_REG, "External Serial Source 13"},
+ { EPIC_SR_INT14_VEC_REG, "External Serial Source 14"},
+ { EPIC_SR_INT15_VEC_REG, "External Serial Source 15"},
+
+ { EPIC_I2C_INT_VEC_REG, "Internal I2C Source"},
+ { EPIC_DMA0_INT_VEC_REG, "Internal DMA0 Source"},
+ { EPIC_DMA1_INT_VEC_REG, "Internal DMA1 Source"},
+ { EPIC_MSG_INT_VEC_REG, "Internal Message Source"},
+ };
+
+VOIDFUNCPTR intVecTbl[MAXVEC]; /* Interrupt vector table */
+
+
+/****************************************************************************
+* epicInit - Initialize the EPIC registers
+*
+* This routine resets the Global Configuration Register, thus it:
+* - Disables all interrupts
+* - Sets epic registers to reset values
+* - Sets the value of the Processor Current Task Priority to the
+* highest priority (0xF).
+* epicInit then sets the EPIC operation mode to Mixed Mode (vs. Pass
+* Through or 8259 compatible mode).
+*
+* If IRQType (input) is Direct IRQs:
+* - IRQType is written to the SIE bit of the EPIC Interrupt
+* Configuration register (ICR).
+* - clkRatio is ignored.
+* If IRQType is Serial IRQs:
+* - both IRQType and clkRatio will be written to the ICR register
+*/
+
+void epicInit
+ (
+ unsigned int IRQType, /* Direct or Serial */
+ unsigned int clkRatio /* Clk Ratio for Serial IRQs */
+ )
+ {
+ ULONG tmp;
+
+ tmp = sysEUMBBARRead(EPIC_GLOBAL_REG);
+ tmp |= 0xa0000000; /* Set the Global Conf. register */
+ sysEUMBBARWrite(EPIC_GLOBAL_REG, tmp);
+ sysEUMBBARWrite(EPIC_GLOBAL_REG, 0x20000000);
+ tmp = sysEUMBBARRead(EPIC_INT_CONF_REG); /* Read interrupt conf. reg */
+
+ if (IRQType == EPIC_DIRECT_IRQ) /* direct mode */
+ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp & 0xf7ffffff);
+ else /* Serial mode */
+ {
+ tmp = (clkRatio << 28) | 0x08000000; /* Set clock ratio */
+ sysEUMBBARWrite(EPIC_INT_CONF_REG, tmp);
+ }
+
+ while (epicIntAck() != 0xff); /* Clear all pending interrupts */
+}
+
+/****************************************************************************
+ * epicIntEnable - Enable an interrupt source
+ *
+ * This routine clears the mask bit of an external, an internal or
+ * a Timer register to enable the interrupt.
+ *
+ * RETURNS: None
+ */
+void epicIntEnable
+ (
+ int intVec /* Interrupt Vector Number */
+ )
+ {
+ ULONG tmp;
+ ULONG srAddr;
+
+ srAddr = SrcVecTable[intVec].srcAddr; /* Retrieve src Vec/Prio register */
+ tmp = sysEUMBBARRead(srAddr);
+ tmp &= 0x7fffffff; /* Clear the mask bit */
+ sysEUMBBARWrite(srAddr, tmp);
+ return;
+ }
+
+/****************************************************************************
+ * epicIntDisable - Disable an interrupt source
+ *
+ * This routine sets the mask bit of an external, an internal or
+ * a Timer register to disable the interrupt.
+ *
+ * RETURNS: OK or ERROR
+ *
+ */
+
+void epicIntDisable
+ (
+ int intVec /* Interrupt vector number */
+ )
+ {
+
+ ULONG tmp, srAddr;
+
+ srAddr = SrcVecTable[intVec].srcAddr;
+ tmp = sysEUMBBARRead(srAddr);
+ tmp |= 0x80000000; /* Set the mask bit */
+ sysEUMBBARWrite(srAddr, tmp);
+ return;
+ }
+
+/****************************************************************************
+ * epicIntSourceConfig - Set properties of an interrupt source
+ *
+ * This function sets interrupt properites (Polarity, Sense, Interrupt
+ * Prority, and Interrupt Vector) of an Interrupt Source. The properties
+ * can be set when the current source is not in-request or in-service,
+ * which is determined by the Activity bit. This routine return ERROR
+ * if the the Activity bit is 1 (in-request or in-service).
+ *
+ * This function assumes that the Source Vector/Priority register (input)
+ * is a valid address.
+ *
+ * RETURNS: OK or ERROR
+ */
+
+int epicIntSourceConfig
+ (
+ int Vect, /* interrupt source vector number */
+ int Polarity, /* interrupt source polarity */
+ int Sense, /* interrupt source Sense */
+ int Prio /* interrupt source priority */
+ )
+
+ {
+ ULONG tmp, newVal;
+ ULONG actBit, srAddr;
+
+ srAddr = SrcVecTable[Vect].srcAddr;
+ tmp = sysEUMBBARRead(srAddr);
+ actBit = (tmp & 40000000) >> 30; /* retrieve activity bit - bit 30 */
+ if (actBit == 1)
+ return ERROR;
+
+ tmp &= 0xff30ff00; /* Erase previously set P,S,Prio,Vector bits */
+ newVal = (Polarity << 23) | (Sense << 22) | (Prio << 16) | Vect;
+ sysEUMBBARWrite(srAddr, tmp | newVal );
+ return (OK);
+ }
+
+/****************************************************************************
+ * epicIntAck - acknowledge an interrupt
+ *
+ * This function reads the Interrupt acknowldge register and return
+ * the vector number of the highest pending interrupt.
+ *
+ * RETURNS: Interrupt Vector number.
+ */
+
+unsigned int epicIntAck(void)
+{
+ return(sysEUMBBARRead( EPIC_PROC_INT_ACK_REG ));
+}
+
+/****************************************************************************
+ * epicEOI - signal an end of interrupt
+ *
+ * This function writes 0x0 to the EOI register to signal end of interrupt.
+ * It is usually called after an interrupt routine is served.
+ *
+ * RETURNS: None
+ */
+
+void epicEOI(void)
+ {
+ sysEUMBBARWrite(EPIC_PROC_EOI_REG, 0x0);
+ }
+
+/****************************************************************************
+ * epicCurTaskPrioSet - sets the priority of the Processor Current Task
+ *
+ * This function should be called after epicInit() to lower the priority
+ * of the processor current task.
+ *
+ * RETURNS: OK or ERROR
+ */
+
+int epicCurTaskPrioSet
+ (
+ int prioNum /* New priority value */
+ )
+ {
+
+ if ( (prioNum < 0) || (prioNum > 0xF))
+ return ERROR;
+ sysEUMBBARWrite(EPIC_PROC_CTASK_PRI_REG, prioNum);
+ return OK;
+ }
+
+
+/************************************************************************
+ * function: epicIntTaskGet
+ *
+ * description: Get value of processor current interrupt task priority register
+ *
+ * note:
+ ***********************************************************************/
+unsigned char epicIntTaskGet()
+{
+ /* get the interrupt task priority register */
+ ULONG reg;
+ unsigned char rec;
+
+ reg = sysEUMBBARRead( EPIC_PROC_CTASK_PRI_REG );
+ rec = ( reg & 0x0F );
+ return rec;
+}
+
+
+/**************************************************************
+ * function: epicISR
+ *
+ * description: EPIC service routine called by the core exception
+ * at 0x500
+ *
+ * note:
+ **************************************************************/
+unsigned int epicISR(void)
+{
+ return 0;
+}
+
+
+/************************************************************
+ * function: epicModeGet
+ *
+ * description: query EPIC mode, return 0 if pass through mode
+ * return 1 if mixed mode
+ *
+ * note:
+ *************************************************************/
+unsigned int epicModeGet(void)
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_GLOBAL_REG );
+ return (( val & 0x20000000 ) >> 29);
+}
+
+
+/*********************************************
+ * function: epicConfigGet
+ *
+ * description: Get the EPIC interrupt Configuration
+ * return 0 if not error, otherwise return 1
+ *
+ * note:
+ ********************************************/
+void epicConfigGet( unsigned int *clkRatio, unsigned int *serEnable)
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_INT_CONF_REG );
+ *clkRatio = ( val & 0x70000000 ) >> 28;
+ *serEnable = ( val & 0x8000000 ) >> 27;
+}
+
+
+/*******************************************************************
+ * sysEUMBBARRead - Read a 32-bit EUMBBAR register
+ *
+ * This routine reads the content of a register in the Embedded
+ * Utilities Memory Block, and swaps to big endian before returning
+ * the value.
+ *
+ * RETURNS: The content of the specified EUMBBAR register.
+ */
+
+ULONG sysEUMBBARRead
+ (
+ ULONG regNum
+ )
+ {
+ ULONG temp;
+
+ temp = *(ULONG *) (CFG_EUMB_ADDR + regNum);
+ return ( LONGSWAP(temp));
+ }
+
+/*******************************************************************
+ * sysEUMBBARWrite - Write a 32-bit EUMBBAR register
+ *
+ * This routine swaps the value to little endian then writes it to
+ * a register in the Embedded Utilities Memory Block address space.
+ *
+ * RETURNS: N/A
+ */
+
+void sysEUMBBARWrite
+ (
+ ULONG regNum, /* EUMBBAR register address */
+ ULONG regVal /* Value to be written */
+ )
+ {
+
+ *(ULONG *) (CFG_EUMB_ADDR + regNum) = LONGSWAP(regVal);
+ return ;
+ }
+
+
+/********************************************************
+ * function: epicVendorId
+ *
+ * description: return the EPIC Vendor Identification
+ * register:
+ *
+ * siliccon version, device id, and vendor id
+ *
+ * note:
+ ********************************************************/
+void epicVendorId
+ (
+ unsigned int *step,
+ unsigned int *devId,
+ unsigned int *venId
+ )
+ {
+ ULONG val;
+ val = sysEUMBBARRead( EPIC_VENDOR_ID_REG );
+ *step = ( val & 0x00FF0000 ) >> 16;
+ *devId = ( val & 0x0000FF00 ) >> 8;
+ *venId = ( val & 0x000000FF );
+ }
+
+/**************************************************
+ * function: epicFeatures
+ *
+ * description: return the number of IRQ supported,
+ * number of CPU, and the version of the
+ * OpenEPIC
+ *
+ * note:
+ *************************************************/
+void epicFeatures
+ (
+ unsigned int *noIRQs,
+ unsigned int *noCPUs,
+ unsigned int *verId
+ )
+ {
+ ULONG val;
+
+ val = sysEUMBBARRead( EPIC_FEATURES_REG );
+ *noIRQs = ( val & 0x07FF0000 ) >> 16;
+ *noCPUs = ( val & 0x00001F00 ) >> 8;
+ *verId = ( val & 0x000000FF );
+}
+
+
+/*********************************************************
+ * function: epciTmFrequncySet
+ *
+ * description: Set the timer frequency reporting register
+ ********************************************************/
+void epicTmFrequencySet( unsigned int frq )
+{
+ sysEUMBBARWrite(EPIC_TM_FREQ_REG, frq);
+}
+
+/*******************************************************
+ * function: epicTmFrequncyGet
+ *
+ * description: Get the current value of the Timer Frequency
+ * Reporting register
+ *
+ ******************************************************/
+unsigned int epicTmFrequencyGet(void)
+{
+ return( sysEUMBBARRead(EPIC_TM_FREQ_REG)) ;
+}
+
+
+/****************************************************
+ * function: epicTmBaseSet
+ *
+ * description: Set the #n global timer base count register
+ * return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ****************************************************/
+unsigned int epicTmBaseSet
+ (
+ ULONG srcAddr, /* Address of the Timer Base register */
+ unsigned int cnt, /* Base count */
+ unsigned int inhibit /* 1 - count inhibit */
+ )
+{
+
+ unsigned int val = 0x80000000;
+ /* First inhibit counting the timer */
+ sysEUMBBARWrite(srcAddr, val) ;
+
+ /* set the new value */
+ val = (cnt & 0x7fffffff) | ((inhibit & 0x1) << 31);
+ sysEUMBBARWrite(srcAddr, val) ;
+ return 0;
+}
+
+/***********************************************************************
+ * function: epicTmBaseGet
+ *
+ * description: Get the current value of the global timer base count register
+ * return 0 if no error, otherwise return 1.
+ *
+ * note:
+ ***********************************************************************/
+unsigned int epicTmBaseGet( ULONG srcAddr, unsigned int *val )
+{
+ *val = sysEUMBBARRead( srcAddr );
+ *val = *val & 0x7fffffff;
+ return 0;
+}
+
+/***********************************************************
+ * function: epicTmCountGet
+ *
+ * description: Get the value of a given global timer
+ * current count register
+ * return 0 if no error, otherwise return 1
+ * note:
+ **********************************************************/
+unsigned int epicTmCountGet( ULONG srcAddr, unsigned int *val )
+{
+ *val = sysEUMBBARRead( srcAddr );
+ *val = *val & 0x7fffffff;
+ return 0;
+}
+
+
+
+/***********************************************************
+ * function: epicTmInhibit
+ *
+ * description: Stop counting of a given global timer
+ * return 0 if no error, otherwise return 1
+ *
+ * note:
+ ***********************************************************/
+unsigned int epicTmInhibit( unsigned int srcAddr )
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( srcAddr );
+ val |= 0x80000000;
+ sysEUMBBARWrite( srcAddr, val );
+ return 0;
+}
+
+/******************************************************************
+ * function: epicTmEnable
+ *
+ * description: Enable counting of a given global timer
+ * return 0 if no error, otherwise return 1
+ *
+ * note:
+ *****************************************************************/
+unsigned int epicTmEnable( ULONG srcAddr )
+{
+ ULONG val;
+
+ val = sysEUMBBARRead( srcAddr );
+ val &= 0x7fffffff;
+ sysEUMBBARWrite( srcAddr, val );
+ return 0;
+}
+
+void epicSourcePrint(int Vect)
+ {
+ ULONG srcVal;
+
+ srcVal = sysEUMBBARRead(SrcVecTable[Vect].srcAddr);
+ PRINT("%s\n", SrcVecTable[Vect].srcName);
+ PRINT("Address = 0x%lx\n", SrcVecTable[Vect].srcAddr);
+ PRINT("Vector = %ld\n", (srcVal & 0x000000FF) );
+ PRINT("Mask = %ld\n", srcVal >> 31);
+ PRINT("Activitiy = %ld\n", (srcVal & 40000000) >> 30);
+ PRINT("Polarity = %ld\n", (srcVal & 0x00800000) >> 23);
+ PRINT("Sense = %ld\n", (srcVal & 0x00400000) >> 22);
+ PRINT("Priority = %ld\n", (srcVal & 0x000F0000) >> 16);
+ }
diff --git a/cpu/mpc824x/traps.c b/cpu/mpc824x/traps.c
new file mode 100644
index 0000000000..11f51c2501
--- /dev/null
+++ b/cpu/mpc824x/traps.c
@@ -0,0 +1,205 @@
+/*
+ * 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
+ * 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 <asm/processor.h>
+
+/* 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 0x00400000
+
+/*
+ * 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;
+ }
+
+ 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)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Alignment Exception");
+}
+
+void
+ProgramCheckException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+SoftEmuException(struct pt_regs *regs)
+{
+ show_regs(regs);
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Software Emulation Exception");
+}
+
+
+void
+UnknownException(struct pt_regs *regs)
+{
+ printf("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
+ regs->nip, regs->msr, regs->trap);
+ _exception(0, regs);
+}
+
+/* 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;
+}
diff --git a/cpu/mpc8260/ether_fcc.c b/cpu/mpc8260/ether_fcc.c
new file mode 100644
index 0000000000..01ddf5ccba
--- /dev/null
+++ b/cpu/mpc8260/ether_fcc.c
@@ -0,0 +1,347 @@
+/*
+ * MPC8260 FCC Fast Ethernet
+ *
+ * Copyright (c) 2000 MontaVista Software, Inc. Dan Malek (dmalek@jlc.net)
+ *
+ * (C) Copyright 2000 Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * MPC8260 FCC Fast Ethernet
+ * Basic ET HW initialization and packet RX/TX routines
+ *
+ * This code will not perform the IO port configuration. This should be
+ * done in the iop_conf_t structure specific for the board.
+ *
+ * TODO:
+ * add a PHY driver to do the negotiation
+ * reflect negotiation results in FPSMR
+ * look for ways to configure the board specific stuff elsewhere, eg.
+ * config_xxx.h or the board directory
+ */
+
+#include <common.h>
+#include <asm/cpm_8260.h>
+#include <mpc8260.h>
+#include <net.h>
+#include <command.h>
+#include <config.h>
+
+#if defined(CONFIG_ETHER_ON_FCC) && (CONFIG_COMMANDS & CFG_CMD_NET)
+
+/*---------------------------------------------------------------------*/
+#if (CONFIG_ETHER_INDEX == 1)
+
+#define PROFF_ENET PROFF_FCC1
+#define CPM_CR_ENET_SBLOCK CPM_CR_FCC1_SBLOCK
+#define CPM_CR_ENET_SBLOCK CPM_CR_FCC1_SBLOCK
+#define CPM_CR_ENET_PAGE CPM_CR_FCC1_PAGE
+
+/*---------------------------------------------------------------------*/
+#elif (CONFIG_ETHER_INDEX == 2)
+
+#define PROFF_ENET PROFF_FCC2
+#define CPM_CR_ENET_SBLOCK CPM_CR_FCC2_SBLOCK
+#define CPM_CR_ENET_PAGE CPM_CR_FCC2_PAGE
+
+/*---------------------------------------------------------------------*/
+#elif (CONFIG_ETHER_INDEX == 3)
+
+#define PROFF_ENET PROFF_FCC3
+#define CPM_CR_ENET_SBLOCK CPM_CR_FCC3_SBLOCK
+#define CPM_CR_ENET_PAGE CPM_CR_FCC3_PAGE
+
+/*---------------------------------------------------------------------*/
+#else
+#error "FCC Ethernet not correctly defined"
+#endif
+/*---------------------------------------------------------------------*/
+
+/* Maximum input DMA size. Must be a should(?) be a multiple of 4. */
+#define PKT_MAXDMA_SIZE 1520
+
+/* The FCC stores dest/src/type, data, and checksum for receive packets. */
+#define PKT_MAXBUF_SIZE 1518
+#define PKT_MINBUF_SIZE 64
+
+/* Maximum input buffer size. Must be a multiple of 32. */
+#define PKT_MAXBLR_SIZE 1536
+
+#define TOUT_LOOP 1000000
+
+#define TX_BUF_CNT 2
+#ifdef __GNUC__
+static char txbuf[TX_BUF_CNT][PKT_MAXBLR_SIZE] __attribute__ ((aligned(8)));
+#else
+#error "txbuf must be 64-bit aligned"
+#endif
+
+static uint rxIdx; /* index of the current RX buffer */
+static uint txIdx; /* index of the current TX buffer */
+
+/*
+ * FCC Ethernet Tx and Rx buffer descriptors.
+ * Provide for Double Buffering
+ * Note: PKTBUFSRX is defined in net.h
+ */
+
+typedef volatile struct rtxbd {
+ cbd_t rxbd[PKTBUFSRX];
+ cbd_t txbd[TX_BUF_CNT];
+} RTXBD;
+
+/* Good news: the FCC supports external BDs! */
+#ifdef __GNUC__
+static RTXBD rtx __attribute__ ((aligned(8)));
+#else
+#error "rtx must be 64-bit aligned"
+#endif
+
+int eth_send(volatile void *packet, int length)
+{
+ int i;
+ int result = 0;
+
+ if (length <= 0) {
+ printf("fec: bad packet size: %d\n", length);
+ goto out;
+ }
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx buffer not ready\n");
+ goto out;
+ }
+ }
+
+ rtx.txbd[txIdx].cbd_bufaddr = (uint)packet;
+ rtx.txbd[txIdx].cbd_datlen = length;
+ rtx.txbd[txIdx].cbd_sc |= (BD_ENET_TX_READY | BD_ENET_TX_LAST |
+ BD_ENET_TX_WRAP);
+
+ for(i=0; rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_READY; i++) {
+ if (i >= TOUT_LOOP) {
+ printf("fec: tx error\n");
+ goto out;
+ }
+ }
+
+#ifdef ET_DEBUG
+ printf("cycles: %d status: %04x\n", i, rtx.txbd[txIdx].cbd_sc);
+#endif
+
+ /* return only status bits */
+ result = rtx.txbd[txIdx].cbd_sc & BD_ENET_TX_STATS;
+
+out:
+ return result;
+}
+
+int eth_rx(void)
+{
+ int length;
+
+ for (;;)
+ {
+ if (rtx.rxbd[rxIdx].cbd_sc & BD_ENET_RX_EMPTY) {
+ length = -1;
+ break; /* nothing received - leave for() loop */
+ }
+ length = rtx.rxbd[rxIdx].cbd_datlen;
+
+ if (rtx.rxbd[rxIdx].cbd_sc & 0x003f) {
+ printf("fec: rx error %04x\n", rtx.rxbd[rxIdx].cbd_sc);
+ }
+ else {
+ /* Pass the packet up to the protocol layers. */
+ NetReceive(NetRxPackets[rxIdx], length - 4);
+ }
+
+
+ /* Give the buffer back to the FCC. */
+ rtx.rxbd[rxIdx].cbd_datlen = 0;
+
+ /* wrap around buffer index when necessary */
+ if ((rxIdx + 1) >= PKTBUFSRX) {
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY);
+ rxIdx = 0;
+ }
+ else {
+ rtx.rxbd[rxIdx].cbd_sc = BD_ENET_RX_EMPTY;
+ rxIdx++;
+ }
+ }
+ return length;
+}
+
+
+int eth_init(bd_t *bis)
+{
+ int i;
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+ volatile cpm8260_t *cp = &(immr->im_cpm);
+ fcc_enet_t *pram_ptr;
+ unsigned long mem_addr;
+
+#if 0
+ mii_discover_phy();
+#endif
+
+ /* 28.9 - (1-2): ioports have been set up already */
+
+ /* 28.9 - (3): connect FCC's tx and rx clocks */
+ immr->im_cpmux.cmx_uar = 0;
+ immr->im_cpmux.cmx_fcr = (immr->im_cpmux.cmx_fcr & ~CFG_CMXFCR_MASK) |
+ CFG_CMXFCR_VALUE;
+
+ /* 28.9 - (4): GFMR: disable tx/rx, CCITT CRC, Mode Ethernet */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_gfmr =
+ FCC_GFMR_MODE_ENET | FCC_GFMR_TCRC_32;
+
+ /* 28.9 - (5): FPSMR: enable full duplex, select CCITT CRC for Ethernet */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_fpsmr = CFG_FCC_PSMR | FCC_PSMR_ENCRC;
+
+ /* 28.9 - (6): FDSR: Ethernet Syn */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_fdsr = 0xD555;
+
+ /* reset indeces to current rx/tx bd (see eth_send()/eth_rx()) */
+ rxIdx = 0;
+ txIdx = 0;
+
+ /* Setup Receiver Buffer Descriptors */
+ for (i = 0; i < PKTBUFSRX; i++)
+ {
+ rtx.rxbd[i].cbd_sc = BD_ENET_RX_EMPTY;
+ rtx.rxbd[i].cbd_datlen = 0;
+ rtx.rxbd[i].cbd_bufaddr = (uint)NetRxPackets[i];
+ }
+ rtx.rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP;
+
+ /* Setup Ethernet Transmitter Buffer Descriptors */
+ for (i = 0; i < TX_BUF_CNT; i++)
+ {
+ rtx.txbd[i].cbd_sc = (BD_ENET_TX_PAD | BD_ENET_TX_LAST | BD_ENET_TX_TC);
+ rtx.txbd[i].cbd_datlen = 0;
+ rtx.txbd[i].cbd_bufaddr = (uint)&txbuf[i][0];
+ }
+ rtx.txbd[TX_BUF_CNT - 1].cbd_sc |= BD_ENET_TX_WRAP;
+
+ /* 28.9 - (7): initialise parameter ram */
+ pram_ptr = (fcc_enet_t *)&(immr->im_dprambase[PROFF_ENET]);
+
+ /* clear whole structure to make sure all reserved fields are zero */
+ memset((void*)pram_ptr, 0, sizeof(fcc_enet_t));
+
+ /*
+ * common Parameter RAM area
+ *
+ * Allocate space in the reserved FCC area of DPRAM for the
+ * internal buffers. No one uses this space (yet), so we
+ * can do this. Later, we will add resource management for
+ * this area.
+ */
+ mem_addr = CPM_FCC_SPECIAL_BASE + ((CONFIG_ETHER_INDEX-1) * 64);
+ pram_ptr->fen_genfcc.fcc_riptr = mem_addr;
+ pram_ptr->fen_genfcc.fcc_tiptr = mem_addr+32;
+ /*
+ * Set maximum bytes per receive buffer.
+ * It must be a multiple of 32.
+ */
+ pram_ptr->fen_genfcc.fcc_mrblr = PKT_MAXBLR_SIZE;
+ pram_ptr->fen_genfcc.fcc_rstate = (CPMFCR_GBL | CPMFCR_EB |
+ CFG_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_rbase = (unsigned int)(&rtx.rxbd[rxIdx]);
+ pram_ptr->fen_genfcc.fcc_tstate = (CPMFCR_GBL | CPMFCR_EB |
+ CFG_CPMFCR_RAMTYPE) << 24;
+ pram_ptr->fen_genfcc.fcc_tbase = (unsigned int)(&rtx.txbd[txIdx]);
+
+ /* protocol-specific area */
+ pram_ptr->fen_cmask = 0xdebb20e3; /* CRC mask */
+ pram_ptr->fen_cpres = 0xffffffff; /* CRC preset */
+ pram_ptr->fen_retlim = 15; /* Retry limit threshold */
+ pram_ptr->fen_mflr = PKT_MAXBUF_SIZE; /* maximum frame length register */
+ /*
+ * Set Ethernet station address.
+ *
+ * This is supplied in the board information structure, so we
+ * copy that into the controller.
+ * So, far we have only been given one Ethernet address. We make
+ * it unique by setting a few bits in the upper byte of the
+ * non-static part of the address.
+ */
+#define ea bis->bi_enetaddr
+ pram_ptr->fen_paddrh = (ea[5] << 8) + ea[4];
+ pram_ptr->fen_paddrm = (ea[3] << 8) + ea[2];
+ pram_ptr->fen_paddrl = (ea[1] << 8) + ea[0];
+#undef ea
+ pram_ptr->fen_minflr = PKT_MINBUF_SIZE; /* minimum frame length register */
+ /* pad pointer. use tiptr since we don't need a specific padding char */
+ pram_ptr->fen_padptr = pram_ptr->fen_genfcc.fcc_tiptr;
+ pram_ptr->fen_maxd1 = PKT_MAXDMA_SIZE; /* maximum DMA1 length */
+ pram_ptr->fen_maxd2 = PKT_MAXDMA_SIZE; /* maximum DMA2 length */
+ pram_ptr->fen_rfthr = 1;
+ pram_ptr->fen_rfcnt = 1;
+#if 0
+ printf("pram_ptr->fen_genfcc.fcc_rbase %08lx\n",
+ pram_ptr->fen_genfcc.fcc_rbase);
+ printf("pram_ptr->fen_genfcc.fcc_tbase %08lx\n",
+ pram_ptr->fen_genfcc.fcc_tbase);
+#endif
+
+ /* 28.9 - (8): clear out events in FCCE */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_fcce = ~0x0;
+
+ /* 28.9 - (9): FCCM: mask all events */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_fccm = 0;
+
+ /* 28.9 - (10-12): we don't use ethernet interrupts */
+
+ /* 28.9 - (13)
+ *
+ * Let's re-initialize the channel now. We have to do it later
+ * than the manual describes because we have just now finished
+ * the BD initialization.
+ */
+ cp->cp_cpcr = mk_cr_cmd(CPM_CR_ENET_PAGE,
+ CPM_CR_ENET_SBLOCK,
+ 0x0c,
+ CPM_CR_INIT_TRX) | CPM_CR_FLG;
+ do {
+ __asm__ __volatile__ ("eieio");
+ } while (cp->cp_cpcr & CPM_CR_FLG);
+
+ /* 28.9 - (14): enable tx/rx in gfmr */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_gfmr |= FCC_GFMR_ENT | FCC_GFMR_ENR;
+
+ return 1;
+}
+
+void eth_halt(void)
+{
+ volatile immap_t *immr = (immap_t *)CFG_IMMR;
+
+ /* write GFMR: disable tx/rx */
+ immr->im_fcc[CONFIG_ETHER_INDEX-1].fcc_gfmr &=
+ ~(FCC_GFMR_ENT | FCC_GFMR_ENR);
+}
+
+#endif /* CONFIG_ETHER_ON_FCC && CFG_CMD_NET */
diff --git a/cpu/mpc8260/traps.c b/cpu/mpc8260/traps.c
new file mode 100644
index 0000000000..a7f6f7e1a7
--- /dev/null
+++ b/cpu/mpc8260/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
+ * 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;
+}
diff --git a/cpu/mpc8xx/traps.c b/cpu/mpc8xx/traps.c
new file mode 100644
index 0000000000..c432be6030
--- /dev/null
+++ b/cpu/mpc8xx/traps.c
@@ -0,0 +1,245 @@
+/*
+ * 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
+ * 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
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#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);
+}
+
+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;
+}
diff --git a/cpu/mpc8xx/upatch.c b/cpu/mpc8xx/upatch.c
new file mode 100644
index 0000000000..99bdf53e27
--- /dev/null
+++ b/cpu/mpc8xx/upatch.c
@@ -0,0 +1,102 @@
+#include <common.h>
+#include <commproc.h>
+
+#if defined(CFG_I2C_UCODE_PATCH) || defined(CFG_SPI_UCODE_PATCH)
+
+static void UcodeCopy (volatile cpm8xx_t *cpm);
+
+void cpm_load_patch (volatile immap_t *immr)
+{
+ immr->im_cpm.cp_rccr &= ~0x0003; /* Disable microcode program area */
+
+ UcodeCopy ((cpm8xx_t *)&immr->im_cpm); /* Copy ucode patch to DPRAM */
+#ifdef CFG_SPI_UCODE_PATCH
+ {
+ volatile spi_t *spi = (spi_t *) & immr->im_cpm.cp_dparam[PROFF_SPI];
+ /* Activate the microcode per the instructions in the microcode manual */
+ /* NOTE: We're only relocating the SPI parameters (not I2C). */
+ immr->im_cpm.cp_cpmcr1 = 0x802a; /* Write Trap register 1 value */
+ immr->im_cpm.cp_cpmcr2 = 0x8028; /* Write Trap register 2 value */
+ spi->spi_rpbase = CFG_SPI_DPMEM_OFFSET; /* Where to relocte SPI params */
+ }
+#endif
+
+#ifdef CFG_I2C_UCODE_PATCH
+ {
+ volatile iic_t *iip = (iic_t *) & immr->im_cpm.cp_dparam[PROFF_IIC];
+ /* Activate the microcode per the instructions in the microcode manual */
+ /* NOTE: We're only relocating the I2C parameters (not SPI). */
+ immr->im_cpm.cp_cpmcr3 = 0x802e; /* Write Trap register 3 value */
+ immr->im_cpm.cp_cpmcr4 = 0x802c; /* Write Trap register 4 value */
+ iip->iic_rpbase = CFG_I2C_DPMEM_OFFSET; /* Where to relocte I2C params */
+ }
+#endif
+
+ /*
+ * Enable DPRAM microcode to execute from the first 512 bytes
+ * and a 256 byte extension of DPRAM.
+ */
+ immr->im_cpm.cp_rccr |= 0x0001;
+}
+
+static ulong patch_2000[] = {
+ 0x7FFFEFD9, 0x3FFD0000, 0x7FFB49F7, 0x7FF90000,
+ 0x5FEFADF7, 0x5F88ADF7, 0x5FEFAFF7, 0x5F88AFF7,
+ 0x3A9CFBC8, 0x77CAE1BB, 0xF4DE7FAD, 0xABAE9330,
+ 0x4E08FDCF, 0x6E0FAFF8, 0x7CCF76CF, 0xFDAFF9CF,
+ 0xABF88DC8, 0xAB5879F7, 0xB0927383, 0xDFD079F7,
+ 0xB090E6BB, 0xE5BBE74F, 0xB3FA6F0F, 0x6FFB76CE,
+ 0xEE0CF9CF, 0x2BFBEFEF, 0xCFEEF9CF, 0x76CEAD23,
+ 0x90B3DF99, 0x7FDDD0C1, 0x4BF847FD, 0x7CCF76CE,
+ 0xCFEF77CA, 0x7EAF7FAD, 0x7DFDF0B7, 0xEF7A7FCA,
+ 0x77CAFBC8, 0x6079E722, 0xFBC85FFF, 0xDFFF5FB3,
+ 0xFFFBFBC8, 0xF3C894A5, 0xE7C9EDF9, 0x7F9A7FAD,
+ 0x5F36AFE8, 0x5F5BFFDF, 0xDF95CB9E, 0xAF7D5FC3,
+ 0xAFED8C1B, 0x5FC3AFDD, 0x5FC5DF99, 0x7EFDB0B3,
+ 0x5FB3FFFE, 0xABAE5FB3, 0xFFFE5FD0, 0x600BE6BB,
+ 0x600B5FD0, 0xDFC827FB, 0xEFDF5FCA, 0xCFDE3A9C,
+ 0xE7C9EDF9, 0xF3C87F9E, 0x54CA7FED, 0x2D3A3637,
+ 0x756F7E9A, 0xF1CE37EF, 0x2E677FEE, 0x10EBADF8,
+ 0xEFDECFEA, 0xE52F7D9F, 0xE12BF1CE, 0x5F647E9A,
+ 0x4DF8CFEA, 0x5F717D9B, 0xEFEECFEA, 0x5F73E522,
+ 0xEFDE5F73, 0xCFDA0B61, 0x7385DF61, 0xE7C9EDF9,
+ 0x7E9A30D5, 0x1458BFFF, 0xF3C85FFF, 0xDFFFA7F8,
+ 0x5F5BBFFE, 0x7F7D10D0, 0x144D5F33, 0xBFFFAF78,
+ 0x5F5BBFFD, 0xA7F85F33, 0xBFFE77FD, 0x30BD4E08,
+ 0xFDCFE5FF, 0x6E0FAFF8, 0x7EEF7E9F, 0xFDEFF1CF,
+ 0x5F17ABF8, 0x0D5B5F5B, 0xFFEF79F7, 0x309EAFDD,
+ 0x5F3147F8, 0x5F31AFED, 0x7FDD50AF, 0x497847FD,
+ 0x7F9E7FED, 0x7DFD70A9, 0xEF7E7ECE, 0x6BA07F9E,
+ 0x2D227EFD, 0x30DB5F5B, 0xFFFD5F5B, 0xFFEF5F5B,
+ 0xFFDF0C9C, 0xAFED0A9A, 0xAFDD0C37, 0x5F37AFBD,
+ 0x7FBDB081, 0x5F8147F8,
+};
+
+static ulong patch_2F00[] = {
+ 0x3E303430, 0x34343737, 0xABBF9B99, 0x4B4FBDBD,
+ 0x59949334, 0x9FFF37FB, 0x9B177DD9, 0x936956BB,
+ 0xFBDD697B, 0xDD2FD113, 0x1DB9F7BB, 0x36313963,
+ 0x79373369, 0x3193137F, 0x7331737A, 0xF7BB9B99,
+ 0x9BB19795, 0x77FDFD3D, 0x573B773F, 0x737933F7,
+ 0xB991D115, 0x31699315, 0x31531694, 0xBF4FBDBD,
+ 0x35931497, 0x35376956, 0xBD697B9D, 0x96931313,
+ 0x19797937, 0x69350000,
+};
+
+static void UcodeCopy (volatile cpm8xx_t *cpm)
+{
+ vu_long *p;
+ int i;
+
+ p = (vu_long *)&(cpm->cp_dpmem[0x0000]);
+ for (i=0; i < sizeof(patch_2000)/4; ++i) {
+ p[i] = patch_2000[i];
+ }
+
+ p = (vu_long *)&(cpm->cp_dpmem[0x0F00]);
+ for (i=0; i < sizeof(patch_2F00)/4; ++i) {
+ p[i] = patch_2F00[i];
+ }
+}
+
+#endif /* CFG_I2C_UCODE_PATCH, CFG_SPI_UCODE_PATCH */
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c
new file mode 100644
index 0000000000..51ba47111b
--- /dev/null
+++ b/cpu/ppc4xx/miiphy.c
@@ -0,0 +1,182 @@
+/*-----------------------------------------------------------------------------+
+ |
+ | This source code has been made available to you by IBM on an AS-IS
+ | basis. Anyone receiving this source is licensed under IBM
+ | copyrights to use it in any way he or she deems fit, including
+ | copying it, modifying it, compiling it, and redistributing it either
+ | with or without modifications. No license under IBM patents or
+ | patent applications is to be implied by the copyright license.
+ |
+ | Any user of this software should understand that IBM cannot provide
+ | technical support for this software and will not be responsible for
+ | any consequences resulting from the use of this software.
+ |
+ | Any person who transfers this source code or any derivative work
+ | must include the IBM copyright notice, this paragraph, and the
+ | preceding two paragraphs in the transferred software.
+ |
+ | COPYRIGHT I B M CORPORATION 1995
+ | LICENSED MATERIAL - PROGRAM PROPERTY OF I B M
+ +-----------------------------------------------------------------------------*/
+/*-----------------------------------------------------------------------------+
+ |
+ | File Name: miiphy.c
+ |
+ | Function: This module has utilities for accessing the MII PHY through
+ | the EMAC3 macro.
+ |
+ | Author: Mark Wisner
+ |
+ | Change Activity-
+ |
+ | Date Description of Change BY
+ | --------- --------------------- ---
+ | 05-May-99 Created MKW
+ | 01-Jul-99 Changed clock setting of sta_reg from 66Mhz to 50Mhz to
+ | better match OPB speed. Also modified delay times. JWB
+ | 29-Jul-99 Added Full duplex support MKW
+ | 24-Aug-99 Removed printf from dp83843_duplex() JWB
+ | 19-Jul-00 Ported to esd cpci405 sr
+ |
+ +-----------------------------------------------------------------------------*/
+
+#include <common.h>
+#include <asm/processor.h>
+#include <ppc_asm.tmpl>
+#include <commproc.h>
+#include <405gp_enet.h>
+#include <405_mal.h>
+#include <miiphy.h>
+
+#if defined(CONFIG_405GP) || defined(CONFIG_440)
+
+
+/***********************************************************/
+/* Dump out to the screen PHY regs */
+/***********************************************************/
+
+void miiphy_dump (unsigned char addr)
+{
+ unsigned long i;
+ unsigned short data;
+
+
+ for (i = 0; i < 0x1A; i++) {
+ if (miiphy_read (addr, i, &data)) {
+ printf ("read error for reg %lx\n", i);
+ return;
+ }
+ printf ("Phy reg %lx ==> %4x\n", i, data);
+
+ /* jump to the next set of regs */
+ if (i == 0x07)
+ i = 0x0f;
+
+ } /* end for loop */
+} /* end dump */
+
+
+
+/***********************************************************/
+/* read a phy reg and return the value with a rc */
+/***********************************************************/
+
+int miiphy_read (unsigned char addr, unsigned char reg,
+ unsigned short *value)
+{
+ unsigned long sta_reg; /* STA scratch area */
+ unsigned long i;
+
+ /* see if it is ready for 1000 nsec */
+ i = 0;
+
+ /* see if it is ready for sec */
+ while ((in32 (EMAC_STACR) & EMAC_STACR_OC) == 0) {
+ udelay (7);
+ if (i > 5) {
+ printf ("read err 1\n");
+ return -1;
+ }
+ i++;
+ }
+ sta_reg = reg; /* reg address */
+ /* set clock (50Mhz) and read flags */
+ sta_reg = (sta_reg | EMAC_STACR_READ) & ~EMAC_STACR_CLK_100MHZ;
+ sta_reg = sta_reg | (addr << 5); /* Phy address */
+
+ out32 (EMAC_STACR, sta_reg);
+#if 0 /* test-only */
+ printf ("a2: write: EMAC_STACR=0x%0x\n", sta_reg); /* test-only */
+#endif
+
+ sta_reg = in32 (EMAC_STACR);
+ i = 0;
+ while ((sta_reg & EMAC_STACR_OC) == 0) {
+ udelay (7);
+ if (i > 5) {
+ printf ("read err 2\n");
+ return -1;
+ }
+ i++;
+ sta_reg = in32 (EMAC_STACR);
+ }
+ if ((sta_reg & EMAC_STACR_PHYE) != 0) {
+ printf ("read err 3\n");
+ printf ("a2: read: EMAC_STACR=0x%0lx, i=%d\n",
+ sta_reg, (int) i); /* test-only */
+ return -1;
+ }
+
+ *value = *(short *) (&sta_reg);
+ return 0;
+
+
+} /* phy_read */
+
+
+/***********************************************************/
+/* write a phy reg and return the value with a rc */
+/***********************************************************/
+
+int miiphy_write (unsigned char addr, unsigned char reg,
+ unsigned short value)
+{
+ unsigned long sta_reg; /* STA scratch area */
+ unsigned long i;
+
+ /* see if it is ready for 1000 nsec */
+ i = 0;
+
+ while ((in32 (EMAC_STACR) & EMAC_STACR_OC) == 0) {
+ if (i > 5)
+ return -1;
+ udelay (7);
+ i++;
+ }
+ sta_reg = 0;
+ sta_reg = reg; /* reg address */
+ /* set clock (50Mhz) and read flags */
+ sta_reg = (sta_reg | EMAC_STACR_WRITE) & ~EMAC_STACR_CLK_100MHZ;
+ sta_reg = sta_reg | ((unsigned long) addr << 5); /* Phy address */
+ memcpy (&sta_reg, &value, 2); /* put in data */
+
+ out32 (EMAC_STACR, sta_reg);
+
+ /* wait for completion */
+ i = 0;
+ sta_reg = in32 (EMAC_STACR);
+ while ((sta_reg & EMAC_STACR_OC) == 0) {
+ udelay (7);
+ if (i > 5)
+ return -1;
+ i++;
+ sta_reg = in32 (EMAC_STACR);
+ }
+
+ if ((sta_reg & EMAC_STACR_PHYE) != 0)
+ return -1;
+ return 0;
+
+} /* phy_read */
+
+#endif /* CONFIG_405GP */
diff --git a/cpu/ppc4xx/traps.c b/cpu/ppc4xx/traps.c
new file mode 100644
index 0000000000..85f2ea4cce
--- /dev/null
+++ b/cpu/ppc4xx/traps.c
@@ -0,0 +1,291 @@
+/*
+ * 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
+ * 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 0x00400000
+
+
+static __inline__ void set_tsr(unsigned long val)
+{
+#if defined(CONFIG_440)
+ asm volatile("mtspr 0x150, %0" : : "r" (val));
+#else
+ asm volatile("mttsr %0" : : "r" (val));
+#endif
+}
+
+static __inline__ unsigned long get_esr(void)
+{
+ unsigned long val;
+
+#if defined(CONFIG_440)
+ asm volatile("mfspr %0, 0x03e" : "=r" (val) :);
+#else
+ asm volatile("mfesr %0" : "=r" (val) :);
+#endif
+ return val;
+}
+
+#define ESR_MCI 0x80000000
+#define ESR_PIL 0x08000000
+#define ESR_PPR 0x04000000
+#define ESR_PTR 0x02000000
+#define ESR_DST 0x00800000
+#define ESR_DIZ 0x00400000
+#define ESR_U0F 0x00008000
+
+#if (CONFIG_COMMANDS & CFG_CMD_BEDBUG)
+extern void do_bedbug_breakpoint(struct pt_regs *);
+#endif
+
+/*
+ * 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)
+{
+ long esr_val;
+
+#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
+ if (debugger_exception_handler && (*debugger_exception_handler)(regs))
+ return;
+#endif
+
+ show_regs(regs);
+
+ esr_val = get_esr();
+ if( esr_val & ESR_PIL )
+ printf( "** Illegal Instruction **\n" );
+ else if( esr_val & ESR_PPR )
+ printf( "** Privileged Instruction **\n" );
+ else if( esr_val & ESR_PTR )
+ printf( "** Trap Instruction **\n" );
+
+ print_backtrace((unsigned long *)regs->gpr[1]);
+ panic("Program Check Exception");
+}
+
+void
+PITException(struct pt_regs *regs)
+{
+ /*
+ * Reset PIT interrupt
+ */
+ set_tsr(0x08000000);
+
+ /*
+ * Call timer_interrupt routine in interrupts.c
+ */
+ timer_interrupt(NULL);
+}
+
+
+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);
+}
+
+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;
+}
OpenPOWER on IntegriCloud