diff options
| author | Stefan Roese <sr@denx.de> | 2010-04-15 16:07:28 +0200 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2010-04-21 23:42:38 +0200 | 
| commit | a47a12becf66f02a56da91c161e2edb625e9f20c (patch) | |
| tree | 6efae7137d26d1e610c5fd56b7aaa3c043ad2b71 /arch/powerpc/cpu/mpc86xx | |
| parent | 254ab7bd464657600aba69d840406f9358f3e116 (diff) | |
| download | olio-uboot-2014.01-a47a12becf66f02a56da91c161e2edb625e9f20c.tar.xz olio-uboot-2014.01-a47a12becf66f02a56da91c161e2edb625e9f20c.zip | |
Move arch/ppc to arch/powerpc
As discussed on the list, move "arch/ppc" to "arch/powerpc" to
better match the Linux directory structure.
Please note that this patch also changes the "ppc" target in
MAKEALL to "powerpc" to match this new infrastructure. But "ppc"
is kept as an alias for now, to not break compatibility with
scripts using this name.
Signed-off-by: Stefan Roese <sr@denx.de>
Acked-by: Wolfgang Denk <wd@denx.de>
Acked-by: Detlev Zundel <dzu@denx.de>
Acked-by: Kim Phillips <kim.phillips@freescale.com>
Cc: Peter Tyser <ptyser@xes-inc.com>
Cc: Anatolij Gustschin <agust@denx.de>
Diffstat (limited to 'arch/powerpc/cpu/mpc86xx')
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/Makefile | 63 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/cache.S | 378 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/config.mk | 27 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/cpu.c | 233 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/cpu_init.c | 190 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/ddr-8641.c | 85 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/fdt.c | 60 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/interrupts.c | 115 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/mp.c | 125 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/release.S | 167 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/speed.c | 163 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/start.S | 957 | ||||
| -rw-r--r-- | arch/powerpc/cpu/mpc86xx/traps.c | 233 | 
13 files changed, 2796 insertions, 0 deletions
| diff --git a/arch/powerpc/cpu/mpc86xx/Makefile b/arch/powerpc/cpu/mpc86xx/Makefile new file mode 100644 index 000000000..daca79ad4 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/Makefile @@ -0,0 +1,63 @@ +# +# Copyright 2007 Freescale Semiconductor, Inc. +# (C) Copyright 2002,2003 Motorola Inc. +# Xianghua Xiao,X.Xiao@motorola.com +# +# (C) Copyright 2004 Freescale Semiconductor. (MC86xx Port) +# Jeff Brown +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(CPU).a + +START	= start.o + +SOBJS-y += cache.o +SOBJS-$(CONFIG_MP) += release.o + +COBJS-y	+= cpu.o +COBJS-y	+= cpu_init.o +# 8610 & 8641 are identical w/regards to DDR +COBJS-$(CONFIG_MPC8610) += ddr-8641.o +COBJS-$(CONFIG_MPC8641) += ddr-8641.o +COBJS-$(CONFIG_OF_LIBFDT) += fdt.o +COBJS-y	+= interrupts.o +COBJS-$(CONFIG_MP) += mp.o +COBJS-y	+= speed.o +COBJS-y	+= traps.o + +SRCS	:= $(START:.o=.S) $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS	:= $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) +START	:= $(addprefix $(obj),$(START)) + +all:	$(obj).depend $(START) $(LIB) + +$(LIB):	$(OBJS) +	$(AR) $(ARFLAGS) $@ $(ASOBJS) $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/arch/powerpc/cpu/mpc86xx/cache.S b/arch/powerpc/cpu/mpc86xx/cache.S new file mode 100644 index 000000000..0bb058b04 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/cache.S @@ -0,0 +1,378 @@ +#include <config.h> +#include <mpc86xx.h> +#include <version.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#ifndef CACHE_LINE_SIZE +# define CACHE_LINE_SIZE L1_CACHE_BYTES +#endif + +#if CACHE_LINE_SIZE == 128 +#define LG_CACHE_LINE_SIZE 7 +#elif CACHE_LINE_SIZE == 32 +#define LG_CACHE_LINE_SIZE 5 +#elif CACHE_LINE_SIZE == 16 +#define LG_CACHE_LINE_SIZE 4 +#elif CACHE_LINE_SIZE == 8 +#define LG_CACHE_LINE_SIZE 3 +#else +# error "Invalid cache line size!" +#endif + +/* + * Most of this code is taken from 74xx_7xx/cache.S + * and then cleaned up a bit + */ + +/* + * Invalidate L1 instruction cache. + */ +_GLOBAL(invalidate_l1_instruction_cache) +	/* use invalidate-all bit in HID0 */ +	mfspr	r3,HID0 +	ori	r3,r3,HID0_ICFI +	mtspr	HID0,r3 +	isync +	blr + +/* + * Invalidate L1 data cache. + */ +_GLOBAL(invalidate_l1_data_cache) +	mfspr	r3,HID0 +	ori	r3,r3,HID0_DCFI +	mtspr	HID0,r3 +	isync +	blr + +/* + * Flush data cache. + */ +_GLOBAL(flush_dcache) +	lis	r3,0 +	lis	r5,CACHE_LINE_SIZE +flush: +	cmp	0,1,r3,r5 +	bge	done +	lwz	r5,0(r3) +	lis	r5,CACHE_LINE_SIZE +	addi	r3,r3,0x4 +	b	flush +done: +	blr +/* + * Write any modified data cache blocks out to memory + * and invalidate the corresponding instruction cache blocks. + * This is a no-op on the 601. + * + * flush_icache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(flush_icache_range) +	li	r5,CACHE_LINE_SIZE-1 +	andc	r3,r3,r5 +	subf	r4,r3,r4 +	add	r4,r4,r5 +	srwi.	r4,r4,LG_CACHE_LINE_SIZE +	beqlr +	mtctr	r4 +	mr	r6,r3 +1:	dcbst	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	sync				/* wait for dcbst's to get to ram */ +	mtctr	r4 +2:	icbi	0,r6 +	addi	r6,r6,CACHE_LINE_SIZE +	bdnz	2b +	sync				/* additional sync needed on g4 */ +	isync +	blr +/* + * Write any modified data cache blocks out to memory. + * Does not invalidate the corresponding cache lines (especially for + * any corresponding instruction cache). + * + * clean_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(clean_dcache_range) +	li	r5,CACHE_LINE_SIZE-1 +	andc	r3,r3,r5	/* align r3 down to cache line */ +	subf	r4,r3,r4	/* r4 = offset of stop from start of cache line */ +	add	r4,r4,r5	/* r4 += cache_line_size-1 */ +	srwi.	r4,r4,LG_CACHE_LINE_SIZE  /* r4 = number of cache lines to flush */ +	beqlr				  /* if r4 == 0 return */ +	mtctr	r4			  /* ctr = r4 */ + +	sync +1:	dcbst	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	sync				/* wait for dcbst's to get to ram */ +	blr + +/* + * Write any modified data cache blocks out to memory + * and invalidate the corresponding instruction cache blocks. + * + * flush_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(flush_dcache_range) +	li	r5,CACHE_LINE_SIZE-1 +	andc	r3,r3,r5 +	subf	r4,r3,r4 +	add	r4,r4,r5 +	srwi.	r4,r4,LG_CACHE_LINE_SIZE +	beqlr +	mtctr	r4 + +	sync +1:	dcbf	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	sync				/* wait for dcbf's to get to ram */ +	blr + +/* + * Like above, but invalidate the D-cache.  This is used by the 8xx + * to invalidate the cache so the PPC core doesn't get stale data + * from the CPM (no cache snooping here :-). + * + * invalidate_dcache_range(unsigned long start, unsigned long stop) + */ +_GLOBAL(invalidate_dcache_range) +	li	r5,CACHE_LINE_SIZE-1 +	andc	r3,r3,r5 +	subf	r4,r3,r4 +	add	r4,r4,r5 +	srwi.	r4,r4,LG_CACHE_LINE_SIZE +	beqlr +	mtctr	r4 + +	sync +1:	dcbi	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	sync				/* wait for dcbi's to get to ram */ +	blr + +/* + * Flush a particular page from the data cache to RAM. + * Note: this is necessary because the instruction cache does *not* + * snoop from the data cache. + * + *	void __flush_page_to_ram(void *page) + */ +_GLOBAL(__flush_page_to_ram) +	rlwinm	r3,r3,0,0,19		/* Get page base address */ +	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */ +	mtctr	r4 +	mr	r6,r3 +0:	dcbst	0,r3			/* Write line to ram */ +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	0b +	sync +	mtctr	r4 +1:	icbi	0,r6 +	addi	r6,r6,CACHE_LINE_SIZE +	bdnz	1b +	sync +	isync +	blr + +/* + * Flush a particular page from the instruction cache. + * Note: this is necessary because the instruction cache does *not* + * snoop from the data cache. + * + *	void __flush_icache_page(void *page) + */ +_GLOBAL(__flush_icache_page) +	li	r4,4096/CACHE_LINE_SIZE	/* Number of lines in a page */ +	mtctr	r4 +1:	icbi	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	sync +	isync +	blr + +/* + * Clear a page using the dcbz instruction, which doesn't cause any + * memory traffic (except to write out any cache lines which get + * displaced).  This only works on cacheable memory. + */ +_GLOBAL(clear_page) +	li	r0,4096/CACHE_LINE_SIZE +	mtctr	r0 +1:	dcbz	0,r3 +	addi	r3,r3,CACHE_LINE_SIZE +	bdnz	1b +	blr + +/* + * Enable L1 Instruction cache + */ +_GLOBAL(icache_enable) +	mfspr	r3, HID0 +	li	r5, HID0_ICFI|HID0_ILOCK +	andc	r3, r3, r5 +	ori	r3, r3, HID0_ICE +	ori	r5, r3, HID0_ICFI +	mtspr	HID0, r5 +	mtspr	HID0, r3 +	isync +	blr + +/* + * Disable L1 Instruction cache + */ +_GLOBAL(icache_disable) +	mflr	r4 +	bl	invalidate_l1_instruction_cache		/* uses r3 */ +	sync +	mtlr	r4 +	mfspr	r3, HID0 +	li	r5, 0 +	ori	r5, r5, HID0_ICE +	andc	r3, r3, r5 +	mtspr	HID0, r3 +	isync +	blr + +/* + * Is instruction cache enabled? + */ +_GLOBAL(icache_status) +	mfspr	r3, HID0 +	andi.	r3, r3, HID0_ICE +	blr + + +_GLOBAL(l1dcache_enable) +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	ori	r3, r3, HID0_DCE +	ori	r5, r3, HID0_DCFI +	mtspr	HID0, r5		/* enable + invalidate */ +	mtspr	HID0, r3		/* enable */ +	sync +	blr + +/* + * Enable data cache(s) - L1 and optionally L2 + * Calls l2cache_enable. LR saved in r5 + */ +_GLOBAL(dcache_enable) +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	ori	r3, r3, HID0_DCE +	ori	r5, r3, HID0_DCFI +	mtspr	HID0, r5		/* enable + invalidate */ +	mtspr	HID0, r3		/* enable */ +	sync +#ifdef CONFIG_SYS_L2 +	mflr	r5 +	bl	l2cache_enable		/* uses r3 and r4 */ +	sync +	mtlr	r5 +#endif +	blr + + +/* + * Disable data cache(s) - L1 and optionally L2 + * Calls flush_dcache and l2cache_disable_no_flush. + * LR saved in r4 + */ +_GLOBAL(dcache_disable) +	mflr	r4			/* save link register */ +	bl	flush_dcache	/* uses r3 and r5 */ +	sync +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	li	r5, HID0_DCE|HID0_DCFI +	andc	r3, r3, r5		/* no enable, no invalidate */ +	mtspr	HID0, r3 +	sync +#ifdef CONFIG_SYS_L2 +	bl	l2cache_disable_no_flush /* uses r3 */ +#endif +	mtlr	r4			/* restore link register */ +	blr + +/* + * Is data cache enabled? + */ +_GLOBAL(dcache_status) +	mfspr	r3, HID0 +	andi.	r3, r3, HID0_DCE +	blr + +/* + * Invalidate L2 cache using L2I, assume L2 is enabled + */ +_GLOBAL(l2cache_invalidate) +	mfspr	r3, l2cr +	rlwinm.	r3, r3, 0, 0, 0 +	beq	1f + +	mfspr	r3, l2cr +	rlwinm	r3, r3, 0, 1, 31 + +#ifdef	CONFIG_ALTIVEC +	dssall +#endif +	sync +	mtspr	l2cr, r3 +	sync +1:	mfspr	r3, l2cr +	oris	r3, r3, L2CR_L2I@h +	mtspr	l2cr, r3 + +invl2: +	mfspr	r3, l2cr +	andis.	r3, r3, L2CR_L2I@h +	bne	invl2 +	blr + +/* + * Enable L2 cache + * Calls l2cache_invalidate. LR is saved in r4 + */ +_GLOBAL(l2cache_enable) +	mflr	r4			/* save link register */ +	bl	l2cache_invalidate	/* uses r3 */ +	sync +	lis	r3, L2_ENABLE@h +	ori	r3, r3, L2_ENABLE@l +	mtspr	l2cr, r3 +	isync +	mtlr	r4			/* restore link register */ +	blr + +/* + * Disable L2 cache + * Calls flush_dcache. LR is saved in r4 + */ +_GLOBAL(l2cache_disable) +	mflr	r4			/* save link register */ +	bl	flush_dcache		/* uses r3 and r5 */ +	sync +	mtlr	r4			/* restore link register */ +l2cache_disable_no_flush:		/* provide way to disable L2 w/o flushing */ +	lis	r3, L2_INIT@h +	ori	r3, r3, L2_INIT@l +	mtspr	l2cr, r3 +	isync +	blr diff --git a/arch/powerpc/cpu/mpc86xx/config.mk b/arch/powerpc/cpu/mpc86xx/config.mk new file mode 100644 index 000000000..ca2f8376e --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/config.mk @@ -0,0 +1,27 @@ +# +# (C) Copyright 2004 Freescale Semiconductor. +# Jeff Brown +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +PLATFORM_RELFLAGS += -fPIC -meabi + +PLATFORM_CPPFLAGS += -ffixed-r2 -mstring +PLATFORM_CPPFLAGS += -maltivec -mabi=altivec -msoft-float diff --git a/arch/powerpc/cpu/mpc86xx/cpu.c b/arch/powerpc/cpu/mpc86xx/cpu.c new file mode 100644 index 000000000..188757587 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/cpu.c @@ -0,0 +1,233 @@ +/* + * Copyright 2006,2009-2010 Freescale Semiconductor, Inc. + * Jeff Brown + * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <watchdog.h> +#include <command.h> +#include <asm/cache.h> +#include <asm/mmu.h> +#include <mpc86xx.h> +#include <asm/fsl_law.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Default board reset function + */ +static void +__board_reset(void) +{ +	/* Do nothing */ +} +void board_reset(void) __attribute__((weak, alias("__board_reset"))); + + +int +checkcpu(void) +{ +	sys_info_t sysinfo; +	uint pvr, svr; +	uint ver; +	uint major, minor; +	char buf1[32], buf2[32]; +	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; +	volatile ccsr_gur_t *gur = &immap->im_gur; +	struct cpu_type *cpu; +	uint msscr0 = mfspr(MSSCR0); + +	svr = get_svr(); +	ver = SVR_SOC_VER(svr); +	major = SVR_MAJ(svr); +	minor = SVR_MIN(svr); + +	if (cpu_numcores() > 1) { +#ifndef CONFIG_MP +		puts("Unicore software on multiprocessor system!!\n" +		     "To enable mutlticore build define CONFIG_MP\n"); +#endif +	} +	puts("CPU:   "); + +	cpu = gd->cpu; + +	puts(cpu->name); + +	printf(", Version: %d.%d, (0x%08x)\n", major, minor, svr); +	puts("Core:  "); + +	pvr = get_pvr(); +	ver = PVR_E600_VER(pvr); +	major = PVR_E600_MAJ(pvr); +	minor = PVR_E600_MIN(pvr); + +	printf("E600 Core %d", (msscr0 & 0x20) ? 1 : 0 ); +	if (gur->pordevsr & MPC86xx_PORDEVSR_CORE1TE) +		puts("\n    Core1Translation Enabled"); +	debug(" (MSSCR0=%x, PORDEVSR=%x)", msscr0, gur->pordevsr); + +	printf(", Version: %d.%d, (0x%08x)\n", major, minor, pvr); + +	get_sys_info(&sysinfo); + +	puts("Clock Configuration:\n"); +	printf("       CPU:%-4s MHz, ", strmhz(buf1, sysinfo.freqProcessor)); +	printf("MPX:%-4s MHz\n", strmhz(buf1, sysinfo.freqSystemBus)); +	printf("       DDR:%-4s MHz (%s MT/s data rate), ", +		strmhz(buf1, sysinfo.freqSystemBus / 2), +		strmhz(buf2, sysinfo.freqSystemBus)); + +	if (sysinfo.freqLocalBus > LCRR_CLKDIV) { +		printf("LBC:%-4s MHz\n", strmhz(buf1, sysinfo.freqLocalBus)); +	} else { +		printf("LBC: unknown (LCRR[CLKDIV] = 0x%02lx)\n", +		       sysinfo.freqLocalBus); +	} + +	puts("L1:    D-cache 32 KB enabled\n"); +	puts("       I-cache 32 KB enabled\n"); + +	puts("L2:    "); +	if (get_l2cr() & 0x80000000) { +#if defined(CONFIG_MPC8610) +		puts("256"); +#elif defined(CONFIG_MPC8641) +		puts("512"); +#endif +		puts(" KB enabled\n"); +	} else { +		puts("Disabled\n"); +	} + +	return 0; +} + + +void +do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; +	volatile ccsr_gur_t *gur = &immap->im_gur; + +	/* Attempt board-specific reset */ +	board_reset(); + +	/* Next try asserting HRESET_REQ */ +	out_be32(&gur->rstcr, MPC86xx_RSTCR_HRST_REQ); + +	while (1) +		; +} + + +/* + * Get timebase clock frequency + */ +unsigned long +get_tbclk(void) +{ +	sys_info_t sys_info; + +	get_sys_info(&sys_info); +	return (sys_info.freqSystemBus + 3L) / 4L; +} + + +#if defined(CONFIG_WATCHDOG) +void +watchdog_reset(void) +{ +#if defined(CONFIG_MPC8610) +	/* +	 * This actually feed the hard enabled watchdog. +	 */ +	volatile immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; +	volatile ccsr_wdt_t *wdt = &immap->im_wdt; +	volatile ccsr_gur_t *gur = &immap->im_gur; +	u32 tmp = gur->pordevsr; + +	if (tmp & 0x4000) { +		wdt->swsrr = 0x556c; +		wdt->swsrr = 0xaa39; +	} +#endif +} +#endif	/* CONFIG_WATCHDOG */ + +/* + * Print out the state of various machine registers. + * Currently prints out LAWs, BR0/OR0, and BATs + */ +void mpc86xx_reginfo(void) +{ +	immap_t *immap = (immap_t *)CONFIG_SYS_IMMR; +	ccsr_lbc_t *lbc = &immap->im_lbc; + +	print_bats(); +	print_laws(); + +	printf ("Local Bus Controller Registers\n" +		"\tBR0\t0x%08X\tOR0\t0x%08X \n", in_be32(&lbc->br0), in_be32(&lbc->or0)); +	printf("\tBR1\t0x%08X\tOR1\t0x%08X \n", in_be32(&lbc->br1), in_be32(&lbc->or1)); +	printf("\tBR2\t0x%08X\tOR2\t0x%08X \n", in_be32(&lbc->br2), in_be32(&lbc->or2)); +	printf("\tBR3\t0x%08X\tOR3\t0x%08X \n", in_be32(&lbc->br3), in_be32(&lbc->or3)); +	printf("\tBR4\t0x%08X\tOR4\t0x%08X \n", in_be32(&lbc->br4), in_be32(&lbc->or4)); +	printf("\tBR5\t0x%08X\tOR5\t0x%08X \n", in_be32(&lbc->br5), in_be32(&lbc->or5)); +	printf("\tBR6\t0x%08X\tOR6\t0x%08X \n", in_be32(&lbc->br6), in_be32(&lbc->or6)); +	printf("\tBR7\t0x%08X\tOR7\t0x%08X \n", in_be32(&lbc->br7), in_be32(&lbc->or7)); + +} + +/* + * Set the DDR BATs to reflect the actual size of DDR. + * + * dram_size is the actual size of DDR, in bytes + * + * Note: we assume that CONFIG_MAX_MEM_MAPPED is 2G or smaller as we only + * are using a single BAT to cover DDR. + * + * If this is not true, (e.g. CONFIG_MAX_MEM_MAPPED is 2GB but HID0_XBSEN + * is not defined) then we might have a situation where U-Boot will attempt + * to relocated itself outside of the region mapped by DBAT0. + * This will cause a machine check. + * + * Currently we are limited to power of two sized DDR since we only use a + * single bat.  If a non-power of two size is used that is less than + * CONFIG_MAX_MEM_MAPPED u-boot will crash. + * + */ +void setup_ddr_bat(phys_addr_t dram_size) +{ +	unsigned long batu, bl; + +	bl = TO_BATU_BL(min(dram_size, CONFIG_MAX_MEM_MAPPED)); + +	if (BATU_SIZE(bl) != dram_size) { +		u64 sz = (u64)dram_size - BATU_SIZE(bl); +		print_size(sz, " left unmapped\n"); +	} + +	batu = bl | BATU_VS | BATU_VP; +	write_bat(DBAT0, batu, CONFIG_SYS_DBAT0L); +	write_bat(IBAT0, batu, CONFIG_SYS_IBAT0L); +} diff --git a/arch/powerpc/cpu/mpc86xx/cpu_init.c b/arch/powerpc/cpu/mpc86xx/cpu_init.c new file mode 100644 index 000000000..b4f047d85 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/cpu_init.c @@ -0,0 +1,190 @@ +/* + * Copyright 2004,2009 Freescale Semiconductor, Inc. + * Jeff Brown + * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * cpu_init.c - low level cpu init + */ + +#include <config.h> +#include <common.h> +#include <mpc86xx.h> +#include <asm/mmu.h> +#include <asm/fsl_law.h> +#include <asm/mp.h> + +void setup_bats(void); + +DECLARE_GLOBAL_DATA_PTR; + +/* + * Breathe some life into the CPU... + * + * Set up the memory map + * initialize a bunch of registers + */ + +void cpu_init_f(void) +{ +	volatile immap_t    *immap = (immap_t *)CONFIG_SYS_IMMR; +	volatile ccsr_lbc_t *memctl = &immap->im_lbc; + +	/* Pointer is writable since we allocated a register for it */ +	gd = (gd_t *) (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET); + +	/* Clear initial global data */ +	memset ((void *) gd, 0, sizeof (gd_t)); + +#ifdef CONFIG_FSL_LAW +	init_laws(); +#endif + +	setup_bats(); + +	/* Map banks 0 and 1 to the FLASH banks 0 and 1 at preliminary +	 * addresses - these have to be modified later when FLASH size +	 * has been determined +	 */ + +#if defined(CONFIG_SYS_OR0_REMAP) +	memctl->or0 = CONFIG_SYS_OR0_REMAP; +#endif +#if defined(CONFIG_SYS_OR1_REMAP) +	memctl->or1 = CONFIG_SYS_OR1_REMAP; +#endif + +	/* now restrict to preliminary range */ +#if defined(CONFIG_SYS_BR0_PRELIM) && defined(CONFIG_SYS_OR0_PRELIM) +	memctl->br0 = CONFIG_SYS_BR0_PRELIM; +	memctl->or0 = CONFIG_SYS_OR0_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR1_PRELIM) && defined(CONFIG_SYS_OR1_PRELIM) +	memctl->or1 = CONFIG_SYS_OR1_PRELIM; +	memctl->br1 = CONFIG_SYS_BR1_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR2_PRELIM) && defined(CONFIG_SYS_OR2_PRELIM) +	memctl->or2 = CONFIG_SYS_OR2_PRELIM; +	memctl->br2 = CONFIG_SYS_BR2_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR3_PRELIM) && defined(CONFIG_SYS_OR3_PRELIM) +	memctl->or3 = CONFIG_SYS_OR3_PRELIM; +	memctl->br3 = CONFIG_SYS_BR3_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR4_PRELIM) && defined(CONFIG_SYS_OR4_PRELIM) +	memctl->or4 = CONFIG_SYS_OR4_PRELIM; +	memctl->br4 = CONFIG_SYS_BR4_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR5_PRELIM) && defined(CONFIG_SYS_OR5_PRELIM) +	memctl->or5 = CONFIG_SYS_OR5_PRELIM; +	memctl->br5 = CONFIG_SYS_BR5_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR6_PRELIM) && defined(CONFIG_SYS_OR6_PRELIM) +	memctl->or6 = CONFIG_SYS_OR6_PRELIM; +	memctl->br6 = CONFIG_SYS_BR6_PRELIM; +#endif + +#if defined(CONFIG_SYS_BR7_PRELIM) && defined(CONFIG_SYS_OR7_PRELIM) +	memctl->or7 = CONFIG_SYS_OR7_PRELIM; +	memctl->br7 = CONFIG_SYS_BR7_PRELIM; +#endif +#if defined(CONFIG_FSL_DMA) +	dma_init(); +#endif + +	/* enable the timebase bit in HID0 */ +	set_hid0(get_hid0() | 0x4000000); + +	/* enable EMCP, SYNCBE | ABE bits in HID1 */ +	set_hid1(get_hid1() | 0x80000C00); +} + +/* + * initialize higher level parts of CPU like timers + */ +int cpu_init_r(void) +{ +#if defined(CONFIG_MP) +	setup_mp(); +#endif +	return 0; +} + +/* Set up BAT registers */ +void setup_bats(void) +{ +#if defined(CONFIG_SYS_DBAT0U) && defined(CONFIG_SYS_DBAT0L) +	write_bat(DBAT0, CONFIG_SYS_DBAT0U, CONFIG_SYS_DBAT0L); +#endif +#if defined(CONFIG_SYS_IBAT0U) && defined(CONFIG_SYS_IBAT0L) +	write_bat(IBAT0, CONFIG_SYS_IBAT0U, CONFIG_SYS_IBAT0L); +#endif +	write_bat(DBAT1, CONFIG_SYS_DBAT1U, CONFIG_SYS_DBAT1L); +	write_bat(IBAT1, CONFIG_SYS_IBAT1U, CONFIG_SYS_IBAT1L); +	write_bat(DBAT2, CONFIG_SYS_DBAT2U, CONFIG_SYS_DBAT2L); +	write_bat(IBAT2, CONFIG_SYS_IBAT2U, CONFIG_SYS_IBAT2L); +	write_bat(DBAT3, CONFIG_SYS_DBAT3U, CONFIG_SYS_DBAT3L); +	write_bat(IBAT3, CONFIG_SYS_IBAT3U, CONFIG_SYS_IBAT3L); +	write_bat(DBAT4, CONFIG_SYS_DBAT4U, CONFIG_SYS_DBAT4L); +	write_bat(IBAT4, CONFIG_SYS_IBAT4U, CONFIG_SYS_IBAT4L); +	write_bat(DBAT5, CONFIG_SYS_DBAT5U, CONFIG_SYS_DBAT5L); +	write_bat(IBAT5, CONFIG_SYS_IBAT5U, CONFIG_SYS_IBAT5L); +	write_bat(DBAT6, CONFIG_SYS_DBAT6U, CONFIG_SYS_DBAT6L); +	write_bat(IBAT6, CONFIG_SYS_IBAT6U, CONFIG_SYS_IBAT6L); +	write_bat(DBAT7, CONFIG_SYS_DBAT7U, CONFIG_SYS_DBAT7L); +	write_bat(IBAT7, CONFIG_SYS_IBAT7U, CONFIG_SYS_IBAT7L); + +	return; +} + +#ifdef CONFIG_ADDR_MAP +/* Initialize address mapping array */ +void init_addr_map(void) +{ +	int i; +	ppc_bat_t bat = DBAT0; +	phys_size_t size; +	unsigned long upper, lower; + +	for (i = 0; i < CONFIG_SYS_NUM_ADDR_MAP; i++, bat++) { +		if (read_bat(bat, &upper, &lower) != -1) { +			if (!BATU_VALID(upper)) +				size = 0; +			else +				size = BATU_SIZE(upper); +			addrmap_set_entry(BATU_VADDR(upper), BATL_PADDR(lower), +					  size, i); +		} +#ifdef CONFIG_HIGH_BATS +		/* High bats are not contiguous with low BAT numbers */ +		if (bat == DBAT3) +			bat = DBAT4 - 1; +#endif +	} +} +#endif diff --git a/arch/powerpc/cpu/mpc86xx/ddr-8641.c b/arch/powerpc/cpu/mpc86xx/ddr-8641.c new file mode 100644 index 000000000..b8f2c9387 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/ddr-8641.c @@ -0,0 +1,85 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include <common.h> +#include <asm/io.h> +#include <asm/fsl_ddr_sdram.h> + +#if (CONFIG_CHIP_SELECTS_PER_CTRL > 4) +#error Invalid setting for CONFIG_CHIP_SELECTS_PER_CTRL +#endif + +void fsl_ddr_set_memctl_regs(const fsl_ddr_cfg_regs_t *regs, +			     unsigned int ctrl_num) +{ +	unsigned int i; +	volatile ccsr_ddr_t *ddr; + +	switch (ctrl_num) { +	case 0: +		ddr = (void *)CONFIG_SYS_MPC86xx_DDR_ADDR; +		break; +	case 1: +		ddr = (void *)CONFIG_SYS_MPC86xx_DDR2_ADDR; +		break; +	default: +		printf("%s unexpected ctrl_num = %u\n", __FUNCTION__, ctrl_num); +		return; +	} + +	for (i = 0; i < CONFIG_CHIP_SELECTS_PER_CTRL; i++) { +		if (i == 0) { +			out_be32(&ddr->cs0_bnds, regs->cs[i].bnds); +			out_be32(&ddr->cs0_config, regs->cs[i].config); + +		} else if (i == 1) { +			out_be32(&ddr->cs1_bnds, regs->cs[i].bnds); +			out_be32(&ddr->cs1_config, regs->cs[i].config); + +		} else if (i == 2) { +			out_be32(&ddr->cs2_bnds, regs->cs[i].bnds); +			out_be32(&ddr->cs2_config, regs->cs[i].config); + +		} else if (i == 3) { +			out_be32(&ddr->cs3_bnds, regs->cs[i].bnds); +			out_be32(&ddr->cs3_config, regs->cs[i].config); +		} +	} + +	out_be32(&ddr->timing_cfg_3, regs->timing_cfg_3); +	out_be32(&ddr->timing_cfg_0, regs->timing_cfg_0); +	out_be32(&ddr->timing_cfg_1, regs->timing_cfg_1); +	out_be32(&ddr->timing_cfg_2, regs->timing_cfg_2); +	out_be32(&ddr->sdram_cfg_2, regs->ddr_sdram_cfg_2); +	out_be32(&ddr->sdram_mode, regs->ddr_sdram_mode); +	out_be32(&ddr->sdram_mode_2, regs->ddr_sdram_mode_2); +	out_be32(&ddr->sdram_mode_cntl, regs->ddr_sdram_md_cntl); +	out_be32(&ddr->sdram_interval, regs->ddr_sdram_interval); +	out_be32(&ddr->sdram_data_init, regs->ddr_data_init); +	out_be32(&ddr->sdram_clk_cntl, regs->ddr_sdram_clk_cntl); +	out_be32(&ddr->init_addr, regs->ddr_init_addr); +	out_be32(&ddr->init_ext_addr, regs->ddr_init_ext_addr); + +	debug("before go\n"); + +	/* +	 * 200 painful micro-seconds must elapse between +	 * the DDR clock setup and the DDR config enable. +	 */ +	udelay(200); +	asm volatile("sync;isync"); + +	out_be32(&ddr->sdram_cfg, regs->ddr_sdram_cfg); + +	/* +	 * Poll DDR_SDRAM_CFG_2[D_INIT] bit until auto-data init is done +	 */ +	while (in_be32(&ddr->sdram_cfg_2) & 0x10) { +		udelay(10000);		/* throttle polling rate */ +	} +} diff --git a/arch/powerpc/cpu/mpc86xx/fdt.c b/arch/powerpc/cpu/mpc86xx/fdt.c new file mode 100644 index 000000000..51f3f4c22 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/fdt.c @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * Version 2 as published by the Free Software Foundation. + */ + +#include <common.h> +#include <libfdt.h> +#include <fdt_support.h> +#include <asm/mp.h> + +DECLARE_GLOBAL_DATA_PTR; + +extern void ft_fixup_num_cores(void *blob); + +void ft_cpu_setup(void *blob, bd_t *bd) +{ +#ifdef CONFIG_MP +	int off; +	u32 bootpg = determine_mp_bootpg(); +#endif + +	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, +			     "timebase-frequency", bd->bi_busfreq / 4, 1); +	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, +			     "bus-frequency", bd->bi_busfreq, 1); +	do_fixup_by_prop_u32(blob, "device_type", "cpu", 4, +			     "clock-frequency", bd->bi_intfreq, 1); +	do_fixup_by_prop_u32(blob, "device_type", "soc", 4, +			     "bus-frequency", bd->bi_busfreq, 1); + +#if defined(CONFIG_MPC8641) +	do_fixup_by_compat_u32(blob, "fsl,mpc8641-localbus", +			       "bus-frequency", gd->lbc_clk, 1); +#endif +	do_fixup_by_compat_u32(blob, "fsl,elbc", +			       "bus-frequency", gd->lbc_clk, 1); + +	fdt_fixup_memory(blob, (u64)bd->bi_memstart, (u64)bd->bi_memsize); + +#if defined(CONFIG_HAS_ETH0) || defined(CONFIG_HAS_ETH1) \ +    || defined(CONFIG_HAS_ETH2) || defined(CONFIG_HAS_ETH3) +	fdt_fixup_ethernet(blob); +#endif + +#ifdef CONFIG_SYS_NS16550 +	do_fixup_by_compat_u32(blob, "ns16550", +			       "clock-frequency", CONFIG_SYS_NS16550_CLK, 1); +#endif + +#ifdef CONFIG_MP +	/* Reserve the boot page so OSes dont use it */ +	off = fdt_add_mem_rsv(blob, bootpg, (u64)4096); +	if (off < 0) +		printf("%s: %s\n", __FUNCTION__, fdt_strerror(off)); +#endif +	ft_fixup_num_cores(blob); +} diff --git a/arch/powerpc/cpu/mpc86xx/interrupts.c b/arch/powerpc/cpu/mpc86xx/interrupts.c new file mode 100644 index 000000000..c78fc7225 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/interrupts.c @@ -0,0 +1,115 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2002 (440 port) + * Scott McNutt, Artesyn Communication Producs, smcnutt@artsyncp.com + * + * (C) Copyright 2003 Motorola Inc. (MPC85xx port) + * Xianghua Xiao (X.Xiao@motorola.com) + * + * (C) Copyright 2004, 2007 Freescale Semiconductor. (MPC86xx Port) + * Jeff Brown + * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc86xx.h> +#include <command.h> +#include <asm/processor.h> + +int interrupt_init_cpu(unsigned long *decrementer_count) +{ +	volatile immap_t *immr = (immap_t *)CONFIG_SYS_IMMR; +	volatile ccsr_pic_t *pic = &immr->im_pic; + +	pic->gcr = MPC86xx_PICGCR_RST; +	while (pic->gcr & MPC86xx_PICGCR_RST) +		; +	pic->gcr = MPC86xx_PICGCR_MODE; + +	*decrementer_count = get_tbclk() / CONFIG_SYS_HZ; +	debug("interrupt init: tbclk() = %d MHz, decrementer_count = %ld\n", +	      (get_tbclk() / 1000000), +	      *decrementer_count); + +#ifdef CONFIG_INTERRUPTS + +	pic->iivpr1 = 0x810001;	/* 50220 enable mcm interrupts */ +	debug("iivpr1@%x = %x\n", &pic->iivpr1, pic->iivpr1); + +	pic->iivpr2 = 0x810002;	/* 50240 enable ddr interrupts */ +	debug("iivpr2@%x = %x\n", &pic->iivpr2, pic->iivpr2); + +	pic->iivpr3 = 0x810003;	/* 50260 enable lbc interrupts */ +	debug("iivpr3@%x = %x\n", &pic->iivpr3, pic->iivpr3); + +#if defined(CONFIG_PCI1) || defined(CONFIG_PCIE1) +	pic->iivpr8 = 0x810008;	/* enable pcie1 interrupts */ +	debug("iivpr8@%x = %x\n", &pic->iivpr8, pic->iivpr8); +#endif +#if defined(CONFIG_PCI2) || defined(CONFIG_PCIE2) +	pic->iivpr9 = 0x810009;	/* enable pcie2 interrupts */ +	debug("iivpr9@%x = %x\n", &pic->iivpr9, pic->iivpr9); +#endif + +	pic->ctpr = 0;	/* 40080 clear current task priority register */ +#endif + +	return 0; +} + +/* + * timer_interrupt - gets called when the decrementer overflows, + * with interrupts disabled. + * Trivial implementation - no need to be really accurate. + */ +void timer_interrupt_cpu(struct pt_regs *regs) +{ +	/* nothing to do here */ +} + +/* + * Install and free a interrupt handler. Not implemented yet. + */ +void irq_install_handler(int vec, interrupt_handler_t *handler, void *arg) +{ +} + +void irq_free_handler(int vec) +{ +} + +/* + * irqinfo - print information about PCI devices,not implemented. + */ +int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	return 0; +} + +/* + * Handle external interrupts + */ +void external_interrupt(struct pt_regs *regs) +{ +	puts("external_interrupt (oops!)\n"); +} diff --git a/arch/powerpc/cpu/mpc86xx/mp.c b/arch/powerpc/cpu/mpc86xx/mp.c new file mode 100644 index 000000000..b4a0faacd --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/mp.c @@ -0,0 +1,125 @@ +/* + * Copyright 2008-2010 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <asm/mmu.h> +#include <ioports.h> +#include <lmb.h> +#include <asm/io.h> +#include <asm/mp.h> + +DECLARE_GLOBAL_DATA_PTR; + +int cpu_reset(int nr) +{ +	/* dummy function so common/cmd_mp.c will build +	 * should be implemented in the future, when cpu_release() +	 * is supported.  Be aware there may be a similiar bug +	 * as exists on MPC85xx w/its PIC having a timing window +	 * associated to resetting the core */ +	return 1; +} + +int cpu_status(int nr) +{ +	/* dummy function so common/cmd_mp.c will build */ +	return 0; +} + +int cpu_disable(int nr) +{ +	volatile immap_t *immap = (immap_t *) CONFIG_SYS_CCSRBAR; +	volatile ccsr_gur_t *gur = &immap->im_gur; + +	switch (nr) { +	case 0: +		setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU0); +		break; +	case 1: +		setbits_be32(&gur->devdisr, MPC86xx_DEVDISR_CPU1); +		break; +	default: +		printf("Invalid cpu number for disable %d\n", nr); +		return 1; +	} + +	return 0; +} + +int cpu_release(int nr, int argc, char *argv[]) +{ +	/* dummy function so common/cmd_mp.c will build +	 * should be implemented in the future */ +	return 1; +} + +u32 determine_mp_bootpg(void) +{ +	/* if we have 4G or more of memory, put the boot page at 4Gb-1M */ +	if ((u64)gd->ram_size > 0xfffff000) +		return (0xfff00000); + +	return (gd->ram_size - (1024 * 1024)); +} + +void cpu_mp_lmb_reserve(struct lmb *lmb) +{ +	u32 bootpg = determine_mp_bootpg(); + +	/* tell u-boot we stole a page */ +	lmb_reserve(lmb, bootpg, 4096); +} + +/* + * Copy the code for other cpus to execute into an + * aligned location accessible via BPTR + */ +void setup_mp(void) +{ +	extern ulong __secondary_start_page; +	ulong fixup = (ulong)&__secondary_start_page; +	u32 bootpg = determine_mp_bootpg(); +	u32 bootpg_va; + +	if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE) { +		/* We're not covered by the DDR mapping, set up BAT  */ +		write_bat(DBAT7, CONFIG_SYS_SCRATCH_VA | BATU_BL_128K | +			  BATU_VS | BATU_VP, +			  bootpg | BATL_PP_RW | BATL_MEMCOHERENCE); +		bootpg_va = CONFIG_SYS_SCRATCH_VA; +	} else { +		bootpg_va = bootpg; +	} + +	memcpy((void *)bootpg_va, (void *)fixup, 4096); +	flush_cache(bootpg_va, 4096); + +	/* remove the temporary BAT mapping */ +	if (bootpg >= CONFIG_SYS_MAX_DDR_BAT_SIZE) +		write_bat(DBAT7, 0, 0); + +	/* If the physical location of bootpg is not at fff00000, set BPTR */ +	if (bootpg != 0xfff00000) +		out_be32((uint *)(CONFIG_SYS_CCSRBAR + 0x20), 0x80000000 | +			 (bootpg >> 12)); +} diff --git a/arch/powerpc/cpu/mpc86xx/release.S b/arch/powerpc/cpu/mpc86xx/release.S new file mode 100644 index 000000000..67a6f2bdb --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/release.S @@ -0,0 +1,167 @@ +/* + * Copyright 2004, 2007, 2008 Freescale Semiconductor. + * Srikanth Srinivasan <srikanth.srinivaan@freescale.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include <config.h> +#include <mpc86xx.h> +#include <version.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +/* If this is a multi-cpu system then we need to handle the + * 2nd cpu.  The assumption is that the 2nd cpu is being + * held in boot holdoff mode until the 1st cpu unlocks it + * from Linux.	We'll do some basic cpu init and then pass + * it to the Linux Reset Vector. + * Sri:	 Much of this initialization is not required. Linux + * rewrites the bats, and the sprs and also enables the L1 cache. + * + * Core 0 must copy this to a 1M aligned region and set BPTR + * to point to it. + */ +	.align 12 +.globl __secondary_start_page +__secondary_start_page: +	.space 0x100	/* space over to reset vector loc */ +	mfspr	r0, MSSCR0 +	andi.	r0, r0, 0x0020 +	rlwinm	r0,r0,27,31,31 +	mtspr	PIR, r0 + +	/* Invalidate BATs */ +	li	r0, 0 +	mtspr	IBAT0U, r0 +	mtspr	IBAT1U, r0 +	mtspr	IBAT2U, r0 +	mtspr	IBAT3U, r0 +	mtspr	IBAT4U, r0 +	mtspr	IBAT5U, r0 +	mtspr	IBAT6U, r0 +	mtspr	IBAT7U, r0 +	isync +	mtspr	DBAT0U, r0 +	mtspr	DBAT1U, r0 +	mtspr	DBAT2U, r0 +	mtspr	DBAT3U, r0 +	mtspr	DBAT4U, r0 +	mtspr	DBAT5U, r0 +	mtspr	DBAT6U, r0 +	mtspr	DBAT7U, r0 +	isync +	sync + +	/* enable extended addressing */ +	mfspr	r0, HID0 +	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h +	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l +	mtspr	HID0, r0 +	sync +	isync + +#ifdef CONFIG_SYS_L2 +	/* init the L2 cache */ +	addis	r3, r0, L2_INIT@h +	ori	r3, r3, L2_INIT@l +	sync +	mtspr	l2cr, r3 +#ifdef CONFIG_ALTIVEC +	dssall +#endif +	/* invalidate the L2 cache */ +	mfspr	r3, l2cr +	rlwinm.	r3, r3, 0, 0, 0 +	beq	1f + +	mfspr	r3, l2cr +	rlwinm	r3, r3, 0, 1, 31 + +#ifdef	CONFIG_ALTIVEC +	dssall +#endif +	sync +	mtspr	l2cr, r3 +	sync +1:	mfspr	r3, l2cr +	oris	r3, r3, L2CR_L2I@h +	mtspr	l2cr, r3 + +invl2: +	mfspr	r3, l2cr +	andis.	r3, r3, L2CR_L2I@h +	bne	invl2 +	sync +#endif + +	/* enable and invalidate the data cache */ +	mfspr	r3, HID0 +	li	r5, HID0_DCFI|HID0_DLOCK +	andc	r3, r3, r5 +	mtspr	HID0, r3		/* no invalidate, unlock */ +	ori	r3, r3, HID0_DCE +	ori	r5, r3, HID0_DCFI +	mtspr	HID0, r5		/* enable + invalidate */ +	mtspr	HID0, r3		/* enable */ +	sync +#ifdef CONFIG_SYS_L2 +	sync +	lis	r3, L2_ENABLE@h +	ori	r3, r3, L2_ENABLE@l +	mtspr	l2cr, r3 +	isync +	sync +#endif + +	/* enable and invalidate the instruction cache*/ +	mfspr	r3, HID0 +	li	r5, HID0_ICFI|HID0_ILOCK +	andc	r3, r3, r5 +	ori	r3, r3, HID0_ICE +	ori	r5, r3, HID0_ICFI +	mtspr	HID0, r5 +	mtspr	HID0, r3 +	isync +	sync + +	/* TBEN in HID0 */ +	mfspr	r4, HID0 +	oris	r4, r4, 0x0400 +	mtspr	HID0, r4 +	sync +	isync + +	/* MCP|SYNCBE|ABE in HID1 */ +	mfspr	r4, HID1 +	oris	r4, r4, 0x8000 +	ori	r4, r4, 0x0C00 +	mtspr	HID1, r4 +	sync +	isync + +	lis	r3, CONFIG_LINUX_RESET_VEC@h +	ori	r3, r3, CONFIG_LINUX_RESET_VEC@l +	mtlr	r3 +	blr + +	/* Never Returns, Running in Linux Now */ diff --git a/arch/powerpc/cpu/mpc86xx/speed.c b/arch/powerpc/cpu/mpc86xx/speed.c new file mode 100644 index 000000000..64a3479d7 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/speed.c @@ -0,0 +1,163 @@ +/* + * Copyright 2004 Freescale Semiconductor. + * Jeff Brown + * Srikanth Srinivasan (srikanth.srinivasan@freescale.com) + * + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <mpc86xx.h> +#include <asm/processor.h> +#include <asm/io.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* used in some defintiions of CONFIG_SYS_CLK_FREQ */ +extern unsigned long get_board_sys_clk(unsigned long dummy); + +void get_sys_info(sys_info_t *sysInfo) +{ +	volatile immap_t *immap = (immap_t *) CONFIG_SYS_IMMR; +	volatile ccsr_gur_t *gur = &immap->im_gur; +	uint plat_ratio, e600_ratio; +	uint lcrr_div; + +	plat_ratio = (gur->porpllsr) & 0x0000003e; +	plat_ratio >>= 1; + +	switch (plat_ratio) { +	case 0x0: +		sysInfo->freqSystemBus = 16 * CONFIG_SYS_CLK_FREQ; +		break; +	case 0x02: +	case 0x03: +	case 0x04: +	case 0x05: +	case 0x06: +	case 0x08: +	case 0x09: +	case 0x0a: +	case 0x0c: +	case 0x10: +		sysInfo->freqSystemBus = plat_ratio * CONFIG_SYS_CLK_FREQ; +		break; +	default: +		sysInfo->freqSystemBus = 0; +		break; +	} + +	e600_ratio = (gur->porpllsr) & 0x003f0000; +	e600_ratio >>= 16; + +	switch (e600_ratio) { +	case 0x10: +		sysInfo->freqProcessor = 2 * sysInfo->freqSystemBus; +		break; +	case 0x19: +		sysInfo->freqProcessor = 5 * sysInfo->freqSystemBus / 2; +		break; +	case 0x20: +		sysInfo->freqProcessor = 3 * sysInfo->freqSystemBus; +		break; +	case 0x39: +		sysInfo->freqProcessor = 7 * sysInfo->freqSystemBus / 2; +		break; +	case 0x28: +		sysInfo->freqProcessor = 4 * sysInfo->freqSystemBus; +		break; +	case 0x1d: +		sysInfo->freqProcessor = 9 * sysInfo->freqSystemBus / 2; +		break; +	default: +		sysInfo->freqProcessor = e600_ratio + sysInfo->freqSystemBus; +		break; +	} + +#if defined(CONFIG_SYS_LBC_LCRR) +	/* We will program LCRR to this value later */ +	lcrr_div = CONFIG_SYS_LBC_LCRR & LCRR_CLKDIV; +#else +	{ +		volatile ccsr_lbc_t *lbc = &immap->im_lbc; +		lcrr_div = in_be32(&lbc->lcrr) & LCRR_CLKDIV; +	} +#endif +	if (lcrr_div == 2 || lcrr_div == 4 || lcrr_div == 8) { +		sysInfo->freqLocalBus = sysInfo->freqSystemBus / (lcrr_div * 2); +	} else { +		/* In case anyone cares what the unknown value is */ +		sysInfo->freqLocalBus = lcrr_div; +	} +} + + +/* + * Measure CPU clock speed (core clock GCLK1, GCLK2) + * (Approx. GCLK frequency in Hz) + */ + +int get_clocks(void) +{ +	sys_info_t sys_info; + +	get_sys_info(&sys_info); +	gd->cpu_clk = sys_info.freqProcessor; +	gd->bus_clk = sys_info.freqSystemBus; +	gd->lbc_clk = sys_info.freqLocalBus; + +	/* +	 * The base clock for I2C depends on the actual SOC.  Unfortunately, +	 * there is no pattern that can be used to determine the frequency, so +	 * the only choice is to look up the actual SOC number and use the value +	 * for that SOC. This information is taken from application note +	 * AN2919. +	 */ +#ifdef CONFIG_MPC8610 +	gd->i2c1_clk = sys_info.freqSystemBus; +#else +	gd->i2c1_clk = sys_info.freqSystemBus / 2; +#endif +	gd->i2c2_clk = gd->i2c1_clk; + +	if (gd->cpu_clk != 0) +		return 0; +	else +		return 1; +} + + +/* + * get_bus_freq + *	Return system bus freq in Hz + */ + +ulong get_bus_freq(ulong dummy) +{ +	ulong val; +	sys_info_t sys_info; + +	get_sys_info(&sys_info); +	val = sys_info.freqSystemBus; + +	return val; +} diff --git a/arch/powerpc/cpu/mpc86xx/start.S b/arch/powerpc/cpu/mpc86xx/start.S new file mode 100644 index 000000000..ed1e4ca66 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/start.S @@ -0,0 +1,957 @@ +/* + * Copyright 2004, 2007 Freescale Semiconductor. + * Srikanth Srinivasan <srikanth.srinivaan@freescale.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/*  U-Boot - Startup Code for 86xx PowerPC based Embedded Boards + * + * + *  The processor starts at 0xfff00100 and the code is executed + *  from flash. The code is organized to be at an other address + *  in memory, but as long we don't jump around before relocating. + *  board_init lies at a quite high address and when the cpu has + *  jumped there, everything is ok. + */ +#include <config.h> +#include <mpc86xx.h> +#include <timestamp.h> +#include <version.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> + +#include <asm/cache.h> +#include <asm/mmu.h> + +#ifndef	CONFIG_IDENT_STRING +#define CONFIG_IDENT_STRING "" +#endif + +/* + * Need MSR_DR | MSR_IR enabled to access I/O (printf) in exceptions + */ + +/* + * Set up GOT: Global Offset Table + * + * Use r12 to access the GOT + */ +	START_GOT +	GOT_ENTRY(_GOT2_TABLE_) +	GOT_ENTRY(_FIXUP_TABLE_) + +	GOT_ENTRY(_start) +	GOT_ENTRY(_start_of_vectors) +	GOT_ENTRY(_end_of_vectors) +	GOT_ENTRY(transfer_to_handler) + +	GOT_ENTRY(__init_end) +	GOT_ENTRY(_end) +	GOT_ENTRY(__bss_start) +	END_GOT + +/* + * r3 - 1st arg to board_init(): IMMP pointer + * r4 - 2nd arg to board_init(): boot flag + */ +	.text +	.long	0x27051956		/* U-Boot Magic Number */ +	.globl	version_string +version_string: +	.ascii	U_BOOT_VERSION +	.ascii	" (", U_BOOT_DATE, " - ", U_BOOT_TIME, ")" +	.ascii	CONFIG_IDENT_STRING, "\0" + +	. = EXC_OFF_SYS_RESET +	.globl	_start +_start: +	li	r21, BOOTFLAG_COLD	/* Normal Power-On: Boot from FLASH */ +	b	boot_cold +	sync + +	. = EXC_OFF_SYS_RESET + 0x10 + +	.globl	_start_warm +_start_warm: +	li	r21, BOOTFLAG_WARM	/* Software reboot */ +	b	boot_warm +	sync + +	/* the boot code is located below the exception table */ + +	.globl	_start_of_vectors +_start_of_vectors: + +/* Machine check */ +	STD_EXCEPTION(0x200, MachineCheck, MachineCheckException) + +/* Data Storage exception. */ +	STD_EXCEPTION(0x300, DataStorage, UnknownException) + +/* Instruction Storage exception. */ +	STD_EXCEPTION(0x400, InstStorage, UnknownException) + +/* External Interrupt exception. */ +	STD_EXCEPTION(0x500, ExtInterrupt, external_interrupt) + +/* Alignment exception. */ +	. = 0x600 +Alignment: +	EXCEPTION_PROLOG(SRR0, SRR1) +	mfspr	r4,DAR +	stw	r4,_DAR(r21) +	mfspr	r5,DSISR +	stw	r5,_DSISR(r21) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	EXC_XFER_TEMPLATE(Alignment, AlignmentException, MSR_KERNEL, COPY_EE) + +/* Program check exception */ +	. = 0x700 +ProgramCheck: +	EXCEPTION_PROLOG(SRR0, SRR1) +	addi	r3,r1,STACK_FRAME_OVERHEAD +	EXC_XFER_TEMPLATE(ProgramCheck, ProgramCheckException, +		MSR_KERNEL, COPY_EE) + +	STD_EXCEPTION(0x800, FPUnavailable, UnknownException) + +	/* I guess we could implement decrementer, and may have +	 * to someday for timekeeping. +	 */ +	STD_EXCEPTION(0x900, Decrementer, timer_interrupt) +	STD_EXCEPTION(0xa00, Trap_0a, UnknownException) +	STD_EXCEPTION(0xb00, Trap_0b, UnknownException) +	STD_EXCEPTION(0xc00, SystemCall, UnknownException) +	STD_EXCEPTION(0xd00, SingleStep, UnknownException) +	STD_EXCEPTION(0xe00, Trap_0e, UnknownException) +	STD_EXCEPTION(0xf00, Trap_0f, UnknownException) +	STD_EXCEPTION(0x1000, SoftEmu, SoftEmuException) +	STD_EXCEPTION(0x1100, InstructionTLBMiss, UnknownException) +	STD_EXCEPTION(0x1200, DataTLBMiss, UnknownException) +	STD_EXCEPTION(0x1300, InstructionTLBError, UnknownException) +	STD_EXCEPTION(0x1400, DataTLBError, UnknownException) +	STD_EXCEPTION(0x1500, Reserved5, UnknownException) +	STD_EXCEPTION(0x1600, Reserved6, UnknownException) +	STD_EXCEPTION(0x1700, Reserved7, UnknownException) +	STD_EXCEPTION(0x1800, Reserved8, UnknownException) +	STD_EXCEPTION(0x1900, Reserved9, UnknownException) +	STD_EXCEPTION(0x1a00, ReservedA, UnknownException) +	STD_EXCEPTION(0x1b00, ReservedB, UnknownException) +	STD_EXCEPTION(0x1c00, DataBreakpoint, UnknownException) +	STD_EXCEPTION(0x1d00, InstructionBreakpoint, UnknownException) +	STD_EXCEPTION(0x1e00, PeripheralBreakpoint, UnknownException) +	STD_EXCEPTION(0x1f00, DevPortBreakpoint, UnknownException) + +	.globl	_end_of_vectors +_end_of_vectors: + +	. = 0x2000 + +boot_cold: +boot_warm: +	/* +	 * NOTE: Only Cpu 0 will ever come here.  Other cores go to an +	 * address specified by the BPTR +	 */ +1: +#ifdef CONFIG_SYS_RAMBOOT +	/* disable everything */ +	li	r0, 0 +	mtspr	HID0, r0 +	sync +	mtmsr	0 +#endif + +	/* Invalidate BATs */ +	bl	invalidate_bats +	sync +	/* Invalidate all of TLB before MMU turn on */ +	bl      clear_tlbs +	sync + +#ifdef CONFIG_SYS_L2 +	/* init the L2 cache */ +	lis	r3, L2_INIT@h +	ori	r3, r3, L2_INIT@l +	mtspr	l2cr, r3 +	/* invalidate the L2 cache */ +	bl	l2cache_invalidate +	sync +#endif + +	/* +	 * Calculate absolute address in FLASH and jump there +	 *------------------------------------------------------*/ +	lis	r3, CONFIG_SYS_MONITOR_BASE_EARLY@h +	ori	r3, r3, CONFIG_SYS_MONITOR_BASE_EARLY@l +	addi	r3, r3, in_flash - _start + EXC_OFF_SYS_RESET +	mtlr	r3 +	blr + +in_flash: +	/* let the C-code set up the rest			*/ +	/*							*/ +	/* Be careful to keep code relocatable !		*/ +	/*------------------------------------------------------*/ +	/* perform low-level init */ + +	/* enable extended addressing */ +	bl	enable_ext_addr + +	/* setup the bats */ +	bl	early_bats + +	/* +	 * Cache must be enabled here for stack-in-cache trick. +	 * This means we need to enable the BATS. +	 * Cache should be turned on after BATs, since by default +	 * everything is write-through. +	 */ + +	/* enable address translation */ +	mfmsr	r5 +	ori	r5, r5, (MSR_IR | MSR_DR) +	lis	r3,addr_trans_enabled@h +	ori	r3, r3, addr_trans_enabled@l +	mtspr	SPRN_SRR0,r3 +	mtspr	SPRN_SRR1,r5 +	rfi + +addr_trans_enabled: +	/* enable and invalidate the data cache */ +/*	bl	l1dcache_enable */ +	bl	dcache_enable +	sync + +#if 1 +	bl	icache_enable +#endif + +#ifdef CONFIG_SYS_INIT_RAM_LOCK +	bl	lock_ram_in_cache +	sync +#endif + +#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR) +	bl      setup_ccsrbar +#endif + +	/* set up the stack pointer in our newly created +	 * cache-ram (r1) */ +	lis	r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@h +	ori	r1, r1, (CONFIG_SYS_INIT_RAM_ADDR + CONFIG_SYS_GBL_DATA_OFFSET)@l + +	li	r0, 0		/* Make room for stack frame header and */ +	stwu	r0, -4(r1)	/* clear final stack frame so that	*/ +	stwu	r0, -4(r1)	/* stack backtraces terminate cleanly	*/ + +	GET_GOT			/* initialize GOT access	*/ + +	/* run low-level CPU init code	   (from Flash) */ +	bl	cpu_init_f +	sync + +#ifdef	RUN_DIAG + +	/* Load PX_AUX register address in r4 */ +	lis	r4, PIXIS_BASE@h +	ori	r4, r4, 0x6 +	/* Load contents of PX_AUX in r3 bits 24 to 31*/ +	lbz	r3, 0(r4) + +	/* Mask and obtain the bit in r3 */ +	rlwinm. r3, r3, 0, 24, 24 +	/* If not zero, jump and continue with u-boot */ +	bne	diag_done + +	/* Load back contents of PX_AUX in r3 bits 24 to 31 */ +	lbz	r3, 0(r4) +	/* Set the MSB of the register value */ +	ori	r3, r3, 0x80 +	/* Write value in r3 back to PX_AUX */ +	stb	r3, 0(r4) + +	/* Get the address to jump to in r3*/ +	lis	r3, CONFIG_SYS_DIAG_ADDR@h +	ori	r3, r3, CONFIG_SYS_DIAG_ADDR@l + +	/* Load the LR with the branch address */ +	mtlr	r3 + +	/* Branch to diagnostic */ +	blr + +diag_done: +#endif + +/*	bl	l2cache_enable */ +	mr	r3, r21 + +	/* r3: BOOTFLAG */ +	/* run 1st part of board init code (from Flash)	  */ +	bl	board_init_f +	sync + +	/* NOTREACHED */ + +	.globl	invalidate_bats +invalidate_bats: + +	li	r0, 0 +	/* invalidate BATs */ +	mtspr	IBAT0U, r0 +	mtspr	IBAT1U, r0 +	mtspr	IBAT2U, r0 +	mtspr	IBAT3U, r0 +	mtspr	IBAT4U, r0 +	mtspr	IBAT5U, r0 +	mtspr	IBAT6U, r0 +	mtspr	IBAT7U, r0 + +	isync +	mtspr	DBAT0U, r0 +	mtspr	DBAT1U, r0 +	mtspr	DBAT2U, r0 +	mtspr	DBAT3U, r0 +	mtspr	DBAT4U, r0 +	mtspr	DBAT5U, r0 +	mtspr	DBAT6U, r0 +	mtspr	DBAT7U, r0 + +	isync +	sync +	blr + +/* + * early_bats: + * + * Set up bats needed early on - this is usually the BAT for the + * stack-in-cache, the Flash, and CCSR space + */ +	.globl  early_bats +early_bats: +	/* IBAT 3 */ +	lis	r4, CONFIG_SYS_IBAT3L@h +	ori     r4, r4, CONFIG_SYS_IBAT3L@l +	lis	r3, CONFIG_SYS_IBAT3U@h +	ori     r3, r3, CONFIG_SYS_IBAT3U@l +	mtspr   IBAT3L, r4 +	mtspr   IBAT3U, r3 +	isync + +	/* DBAT 3 */ +	lis	r4, CONFIG_SYS_DBAT3L@h +	ori     r4, r4, CONFIG_SYS_DBAT3L@l +	lis	r3, CONFIG_SYS_DBAT3U@h +	ori     r3, r3, CONFIG_SYS_DBAT3U@l +	mtspr   DBAT3L, r4 +	mtspr   DBAT3U, r3 +	isync + +	/* IBAT 5 */ +	lis	r4, CONFIG_SYS_IBAT5L@h +	ori     r4, r4, CONFIG_SYS_IBAT5L@l +	lis	r3, CONFIG_SYS_IBAT5U@h +	ori     r3, r3, CONFIG_SYS_IBAT5U@l +	mtspr   IBAT5L, r4 +	mtspr   IBAT5U, r3 +	isync + +	/* DBAT 5 */ +	lis	r4, CONFIG_SYS_DBAT5L@h +	ori     r4, r4, CONFIG_SYS_DBAT5L@l +	lis	r3, CONFIG_SYS_DBAT5U@h +	ori     r3, r3, CONFIG_SYS_DBAT5U@l +	mtspr   DBAT5L, r4 +	mtspr   DBAT5U, r3 +	isync + +	/* IBAT 6 */ +	lis	r4, CONFIG_SYS_IBAT6L_EARLY@h +	ori     r4, r4, CONFIG_SYS_IBAT6L_EARLY@l +	lis	r3, CONFIG_SYS_IBAT6U_EARLY@h +	ori     r3, r3, CONFIG_SYS_IBAT6U_EARLY@l +	mtspr   IBAT6L, r4 +	mtspr   IBAT6U, r3 +	isync + +	/* DBAT 6 */ +	lis	r4, CONFIG_SYS_DBAT6L_EARLY@h +	ori     r4, r4, CONFIG_SYS_DBAT6L_EARLY@l +	lis	r3, CONFIG_SYS_DBAT6U_EARLY@h +	ori     r3, r3, CONFIG_SYS_DBAT6U_EARLY@l +	mtspr   DBAT6L, r4 +	mtspr   DBAT6U, r3 +	isync + +#if(CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR) +	/* IBAT 7 */ +	lis	r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@h +	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_IBATL@l +	lis	r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@h +	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_IBATU@l +	mtspr   IBAT7L, r4 +	mtspr   IBAT7U, r3 +	isync + +	/* DBAT 7 */ +	lis	r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@h +	ori     r4, r4, CONFIG_SYS_CCSR_DEFAULT_DBATL@l +	lis	r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@h +	ori     r3, r3, CONFIG_SYS_CCSR_DEFAULT_DBATU@l +	mtspr   DBAT7L, r4 +	mtspr   DBAT7U, r3 +	isync +#endif +	blr + +	.globl clear_tlbs +clear_tlbs: +	addis   r3, 0, 0x0000 +	addis   r5, 0, 0x4 +	isync +tlblp: +	tlbie   r3 +	sync +	addi    r3, r3, 0x1000 +	cmp     0, 0, r3, r5 +	blt tlblp +	blr + +	.globl disable_addr_trans +disable_addr_trans: +	/* disable address translation */ +	mflr	r4 +	mfmsr	r3 +	andi.	r0, r3, (MSR_IR | MSR_DR) +	beqlr +	andc	r3, r3, r0 +	mtspr	SRR0, r4 +	mtspr	SRR1, r3 +	rfi + +/* + * This code finishes saving the registers to the exception frame + * and jumps to the appropriate handler for the exception. + * Register r21 is pointer into trap frame, r1 has new stack pointer. + */ +	.globl	transfer_to_handler +transfer_to_handler: +	stw	r22,_NIP(r21) +	lis	r22,MSR_POW@h +	andc	r23,r23,r22 +	stw	r23,_MSR(r21) +	SAVE_GPR(7, r21) +	SAVE_4GPRS(8, r21) +	SAVE_8GPRS(12, r21) +	SAVE_8GPRS(24, r21) +	mflr	r23 +	andi.	r24,r23,0x3f00		/* get vector offset */ +	stw	r24,TRAP(r21) +	li	r22,0 +	stw	r22,RESULT(r21) +	mtspr	SPRG2,r22		/* r1 is now kernel sp */ +	lwz	r24,0(r23)		/* virtual address of handler */ +	lwz	r23,4(r23)		/* where to go when done */ +	mtspr	SRR0,r24 +	mtspr	SRR1,r20 +	mtlr	r23 +	SYNC +	rfi				/* jump to handler, enable MMU */ + +int_return: +	mfmsr	r28		/* Disable interrupts */ +	li	r4,0 +	ori	r4,r4,MSR_EE +	andc	r28,r28,r4 +	SYNC			/* Some chip revs need this... */ +	mtmsr	r28 +	SYNC +	lwz	r2,_CTR(r1) +	lwz	r0,_LINK(r1) +	mtctr	r2 +	mtlr	r0 +	lwz	r2,_XER(r1) +	lwz	r0,_CCR(r1) +	mtspr	XER,r2 +	mtcrf	0xFF,r0 +	REST_10GPRS(3, r1) +	REST_10GPRS(13, r1) +	REST_8GPRS(23, r1) +	REST_GPR(31, r1) +	lwz	r2,_NIP(r1)	/* Restore environment */ +	lwz	r0,_MSR(r1) +	mtspr	SRR0,r2 +	mtspr	SRR1,r0 +	lwz	r0,GPR0(r1) +	lwz	r2,GPR2(r1) +	lwz	r1,GPR1(r1) +	SYNC +	rfi + +	.globl	dc_read +dc_read: +	blr + +	.globl get_pvr +get_pvr: +	mfspr	r3, PVR +	blr + +	.globl get_svr +get_svr: +	mfspr	r3, SVR +	blr + + +/* + * Function:	in8 + * Description:	Input 8 bits + */ +	.globl	in8 +in8: +	lbz	r3,0x0000(r3) +	blr + +/* + * Function:	out8 + * Description:	Output 8 bits + */ +	.globl	out8 +out8: +	stb	r4,0x0000(r3) +	blr + +/* + * Function:	out16 + * Description:	Output 16 bits + */ +	.globl	out16 +out16: +	sth	r4,0x0000(r3) +	blr + +/* + * Function:	out16r + * Description:	Byte reverse and output 16 bits + */ +	.globl	out16r +out16r: +	sthbrx	r4,r0,r3 +	blr + +/* + * Function:	out32 + * Description:	Output 32 bits + */ +	.globl	out32 +out32: +	stw	r4,0x0000(r3) +	blr + +/* + * Function:	out32r + * Description:	Byte reverse and output 32 bits + */ +	.globl	out32r +out32r: +	stwbrx	r4,r0,r3 +	blr + +/* + * Function:	in16 + * Description:	Input 16 bits + */ +	.globl	in16 +in16: +	lhz	r3,0x0000(r3) +	blr + +/* + * Function:	in16r + * Description:	Input 16 bits and byte reverse + */ +	.globl	in16r +in16r: +	lhbrx	r3,r0,r3 +	blr + +/* + * Function:	in32 + * Description:	Input 32 bits + */ +	.globl	in32 +in32: +	lwz	3,0x0000(3) +	blr + +/* + * Function:	in32r + * Description:	Input 32 bits and byte reverse + */ +	.globl	in32r +in32r: +	lwbrx	r3,r0,r3 +	blr + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * r3 = dest + * r4 = src + * r5 = length in bytes + * r6 = cachelinesize + */ +	.globl	relocate_code +relocate_code: + +	mr	r1,  r3		/* Set new stack pointer		*/ +	mr	r9,  r4		/* Save copy of Global Data pointer	*/ +	mr	r10, r5		/* Save copy of Destination Address	*/ + +	GET_GOT +	mr	r3,  r5				/* Destination Address	*/ +	lis	r4, CONFIG_SYS_MONITOR_BASE@h		/* Source      Address	*/ +	ori	r4, r4, CONFIG_SYS_MONITOR_BASE@l +	lwz	r5, GOT(__init_end) +	sub	r5, r5, r4 +	li	r6, CONFIG_SYS_CACHELINE_SIZE		/* Cache Line Size	*/ + +	/* +	 * Fix GOT pointer: +	 * +	 * New GOT-PTR = (old GOT-PTR - CONFIG_SYS_MONITOR_BASE) + Destination Address +	 * +	 * Offset: +	 */ +	sub	r15, r10, r4 + +	/* First our own GOT */ +	add	r12, r12, r15 +	/* then the one used by the C code */ +	add	r30, r30, r15 + +	/* +	 * Now relocate code +	 */ +	cmplw	cr1,r3,r4 +	addi	r0,r5,3 +	srwi.	r0,r0,2 +	beq	cr1,4f		/* In place copy is not necessary	*/ +	beq	7f		/* Protect against 0 count		*/ +	mtctr	r0 +	bge	cr1,2f + +	la	r8,-4(r4) +	la	r7,-4(r3) +1:	lwzu	r0,4(r8) +	stwu	r0,4(r7) +	bdnz	1b +	b	4f + +2:	slwi	r0,r0,2 +	add	r8,r4,r0 +	add	r7,r3,r0 +3:	lwzu	r0,-4(r8) +	stwu	r0,-4(r7) +	bdnz	3b +/* + * Now flush the cache: note that we must start from a cache aligned + * address. Otherwise we might miss one cache line. + */ +4:	cmpwi	r6,0 +	add	r5,r3,r5 +	beq	7f		/* Always flush prefetch queue in any case */ +	subi	r0,r6,1 +	andc	r3,r3,r0 +	mr	r4,r3 +5:	dcbst	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	5b +	sync			/* Wait for all dcbst to complete on bus */ +	mr	r4,r3 +6:	icbi	0,r4 +	add	r4,r4,r6 +	cmplw	r4,r5 +	blt	6b +7:	sync			/* Wait for all icbi to complete on bus */ +	isync + +/* + * We are done. Do not return, instead branch to second part of board + * initialization, now running from RAM. + */ +	addi	r0, r10, in_ram - _start + EXC_OFF_SYS_RESET +	mtlr	r0 +	blr + +in_ram: +	/* +	 * Relocation Function, r12 point to got2+0x8000 +	 * +	 * Adjust got2 pointers, no need to check for 0, this code +	 * already puts a few entries in the table. +	 */ +	li	r0,__got2_entries@sectoff@l +	la	r3,GOT(_GOT2_TABLE_) +	lwz	r11,GOT(_GOT2_TABLE_) +	mtctr	r0 +	sub	r11,r3,r11 +	addi	r3,r3,-4 +1:	lwzu	r0,4(r3) +	cmpwi	r0,0 +	beq-	2f +	add	r0,r0,r11 +	stw	r0,0(r3) +2:	bdnz	1b + +	/* +	 * Now adjust the fixups and the pointers to the fixups +	 * in case we need to move ourselves again. +	 */ +	li	r0,__fixup_entries@sectoff@l +	lwz	r3,GOT(_FIXUP_TABLE_) +	cmpwi	r0,0 +	mtctr	r0 +	addi	r3,r3,-4 +	beq	4f +3:	lwzu	r4,4(r3) +	lwzux	r0,r4,r11 +	add	r0,r0,r11 +	stw	r10,0(r3) +	stw	r0,0(r4) +	bdnz	3b +4: +/* clear_bss: */ +	/* +	 * Now clear BSS segment +	 */ +	lwz	r3,GOT(__bss_start) +	lwz	r4,GOT(_end) + +	cmplw	0, r3, r4 +	beq	6f + +	li	r0, 0 +5: +	stw	r0, 0(r3) +	addi	r3, r3, 4 +	cmplw	0, r3, r4 +	bne	5b +6: +	mr	r3, r9		/* Init Date pointer		*/ +	mr	r4, r10		/* Destination Address		*/ +	bl	board_init_r + +	/* not reached - end relocate_code */ +/*-----------------------------------------------------------------------*/ + +	/* +	 * Copy exception vector code to low memory +	 * +	 * r3: dest_addr +	 * r7: source address, r8: end address, r9: target address +	 */ +	.globl	trap_init +trap_init: +	mflr	r4			/* save link register		*/ +	GET_GOT +	lwz	r7, GOT(_start) +	lwz	r8, GOT(_end_of_vectors) + +	li	r9, 0x100		/* reset vector always at 0x100 */ + +	cmplw	0, r7, r8 +	bgelr				/* return if r7>=r8 - just in case */ +1: +	lwz	r0, 0(r7) +	stw	r0, 0(r9) +	addi	r7, r7, 4 +	addi	r9, r9, 4 +	cmplw	0, r7, r8 +	bne	1b + +	/* +	 * relocate `hdlr' and `int_return' entries +	 */ +	li	r7, .L_MachineCheck - _start + EXC_OFF_SYS_RESET +	li	r8, Alignment - _start + EXC_OFF_SYS_RESET +2: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector	*/ +	cmplw	0, r7, r8 +	blt	2b + +	li	r7, .L_Alignment - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_ProgramCheck - _start + EXC_OFF_SYS_RESET +	bl	trap_reloc + +	li	r7, .L_FPUnavailable - _start + EXC_OFF_SYS_RESET +	li	r8, SystemCall - _start + EXC_OFF_SYS_RESET +3: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector	*/ +	cmplw	0, r7, r8 +	blt	3b + +	li	r7, .L_SingleStep - _start + EXC_OFF_SYS_RESET +	li	r8, _end_of_vectors - _start + EXC_OFF_SYS_RESET +4: +	bl	trap_reloc +	addi	r7, r7, 0x100		/* next exception vector	*/ +	cmplw	0, r7, r8 +	blt	4b + +	/* enable execptions from RAM vectors */ +	mfmsr	r7 +	li	r8,MSR_IP +	andc	r7,r7,r8 +	ori	r7,r7,MSR_ME		/* Enable Machine Check */ +	mtmsr	r7 + +	mtlr	r4			/* restore link register	*/ +	blr + +.globl enable_ext_addr +enable_ext_addr: +	mfspr	r0, HID0 +	lis	r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@h +	ori	r0, r0, (HID0_HIGH_BAT_EN | HID0_XBSEN | HID0_XAEN)@l +	mtspr	HID0, r0 +	sync +	isync +	blr + +#if (CONFIG_SYS_CCSRBAR_DEFAULT != CONFIG_SYS_CCSRBAR) +.globl setup_ccsrbar +setup_ccsrbar: +	/* Special sequence needed to update CCSRBAR itself */ +	lis	r4, CONFIG_SYS_CCSRBAR_DEFAULT@h +	ori	r4, r4, CONFIG_SYS_CCSRBAR_DEFAULT@l + +	lis	r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@h +	ori	r5, r5, CONFIG_SYS_CCSRBAR_PHYS_LOW@l +	srwi	r5,r5,12 +	li	r6, CONFIG_SYS_CCSRBAR_PHYS_HIGH@l +	rlwimi	r5,r6,20,8,11 +	stw	r5, 0(r4) /* Store physical value of CCSR */ +	isync + +	lis	r5, TEXT_BASE@h +	ori	r5,r5,TEXT_BASE@l +	lwz	r5, 0(r5) +	isync + +	/* Use VA of CCSR to do read */ +	lis	r3, CONFIG_SYS_CCSRBAR@h +	lwz	r5, CONFIG_SYS_CCSRBAR@l(r3) +	isync + +	blr +#endif + +#ifdef CONFIG_SYS_INIT_RAM_LOCK +lock_ram_in_cache: +	/* Allocate Initial RAM in data cache. +	 */ +	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h +	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l +	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \ +		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32 +	mtctr	r4 +1: +	dcbz	r0, r3 +	addi	r3, r3, 32 +	bdnz	1b +#if 1 +/* Lock the data cache */ +	mfspr	r0, HID0 +	ori	r0, r0, 0x1000 +	sync +	mtspr	HID0, r0 +	sync +	blr +#endif +#if 0 +	/* Lock the first way of the data cache */ +	mfspr	r0, LDSTCR +	ori	r0, r0, 0x0080 +#if defined(CONFIG_ALTIVEC) +	dssall +#endif +	sync +	mtspr	LDSTCR, r0 +	sync +	isync +	blr +#endif + +.globl unlock_ram_in_cache +unlock_ram_in_cache: +	/* invalidate the INIT_RAM section */ +	lis	r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@h +	ori	r3, r3, (CONFIG_SYS_INIT_RAM_ADDR & ~31)@l +	li	r4, ((CONFIG_SYS_INIT_RAM_END & ~31) + \ +		     (CONFIG_SYS_INIT_RAM_ADDR & 31) + 31) / 32 +	mtctr	r4 +1:	icbi	r0, r3 +	addi	r3, r3, 32 +	bdnz	1b +	sync			/* Wait for all icbi to complete on bus */ +	isync +#if 1 +/* Unlock the data cache and invalidate it */ +	mfspr	r0, HID0 +	li	r3,0x1000 +	andc	r0,r0,r3 +	li	r3,0x0400 +	or	r0,r0,r3 +	sync +	mtspr	HID0, r0 +	sync +	blr +#endif +#if 0 +	/* Unlock the first way of the data cache */ +	mfspr	r0, LDSTCR +	li	r3,0x0080 +	andc	r0,r0,r3 +#ifdef CONFIG_ALTIVEC +	dssall +#endif +	sync +	mtspr	LDSTCR, r0 +	sync +	isync +	li	r3,0x0400 +	or	r0,r0,r3 +	sync +	mtspr	HID0, r0 +	sync +	blr +#endif +#endif diff --git a/arch/powerpc/cpu/mpc86xx/traps.c b/arch/powerpc/cpu/mpc86xx/traps.c new file mode 100644 index 000000000..406403e51 --- /dev/null +++ b/arch/powerpc/cpu/mpc86xx/traps.c @@ -0,0 +1,233 @@ +/* + * 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 <kgdb.h> +#include <asm/processor.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* Returns 0 if exception not found and fixup otherwise.  */ +extern unsigned long search_exception_table(unsigned long); + +/* + * End of addressable memory.  This may be less than the actual + * amount of memory on the system if we're unable to keep all + * the memory mapped in. + */ +extern ulong get_effective_memsize(void); +#define END_OF_MEM (gd->bd->bi_memstart + get_effective_memsize()) + +/* + * 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 defined(CONFIG_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 & 0x001F0000) { +	case (0x80000000>>11): +		printf("MSS error. MSSSR0: %08x\n", mfspr(SPRN_MSSSR0)); +		break; +	case (0x80000000>>12): +		printf("Machine check signal - probably due to mm fault\n" +		       "with mmu off\n"); +		break; +	case (0x80000000 >> 13): +		printf("Transfer error ack signal\n"); +		break; +	case (0x80000000 >> 14): +		printf("Data parity signal\n"); +		break; +	case (0x80000000 >> 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 defined(CONFIG_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) +{ +	unsigned char *p = regs ? (unsigned char *)(regs->nip) : NULL; +	int i, j; + +#if defined(CONFIG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler) (regs)) +		return; +#endif +	show_regs(regs); + +	p = (unsigned char *)((unsigned long)p & 0xFFFFFFE0); +	p -= 32; +	for (i = 0; i < 256; i += 16) { +		printf("%08x: ", (unsigned int)p + i); +		for (j = 0; j < 16; j++) { +			printf("%02x ", p[i + j]); +		} +		printf("\n"); +	} + +	print_backtrace((unsigned long *)regs->gpr[1]); +	panic("Program Check Exception"); +} + +void +SoftEmuException(struct pt_regs *regs) +{ +#if defined(CONFIG_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 defined(CONFIG_CMD_KGDB) +	if (debugger_exception_handler && (*debugger_exception_handler) (regs)) +		return; +#endif +	printf("UnknownException regs@%lx\n", (ulong)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) +{ +	return 0; +} |