diff options
| -rwxr-xr-x | MAKEALL | 4 | ||||
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | README | 22 | ||||
| -rw-r--r-- | board/mpc7448hpc2/Makefile | 48 | ||||
| -rw-r--r-- | board/mpc7448hpc2/asm_init.S | 955 | ||||
| -rw-r--r-- | board/mpc7448hpc2/config.mk | 28 | ||||
| -rw-r--r-- | board/mpc7448hpc2/mpc7448hpc2.c | 489 | ||||
| -rw-r--r-- | board/mpc7448hpc2/tsi108_init.c | 662 | ||||
| -rw-r--r-- | board/mpc7448hpc2/u-boot.lds | 136 | ||||
| -rw-r--r-- | cpu/74xx_7xx/cpu.c | 54 | ||||
| -rw-r--r-- | cpu/74xx_7xx/cpu_init.c | 2 | ||||
| -rw-r--r-- | cpu/74xx_7xx/speed.c | 55 | ||||
| -rw-r--r-- | doc/README.mpc7448hpc2 | 193 | ||||
| -rw-r--r-- | drivers/Makefile | 6 | ||||
| -rw-r--r-- | drivers/cfi_flash.c | 29 | ||||
| -rw-r--r-- | drivers/tsi108_eth.c | 1043 | ||||
| -rw-r--r-- | drivers/tsi108_i2c.c | 300 | ||||
| -rw-r--r-- | drivers/tsi108_pci.c | 178 | ||||
| -rw-r--r-- | include/74xx_7xx.h | 1 | ||||
| -rw-r--r-- | include/asm-ppc/global_data.h | 3 | ||||
| -rw-r--r-- | include/configs/mpc7448hpc2.h | 444 | ||||
| -rw-r--r-- | include/tsi108.h | 221 | ||||
| -rw-r--r-- | lib_ppc/extable.c | 10 | ||||
| -rw-r--r-- | net/eth.c | 4 | 
24 files changed, 4860 insertions, 30 deletions
| @@ -150,8 +150,8 @@ LIST_85xx="	\  #########################################################################  LIST_74xx="	\ -	DB64360		DB64460		EVB64260	P3G4		\ -	PCIPPC2		PCIPPC6		ZUMA				\ +	DB64360		DB64460		EVB64260	mpc7448hpc2	\ +	P3G4    	PCIPPC2		PCIPPC6		ZUMA		\  "  LIST_7xx="	\ @@ -1721,6 +1721,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 @@ -2312,17 +2312,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..d5ed01f02 --- /dev/null +++ b/board/mpc7448hpc2/Makefile @@ -0,0 +1,48 @@ +# +# (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	= lib$(BOARD).a + +OBJS	= $(BOARD).o tsi108_init.o + +SOBJS	= asm_init.o + +$(LIB):	.depend $(OBJS) $(SOBJS) +	$(AR) crv $@  $(OBJS) $(SOBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend + +######################################################################### + +.depend:	Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) +		$(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/board/mpc7448hpc2/asm_init.S b/board/mpc7448hpc2/asm_init.S new file mode 100644 index 000000000..8c15a3d49 --- /dev/null +++ b/board/mpc7448hpc2/asm_init.S @@ -0,0 +1,955 @@ +/***************************************************************************** + * (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 + +#if(1) /* def CONFIG_DUAL_CPU +    ------------------------------------------------------------------------- +     For MPC74xx processor, use MSSCR0[ID] bit to identify CPU number. +     */ + +    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)) /* value for 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,0x000024C7)  value for PB_SCR: TEA enabled,AACK delay = 7 */ +    LOAD_U32(r5,0x00002481) /* value for 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,0x0040             Set pipeline depth 4 +    ori r5,r5,0x0080             Set pipeline depth 8 +    ori r5,r5,0x0020            !!!avb Testing: set pipeline depth 2 */ +    ori r5,r5,0x0001 +    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 +    beq wait_init_complete  /* wait until SDRAM initialization is 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) */ + +    LOAD_U32(r5, 0x00000011)  /* BA=0,Size=512MB, ENable, No Addr.Translation */ +    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. +===========================================================================*/ + +    .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 +/*=========================================================================== + enable_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 +/*    lwz r3,SD_INT_STATUS(r4)       Read SDRAM ECC Control Register */ +    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 +	rlwinm r3,r3,30,2,31/* right shift tRCD by 2 bits as per DDR2 spec */ +	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..f90a75124 --- /dev/null +++ b/board/mpc7448hpc2/mpc7448hpc2.c @@ -0,0 +1,489 @@ +/* + * (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); +} + +/* DRAM check routines copied from gw8260 */ + +#if defined (CFG_DRAM_TEST) + +/*********************************************************************/ +/* NAME:  move64() -  moves a double word (64-bit)		     */ +/*								     */ +/* DESCRIPTION:							     */ +/*   this function performs a double word move from the data at	     */ +/*   the source pointer to the location at the destination pointer.  */ +/*								     */ +/* INPUTS:							     */ +/*   unsigned long long *src  - pointer to data to move		     */ +/*								     */ +/* OUTPUTS:							     */ +/*   unsigned long long *dest - pointer to locate to move data	     */ +/*								     */ +/* RETURNS:							     */ +/*   None							     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*   May cloober fr0.						     */ +/*								     */ +/*********************************************************************/ +static void move64(unsigned long long *src, unsigned long long *dest) +{ +	asm("lfd  0, 0(3)\n\t"	/* fpr0   =  *scr       */ +	    "stfd 0, 0(4)"	/* *dest  =  fpr0       */ +      : : :"fr0");		/* Clobbers fr0         */ +	return; +} + +#if defined (CFG_DRAM_TEST_DATA) + +unsigned long long pattern[] = { +	0xaaaaaaaaaaaaaaaaULL, +	0xccccccccccccccccULL, +	0xf0f0f0f0f0f0f0f0ULL, +	0xff00ff00ff00ff00ULL, +	0xffff0000ffff0000ULL, +	0xffffffff00000000ULL, +	0x00000000ffffffffULL, +	0x0000ffff0000ffffULL, +	0x00ff00ff00ff00ffULL, +	0x0f0f0f0f0f0f0f0fULL, +	0x3333333333333333ULL, +	0x5555555555555555ULL +}; + +/*********************************************************************/ +/* NAME:  mem_test_data() -  test data lines for shorts and opens    */ +/*								     */ +/* DESCRIPTION:							     */ +/*   Tests data lines for shorts and opens by forcing adjacent data  */ +/*   to opposite states. Because the data lines could be routed in   */ +/*   an arbitrary manner the must ensure test patterns ensure that   */ +/*   every case is tested. By using the following series of binary   */ +/*   patterns every combination of adjacent bits is test regardless  */ +/*   of routing.						     */ +/*								     */ +/*     ...101010101010101010101010				     */ +/*     ...110011001100110011001100				     */ +/*     ...111100001111000011110000				     */ +/*     ...111111110000000011111111				     */ +/*								     */ +/*   Carrying this out, gives us six hex patterns as follows:	     */ +/*								     */ +/*     0xaaaaaaaaaaaaaaaa					     */ +/*     0xcccccccccccccccc					     */ +/*     0xf0f0f0f0f0f0f0f0					     */ +/*     0xff00ff00ff00ff00					     */ +/*     0xffff0000ffff0000					     */ +/*     0xffffffff00000000					     */ +/*								     */ +/*   The number test patterns will always be given by:		     */ +/*								     */ +/*   log(base 2)(number data bits) = log2 (64) = 6		     */ +/*								     */ +/*   To test for short and opens to other signals on our boards. we  */ +/*   simply							     */ +/*   test with the 1's complemnt of the paterns as well.	     */ +/*								     */ +/* OUTPUTS:							     */ +/*   Displays failing test pattern				     */ +/*								     */ +/* RETURNS:							     */ +/*   0 -  Passed test						     */ +/*   1 -  Failed test						     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*  Assumes only one one SDRAM bank				     */ +/*								     */ +/*********************************************************************/ +int mem_test_data(void) +{ +	unsigned long long *pmem = (unsigned long long *)CFG_MEMTEST_START; +	unsigned long long temp64; +	int num_patterns = sizeof(pattern) / sizeof(pattern[0]); +	int i; +	unsigned int hi, lo; + +	for (i = 0; i < num_patterns; i++) { +		move64(&(pattern[i]), pmem); +		move64(pmem, &temp64); + +		/* hi = (temp64>>32) & 0xffffffff;          */ +		/* lo = temp64 & 0xffffffff;                */ +		/* printf("\ntemp64 = 0x%08x%08x", hi, lo); */ + +		hi = (pattern[i] >> 32) & 0xffffffff; +		lo = pattern[i] & 0xffffffff; +		/* printf("\npattern[%d] = 0x%08x%08x", i, hi, lo);  */ + +		if (temp64 != pattern[i]) { +			printf("\n   Data Test Failed, pattern 0x%08x%08x", +			       hi, lo); +			return 1; +		} +	} + +	return 0; +} +#endif	/* CFG_DRAM_TEST_DATA */ + +#if defined (CFG_DRAM_TEST_ADDRESS) +/*********************************************************************/ +/* NAME:  mem_test_address() -	test address lines		     */ +/*								     */ +/* DESCRIPTION:							     */ +/*   This function performs a test to verify that each word im	     */ +/*   memory is uniquly addressable. The test sequence is as follows: */ +/*								     */ +/*   1) write the address of each word to each word.		     */ +/*   2) verify that each location equals its address		     */ +/*								     */ +/* OUTPUTS:							     */ +/*   Displays failing test pattern and address			     */ +/*								     */ +/* RETURNS:							     */ +/*   0 -  Passed test						     */ +/*   1 -  Failed test						     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*								     */ +/*								     */ +/*********************************************************************/ +int mem_test_address(void) +{ +	volatile unsigned int *pmem = +	    (volatile unsigned int *)CFG_MEMTEST_START; +	const unsigned int size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 4; +	unsigned int i; + +	/* write address to each location */ +	for (i = 0; i < size; i++) { +		pmem[i] = i; +	} + +	/* verify each loaction */ +	for (i = 0; i < size; i++) { +		if (pmem[i] != i) { +			printf("\n   Address Test Failed at 0x%x", i); +			return 1; +		} +	} +	return 0; +} +#endif				/* CFG_DRAM_TEST_ADDRESS */ + +#if defined (CFG_DRAM_TEST_WALK) +/*********************************************************************/ +/* NAME:   mem_march() -  memory march				     */ +/*								     */ +/* DESCRIPTION:							     */ +/*   Marches up through memory. At each location verifies rmask if   */ +/*   read = 1. At each location write wmask if	write = 1. Displays  */ +/*   failing address and pattern.				     */ +/*								     */ +/* INPUTS:							     */ +/*   volatile unsigned long long * base - start address of test	     */ +/*   unsigned int size - number of dwords(64-bit) to test	     */ +/*   unsigned long long rmask - read verify mask		     */ +/*   unsigned long long wmask - wrtie verify mask		     */ +/*   short read - verifies rmask if read = 1			     */ +/*   short write  - writes wmask if write = 1			     */ +/*								     */ +/* OUTPUTS:							     */ +/*   Displays failing test pattern and address			     */ +/*								     */ +/* RETURNS:							     */ +/*   0 -  Passed test						     */ +/*   1 -  Failed test						     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*								     */ +/*								     */ +/*********************************************************************/ +int mem_march(volatile unsigned long long *base, +	      unsigned int size, +	      unsigned long long rmask, +	      unsigned long long wmask, short read, short write) +{ +	unsigned int i; +	unsigned long long temp; +	unsigned int hitemp, lotemp, himask, lomask; + +	for (i = 0; i < size; i++) { +		if (read != 0) { +			/* temp = base[i]; */ +			move64((unsigned long long *)&(base[i]), &temp); +			if (rmask != temp) { +				hitemp = (temp >> 32) & 0xffffffff; +				lotemp = temp & 0xffffffff; +				himask = (rmask >> 32) & 0xffffffff; +				lomask = rmask & 0xffffffff; + +				printf("\n Walking one's test failed:	\  +					address = 0x%08x," "\n\texpected \ +					0x%08x%08x, found 0x%08x%08x", i << 3,\ +					himask, lomask, hitemp, lotemp); +				return 1; +			} +		} +		if (write != 0) { +			/*  base[i] = wmask; */ +			move64(&wmask, (unsigned long long *)&(base[i])); +		} +	} +	return 0; +} +#endif				/* CFG_DRAM_TEST_WALK */ + +/*********************************************************************/ +/* NAME:   mem_test_walk() -  a simple walking ones test	     */ +/*								     */ +/* DESCRIPTION:							     */ +/*   Performs a walking ones through entire physical memory. The     */ +/*   test uses as series of memory marches, mem_march(), to verify   */ +/*   and write the test patterns to memory. The test sequence is as  */ +/*   follows:							     */ +/*     1) march writing 0000...0001				     */ +/*     2) march verifying 0000...0001  , writing  0000...0010	     */ +/*     3) repeat step 2 shifting masks left 1 bit each time unitl    */ +/*	   the write mask equals 1000...0000			     */ +/*     4) march verifying 1000...0000				     */ +/*   The test fails if any of the memory marches return a failure.   */ +/*								     */ +/* OUTPUTS:							     */ +/*   Displays which pass on the memory test is executing	     */ +/*								     */ +/* RETURNS:							     */ +/*   0 -  Passed test						     */ +/*   1 -  Failed test						     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*								     */ +/*								     */ +/*********************************************************************/ +int mem_test_walk(void) +{ +	unsigned long long mask; +	volatile unsigned long long *pmem = +	    (volatile unsigned long long *)CFG_MEMTEST_START; +	const unsigned long size = (CFG_MEMTEST_END - CFG_MEMTEST_START) / 8; + +	unsigned int i; + +	mask = 0x01; + +	printf("Initial Pass"); +	mem_march(pmem, size, 0x0, 0x1, 0, 1); + +	printf("\b\b\b\b\b\b\b\b\b\b\b\b"); +	printf("		"); +	printf("         "); +	printf("\b\b\b\b\b\b\b\b\b\b\b\b"); + +	for (i = 0; i < 63; i++) { +		printf("Pass %2d", i + 2); +		if (mem_march(pmem, size, mask, mask << 1, 1, 1) != 0) { +			/*printf("mask: 0x%x, pass: %d, ", mask, i); */ +			return 1; +		} +		mask = mask << 1; +		printf("\b\b\b\b\b\b\b"); +	} + +	printf("Last Pass"); +	if (mem_march(pmem, size, 0, mask, 0, 1) != 0) { +		/* printf("mask: 0x%x", mask); */ +		return 1; +	} +	printf("\b\b\b\b\b\b\b\b\b"); +	printf("	     "); +	printf("\b\b\b\b\b\b\b\b\b"); + +	return 0; +} + +/*********************************************************************/ +/* NAME:    testdram() -  calls any enabled memory tests	     */ +/*								     */ +/* DESCRIPTION:							     */ +/*   Runs memory tests if the environment test variables are set to  */ +/*   'y'.							     */ +/*								     */ +/* INPUTS:							     */ +/*   testdramdata    - If set to 'y', data test is run.		     */ +/*   testdramaddress - If set to 'y', address test is run.	     */ +/*   testdramwalk    - If set to 'y', walking ones test is run	     */ +/*								     */ +/* OUTPUTS:							     */ +/*   None							     */ +/*								     */ +/* RETURNS:							     */ +/*   0 -  Passed test						     */ +/*   1 -  Failed test						     */ +/*								     */ +/* RESTRICTIONS/LIMITATIONS:					     */ +/*								     */ +/*								     */ +/*********************************************************************/ +int testdram(void) +{ +	char *s; +	int rundata, runaddress, runwalk; + +	s = getenv("testdramdata"); +	rundata = (s && (*s == 'y')) ? 1 : 0; +	s = getenv("testdramaddress"); +	runaddress = (s && (*s == 'y')) ? 1 : 0; +	s = getenv("testdramwalk"); +	runwalk = (s && (*s == 'y')) ? 1 : 0; + +/*    rundata = 1; */ +/*    runaddress = 0; */ +/*    runwalk = 0; */ + +	if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { +		printf("Testing RAM from 0x%08x to 0x%08x ...  \ +			(don't panic... that will take a moment !!!!)\n", \ +			CFG_MEMTEST_START, CFG_MEMTEST_END); +	} +#ifdef CFG_DRAM_TEST_DATA +	if (rundata == 1) { +		printf("Test DATA ...  "); +		if (mem_test_data () == 1) { +			printf("failed \n"); +			return 1; +		} else +			printf("ok \n"); +	} +#endif +#ifdef CFG_DRAM_TEST_ADDRESS +	if (runaddress == 1) { +		printf("Test ADDRESS ...  "); +		if (mem_test_address () == 1) { +			printf("failed \n"); +			return 1; +		} else +			printf("ok \n"); +	} +#endif +#ifdef CFG_DRAM_TEST_WALK +	if (runwalk == 1) { +		printf("Test WALKING ONEs ...  "); +		if (mem_test_walk() == 1) { +			printf("failed \n"); +			return 1; +		} else +			printf("ok \n"); +	} +#endif +	if ((rundata == 1) || (runaddress == 1) || (runwalk == 1)) { +		printf("passed\n"); +	} +	return 0; + +} +#endif /* CFG_DRAM_TEST */ + +#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..6f517f5a2 --- /dev/null +++ b/board/mpc7448hpc2/tsi108_init.c @@ -0,0 +1,662 @@ +/***************************************************************************** + * (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; +	switch (i) { +	case 0: +		printf("Using external clock\n"); +		break; +	case 1: +		gd->mem_clk = gd->bus_clk; +		break; +	case 4: +	case 5: +	case 6: +		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 ca45e17ed..c3aadca29 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,14 @@ get_cpu_type(void)  		type = CPU_7457;  		break; +	case 0x8003: +		type = CPU_7447A; +		break; +		 +	case 0x8004: +		type = CPU_7448; +		break; +		  	default:  		break;  	} @@ -164,6 +176,14 @@ int checkcpu (void)  		str = "MPC7457";  		break; +	case CPU_7447A: +		str = "MPC7447A"; +		break; + +	case CPU_7448: +		str = "MPC7448"; +		break; +  	default:  		printf("Unknown CPU -- PVR: 0x%08x\n", pvr);  		return -1; @@ -256,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 @@ -281,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 93f180f26..1dd1b2cd8 100644 --- a/cpu/74xx_7xx/cpu_init.c +++ b/cpu/74xx_7xx/cpu_init.c @@ -43,6 +43,8 @@ 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);  		break; diff --git a/cpu/74xx_7xx/speed.c b/cpu/74xx_7xx/speed.c index 2dc510746..d52079456 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,41 @@ static const int hid1_multipliers_x_10[] = {  	0	/* 1111 - off */  }; +static const int hid1_7447A_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 - 13x    */ +	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,8 +126,19 @@ int get_clocks (void)  {  	ulong clock = 0; +#ifdef CFG_CONFIG_BUS_CLK +	gd->bus_clk = get_board_bus_clk(); +#else +	gd->bus_clk = CFG_BUS_CLK; +#endif +  	/* calculate the clock frequency based upon the CPU type */  	switch (get_cpu_type()) { +	case CPU_7447A: +	case CPU_7448: +		clock = (gd->bus_clk / 10) * hid1_7447A_multipliers_x_10[(get_hid1 () >> 12) & 0x1F]; +		break; +		  	case CPU_7455:  	case CPU_7457:  		/* @@ -98,12 +146,12 @@ 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 () >> 13) & 0xF]; +		clock = (gd->bus_clk / 10) * hid1_multipliers_x_10[(get_hid1 () >> 13) & 0xF];  		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: @@ -120,7 +168,7 @@ 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: @@ -130,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..5142a0f63 --- /dev/null +++ b/doc/README.mpc7448hpc2 @@ -0,0 +1,193 @@ +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 9b10220fc..8f959e72a 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 @@ -253,7 +260,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]); @@ -280,7 +287,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) | @@ -312,7 +319,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 @@ -902,12 +909,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..d95a047ce --- /dev/null +++ b/drivers/tsi108_eth.c @@ -0,0 +1,1043 @@ +/*********************************************************************** + * + * 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..08e5e3b4f --- /dev/null +++ b/drivers/tsi108_i2c.c @@ -0,0 +1,300 @@ +/* + * (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> + +#ifdef CONFIG_TSI108_I2C + +#include <common.h> +#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..f374ede66 --- /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 a6287982a..7cd2f10b0 100644 --- a/include/74xx_7xx.h +++ b/include/74xx_7xx.h @@ -112,6 +112,7 @@ typedef enum __cpu_t {  	CPU_7400,  	CPU_7410,  	CPU_7450, CPU_7455, CPU_7457, +	CPU_7447A, CPU_7448,  	CPU_UNKNOWN} cpu_t;  extern cpu_t get_cpu_type(void); diff --git a/include/asm-ppc/global_data.h b/include/asm-ppc/global_data.h index b73af9646..166afbe87 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..24cc86beb --- /dev/null +++ b/include/configs/mpc7448hpc2.h @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2005 Freescale Semiconductor, Inc. + * + * (C) Copyright 2006 + * Alex Bounine , Tundra Semiconductor Corp. + * Roy Zang	, 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 + +/* Default MAC Addresses for on-chip GIGE Controller */ + +#define CONFIG_ETHADDR      00:06:D2:00:00:01 + +#define CONFIG_HAS_ETH1 +#define CONFIG_ETH1ADDR     00:06:D2:00:00:02 + +#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_IPADDR       172.27.234.48 +#define CONFIG_SERVERIP     172.27.234.10 +#define CONFIG_NETMASK      255.255.0.0 +#define CONFIG_GATEWAYIP    172.27.255.254 + +#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_DRAM_TEST + * DRAM tests + *   CFG_DRAM_TEST - enables the following tests. + * + *   CFG_DRAM_TEST_DATA - Enables test for shorted or open data lines + *			  Environment variable 'test_dram_data' must be + *			  set to 'y'. + *   CFG_DRAM_TEST_ADDRESS - Enables test to verify that each word is uniquely + *			  addressable. Environment variable + *			  'test_dram_address' must be set to 'y'. + *   CFG_DRAM_TEST_WALK - Enables test a 64-bit walking ones pattern test. + *			  This test takes about 6 minutes to test 64 MB. + *			  Environment variable 'test_dram_walk' must be + *			  set to 'y'. + */ +#undef CFG_DRAM_TEST +#define CFG_MEMTEST_START       0x00400000	/* memtest works on */ +#define CFG_MEMTEST_END         0x07c00000	/* 4 ... 124 MB in DRAM */ +#if defined(CFG_DRAM_TEST) +#define CFG_DRAM_TEST_DATA +#define CFG_DRAM_TEST_ADDRESS +#define CFG_DRAM_TEST_WALK +#endif				/* CFG_DRAM_TEST */ + +#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)	//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_EXCEPTION_AFTER_RELOCATE +#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..072daa03c --- /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	/* register block offset for general use I2C channel */ +#define TSI108_I2C_SDRAM_OFFSET 0x4400	/* register block 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..34b5d460c 100644 --- a/lib_ppc/extable.c +++ b/lib_ppc/extable.c @@ -50,14 +50,22 @@ search_one_table(const struct exception_table_entry *first,  		 const struct exception_table_entry *last,  		 unsigned long value)  { +	DECLARE_GLOBAL_DATA_PTR; +  	while (first <= last) {  		const struct exception_table_entry *mid;  		long diff;  		mid = (last - first) / 2 + first; +#ifdef CFG_EXCEPTION_AFTER_RELOCATE +		diff = (mid->insn + gd->reloc_off) - value; +		if (diff == 0) +			return (mid->fixup + gd->reloc_off); +#else  		diff = mid->insn - value;  		if (diff == 0)  			return mid->fixup; +#endif  		else if (diff < 0)  			first = mid+1;  		else @@ -75,8 +83,10 @@ 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 !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 *); @@ -245,6 +246,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 |