diff options
-rw-r--r-- | arch/arm/dts/socfpga.dtsi | 4 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/include/mach/sdram_gen5.h | 4 | ||||
-rw-r--r-- | arch/arm/mach-socfpga/spl_gen5.c | 29 | ||||
-rw-r--r-- | drivers/ddr/altera/Kconfig | 2 | ||||
-rw-r--r-- | drivers/ddr/altera/sdram_gen5.c | 143 | ||||
-rw-r--r-- | drivers/ddr/altera/sequencer.c | 9 | ||||
-rw-r--r-- | drivers/ddr/altera/sequencer.h | 35 |
7 files changed, 184 insertions, 42 deletions
diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi index ec1966480f..51a6a51b53 100644 --- a/arch/arm/dts/socfpga.dtsi +++ b/arch/arm/dts/socfpga.dtsi @@ -791,9 +791,9 @@ reg = <0xfffec000 0x100>; }; - sdr: sdr@ffc25000 { + sdr: sdr@ffc20000 { compatible = "altr,sdr-ctl", "syscon"; - reg = <0xffc25000 0x1000>; + reg = <0xffc20000 0x6000>; resets = <&rst SDR_RESET>; }; diff --git a/arch/arm/mach-socfpga/include/mach/sdram_gen5.h b/arch/arm/mach-socfpga/include/mach/sdram_gen5.h index a238d5d17f..c41208591a 100644 --- a/arch/arm/mach-socfpga/include/mach/sdram_gen5.h +++ b/arch/arm/mach-socfpga/include/mach/sdram_gen5.h @@ -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); diff --git a/arch/arm/mach-socfpga/spl_gen5.c b/arch/arm/mach-socfpga/spl_gen5.c index 142b60f887..c5399bb697 100644 --- a/arch/arm/mach-socfpga/spl_gen5.c +++ b/arch/arm/mach-socfpga/spl_gen5.c @@ -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(); } 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_ */ |