Das U-Boot: Universal Boot Loader

This commit is contained in:
wdenk
2002-08-17 09:36:01 +00:00
parent a0fb24cb71
commit 73e319c4e2
89 changed files with 34073 additions and 0 deletions

234
cpu/74xx_7xx/traps.c Normal file
View File

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

View File

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

205
cpu/mpc824x/traps.c Normal file
View File

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

347
cpu/mpc8260/ether_fcc.c Normal file
View File

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

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

@@ -0,0 +1,246 @@
/*
* linux/arch/ppc/kernel/traps.c
*
* Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
*
* Modified by Cort Dougan (cort@cs.nmt.edu)
* and Paul Mackerras (paulus@cs.anu.edu.au)
*
* (C) Copyright 2000
* 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;
}

245
cpu/mpc8xx/traps.c Normal file
View File

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

102
cpu/mpc8xx/upatch.c Normal file
View File

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

182
cpu/ppc4xx/miiphy.c Normal file
View File

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

291
cpu/ppc4xx/traps.c Normal file
View File

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