summaryrefslogtreecommitdiff
path: root/drivers/ddr
diff options
context:
space:
mode:
authorSimon Goldschmidt <simon.k.r.goldschmidt@gmail.com>2019-04-16 22:04:39 +0200
committerMarek Vasut <marex@denx.de>2019-04-17 22:20:16 +0200
commit29873c74f367474faafd16376e2a9f404172fbdd (patch)
tree774cc94f1d909f9046eea4b233d772572e5fad8b /drivers/ddr
parentede6e7b64fbd3beef691f526d14e088583f74472 (diff)
downloadu-boot-29873c74f367474faafd16376e2a9f404172fbdd.tar.gz
u-boot-29873c74f367474faafd16376e2a9f404172fbdd.tar.bz2
u-boot-29873c74f367474faafd16376e2a9f404172fbdd.zip
arm: socfpga: move gen5 SDR driver to DM
To clean up reset handling for socfpga gen5, port the DDR driver to DM using UCLASS_RAM and implement proper reset handling. This gets us rid of one ad-hoc call to socfpga_per_reset(). The gen5 driver is implemented in 2 distinct files. One of it (containing the calibration training) is not touched much and is kept at using hard coded addresses since the code grows even more otherwise. SPL is changed from calling hard into the DDR driver code to just probing UCLASS_RESET and UCLASS_RAM. It is happy after finding a RAM driver after that. Signed-off-by: Simon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Diffstat (limited to 'drivers/ddr')
-rw-r--r--drivers/ddr/altera/Kconfig2
-rw-r--r--drivers/ddr/altera/sdram_gen5.c143
-rw-r--r--drivers/ddr/altera/sequencer.c9
-rw-r--r--drivers/ddr/altera/sequencer.h35
4 files changed, 173 insertions, 16 deletions
diff --git a/drivers/ddr/altera/Kconfig b/drivers/ddr/altera/Kconfig
index 2b28a97f6e..8f60b56eb8 100644
--- a/drivers/ddr/altera/Kconfig
+++ b/drivers/ddr/altera/Kconfig
@@ -1,5 +1,7 @@
config ALTERA_SDRAM
bool "SoCFPGA DDR SDRAM driver"
depends on TARGET_SOCFPGA_GEN5 || TARGET_SOCFPGA_ARRIA10
+ select RAM if TARGET_SOCFPGA_GEN5
+ select SPL_RAM if TARGET_SOCFPGA_GEN5
help
Enable DDR SDRAM controller for the SoCFPGA devices.
diff --git a/drivers/ddr/altera/sdram_gen5.c b/drivers/ddr/altera/sdram_gen5.c
index 821060459c..fcd89b619d 100644
--- a/drivers/ddr/altera/sdram_gen5.c
+++ b/drivers/ddr/altera/sdram_gen5.c
@@ -3,14 +3,30 @@
* Copyright Altera Corporation (C) 2014-2015
*/
#include <common.h>
+#include <dm.h>
#include <errno.h>
#include <div64.h>
+#include <ram.h>
+#include <reset.h>
#include <watchdog.h>
#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
#include <asm/arch/sdram.h>
#include <asm/arch/system_manager.h>
#include <asm/io.h>
+#include "sequencer.h"
+
+#ifdef CONFIG_SPL_BUILD
+
+struct altera_gen5_sdram_priv {
+ struct ram_info info;
+};
+
+struct altera_gen5_sdram_platdata {
+ struct socfpga_sdr *sdr;
+};
+
struct sdram_prot_rule {
u32 sdram_start; /* SDRAM start address */
u32 sdram_end; /* SDRAM end address */
@@ -26,8 +42,8 @@ struct sdram_prot_rule {
static struct socfpga_system_manager *sysmgr_regs =
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
-static struct socfpga_sdr_ctrl *sdr_ctrl =
- (struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS;
+
+static unsigned long sdram_calculate_size(struct socfpga_sdr_ctrl *sdr_ctrl);
/**
* get_errata_rows() - Up the number of DRAM rows to cover entire address space
@@ -104,7 +120,8 @@ static int get_errata_rows(const struct socfpga_sdram_config *cfg)
}
/* SDRAM protection rules vary from 0-19, a total of 20 rules. */
-static void sdram_set_rule(struct sdram_prot_rule *prule)
+static void sdram_set_rule(struct socfpga_sdr_ctrl *sdr_ctrl,
+ struct sdram_prot_rule *prule)
{
u32 lo_addr_bits;
u32 hi_addr_bits;
@@ -141,7 +158,8 @@ static void sdram_set_rule(struct sdram_prot_rule *prule)
writel(0, &sdr_ctrl->prot_rule_rdwr);
}
-static void sdram_get_rule(struct sdram_prot_rule *prule)
+static void sdram_get_rule(struct socfpga_sdr_ctrl *sdr_ctrl,
+ struct sdram_prot_rule *prule)
{
u32 addr;
u32 id;
@@ -172,7 +190,8 @@ static void sdram_get_rule(struct sdram_prot_rule *prule)
}
static void
-sdram_set_protection_config(const u32 sdram_start, const u32 sdram_end)
+sdram_set_protection_config(struct socfpga_sdr_ctrl *sdr_ctrl,
+ const u32 sdram_start, const u32 sdram_end)
{
struct sdram_prot_rule rule;
int rules;
@@ -185,7 +204,7 @@ sdram_set_protection_config(const u32 sdram_start, const u32 sdram_end)
for (rules = 0; rules < 20; rules++) {
rule.rule = rules;
- sdram_set_rule(&rule);
+ sdram_set_rule(sdr_ctrl, &rule);
}
/* new rule: accept SDRAM */
@@ -200,13 +219,13 @@ sdram_set_protection_config(const u32 sdram_start, const u32 sdram_end)
rule.rule = 0;
/* set new rule */
- sdram_set_rule(&rule);
+ sdram_set_rule(sdr_ctrl, &rule);
/* default rule: reject everything */
writel(0x3ff, &sdr_ctrl->protport_default);
}
-static void sdram_dump_protection_config(void)
+static void sdram_dump_protection_config(struct socfpga_sdr_ctrl *sdr_ctrl)
{
struct sdram_prot_rule rule;
int rules;
@@ -216,7 +235,7 @@ static void sdram_dump_protection_config(void)
for (rules = 0; rules < 20; rules++) {
rule.rule = rules;
- sdram_get_rule(&rule);
+ sdram_get_rule(sdr_ctrl, &rule);
debug("Rule %d, rules ...\n", rules);
debug(" sdram start %x\n", rule.sdram_start);
debug(" sdram end %x\n", rule.sdram_end);
@@ -322,7 +341,8 @@ static u32 sdr_get_addr_rw(const struct socfpga_sdram_config *cfg)
*
* This function loads the register values into the SDRAM controller block.
*/
-static void sdr_load_regs(const struct socfpga_sdram_config *cfg)
+static void sdr_load_regs(struct socfpga_sdr_ctrl *sdr_ctrl,
+ const struct socfpga_sdram_config *cfg)
{
const u32 ctrl_cfg = sdr_get_ctrlcfg(cfg);
const u32 dram_addrw = sdr_get_addr_rw(cfg);
@@ -426,7 +446,8 @@ static void sdr_load_regs(const struct socfpga_sdram_config *cfg)
*
* Initialize the SDRAM MMR.
*/
-int sdram_mmr_init_full(unsigned int sdr_phy_reg)
+int sdram_mmr_init_full(struct socfpga_sdr_ctrl *sdr_ctrl,
+ unsigned int sdr_phy_reg)
{
const struct socfpga_sdram_config *cfg = socfpga_get_sdram_config();
const unsigned int rows =
@@ -436,7 +457,7 @@ int sdram_mmr_init_full(unsigned int sdr_phy_reg)
writel(rows, &sysmgr_regs->iswgrp_handoff[4]);
- sdr_load_regs(cfg);
+ sdr_load_regs(sdr_ctrl, cfg);
/* saving this value to SYSMGR.ISWGRP.HANDOFF.FPGA2SDR */
writel(cfg->fpgaport_rst, &sysmgr_regs->iswgrp_handoff[3]);
@@ -459,9 +480,10 @@ int sdram_mmr_init_full(unsigned int sdr_phy_reg)
SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK,
1 << SDR_CTRLGRP_STATICCFG_APPLYCFG_LSB);
- sdram_set_protection_config(0, sdram_calculate_size() - 1);
+ sdram_set_protection_config(sdr_ctrl, 0,
+ sdram_calculate_size(sdr_ctrl) - 1);
- sdram_dump_protection_config();
+ sdram_dump_protection_config(sdr_ctrl);
return 0;
}
@@ -472,7 +494,7 @@ int sdram_mmr_init_full(unsigned int sdr_phy_reg)
* Calculate SDRAM device size based on SDRAM controller parameters.
* Size is specified in bytes.
*/
-unsigned long sdram_calculate_size(void)
+static unsigned long sdram_calculate_size(struct socfpga_sdr_ctrl *sdr_ctrl)
{
unsigned long temp;
unsigned long row, bank, col, cs, width;
@@ -534,3 +556,94 @@ unsigned long sdram_calculate_size(void)
return temp;
}
+
+static int altera_gen5_sdram_ofdata_to_platdata(struct udevice *dev)
+{
+ struct altera_gen5_sdram_platdata *plat = dev->platdata;
+
+ plat->sdr = (struct socfpga_sdr *)devfdt_get_addr_index(dev, 0);
+ if (!plat->sdr)
+ return -ENODEV;
+
+ return 0;
+}
+
+static int altera_gen5_sdram_probe(struct udevice *dev)
+{
+ int ret;
+ unsigned long sdram_size;
+ struct altera_gen5_sdram_platdata *plat = dev->platdata;
+ struct altera_gen5_sdram_priv *priv = dev_get_priv(dev);
+ struct socfpga_sdr_ctrl *sdr_ctrl = &plat->sdr->sdr_ctrl;
+ struct reset_ctl_bulk resets;
+
+ ret = reset_get_bulk(dev, &resets);
+ if (ret) {
+ dev_err(dev, "Can't get reset: %d\n", ret);
+ return -ENODEV;
+ }
+ reset_deassert_bulk(&resets);
+
+ if (sdram_mmr_init_full(sdr_ctrl, 0xffffffff) != 0) {
+ puts("SDRAM init failed.\n");
+ goto failed;
+ }
+
+ debug("SDRAM: Calibrating PHY\n");
+ /* SDRAM calibration */
+ if (sdram_calibration_full(plat->sdr) == 0) {
+ puts("SDRAM calibration failed.\n");
+ goto failed;
+ }
+
+ sdram_size = sdram_calculate_size(sdr_ctrl);
+ debug("SDRAM: %ld MiB\n", sdram_size >> 20);
+
+ /* Sanity check ensure correct SDRAM size specified */
+ if (get_ram_size(0, sdram_size) != sdram_size) {
+ puts("SDRAM size check failed!\n");
+ goto failed;
+ }
+
+ priv->info.base = 0;
+ priv->info.size = sdram_size;
+
+ return 0;
+
+failed:
+ reset_release_bulk(&resets);
+ return -ENODEV;
+}
+
+static int altera_gen5_sdram_get_info(struct udevice *dev,
+ struct ram_info *info)
+{
+ struct altera_gen5_sdram_priv *priv = dev_get_priv(dev);
+
+ info->base = priv->info.base;
+ info->size = priv->info.size;
+
+ return 0;
+}
+
+static struct ram_ops altera_gen5_sdram_ops = {
+ .get_info = altera_gen5_sdram_get_info,
+};
+
+static const struct udevice_id altera_gen5_sdram_ids[] = {
+ { .compatible = "altr,sdr-ctl" },
+ { /* sentinel */ }
+};
+
+U_BOOT_DRIVER(altera_gen5_sdram) = {
+ .name = "altr_sdr_ctl",
+ .id = UCLASS_RAM,
+ .of_match = altera_gen5_sdram_ids,
+ .ops = &altera_gen5_sdram_ops,
+ .ofdata_to_platdata = altera_gen5_sdram_ofdata_to_platdata,
+ .platdata_auto_alloc_size = sizeof(struct altera_gen5_sdram_platdata),
+ .probe = altera_gen5_sdram_probe,
+ .priv_auto_alloc_size = sizeof(struct altera_gen5_sdram_priv),
+};
+
+#endif /* CONFIG_SPL_BUILD */
diff --git a/drivers/ddr/altera/sequencer.c b/drivers/ddr/altera/sequencer.c
index 5e7a943b68..0e4526288e 100644
--- a/drivers/ddr/altera/sequencer.c
+++ b/drivers/ddr/altera/sequencer.c
@@ -3705,12 +3705,19 @@ static void initialize_tracking(void)
&sdr_reg_file->trk_rfsh);
}
-int sdram_calibration_full(void)
+int sdram_calibration_full(struct socfpga_sdr *sdr)
{
struct param_type my_param;
struct gbl_type my_gbl;
u32 pass;
+ /*
+ * For size reasons, this file uses hard coded addresses.
+ * Check if we are called with the correct address.
+ */
+ if (sdr != (struct socfpga_sdr *)SOCFPGA_SDR_ADDRESS)
+ return -ENODEV;
+
memset(&my_param, 0, sizeof(my_param));
memset(&my_gbl, 0, sizeof(my_gbl));
diff --git a/drivers/ddr/altera/sequencer.h b/drivers/ddr/altera/sequencer.h
index a5760b03a5..d7f6935201 100644
--- a/drivers/ddr/altera/sequencer.h
+++ b/drivers/ddr/altera/sequencer.h
@@ -223,4 +223,39 @@ struct socfpga_data_mgr {
u32 mem_t_add;
u32 t_rl_add;
};
+
+/* This struct describes the controller @ SOCFPGA_SDR_ADDRESS */
+struct socfpga_sdr {
+ /* SDR_PHYGRP_SCCGRP_ADDRESS */
+ u8 _align1[0xe00];
+ /* SDR_PHYGRP_SCCGRP_ADDRESS | 0xe00 */
+ struct socfpga_sdr_scc_mgr sdr_scc_mgr;
+ u8 _align2[0x1bc];
+ /* SDR_PHYGRP_PHYMGRGRP_ADDRESS */
+ struct socfpga_phy_mgr_cmd phy_mgr_cmd;
+ u8 _align3[0x2c];
+ /* SDR_PHYGRP_PHYMGRGRP_ADDRESS | 0x40 */
+ struct socfpga_phy_mgr_cfg phy_mgr_cfg;
+ u8 _align4[0xfa0];
+ /* SDR_PHYGRP_RWMGRGRP_ADDRESS */
+ u8 rwmgr_grp[0x800];
+ /* SDR_PHYGRP_RWMGRGRP_ADDRESS | 0x800 */
+ struct socfpga_sdr_rw_load_manager sdr_rw_load_mgr_regs;
+ u8 _align5[0x3f0];
+ /* SDR_PHYGRP_RWMGRGRP_ADDRESS | 0xC00 */
+ struct socfpga_sdr_rw_load_jump_manager sdr_rw_load_jump_mgr_regs;
+ u8 _align6[0x13f0];
+ /* SDR_PHYGRP_DATAMGRGRP_ADDRESS */
+ struct socfpga_data_mgr data_mgr;
+ u8 _align7[0x7f0];
+ /* SDR_PHYGRP_REGFILEGRP_ADDRESS */
+ struct socfpga_sdr_reg_file sdr_reg_file;
+ u8 _align8[0x7c8];
+ /* SDR_CTRLGRP_ADDRESS */
+ struct socfpga_sdr_ctrl sdr_ctrl;
+ u8 _align9[0xea4];
+};
+
+int sdram_calibration_full(struct socfpga_sdr *sdr);
+
#endif /* _SEQUENCER_H_ */