diff options
37 files changed, 5708 insertions, 844 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f90c5a65f..1d0a8dfdb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -288,6 +288,7 @@ Stefan Roese <sr@denx.de>  	bamboo			PPC440EP  	bunbinga		PPC405EP  	ebony			PPC440GP +	katmai			PPC440SPe  	ocotea			PPC440GX  	p3p440			PPC440GP  	pcs440ep		PPC440EP @@ -82,15 +82,15 @@ LIST_4xx="	\  	CRAYL1		csb272		csb472		DASA_SIM	\  	DP405		DU405		ebony		ERIC		\  	EXBITGEN	G2000		HH405		HUB405		\ -	JSE		KAREF		luan		METROBOX	\ -	MIP405		MIP405T		ML2		ml300		\ -	ocotea		OCRTC		ORSG		p3p440		\ -	PCI405		pcs440ep	PIP405		PLU405		\ -	PMC405		PPChameleonEVB	sbc405		sc3		\ -	sequoia		sequoia_nand	taishan		VOH405		\ -	VOM405		W7OLMC		W7OLMG		walnut		\ -	WUH405		XPEDITE1K	yellowstone	yosemite	\ -	yucca								\ +	JSE		KAREF		katmai		luan		\ +	METROBOX	MIP405		MIP405T		ML2		\ +	ml300		ocotea		OCRTC		ORSG		\ +	p3p440		PCI405		pcs440ep	PIP405		\ +	PLU405		PMC405		PPChameleonEVB	sbc405		\ +	sc3		sequoia		sequoia_nand	taishan		\ +	VOH405		VOM405		W7OLMC		W7OLMG		\ +	walnut		WUH405		XPEDITE1K	yellowstone	\ +	yosemite	yucca						\  "  ######################################################################### @@ -1095,6 +1095,9 @@ JSE_config:	unconfig  KAREF_config: unconfig  	@$(MKCONFIG) $(@:_config=) ppc ppc4xx karef sandburst +katmai_config:	unconfig +	@$(MKCONFIG) $(@:_config=) ppc ppc4xx katmai amcc +  luan_config:	unconfig  	@$(MKCONFIG) $(@:_config=) ppc ppc4xx luan amcc @@ -1347,6 +1347,16 @@ The following options need to be configured:  		If defined, then this indicates the I2C bus number for DDR SPD.  		If not defined, then U-Boot assumes that SPD is on I2C bus 0. +		CFG_RTC_BUS_NUM + +		If defined, then this indicates the I2C bus number for the RTC. +		If not defined, then U-Boot assumes that RTC is on I2C bus 0. + +		CFG_DTT_BUS_NUM + +		If defined, then this indicates the I2C bus number for the DTT. +		If not defined, then U-Boot assumes that DTT is on I2C bus 0. +  		CONFIG_FSL_I2C  		Define this option if you want to use Freescale's I2C driver in diff --git a/board/amcc/katmai/Makefile b/board/amcc/katmai/Makefile new file mode 100644 index 000000000..d06a402d1 --- /dev/null +++ b/board/amcc/katmai/Makefile @@ -0,0 +1,51 @@ +# +# (C) Copyright 2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB	= $(obj)lib$(BOARD).a + +COBJS	= $(BOARD).o cmd_katmai.o +SOBJS	= init.o + +SRCS	:= $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS	:= $(addprefix $(obj),$(COBJS)) +SOBJS	:= $(addprefix $(obj),$(SOBJS)) + +$(LIB):	$(obj).depend $(OBJS) $(SOBJS) +	$(AR) $(ARFLAGS) $@ $(OBJS) + +clean: +	rm -f $(SOBJS) $(OBJS) + +distclean:	clean +	rm -f $(LIB) core *.bak .depend *~ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/board/amcc/katmai/cmd_katmai.c b/board/amcc/katmai/cmd_katmai.c new file mode 100644 index 000000000..684f6a586 --- /dev/null +++ b/board/amcc/katmai/cmd_katmai.c @@ -0,0 +1,267 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <command.h> +#include <i2c.h> +#include <asm/byteorder.h> + +static int do_bootstrap(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +	uchar	chip; +	ulong	data; +	int	nbytes; +	extern char console_buffer[]; + +	char sysClock[4]; +	char cpuClock[4]; +	char plbClock[4]; +	char pcixClock[4]; + +	if (argc < 3) { +		printf ("Usage:\n%s\n", cmdtp->usage); +		return 1; +	} + +	if (strcmp(argv[2], "prom0") == 0) +		chip = IIC0_BOOTPROM_ADDR; +	else +		chip = IIC0_ALT_BOOTPROM_ADDR; + +	do { +		printf("enter sys clock frequency 33 or 66 Mhz or quit to abort\n"); +		nbytes = readline (" ? "); + +		if (strcmp(console_buffer, "quit") == 0) +			return 0; + +		if ((strcmp(console_buffer, "33") != 0) & +		    (strcmp(console_buffer, "66") != 0)) +			nbytes=0; + +		strcpy(sysClock, console_buffer); + +	} while (nbytes == 0); + +	do { +		if (strcmp(sysClock, "66") == 0) { +			printf("enter cpu clock frequency 400, 533 Mhz or quit to abort\n"); +		} else { +#ifdef	CONFIG_STRESS +			printf("enter cpu clock frequency 400, 500, 533, 667 Mhz or quit to abort\n"); +#else +			printf("enter cpu clock frequency 400, 500, 533 Mhz or quit to abort\n"); +#endif +		} +		nbytes = readline (" ? "); + +		if (strcmp(console_buffer, "quit") == 0) +			return 0; + +		if (strcmp(sysClock, "66") == 0) { +			if ((strcmp(console_buffer, "400") != 0) & +			    (strcmp(console_buffer, "533") != 0) +#ifdef	CONFIG_STRESS +			    & (strcmp(console_buffer, "667") != 0) +#endif +				) { +				nbytes = 0; +			} +		} else { +			if ((strcmp(console_buffer, "400") != 0) & +			    (strcmp(console_buffer, "500") != 0) & +			    (strcmp(console_buffer, "533") != 0) +#ifdef	CONFIG_STRESS +			    & (strcmp(console_buffer, "667") != 0) +#endif +				) { +				nbytes = 0; +			} +		} + +		strcpy(cpuClock, console_buffer); + +	} while (nbytes == 0); + +	if (strcmp(cpuClock, "500") == 0) +		strcpy(plbClock, "166"); +	else if (strcmp(cpuClock, "533") == 0) +		strcpy(plbClock, "133"); +	else { +		do { +			if (strcmp(cpuClock, "400") == 0) +				printf("enter plb clock frequency 100, 133 Mhz or quit to abort\n"); + +#ifdef	CONFIG_STRESS +			if (strcmp(cpuClock, "667") == 0) +				printf("enter plb clock frequency 133, 166 Mhz or quit to abort\n"); + +#endif +			nbytes = readline (" ? "); + +			if (strcmp(console_buffer, "quit") == 0) +				return 0; + +			if (strcmp(cpuClock, "400") == 0) { +				if ((strcmp(console_buffer, "100") != 0) & +				    (strcmp(console_buffer, "133") != 0)) +					nbytes = 0; +			} +#ifdef	CONFIG_STRESS +			if (strcmp(cpuClock, "667") == 0) { +				if ((strcmp(console_buffer, "133") != 0) & +				    (strcmp(console_buffer, "166") != 0)) +					nbytes = 0; +			} +#endif +			strcpy(plbClock, console_buffer); + +		} while (nbytes == 0); +	} + +	do { +		printf("enter Pci-X clock frequency 33, 66, 100 or 133 Mhz or quit to abort\n"); +		nbytes = readline (" ? "); + +		if (strcmp(console_buffer, "quit") == 0) +			return 0; + +		if ((strcmp(console_buffer, "33") != 0) & +		    (strcmp(console_buffer, "66") != 0) & +		    (strcmp(console_buffer, "100") != 0) & +		    (strcmp(console_buffer, "133") != 0)) { +			nbytes = 0; +		} +		strcpy(pcixClock, console_buffer); + +	} while (nbytes == 0); + +	printf("\nsys clk   = %sMhz\n", sysClock); +	printf("cpu clk   = %sMhz\n", cpuClock); +	printf("plb clk   = %sMhz\n", plbClock); +	printf("Pci-X clk = %sMhz\n", pcixClock); + +	do { +		printf("\npress [y] to write I2C bootstrap \n"); +		printf("or [n] to abort.  \n"); +		printf("Don't forget to set board switches \n"); +		printf("according to your choice before re-starting \n"); +		printf("(refer to 440spe_uboot_kit_um_1_01.pdf) \n"); + +		nbytes = readline (" ? "); +		if (strcmp(console_buffer, "n") == 0) +			return 0; + +	} while (nbytes == 0); + +	if (strcmp(sysClock, "33") == 0) { +		if ((strcmp(cpuClock, "400") == 0) & +		    (strcmp(plbClock, "100") == 0)) +			data = 0x8678c206; + +		if ((strcmp(cpuClock, "400") == 0) & +		    (strcmp(plbClock, "133") == 0)) +			data = 0x8678c2c6; + +		if ((strcmp(cpuClock, "500") == 0)) +			data = 0x8778f2c6; + +		if ((strcmp(cpuClock, "533") == 0)) +			data = 0x87790252; + +#ifdef	CONFIG_STRESS +		if ((strcmp(cpuClock, "667") == 0) & +		    (strcmp(plbClock, "133") == 0)) +			data = 0x87794256; + +		if ((strcmp(cpuClock, "667") == 0) & +		    (strcmp(plbClock, "166") == 0)) +			data = 0x87794206; + +#endif +	} +	if (strcmp(sysClock, "66") == 0) { +		if ((strcmp(cpuClock, "400") == 0) & +		    (strcmp(plbClock, "100") == 0)) +			data = 0x84706206; + +		if ((strcmp(cpuClock, "400") == 0) & +		    (strcmp(plbClock, "133") == 0)) +			data = 0x847062c6; + +		if ((strcmp(cpuClock, "533") == 0)) +			data = 0x85708206; + +#ifdef	CONFIG_STRESS +		if ((strcmp(cpuClock, "667") == 0) & +		    (strcmp(plbClock, "133") == 0)) +			data = 0x8570a256; + +		if ((strcmp(cpuClock, "667") == 0) & +		    (strcmp(plbClock, "166") == 0)) +			data = 0x8570a206; + +#endif +	} + +#ifdef	DEBUG +	printf(" pin strap0 to write in i2c  = %x\n", data); +#endif	/* DEBUG */ + +	if (i2c_write(chip, 0, 1, (uchar *)&data, 4) != 0) +		printf("Error writing strap0 in %s\n", argv[2]); + +	if (strcmp(pcixClock, "33") == 0) +		data = 0x00000701; + +	if (strcmp(pcixClock, "66") == 0) +		data = 0x00000601; + +	if (strcmp(pcixClock, "100") == 0) +		data = 0x00000501; + +	if (strcmp(pcixClock, "133") == 0) +		data = 0x00000401; + +	if (strcmp(plbClock, "166") == 0) +		data |= 0x05950000; +	else +		data |= 0x05A50000; + +#ifdef	DEBUG +	printf(" pin strap1 to write in i2c  = %x\n", data); +#endif	/* DEBUG */ + +	udelay(1000); +	if (i2c_write(chip, 4, 1, (uchar *)&data, 4) != 0) +		printf("Error writing strap1 in %s\n", argv[2]); + +	return 0; +} + +U_BOOT_CMD( +	bootstrap,	3,	1,	do_bootstrap, +	"bootstrap - program the serial device strap\n", +	"wrclk [prom0|prom1] - program the serial device strap\n" +	); diff --git a/board/amcc/katmai/config.mk b/board/amcc/katmai/config.mk new file mode 100644 index 000000000..115c1aed0 --- /dev/null +++ b/board/amcc/katmai/config.mk @@ -0,0 +1,38 @@ +# +# (C) Copyright 2006 +# 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 +# + +# +# AMCC 440SPe Evaluation (Katmai) board +# + +TEXT_BASE = 0xfffc0000 + +PLATFORM_CPPFLAGS += -DCONFIG_440=1 + +ifeq ($(debug),1) +PLATFORM_CPPFLAGS += -DDEBUG +endif + +ifeq ($(dbcr),1) +PLATFORM_CPPFLAGS += -DCFG_INIT_DBCR=0x8cff0000 +endif diff --git a/board/amcc/katmai/init.S b/board/amcc/katmai/init.S new file mode 100644 index 000000000..f5900bcb7 --- /dev/null +++ b/board/amcc/katmai/init.S @@ -0,0 +1,108 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + *  Copyright (C) 2002 Scott McNutt <smcnutt@artesyncp.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <ppc_asm.tmpl> +#include <config.h> +#include <asm-ppc/mmu.h> + +/************************************************************************** + * TLB TABLE + * + * This table is used by the cpu boot code to setup the initial tlb + * entries. Rather than make broad assumptions in the cpu source tree, + * this table lets each board set things up however they like. + * + *  Pointer to the table is returned in r1 + * + *************************************************************************/ + +	.section .bootpg,"ax" + +/************************************************************************** + * TLB table for revA + *************************************************************************/ +	.globl tlbtabA +tlbtabA: +	tlbtab_start +	tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + +	/* +	 * TLB entries for SDRAM are not needed on this platform. +	 * They are dynamically generated in the SPD DDR(2) detection +	 * routine. +	 */ + +	tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) +	tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) + +	tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE_BASE, SZ_16K, 0x20000000, 0xC, AC_R|AC_W|SA_G|SA_I) + +	tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x40000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x80000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0xC0000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x50000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x90000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0xD0000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbtab_end + +/************************************************************************** + * TLB table for revB + * + * Notice: revB of the 440SPe chip is very strict about PLB real addresses + * and ranges to be mapped for config space: it seems to only work with + * d_nnnn_nnnn range (hangs the core upon config transaction attempts when + * set otherwise) while revA uses c_nnnn_nnnn. + *************************************************************************/ +	.globl tlbtabB +tlbtabB: +	tlbtab_start +	tlbentry(0xff000000, SZ_16M, 0xff000000, 4, AC_R|AC_W|AC_X|SA_G) + +	/* +	 * TLB entries for SDRAM are not needed on this platform. +	 * They are dynamically generated in the SPD DDR(2) detection +	 * routine. +	 */ + +	tlbentry(CFG_ISRAM_BASE, SZ_256K, 0x00000000, 4, AC_R|AC_W|AC_X|SA_I) + +	tlbentry(CFG_PERIPHERAL_BASE, SZ_4K, 0xF0000000, 4, AC_R|AC_W|SA_G|SA_I) + +	tlbentry(CFG_ACE_BASE, SZ_1K, 0xE0000000, 4,AC_R|AC_W|SA_G|SA_I) + +	tlbentry(CFG_PCI_BASE, SZ_256M, 0x00000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCI_MEMBASE, SZ_256M, 0x10000000, 0xC, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE_MEMBASE, SZ_256M, 0xB0000000, 0xD, AC_R|AC_W|SA_G|SA_I) + +	tlbentry(CFG_PCIE0_CFGBASE, SZ_1K, 0x00100000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE1_CFGBASE, SZ_1K, 0x20100000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE2_CFGBASE, SZ_1K, 0x40100000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE0_XCFGBASE, SZ_1K, 0x10000000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE1_XCFGBASE, SZ_1K, 0x30000000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbentry(CFG_PCIE2_XCFGBASE, SZ_1K, 0x50000000, 0xD, AC_R|AC_W|SA_G|SA_I) +	tlbtab_end diff --git a/board/amcc/katmai/katmai.c b/board/amcc/katmai/katmai.c new file mode 100644 index 000000000..8704925a9 --- /dev/null +++ b/board/amcc/katmai/katmai.c @@ -0,0 +1,514 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + */ + +#include <common.h> +#include <ppc4xx.h> +#include <asm/processor.h> +#include <i2c.h> +#include <asm-ppc/io.h> + +#include "katmai.h" +#include "../cpu/ppc4xx/440spe_pcie.h" + +#undef PCIE_ENDPOINT +/* #define PCIE_ENDPOINT 1 */ + +int ppc440spe_init_pcie_rootport(int port); +void ppc440spe_setup_pcie(struct pci_controller *hose, int port); + +int board_early_init_f (void) +{ +	unsigned long mfr; +	unsigned long pfc; + +	/*----------------------------------------------------------------------+ +	 * Interrupt controller setup for the Katmai 440SPe Evaluation board. +	 *-----------------------------------------------------------------------+ +	 *-----------------------------------------------------------------------+ +	 * Interrupt | Source                            | Pol.  | Sensi.| Crit. | +	 *-----------+-----------------------------------+-------+-------+-------+ +	 * IRQ 00    | UART0                             | High  | Level | Non   | +	 * IRQ 01    | UART1                             | High  | Level | Non   | +	 * IRQ 02    | IIC0                              | High  | Level | Non   | +	 * IRQ 03    | IIC1                              | High  | Level | Non   | +	 * IRQ 04    | PCI0X0 MSG IN                     | High  | Level | Non   | +	 * IRQ 05    | PCI0X0 CMD Write                  | High  | Level | Non   | +	 * IRQ 06    | PCI0X0 Power Mgt                  | High  | Level | Non   | +	 * IRQ 07    | PCI0X0 VPD Access                 | Rising| Edge  | Non   | +	 * IRQ 08    | PCI0X0 MSI level 0                | High  | Lvl/ed| Non   | +	 * IRQ 09    | External IRQ 15 - (PCI-Express)   | pgm H | Pgm   | Non   | +	 * IRQ 10    | UIC2 Non-critical Int.            | NA    | NA    | Non   | +	 * IRQ 11    | UIC2 Critical Interrupt           | NA    | NA    | Crit  | +	 * IRQ 12    | PCI Express MSI Level 0           | Rising| Edge  | Non   | +	 * IRQ 13    | PCI Express MSI Level 1           | Rising| Edge  | Non   | +	 * IRQ 14    | PCI Express MSI Level 2           | Rising| Edge  | Non   | +	 * IRQ 15    | PCI Express MSI Level 3           | Rising| Edge  | Non   | +	 * IRQ 16    | UIC3 Non-critical Int.            | NA    | NA    | Non   | +	 * IRQ 17    | UIC3 Critical Interrupt           | NA    | NA    | Crit  | +	 * IRQ 18    | External IRQ 14 - (PCI-Express)   | Pgm   | Pgm   | Non   | +	 * IRQ 19    | DMA Channel 0 FIFO Full           | High  | Level | Non   | +	 * IRQ 20    | DMA Channel 0 Stat FIFO           | High  | Level | Non   | +	 * IRQ 21    | DMA Channel 1 FIFO Full           | High  | Level | Non   | +	 * IRQ 22    | DMA Channel 1 Stat FIFO           | High  | Level | Non   | +	 * IRQ 23    | I2O Inbound Doorbell              | High  | Level | Non   | +	 * IRQ 24    | Inbound Post List FIFO Not Empt   | High  | Level | Non   | +	 * IRQ 25    | I2O Region 0 LL PLB Write         | High  | Level | Non   | +	 * IRQ 26    | I2O Region 1 LL PLB Write         | High  | Level | Non   | +	 * IRQ 27    | I2O Region 0 HB PLB Write         | High  | Level | Non   | +	 * IRQ 28    | I2O Region 1 HB PLB Write         | High  | Level | Non   | +	 * IRQ 29    | GPT Down Count Timer              | Rising| Edge  | Non   | +	 * IRQ 30    | UIC1 Non-critical Int.            | NA    | NA    | Non   | +	 * IRQ 31    | UIC1 Critical Interrupt           | NA    | NA    | Crit. | +	 *------------------------------------------------------------------------ +	 * IRQ 32    | Ext. IRQ 13 - (PCI-Express)       |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 33    | MAL Serr                          | High  | Level | Non   | +	 * IRQ 34    | MAL Txde                          | High  | Level | Non   | +	 * IRQ 35    | MAL Rxde                          | High  | Level | Non   | +	 * IRQ 36    | DMC CE or DMC UE                  | High  | Level | Non   | +	 * IRQ 37    | EBC or UART2                      | High  |Lvl Edg| Non   | +	 * IRQ 38    | MAL TX EOB                        | High  | Level | Non   | +	 * IRQ 39    | MAL RX EOB                        | High  | Level | Non   | +	 * IRQ 40    | PCIX0 MSI Level 1                 | High  |Lvl Edg| Non   | +	 * IRQ 41    | PCIX0 MSI level 2                 | High  |Lvl Edg| Non   | +	 * IRQ 42    | PCIX0 MSI level 3                 | High  |Lvl Edg| Non   | +	 * IRQ 43    | L2 Cache                          | Risin | Edge  | Non   | +	 * IRQ 44    | GPT Compare Timer 0               | Risin | Edge  | Non   | +	 * IRQ 45    | GPT Compare Timer 1               | Risin | Edge  | Non   | +	 * IRQ 46    | GPT Compare Timer 2               | Risin | Edge  | Non   | +	 * IRQ 47    | GPT Compare Timer 3               | Risin | Edge  | Non   | +	 * IRQ 48    | GPT Compare Timer 4               | Risin | Edge  | Non   | +	 * IRQ 49    | Ext. IRQ 12 - PCI-X               |pgm/Fal|pgm/Lvl| Non   | +	 * IRQ 50    | Ext. IRQ 11 -                     |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 51    | Ext. IRQ 10 -                     |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 52    | Ext. IRQ 9                        |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 53    | Ext. IRQ 8                        |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 54    | DMA Error                         | High  | Level | Non   | +	 * IRQ 55    | DMA I2O Error                     | High  | Level | Non   | +	 * IRQ 56    | Serial ROM                        | High  | Level | Non   | +	 * IRQ 57    | PCIX0 Error                       | High  | Edge  | Non   | +	 * IRQ 58    | Ext. IRQ 7-                       |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 59    | Ext. IRQ 6-                       |pgm (H)|pgm/Lvl| Non   | +	 * IRQ 60    | EMAC0 Interrupt                   | High  | Level | Non   | +	 * IRQ 61    | EMAC0 Wake-up                     | High  | Level | Non   | +	 * IRQ 62    | Reserved                          | High  | Level | Non   | +	 * IRQ 63    | XOR                               | High  | Level | Non   | +	 *----------------------------------------------------------------------- +	 * IRQ 64    | PE0 AL                            | High  | Level | Non   | +	 * IRQ 65    | PE0 VPD Access                    | Risin | Edge  | Non   | +	 * IRQ 66    | PE0 Hot Reset Request             | Risin | Edge  | Non   | +	 * IRQ 67    | PE0 Hot Reset Request             | Falli | Edge  | Non   | +	 * IRQ 68    | PE0 TCR                           | High  | Level | Non   | +	 * IRQ 69    | PE0 BusMaster VCO                 | Falli | Edge  | Non   | +	 * IRQ 70    | PE0 DCR Error                     | High  | Level | Non   | +	 * IRQ 71    | Reserved                          | N/A   | N/A   | Non   | +	 * IRQ 72    | PE1 AL                            | High  | Level | Non   | +	 * IRQ 73    | PE1 VPD Access                    | Risin | Edge  | Non   | +	 * IRQ 74    | PE1 Hot Reset Request             | Risin | Edge  | Non   | +	 * IRQ 75    | PE1 Hot Reset Request             | Falli | Edge  | Non   | +	 * IRQ 76    | PE1 TCR                           | High  | Level | Non   | +	 * IRQ 77    | PE1 BusMaster VCO                 | Falli | Edge  | Non   | +	 * IRQ 78    | PE1 DCR Error                     | High  | Level | Non   | +	 * IRQ 79    | Reserved                          | N/A   | N/A   | Non   | +	 * IRQ 80    | PE2 AL                            | High  | Level | Non   | +	 * IRQ 81    | PE2 VPD Access                    | Risin | Edge  | Non   | +	 * IRQ 82    | PE2 Hot Reset Request             | Risin | Edge  | Non   | +	 * IRQ 83    | PE2 Hot Reset Request             | Falli | Edge  | Non   | +	 * IRQ 84    | PE2 TCR                           | High  | Level | Non   | +	 * IRQ 85    | PE2 BusMaster VCO                 | Falli | Edge  | Non   | +	 * IRQ 86    | PE2 DCR Error                     | High  | Level | Non   | +	 * IRQ 87    | Reserved                          | N/A   | N/A   | Non   | +	 * IRQ 88    | External IRQ(5)                   | Progr | Progr | Non   | +	 * IRQ 89    | External IRQ 4 - Ethernet         | Progr | Progr | Non   | +	 * IRQ 90    | External IRQ 3 - PCI-X            | Progr | Progr | Non   | +	 * IRQ 91    | External IRQ 2 - PCI-X            | Progr | Progr | Non   | +	 * IRQ 92    | External IRQ 1 - PCI-X            | Progr | Progr | Non   | +	 * IRQ 93    | External IRQ 0 - PCI-X            | Progr | Progr | Non   | +	 * IRQ 94    | Reserved                          | N/A   | N/A   | Non   | +	 * IRQ 95    | Reserved                          | N/A   | N/A   | Non   | +	 *----------------------------------------------------------------------- +	 * IRQ 96    | PE0 INTA                          | High  | Level | Non   | +	 * IRQ 97    | PE0 INTB                          | High  | Level | Non   | +	 * IRQ 98    | PE0 INTC                          | High  | Level | Non   | +	 * IRQ 99    | PE0 INTD                          | High  | Level | Non   | +	 * IRQ 100   | PE1 INTA                          | High  | Level | Non   | +	 * IRQ 101   | PE1 INTB                          | High  | Level | Non   | +	 * IRQ 102   | PE1 INTC                          | High  | Level | Non   | +	 * IRQ 103   | PE1 INTD                          | High  | Level | Non   | +	 * IRQ 104   | PE2 INTA                          | High  | Level | Non   | +	 * IRQ 105   | PE2 INTB                          | High  | Level | Non   | +	 * IRQ 106   | PE2 INTC                          | High  | Level | Non   | +	 * IRQ 107   | PE2 INTD                          | Risin | Edge  | Non   | +	 * IRQ 108   | PCI Express MSI Level 4           | Risin | Edge  | Non   | +	 * IRQ 109   | PCI Express MSI Level 5           | Risin | Edge  | Non   | +	 * IRQ 110   | PCI Express MSI Level 6           | Risin | Edge  | Non   | +	 * IRQ 111   | PCI Express MSI Level 7           | Risin | Edge  | Non   | +	 * IRQ 116   | PCI Express MSI Level 12          | Risin | Edge  | Non   | +	 * IRQ 112   | PCI Express MSI Level 8           | Risin | Edge  | Non   | +	 * IRQ 113   | PCI Express MSI Level 9           | Risin | Edge  | Non   | +	 * IRQ 114   | PCI Express MSI Level 10          | Risin | Edge  | Non   | +	 * IRQ 115   | PCI Express MSI Level 11          | Risin | Edge  | Non   | +	 * IRQ 117   | PCI Express MSI Level 13          | Risin | Edge  | Non   | +	 * IRQ 118   | PCI Express MSI Level 14          | Risin | Edge  | Non   | +	 * IRQ 119   | PCI Express MSI Level 15          | Risin | Edge  | Non   | +	 * IRQ 120   | PCI Express MSI Level 16          | Risin | Edge  | Non   | +	 * IRQ 121   | PCI Express MSI Level 17          | Risin | Edge  | Non   | +	 * IRQ 122   | PCI Express MSI Level 18          | Risin | Edge  | Non   | +	 * IRQ 123   | PCI Express MSI Level 19          | Risin | Edge  | Non   | +	 * IRQ 124   | PCI Express MSI Level 20          | Risin | Edge  | Non   | +	 * IRQ 125   | PCI Express MSI Level 21          | Risin | Edge  | Non   | +	 * IRQ 126   | PCI Express MSI Level 22          | Risin | Edge  | Non   | +	 * IRQ 127   | PCI Express MSI Level 23          | Risin | Edge  | Non   | +	 *-----------+-----------------------------------+-------+-------+-------+ */ +	/*-------------------------------------------------------------------------+ +	 * Put UICs in PowerPC440SPemode. +	 * Initialise UIC registers.  Clear all interrupts.  Disable all interrupts. +	 * Set critical interrupt values.  Set interrupt polarities.  Set interrupt +	 * trigger levels.  Make bit 0 High  priority.  Clear all interrupts again. +	 *------------------------------------------------------------------------*/ +	mtdcr (uic3sr, 0xffffffff);	/* Clear all interrupts */ +	mtdcr (uic3er, 0x00000000);	/* disable all interrupts */ +	mtdcr (uic3cr, 0x00000000);	/* Set Critical / Non Critical interrupts: */ +	mtdcr (uic3pr, 0xffffffff);	/* Set Interrupt Polarities*/ +	mtdcr (uic3tr, 0x001fffff);	/* Set Interrupt Trigger Levels */ +	mtdcr (uic3vr, 0x00000001);	/* Set Vect base=0,INT31 Highest priority */ +	mtdcr (uic3sr, 0x00000000);	/* clear all  interrupts*/ +	mtdcr (uic3sr, 0xffffffff);	/* clear all  interrupts*/ + + +	mtdcr (uic2sr, 0xffffffff);	/* Clear all interrupts */ +	mtdcr (uic2er, 0x00000000);	/* disable all interrupts*/ +	mtdcr (uic2cr, 0x00000000);	/* Set Critical / Non Critical interrupts*/ +	mtdcr (uic2pr, 0xebebebff);	/* Set Interrupt Polarities*/ +	mtdcr (uic2tr, 0x74747400);	/* Set Interrupt Trigger Levels */ +	mtdcr (uic2vr, 0x00000001);	/* Set Vect base=0,INT31 Highest priority */ +	mtdcr (uic2sr, 0x00000000);	/* clear all interrupts */ +	mtdcr (uic2sr, 0xffffffff);	/* clear all interrupts */ + +	mtdcr (uic1sr, 0xffffffff);	/* Clear all interrupts*/ +	mtdcr (uic1er, 0x00000000);	/* disable all interrupts*/ +	mtdcr (uic1cr, 0x00000000);	/* Set Critical / Non Critical interrupts*/ +	mtdcr (uic1pr, 0xffffffff);	/* Set Interrupt Polarities */ +	mtdcr (uic1tr, 0x001f8040);	/* Set Interrupt Trigger Levels*/ +	mtdcr (uic1vr, 0x00000001);	/* Set Vect base=0,INT31 Highest priority */ +	mtdcr (uic1sr, 0x00000000);	/* clear all interrupts*/ +	mtdcr (uic1sr, 0xffffffff);	/* clear all interrupts*/ + +	mtdcr (uic0sr, 0xffffffff);	/* Clear all interrupts */ +	mtdcr (uic0er, 0x00000000);	/* disable all interrupts excepted cascade    to be checked */ +	mtdcr (uic0cr, 0x00104001);	/* Set Critical / Non Critical interrupts*/ +	mtdcr (uic0pr, 0xffffffff);	/* Set Interrupt Polarities*/ +	mtdcr (uic0tr, 0x010f0004);	/* Set Interrupt Trigger Levels */ +	mtdcr (uic0vr, 0x00000001);	/* Set Vect base=0,INT31 Highest priority */ +	mtdcr (uic0sr, 0x00000000);	/* clear all interrupts*/ +	mtdcr (uic0sr, 0xffffffff);	/* clear all interrupts*/ + +/* SDR0_MFR should be part of Ethernet init */ +	mfsdr (sdr_mfr, mfr); +	mfr &= ~SDR0_MFR_ECS_MASK; +/*	mtsdr(sdr_mfr, mfr); */ + +	/* +	 * Setup GPIO signalling per defines in katmai.h +	 */ +	pfc = PFC0_KATMAI; +	mtsdr(SDR0_PFC0, pfc); + +	out32(GPIO0_OR_ADDR, GPIO_OR_KATMAI); +	out32(GPIO0_ODR_ADDR, GPIO_ODR_KATMAI); +	out32(GPIO0_TCR_ADDR, GPIO_TCR_KATMAI); + +	return 0; +} + +int checkboard (void) +{ +	char *s = getenv("serial#"); + +	printf("Board: Katmai - AMCC 440SPe Evaluation Board"); +	if (s != NULL) { +		puts(", serial# "); +		puts(s); +	} +	putc('\n'); + +	return 0; +} + +#if defined(CFG_DRAM_TEST) +int testdram (void) +{ +	uint *pstart = (uint *) 0x00000000; +	uint *pend = (uint *) 0x08000000; +	uint *p; + +	for (p = pstart; p < pend; p++) +		*p = 0xaaaaaaaa; + +	for (p = pstart; p < pend; p++) { +		if (*p != 0xaaaaaaaa) { +			printf ("SDRAM test fails at: %08x\n", (uint) p); +			return 1; +		} +	} + +	for (p = pstart; p < pend; p++) +		*p = 0x55555555; + +	for (p = pstart; p < pend; p++) { +		if (*p != 0x55555555) { +			printf ("SDRAM test fails at: %08x\n", (uint) p); +			return 1; +		} +	} +	return 0; +} +#endif + +/************************************************************************* + *  pci_pre_init + * + *  This routine is called just prior to registering the hose and gives + *  the board the opportunity to check things. Returning a value of zero + *  indicates that things are bad & PCI initialization should be aborted. + * + *	Different boards may wish to customize the pci controller structure + *	(add regions, override default access routines, etc) or perform + *	certain pre-initialization actions. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) +int pci_pre_init(struct pci_controller * hose ) +{ +	unsigned long strap; + +	/*-------------------------------------------------------------------+ +	 *	The katmai board is always configured as the host & requires the +	 *	PCI arbiter to be enabled. +	 *-------------------------------------------------------------------*/ +	mfsdr(sdr_sdstp1, strap); +	if( (strap & SDR0_SDSTP1_PAE_MASK) == 0 ) { +		printf("PCI: SDR0_STRP1[%08lX] - PCI Arbiter disabled.\n",strap); +		return 0; +	} + +	return 1; +} +#endif	/* defined(CONFIG_PCI) && defined(CFG_PCI_PRE_INIT) */ + +/************************************************************************* + *  pci_target_init + * + *	The bootstrap configuration provides default settings for the pci + *	inbound map (PIM). But the bootstrap config choices are limited and + *	may not be sufficient for a given board. + * + ************************************************************************/ +#if defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) +void pci_target_init(struct pci_controller * hose ) +{ +	DECLARE_GLOBAL_DATA_PTR; + +	/*-------------------------------------------------------------------+ +	 * Disable everything +	 *-------------------------------------------------------------------*/ +	out32r( PCIX0_PIM0SA, 0 ); /* disable */ +	out32r( PCIX0_PIM1SA, 0 ); /* disable */ +	out32r( PCIX0_PIM2SA, 0 ); /* disable */ +	out32r( PCIX0_EROMBA, 0 ); /* disable expansion rom */ + +	/*-------------------------------------------------------------------+ +	 * Map all of SDRAM to PCI address 0x0000_0000. Note that the 440 +	 * strapping options to not support sizes such as 128/256 MB. +	 *-------------------------------------------------------------------*/ +	out32r( PCIX0_PIM0LAL, CFG_SDRAM_BASE ); +	out32r( PCIX0_PIM0LAH, 0 ); +	out32r( PCIX0_PIM0SA, ~(gd->ram_size - 1) | 1 ); +	out32r( PCIX0_BAR0, 0 ); + +	/*-------------------------------------------------------------------+ +	 * Program the board's subsystem id/vendor id +	 *-------------------------------------------------------------------*/ +	out16r( PCIX0_SBSYSVID, CFG_PCI_SUBSYS_VENDORID ); +	out16r( PCIX0_SBSYSID, CFG_PCI_SUBSYS_DEVICEID ); + +	out16r( PCIX0_CMD, in16r(PCIX0_CMD) | PCI_COMMAND_MEMORY ); +} +#endif	/* defined(CONFIG_PCI) && defined(CFG_PCI_TARGET_INIT) */ + +#if defined(CONFIG_PCI) +/************************************************************************* + *  is_pci_host + * + *	This routine is called to determine if a pci scan should be + *	performed. With various hardware environments (especially cPCI and + *	PPMC) it's insufficient to depend on the state of the arbiter enable + *	bit in the strap register, or generic host/adapter assumptions. + * + *	Rather than hard-code a bad assumption in the general 440 code, the + *	440 pci code requires the board to decide at runtime. + * + *	Return 0 for adapter mode, non-zero for host (monarch) mode. + * + * + ************************************************************************/ +int is_pci_host(struct pci_controller *hose) +{ +	/* The katmai board is always configured as host. */ +	return 1; +} + +static struct pci_controller pcie_hose[3] = {{0},{0},{0}}; + +void pcie_setup_hoses(void) +{ +	struct pci_controller *hose; +	int i, bus; + +	/* +	 * assume we're called after the PCIX hose is initialized, which takes +	 * bus ID 0 and therefore start numbering PCIe's from 1. +	 */ +	bus = 1; +	for (i = 0; i <= 2; i++) { +#ifdef PCIE_ENDPOINT + 		if (ppc440spe_init_pcie_endport(i)) { +#else +		if (ppc440spe_init_pcie_rootport(i)) { +#endif +			printf("PCIE%d: initialization failed\n", i); +			continue; +		} + +		hose = &pcie_hose[i]; +		hose->first_busno = bus; +		hose->last_busno  = bus; +		bus++; + +		/* setup mem resource */ +		pci_set_region(hose->regions + 0, +			       CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, +			       CFG_PCIE_MEMBASE + i * CFG_PCIE_MEMSIZE, +			       CFG_PCIE_MEMSIZE, +			       PCI_REGION_MEM +			); +		hose->region_count = 1; +		pci_register_hose(hose); + +#ifdef PCIE_ENDPOINT +		ppc440spe_setup_pcie_endpoint(hose, i); +		/* +		 * Reson for no scanning is endpoint can not generate +		 * upstream configuration accesses. +		 */ +#else +		ppc440spe_setup_pcie_rootpoint(hose, i); +		/* +		 * Config access can only go down stream +		 */ +		hose->last_busno = pci_hose_scan(hose); +#endif +	} +} +#endif	/* defined(CONFIG_PCI) */ + +int misc_init_f (void) +{ +	uint reg; +#if defined(CONFIG_STRESS) +	uint i ; +	uint disp; +#endif + +	/* minimal init for PCIe */ +#if 0 /* test-only: test endpoint at some time, for now rootpoint only */ +	/* pci express 0 Endpoint Mode */ +	mfsdr(SDR0_PE0DLPSET, reg); +	reg &= (~0x00400000); +	mtsdr(SDR0_PE0DLPSET, reg); +#else +	/* pci express 0 Rootpoint  Mode */ +	mfsdr(SDR0_PE0DLPSET, reg); +	reg |= 0x00400000; +	mtsdr(SDR0_PE0DLPSET, reg); +#endif +	/* pci express 1 Rootpoint  Mode */ +	mfsdr(SDR0_PE1DLPSET, reg); +	reg |= 0x00400000; +	mtsdr(SDR0_PE1DLPSET, reg); +	/* pci express 2 Rootpoint  Mode */ +	mfsdr(SDR0_PE2DLPSET, reg); +	reg |= 0x00400000; +	mtsdr(SDR0_PE2DLPSET, reg); + +#if defined(CONFIG_STRESS) +	/* +	 * All this setting done by linux only needed by stress an charac. test +	 * procedure +	 * PCIe 1 Rootpoint PCIe2 Endpoint +	 * PCIe 0 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level +	 */ +	for (i=0,disp=0; i<8; i++,disp+=3) { +		mfsdr(SDR0_PE0HSSSET1L0+disp, reg); +		reg |= 0x33000000; +		mtsdr(SDR0_PE0HSSSET1L0+disp, reg); +	} + +	/*PCIe 1 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */ +	for (i=0,disp=0; i<4; i++,disp+=3) { +		mfsdr(SDR0_PE1HSSSET1L0+disp, reg); +		reg |= 0x33000000; +		mtsdr(SDR0_PE1HSSSET1L0+disp, reg); +	} + +	/*PCIE 2 FIR Pre-emphasis Filter Coefficients & Transmit Driver Power Level */ +	for (i=0,disp=0; i<4; i++,disp+=3) { +		mfsdr(SDR0_PE2HSSSET1L0+disp, reg); +		reg |= 0x33000000; +		mtsdr(SDR0_PE2HSSSET1L0+disp, reg); +	} + +	reg = 0x21242222; +	mtsdr(SDR0_PE2UTLSET1, reg); +	reg = 0x11000000; +	mtsdr(SDR0_PE2UTLSET2, reg); +	/* pci express 1 Endpoint  Mode */ +	reg = 0x00004000; +	mtsdr(SDR0_PE2DLPSET, reg); + +	mtsdr(SDR0_UART1, 0x2080005a);	/* patch for TG */ +#endif + +	return 0; +} + +#ifdef CONFIG_POST +/* + * Returns 1 if keys pressed to start the power-on long-running tests + * Called from board_init_f(). + */ +int post_hotkeys_pressed(void) +{ +	return (ctrlc()); +} +#endif diff --git a/board/amcc/katmai/katmai.h b/board/amcc/katmai/katmai.h new file mode 100644 index 000000000..9d5b793f1 --- /dev/null +++ b/board/amcc/katmai/katmai.h @@ -0,0 +1,65 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 + */ + +#ifndef __KATMAI_H_ +#define __KATMAI_H_ + +/*---------------------------------------------------------------------------- + *                    XX + *   XXXX    XX XXX   XXX     XXXX + * XX        XX  XX   XX    XX  XX + * XX  XXX   XX  XX   XX    XX  XX + * XX  XX    XXXXX    XX    XX  XX + *  XXXX     XX      XXXX    XXXX + *          XXXX + * + *  The 440SPe provices 32 bits of GPIO.  By default all GPIO pins + *  are disabled, and must be explicitly enabled by setting a + *  bit in the SDR0_PFC0 indirect DCR.  Each GPIO maps 1-to-1 with the + *  corresponding bit in the SDR0_PFC0 register (note that bit numbers + *  reflect the PowerPC convention where bit 0 is the most-significant + *  bit). + * + *   Katmai specific: + *      RS232_RX_EN# is held HIGH during reset by hardware, keeping the + *      RS232_CTS, DSR & DCD  signals coming from the MAX3411 (U26) in + *      Hi-Z condition. This prevents contention between the MAX3411 (U26) + *      and 74CBTLV3125PG (U2) during reset. + * + *      RS232_RX_EN# is connected as GPIO pin 30.  Once the processor + *      is released from reset, this pin must be configured as an output and + *      then driven high to enable the receive signals from the UART transciever. + *----------------------------------------------------------------------------*/ +#define GPIO_ENABLE(gpio)       (0x80000000 >> (gpio)) + +#define PFC0_KATMAI             GPIO_ENABLE(30) +#define GPIO_OR_KATMAI          GPIO_ENABLE(30)     /* Drive all outputs low except GPIO 30 */ +#define GPIO_TCR_KATMAI         GPIO_ENABLE(30) +#define GPIO_ODR_KATMAI         0                   /* Disable open drain for all outputs */ + +#define GPIO0_OR_ADDR           (CFG_PERIPHERAL_BASE + 0x700) +#define GPIO0_TCR_ADDR          (CFG_PERIPHERAL_BASE + 0x704) +#define GPIO0_ODR_ADDR          (CFG_PERIPHERAL_BASE + 0x718) +#define GPIO0_IR_ADDR           (CFG_PERIPHERAL_BASE + 0x71C) + +#endif /* __KATMAI_H_ */ diff --git a/board/amcc/katmai/u-boot.lds b/board/amcc/katmai/u-boot.lds new file mode 100644 index 000000000..9fe661e24 --- /dev/null +++ b/board/amcc/katmai/u-boot.lds @@ -0,0 +1,157 @@ +/* + * (C) Copyright 2004 + * 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 + */ + +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 +{ +  .resetvec 0xFFFFFFFC : +  { +    *(.resetvec) +  } = 0xffff + +  .bootpg 0xFFFFF000 : +  { +    cpu/ppc4xx/start.o	(.bootpg) +  } = 0xffff + +  /* 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      : +  { +    /* WARNING - the following is hand-optimized to fit within	*/ +    /* the sector layout of our flash chips!	XXX FIXME XXX	*/ + +    cpu/ppc4xx/start.o		(.text) +    board/amcc/katmai/init.o	(.text) +    cpu/ppc4xx/kgdb.o		(.text) +    cpu/ppc4xx/traps.o		(.text) +    cpu/ppc4xx/interrupts.o	(.text) +    cpu/ppc4xx/serial.o		(.text) +    cpu/ppc4xx/cpu_init.o	(.text) +    cpu/ppc4xx/speed.o		(.text) +    common/dlmalloc.o		(.text) +    lib_generic/crc32.o		(.text) +    lib_ppc/extable.o		(.text) +    lib_generic/zlib.o		(.text) + +/*    . = env_offset;*/ +/*    common/environment.o(.text)*/ + +    *(.text) +    *(.fixup) +    *(.got1) +  } +  _etext = .; +  PROVIDE (etext = .); +  .rodata    : +  { +    *(.rodata) +    *(.rodata1) +    *(.rodata.str1.4) +    *(.eh_frame) +  } +  .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/board/cray/L1/L1.c b/board/cray/L1/L1.c index a7114eb07..a0fac7fe5 100644 --- a/board/cray/L1/L1.c +++ b/board/cray/L1/L1.c @@ -23,7 +23,7 @@  #include <common.h>  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <command.h>  #include <rtc.h>  #include <post.h> diff --git a/board/esd/du405/du405.c b/board/esd/du405/du405.c index a019ce421..69432138d 100644 --- a/board/esd/du405/du405.c +++ b/board/esd/du405/du405.c @@ -25,7 +25,7 @@  #include "du405.h"  #include <asm/processor.h>  #include <ppc4xx.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <command.h>  DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mpl/common/memtst.c b/board/mpl/common/memtst.c index ff1190ab2..1d28513d8 100644 --- a/board/mpl/common/memtst.c +++ b/board/mpl/common/memtst.c @@ -48,7 +48,7 @@ int testdram (void)  #include <common.h>  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mpl/mip405/mip405.c b/board/mpl/mip405/mip405.c index 13249787d..4b1c1c066 100644 --- a/board/mpl/mip405/mip405.c +++ b/board/mpl/mip405/mip405.c @@ -65,7 +65,7 @@  #include <common.h>  #include "mip405.h"  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <miiphy.h>  #include "../common/common_util.h"  #include <i2c.h> diff --git a/board/sandburst/common/ppc440gx_i2c.c b/board/sandburst/common/ppc440gx_i2c.c index 859dd7afe..1e3dffb1e 100644 --- a/board/sandburst/common/ppc440gx_i2c.c +++ b/board/sandburst/common/ppc440gx_i2c.c @@ -27,13 +27,8 @@   */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h> -#include <440_i2c.h>  #include <command.h>  #include "ppc440gx_i2c.h" diff --git a/board/sandburst/common/ppc440gx_i2c.h b/board/sandburst/common/ppc440gx_i2c.h index cd4fc8666..10000f5ba 100644 --- a/board/sandburst/common/ppc440gx_i2c.h +++ b/board/sandburst/common/ppc440gx_i2c.h @@ -27,11 +27,7 @@   */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h>  #ifdef CONFIG_HARD_I2C diff --git a/common/cmd_date.c b/common/cmd_date.c index 84932f756..33d2e5661 100644 --- a/common/cmd_date.c +++ b/common/cmd_date.c @@ -27,6 +27,7 @@  #include <common.h>  #include <command.h>  #include <rtc.h> +#include <i2c.h>  DECLARE_GLOBAL_DATA_PTR; @@ -44,6 +45,11 @@ int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  {  	struct rtc_time tm;  	int rcode = 0; +	int old_bus; + +	/* switch to correct I2C bus */ +	old_bus = I2C_GET_BUS(); +	I2C_SET_BUS(CFG_RTC_BUS_NUM);  	switch (argc) {  	case 2:			/* set date & time */ @@ -56,7 +62,7 @@ int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  			/* insert new date & time */  			if (mk_date (argv[1], &tm) != 0) {  				puts ("## Bad date format\n"); -				return 1; +				break;  			}  			/* and write to RTC */  			rtc_set (&tm); @@ -71,11 +77,15 @@ int do_date (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])  				"unknown " : RELOC(weekdays[tm.tm_wday]),  			tm.tm_hour, tm.tm_min, tm.tm_sec); -		return 0; +		break;  	default:  		printf ("Usage:\n%s\n", cmdtp->usage);  		rcode = 1;  	} + +	/* switch back to original I2C bus */ +	I2C_SET_BUS(old_bus); +  	return rcode;  } diff --git a/common/cmd_dtt.c b/common/cmd_dtt.c index 9db64e9e3..4f7b049d7 100644 --- a/common/cmd_dtt.c +++ b/common/cmd_dtt.c @@ -28,19 +28,27 @@  #if (CONFIG_COMMANDS & CFG_CMD_DTT)  #include <dtt.h> +#include <i2c.h>  int do_dtt (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])  {  	int i;  	unsigned char sensors[] = CONFIG_DTT_SENSORS; +	int old_bus; + +	/* switch to correct I2C bus */ +	old_bus = I2C_GET_BUS(); +	I2C_SET_BUS(CFG_DTT_BUS_NUM);  	/*  	 * Loop through sensors, read  	 * temperature, and output it.  	 */ -	for (i = 0; i < sizeof (sensors); i++) { +	for (i = 0; i < sizeof (sensors); i++)  		printf ("DTT%d: %i C\n", i + 1, dtt_get_temp (sensors[i])); -	} + +	/* switch back to original I2C bus */ +	I2C_SET_BUS(old_bus);  	return 0;  }	/* do_dtt() */ diff --git a/cpu/ppc4xx/40x_spd_sdram.c b/cpu/ppc4xx/40x_spd_sdram.c new file mode 100644 index 000000000..19c4f764e --- /dev/null +++ b/cpu/ppc4xx/40x_spd_sdram.c @@ -0,0 +1,469 @@ +/* + * cpu/ppc4xx/40x_spd_sdram.c + * This SPD SDRAM detection code supports IBM/AMCC PPC44x cpu with a + * SDRAM controller. Those are all current 405 PPC's. + * + * (C) Copyright 2001 + * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com + * + * Based on code by: + * + * Kenneth Johansson ,Ericsson AB. + * kenneth.johansson@etx.ericsson.se + * + * hacked up by bill hunter. fixed so we could run before + * serial_init and console_init. previous version avoided this by + * running out of cache memory during serial/console init, then running + * this code later. + * + * (C) Copyright 2002 + * Jun Gu, Artesyn Technology, jung@artesyncp.com + * Support for AMCC 440 based on OpenBIOS draminit.c from IBM. + * + * (C) Copyright 2005 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/processor.h> +#include <i2c.h> +#include <ppc4xx.h> + +#if defined(CONFIG_SPD_EEPROM) && !defined(CONFIG_440) + +/* + * Set default values + */ +#ifndef CFG_I2C_SPEED +#define CFG_I2C_SPEED	50000 +#endif + +#ifndef CFG_I2C_SLAVE +#define CFG_I2C_SLAVE	0xFE +#endif + +#define ONE_BILLION	1000000000 + +#define	 SDRAM0_CFG_DCE		0x80000000 +#define	 SDRAM0_CFG_SRE		0x40000000 +#define	 SDRAM0_CFG_PME		0x20000000 +#define	 SDRAM0_CFG_MEMCHK	0x10000000 +#define	 SDRAM0_CFG_REGEN	0x08000000 +#define	 SDRAM0_CFG_ECCDD	0x00400000 +#define	 SDRAM0_CFG_EMDULR	0x00200000 +#define	 SDRAM0_CFG_DRW_SHIFT	(31-6) +#define	 SDRAM0_CFG_BRPF_SHIFT	(31-8) + +#define	 SDRAM0_TR_CASL_SHIFT	(31-8) +#define	 SDRAM0_TR_PTA_SHIFT	(31-13) +#define	 SDRAM0_TR_CTP_SHIFT	(31-15) +#define	 SDRAM0_TR_LDF_SHIFT	(31-17) +#define	 SDRAM0_TR_RFTA_SHIFT	(31-29) +#define	 SDRAM0_TR_RCD_SHIFT	(31-31) + +#define	 SDRAM0_RTR_SHIFT	(31-15) +#define	 SDRAM0_ECCCFG_SHIFT	(31-11) + +/* SDRAM0_CFG enable macro  */ +#define SDRAM0_CFG_BRPF(x) ( ( x & 0x3)<< SDRAM0_CFG_BRPF_SHIFT ) + +#define SDRAM0_BXCR_SZ_MASK	0x000e0000 +#define SDRAM0_BXCR_AM_MASK	0x0000e000 + +#define SDRAM0_BXCR_SZ_SHIFT	(31-14) +#define SDRAM0_BXCR_AM_SHIFT	(31-18) + +#define SDRAM0_BXCR_SZ(x)	( (( x << SDRAM0_BXCR_SZ_SHIFT) & SDRAM0_BXCR_SZ_MASK) ) +#define SDRAM0_BXCR_AM(x)	( (( x << SDRAM0_BXCR_AM_SHIFT) & SDRAM0_BXCR_AM_MASK) ) + +#ifdef CONFIG_SPDDRAM_SILENT +# define SPD_ERR(x) do { return 0; } while (0) +#else +# define SPD_ERR(x) do { printf(x); return(0); } while (0) +#endif + +#define sdram_HZ_to_ns(hertz) (1000000000/(hertz)) + +/* function prototypes */ +int spd_read(uint addr); + + +/* + * This function is reading data from the DIMM module EEPROM over the SPD bus + * and uses that to program the sdram controller. + * + * This works on boards that has the same schematics that the AMCC walnut has. + * + * Input: null for default I2C spd functions or a pointer to a custom function + * returning spd_data. + */ + +long int spd_sdram(int(read_spd)(uint addr)) +{ +	int tmp,row,col; +	int total_size,bank_size,bank_code; +	int ecc_on; +	int mode; +	int bank_cnt; + +	int sdram0_pmit=0x07c00000; +#ifndef CONFIG_405EP /* not on PPC405EP */ +	int sdram0_besr0=-1; +	int sdram0_besr1=-1; +	int sdram0_eccesr=-1; +#endif +	int sdram0_ecccfg; + +	int sdram0_rtr=0; +	int sdram0_tr=0; + +	int sdram0_b0cr; +	int sdram0_b1cr; +	int sdram0_b2cr; +	int sdram0_b3cr; + +	int sdram0_cfg=0; + +	int t_rp; +	int t_rcd; +	int t_ras; +	int t_rc; +	int min_cas; + +	PPC405_SYS_INFO sys_info; +	unsigned long bus_period_x_10; + +	/* +	 * get the board info +	 */ +	get_sys_info(&sys_info); +	bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); + +	if (read_spd == 0){ +		read_spd=spd_read; +		/* +		 * Make sure I2C controller is initialized +		 * before continuing. +		 */ +		i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); +	} + +	/* Make shure we are using SDRAM */ +	if (read_spd(2) != 0x04) { +		SPD_ERR("SDRAM - non SDRAM memory module found\n"); +	} + +	/* ------------------------------------------------------------------ +	 * configure memory timing register +	 * +	 * data from DIMM: +	 * 27	IN Row Precharge Time ( t RP) +	 * 29	MIN RAS to CAS Delay ( t RCD) +	 * 127	 Component and Clock Detail ,clk0-clk3, junction temp, CAS +	 * -------------------------------------------------------------------*/ + +	/* +	 * first figure out which cas latency mode to use +	 * use the min supported mode +	 */ + +	tmp = read_spd(127) & 0x6; +	if (tmp == 0x02) {		/* only cas = 2 supported */ +		min_cas = 2; +/*		t_ck = read_spd(9); */ +/*		t_ac = read_spd(10); */ +	} else if (tmp == 0x04) {	/* only cas = 3 supported */ +		min_cas = 3; +/*		t_ck = read_spd(9); */ +/*		t_ac = read_spd(10); */ +	} else if (tmp == 0x06) {	/* 2,3 supported, so use 2 */ +		min_cas = 2; +/*		t_ck = read_spd(23); */ +/*		t_ac = read_spd(24); */ +	} else { +		SPD_ERR("SDRAM - unsupported CAS latency \n"); +	} + +	/* get some timing values, t_rp,t_rcd,t_ras,t_rc +	 */ +	t_rp = read_spd(27); +	t_rcd = read_spd(29); +	t_ras = read_spd(30); +	t_rc = t_ras + t_rp; + +	/* The following timing calcs subtract 1 before deviding. +	 * this has effect of using ceiling instead of floor rounding, +	 * and also subtracting 1 to convert number to reg value +	 */ +	/* set up CASL */ +	sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT; +	/* set up PTA */ +	sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT; +	/* set up CTP */ +	tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3; +	if (tmp < 1) +		tmp = 1; +	sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT; +	/* set LDF	= 2 cycles, reg value = 1 */ +	sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT; +	/* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */ +	tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3; +	if (tmp < 0) +		tmp = 0; +	if (tmp > 6) +		tmp = 6; +	sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT; +	/* set RCD = t_rcd/bus_period*/ +	sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ; + + +	/*------------------------------------------------------------------ +	 * configure RTR register +	 * -------------------------------------------------------------------*/ +	row = read_spd(3); +	col = read_spd(4); +	tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */ +	switch (tmp) { +	case 0x00: +		tmp = 15625; +		break; +	case 0x01: +		tmp = 15625 / 4; +		break; +	case 0x02: +		tmp = 15625 / 2; +		break; +	case 0x03: +		tmp = 15625 * 2; +		break; +	case 0x04: +		tmp = 15625 * 4; +		break; +	case 0x05: +		tmp = 15625 * 8; +		break; +	default: +		SPD_ERR("SDRAM - Bad refresh period \n"); +	} +	/* convert from nsec to bus cycles */ +	tmp = (tmp * 10) / bus_period_x_10; +	sdram0_rtr = (tmp & 0x3ff8) <<	SDRAM0_RTR_SHIFT; + +	/*------------------------------------------------------------------ +	 * determine the number of banks used +	 * -------------------------------------------------------------------*/ +	/* byte 7:6 is module data width */ +	if (read_spd(7) != 0) +		SPD_ERR("SDRAM - unsupported module width\n"); +	tmp = read_spd(6); +	if (tmp < 32) +		SPD_ERR("SDRAM - unsupported module width\n"); +	else if (tmp < 64) +		bank_cnt = 1;		/* one bank per sdram side */ +	else if (tmp < 73) +		bank_cnt = 2;	/* need two banks per side */ +	else if (tmp < 161) +		bank_cnt = 4;	/* need four banks per side */ +	else +		SPD_ERR("SDRAM - unsupported module width\n"); + +	/* byte 5 is the module row count (refered to as dimm "sides") */ +	tmp = read_spd(5); +	if (tmp == 1) +		; +	else if (tmp==2) +		bank_cnt *= 2; +	else if (tmp==4) +		bank_cnt *= 4; +	else +		bank_cnt = 8;		/* 8 is an error code */ + +	if (bank_cnt > 4)	/* we only have 4 banks to work with */ +		SPD_ERR("SDRAM - unsupported module rows for this width\n"); + +	/* now check for ECC ability of module. We only support ECC +	 *   on 32 bit wide devices with 8 bit ECC. +	 */ +	if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) { +		sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT; +		ecc_on = 1; +	} else { +		sdram0_ecccfg = 0; +		ecc_on = 0; +	} + +	/*------------------------------------------------------------------ +	 * calculate total size +	 * -------------------------------------------------------------------*/ +	/* calculate total size and do sanity check */ +	tmp = read_spd(31); +	total_size = 1 << 22;	/* total_size = 4MB */ +	/* now multiply 4M by the smallest device row density */ +	/* note that we don't support asymetric rows */ +	while (((tmp & 0x0001) == 0) && (tmp != 0)) { +		total_size = total_size << 1; +		tmp = tmp >> 1; +	} +	total_size *= read_spd(5);	/* mult by module rows (dimm sides) */ + +	/*------------------------------------------------------------------ +	 * map	rows * cols * banks to a mode +	 * -------------------------------------------------------------------*/ + +	switch (row) { +	case 11: +		switch (col) { +		case 8: +			mode=4; /* mode 5 */ +			break; +		case 9: +		case 10: +			mode=0; /* mode 1 */ +			break; +		default: +			SPD_ERR("SDRAM - unsupported mode\n"); +		} +		break; +	case 12: +		switch (col) { +		case 8: +			mode=3; /* mode 4 */ +			break; +		case 9: +		case 10: +			mode=1; /* mode 2 */ +			break; +		default: +			SPD_ERR("SDRAM - unsupported mode\n"); +		} +		break; +	case 13: +		switch (col) { +		case 8: +			mode=5; /* mode 6 */ +			break; +		case 9: +		case 10: +			if (read_spd(17) == 2) +				mode = 6; /* mode 7 */ +			else +				mode = 2; /* mode 3 */ +			break; +		case 11: +			mode = 2; /* mode 3 */ +			break; +		default: +			SPD_ERR("SDRAM - unsupported mode\n"); +		} +		break; +	default: +		SPD_ERR("SDRAM - unsupported mode\n"); +	} + +	/*------------------------------------------------------------------ +	 * using the calculated values, compute the bank +	 * config register values. +	 * -------------------------------------------------------------------*/ +	sdram0_b1cr = 0; +	sdram0_b2cr = 0; +	sdram0_b3cr = 0; + +	/* compute the size of each bank */ +	bank_size = total_size / bank_cnt; +	/* convert bank size to bank size code for ppc4xx +	   by takeing log2(bank_size) - 22 */ +	tmp = bank_size;		/* start with tmp = bank_size */ +	bank_code = 0;			/* and bank_code = 0 */ +	while (tmp > 1) {		/* this takes log2 of tmp */ +		bank_code++;		/* and stores result in bank_code */ +		tmp = tmp >> 1; +	}				/* bank_code is now log2(bank_size) */ +	bank_code -= 22;		/* subtract 22 to get the code */ + +	tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1; +	sdram0_b0cr = (bank_size * 0) | tmp; +#ifndef CONFIG_405EP /* not on PPC405EP */ +	if (bank_cnt > 1) +		sdram0_b2cr = (bank_size * 1) | tmp; +	if (bank_cnt > 2) +		sdram0_b1cr = (bank_size * 2) | tmp; +	if (bank_cnt > 3) +		sdram0_b3cr = (bank_size * 3) | tmp; +#else +	/* PPC405EP chip only supports two SDRAM banks */ +	if (bank_cnt > 1) +		sdram0_b1cr = (bank_size * 1) | tmp; +	if (bank_cnt > 2) +		total_size = 2 * bank_size; +#endif + +	/* +	 *   enable sdram controller DCE=1 +	 *  enable burst read prefetch to 32 bytes BRPF=2 +	 *  leave other functions off +	 */ + +	/*------------------------------------------------------------------ +	 * now that we've done our calculations, we are ready to +	 * program all the registers. +	 * -------------------------------------------------------------------*/ + +#define mtsdram0(reg, data)  mtdcr(memcfga,reg);mtdcr(memcfgd,data) +	/* disable memcontroller so updates work */ +	mtsdram0( mem_mcopt1, 0 ); + +#ifndef CONFIG_405EP /* not on PPC405EP */ +	mtsdram0( mem_besra , sdram0_besr0 ); +	mtsdram0( mem_besrb , sdram0_besr1 ); +	mtsdram0( mem_ecccf , sdram0_ecccfg ); +	mtsdram0( mem_eccerr, sdram0_eccesr ); +#endif +	mtsdram0( mem_rtr   , sdram0_rtr ); +	mtsdram0( mem_pmit  , sdram0_pmit ); +	mtsdram0( mem_mb0cf , sdram0_b0cr ); +	mtsdram0( mem_mb1cf , sdram0_b1cr ); +#ifndef CONFIG_405EP /* not on PPC405EP */ +	mtsdram0( mem_mb2cf , sdram0_b2cr ); +	mtsdram0( mem_mb3cf , sdram0_b3cr ); +#endif +	mtsdram0( mem_sdtr1 , sdram0_tr ); + +	/* SDRAM have a power on delay,	 500 micro should do */ +	udelay(500); +	sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR; +	if (ecc_on) +		sdram0_cfg |= SDRAM0_CFG_MEMCHK; +	mtsdram0(mem_mcopt1, sdram0_cfg); + +	return (total_size); +} + +int spd_read(uint addr) +{ +	uchar data[2]; + +	if (i2c_read(SPD_EEPROM_ADDRESS, addr, 1, data, 1) == 0) +		return (int)data[0]; +	else +		return 0; +} + +#endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/ppc4xx/spd_sdram.c b/cpu/ppc4xx/44x_spd_ddr.c index c24456bea..32d44dbe5 100644 --- a/cpu/ppc4xx/spd_sdram.c +++ b/cpu/ppc4xx/44x_spd_ddr.c @@ -1,4 +1,8 @@  /* + * cpu/ppc4xx/44x_spd_ddr.c + * This SPD DDR detection code supports IBM/AMCC PPC44x cpu with a + * DDR controller. Those are 440GP/GX/EP/GR. + *   * (C) Copyright 2001   * Bill Hunter, Wave 7 Optics, williamhunter@attbi.com   * @@ -43,7 +47,9 @@  #include <i2c.h>  #include <ppc4xx.h> -#ifdef CONFIG_SPD_EEPROM +#if defined(CONFIG_SPD_EEPROM) &&					\ +	(defined(CONFIG_440GP) || defined(CONFIG_440GX) ||		\ +	 defined(CONFIG_440EP) || defined(CONFIG_440GR))  /*   * Set default values @@ -58,414 +64,6 @@  #define ONE_BILLION	1000000000 -#ifndef	 CONFIG_440		/* for 405 WALNUT/SYCAMORE/BUBINGA boards */ - -#define	 SDRAM0_CFG_DCE		0x80000000 -#define	 SDRAM0_CFG_SRE		0x40000000 -#define	 SDRAM0_CFG_PME		0x20000000 -#define	 SDRAM0_CFG_MEMCHK	0x10000000 -#define	 SDRAM0_CFG_REGEN	0x08000000 -#define	 SDRAM0_CFG_ECCDD	0x00400000 -#define	 SDRAM0_CFG_EMDULR	0x00200000 -#define	 SDRAM0_CFG_DRW_SHIFT	(31-6) -#define	 SDRAM0_CFG_BRPF_SHIFT	(31-8) - -#define	 SDRAM0_TR_CASL_SHIFT	(31-8) -#define	 SDRAM0_TR_PTA_SHIFT	(31-13) -#define	 SDRAM0_TR_CTP_SHIFT	(31-15) -#define	 SDRAM0_TR_LDF_SHIFT	(31-17) -#define	 SDRAM0_TR_RFTA_SHIFT	(31-29) -#define	 SDRAM0_TR_RCD_SHIFT	(31-31) - -#define	 SDRAM0_RTR_SHIFT	(31-15) -#define	 SDRAM0_ECCCFG_SHIFT	(31-11) - -/* SDRAM0_CFG enable macro  */ -#define SDRAM0_CFG_BRPF(x) ( ( x & 0x3)<< SDRAM0_CFG_BRPF_SHIFT ) - -#define SDRAM0_BXCR_SZ_MASK	0x000e0000 -#define SDRAM0_BXCR_AM_MASK	0x0000e000 - -#define SDRAM0_BXCR_SZ_SHIFT	(31-14) -#define SDRAM0_BXCR_AM_SHIFT	(31-18) - -#define SDRAM0_BXCR_SZ(x)	( (( x << SDRAM0_BXCR_SZ_SHIFT) & SDRAM0_BXCR_SZ_MASK) ) -#define SDRAM0_BXCR_AM(x)	( (( x << SDRAM0_BXCR_AM_SHIFT) & SDRAM0_BXCR_AM_MASK) ) - -#ifdef CONFIG_SPDDRAM_SILENT -# define SPD_ERR(x) do { return 0; } while (0) -#else -# define SPD_ERR(x) do { printf(x); return(0); } while (0) -#endif - -#define sdram_HZ_to_ns(hertz) (1000000000/(hertz)) - -/* function prototypes */ -int spd_read(uint addr); - - -/* - * This function is reading data from the DIMM module EEPROM over the SPD bus - * and uses that to program the sdram controller. - * - * This works on boards that has the same schematics that the AMCC walnut has. - * - * Input: null for default I2C spd functions or a pointer to a custom function - * returning spd_data. - */ - -long int spd_sdram(int(read_spd)(uint addr)) -{ -	int tmp,row,col; -	int total_size,bank_size,bank_code; -	int ecc_on; -	int mode; -	int bank_cnt; - -	int sdram0_pmit=0x07c00000; -#ifndef CONFIG_405EP /* not on PPC405EP */ -	int sdram0_besr0=-1; -	int sdram0_besr1=-1; -	int sdram0_eccesr=-1; -#endif -	int sdram0_ecccfg; - -	int sdram0_rtr=0; -	int sdram0_tr=0; - -	int sdram0_b0cr; -	int sdram0_b1cr; -	int sdram0_b2cr; -	int sdram0_b3cr; - -	int sdram0_cfg=0; - -	int t_rp; -	int t_rcd; -	int t_ras; -	int t_rc; -	int min_cas; - -	PPC405_SYS_INFO sys_info; -	unsigned long bus_period_x_10; - -	/* -	 * get the board info -	 */ -	get_sys_info(&sys_info); -	bus_period_x_10 = ONE_BILLION / (sys_info.freqPLB / 10); - -	if (read_spd == 0){ -		read_spd=spd_read; -		/* -		 * Make sure I2C controller is initialized -		 * before continuing. -		 */ -		i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); -	} - -	/* Make shure we are using SDRAM */ -	if (read_spd(2) != 0x04) { -		SPD_ERR("SDRAM - non SDRAM memory module found\n"); -	} - -	/* ------------------------------------------------------------------ -	 * configure memory timing register -	 * -	 * data from DIMM: -	 * 27	IN Row Precharge Time ( t RP) -	 * 29	MIN RAS to CAS Delay ( t RCD) -	 * 127	 Component and Clock Detail ,clk0-clk3, junction temp, CAS -	 * -------------------------------------------------------------------*/ - -	/* -	 * first figure out which cas latency mode to use -	 * use the min supported mode -	 */ - -	tmp = read_spd(127) & 0x6; -	if (tmp == 0x02) {		/* only cas = 2 supported */ -		min_cas = 2; -/*		t_ck = read_spd(9); */ -/*		t_ac = read_spd(10); */ -	} else if (tmp == 0x04) {	/* only cas = 3 supported */ -		min_cas = 3; -/*		t_ck = read_spd(9); */ -/*		t_ac = read_spd(10); */ -	} else if (tmp == 0x06) {	/* 2,3 supported, so use 2 */ -		min_cas = 2; -/*		t_ck = read_spd(23); */ -/*		t_ac = read_spd(24); */ -	} else { -		SPD_ERR("SDRAM - unsupported CAS latency \n"); -	} - -	/* get some timing values, t_rp,t_rcd,t_ras,t_rc -	 */ -	t_rp = read_spd(27); -	t_rcd = read_spd(29); -	t_ras = read_spd(30); -	t_rc = t_ras + t_rp; - -	/* The following timing calcs subtract 1 before deviding. -	 * this has effect of using ceiling instead of floor rounding, -	 * and also subtracting 1 to convert number to reg value -	 */ -	/* set up CASL */ -	sdram0_tr = (min_cas - 1) << SDRAM0_TR_CASL_SHIFT; -	/* set up PTA */ -	sdram0_tr |= ((((t_rp - 1) * 10)/bus_period_x_10) & 0x3) << SDRAM0_TR_PTA_SHIFT; -	/* set up CTP */ -	tmp = (((t_rc - t_rcd - t_rp -1) * 10) / bus_period_x_10) & 0x3; -	if (tmp < 1) -		tmp = 1; -	sdram0_tr |= tmp << SDRAM0_TR_CTP_SHIFT; -	/* set LDF	= 2 cycles, reg value = 1 */ -	sdram0_tr |= 1 << SDRAM0_TR_LDF_SHIFT; -	/* set RFTA = t_rfc/bus_period, use t_rfc = t_rc */ -	tmp = (((t_rc - 1) * 10) / bus_period_x_10) - 3; -	if (tmp < 0) -		tmp = 0; -	if (tmp > 6) -		tmp = 6; -	sdram0_tr |= tmp << SDRAM0_TR_RFTA_SHIFT; -	/* set RCD = t_rcd/bus_period*/ -	sdram0_tr |= ((((t_rcd - 1) * 10) / bus_period_x_10) &0x3) << SDRAM0_TR_RCD_SHIFT ; - - -	/*------------------------------------------------------------------ -	 * configure RTR register -	 * -------------------------------------------------------------------*/ -	row = read_spd(3); -	col = read_spd(4); -	tmp = read_spd(12) & 0x7f ; /* refresh type less self refresh bit */ -	switch (tmp) { -	case 0x00: -		tmp = 15625; -		break; -	case 0x01: -		tmp = 15625 / 4; -		break; -	case 0x02: -		tmp = 15625 / 2; -		break; -	case 0x03: -		tmp = 15625 * 2; -		break; -	case 0x04: -		tmp = 15625 * 4; -		break; -	case 0x05: -		tmp = 15625 * 8; -		break; -	default: -		SPD_ERR("SDRAM - Bad refresh period \n"); -	} -	/* convert from nsec to bus cycles */ -	tmp = (tmp * 10) / bus_period_x_10; -	sdram0_rtr = (tmp & 0x3ff8) <<	SDRAM0_RTR_SHIFT; - -	/*------------------------------------------------------------------ -	 * determine the number of banks used -	 * -------------------------------------------------------------------*/ -	/* byte 7:6 is module data width */ -	if (read_spd(7) != 0) -		SPD_ERR("SDRAM - unsupported module width\n"); -	tmp = read_spd(6); -	if (tmp < 32) -		SPD_ERR("SDRAM - unsupported module width\n"); -	else if (tmp < 64) -		bank_cnt = 1;		/* one bank per sdram side */ -	else if (tmp < 73) -		bank_cnt = 2;	/* need two banks per side */ -	else if (tmp < 161) -		bank_cnt = 4;	/* need four banks per side */ -	else -		SPD_ERR("SDRAM - unsupported module width\n"); - -	/* byte 5 is the module row count (refered to as dimm "sides") */ -	tmp = read_spd(5); -	if (tmp == 1) -		; -	else if (tmp==2) -		bank_cnt *= 2; -	else if (tmp==4) -		bank_cnt *= 4; -	else -		bank_cnt = 8;		/* 8 is an error code */ - -	if (bank_cnt > 4)	/* we only have 4 banks to work with */ -		SPD_ERR("SDRAM - unsupported module rows for this width\n"); - -	/* now check for ECC ability of module. We only support ECC -	 *   on 32 bit wide devices with 8 bit ECC. -	 */ -	if ((read_spd(11)==2) && (read_spd(6)==40) && (read_spd(14)==8)) { -		sdram0_ecccfg = 0xf << SDRAM0_ECCCFG_SHIFT; -		ecc_on = 1; -	} else { -		sdram0_ecccfg = 0; -		ecc_on = 0; -	} - -	/*------------------------------------------------------------------ -	 * calculate total size -	 * -------------------------------------------------------------------*/ -	/* calculate total size and do sanity check */ -	tmp = read_spd(31); -	total_size = 1 << 22;	/* total_size = 4MB */ -	/* now multiply 4M by the smallest device row density */ -	/* note that we don't support asymetric rows */ -	while (((tmp & 0x0001) == 0) && (tmp != 0)) { -		total_size = total_size << 1; -		tmp = tmp >> 1; -	} -	total_size *= read_spd(5);	/* mult by module rows (dimm sides) */ - -	/*------------------------------------------------------------------ -	 * map	rows * cols * banks to a mode -	 * -------------------------------------------------------------------*/ - -	switch (row) { -	case 11: -		switch (col) { -		case 8: -			mode=4; /* mode 5 */ -			break; -		case 9: -		case 10: -			mode=0; /* mode 1 */ -			break; -		default: -			SPD_ERR("SDRAM - unsupported mode\n"); -		} -		break; -	case 12: -		switch (col) { -		case 8: -			mode=3; /* mode 4 */ -			break; -		case 9: -		case 10: -			mode=1; /* mode 2 */ -			break; -		default: -			SPD_ERR("SDRAM - unsupported mode\n"); -		} -		break; -	case 13: -		switch (col) { -		case 8: -			mode=5; /* mode 6 */ -			break; -		case 9: -		case 10: -			if (read_spd(17) == 2) -				mode = 6; /* mode 7 */ -			else -				mode = 2; /* mode 3 */ -			break; -		case 11: -			mode = 2; /* mode 3 */ -			break; -		default: -			SPD_ERR("SDRAM - unsupported mode\n"); -		} -		break; -	default: -		SPD_ERR("SDRAM - unsupported mode\n"); -	} - -	/*------------------------------------------------------------------ -	 * using the calculated values, compute the bank -	 * config register values. -	 * -------------------------------------------------------------------*/ -	sdram0_b1cr = 0; -	sdram0_b2cr = 0; -	sdram0_b3cr = 0; - -	/* compute the size of each bank */ -	bank_size = total_size / bank_cnt; -	/* convert bank size to bank size code for ppc4xx -	   by takeing log2(bank_size) - 22 */ -	tmp = bank_size;		/* start with tmp = bank_size */ -	bank_code = 0;			/* and bank_code = 0 */ -	while (tmp > 1) {		/* this takes log2 of tmp */ -		bank_code++;		/* and stores result in bank_code */ -		tmp = tmp >> 1; -	}				/* bank_code is now log2(bank_size) */ -	bank_code -= 22;		/* subtract 22 to get the code */ - -	tmp = SDRAM0_BXCR_SZ(bank_code) | SDRAM0_BXCR_AM(mode) | 1; -	sdram0_b0cr = (bank_size * 0) | tmp; -#ifndef CONFIG_405EP /* not on PPC405EP */ -	if (bank_cnt > 1) -		sdram0_b2cr = (bank_size * 1) | tmp; -	if (bank_cnt > 2) -		sdram0_b1cr = (bank_size * 2) | tmp; -	if (bank_cnt > 3) -		sdram0_b3cr = (bank_size * 3) | tmp; -#else -	/* PPC405EP chip only supports two SDRAM banks */ -	if (bank_cnt > 1) -		sdram0_b1cr = (bank_size * 1) | tmp; -	if (bank_cnt > 2) -		total_size = 2 * bank_size; -#endif - -	/* -	 *   enable sdram controller DCE=1 -	 *  enable burst read prefetch to 32 bytes BRPF=2 -	 *  leave other functions off -	 */ - -	/*------------------------------------------------------------------ -	 * now that we've done our calculations, we are ready to -	 * program all the registers. -	 * -------------------------------------------------------------------*/ - -#define mtsdram0(reg, data)  mtdcr(memcfga,reg);mtdcr(memcfgd,data) -	/* disable memcontroller so updates work */ -	mtsdram0( mem_mcopt1, 0 ); - -#ifndef CONFIG_405EP /* not on PPC405EP */ -	mtsdram0( mem_besra , sdram0_besr0 ); -	mtsdram0( mem_besrb , sdram0_besr1 ); -	mtsdram0( mem_ecccf , sdram0_ecccfg ); -	mtsdram0( mem_eccerr, sdram0_eccesr ); -#endif -	mtsdram0( mem_rtr   , sdram0_rtr ); -	mtsdram0( mem_pmit  , sdram0_pmit ); -	mtsdram0( mem_mb0cf , sdram0_b0cr ); -	mtsdram0( mem_mb1cf , sdram0_b1cr ); -#ifndef CONFIG_405EP /* not on PPC405EP */ -	mtsdram0( mem_mb2cf , sdram0_b2cr ); -	mtsdram0( mem_mb3cf , sdram0_b3cr ); -#endif -	mtsdram0( mem_sdtr1 , sdram0_tr ); - -	/* SDRAM have a power on delay,	 500 micro should do */ -	udelay(500); -	sdram0_cfg = SDRAM0_CFG_DCE | SDRAM0_CFG_BRPF(1) | SDRAM0_CFG_ECCDD | SDRAM0_CFG_EMDULR; -	if (ecc_on) -		sdram0_cfg |= SDRAM0_CFG_MEMCHK; -	mtsdram0(mem_mcopt1, sdram0_cfg); - -	return (total_size); -} - -int spd_read(uint addr) -{ -	uchar data[2]; - -	if (i2c_read(SPD_EEPROM_ADDRESS, addr, 1, data, 1) == 0) -		return (int)data[0]; -	else -		return 0; -} - -#else /* CONFIG_440 */ -  /*-----------------------------------------------------------------------------    |  Memory Controller Options 0    +-----------------------------------------------------------------------------*/ @@ -1825,7 +1423,4 @@ void program_ecc (unsigned long	 num_bytes)  			SDRAM_CFG0_MCHK_CHK);  	}  } - -#endif /* CONFIG_440 */ -  #endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/ppc4xx/44x_spd_ddr2.c b/cpu/ppc4xx/44x_spd_ddr2.c new file mode 100644 index 000000000..6cff3a2e1 --- /dev/null +++ b/cpu/ppc4xx/44x_spd_ddr2.c @@ -0,0 +1,2759 @@ +/* + * cpu/ppc4xx/44x_spd_ddr2.c + * This SPD SDRAM detection code supports AMCC PPC44x cpu's with a + * DDR2 controller (non Denali Core). Those are 440SP/SPe. + * + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * COPYRIGHT   AMCC   CORPORATION 2004 + * + * 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 + * + */ + +/* define DEBUG for debugging output (obviously ;-)) */ +#if 0 +#define DEBUG +#endif + +#include <common.h> +#include <ppc4xx.h> +#include <i2c.h> +#include <asm/io.h> +#include <asm/processor.h> +#include <asm/mmu.h> + +#if defined(CONFIG_SPD_EEPROM) &&				\ +	(defined(CONFIG_440SP) || defined(CONFIG_440SPE)) + +#ifndef	TRUE +#define TRUE            1 +#endif +#ifndef FALSE +#define FALSE           0 +#endif + +#define SDRAM_DDR1	1 +#define SDRAM_DDR2	2 +#define SDRAM_NONE	0 + +#define MAXDIMMS 	2 +#define MAXRANKS 	4 +#define MAXBXCF		4 +#define MAX_SPD_BYTES	256   /* Max number of bytes on the DIMM's SPD EEPROM */ + +#define ONE_BILLION	1000000000 + +#define MULDIV64(m1, m2, d)	(u32)(((u64)(m1) * (u64)(m2)) / (u64)(d)) + +#if defined(DEBUG) +static void ppc440sp_sdram_register_dump(void); +#endif + +/*-----------------------------------------------------------------------------+ + * Defines + *-----------------------------------------------------------------------------*/ +/* Defines for the Read Cycle Delay test */ +#define NUMMEMTESTS 8 +#define NUMMEMWORDS 8 + +/* Private Structure Definitions */ + +/* enum only to ease code for cas latency setting */ +typedef enum ddr_cas_id { +	DDR_CAS_2      = 20, +	DDR_CAS_2_5    = 25, +	DDR_CAS_3      = 30, +	DDR_CAS_4      = 40, +	DDR_CAS_5      = 50 +} ddr_cas_id_t; + +/*-----------------------------------------------------------------------------+ + * Prototypes + *-----------------------------------------------------------------------------*/ +static unsigned long sdram_memsize(void); +void program_tlb(u32 start, u32 size); +static void get_spd_info(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks); +static void check_mem_type(unsigned long *dimm_populated, +			   unsigned char *iic0_dimm_addr, +			   unsigned long num_dimm_banks); +static void check_frequency(unsigned long *dimm_populated, +			    unsigned char *iic0_dimm_addr, +			    unsigned long num_dimm_banks); +static void check_rank_number(unsigned long *dimm_populated, +			      unsigned char *iic0_dimm_addr, +			      unsigned long num_dimm_banks); +static void check_voltage_type(unsigned long *dimm_populated, +			       unsigned char *iic0_dimm_addr, +			       unsigned long num_dimm_banks); +static void program_memory_queue(unsigned long *dimm_populated, +				 unsigned char *iic0_dimm_addr, +				 unsigned long num_dimm_banks); +static void program_codt(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks); +static void program_mode(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks, +                         ddr_cas_id_t *selected_cas); +static void program_tr(unsigned long *dimm_populated, +		       unsigned char *iic0_dimm_addr, +		       unsigned long num_dimm_banks); +static void program_rtr(unsigned long *dimm_populated, +			unsigned char *iic0_dimm_addr, +			unsigned long num_dimm_banks); +static void program_bxcf(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks); +static void program_copt1(unsigned long *dimm_populated, +			  unsigned char *iic0_dimm_addr, +			  unsigned long num_dimm_banks); +static void program_initplr(unsigned long *dimm_populated, +			    unsigned char *iic0_dimm_addr, +			    unsigned long num_dimm_banks, +                            ddr_cas_id_t selected_cas); +static unsigned long is_ecc_enabled(void); +static void program_ecc(unsigned long *dimm_populated, +			unsigned char *iic0_dimm_addr, +			unsigned long num_dimm_banks); +static void program_ecc_addr(unsigned long start_address, +			     unsigned long num_bytes); + +#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ +static void          test(void); +#else +static void          DQS_calibration_process(void); +#endif +static void program_DQS_calibration(unsigned long *dimm_populated, +				    unsigned char *iic0_dimm_addr, +				    unsigned long num_dimm_banks); + +static u32 mfdcr_any(u32 dcr) +{ +	u32 val; + +	switch (dcr) { +	case SDRAM_R0BAS + 0: +		val = mfdcr(SDRAM_R0BAS + 0); +		break; +	case SDRAM_R0BAS + 1: +		val = mfdcr(SDRAM_R0BAS + 1); +		break; +	case SDRAM_R0BAS + 2: +		val = mfdcr(SDRAM_R0BAS + 2); +		break; +	case SDRAM_R0BAS + 3: +		val = mfdcr(SDRAM_R0BAS + 3); +		break; +	default: +		printf("DCR %d not defined in case statement!!!\n", dcr); +		val = 0; /* just to satisfy the compiler */ +	} + +	return val; +} + +static void mtdcr_any(u32 dcr, u32 val) +{ +	switch (dcr) { +	case SDRAM_R0BAS + 0: +		mtdcr(SDRAM_R0BAS + 0, val); +		break; +	case SDRAM_R0BAS + 1: +		mtdcr(SDRAM_R0BAS + 1, val); +		break; +	case SDRAM_R0BAS + 2: +		mtdcr(SDRAM_R0BAS + 2, val); +		break; +	case SDRAM_R0BAS + 3: +		mtdcr(SDRAM_R0BAS + 3, val); +		break; +	default: +		printf("DCR %d not defined in case statement!!!\n", dcr); +	} +} + +static void wait_ddr_idle(void) +{ +	u32 val; + +	do { +		mfsdram(SDRAM_MCSTAT, val); +	} while ((val & SDRAM_MCSTAT_IDLE_MASK) == SDRAM_MCSTAT_IDLE_NOT); +} + +static unsigned char spd_read(uchar chip, uint addr) +{ +	unsigned char data[2]; + +	if (i2c_probe(chip) == 0) +		if (i2c_read(chip, addr, 1, data, 1) == 0) +			return data[0]; + +	return 0; +} + +/*-----------------------------------------------------------------------------+ + * sdram_memsize + *-----------------------------------------------------------------------------*/ +static unsigned long sdram_memsize(void) +{ +	unsigned long mem_size; +	unsigned long mcopt2; +	unsigned long mcstat; +	unsigned long mb0cf; +	unsigned long sdsz; +	unsigned long i; + +	mem_size = 0; + +	mfsdram(SDRAM_MCOPT2, mcopt2); +	mfsdram(SDRAM_MCSTAT, mcstat); + +	/* DDR controller must be enabled and not in self-refresh. */ +	/* Otherwise memsize is zero. */ +	if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) +	    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) +	    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) +		== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { +		for (i = 0; i < 4; i++) { +			mfsdram(SDRAM_MB0CF + (i << 2), mb0cf); +			/* Banks enabled */ +			if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { +				sdsz = mfdcr_any(SDRAM_R0BAS + i) & SDRAM_RXBAS_SDSZ_MASK; + +				switch(sdsz) { +				case SDRAM_RXBAS_SDSZ_8: +					mem_size+=8; +					break; +				case SDRAM_RXBAS_SDSZ_16: +					mem_size+=16; +					break; +				case SDRAM_RXBAS_SDSZ_32: +					mem_size+=32; +					break; +				case SDRAM_RXBAS_SDSZ_64: +					mem_size+=64; +					break; +				case SDRAM_RXBAS_SDSZ_128: +					mem_size+=128; +					break; +				case SDRAM_RXBAS_SDSZ_256: +					mem_size+=256; +					break; +				case SDRAM_RXBAS_SDSZ_512: +					mem_size+=512; +					break; +				case SDRAM_RXBAS_SDSZ_1024: +					mem_size+=1024; +					break; +				case SDRAM_RXBAS_SDSZ_2048: +					mem_size+=2048; +					break; +				case SDRAM_RXBAS_SDSZ_4096: +					mem_size+=4096; +					break; +				default: +					mem_size=0; +					break; +				} +			} +		} +	} + +	mem_size *= 1024 * 1024; +	return(mem_size); +} + +/*-----------------------------------------------------------------------------+ + * initdram.  Initializes the 440SP Memory Queue and DDR SDRAM controller. + * Note: This routine runs from flash with a stack set up in the chip's + * sram space.  It is important that the routine does not require .sbss, .bss or + * .data sections.  It also cannot call routines that require these sections. + *-----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------- + * Function:     initdram + * Description:  Configures SDRAM memory banks for DDR operation. + *               Auto Memory Configuration option reads the DDR SDRAM EEPROMs + *               via the IIC bus and then configures the DDR SDRAM memory + *               banks appropriately. If Auto Memory Configuration is + *               not used, it is assumed that no DIMM is plugged + *-----------------------------------------------------------------------------*/ +long int initdram(int board_type) +{ +	unsigned char spd0[MAX_SPD_BYTES]; +	unsigned char spd1[MAX_SPD_BYTES]; +	unsigned char *dimm_spd[MAXDIMMS]; +	unsigned long dimm_populated[MAXDIMMS]; +	unsigned char iic0_dimm_addr[MAXDIMMS]; +	unsigned long num_dimm_banks;		    /* on board dimm banks */ +	unsigned long val; +	ddr_cas_id_t  selected_cas; +	unsigned long dram_size = 0; + +	num_dimm_banks = sizeof(iic0_dimm_addr); + +	/*------------------------------------------------------------------ +	 * Set up an array of SPD matrixes. +	 *-----------------------------------------------------------------*/ +	dimm_spd[0] = spd0; +	dimm_spd[1] = spd1; + +	/*------------------------------------------------------------------ +	 * Set up an array of iic0 dimm addresses. +	 *-----------------------------------------------------------------*/ +	iic0_dimm_addr[0] = IIC0_DIMM0_ADDR; +	iic0_dimm_addr[1] = IIC0_DIMM1_ADDR; + +	/*------------------------------------------------------------------ +	 * Reset the DDR-SDRAM controller. +	 *-----------------------------------------------------------------*/ +	mtsdr(SDR0_SRST, 0x00200000); +	mtsdr(SDR0_SRST, 0x00000000); + +	/* +	 * Make sure I2C controller is initialized +	 * before continuing. +	 */ + +	/* switch to correct I2C bus */ +	I2C_SET_BUS(CFG_SPD_BUS_NUM); +	i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); + +	/*------------------------------------------------------------------ +	 * Clear out the serial presence detect buffers. +	 * Perform IIC reads from the dimm.  Fill in the spds. +	 * Check to see if the dimm slots are populated +	 *-----------------------------------------------------------------*/ +	get_spd_info(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Check the memory type for the dimms plugged. +	 *-----------------------------------------------------------------*/ +	check_mem_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Check the frequency supported for the dimms plugged. +	 *-----------------------------------------------------------------*/ +	check_frequency(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Check the total rank number. +	 *-----------------------------------------------------------------*/ +	check_rank_number(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Check the voltage type for the dimms plugged. +	 *-----------------------------------------------------------------*/ +	check_voltage_type(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Program SDRAM controller options 2 register +	 * Except Enabling of the memory controller. +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT2, val); +	mtsdram(SDRAM_MCOPT2, +		(val & +		 ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_PMEN_MASK | +		   SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_XSRP_MASK | +		   SDRAM_MCOPT2_ISIE_MASK)) +		| (SDRAM_MCOPT2_SREN_ENTER | SDRAM_MCOPT2_PMEN_DISABLE | +		   SDRAM_MCOPT2_IPTR_IDLE | SDRAM_MCOPT2_XSRP_ALLOW | +		   SDRAM_MCOPT2_ISIE_ENABLE)); + +	/*------------------------------------------------------------------ +	 * Program SDRAM controller options 1 register +	 * Note: Does not enable the memory controller. +	 *-----------------------------------------------------------------*/ +	program_copt1(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Controller On Die Termination Register +	 *-----------------------------------------------------------------*/ +	program_codt(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Program SDRAM refresh register. +	 *-----------------------------------------------------------------*/ +	program_rtr(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Program SDRAM mode register. +	 *-----------------------------------------------------------------*/ +	program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks, &selected_cas); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Write Data/DM/DQS Clock Timing Reg +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_WRDTR, val); +	mtsdram(SDRAM_WRDTR, (val & ~(SDRAM_WRDTR_LLWP_MASK | SDRAM_WRDTR_WTR_MASK)) | +		(SDRAM_WRDTR_LLWP_1_CYC | SDRAM_WRDTR_WTR_90_DEG_ADV)); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Clock Timing Register +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_CLKTR, val); +	mtsdram(SDRAM_CLKTR, (val & ~SDRAM_CLKTR_CLKP_MASK) | SDRAM_CLKTR_CLKP_0_DEG); + +	/*------------------------------------------------------------------ +	 * Program the BxCF registers. +	 *-----------------------------------------------------------------*/ +	program_bxcf(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Program SDRAM timing registers. +	 *-----------------------------------------------------------------*/ +	program_tr(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Set the Extended Mode register +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MEMODE, val); +	mtsdram(SDRAM_MEMODE, +		(val & ~(SDRAM_MEMODE_DIC_MASK  | SDRAM_MEMODE_DLL_MASK | +			 SDRAM_MEMODE_RTT_MASK | SDRAM_MEMODE_DQS_MASK)) | +		(SDRAM_MEMODE_DIC_NORMAL | SDRAM_MEMODE_DLL_ENABLE +		 | SDRAM_MEMODE_RTT_75OHM | SDRAM_MEMODE_DQS_ENABLE)); + +	/*------------------------------------------------------------------ +	 * Program Initialization preload registers. +	 *-----------------------------------------------------------------*/ +	program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks, +			selected_cas); + +	/*------------------------------------------------------------------ +	 * Delay to ensure 200usec have elapsed since reset. +	 *-----------------------------------------------------------------*/ +	udelay(400); + +	/*------------------------------------------------------------------ +	 * Set the memory queue core base addr. +	 *-----------------------------------------------------------------*/ +	program_memory_queue(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +	/*------------------------------------------------------------------ +	 * Program SDRAM controller options 2 register +	 * Enable the memory controller. +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT2, val); +	mtsdram(SDRAM_MCOPT2, +		(val & ~(SDRAM_MCOPT2_SREN_MASK | SDRAM_MCOPT2_DCEN_MASK | +			 SDRAM_MCOPT2_IPTR_MASK | SDRAM_MCOPT2_ISIE_MASK)) | +		(SDRAM_MCOPT2_DCEN_ENABLE | SDRAM_MCOPT2_IPTR_EXECUTE)); + +	/*------------------------------------------------------------------ +	 * Wait for SDRAM_CFG0_DC_EN to complete. +	 *-----------------------------------------------------------------*/ +	do { +		mfsdram(SDRAM_MCSTAT, val); +	} while ((val & SDRAM_MCSTAT_MIC_MASK) == SDRAM_MCSTAT_MIC_NOTCOMP); + +	/* get installed memory size */ +	dram_size = sdram_memsize(); + +	/* and program tlb entries for this size (dynamic) */ +	program_tlb(0, dram_size); + +#if 1 /* TODO: ECC support will come later */ +	/*------------------------------------------------------------------ +	 * If ecc is enabled, initialize the parity bits. +	 *-----------------------------------------------------------------*/ +	program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks); +#endif + +	/*------------------------------------------------------------------ +	 * DQS calibration. +	 *-----------------------------------------------------------------*/ +	program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks); + +#ifdef DEBUG +	ppc440sp_sdram_register_dump(); +#endif + +	return dram_size; +} + +static void get_spd_info(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long dimm_found; +	unsigned char num_of_bytes; +	unsigned char total_size; + +	dimm_found = FALSE; +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		num_of_bytes = 0; +		total_size = 0; + +		num_of_bytes = spd_read(iic0_dimm_addr[dimm_num], 0); +		debug("\nspd_read(0x%x) returned %d\n", +		      iic0_dimm_addr[dimm_num], num_of_bytes); +		total_size = spd_read(iic0_dimm_addr[dimm_num], 1); +		debug("spd_read(0x%x) returned %d\n", +		      iic0_dimm_addr[dimm_num], total_size); + +		if ((num_of_bytes != 0) && (total_size != 0)) { +			dimm_populated[dimm_num] = TRUE; +			dimm_found = TRUE; +			debug("DIMM slot %lu: populated\n", dimm_num); +		} else { +			dimm_populated[dimm_num] = FALSE; +			debug("DIMM slot %lu: Not populated\n", dimm_num); +		} +	} + +	if (dimm_found == FALSE) { +		printf("ERROR - No memory installed. Install a DDR-SDRAM DIMM.\n\n"); +		hang(); +	} +} + +#ifdef CONFIG_ADD_RAM_INFO +void board_add_ram_info(int use_default) +{ +        if (is_ecc_enabled()) +                puts(" (ECC enabled)"); +        else +                puts(" (ECC not enabled)"); +} +#endif + +/*------------------------------------------------------------------ + * For the memory DIMMs installed, this routine verifies that they + * really are DDR specific DIMMs. + *-----------------------------------------------------------------*/ +static void check_mem_type(unsigned long *dimm_populated, +			   unsigned char *iic0_dimm_addr, +			   unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long dimm_type; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] == TRUE) { +			dimm_type = spd_read(iic0_dimm_addr[dimm_num], 2); +			switch (dimm_type) { +			case 1: +				printf("ERROR: Standard Fast Page Mode DRAM DIMM detected in " +				       "slot %d.\n", (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 2: +				printf("ERROR: EDO DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 3: +				printf("ERROR: Pipelined Nibble DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 4: +				printf("ERROR: SDRAM DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 5: +				printf("ERROR: Multiplexed ROM DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 6: +				printf("ERROR: SGRAM DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			case 7: +				debug("DIMM slot %d: DDR1 SDRAM detected\n", dimm_num); +				dimm_populated[dimm_num] = SDRAM_DDR1; +				break; +			case 8: +				debug("DIMM slot %d: DDR2 SDRAM detected\n", dimm_num); +				dimm_populated[dimm_num] = SDRAM_DDR2; +				break; +			default: +				printf("ERROR: Unknown DIMM detected in slot %d.\n", +				       (unsigned int)dimm_num); +				printf("Only DDR1 and DDR2 SDRAM DIMMs are supported.\n"); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			} +		} +	} +	for (dimm_num = 1; dimm_num < num_dimm_banks; dimm_num++) { +		if ((dimm_populated[dimm_num-1] != SDRAM_NONE) +		    && (dimm_populated[dimm_num]   != SDRAM_NONE) +		    && (dimm_populated[dimm_num-1] != dimm_populated[dimm_num])) { +			printf("ERROR: DIMM's DDR1 and DDR2 type can not be mixed.\n"); +			hang(); +		} +	} +} + +/*------------------------------------------------------------------ + * For the memory DIMMs installed, this routine verifies that + * frequency previously calculated is supported. + *-----------------------------------------------------------------*/ +static void check_frequency(unsigned long *dimm_populated, +			    unsigned char *iic0_dimm_addr, +			    unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long tcyc_reg; +	unsigned long cycle_time; +	unsigned long calc_cycle_time; +	unsigned long sdram_freq; +	unsigned long sdr_ddrpll; +	PPC440_SYS_INFO board_cfg; + +	/*------------------------------------------------------------------ +	 * Get the board configuration info. +	 *-----------------------------------------------------------------*/ +	get_sys_info(&board_cfg); + +	mfsdr(sdr_ddr0, sdr_ddrpll); +	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); + +	/* +	 * calc_cycle_time is calculated from DDR frequency set by board/chip +	 * and is expressed in multiple of 10 picoseconds +	 * to match the way DIMM cycle time is calculated below. +	 */ +	calc_cycle_time = MULDIV64(ONE_BILLION, 100, sdram_freq); + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); +			/* +			 * Byte 9, Cycle time for CAS Latency=X, is split into two nibbles: +			 * the higher order nibble (bits 4-7) designates the cycle time +			 * to a granularity of 1ns; +			 * the value presented by the lower order nibble (bits 0-3) +			 * has a granularity of .1ns and is added to the value designated +			 * by the higher nibble. In addition, four lines of the lower order +			 * nibble are assigned to support +.25,+.33, +.66 and +.75. +			 */ +			 /* Convert from hex to decimal */ +			if ((tcyc_reg & 0x0F) == 0x0D) +				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 75; +			else if ((tcyc_reg & 0x0F) == 0x0C) +				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 66; +			else if ((tcyc_reg & 0x0F) == 0x0B) +				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 33; +			else if ((tcyc_reg & 0x0F) == 0x0A) +				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + 25; +			else +				cycle_time = (((tcyc_reg & 0xF0) >> 4) * 100) + +					((tcyc_reg & 0x0F)*10); + +			if  (cycle_time > (calc_cycle_time + 10)) { +				/* +				 * the provided sdram cycle_time is too small +				 * for the available DIMM cycle_time. +				 * The additionnal 100ps is here to accept a small incertainty. +				 */ +				printf("ERROR: DRAM DIMM detected with cycle_time %d ps in " +				       "slot %d \n while calculated cycle time is %d ps.\n", +				       (unsigned int)(cycle_time*10), +				       (unsigned int)dimm_num, +				       (unsigned int)(calc_cycle_time*10)); +				printf("Replace the DIMM, or change DDR frequency via " +				       "strapping bits.\n\n"); +				hang(); +			} +		} +	} +} + +/*------------------------------------------------------------------ + * For the memory DIMMs installed, this routine verifies two + * ranks/banks maximum are availables. + *-----------------------------------------------------------------*/ +static void check_rank_number(unsigned long *dimm_populated, +			      unsigned char *iic0_dimm_addr, +			      unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long dimm_rank; +	unsigned long total_rank = 0; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			dimm_rank = spd_read(iic0_dimm_addr[dimm_num], 5); +			if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) +				dimm_rank = (dimm_rank & 0x0F) +1; +			else +				dimm_rank = dimm_rank & 0x0F; + + +			if (dimm_rank > MAXRANKS) { +				printf("ERROR: DRAM DIMM detected with %d ranks in " +				       "slot %d is not supported.\n", dimm_rank, dimm_num); +				printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +			} else +				total_rank += dimm_rank; +		} +		if (total_rank > MAXRANKS) { +			printf("ERROR: DRAM DIMM detected with a total of %d ranks " +			       "for all slots.\n", (unsigned int)total_rank); +			printf("Only %d ranks are supported for all DIMM.\n", MAXRANKS); +			printf("Remove one of the DIMM modules.\n\n"); +			hang(); +		} +	} +} + +/*------------------------------------------------------------------ + * only support 2.5V modules. + * This routine verifies this. + *-----------------------------------------------------------------*/ +static void check_voltage_type(unsigned long *dimm_populated, +			       unsigned char *iic0_dimm_addr, +			       unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long voltage_type; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			voltage_type = spd_read(iic0_dimm_addr[dimm_num], 8); +			switch (voltage_type) { +			case 0x00: +				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); +				printf("This DIMM is 5.0 Volt/TTL.\n"); +				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", +				       (unsigned int)dimm_num); +				hang(); +				break; +			case 0x01: +				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); +				printf("This DIMM is LVTTL.\n"); +				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", +				       (unsigned int)dimm_num); +				hang(); +				break; +			case 0x02: +				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); +				printf("This DIMM is 1.5 Volt.\n"); +				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", +				       (unsigned int)dimm_num); +				hang(); +				break; +			case 0x03: +				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); +				printf("This DIMM is 3.3 Volt/TTL.\n"); +				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", +				       (unsigned int)dimm_num); +				hang(); +				break; +			case 0x04: +				/* 2.5 Voltage only for DDR1 */ +				break; +			case 0x05: +				/* 1.8 Voltage only for DDR2 */ +				break; +			default: +				printf("ERROR: Only DIMMs DDR 2.5V or DDR2 1.8V are supported.\n"); +				printf("Replace the DIMM module in slot %d with a supported DIMM.\n\n", +				       (unsigned int)dimm_num); +				hang(); +				break; +			} +		} +	} +} + +/*-----------------------------------------------------------------------------+ + * program_copt1. + *-----------------------------------------------------------------------------*/ +static void program_copt1(unsigned long *dimm_populated, +			  unsigned char *iic0_dimm_addr, +			  unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long mcopt1; +	unsigned long ecc_enabled; +	unsigned long ecc = 0; +	unsigned long data_width = 0; +	unsigned long dimm_32bit; +	unsigned long dimm_64bit; +	unsigned long registered = 0; +	unsigned long attribute = 0; +	unsigned long buf0, buf1; /* TODO: code to be changed for IOP1.6 to support 4 DIMMs */ +	unsigned long bankcount; +	unsigned long ddrtype; +	unsigned long val; + +	ecc_enabled = TRUE; +	dimm_32bit = FALSE; +	dimm_64bit = FALSE; +	buf0 = FALSE; +	buf1 = FALSE; + +	/*------------------------------------------------------------------ +	 * Set memory controller options reg 1, SDRAM_MCOPT1. +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT1, val); +	mcopt1 = val & ~(SDRAM_MCOPT1_MCHK_MASK | SDRAM_MCOPT1_RDEN_MASK | +			 SDRAM_MCOPT1_PMU_MASK  | SDRAM_MCOPT1_DMWD_MASK | +			 SDRAM_MCOPT1_UIOS_MASK | SDRAM_MCOPT1_BCNT_MASK | +			 SDRAM_MCOPT1_DDR_TYPE_MASK | SDRAM_MCOPT1_RWOO_MASK | +			 SDRAM_MCOPT1_WOOO_MASK | SDRAM_MCOPT1_DCOO_MASK | +			 SDRAM_MCOPT1_DREF_MASK); + +	mcopt1 |= SDRAM_MCOPT1_QDEP; +	mcopt1 |= SDRAM_MCOPT1_PMU_OPEN; +	mcopt1 |= SDRAM_MCOPT1_RWOO_DISABLED; +	mcopt1 |= SDRAM_MCOPT1_WOOO_DISABLED; +	mcopt1 |= SDRAM_MCOPT1_DCOO_DISABLED; +	mcopt1 |= SDRAM_MCOPT1_DREF_NORMAL; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			/* test ecc support */ +			ecc = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 11); +			if (ecc != 0x02) /* ecc not supported */ +				ecc_enabled = FALSE; + +			/* test bank count */ +			bankcount = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 17); +			if (bankcount == 0x04) /* bank count = 4 */ +				mcopt1 |= SDRAM_MCOPT1_4_BANKS; +			else /* bank count = 8 */ +				mcopt1 |= SDRAM_MCOPT1_8_BANKS; + +			/* test DDR type */ +			ddrtype = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2); +			/* test for buffered/unbuffered, registered, differential clocks */ +			registered = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 20); +			attribute = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 21); + +			/* TODO: code to be changed for IOP1.6 to support 4 DIMMs */ +			if (dimm_num == 0) { +				if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */ +					mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE; +				if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */ +					mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE; +				if (registered == 1) { /* DDR2 always buffered */ +					/* TODO: what about above  comments ? */ +					mcopt1 |= SDRAM_MCOPT1_RDEN; +					buf0 = TRUE; +				} else { +					/* TODO: the mask 0x02 doesn't match Samsung def for byte 21. */ +					if ((attribute & 0x02) == 0x00) { +						/* buffered not supported */ +						buf0 = FALSE; +					} else { +						mcopt1 |= SDRAM_MCOPT1_RDEN; +						buf0 = TRUE; +					} +				} +			} +			else if (dimm_num == 1) { +				if (dimm_populated[dimm_num] == SDRAM_DDR1) /* DDR1 type */ +					mcopt1 |= SDRAM_MCOPT1_DDR1_TYPE; +				if (dimm_populated[dimm_num] == SDRAM_DDR2) /* DDR2 type */ +					mcopt1 |= SDRAM_MCOPT1_DDR2_TYPE; +				if (registered == 1) { +					/* DDR2 always buffered */ +					mcopt1 |= SDRAM_MCOPT1_RDEN; +					buf1 = TRUE; +				} else { +					if ((attribute & 0x02) == 0x00) { +						/* buffered not supported */ +						buf1 = FALSE; +					} else { +						mcopt1 |= SDRAM_MCOPT1_RDEN; +						buf1 = TRUE; +					} +				} +			} + +			/* Note that for DDR2 the byte 7 is reserved, but OK to keep code as is. */ +			data_width = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 6) + +				(((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 7)) << 8); + +			switch (data_width) { +			case 72: +			case 64: +				dimm_64bit = TRUE; +				break; +			case 40: +			case 32: +				dimm_32bit = TRUE; +				break; +			default: +				printf("WARNING: Detected a DIMM with a data width of %d bits.\n", +				       data_width); +				printf("Only DIMMs with 32 or 64 bit DDR-SDRAM widths are supported.\n"); +				break; +			} +		} +	} + +	/* verify matching properties */ +	if ((dimm_populated[0] != SDRAM_NONE) && (dimm_populated[1] != SDRAM_NONE)) { +		if (buf0 != buf1) { +			printf("ERROR: DIMM's buffered/unbuffered, registered, clocking don't match.\n"); +			hang(); +		} +	} + +	if ((dimm_64bit == TRUE) && (dimm_32bit == TRUE)) { +		printf("ERROR: Cannot mix 32 bit and 64 bit DDR-SDRAM DIMMs together.\n"); +		hang(); +	} +	else if ((dimm_64bit == TRUE) && (dimm_32bit == FALSE)) { +		mcopt1 |= SDRAM_MCOPT1_DMWD_64; +	} else if ((dimm_64bit == FALSE) && (dimm_32bit == TRUE)) { +		mcopt1 |= SDRAM_MCOPT1_DMWD_32; +	} else { +		printf("ERROR: Please install only 32 or 64 bit DDR-SDRAM DIMMs.\n\n"); +		hang(); +	} + +	if (ecc_enabled == TRUE) +		mcopt1 |= SDRAM_MCOPT1_MCHK_GEN; +	else +		mcopt1 |= SDRAM_MCOPT1_MCHK_NON; + +	mtsdram(SDRAM_MCOPT1, mcopt1); +} + +/*-----------------------------------------------------------------------------+ + * program_codt. + *-----------------------------------------------------------------------------*/ +static void program_codt(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks) +{ +	unsigned long codt; +	unsigned long modt0 = 0; +	unsigned long modt1 = 0; +	unsigned long modt2 = 0; +	unsigned long modt3 = 0; +	unsigned char dimm_num; +	unsigned char dimm_rank; +	unsigned char total_rank = 0; +	unsigned char total_dimm = 0; +	unsigned char dimm_type = 0; +	unsigned char firstSlot = 0; + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Controller On Die Termination Register +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_CODT, codt); +	codt |= (SDRAM_CODT_IO_NMODE +		 & (~SDRAM_CODT_DQS_SINGLE_END +		    & ~SDRAM_CODT_CKSE_SINGLE_END +		    & ~SDRAM_CODT_FEEBBACK_RCV_SINGLE_END +		    & ~SDRAM_CODT_FEEBBACK_DRV_SINGLE_END)); + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			dimm_rank = (unsigned long)spd_read(iic0_dimm_addr[dimm_num], 5); +			if (((unsigned long)spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) { +				dimm_rank = (dimm_rank & 0x0F) + 1; +				dimm_type = SDRAM_DDR2; +			} else { +				dimm_rank = dimm_rank & 0x0F; +				dimm_type = SDRAM_DDR1; +			} + +			total_rank +=  dimm_rank; +			total_dimm ++; +			if ((dimm_num == 0) && (total_dimm == 1)) +				firstSlot = TRUE; +			else +				firstSlot = FALSE; +		} +	} +	if (dimm_type == SDRAM_DDR2) { +		codt |= SDRAM_CODT_DQS_1_8_V_DDR2; +		if ((total_dimm == 1) && (firstSlot == TRUE)) { +			if (total_rank == 1) { +				codt |= 0x00800000; +				modt0 = 0x01000000; +				modt1 = 0x00000000; +				modt2 = 0x00000000; +				modt3 = 0x00000000; +			} +			if (total_rank == 2) { +				codt |= 0x02800000; +				modt0 = 0x06000000; +				modt1 = 0x01800000; +				modt2 = 0x00000000; +				modt3 = 0x00000000; +			} +		} else { +			if (total_rank == 1) { +				codt |= 0x00800000; +				modt0 = 0x01000000; +				modt1 = 0x00000000; +				modt2 = 0x00000000; +				modt3 = 0x00000000; +			} +			if (total_rank == 2) { +				codt |= 0x02800000; +				modt0 = 0x06000000; +				modt1 = 0x01800000; +				modt2 = 0x00000000; +				modt3 = 0x00000000; +			} +		} +		if (total_dimm == 2) { +			if (total_rank == 2) { +				codt |= 0x08800000; +				modt0 = 0x18000000; +				modt1 = 0x00000000; +				modt2 = 0x01800000; +				modt3 = 0x00000000; +			} +			if (total_rank == 4) { +				codt |= 0x2a800000; +				modt0 = 0x18000000; +				modt1 = 0x18000000; +				modt2 = 0x01800000; +				modt3 = 0x01800000; +			} +		} +  	} else { +		codt |= SDRAM_CODT_DQS_2_5_V_DDR1; +		modt0 = 0x00000000; +		modt1 = 0x00000000; +		modt2 = 0x00000000; +		modt3 = 0x00000000; + +		if (total_dimm == 1) { +			if (total_rank == 1) +				codt |= 0x00800000; +			if (total_rank == 2) +				codt |= 0x02800000; +		} +		if (total_dimm == 2) { +			if (total_rank == 2) +				codt |= 0x08800000; +			if (total_rank == 4) +				codt |= 0x2a800000; +		} +	} + +	debug("nb of dimm %d\n", total_dimm); +	debug("nb of rank %d\n", total_rank); +	if (total_dimm == 1) +		debug("dimm in slot %d\n", firstSlot); + +	mtsdram(SDRAM_CODT, codt); +	mtsdram(SDRAM_MODT0, modt0); +	mtsdram(SDRAM_MODT1, modt1); +	mtsdram(SDRAM_MODT2, modt2); +	mtsdram(SDRAM_MODT3, modt3); +} + +/*-----------------------------------------------------------------------------+ + * program_initplr. + *-----------------------------------------------------------------------------*/ +static void program_initplr(unsigned long *dimm_populated, +			    unsigned char *iic0_dimm_addr, +			    unsigned long num_dimm_banks, +                            ddr_cas_id_t selected_cas) +{ +	unsigned long MR_CAS_value = 0; + +	/****************************************************** +	 ** Assumption: if more than one DIMM, all DIMMs are the same +	 **             as already checked in check_memory_type +	 ******************************************************/ + +	if ((dimm_populated[0] == SDRAM_DDR1) || (dimm_populated[1] == SDRAM_DDR1)) { +		mtsdram(SDRAM_INITPLR0, 0x81B80000); +		mtsdram(SDRAM_INITPLR1, 0x81900400); +		mtsdram(SDRAM_INITPLR2, 0x81810000); +		mtsdram(SDRAM_INITPLR3, 0xff800162); +		mtsdram(SDRAM_INITPLR4, 0x81900400); +		mtsdram(SDRAM_INITPLR5, 0x86080000); +		mtsdram(SDRAM_INITPLR6, 0x86080000); +		mtsdram(SDRAM_INITPLR7, 0x81000062); +	} else if ((dimm_populated[0] == SDRAM_DDR2) || (dimm_populated[1] == SDRAM_DDR2)) { +		switch (selected_cas) { +			/* +			 * The CAS latency is a field of the Mode Reg +			 * that need to be set from caller input. +			 * CAS bits in Mode Reg are starting at bit 4 at least for the Micron DDR2 +			 * this is the reason of the shift. +			 */ +		case DDR_CAS_3: +			MR_CAS_value = 3 << 4; +			break; +		case DDR_CAS_4: +			MR_CAS_value = 4 << 4; +			break; +		case DDR_CAS_5: +			MR_CAS_value = 5 << 4; +			break; +		default: +			printf("ERROR: ucode error on selected_cas value %d", (unsigned char)selected_cas); +			hang(); +			break; +		} + +		mtsdram(SDRAM_INITPLR0,  0xB5380000);			/* NOP */ +		mtsdram(SDRAM_INITPLR1,  0x82100400);			/* precharge 8 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR2,  0x80820000);			/* EMR2 */ +		mtsdram(SDRAM_INITPLR3,  0x80830000);			/* EMR3 */ +		mtsdram(SDRAM_INITPLR4,  0x80810000);			/* EMR DLL ENABLE */ +		mtsdram(SDRAM_INITPLR5,  0x80800502 | MR_CAS_value);	/* MR w/ DLL reset */ +		mtsdram(SDRAM_INITPLR6,  0x82100400);			/* precharge 8 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR7,  0x8a080000);			/* Refresh  50 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR8,  0x8a080000);			/* Refresh  50 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR9,  0x8a080000);			/* Refresh  50 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR10, 0x8a080000);			/* Refresh  50 DDR clock cycle */ +		mtsdram(SDRAM_INITPLR11, 0x80800402 | MR_CAS_value);	/* MR w/o DLL reset */ +		mtsdram(SDRAM_INITPLR12, 0x80810380);			/* EMR OCD Default */ +		mtsdram(SDRAM_INITPLR13, 0x80810000);			/* EMR OCD Exit */ +	} else { +		printf("ERROR: ucode error as unknown DDR type in program_initplr"); +		hang(); +	} +} + +/*------------------------------------------------------------------ + * This routine programs the SDRAM_MMODE register. + * the selected_cas is an output parameter, that will be passed + * by caller to call the above program_initplr( ) + *-----------------------------------------------------------------*/ +static void program_mode(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks, +			 ddr_cas_id_t *selected_cas) +{ +	unsigned long dimm_num; +	unsigned long sdram_ddr1; +	unsigned long t_wr_ns; +	unsigned long t_wr_clk; +	unsigned long cas_bit; +	unsigned long cas_index; +	unsigned long sdram_freq; +	unsigned long ddr_check; +	unsigned long mmode; +	unsigned long tcyc_reg; +	unsigned long cycle_2_0_clk; +	unsigned long cycle_2_5_clk; +	unsigned long cycle_3_0_clk; +	unsigned long cycle_4_0_clk; +	unsigned long cycle_5_0_clk; +	unsigned long max_2_0_tcyc_ns_x_100; +	unsigned long max_2_5_tcyc_ns_x_100; +	unsigned long max_3_0_tcyc_ns_x_100; +	unsigned long max_4_0_tcyc_ns_x_100; +	unsigned long max_5_0_tcyc_ns_x_100; +	unsigned long cycle_time_ns_x_100[3]; +	PPC440_SYS_INFO board_cfg; +	unsigned char cas_2_0_available; +	unsigned char cas_2_5_available; +	unsigned char cas_3_0_available; +	unsigned char cas_4_0_available; +	unsigned char cas_5_0_available; +	unsigned long sdr_ddrpll; + +	/*------------------------------------------------------------------ +	 * Get the board configuration info. +	 *-----------------------------------------------------------------*/ +	get_sys_info(&board_cfg); + +	mfsdr(sdr_ddr0, sdr_ddrpll); +	sdram_freq = MULDIV64((board_cfg.freqPLB), SDR0_DDR0_DDRM_DECODE(sdr_ddrpll), 1); + +	/*------------------------------------------------------------------ +	 * Handle the timing.  We need to find the worst case timing of all +	 * the dimm modules installed. +	 *-----------------------------------------------------------------*/ +	t_wr_ns = 0; +	cas_2_0_available = TRUE; +	cas_2_5_available = TRUE; +	cas_3_0_available = TRUE; +	cas_4_0_available = TRUE; +	cas_5_0_available = TRUE; +	max_2_0_tcyc_ns_x_100 = 10; +	max_2_5_tcyc_ns_x_100 = 10; +	max_3_0_tcyc_ns_x_100 = 10; +	max_4_0_tcyc_ns_x_100 = 10; +	max_5_0_tcyc_ns_x_100 = 10; +	sdram_ddr1 = TRUE; + +	/* loop through all the DIMM slots on the board */ +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		/* If a dimm is installed in a particular slot ... */ +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			if (dimm_populated[dimm_num] == SDRAM_DDR1) +				sdram_ddr1 = TRUE; +			else +				sdram_ddr1 = FALSE; + +			/* t_wr_ns = max(t_wr_ns, (unsigned long)dimm_spd[dimm_num][36] >> 2); */ /*  not used in this loop. */ +			cas_bit = spd_read(iic0_dimm_addr[dimm_num], 18); + +			/* For a particular DIMM, grab the three CAS values it supports */ +			for (cas_index = 0; cas_index < 3; cas_index++) { +				switch (cas_index) { +				case 0: +					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 9); +					break; +				case 1: +					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 23); +					break; +				default: +					tcyc_reg = spd_read(iic0_dimm_addr[dimm_num], 25); +					break; +				} + +				if ((tcyc_reg & 0x0F) >= 10) { +					if ((tcyc_reg & 0x0F) == 0x0D) { +						/* Convert from hex to decimal */ +						cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + 75; +					} else { +						printf("ERROR: SPD reported Tcyc is incorrect for DIMM " +						       "in slot %d\n", (unsigned int)dimm_num); +						hang(); +					} +				} else { +					/* Convert from hex to decimal */ +					cycle_time_ns_x_100[cas_index] = (((tcyc_reg & 0xF0) >> 4) * 100) + +						((tcyc_reg & 0x0F)*10); +				} +			} + +			/* The rest of this routine determines if CAS 2.0, 2.5, 3.0, 4.0 and 5.0 are */ +			/* supported for a particular DIMM. */ +			cas_index = 0; + +			if (sdram_ddr1) { +				/* +				 * DDR devices use the following bitmask for CAS latency: +				 *  Bit   7    6    5    4    3    2    1    0 +				 *       TBD  4.0  3.5  3.0  2.5  2.0  1.5  1.0 +				 */ +				if (((cas_bit & 0x40) == 0x40) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_4_0_available = FALSE; +				} + +				if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_3_0_available = FALSE; +				} + +				if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_2_5_tcyc_ns_x_100 = max(max_2_5_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_2_5_available = FALSE; +				} + +				if (((cas_bit & 0x04) == 0x04) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_2_0_tcyc_ns_x_100 = max(max_2_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_2_0_available = FALSE; +				} +			} else { +				/* +				 * DDR2 devices use the following bitmask for CAS latency: +				 *  Bit   7    6    5    4    3    2    1    0 +				 *       TBD  6.0  5.0  4.0  3.0  2.0  TBD  TBD +				 */ +				if (((cas_bit & 0x20) == 0x20) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_5_0_tcyc_ns_x_100 = max(max_5_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_5_0_available = FALSE; +				} + +				if (((cas_bit & 0x10) == 0x10) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_4_0_tcyc_ns_x_100 = max(max_4_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_4_0_available = FALSE; +				} + +				if (((cas_bit & 0x08) == 0x08) && (cas_index < 3) && (cycle_time_ns_x_100[cas_index] != 0)) { +					max_3_0_tcyc_ns_x_100 = max(max_3_0_tcyc_ns_x_100, cycle_time_ns_x_100[cas_index]); +					cas_index++; +				} else { +					if (cas_index != 0) +						cas_index++; +					cas_3_0_available = FALSE; +				} +			} +		} +	} + +	/*------------------------------------------------------------------ +	 * Set the SDRAM mode, SDRAM_MMODE +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MMODE, mmode); +	mmode = mmode & ~(SDRAM_MMODE_WR_MASK | SDRAM_MMODE_DCL_MASK); + +	cycle_2_0_clk = MULDIV64(ONE_BILLION, 100, max_2_0_tcyc_ns_x_100); +	cycle_2_5_clk = MULDIV64(ONE_BILLION, 100, max_2_5_tcyc_ns_x_100); +	cycle_3_0_clk = MULDIV64(ONE_BILLION, 100, max_3_0_tcyc_ns_x_100); +	cycle_4_0_clk = MULDIV64(ONE_BILLION, 100, max_4_0_tcyc_ns_x_100); +	cycle_5_0_clk = MULDIV64(ONE_BILLION, 100, max_5_0_tcyc_ns_x_100); + +	if (sdram_ddr1 == TRUE) { /* DDR1 */ +		if ((cas_2_0_available == TRUE) && (sdram_freq <= cycle_2_0_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR1_2_0_CLK; +			*selected_cas = DDR_CAS_2; +		} else if ((cas_2_5_available == TRUE) && (sdram_freq <= cycle_2_5_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR1_2_5_CLK; +			*selected_cas = DDR_CAS_2_5; +		} else if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR1_3_0_CLK; +			*selected_cas = DDR_CAS_3; +		} else { +			printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); +			printf("Only DIMMs DDR1 with CAS latencies of 2.0, 2.5, and 3.0 are supported.\n"); +			printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); +			hang(); +		} +	} else { /* DDR2 */ +		if ((cas_3_0_available == TRUE) && (sdram_freq <= cycle_3_0_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR2_3_0_CLK; +			*selected_cas = DDR_CAS_3; +		} else if ((cas_4_0_available == TRUE) && (sdram_freq <= cycle_4_0_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR2_4_0_CLK; +			*selected_cas = DDR_CAS_4; +		} else if ((cas_5_0_available == TRUE) && (sdram_freq <= cycle_5_0_clk)) { +			mmode |= SDRAM_MMODE_DCL_DDR2_5_0_CLK; +			*selected_cas = DDR_CAS_5; +		} else { +			printf("ERROR: Cannot find a supported CAS latency with the installed DIMMs.\n"); +			printf("Only DIMMs DDR2 with CAS latencies of 3.0, 4.0, and 5.0 are supported.\n"); +			printf("Make sure the PLB speed is within the supported range of the DIMMs.\n\n"); +			hang(); +		} +	} + +	if (sdram_ddr1 == TRUE) +		mmode |= SDRAM_MMODE_WR_DDR1; +	else { + +		/* loop through all the DIMM slots on the board */ +		for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +			/* If a dimm is installed in a particular slot ... */ +			if (dimm_populated[dimm_num] != SDRAM_NONE) +				t_wr_ns = max(t_wr_ns, +					      spd_read(iic0_dimm_addr[dimm_num], 36) >> 2); +		} + +		/* +		 * convert from nanoseconds to ddr clocks +		 * round up if necessary +		 */ +		t_wr_clk = MULDIV64(sdram_freq, t_wr_ns, ONE_BILLION); +		ddr_check = MULDIV64(ONE_BILLION, t_wr_clk, t_wr_ns); +		if (sdram_freq != ddr_check) +			t_wr_clk++; + +		switch (t_wr_clk) { +		case 0: +		case 1: +		case 2: +		case 3: +			mmode |= SDRAM_MMODE_WR_DDR2_3_CYC; +			break; +		case 4: +			mmode |= SDRAM_MMODE_WR_DDR2_4_CYC; +			break; +		case 5: +			mmode |= SDRAM_MMODE_WR_DDR2_5_CYC; +			break; +		default: +			mmode |= SDRAM_MMODE_WR_DDR2_6_CYC; +			break; +		} +	} + +	mtsdram(SDRAM_MMODE, mmode); +} + +/*-----------------------------------------------------------------------------+ + * program_rtr. + *-----------------------------------------------------------------------------*/ +static void program_rtr(unsigned long *dimm_populated, +			unsigned char *iic0_dimm_addr, +			unsigned long num_dimm_banks) +{ +	PPC440_SYS_INFO board_cfg; +	unsigned long max_refresh_rate; +	unsigned long dimm_num; +	unsigned long refresh_rate_type; +	unsigned long refresh_rate; +	unsigned long rint; +	unsigned long sdram_freq; +	unsigned long sdr_ddrpll; +	unsigned long val; + +	/*------------------------------------------------------------------ +	 * Get the board configuration info. +	 *-----------------------------------------------------------------*/ +	get_sys_info(&board_cfg); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Refresh Timing Register, SDRAM_RTR +	 *-----------------------------------------------------------------*/ +	mfsdr(sdr_ddr0, sdr_ddrpll); +	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); + +	max_refresh_rate = 0; +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { + +			refresh_rate_type = spd_read(iic0_dimm_addr[dimm_num], 12); +			refresh_rate_type &= 0x7F; +			switch (refresh_rate_type) { +			case 0: +				refresh_rate =  15625; +				break; +			case 1: +				refresh_rate =   3906; +				break; +			case 2: +				refresh_rate =   7812; +				break; +			case 3: +				refresh_rate =  31250; +				break; +			case 4: +				refresh_rate =  62500; +				break; +			case 5: +				refresh_rate = 125000; +				break; +			default: +				refresh_rate = 0; +				printf("ERROR: DIMM %d unsupported refresh rate/type.\n", +				       (unsigned int)dimm_num); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +				break; +			} + +			max_refresh_rate = max(max_refresh_rate, refresh_rate); +		} +	} + +	rint = MULDIV64(sdram_freq, max_refresh_rate, ONE_BILLION); +	mfsdram(SDRAM_RTR, val); +	mtsdram(SDRAM_RTR, (val & ~SDRAM_RTR_RINT_MASK) | +		(SDRAM_RTR_RINT_ENCODE(rint))); +} + +/*------------------------------------------------------------------ + * This routine programs the SDRAM_TRx registers. + *-----------------------------------------------------------------*/ +static void program_tr(unsigned long *dimm_populated, +		       unsigned char *iic0_dimm_addr, +		       unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long sdram_ddr1; +	unsigned long t_rp_ns; +	unsigned long t_rcd_ns; +	unsigned long t_rrd_ns; +	unsigned long t_ras_ns; +	unsigned long t_rc_ns; +	unsigned long t_rfc_ns; +	unsigned long t_wpc_ns; +	unsigned long t_wtr_ns; +	unsigned long t_rpc_ns; +	unsigned long t_rp_clk; +	unsigned long t_rcd_clk; +	unsigned long t_rrd_clk; +	unsigned long t_ras_clk; +	unsigned long t_rc_clk; +	unsigned long t_rfc_clk; +	unsigned long t_wpc_clk; +	unsigned long t_wtr_clk; +	unsigned long t_rpc_clk; +	unsigned long sdtr1, sdtr2, sdtr3; +	unsigned long ddr_check; +	unsigned long sdram_freq; +	unsigned long sdr_ddrpll; + +	PPC440_SYS_INFO board_cfg; + +	/*------------------------------------------------------------------ +	 * Get the board configuration info. +	 *-----------------------------------------------------------------*/ +	get_sys_info(&board_cfg); + +	mfsdr(sdr_ddr0, sdr_ddrpll); +	sdram_freq = ((board_cfg.freqPLB) * SDR0_DDR0_DDRM_DECODE(sdr_ddrpll)); + +	/*------------------------------------------------------------------ +	 * Handle the timing.  We need to find the worst case timing of all +	 * the dimm modules installed. +	 *-----------------------------------------------------------------*/ +	t_rp_ns = 0; +	t_rrd_ns = 0; +	t_rcd_ns = 0; +	t_ras_ns = 0; +	t_rc_ns = 0; +	t_rfc_ns = 0; +	t_wpc_ns = 0; +	t_wtr_ns = 0; +	t_rpc_ns = 0; +	sdram_ddr1 = TRUE; + +	/* loop through all the DIMM slots on the board */ +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		/* If a dimm is installed in a particular slot ... */ +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			if (dimm_populated[dimm_num] == SDRAM_DDR2) +				sdram_ddr1 = TRUE; +			else +				sdram_ddr1 = FALSE; + +			t_rcd_ns = max(t_rcd_ns, spd_read(iic0_dimm_addr[dimm_num], 29) >> 2); +			t_rrd_ns = max(t_rrd_ns, spd_read(iic0_dimm_addr[dimm_num], 28) >> 2); +			t_rp_ns  = max(t_rp_ns,  spd_read(iic0_dimm_addr[dimm_num], 27) >> 2); +			t_ras_ns = max(t_ras_ns, spd_read(iic0_dimm_addr[dimm_num], 30)); +			t_rc_ns  = max(t_rc_ns,  spd_read(iic0_dimm_addr[dimm_num], 41)); +			t_rfc_ns = max(t_rfc_ns, spd_read(iic0_dimm_addr[dimm_num], 42)); +		} +	} + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Timing Reg 1, SDRAM_TR1 +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_SDTR1, sdtr1); +	sdtr1 &= ~(SDRAM_SDTR1_LDOF_MASK | SDRAM_SDTR1_RTW_MASK | +		   SDRAM_SDTR1_WTWO_MASK | SDRAM_SDTR1_RTRO_MASK); + +	/* default values */ +	sdtr1 |= SDRAM_SDTR1_LDOF_2_CLK; +	sdtr1 |= SDRAM_SDTR1_RTW_2_CLK; + +	/* normal operations */ +	sdtr1 |= SDRAM_SDTR1_WTWO_0_CLK; +	sdtr1 |= SDRAM_SDTR1_RTRO_1_CLK; + +	mtsdram(SDRAM_SDTR1, sdtr1); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Timing Reg 2, SDRAM_TR2 +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_SDTR2, sdtr2); +	sdtr2 &= ~(SDRAM_SDTR2_RCD_MASK  | SDRAM_SDTR2_WTR_MASK | +		   SDRAM_SDTR2_XSNR_MASK | SDRAM_SDTR2_WPC_MASK | +		   SDRAM_SDTR2_RPC_MASK  | SDRAM_SDTR2_RP_MASK  | +		   SDRAM_SDTR2_RRD_MASK); + +	/* +	 * convert t_rcd from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_rcd_clk = MULDIV64(sdram_freq, t_rcd_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_rcd_clk, t_rcd_ns); +	if (sdram_freq != ddr_check) +		t_rcd_clk++; + +	switch (t_rcd_clk) { +	case 0: +	case 1: +		sdtr2 |= SDRAM_SDTR2_RCD_1_CLK; +		break; +	case 2: +		sdtr2 |= SDRAM_SDTR2_RCD_2_CLK; +		break; +	case 3: +		sdtr2 |= SDRAM_SDTR2_RCD_3_CLK; +		break; +	case 4: +		sdtr2 |= SDRAM_SDTR2_RCD_4_CLK; +		break; +	default: +		sdtr2 |= SDRAM_SDTR2_RCD_5_CLK; +		break; +	} + +	if (sdram_ddr1 == TRUE) { /* DDR1 */ +		if (sdram_freq < 200000000) { +			sdtr2 |= SDRAM_SDTR2_WTR_1_CLK; +			sdtr2 |= SDRAM_SDTR2_WPC_2_CLK; +			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; +		} else { +			sdtr2 |= SDRAM_SDTR2_WTR_2_CLK; +			sdtr2 |= SDRAM_SDTR2_WPC_3_CLK; +			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; +		} +	} else { /* DDR2 */ +		/* loop through all the DIMM slots on the board */ +		for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +			/* If a dimm is installed in a particular slot ... */ +			if (dimm_populated[dimm_num] != SDRAM_NONE) { +				t_wpc_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 36) >> 2); +				t_wtr_ns = max(t_wtr_ns, spd_read(iic0_dimm_addr[dimm_num], 37) >> 2); +				t_rpc_ns = max(t_rpc_ns, spd_read(iic0_dimm_addr[dimm_num], 38) >> 2); +			} +		} + +		/* +		 * convert from nanoseconds to ddr clocks +		 * round up if necessary +		 */ +		t_wpc_clk = MULDIV64(sdram_freq, t_wpc_ns, ONE_BILLION); +		ddr_check = MULDIV64(ONE_BILLION, t_wpc_clk, t_wpc_ns); +		if (sdram_freq != ddr_check) +			t_wpc_clk++; + +		switch (t_wpc_clk) { +		case 0: +		case 1: +		case 2: +			sdtr2 |= SDRAM_SDTR2_WPC_2_CLK; +			break; +		case 3: +			sdtr2 |= SDRAM_SDTR2_WPC_3_CLK; +			break; +		case 4: +			sdtr2 |= SDRAM_SDTR2_WPC_4_CLK; +			break; +		case 5: +			sdtr2 |= SDRAM_SDTR2_WPC_5_CLK; +			break; +		default: +			sdtr2 |= SDRAM_SDTR2_WPC_6_CLK; +			break; +		} + +		/* +		 * convert from nanoseconds to ddr clocks +		 * round up if necessary +		 */ +		t_wtr_clk = MULDIV64(sdram_freq, t_wtr_ns, ONE_BILLION); +		ddr_check = MULDIV64(ONE_BILLION, t_wtr_clk, t_wtr_ns); +		if (sdram_freq != ddr_check) +			t_wtr_clk++; + +		switch (t_wtr_clk) { +		case 0: +		case 1: +			sdtr2 |= SDRAM_SDTR2_WTR_1_CLK; +			break; +		case 2: +			sdtr2 |= SDRAM_SDTR2_WTR_2_CLK; +			break; +		case 3: +			sdtr2 |= SDRAM_SDTR2_WTR_3_CLK; +			break; +		default: +			sdtr2 |= SDRAM_SDTR2_WTR_4_CLK; +			break; +		} + +		/* +		 * convert from nanoseconds to ddr clocks +		 * round up if necessary +		 */ +		t_rpc_clk = MULDIV64(sdram_freq, t_rpc_ns, ONE_BILLION); +		ddr_check = MULDIV64(ONE_BILLION, t_rpc_clk, t_rpc_ns); +		if (sdram_freq != ddr_check) +			t_rpc_clk++; + +		switch (t_rpc_clk) { +		case 0: +		case 1: +		case 2: +			sdtr2 |= SDRAM_SDTR2_RPC_2_CLK; +			break; +		case 3: +			sdtr2 |= SDRAM_SDTR2_RPC_3_CLK; +			break; +		default: +			sdtr2 |= SDRAM_SDTR2_RPC_4_CLK; +			break; +		} +	} + +	/* default value */ +	sdtr2 |= SDRAM_SDTR2_XSNR_16_CLK; + +	/* +	 * convert t_rrd from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_rrd_clk = MULDIV64(sdram_freq, t_rrd_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_rrd_clk, t_rrd_ns); +	if (sdram_freq != ddr_check) +		t_rrd_clk++; + +	if (t_rrd_clk == 3) +		sdtr2 |= SDRAM_SDTR2_RRD_3_CLK; +	else +		sdtr2 |= SDRAM_SDTR2_RRD_2_CLK; + +	/* +	 * convert t_rp from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_rp_clk = MULDIV64(sdram_freq, t_rp_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_rp_clk, t_rp_ns); +	if (sdram_freq != ddr_check) +		t_rp_clk++; + +	switch (t_rp_clk) { +	case 0: +	case 1: +	case 2: +	case 3: +		sdtr2 |= SDRAM_SDTR2_RP_3_CLK; +		break; +	case 4: +		sdtr2 |= SDRAM_SDTR2_RP_4_CLK; +		break; +	case 5: +		sdtr2 |= SDRAM_SDTR2_RP_5_CLK; +		break; +	case 6: +		sdtr2 |= SDRAM_SDTR2_RP_6_CLK; +		break; +	default: +		sdtr2 |= SDRAM_SDTR2_RP_7_CLK; +		break; +	} + +	mtsdram(SDRAM_SDTR2, sdtr2); + +	/*------------------------------------------------------------------ +	 * Set the SDRAM Timing Reg 3, SDRAM_TR3 +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_SDTR3, sdtr3); +	sdtr3 &= ~(SDRAM_SDTR3_RAS_MASK  | SDRAM_SDTR3_RC_MASK | +		   SDRAM_SDTR3_XCS_MASK | SDRAM_SDTR3_RFC_MASK); + +	/* +	 * convert t_ras from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_ras_clk = MULDIV64(sdram_freq, t_ras_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_ras_clk, t_ras_ns); +	if (sdram_freq != ddr_check) +		t_ras_clk++; + +	sdtr3 |= SDRAM_SDTR3_RAS_ENCODE(t_ras_clk); + +	/* +	 * convert t_rc from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_rc_clk = MULDIV64(sdram_freq, t_rc_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_rc_clk, t_rc_ns); +	if (sdram_freq != ddr_check) +		t_rc_clk++; + +	sdtr3 |= SDRAM_SDTR3_RC_ENCODE(t_rc_clk); + +	/* default xcs value */ +	sdtr3 |= SDRAM_SDTR3_XCS; + +	/* +	 * convert t_rfc from nanoseconds to ddr clocks +	 * round up if necessary +	 */ +	t_rfc_clk = MULDIV64(sdram_freq, t_rfc_ns, ONE_BILLION); +	ddr_check = MULDIV64(ONE_BILLION, t_rfc_clk, t_rfc_ns); +	if (sdram_freq != ddr_check) +		t_rfc_clk++; + +	sdtr3 |= SDRAM_SDTR3_RFC_ENCODE(t_rfc_clk); + +	mtsdram(SDRAM_SDTR3, sdtr3); +} + +/*-----------------------------------------------------------------------------+ + * program_bxcf. + *-----------------------------------------------------------------------------*/ +static void program_bxcf(unsigned long *dimm_populated, +			 unsigned char *iic0_dimm_addr, +			 unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long num_col_addr; +	unsigned long num_ranks; +	unsigned long num_banks; +	unsigned long mode; +	unsigned long ind_rank; +	unsigned long ind; +	unsigned long ind_bank; +	unsigned long bank_0_populated; + +	/*------------------------------------------------------------------ +	 * Set the BxCF regs.  First, wipe out the bank config registers. +	 *-----------------------------------------------------------------*/ +	mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF); +	mtdcr(SDRAMC_CFGDATA, 0x00000000); +	mtdcr(SDRAMC_CFGADDR, SDRAM_MB1CF); +	mtdcr(SDRAMC_CFGDATA, 0x00000000); +	mtdcr(SDRAMC_CFGADDR, SDRAM_MB2CF); +	mtdcr(SDRAMC_CFGDATA, 0x00000000); +	mtdcr(SDRAMC_CFGADDR, SDRAM_MB3CF); +	mtdcr(SDRAMC_CFGDATA, 0x00000000); + +	mode = SDRAM_BXCF_M_BE_ENABLE; + +	bank_0_populated = 0; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			num_col_addr = spd_read(iic0_dimm_addr[dimm_num], 4); +			num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5); +			if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) +				num_ranks = (num_ranks & 0x0F) +1; +			else +				num_ranks = num_ranks & 0x0F; + +			num_banks = spd_read(iic0_dimm_addr[dimm_num], 17); + +			for (ind_bank = 0; ind_bank < 2; ind_bank++) { +				if (num_banks == 4) +					ind = 0; +				else +					ind = 5; +				switch (num_col_addr) { +				case 0x08: +					mode |= (SDRAM_BXCF_M_AM_0 + ind); +					break; +				case 0x09: +					mode |= (SDRAM_BXCF_M_AM_1 + ind); +					break; +				case 0x0A: +					mode |= (SDRAM_BXCF_M_AM_2 + ind); +					break; +				case 0x0B: +					mode |= (SDRAM_BXCF_M_AM_3 + ind); +					break; +				case 0x0C: +					mode |= (SDRAM_BXCF_M_AM_4 + ind); +					break; +				default: +					printf("DDR-SDRAM: DIMM %d BxCF configuration.\n", +					       (unsigned int)dimm_num); +					printf("ERROR: Unsupported value for number of " +					       "column addresses: %d.\n", (unsigned int)num_col_addr); +					printf("Replace the DIMM module with a supported DIMM.\n\n"); +					hang(); +				} +			} + +			if ((dimm_populated[dimm_num] != SDRAM_NONE)&& (dimm_num ==1)) +				bank_0_populated = 1; + +			for (ind_rank = 0; ind_rank < num_ranks; ind_rank++) { +				mtdcr(SDRAMC_CFGADDR, SDRAM_MB0CF + ((dimm_num + bank_0_populated + ind_rank) << 2)); +				mtdcr(SDRAMC_CFGDATA, mode); +			} +		} +	} +} + +/*------------------------------------------------------------------ + * program memory queue. + *-----------------------------------------------------------------*/ +static void program_memory_queue(unsigned long *dimm_populated, +				 unsigned char *iic0_dimm_addr, +				 unsigned long num_dimm_banks) +{ +	unsigned long dimm_num; +	unsigned long rank_base_addr; +	unsigned long rank_reg; +	unsigned long rank_size_bytes; +	unsigned long rank_size_id; +	unsigned long num_ranks; +	unsigned long baseadd_size; +	unsigned long i; +	unsigned long bank_0_populated = 0; + +	/*------------------------------------------------------------------ +	 * Reset the rank_base_address. +	 *-----------------------------------------------------------------*/ +	rank_reg   = SDRAM_R0BAS; + +	rank_base_addr = 0x00000000; + +	for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++) { +		if (dimm_populated[dimm_num] != SDRAM_NONE) { +			num_ranks = spd_read(iic0_dimm_addr[dimm_num], 5); +			if ((spd_read(iic0_dimm_addr[dimm_num], 2)) == 0x08) +				num_ranks = (num_ranks & 0x0F) + 1; +			else +				num_ranks = num_ranks & 0x0F; + +			rank_size_id = spd_read(iic0_dimm_addr[dimm_num], 31); + +			/*------------------------------------------------------------------ +			 * Set the sizes +			 *-----------------------------------------------------------------*/ +			baseadd_size = 0; +			rank_size_bytes = 1024 * 1024 * rank_size_id; +			switch (rank_size_id) { +			case 0x02: +				baseadd_size |= SDRAM_RXBAS_SDSZ_8; +				break; +			case 0x04: +				baseadd_size |= SDRAM_RXBAS_SDSZ_16; +				break; +			case 0x08: +				baseadd_size |= SDRAM_RXBAS_SDSZ_32; +				break; +			case 0x10: +				baseadd_size |= SDRAM_RXBAS_SDSZ_64; +				break; +			case 0x20: +				baseadd_size |= SDRAM_RXBAS_SDSZ_128; +				break; +			case 0x40: +				baseadd_size |= SDRAM_RXBAS_SDSZ_256; +				break; +			case 0x80: +				baseadd_size |= SDRAM_RXBAS_SDSZ_512; +				break; +			default: +				printf("DDR-SDRAM: DIMM %d memory queue configuration.\n", +				       (unsigned int)dimm_num); +				printf("ERROR: Unsupported value for the banksize: %d.\n", +				       (unsigned int)rank_size_id); +				printf("Replace the DIMM module with a supported DIMM.\n\n"); +				hang(); +			} + +			if ((dimm_populated[dimm_num] != SDRAM_NONE) && (dimm_num == 1)) +				bank_0_populated = 1; + +			for (i = 0; i < num_ranks; i++)	{ +				mtdcr_any(rank_reg+i+dimm_num+bank_0_populated, +					  (rank_base_addr & SDRAM_RXBAS_SDBA_MASK) | +					  baseadd_size); +				rank_base_addr += rank_size_bytes; +			} +		} +	} +} + +/*-----------------------------------------------------------------------------+ + * is_ecc_enabled. + *-----------------------------------------------------------------------------*/ +static unsigned long is_ecc_enabled(void) +{ +	unsigned long dimm_num; +	unsigned long ecc; +	unsigned long val; + +	ecc = 0; +	/* loop through all the DIMM slots on the board */ +	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { +		mfsdram(SDRAM_MCOPT1, val); +		ecc = max(ecc, SDRAM_MCOPT1_MCHK_CHK_DECODE(val)); +	} + +	return(ecc); +} + +/*-----------------------------------------------------------------------------+ + * program_ecc. + *-----------------------------------------------------------------------------*/ +static void program_ecc(unsigned long *dimm_populated, +			unsigned char *iic0_dimm_addr, +			unsigned long num_dimm_banks) +{ +	unsigned long mcopt1; +	unsigned long mcopt2; +	unsigned long mcstat; +	unsigned long dimm_num; +	unsigned long ecc; + +	ecc = 0; +	/* loop through all the DIMM slots on the board */ +	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { +		/* If a dimm is installed in a particular slot ... */ +		if (dimm_populated[dimm_num] != SDRAM_NONE) +			ecc = max(ecc, spd_read(iic0_dimm_addr[dimm_num], 11)); +	} +	if (ecc == 0) +		return; + +	mfsdram(SDRAM_MCOPT1, mcopt1); +	mfsdram(SDRAM_MCOPT2, mcopt2); + +	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { +		/* DDR controller must be enabled and not in self-refresh. */ +		mfsdram(SDRAM_MCSTAT, mcstat); +		if (((mcopt2 & SDRAM_MCOPT2_DCEN_MASK) == SDRAM_MCOPT2_DCEN_ENABLE) +		    && ((mcopt2 & SDRAM_MCOPT2_SREN_MASK) == SDRAM_MCOPT2_SREN_EXIT) +		    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK)) +			== (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) { + +			program_ecc_addr(0, sdram_memsize()); +		} +	} + +	return; +} + +/*-----------------------------------------------------------------------------+ + * program_ecc_addr. + *-----------------------------------------------------------------------------*/ +static void program_ecc_addr(unsigned long start_address, +			     unsigned long num_bytes) +{ +	unsigned long current_address; +	unsigned long end_address; +	unsigned long address_increment; +	unsigned long mcopt1; + +	current_address = start_address; +	mfsdram(SDRAM_MCOPT1, mcopt1); +	if ((mcopt1 & SDRAM_MCOPT1_MCHK_MASK) != SDRAM_MCOPT1_MCHK_NON) { +		mtsdram(SDRAM_MCOPT1, +			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_GEN); +		sync(); +		eieio(); +		wait_ddr_idle(); + +		/* ECC bit set method for non-cached memory */ +		if ((mcopt1 & SDRAM_MCOPT1_DMWD_MASK) == SDRAM_MCOPT1_DMWD_32) +			address_increment = 4; +		else +			address_increment = 8; +		end_address = current_address + num_bytes; + +		while (current_address < end_address) { +			*((unsigned long *)current_address) = 0x00000000; +			current_address += address_increment; +		} +		sync(); +		eieio(); +		wait_ddr_idle(); + +		mtsdram(SDRAM_MCOPT1, +			(mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK); +		sync(); +		eieio(); +		wait_ddr_idle(); +	} +} + +/*-----------------------------------------------------------------------------+ + * program_DQS_calibration. + *-----------------------------------------------------------------------------*/ +static void program_DQS_calibration(unsigned long *dimm_populated, +				    unsigned char *iic0_dimm_addr, +				    unsigned long num_dimm_banks) +{ +	unsigned long val; + +#ifdef HARD_CODED_DQS /* calibration test with hardvalues */ +	mtsdram(SDRAM_RQDC, 0x80000037); +	mtsdram(SDRAM_RDCC, 0x40000000); +	mtsdram(SDRAM_RFDC, 0x000001DF); + +	test(); +#else +	/*------------------------------------------------------------------ +	 * Program RDCC register +	 * Read sample cycle auto-update enable +	 *-----------------------------------------------------------------*/ + +	/* +	 * Modified for the Katmai platform:  with some DIMMs, the DDR2 +	 * controller automatically selects the T2 read cycle, but this +	 * proves unreliable.  Go ahead and force the DDR2 controller +	 * to use the T4 sample and disable the automatic update of the +	 * RDSS field. +	 */ +	mfsdram(SDRAM_RDCC, val); +	mtsdram(SDRAM_RDCC, +		(val & ~(SDRAM_RDCC_RDSS_MASK | SDRAM_RDCC_RSAE_MASK)) +		| (SDRAM_RDCC_RDSS_T4 | SDRAM_RDCC_RSAE_DISABLE)); + +	/*------------------------------------------------------------------ +	 * Program RQDC register +	 * Internal DQS delay mechanism enable +	 *-----------------------------------------------------------------*/ +	mtsdram(SDRAM_RQDC, (SDRAM_RQDC_RQDE_ENABLE|SDRAM_RQDC_RQFD_ENCODE(0x38))); + +	/*------------------------------------------------------------------ +	 * Program RFDC register +	 * Set Feedback Fractional Oversample +	 * Auto-detect read sample cycle enable +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_RFDC, val); +	mtsdram(SDRAM_RFDC, +		(val & ~(SDRAM_RFDC_ARSE_MASK | SDRAM_RFDC_RFOS_MASK | +			 SDRAM_RFDC_RFFD_MASK)) +		| (SDRAM_RFDC_ARSE_ENABLE | SDRAM_RFDC_RFOS_ENCODE(0) | +		   SDRAM_RFDC_RFFD_ENCODE(0))); + +	DQS_calibration_process(); +#endif +} + +static u32 short_mem_test(void) +{ +	u32 *membase; +	u32 bxcr_num; +	u32 bxcf; +	int i; +	int j; +	u32 test[NUMMEMTESTS][NUMMEMWORDS] = { +		{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, +		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, +		{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, +		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, +		{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, +		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, +		{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, +		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, +		{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, +		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, +		{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, +		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, +		{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, +		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, +		{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, +		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} }; + +	for (bxcr_num = 0; bxcr_num < MAXBXCF; bxcr_num++) { +		mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf); + +		/* Banks enabled */ +		if ((bxcf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { + +			/* Bank is enabled */ +			membase = (u32 *)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+bxcr_num))); + +			/*------------------------------------------------------------------ +			 * Run the short memory test. +			 *-----------------------------------------------------------------*/ +			for (i = 0; i < NUMMEMTESTS; i++) { +				for (j = 0; j < NUMMEMWORDS; j++) { +					membase[j] = test[i][j]; +					ppcDcbf((u32)&(membase[j])); +				} +				sync(); +				for (j = 0; j < NUMMEMWORDS; j++) { +					if (membase[j] != test[i][j]) { +						ppcDcbf((u32)&(membase[j])); +						break; +					} +					ppcDcbf((u32)&(membase[j])); +				} +				sync(); +				if (j < NUMMEMWORDS) +					break; +			} +			if (i < NUMMEMTESTS) +				break; +		}	/* if bank enabled */ +	}		/* for bxcf_num */ + +	return bxcr_num; +} + +#ifndef HARD_CODED_DQS +/*-----------------------------------------------------------------------------+ + * DQS_calibration_process. + *-----------------------------------------------------------------------------*/ +static void DQS_calibration_process(void) +{ +	unsigned long ecc_temp; +	unsigned long rfdc_reg; +	unsigned long rffd; +	unsigned long rqdc_reg; +	unsigned long rqfd; +	unsigned long bxcr_num; +	unsigned long val; +	long rqfd_average; +	long rffd_average; +	long max_start; +	long min_end; +	unsigned long begin_rqfd[MAXRANKS]; +	unsigned long begin_rffd[MAXRANKS]; +	unsigned long end_rqfd[MAXRANKS]; +	unsigned long end_rffd[MAXRANKS]; +	char window_found; +	unsigned long dlycal; +	unsigned long dly_val; +	unsigned long max_pass_length; +	unsigned long current_pass_length; +	unsigned long current_fail_length; +	unsigned long current_start; +	long max_end; +	unsigned char fail_found; +	unsigned char pass_found; + +	/*------------------------------------------------------------------ +	 * Test to determine the best read clock delay tuning bits. +	 * +	 * Before the DDR controller can be used, the read clock delay needs to be +	 * set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. +	 * This value cannot be hardcoded into the program because it changes +	 * depending on the board's setup and environment. +	 * To do this, all delay values are tested to see if they +	 * work or not.  By doing this, you get groups of fails with groups of +	 * passing values.  The idea is to find the start and end of a passing +	 * window and take the center of it to use as the read clock delay. +	 * +	 * A failure has to be seen first so that when we hit a pass, we know +	 * that it is truely the start of the window.  If we get passing values +	 * to start off with, we don't know if we are at the start of the window. +	 * +	 * The code assumes that a failure will always be found. +	 * If a failure is not found, there is no easy way to get the middle +	 * of the passing window.  I guess we can pretty much pick any value +	 * but some values will be better than others.  Since the lowest speed +	 * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), +	 * from experimentation it is safe to say you will always have a failure. +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT1, ecc_temp); +	ecc_temp &= SDRAM_MCOPT1_MCHK_MASK; +	mfsdram(SDRAM_MCOPT1, val); +	mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | +		SDRAM_MCOPT1_MCHK_NON); + +	max_start = 0; +	min_end = 0; +	begin_rqfd[0] = 0; +	begin_rffd[0] = 0; +	begin_rqfd[1] = 0; +	begin_rffd[1] = 0; +	end_rqfd[0] = 0; +	end_rffd[0] = 0; +	end_rqfd[1] = 0; +	end_rffd[1] = 0; +	window_found = FALSE; + +	max_pass_length = 0; +	max_start = 0; +	max_end = 0; +	current_pass_length = 0; +	current_fail_length = 0; +	current_start = 0; +	window_found = FALSE; +	fail_found = FALSE; +	pass_found = FALSE; + +	/* first fix RQDC[RQFD] to an average of 80 degre phase shift to find RFDC[RFFD] */ +	/* rqdc_reg = mfsdram(SDRAM_RQDC) & ~(SDRAM_RQDC_RQFD_MASK); */ + +	/* +	 * get the delay line calibration register value +	 */ +	mfsdram(SDRAM_DLCR, dlycal); +	dly_val = SDRAM_DLYCAL_DLCV_DECODE(dlycal) << 2; + +	for (rffd = 0; rffd <= SDRAM_RFDC_RFFD_MAX; rffd++) { +		mfsdram(SDRAM_RFDC, rfdc_reg); +		rfdc_reg &= ~(SDRAM_RFDC_RFFD_MASK); + +		/*------------------------------------------------------------------ +		 * Set the timing reg for the test. +		 *-----------------------------------------------------------------*/ +		mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd)); + +		/* do the small memory test */ +		bxcr_num = short_mem_test(); + +		/*------------------------------------------------------------------ +		 * See if the rffd value passed. +		 *-----------------------------------------------------------------*/ +		if (bxcr_num == MAXBXCF) { +			if (fail_found == TRUE) { +				pass_found = TRUE; +				if (current_pass_length == 0) +					current_start = rffd; + +				current_fail_length = 0; +				current_pass_length++; + +				if (current_pass_length > max_pass_length) { +					max_pass_length = current_pass_length; +					max_start = current_start; +					max_end = rffd; +				} +			} +		} else { +			current_pass_length = 0; +			current_fail_length++; + +			if (current_fail_length >= (dly_val >> 2)) { +				if (fail_found == FALSE) { +					fail_found = TRUE; +				} else if (pass_found == TRUE) { +					window_found = TRUE; +					break; +				} +			} +		} +	}		/* for rffd */ + + +	/*------------------------------------------------------------------ +	 * Set the average RFFD value +	 *-----------------------------------------------------------------*/ +	rffd_average = ((max_start + max_end) >> 1); + +	if (rffd_average < 0) +		rffd_average = 0; + +	if (rffd_average > SDRAM_RFDC_RFFD_MAX) +		rffd_average = SDRAM_RFDC_RFFD_MAX; +	/* now fix RFDC[RFFD] found and find RQDC[RQFD] */ +	mtsdram(SDRAM_RFDC, rfdc_reg | SDRAM_RFDC_RFFD_ENCODE(rffd_average)); + +	max_pass_length = 0; +	max_start = 0; +	max_end = 0; +	current_pass_length = 0; +	current_fail_length = 0; +	current_start = 0; +	window_found = FALSE; +	fail_found = FALSE; +	pass_found = FALSE; + +	for (rqfd = 0; rqfd <= SDRAM_RQDC_RQFD_MAX; rqfd++) { +		mfsdram(SDRAM_RQDC, rqdc_reg); +		rqdc_reg &= ~(SDRAM_RQDC_RQFD_MASK); + +		/*------------------------------------------------------------------ +		 * Set the timing reg for the test. +		 *-----------------------------------------------------------------*/ +		mtsdram(SDRAM_RQDC, rqdc_reg | SDRAM_RQDC_RQFD_ENCODE(rqfd)); + +		/* do the small memory test */ +		bxcr_num = short_mem_test(); + +		/*------------------------------------------------------------------ +		 * See if the rffd value passed. +		 *-----------------------------------------------------------------*/ +		if (bxcr_num == MAXBXCF) { +			if (fail_found == TRUE) { +				pass_found = TRUE; +				if (current_pass_length == 0) +					current_start = rqfd; + +				current_fail_length = 0; +				current_pass_length++; + +				if (current_pass_length > max_pass_length) { +					max_pass_length = current_pass_length; +					max_start = current_start; +					max_end = rqfd; +				} +			} +		} else { +			current_pass_length = 0; +			current_fail_length++; + +			if (fail_found == FALSE) { +				fail_found = TRUE; +			} else if (pass_found == TRUE) { +				window_found = TRUE; +				break; +			} +		} +	} + +	/*------------------------------------------------------------------ +	 * Make sure we found the valid read passing window.  Halt if not +	 *-----------------------------------------------------------------*/ +	if (window_found == FALSE) { +		printf("ERROR: Cannot determine a common read delay for the " +		       "DIMM(s) installed.\n"); +		debug("%s[%d] ERROR : \n", __FUNCTION__,__LINE__); +		hang(); +	} + +	rqfd_average = ((max_start + max_end) >> 1); + +	if (rqfd_average < 0) +		rqfd_average = 0; + +	if (rqfd_average > SDRAM_RQDC_RQFD_MAX) +		rqfd_average = SDRAM_RQDC_RQFD_MAX; + +	/*------------------------------------------------------------------ +	 * Restore the ECC variable to what it originally was +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT1, val); +	mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | ecc_temp); + +	mtsdram(SDRAM_RQDC, +		(rqdc_reg & ~SDRAM_RQDC_RQFD_MASK) | +		SDRAM_RQDC_RQFD_ENCODE(rqfd_average)); + +	mfsdram(SDRAM_DLCR, val); +	debug("%s[%d] DLCR: 0x%08X\n", __FUNCTION__, __LINE__, val); +	mfsdram(SDRAM_RQDC, val); +	debug("%s[%d] RQDC: 0x%08X\n", __FUNCTION__, __LINE__, val); +	mfsdram(SDRAM_RFDC, val); +	debug("%s[%d] RFDC: 0x%08X\n", __FUNCTION__, __LINE__, val); +} +#else /* calibration test with hardvalues */ +/*-----------------------------------------------------------------------------+ + * DQS_calibration_process. + *-----------------------------------------------------------------------------*/ +static void test(void) +{ +	unsigned long dimm_num; +	unsigned long ecc_temp; +	unsigned long i, j; +	unsigned long *membase; +	unsigned long bxcf[MAXRANKS]; +	unsigned long val; +	char window_found; +	char begin_found[MAXDIMMS]; +	char end_found[MAXDIMMS]; +	char search_end[MAXDIMMS]; +	unsigned long test[NUMMEMTESTS][NUMMEMWORDS] = { +		{0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, +		 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF}, +		{0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, +		 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000}, +		{0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555, +		 0xAAAAAAAA, 0xAAAAAAAA, 0x55555555, 0x55555555}, +		{0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA, +		 0x55555555, 0x55555555, 0xAAAAAAAA, 0xAAAAAAAA}, +		{0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A, +		 0xA5A5A5A5, 0xA5A5A5A5, 0x5A5A5A5A, 0x5A5A5A5A}, +		{0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5, +		 0x5A5A5A5A, 0x5A5A5A5A, 0xA5A5A5A5, 0xA5A5A5A5}, +		{0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA, +		 0xAA55AA55, 0xAA55AA55, 0x55AA55AA, 0x55AA55AA}, +		{0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55, +		 0x55AA55AA, 0x55AA55AA, 0xAA55AA55, 0xAA55AA55} }; + +	/*------------------------------------------------------------------ +	 * Test to determine the best read clock delay tuning bits. +	 * +	 * Before the DDR controller can be used, the read clock delay needs to be +	 * set.  This is SDRAM_RQDC[RQFD] and SDRAM_RFDC[RFFD]. +	 * This value cannot be hardcoded into the program because it changes +	 * depending on the board's setup and environment. +	 * To do this, all delay values are tested to see if they +	 * work or not.  By doing this, you get groups of fails with groups of +	 * passing values.  The idea is to find the start and end of a passing +	 * window and take the center of it to use as the read clock delay. +	 * +	 * A failure has to be seen first so that when we hit a pass, we know +	 * that it is truely the start of the window.  If we get passing values +	 * to start off with, we don't know if we are at the start of the window. +	 * +	 * The code assumes that a failure will always be found. +	 * If a failure is not found, there is no easy way to get the middle +	 * of the passing window.  I guess we can pretty much pick any value +	 * but some values will be better than others.  Since the lowest speed +	 * we can clock the DDR interface at is 200 MHz (2x 100 MHz PLB speed), +	 * from experimentation it is safe to say you will always have a failure. +	 *-----------------------------------------------------------------*/ +	mfsdram(SDRAM_MCOPT1, ecc_temp); +	ecc_temp &= SDRAM_MCOPT1_MCHK_MASK; +	mfsdram(SDRAM_MCOPT1, val); +	mtsdram(SDRAM_MCOPT1, (val & ~SDRAM_MCOPT1_MCHK_MASK) | +		SDRAM_MCOPT1_MCHK_NON); + +	window_found = FALSE; +	begin_found[0] = FALSE; +	end_found[0] = FALSE; +	search_end[0] = FALSE; +	begin_found[1] = FALSE; +	end_found[1] = FALSE; +	search_end[1] = FALSE; + +	for (dimm_num = 0; dimm_num < MAXDIMMS; dimm_num++) { +		mfsdram(SDRAM_MB0CF + (bxcr_num << 2), bxcf[bxcr_num]); + +		/* Banks enabled */ +		if ((bxcf[dimm_num] & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) { + +			/* Bank is enabled */ +			membase = +				(unsigned long*)(SDRAM_RXBAS_SDBA_DECODE(mfdcr_any(SDRAM_R0BAS+dimm_num))); + +			/*------------------------------------------------------------------ +			 * Run the short memory test. +			 *-----------------------------------------------------------------*/ +			for (i = 0; i < NUMMEMTESTS; i++) { +				for (j = 0; j < NUMMEMWORDS; j++) { +					membase[j] = test[i][j]; +					ppcDcbf((u32)&(membase[j])); +				} +				sync(); +				for (j = 0; j < NUMMEMWORDS; j++) { +					if (membase[j] != test[i][j]) { +						ppcDcbf((u32)&(membase[j])); +						break; +					} +					ppcDcbf((u32)&(membase[j])); +				} +				sync(); +				if (j < NUMMEMWORDS) +					break; +			} + +			/*------------------------------------------------------------------ +			 * See if the rffd value passed. +			 *-----------------------------------------------------------------*/ +			if (i < NUMMEMTESTS) { +				if ((end_found[dimm_num] == FALSE) && +				    (search_end[dimm_num] == TRUE)) { +					end_found[dimm_num] = TRUE; +				} +				if ((end_found[0] == TRUE) && +				    (end_found[1] == TRUE)) +					break; +			} else { +				if (begin_found[dimm_num] == FALSE) { +					begin_found[dimm_num] = TRUE; +					search_end[dimm_num] = TRUE; +				} +			} +		} else { +			begin_found[dimm_num] = TRUE; +			end_found[dimm_num] = TRUE; +		} +	} + +	if ((begin_found[0] == TRUE) && (begin_found[1] == TRUE)) +		window_found = TRUE; + +	/*------------------------------------------------------------------ +	 * Make sure we found the valid read passing window.  Halt if not +	 *-----------------------------------------------------------------*/ +	if (window_found == FALSE) { +		printf("ERROR: Cannot determine a common read delay for the " +		       "DIMM(s) installed.\n"); +		hang(); +	} + +	/*------------------------------------------------------------------ +	 * Restore the ECC variable to what it originally was +	 *-----------------------------------------------------------------*/ +	mtsdram(SDRAM_MCOPT1, +		(ppcMfdcr_sdram(SDRAM_MCOPT1) & ~SDRAM_MCOPT1_MCHK_MASK) +		| ecc_temp); +} +#endif + +#if defined(DEBUG) +static void ppc440sp_sdram_register_dump(void) +{ +	unsigned int sdram_reg; +	unsigned int sdram_data; +	unsigned int dcr_data; + +	printf("\n  Register Dump:\n"); +	sdram_reg = SDRAM_MCSTAT; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MCSTAT    = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MCOPT1; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MCOPT1    = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MCOPT2; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MCOPT2    = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MODT0; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MODT0     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MODT1; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MODT1     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MODT2; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MODT2     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MODT3; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MODT3     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_CODT; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_CODT      = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_VVPR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_VVPR      = 0x%08X", sdram_data); +	sdram_reg = SDRAM_OPARS; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_OPARS     = 0x%08X\n", sdram_data); +	/* +	 * OPAR2 is only used as a trigger register. +	 * No data is contained in this register, and reading or writing +	 * to is can cause bad things to happen (hangs).  Just skip it +	 * and report NA +	 * sdram_reg = SDRAM_OPAR2; +	 * mfsdram(sdram_reg, sdram_data); +	 * printf("        SDRAM_OPAR2     = 0x%08X\n", sdram_data); +	 */ +	printf("        SDRAM_OPART     = N/A       "); +	sdram_reg = SDRAM_RTR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_RTR       = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MB0CF; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MB0CF     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MB1CF; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MB1CF     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MB2CF; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MB2CF     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MB3CF; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MB3CF     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR0; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR0  = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR1; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR1  = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR2; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR2  = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR3; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR3  = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR4; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR4  = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR5; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR5  = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR6; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR6  = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR7; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR7  = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR8; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR8  = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR9; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR9  = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR10; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR10 = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR11; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR11 = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR12; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR12 = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR13; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR13 = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_INITPLR14; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR14 = 0x%08X", sdram_data); +	sdram_reg = SDRAM_INITPLR15; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_INITPLR15 = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_RQDC; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_RQDC      = 0x%08X", sdram_data); +	sdram_reg = SDRAM_RFDC; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_RFDC      = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_RDCC; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_RDCC      = 0x%08X", sdram_data); +	sdram_reg = SDRAM_DLCR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_DLCR      = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_CLKTR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_CLKTR     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_WRDTR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_WRDTR     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_SDTR1; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_SDTR1     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_SDTR2; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_SDTR2     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_SDTR3; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_SDTR3     = 0x%08X", sdram_data); +	sdram_reg = SDRAM_MMODE; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MMODE     = 0x%08X\n", sdram_data); +	sdram_reg = SDRAM_MEMODE; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_MEMODE    = 0x%08X", sdram_data); +	sdram_reg = SDRAM_ECCCR; +	mfsdram(sdram_reg, sdram_data); +	printf("        SDRAM_ECCCR     = 0x%08X\n\n", sdram_data); + +	dcr_data = mfdcr(SDRAM_R0BAS); +	printf("        MQ0_B0BAS       = 0x%08X", dcr_data); +	dcr_data = mfdcr(SDRAM_R1BAS); +	printf("        MQ1_B0BAS       = 0x%08X\n", dcr_data); +	dcr_data = mfdcr(SDRAM_R2BAS); +	printf("        MQ2_B0BAS       = 0x%08X", dcr_data); +	dcr_data = mfdcr(SDRAM_R3BAS); +	printf("        MQ3_B0BAS       = 0x%08X\n", dcr_data); +} +#endif +#endif /* CONFIG_SPD_EEPROM */ diff --git a/cpu/ppc4xx/Makefile b/cpu/ppc4xx/Makefile index baecf7035..96f0f62eb 100644 --- a/cpu/ppc4xx/Makefile +++ b/cpu/ppc4xx/Makefile @@ -31,7 +31,8 @@ COBJS	= 405gp_pci.o 4xx_enet.o \  	  bedbug_405.o commproc.o \  	  cpu.o cpu_init.o i2c.o interrupts.o \  	  miiphy.o ndfc.o sdram.o serial.o \ -	  spd_sdram.o speed.o traps.o usb_ohci.o usbdev.o \ +	  40x_spd_sdram.o 44x_spd_ddr.o 44x_spd_ddr2.o speed.o \ +	  tlb.o traps.o usb_ohci.o usbdev.o \  	  440spe_pcie.o  SRCS	:= $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) diff --git a/cpu/ppc4xx/cpu_init.c b/cpu/ppc4xx/cpu_init.c index ae2459108..82ae4434b 100644 --- a/cpu/ppc4xx/cpu_init.c +++ b/cpu/ppc4xx/cpu_init.c @@ -314,7 +314,7 @@ cpu_init_f (void)  #endif  #if defined (CFG_EBC_CFG) -	mtebc(epcr, CFG_EBC_CFG); +	mtebc(EBC0_CFG, CFG_EBC_CFG);  #endif  #if defined(CONFIG_WATCHDOG) diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 7db1cd804..0b056a15d 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -1,91 +1,100 @@ -/*****************************************************************************/ -/* I2C Bus interface initialisation and I2C Commands                         */ -/* for PPC405GP		                                                     */ -/* Author : AS HARNOIS                                                       */ -/* Date   : 13.Dec.00                                                        */ -/*****************************************************************************/ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * based on work by Anne Sophie Harnois <anne-sophie.harnois@nextream.fr> + * + * (C) Copyright 2001 + * Bill Hunter,  Wave 7 Optics, williamhunter@mediaone.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h> +#include <asm-ppc/io.h>  #ifdef CONFIG_HARD_I2C  DECLARE_GLOBAL_DATA_PTR; -#define IIC_OK		0 -#define IIC_NOK		1 -#define IIC_NOK_LA	2		/* Lost arbitration */ -#define IIC_NOK_ICT	3		/* Incomplete transfer */ -#define IIC_NOK_XFRA	4		/* Transfer aborted */ -#define IIC_NOK_DATA	5		/* No data in buffer */ -#define IIC_NOK_TOUT	6		/* Transfer timeout */ - -#define IIC_TIMEOUT 1			/* 1 seconde */ - +#if defined(CONFIG_I2C_MULTI_BUS) +/* Initialize the bus pointer to whatever one the SPD EEPROM is on. + * Default is bus 0.  This is necessary because the DDR initialization + * runs from ROM, and we can't switch buses because we can't modify + * the global variables. + */ +#ifdef CFG_SPD_BUS_NUM +static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = CFG_SPD_BUS_NUM; +#else +static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0; +#endif +#endif /* CONFIG_I2C_MULTI_BUS */ -static void _i2c_bus_reset (void) +static void _i2c_bus_reset(void)  { -	int i, status; +	int i; +	u8 dc;  	/* Reset status register */  	/* write 1 in SCMP and IRQA to clear these fields */ -	out8 (IIC_STS, 0x0A); +	out_8((u8 *)IIC_STS, 0x0A);  	/* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */ -	out8 (IIC_EXTSTS, 0x8F); -	__asm__ volatile ("eieio"); +	out_8((u8 *)IIC_EXTSTS, 0x8F); -	/* -	 * Get current state, reset bus -	 * only if no transfers are pending. -	 */ -	i = 10; -	do { -		/* Get status */ -		status = in8 (IIC_STS); -		udelay (500);			/* 500us */ -		i--; -	} while ((status & IIC_STS_PT) && (i > 0)); -	/* Soft reset controller */ -	status = in8 (IIC_XTCNTLSS); -	out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST)); -	__asm__ volatile ("eieio"); +    	/* Place chip in the reset state */ +	out_8((u8 *)IIC_XTCNTLSS, IIC_XTCNTLSS_SRST); -	/* make sure where in initial state, data hi, clock hi */ -	out8 (IIC_DIRECTCNTL, 0xC); -	for (i = 0; i < 10; i++) { -		if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) { -			/* clock until we get to known state */ -			out8 (IIC_DIRECTCNTL, 0x8);	/* clock lo */ -			udelay (100);		/* 100us */ -			out8 (IIC_DIRECTCNTL, 0xC);	/* clock hi */ -			udelay (100);		/* 100us */ -		} else { -			break; +	/* Check if bus is free */ +	dc = in_8((u8 *)IIC_DIRECTCNTL); +	if (!DIRCTNL_FREE(dc)){ +		/* Try to set bus free state */ +		out_8((u8 *)IIC_DIRECTCNTL, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC); + +		/* Wait until we regain bus control */ +		for (i = 0; i < 100; ++i) { +			dc = in_8((u8 *)IIC_DIRECTCNTL); +			if (DIRCTNL_FREE(dc)) +				break; + +			/* Toggle SCL line */ +			dc ^= IIC_DIRCNTL_SCC; +			out_8((u8 *)IIC_DIRECTCNTL, dc); +			udelay(10); +			dc ^= IIC_DIRCNTL_SCC; +			out_8((u8 *)IIC_DIRECTCNTL, dc);  		}  	} -	/* send start condition */ -	out8 (IIC_DIRECTCNTL, 0x4); -	udelay (1000);				/* 1ms */ -	/* send stop condition */ -	out8 (IIC_DIRECTCNTL, 0xC); -	udelay (1000);				/* 1ms */ -	/* Unreset controller */ -	out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST)); -	udelay (1000);				/* 1ms */ + +	/* Remove reset */ +	out_8((u8 *)IIC_XTCNTLSS, 0);  } -void i2c_init (int speed, int slaveadd) +void i2c_init(int speed, int slaveadd)  {  	sys_info_t sysInfo;  	unsigned long freqOPB;  	int val, divisor; +	int bus;  #ifdef CFG_I2C_INIT_BOARD  	/* call board specific i2c bus reset routine before accessing the   */ @@ -94,101 +103,100 @@ void i2c_init (int speed, int slaveadd)  	i2c_init_board();  #endif -	/* Handle possible failed I2C state */ -	/* FIXME: put this into i2c_init_board()? */ -	_i2c_bus_reset (); +	for (bus = 0; bus < CFG_MAX_I2C_BUS; bus++) { +		I2C_SET_BUS(bus); -	/* clear lo master address */ -	out8 (IIC_LMADR, 0); +		/* Handle possible failed I2C state */ +		/* FIXME: put this into i2c_init_board()? */ +		_i2c_bus_reset(); -	/* clear hi master address */ -	out8 (IIC_HMADR, 0); +		/* clear lo master address */ +		out_8((u8 *)IIC_LMADR, 0); -	/* clear lo slave address */ -	out8 (IIC_LSADR, 0); +		/* clear hi master address */ +		out_8((u8 *)IIC_HMADR, 0); -	/* clear hi slave address */ -	out8 (IIC_HSADR, 0); +		/* clear lo slave address */ +		out_8((u8 *)IIC_LSADR, 0); -	/* Clock divide Register */ -	/* get OPB frequency */ -	get_sys_info (&sysInfo); -	freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv; -	/* set divisor according to freqOPB */ -	divisor = (freqOPB - 1) / 10000000; -	if (divisor == 0) -		divisor = 1; -	out8 (IIC_CLKDIV, divisor); +		/* clear hi slave address */ +		out_8((u8 *)IIC_HSADR, 0); -	/* no interrupts */ -	out8 (IIC_INTRMSK, 0); +		/* Clock divide Register */ +		/* get OPB frequency */ +		get_sys_info(&sysInfo); +		freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv; +		/* set divisor according to freqOPB */ +		divisor = (freqOPB - 1) / 10000000; +		if (divisor == 0) +			divisor = 1; +		out_8((u8 *)IIC_CLKDIV, divisor); -	/* clear transfer count */ -	out8 (IIC_XFRCNT, 0); +		/* no interrupts */ +		out_8((u8 *)IIC_INTRMSK, 0); -	/* clear extended control & stat */ -	/* write 1 in SRC SRS SWC SWS to clear these fields */ -	out8 (IIC_XTCNTLSS, 0xF0); +		/* clear transfer count */ +		out_8((u8 *)IIC_XFRCNT, 0); -	/* Mode Control Register -	   Flush Slave/Master data buffer */ -	out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); -	__asm__ volatile ("eieio"); +		/* clear extended control & stat */ +		/* write 1 in SRC SRS SWC SWS to clear these fields */ +		out_8((u8 *)IIC_XTCNTLSS, 0xF0); +		/* Mode Control Register +		   Flush Slave/Master data buffer */ +		out_8((u8 *)IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); -	val = in8(IIC_MDCNTL); -	__asm__ volatile ("eieio"); +		val = in_8((u8 *)IIC_MDCNTL); -	/* Ignore General Call, slave transfers are ignored, -	   disable interrupts, exit unknown bus state, enable hold -	   SCL -	   100kHz normaly or FastMode for 400kHz and above -	*/ +		/* Ignore General Call, slave transfers are ignored, +		 * disable interrupts, exit unknown bus state, enable hold +		 * SCL 100kHz normaly or FastMode for 400kHz and above +		 */ -	val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; -	if( speed >= 400000 ){ -		val |= IIC_MDCNTL_FSM; -	} -	out8 (IIC_MDCNTL, val); +		val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; +		if (speed >= 400000) +			val |= IIC_MDCNTL_FSM; +		out_8((u8 *)IIC_MDCNTL, val); -	/* clear control reg */ -	out8 (IIC_CNTL, 0x00); -	__asm__ volatile ("eieio"); +		/* clear control reg */ +		out_8((u8 *)IIC_CNTL, 0x00); +	} +	/* set to SPD bus as default bus upon powerup */ +	I2C_SET_BUS(CFG_SPD_BUS_NUM);  }  /* -  This code tries to use the features of the 405GP i2c -  controller. It will transfer up to 4 bytes in one pass -  on the loop. It only does out8(lbz) to the buffer when it -  is possible to do out16(lhz) transfers. - -  cmd_type is 0 for write 1 for read. - -  addr_len can take any value from 0-255, it is only limited -  by the char, we could make it larger if needed. If it is -  0 we skip the address write cycle. - -  Typical case is a Write of an addr followd by a Read. The -  IBM FAQ does not cover this. On the last byte of the write -  we don't set the creg CHT bit, and on the first bytes of the -  read we set the RPST bit. - -  It does not support address only transfers, there must be -  a data part. If you want to write the address yourself, put -  it in the data pointer. - -  It does not support transfer to/from address 0. - -  It does not check XFRCNT. -*/ -static -int i2c_transfer(unsigned char cmd_type, -		 unsigned char chip, -		 unsigned char addr[], -		 unsigned char addr_len, -		 unsigned char data[], -		 unsigned short data_len ) + * This code tries to use the features of the 405GP i2c + * controller. It will transfer up to 4 bytes in one pass + * on the loop. It only does out_8((u8 *)lbz) to the buffer when it + * is possible to do out16(lhz) transfers. + * + * cmd_type is 0 for write 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + * + * Typical case is a Write of an addr followd by a Read. The + * IBM FAQ does not cover this. On the last byte of the write + * we don't set the creg CHT bit, and on the first bytes of the + * read we set the RPST bit. + * + * It does not support address only transfers, there must be + * a data part. If you want to write the address yourself, put + * it in the data pointer. + * + * It does not support transfer to/from address 0. + * + * It does not check XFRCNT. + */ +static int i2c_transfer(unsigned char cmd_type, +			unsigned char chip, +			unsigned char addr[], +			unsigned char addr_len, +			unsigned char data[], +			unsigned short data_len)  {  	unsigned char* ptr;  	int reading; @@ -198,97 +206,88 @@ int i2c_transfer(unsigned char cmd_type,  	int i;  	uchar creg; -	if( data == 0 || data_len == 0 ){ -		/*Don't support data transfer of no length or to address 0*/ +	if (data == 0 || data_len == 0) { +		/* Don't support data transfer of no length or to address 0 */  		printf( "i2c_transfer: bad call\n" );  		return IIC_NOK;  	} -	if( addr && addr_len ){ +	if (addr && addr_len) {  		ptr = addr;  		cnt = addr_len;  		reading = 0; -	}else{ +	} else {  		ptr = data;  		cnt = data_len;  		reading = cmd_type;  	} -	/*Clear Stop Complete Bit*/ -	out8(IIC_STS,IIC_STS_SCMP); +	/* Clear Stop Complete Bit */ +	out_8((u8 *)IIC_STS, IIC_STS_SCMP);  	/* Check init */ -	i=10; +	i = 10;  	do {  		/* Get status */ -		status = in8(IIC_STS); -		__asm__ volatile("eieio"); +		status = in_8((u8 *)IIC_STS);  		i--; -	} while ((status & IIC_STS_PT) && (i>0)); +	} while ((status & IIC_STS_PT) && (i > 0));  	if (status & IIC_STS_PT) {  		result = IIC_NOK_TOUT;  		return(result);  	} -	/*flush the Master/Slave Databuffers*/ -	out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); -	/*need to wait 4 OPB clocks? code below should take that long*/ +	/* flush the Master/Slave Databuffers */ +	out_8((u8 *)IIC_MDCNTL, ((in_8((u8 *)IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); +	/* need to wait 4 OPB clocks? code below should take that long */  	/* 7-bit adressing */ -	out8(IIC_HMADR,0); -	out8(IIC_LMADR, chip); -	__asm__ volatile("eieio"); +	out_8((u8 *)IIC_HMADR, 0); +	out_8((u8 *)IIC_LMADR, chip);  	tran = 0;  	result = IIC_OK;  	creg = 0; -	while ( tran != cnt && (result == IIC_OK)) { +	while (tran != cnt && (result == IIC_OK)) {  		int  bc,j;  		/* Control register = -		   Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, -		   Transfer is a sequence of transfers -		*/ +		 * Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, +		 * Transfer is a sequence of transfers +		 */  		creg |= IIC_CNTL_PT; -		bc = (cnt - tran) > 4 ? 4 : -			cnt - tran; -		creg |= (bc-1)<<4; -		/* if the real cmd type is write continue trans*/ -		if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) ) +		bc = (cnt - tran) > 4 ? 4 : cnt - tran; +		creg |= (bc - 1) << 4; +		/* if the real cmd type is write continue trans */ +		if ((!cmd_type && (ptr == addr)) || ((tran + bc) != cnt))  			creg |= IIC_CNTL_CHT;  		if (reading)  			creg |= IIC_CNTL_READ; -		else { -			for(j=0; j<bc; j++) { +		else +			for(j=0; j < bc; j++)  				/* Set buffer */ -				out8(IIC_MDBUF,ptr[tran+j]); -				__asm__ volatile("eieio"); -			} -		} -		out8(IIC_CNTL, creg ); -		__asm__ volatile("eieio"); +				out_8((u8 *)IIC_MDBUF, ptr[tran+j]); +		out_8((u8 *)IIC_CNTL, creg);  		/* Transfer is in progress -		   we have to wait for upto 5 bytes of data -		   1 byte chip address+r/w bit then bc bytes -		   of data. -		   udelay(10) is 1 bit time at 100khz -		   Doubled for slop. 20 is too small. -		*/ -		i=2*5*8; +		 * we have to wait for upto 5 bytes of data +		 * 1 byte chip address+r/w bit then bc bytes +		 * of data. +		 * udelay(10) is 1 bit time at 100khz +		 * Doubled for slop. 20 is too small. +		 */ +		i = 2*5*8;  		do {  			/* Get status */ -			status = in8(IIC_STS); -			__asm__ volatile("eieio"); -			udelay (10); +			status = in_8((u8 *)IIC_STS); +			udelay(10);  			i--; -		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) -			 && (i>0)); +		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i > 0));  		if (status & IIC_STS_ERR) {  			result = IIC_NOK; -			status = in8 (IIC_EXTSTS); +			status = in_8((u8 *)IIC_EXTSTS);  			/* Lost arbitration? */  			if (status & IIC_EXTSTS_LA)  				result = IIC_NOK_LA; @@ -306,34 +305,32 @@ int i2c_transfer(unsigned char cmd_type,  			/* Are there data in buffer */  			if (status & IIC_STS_MDBS) {  				/* -				  even if we have data we have to wait 4OPB clocks -				  for it to hit the front of the FIFO, after that -				  we can just read. We should check XFCNT here and -				  if the FIFO is full there is no need to wait. -				*/ -				udelay (1); -				for(j=0;j<bc;j++) { -					ptr[tran+j] = in8(IIC_MDBUF); -					__asm__ volatile("eieio"); -				} +				 * even if we have data we have to wait 4OPB clocks +				 * for it to hit the front of the FIFO, after that +				 * we can just read. We should check XFCNT here and +				 * if the FIFO is full there is no need to wait. +				 */ +				udelay(1); +				for (j=0; j<bc; j++) +					ptr[tran+j] = in_8((u8 *)IIC_MDBUF);  			} else  				result = IIC_NOK_DATA;  		}  		creg = 0; -		tran+=bc; -		if( ptr == addr && tran == cnt ) { +		tran += bc; +		if (ptr == addr && tran == cnt) {  			ptr = data;  			cnt = data_len;  			tran = 0;  			reading = cmd_type; -			if( reading ) +			if (reading)  				creg = IIC_CNTL_RPST;  		}  	}  	return (result);  } -int i2c_probe (uchar chip) +int i2c_probe(uchar chip)  {  	uchar buf[1]; @@ -344,21 +341,21 @@ int i2c_probe (uchar chip)  	 * address was <ACK>ed (i.e. there was a chip at that address which  	 * drove the data line low).  	 */ -	return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0); +	return (i2c_transfer(1, chip << 1, 0,0, buf, 1) != 0);  } -int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)  {  	uchar xaddr[4];  	int ret; -	if ( alen > 4 ) { +	if (alen > 4) {  		printf ("I2C read: addr len %d not supported\n", alen);  		return 1;  	} -	if ( alen > 0 ) { +	if (alen > 0) {  		xaddr[0] = (addr >> 24) & 0xFF;  		xaddr[1] = (addr >> 16) & 0xFF;  		xaddr[2] = (addr >> 8) & 0xFF; @@ -378,10 +375,10 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)  	 * still be one byte because the extra address bits are  	 * hidden in the chip address.  	 */ -	if( alen > 0 ) +	if (alen > 0)  		chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);  #endif -	if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) { +	if ((ret = i2c_transfer(1, chip<<1, &xaddr[4-alen], alen, buffer, len)) != 0) {  		if (gd->have_console)  			printf( "I2c read: failed %d\n", ret);  		return 1; @@ -389,16 +386,17 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)  	return 0;  } -int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len)  {  	uchar xaddr[4]; -	if ( alen > 4 ) { +	if (alen > 4) {  		printf ("I2C write: addr len %d not supported\n", alen);  		return 1;  	} -	if ( alen > 0 ) { + +	if (alen > 0) {  		xaddr[0] = (addr >> 24) & 0xFF;  		xaddr[1] = (addr >> 16) & 0xFF;  		xaddr[2] = (addr >> 8) & 0xFF; @@ -417,11 +415,11 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)  	 * still be one byte because the extra address bits are  	 * hidden in the chip address.  	 */ -	if( alen > 0 ) +	if (alen > 0)  		chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW);  #endif -	return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); +	return (i2c_transfer(0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0);  }  /*----------------------------------------------------------------------- @@ -433,7 +431,7 @@ uchar i2c_reg_read(uchar i2c_addr, uchar reg)  	i2c_read(i2c_addr, reg, 1, &buf, 1); -	return(buf); +	return (buf);  }  /*----------------------------------------------------------------------- @@ -443,4 +441,38 @@ void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)  {  	i2c_write(i2c_addr, reg, 1, &val, 1);  } + +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Functions for multiple I2C bus handling + */ +unsigned int i2c_get_bus_num(void) +{ +	return i2c_bus_num; +} + +int i2c_set_bus_num(unsigned int bus) +{ +	if (bus >= CFG_MAX_I2C_BUS) +		return -1; + +	i2c_bus_num = bus; + +	return 0; +} + +/* TODO: add 100/400k switching */ +unsigned int i2c_get_bus_speed(void) +{ +	return CFG_I2C_SPEED; +} + +int i2c_set_bus_speed(unsigned int speed) +{ +	if (speed != CFG_I2C_SPEED) +		return -1; + +	return 0; +} +#endif	/* CONFIG_I2C_MULTI_BUS */  #endif	/* CONFIG_HARD_I2C */ diff --git a/cpu/ppc4xx/speed.c b/cpu/ppc4xx/speed.c index 2d16a8342..06220c343 100644 --- a/cpu/ppc4xx/speed.c +++ b/cpu/ppc4xx/speed.c @@ -331,7 +331,7 @@ void get_sys_info (sys_info_t * sysInfo)  	unsigned long m;  	unsigned long prbdv0; -#if defined(CONFIG_440SPE) +#if defined(CONFIG_YUCCA)  	unsigned long sys_freq;  	unsigned long sys_per=0;  	unsigned long msr; @@ -348,7 +348,7 @@ void get_sys_info (sys_info_t * sysInfo)  	/*-------------------------------------------------------------------------+  	 | Calculate the system clock speed from the period.  	 +-------------------------------------------------------------------------*/ -	sys_freq=(ONE_BILLION/sys_per)*1000; +	sys_freq = (ONE_BILLION / sys_per) * 1000;  #endif  	/* Extract configured divisors */ @@ -385,17 +385,17 @@ void get_sys_info (sys_info_t * sysInfo)  		m = sysInfo->pllExtBusDiv * sysInfo->pllOpbDiv * sysInfo->pllFwdDivB;  	/* Now calculate the individual clocks */ -#if defined(CONFIG_440SPE) +#if defined(CONFIG_YUCCA)  	sysInfo->freqVCOMhz = (m * sys_freq) ;  #else -	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m>>1); +	sysInfo->freqVCOMhz = (m * CONFIG_SYS_CLK_FREQ) + (m >> 1);  #endif  	sysInfo->freqProcessor = sysInfo->freqVCOMhz/sysInfo->pllFwdDivA;  	sysInfo->freqPLB = sysInfo->freqVCOMhz/sysInfo->pllFwdDivB/prbdv0;  	sysInfo->freqOPB = sysInfo->freqPLB/sysInfo->pllOpbDiv;  	sysInfo->freqEPB = sysInfo->freqOPB/sysInfo->pllExtBusDiv; -#if defined(CONFIG_440SPE) +#if defined(CONFIG_YUCCA)  	/* Determine PCI Clock Period */  	pci_clock_per = determine_pci_clock_per();  	sysInfo->freqPCI = (ONE_BILLION/pci_clock_per) * 1000; @@ -408,7 +408,7 @@ void get_sys_info (sys_info_t * sysInfo)  #endif -#if defined(CONFIG_440SPE) +#if defined(CONFIG_YUCCA)  unsigned long determine_sysper(void)  {  	unsigned int fpga_clocking_reg; @@ -583,7 +583,6 @@ unsigned long determine_sysper(void)  	}  	return(sys_per); -  }  /*-------------------------------------------------------------------------+ diff --git a/cpu/ppc4xx/start.S b/cpu/ppc4xx/start.S index 8e000d309..a3db93ffb 100644 --- a/cpu/ppc4xx/start.S +++ b/cpu/ppc4xx/start.S @@ -1856,3 +1856,60 @@ pll_wait:  				     /* execution will continue from the poweron */  				     /* vector of 0xfffffffc */  #endif /* CONFIG_405EP */ + +#if defined(CONFIG_440) +#define function_prolog(func_name)      .text; \ +                                        .align 2; \ +                                        .globl func_name; \ +                                        func_name: +#define function_epilog(func_name)      .type func_name,@function; \ +                                        .size func_name,.-func_name + +/*----------------------------------------------------------------------------+ +| mttlb3. ++----------------------------------------------------------------------------*/ +	function_prolog(mttlb3) +	TLBWE(4,3,2) +	blr +	function_epilog(mttlb3) + +/*----------------------------------------------------------------------------+ +| mftlb3. ++----------------------------------------------------------------------------*/ +	function_prolog(mftlb3) +        TLBRE(3,3,2) +	blr +	function_epilog(mftlb3) + +/*----------------------------------------------------------------------------+ +| mttlb2. ++----------------------------------------------------------------------------*/ +	function_prolog(mttlb2) +	TLBWE(4,3,1) +	blr +	function_epilog(mttlb2) + +/*----------------------------------------------------------------------------+ +| mftlb2. ++----------------------------------------------------------------------------*/ +	function_prolog(mftlb2) +        TLBRE(3,3,1) +	blr +	function_epilog(mftlb2) + +/*----------------------------------------------------------------------------+ +| mttlb1. ++----------------------------------------------------------------------------*/ +	function_prolog(mttlb1) +	TLBWE(4,3,0) +	blr +	function_epilog(mttlb1) + +/*----------------------------------------------------------------------------+ +| mftlb1. ++----------------------------------------------------------------------------*/ +	function_prolog(mftlb1) +        TLBRE(3,3,0) +	blr +	function_epilog(mftlb1) +#endif /* CONFIG_440 */ diff --git a/cpu/ppc4xx/tlb.c b/cpu/ppc4xx/tlb.c new file mode 100644 index 000000000..8c605591b --- /dev/null +++ b/cpu/ppc4xx/tlb.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +#if defined(CONFIG_440) + +#include <ppc4xx.h> +#include <ppc440.h> +#include <asm/io.h> +#include <asm/mmu.h> + +typedef struct region { +	unsigned long base; +	unsigned long size; +	unsigned long tlb_word2_i_value; +} region_t; + +static int add_tlb_entry(unsigned long base_addr, +                         unsigned long tlb_word0_size_value, +                         unsigned long tlb_word2_i_value) +{ +	int i; +	unsigned long tlb_word0_value; +	unsigned long tlb_word1_value; +	unsigned long tlb_word2_value; + +	/* First, find the index of a TLB entry not being used */ +	for (i=0; i<PPC4XX_TLB_SIZE; i++) { +		tlb_word0_value = mftlb1(i); +		if ((tlb_word0_value & TLB_WORD0_V_MASK) == TLB_WORD0_V_DISABLE) +			break; +	} +	if (i >= PPC4XX_TLB_SIZE) +		return -1; + +	/* Second, create the TLB entry */ +	tlb_word0_value = TLB_WORD0_EPN_ENCODE(base_addr) | TLB_WORD0_V_ENABLE | +		TLB_WORD0_TS_0 | tlb_word0_size_value; +	tlb_word1_value = TLB_WORD1_RPN_ENCODE(base_addr) | TLB_WORD1_ERPN_ENCODE(0); +	tlb_word2_value = TLB_WORD2_U0_DISABLE | TLB_WORD2_U1_DISABLE | +		TLB_WORD2_U2_DISABLE | TLB_WORD2_U3_DISABLE | +		TLB_WORD2_W_DISABLE | tlb_word2_i_value | +		TLB_WORD2_M_DISABLE | TLB_WORD2_G_DISABLE | +		TLB_WORD2_E_DISABLE | TLB_WORD2_UX_ENABLE | +		TLB_WORD2_UW_ENABLE | TLB_WORD2_UR_ENABLE | +		TLB_WORD2_SX_ENABLE | TLB_WORD2_SW_ENABLE | +		TLB_WORD2_SR_ENABLE; + +	/* Wait for all memory accesses to complete */ +	sync(); + +	/* Third, add the TLB entries */ +	mttlb1(i, tlb_word0_value); +	mttlb2(i, tlb_word1_value); +	mttlb3(i, tlb_word2_value); + +	/* Execute an ISYNC instruction so that the new TLB entry takes effect */ +	asm("isync"); + +	return 0; +} + +static void program_tlb_addr(unsigned long base_addr, unsigned long mem_size, +                             unsigned long tlb_word2_i_value) +{ +	int rc; +	int tlb_i; + +	tlb_i = tlb_word2_i_value; +	while (mem_size != 0) { +		rc = 0; +		/* Add the TLB entries in to map the region. */ +		if (((base_addr & TLB_256MB_ALIGN_MASK) == base_addr) && +		    (mem_size >= TLB_256MB_SIZE)) { +			/* Add a 256MB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_256MB, tlb_i)) == 0) { +				mem_size -= TLB_256MB_SIZE; +				base_addr += TLB_256MB_SIZE; +			} +		} else if (((base_addr & TLB_16MB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_16MB_SIZE)) { +			/* Add a 16MB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_16MB, tlb_i)) == 0) { +				mem_size -= TLB_16MB_SIZE; +				base_addr += TLB_16MB_SIZE; +			} +		} else if (((base_addr & TLB_1MB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_1MB_SIZE)) { +			/* Add a 1MB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_1MB, tlb_i)) == 0) { +				mem_size -= TLB_1MB_SIZE; +				base_addr += TLB_1MB_SIZE; +			} +		} else if (((base_addr & TLB_256KB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_256KB_SIZE)) { +			/* Add a 256KB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_256KB, tlb_i)) == 0) { +				mem_size -= TLB_256KB_SIZE; +				base_addr += TLB_256KB_SIZE; +			} +		} else if (((base_addr & TLB_64KB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_64KB_SIZE)) { +			/* Add a 64KB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_64KB, tlb_i)) == 0) { +				mem_size -= TLB_64KB_SIZE; +				base_addr += TLB_64KB_SIZE; +			} +		} else if (((base_addr & TLB_16KB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_16KB_SIZE)) { +			/* Add a 16KB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_16KB, tlb_i)) == 0) { +				mem_size -= TLB_16KB_SIZE; +				base_addr += TLB_16KB_SIZE; +			} +		} else if (((base_addr & TLB_4KB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_4KB_SIZE)) { +			/* Add a 4KB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_4KB, tlb_i)) == 0) { +				mem_size -= TLB_4KB_SIZE; +				base_addr += TLB_4KB_SIZE; +			} +		} else if (((base_addr & TLB_1KB_ALIGN_MASK) == base_addr) && +			   (mem_size >= TLB_1KB_SIZE)) { +			/* Add a 1KB TLB entry */ +			if ((rc = add_tlb_entry(base_addr, TLB_WORD0_SIZE_1KB, tlb_i)) == 0) { +				mem_size -= TLB_1KB_SIZE; +				base_addr += TLB_1KB_SIZE; +			} +		} else { +			printf("ERROR: no TLB size exists for the base address 0x%0X.\n", +				base_addr); +		} + +		if (rc != 0) +			printf("ERROR: no TLB entries available for the base addr 0x%0X.\n", +				base_addr); +	} + +	return; +} + +/* + * Program one (or multiple) TLB entries for one memory region + * + * Common usage for boards with SDRAM DIMM modules to dynamically + * configure the TLB's for the SDRAM + */ +void program_tlb(u32 start, u32 size) +{ +	region_t region_array; + +	region_array.base = start; +	region_array.size = size; +	region_array.tlb_word2_i_value = TLB_WORD2_I_ENABLE;	/* disable cache (for now) */ + +	/* Call the routine to add in the tlb entries for the memory regions */ +	program_tlb_addr(region_array.base, region_array.size, +			 region_array.tlb_word2_i_value); + +	return; +} + +#endif /* CONFIG_440 */ diff --git a/dtt/adm1021.c b/dtt/adm1021.c index 14c38f0a8..9f65cfb27 100644 --- a/dtt/adm1021.c +++ b/dtt/adm1021.c @@ -144,12 +144,15 @@ dtt_init (void)  	unsigned char sensors[] = CONFIG_DTT_SENSORS;  	const char *const header = "DTT:   "; +	/* switch to correct I2C bus */ +	I2C_SET_BUS(CFG_DTT_BUS_NUM); +  	for (i = 0; i < sizeof(sensors); i++) { -	    if (_dtt_init(sensors[i]) != 0) -		printf ("%s%d FAILED INIT\n", header, i+1); -	    else -		printf ("%s%d is %i C\n", header, i+1, -		       dtt_get_temp(sensors[i])); +		if (_dtt_init(sensors[i]) != 0) +			printf ("%s%d FAILED INIT\n", header, i+1); +		else +			printf ("%s%d is %i C\n", header, i+1, +				dtt_get_temp(sensors[i]));  	}  	return (0); diff --git a/include/405gp_i2c.h b/include/405gp_i2c.h deleted file mode 100644 index 5a9a49753..000000000 --- a/include/405gp_i2c.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _405gp_i2c_h_ -#define _405gp_i2c_h_ - -#define	   I2C_REGISTERS_BASE_ADDRESS 0xEF600500 -#define    IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) -#define    IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) -#define    IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) -#define    IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) -#define    IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) -#define    IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) -#define    IIC_STS	(I2C_REGISTERS_BASE_ADDRESS+IICSTS) -#define    IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) -#define    IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) -#define    IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) -#define    IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) -#define    IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) -#define    IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) -#define    IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) -#define    IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) - -/* MDCNTL Register Bit definition */ -#define    IIC_MDCNTL_HSCL 0x01 -#define    IIC_MDCNTL_EUBS 0x02 -#define    IIC_MDCNTL_EINT 0x04 -#define    IIC_MDCNTL_ESM  0x08 -#define    IIC_MDCNTL_FSM  0x10 -#define    IIC_MDCNTL_EGC  0x20 -#define    IIC_MDCNTL_FMDB 0x40 -#define    IIC_MDCNTL_FSDB 0x80 - -/* CNTL Register Bit definition */ -#define    IIC_CNTL_PT     0x01 -#define    IIC_CNTL_READ   0x02 -#define    IIC_CNTL_CHT    0x04 -#define    IIC_CNTL_RPST   0x08 -/* bit 2/3 for Transfer count*/ -#define    IIC_CNTL_AMD    0x40 -#define    IIC_CNTL_HMT    0x80 - -/* STS Register Bit definition */ -#define    IIC_STS_PT	   0X01 -#define    IIC_STS_IRQA    0x02 -#define    IIC_STS_ERR	   0X04 -#define    IIC_STS_SCMP    0x08 -#define    IIC_STS_MDBF    0x10 -#define    IIC_STS_MDBS    0X20 -#define    IIC_STS_SLPR    0x40 -#define    IIC_STS_SSS     0x80 - -/* EXTSTS Register Bit definition */ -#define    IIC_EXTSTS_XFRA 0X01 -#define    IIC_EXTSTS_ICT  0X02 -#define    IIC_EXTSTS_LA   0X04 - -/* XTCNTLSS Register Bit definition */ -#define    IIC_XTCNTLSS_SRST  0x01 -#define    IIC_XTCNTLSS_EPI   0x02 -#define    IIC_XTCNTLSS_SDBF  0x04 -#define    IIC_XTCNTLSS_SBDD  0x08 -#define    IIC_XTCNTLSS_SWS   0x10 -#define    IIC_XTCNTLSS_SWC   0x20 -#define    IIC_XTCNTLSS_SRS   0x40 -#define    IIC_XTCNTLSS_SRC   0x80 -#endif diff --git a/include/440_i2c.h b/include/440_i2c.h deleted file mode 100644 index 0c2bf3627..000000000 --- a/include/440_i2c.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _440_i2c_h_ -#define _440_i2c_h_ - -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ -    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define    I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000700) -#else -#define    I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000400) -#endif /*CONFIG_440EP CONFIG_440GR*/ - -#define	   I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR -#define    IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) -#define    IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) -#define    IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) -#define    IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) -#define    IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) -#define    IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) -#define    IIC_STS	(I2C_REGISTERS_BASE_ADDRESS+IICSTS) -#define    IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) -#define    IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) -#define    IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) -#define    IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) -#define    IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) -#define    IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) -#define    IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) -#define    IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) - -/* MDCNTL Register Bit definition */ -#define    IIC_MDCNTL_HSCL 0x01 -#define    IIC_MDCNTL_EUBS 0x02 -#define    IIC_MDCNTL_EINT 0x04 -#define    IIC_MDCNTL_ESM  0x08 -#define    IIC_MDCNTL_FSM  0x10 -#define    IIC_MDCNTL_EGC  0x20 -#define    IIC_MDCNTL_FMDB 0x40 -#define    IIC_MDCNTL_FSDB 0x80 - -/* CNTL Register Bit definition */ -#define    IIC_CNTL_PT     0x01 -#define    IIC_CNTL_READ   0x02 -#define    IIC_CNTL_CHT    0x04 -#define    IIC_CNTL_RPST   0x08 -/* bit 2/3 for Transfer count*/ -#define    IIC_CNTL_AMD    0x40 -#define    IIC_CNTL_HMT    0x80 - -/* STS Register Bit definition */ -#define    IIC_STS_PT	   0X01 -#define    IIC_STS_IRQA    0x02 -#define    IIC_STS_ERR	   0X04 -#define    IIC_STS_SCMP    0x08 -#define    IIC_STS_MDBF    0x10 -#define    IIC_STS_MDBS    0X20 -#define    IIC_STS_SLPR    0x40 -#define    IIC_STS_SSS     0x80 - -/* EXTSTS Register Bit definition */ -#define    IIC_EXTSTS_XFRA 0X01 -#define    IIC_EXTSTS_ICT  0X02 -#define    IIC_EXTSTS_LA   0X04 - -/* XTCNTLSS Register Bit definition */ -#define    IIC_XTCNTLSS_SRST  0x01 -#define    IIC_XTCNTLSS_EPI   0x02 -#define    IIC_XTCNTLSS_SDBF  0x04 -#define    IIC_XTCNTLSS_SBDD  0x08 -#define    IIC_XTCNTLSS_SWS   0x10 -#define    IIC_XTCNTLSS_SWC   0x20 -#define    IIC_XTCNTLSS_SRS   0x40 -#define    IIC_XTCNTLSS_SRC   0x80 -#endif diff --git a/include/4xx_i2c.h b/include/4xx_i2c.h new file mode 100644 index 000000000..66b799741 --- /dev/null +++ b/include/4xx_i2c.h @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@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 + */ + +#ifndef _4xx_i2c_h_ +#define _4xx_i2c_h_ + +#define IIC_OK		0 +#define IIC_NOK		1 +#define IIC_NOK_LA	2		/* Lost arbitration */ +#define IIC_NOK_ICT	3		/* Incomplete transfer */ +#define IIC_NOK_XFRA	4		/* Transfer aborted */ +#define IIC_NOK_DATA	5		/* No data in buffer */ +#define IIC_NOK_TOUT	6		/* Transfer timeout */ + +#define IIC_TIMEOUT	1		/* 1 second */ + +#if defined(CONFIG_I2C_MULTI_BUS) +#define I2C_BUS_OFFS	(i2c_bus_num * 0x100) +#else +#define I2C_BUS_OFFS	(0x000) +#endif /* CONFIG_I2C_MULTI_BUS */ + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define I2C_BASE_ADDR	(CFG_PERIPHERAL_BASE + 0x00000700 + I2C_BUS_OFFS) +#elif defined(CONFIG_440) +/* all remaining 440 variants */ +#define I2C_BASE_ADDR	(CFG_PERIPHERAL_BASE + 0x00000400 + I2C_BUS_OFFS) +#else +/* all 405 variants */ +#define I2C_BASE_ADDR	(0xEF600500 + I2C_BUS_OFFS) +#endif + +#define I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR +#define IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) +#define IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) +#define IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) +#define IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) +#define IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) +#define IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) +#define IIC_STS		(I2C_REGISTERS_BASE_ADDRESS+IICSTS) +#define IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) +#define IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) +#define IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) +#define IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) +#define IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) +#define IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) +#define IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) +#define IIC_DIRECTCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) + +/* MDCNTL Register Bit definition */ +#define IIC_MDCNTL_HSCL		0x01 +#define IIC_MDCNTL_EUBS		0x02 +#define IIC_MDCNTL_EINT		0x04 +#define IIC_MDCNTL_ESM		0x08 +#define IIC_MDCNTL_FSM		0x10 +#define IIC_MDCNTL_EGC		0x20 +#define IIC_MDCNTL_FMDB		0x40 +#define IIC_MDCNTL_FSDB		0x80 + +/* CNTL Register Bit definition */ +#define IIC_CNTL_PT		0x01 +#define IIC_CNTL_READ		0x02 +#define IIC_CNTL_CHT		0x04 +#define IIC_CNTL_RPST		0x08 +/* bit 2/3 for Transfer count*/ +#define IIC_CNTL_AMD		0x40 +#define IIC_CNTL_HMT		0x80 + +/* STS Register Bit definition */ +#define IIC_STS_PT		0x01 +#define IIC_STS_IRQA		0x02 +#define IIC_STS_ERR		0x04 +#define IIC_STS_SCMP		0x08 +#define IIC_STS_MDBF		0x10 +#define IIC_STS_MDBS		0x20 +#define IIC_STS_SLPR		0x40 +#define IIC_STS_SSS		0x80 + +/* EXTSTS Register Bit definition */ +#define IIC_EXTSTS_XFRA		0x01 +#define IIC_EXTSTS_ICT		0x02 +#define IIC_EXTSTS_LA		0x04 + +/* XTCNTLSS Register Bit definition */ +#define IIC_XTCNTLSS_SRST	0x01 +#define IIC_XTCNTLSS_EPI	0x02 +#define IIC_XTCNTLSS_SDBF	0x04 +#define IIC_XTCNTLSS_SBDD	0x08 +#define IIC_XTCNTLSS_SWS	0x10 +#define IIC_XTCNTLSS_SWC	0x20 +#define IIC_XTCNTLSS_SRS	0x40 +#define IIC_XTCNTLSS_SRC	0x80 + +/* IICx_DIRECTCNTL register */ +#define IIC_DIRCNTL_SDAC	0x08 +#define IIC_DIRCNTL_SCC		0x04 +#define IIC_DIRCNTL_MSDA	0x02 +#define IIC_DIRCNTL_MSC		0x01 + +#define DIRCTNL_FREE(v)		(((v) & 0x0f) == 0x0f) +#endif diff --git a/include/asm-ppc/mmu.h b/include/asm-ppc/mmu.h index 914f28b46..b226825ee 100644 --- a/include/asm-ppc/mmu.h +++ b/include/asm-ppc/mmu.h @@ -335,41 +335,6 @@ extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);   * instructions.   */ -#define	TLB_LO          1 -#define	TLB_HI          0 - -#define	TLB_DATA        TLB_LO -#define	TLB_TAG         TLB_HI - -/* Tag portion */ - -#define TLB_EPN_MASK    0xFFFFFC00      /* Effective Page Number */ -#define TLB_PAGESZ_MASK 0x00000380 -#define TLB_PAGESZ(x)   (((x) & 0x7) << 7) -#define   PAGESZ_1K		0 -#define   PAGESZ_4K             1 -#define   PAGESZ_16K            2 -#define   PAGESZ_64K            3 -#define   PAGESZ_256K           4 -#define   PAGESZ_1M             5 -#define   PAGESZ_4M             6 -#define   PAGESZ_16M            7 -#define TLB_VALID       0x00000040      /* Entry is valid */ - -/* Data portion */ - -#define TLB_RPN_MASK    0xFFFFFC00      /* Real Page Number */ -#define TLB_PERM_MASK   0x00000300 -#define TLB_EX          0x00000200      /* Instruction execution allowed */ -#define TLB_WR          0x00000100      /* Writes permitted */ -#define TLB_ZSEL_MASK   0x000000F0 -#define TLB_ZSEL(x)     (((x) & 0xF) << 4) -#define TLB_ATTR_MASK   0x0000000F -#define TLB_W           0x00000008      /* Caching is write-through */ -#define TLB_I           0x00000004      /* Caching is inhibited */ -#define TLB_M           0x00000002      /* Memory is coherent */ -#define TLB_G           0x00000001      /* Memory is guarded from prefetch */ -  /*   * e500 support   */ @@ -482,7 +447,162 @@ extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);  #define LAWAR_SIZE_16G		(LAWAR_SIZE_BASE+23)  #define LAWAR_SIZE_32G		(LAWAR_SIZE_BASE+24) -#ifdef CONFIG_440SPE +#ifdef CONFIG_440 +/* General */ +#define TLB_VALID   0x00000200 + +/* Supported page sizes */ + +#define SZ_1K	0x00000000 +#define SZ_4K	0x00000010 +#define SZ_16K	0x00000020 +#define SZ_64K	0x00000030 +#define SZ_256K	0x00000040 +#define SZ_1M	0x00000050 +#define SZ_16M	0x00000070 +#define SZ_256M	0x00000090 + +/* Storage attributes */ +#define SA_W	0x00000800	/* Write-through */ +#define SA_I	0x00000400	/* Caching inhibited */ +#define SA_M	0x00000200	/* Memory coherence */ +#define SA_G	0x00000100	/* Guarded */ +#define SA_E	0x00000080	/* Endian */ + +/* Access control */ +#define AC_X	0x00000024	/* Execute */ +#define AC_W	0x00000012	/* Write */ +#define AC_R	0x00000009	/* Read */ + +/* Some handy macros */ + +#define EPN(e)		((e) & 0xfffffc00) +#define TLB0(epn,sz)	((EPN((epn)) | (sz) | TLB_VALID )) +#define TLB1(rpn,erpn)	(((rpn) & 0xfffffc00) | (erpn)) +#define TLB2(a)		((a) & 0x00000fbf) + +#define tlbtab_start\ +	mflr	r1	;\ +	bl	0f	; + +#define tlbtab_end\ +	.long 0, 0, 0	;\ +0:	mflr	r0	;\ +	mtlr	r1	;\ +	blr		; + +#define tlbentry(epn,sz,rpn,erpn,attr)\ +	.long TLB0(epn,sz),TLB1(rpn,erpn),TLB2(attr) + +/*----------------------------------------------------------------------------+ +| TLB specific defines. ++----------------------------------------------------------------------------*/ +#define TLB_256MB_ALIGN_MASK 0xF0000000 +#define TLB_16MB_ALIGN_MASK  0xFF000000 +#define TLB_1MB_ALIGN_MASK   0xFFF00000 +#define TLB_256KB_ALIGN_MASK 0xFFFC0000 +#define TLB_64KB_ALIGN_MASK  0xFFFF0000 +#define TLB_16KB_ALIGN_MASK  0xFFFFC000 +#define TLB_4KB_ALIGN_MASK   0xFFFFF000 +#define TLB_1KB_ALIGN_MASK   0xFFFFFC00 +#define TLB_256MB_SIZE       0x10000000 +#define TLB_16MB_SIZE        0x01000000 +#define TLB_1MB_SIZE         0x00100000 +#define TLB_256KB_SIZE       0x00040000 +#define TLB_64KB_SIZE        0x00010000 +#define TLB_16KB_SIZE        0x00004000 +#define TLB_4KB_SIZE         0x00001000 +#define TLB_1KB_SIZE         0x00000400 + +#define TLB_WORD0_EPN_MASK   0xFFFFFC00 +#define TLB_WORD0_EPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00) +#define TLB_WORD0_EPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00) +#define TLB_WORD0_V_MASK     0x00000200 +#define TLB_WORD0_V_ENABLE   0x00000200 +#define TLB_WORD0_V_DISABLE  0x00000000 +#define TLB_WORD0_TS_MASK    0x00000100 +#define TLB_WORD0_TS_1       0x00000100 +#define TLB_WORD0_TS_0       0x00000000 +#define TLB_WORD0_SIZE_MASK  0x000000F0 +#define TLB_WORD0_SIZE_1KB   0x00000000 +#define TLB_WORD0_SIZE_4KB   0x00000010 +#define TLB_WORD0_SIZE_16KB  0x00000020 +#define TLB_WORD0_SIZE_64KB  0x00000030 +#define TLB_WORD0_SIZE_256KB 0x00000040 +#define TLB_WORD0_SIZE_1MB   0x00000050 +#define TLB_WORD0_SIZE_16MB  0x00000070 +#define TLB_WORD0_SIZE_256MB 0x00000090 +#define TLB_WORD0_TPAR_MASK  0x0000000F +#define TLB_WORD0_TPAR_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0) +#define TLB_WORD0_TPAR_DECODE(n) ((((unsigned long)(n))>>0)&0x0F) + +#define TLB_WORD1_RPN_MASK   0xFFFFFC00 +#define TLB_WORD1_RPN_ENCODE(n) (((unsigned long)(n))&0xFFFFFC00) +#define TLB_WORD1_RPN_DECODE(n) (((unsigned long)(n))&0xFFFFFC00) +#define TLB_WORD1_PAR1_MASK  0x00000300 +#define TLB_WORD1_PAR1_ENCODE(n) ((((unsigned long)(n))&0x03)<<8) +#define TLB_WORD1_PAR1_DECODE(n) ((((unsigned long)(n))>>8)&0x03) +#define TLB_WORD1_PAR1_0     0x00000000 +#define TLB_WORD1_PAR1_1     0x00000100 +#define TLB_WORD1_PAR1_2     0x00000200 +#define TLB_WORD1_PAR1_3     0x00000300 +#define TLB_WORD1_ERPN_MASK  0x0000000F +#define TLB_WORD1_ERPN_ENCODE(n) ((((unsigned long)(n))&0x0F)<<0) +#define TLB_WORD1_ERPN_DECODE(n) ((((unsigned long)(n))>>0)&0x0F) + +#define TLB_WORD2_PAR2_MASK  0xC0000000 +#define TLB_WORD2_PAR2_ENCODE(n) ((((unsigned long)(n))&0x03)<<30) +#define TLB_WORD2_PAR2_DECODE(n) ((((unsigned long)(n))>>30)&0x03) +#define TLB_WORD2_PAR2_0     0x00000000 +#define TLB_WORD2_PAR2_1     0x40000000 +#define TLB_WORD2_PAR2_2     0x80000000 +#define TLB_WORD2_PAR2_3     0xC0000000 +#define TLB_WORD2_U0_MASK    0x00008000 +#define TLB_WORD2_U0_ENABLE  0x00008000 +#define TLB_WORD2_U0_DISABLE 0x00000000 +#define TLB_WORD2_U1_MASK    0x00004000 +#define TLB_WORD2_U1_ENABLE  0x00004000 +#define TLB_WORD2_U1_DISABLE 0x00000000 +#define TLB_WORD2_U2_MASK    0x00002000 +#define TLB_WORD2_U2_ENABLE  0x00002000 +#define TLB_WORD2_U2_DISABLE 0x00000000 +#define TLB_WORD2_U3_MASK    0x00001000 +#define TLB_WORD2_U3_ENABLE  0x00001000 +#define TLB_WORD2_U3_DISABLE 0x00000000 +#define TLB_WORD2_W_MASK     0x00000800 +#define TLB_WORD2_W_ENABLE   0x00000800 +#define TLB_WORD2_W_DISABLE  0x00000000 +#define TLB_WORD2_I_MASK     0x00000400 +#define TLB_WORD2_I_ENABLE   0x00000400 +#define TLB_WORD2_I_DISABLE  0x00000000 +#define TLB_WORD2_M_MASK     0x00000200 +#define TLB_WORD2_M_ENABLE   0x00000200 +#define TLB_WORD2_M_DISABLE  0x00000000 +#define TLB_WORD2_G_MASK     0x00000100 +#define TLB_WORD2_G_ENABLE   0x00000100 +#define TLB_WORD2_G_DISABLE  0x00000000 +#define TLB_WORD2_E_MASK     0x00000080 +#define TLB_WORD2_E_ENABLE   0x00000080 +#define TLB_WORD2_E_DISABLE  0x00000000 +#define TLB_WORD2_UX_MASK    0x00000020 +#define TLB_WORD2_UX_ENABLE  0x00000020 +#define TLB_WORD2_UX_DISABLE 0x00000000 +#define TLB_WORD2_UW_MASK    0x00000010 +#define TLB_WORD2_UW_ENABLE  0x00000010 +#define TLB_WORD2_UW_DISABLE 0x00000000 +#define TLB_WORD2_UR_MASK    0x00000008 +#define TLB_WORD2_UR_ENABLE  0x00000008 +#define TLB_WORD2_UR_DISABLE 0x00000000 +#define TLB_WORD2_SX_MASK    0x00000004 +#define TLB_WORD2_SX_ENABLE  0x00000004 +#define TLB_WORD2_SX_DISABLE 0x00000000 +#define TLB_WORD2_SW_MASK    0x00000002 +#define TLB_WORD2_SW_ENABLE  0x00000002 +#define TLB_WORD2_SW_DISABLE 0x00000000 +#define TLB_WORD2_SR_MASK    0x00000001 +#define TLB_WORD2_SR_ENABLE  0x00000001 +#define TLB_WORD2_SR_DISABLE 0x00000000 +  /*----------------------------------------------------------------------------+  | Following instructions are not available in Book E mode of the GNU assembler.  +----------------------------------------------------------------------------*/ @@ -516,11 +636,15 @@ extern int write_bat(ppc_bat_t bat, unsigned long upper, unsigned long lower);  #define MBAR_INST 				.long 0x7c000000|\  					(854<<1) -/*----------------------------------------------------------------------------+ -| Following instruction is not available in PPC405 mode of the GNU assembler. -+----------------------------------------------------------------------------*/ -#define TLBRE(rt,ra,ws)			.long 0x7c000000|\ -					(rt<<21)|(ra<<16)|(ws<<11)|(946<<1) +#ifndef __ASSEMBLY__ +/* Prototypes */ +void mttlb1(unsigned long index, unsigned long value); +void mttlb2(unsigned long index, unsigned long value); +void mttlb3(unsigned long index, unsigned long value); +unsigned long mftlb1(unsigned long index); +unsigned long mftlb2(unsigned long index); +unsigned long mftlb3(unsigned long index); +#endif /* __ASSEMBLY__ */ -#endif +#endif /* CONFIG_440 */  #endif /* _PPC_MMU_H_ */ diff --git a/include/configs/katmai.h b/include/configs/katmai.h new file mode 100644 index 000000000..c750e1465 --- /dev/null +++ b/include/configs/katmai.h @@ -0,0 +1,415 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * (C) Copyright 2004 Paul Reynolds <PaulReynolds@lhsolutions.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 + */ + +/************************************************************************ + * katmai.h - configuration for AMCC Katmai (440SPe) + ***********************************************************************/ + +#ifndef __CONFIG_H +#define __CONFIG_H + +/*----------------------------------------------------------------------- + * High Level Configuration Options + *----------------------------------------------------------------------*/ +#define CONFIG_KATMAI			1	/* Board is Katmai	*/ +#define CONFIG_4xx			1	/* ... PPC4xx family	*/ +#define CONFIG_440			1	/* ... PPC440 family	*/ +#define CONFIG_440SPE			1	/* Specifc SPe support	*/ +#undef	CFG_DRAM_TEST				/* Disable-takes long time */ +#define CONFIG_SYS_CLK_FREQ	33333333	/* external freq to pll	*/ + +#define CONFIG_BOARD_EARLY_INIT_F 1	/* Call board_pre_init		*/ +#define	CONFIG_MISC_INIT_F	1	/* Use misc_init_f()		*/ +#define CONFIG_ADD_RAM_INFO	1	/* Print additional info	*/ +#undef  CONFIG_SHOW_BOOT_PROGRESS + +/*----------------------------------------------------------------------- + * Base addresses -- Note these are effective addresses where the + * actual resources get mapped (not physical addresses) + *----------------------------------------------------------------------*/ +#define CFG_MONITOR_LEN		(256 * 1024)	/* Reserve 256 kB for Mon */ +#define CFG_MALLOC_LEN		(512 * 1024)	/* Reserve 512 kB for malloc */ + +#define CFG_SDRAM_BASE		0x00000000	/* _must_ be 0		*/ +#define CFG_FLASH_BASE		0xff000000	/* start of FLASH	*/ +#define CFG_MONITOR_BASE	TEXT_BASE +#define CFG_PERIPHERAL_BASE	0xa0000000	/* internal peripherals	*/ +#define CFG_ISRAM_BASE		0x90000000	/* internal SRAM	*/ + +#define CFG_PCI_MEMBASE		0x80000000	/* mapped PCI memory	*/ +#define CFG_PCI_BASE		0xd0000000	/* internal PCI regs	*/ +#define CFG_PCI_TARGBASE	CFG_PCI_MEMBASE + +#define CFG_PCIE_MEMBASE	0xb0000000	/* mapped PCIe memory	*/ +#define CFG_PCIE_MEMSIZE	0x01000000 +#define CFG_PCIE_BASE		0xe0000000	/* PCIe UTL regs */ + +#define CFG_PCIE0_CFGBASE	0xc0000000 +#define CFG_PCIE0_XCFGBASE	0xc0000400 +#define CFG_PCIE1_CFGBASE	0xc0001000 +#define CFG_PCIE1_XCFGBASE	0xc0001400 +#define CFG_PCIE2_CFGBASE	0xc0002000 +#define CFG_PCIE2_XCFGBASE	0xc0002400 + +/* System RAM mapped to PCI space */ +#define CONFIG_PCI_SYS_MEM_BUS	CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_PHYS	CFG_SDRAM_BASE +#define CONFIG_PCI_SYS_MEM_SIZE	(1024 * 1024 * 1024) + +#define CFG_ACE_BASE		0xe0000000	/* Xilinx ACE controller - Compact Flash */ + +/*----------------------------------------------------------------------- + * Initial RAM & stack pointer (placed in internal SRAM) + *----------------------------------------------------------------------*/ +#define CFG_TEMP_STACK_OCM	1 +#define CFG_OCM_DATA_ADDR	CFG_ISRAM_BASE +#define CFG_INIT_RAM_ADDR	CFG_ISRAM_BASE	/* Initial RAM address	*/ +#define CFG_INIT_RAM_END	0x2000		/* End of used area in RAM */ +#define CFG_GBL_DATA_SIZE	128		/* num bytes initial data */ + +#define CFG_GBL_DATA_OFFSET	(CFG_INIT_RAM_END - CFG_GBL_DATA_SIZE) +#define CFG_POST_WORD_ADDR	(CFG_GBL_DATA_OFFSET - 0x4) +#define CFG_INIT_SP_OFFSET	CFG_POST_WORD_ADDR + +/*----------------------------------------------------------------------- + * Serial Port + *----------------------------------------------------------------------*/ +#define CONFIG_SERIAL_MULTI	1 +#undef CONFIG_UART1_CONSOLE +#undef CFG_EXT_SERIAL_CLOCK +#define CONFIG_BAUDRATE		115200 +#define CFG_BAUDRATE_TABLE  \ +	{300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200} + +/*----------------------------------------------------------------------- + * DDR SDRAM + *----------------------------------------------------------------------*/ +#define CONFIG_SPD_EEPROM	1	/* Use SPD EEPROM for setup	*/ +#define SPD_EEPROM_ADDRESS {0x51, 0x52}	/* SPD i2c spd addresses	*/ +#define IIC0_DIMM0_ADDR		0x51 +#define IIC0_DIMM1_ADDR		0x52 +#undef  CONFIG_STRESS +#undef  ENABLE_ECC + +/*----------------------------------------------------------------------- + * I2C + *----------------------------------------------------------------------*/ +#define CONFIG_HARD_I2C		1	/* I2C with hardware support	*/ +#undef	CONFIG_SOFT_I2C			/* I2C bit-banged		*/ +#define CFG_I2C_SPEED		100000	/* I2C speed and slave address	*/ +#define CFG_I2C_SLAVE		0x7F + +#define CONFIG_I2C_MULTI_BUS +#define CONFIG_I2C_CMD_TREE +#define CFG_SPD_BUS_NUM		0	/* The I2C bus for SPD		*/ + +#define IIC0_BOOTPROM_ADDR	0x50 +#define IIC0_ALT_BOOTPROM_ADDR	0x54 + +#define CFG_I2C_MULTI_EEPROMS +#define CFG_I2C_EEPROM_ADDR	(0x50) +#define CFG_I2C_EEPROM_ADDR_LEN 1 +#define CFG_EEPROM_PAGE_WRITE_ENABLE +#define CFG_EEPROM_PAGE_WRITE_BITS 3 +#define CFG_EEPROM_PAGE_WRITE_DELAY_MS 10 + +/* I2C RTC */ +#define CONFIG_RTC_M41T11	1 +#define CFG_RTC_BUS_NUM		1	/* The I2C bus for RTC		*/ +#define CFG_I2C_RTC_ADDR	0x68 +#define CFG_M41T11_BASE_YEAR	1900	/* play along with linux	*/ + +/* I2C DTT */ +#define CONFIG_DTT_ADM1021	1	/* ADM1021 temp sensor support	*/ +#define CFG_DTT_BUS_NUM		1	/* The I2C bus for DTT		*/ +/* + * standard dtt sensor configuration - bottom bit will determine local or + * remote sensor of the ADM1021, the rest determines index into + * CFG_DTT_ADM1021 array below. + */ +#define CONFIG_DTT_SENSORS	{ 0, 1 } + +/* + * ADM1021 temp sensor configuration (see dtt/adm1021.c for details). + * there will be one entry in this array for each two (dummy) sensors in + * CONFIG_DTT_SENSORS. + * + * For Katmai board: + * - only one ADM1021 + * - i2c addr 0x18 + * - conversion rate 0x02 = 0.25 conversions/second + * - ALERT ouput disabled + * - local temp sensor enabled, min set to 0 deg, max set to 85 deg + * - remote temp sensor enabled, min set to 0 deg, max set to 85 deg + */ +#define CFG_DTT_ADM1021		{ { 0x18, 0x02, 0, 1, 0, 85, 1, 0, 58} } + +/*----------------------------------------------------------------------- + * Environment + *----------------------------------------------------------------------*/ +#define	CFG_ENV_IS_IN_FLASH	1	/* Environment uses flash	*/ + +#define CONFIG_PREBOOT	"echo;"	\ +	"echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ +	"echo" + +#undef	CONFIG_BOOTARGS + +#define	CONFIG_EXTRA_ENV_SETTINGS					\ +	"netdev=eth0\0"							\ +	"hostname=katmai\0"						\ +	"nfsargs=setenv bootargs root=/dev/nfs rw "			\ +		"nfsroot=${serverip}:${rootpath}\0"			\ +	"ramargs=setenv bootargs root=/dev/ram rw\0"			\ +	"addip=setenv bootargs ${bootargs} "				\ +		"ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}"	\ +		":${hostname}:${netdev}:off panic=1\0"			\ +	"addtty=setenv bootargs ${bootargs} console=ttyS0,${baudrate}\0"\ +	"flash_nfs=run nfsargs addip addtty;"				\ +		"bootm ${kernel_addr}\0"				\ +	"flash_self=run ramargs addip addtty;"				\ +		"bootm ${kernel_addr} ${ramdisk_addr}\0"		\ +	"net_nfs=tftp 200000 ${bootfile};run nfsargs addip addtty;"     \ +		"bootm\0"						\ +	"rootpath=/opt/eldk/ppc_4xx\0"				\ +	"bootfile=katmai/uImage\0"					\ +	"kernel_addr=fff10000\0"					\ +	"ramdisk_addr=fff20000\0"					\ +	"initrd_high=30000000\0"					\ +	"load=tftp 200000 katmai/u-boot.bin\0"				\ +	"update=protect off fffc0000 ffffffff;era fffc0000 ffffffff;"	\ +		"cp.b ${fileaddr} fffc0000 ${filesize};"		\ +		"setenv filesize;saveenv\0"				\ +	"upd=run load;run update\0"					\ +	"kozio=bootm ffc60000\0"					\ +	"" +#define CONFIG_BOOTCOMMAND	"run flash_self" + +#define CONFIG_BOOTDELAY	5	/* autoboot after 5 seconds	*/ + +#define CONFIG_LOADS_ECHO	1	/* echo on for serial download	*/ +#define CFG_LOADS_BAUD_CHANGE	1	/* allow baudrate change	*/ + +#define CONFIG_COMMANDS	       (CONFIG_CMD_DFL	| \ +				CFG_CMD_ASKENV	| \ +				CFG_CMD_EEPROM	| \ +				CFG_CMD_DATE	| \ +				CFG_CMD_DHCP	| \ +				CFG_CMD_DIAG	| \ +				CFG_CMD_DTT	| \ +				CFG_CMD_ELF	| \ +				CFG_CMD_EXT2	| \ +				CFG_CMD_FAT	| \ +				CFG_CMD_I2C	| \ +				CFG_CMD_IRQ	| \ +				CFG_CMD_MII	| \ +				CFG_CMD_NET	| \ +				CFG_CMD_NFS	| \ +				CFG_CMD_PCI	| \ +				CFG_CMD_PING	| \ +				CFG_CMD_REGINFO	| \ +				CFG_CMD_SDRAM) + +/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */ +#include <cmd_confdefs.h> + +#define	CONFIG_IBM_EMAC4_V4	1	/* 440SPe has this EMAC version	*/ +#define CONFIG_MII		1	/* MII PHY management		*/ +#define CONFIG_PHY_ADDR		1	/* PHY address, See schematics	*/ +#define CONFIG_HAS_ETH0 +#define CONFIG_PHY_RESET        1	/* reset phy upon startup	*/ +#define CONFIG_PHY_RESET_DELAY	1000 +#define CONFIG_CIS8201_PHY	1	/* Enable 'special' RGMII mode for Cicada phy */ +#define CONFIG_PHY_GIGE		1	/* Include GbE speed/duplex detection */ +#define CFG_RX_ETH_BUFFER	32	/* Number of ethernet rx buffers & descriptors */ + +#define CONFIG_NETCONSOLE		/* include NetConsole support	*/ +#define CONFIG_NET_MULTI		/* needed for NetConsole	*/ + +#undef CONFIG_WATCHDOG			/* watchdog disabled		*/ + +/* + * Miscellaneous configurable options + */ +#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	*/ +#else +#define CFG_CBSIZE		256		/* Console I/O Buffer Size	*/ +#endif +#define CFG_PBSIZE		(CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS		16		/* max number of command args	*/ +#define CFG_BARGSIZE		CFG_CBSIZE	/* Boot Argument Buffer Size	*/ + +#define CFG_MEMTEST_START	0x0400000	/* memtest works on		*/ +#define CFG_MEMTEST_END		0x0C00000	/* 4 ... 12 MB in DRAM		*/ + +#define CFG_LOAD_ADDR		0x100000	/* default load address		*/ +#define CFG_EXTBDINFO		1		/* To use extended board_into (bd_t) */ + +#define CFG_HZ			1000		/* decrementer freq: 1 ms ticks */ + +#define CONFIG_CMDLINE_EDITING	1	/* add command line history	*/ +#define CONFIG_LOOPW            1       /* enable loopw command         */ +#define CONFIG_MX_CYCLIC        1       /* enable mdc/mwc commands      */ +#define CONFIG_ZERO_BOOTDELAY_CHECK	/* check for keypress on bootdelay==0 */ +#define CONFIG_VERSION_VARIABLE 1	/* include version env variable */ + +#define CFG_4xx_RESET_TYPE	0x2	/* use chip reset on this board	*/ + +/*----------------------------------------------------------------------- + * FLASH related + *----------------------------------------------------------------------*/ +#define CFG_FLASH_CFI +#define CFG_FLASH_CFI_DRIVER +#define CFG_FLASH_EMPTY_INFO		/* print 'E' for empty sector on flinfo */ +#define CFG_FLASH_USE_BUFFER_WRITE 1	/* use buffered writes (20x faster)	*/ + +#define CFG_FLASH_BANKS_LIST    {CFG_FLASH_BASE} +#define CFG_MAX_FLASH_BANKS     1		    /* number of banks	    */ +#define CFG_MAX_FLASH_SECT	1024		    /* sectors per device   */ + +#undef	CFG_FLASH_CHECKSUM +#define CFG_FLASH_ERASE_TOUT	120000	/* Timeout for Flash Erase (in ms)	*/ +#define CFG_FLASH_WRITE_TOUT	500	/* Timeout for Flash Write (in ms)	*/ + +#define CFG_ENV_SECT_SIZE	0x20000 /* size of one complete sector	*/ +#define CFG_ENV_ADDR		(CFG_MONITOR_BASE-CFG_ENV_SECT_SIZE) +#define	CFG_ENV_SIZE		0x4000	/* Total Size of Environment Sector	*/ + +/* Address and size of Redundant Environment Sector	*/ +#define CFG_ENV_ADDR_REDUND	(CFG_ENV_ADDR-CFG_ENV_SECT_SIZE) +#define CFG_ENV_SIZE_REDUND	(CFG_ENV_SIZE) + +/*----------------------------------------------------------------------- + * PCI stuff + *----------------------------------------------------------------------- + */ +/* General PCI */ +#define CONFIG_PCI			/* include pci support		*/ +#define CONFIG_PCI_PNP		1	/* do pci plug-and-play		*/ +#define CONFIG_PCI_SCAN_SHOW	1	/* show pci devices on startup	*/ +#undef CONFIG_PCI_CONFIG_HOST_BRIDGE + +/* Board-specific PCI */ +#define CFG_PCI_PRE_INIT	1	/* enable board pci_pre_init()	*/ +#define CFG_PCI_TARGET_INIT		/* let board init pci target    */ +#undef	CFG_PCI_MASTER_INIT + +#define CFG_PCI_SUBSYS_VENDORID 0x1014	/* IBM				*/ +#define CFG_PCI_SUBSYS_DEVICEID 0xcafe	/* Whatever			*/ +/* #define CFG_PCI_SUBSYS_ID	CFG_PCI_SUBSYS_DEVICEID */ + +/* + *  NETWORK Support (PCI): + */ +/* Support for Intel 82557/82559/82559ER chips. */ +#define CONFIG_EEPRO100 + +/*----------------------------------------------------------------------- + * Xilinx System ACE support + *----------------------------------------------------------------------*/ +#define CONFIG_SYSTEMACE	1	/* Enable SystemACE support	*/ +#define CFG_SYSTEMACE_WIDTH	16	/* Data bus width is 16		*/ +#define CFG_SYSTEMACE_BASE	CFG_ACE_BASE +#define CONFIG_DOS_PARTITION	1 + +/*----------------------------------------------------------------------- + * External Bus Controller (EBC) Setup + *----------------------------------------------------------------------*/ + +/* Memory Bank 0 (Flash) initialization					*/ +#define CFG_EBC_PB0AP		(EBC_BXAP_BME_DISABLED      |		\ +				 EBC_BXAP_TWT_ENCODE(7)     |		\ +				 EBC_BXAP_BCE_DISABLE       |		\ +				 EBC_BXAP_BCT_2TRANS        |		\ +				 EBC_BXAP_CSN_ENCODE(0)     |		\ +				 EBC_BXAP_OEN_ENCODE(0)     |		\ +				 EBC_BXAP_WBN_ENCODE(0)     |		\ +				 EBC_BXAP_WBF_ENCODE(0)     |		\ +				 EBC_BXAP_TH_ENCODE(0)      |		\ +				 EBC_BXAP_RE_DISABLED       |		\ +				 EBC_BXAP_SOR_DELAYED       |		\ +				 EBC_BXAP_BEM_WRITEONLY     |		\ +				 EBC_BXAP_PEN_DISABLED) +#define CFG_EBC_PB0CR		(EBC_BXCR_BAS_ENCODE(CFG_FLASH_BASE) |	\ +				 EBC_BXCR_BS_16MB                    |	\ +				 EBC_BXCR_BU_RW                      |	\ +				 EBC_BXCR_BW_16BIT) + +/* Memory Bank 1 (Xilinx System ACE controller) initialization		*/ +#define CFG_EBC_PB1AP		0x7F8FFE80 +#define CFG_EBC_PB1CR		(EBC_BXCR_BAS_ENCODE(CFG_ACE_BASE)  |	\ +				 EBC_BXCR_BS_1MB                    |	\ +				 EBC_BXCR_BU_RW                     |	\ +				 EBC_BXCR_BW_16BIT) + +/*------------------------------------------------------------------------- + * Initialize EBC CONFIG - + * Keep the Default value, but the bit PDT which has to be set to 1 ?TBC + * default value : 0x07C00000 - 0 0 000 1 1 1 1 1 0000 0 00000 000000000000 + *-------------------------------------------------------------------------*/ +#define CFG_EBC_CFG		(EBC_CFG_LE_UNLOCK    |	\ +				 EBC_CFG_PTD_ENABLE   |	\ +				 EBC_CFG_RTC_16PERCLK | \ +				 EBC_CFG_ATC_PREVIOUS | \ +				 EBC_CFG_DTC_PREVIOUS | \ +				 EBC_CFG_CTC_PREVIOUS | \ +				 EBC_CFG_OEO_PREVIOUS | \ +				 EBC_CFG_EMC_DEFAULT  |	\ +				 EBC_CFG_PME_DISABLE  |	\ +				 EBC_CFG_PR_16) + +/* + * 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*/ +/*----------------------------------------------------------------------- + * Cache Configuration + */ +#define CFG_DCACHE_SIZE		8192	/* For AMCC 405 CPUs		*/ +#define CFG_CACHELINE_SIZE	32	/* ...				*/ +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CFG_CACHELINE_SHIFT	5	/* log base 2 of the above value */ +#endif + +/* + * Internal Definitions + * + * Boot Flags + */ +#define BOOTFLAG_COLD	0x01		/* Normal Power-On: Boot from FLASH */ +#define BOOTFLAG_WARM	0x02		/* Software reboot */ + +#if (CONFIG_COMMANDS & CFG_CMD_KGDB) +#define CONFIG_KGDB_BAUDRATE	230400	/* speed to run kgdb serial port */ +#define CONFIG_KGDB_SER_INDEX	2	/* which serial port to use */ +#endif + +#endif	/* __CONFIG_H */ diff --git a/include/i2c.h b/include/i2c.h index a8f729afe..54c6f9fbc 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -46,6 +46,16 @@   */  #define I2C_RXTX_LEN	128	/* maximum tx/rx buffer length */ +#if defined(CONFIG_I2C_MULTI_BUS) +#define CFG_MAX_I2C_BUS		2 +#define I2C_GET_BUS()		i2c_get_bus_num() +#define I2C_SET_BUS(a)		i2c_set_bus_num(a) +#else +#define CFG_MAX_I2C_BUS		1 +#define I2C_GET_BUS()		0 +#define I2C_SET_BUS(a) +#endif +  /*   * Initialization, must be called once on start up, may be called   * repeatedly to change the speed and slave addresses. diff --git a/include/ppc405.h b/include/ppc405.h index e475fa54c..a49912cab 100644 --- a/include/ppc405.h +++ b/include/ppc405.h @@ -240,6 +240,7 @@    #define pbesr0      0x21    /* periph bus error status reg 0       */    #define pbesr1      0x22    /* periph bus error status reg 1       */    #define epcr        0x23    /* external periph control reg         */ +#define EBC0_CFG	0x23	/* external bus configuration reg	*/  #ifdef CONFIG_405EP  /****************************************************************************** diff --git a/include/ppc440.h b/include/ppc440.h index 91cff414a..c24f5b7ab 100644 --- a/include/ppc440.h +++ b/include/ppc440.h @@ -533,9 +533,12 @@  #define SDRAM_MCSTAT_MIC_MASK		0x80000000	/* Memory init status mask	*/  #define SDRAM_MCSTAT_MIC_NOTCOMP	0x00000000	/* Mem init not complete	*/  #define SDRAM_MCSTAT_MIC_COMP		0x80000000	/* Mem init complete		*/ -#define SDRAM_MCSTAT_SRMS_MASK		0x80000000	/* Mem self refresh stat mask	*/ +#define SDRAM_MCSTAT_SRMS_MASK		0x40000000	/* Mem self refresh stat mask	*/  #define SDRAM_MCSTAT_SRMS_NOT_SF	0x00000000	/* Mem not in self refresh	*/ -#define SDRAM_MCSTAT_SRMS_SF		0x80000000	/* Mem in self refresh		*/ +#define SDRAM_MCSTAT_SRMS_SF		0x40000000	/* Mem in self refresh		*/ +#define SDRAM_MCSTAT_IDLE_MASK		0x20000000	/* Mem self refresh stat mask	*/ +#define SDRAM_MCSTAT_IDLE_NOT		0x00000000	/* Mem contr not idle		*/ +#define SDRAM_MCSTAT_IDLE		0x20000000	/* Mem contr idle		*/  /*-----------------------------------------------------------------------------+  |  Memory Controller Options 1 @@ -730,6 +733,7 @@  #define SDRAM_WRDTR_LLWP_1_CYC		0x00000000  #define SDRAM_WRDTR_WTR_MASK		0x0E000000  #define SDRAM_WRDTR_WTR_0_DEG		0x06000000 +#define SDRAM_WRDTR_WTR_90_DEG_ADV	0x04000000  #define SDRAM_WRDTR_WTR_180_DEG_ADV	0x02000000  #define SDRAM_WRDTR_WTR_270_DEG_ADV	0x00000000 @@ -847,6 +851,7 @@  #define pbear		0x20	/* periph bus error addr reg		*/  #define pbesr		0x21	/* periph bus error status reg		*/  #define xbcfg		0x23	/* external bus configuration reg	*/ +#define EBC0_CFG	0x23	/* external bus configuration reg	*/  #define xbcid		0x24	/* external bus core id reg		*/  #if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \  |