[PATCH] Update AMCC Katmai 440SPe eval board support
authorStefan Roese <sr@denx.de>
Thu, 1 Mar 2007 20:11:36 +0000 (21:11 +0100)
committerStefan Roese <sr@denx.de>
Thu, 1 Mar 2007 20:11:36 +0000 (21:11 +0100)
This patch updates the recently added Katmai board support. The biggest
change is the support of ECC DIMM modules in the 440SP(e) SPD DDR2
driver.

Please note, that still some problems are left with some memory
configurations. See the driver for more details.

Signed-off-by: Stefan Roese <sr@denx.de>
board/amcc/katmai/katmai.c
board/amcc/katmai/katmai.h [deleted file]
cpu/ppc4xx/44x_spd_ddr2.c
cpu/ppc4xx/start.S
cpu/ppc4xx/tlb.c
include/configs/katmai.h
include/ppc440.h

index 8704925a9cbbc4b40799a10cffb4a75c3e8b5c07..fbf1a98ab3d96b9bd57a5e5577f9a190b09b9beb 100644 (file)
@@ -28,7 +28,6 @@
 #include <i2c.h>
 #include <asm-ppc/io.h>
 
-#include "katmai.h"
 #include "../cpu/ppc4xx/440spe_pcie.h"
 
 #undef PCIE_ENDPOINT
@@ -40,7 +39,6 @@ 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.
@@ -228,15 +226,11 @@ int board_early_init_f (void)
        mfr &= ~SDR0_MFR_ECS_MASK;
 /*     mtsdr(sdr_mfr, mfr); */
 
-       /*
-        * Setup GPIO signalling per defines in katmai.h
-        */
-       pfc = PFC0_KATMAI;
-       mtsdr(SDR0_PFC0, pfc);
+       mtsdr(SDR0_PFC0, CFG_PFC0);
 
-       out32(GPIO0_OR_ADDR, GPIO_OR_KATMAI);
-       out32(GPIO0_ODR_ADDR, GPIO_ODR_KATMAI);
-       out32(GPIO0_TCR_ADDR, GPIO_TCR_KATMAI);
+       out32(GPIO0_OR, CFG_GPIO_OR);
+       out32(GPIO0_ODR, CFG_GPIO_ODR);
+       out32(GPIO0_TCR, CFG_GPIO_TCR);
 
        return 0;
 }
@@ -378,6 +372,23 @@ int is_pci_host(struct pci_controller *hose)
        return 1;
 }
 
+int katmai_pcie_card_present(int port)
+{
+       u32 val;
+
+       val = in32(GPIO0_IR);
+       switch (port) {
+       case 0:
+               return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT0));
+       case 1:
+               return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT1));
+       case 2:
+               return !(val & GPIO_VAL(CFG_GPIO_PCIE_PRESENT2));
+       default:
+               return 0;
+       }
+}
+
 static struct pci_controller pcie_hose[3] = {{0},{0},{0}};
 
 void pcie_setup_hoses(void)
