arm: socfpga: move gen5 SDR driver to DM
authorSimon Goldschmidt <simon.k.r.goldschmidt@gmail.com>
Tue, 16 Apr 2019 20:04:39 +0000 (22:04 +0200)
committerMarek Vasut <marex@denx.de>
Wed, 17 Apr 2019 20:20:16 +0000 (22:20 +0200)
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>
arch/arm/dts/socfpga.dtsi
arch/arm/mach-socfpga/include/mach/sdram_gen5.h
arch/arm/mach-socfpga/spl_gen5.c
drivers/ddr/altera/Kconfig
drivers/ddr/altera/sdram_gen5.c
drivers/ddr/altera/sequencer.c
drivers/ddr/altera/sequencer.h

index ec1966480f2f0376522bda05d1e7347821238a46..51a6a51b5380e920b6db44e095b096fbfbca81a5 100644 (file)
                        reg = <0xfffec000 0x100>;
                };
 
-               sdr: sdr@ffc25000 {
+               sdr: sdr@ffc20000 {
                        compatible = "altr,sdr-ctl", "syscon";
-                       reg = <0xffc25000 0x1000>;
+                       reg = <0xffc20000 0x6000>;
                        resets = <&rst SDR_RESET>;
                };
 
index a238d5d17fe92a1f2dbe390b33fc9f0ffc278e74..c41208591a1f03523afe8e9155bbafd3fde12c44 100644 (file)
@@ -7,10 +7,6 @@
 
 #ifndef __ASSEMBLY__
 
-unsigned long sdram_calculate_size(void);
-int sdram_mmr_init_full(unsigned int sdr_phy_reg);
-int sdram_calibration_full(void);
-
 const struct socfpga_sdram_config *socfpga_get_sdram_config(void);
 
 void socfpga_get_seq_ac_init(const u32 **init, unsigned int *nelem);
index 142b60f887d3edce87ba0fdad105b54a086c8388..c5399bb69792c40e64b636c47d1b585dbcd39f6d 100644 (file)
@@ -21,6 +21,7 @@
 #include <debug_uart.h>
 #include <fdtdec.h>
 #include <watchdog.h>
+#include <dm/uclass.h>
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -123,9 +124,9 @@ static void socfpga_pl310_clear(void)
 void board_init_f(ulong dummy)
 {
        const struct cm_config *cm_default_cfg = cm_get_default_config();
-       unsigned long sdram_size;
        unsigned long reg;
        int ret;
+       struct udevice *dev;
 
        /*
         * First C code to run. Clear fake OCRAM ECC first as SBE
@@ -156,7 +157,6 @@ void board_init_f(ulong dummy)
                socfpga_bridges_reset(1);
        }
 
-       socfpga_per_reset(SOCFPGA_RESET(SDR), 0);
        socfpga_per_reset(SOCFPGA_RESET(UART0), 0);
        socfpga_per_reset(SOCFPGA_RESET(OSC1TIMER0), 0);
 
@@ -200,27 +200,16 @@ void board_init_f(ulong dummy)
                hang();
        }
 
+       ret = uclass_get_device(UCLASS_RESET, 0, &dev);
+       if (ret)
+               debug("Reset init failed: %d\n", ret);
+
        /* enable console uart printing */
        preloader_console_init();
 
-       if (sdram_mmr_init_full(0xffffffff) != 0) {
-               puts("SDRAM init failed.\n");
-               hang();
-       }
-
-       debug("SDRAM: Calibrating PHY\n");
-       /* SDRAM calibration */
-       if (sdram_calibration_full() == 0) {
-               puts("SDRAM calibration failed.\n");
-               hang();
-       }
-
-       sdram_size = sdram_calculate_size();
-       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");
+       ret = uclass_get_device(UCLASS_RAM, 0, &dev);
+       if (ret) {
+               debug("DRAM init failed: %d\n", ret);
                hang();
        }
 
index 2b28a97f6e7fb866fcfeea65e97eeef4065882ef..8f60b56eb84886f534e663373ffff2e392612e1d 100644 (file)
@@ -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.
index 821060459cf143af860ef749666f71af9f90772c..fcd89b619dbe2bf5e7ab379170891c3bb52e21c3 100644 (file)
@@ -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 */
index 5e7a943b680c9b0a8776e064655c98c61d862768..0e4526288e2aaec22c56b09121381e78c3b4af03 100644 (file)
@@ -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));
 
index a5760b03a55bb0113cc8bfc89d2368088868b12d..d7f6935201fdad5210b9e0e4ee8528255eaa3bde 100644 (file)
@@ -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_ */