[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