@@ -391,6 +402,10 @@ void pcie_setup_hoses(void)
         */
        bus = 1;
        for (i = 0; i <= 2; i++) {
+               /* Check for katmai card presence */
+               if (!katmai_pcie_card_present(i))
+                       continue;
+
 #ifdef PCIE_ENDPOINT
                if (ppc440spe_init_pcie_endport(i)) {
 #else
diff --git a/board/amcc/katmai/katmai.h b/board/amcc/katmai/katmai.h
deleted file mode 100644 (file)
index 9d5b793..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * (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_ */
index 6cff3a2e1a96fbf101185753766efc4019f92a36..fe0f2b6ea4e4ea89469d276db0ad578eb8488eb2 100644 (file)
@@ -34,6 +34,7 @@
 #endif
 
 #include <common.h>
+#include <command.h>
 #include <ppc4xx.h>
 #include <i2c.h>
 #include <asm/io.h>
@@ -43,6 +44,9 @@
 #if defined(CONFIG_SPD_EEPROM) &&                              \
        (defined(CONFIG_440SP) || defined(CONFIG_440SPE))
 
+/*-----------------------------------------------------------------------------+
+ * Defines
+ *-----------------------------------------------------------------------------*/
 #ifndef        TRUE
 #define TRUE            1
 #endif
 
 #define MULDIV64(m1, m2, d)    (u32)(((u64)(m1) * (u64)(m2)) / (u64)(d))
 
-#if defined(DEBUG)
-static void ppc440sp_sdram_register_dump(void);
-#endif
+#define CMD_NOP                (7 << 19)
+#define CMD_PRECHARGE  (2 << 19)
+#define CMD_REFRESH    (1 << 19)
+#define CMD_EMR                (0 << 19)
+#define CMD_READ       (5 << 19)
+#define CMD_WRITE      (4 << 19)
+
+#define SELECT_MR      (0 << 16)
+#define SELECT_EMR     (1 << 16)
+#define SELECT_EMR2    (2 << 16)
+#define SELECT_EMR3    (3 << 16)
+
+/* MR */
+#define DLL_RESET      0x00000100
+
+#define WRITE_RECOV_2  (1 << 9)
+#define WRITE_RECOV_3  (2 << 9)
+#define WRITE_RECOV_4  (3 << 9)
+#define WRITE_RECOV_5  (4 << 9)
+#define WRITE_RECOV_6  (5 << 9)
+
+#define BURST_LEN_4    0x00000002
+
+/* EMR */
+#define ODT_0_OHM      0x00000000
+#define ODT_50_OHM     0x00000044
+#define ODT_75_OHM     0x00000004
+#define ODT_150_OHM    0x00000040
+
+#define ODS_FULL       0x00000000
+#define ODS_REDUCED    0x00000002
+
+/* defines for ODT (On Die Termination) of the 440SP(e) DDR2 controller */
+#define ODT_EB0R       (0x80000000 >> 8)
+#define ODT_EB0W       (0x80000000 >> 7)
+#define CALC_ODT_R(n)  (ODT_EB0R << (n << 1))
+#define CALC_ODT_W(n)  (ODT_EB0W << (n << 1))
+#define CALC_ODT_RW(n) (CALC_ODT_R(n) | CALC_ODT_W(n))
 
-/*-----------------------------------------------------------------------------+
- * Defines
- *-----------------------------------------------------------------------------*/
 /* Defines for the Read Cycle Delay test */
 #define NUMMEMTESTS 8
 #define NUMMEMWORDS 8
 
+#define CONFIG_ECC_ERROR_RESET         /* test-only: see description below, at check_ecc() */
+
+/*
+ * This DDR2 setup code can dynamically setup the TLB entries for the DDR2 memory
+ * region. Right now the cache should still be disabled in U-Boot because of the
+ * EMAC driver, that need it's buffer descriptor to be located in non cached
+ * memory.
+ *
+ * If at some time this restriction doesn't apply anymore, just define
+ * CFG_ENABLE_SDRAM_CACHE in the board config file and this code should setup
+ * everything correctly.
+ */
+#ifdef CFG_ENABLE_SDRAM_CACHE
+#define MY_TLB_WORD2_I_ENABLE  0                       /* enable caching on SDRAM */
+#else
+#define MY_TLB_WORD2_I_ENABLE  TLB_WORD2_I_ENABLE      /* disable caching on SDRAM */
+#endif
+
 /* Private Structure Definitions */
 
 /* enum only to ease code for cas latency setting */
@@ -89,7 +143,7 @@ typedef enum ddr_cas_id {
  * Prototypes
  *-----------------------------------------------------------------------------*/
 static unsigned long sdram_memsize(void);
-void program_tlb(u32 start, u32 size);
+void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value);
 static void get_spd_info(unsigned long *dimm_populated,
                         unsigned char *iic0_dimm_addr,
                         unsigned long num_dimm_banks);
@@ -114,7 +168,8 @@ static void program_codt(unsigned long *dimm_populated,
 static void program_mode(unsigned long *dimm_populated,
                         unsigned char *iic0_dimm_addr,
                         unsigned long num_dimm_banks,
-                         ddr_cas_id_t *selected_cas);
+                         ddr_cas_id_t *selected_cas,
+                         int *write_recovery);
 static void program_tr(unsigned long *dimm_populated,
                       unsigned char *iic0_dimm_addr,
                       unsigned long num_dimm_banks);
@@ -130,22 +185,30 @@ static void program_copt1(unsigned long *dimm_populated,
 static void program_initplr(unsigned long *dimm_populated,
                            unsigned char *iic0_dimm_addr,
                            unsigned long num_dimm_banks,
-                            ddr_cas_id_t selected_cas);
+                            ddr_cas_id_t selected_cas,
+                           int write_recovery);
 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);
+                       unsigned long num_dimm_banks,
+                       unsigned long tlb_word2_i_value);
 static void program_ecc_addr(unsigned long start_address,
-                            unsigned long num_bytes);
-
+                            unsigned long num_bytes,
+                            unsigned long tlb_word2_i_value);
+static void program_DQS_calibration(unsigned long *dimm_populated,
+                                   unsigned char *iic0_dimm_addr,
+                                   unsigned long num_dimm_banks);
 #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);
