diff options
| -rwxr-xr-x | MAKEALL | 1 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | README | 22 | ||||
| -rw-r--r-- | board/mpc7448hpc2/Makefile | 52 | ||||
| -rw-r--r-- | board/mpc7448hpc2/asm_init.S | 918 | ||||
| -rw-r--r-- | board/mpc7448hpc2/config.mk | 28 | ||||
| -rw-r--r-- | board/mpc7448hpc2/mpc7448hpc2.c | 107 | ||||
| -rw-r--r-- | board/mpc7448hpc2/tsi108_init.c | 665 | ||||
| -rw-r--r-- | board/mpc7448hpc2/u-boot.lds | 136 | ||||
| -rw-r--r-- | cpu/74xx_7xx/cpu.c | 46 | ||||
| -rw-r--r-- | cpu/74xx_7xx/cpu_init.c | 1 | ||||
| -rw-r--r-- | cpu/74xx_7xx/speed.c | 56 | ||||
| -rw-r--r-- | doc/README.mpc7448hpc2 | 185 | ||||
| -rw-r--r-- | drivers/Makefile | 6 | ||||
| -rw-r--r-- | drivers/cfi_flash.c | 29 | ||||
| -rw-r--r-- | drivers/tsi108_eth.c | 1036 | ||||
| -rw-r--r-- | drivers/tsi108_i2c.c | 298 | ||||
| -rw-r--r-- | drivers/tsi108_pci.c | 178 | ||||
| -rw-r--r-- | include/74xx_7xx.h | 2 | ||||
| -rw-r--r-- | include/asm-ppc/global_data.h | 3 | ||||
| -rw-r--r-- | include/configs/mpc7448hpc2.h | 411 | ||||
| -rw-r--r-- | include/tsi108.h | 221 | ||||
| -rw-r--r-- | lib_ppc/extable.c | 25 | ||||
| -rw-r--r-- | net/eth.c | 4 | 
24 files changed, 4399 insertions, 34 deletions
| @@ -152,6 +152,7 @@ LIST_85xx="	\  LIST_74xx="	\  	DB64360		DB64460		EVB64260	P3G4		\  	p3m7448		PCIPPC2		PCIPPC6		ZUMA		\ +	mpc7448hpc2  "  LIST_7xx="	\ @@ -1751,6 +1751,9 @@ EVB64260_config	\  EVB64260_750CX_config:	unconfig  	@$(MKCONFIG) EVB64260 ppc 74xx_7xx evb64260 +mpc7448hpc2_config:  unconfig +	@$(MKCONFIG) $(@:_config=) ppc 74xx_7xx mpc7448hpc2 +  P3G4_config: unconfig  	@$(MKCONFIG) $(@:_config=) ppc 74xx_7xx evb64260 @@ -2371,17 +2371,17 @@ configurations; the following names are supported:  	csb272_config		lwmon_config		sbc8260_config  	CU824_config		MBX860T_config		sbc8560_33_config  	DUET_ADS_config		MBX_config		sbc8560_66_config -	EBONY_config		MPC8260ADS_config	SM850_config -	ELPT860_config		MPC8540ADS_config	SPD823TS_config -	ESTEEM192E_config	MPC8540EVAL_config	stxgp3_config -	ETX094_config		MPC8560ADS_config	SXNI855T_config -	FADS823_config		NETVIA_config		TQM823L_config -	FADS850SAR_config	omap1510inn_config	TQM850L_config -	FADS860T_config		omap1610h2_config	TQM855L_config -	FPS850L_config		omap1610inn_config	TQM860L_config -				omap5912osk_config	walnut_config -				omap2420h4_config	Yukon8220_config -							ZPC1900_config +	EBONY_config		mpc7448hpc2_config	SM850_config +	ELPT860_config		MPC8260ADS_config	SPD823TS_config +	ESTEEM192E_config	MPC8540ADS_config	stxgp3_config +	ETX094_config		MPC8540EVAL_config	SXNI855T_config +	FADS823_config		NMPC8560ADS_config	TQM823L_config +	FADS850SAR_config	NETVIA_config		TQM850L_config +	FADS860T_config		omap1510inn_config	TQM855L_config +	FPS850L_config		omap1610h2_config	TQM860L_config +				omap1610inn_config	walnut_config +				omap5912osk_config	Yukon8220_config +				omap2420h4_config	ZPC1900_config  Note: for some board special configuration names may exist; check if        additional information is available from the board vendor; for diff --git a/board/mpc7448hpc2/Makefile b/board/mpc7448hpc2/Makefile new file mode 100644 index 000000000..e3d757d5d --- /dev/null +++ b/board/mpc7448hpc2/Makefile @@ -0,0 +1,52 @@ +# +# (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 +# + +include $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	:= $(BOARD).o tsi108_init.o +SOBJS	:= asm_init.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +.PHONY: distclean +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude ($obj).depend + +######################################################################### diff --git a/board/mpc7448hpc2/asm_init.S b/board/mpc7448hpc2/asm_init.S new file mode 100644 index 000000000..a7a40a134 --- /dev/null +++ b/board/mpc7448hpc2/asm_init.S @@ -0,0 +1,918 @@ +/* + * (C) Copyright 2004-05;  Tundra Semiconductor Corp. + * + * Added automatic detect of SDC settings + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * Maintainer tie-fei.zang@freescale.com + * + * 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 + */ + +/* + * FILENAME: asm_init.s + * + * Originator: Alex Bounine + * + * DESCRIPTION: + * Initialization code for the Tundra Tsi108 bridge chip + * + */ + +#include <config.h> +#include <version.h> + +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/processor.h> + +#include <tsi108.h> + +/* + * Build Configuration Options + */ + +/* #define DISABLE_PBM		disables usage of PB Master */ +/* #define SDC_HARDCODED_INIT	config SDRAM controller with hardcoded values */ +/* #define SDC_AUTOPRECH_EN	enable SDRAM auto precharge */ + +/* + * Hardcoded SDC settings + */ + +#ifdef SDC_HARDCODED_INIT + +/* Micron MT9HTF6472AY-40EA1 : Unbuffered, 512MB, 400, CL3, Single Rank */ + +#define VAL_SD_REFRESH	(0x61A) +#define VAL_SD_TIMING	(0x0308336b) +#define VAL_SD_D0_CTRL	(0x07100021)	/* auto-precharge disabled */ +#define VAL_SD_D0_BAR	(0x0FE00000)	/* 512MB @ 0x00000000 */ +#define VAL_SD_D1_CTRL	(0x07100021)	/* auto-precharge disabled */ +#define VAL_SD_D1_BAR	(0x0FE00200)	/* 512MB @ 0x20000000 */ + +#endif /* SDC_HARDCODED_INIT */ + +/* + CPU Configuration: + + CPU Address and Data Parity enables. + +#define CPU_AP +#define CPU_DP +*/ + +/* + * Macros + * !!! Attention !!! Macros LOAD_PTR, LOAD_U32 and LOAD_MEM defined below are + * expected to work correctly for the CSR space within 32KB range. + * + * LOAD_PTR and LOAD_U32 - load specified register with a 32 bit constant. + * These macros are absolutely identical except their names. This difference + * is provided intentionally for better readable code. + */ + +#define LOAD_PTR(reg,const32) \ +	addis reg,r0,const32@h; ori reg,reg,const32@l + +#define LOAD_U32(reg,const32) \ +	addis reg,r0,const32@h; ori reg,reg,const32@l + +/* LOADMEM initializes a register with the contents of a specified 32-bit + * memory location, usually a CSR value. + */ + +#define LOAD_MEM(reg,addr32) \ +	addis reg,r0,addr32@ha; lwz reg,addr32@l(reg) + +#ifndef SDC_HARDCODED_INIT +sdc_clk_sync: +	/* MHz: 0,0,183,100,133,167,200,233 */ +	.long	0, 0, 6, 10, 8, 6, 5, 4		/* nSec */ +#endif + +/* + * board_asm_init() - early initialization function. Coded to be portable to + * dual-CPU configuration. + * Checks CPU number and performs board HW initialization if called for CPU0. + * Registers used: r3,r4,r5,r6,r19,r29 + * + * NOTE: For dual-CPU configuration only CPU0 is allowed to configure Tsi108 + * and the rest of the board. Current implementation demonstrates two + * possible ways to identify CPU number: + * - for MPC74xx platform: uses MSSCR0[ID] bit as defined in UM. + * - for PPC750FX/GX boards: uses WHO_AM_I bit reported by Tsi108. + */ + +	.globl board_asm_init +board_asm_init: +	mflr	r19	/* Save LR to be able return later. */ +	bl	icache_enable	/* Enable icache to reduce reads from flash. */ + +/* Initialize pointer to Tsi108 register space */ + +	LOAD_PTR(r29,CFG_TSI108_CSR_RST_BASE)/* r29 - pointer to tsi108 CSR space */ +	ori r4,r29,TSI108_PB_REG_OFFSET + +/* Check Processor Version Number */ + +	mfspr	r3, PVR +	rlwinm	r3,r3,16,16,23	/* get ((Processor Version Number) & 0xFF00) */ + +	cmpli	0,0,r3,0x8000	/* MPC74xx */ +	bne	cont_brd_init + +	/* +	 * For MPC744x/5x enable extended BATs[4-7] +	 * Sri: Set HIGH_BAT_EN and XBSEN, and SPD =1 +	 * to disable prefetch +	 */ + +	mfspr	r5, HID0 +	oris	r5, r5, 0x0080	/* Set HID0[HIGH_BAT_EN] bit #8 */ +	ori	r5, r5, 0x0380	/* Set SPD,XBSEN,SGE bits #22,23,24 */ +	mtspr	HID0, r5 +	isync +	sync + +	/* Adding code to disable external interventions in MPX bus mode */ +	mfspr	r3, 1014 +	oris	r3, r3, 0x0100	/* Set the EIDIS bit in MSSCR0:  bit 7 */ +	mtspr	1014, r3 +	isync +	sync + +	/* Sri: code to enable FP unit */ +	mfmsr	r3 +	ori	r3, r3, 0x2000 +	mtmsr	r3 +	isync +	sync + +	/* def CONFIG_DUAL_CPU +	 * For MPC74xx processor, use MSSCR0[ID] bit to identify CPU number. +	 */ +#if(1) +	mfspr	r3,1014		/* read MSSCR0 */ +	rlwinm.	r3,r3,27,31,31	/* get processor ID number */ +	mtspr	SPRN_PIR,r3	/* Save CPU ID */ +	sync +	bne	init_done +	b	do_tsi108_init + +cont_brd_init: + +	/* An alternative method of checking the processor number (in addition +	 * to configuration using MSSCR0[ID] bit on MPC74xx). +	 * Good for IBM PPC750FX/GX. +	 */ + +	lwz	r3,PB_BUS_MS_SELECT(r4)	/* read PB_ID register */ +	rlwinm.	r3,r3,24,31,31		/* get processor ID number */ +	bne init_done +#else + +cont_brd_init: + +#endif /* CONFIG_DUAL_CPU */ + +	/* Initialize Tsi108 chip */ + +do_tsi108_init: + +	/* +	 * Adjust HLP/Flash parameters. By default after reset the HLP port is +	 * set to support slow devices. Better performance can be achived when +	 * an optimal parameters are used for specific EPROM device. +	 * NOTE: This should be performed ASAP for the emulation platform +	 * because it has 5MHz HLP clocking. +	 */ + +#ifdef CONFIG_TSI108EMU +	ori	r4,r29,TSI108_HLP_REG_OFFSET +	LOAD_U32(r5,0x434422c0) +	stw	r5,0x08(r4)	/* set HLP B0_CTRL0 */ +	sync +	LOAD_U32(r5,0xd0012000) +	stw	r5,0x0c(r4)		/* set HLP B0_CTRL1 */ +	sync +#endif + +	/* Initialize PB interface. */ + +	ori r4,r29,TSI108_PB_REG_OFFSET + +#if (CFG_TSI108_CSR_BASE != CFG_TSI108_CSR_RST_BASE) +	/* Relocate (if required) Tsi108 registers. Set new value for +	 * PB_REG_BAR: +	 * Note we are in the 32-bit address mode. +	 */ +	LOAD_U32(r5,(CFG_TSI108_CSR_BASE | 0x01)) /* PB_REG_BAR: BA + EN */ +	stw	r5,PB_REG_BAR(r4) +	andis.	r29,r5,0xFFFF +	sync +	ori	r4,r29,TSI108_PB_REG_OFFSET +#endif + +	/* Set PB Slave configuration register */ + +	LOAD_U32(r5,0x00002481)	/* PB_SCR: TEA enabled,AACK delay = 1 */ +	lwz	r3, PB_RSR(r4)	/* get PB bus mode */ +	xori	r3,r3,0x0001	/* mask PB_BMODE: r3 -> (0 = 60X, 1 = MPX) */ +	rlwimi  r5,r3,14,17,17	/* for MPX: set DTI_MODE bit */ +	stw	r5,PB_SCR(r4) +	sync + +	/* Configure PB Arbiter */ + +	lwz	r5,PB_ARB_CTRL(r4)	/* Read PB Arbiter Control Register */ +	li	r3, 0x00F0		/* ARB_PIPELINE_DEP mask */ +#ifdef DISABLE_PBM +	ori	r3,r3,0x1000	/* add PBM_EN to clear (enabled by default) */ +#endif +	andc	r5,r5,r3	/* Clear the masked bit fields */ +	ori	r5,r5,0x0001	/* Set pipeline depth */ +	stw	r5,PB_ARB_CTRL(r4) + +#if (0)	/* currently using the default settings for PBM after reset */ +	LOAD_U32(r5,0x)		/* value for PB_MCR */ +	stw	r5,PB_MCR(r4) +	sync + +	LOAD_U32(r5,0x)		/* value for PB_MCMD */ +	stw	r5,PB_MCMD(r4) +	sync +#endif + +	/* Disable or enable PVT based on processor bus frequency +	 * 1. Read CG_PWRUP_STATUS register field bits 18,17,16 +	 * 2. See if the value is < or > 133mhz (18:16 = 100) +	 * 3. If > enable PVT +	 */ + +	LOAD_U32(r3,0xC0002234) +	lwz	r3,0(r3) +	rlwinm	r3,r3,16,29,31 + +	cmpi	0,0,r3,0x0004 +	bgt	sdc_init + +#ifndef CONFIG_TSI108EMU +	/* FIXME: Disable PB calibration control for any real Tsi108 board */ +	li	r5,0x0101	/* disable calibration control */ +	stw	r5,PB_PVT_CTRL2(r4) +	sync +#endif + +	/* Initialize SDRAM controller. */ + +sdc_init: + +#ifndef SDC_HARDCODED_INIT +	/* get SDC clock prior doing sdram controller autoconfig */ +	ori	r4,r29,TSI108_CLK_REG_OFFSET	/* r4 - ptr to CG registers */ +	lwz	r3, CG_PWRUP_STATUS(r4)		/* get CG configuration */ +	rlwinm	r3,r3,12,29,31			/* r3 - SD clk */ +	lis	r5,sdc_clk_sync@h +	ori	r5,r5,sdc_clk_sync@l +	/* Sri:  At this point check if r3 = 001. If yes, +	 * the memory frequency should be same as the +	 * MPX bus frequency +	 */ +	cmpi	0,0,r3,0x0001 +	bne	get_nsec +	lwz	r6, CG_PWRUP_STATUS(r4) +	rlwinm	r6,r6,16,29,31 +	mr	r3,r6 + +get_nsec: +	rlwinm	r3,r3,2,0,31 +	lwzx	r9,r5,r3	/* get SD clk rate in nSec */ +	/* ATTN: r9 will be used by SPD routine */ +#endif /* !SDC_HARDCODED_INIT */ + +	ori	r4,r29,TSI108_SD_REG_OFFSET /* r4 - ptr to SDRAM registers */ + +	/* Initialize SDRAM controller. SDRAM Size = 512MB, One DIMM. */ + +	LOAD_U32(r5,0x00) +	stw	r5,SD_INT_ENABLE(r4) /* Ensure that interrupts are disabled */ +#ifdef ENABLE_SDRAM_ECC +	li	r5, 0x01 +#endif /* ENABLE_SDRAM_ECC */ +	stw	r5,SD_ECC_CTRL(r4)	/* Enable/Disable ECC */ +	sync + +#ifdef SDC_HARDCODED_INIT /* config sdram controller with hardcoded values */ + +	/* First read the CG_PWRUP_STATUS register to get the +	 * memory speed from bits 22,21,20 +	 */ + +	LOAD_U32(r3,0xC0002234) +	lwz	r3,0(r3) +	rlwinm	r3,r3,12,29,31 + +	/* Now first check for 166, then 200, or default */ + +	cmpi	0,0,r3,0x0005 +	bne	check_for_200mhz + +	/* set values for 166 Mhz memory speed +	 * Set refresh rate and timing parameters +	 */ +	LOAD_U32(r5,0x00000515) +	stw	r5,SD_REFRESH(r4) +	LOAD_U32(r5,0x03073368) +	stw	r5,SD_TIMING(r4) +	sync + +	/* Initialize DIMM0 control and BAR registers */ +	LOAD_U32(r5,VAL_SD_D0_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001		/* set auto precharge EN bit */ +#endif +	stw	r5,SD_D0_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D0_BAR) +	stw	r5,SD_D0_BAR(r4) +	sync + +	/* Initialize DIMM1 control and BAR registers +	 * (same as dimm 0, next 512MB, disabled) +	 */ +	LOAD_U32(r5,VAL_SD_D1_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001	/* set auto precharge EN bit */ +#endif +	stw	r5,SD_D1_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D1_BAR) +	stw	r5,SD_D1_BAR(r4) +	sync + +	b	sdc_init_done + +check_for_200mhz: + +	cmpi	0,0,r3,0x0006 +	bne	set_default_values + +	/* set values for 200Mhz memory speed +	 * Set refresh rate and timing parameters +	 */ +	LOAD_U32(r5,0x0000061a) +	stw	r5,SD_REFRESH(r4) +	LOAD_U32(r5,0x03083348) +	stw	r5,SD_TIMING(r4) +	sync + +	/* Initialize DIMM0 control and BAR registers */ +	LOAD_U32(r5,VAL_SD_D0_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001		/* set auto precharge EN bit */ +#endif +	stw	r5,SD_D0_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D0_BAR) +	stw	r5,SD_D0_BAR(r4) +	sync + +	/* Initialize DIMM1 control and BAR registers +	 * (same as dimm 0, next 512MB, disabled) +	 */ +	LOAD_U32(r5,VAL_SD_D1_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001		/* set auto precharge EN bit */ +#endif +	stw	r5,SD_D1_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D1_BAR) +	stw	r5,SD_D1_BAR(r4) +	sync + +	b	sdc_init_done + +set_default_values: + +	/* Set refresh rate and timing parameters */ +	LOAD_U32(r5,VAL_SD_REFRESH) +	stw	r5,SD_REFRESH(r4) +	LOAD_U32(r5,VAL_SD_TIMING) +	stw	r5,SD_TIMING(r4) +	sync + +	/* Initialize DIMM0 control and BAR registers */ +	LOAD_U32(r5,VAL_SD_D0_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001		/* set auto precharge EN bit */ +#endif +	stw 	r5,SD_D0_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D0_BAR) +	stw	r5,SD_D0_BAR(r4) +	sync + +	/* Initialize DIMM1 control and BAR registers +	 * (same as dimm 0, next 512MB, disabled) +	 */ +	LOAD_U32(r5,VAL_SD_D1_CTRL)	/* auto-precharge disabled */ +#ifdef SDC_AUTOPRECH_EN +	oris	r5,r5,0x0001		/* set auto precharge EN bit */ +#endif +	stw	r5,SD_D1_CTRL(r4) +	LOAD_U32(r5,VAL_SD_D1_BAR) +	stw	r5,SD_D1_BAR(r4) +	sync +#else /* !SDC_HARDCODED_INIT */ +	bl	tsi108_sdram_spd	/* automatically detect SDC settings */ +#endif /* SDC_HARDCODED_INIT */ + +sdc_init_done: + +#ifdef DISABLE_PBM +	LOAD_U32(r5,0x00000030)		/* PB_EN + OCN_EN */ +#else +	LOAD_U32(r5,0x00000230)		/* PB_EN + OCN_EN + PB/OCN=80/20 */ +#endif /* DISABLE_PBM */ + +#ifdef CONFIG_TSI108EMU +	oris	r5,r5,0x0010		/* set EMULATION_MODE bit */ +#endif + +	stw	r5,SD_CTRL(r4) +	eieio +	sync + +	/* Enable SDRAM access */ + +	oris	r5,r5,0x8000		/* start SDC: set SD_CTRL[ENABLE] bit */ +	stw	r5,SD_CTRL(r4) +	sync + +wait_init_complete: +	lwz	r5,SD_STATUS(r4) +	andi.	r5,r5,0x0001 +	/* wait until SDRAM initialization is complete */ +	beq	wait_init_complete + +	/* Map SDRAM into the processor bus address space */ + +	ori	r4,r29,TSI108_PB_REG_OFFSET + +	/* Setup BARs associated with direct path PB<->SDRAM */ + +	/* PB_SDRAM_BAR1: +	 * provides a direct path to the main system memory (cacheable SDRAM) +	 */ + +	/* BA=0,Size=512MB, ENable, No Addr.Translation */ +	LOAD_U32(r5, 0x00000011) +	stw	r5,PB_SDRAM_BAR1(r4) +	sync + +	/* Make sure that PB_SDRAM_BAR1 decoder is set +	 * (to allow following immediate read from SDRAM) +	 */ +	lwz	r5,PB_SDRAM_BAR1(r4) +	sync + +	/* PB_SDRAM_BAR2: +	 * provides non-cacheable alias (via the direct path) to main +	 * system memory. +	 * Size = 512MB, ENable, Addr.Translation - ON, +	 * BA = 0x0_40000000, TA = 0x0_00000000 +	 */ + +	LOAD_U32(r5, 0x40010011) +	stw	r5,PB_SDRAM_BAR2(r4) +	sync + +	/* Make sure that PB_SDRAM_BAR2 decoder is set +	 * (to allow following immediate read from SDRAM) +	 */ +	lwz	r5,PB_SDRAM_BAR2(r4) +	sync + +init_done: + +	/* All done. Restore LR and return. */ +	mtlr	r19 +	blr + +#if (0) +	/* +	 * init_cpu1 +	 * This routine enables CPU1 on the dual-processor system. +	 * Now there is only one processor in the system +	 */ + +	.global enable_cpu1 +enable_cpu1: + +	lis	r3,Tsi108_Base@ha	/* Get Grendel CSR Base Addr */ +	addi	r3,r3,Tsi108_Base@l +	lwz	r3,0(r3)		/* R3 = CSR Base Addr */ +	ori	r4,r3,TSI108_PB_REG_OFFSET +	lwz	r3,PB_ARB_CTRL(r4)	/* Read PB Arbiter Control Register */ +	ori	r3,r3,0x0200		/* Set M1_EN bit */ +	stw	r3,PB_ARB_CTRL(r4) + +	blr +#endif + +	/* +	 * enable_EI +	 * Enable CPU core external interrupt +	 */ + +	.global	enable_EI +enable_EI: +	mfmsr	r3 +	ori	r3,r3,0x8000	/* set EE bit */ +	mtmsr	r3 +	blr + +	/* +	 * disable_EI +	 * Disable CPU core external interrupt +	 */ + +	.global disable_EI +disable_EI: +	mfmsr	r3 +	li	r4,-32768	/* aka "li  r4,0x8000" */ +	andc	r3,r3,r4	/* clear EE bit */ +	mtmsr	r3 +	blr + +#ifdef ENABLE_SDRAM_ECC +	/* enables SDRAM ECC  */ + +	.global	enable_ECC +enable_ECC: +	ori	r4,r29,TSI108_SD_REG_OFFSET +	lwz	r3,SD_ECC_CTRL(r4)	/* Read SDRAM ECC Control Register */ +	ori	r3,r3,0x0001		/* Set ECC_EN bit */ +	stw	r3,SD_ECC_CTRL(r4) +	blr + +	/* +	 * clear_ECC_err +	 * Clears all pending SDRAM ECC errors +	 * (normally after SDRAM scrubbing/initialization) +	 */ + +	.global	clear_ECC_err +clear_ECC_err: +	ori r4,r29,TSI108_SD_REG_OFFSET +	ori r3,r0,0x0030	/* ECC_UE_INT + ECC_CE_INT bits */ +	stw r3,SD_INT_STATUS(r4) +	blr + +#endif /* ENABLE_SDRAM_ECC */ + +#ifndef SDC_HARDCODED_INIT + +	/* SDRAM SPD Support */ +#define	SD_I2C_CTRL1	(0x400) +#define	SD_I2C_CTRL2	(0x404) +#define SD_I2C_RD_DATA	(0x408) +#define SD_I2C_WR_DATA	(0x40C) + +	/* +	 * SDRAM SPD Support Macros +	 */ + +#define SPD_DIMM0	(0x00000100) +#define SPD_DIMM1	(0x00000200)	/* SPD_DIMM1 was 0x00000000 */ + +#define SPD_RDIMM			(0x01) +#define SPD_UDIMM			(0x02) + +#define SPD_CAS_3			0x8 +#define SPD_CAS_4			0x10 +#define SPD_CAS_5			0x20 + +#define ERR_NO_DIMM_FOUND		(0xdb0) +#define ERR_TRAS_FAIL			(0xdb1) +#define ERR_TRCD_FAIL			(0xdb2) +#define ERR_TRP_FAIL			(0xdb3) +#define ERR_TWR_FAIL			(0xdb4) +#define ERR_UNKNOWN_PART		(0xdb5) +#define ERR_NRANK_INVALID		(0xdb6) +#define ERR_DIMM_SIZE			(0xdb7) +#define ERR_ADDR_MODE			(0xdb8) +#define ERR_RFRSH_RATE			(0xdb9) +#define ERR_DIMM_TYPE			(0xdba) +#define ERR_CL_VALUE			(0xdbb) +#define ERR_TRFC_FAIL			(0xdbc) + +/* READ_SPD requirements: + * byte - byte address in SPD device (0 - 255) + * r3 = will return data read from I2C Byte location + * r4 - unchanged (SDC base addr) + * r5 - clobbered in routine (I2C status) + * r10 - number of DDR slot where first SPD device is detected + */ + +#define READ_SPD(byte_num)		\ +	addis	r3, 0, byte_num@l;	\ +	or	r3, r3, r10;		\ +	ori	r3, r3, 0x0A;		\ +	stw	r3, SD_I2C_CTRL1(r4);	\ +	li	r3, I2C_CNTRL2_START;	\ +	stw	r3, SD_I2C_CTRL2(r4);	\ +	eieio;				\ +	sync;				\ +	li	r3, 0x100;		\ +1:;					\ +	addic.	r3, r3, -1;		\ +	bne	1b;			\ +2:;					\ +	lwz	r5, SD_I2C_CTRL2(r4);	\ +	rlwinm.	r3,r5,0,23,23;		\ +	bne	2b;			\ +	rlwinm.	r3,r5,0,3,3;		\ +	lwz	r3,SD_I2C_RD_DATA(r4) + +#define SPD_MIN_RFRSH	(0x80) +#define SPD_MAX_RFRSH	(0x85) + +refresh_rates:	/* in nSec */ +	.long	15625	/* Normal (0x80) */ +	.long	3900	/* Reduced 0.25x (0x81) */ +	.long	7800	/* Reduced 0.5x (0x82) */ +	.long	31300	/* Extended 2x (0x83) */ +	.long	62500	/* Extended 4x (0x84) */ +	.long	125000	/* Extended 8x (0x85) */ + +/* + * tsi108_sdram_spd + * + * Inittializes SDRAM Controller using DDR2 DIMM Serial Presence Detect data + * Uses registers: r4 - SDC base address (not changed) + *				   r9 - SDC clocking period in nSec + * Changes registers: r3,r5,r6,r7,r8,r10,r11 + */ + +tsi108_sdram_spd: + +	li	r10,SPD_DIMM0 +	xor	r11,r11,r11		/* DIMM Base Address: starts from 0 */ + +do_first_dimm: + +	/* Program Refresh Rate	Register */ + +	READ_SPD(12)			/* get Refresh Rate */ +	beq	check_next_slot +	li	r5, ERR_RFRSH_RATE +	cmpi	0,0,r3,SPD_MIN_RFRSH +	ble	spd_fail +	cmpi	0,0,r3,SPD_MAX_RFRSH +	bgt	spd_fail +	addi	r3,r3,-SPD_MIN_RFRSH +	rlwinm	r3,r3,2,0,31 +	lis	r5,refresh_rates@h +	ori	r5,r5,refresh_rates@l +	lwzx	r5,r5,r3		/* get refresh rate in nSec */ +	divwu	r5,r5,r9		/* calculate # of SDC clocks */ +	stw	r5,SD_REFRESH(r4)	/* Set refresh rate */ +	sync + +	/* Program SD Timing Register */ + +	li	r7, 0		/* clear r7 prior parameter collection */ + +	READ_SPD(20)		/* get DIMM type: Registered or Unbuffered */ +	beq	spd_read_fail +	li	r5, ERR_DIMM_TYPE +	cmpi	0,0,r3,SPD_UDIMM +	beq	do_cl +	cmpi	0,0,r3,SPD_RDIMM +	bne	spd_fail +	oris	r7,r7,0x1000	/* set SD_TIMING[DIMM_TYPE] bit */ + +do_cl: +	READ_SPD(18)		/* Get CAS Latency */ +	beq	spd_read_fail +	li	r5,ERR_CL_VALUE +	andi.	r6,r3,SPD_CAS_3 +	beq	cl_4 +	li	r6,3 +	b	set_cl +cl_4: +	andi.	r6,r3,SPD_CAS_4 +	beq	cl_5 +	li	r6,4 +	b	set_cl +cl_5: +	andi.	r6,r3,SPD_CAS_5 +	beq	spd_fail +	li	r6,5 +set_cl: +	rlwimi	r7,r6,24,5,7 + +	READ_SPD(30)		/* Get tRAS */ +	beq	spd_read_fail +	divwu	r6,r3,r9 +	mullw	r8,r6,r9 +	subf.	r8,r8,r3 +	beq	set_tras +	addi	r6,r6,1 +set_tras: +	li r5,ERR_TRAS_FAIL +	cmpi	0,0,r6,0x0F	/* max supported value */ +	bgt	spd_fail +	rlwimi	r7,r6,16,12,15 + +	READ_SPD(29)	/* Get tRCD */ +	beq	spd_read_fail +	/* right shift tRCD by 2 bits as per DDR2 spec */ +	rlwinm	r3,r3,30,2,31 +	divwu	r6,r3,r9 +	mullw	r8,r6,r9 +	subf.	r8,r8,r3 +	beq	set_trcd +	addi	r6,r6,1 +set_trcd: +	li	r5,ERR_TRCD_FAIL +	cmpi	0,0,r6,0x07	/* max supported value */ +	bgt	spd_fail +	rlwimi	r7,r6,12,17,19 + +	READ_SPD(27)	/* Get tRP value */ +	beq	spd_read_fail +	rlwinm	r3,r3,30,2,31	/* right shift tRP by 2 bits as per DDR2 spec */ +	divwu	r6,r3,r9 +	mullw	r8,r6,r9 +	subf.	r8,r8,r3 +	beq	set_trp +	addi	r6,r6,1 +set_trp: +	li	r5,ERR_TRP_FAIL +	cmpi	0,0,r6,0x07	/* max supported value */ +	bgt	spd_fail +	rlwimi	r7,r6,8,21,23 + +	READ_SPD(36)	/* Get tWR value */ +	beq	spd_read_fail +	rlwinm	r3,r3,30,2,31	/* right shift tWR by 2 bits as per DDR2 spec */ +	divwu	r6,r3,r9 +	mullw	r8,r6,r9 +	subf.	r8,r8,r3 +	beq	set_twr +	addi	r6,r6,1 +set_twr: +	addi	r6,r6,-1	/* Tsi108 SDC always gives one extra clock */ +	li	r5,ERR_TWR_FAIL +	cmpi	0,0,r6,0x07	/* max supported value */ +	bgt	spd_fail +	rlwimi	r7,r6,5,24,26 + +	READ_SPD(42)	/* Get tRFC */ +	beq	spd_read_fail +	li	r5, ERR_TRFC_FAIL +	/* Tsi108 spec: tRFC=(tRFC + 1)/2 */ +	addi	r3,r3,1 +	rlwinm.	r3,r3,31,1,31	/* divide by 2 */ +	beq	spd_fail +	divwu	r6,r3,r9 +	mullw	r8,r6,r9 +	subf.	r8,r8,r3 +	beq	set_trfc +	addi	r6,r6,1 +set_trfc: +	cmpi	0,0,r6,0x1F	/* max supported value */ +	bgt	spd_fail +	rlwimi	r7,r6,0,27,31 + +	stw	r7,SD_TIMING(r4) +	sync + +	/* +	 * The following two registers are set on per-DIMM basis. +	 * The SD_REFRESH and SD_TIMING settings are common for both DIMMS +	 */ + +do_each_dimm: + +	/* Program SDRAM DIMM Control Register */ + +	li	r7, 0		/* clear r7 prior parameter collection */ + +	READ_SPD(13)		/* Get Primary SDRAM Width */ +	beq	spd_read_fail +	cmpi	0,0,r3,4	/* Check for 4-bit SDRAM */ +	beq	do_nbank +	oris	r7,r7,0x0010	/* Set MEM_WIDTH bit */ + +do_nbank: +	READ_SPD(17)		/* Get Number of banks on SDRAM device */ +	beq	spd_read_fail +	/* Grendel only distinguish betw. 4 or 8-bank memory parts */ +	li	r5,ERR_UNKNOWN_PART	/* non-supported memory part */ +	cmpi	0,0,r3,4 +	beq	do_nrank +	cmpi	0,0,r3,8 +	bne	spd_fail +	ori	r7,r7,0x1000 + +do_nrank: +	READ_SPD(5)		/* Get # of Ranks */ +	beq	spd_read_fail +	li	r5,ERR_NRANK_INVALID +	andi.	r6,r3,0x7	/* Use bits [2..0] only */ +	beq	do_addr_mode +	cmpi	0,0,r6,1 +	bgt	spd_fail +	rlwimi	r7,r6,8,23,23 + +do_addr_mode: +	READ_SPD(4)		/* Get # of Column Addresses */ +	beq	spd_read_fail +	li	r5, ERR_ADDR_MODE +	andi.	r3,r3,0x0f	/* cut off reserved bits */ +	cmpi	0,0,r3,8 +	ble	spd_fail +	cmpi	0,0,r3,15 +	bgt	spd_fail +	addi	r6,r3,-8	/* calculate ADDR_MODE parameter */ +	rlwimi	r7,r6,4,24,27	/* set ADDR_MODE field */ + +set_dimm_ctrl: +#ifdef SDC_AUTOPRECH_EN +	oris	r7,r7,0x0001	/* set auto precharge EN bit */ +#endif +	ori	r7,r7,1		/* set ENABLE bit */ +	cmpi	0,0,r10,SPD_DIMM0 +	bne	1f +	stw	r7,SD_D0_CTRL(r4) +	sync +	b	set_dimm_bar +1: +	stw	r7,SD_D1_CTRL(r4) +	sync + + +	/* Program SDRAM DIMMx Base Address Register */ + +set_dimm_bar: +	READ_SPD(5)		/* get # of Ranks */ +	beq	spd_read_fail +	andi.	r7,r3,0x7 +	addi	r7,r7,1 +	READ_SPD(31)		/* Read DIMM rank density */ +	beq	spd_read_fail +	rlwinm	r5,r3,27,29,31 +	rlwinm	r6,r3,3,24,28 +	or	r5,r6,r5	/* r5 = Normalized Rank Density byte */ +	lis	r8, 0x0080	/* 128MB >> 4 */ +	mullw	r8,r8,r5	/* r8 = (rank_size >> 4) */ +	mullw	r8,r8,r7	/* r8 = (DIMM_size >> 4) */ +	neg	r7,r8 +	rlwinm	r7,r7,28,4,31 +	or	r7,r7,r11	/* set ADDR field */ +	rlwinm	r8,r8,12,20,31 +	add	r11,r11,r8	/* set Base Addr for next DIMM */ + +	cmpi	0,0,r10,SPD_DIMM0 +	bne	set_dimm1_size +	stw	r7,SD_D0_BAR(r4) +	sync +	li	r10,SPD_DIMM1 +	READ_SPD(0) +	bne do_each_dimm +	b spd_done + +set_dimm1_size: +	stw	r7,SD_D1_BAR(r4) +	sync +spd_done: +	blr + +check_next_slot: +	cmpi	0,0,r10,SPD_DIMM1 +	beq	spd_read_fail +	li	r10,SPD_DIMM1 +	b	do_first_dimm +spd_read_fail: +	ori	r3,r0,0xdead +	b	err_hung +spd_fail: +	li	r3,0x0bad +	sync +err_hung:	/* hang here for debugging */ +	nop +	nop +	b	err_hung + +#endif /* !SDC_HARDCODED_INIT */ diff --git a/board/mpc7448hpc2/config.mk b/board/mpc7448hpc2/config.mk new file mode 100644 index 000000000..2e58858c4 --- /dev/null +++ b/board/mpc7448hpc2/config.mk @@ -0,0 +1,28 @@ +# +# Copyright (c) 2005 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 +# + +# Flash address +TEXT_BASE = 0xFF000000 +# RAM address +#TEXT_BASE = 0x00400000 + +PLATFORM_CPPFLAGS += -DTEXT_BASE=$(TEXT_BASE) -maltivec -mabi=altivec -msoft-float diff --git a/board/mpc7448hpc2/mpc7448hpc2.c b/board/mpc7448hpc2/mpc7448hpc2.c new file mode 100644 index 000000000..d4a047c1d --- /dev/null +++ b/board/mpc7448hpc2/mpc7448hpc2.c @@ -0,0 +1,107 @@ +/* + * (C) Copyright 2005 Freescale Semiconductor, Inc. + * + * Roy Zang <tie-fei.zang@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 + * + * modifications for the Tsi108 Emul Board by avb@Tundra + */ + +/* + * board support/init functions for the + * Freescale MPC7448 HPC2 (High-Performance Computing 2 Platform). + */ + +#include <common.h> +#include <74xx_7xx.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +extern void ft_cpu_setup (void *blob, bd_t *bd); +#endif + +#undef	DEBUG + +extern void flush_data_cache (void); +extern void invalidate_l1_instruction_cache (void); +extern void tsi108_init_f (void); + +int display_mem_map (void); + +void after_reloc (ulong dest_addr) +{ +	DECLARE_GLOBAL_DATA_PTR; +	 +	/* +	 * Jump to the main U-Boot board init code +	 */ +	board_init_r ((gd_t *) gd, dest_addr); +	/* NOTREACHED */ +} + +/* + * Check Board Identity: + * report board type + */ + +int checkboard (void) +{ +	int l_type = 0; + +	printf ("BOARD: %s\n", CFG_BOARD_NAME); +	return (l_type); +} + +/* + * Read Processor ID: + * + * report calling processor number + */ + +int read_pid (void) +{ +	return 0;		/* we are on single CPU platform for a while */ +} + +long int dram_size (int board_type) +{ +	return 0x20000000;	/* 256M bytes */ +} + +long int initdram (int board_type) +{ +	return dram_size (board_type); +} + +#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) +void +ft_board_setup (void *blob, bd_t *bd) +{ +	u32 *p; +	int len; + +	ft_cpu_setup (blob, bd); + +	p = ft_get_prop (blob, "/memory/reg", &len); +	if (p != NULL) { +		*p++ = cpu_to_be32 (bd->bi_memstart); +		*p = cpu_to_be32 (bd->bi_memsize); +	} +} +#endif diff --git a/board/mpc7448hpc2/tsi108_init.c b/board/mpc7448hpc2/tsi108_init.c new file mode 100644 index 000000000..e3b09cfad --- /dev/null +++ b/board/mpc7448hpc2/tsi108_init.c @@ -0,0 +1,665 @@ +/***************************************************************************** + * (C) Copyright 2003;  Tundra Semiconductor Corp. + * + * 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 + *****************************************************************************/ + +/*---------------------------------------------------------------------------- + * FILENAME: tsi108_init.c + * + * Originator: Alex Bounine + * + * DESCRIPTION: + * Initialization code for the Tundra Tsi108 bridge chip + *---------------------------------------------------------------------------*/ + +#include <common.h> +#include <74xx_7xx.h> +#include <config.h> +#include <version.h> +#include <asm/processor.h> +#include <tsi108.h> + +extern void mpicInit (int verbose); + +/* + * Configuration Options + */ + +typedef struct { +	ulong upper; +	ulong lower; +} PB2OCN_LUT_ENTRY; + +PB2OCN_LUT_ENTRY pb2ocn_lut1[32] = { +	/* 0 - 7 */ +	{0x00000000, 0x00000201}, /* PBA=0xE000_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE100_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE200_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE300_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE400_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE500_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE600_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE700_0000 -> PCI/X (Byte-Swap) */ + +	/* 8 - 15 */ +	{0x00000000, 0x00000201}, /* PBA=0xE800_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xE900_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xEA00_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xEB00_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xEC00_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xED00_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xEE00_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xEF00_0000 -> PCI/X (Byte-Swap) */ + +	/* 16 - 23 */ +	{0x00000000, 0x00000201}, /* PBA=0xF000_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF100_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF200_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF300_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF400_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF500_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF600_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF700_0000 -> PCI/X (Byte-Swap) */ +	/* 24 - 31 */ +	{0x00000000, 0x00000201}, /* PBA=0xF800_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xF900_0000 -> PCI/X (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xFA00_0000 -> PCI/X  PCI I/O (Byte-Swap) */ +	{0x00000000, 0x00000201}, /* PBA=0xFB00_0000 -> PCI/X  PCI Config (Byte-Swap) */ + +	{0x00000000, 0x02000240}, /* PBA=0xFC00_0000 -> HLP */ +	{0x00000000, 0x01000240}, /* PBA=0xFD00_0000 -> HLP */ +	{0x00000000, 0x03000240}, /* PBA=0xFE00_0000 -> HLP */ +	{0x00000000, 0x00000240}  /* PBA=0xFF00_0000 -> HLP : (Translation Enabled + Byte-Swap)*/ +}; + +#ifdef CFG_CLK_SPREAD +typedef struct { +	ulong ctrl0; +	ulong ctrl1; +} PLL_CTRL_SET; + +/* + * Clock Generator SPLL0 initialization values + * PLL0 configuration table for various PB_CLKO freq. + * Uses pre-calculated values for Fs = 30 kHz, D = 0.5% + * Fout depends on required PB_CLKO. Based on Fref = 33 MHz + */ + +static PLL_CTRL_SET pll0_config[8] = { +	{0x00000000, 0x00000000},	/* 0: bypass */ +	{0x00000000, 0x00000000},	/* 1: reserved */ +	{0x00430044, 0x00000043},	/* 2: CG_PB_CLKO = 183 MHz */ +	{0x005c0044, 0x00000039},	/* 3: CG_PB_CLKO = 100 MHz */ +	{0x005c0044, 0x00000039},	/* 4: CG_PB_CLKO = 133 MHz */ +	{0x004a0044, 0x00000040},	/* 5: CG_PB_CLKO = 167 MHz */ +	{0x005c0044, 0x00000039},	/* 6: CG_PB_CLKO = 200 MHz */ +	{0x004f0044, 0x0000003e}	/* 7: CG_PB_CLKO = 233 MHz */ +}; +#endif	/* CFG_CLK_SPREAD */ + +/* + * Prosessor Bus Clock (in MHz) defined by CG_PB_SELECT + * (based on recommended Tsi108 reference clock 33MHz) + */ +static int pb_clk_sel[8] = { 0, 0, 183, 100, 133, 167, 200, 233 }; + +/* + * get_board_bus_clk () + * + * returns the bus clock in Hz. + */ +unsigned long get_board_bus_clk (void) +{ +	ulong i; + +	/* Detect PB clock freq. */ +	i = in32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PWRUP_STATUS); +	i = (i >> 16) & 0x07;	/* Get PB PLL multiplier */ + +	return pb_clk_sel[i] * 1000000; +} + +/* + * board_early_init_f () + * + * board-specific initialization executed from flash + */ + +int board_early_init_f (void) +{ +	DECLARE_GLOBAL_DATA_PTR; +	ulong i; + +	gd->mem_clk = 0; +	i = in32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + +			CG_PWRUP_STATUS); +	i = (i >> 20) & 0x07;	/* Get GD PLL multiplier */ +	switch (i) { +	case 0:	/* external clock */ +		printf ("Using external clock\n"); +		break; +	case 1:	/* system clock */ +		gd->mem_clk = gd->bus_clk; +		break; +	case 4:	/* 133 MHz */ +	case 5:	/* 166 MHz */ +	case 6:	/* 200 MHz */ +		gd->mem_clk = pb_clk_sel[i] * 1000000; +		break; +	default: +		printf ("Invalid DDR2 clock setting\n"); +		return -1; +	} +	printf ("BUS: %d MHz\n", get_board_bus_clk() / 1000000); +	printf ("MEM: %d MHz\n", gd->mem_clk / 1000000); +	return 0; +} + +/* + * board_early_init_r() - Tsi108 initialization function executed right after + * relocation. Contains code that cannot be executed from flash. + */ + +int board_early_init_r (void) +{ +	ulong temp, i; +	ulong reg_val; +	volatile ulong *reg_ptr; +	 +	reg_ptr = +		(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + 0x900); + +	for (i = 0; i < 32; i++) { +		*reg_ptr++ = 0x00000201;	/* SWAP ENABLED */ +		*reg_ptr++ = 0x00; +	} + +	__asm__ __volatile__ ("eieio"); +	__asm__ __volatile__ ("sync"); + +	/* Setup PB_OCN_BAR2: size 256B + ENable @ 0x0_80000000 */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR2, +		0x80000001); +	__asm__ __volatile__ ("sync"); + +	/* Make sure that OCN_BAR2 decoder is set (to allow following immediate +	 * read from SDRAM) +	 */ + +	temp = in32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR2); +	__asm__ __volatile__ ("sync"); + +	/* +	 * Remap PB_OCN_BAR1 to accomodate PCI-bus aperture and EPROM into the +	 * processor bus address space. Immediately after reset LUT and address +	 * translation are disabled for this BAR. Now we have to initialize LUT +	 * and switch from the BOOT mode to the normal operation mode. +	 * +	 * The aperture defined by PB_OCN_BAR1 startes at address 0xE0000000 +	 * and covers 512MB of address space. To allow larger aperture we also +	 * have to relocate register window of Tsi108 +	 * +	 * Initialize LUT (32-entries) prior switching PB_OCN_BAR1 from BOOT +	 * mode. +	 * +	 * initialize pointer to LUT associated with PB_OCN_BAR1 +	 */ +	reg_ptr = +		(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + 0x800); + +	for (i = 0; i < 32; i++) { +		*reg_ptr++ = pb2ocn_lut1[i].lower; +		*reg_ptr++ = pb2ocn_lut1[i].upper; +	} + +	__asm__ __volatile__ ("sync"); + +	/* Base addresses for CS0, CS1, CS2, CS3 */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_ADDR, +		0x00000000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_ADDR, +		0x00100000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_ADDR, +		0x00200000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_ADDR, +		0x00300000); +	__asm__ __volatile__ ("sync"); + +	/* Masks for HLP banks */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_MASK, +		0xFFF00000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_MASK, +		0xFFF00000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_MASK, +		0xFFF00000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_MASK, +		0xFFF00000); +	__asm__ __volatile__ ("sync"); + +	/* Set CTRL0 values for banks */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_CTRL0, +		0x7FFC44C2); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_CTRL0, +		0x7FFC44C0); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_CTRL0, +		0x7FFC44C0); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_CTRL0, +		0x7FFC44C2); +	__asm__ __volatile__ ("sync"); + +	/* Set banks to latched mode, enabled, and other default settings */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B0_CTRL1, +		0x7C0F2000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B1_CTRL1, +		0x7C0F2000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B2_CTRL1, +		0x7C0F2000); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_HLP_REG_OFFSET + HLP_B3_CTRL1, +		0x7C0F2000); +	__asm__ __volatile__ ("sync"); +	 +	/* +	 * Set new value for PB_OCN_BAR1: switch from BOOT to LUT mode. +	 * value for PB_OCN_BAR1: (BA-0xE000_0000 + size 512MB + ENable) +	 */ +	out32 (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR1, +		0xE0000011); +	__asm__ __volatile__ ("sync"); + +	/* Make sure that OCN_BAR2 decoder is set (to allow following +	 * immediate read from SDRAM) +	 */ +	 +	temp = in32(CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_OCN_BAR1); +	__asm__ __volatile__ ("sync"); + +	/* +	 * SRI: At this point we have enabled the HLP banks. That means we can +	 * now read from the NVRAM and initialize the environment variables. +	 * We will over-ride the env_init called in board_init_f +	 * This is really a work-around because, the HLP bank 1 +	 * where NVRAM resides is not visible during board_init_f +	 * (lib_ppc/board.c) +	 * Alternatively, we could use the I2C EEPROM at start-up to configure +	 * and enable all HLP banks and not just HLP 0 as is being done for +	 * Taiga Rev. 2. +	 */ +	 +	env_init (); + +#ifndef DISABLE_PBM +	 +	/* +	 * For IBM processors we have to set Address-Only commands generated +	 * by PBM that are different from ones set after reset. +	 */ + +	temp = get_cpu_type (); + +	if ((CPU_750FX == temp) || (CPU_750GX == temp)) +		out32 (CFG_TSI108_CSR_BASE + TSI108_PB_REG_OFFSET + PB_MCMD, +			0x00009955); +#endif	/* DISABLE_PBM */ + +#ifdef CONFIG_PCI +	/* +	 * Initialize PCI/X block +	 */ + +	/* Map PCI/X Configuration Space (16MB @ 0x0_FE000000) */ +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + +		PCI_PFAB_BAR0_UPPER, 0); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_BAR0, +		0xFB000001); +	__asm__ __volatile__ ("sync"); + +	/* Set Bus Number for the attached PCI/X bus (we will use 0 for NB) */ + +	temp =	in32(CFG_TSI108_CSR_BASE + +		TSI108_PCI_REG_OFFSET + PCI_PCIX_STAT); + +	temp &= ~0xFF00;	/* Clear the BUS_NUM field */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PCIX_STAT, +		temp); + +	/* Map PCI/X IO Space (64KB @ 0x0_FD000000) takes one 16MB LUT entry */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_IO_UPPER, +		0); +	__asm__ __volatile__ ("sync"); + +	/* This register is on the PCI side to interpret the address it receives +	 * and maps it as a IO address. +	 */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_PFAB_IO, +		0xFA000001); +	__asm__ __volatile__ ("sync"); + +	/* +	 * Map PCI/X Memory Space +	 * +	 * Transactions directed from OCM to PCI Memory Space are directed +	 * from PB to PCI +	 * unchanged (as defined by PB_OCN_BAR1,2 and LUT settings). +	 * If address remapping is required the corresponding PCI_PFAB_MEM32 +	 * and PCI_PFAB_PFMx register groups have to be configured. +	 * +	 * Map the path from the PCI/X bus into the system memory +	 * +	 * The memory mapped window assotiated with PCI P2O_BAR2 provides +	 * access to the system memory without address remapping. +	 * All system memory is opened for accesses initiated by PCI/X bus +	 * masters. +	 * +	 * Initialize LUT associated with PCI P2O_BAR2 +	 * +	 * set pointer to LUT associated with PCI P2O_BAR2 +	 */ + +	reg_ptr = +		(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + 0x500); + +#ifdef DISABLE_PBM + +	/* In case when PBM is disabled (no HW supported cache snoopng on PB) +	 * P2O_BAR2 is directly mapped into the system memory without address +	 * translation. +	 */ + +	reg_val = 0x00000004;	/* SDRAM port + NO Addr_Translation */ + +	for (i = 0; i < 32; i++) { +		*reg_ptr++ = reg_val;	/* P2O_BAR2_LUTx */ +		*reg_ptr++ = 0;		/* P2O_BAR2_LUT_UPPERx */ +	} + +	/* value for PCI BAR2 (size = 512MB, Enabled, No Addr. Translation) */ +	reg_val = 0x00007500; +#else + +	reg_val = 0x00000002;	/* Destination port = PBM */ + +	for (i = 0; i < 32; i++) { +		*reg_ptr++ = reg_val;	/* P2O_BAR2_LUTx */ +/* P2O_BAR2_LUT_UPPERx : Set data swapping mode for PBM (byte swapping) */ +		*reg_ptr++ = 0x40000000; +/* offset = 16MB, address translation is enabled to allow byte swapping */ +		reg_val += 0x01000000; +	} + +/* value for PCI BAR2 (size = 512MB, Enabled, Address Translation Enabled) */ +	reg_val = 0x00007100; +#endif + +	__asm__ __volatile__ ("eieio"); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_PAGE_SIZES, +		reg_val); +	__asm__ __volatile__ ("sync"); + +	/* Set 64-bit PCI bus address for system memory +	 * ( 0 is the best choice for easy mapping) +	 */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR2, +		0x00000000); +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR2_UPPER, +		0x00000000); +	__asm__ __volatile__ ("sync"); + +#ifndef DISABLE_PBM +	/* +	 *  The memory mapped window assotiated with PCI P2O_BAR3 provides +	 *  access to the system memory using SDRAM OCN port and address +	 *  translation. This is alternative way to access SDRAM from PCI +	 *  required for Tsi108 emulation testing. +	 *  All system memory is opened for accesses initiated by +	 *  PCI/X bus masters. +	 * +	 *  Initialize LUT associated with PCI P2O_BAR3 +	 * +	 *  set pointer to LUT associated with PCI P2O_BAR3 +	 */ +	reg_ptr = +		(ulong *) (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + 0x600); + +	reg_val = 0x00000004;	/* Destination port = SDC */ + +	for (i = 0; i < 32; i++) { +		*reg_ptr++ = reg_val;	/* P2O_BAR3_LUTx */ +		 +/* P2O_BAR3_LUT_UPPERx : Set data swapping mode for PBM (byte swapping) */ +		*reg_ptr++ = 0;	 +		 +/* offset = 16MB, address translation is enabled to allow byte swapping */ +		reg_val += 0x01000000; +	} + +	__asm__ __volatile__ ("eieio"); +	__asm__ __volatile__ ("sync"); + +	/* Configure PCI P2O_BAR3 (size = 512MB, Enabled) */ + +	reg_val = +		in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + +		 PCI_P2O_PAGE_SIZES); +	reg_val &= ~0x00FF; +	reg_val |= 0x0071; +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_PAGE_SIZES, +		reg_val); +	__asm__ __volatile__ ("sync"); + +	/* Set 64-bit base PCI bus address for window (0x20000000) */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR3_UPPER, +		0x00000000); +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR3, +		0x20000000); +	__asm__ __volatile__ ("sync"); + +#endif	/* !DISABLE_PBM */ + +#ifdef ENABLE_PCI_CSR_BAR	 +	/* open if required access to Tsi108 CSRs from the PCI/X bus */ +	/* enable BAR0 on the PCI/X bus */ +	reg_val = in32(CFG_TSI108_CSR_BASE + +		TSI108_PCI_REG_OFFSET + PCI_MISC_CSR); +	reg_val |= 0x02; +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_MISC_CSR, +		reg_val); +	__asm__ __volatile__ ("sync"); + +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR0_UPPER, +		0x00000000); +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_P2O_BAR0, +		CFG_TSI108_CSR_BASE); +	__asm__ __volatile__ ("sync"); + +#endif + +	/* +	 * Finally enable PCI/X Bus Master and Memory Space access +	 */ +	 +	reg_val = in32(CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_CSR); +	reg_val |= 0x06; +	out32 (CFG_TSI108_CSR_BASE + TSI108_PCI_REG_OFFSET + PCI_CSR, reg_val); +	__asm__ __volatile__ ("sync"); + +#endif	/* CONFIG_PCI */ + +	/* +	 * Initialize MPIC outputs (interrupt pins): +	 * Interrupt routing on the Grendel Emul. Board: +	 * PB_INT[0] -> INT (CPU0) +	 * PB_INT[1] -> INT (CPU1) +	 * PB_INT[2] -> MCP (CPU0) +	 * PB_INT[3] -> MCP (CPU1) +	 * Set interrupt controller outputs as Level_Sensitive/Active_Low +	 */ +	out32 (CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(0), 0x02); +	out32 (CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(1), 0x02); +	out32 (CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(2), 0x02); +	out32 (CFG_TSI108_CSR_BASE + TSI108_MPIC_REG_OFFSET + MPIC_CSR(3), 0x02); +	__asm__ __volatile__ ("sync"); + +	/* +	 * Ensure that Machine Check exception is enabled +	 * We need it to support PCI Bus probing (configuration reads) +	 */ +	 +	reg_val = mfmsr (); +	mtmsr(reg_val | MSR_ME); + +	return 0; +} + +/* + * Needed to print out L2 cache info + * used in the misc_init_r function + */ + +unsigned long get_l2cr (void) +{ +	unsigned long l2controlreg; +	asm volatile ("mfspr %0, 1017":"=r" (l2controlreg):); +	return l2controlreg; +} + +/* + * misc_init_r() + * + * various things to do after relocation + * + */ + +int misc_init_r (void) +{ +	DECLARE_GLOBAL_DATA_PTR; +#ifdef CFG_CLK_SPREAD	/* Initialize Spread-Spectrum Clock generation */ +	ulong i; + +	/* Ensure that Spread-Spectrum is disabled */ +	out32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0, 0); +	out32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, 0); + +	/* Initialize PLL1: CG_PCI_CLK , internal OCN_CLK +	 * Uses pre-calculated value for Fout = 800 MHz, Fs = 30 kHz, D = 0.5% +	 */ + +	out32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, +		0x002e0044);	/* D = 0.25% */ +	out32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL1, +		0x00000039);	/* BWADJ */ + +	/* Initialize PLL0: CG_PB_CLKO  */ +	/* Detect PB clock freq. */ +	i = in32(CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PWRUP_STATUS); +	i = (i >> 16) & 0x07;	/* Get PB PLL multiplier */ + +	out32 (CFG_TSI108_CSR_BASE + +		TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0, pll0_config[i].ctrl0); +	out32 (CFG_TSI108_CSR_BASE + +		TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL1, pll0_config[i].ctrl1); + +	/* Wait and set SSEN for both PLL0 and 1 */ +	udelay (1000); +	out32 (CFG_TSI108_CSR_BASE + TSI108_CLK_REG_OFFSET + CG_PLL1_CTRL0, +		0x802e0044);	/* D=0.25% */ +	out32 (CFG_TSI108_CSR_BASE + +		TSI108_CLK_REG_OFFSET + CG_PLL0_CTRL0, +	 	0x80000000 | pll0_config[i].ctrl0); +#endif	/* CFG_CLK_SPREAD */ + +#ifdef CFG_L2 +	l2cache_enable (); +#endif +	printf ("BUS:   %d MHz\n", gd->bus_clk / 1000000); +	printf ("MEM:   %d MHz\n", gd->mem_clk / 1000000); + +	/* +	 * All the information needed to print the cache details is avaiblable +	 * at this point i.e. above call to l2cache_enable is the very last +	 * thing done with regards to enabling diabling the cache. +	 * So this seems like a good place to print all this information +	 */ +	 +	printf ("CACHE: "); +	switch (get_cpu_type()) { +	case CPU_7447A: +		printf ("L1 Instruction cache - 32KB 8-way"); +		(get_hid0 () & (1 << 15)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		printf ("L1 Data cache - 32KB 8-way"); +		(get_hid0 () & (1 << 14)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		printf ("Unified L2 cache - 512KB 8-way"); +		(get_l2cr () & (1 << 31)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		printf ("\n"); +		break; + +	case CPU_7448: +		printf ("L1 Instruction cache - 32KB 8-way"); +		(get_hid0 () & (1 << 15)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		printf ("L1 Data cache - 32KB 8-way"); +		(get_hid0 () & (1 << 14)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		printf ("Unified L2 cache - 1MB 8-way"); +		(get_l2cr () & (1 << 31)) ? printf (" ENABLED\n") : +			printf (" DISABLED\n"); +		break; +	default: +		break; +	} +	return 0; +} diff --git a/board/mpc7448hpc2/u-boot.lds b/board/mpc7448hpc2/u-boot.lds new file mode 100644 index 000000000..8f24213fc --- /dev/null +++ b/board/mpc7448hpc2/u-boot.lds @@ -0,0 +1,136 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * u-boot.lds - linker script for U-Boot on mpc7448hpc2 Board. + */ + +OUTPUT_ARCH(powerpc) +SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/local/powerpc-any-elf/lib); +/* Do we need any of these for elf? +   __DYNAMIC = 0;    */ +SECTIONS +{ +  /* Read-only sections, merged into text segment: */ +  . = + SIZEOF_HEADERS; +  .interp : { *(.interp) } +  .hash          : { *(.hash)		} +  .dynsym        : { *(.dynsym)		} +  .dynstr        : { *(.dynstr)		} +  .rel.text      : { *(.rel.text)		} +  .rela.text     : { *(.rela.text) 	} +  .rel.data      : { *(.rel.data)		} +  .rela.data     : { *(.rela.data) 	} +  .rel.rodata    : { *(.rel.rodata) 	} +  .rela.rodata   : { *(.rela.rodata) 	} +  .rel.got       : { *(.rel.got)		} +  .rela.got      : { *(.rela.got)		} +  .rel.ctors     : { *(.rel.ctors)	} +  .rela.ctors    : { *(.rela.ctors)	} +  .rel.dtors     : { *(.rel.dtors)	} +  .rela.dtors    : { *(.rela.dtors)	} +  .rel.bss       : { *(.rel.bss)		} +  .rela.bss      : { *(.rela.bss)		} +  .rel.plt       : { *(.rel.plt)		} +  .rela.plt      : { *(.rela.plt)		} +  .init          : { *(.init)	} +  .plt : { *(.plt) } +  .text      : +  { +    cpu/74xx_7xx/start.o	(.text) + +/* store the environment in a seperate sector in the boot flash */ +/*    . = env_offset; */ +/*    common/environment.o(.text) */ + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +  } +  .fini      : { *(.fini)    } =0 +  .ctors     : { *(.ctors)   } +  .dtors     : { *(.dtors)   } + +  /* Read-write section, merged into data segment: */ +  . = (. + 0x00FF) & 0xFFFFFF00; +  _erotext = .; +  PROVIDE (erotext = .); +  .reloc   : +  { +    *(.got) +    _GOT2_TABLE_ = .; +    *(.got2) +    _FIXUP_TABLE_ = .; +    *(.fixup) +  } +  __got2_entries = (_FIXUP_TABLE_ - _GOT2_TABLE_) >>2; +  __fixup_entries = (. - _FIXUP_TABLE_)>>2; + +  .data    : +  { +    *(.data) +    *(.data1) +    *(.sdata) +    *(.sdata2) +    *(.dynamic) +    CONSTRUCTORS +  } +  _edata  =  .; +  PROVIDE (edata = .); + +  . = .; +  __u_boot_cmd_start = .; +  .u_boot_cmd : { *(.u_boot_cmd) } +  __u_boot_cmd_end = .; + +  . = .; +  __start___ex_table = .; +  __ex_table : { *(__ex_table) } +  __stop___ex_table = .; + +  . = ALIGN(256); +  __init_begin = .; +  .text.init : { *(.text.init) } +  .data.init : { *(.data.init) } +  . = ALIGN(256); +  __init_end = .; + +  __bss_start = .; +  .bss       : +  { +   *(.sbss) *(.scommon) +   *(.dynbss) +   *(.bss) +   *(COMMON) +  } +  _end = . ; +  PROVIDE (end = .); +} diff --git a/cpu/74xx_7xx/cpu.c b/cpu/74xx_7xx/cpu.c index f4e5fc504..84d5da311 100644 --- a/cpu/74xx_7xx/cpu.c +++ b/cpu/74xx_7xx/cpu.c @@ -44,6 +44,10 @@  #include <74xx_7xx.h>  #include <asm/cache.h> +#if defined(CONFIG_OF_FLAT_TREE) +#include <ft_build.h> +#endif +  #ifdef CONFIG_AMIGAONEG3SE  #include "../board/MAI/AmigaOneG3SE/via686.h"  #include "../board/MAI/AmigaOneG3SE/memio.h" @@ -101,6 +105,10 @@ get_cpu_type(void)  		type = CPU_7457;  		break; +	case 0x8003: +		type = CPU_7447A; +		break; +  	case 0x8004:  		type = CPU_7448;  		break; @@ -156,6 +164,10 @@ int checkcpu (void)  		str = "MPC7410";  		break; +	case CPU_7447A: +		str = "MPC7447A"; +		break; +  	case CPU_7448:  		str = "MPC7448";  		break; @@ -264,20 +276,19 @@ do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  /*   * For the 7400 the TB clock runs at 1/4 the cpu bus speed.   */ -#ifdef CONFIG_AMIGAONEG3SE +#if defined(CONFIG_AMIGAONEG3SE) || defined(CFG_CONFIG_BUS_CLK)  unsigned long get_tbclk(void)  {  	return (gd->bus_clk / 4);  } -#else	/* ! CONFIG_AMIGAONEG3SE */ +#else	/* ! CONFIG_AMIGAONEG3SE and !CFG_CONFIG_BUS_CLK*/  unsigned long get_tbclk (void)  {  	return CFG_BUS_HZ / 4;  } -#endif	/* CONFIG_AMIGAONEG3SE */ +#endif	/* CONFIG_AMIGAONEG3SE or CFG_CONFIG_BUS_CLK*/  /* ------------------------------------------------------------------------- */ -  #if defined(CONFIG_WATCHDOG)  #if !defined(CONFIG_PCIPPC2) && !defined(CONFIG_BAB7xx)  void @@ -289,3 +300,30 @@ watchdog_reset(void)  #endif	/* CONFIG_WATCHDOG */  /* ------------------------------------------------------------------------- */ + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_cpu_setup (void *blob, bd_t *bd) +{ +	u32 *p; +	ulong clock; +	int len; +		 +	clock = bd->bi_busfreq; +	 +	p = ft_get_prop (blob, "/cpus/" OF_CPU "/bus-frequency", &len); +	if (p != NULL) +		*p = cpu_to_be32 (clock); + +#if defined(CONFIG_TSI108_ETH) +	p = ft_get_prop (blob, "/" OF_TSI "/ethernet@6200/address", &len); +		memcpy (p, bd->bi_enetaddr, 6); +#endif + +#if defined(CONFIG_HAS_ETH1) +	p = ft_get_prop (blob, "/" OF_TSI "/ethernet@6600/address", &len); +		memcpy (p, bd->bi_enet1addr, 6); +#endif +} +#endif +/* ------------------------------------------------------------------------- */ diff --git a/cpu/74xx_7xx/cpu_init.c b/cpu/74xx_7xx/cpu_init.c index e02a4cc21..1dd1b2cd8 100644 --- a/cpu/74xx_7xx/cpu_init.c +++ b/cpu/74xx_7xx/cpu_init.c @@ -43,6 +43,7 @@ cpu_init_f (void)  	case CPU_7450:  	case CPU_7455:  	case CPU_7457: +	case CPU_7447A:  	case CPU_7448:  		/* enable the timebase bit in HID0 */  		set_hid0(get_hid0() | 0x4000000); diff --git a/cpu/74xx_7xx/speed.c b/cpu/74xx_7xx/speed.c index d1800ede0..d8c40cea0 100644 --- a/cpu/74xx_7xx/speed.c +++ b/cpu/74xx_7xx/speed.c @@ -31,6 +31,8 @@  DECLARE_GLOBAL_DATA_PTR; +extern unsigned long get_board_bus_clk (void); +  static const int hid1_multipliers_x_10[] = {  	25,	/* 0000 - 2.5x */  	75,	/* 0001 - 7.5x */ @@ -50,6 +52,42 @@ static const int hid1_multipliers_x_10[] = {  	0	/* 1111 - off */  }; +/* PLL_CFG[0:4] table for cpu 7448/7447A/7455/7457 */ +static const int hid1_74xx_multipliers_x_10[] = { +	115,	/* 00000 - 11.5x  */ +	170,	/* 00001 - 17x    */ +	75,	/* 00010 -  7.5x  */ +	150,	/* 00011 - 15x    */ +	70,	/* 00100 -  7x    */ +	180,	/* 00101 - 18x    */ +	10,	/* 00110 - bypass */ +	200,	/* 00111 - 20x    */ +	20,	/* 01000 -  2x    */ +	210,	/* 01001 - 21x    */ +	65,	/* 01010 -  6.5x  */ +	130,	/* 01011 - 13x    */ +	85,	/* 01100 -  8.5x  */ +	240,	/* 01101 - 24x    */ +	95,	/* 01110 -  9.5x  */ +	90,	/* 01111 -  9x    */ +	30,	/* 10000 -  3x    */ +	105,	/* 10001 - 10.5x  */ +	55,	/* 10010 -  5.5x  */ +	110,	/* 10011 - 11x    */ +	40,	/* 10100 -  4x    */ +	100,	/* 10101 - 10x    */ +	50,	/* 10110 -  5x    */ +	120,	/* 10111 - 12x    */ +	80,	/* 11000 -  8x    */ +	140,	/* 11001 - 14x    */ +	60,	/* 11010 -  6x    */ +	160,	/* 11011 - 16x    */ +	135,	/* 11100 - 13.5x  */ +	280,	/* 11101 - 28x    */ +	0,	/* 11110 - off    */ +	125	/* 11111 - 12.5x  */ +}; +  static const int hid1_fx_multipliers_x_10[] = {  	00,	/* 0000 - off */  	00,	/* 0001 - off */ @@ -89,22 +127,30 @@ int get_clocks (void)  {  	ulong clock = 0; +#ifdef CFG_BUS_CLK +	gd->bus_clk = CFG_BUS_CLK;	/* bus clock is a fixed frequency */ +#else +	gd->bus_clk = get_board_bus_clk ();	/* bus clock is configurable */ +#endif +  	/* calculate the clock frequency based upon the CPU type */  	switch (get_cpu_type()) { +	case CPU_7447A:  	case CPU_7448:  	case CPU_7455:  	case CPU_7457:  		/* -		 * It is assumed that the PLL_EXT line is zero.  		 * Make sure division is done before multiplication to prevent 32-bit  		 * arithmetic overflows which will cause a negative number  		 */ -		clock = (CFG_BUS_CLK / 10) * hid1_multipliers_x_10[(get_hid1 () >> 13) & 0xF]; +		clock = (gd->bus_clk / 10) * +			hid1_74xx_multipliers_x_10[(get_hid1 () >> 12) & 0x1F];  		break;  	case CPU_750GX:  	case CPU_750FX: -		clock = CFG_BUS_CLK * hid1_fx_multipliers_x_10[get_hid1 () >> 27] / 10; +		clock = gd->bus_clk * +			hid1_fx_multipliers_x_10[get_hid1 () >> 27] / 10;  		break;  	case CPU_7450: @@ -121,7 +167,8 @@ int get_clocks (void)  		 * Make sure division is done before multiplication to prevent 32-bit  		 * arithmetic overflows which will cause a negative number  		 */ -		clock = (CFG_BUS_CLK / 10) * hid1_multipliers_x_10[get_hid1 () >> 28]; +		clock = (gd->bus_clk / 10) * +			hid1_multipliers_x_10[get_hid1 () >> 28];  		break;  	case CPU_UNKNOWN: @@ -131,7 +178,6 @@ int get_clocks (void)  	}  	gd->cpu_clk = clock; -	gd->bus_clk = CFG_BUS_CLK;  	return (0);  } diff --git a/doc/README.mpc7448hpc2 b/doc/README.mpc7448hpc2 new file mode 100644 index 000000000..0e40e3926 --- /dev/null +++ b/doc/README.mpc7448hpc2 @@ -0,0 +1,185 @@ +Freescale MPC7448hpc2 (Taiga) board +=================================== + +Created 08/11/2006 Roy Zang +-------------------------- +MPC7448hpc2 (Taiga) board is a high-performance PowerPC server reference +design, which is optimized for high speed throughput between the processor and +the memory, disk drive and Ethernet port subsystems. + +MPC7448hpc2(Taiga) is designed to the micro-ATX chassis, allowing it to be +used in 1U or 2U rack-mount chassis¡¯, as well as in standard ATX/Micro-ATX +chassis. + +Building U-Boot +------------------ +The mpc7448hpc2 code base is known to compile using: +	Binutils 2.15, Gcc 3.4.3, Glibc 2.3.3 + +	$ make mpc7448hpc2_config +	Configuring for mpc7448hpc2 board... + +	$ make + +Memory Map +---------- + +The memory map is setup for Linux to operate properly. + +The mapping is: + +	Range Start	Range End	Definition			Size + +	0x0000_0000	0x7fff_ffff	DDR				2G +	0xe000_0000	0xe7ff_ffff	PCI Memory			128M +	0xfa00_0000	0xfaff_ffff	PCI IO				16M +	0xfb00_0000	0xfbff_ffff	PCI Config			16M +	0xfc00_0000	0xfc0f_ffff	NVRAM/CADMUS			1M +	0xfe00_0000	0xfeff_ffff	PromJet				16M +	0xff00_0000	0xff80_0000	FLASH (boot flash)		8M +	0xff80_0000	0xffff_ffff	FLASH (second half flash)	8M + +Using Flash +----------- + +The MPC7448hpc2 board has two "banks" of flash, each 8MB in size +(2^23 = 0x00800000). + +Note: the "bank" here refers to half of the flash. In fact, there is only one +bank of flash, which is divided into low and high half. Each is controlled by +the most significant bit of the address bus. The so called "bank" is only for +convenience. + +There is a switch which allows the "bank" to be selected.  The switch +settings for updating flash are given below. + +The u-boot commands for copying the boot-bank into the secondary bank are +as follows: + +	erase ff800000 ff880000 +	cp.b ff000000 ff800000 80000 + +U-boot commands for downloading an image via tftp and flashing +it into the secondary bank: + +	tftp 10000 <u-boot.bin.image> +	erase ff000000 ff080000 +	cp.b 10000 ff000000 80000 + +After copying the image into the second bank of flash, be sure to toggle +SW3[4] on board before resetting the board in order to set the +secondary bank as the boot-bank. + +Board Switches +---------------------- + +Most switches on the board should not be changed.  The most frequent +user-settable switches on the board are used to configure +the flash banks and determining the PCI frequency. + +SW1[1-5]: Processor core voltage + +	12345		Core Voltage +	----- +	SW1=01111	1.000V. +	SW1=01101	1.100V. +	SW1=01011	1.200V. +	SW1=01001	1.300V only for MPC7447A. + + +SW2[1-6]: CPU core frequency + +		CPU Core Frequency (MHz) +			Bus Frequency +	123456		100	133	167	200	Ratio +	 +	------ +	SW2=101100	500	667	833	1000	5x +	SW2=100100	550	733	917	1100	5.5x +	SW2=110100	600	800	1000	1200	6x +	SW2=010100	650	866	1083	1300	6.5x +	SW2=001000	700	930	1167	1400	7x +	SW2=000100	750	1000	1250	1500	7.5x +	SW2=110000	800	1066	1333	1600	8x +	SW2=011000	850	1333	1417	1700	8.5x only for MPC7447A +	SW2=011110	900	1200	1500	1800	9x + +This table shows only a subset of available frequency options; see the CPU +hardware specifications for more information. + +SW2[7-8]: Bus Protocol and CPU Reset Option + +	7		 +	- +	SW2=0		System bus uses MPX bus protocol +	SW2=1		System bus uses 60x bus protocol + +	8		 +	- +	SW2=0		TSI108 can cause CPU reset +	SW2=1		TSI108 can not cause CPU reset + +SW3[1-8] system options + +	123		 +	--- +	SW3=xxx		Connected to GPIO[0:2] on TSI108 + +	4		 +	- +	SW3=0		CPU boots from low half of flash +	SW3=1		CPU boots from high half of flash + +	5		 +	- +	SW3=0		SATA and slot2 connected to PCI bus +	SW3=1		Only slot1 connected to PCI bus + +	6		 +	- +	SW3=0		USB connected to PCI bus +	SW3=1		USB disconnected from PCI bus + +	7		 +	- +	SW3=0		Flash is write protected +	SW3=1		Flash is NOT write protected + +	8		 +	- +	SW3=0		CPU will boot from flash +	SW3=1		CPU will boot from PromJet + +SW4[1-3]: System bus frequency + +			Bus Frequency (MHz) +	--- +	SW4=010			183 +	SW4=011			100 +	SW4=100			133 +	SW4=101			166 only for MPC7447A +	SW4=110			200 only for MPC7448 +	others			reserved + +SW4[4-6]: DDR2 SDRAM frequency + +			Bus Frequency (MHz) +	--- +	SW4=000		external clock +	SW4=011		system clock	 +	SW4=100		133 +	SW4=101		166 +	SW4=110		200 +	others		reserved + +SW4[7-8]: PCI/PCI-X frequency control +	7		 +	- +	SW4=0		PCI/PCI-X bus operates normally +	SW4=1		PCI bus forced to PCI-33 mode + +	8		 +	- +	SW4=0		PCI-X mode at 133 MHz allowed +	SW4=1		PCI-X mode limited to 100 MHz + diff --git a/drivers/Makefile b/drivers/Makefile index 5a369df2c..6a3ea5da2 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -35,8 +35,8 @@ COBJS	= 3c589.o 5701rls.o ali512x.o atmel_usart.o \  	  lan91c96.o \  	  natsemi.o ne2000.o netarm_eth.o netconsole.o \  	  ns16550.o ns8382x.o ns87308.o ns7520_eth.o omap1510_i2c.o \ -	  omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o \ -	  pcnet.o plb2800_eth.o \ +	  omap24xx_i2c.o pci.o pci_auto.o pci_indirect.o tsi108_pci.o\ +	  tsi108_i2c.o pcnet.o plb2800_eth.o \  	  ps2ser.o ps2mult.o pc_keyb.o \  	  rtl8019.o rtl8139.o rtl8169.o \  	  s3c4510b_eth.o s3c4510b_uart.o \ @@ -45,7 +45,7 @@ COBJS	= 3c589.o 5701rls.o ali512x.o atmel_usart.o \  	  serial_pl010.o serial_pl011.o serial_xuartlite.o \  	  sl811_usb.o sm501.o smc91111.o smiLynxEM.o \  	  status_led.o sym53c8xx.o ahci.o \ -	  ti_pci1410a.o tigon3.o tsec.o \ +	  ti_pci1410a.o tigon3.o tsec.o tsi108_eth.o\  	  usbdcore.o usbdcore_ep0.o usbdcore_omap1510.o usbtty.o \  	  videomodes.o w83c553f.o \  	  ks8695eth.o \ diff --git a/drivers/cfi_flash.c b/drivers/cfi_flash.c index 2699cce85..a834cb4cf 100644 --- a/drivers/cfi_flash.c +++ b/drivers/cfi_flash.c @@ -2,7 +2,7 @@   * (C) Copyright 2002-2004   * Brad Kemp, Seranoa Networks, Brad.Kemp@seranoa.com   * - * Copyright (C) 2003 Arabella Software Ltd. + * Copyright (C) 2003, 2006 Arabella Software Ltd.   * Yuli Barcohen <yuli@arabellasw.com>   *   * Copyright (C) 2004 @@ -35,10 +35,13 @@  /* #define DEBUG	*/  #include <common.h> + +#ifdef	CFG_FLASH_CFI_DRIVER + +#include <watchdog.h>  #include <asm/processor.h>  #include <asm/byteorder.h>  #include <environment.h> -#ifdef	CFG_FLASH_CFI_DRIVER  /*   * This file implements a Common Flash Interface (CFI) driver for U-Boot. @@ -56,6 +59,10 @@   *   */ +#if defined(__LITTLE_ENDIAN) && !defined(CFG_FLASH_CFI_SWAP) +#define CFG_FLASH_CFI_SWAP +#endif +  #ifndef CFG_FLASH_BANKS_LIST  #define CFG_FLASH_BANKS_LIST { CFG_FLASH_BASE }  #endif @@ -256,7 +263,7 @@ inline uchar flash_read_uchar (flash_info_t * info, uint offset)  	uchar *cp;  	cp = flash_make_addr (info, 0, offset); -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP)  	return (cp[0]);  #else  	return (cp[info->portwidth - 1]); @@ -283,7 +290,7 @@ ushort flash_read_ushort (flash_info_t * info, flash_sect_t sect, uint offset)  		debug ("addr[%x] = 0x%x\n", x, addr[x]);  	}  #endif -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP)  	retval = ((addr[(info->portwidth)] << 8) | addr[0]);  #else  	retval = ((addr[(2 * info->portwidth) - 1] << 8) | @@ -315,7 +322,7 @@ ulong flash_read_long (flash_info_t * info, flash_sect_t sect, uint offset)  		debug ("addr[%x] = 0x%x\n", x, addr[x]);  	}  #endif -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP)  	retval = (addr[0] << 16) | (addr[(info->portwidth)] << 24) |  		(addr[(2 * info->portwidth)]) | (addr[(3 * info->portwidth)] << 8);  #else @@ -905,12 +912,22 @@ static void flash_make_cmd (flash_info_t * info, uchar cmd, void *cmdbuf)  	int i;  	uchar *cp = (uchar *) cmdbuf; -#if defined(__LITTLE_ENDIAN) +#if defined(CFG_FLASH_CFI_SWAP)  	for (i = info->portwidth; i > 0; i--)  #else  	for (i = 1; i <= info->portwidth; i++)  #endif  		*cp++ = (i & (info->chipwidth - 1)) ? '\0' : cmd; +#ifdef CFG_FLASH_CFI_2x16 +	if ((info->portwidth == FLASH_CFI_32BIT) && (info->chipwidth == FLASH_CFI_BY16)) +	{ +	   uchar tmp; +	   cp = (uchar *) cmdbuf; +	   tmp = cp[1]; +	   cp[1] = cp[2]; +	   cp[2] = tmp; +	} +#endif /* CFG_FLASH_CFI_2x16 */  }  /* diff --git a/drivers/tsi108_eth.c b/drivers/tsi108_eth.c new file mode 100644 index 000000000..47341bee7 --- /dev/null +++ b/drivers/tsi108_eth.c @@ -0,0 +1,1036 @@ +/*********************************************************************** + * + * Copyright (c) 2005 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 + * + * Description: + *   Ethernet interface for Tundra TSI108 bridge chip + * + ***********************************************************************/ + +#include <config.h> + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ +	&& defined(CONFIG_TSI108_ETH) + +#if !defined(CONFIG_TSI108_ETH_NUM_PORTS) || (CONFIG_TSI108_ETH_NUM_PORTS > 2) +#error "CONFIG_TSI108_ETH_NUM_PORTS must be defined as 1 or 2" +#endif + +#include <common.h> +#include <malloc.h> +#include <net.h> +#include <asm/cache.h> + +#ifdef DEBUG +#define TSI108_ETH_DEBUG 7 +#else +#define TSI108_ETH_DEBUG 0 +#endif + +#if TSI108_ETH_DEBUG > 0 +#define debug_lev(lev, fmt, args...) \ +if (lev <= TSI108_ETH_DEBUG) \ +printf ("%s %d: " fmt, __FUNCTION__, __LINE__, ##args) +#else +#define debug_lev(lev, fmt, args...) do{}while(0) +#endif + +#define RX_PRINT_ERRORS +#define TX_PRINT_ERRORS + +#define ETH_BASE	(CFG_TSI108_CSR_BASE + 0x6000) + +#define ETH_PORT_OFFSET	0x400 + +#define __REG32(base, offset) (*((volatile u32 *)((char *)(base) + (offset)))) + +#define reg_MAC_CONFIG_1(base)		__REG32(base, 0x00000000) +#define MAC_CONFIG_1_TX_ENABLE		(0x00000001) +#define MAC_CONFIG_1_SYNC_TX_ENABLE	(0x00000002) +#define MAC_CONFIG_1_RX_ENABLE		(0x00000004) +#define MAC_CONFIG_1_SYNC_RX_ENABLE	(0x00000008) +#define MAC_CONFIG_1_TX_FLOW_CONTROL	(0x00000010) +#define MAC_CONFIG_1_RX_FLOW_CONTROL	(0x00000020) +#define MAC_CONFIG_1_LOOP_BACK		(0x00000100) +#define MAC_CONFIG_1_RESET_TX_FUNCTION	(0x00010000) +#define MAC_CONFIG_1_RESET_RX_FUNCTION	(0x00020000) +#define MAC_CONFIG_1_RESET_TX_MAC	(0x00040000) +#define MAC_CONFIG_1_RESET_RX_MAC	(0x00080000) +#define MAC_CONFIG_1_SIM_RESET		(0x40000000) +#define MAC_CONFIG_1_SOFT_RESET		(0x80000000) + +#define reg_MAC_CONFIG_2(base)		__REG32(base, 0x00000004) +#define MAC_CONFIG_2_FULL_DUPLEX	(0x00000001) +#define MAC_CONFIG_2_CRC_ENABLE		(0x00000002) +#define MAC_CONFIG_2_PAD_CRC		(0x00000004) +#define MAC_CONFIG_2_LENGTH_CHECK	(0x00000010) +#define MAC_CONFIG_2_HUGE_FRAME		(0x00000020) +#define MAC_CONFIG_2_INTERFACE_MODE(val)	(((val) & 0x3) << 8) +#define MAC_CONFIG_2_PREAMBLE_LENGTH(val)	(((val) & 0xf) << 12) +#define INTERFACE_MODE_NIBBLE		1	/* 10/100 Mb/s MII) */ +#define INTERFACE_MODE_BYTE		2	/* 1000 Mb/s GMII/TBI */ + +#define reg_MAXIMUM_FRAME_LENGTH(base)		__REG32(base, 0x00000010) + +#define reg_MII_MGMT_CONFIG(base)		__REG32(base, 0x00000020) +#define MII_MGMT_CONFIG_MGMT_CLOCK_SELECT(val)	((val) & 0x7) +#define MII_MGMT_CONFIG_NO_PREAMBLE		(0x00000010) +#define MII_MGMT_CONFIG_SCAN_INCREMENT		(0x00000020) +#define MII_MGMT_CONFIG_RESET_MGMT		(0x80000000) + +#define reg_MII_MGMT_COMMAND(base)		__REG32(base, 0x00000024) +#define MII_MGMT_COMMAND_READ_CYCLE		(0x00000001) +#define MII_MGMT_COMMAND_SCAN_CYCLE		(0x00000002) + +#define reg_MII_MGMT_ADDRESS(base)		__REG32(base, 0x00000028) +#define reg_MII_MGMT_CONTROL(base)		__REG32(base, 0x0000002c) +#define reg_MII_MGMT_STATUS(base)		__REG32(base, 0x00000030) + +#define reg_MII_MGMT_INDICATORS(base)		__REG32(base, 0x00000034) +#define MII_MGMT_INDICATORS_BUSY		(0x00000001) +#define MII_MGMT_INDICATORS_SCAN		(0x00000002) +#define MII_MGMT_INDICATORS_NOT_VALID		(0x00000004) + +#define reg_INTERFACE_STATUS(base)		__REG32(base, 0x0000003c) +#define INTERFACE_STATUS_LINK_FAIL		(0x00000008) +#define INTERFACE_STATUS_EXCESS_DEFER		(0x00000200) + +#define reg_STATION_ADDRESS_1(base)		__REG32(base, 0x00000040) +#define reg_STATION_ADDRESS_2(base)		__REG32(base, 0x00000044) + +#define reg_PORT_CONTROL(base)			__REG32(base, 0x00000200) +#define PORT_CONTROL_PRI		(0x00000001) +#define PORT_CONTROL_BPT		(0x00010000) +#define PORT_CONTROL_SPD		(0x00040000) +#define PORT_CONTROL_RBC		(0x00080000) +#define PORT_CONTROL_PRB		(0x00200000) +#define PORT_CONTROL_DIS		(0x00400000) +#define PORT_CONTROL_TBI		(0x00800000) +#define PORT_CONTROL_STE		(0x10000000) +#define PORT_CONTROL_ZOR		(0x20000000) +#define PORT_CONTROL_CLR		(0x40000000) +#define PORT_CONTROL_SRT		(0x80000000) + +#define reg_TX_CONFIG(base)		__REG32(base, 0x00000220) +#define TX_CONFIG_START_Q		(0x00000003) +#define TX_CONFIG_EHP			(0x00400000) +#define TX_CONFIG_CHP			(0x00800000) +#define TX_CONFIG_RST			(0x80000000) + +#define reg_TX_CONTROL(base)		__REG32(base, 0x00000224) +#define TX_CONTROL_GO			(0x00008000) +#define TX_CONTROL_MP			(0x01000000) +#define TX_CONTROL_EAI			(0x20000000) +#define TX_CONTROL_ABT			(0x40000000) +#define TX_CONTROL_EII			(0x80000000) + +#define reg_TX_STATUS(base)		__REG32(base, 0x00000228) +#define TX_STATUS_QUEUE_USABLE		(0x0000000f) +#define TX_STATUS_CURR_Q		(0x00000300) +#define TX_STATUS_ACT			(0x00008000) +#define TX_STATUS_QUEUE_IDLE		(0x000f0000) +#define TX_STATUS_EOQ_PENDING		(0x0f000000) + +#define reg_TX_EXTENDED_STATUS(base)		__REG32(base, 0x0000022c) +#define TX_EXTENDED_STATUS_END_OF_QUEUE_CONDITION		(0x0000000f) +#define TX_EXTENDED_STATUS_END_OF_FRAME_CONDITION		(0x00000f00) +#define TX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION	(0x000f0000) +#define TX_EXTENDED_STATUS_ERROR_FLAG				(0x0f000000) + +#define reg_TX_THRESHOLDS(base)			__REG32(base, 0x00000230) + +#define reg_TX_DIAGNOSTIC_ADDR(base)           __REG32(base, 0x00000270) +#define TX_DIAGNOSTIC_ADDR_INDEX		(0x0000007f) +#define TX_DIAGNOSTIC_ADDR_DFR			(0x40000000) +#define TX_DIAGNOSTIC_ADDR_AI			(0x80000000) + +#define reg_TX_DIAGNOSTIC_DATA(base)		__REG32(base, 0x00000274) + +#define reg_TX_ERROR_STATUS(base)		__REG32(base, 0x00000278) +#define TX_ERROR_STATUS				(0x00000278) +#define TX_ERROR_STATUS_QUEUE_0_ERROR_RESPONSE	(0x0000000f) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_0		(0x00000010) +#define TX_ERROR_STATUS_RER_ON_QUEUE_0		(0x00000020) +#define TX_ERROR_STATUS_TER_ON_QUEUE_0		(0x00000040) +#define TX_ERROR_STATUS_DER_ON_QUEUE_0		(0x00000080) +#define TX_ERROR_STATUS_QUEUE_1_ERROR_RESPONSE	(0x00000f00) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_1		(0x00001000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_1		(0x00002000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_1		(0x00004000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_1		(0x00008000) +#define TX_ERROR_STATUS_QUEUE_2_ERROR_RESPONSE	(0x000f0000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_2		(0x00100000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_2		(0x00200000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_2		(0x00400000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_2		(0x00800000) +#define TX_ERROR_STATUS_QUEUE_3_ERROR_RESPONSE	(0x0f000000) +#define TX_ERROR_STATUS_TEA_ON_QUEUE_3		(0x10000000) +#define TX_ERROR_STATUS_RER_ON_QUEUE_3		(0x20000000) +#define TX_ERROR_STATUS_TER_ON_QUEUE_3		(0x40000000) +#define TX_ERROR_STATUS_DER_ON_QUEUE_3		(0x80000000) + +#define reg_TX_QUEUE_0_CONFIG(base)		__REG32(base, 0x00000280) +#define TX_QUEUE_0_CONFIG_OCN_PORT		(0x0000003f) +#define TX_QUEUE_0_CONFIG_BSWP			(0x00000400) +#define TX_QUEUE_0_CONFIG_WSWP			(0x00000800) +#define TX_QUEUE_0_CONFIG_AM			(0x00004000) +#define TX_QUEUE_0_CONFIG_GVI			(0x00008000) +#define TX_QUEUE_0_CONFIG_EEI			(0x00010000) +#define TX_QUEUE_0_CONFIG_ELI			(0x00020000) +#define TX_QUEUE_0_CONFIG_ENI			(0x00040000) +#define TX_QUEUE_0_CONFIG_ESI			(0x00080000) +#define TX_QUEUE_0_CONFIG_EDI			(0x00100000) + +#define reg_TX_QUEUE_0_BUF_CONFIG(base)		__REG32(base, 0x00000284) +#define TX_QUEUE_0_BUF_CONFIG_OCN_PORT		(0x0000003f) +#define TX_QUEUE_0_BUF_CONFIG_BURST		(0x00000300) +#define TX_QUEUE_0_BUF_CONFIG_BSWP		(0x00000400) +#define TX_QUEUE_0_BUF_CONFIG_WSWP		(0x00000800) + +#define OCN_PORT_HLP			0	/* HLP Interface */ +#define OCN_PORT_PCI_X			1	/* PCI-X Interface */ +#define OCN_PORT_PROCESSOR_MASTER	2	/* Processor Interface (master) */ +#define OCN_PORT_PROCESSOR_SLAVE	3	/* Processor Interface (slave) */ +#define OCN_PORT_MEMORY			4	/* Memory Controller */ +#define OCN_PORT_DMA			5	/* DMA Controller */ +#define OCN_PORT_ETHERNET		6	/* Ethernet Controller */ +#define OCN_PORT_PRINT			7	/* Print Engine Interface */ + +#define reg_TX_QUEUE_0_PTR_LOW(base)		__REG32(base, 0x00000288) + +#define reg_TX_QUEUE_0_PTR_HIGH(base)		__REG32(base, 0x0000028c) +#define TX_QUEUE_0_PTR_HIGH_VALID		(0x80000000) + +#define reg_RX_CONFIG(base)			__REG32(base, 0x00000320) +#define RX_CONFIG_DEF_Q				(0x00000003) +#define RX_CONFIG_EMF				(0x00000100) +#define RX_CONFIG_EUF				(0x00000200) +#define RX_CONFIG_BFE				(0x00000400) +#define RX_CONFIG_MFE				(0x00000800) +#define RX_CONFIG_UFE				(0x00001000) +#define RX_CONFIG_SE				(0x00002000) +#define RX_CONFIG_ABF				(0x00200000) +#define RX_CONFIG_APE				(0x00400000) +#define RX_CONFIG_CHP				(0x00800000) +#define RX_CONFIG_RST				(0x80000000) + +#define reg_RX_CONTROL(base)			__REG32(base, 0x00000324) +#define GE_E0_RX_CONTROL_QUEUE_ENABLES		(0x0000000f) +#define GE_E0_RX_CONTROL_GO			(0x00008000) +#define GE_E0_RX_CONTROL_EAI			(0x20000000) +#define GE_E0_RX_CONTROL_ABT			(0x40000000) +#define GE_E0_RX_CONTROL_EII			(0x80000000) + +#define reg_RX_EXTENDED_STATUS(base)		__REG32(base, 0x0000032c) +#define RX_EXTENDED_STATUS			(0x0000032c) +#define RX_EXTENDED_STATUS_EOQ			(0x0000000f) +#define RX_EXTENDED_STATUS_EOQ_0		(0x00000001) +#define RX_EXTENDED_STATUS_EOF			(0x00000f00) +#define RX_EXTENDED_STATUS_DESCRIPTOR_INTERRUPT_CONDITION	(0x000f0000) +#define RX_EXTENDED_STATUS_ERROR_FLAG				(0x0f000000) + +#define reg_RX_THRESHOLDS(base)			__REG32(base, 0x00000330) + +#define reg_RX_DIAGNOSTIC_ADDR(base)		__REG32(base, 0x00000370) +#define RX_DIAGNOSTIC_ADDR_INDEX		(0x0000007f) +#define RX_DIAGNOSTIC_ADDR_DFR			(0x40000000) +#define RX_DIAGNOSTIC_ADDR_AI			(0x80000000) + +#define reg_RX_DIAGNOSTIC_DATA(base)		__REG32(base, 0x00000374) + +#define reg_RX_QUEUE_0_CONFIG(base)		__REG32(base, 0x00000380) +#define RX_QUEUE_0_CONFIG_OCN_PORT		(0x0000003f) +#define RX_QUEUE_0_CONFIG_BSWP			(0x00000400) +#define RX_QUEUE_0_CONFIG_WSWP			(0x00000800) +#define RX_QUEUE_0_CONFIG_AM			(0x00004000) +#define RX_QUEUE_0_CONFIG_EEI			(0x00010000) +#define RX_QUEUE_0_CONFIG_ELI			(0x00020000) +#define RX_QUEUE_0_CONFIG_ENI			(0x00040000) +#define RX_QUEUE_0_CONFIG_ESI			(0x00080000) +#define RX_QUEUE_0_CONFIG_EDI			(0x00100000) + +#define reg_RX_QUEUE_0_BUF_CONFIG(base)		__REG32(base, 0x00000384) +#define RX_QUEUE_0_BUF_CONFIG_OCN_PORT		(0x0000003f) +#define RX_QUEUE_0_BUF_CONFIG_BURST		(0x00000300) +#define RX_QUEUE_0_BUF_CONFIG_BSWP		(0x00000400) +#define RX_QUEUE_0_BUF_CONFIG_WSWP		(0x00000800) + +#define reg_RX_QUEUE_0_PTR_LOW(base)		__REG32(base, 0x00000388) + +#define reg_RX_QUEUE_0_PTR_HIGH(base)		__REG32(base, 0x0000038c) +#define RX_QUEUE_0_PTR_HIGH_VALID		(0x80000000) + +/* + *  PHY register definitions + */ +/* the first 15 PHY registers are standard. */ +#define PHY_CTRL_REG		0	/* Control Register */ +#define PHY_STATUS_REG		1	/* Status Regiser */ +#define PHY_ID1_REG		2	/* Phy Id Reg (word 1) */ +#define PHY_ID2_REG		3	/* Phy Id Reg (word 2) */ +#define PHY_AN_ADV_REG		4	/* Autoneg Advertisement */ +#define PHY_LP_ABILITY_REG	5	/* Link Partner Ability (Base Page) */ +#define PHY_AUTONEG_EXP_REG	6	/* Autoneg Expansion Reg */ +#define PHY_NEXT_PAGE_TX_REG	7	/* Next Page TX */ +#define PHY_LP_NEXT_PAGE_REG	8	/* Link Partner Next Page */ +#define PHY_1000T_CTRL_REG	9	/* 1000Base-T Control Reg */ +#define PHY_1000T_STATUS_REG	10	/* 1000Base-T Status Reg */ +#define PHY_EXT_STATUS_REG	11	/* Extended Status Reg */ + +/* + * PHY Register bit masks. + */ +#define PHY_CTRL_RESET		(1 << 15) +#define PHY_CTRL_LOOPBACK	(1 << 14) +#define PHY_CTRL_SPEED0		(1 << 13) +#define PHY_CTRL_AN_EN		(1 << 12) +#define PHY_CTRL_PWR_DN		(1 << 11) +#define PHY_CTRL_ISOLATE	(1 << 10) +#define PHY_CTRL_RESTART_AN	(1 << 9) +#define PHY_CTRL_FULL_DUPLEX	(1 << 8) +#define PHY_CTRL_CT_EN		(1 << 7) +#define PHY_CTRL_SPEED1		(1 << 6) + +#define PHY_STAT_100BASE_T4	(1 << 15) +#define PHY_STAT_100BASE_X_FD	(1 << 14) +#define PHY_STAT_100BASE_X_HD	(1 << 13) +#define PHY_STAT_10BASE_T_FD	(1 << 12) +#define PHY_STAT_10BASE_T_HD	(1 << 11) +#define PHY_STAT_100BASE_T2_FD	(1 << 10) +#define PHY_STAT_100BASE_T2_HD	(1 << 9) +#define PHY_STAT_EXT_STAT	(1 << 8) +#define PHY_STAT_RESERVED	(1 << 7) +#define PHY_STAT_MFPS		(1 << 6)	/* Management Frames Preamble Suppression */ +#define PHY_STAT_AN_COMPLETE	(1 << 5) +#define PHY_STAT_REM_FAULT	(1 << 4) +#define PHY_STAT_AN_CAP		(1 << 3) +#define PHY_STAT_LINK_UP	(1 << 2) +#define PHY_STAT_JABBER		(1 << 1) +#define PHY_STAT_EXT_CAP	(1 << 0) + +#define TBI_CONTROL_2					0x11 +#define TBI_CONTROL_2_ENABLE_COMMA_DETECT		0x0001 +#define TBI_CONTROL_2_ENABLE_WRAP			0x0002 +#define TBI_CONTROL_2_G_MII_MODE			0x0010 +#define TBI_CONTROL_2_RECEIVE_CLOCK_SELECT		0x0020 +#define TBI_CONTROL_2_AUTO_NEGOTIATION_SENSE		0x0100 +#define TBI_CONTROL_2_DISABLE_TRANSMIT_RUNNING_DISPARITY	0x1000 +#define TBI_CONTROL_2_DISABLE_RECEIVE_RUNNING_DISPARITY		0x2000 +#define TBI_CONTROL_2_SHORTCUT_LINK_TIMER			0x4000 +#define TBI_CONTROL_2_SOFT_RESET				0x8000 + +/* marvel specific */ +#define MV1111_EXT_CTRL1_REG	16	/* PHY Specific Control Reg */ +#define MV1111_SPEC_STAT_REG	17	/* PHY Specific Status Reg */ +#define MV1111_EXT_CTRL2_REG	20	/* Extended PHY Specific Control Reg */ + +/* + * MARVELL 88E1111 PHY register bit masks + */ +/* PHY Specific Status Register (MV1111_EXT_CTRL1_REG) */ + +#define SPEC_STAT_SPEED_MASK	(3 << 14) +#define SPEC_STAT_FULL_DUP	(1 << 13) +#define SPEC_STAT_PAGE_RCVD	(1 << 12) +#define SPEC_STAT_RESOLVED	(1 << 11)	/* Speed and Duplex Resolved */ +#define SPEC_STAT_LINK_UP	(1 << 10) +#define SPEC_STAT_CABLE_LEN_MASK	(7 << 7)/* Cable Length (100/1000 modes only) */ +#define SPEC_STAT_MDIX		(1 << 6) +#define SPEC_STAT_POLARITY	(1 << 1) +#define SPEC_STAT_JABBER	(1 << 0) + +#define SPEED_1000		(2 << 14) +#define SPEED_100		(1 << 14) +#define SPEED_10		(0 << 14) + +#define TBI_ADDR	0x1E	/* Ten Bit Interface address */ + +/* negotiated link parameters */ +#define LINK_SPEED_UNKNOWN	0 +#define LINK_SPEED_10		1 +#define LINK_SPEED_100		2 +#define LINK_SPEED_1000		3 + +#define LINK_DUPLEX_UNKNOWN	0 +#define LINK_DUPLEX_HALF	1 +#define LINK_DUPLEX_FULL	2 + +static unsigned int phy_address[] = { 8, 9 }; + +#define vuint32 volatile u32 + +/* TX/RX buffer descriptors. MUST be cache line aligned in memory. (32 byte) + * This structure is accessed by the ethernet DMA engine which means it + * MUST be in LITTLE ENDIAN format */ +struct dma_descriptor { +	vuint32 start_addr0;	/* buffer address, least significant bytes. */ +	vuint32 start_addr1;	/* buffer address, most significant bytes. */ +	vuint32 next_descr_addr0;/* next descriptor address, least significant bytes.  Must be 64-bit aligned. */ +	vuint32 next_descr_addr1;/* next descriptor address, most significant bytes. */ +	vuint32 vlan_byte_count;/* VLAN tag(top 2 bytes) and byte countt (bottom 2 bytes). */ +	vuint32 config_status;	/* Configuration/Status. */ +	vuint32 reserved1;	/* reserved to make the descriptor cache line aligned. */ +	vuint32 reserved2;	/* reserved to make the descriptor cache line aligned. */ +}; + +/* last next descriptor address flag */ +#define DMA_DESCR_LAST		(1 << 31) + +/* TX DMA descriptor config status bits */ +#define DMA_DESCR_TX_EOF	(1 <<  0)	/* end of frame */ +#define DMA_DESCR_TX_SOF	(1 <<  1)	/* start of frame */ +#define DMA_DESCR_TX_PFVLAN	(1 <<  2) +#define DMA_DESCR_TX_HUGE	(1 <<  3) +#define DMA_DESCR_TX_PAD	(1 <<  4) +#define DMA_DESCR_TX_CRC	(1 <<  5) +#define DMA_DESCR_TX_DESCR_INT	(1 << 14) +#define DMA_DESCR_TX_RETRY_COUNT	0x000F0000 +#define DMA_DESCR_TX_ONE_COLLISION	(1 << 20) +#define DMA_DESCR_TX_LATE_COLLISION	(1 << 24) +#define DMA_DESCR_TX_UNDERRUN		(1 << 25) +#define DMA_DESCR_TX_RETRY_LIMIT	(1 << 26) +#define DMA_DESCR_TX_OK			(1 << 30) +#define DMA_DESCR_TX_OWNER		(1 << 31) + +/* RX DMA descriptor status bits */ +#define DMA_DESCR_RX_EOF		(1 <<  0) +#define DMA_DESCR_RX_SOF		(1 <<  1) +#define DMA_DESCR_RX_VTF		(1 <<  2) +#define DMA_DESCR_RX_FRAME_IS_TYPE	(1 <<  3) +#define DMA_DESCR_RX_SHORT_FRAME	(1 <<  4) +#define DMA_DESCR_RX_HASH_MATCH		(1 <<  7) +#define DMA_DESCR_RX_BAD_FRAME		(1 <<  8) +#define DMA_DESCR_RX_OVERRUN		(1 <<  9) +#define DMA_DESCR_RX_MAX_FRAME_LEN	(1 << 11) +#define DMA_DESCR_RX_CRC_ERROR		(1 << 12) +#define DMA_DESCR_RX_DESCR_INT		(1 << 13) +#define DMA_DESCR_RX_OWNER		(1 << 15) + +#define RX_BUFFER_SIZE	PKTSIZE +#define NUM_RX_DESC	PKTBUFSRX + +static struct dma_descriptor tx_descriptor __attribute__ ((aligned(32))); + +static struct dma_descriptor rx_descr_array[NUM_RX_DESC] +	__attribute__ ((aligned(32))); + +static struct dma_descriptor *rx_descr_current; + +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis); +static int tsi108_eth_send (struct eth_device *dev, +			   volatile void *packet, int length); +static int tsi108_eth_recv (struct eth_device *dev); +static void tsi108_eth_halt (struct eth_device *dev); +static unsigned int read_phy (unsigned int base, +			     unsigned int phy_addr, unsigned int phy_reg); +static void write_phy (unsigned int base, +		      unsigned int phy_addr, +		      unsigned int phy_reg, unsigned int phy_data); + +#if TSI108_ETH_DEBUG > 100 +/* + * print phy debug infomation + */ +static void dump_phy_regs (unsigned int phy_addr) +{ +	int i; + +	printf ("PHY %d registers\n", phy_addr); +	for (i = 0; i <= 30; i++) { +		printf ("%2d  0x%04x\n", i, read_phy (ETH_BASE, phy_addr, i)); +	} +	printf ("\n"); + +} +#else +#define dump_phy_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void tx_diag_regs (unsigned int base) +{ +	int i; +	unsigned long dummy; + +	printf ("TX diagnostics registers\n"); +	reg_TX_DIAGNOSTIC_ADDR(base) = 0x00 | TX_DIAGNOSTIC_ADDR_AI; +	udelay (1000); +	dummy = reg_TX_DIAGNOSTIC_DATA(base); +	for (i = 0x00; i <= 0x05; i++) { +		udelay (1000); +		printf ("0x%02x  0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); +	} +	reg_TX_DIAGNOSTIC_ADDR(base) = 0x40 | TX_DIAGNOSTIC_ADDR_AI; +	udelay (1000); +	dummy = reg_TX_DIAGNOSTIC_DATA(base); +	for (i = 0x40; i <= 0x47; i++) { +		udelay (1000); +		printf ("0x%02x  0x%08x\n", i, reg_TX_DIAGNOSTIC_DATA(base)); +	} +	printf ("\n"); + +} +#else +#define tx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void rx_diag_regs (unsigned int base) +{ +	int i; +	unsigned long dummy; + +	printf ("RX diagnostics registers\n"); +	reg_RX_DIAGNOSTIC_ADDR(base) = 0x00 | RX_DIAGNOSTIC_ADDR_AI; +	udelay (1000); +	dummy = reg_RX_DIAGNOSTIC_DATA(base); +	for (i = 0x00; i <= 0x05; i++) { +		udelay (1000); +		printf ("0x%02x  0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); +	} +	reg_RX_DIAGNOSTIC_ADDR(base) = 0x40 | RX_DIAGNOSTIC_ADDR_AI; +	udelay (1000); +	dummy = reg_RX_DIAGNOSTIC_DATA(base); +	for (i = 0x08; i <= 0x0a; i++) { +		udelay (1000); +		printf ("0x%02x  0x%08x\n", i, reg_RX_DIAGNOSTIC_DATA(base)); +	} +	printf ("\n"); + +} +#else +#define rx_diag_regs(base) do{}while(0) +#endif + +#if TSI108_ETH_DEBUG > 100 +/* + * print debug infomation + */ +static void debug_mii_regs (unsigned int base) +{ +	printf ("MII_MGMT_CONFIG     0x%08x\n", reg_MII_MGMT_CONFIG(base)); +	printf ("MII_MGMT_COMMAND    0x%08x\n", reg_MII_MGMT_COMMAND(base)); +	printf ("MII_MGMT_ADDRESS    0x%08x\n", reg_MII_MGMT_ADDRESS(base)); +	printf ("MII_MGMT_CONTROL    0x%08x\n", reg_MII_MGMT_CONTROL(base)); +	printf ("MII_MGMT_STATUS     0x%08x\n", reg_MII_MGMT_STATUS(base)); +	printf ("MII_MGMT_INDICATORS 0x%08x\n", reg_MII_MGMT_INDICATORS(base)); +	printf ("\n"); + +} +#else +#define debug_mii_regs(base) do{}while(0) +#endif + +/* + * Wait until the phy bus is non-busy + */ +static void phy_wait (unsigned int base, unsigned int condition) +{ +	int timeout; + +	timeout = 0; +	while (reg_MII_MGMT_INDICATORS(base) & condition) { +		udelay (10); +		if (++timeout > 10000) { +			printf ("ERROR: timeout waiting for phy bus (%d)\n", +			       condition); +			break; +		} +	} +} + +/* + * read phy register + */ +static unsigned int read_phy (unsigned int base, +			     unsigned int phy_addr, unsigned int phy_reg) +{ +	unsigned int value; + +	phy_wait (base, MII_MGMT_INDICATORS_BUSY); + +	reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + +	/* Ensure that the Read Cycle bit is cleared prior to next read cycle */ +	reg_MII_MGMT_COMMAND(base) = 0; + +	/* start the read */ +	reg_MII_MGMT_COMMAND(base) = MII_MGMT_COMMAND_READ_CYCLE; + +	/* wait for the read to complete */ +	phy_wait (base, +		 MII_MGMT_INDICATORS_NOT_VALID | MII_MGMT_INDICATORS_BUSY); + +	value = reg_MII_MGMT_STATUS(base); + +	reg_MII_MGMT_COMMAND(base) = 0; + +	return value; +} + +/* + * write phy register + */ +static void write_phy (unsigned int base, +		      unsigned int phy_addr, +		      unsigned int phy_reg, unsigned int phy_data) +{ +	phy_wait (base, MII_MGMT_INDICATORS_BUSY); + +	reg_MII_MGMT_ADDRESS(base) = (phy_addr << 8) | phy_reg; + +	/* Ensure that the Read Cycle bit is cleared prior to next cycle */ +	reg_MII_MGMT_COMMAND(base) = 0; + +	/* start the write */ +	reg_MII_MGMT_CONTROL(base) = phy_data; +} + +/* + * configure the marvell 88e1111 phy + */ +static int marvell_88e_phy_config (struct eth_device *dev, int *speed, +				  int *duplex) +{ +	unsigned long base; +	unsigned long phy_addr; +	unsigned int phy_status; +	unsigned int phy_spec_status; +	int timeout; +	int phy_speed; +	int phy_duplex; +	unsigned int value; + +	phy_speed = LINK_SPEED_UNKNOWN; +	phy_duplex = LINK_DUPLEX_UNKNOWN; + +	base = dev->iobase; +	phy_addr = (unsigned long)dev->priv; + +	/* Take the PHY out of reset. */ +	write_phy (ETH_BASE, phy_addr, PHY_CTRL_REG, PHY_CTRL_RESET); + +	/* Wait for the reset process to complete. */ +	udelay (10); +	timeout = 0; +	while ((phy_status = +		read_phy (ETH_BASE, phy_addr, PHY_CTRL_REG)) & PHY_CTRL_RESET) { +		udelay (10); +		if (++timeout > 10000) { +			printf ("ERROR: timeout waiting for phy reset\n"); +			break; +		} +	} + +	/* TBI Configuration. */ +	write_phy (base, TBI_ADDR, TBI_CONTROL_2, TBI_CONTROL_2_G_MII_MODE | +		  TBI_CONTROL_2_RECEIVE_CLOCK_SELECT); +	/* Wait for the link to be established. */ +	timeout = 0; +	do { +		udelay (20000); +		phy_status = read_phy (ETH_BASE, phy_addr, PHY_STATUS_REG); +		if (++timeout > 100) { +			debug_lev(1, "ERROR: unable to establish link!!!\n"); +			break; +		} +	} while ((phy_status & PHY_STAT_LINK_UP) == 0); + +	if ((phy_status & PHY_STAT_LINK_UP) == 0) +		return 0; + +	value = 0; +	phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); +	if (phy_spec_status & SPEC_STAT_RESOLVED) { +		switch (phy_spec_status & SPEC_STAT_SPEED_MASK) { +		case SPEED_1000: +			phy_speed = LINK_SPEED_1000; +			value |= PHY_CTRL_SPEED1; +			break; +		case SPEED_100: +			phy_speed = LINK_SPEED_100; +			value |= PHY_CTRL_SPEED0; +			break; +		case SPEED_10: +			phy_speed = LINK_SPEED_10; +			break; +		} +		if (phy_spec_status & SPEC_STAT_FULL_DUP) { +			phy_duplex = LINK_DUPLEX_FULL; +			value |= PHY_CTRL_FULL_DUPLEX; +		} else +			phy_duplex = LINK_DUPLEX_HALF; +	} +	/* set TBI speed */ +	write_phy (base, TBI_ADDR, PHY_CTRL_REG, value); +	write_phy (base, TBI_ADDR, PHY_AN_ADV_REG, 0x0060); + +#if TSI108_ETH_DEBUG > 0 +	printf ("%s link is up", dev->name); +	phy_spec_status = read_phy (ETH_BASE, phy_addr, MV1111_SPEC_STAT_REG); +	if (phy_spec_status & SPEC_STAT_RESOLVED) { +		switch (phy_speed) { +		case LINK_SPEED_1000: +			printf (", 1000 Mbps"); +			break; +		case LINK_SPEED_100: +			printf (", 100 Mbps"); +			break; +		case LINK_SPEED_10: +			printf (", 10 Mbps"); +			break; +		} +		if (phy_duplex == LINK_DUPLEX_FULL) +			printf (", Full duplex"); +		else +			printf (", Half duplex"); +	} +	printf ("\n"); +#endif + +	dump_phy_regs (TBI_ADDR); +	if (speed) +		*speed = phy_speed; +	if (duplex) +		*duplex = phy_duplex; + +	return 1; +} + +/* + * External interface + * + * register the tsi108 ethernet controllers with the multi-ethernet system + */ +int tsi108_eth_initialize (bd_t * bis) +{ +	struct eth_device *dev; +	int index; + +	for (index = 0; index < CONFIG_TSI108_ETH_NUM_PORTS; index++) { +		dev = (struct eth_device *)malloc(sizeof(struct eth_device)); + +		sprintf (dev->name, "TSI108_eth%d", index); + +		dev->iobase = ETH_BASE + (index * ETH_PORT_OFFSET); +		dev->priv = (void *)(phy_address[index]); +		dev->init = tsi108_eth_probe; +		dev->halt = tsi108_eth_halt; +		dev->send = tsi108_eth_send; +		dev->recv = tsi108_eth_recv; + +		eth_register(dev); +	} +	return index; +} + +/* + * probe for and initialize a single ethernet interface + */ +static int tsi108_eth_probe (struct eth_device *dev, bd_t * bis) +{ +	unsigned long base; +	unsigned long value; +	int index; +	struct dma_descriptor *tx_descr; +	struct dma_descriptor *rx_descr; +	int speed; +	int duplex; + +	base = dev->iobase; + +	reg_PORT_CONTROL(base) = PORT_CONTROL_STE | PORT_CONTROL_BPT; + +	/* Bring DMA/FIFO out of reset. */ +	reg_TX_CONFIG(base) = 0x00000000; +	reg_RX_CONFIG(base) = 0x00000000; + +	reg_TX_THRESHOLDS(base) = (192 << 16) | 192; +	reg_RX_THRESHOLDS(base) = (192 << 16) | 112; + +	/* Bring MAC out of reset. */ +	reg_MAC_CONFIG_1(base) = 0x00000000; + +	/* DMA MAC configuration. */ +	reg_MAC_CONFIG_1(base) = +	    MAC_CONFIG_1_RX_ENABLE | MAC_CONFIG_1_TX_ENABLE; + +	reg_MII_MGMT_CONFIG(base) = MII_MGMT_CONFIG_NO_PREAMBLE; +	reg_MAXIMUM_FRAME_LENGTH(base) = RX_BUFFER_SIZE; + +	/* Note: Early tsi108 manual did not have correct byte order +	 * for the station address.*/ +	reg_STATION_ADDRESS_1(base) = (dev->enetaddr[5] << 24) | +	    (dev->enetaddr[4] << 16) | +	    (dev->enetaddr[3] << 8) | (dev->enetaddr[2] << 0); + +	reg_STATION_ADDRESS_2(base) = (dev->enetaddr[1] << 24) | +	    (dev->enetaddr[0] << 16); + +	if (marvell_88e_phy_config(dev, &speed, &duplex) == 0) +		return 0; + +	value = +	    MAC_CONFIG_2_PREAMBLE_LENGTH(7) | MAC_CONFIG_2_PAD_CRC | +	    MAC_CONFIG_2_CRC_ENABLE; +	if (speed == LINK_SPEED_1000) +		value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_BYTE); +	else { +		value |= MAC_CONFIG_2_INTERFACE_MODE(INTERFACE_MODE_NIBBLE); +		reg_PORT_CONTROL(base) |= PORT_CONTROL_SPD; +	} +	if (duplex == LINK_DUPLEX_FULL) { +		value |= MAC_CONFIG_2_FULL_DUPLEX; +		reg_PORT_CONTROL(base) &= ~PORT_CONTROL_BPT; +	} else +		reg_PORT_CONTROL(base) |= PORT_CONTROL_BPT; +	reg_MAC_CONFIG_2(base) = value; + +	reg_RX_CONFIG(base) = RX_CONFIG_SE; +	reg_RX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; +	reg_RX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + +	/* initialize the RX DMA descriptors */ +	rx_descr = &rx_descr_array[0]; +	rx_descr_current = rx_descr; +	for (index = 0; index < NUM_RX_DESC; index++) { +		/* make sure the receive buffers are not in cache */ +		invalidate_dcache_range((unsigned long)NetRxPackets[index], +					(unsigned long)NetRxPackets[index] + +					RX_BUFFER_SIZE); +		rx_descr->start_addr0 = +		    cpu_to_le32((vuint32) NetRxPackets[index]); +		rx_descr->start_addr1 = 0; +		rx_descr->next_descr_addr0 = +		    cpu_to_le32((vuint32) (rx_descr + 1)); +		rx_descr->next_descr_addr1 = 0; +		rx_descr->vlan_byte_count = 0; +		rx_descr->config_status = cpu_to_le32((RX_BUFFER_SIZE << 16) | +						      DMA_DESCR_RX_OWNER); +		rx_descr++; +	} +	rx_descr--; +	rx_descr->next_descr_addr0 = 0; +	rx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); +	/* Push the descriptors to RAM so the ethernet DMA can see them */ +	invalidate_dcache_range((unsigned long)rx_descr_array, +				(unsigned long)rx_descr_array + +				sizeof(rx_descr_array)); + +	/* enable RX queue */ +	reg_RX_CONTROL(base) = TX_CONTROL_GO | 0x01; +	reg_RX_QUEUE_0_PTR_LOW(base) = (u32) rx_descr_current; +	/* enable receive DMA */ +	reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; + +	reg_TX_QUEUE_0_CONFIG(base) = OCN_PORT_MEMORY; +	reg_TX_QUEUE_0_BUF_CONFIG(base) = OCN_PORT_MEMORY; + +	/* initialize the TX DMA descriptor */ +	tx_descr = &tx_descriptor; + +	tx_descr->start_addr0 = 0; +	tx_descr->start_addr1 = 0; +	tx_descr->next_descr_addr0 = 0; +	tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); +	tx_descr->vlan_byte_count = 0; +	tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OK | +					      DMA_DESCR_TX_SOF | +					      DMA_DESCR_TX_EOF); +	/* enable TX queue */ +	reg_TX_CONTROL(base) = TX_CONTROL_GO | 0x01; + +	return 1; +} + +/* + * send a packet + */ +static int tsi108_eth_send (struct eth_device *dev, +			   volatile void *packet, int length) +{ +	unsigned long base; +	int timeout; +	struct dma_descriptor *tx_descr; +	unsigned long status; + +	base = dev->iobase; +	tx_descr = &tx_descriptor; + +	/* Wait until the last packet has been transmitted. */ +	timeout = 0; +	do { +		/* make sure we see the changes made by the DMA engine */ +		invalidate_dcache_range((unsigned long)tx_descr, +					(unsigned long)tx_descr + +					sizeof(struct dma_descriptor)); + +		if (timeout != 0) +			udelay (15); +		if (++timeout > 10000) { +			tx_diag_regs(base); +			debug_lev(1, +				  "ERROR: timeout waiting for last transmit packet to be sent\n"); +			return 0; +		} +	} while (tx_descr->config_status & cpu_to_le32(DMA_DESCR_TX_OWNER)); + +	status = le32_to_cpu(tx_descr->config_status); +	if ((status & DMA_DESCR_TX_OK) == 0) { +#ifdef TX_PRINT_ERRORS +		printf ("TX packet error: 0x%08x\n    %s%s%s%s\n", status, +		       status & DMA_DESCR_TX_OK ? "tx error, " : "", +		       status & DMA_DESCR_TX_RETRY_LIMIT ? +		       "retry limit reached, " : "", +		       status & DMA_DESCR_TX_UNDERRUN ? "underrun, " : "", +		       status & DMA_DESCR_TX_LATE_COLLISION ? "late collision, " +		       : ""); +#endif +	} + +	debug_lev (9, "sending packet %d\n", length); +	tx_descr->start_addr0 = cpu_to_le32((vuint32) packet); +	tx_descr->start_addr1 = 0; +	tx_descr->next_descr_addr0 = 0; +	tx_descr->next_descr_addr1 = cpu_to_le32(DMA_DESCR_LAST); +	tx_descr->vlan_byte_count = cpu_to_le32(length); +	tx_descr->config_status = cpu_to_le32(DMA_DESCR_TX_OWNER | +					      DMA_DESCR_TX_CRC | +					      DMA_DESCR_TX_PAD | +					      DMA_DESCR_TX_SOF | +					      DMA_DESCR_TX_EOF); + +	invalidate_dcache_range((unsigned long)tx_descr, +				(unsigned long)tx_descr + +				sizeof(struct dma_descriptor)); + +	invalidate_dcache_range((unsigned long)packet, +				(unsigned long)packet + length); + +	reg_TX_QUEUE_0_PTR_LOW(base) = (u32) tx_descr; +	reg_TX_QUEUE_0_PTR_HIGH(base) = TX_QUEUE_0_PTR_HIGH_VALID; + +	return length; +} + +/* + * Check for received packets and send them up the protocal stack + */ +static int tsi108_eth_recv (struct eth_device *dev) +{ +	struct dma_descriptor *rx_descr; +	unsigned long base; +	int length = 0; +	unsigned long status; +	volatile uchar *buffer; + +	base = dev->iobase; + +	/* make sure we see the changes made by the DMA engine */ +	invalidate_dcache_range ((unsigned long)rx_descr_array, +				(unsigned long)rx_descr_array + +				sizeof(rx_descr_array)); + +	/* process all of the received packets */ +	rx_descr = rx_descr_current; +	while ((rx_descr->config_status & cpu_to_le32(DMA_DESCR_RX_OWNER)) == 0) { +		/* check for error */ +		status = le32_to_cpu(rx_descr->config_status); +		if (status & DMA_DESCR_RX_BAD_FRAME) { +#ifdef RX_PRINT_ERRORS +			printf ("RX packet error: 0x%08x\n    %s%s%s%s%s%s\n", +			       status, +			       status & DMA_DESCR_RX_FRAME_IS_TYPE ? "too big, " +			       : "", +			       status & DMA_DESCR_RX_SHORT_FRAME ? "too short, " +			       : "", +			       status & DMA_DESCR_RX_BAD_FRAME ? "bad frame, " : +			       "", +			       status & DMA_DESCR_RX_OVERRUN ? "overrun, " : "", +			       status & DMA_DESCR_RX_MAX_FRAME_LEN ? +			       "max length, " : "", +			       status & DMA_DESCR_RX_CRC_ERROR ? "CRC error, " : +			       ""); +#endif +		} else { +			length = +			    le32_to_cpu(rx_descr->vlan_byte_count) & 0xFFFF; + +			/*** process packet ***/ +			buffer = +			    (volatile uchar +			     *)(le32_to_cpu (rx_descr->start_addr0)); +			NetReceive (buffer, length); + +			invalidate_dcache_range ((unsigned long)buffer, +						(unsigned long)buffer + +						RX_BUFFER_SIZE); +		} +		/* Give this buffer back to the DMA engine */ +		rx_descr->vlan_byte_count = 0; +		rx_descr->config_status = cpu_to_le32 ((RX_BUFFER_SIZE << 16) | +						      DMA_DESCR_RX_OWNER); +		/* move descriptor pointer forward */ +		rx_descr = +		    (struct dma_descriptor +		     *)(le32_to_cpu (rx_descr->next_descr_addr0)); +		if (rx_descr == 0) +			rx_descr = &rx_descr_array[0]; +	} +	/* remember where we are for next time */ +	rx_descr_current = rx_descr; + +	/* If the DMA engine has reached the end of the queue +	 * start over at the begining */ +	if (reg_RX_EXTENDED_STATUS(base) & RX_EXTENDED_STATUS_EOQ_0) { + +		reg_RX_EXTENDED_STATUS(base) = RX_EXTENDED_STATUS_EOQ_0; +		reg_RX_QUEUE_0_PTR_LOW(base) = (u32) & rx_descr_array[0]; +		reg_RX_QUEUE_0_PTR_HIGH(base) = RX_QUEUE_0_PTR_HIGH_VALID; +	} + +	return length; +} + +/* + * disable an ethernet interface + */ +static void tsi108_eth_halt (struct eth_device *dev) +{ +	unsigned long base; + +	base = dev->iobase; + +	/* Put DMA/FIFO into reset state. */ +	reg_TX_CONFIG(base) = TX_CONFIG_RST; +	reg_RX_CONFIG(base) = RX_CONFIG_RST; + +	/* Put MAC into reset state. */ +	reg_MAC_CONFIG_1(base) = MAC_CONFIG_1_SOFT_RESET; +} + +#endif diff --git a/drivers/tsi108_i2c.c b/drivers/tsi108_i2c.c new file mode 100644 index 000000000..c100cb824 --- /dev/null +++ b/drivers/tsi108_i2c.c @@ -0,0 +1,298 @@ +/* + * (C) Copyright 2004 Tundra Semiconductor Corp. + * Author: Alex Bounine + * + * 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 <common.h> + +#ifdef CONFIG_TSI108_I2C +#include <tsi108.h> + +#if (CONFIG_COMMANDS & CFG_CMD_I2C) + +#define I2C_DELAY	100000 +#undef  DEBUG_I2C + +#ifdef DEBUG_I2C +#define DPRINT(x) printf (x) +#else +#define DPRINT(x) +#endif + +/* All functions assume that Tsi108 I2C block is the only master on the bus */ +/* I2C read helper function */ + +static int i2c_read_byte ( +		uint i2c_chan,	/* I2C channel number: 0 - main, 1 - SDC SPD */ +		uchar chip_addr,/* I2C device address on the bus */ +		uint byte_addr,	/* Byte address within I2C device */ +		uchar * buffer	/* pointer to data buffer */ +		) +{ +	u32 temp; +	u32 to_count = I2C_DELAY; +	u32 op_status = TSI108_I2C_TIMEOUT_ERR; +	u32 chan_offset = TSI108_I2C_OFFSET; + +	DPRINT (("I2C read_byte() %d 0x%02x 0x%02x\n", +		i2c_chan, chip_addr, byte_addr)); + +	if (0 != i2c_chan) +		chan_offset = TSI108_I2C_SDRAM_OFFSET; + +	/* Check if I2C operation is in progress */ +	temp = *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); + +	if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | +			  I2C_CNTRL2_START))) { +		/* Set device address and operation (read = 0) */ +		temp = (byte_addr << 16) | ((chip_addr & 0x07) << 8) | +		    ((chip_addr >> 3) & 0x0F); +		*(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL1) = +		    temp; + +		/* Issue the read command +		 * (at this moment all other parameters are 0 +		 * (size = 1 byte, lane = 0) +		 */ + +		*(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2) = +		    (I2C_CNTRL2_START); + +		/* Wait until operation completed */ +		do { +			/* Read I2C operation status */ +			temp = +			    *(u32 *) (CFG_TSI108_CSR_BASE + chan_offset + +				      I2C_CNTRL2); + +			if (0 == +			    (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_START))) +			{ +				if (0 == +				    (temp & +				     (I2C_CNTRL2_I2C_CFGERR | +				      I2C_CNTRL2_I2C_TO_ERR)) +				    ) { +					op_status = TSI108_I2C_SUCCESS; + +					temp = *(u32 *) (CFG_TSI108_CSR_BASE + +							 chan_offset + +							 I2C_RD_DATA); + +					*buffer = (u8) (temp & 0xFF); +				} else { +					/* report HW error */ +					op_status = TSI108_I2C_IF_ERROR; + +					DPRINT (("I2C HW error reported: 0x%02x\n", temp)); +				} + +				break; +			} +		} while (to_count--); +	} else { +		op_status = TSI108_I2C_IF_BUSY; + +		DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); +	} + +	DPRINT (("I2C read_byte() status: 0x%02x\n", op_status)); +	return op_status; +} + +/* + * I2C Read interface as defined in "include/i2c.h" : + *   chip_addr: I2C chip address, range 0..127 + *                  (to read from SPD channel EEPROM use (0xD0 ... 0xD7) + *              NOTE: The bit 7 in the chip_addr serves as a channel select. + *              This hack is for enabling "isdram" command on Tsi108 boards + *              without changes to common code. Used for I2C reads only. + *   byte_addr: Memory or register address within the chip + *   alen:      Number of bytes to use for addr (typically 1, 2 for larger + *              memories, 0 for register type devices with only one + *              register) + *   buffer:    Pointer to destination buffer for data to be read + *   len:       How many bytes to read + * + *   Returns: 0 on success, not 0 on failure + */ + +int i2c_read (uchar chip_addr, uint byte_addr, int alen, +		uchar * buffer, int len) +{ +	u32 op_status = TSI108_I2C_PARAM_ERR; +	u32 i2c_if = 0; + +	/* Hack to support second (SPD) I2C controller (SPD EEPROM read only).*/ +	if (0xD0 == (chip_addr & ~0x07)) { +		i2c_if = 1; +		chip_addr &= 0x7F; +	} +	/* Check for valid I2C address */ +	if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { +		while (len--) { +			op_status = +			    i2c_read_byte(i2c_if, chip_addr, byte_addr++, +					  buffer++); + +			if (TSI108_I2C_SUCCESS != op_status) { +				DPRINT (("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); + +				break; +			} +		} +	} + +	DPRINT (("I2C read() status: 0x%02x\n", op_status)); +	return op_status; +} + +/* I2C write helper function */ + +static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ +			  uint byte_addr, /* Byte address within I2C device */ +			  uchar * buffer  /*  pointer to data buffer */ +			  ) +{ +	u32 temp; +	u32 to_count = I2C_DELAY; +	u32 op_status = TSI108_I2C_TIMEOUT_ERR; + +	/* Check if I2C operation is in progress */ +	temp = *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); + +	if (0 == +	    (temp & +	     (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) +	{ +		/* Place data into the I2C Tx Register */ +		*(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + +			  I2C_TX_DATA) = (u32) * buffer; + +		/* Set device address and operation  */ +		temp = +		    I2C_CNTRL1_I2CWRITE | (byte_addr << 16) | +		    ((chip_addr & 0x07) << 8) | ((chip_addr >> 3) & 0x0F); +		*(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + +			  I2C_CNTRL1) = temp; + +		/* Issue the write command (at this moment all other parameters +		 * are 0 (size = 1 byte, lane = 0) +		 */ +		 +		*(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + +			  I2C_CNTRL2) = (I2C_CNTRL2_START); + +		op_status = TSI108_I2C_TIMEOUT_ERR; + +		/* Wait until operation completed */ +		do { +			/* Read I2C operation status */ +			temp = +			    *(u32 *) (CFG_TSI108_CSR_BASE + TSI108_I2C_OFFSET + +				      I2C_CNTRL2); + +			if (0 == +			    (temp & (I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) +			{ +				if (0 == +				    (temp & +				     (I2C_CNTRL2_I2C_CFGERR | +				      I2C_CNTRL2_I2C_TO_ERR))) { +					op_status = TSI108_I2C_SUCCESS; +				} else { +					/* report detected HW error */ +					op_status = TSI108_I2C_IF_ERROR; + +					DPRINT (("I2C HW error reported: 0x%02x\n", temp)); +				} + +				break; +			} + +		} while (to_count--); +	} else { +		op_status = TSI108_I2C_IF_BUSY; + +		DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); +	} + +	return op_status; +} + +/* + * I2C Write interface as defined in "include/i2c.h" : + *   chip_addr: I2C chip address, range 0..127 + *   byte_addr: Memory or register address within the chip + *   alen:      Number of bytes to use for addr (typically 1, 2 for larger + *              memories, 0 for register type devices with only one + *              register) + *   buffer:    Pointer to data to be written + *   len:       How many bytes to write + * + *   Returns: 0 on success, not 0 on failure + */ + +int i2c_write (uchar chip_addr, uint byte_addr, int alen, uchar * buffer, +	      int len) +{ +	u32 op_status = TSI108_I2C_PARAM_ERR; + +	/* Check for valid I2C address */ +	if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { +		while (len--) { +			op_status = +			    i2c_write_byte (chip_addr, byte_addr++, buffer++); + +			if (TSI108_I2C_SUCCESS != op_status) { +				DPRINT (("I2C write_byte() failed: 0x%02x (%d left)\n", op_status, len)); + +				break; +			} +		} +	} + +	return op_status; +} + +/* + * I2C interface function as defined in "include/i2c.h". + * Probe the given I2C chip address by reading single byte from offset 0. + * Returns 0 if a chip responded, not 0 on failure. + */ + +int i2c_probe (uchar chip) +{ +	u32 tmp; + +	/* +	 * Try to read the first location of the chip. +	 * The Tsi108 HW doesn't support sending just the chip address +	 * and checkong for an <ACK> back. +	 */ +	return i2c_read (chip, 0, 1, (char *)&tmp, 1); +} + +#endif	/* (CONFIG_COMMANDS & CFG_CMD_I2C) */ +#endif /* CONFIG_TSI108_I2C */ diff --git a/drivers/tsi108_pci.c b/drivers/tsi108_pci.c new file mode 100644 index 000000000..9f606df51 --- /dev/null +++ b/drivers/tsi108_pci.c @@ -0,0 +1,178 @@ +/* + * (C) Copyright 2004 Tundra Semiconductor Corp. + * Alex Bounine <alexandreb@tundra.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 + */ + +/* + * PCI initialisation for the Tsi108 EMU board. + */ + +#include <config.h> + +#ifdef CONFIG_TSI108_PCI + +#include <common.h> +#include <pci.h> +#include <asm/io.h> +#include <tsi108.h> + +struct pci_controller local_hose; + +void tsi108_clear_pci_error (void) +{ +	u32 err_stat, err_addr, pci_stat; + +	/* +	 * Quietly clear errors signalled as result of PCI/X configuration read +	 * requests. +	 */ +	/* Read PB Error Log Registers */ +	err_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + +				     TSI108_PB_REG_OFFSET + PB_ERRCS); +	err_addr = *(volatile u32 *)(CFG_TSI108_CSR_BASE + +				     TSI108_PB_REG_OFFSET + PB_AERR); +	if (err_stat & PB_ERRCS_ES) { +		/* Clear PCI/X bus errors if applicable */ +		if ((err_addr & 0xFF000000) == CFG_PCI_CFG_BASE) { +			/* Clear error flag */ +			*(u32 *) (CFG_TSI108_CSR_BASE + +				  TSI108_PB_REG_OFFSET + PB_ERRCS) = +			    PB_ERRCS_ES; + +			/* Clear read error reported in PB_ISR */ +			*(u32 *) (CFG_TSI108_CSR_BASE + +				  TSI108_PB_REG_OFFSET + PB_ISR) = +			    PB_ISR_PBS_RD_ERR; + +		/* Clear errors reported by PCI CSR (Normally Master Abort) */ +			pci_stat = *(volatile u32 *)(CFG_TSI108_CSR_BASE + +						     TSI108_PCI_REG_OFFSET + +						     PCI_CSR); +			*(volatile u32 *)(CFG_TSI108_CSR_BASE + +					  TSI108_PCI_REG_OFFSET + PCI_CSR) = +			    pci_stat; + +			*(volatile u32 *)(CFG_TSI108_CSR_BASE + +					  TSI108_PCI_REG_OFFSET + +					  PCI_IRP_STAT) = PCI_IRP_STAT_P_CSR; +		} +	} + +	return; +} + +unsigned int __get_pci_config_dword (u32 addr) +{ +	unsigned int retval; + +	__asm__ __volatile__ ("       lwbrx %0,0,%1\n" +			     "1:     eieio\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); +} + +static int tsi108_read_config_dword (struct pci_controller *hose, +				    pci_dev_t dev, int offset, u32 * value) +{ +	dev &= (CFG_PCI_CFG_SIZE - 1); +	dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); +	*value = __get_pci_config_dword(dev); +	if (0xFFFFFFFF == *value) +		tsi108_clear_pci_error (); +	return 0; +} + +static int tsi108_write_config_dword (struct pci_controller *hose, +				     pci_dev_t dev, int offset, u32 value) +{ +	dev &= (CFG_PCI_CFG_SIZE - 1); +	dev |= (CFG_PCI_CFG_BASE | (offset & 0xfc)); + +	out_le32 ((volatile unsigned *)dev, value); + +	return 0; +} + +void pci_init_board (void) +{ +	struct pci_controller *hose = (struct pci_controller *)&local_hose; + +	hose->first_busno = 0; +	hose->last_busno = 0xff; + +	pci_set_region (hose->regions + 0, +		       CFG_PCI_MEMORY_BUS, +		       CFG_PCI_MEMORY_PHYS, +		       CFG_PCI_MEMORY_SIZE, PCI_REGION_MEM | PCI_REGION_MEMORY); + +	/* PCI memory space */ +	pci_set_region (hose->regions + 1, +		       CFG_PCI_MEM_BUS, +		       CFG_PCI_MEM_PHYS, CFG_PCI_MEM_SIZE, PCI_REGION_MEM); + +	/* PCI I/O space */ +	pci_set_region (hose->regions + 2, +		       CFG_PCI_IO_BUS, +		       CFG_PCI_IO_PHYS, CFG_PCI_IO_SIZE, PCI_REGION_IO); + +	hose->region_count = 3; + +	pci_set_ops (hose, +		    pci_hose_read_config_byte_via_dword, +		    pci_hose_read_config_word_via_dword, +		    tsi108_read_config_dword, +		    pci_hose_write_config_byte_via_dword, +		    pci_hose_write_config_word_via_dword, +		    tsi108_write_config_dword); + +	pci_register_hose (hose); + +	hose->last_busno = pci_hose_scan (hose); + +	debug ("Done PCI initialization\n"); +	return; +} + +#ifdef CONFIG_OF_FLAT_TREE +void +ft_pci_setup (void *blob, bd_t *bd) +{ +	u32 *p; +	int len; + +	p = (u32 *)ft_get_prop (blob, "/" OF_TSI "/pci@1000/bus-range", &len); +	if (p != NULL) { +		p[0] = local_hose.first_busno; +		p[1] = local_hose.last_busno; +	} + +} +#endif + +#endif	/* CONFIG_TSI108_PCI */ diff --git a/include/74xx_7xx.h b/include/74xx_7xx.h index 33e396a06..ba73bae9e 100644 --- a/include/74xx_7xx.h +++ b/include/74xx_7xx.h @@ -111,7 +111,7 @@ typedef enum __cpu_t {  	CPU_750CX, CPU_750FX, CPU_750GX,  	CPU_7400,  	CPU_7410, -	CPU_7448, +	CPU_7447A, CPU_7448,  	CPU_7450, CPU_7455, CPU_7457,  	CPU_UNKNOWN} cpu_t; diff --git a/include/asm-ppc/global_data.h b/include/asm-ppc/global_data.h index 8bc61b63a..5f0f0b4b0 100644 --- a/include/asm-ppc/global_data.h +++ b/include/asm-ppc/global_data.h @@ -49,6 +49,9 @@ typedef	struct	global_data {  	unsigned long	scc_clk;  	unsigned long	brg_clk;  #endif +#if defined(CONFIG_MPC7448HPC2) +	unsigned long   mem_clk; +#endif  #if defined(CONFIG_MPC83XX)  	/* There are other clocks in the MPC83XX */  	u32 csb_clk; diff --git a/include/configs/mpc7448hpc2.h b/include/configs/mpc7448hpc2.h new file mode 100644 index 000000000..6bad51547 --- /dev/null +++ b/include/configs/mpc7448hpc2.h @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * (C) Copyright 2006 + * Alex Bounine , Tundra Semiconductor Corp. + * Roy Zang	, <tie-fei.zang@freescale.com> Freescale Corp. + * + * 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 + */ + +/* + * board specific configuration options for Freescale + * MPC7448HPC2 (High-Performance Computing II) (Taiga) board + * + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#undef DEBUG + +/* Board Configuration Definitions */ +/* MPC7448HPC2 (High-Performance Computing II) (Taiga) board */ + +#define CONFIG_MPC7448HPC2 + +#define CONFIG_74xx +#define CONFIG_750FX		/* this option to enable init of extended BATs */ +#define CONFIG_ALTIVEC		/* undef to disable */ + +#define CFG_BOARD_NAME		"MPC7448 HPC II" +#define CONFIG_IDENT_STRING	" Freescale MPC7448 HPC II" + +#define CFG_OCN_CLK		133000000	/* 133 MHz */ +#define CFG_CONFIG_BUS_CLK	133000000 + +#define CFG_CLK_SPREAD		/* Enable Spread-Spectrum Clock generation */ + +#undef  CONFIG_ECC		/* disable ECC support */ + +/* Board-specific Initialization Functions to be called */ +#define CFG_BOARD_ASM_INIT +#define CONFIG_BOARD_EARLY_INIT_F +#define CONFIG_BOARD_EARLY_INIT_R +#define CONFIG_MISC_INIT_R + +#define CONFIG_HAS_ETH1 + +#define CONFIG_ENV_OVERWRITE + +/* + * High Level Configuration Options + * (easy to change) + */ + +#define CONFIG_BAUDRATE		115200	/* console baudrate = 115000 */ + +/*#define CFG_HUSH_PARSER */ +#undef CFG_HUSH_PARSER + +#define CFG_PROMPT_HUSH_PS2	"> " + +/* Pass open firmware flat tree */ +#define CONFIG_OF_FLAT_TREE	1 +#define CONFIG_OF_BOARD_SETUP	1 + +/* maximum size of the flat tree (8K) */ +#define OF_FLAT_TREE_MAX_SIZE	8192 + +#define OF_CPU			"PowerPC,7448@0" +#define OF_TSI			"tsi108@c0000000" +#define OF_TBCLK		(bd->bi_busfreq / 8) +#define OF_STDOUT_PATH		"/tsi108@c0000000/serial@7808" + +/* + * The following defines let you select what serial you want to use + * for your console driver. + * + * what to do: + * If you have hacked a serial cable onto the second DUART channel, + * change the CFG_DUART port from 1 to 0 below. + * + */ + +#define CONFIG_CONS_INDEX	1 +#define CFG_NS16550 +#define CFG_NS16550_SERIAL +#define CFG_NS16550_REG_SIZE	1 +#define CFG_NS16550_CLK		CFG_OCN_CLK * 8 + +#define CFG_NS16550_COM1	(CFG_TSI108_CSR_RST_BASE+0x7808) +#define CFG_NS16550_COM2	(CFG_TSI108_CSR_RST_BASE+0x7C08) +#define CFG_BAUDRATE_TABLE	{ 9600, 19200, 38400, 57600, 115200 } + +#define CONFIG_BOOTDELAY	3	/* autoboot after 3 seconds */ +#define CONFIG_ZERO_BOOTDELAY_CHECK + +#undef CONFIG_BOOTARGS +/* #define CONFIG_PREBOOT  "echo;echo Type \"run flash_nfs\" + * to mount root filesystem over NFS;echo" */ + +#if (CONFIG_BOOTDELAY >= 0) +#define CONFIG_BOOTCOMMAND	"tftpboot 0x400000 zImage.initrd.elf;\ + setenv bootargs $(bootargs) $(bootargs_root) nfsroot=$(serverip):$(rootpath) \ + ip=$(ipaddr):$(serverip)$(bootargs_end);  bootm 0x400000; " + +#define CONFIG_BOOTARGS "console=ttyS0,115200" +#endif + +#undef CONFIG_EXTRA_ENV_SETTINGS + +#define CONFIG_SERIAL	"No. 1" + +/* Networking Configuration */ + +#define KSEG1ADDR(a)	(a)	/* Needed by the rtl8139 driver */ + +#define CONFIG_TSI108_ETH +#define CONFIG_TSI108_ETH_NUM_PORTS	2 + +#define CONFIG_NET_MULTI + +#define CONFIG_BOOTFILE		zImage.initrd.elf +#define CONFIG_LOADADDR		0x400000 + +/*-------------------------------------------------------------------------- */ + +#define CONFIG_LOADS_ECHO	0	/* echo off for serial download */ +#define CFG_LOADS_BAUD_CHANGE	/* allow baudrate changes */ + +#undef CONFIG_WATCHDOG		/* watchdog disabled */ + +#define CONFIG_BOOTP_MASK	(CONFIG_BOOTP_DEFAULT | \ +				CONFIG_BOOTP_BOOTFILESIZE) + +#define CONFIG_COMMANDS (CONFIG_CMD_DFL \ +		| CFG_CMD_ASKENV \ +		| CFG_CMD_CACHE \ +		| CFG_CMD_PCI \ +		| CFG_CMD_I2C \ +		| CFG_CMD_SDRAM \ +		| CFG_CMD_EEPROM \ +		| CFG_CMD_FLASH \ +		| CFG_CMD_ENV \ +		| CFG_CMD_BSP \ +		| CFG_CMD_DHCP \ +		| CFG_CMD_PING \ +		| CFG_CMD_DATE) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +/*set date in u-boot*/ +#define CONFIG_RTC_M48T35A +#define CFG_NVRAM_BASE_ADDR	0xfc000000 +#define CFG_NVRAM_SIZE		0x8000 +/* + * Miscellaneous configurable options + */ +#define CONFIG_VERSION_VARIABLE		1 +#define CONFIG_TSI108_I2C + +#define CFG_I2C_EEPROM_ADDR		0x50	/* I2C EEPROM page 1 */ +#define CFG_I2C_EEPROM_ADDR_LEN		1	/* Bytes of address */ + +#define CFG_LONGHELP		/* undef to save memory */ +#define CFG_PROMPT	"=> "	/* Monitor Command Prompt */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CBSIZE		1024	/* Console I/O Buffer Size */ +#define CONFIG_KGDB_BAUDRATE	115200	/* speed to run kgdb serial port at */ +#else +#define CFG_CBSIZE		256	/* Console I/O Buffer Size */ +#endif + +#define CFG_PBSIZE (CFG_CBSIZE + sizeof(CFG_PROMPT) + 16)/* Print Buffer Size */ +#define CFG_MAXARGS	16		/* max number of command args */ +#define CFG_BARGSIZE	CFG_CBSIZE	/* Boot Argument Buffer Size */ + +#define CFG_MEMTEST_START	0x00400000	/* memtest works on */ +#define CFG_MEMTEST_END		0x07c00000	/* 4 ... 124 MB in DRAM */ + +#define CFG_LOAD_ADDR	0x00400000	/* default load address */ + +#define CFG_HZ		1000		/* decr freq: 1ms ticks */ + +/* + * Low Level Configuration Settings + * (address mappings, register initial values, etc.) + * You should know what you are doing if you make changes here. + */ + +/*----------------------------------------------------------------------- + * Definitions for initial stack pointer and data area + */ + +/* + * When locking data in cache you should point the CFG_INIT_RAM_ADDRESS + * To an unused memory region. The stack will remain in cache until RAM + * is initialized + */ +#undef  CFG_INIT_RAM_LOCK +#define CFG_INIT_RAM_ADDR	0x07d00000	/* unused memory region */ +#define CFG_INIT_RAM_END	0x4000/* larger space - we have SDRAM initialized */ + +#define CFG_GBL_DATA_SIZE	128/* size in bytes reserved for init data */ +#define CFG_GBL_DATA_OFFSET (CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) + +/*----------------------------------------------------------------------- + * Start addresses for the final memory configuration + * (Set up by the startup code) + * Please note that CFG_SDRAM_BASE _must_ start at 0 + */ + +#define CFG_SDRAM_BASE		0x00000000	/* first 256 MB of SDRAM */ +#define CFG_SDRAM1_BASE		0x10000000	/* next 256MB of SDRAM */ + +#define CFG_SDRAM2_BASE	0x40000000	/* beginning of non-cacheable alias for SDRAM - first 256MB */ +#define CFG_SDRAM3_BASE	0x50000000	/* next Non-Cacheable 256MB of SDRAM */ + +#define CFG_PCI_PFM_BASE	0x80000000	/* Prefetchable (cacheable) PCI/X PFM and SDRAM OCN (128MB+128MB) */ + +#define CFG_PCI_MEM32_BASE	0xE0000000	/* Non-Cacheable PCI/X MEM and SDRAM OCN (128MB+128MB) */ + +#define CFG_MISC_REGION_BASE	0xf0000000	/* Base Address for (PCI/X + Flash) region */ + +#define CFG_FLASH_BASE	0xff000000	/* Base Address of Flash device */ +#define CFG_FLASH_BASE2	0xfe000000	/* Alternate Flash Base Address */ + +#define CONFIG_VERY_BIG_RAM	/* we will use up to 256M memory for cause we are short of BATS */ + +#define PCI0_IO_BASE_BOOTM	0xfd000000 + +#define CFG_RESET_ADDRESS	0x3fffff00 +#define CFG_MONITOR_LEN		(256 << 10)	/* Reserve 256 kB for Monitor */ +#define CFG_MONITOR_BASE	TEXT_BASE	/* u-boot code base */ +#define CFG_MALLOC_LEN		(256 << 10)	/* Reserve 256 kB for malloc */ + +/* Peripheral Device section */ + +/* + * Resources on the Tsi108 + */ + +#define CFG_TSI108_CSR_RST_BASE	0xC0000000	/* Tsi108 CSR base after reset */ +#define CFG_TSI108_CSR_BASE	CFG_TSI108_CSR_RST_BASE	/* Runtime Tsi108 CSR base */ + +#define ENABLE_PCI_CSR_BAR	/* enables access to Tsi108 CSRs from the PCI/X bus */ + +#undef  DISABLE_PBM + +/* + * PCI stuff + * + */ + +#define CONFIG_PCI		/* include pci support */ +#define CONFIG_TSI108_PCI	/* include tsi108 pci support */ + +#define PCI_HOST_ADAPTER	0	/* configure as pci adapter */ +#define PCI_HOST_FORCE		1	/* configure as pci host */ +#define PCI_HOST_AUTO		2	/* detected via arbiter enable */ + +#define CONFIG_PCI_HOST PCI_HOST_FORCE	/* select pci host function */ +#define CONFIG_PCI_PNP		/* do pci plug-and-play */ + +/* PCI MEMORY MAP section */ + +/* PCI view of System Memory */ +#define CFG_PCI_MEMORY_BUS	0x00000000 +#define CFG_PCI_MEMORY_PHYS	0x00000000 +#define CFG_PCI_MEMORY_SIZE	0x80000000	 + +/* PCI Memory Space */ +#define CFG_PCI_MEM_BUS		(CFG_PCI_MEM_PHYS) +#define CFG_PCI_MEM_PHYS	(CFG_PCI_MEM32_BASE)	/* 0xE0000000 */ +#define CFG_PCI_MEM_SIZE	0x10000000	/* 256 MB space for PCI/X Mem + SDRAM OCN */ + +/* PCI I/O Space */ +#define CFG_PCI_IO_BUS		0x00000000 +#define CFG_PCI_IO_PHYS		0xfa000000	/* Changed from fd000000 */ + +#define CFG_PCI_IO_SIZE		0x01000000	/* 16MB */ + +#define _IO_BASE		0x00000000	/* points to PCI I/O space      */ + +/* PCI Config Space mapping */ +#define CFG_PCI_CFG_BASE	0xfb000000	/* Changed from FE000000 */ +#define CFG_PCI_CFG_SIZE	0x01000000	/* 16MB */ + +#define CFG_IBAT0U	0xFE0003FF +#define CFG_IBAT0L	0xFE000002 + +#define CFG_IBAT1U	0x00007FFF +#define CFG_IBAT1L	0x00000012 + +#define CFG_IBAT2U	0x80007FFF +#define CFG_IBAT2L	0x80000022 + +#define CFG_IBAT3U	0x00000000 +#define CFG_IBAT3L	0x00000000 + +#define CFG_IBAT4U	0x00000000 +#define CFG_IBAT4L	0x00000000 + +#define CFG_IBAT5U	0x00000000 +#define CFG_IBAT5L	0x00000000 + +#define CFG_IBAT6U	0x00000000 +#define CFG_IBAT6L	0x00000000 + +#define CFG_IBAT7U	0x00000000 +#define CFG_IBAT7L	0x00000000 + +#define CFG_DBAT0U	0xE0003FFF +#define CFG_DBAT0L	0xE000002A + +#define CFG_DBAT1U	0x00007FFF +#define CFG_DBAT1L	0x00000012 + +#define CFG_DBAT2U	0x00000000 +#define CFG_DBAT2L	0x00000000 + +#define CFG_DBAT3U	0xC0000003 +#define CFG_DBAT3L	0xC000002A + +#define CFG_DBAT4U	0x00000000 +#define CFG_DBAT4L	0x00000000 + +#define CFG_DBAT5U	0x00000000 +#define CFG_DBAT5L	0x00000000 + +#define CFG_DBAT6U	0x00000000 +#define CFG_DBAT6L	0x00000000 + +#define CFG_DBAT7U	0x00000000 +#define CFG_DBAT7L	0x00000000 + +/* I2C addresses for the two DIMM SPD chips */ +#define DIMM0_I2C_ADDR	0x51 +#define DIMM1_I2C_ADDR	0x52 + +/* + * For booting Linux, the board info and command line data + * have to be in the first 8 MB of memory, since this is + * the maximum mapped by the Linux kernel during initialization. + */ +#define CFG_BOOTMAPSZ	(8<<20)	/* Initial Memory map for Linux */ + +/*----------------------------------------------------------------------- + * FLASH organization + */ +#define CFG_MAX_FLASH_BANKS	1/* Flash can be at one of two addresses */ +#define FLASH_BANK_SIZE		0x01000000	/* 16 MB Total */ +#define CFG_FLASH_BANKS_LIST {CFG_FLASH_BASE, CFG_FLASH_BASE2} + +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_CFI +#define CFG_FLASH_CFI_SWAP + +#define PHYS_FLASH_SIZE		0x01000000 +#define CFG_MAX_FLASH_SECT	(128) + +#define CFG_ENV_IS_IN_NVRAM +#define CFG_ENV_ADDR		0xFC000000 + +#define CFG_ENV_OFFSET	0x00000000	/* Offset of Environment Sector */ +#define CFG_ENV_SIZE	0x00000400	/* Total Size of Environment Space */ + +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_CACHELINE_SIZE	32	/* For all MPC74xx CPUs */ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT	5	/* log base 2 of the above value */ +#endif + +/*----------------------------------------------------------------------- + * L2CR setup -- make sure this is right for your board! + * look in include/mpc74xx.h for the defines used here + */ +#undef CFG_L2 + +#define L2_INIT		0 +#define L2_ENABLE	(L2_INIT | L2CR_L2E) + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD	0x01	/* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM	0x02	/* Software reboot */ +#define CFG_SERIAL_HANG_IN_EXCEPTION +#endif	/* __CONFIG_H */ diff --git a/include/tsi108.h b/include/tsi108.h new file mode 100644 index 000000000..ba62e7abe --- /dev/null +++ b/include/tsi108.h @@ -0,0 +1,221 @@ +/***************************************************************************** + * (C) Copyright 2003;  Tundra Semiconductor Corp. + * (C) Copyright 2006;  Freescale Semiconductor Corp. + * + * 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 + *****************************************************************************/ + +/* + * FILENAME: tsi108.h + * + * Originator: Alex Bounine + * + * DESCRIPTION: + * Common definitions for the Tundra Tsi108 bridge chip + * + */ + +#ifndef _TSI108_H_ +#define _TSI108_H_ + +#define TSI108_HLP_REG_OFFSET	(0x0000) +#define TSI108_PCI_REG_OFFSET	(0x1000) +#define TSI108_CLK_REG_OFFSET	(0x2000) +#define TSI108_PB_REG_OFFSET	(0x3000) +#define TSI108_SD_REG_OFFSET	(0x4000) +#define TSI108_MPIC_REG_OFFSET	(0x7400) + +#define PB_ID			(0x000) +#define PB_RSR			(0x004) +#define PB_BUS_MS_SELECT	(0x008) +#define PB_ISR			(0x00C) +#define PB_ARB_CTRL		(0x018) +#define PB_PVT_CTRL2		(0x034) +#define PB_SCR			(0x400) +#define PB_ERRCS		(0x404) +#define PB_AERR			(0x408) +#define PB_REG_BAR		(0x410) +#define PB_OCN_BAR1		(0x414) +#define PB_OCN_BAR2		(0x418) +#define PB_SDRAM_BAR1		(0x41C) +#define PB_SDRAM_BAR2		(0x420) +#define PB_MCR			(0xC00) +#define PB_MCMD			(0xC04) + +#define HLP_B0_ADDR		(0x000) +#define HLP_B1_ADDR		(0x010) +#define HLP_B2_ADDR		(0x020) +#define HLP_B3_ADDR		(0x030) + +#define HLP_B0_MASK		(0x004) +#define HLP_B1_MASK		(0x014) +#define HLP_B2_MASK		(0x024) +#define HLP_B3_MASK		(0x034) + +#define HLP_B0_CTRL0		(0x008) +#define HLP_B1_CTRL0		(0x018) +#define HLP_B2_CTRL0		(0x028) +#define HLP_B3_CTRL0		(0x038) + +#define HLP_B0_CTRL1		(0x00C) +#define HLP_B1_CTRL1		(0x01C) +#define HLP_B2_CTRL1		(0x02C) +#define HLP_B3_CTRL1		(0x03C) + +#define PCI_CSR			(0x004) +#define PCI_P2O_BAR0		(0x010) +#define PCI_P2O_BAR0_UPPER	(0x014) +#define PCI_P2O_BAR2		(0x018) +#define PCI_P2O_BAR2_UPPER	(0x01C) +#define PCI_P2O_BAR3		(0x020) +#define PCI_P2O_BAR3_UPPER	(0x024) + +#define PCI_MISC_CSR		(0x040) +#define PCI_P2O_PAGE_SIZES	(0x04C) + +#define PCI_PCIX_STAT		(0x0F4) + +#define PCI_IRP_STAT		(0x184) + +#define PCI_PFAB_BAR0		(0x204) +#define PCI_PFAB_BAR0_UPPER	(0x208) +#define PCI_PFAB_IO		(0x20C) +#define PCI_PFAB_IO_UPPER	(0x210) + +#define PCI_PFAB_MEM32		(0x214) +#define PCI_PFAB_MEM32_REMAP	(0x218) +#define PCI_PFAB_MEM32_MASK	(0x21C) + +#define CG_PLL0_CTRL0		(0x210) +#define CG_PLL0_CTRL1		(0x214) +#define CG_PLL1_CTRL0		(0x220) +#define CG_PLL1_CTRL1		(0x224) +#define CG_PWRUP_STATUS		(0x234) + +#define MPIC_CSR(n) (0x30C + (n * 0x40)) + +#define SD_CTRL			(0x000) +#define SD_STATUS		(0x004) +#define SD_TIMING		(0x008) +#define SD_REFRESH		(0x00C) +#define SD_INT_STATUS		(0x010) +#define SD_INT_ENABLE		(0x014) +#define SD_INT_SET		(0x018) +#define SD_D0_CTRL		(0x020) +#define SD_D1_CTRL		(0x024) +#define SD_D0_BAR		(0x028) +#define SD_D1_BAR		(0x02C) +#define SD_ECC_CTRL		(0x040) +#define SD_DLL_STATUS		(0x250) + +#define TS_SD_CTRL_ENABLE	(1 << 31) + +#define PB_ERRCS_ES		(1 << 1) +#define PB_ISR_PBS_RD_ERR	(1 << 8) +#define PCI_IRP_STAT_P_CSR	(1 << 23) + +/* + * I2C : Register address offset definitions + */ +#define I2C_CNTRL1		(0x00000000) +#define I2C_CNTRL2		(0x00000004) +#define I2C_RD_DATA		(0x00000008) +#define I2C_TX_DATA		(0x0000000c) + +/* + * I2C : Register Bit Masks and Reset Values + * definitions for every register + */ + +/* I2C_CNTRL1 : Reset Value */ +#define I2C_CNTRL1_RESET_VALUE				(0x0000000a) + +/* I2C_CNTRL1 : Register Bits Masks Definitions */ +#define I2C_CNTRL1_DEVCODE				(0x0000000f) +#define I2C_CNTRL1_PAGE					(0x00000700) +#define I2C_CNTRL1_BYTADDR				(0x00ff0000) +#define I2C_CNTRL1_I2CWRITE				(0x01000000) + +/* I2C_CNTRL1 : Read/Write Bit Mask Definition */ +#define I2C_CNTRL1_RWMASK				(0x01ff070f) + +/* I2C_CNTRL1 : Unused/Reserved bits Definition */ +#define I2C_CNTRL1_RESERVED				(0xfe00f8f0) + +/* I2C_CNTRL2 : Reset Value */ +#define I2C_CNTRL2_RESET_VALUE				(0x00000000) + +/* I2C_CNTRL2 : Register Bits Masks Definitions */ +#define I2C_CNTRL2_SIZE					(0x00000003) +#define I2C_CNTRL2_LANE					(0x0000000c) +#define I2C_CNTRL2_MULTIBYTE				(0x00000010) +#define I2C_CNTRL2_START				(0x00000100) +#define I2C_CNTRL2_WR_STATUS				(0x00010000) +#define I2C_CNTRL2_RD_STATUS				(0x00020000) +#define I2C_CNTRL2_I2C_TO_ERR				(0x04000000) +#define I2C_CNTRL2_I2C_CFGERR				(0x08000000) +#define I2C_CNTRL2_I2C_CMPLT				(0x10000000) + +/* I2C_CNTRL2 : Read/Write Bit Mask Definition */ +#define I2C_CNTRL2_RWMASK				(0x0000011f) + +/* I2C_CNTRL2 : Unused/Reserved bits Definition */ +#define I2C_CNTRL2_RESERVED				(0xe3fcfee0) + +/* I2C_RD_DATA : Reset Value */ +#define I2C_RD_DATA_RESET_VALUE				(0x00000000) + +/* I2C_RD_DATA : Register Bits Masks Definitions */ +#define I2C_RD_DATA_RBYTE0				(0x000000ff) +#define I2C_RD_DATA_RBYTE1				(0x0000ff00) +#define I2C_RD_DATA_RBYTE2				(0x00ff0000) +#define I2C_RD_DATA_RBYTE3				(0xff000000) + +/* I2C_RD_DATA : Read/Write Bit Mask Definition */ +#define I2C_RD_DATA_RWMASK				(0x00000000) + +/* I2C_RD_DATA : Unused/Reserved bits Definition */ +#define I2C_RD_DATA_RESERVED				(0x00000000) + +/* I2C_TX_DATA : Reset Value */ +#define I2C_TX_DATA_RESET_VALUE				(0x00000000) + +/* I2C_TX_DATA : Register Bits Masks Definitions */ +#define I2C_TX_DATA_TBYTE0				(0x000000ff) +#define I2C_TX_DATA_TBYTE1				(0x0000ff00) +#define I2C_TX_DATA_TBYTE2				(0x00ff0000) +#define I2C_TX_DATA_TBYTE3				(0xff000000) + +/* I2C_TX_DATA : Read/Write Bit Mask Definition */ +#define I2C_TX_DATA_RWMASK				(0xffffffff) + +/* I2C_TX_DATA : Unused/Reserved bits Definition */ +#define I2C_TX_DATA_RESERVED				(0x00000000) + +#define TSI108_I2C_OFFSET	0x7000	/* offset for general use I2C channel */ +#define TSI108_I2C_SDRAM_OFFSET	0x4400	/* offset for SPD I2C channel */ + +#define I2C_EEPROM_DEVCODE	0xA	/* standard I2C EEPROM device code */ + +/* I2C status codes */ + +#define TSI108_I2C_SUCCESS	0 +#define TSI108_I2C_PARAM_ERR	1 +#define TSI108_I2C_TIMEOUT_ERR	2 +#define TSI108_I2C_IF_BUSY	3 +#define TSI108_I2C_IF_ERROR	4 + +#endif		/* _TSI108_H_ */ diff --git a/lib_ppc/extable.c b/lib_ppc/extable.c index d92f14270..fe856ffbb 100644 --- a/lib_ppc/extable.c +++ b/lib_ppc/extable.c @@ -37,6 +37,8 @@   * on our cache or tlb entries.   */ +DECLARE_GLOBAL_DATA_PTR; +  struct exception_table_entry  {  	unsigned long insn, fixup; @@ -55,10 +57,22 @@ search_one_table(const struct exception_table_entry *first,  		long diff;  		mid = (last - first) / 2 + first; -		diff = mid->insn - value; -		if (diff == 0) -			return mid->fixup; -		else if (diff < 0) +		if (mid > CFG_MONITOR_BASE) { +		/* exception occurs in FLASH, before u-boot relocation. +		 * No relocation offset is needed. +		 */ +			diff = mid->insn - value; +			if (diff == 0) +				return mid->fixup; +		} else { +		/* exception occurs in RAM, after u-boot relocation. +		 * A relocation offset should be added. +		 */ +			diff = (mid->insn + gd->reloc_off) - value; +			if (diff == 0) +				return (mid->fixup + gd->reloc_off); +		} +		if (diff < 0)  			first = mid+1;  		else  			last = mid-1; @@ -75,8 +89,11 @@ search_exception_table(unsigned long addr)  	/* There is only the kernel to search.  */  	ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); +	/* if the serial port does not hang in exception, printf can be used */ +#if !defined(CFG_SERIAL_HANG_IN_EXCEPTION)  	if (ex_tab_message)  		printf("Bus Fault @ 0x%08lx, fixup 0x%08lx\n", addr, ret); +#endif  	if (ret) return ret;  	return 0; @@ -52,6 +52,7 @@ extern int rtl8139_initialize(bd_t*);  extern int rtl8169_initialize(bd_t*);  extern int scc_initialize(bd_t*);  extern int skge_initialize(bd_t*); +extern int tsi108_eth_initialize(bd_t*);  extern int tsec_initialize(bd_t*, int, char *);  extern int npe_initialize(bd_t *);  extern int uec_initialize(int); @@ -249,6 +250,9 @@ int eth_initialize(bd_t *bis)  #ifdef CONFIG_NS8382X  	ns8382x_initialize(bis);  #endif +#if defined(CONFIG_TSI108_ETH) +	tsi108_eth_initialize(bis); +#endif  #if defined(CONFIG_RTL8139)  	rtl8139_initialize(bis);  #endif |