On Thu, Oct 5, 2017 at 8:07 AM, <chin.liang....@intel.com> wrote: > From: Chin Liang See <chin.liang....@intel.com> > > Add DDR support for Stratix SoC > > Signed-off-by: Chin Liang See <chin.liang....@intel.com> > --- > arch/arm/mach-socfpga/include/mach/sdram_s10.h | 333 +++++++++++++++++++++ > drivers/ddr/altera/Makefile | 1 + > drivers/ddr/altera/sdram_s10.c | 382 > +++++++++++++++++++++++++ > 3 files changed, 716 insertions(+) > create mode 100644 arch/arm/mach-socfpga/include/mach/sdram_s10.h > create mode 100644 drivers/ddr/altera/sdram_s10.c > > diff --git a/arch/arm/mach-socfpga/include/mach/sdram_s10.h > b/arch/arm/mach-socfpga/include/mach/sdram_s10.h > new file mode 100644 > index 0000000..d0fd958
[...] > diff --git a/drivers/ddr/altera/Makefile b/drivers/ddr/altera/Makefile > index bdd2872..943b6cd 100644 > --- a/drivers/ddr/altera/Makefile > +++ b/drivers/ddr/altera/Makefile > @@ -10,4 +10,5 @@ > > ifdef CONFIG_ALTERA_SDRAM > obj-$(CONFIG_TARGET_SOCFPGA_GEN5) += sdram.o sequencer.o > +obj-$(CONFIG_TARGET_SOCFPGA_STRATIX10) += sdram_s10.o > endif > diff --git a/drivers/ddr/altera/sdram_s10.c b/drivers/ddr/altera/sdram_s10.c > new file mode 100644 > index 0000000..c488caf > --- /dev/null > +++ b/drivers/ddr/altera/sdram_s10.c > @@ -0,0 +1,382 @@ > +/* > + * Copyright (C) 2016-2017 Intel Corporation <www.intel.com> > + * > + * SPDX-License-Identifier: GPL-2.0 > + */ > + > +#include <common.h> > +#include <errno.h> > +#include <div64.h> > +#include <asm/io.h> > +#include <watchdog.h> > +#include <asm/arch/sdram_s10.h> > +#include <asm/arch/system_manager.h> > +#include <asm/arch/reset_manager.h> > + > +DECLARE_GLOBAL_DATA_PTR; > + > +static const struct socfpga_ecc_hmc *socfpga_ecc_hmc_base = > + (void *)SOCFPGA_SDR_ADDRESS; > +static const struct socfpga_noc_ddr_scheduler > *socfpga_noc_ddr_scheduler_base = > + (void *)SOCFPGA_SDR_SCHEDULER_ADDRESS; > +static const struct socfpga_io48_mmr *socfpga_io48_mmr_base = > + (void *)SOCFPGA_HMC_MMR_IO48_ADDRESS; > +static const struct socfpga_system_manager *sysmgr_regs = > + (void *)SOCFPGA_SYSMGR_ADDRESS; > + > +#define DDR_CONFIG(A, B, C, R) ((A<<24)|(B<<16)|(C<<8)|R) > + > +/* The followring are the supported configurations */ > +u32 ddr_config[] = { > + /* DDR_CONFIG(Address order,Bank,Column,Row) */ > + /* List for DDR3 or LPDDR3 (pinout order > chip, row, bank, column) */ > + DDR_CONFIG(0, 3, 10, 12), > + DDR_CONFIG(0, 3, 9, 13), > + DDR_CONFIG(0, 3, 10, 13), > + DDR_CONFIG(0, 3, 9, 14), > + DDR_CONFIG(0, 3, 10, 14), > + DDR_CONFIG(0, 3, 10, 15), > + DDR_CONFIG(0, 3, 11, 14), > + DDR_CONFIG(0, 3, 11, 15), > + DDR_CONFIG(0, 3, 10, 16), > + DDR_CONFIG(0, 3, 11, 16), > + DDR_CONFIG(0, 3, 12, 15), /* 0xa */ > + /* List for DDR4 only (pinout order > chip, bank, row, column) */ > + DDR_CONFIG(1, 3, 10, 14), > + DDR_CONFIG(1, 4, 10, 14), > + DDR_CONFIG(1, 3, 10, 15), > + DDR_CONFIG(1, 4, 10, 15), > + DDR_CONFIG(1, 3, 10, 16), > + DDR_CONFIG(1, 4, 10, 16), > + DDR_CONFIG(1, 3, 10, 17), > + DDR_CONFIG(1, 4, 10, 17), > +}; > + > +#define DDR_CONFIG_ELEMENTS (sizeof(ddr_config)/sizeof(u32)) > + > +int match_ddr_conf(u32 ddr_conf) Should be static. > +{ > + int i; > + for (i = 0; i < DDR_CONFIG_ELEMENTS; i++) { > + if (ddr_conf == ddr_config[i]) > + return i; > + } > + return 0; > +} > + > +static int emif_clear(void) > +{ > + u32 s2c, i; > + > + writel(0, &socfpga_ecc_hmc_base->rsthandshakectrl); > + s2c = readl(&socfpga_ecc_hmc_base->rsthandshakestat) & > + DDR_HMC_RSTHANDSHAKE_MASK; > + > + for (i = 1000; (i > 0) && s2c; i--) { > + WATCHDOG_RESET(); > + mdelay(1); > + s2c = readl(&socfpga_ecc_hmc_base->rsthandshakestat) & > + DDR_HMC_RSTHANDSHAKE_MASK; > + } > + return !s2c; > +} > + > +static int emif_reset(void) What's the return used for? I don't see the callers of emif_reset checking the return values at all. > +{ > + u32 c2s, s2c, i; > + > + c2s = readl(&socfpga_ecc_hmc_base->rsthandshakectrl) & > + DDR_HMC_RSTHANDSHAKE_MASK; > + s2c = readl(&socfpga_ecc_hmc_base->rsthandshakestat) & > + DDR_HMC_RSTHANDSHAKE_MASK; > + > + debug("DDR: c2s=%08x s2c=%08x nr0=%08x nr1=%08x nr2=%08x dst=%08x\n", > + c2s, s2c, readl(&socfpga_io48_mmr_base->niosreserve0), > + readl(&socfpga_io48_mmr_base->niosreserve1), > + readl(&socfpga_io48_mmr_base->niosreserve2), > + readl(&socfpga_io48_mmr_base->dramsts)); > + > + if (s2c && emif_clear()) { > + printf("DDR: emif_clear() failed\n"); > + return -1; > + } > + > + puts("DDR: Triggerring emif_reset\n"); > + writel(DDR_HMC_CORE2SEQ_INT_REQ, > + &socfpga_ecc_hmc_base->rsthandshakectrl); > + > + for (i = 1000; i > 0; i--) { > + /* if seq2core[3] = 0, we are good */ > + if (!(readl(&socfpga_ecc_hmc_base->rsthandshakestat) & > + DDR_HMC_SEQ2CORE_INT_RESP_MASK)) > + break; > + WATCHDOG_RESET(); > + mdelay(1); > + } > + > + if (!i) { > + printf("DDR: failed to get ack from EMIF\n"); > + return -2; > + } > + > + if (emif_clear()) { > + printf("DDR: emif_clear() failed\n"); > + return -3; > + } > + > + printf("DDR: emif_reset triggered successly\n"); > + return 0; > +} > + > +static int poll_hmc_clock_status(void) > +{ > + u32 status, i; > + > + for (i = 1000; i > 0; i--) { > + status = readl(&sysmgr_regs->hmc_clk) & > + SYSMGR_HMC_CLK_STATUS_MSK; > + udelay(1); > + if (status) > + break; > + WATCHDOG_RESET(); > + } > + return status; > +} > + > +/** > + * sdram_mmr_init_full() - Function to initialize SDRAM MMR > + * > + * Initialize the SDRAM MMR. Remove extra comment that says the same thing. > + */ > +int sdram_mmr_init_full(unsigned int unused) > +{ > + u32 update_value, io48_value, ddrioctl; > + u32 i, j, cal_success; > + > + /* Enable access to DDR from CPU master */ > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_DDRREG_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE0_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE1A_ADDR, > CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE1B_ADDR, > CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE1C_ADDR, > CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE1D_ADDR, > CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_CPU0_MPRT_ADBASE_MEMSPACE1E_ADDR, > CCU_ADBASE_DI_MASK); > + > + /* Enable access to DDR from IO master */ > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE0_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE1A_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE1B_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE1C_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE1D_ADDR, CCU_ADBASE_DI_MASK); > + clrbits_le32(CCU_IOM_MPRT_ADBASE_MEMSPACE1E_ADDR, CCU_ADBASE_DI_MASK); > + > + /* this enables nonsecure access to DDR */ > + /* mpuregion0addr_limit */ > + writel(0xFFFF0000, 0xF8020118); > + writel(0x1F, 0xF802011c); > + > + /* nonmpuregion0addr_limit */ > + writel(0xFFFF0000, 0xF8020198); > + writel(0x1F, 0xF802019C); > + > + /* Enable mpuregion0enable and nonmpuregion0enable */ > + writel(BIT(0) | BIT(8), 0xF8020100); Add defines for the above addresses please. > + > + /* Ensure HMC clock is running */ > + if (!poll_hmc_clock_status()) { > + puts("DDR: Error as HMC clock not running\n"); > + return -1; Use a valid error code... > + } > + > + /* release DDR scheduler from reset */ > + socfpga_per_reset(SOCFPGA_RESET(SDR), 0); > + > + /* Try 3 times to do a calibration */ > + for (i = 0; i < 3; i++) { > + cal_success = readl(&socfpga_ecc_hmc_base->ddrcalstat) & > + DDR_HMC_DDRCALSTAT_CAL_MSK; > + /* A delay to wait for calibration bit to set */ > + for (j = 0; (j < 1000) && !cal_success; j++) { > + WATCHDOG_RESET(); > + mdelay(1); > + cal_success = readl(&socfpga_ecc_hmc_base->ddrcalstat) > + & DDR_HMC_DDRCALSTAT_CAL_MSK; > + } > + > + if (cal_success) > + break; > + else > + emif_reset(); > + } > + > + if (!cal_success) { > + puts("DDR: Error as SDRAM calibration failed\n"); > + return -1; Use a valid error code.. Dinh _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot