diff options
Diffstat (limited to 'cpu/ppc4xx')
-rw-r--r-- | cpu/ppc4xx/miiphy.c | 182 | ||||
-rw-r--r-- | cpu/ppc4xx/traps.c | 291 |
2 files changed, 473 insertions, 0 deletions
diff --git a/cpu/ppc4xx/miiphy.c b/cpu/ppc4xx/miiphy.c new file mode 100644 index 0000000..51ba471 --- /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 0000000..85f2ea4 --- /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; +} |