+#if defined(DEBUG)
+static void ppc440sp_sdram_register_dump(void);
+#endif
+int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+void dcbz_area(u32 start_address, u32 num_bytes);
+void dflush(void);
 
 static u32 mfdcr_any(u32 dcr)
 {
@@ -235,7 +298,7 @@ static unsigned long sdram_memsize(void)
            && ((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++) {
+               for (i = 0; i < MAXBXCF; i++) {
                        mfsdram(SDRAM_MB0CF + (i << 2), mb0cf);
                        /* Banks enabled */
                        if ((mb0cf & SDRAM_BXCF_M_BE_MASK) == SDRAM_BXCF_M_BE_ENABLE) {
@@ -300,14 +363,15 @@ static unsigned long sdram_memsize(void)
  *-----------------------------------------------------------------------------*/
 long int initdram(int board_type)
 {
+       unsigned char iic0_dimm_addr[] = SPD_EEPROM_ADDRESS;
        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;
+       int write_recovery;
        unsigned long dram_size = 0;
 
        num_dimm_banks = sizeof(iic0_dimm_addr);
@@ -318,16 +382,10 @@ long int initdram(int board_type)
        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, (0x80000000 >> 10));
        mtsdr(SDR0_SRST, 0x00000000);
 
        /*
@@ -399,7 +457,8 @@ long int initdram(int board_type)
        /*------------------------------------------------------------------
         * Program SDRAM mode register.
         *-----------------------------------------------------------------*/
-       program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks, &selected_cas);
+       program_mode(dimm_populated, iic0_dimm_addr, num_dimm_banks,
+                    &selected_cas, &write_recovery);
 
        /*------------------------------------------------------------------
         * Set the SDRAM Write Data/DM/DQS Clock Timing Reg
@@ -438,7 +497,7 @@ long int initdram(int board_type)
         * Program Initialization preload registers.
         *-----------------------------------------------------------------*/
        program_initplr(dimm_populated, iic0_dimm_addr, num_dimm_banks,
-                       selected_cas);
+                       selected_cas, write_recovery);
 
        /*------------------------------------------------------------------
         * Delay to ensure 200usec have elapsed since reset.
@@ -471,19 +530,17 @@ long int initdram(int board_type)
        dram_size = sdram_memsize();
 
        /* and program tlb entries for this size (dynamic) */
-       program_tlb(0, dram_size);
+       program_tlb(0, dram_size, MY_TLB_WORD2_I_ENABLE);
 
-#if 1 /* TODO: ECC support will come later */
        /*------------------------------------------------------------------
-        * If ecc is enabled, initialize the parity bits.
+        * DQS calibration.
         *-----------------------------------------------------------------*/
-       program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks);
-#endif
+       program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks);
 
        /*------------------------------------------------------------------
-        * DQS calibration.
+        * If ecc is enabled, initialize the parity bits.
         *-----------------------------------------------------------------*/
-       program_DQS_calibration(dimm_populated, iic0_dimm_addr, num_dimm_banks);
+       program_ecc(dimm_populated, iic0_dimm_addr, num_dimm_banks, MY_TLB_WORD2_I_ENABLE);
 
 #ifdef DEBUG
        ppc440sp_sdram_register_dump();
@@ -996,8 +1053,8 @@ static void program_codt(unsigned long *dimm_populated,
                                dimm_type = SDRAM_DDR1;
                        }
 
-                       total_rank +=  dimm_rank;
-                       total_dimm ++;
+                       total_rank += dimm_rank;
+                       total_dimm++;
                        if ((dimm_num == 0) && (total_dimm == 1))
                                firstSlot = TRUE;
                        else
@@ -1008,49 +1065,49 @@ static void program_codt(unsigned long *dimm_populated,
                codt |= SDRAM_CODT_DQS_1_8_V_DDR2;
                if ((total_dimm == 1) && (firstSlot == TRUE)) {
                        if (total_rank == 1) {
-                               codt |= 0x00800000;
-                               modt0 = 0x01000000;
+                               codt |= CALC_ODT_R(0);
+                               modt0 = CALC_ODT_W(0);
                                modt1 = 0x00000000;
                                modt2 = 0x00000000;
                                modt3 = 0x00000000;
                        }
                        if (total_rank == 2) {
-                               codt |= 0x02800000;
-                               modt0 = 0x06000000;
-                               modt1 = 0x01800000;
+                               codt |= CALC_ODT_R(0) | CALC_ODT_R(1);
+                               modt0 = CALC_ODT_W(0);
+                               modt1 = CALC_ODT_W(0);
                                modt2 = 0x00000000;
                                modt3 = 0x00000000;
                        }
-               } else {
+               } else if ((total_dimm == 1) && (firstSlot != TRUE)) {
                        if (total_rank == 1) {
-                               codt |= 0x00800000;
-                               modt0 = 0x01000000;
+                               codt |= CALC_ODT_R(2);
+                               modt0 = 0x00000000;
                                modt1 = 0x00000000;
-                               modt2 = 0x00000000;
+                               modt2 = CALC_ODT_W(2);
                                modt3 = 0x00000000;
                        }
                        if (total_rank == 2) {
-                               codt |= 0x02800000;
-                               modt0 = 0x06000000;
-                               modt1 = 0x01800000;
-                               modt2 = 0x00000000;
-                               modt3 = 0x00000000;
+                               codt |= CALC_ODT_R(2) | CALC_ODT_R(3);
+                               modt0 = 0x00000000;
+                               modt1 = 0x00000000;
+                               modt2 = CALC_ODT_W(2);
+                               modt3 = CALC_ODT_W(2);
                        }
                }
                if (total_dimm == 2) {
                        if (total_rank == 2) {
-                               codt |= 0x08800000;
-                               modt0 = 0x18000000;
+                               codt |= CALC_ODT_R(0) | CALC_ODT_R(2);
+                               modt0 = CALC_ODT_RW(2);
                                modt1 = 0x00000000;
-                               modt2 = 0x01800000;
+                               modt2 = CALC_ODT_RW(0);
                                modt3 = 0x00000000;
                        }
                        if (total_rank == 4) {
-                               codt |= 0x2a800000;
-                               modt0 = 0x18000000;
-                               modt1 = 0x18000000;
-                               modt2 = 0x01800000;
-                               modt3 = 0x01800000;
+                               codt |= CALC_ODT_R(0) | CALC_ODT_R(1) | CALC_ODT_R(2) | CALC_ODT_R(3);
+                               modt0 = CALC_ODT_RW(2);
+                               modt1 = 0x00000000;
+                               modt2 = CALC_ODT_RW(0);
+                               modt3 = 0x00000000;
                        }
                }
        } else {
@@ -1092,9 +1149,19 @@ static void program_codt(unsigned long *dimm_populated,
 static void program_initplr(unsigned long *dimm_populated,
                            unsigned char *iic0_dimm_addr,
                            unsigned long num_dimm_banks,
-                            ddr_cas_id_t selected_cas)
+                            ddr_cas_id_t selected_cas,
+                           int write_recovery)
 {
-       unsigned long MR_CAS_value = 0;
+       u32 cas = 0;
+       u32 odt = 0;
+       u32 ods = 0;
+       u32 mr;
+       u32 wr;
+       u32 emr;
+       u32 emr2;
+       u32 emr3;
+       int dimm_num;
+       int total_dimm = 0;
 
        /******************************************************
         ** Assumption: if more than one DIMM, all DIMMs are the same
@@ -1112,41 +1179,90 @@ static void program_initplr(unsigned long *dimm_populated,
                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;
+                       cas = 3 << 4;
                        break;
                case DDR_CAS_4:
-                       MR_CAS_value = 4 << 4;
+                       cas = 4 << 4;
                        break;
                case DDR_CAS_5:
-                       MR_CAS_value = 5 << 4;
+                       cas = 5 << 4;
                        break;
                default:
-                       printf("ERROR: ucode error on selected_cas value %d", (unsigned char)selected_cas);
+                       printf("ERROR: ucode error on selected_cas value %d", 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 */
+#if 0
+               /*
+                * ToDo - Still a problem with the write recovery:
+                * On the Corsair CM2X512-5400C4 module, setting write recovery
+                * in the INITPLR reg to the value calculated in program_mode()
+                * results in not correctly working DDR2 memory (crash after
+                * relocation).
+                *
+                * So for now, set the write recovery to 3. This seems to work
+                * on the Corair module too.
+                *
+                * 2007-03-01, sr
+                */
+               switch (write_recovery) {
+               case 3:
+                       wr = WRITE_RECOV_3;
+                       break;
+               case 4:
+                       wr = WRITE_RECOV_4;
+                       break;
+               case 5:
+                       wr = WRITE_RECOV_5;
+                       break;
+               case 6:
+                       wr = WRITE_RECOV_6;
+                       break;
+               default:
+                       printf("ERROR: write recovery not support (%d)", write_recovery);
+                       hang();
+                       break;
+               }
+#else
+               wr = WRITE_RECOV_3; /* test-only, see description above */
+#endif
+
+               for (dimm_num = 0; dimm_num < num_dimm_banks; dimm_num++)
+                       if (dimm_populated[dimm_num] != SDRAM_NONE)
+                               total_dimm++;
+               if (total_dimm == 1) {
+                       odt = ODT_150_OHM;
+                       ods = ODS_FULL;
+               } else if (total_dimm == 2) {
+                       odt = ODT_75_OHM;
+                       ods = ODS_REDUCED;
+               } else {
+                       printf("ERROR: Unsupported number of DIMM's (%d)", total_dimm);
+                       hang();
+               }
+
+               mr = CMD_EMR | SELECT_MR | BURST_LEN_4 | wr | cas;
+               emr = CMD_EMR | SELECT_EMR | odt | ods;
+               emr2 = CMD_EMR | SELECT_EMR2;
+               emr3 = CMD_EMR | SELECT_EMR3;
+               mtsdram(SDRAM_INITPLR0,  0xB5000000 | CMD_NOP);         /* NOP */
+               udelay(1000);
+               mtsdram(SDRAM_INITPLR1,  0x82000400 | CMD_PRECHARGE);   /* precharge 8 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR2,  0x80800000 | emr2);            /* EMR2 */
+               mtsdram(SDRAM_INITPLR3,  0x80800000 | emr3);            /* EMR3 */
+               mtsdram(SDRAM_INITPLR4,  0x80800000 | emr);             /* EMR DLL ENABLE */
+               mtsdram(SDRAM_INITPLR5,  0x80800000 | mr | DLL_RESET);  /* MR w/ DLL reset */
+               udelay(1000);
+               mtsdram(SDRAM_INITPLR6,  0x82000400 | CMD_PRECHARGE);   /* precharge 8 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR7,  0x8a000000 | CMD_REFRESH);     /* Refresh  50 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR8,  0x8a000000 | CMD_REFRESH);     /* Refresh  50 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR9,  0x8a000000 | CMD_REFRESH);     /* Refresh  50 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR10, 0x8a000000 | CMD_REFRESH);     /* Refresh  50 DDR clock cycle */
+               mtsdram(SDRAM_INITPLR11, 0x80000000 | mr);              /* MR w/o DLL reset */
+               mtsdram(SDRAM_INITPLR12, 0x80800380 | emr);             /* EMR OCD Default */
+               mtsdram(SDRAM_INITPLR13, 0x80800000 | emr);             /* EMR OCD Exit */
        } else {
                printf("ERROR: ucode error as unknown DDR type in program_initplr");
                hang();
@@ -1161,7 +1277,8 @@ static void program_initplr(unsigned long *dimm_populated,
 static void program_mode(unsigned long *dimm_populated,
                         unsigned char *iic0_dimm_addr,
                         unsigned long num_dimm_banks,
-                        ddr_cas_id_t *selected_cas)
+                        ddr_cas_id_t *selected_cas,
+                        int *write_recovery)
 {
        unsigned long dimm_num;
        unsigned long sdram_ddr1;
@@ -1424,8 +1541,12 @@ static void program_mode(unsigned long *dimm_populated,
                        mmode |= SDRAM_MMODE_WR_DDR2_6_CYC;
                        break;
                }
+               *write_recovery = t_wr_clk;
        }
 
+       debug("CAS latency = %d\n", *selected_cas);
+       debug("Write recovery = %d\n", *write_recovery);
+
        mtsdram(SDRAM_MMODE, mmode);
 }
 
@@ -2017,7 +2138,8 @@ 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)
+                       unsigned long num_dimm_banks,
+                       unsigned long tlb_word2_i_value)
 {
        unsigned long mcopt1;
        unsigned long mcopt2;
@@ -2046,23 +2168,59 @@ static void program_ecc(unsigned long *dimm_populated,
                    && ((mcstat & (SDRAM_MCSTAT_MIC_MASK | SDRAM_MCSTAT_SRMS_MASK))
                        == (SDRAM_MCSTAT_MIC_COMP | SDRAM_MCSTAT_SRMS_NOT_SF))) {
 
-                       program_ecc_addr(0, sdram_memsize());
+                       program_ecc_addr(0, sdram_memsize(), tlb_word2_i_value);
                }
        }
 
        return;
 }
 
