diff options
39 files changed, 5717 insertions, 849 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index f90c5a6..1d0a8df 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 0000000..d06a402 --- /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 0000000..684f6a5 --- /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 0000000..115c1ae --- /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 0000000..f5900bc --- /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 0000000..8704925 --- /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 0000000..9d5b793 --- /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 0000000..bf8fc5d --- /dev/null +++ b/board/amcc/katmai/u-boot.lds @@ -0,0 +1,141 @@ +/* + * (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 : + { + cpu/ppc4xx/start.o (.text) + board/amcc/katmai/init.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 a7114eb..a0fac7f 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 a019ce4..6943213 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 ff1190a..1d28513 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 1324978..4b1c1c0 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 859dd7a..1e3dffb 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 cd4fc86..10000f5 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 84932f7..33d2e56 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 9db64e9..4f7b049 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 0000000..19c4f76 --- /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 c24456b..32d44db 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 0000000..6cff3a2 --- /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 baecf70..96f0f62 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 ae24591..82ae443 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 7db1cd8..0b056a1 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"); - - /* - * 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"); - - /* 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; + out_8((u8 *)IIC_EXTSTS, 0x8F); + + /* Place chip in the reset state */ + out_8((u8 *)IIC_XTCNTLSS, IIC_XTCNTLSS_SRST); + + /* 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 2d16a83..06220c3 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 8e000d3..a3db93f 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 0000000..8c60559 --- /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/disk/part.c b/disk/part.c index f1026c5..37bba77 100644 --- a/disk/part.c +++ b/disk/part.c @@ -64,13 +64,25 @@ static const struct block_drvr block_drvr[] = { { }, }; +#ifndef CFG_FIXUP_RELOCATION +DECLARE_GLOBAL_DATA_PTR; +#endif + block_dev_desc_t *get_dev(char* ifname, int dev) { const struct block_drvr *drvr = block_drvr; while (drvr->name) { +#ifndef CFG_FIXUP_RELOCATION + block_dev_desc_t* (*reloc_get_dev)(int dev); + + reloc_get_dev = drvr->get_dev + gd->reloc_off; + if (strncmp(ifname, drvr->name, strlen(drvr->name)) == 0) + return reloc_get_dev(dev); +#else if (strncmp(ifname, drvr->name, strlen(drvr->name)) == 0) return drvr->get_dev(dev); +#endif drvr++; } return NULL; diff --git a/drivers/systemace.c b/drivers/systemace.c index 9502623..3bd2ea9 100644 --- a/drivers/systemace.c +++ b/drivers/systemace.c @@ -66,8 +66,8 @@ writeb(val>>8, CFG_SYSTEMACE_BASE+off+1);} #endif #else -#define ace_readw(off) (readw(CFG_SYSTEMACE_BASE+off)) -#define ace_writew(val, off) (writew(val, CFG_SYSTEMACE_BASE+off)) +#define ace_readw(off) (in16(CFG_SYSTEMACE_BASE+off)) +#define ace_writew(val, off) (out16(CFG_SYSTEMACE_BASE+off,val)) #endif /* */ @@ -119,6 +119,14 @@ block_dev_desc_t *systemace_get_dev(int dev) systemace_dev.removable = 1; systemace_dev.block_read = systemace_read; +#if (CFG_SYSTEMACE_WIDTH == 16) + /* + * By default the SystemACE comes up in 8-bit mode. + * Ensure that 16-bit mode gets enabled. + */ + ace_writew(0x0001, 0); +#endif + init_part(&systemace_dev); } @@ -197,7 +205,7 @@ static unsigned long systemace_read(int dev, unsigned long start, #endif /* Write LBA block address */ ace_writew((start >> 0) & 0xffff, 0x10); - ace_writew((start >> 16) & 0x00ff, 0x12); + ace_writew((start >> 16) & 0x0fff, 0x12); /* NOTE: in the Write Sector count below, a count of 0 causes a transfer of 256, so &0xff gives the right diff --git a/dtt/adm1021.c b/dtt/adm1021.c index 14c38f0..9f65cfb 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 5a9a497..0000000 --- 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 0c2bf36..0000000 --- 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 0000000..66b7997 --- /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 914f28b..b226825 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 0000000..c750e14 --- /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 a8f729a..54c6f9f 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 e475fa5..a49912c 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 91cff41..c24f5b7 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) || \ |