[U-Boot] [PATCH v2 12/14] ddr: altera: stratix10: Add DDR support for Stratix10 SoC
Dinh Nguyen
dinh.linux at gmail.com
Wed Oct 11 20:46:14 UTC 2017
On Thu, Oct 5, 2017 at 8:07 AM, <chin.liang.see at intel.com> wrote:
> From: Chin Liang See <chin.liang.see at intel.com>
>
> Add DDR support for Stratix SoC
>
> Signed-off-by: Chin Liang See <chin.liang.see at 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
More information about the U-Boot
mailing list