+#ifdef CONFIG_ECC_ERROR_RESET
+/*
+ * Check for ECC errors and reset board upon any error here
+ *
+ * On the Katmai 440SPe eval board, from time to time, the first
+ * lword write access after DDR2 initializazion with ECC checking
+ * enabled, leads to an ECC error. I couldn't find a configuration
+ * without this happening. On my board with the current setup it
+ * happens about 1 from 10 times.
+ *
+ * The ECC modules used for testing are:
+ * - Kingston ValueRAM KVR667D2E5/512 (tested with 1 and 2 DIMM's)
+ *
+ * This has to get fixed for the Katmai and tested for the other
+ * board (440SP/440SPe) that will eventually use this code in the
+ * future.
+ *
+ * 2007-03-01, sr
+ */
+static void check_ecc(void)
+{
+       u32 val;
+
+       mfsdram(SDRAM_ECCCR, val);
+       if (val != 0) {
+               printf("\nECC error: MCIF0_ECCES=%08lx MQ0_ESL=%08lx address=%08lx\n",
+                      val, mfdcr(0x4c), mfdcr(0x4e));
+               printf("ECC error occured, resetting board...\n");
+               do_reset(NULL, 0, 0, NULL);
+       }
+}
+#endif
+
 /*-----------------------------------------------------------------------------+
  * program_ecc_addr.
  *-----------------------------------------------------------------------------*/
 static void program_ecc_addr(unsigned long start_address,
-                            unsigned long num_bytes)
+                            unsigned long num_bytes,
+                            unsigned long tlb_word2_i_value)
 {
        unsigned long current_address;
        unsigned long end_address;
        unsigned long address_increment;
        unsigned long mcopt1;
+       char str[] = "ECC generation...";
+       int i;
 
        current_address = start_address;
        mfsdram(SDRAM_MCOPT1, mcopt1);
@@ -2073,26 +2231,49 @@ static void program_ecc_addr(unsigned long start_address,
                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;
+               puts(str);
+               if (tlb_word2_i_value == TLB_WORD2_I_ENABLE) {
+                       /* 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;
+                       while (current_address < end_address) {
+                               *((unsigned long *)current_address) = 0x00000000;
+                               current_address += address_increment;
+                       }
+               } else {
+                       /* ECC bit set method for cached memory */
+                       dcbz_area(start_address, num_bytes);
+                       dflush();
                }
+               for (i=0; i<strlen(str); i++)
+                       putc('\b');
+
                sync();
                eieio();
                wait_ddr_idle();
 
+               /* clear ECC error repoting registers */
+               mtsdram(SDRAM_ECCCR, 0xffffffff);
+               mtdcr(0x4c, 0xffffffff);
+
                mtsdram(SDRAM_MCOPT1,
-                       (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK);
+                       (mcopt1 & ~SDRAM_MCOPT1_MCHK_MASK) | SDRAM_MCOPT1_MCHK_CHK_REP);
                sync();
                eieio();
                wait_ddr_idle();
+
+#ifdef CONFIG_ECC_ERROR_RESET
+               /*
+                * One write to 0 is enough to trigger this ECC error
+                * (see description above)
+                */
+               out_be32(0, 0x12345678);
+               check_ecc();
+#endif
        }
 }
 
