74xx_7xx: CPCI750: Add ECC support on esd CPCI-CPU/750 board
authorReinhard Arlt <reinhard.arlt@esd.eu>
Tue, 13 Apr 2010 07:59:09 +0000 (09:59 +0200)
committerWolfgang Denk <wd@denx.de>
Wed, 5 May 2010 22:22:53 +0000 (00:22 +0200)
Add ECC support for DDR RAM for MV64360 on esd CPCI-CPU/750 board.

This patch also adds the "pldver" command to display the CPLD
revision.

Signed-off-by: Reinhard Arlt <reinhard.arlt@esd.eu>
Signed-off-by: Stefan Roese <sr@denx.de>
board/esd/cpci750/cpci750.c
board/esd/cpci750/sdram_init.c
include/configs/CPCI750.h

index 2ae4cbd6c0b0ca5db6ec13575c257a189e950073..a199d461827fbbe10fa3ff0246978b08aa248ef3 100644 (file)
@@ -1090,3 +1090,15 @@ U_BOOT_CMD(
        "Show Marvell strapping register",
        "Show Marvell strapping register (ResetSampleLow ResetSampleHigh)"
 );
+
+int do_pldver(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       printf("PLD version:0x%02x\n", in_8((void *)CONFIG_SYS_PLD_VER));
+
+       return 0;
+}
+
+U_BOOT_CMD(
+       pldver, 1, 1, do_pldver,
+       "Show PLD version",
+       "Show PLD version)");
index 4c03630fb574fd02eaefe9e56a811b69b863fa84..534795808560dded763b438015f91ae8ff7d6ca2 100644 (file)
@@ -538,14 +538,14 @@ static int check_dimm (uchar slot, AUX_MEM_DIMM_INFO * dimmInfo)
                        break;
 /*------------------------------------------------------------------------------------------------------------------------------*/
 
-#ifdef CONFIG_ECC
+#ifdef CONFIG_MV64360_ECC
                case 11:        /* Error Check Type */
                        dimmInfo->errorCheckType = data[i];
                        DP (printf
                            ("Error Check Type (0=NONE):                        %d\n",
                             dimmInfo->errorCheckType));
                        break;
-#endif
+#endif /* of ifdef CONFIG_MV64360_ECC */
 /*------------------------------------------------------------------------------------------------------------------------------*/
 
                case 12:        /* Refresh Interval */
@@ -1254,6 +1254,7 @@ int setup_sdram (AUX_MEM_DIMM_INFO * info)
        ulong tmp;
        ulong tmp_sdram_mode = 0;       /* 0x141c */
        ulong tmp_dunit_control_low = 0;        /* 0x1404 */
+       uint sdram_config_reg = CONFIG_SYS_SDRAM_CONFIG;
        int i;
 
        /* sanity checking */
@@ -1269,7 +1270,6 @@ int setup_sdram (AUX_MEM_DIMM_INFO * info)
                DP (printf
                    ("Module is registered, but we do not support registered Modules !!!\n"));
 
-
        /* delay line */
        set_dfcdlInit ();       /* may be its not needed */
        DP (printf ("Delay line set done\n"));
@@ -1281,8 +1281,16 @@ int setup_sdram (AUX_MEM_DIMM_INFO * info)
                    ("\n*** SDRAM_OPERATION 1418: Module still busy ... please wait... ***\n"));
        }
 
+#ifdef CONFIG_MV64360_ECC
+       if ((info->errorCheckType == 0x2) && (CPCI750_ECC_TEST)) {
+               /* DRAM has ECC, so turn it on */
+               sdram_config_reg |= BIT18;
+               DP(printf("Enabling ECC\n"));
+       }
+#endif /* of ifdef CONFIG_MV64360_ECC */
+
        /* SDRAM configuration */
-       GT_REG_WRITE (SDRAM_CONFIG, 0x58200400);
+       GT_REG_WRITE(SDRAM_CONFIG, sdram_config_reg);
        DP (printf ("sdram_conf 0x1400: %08x\n", GTREGREAD (SDRAM_CONFIG)));
 
        /* SDRAM open pages controll keep open as much as I can */
@@ -1598,7 +1606,84 @@ dram_size(long int *base, long int maxsize)
     return maxsize;
 }
 
