summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-socfpga/include/mach/sdram_s10.h9
-rw-r--r--drivers/ddr/altera/sdram_s10.c81
2 files changed, 90 insertions, 0 deletions
diff --git a/arch/arm/mach-socfpga/include/mach/sdram_s10.h b/arch/arm/mach-socfpga/include/mach/sdram_s10.h
index ca685944453..f39206ca1ee 100644
--- a/arch/arm/mach-socfpga/include/mach/sdram_s10.h
+++ b/arch/arm/mach-socfpga/include/mach/sdram_s10.h
@@ -22,6 +22,7 @@ int sdram_calibration_full(void);
#define ECCCTRL1 0x100
#define ECCCTRL2 0x104
#define ERRINTEN 0x110
+#define ERRINTENS 0x114
#define INTMODE 0x11c
#define INTSTAT 0x120
#define AUTOWB_CORRADDR 0x138
@@ -52,6 +53,10 @@ int sdram_calibration_full(void);
#define DDR_HMC_SEQ2CORE_INT_RESP_MASK BIT(3)
#define DDR_HMC_HPSINTFCSEL_ENABLE_MASK 0x001f1f1f
+#define DDR_HMC_ERRINTEN_INTMASK \
+ (DDR_HMC_ERRINTEN_SERRINTEN_EN_SET_MSK | \
+ DDR_HMC_ERRINTEN_DERRINTEN_EN_SET_MSK)
+
/* NOC DDR scheduler */
#define DDR_SCH_ID_COREID 0
#define DDR_SCH_ID_REVID 0x4
@@ -180,4 +185,8 @@ int sdram_calibration_full(void);
#define CALTIMING9_CFG_4_ACT_TO_ACT(x) \
(((x) >> 0) & 0xFF)
+/* Firewall DDR scheduler MPFE */
+#define FW_HMC_ADAPTOR_REG_ADDR 0xf8020004
+#define FW_HMC_ADAPTOR_MPU_MASK BIT(0)
+
#endif /* _SDRAM_S10_H_ */
diff --git a/drivers/ddr/altera/sdram_s10.c b/drivers/ddr/altera/sdram_s10.c
index 462c8feaefe..e4d4a02ca2c 100644
--- a/drivers/ddr/altera/sdram_s10.c
+++ b/drivers/ddr/altera/sdram_s10.c
@@ -23,6 +23,8 @@ static const struct socfpga_system_manager *sysmgr_regs =
#define DDR_CONFIG(A, B, C, R) (((A) << 24) | ((B) << 16) | ((C) << 8) | (R))
+#define PGTABLE_OFF 0x4000
+
/* The followring are the supported configurations */
u32 ddr_config[] = {
/* DDR_CONFIG(Address order,Bank,Column,Row) */
@@ -136,6 +138,76 @@ static int poll_hmc_clock_status(void)
SYSMGR_HMC_CLK_STATUS_MSK, true, 1000, false);
}
+static void sdram_clear_mem(phys_addr_t addr, phys_size_t size)
+{
+ phys_size_t i;
+
+ if (addr % CONFIG_SYS_CACHELINE_SIZE) {
+ printf("DDR: address 0x%llx is not cacheline size aligned.\n",
+ addr);
+ hang();
+ }
+
+ if (size % CONFIG_SYS_CACHELINE_SIZE) {
+ printf("DDR: size 0x%llx is not multiple of cacheline size\n",
+ size);
+ hang();
+ }
+
+ /* Use DC ZVA instruction to clear memory to zeros by a cache line */
+ for (i = 0; i < size; i = i + CONFIG_SYS_CACHELINE_SIZE) {
+ asm volatile("dc zva, %0"
+ :
+ : "r"(addr)
+ : "memory");
+ addr += CONFIG_SYS_CACHELINE_SIZE;
+ }
+}
+
+static void sdram_init_ecc_bits(bd_t *bd)
+{
+ phys_size_t size, size_init;
+ phys_addr_t start_addr;
+ int bank = 0;
+ unsigned int start = get_timer(0);
+
+ icache_enable();
+
+ start_addr = bd->bi_dram[0].start;
+ size = bd->bi_dram[0].size;
+
+ /* Initialize small block for page table */
+ memset((void *)start_addr, 0, PGTABLE_SIZE + PGTABLE_OFF);
+ gd->arch.tlb_addr = start_addr + PGTABLE_OFF;
+ gd->arch.tlb_size = PGTABLE_SIZE;
+ start_addr += PGTABLE_SIZE + PGTABLE_OFF;
+ size -= (PGTABLE_OFF + PGTABLE_SIZE);
+ dcache_enable();
+
+ while (1) {
+ while (size) {
+ size_init = min((phys_addr_t)SZ_1G, (phys_addr_t)size);
+ sdram_clear_mem(start_addr, size_init);
+ size -= size_init;
+ start_addr += size_init;
+ WATCHDOG_RESET();
+ }
+
+ bank++;
+ if (bank >= CONFIG_NR_DRAM_BANKS)
+ break;
+
+ start_addr = bd->bi_dram[bank].start;
+ size = bd->bi_dram[bank].size;
+ }
+
+ dcache_disable();
+ icache_disable();
+
+ printf("SDRAM-ECC: Initialized success with %d ms\n",
+ (unsigned int)get_timer(start));
+}
+
static void sdram_size_check(bd_t *bd)
{
phys_size_t total_ram_check = 0;
@@ -400,6 +472,15 @@ int sdram_mmr_init_full(unsigned int unused)
setbits_le32(SOCFPGA_SDR_ADDRESS + ECCCTRL2,
(DDR_HMC_ECCCTL2_RMW_EN_SET_MSK |
DDR_HMC_ECCCTL2_AWB_EN_SET_MSK));
+ writel(DDR_HMC_ERRINTEN_INTMASK,
+ SOCFPGA_SDR_ADDRESS + ERRINTENS);
+
+ /* Enable non-secure writes to HMC Adapter for SDRAM ECC */
+ writel(FW_HMC_ADAPTOR_MPU_MASK, FW_HMC_ADAPTOR_REG_ADDR);
+
+ /* Initialize memory content if not from warm reset */
+ if (!cpu_has_been_warmreset())
+ sdram_init_ecc_bits(&bd);
} else {
clrbits_le32(SOCFPGA_SDR_ADDRESS + ECCCTRL1,
(DDR_HMC_ECCCTL_AWB_CNT_RST_SET_MSK |