index a3db93ffbb7b4506254885e655f8b12d659504c4..cd2cceced9aca983980f7545c1de3433f88e951a 100644 (file)
@@ -1912,4 +1912,47 @@ pll_wait:
         TLBRE(3,3,0)
        blr
        function_epilog(mftlb1)
+
+/*----------------------------------------------------------------------------+
+| dcbz_area.
++----------------------------------------------------------------------------*/
+        function_prolog(dcbz_area)
+        rlwinm. r5,r4,0,27,31
+        rlwinm  r5,r4,27,5,31
+        beq     ..d_ra2
+        addi    r5,r5,0x0001
+..d_ra2:mtctr   r5
+..d_ag2:dcbz    r0,r3
+        addi    r3,r3,32
+        bdnz    ..d_ag2
+        sync
+        blr
+        function_epilog(dcbz_area)
+
+/*----------------------------------------------------------------------------+
+| dflush.  Assume 32K at vector address is cachable.
++----------------------------------------------------------------------------*/
+        function_prolog(dflush)
+        mfmsr   r9
+        rlwinm  r8,r9,0,15,13
+        rlwinm  r8,r8,0,17,15
+        mtmsr   r8
+        addi    r3,r0,0x0000
+        mtspr   dvlim,r3
+        mfspr   r3,ivpr
+        addi    r4,r0,1024
+        mtctr   r4
+..dflush_loop:
+        lwz     r6,0x0(r3)
+        addi    r3,r3,32
+        bdnz    ..dflush_loop
+        addi    r3,r3,-32
+        mtctr   r4
+..ag:   dcbf    r0,r3
+        addi    r3,r3,-32
+        bdnz    ..ag
+        sync
+        mtmsr   r9
+        blr
+        function_epilog(dflush)
 #endif /* CONFIG_440 */