-/* ------------------------------------------------------------------------- */
+#ifdef CONFIG_MV64360_ECC
+/*
+ * mv_dma_is_channel_active:
+ * Checks if a engine is busy.
+ */
+int mv_dma_is_channel_active(int engine)
+{
+       ulong data;
+
+       data = GTREGREAD(MV64360_DMA_CHANNEL0_CONTROL + 4 * engine);
+       if (data & BIT14)       /* activity status */
+               return 1;
+
+       return 0;
+}
+
+/*
+ * mv_dma_set_memory_space:
+ * Set a DMA memory window for the DMA's address decoding map.
+ */
+int mv_dma_set_memory_space(ulong mem_space, ulong mem_space_target,
+                           ulong mem_space_attr, ulong base_address,
+                           ulong size)
+{
+       ulong temp;
+
+       /* The base address must be aligned to the size.  */
+       if (base_address % size != 0)
+               return 0;
+
+       if (size >= 0x10000) {
+               size &= 0xffff0000;
+               base_address = (base_address & 0xffff0000);
+               /* Set the new attributes */
+               GT_REG_WRITE(MV64360_DMA_BASE_ADDR_REG0 + mem_space * 8,
+                            (base_address | mem_space_target |
+                             mem_space_attr));
+               GT_REG_WRITE((MV64360_DMA_SIZE_REG0 + mem_space * 8),
+                            (size - 1) & 0xffff0000);
+               temp = GTREGREAD(MV64360_DMA_BASE_ADDR_ENABLE_REG);
+               GT_REG_WRITE(DMA_BASE_ADDR_ENABLE_REG,
+                            (temp & ~(BIT0 << mem_space)));
+               return 1;
+       }
+
+       return 0;
+}
+
+
+/*
+ * mv_dma_transfer:
+ * Transfer data from source_addr to dest_addr on one of the 4 DMA channels.
+ */
+int mv_dma_transfer(int engine, ulong source_addr,
+                   ulong dest_addr, ulong bytes, ulong command)
+{
+       ulong eng_off_reg;      /* Engine Offset Register */
+
+       if (bytes > 0xffff)
+               command = command | BIT31;       /* DMA_16M_DESCRIPTOR_MODE */
+
+       command = command | ((command >> 6) & 0x7);
+       eng_off_reg = engine * 4;
+       GT_REG_WRITE(MV64360_DMA_CHANNEL0_BYTE_COUNT + eng_off_reg,
+                    bytes);
+       GT_REG_WRITE(MV64360_DMA_CHANNEL0_SOURCE_ADDR + eng_off_reg,
+                    source_addr);
+       GT_REG_WRITE(MV64360_DMA_CHANNEL0_DESTINATION_ADDR + eng_off_reg,
+                    dest_addr);
+       command |= BIT12        /* DMA_CHANNEL_ENABLE */
+               | BIT9;         /* DMA_NON_CHAIN_MODE */
+
+       /* Activate DMA engine By writting to mv_dma_control_register */
+       GT_REG_WRITE(MV64360_DMA_CHANNEL0_CONTROL + eng_off_reg, command);
+
+       return 1;
+}
+#endif /* of ifdef CONFIG_MV64360_ECC */
 
 /* ppcboot interface function to SDRAM init - this is where all the
  * controlling logic happens */
@@ -1607,10 +1692,13 @@ initdram(int board_type)
 {
        int s0 = 0, s1 = 0;
        int checkbank[4] = { [0 ... 3] = 0 };
-               ulong bank_no, realsize, total, check;
+       ulong realsize, total, check;
        AUX_MEM_DIMM_INFO dimmInfo1;
        AUX_MEM_DIMM_INFO dimmInfo2;
-       int nhr;
+       int bank_no, nhr;
+#ifdef CONFIG_MV64360_ECC
+       ulong dest, mem_space_attr;
+#endif /* of ifdef CONFIG_MV64360_ECC */
 
        /* first, use the SPD to get info about the SDRAM/ DDRRAM */
 
@@ -1668,6 +1756,28 @@ initdram(int board_type)
                realsize = dram_size((long int *)total, check);
                memory_map_bank(bank_no, total, realsize);
 
+#ifdef CONFIG_MV64360_ECC
+               if (((dimmInfo1.errorCheckType != 0) &&
+                    ((dimmInfo2.errorCheckType != 0) ||
+                     (dimmInfo2.numOfModuleBanks == 0))) &&
+                   (CPCI750_ECC_TEST)) {
+                       printf("ECC Initialization of Bank %d:", bank_no);
+                       mem_space_attr = ((~(BIT0 << bank_no)) & 0xf) << 8;
+                       mv_dma_set_memory_space(0, 0, mem_space_attr, total,
+                                               realsize);
+                       for (dest = total; dest < total + realsize;
+                            dest += _8M) {
+                               mv_dma_transfer(0, total, dest, _8M,
+                                               BIT8 |  /* DMA_DTL_128BYTES */
+                                               BIT3 |  /* DMA_HOLD_SOURCE_ADDR */
+                                               BIT11); /* DMA_BLOCK_TRANSFER_MODE */
+                               while (mv_dma_is_channel_active(0))
+                                       ;
+                       }
+                       printf(" PASS\n");
+               }
+#endif /* of ifdef CONFIG_MV64360_ECC */
+
                total += realsize;
        }
 
@@ -1700,3 +1810,30 @@ int set_dfcdlInit (void)
 
        return (0);
 }
+
+int do_show_ecc(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+       unsigned int ecc_counter;
+       unsigned int ecc_addr;
+
+       GT_REG_READ(0x1458, &ecc_counter);
+       GT_REG_READ(0x1450, &ecc_addr);
+       GT_REG_WRITE(0x1450, 0);
+
+       printf("Error Counter since Reset:  %8d\n", ecc_counter);
+       printf("Last error address       :0x%08x (" , ecc_addr & 0xfffffff8);
+       if (ecc_addr & 0x01)
+               printf("double");
+       else
+               printf("single");
+       printf(" bit) at DDR-RAM CS#%d\n", ((ecc_addr & 0x6) >> 1));
+
+       return 0;
+}
+
+
+U_BOOT_CMD(
+       show_ecc, 1, 1, do_show_ecc,
+       "Show Marvell MV64360 ECC Info",
+       "Show Marvell MV64360 ECC Counter and last error."
+);
index d516c3cb8128e0f11faeb0ba7919ef7b7bcabf30..1c8c68b3e47960e81eae73dc645dff2e5566b232 100644 (file)
@@ -59,7 +59,7 @@
 
 #define CONFIG_BAUDRATE                9600    /* console baudrate = 9600      */
 
-#undef CONFIG_ECC                      /* enable ECC support */
+#define CONFIG_MV64360_ECC             /* enable ECC support */
 
 #define CONFIG_HIGH_BATS       1       /* High BATs supported */
 
 #define CONFIG_SYS_BOARD_ASM_INIT      1
 
 #define CPCI750_SLAVE_TEST     (((in8(0xf0300000) & 0x80) == 0) ? 0 : 1)
+#define CPCI750_ECC_TEST       (((in8(0xf0300000) & 0x02) == 0) ? 1 : 0)
+#define CONFIG_SYS_PLD_VER     0xf0e00000
 
 #endif /* __CONFIG_H */