index 8c605591b8103d466ebede3ac46b6c98117ca5bb..08ae76c3f47188b793c075fc19f363d475fca76f 100644 (file)
@@ -166,13 +166,13 @@ static void program_tlb_addr(unsigned long base_addr, unsigned long mem_size,
  * Common usage for boards with SDRAM DIMM modules to dynamically
  * configure the TLB's for the SDRAM
  */
-void program_tlb(u32 start, u32 size)
+void program_tlb(u32 start, u32 size, u32 tlb_word2_i_value)
 {
        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) */
+       region_array.tlb_word2_i_value = tlb_word2_i_value;     /* en-/disable cache */
 
        /* Call the routine to add in the tlb entries for the memory regions */
        program_tlb_addr(region_array.base, region_array.size,
index c750e1465698a2d0b4014025de274a63e6d3b975..f350155c83d9eca55944ea8ccde9ec23ba43f76f 100644 (file)
  * 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
+#define SPD_EEPROM_ADDRESS     {0x51, 0x52}    /* SPD i2c spd addresses*/
 #undef  CONFIG_STRESS
-#undef  ENABLE_ECC
 
 /*-----------------------------------------------------------------------
  * I2C
                                 EBC_CFG_PME_DISABLE  | \
                                 EBC_CFG_PR_16)
 
+/*-----------------------------------------------------------------------
+ * GPIO Setup
+ *----------------------------------------------------------------------*/
+#define CFG_GPIO_PCIE_PRESENT0 17
+#define CFG_GPIO_PCIE_PRESENT1 21
+#define CFG_GPIO_PCIE_PRESENT2 23
+#define CFG_GPIO_RS232_FORCEOFF        30
+
+#define CFG_PFC0               (GPIO_VAL(CFG_GPIO_PCIE_PRESENT0) | \
+                                GPIO_VAL(CFG_GPIO_PCIE_PRESENT1) | \
+                                GPIO_VAL(CFG_GPIO_PCIE_PRESENT2) | \
+                                GPIO_VAL(CFG_GPIO_RS232_FORCEOFF))
+#define CFG_GPIO_OR            GPIO_VAL(CFG_GPIO_RS232_FORCEOFF)
+#define CFG_GPIO_TCR           GPIO_VAL(CFG_GPIO_RS232_FORCEOFF)
+#define CFG_GPIO_ODR           0
+
 /*
  * For booting Linux, the board info and command line data
  * have to be in the first 8 MB of memory, since this is
index c24f5b7ab1773e110cf089a480d30a7f6f7020bc..1c7f11c4885778813295ac5875fcf906daf14ff9 100644 (file)
 #define GPIO0                  0
 #define GPIO1                  1
 
-#if defined(CONFIG_440GP) || defined(CONFIG_440GX)
+#if defined(CONFIG_440GP) || defined(CONFIG_440GX) || \
+    defined(CONFIG_440SP) || defined(CONFIG_440SPE)
 #define GPIO0_BASE             (CFG_PERIPHERAL_BASE+0x00000700)
 
 #define GPIO0_OR               (GPIO0_BASE+0x0)
 #define GPIO_IN_SEL        0x40000000      /* GPIO_IN value put in GPIO_ISx for the GPIO nb 0 */
                                            /* For the other GPIO number, you must shift */
 
+#define GPIO_VAL(gpio)         (0x80000000 >> (gpio))
+
 #ifndef __ASSEMBLY__
 
 typedef enum gpio_select { GPIO_SEL, GPIO_ALT1, GPIO_ALT2, GPIO_ALT3 } gpio_select_t;
@@ -3285,7 +3288,6 @@ typedef struct { unsigned long    add;    /* gpio core base address */
        gpio_select_t  alt_nb; /* Selected Alternate */
 } gpio_param_s;
 
-
 #endif /* __ASSEMBLY__ */
 
 /*