[U-Boot] [RFCv2] mainline u-boot on socfpga
Pavel Machek
pavel at denx.de
Mon Sep 8 14:08:45 CEST 2014
Hi!
I know coding style leaves something to be desired.
But.. it recognizes MMC/ethernet, and can load linux kernel.
Unfortunately, 1MB of memory at 0 is not available for some reason;
but linux works ok if you avoid that area.
"fpga load 0" now seems to work.
For some reason, I had to rewrite fpgamgr_axi_write(). There's some
bug in assembly version, causing code to get confused after it is
executed.
If some ARM expert could take a look, that would be great; bug is
likely also present in rocketboards version of u-boot.
Best regards,
Pavel
diff --git a/arch/arm/cpu/armv7/socfpga/Makefile b/arch/arm/cpu/armv7/socfpga/Makefile
index eb33f2c..c36e0d0 100644
--- a/arch/arm/cpu/armv7/socfpga/Makefile
+++ b/arch/arm/cpu/armv7/socfpga/Makefile
@@ -10,3 +10,4 @@
obj-y := lowlevel_init.o
obj-y += misc.o timer.o reset_manager.o system_manager.o clock_manager.o
obj-$(CONFIG_SPL_BUILD) += spl.o freeze_controller.o scan_manager.o
+obj-y += fpga_manager.o
diff --git a/arch/arm/cpu/armv7/socfpga/clock_manager.c b/arch/arm/cpu/armv7/socfpga/clock_manager.c
index 158501a..fae5724 100644
--- a/arch/arm/cpu/armv7/socfpga/clock_manager.c
+++ b/arch/arm/cpu/armv7/socfpga/clock_manager.c
@@ -30,6 +30,10 @@ static const struct socfpga_clock_manager *clock_manager_base =
CLKMGR_MAINPLLGRP_VCO_EN_SET(1)| \
CLKMGR_MAINPLLGRP_VCO_BGPWRDN_SET(0))
+unsigned long cm_l4_sp_clock;
+unsigned long cm_sdmmc_clock;
+unsigned long cm_qspi_clock;
+
static inline void cm_wait_for_lock(uint32_t mask)
{
register uint32_t inter_val;
@@ -358,3 +362,219 @@ void cm_basic_init(const cm_config_t *cfg)
writel(~0, &clock_manager_base->per_pll.en);
writel(~0, &clock_manager_base->sdr_pll.en);
}
+
+#define CLKMGR_CTRL_ADDRESS 0x0
+#define CLKMGR_BYPASS_ADDRESS 0x4
+#define CLKMGR_INTER_ADDRESS 0x8
+#define CLKMGR_INTREN_ADDRESS 0xc
+#define CLKMGR_DBCTRL_ADDRESS 0x10
+#define CLKMGR_STAT_ADDRESS 0x14
+#define CLKMGR_MAINPLLGRP_ADDRESS 0x40
+#define CLKMGR_MAINPLLGRP_VCO_ADDRESS 0x40
+#define CLKMGR_MAINPLLGRP_MISC_ADDRESS 0x44
+#define CLKMGR_MAINPLLGRP_MPUCLK_ADDRESS 0x48
+#define CLKMGR_MAINPLLGRP_MAINCLK_ADDRESS 0x4c
+#define CLKMGR_MAINPLLGRP_DBGATCLK_ADDRESS 0x50
+#define CLKMGR_MAINPLLGRP_MAINQSPICLK_ADDRESS 0x54
+#define CLKMGR_MAINPLLGRP_MAINNANDSDMMCCLK_ADDRESS 0x58
+#define CLKMGR_MAINPLLGRP_CFGS2FUSER0CLK_ADDRESS 0x5c
+#define CLKMGR_MAINPLLGRP_EN_ADDRESS 0x60
+#define CLKMGR_MAINPLLGRP_MAINDIV_ADDRESS 0x64
+#define CLKMGR_MAINPLLGRP_DBGDIV_ADDRESS 0x68
+#define CLKMGR_MAINPLLGRP_TRACEDIV_ADDRESS 0x6c
+#define CLKMGR_MAINPLLGRP_L4SRC_ADDRESS 0x70
+#define CLKMGR_PERPLLGRP_ADDRESS 0x80
+#define CLKMGR_PERPLLGRP_VCO_ADDRESS 0x80
+#define CLKMGR_PERPLLGRP_MISC_ADDRESS 0x84
+#define CLKMGR_PERPLLGRP_EMAC0CLK_ADDRESS 0x88
+#define CLKMGR_PERPLLGRP_EMAC1CLK_ADDRESS 0x8c
+#define CLKMGR_PERPLLGRP_PERQSPICLK_ADDRESS 0x90
+#define CLKMGR_PERPLLGRP_PERNANDSDMMCCLK_ADDRESS 0x94
+#define CLKMGR_PERPLLGRP_PERBASECLK_ADDRESS 0x98
+#define CLKMGR_PERPLLGRP_S2FUSER1CLK_ADDRESS 0x9c
+#define CLKMGR_PERPLLGRP_EN_ADDRESS 0xa0
+#define CLKMGR_PERPLLGRP_DIV_ADDRESS 0xa4
+#define CLKMGR_PERPLLGRP_GPIODIV_ADDRESS 0xa8
+#define CLKMGR_PERPLLGRP_SRC_ADDRESS 0xac
+#define CLKMGR_SDRPLLGRP_ADDRESS 0xc0
+#define CLKMGR_SDRPLLGRP_VCO_ADDRESS 0xc0
+#define CLKMGR_SDRPLLGRP_CTRL_ADDRESS 0xc4
+#define CLKMGR_SDRPLLGRP_DDRDQSCLK_ADDRESS 0xc8
+#define CLKMGR_SDRPLLGRP_DDR2XDQSCLK_ADDRESS 0xcc
+#define CLKMGR_SDRPLLGRP_DDRDQCLK_ADDRESS 0xd0
+#define CLKMGR_SDRPLLGRP_S2FUSER2CLK_ADDRESS 0xd4
+#define CLKMGR_SDRPLLGRP_EN_ADDRESS 0xd8
+#define CLKMGR_ALTERAGRP_MPUCLK 0xe0
+#define CLKMGR_ALTERAGRP_MAINCLK 0xe4
+
+#define CLKMGR_MAINPLLGRP_VCO_DENOM_GET(x) (((x) & 0x003f0000) >> 16)
+#define CLKMGR_MAINPLLGRP_VCO_NUMER_GET(x) (((x) & 0x0000fff8) >> 3)
+#define CLKMGR_MAINPLLGRP_L4SRC_L4SP_GET(x) (((x) & 0x00000002) >> 1)
+#define CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_GET(x) (((x) & 0x00000380) >> 7)
+#define CLKMGR_SDRPLLGRP_VCO_SSRC_GET(x) (((x) & 0x00c00000) >> 22)
+#define CLKMGR_SDRPLLGRP_VCO_DENOM_GET(x) (((x) & 0x003f0000) >> 16)
+#define CLKMGR_SDRPLLGRP_VCO_NUMER_GET(x) (((x) & 0x0000fff8) >> 3)
+#define CLKMGR_SDRPLLGRP_DDRDQSCLK_CNT_GET(x) (((x) & 0x000001ff) >> 0)
+#define CLKMGR_PERPLLGRP_VCO_SSRC_GET(x) (((x) & 0x00c00000) >> 22)
+#define CLKMGR_PERPLLGRP_VCO_DENOM_GET(x) (((x) & 0x003f0000) >> 16)
+#define CLKMGR_PERPLLGRP_VCO_NUMER_GET(x) (((x) & 0x0000fff8) >> 3)
+#define CLKMGR_PERPLLGRP_SRC_QSPI_GET(x) (((x) & 0x00000030) >> 4)
+#define CLKMGR_PERPLLGRP_SRC_SDMMC_GET(x) (((x) & 0x00000003) >> 0)
+
+#define CLKMGR_VCO_SSRC_EOSC1 0x0
+#define CLKMGR_VCO_SSRC_EOSC2 0x1
+#define CLKMGR_VCO_SSRC_F2S 0x2
+#define CLKMGR_L4_SP_CLK_SRC_MAINPLL 0x0
+#define CLKMGR_L4_SP_CLK_SRC_PERPLL 0x1
+#define CLKMGR_SDMMC_CLK_SRC_F2S 0x0
+#define CLKMGR_SDMMC_CLK_SRC_MAIN 0x1
+#define CLKMGR_SDMMC_CLK_SRC_PER 0x2
+#define CLKMGR_QSPI_CLK_SRC_F2S 0x0
+#define CLKMGR_QSPI_CLK_SRC_MAIN 0x1
+#define CLKMGR_QSPI_CLK_SRC_PER 0x2
+
+#define CLKMGR_L4_SP_CLK_SRC_MAINPLL 0x0
+#define CLKMGR_L4_SP_CLK_SRC_PERPLL 0x1
+#define CLKMGR_SDMMC_CLK_SRC_F2S 0x0
+#define CLKMGR_SDMMC_CLK_SRC_MAIN 0x1
+#define CLKMGR_SDMMC_CLK_SRC_PER 0x2
+#define CLKMGR_QSPI_CLK_SRC_F2S 0x0
+#define CLKMGR_QSPI_CLK_SRC_MAIN 0x1
+#define CLKMGR_QSPI_CLK_SRC_PER 0x2
+
+#define CONFIG_HPS_CLK_OSC2_HZ (0)
+#define CONFIG_HPS_CLK_F2S_SDR_REF_HZ (0)
+#define CONFIG_HPS_CLK_F2S_PER_REF_HZ (0)
+
+unsigned long cm_get_l4_sp_clk_hz(void)
+{
+ uint32_t reg, clock = 0;
+
+ /* identify the source of L4 SP clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLLGRP_L4SRC_ADDRESS);
+ reg = CLKMGR_MAINPLLGRP_L4SRC_L4SP_GET(reg);
+
+ if (reg == CLKMGR_L4_SP_CLK_SRC_MAINPLL) {
+ /* get the main VCO clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_MAINPLLGRP_VCO_ADDRESS);
+ clock = CONFIG_HPS_CLK_OSC1_HZ /
+ (CLKMGR_MAINPLLGRP_VCO_DENOM_GET(reg) + 1);
+ clock *= (CLKMGR_MAINPLLGRP_VCO_NUMER_GET(reg) + 1);
+
+ /* get the clock prior L4 SP divider (main clk) */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_ALTERAGRP_MAINCLK);
+ clock /= (reg + 1);
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_MAINPLLGRP_MAINCLK_ADDRESS);
+ clock /= (reg + 1);
+ } else if (reg == CLKMGR_L4_SP_CLK_SRC_PERPLL) {
+ /* identify PER PLL clock source */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_VCO_ADDRESS);
+ reg = CLKMGR_PERPLLGRP_VCO_SSRC_GET(reg);
+ if (reg == CLKMGR_VCO_SSRC_EOSC1)
+ clock = CONFIG_HPS_CLK_OSC1_HZ;
+ else if (reg == CLKMGR_VCO_SSRC_EOSC2)
+ clock = CONFIG_HPS_CLK_OSC2_HZ;
+ else if (reg == CLKMGR_VCO_SSRC_F2S)
+ clock = CONFIG_HPS_CLK_F2S_PER_REF_HZ;
+
+ /* get the PER VCO clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_VCO_ADDRESS);
+ clock /= (CLKMGR_PERPLLGRP_VCO_DENOM_GET(reg) + 1);
+ clock *= (CLKMGR_PERPLLGRP_VCO_NUMER_GET(reg) + 1);
+
+ /* get the clock prior L4 SP divider (periph_base_clk) */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_PERBASECLK_ADDRESS);
+ clock /= (reg + 1);
+ }
+
+ /* get the L4 SP clock which supplied to UART */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_MAINPLLGRP_MAINDIV_ADDRESS);
+ reg = CLKMGR_MAINPLLGRP_MAINDIV_L4SPCLK_GET(reg);
+ clock = clock / (reg + 1);
+
+ return clock;
+}
+
+void cm_print_clock_quick_summary(void)
+{
+ printf("CLOCK: EOSC1 clock %d KHz\n",
+ (CONFIG_HPS_CLK_OSC1_HZ / 1000));
+ printf("CLOCK: EOSC2 clock %d KHz\n",
+ (CONFIG_HPS_CLK_OSC2_HZ / 1000));
+ printf("CLOCK: F2S_SDR_REF clock %d KHz\n",
+ (CONFIG_HPS_CLK_F2S_SDR_REF_HZ / 1000));
+ printf("CLOCK: F2S_PER_REF clock %d KHz\n",
+ (CONFIG_HPS_CLK_F2S_PER_REF_HZ / 1000));
+ printf("CLOCK: UART clock %ld KHz\n",
+ (cm_get_l4_sp_clk_hz() / 1000));
+
+}
+
+unsigned long cm_get_mmc_controller_clk_hz(void)
+{
+ uint32_t reg, clock = 0;
+
+ /* identify the source of MMC clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS + CLKMGR_PERPLLGRP_SRC_ADDRESS);
+ reg = CLKMGR_PERPLLGRP_SRC_SDMMC_GET(reg);
+
+ if (reg == CLKMGR_SDMMC_CLK_SRC_F2S)
+ clock = CONFIG_HPS_CLK_F2S_PER_REF_HZ;
+ else if (reg == CLKMGR_SDMMC_CLK_SRC_MAIN) {
+ /* get the main VCO clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_MAINPLLGRP_VCO_ADDRESS);
+ clock = CONFIG_HPS_CLK_OSC1_HZ /
+ (CLKMGR_MAINPLLGRP_VCO_DENOM_GET(reg) + 1);
+ clock *= (CLKMGR_MAINPLLGRP_VCO_NUMER_GET(reg) + 1);
+
+ /* get the SDMMC clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_MAINPLLGRP_MAINNANDSDMMCCLK_ADDRESS);
+ clock /= (reg + 1);
+ } else if (reg == CLKMGR_SDMMC_CLK_SRC_PER) {
+ /* identify PER PLL clock source */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_VCO_ADDRESS);
+ reg = CLKMGR_PERPLLGRP_VCO_SSRC_GET(reg);
+ if (reg == CLKMGR_VCO_SSRC_EOSC1)
+ clock = CONFIG_HPS_CLK_OSC1_HZ;
+ else if (reg == CLKMGR_VCO_SSRC_EOSC2)
+ clock = CONFIG_HPS_CLK_OSC2_HZ;
+ else if (reg == CLKMGR_VCO_SSRC_F2S)
+ clock = CONFIG_HPS_CLK_F2S_PER_REF_HZ;
+
+ /* get the PER VCO clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_VCO_ADDRESS);
+ clock /= (CLKMGR_PERPLLGRP_VCO_DENOM_GET(reg) + 1);
+ clock *= (CLKMGR_PERPLLGRP_VCO_NUMER_GET(reg) + 1);
+
+ /* get the SDMMC clock */
+ reg = readl(SOCFPGA_CLKMGR_ADDRESS +
+ CLKMGR_PERPLLGRP_PERNANDSDMMCCLK_ADDRESS);
+ clock /= (reg + 1);
+ }
+
+ /* further divide by 4 as we have fixed divider at wrapper */
+ clock /= 4;
+ return clock;
+}
+
+void cm_derive_clocks_for_drivers(void)
+{
+ cm_l4_sp_clock = cm_get_l4_sp_clk_hz();
+ cm_sdmmc_clock = cm_get_mmc_controller_clk_hz();
+
+ cm_print_clock_quick_summary();
+ printf("sdmmc_clock: %d\n", cm_sdmmc_clock);
+#if 0
+ cm_qspi_clock = cm_get_qspi_controller_clk_hz();
+#endif
+}
diff --git a/arch/arm/cpu/armv7/socfpga/fpga_manager.c b/arch/arm/cpu/armv7/socfpga/fpga_manager.c
new file mode 100644
index 0000000..19e4eea
--- /dev/null
+++ b/arch/arm/cpu/armv7/socfpga/fpga_manager.c
@@ -0,0 +1,378 @@
+/*
+ *
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Altera Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL ALTERA CORPORATION BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/arch/fpga_manager.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/system_manager.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static const struct socfpga_fpga_manager *fpga_manager_base =
+ (void *)SOCFPGA_FPGAMGRREGS_ADDRESS;
+
+#define DEBUG_MEMORY printf("%s\n", __func__ );
+#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
+
+/* Check whether FPGA Init_Done signal is high */
+static int is_fpgamgr_initdone_high(void)
+{
+ unsigned long val;
+ DEBUG_MEMORY
+ val = readl(SOCFPGA_FPGAMGRREGS_ADDRESS +
+ FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS);
+ if (val & FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK)
+ return 1;
+ else
+ return 0;
+}
+
+/* Get the FPGA mode */
+static int fpgamgr_get_mode(void)
+{
+ unsigned long val;
+ //DEBUG_MEMORY
+ printf("get_mode ");
+ val = readl(&fpga_manager_base->stat);
+ val = val & FPGAMGRREGS_STAT_MODE_MASK;
+ return val;
+}
+
+/* Check whether FPGA is ready to be accessed */
+int is_fpgamgr_fpga_ready(void)
+{
+ /* check for init done signal */
+ if (is_fpgamgr_initdone_high() == 0)
+ return 0;
+ /* check again to avoid false glitches */
+ if (is_fpgamgr_initdone_high() == 0)
+ return 0;
+ if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_USERMODE)
+ return 0;
+ return 1;
+}
+
+/* Poll until FPGA is ready to be accessed or timeout occurred */
+int poll_fpgamgr_fpga_ready(void)
+{
+ unsigned long i;
+ DEBUG_MEMORY
+ /* If FPGA is blank, wait till WD invoke warm reset */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ /* check for init done signal */
+ if (is_fpgamgr_initdone_high() == 0)
+ continue;
+ /* check again to avoid false glitches */
+ if (is_fpgamgr_initdone_high() == 0)
+ continue;
+ return 1;
+ }
+ DEBUG_MEMORY
+ return 0;
+}
+
+/* set CD ratio */
+static void fpgamgr_set_cd_ratio(unsigned long ratio)
+{
+ unsigned long reg;
+ reg = readl(&fpga_manager_base->ctrl);
+ reg = (reg & ~(0x3 << FPGAMGRREGS_CTRL_CDRATIO_LSB)) |
+ ((ratio & 0x3) << FPGAMGRREGS_CTRL_CDRATIO_LSB);
+ writel(reg, &fpga_manager_base->ctrl);
+}
+
+static int fpgamgr_dclkcnt_set(unsigned long cnt)
+{
+ unsigned long i;
+
+ /* clear any existing done status */
+ if (readl(&fpga_manager_base->dclkstat))
+ writel(0x1, &fpga_manager_base->dclkstat);
+ /* write the dclkcnt */
+ writel(cnt, &fpga_manager_base->dclkcnt);
+ /*
+ * wait till the dclkcnt done
+ */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (readl(&fpga_manager_base->dclkstat)) {
+ writel(0x1, &fpga_manager_base->dclkstat);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+/* Start the FPGA programming by initialize the FPGA Manager */
+int fpgamgr_program_init(void)
+{
+ unsigned long reg, i;
+
+ debug("fpga: program_init\n");
+ /* get the MSEL value */
+ reg = readl(&fpga_manager_base->stat);
+ reg = ((reg & FPGAMGRREGS_STAT_MSEL_MASK) >> FPGAMGRREGS_STAT_MSEL_LSB);
+
+ /*
+ * Set the cfg width
+ * If MSEL[3] = 1, cfg width = 32 bit
+ */
+ if (reg & 0x8)
+ setbits_le32(&fpga_manager_base->ctrl,
+ FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+ else
+ clrbits_le32(&fpga_manager_base->ctrl,
+ FPGAMGRREGS_CTRL_CFGWDTH_MASK);
+
+ /* To determine the CD ratio */
+ /* MSEL[3] = 1 & MSEL[1:0] = 0, CD Ratio = 1 */
+ if ((reg & 0xb) == 0x8)
+ fpgamgr_set_cd_ratio(CDRATIO_x1);
+ /* MSEL[3] = 1 & MSEL[1:0] = 1, CD Ratio = 4 */
+ else if ((reg & 0xb) == 0x9)
+ fpgamgr_set_cd_ratio(CDRATIO_x4);
+ /* MSEL[3] = 1 & MSEL[1:0] = 2, CD Ratio = 8 */
+ else if ((reg & 0xb) == 0xa)
+ fpgamgr_set_cd_ratio(CDRATIO_x8);
+ /* MSEL[3] = 0 & MSEL[1:0] = 0, CD Ratio = 1 */
+ else if ((reg & 0xb) == 0x0)
+ fpgamgr_set_cd_ratio(CDRATIO_x1);
+ /* MSEL[3] = 0 & MSEL[1:0] = 1, CD Ratio = 2 */
+ else if ((reg & 0xb) == 0x1)
+ fpgamgr_set_cd_ratio(CDRATIO_x2);
+ /* MSEL[3] = 0 & MSEL[1:0] = 2, CD Ratio = 4 */
+ else if ((reg & 0xb) == 0x2)
+ fpgamgr_set_cd_ratio(CDRATIO_x4);
+
+ debug("fpga: enable config\n");
+
+ /* to enable FPGA Manager configuration */
+ clrbits_le32(&fpga_manager_base->ctrl, FPGAMGRREGS_CTRL_NCE_MASK);
+
+ /* to enable FPGA Manager drive over configuration line */
+ setbits_le32(&fpga_manager_base->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+ /* put FPGA into reset phase */
+ setbits_le32(&fpga_manager_base->ctrl,
+ FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+ debug("fpga: wait for reset\n");
+
+ /* (1) wait until FPGA enter reset phase */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_RESETPHASE)
+ break;
+ }
+ /* if not in reset state, return error */
+ if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_RESETPHASE) {
+ printf("fpga: could not reset\n");
+ return -1;
+ }
+
+ /* release FPGA from reset phase */
+ clrbits_le32(&fpga_manager_base->ctrl,
+ FPGAMGRREGS_CTRL_NCONFIGPULL_MASK);
+
+ debug("fpga: wait for config\n");
+
+ /* (2) wait until FPGA enter configuration phase */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_CFGPHASE)
+ break;
+ }
+ /* if not in configuration state, return error */
+ if (fpgamgr_get_mode() != FPGAMGRREGS_MODE_CFGPHASE)
+ return -2;
+
+ /* clear all interrupts in CB Monitor */
+ writel(0xFFF, (SOCFPGA_FPGAMGRREGS_ADDRESS +
+ FPGAMGRREGS_MON_GPIO_PORTA_EOI_ADDRESS));
+
+ /* enable AXI configuration */
+ setbits_le32(&fpga_manager_base->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+
+ debug("fpga: prepare done\n");
+
+ return 0;
+}
+
+/* Write the RBF data to FPGA Manager */
+void fpgamgr_program_write(const unsigned long *rbf_data,
+ unsigned long rbf_size)
+{
+ printf("copying from %lx to %lx, %d bytes\n", rbf_data, SOCFPGA_FPGAMGRDATA_ADDRESS, rbf_size);
+
+ printf("_axi_write\n");
+ // fpgamgr_axi_write(rbf_data, SOCFPGA_FPGAMGRDATA_ADDRESS, rbf_size);
+ {
+ long i;
+ for (i=0; i<(rbf_size/4); i++) {
+ volatile long *data = SOCFPGA_FPGAMGRDATA_ADDRESS;
+ *data = rbf_data[i];
+ }
+ }
+
+ printf("_axi_done\n");
+
+ printf("copying done.\n");
+}
+
+/* Ensure the FPGA entering config done */
+int fpgamgr_program_poll_cd(void)
+{
+ unsigned long reg, i;
+
+ printf("poll_cd, %d\n", FPGA_TIMEOUT_CNT);
+ /* (3) wait until full config done */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (!(i % 1000))
+ printf("reading %d/%d.\n", i, FPGA_TIMEOUT_CNT);
+ reg = readl(SOCFPGA_FPGAMGRREGS_ADDRESS +
+ FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS);
+ /* config error */
+ if (!(reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK) &&
+ !(reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK))
+ return -3;
+ /* config done without error */
+ if ((reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK) &&
+ (reg & FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK))
+ break;
+ }
+
+ /* tiemout happen, return error */
+ if (i == FPGA_TIMEOUT_CNT) {
+ printf("fpga: timeout waiting for program.\n");
+ return -4;
+ }
+
+ /* disable AXI configuration */
+ clrbits_le32(&fpga_manager_base->ctrl, FPGAMGRREGS_CTRL_AXICFGEN_MASK);
+ return 0;
+}
+
+/* Ensure the FPGA entering init phase */
+int fpgamgr_program_poll_initphase(void)
+{
+ unsigned long i;
+
+ /* additional clocks for the CB to enter initialization phase */
+ if (fpgamgr_dclkcnt_set(0x4) != 0)
+ return -5;
+
+ /* (4) wait until FPGA enter init phase or user mode */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_INITPHASE)
+ break;
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+ break;
+ }
+ /* if not in configuration state, return error */
+ if (i == FPGA_TIMEOUT_CNT)
+ return -6;
+
+ return 0;
+}
+
+/* Ensure the FPGA entering user mode */
+int fpgamgr_program_poll_usermode(void)
+{
+ unsigned long i;
+
+ /* additional clocks for the CB to exit initialization phase */
+ if (fpgamgr_dclkcnt_set(0x5000) != 0)
+ return -7;
+
+ /* (5) wait until FPGA enter user mode */
+ for (i = 0; i < FPGA_TIMEOUT_CNT; i++) {
+ if (fpgamgr_get_mode() == FPGAMGRREGS_MODE_USERMODE)
+ break;
+ }
+ /* if not in configuration state, return error */
+ if (i == FPGA_TIMEOUT_CNT)
+ return -8;
+
+ /* to release FPGA Manager drive over configuration line */
+ clrbits_le32(&fpga_manager_base->ctrl, FPGAMGRREGS_CTRL_EN_MASK);
+
+ return 0;
+}
+
+/*
+ * Using FPGA Manager to program the FPGA
+ * Return 0 for sucess
+ */
+int fpgamgr_program_fpga(const unsigned long *rbf_data,
+ unsigned long rbf_size)
+{
+ unsigned long status;
+
+ printf("program: 1\n");
+ /* prior programming the FPGA, all bridges need to be shut off */
+
+ /* disable all signals from hps peripheral controller to fpga */
+ writel(0, SYSMGR_FPGAINTF_MODULE);
+
+ printf("program: 1a\n");
+ /* disable all signals from fpga to hps sdram */
+ writel(0, (SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
+
+ printf("program: 2\n");
+ /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */
+ reset_assert_all_bridges();
+ /* unmap the bridges from NIC-301 */
+ writel(0x1, SOCFPGA_L3REGS_ADDRESS);
+
+ printf("program: 3\n");
+ /* initialize the FPGA Manager */
+ status = fpgamgr_program_init();
+ if (status)
+ return status;
+
+ printf("program: 4\n");
+ /* Write the RBF data to FPGA Manager */
+ fpgamgr_program_write(rbf_data, rbf_size);
+
+ printf("...here!\n");
+
+ printf("program: 5\n");
+ /* Ensure the FPGA entering config done */
+ status = fpgamgr_program_poll_cd();
+ if (status)
+ return status;
+
+ printf("program: 6\n");
+
+ /* Ensure the FPGA entering init phase */
+ status = fpgamgr_program_poll_initphase();
+ if (status)
+ return status;
+
+ printf("program: 7\n");
+ /* Ensure the FPGA entering user mode */
+ return fpgamgr_program_poll_usermode();
+}
diff --git a/arch/arm/cpu/armv7/socfpga/lowlevel_init.S b/arch/arm/cpu/armv7/socfpga/lowlevel_init.S
index 2f2e9fc..4b5865a 100644
--- a/arch/arm/cpu/armv7/socfpga/lowlevel_init.S
+++ b/arch/arm/cpu/armv7/socfpga/lowlevel_init.S
@@ -6,6 +6,7 @@
#include <config.h>
#include <version.h>
+#include <asm/system.h>
/* Save the parameter pass in by previous boot loader */
.global save_boot_params
@@ -51,3 +52,112 @@ lowlevel_init:
str r2, [r1]
#endif /* #ifdef CONFIG_SPL_BUILD */
mov pc, lr
+
+/*
+ * Write RBF data in burst form to FPGA Manager
+ * [r0] RBF binary source address
+ * [r1] FPGA Manager data address
+ * [r2] RBF data length
+ */
+
+
+//ENTRY(fpgamgr_axi_write)
+.globl fpgamgr_axi_write
+fpgamgr_axi_write:
+ PUSH {r4-r11, lr} /* save registers per AAPCS */
+
+write_burst:
+ cmp r2,#32
+ beq write_burst_cont
+ bls write_word
+write_burst_cont:
+ ldmia r0!, {r4-r11}
+ stmia r1, {r4-r11}
+ subs r2, r2, #32
+ b write_burst
+
+write_word:
+ cmp r2,#4
+ beq write_word_cont
+ bls write_byte
+write_word_cont:
+ ldmia r0!, {r4}
+ stmia r1, {r4}
+ subs r2, r2, #4
+ b write_word
+
+ /* FIXME: this is wrong, right? It will copy just one byte when copy of 3
+ is requested */
+write_byte:
+ cmp r2,#0
+ beq write_end
+ ldr r3, [r0]
+ str r3, [r1]
+write_end:
+ POP {r4-r11, pc}
+//ENDPROC(fpgamgr_axi_write)
+
+#define SDR_CTRLGRP_STATICCFG_ADDRESS 0x505c
+#define SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK 0x00000008
+
+/*
+ * Configure the fpga2sdram register
+ * For U-Boot only and this code need to run on OCRAM
+ * No stack activity or function call to avoid access to SDRAM
+ *
+ * Note that sdram_applycfg_uboot copies fixed ammount of memory;
+ * be careful if you make this function longer.
+ */
+
+.global sdram_applycfg_ocram
+sdram_applycfg_ocram:
+ mrc p15, 0, r0, c1, c0, 0 @ Read CP15 SCTRL Register
+ bic r0, #CR_Z @ Disable branch predictor
+ bic r0, #CR_I @ Disable i-cache
+ mcr p15, 0, r0, c1, c0, 0 @ Write CP15 SCTRL Register
+ dsb
+ isb
+
+ ldr r1, SDR_CTRL
+ ldr r2, SDR_STATICCFG
+ add r1, r1, r2
+ ldr r0, [r1]
+ ldr r3, SDR_APPLYCFG_MASK
+ orr r0, r0, r3
+ str r0, [r1]
+ dsb
+ isb
+
+ mrc p15, 0, r4, c1, c0, 0 @ Read CP15 SCTRL Register
+ orr r4, r4, #CR_Z @ Enable back branch predictor
+ orr r4, r4, #CR_I @ Enable back i-cache
+ mcr p15, 0, r4, c1, c0, 0 @ Write CP15 SCTRL Register
+
+ mov r0, #0
+ mov pc, lr
+
+SDR_CTRL: .word SOCFPGA_SDR_ADDRESS
+SDR_STATICCFG: .word SDR_CTRLGRP_STATICCFG_ADDRESS
+SDR_APPLYCFG_MASK: .word SDR_CTRLGRP_STATICCFG_APPLYCFG_MASK
+
+/*
+ * Relocate the sdram_applycfg_ocram function to OCRAM and call it
+ */
+.globl sdram_applycfg_uboot
+sdram_applycfg_uboot:
+ PUSH {r4-r11, lr} /* save registers per AAPCS */
+
+ ldr r1, =sdram_applycfg_ocram
+ ldr r2, =CONFIG_SYS_INIT_RAM_ADDR
+ mov r3, r2
+ ldmia r1!, {r4 - r11}
+ stmia r3!, {r4 - r11}
+ ldmia r1!, {r4 - r11} /* copy more in case code added */
+ stmia r3!, {r4 - r11} /* in the future */
+ ldmia r1!, {r4 - r11} /* copy more in case code added */
+ stmia r3!, {r4 - r11} /* in the future */
+ dsb
+ isb
+ blx r2 /* jump to OCRAM */
+ POP {r4-r11, pc}
+
diff --git a/arch/arm/cpu/armv7/socfpga/misc.c b/arch/arm/cpu/armv7/socfpga/misc.c
index ecae393..5842734 100644
--- a/arch/arm/cpu/armv7/socfpga/misc.c
+++ b/arch/arm/cpu/armv7/socfpga/misc.c
@@ -8,6 +8,10 @@
#include <asm/io.h>
#include <miiphy.h>
#include <netdev.h>
+#include <altera.h>
+#include <asm/arch/reset_manager.h>
+#include <asm/arch/dwmmc.h>
+
DECLARE_GLOBAL_DATA_PTR;
@@ -17,6 +21,117 @@ int dram_init(void)
return 0;
}
+#define L3REGS_SECGRP_LWHPS2FPGAREGS_ADDRESS 0x20
+#define L3REGS_SECGRP_HPS2FPGAREGS_ADDRESS 0x90
+#define L3REGS_SECGRP_ACP_ADDRESS 0x94
+#define L3REGS_SECGRP_ROM_ADDRESS 0x98
+#define L3REGS_SECGRP_OCRAM_ADDRESS 0x9c
+#define L3REGS_SECGRP_SDRDATA_ADDRESS 0xa0
+
+#define L3REGS_REMAP_LWHPS2FPGA_MASK 0x00000010
+#define L3REGS_REMAP_HPS2FPGA_MASK 0x00000008
+#define L3REGS_REMAP_OCRAM_MASK 0x00000001
+
+/*
+ * Convert all slave from secure to non secure
+ */
+void nic301_slave_ns(void)
+{
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_LWHPS2FPGAREGS_ADDRESS));
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_HPS2FPGAREGS_ADDRESS));
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_ACP_ADDRESS));
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_ROM_ADDRESS));
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_OCRAM_ADDRESS));
+ writel(0x1, (SOCFPGA_L3REGS_ADDRESS +
+ L3REGS_SECGRP_SDRDATA_ADDRESS));
+ return;
+}
+
+
+static const struct socfpga_reset_manager *reset_manager_base =
+ (void *)SOCFPGA_RSTMGR_ADDRESS;
+
+#define CONFIG_SYSMGR_EMAC_CTRL (SOCFPGA_SYSMGR_ADDRESS + 0x60)
+
+/* Enumeration: sysmgr::emacgrp::ctrl::physel::enum */
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB 0
+#define SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB 2
+#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK 0x00000003
+
+/* EMAC controller and PHY used */
+#define CONFIG_EPHY_PHY_ADDR CONFIG_EPHY1_PHY_ADDR
+
+#define SYSMGR_FPGAINTF_MODULE (SOCFPGA_SYSMGR_ADDRESS + 0x28)
+
+/* Preloader handoff to bootloader register */
+#define SYSMGR_ISWGRP_HANDOFF0 (SOCFPGA_SYSMGR_ADDRESS + 0x80)
+#define SYSMGR_ISWGRP_HANDOFF1 (SOCFPGA_SYSMGR_ADDRESS + 0x84)
+#define SYSMGR_ISWGRP_HANDOFF2 (SOCFPGA_SYSMGR_ADDRESS + 0x88)
+#define SYSMGR_ISWGRP_HANDOFF3 (SOCFPGA_SYSMGR_ADDRESS + 0x8C)
+#define SYSMGR_ISWGRP_HANDOFF4 (SOCFPGA_SYSMGR_ADDRESS + 0x90)
+#define SYSMGR_ISWGRP_HANDOFF5 (SOCFPGA_SYSMGR_ADDRESS + 0x94)
+#define SYSMGR_ISWGRP_HANDOFF6 (SOCFPGA_SYSMGR_ADDRESS + 0x98)
+#define SYSMGR_ISWGRP_HANDOFF7 (SOCFPGA_SYSMGR_ADDRESS + 0x9C)
+
+#define ISWGRP_HANDOFF_AXIBRIDGE SYSMGR_ISWGRP_HANDOFF0
+#define ISWGRP_HANDOFF_L3REMAP SYSMGR_ISWGRP_HANDOFF1
+#define ISWGRP_HANDOFF_FPGAINTF SYSMGR_ISWGRP_HANDOFF2
+#define ISWGRP_HANDOFF_FPGA2SDR SYSMGR_ISWGRP_HANDOFF3
+
+#define SDR_CTRLGRP_FPGAPORTRST_ADDRESS 0x5080
+
+/*
+ * DesignWare Ethernet initialization
+ */
+#ifdef CONFIG_DESIGNWARE_ETH
+int cpu_eth_init(bd_t *bis)
+{
+ /* Initialize EMAC. This needs to be done at least once per boot. */
+
+ /*
+ * Putting the EMAC controller to reset when configuring the PHY
+ * interface select at System Manager
+ */
+ emac0_reset_enable(1);
+ emac1_reset_enable(1);
+
+ /* Clearing emac0 PHY interface select to 0 */
+ clrbits_le32(CONFIG_SYSMGR_EMAC_CTRL,
+ (SYSMGR_EMACGRP_CTRL_PHYSEL_MASK <<
+ SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB));
+
+ /* configure to PHY interface select choosed */
+ setbits_le32(CONFIG_SYSMGR_EMAC_CTRL,
+ (SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII <<
+ SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB));
+ /* Release the EMAC controller from reset */
+ emac1_reset_enable(0);
+
+ /* initialize and register the emac */
+ return designware_initialize(CONFIG_EMAC_BASE,
+ CONFIG_PHY_INTERFACE_MODE);
+}
+#endif
+
+#ifdef CONFIG_DWMMC
+/*
+ * Initializes MMC controllers.
+ * to override, implement board_mmc_init()
+ */
+int cpu_mmc_init(bd_t *bis)
+{
+ return socfpga_dwmmc_init(SOCFPGA_SDMMC_ADDRESS, 4, 0);
+}
+#endif
+
#if defined(CONFIG_DISPLAY_CPUINFO)
/*
* Print CPU information
@@ -36,22 +151,123 @@ int overwrite_console(void)
}
#endif
-int misc_init_r(void)
+#ifdef CONFIG_FPGA
+/*
+ * FPGA programming support for SoC FPGA Cyclone V
+ */
+/* currently only single FPGA device avaiable on dev kit */
+Altera_desc altera_fpga[CONFIG_FPGA_COUNT] = {
+ {Altera_SoCFPGA, /* family */
+ fast_passive_parallel, /* interface type */
+ -1, /* no limitation as
+ additional data will be ignored */
+ NULL, /* no device function table */
+ NULL, /* base interface address specified in driver */
+ 0} /* no cookie implementation */
+};
+
+/* add device descriptor to FPGA device table */
+void socfpga_fpga_add(void)
{
- return 0;
+ int i;
+ fpga_init();
+ for (i = 0; i < CONFIG_FPGA_COUNT; i++)
+ fpga_add(fpga_altera, &altera_fpga[i]);
+}
+#endif
+
+void sdram_applycfg_uboot(void);
+
+#define SOCFPGA_MPUL2_ADDRESS 0xfffef000
+#define SOCFPGA_MPUL2_ADRFLTR_START (0xC00)
+
+/* create environment for bridges and handoff */
+static void prepare_environment(void)
+{
+ char buf[32];
+
+ /* hps peripheral controller to fgpa */
+ setenv_addr("fpgaintf", (void *)SYSMGR_FPGAINTF_MODULE);
+ sprintf(buf, "0x%08x", readl(ISWGRP_HANDOFF_FPGAINTF));
+ setenv("fpgaintf_handoff", buf);
+
+ /* fpga2sdram port */
+ setenv_addr("fpga2sdram", (void *)(SOCFPGA_SDR_ADDRESS +
+ SDR_CTRLGRP_FPGAPORTRST_ADDRESS));
+ sprintf(buf, "0x%08x", readl(ISWGRP_HANDOFF_FPGA2SDR));
+ setenv("fpga2sdram_handoff", buf);
+ setenv_addr("fpga2sdram_apply", (void *)sdram_applycfg_uboot);
+
+ /* axi bridges (hps2fpga, lwhps2fpga and fpga2hps) */
+ setenv_addr("axibridge", (void *)&reset_manager_base->brg_mod_reset);
+ sprintf(buf, "0x%08x", readl(ISWGRP_HANDOFF_AXIBRIDGE));
+ setenv("axibridge_handoff", buf);
+
+ /* l3 remap register */
+ setenv_addr("l3remap", (void *)SOCFPGA_L3REGS_ADDRESS);
+ sprintf(buf, "0x%08x", readl(ISWGRP_HANDOFF_L3REMAP));
+ setenv("l3remap_handoff", buf);
+
+ /* add signle command to enable all bridges based on handoff */
+ setenv("bridge_enable_handoff",
+ "mw $fpgaintf ${fpgaintf_handoff}; "
+ "go $fpga2sdram_apply; "
+ "mw $fpga2sdram ${fpga2sdram_handoff}; "
+ "mw $axibridge ${axibridge_handoff}; "
+ "mw $l3remap ${l3remap_handoff} ");
+
+ /* add signle command to disable all bridges */
+ setenv("bridge_disable",
+ "mw $fpgaintf 0; "
+ "mw $fpga2sdram 0; "
+ "go $fpga2sdram_apply; "
+ "mw $axibridge 0; "
+ "mw $l3remap 0x1 ");
}
+int misc_init_r(void)
+{
+#if 1 /* FIXME */
+ printf("Turning off all the bridges\n");
+ reset_assert_all_bridges();
+ /* reset_deassert_all_bridges(); <- original code never does that */
+ printf("non-secure access to everyone\n");
+ nic301_slave_ns();
+#endif
+
+#if 1 /* FIXME */
+#define SOCFPGA_MPUSCU_ADDRESS 0xfffec000
/*
- * DesignWare Ethernet initialization
+ * SCU Non-secure Access Control
*/
-int cpu_eth_init(bd_t *bis)
-{
-#if !defined(CONFIG_SOCFPGA_VIRTUAL_TARGET) && !defined(CONFIG_SPL_BUILD)
- /* initialize and register the emac */
- return designware_initialize(CONFIG_EMAC_BASE,
- CONFIG_PHY_INTERFACE_MODE);
+#define SOCFPGA_SCU_SNSAC (SOCFPGA_MPUSCU_ADDRESS + 0x54)
+
+ /*
+ * Private components security
+ * U-Boot : configure private timer, global timer and cpu
+ * component access as non secure for kernel stage (as required
+ * by kernel)
+ */
+ setbits_le32(SOCFPGA_SCU_SNSAC, 0xfff);
+#endif
+
+ /* Configure the L2 controller to make SDRAM start at 0 */
+#ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET
+ writel(0x2, SOCFPGA_L3REGS_ADDRESS);
#else
- return 0;
+ writel(0x1, (SOCFPGA_MPUL2_ADDRESS + SOCFPGA_MPUL2_ADRFLTR_START));
#endif
+
+#ifdef CONFIG_FPGA
+ /* add device descriptor to FPGA device table */
+ socfpga_fpga_add();
+#endif
+
+ /* This is needed, otherwise kernel is rebooted by watchdog. */
+ watchdog_disable();
+
+ if (1) /* FIXME */
+ prepare_environment();
+ return 0;
}
diff --git a/arch/arm/cpu/armv7/socfpga/reset_manager.c b/arch/arm/cpu/armv7/socfpga/reset_manager.c
index e320c01..afc179b 100644
--- a/arch/arm/cpu/armv7/socfpga/reset_manager.c
+++ b/arch/arm/cpu/armv7/socfpga/reset_manager.c
@@ -14,6 +14,22 @@ DECLARE_GLOBAL_DATA_PTR;
static const struct socfpga_reset_manager *reset_manager_base =
(void *)SOCFPGA_RSTMGR_ADDRESS;
+#define RSTMGR_PERMODRST_L4WD0_LSB 6
+
+#define RSTMGR_PERMODRST_EMAC0_LSB 0
+#define RSTMGR_PERMODRST_EMAC1_LSB 1
+
+/* Disable the watchdog (toggle reset to watchdog) */
+void watchdog_disable(void)
+{
+ /* assert reset for watchdog */
+ setbits_le32(&reset_manager_base->per_mod_reset,
+ (1<<RSTMGR_PERMODRST_L4WD0_LSB));
+ /* deassert watchdog from reset (watchdog in not running state) */
+ clrbits_le32(&reset_manager_base->per_mod_reset,
+ (1<<RSTMGR_PERMODRST_L4WD0_LSB));
+}
+
/*
* Write the reset manager register to cause reset
*/
@@ -37,3 +53,62 @@ void reset_deassert_peripherals_handoff(void)
{
writel(0, &reset_manager_base->per_mod_reset);
}
+
+/* Assert reset to all bridges through reset manager */
+void reset_assert_all_bridges(void)
+{
+#if !defined(CONFIG_SOCFPGA_VIRTUAL_TARGET)
+ writel(~0, &reset_manager_base->brg_mod_reset);
+#endif
+}
+
+/* Change the reset state for EMAC0 */
+void emac0_reset_enable(uint state)
+{
+ if (state)
+ setbits_le32(&reset_manager_base->per_mod_reset,
+ (1 << RSTMGR_PERMODRST_EMAC0_LSB));
+ else
+ clrbits_le32(&reset_manager_base->per_mod_reset,
+ (1 << RSTMGR_PERMODRST_EMAC0_LSB));
+}
+
+/* Change the reset state for EMAC1 */
+void emac1_reset_enable(uint state)
+{
+ if (state)
+ setbits_le32(&reset_manager_base->per_mod_reset,
+ (1 << RSTMGR_PERMODRST_EMAC1_LSB));
+ else
+ clrbits_le32(&reset_manager_base->per_mod_reset,
+ (1 << RSTMGR_PERMODRST_EMAC1_LSB));
+}
+
+#define L3REGS_REMAP_LWHPS2FPGA_MASK 0x00000010
+#define L3REGS_REMAP_HPS2FPGA_MASK 0x00000008
+#define L3REGS_REMAP_OCRAM_MASK 0x00000001
+
+void reset_deassert_all_bridges(void)
+{
+#if !defined(CONFIG_SOCFPGA_VIRTUAL_TARGET)
+#if 1 /* FIXME */
+ printf("wait for fpga\n");
+ /* check signal from FPGA */
+ if (poll_fpgamgr_fpga_ready() == 0) {
+ /* FPGA not ready. Not much can be done but let WD timeout */
+ printf("reset_deassert_all_bridges: fpga not ready, hanging.\n");
+ for (;;)
+ ;
+ }
+
+ printf("modrst\n");
+ /* brdmodrst */
+ writel(0, &reset_manager_base->brg_mod_reset);
+#endif
+
+ printf("bridges\n");
+ /* remap the bridges into memory map */
+ writel((L3REGS_REMAP_LWHPS2FPGA_MASK | L3REGS_REMAP_HPS2FPGA_MASK |
+ L3REGS_REMAP_OCRAM_MASK), SOCFPGA_L3REGS_ADDRESS);
+#endif
+}
diff --git a/arch/arm/cpu/armv7/socfpga/system_manager.c b/arch/arm/cpu/armv7/socfpga/system_manager.c
index d96521b..0659407 100644
--- a/arch/arm/cpu/armv7/socfpga/system_manager.c
+++ b/arch/arm/cpu/armv7/socfpga/system_manager.c
@@ -7,8 +7,45 @@
#include <common.h>
#include <asm/io.h>
#include <asm/arch/system_manager.h>
+#include <asm/arch/fpga_manager.h>
DECLARE_GLOBAL_DATA_PTR;
+/*
+ * Populate the value for SYSMGR.FPGAINTF.MODULE based on pinmux setting.
+ * The value is not wrote to SYSMGR.FPGAINTF.MODULE but
+ * CONFIG_SYSMGR_ISWGRP_HANDOFF.
+ */
+static unsigned long populate_sysmgr_fpgaintf_module(void)
+{
+ writel(0, ISWGRP_HANDOFF_FPGAINTF);
+
+ /* enable the signal for those hps peripheral use fpga */
+ if (readl(SYSMGR_PINMUXGRP_NANDUSEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_NAND);
+
+ if (readl(SYSMGR_PINMUXGRP_EMAC1USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_EMAC1);
+
+ if (readl(SYSMGR_PINMUXGRP_SDMMCUSEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_SDMMC);
+
+ if (readl(SYSMGR_PINMUXGRP_EMAC0USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_EMAC0);
+
+ if (readl(SYSMGR_PINMUXGRP_SPIM1USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_SPIM1);
+
+ if (readl(SYSMGR_PINMUXGRP_SPIM0USEFPGA) == SYSMGR_FPGAINTF_USEFPGA)
+ setbits_le32(ISWGRP_HANDOFF_FPGAINTF,
+ SYSMGR_FPGAINTF_SPIM0);
+
+ return readl(ISWGRP_HANDOFF_FPGAINTF);
+}
/*
* Configure all the pin muxes
@@ -18,10 +55,19 @@ void sysmgr_pinmux_init(void)
unsigned long offset = CONFIG_SYSMGR_PINMUXGRP_OFFSET;
const unsigned long *pval = sys_mgr_init_table;
- unsigned long i;
+ unsigned long i, reg_value;
for (i = 0; i < ARRAY_SIZE(sys_mgr_init_table);
i++, offset += sizeof(unsigned long)) {
writel(*pval++, (SOCFPGA_SYSMGR_ADDRESS + offset));
}
+
+ /* populate (not writing) the value for SYSMGR.FPGAINTF.MODULE
+ based on pinmux setting */
+ reg_value = populate_sysmgr_fpgaintf_module();
+
+ if (is_fpgamgr_fpga_ready()) {
+ /* enable the required signals only */
+ writel(reg_value, SYSMGR_FPGAINTF_MODULE);
+ }
}
diff --git a/arch/arm/include/asm/arch-socfpga/clock_manager.h b/arch/arm/include/asm/arch-socfpga/clock_manager.h
index babac0e..d7c87199 100644
--- a/arch/arm/include/asm/arch-socfpga/clock_manager.h
+++ b/arch/arm/include/asm/arch-socfpga/clock_manager.h
@@ -208,4 +208,9 @@ struct socfpga_clock_manager {
CLKMGR_SDRPLLGRP_VCO_DENOM_SET(CONFIG_HPS_SDRPLLGRP_VCO_DENOM) | \
CLKMGR_SDRPLLGRP_VCO_NUMER_SET(CONFIG_HPS_SDRPLLGRP_VCO_NUMER))
+/* global variable which consume by drivers */
+extern unsigned long cm_l4_sp_clock;
+extern unsigned long cm_sdmmc_clock;
+extern unsigned long cm_qspi_clock;
+
#endif /* _CLOCK_MANAGER_H_ */
diff --git a/arch/arm/include/asm/arch-socfpga/fpga_manager.h b/arch/arm/include/asm/arch-socfpga/fpga_manager.h
new file mode 100644
index 0000000..8e410c5
--- /dev/null
+++ b/arch/arm/include/asm/arch-socfpga/fpga_manager.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * - Neither the name of the Altera Corporation nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL ALTERA CORPORATION BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FPGA_MANAGER_H_
+#define _FPGA_MANAGER_H_
+
+struct socfpga_fpga_manager {
+ u32 stat;
+ u32 ctrl;
+ u32 dclkcnt;
+ u32 dclkstat;
+ u32 gpo;
+ u32 gpi;
+ u32 misci;
+};
+
+#define FPGAMGRREGS_MON_GPIO_PORTA_EOI_ADDRESS 0x84c
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ADDRESS 0x850
+
+#define FPGAMGRREGS_CTRL_CFGWDTH_MASK 0x200
+#define FPGAMGRREGS_CTRL_AXICFGEN_MASK 0x100
+#define FPGAMGRREGS_CTRL_NCONFIGPULL_MASK 0x4
+#define FPGAMGRREGS_CTRL_NCE_MASK 0x2
+#define FPGAMGRREGS_CTRL_EN_MASK 0x1
+#define FPGAMGRREGS_CTRL_CDRATIO_LSB 6
+
+#define FPGAMGRREGS_STAT_MODE_MASK 0x7
+#define FPGAMGRREGS_STAT_MSEL_MASK 0xf8
+#define FPGAMGRREGS_STAT_MSEL_LSB 3
+
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CRC_MASK 0x8
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_ID_MASK 0x4
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_CD_MASK 0x2
+#define FPGAMGRREGS_MON_GPIO_EXT_PORTA_NS_MASK 0x1
+
+/* Timeout counter */
+#define FPGA_TIMEOUT_CNT 0x1000000
+
+/* FPGA Mode */
+#define FPGAMGRREGS_MODE_FPGAOFF 0x0
+#define FPGAMGRREGS_MODE_RESETPHASE 0x1
+#define FPGAMGRREGS_MODE_CFGPHASE 0x2
+#define FPGAMGRREGS_MODE_INITPHASE 0x3
+#define FPGAMGRREGS_MODE_USERMODE 0x4
+#define FPGAMGRREGS_MODE_UNKNOWN 0x5
+
+/* FPGA CD Ratio Value */
+#define CDRATIO_x1 0x0
+#define CDRATIO_x2 0x1
+#define CDRATIO_x4 0x2
+#define CDRATIO_x8 0x3
+
+/* Functions */
+int is_fpgamgr_fpga_ready(void);
+int poll_fpgamgr_fpga_ready(void);
+int fpgamgr_program_init(void);
+void fpgamgr_program_write(const unsigned long *rbf_data,
+ unsigned long rbf_size);
+int fpgamgr_program_poll_cd(void);
+int fpgamgr_program_poll_initphase(void);
+int fpgamgr_program_poll_usermode(void);
+int fpgamgr_program_fpga(const unsigned long *rbf_data,
+ unsigned long rbf_size);
+void fpgamgr_axi_write(const unsigned long *rbf_data,
+ const unsigned long fpgamgr_data_addr, unsigned long rbf_size);
+
+#endif /* _FPGA_MANAGER_H_ */
diff --git a/arch/arm/include/asm/arch-socfpga/reset_manager.h b/arch/arm/include/asm/arch-socfpga/reset_manager.h
index 3e95476..eb95c5b 100644
--- a/arch/arm/include/asm/arch-socfpga/reset_manager.h
+++ b/arch/arm/include/asm/arch-socfpga/reset_manager.h
@@ -10,6 +10,14 @@
void reset_cpu(ulong addr);
void reset_deassert_peripherals_handoff(void);
+void reset_deassert_all_bridges(void);
+void reset_assert_all_bridges(void);
+
+void emac0_reset_enable(uint state);
+void emac1_reset_enable(uint state);
+
+void watchdog_disable(void);
+
struct socfpga_reset_manager {
u32 status;
u32 ctrl;
diff --git a/arch/arm/include/asm/arch-socfpga/socfpga_base_addrs.h b/arch/arm/include/asm/arch-socfpga/socfpga_base_addrs.h
index 2d3152d..39a7874 100644
--- a/arch/arm/include/asm/arch-socfpga/socfpga_base_addrs.h
+++ b/arch/arm/include/asm/arch-socfpga/socfpga_base_addrs.h
@@ -7,9 +7,15 @@
#ifndef _SOCFPGA_BASE_ADDRS_H_
#define _SOCFPGA_BASE_ADDRS_H_
+#define SOCFPGA_EMAC0_ADDRESS 0xff700000
+#define SOCFPGA_EMAC1_ADDRESS 0xff702000
+#define SOCFPGA_SDMMC_ADDRESS 0xff704000
+#define SOCFPGA_FPGAMGRREGS_ADDRESS 0xff706000
#define SOCFPGA_L3REGS_ADDRESS 0xff800000
+#define SOCFPGA_FPGAMGRDATA_ADDRESS 0xffb90000
#define SOCFPGA_UART0_ADDRESS 0xffc02000
#define SOCFPGA_UART1_ADDRESS 0xffc03000
+#define SOCFPGA_SDR_ADDRESS 0xffc20000
#define SOCFPGA_OSC1TIMER0_ADDRESS 0xffd00000
#define SOCFPGA_L4WD0_ADDRESS 0xffd02000
#define SOCFPGA_CLKMGR_ADDRESS 0xffd04000
diff --git a/arch/arm/include/asm/arch-socfpga/system_manager.h b/arch/arm/include/asm/arch-socfpga/system_manager.h
index 838d210..38b5598 100644
--- a/arch/arm/include/asm/arch-socfpga/system_manager.h
+++ b/arch/arm/include/asm/arch-socfpga/system_manager.h
@@ -84,4 +84,49 @@ struct socfpga_system_manager {
u32 eccgrp_sdmmc;
};
+/* FPGA interface group */
+#define SYSMGR_FPGAINTF_MODULE (SOCFPGA_SYSMGR_ADDRESS + 0x28)
+/* EMAC interface selection */
+#define CONFIG_SYSMGR_EMAC_CTRL (SOCFPGA_SYSMGR_ADDRESS + 0x60)
+
+/* Preloader handoff to bootloader register */
+#define SYSMGR_ISWGRP_HANDOFF0 (SOCFPGA_SYSMGR_ADDRESS + 0x80)
+#define SYSMGR_ISWGRP_HANDOFF1 (SOCFPGA_SYSMGR_ADDRESS + 0x84)
+#define SYSMGR_ISWGRP_HANDOFF2 (SOCFPGA_SYSMGR_ADDRESS + 0x88)
+#define SYSMGR_ISWGRP_HANDOFF3 (SOCFPGA_SYSMGR_ADDRESS + 0x8C)
+#define SYSMGR_ISWGRP_HANDOFF4 (SOCFPGA_SYSMGR_ADDRESS + 0x90)
+#define SYSMGR_ISWGRP_HANDOFF5 (SOCFPGA_SYSMGR_ADDRESS + 0x94)
+#define SYSMGR_ISWGRP_HANDOFF6 (SOCFPGA_SYSMGR_ADDRESS + 0x98)
+#define SYSMGR_ISWGRP_HANDOFF7 (SOCFPGA_SYSMGR_ADDRESS + 0x9C)
+
+#define ISWGRP_HANDOFF_AXIBRIDGE SYSMGR_ISWGRP_HANDOFF0
+#define ISWGRP_HANDOFF_L3REMAP SYSMGR_ISWGRP_HANDOFF1
+#define ISWGRP_HANDOFF_FPGAINTF SYSMGR_ISWGRP_HANDOFF2
+#define ISWGRP_HANDOFF_FPGA2SDR SYSMGR_ISWGRP_HANDOFF3
+
+/* bit fields */
+#define CONFIG_SYSMGR_PINMUXGRP_OFFSET (0x400)
+#define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGPINMUX (1<<0)
+#define SYSMGR_ROMCODEGRP_CTRL_WARMRSTCFGIO (1<<1)
+#define SYSMGR_ECC_OCRAM_EN (1<<0)
+#define SYSMGR_ECC_OCRAM_SERR (1<<3)
+#define SYSMGR_ECC_OCRAM_DERR (1<<4)
+#define SYSMGR_FPGAINTF_USEFPGA 0x1
+#define SYSMGR_FPGAINTF_SPIM0 (1<<0)
+#define SYSMGR_FPGAINTF_SPIM1 (1<<1)
+#define SYSMGR_FPGAINTF_EMAC0 (1<<2)
+#define SYSMGR_FPGAINTF_EMAC1 (1<<3)
+#define SYSMGR_FPGAINTF_NAND (1<<4)
+#define SYSMGR_FPGAINTF_SDMMC (1<<5)
+
+/* pin mux */
+#define SYSMGR_PINMUXGRP (SOCFPGA_SYSMGR_ADDRESS + 0x400)
+#define SYSMGR_PINMUXGRP_FLASHIO1 (SYSMGR_PINMUXGRP + 0x54)
+#define SYSMGR_PINMUXGRP_NANDUSEFPGA (SYSMGR_PINMUXGRP + 0x2F0)
+#define SYSMGR_PINMUXGRP_EMAC1USEFPGA (SYSMGR_PINMUXGRP + 0x2F8)
+#define SYSMGR_PINMUXGRP_SDMMCUSEFPGA (SYSMGR_PINMUXGRP + 0x308)
+#define SYSMGR_PINMUXGRP_EMAC0USEFPGA (SYSMGR_PINMUXGRP + 0x314)
+#define SYSMGR_PINMUXGRP_SPIM1USEFPGA (SYSMGR_PINMUXGRP + 0x330)
+#define SYSMGR_PINMUXGRP_SPIM0USEFPGA (SYSMGR_PINMUXGRP + 0x338)
+
#endif /* _SYSTEM_MANAGER_H_ */
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index d51ba66..f0dcbd7 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -185,6 +185,7 @@ enum dcache_option {
DCACHE_OFF = 0x12,
DCACHE_WRITETHROUGH = 0x1a,
DCACHE_WRITEBACK = 0x1e,
+ DCACHE_WRITEBACK_WRITEALLOCATE = 0x16,
};
/* Size of an MMU section */
diff --git a/arch/arm/lib/cache-cp15.c b/arch/arm/lib/cache-cp15.c
index 3e62d58..3227e5d 100644
--- a/arch/arm/lib/cache-cp15.c
+++ b/arch/arm/lib/cache-cp15.c
@@ -73,6 +73,8 @@ __weak void dram_bank_mmu_setup(int bank)
i++) {
#if defined(CONFIG_SYS_ARM_CACHE_WRITETHROUGH)
set_section_dcache(i, DCACHE_WRITETHROUGH);
+#elif defined(CONFIG_SYS_ARM_CACHE_WRITEBACK_WRITEALLOCATE)
+ set_section_dcache(i, DCACHE_WRITEBACK_WRITEALLOCATE);
#else
set_section_dcache(i, DCACHE_WRITEBACK);
#endif
diff --git a/board/altera/socfpga/socfpga_cyclone5.c b/board/altera/socfpga/socfpga_cyclone5.c
index fb92852..6b74997d 100644
--- a/board/altera/socfpga/socfpga_cyclone5.c
+++ b/board/altera/socfpga/socfpga_cyclone5.c
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Altera Corporation <www.altera.com>
+ * Copyright (C) 2014 Pavel Machek, pavel at denx.de
*
* SPDX-License-Identifier: GPL-2.0+
*/
@@ -8,8 +9,6 @@
#include <asm/arch/reset_manager.h>
#include <asm/io.h>
-#include <netdev.h>
-
DECLARE_GLOBAL_DATA_PTR;
/*
@@ -34,6 +33,17 @@ int board_early_init_f(void)
*/
int board_init(void)
{
- icache_enable();
+ // icache_enable();
+ puts("derive_clocks_for_drivers... \n");
+#if 1
+ /* calculate the clock frequencies required for drivers */
+ cm_derive_clocks_for_drivers();
+
+ puts("derive_clocks_for_drivers... done\n");
+#endif
+
+ /* adress of boot parameters for ATAG (if ATAG is used) */
+ gd->bd->bi_boot_params = 0x00000100;
+
return 0;
}
diff --git a/common/cmd_fpga.c b/common/cmd_fpga.c
index 8c5bf44..884c61a 100644
--- a/common/cmd_fpga.c
+++ b/common/cmd_fpga.c
@@ -43,6 +43,7 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
void *fpga_data = NULL;
char *devstr = getenv("fpga");
char *datastr = getenv("fpgadata");
+ char *devsizestr = getenv("fpgadatasize");
int rc = FPGA_FAIL;
int wrong_parms = 0;
#if defined(CONFIG_FIT)
@@ -57,7 +58,9 @@ int do_fpga(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
if (devstr)
dev = (int) simple_strtoul(devstr, NULL, 16);
if (datastr)
- fpga_data = (void *)simple_strtoul(datastr, NULL, 16);
+ fpga_data = (void *) simple_strtoul(datastr, NULL, 16);
+ if (devsizestr)
+ data_size = (size_t) simple_strtoul(devsizestr, NULL, 16);
switch (argc) {
#if defined(CONFIG_CMD_FPGA_LOADFS)
diff --git a/common/memsize.c b/common/memsize.c
index 589400d..0cae738 100644
--- a/common/memsize.c
+++ b/common/memsize.c
@@ -33,6 +33,8 @@ long get_ram_size(long *base, long maxsize)
long size;
int i = 0;
+ return maxsize;
+
for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
sync ();
diff --git a/drivers/fpga/altera.c b/drivers/fpga/altera.c
index 6e34a8e..36d8826 100644
--- a/drivers/fpga/altera.c
+++ b/drivers/fpga/altera.c
@@ -1,4 +1,7 @@
/*
+ * (C) Copyright 2013
+ * Altera Corporation <www.altera.com>
+ *
* (C) Copyright 2003
* Steven Scholz, imc Measurement & Control, steven.scholz at imc-berlin.de
*
@@ -14,6 +17,9 @@
#include <common.h>
#include <ACEX1K.h>
#include <stratixII.h>
+#if defined(CONFIG_FPGA_SOCFPGA)
+#include <asm/arch/fpga_manager.h>
+#endif
/* Define FPGA_DEBUG to get debug printf's */
/* #define FPGA_DEBUG */
@@ -59,6 +65,18 @@ int altera_load(Altera_desc *desc, const void *buf, size_t bsize)
ret_val = StratixII_load (desc, buf, bsize);
break;
#endif
+#if defined(CONFIG_FPGA_SOCFPGA)
+ case Altera_SoCFPGA:
+ PRINTF("%s: Launching the SoC FPGA Loader...\n",
+ __func__);
+ ret_val = fpgamgr_program_fpga(buf, bsize);
+ if (ret_val) {
+ printf("%s: Failed with error code %d\n",
+ __func__, ret_val);
+ ret_val = 1;
+ }
+ break;
+#endif
default:
printf ("%s: Unsupported family type, %d\n",
__FUNCTION__, desc->family);
@@ -94,6 +112,11 @@ int altera_dump(Altera_desc *desc, const void *buf, size_t bsize)
ret_val = StratixII_dump (desc, buf, bsize);
break;
#endif
+ case Altera_SoCFPGA:
+ printf("%s: Unsupported due to security reason, %d\n",
+ __func__, desc->family);
+ ret_val = FPGA_SUCCESS;
+ break;
default:
printf ("%s: Unsupported family type, %d\n",
__FUNCTION__, desc->family);
@@ -119,6 +142,9 @@ int altera_info( Altera_desc *desc )
case Altera_StratixII:
printf ("Stratix II\n");
break;
+ case Altera_SoCFPGA:
+ printf("SoC FPGA\n");
+ break;
/* Add new family types here */
default:
printf ("Unknown family type, %d\n", desc->family);
diff --git a/drivers/mmc/dw_mmc.c b/drivers/mmc/dw_mmc.c
index 0df30bc..4c16e7f 100644
--- a/drivers/mmc/dw_mmc.c
+++ b/drivers/mmc/dw_mmc.c
@@ -177,14 +177,16 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
}
}
- if (i == retry)
+ if (i == retry) {
+ printf("dwmci_send_cmd: timeout..\n");
return TIMEOUT;
+ }
if (mask & DWMCI_INTMSK_RTO) {
- debug("Response Timeout..\n");
+ printf("dwmci_send_cmd: Response Timeout..\n");
return TIMEOUT;
} else if (mask & DWMCI_INTMSK_RE) {
- debug("Response Error..\n");
+ printf("dwmci_send_cmd: Response Error..\n");
return -1;
}
@@ -204,7 +206,7 @@ static int dwmci_send_cmd(struct mmc *mmc, struct mmc_cmd *cmd,
do {
mask = dwmci_readl(host, DWMCI_RINTSTS);
if (mask & (DWMCI_DATA_ERR | DWMCI_DATA_TOUT)) {
- debug("DATA ERROR!\n");
+ printf("dwmci_send_cmd: DATA ERROR!\n");
return -1;
}
} while (!(mask & DWMCI_INTMSK_DTO));
@@ -232,16 +234,16 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
if ((freq == host->clock) || (freq == 0))
return 0;
/*
- * If host->get_mmc_clk didn't define,
+ * If host->get_mmc_clk isn't defined,
* then assume that host->bus_hz is source clock value.
- * host->bus_hz should be set from user.
+ * host->bus_hz should be set by user.
*/
if (host->get_mmc_clk)
sclk = host->get_mmc_clk(host);
else if (host->bus_hz)
sclk = host->bus_hz;
else {
- printf("Didn't get source clock value..\n");
+ printf("dwmci_setup_bus: Didn't get source clock value..\n");
return -EINVAL;
}
@@ -260,7 +262,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
do {
status = dwmci_readl(host, DWMCI_CMD);
if (timeout-- < 0) {
- printf("TIMEOUT error!!\n");
+ printf("dwmci_setup_bus: timeout!\n");
return -ETIMEDOUT;
}
} while (status & DWMCI_CMD_START);
@@ -275,7 +277,7 @@ static int dwmci_setup_bus(struct dwmci_host *host, u32 freq)
do {
status = dwmci_readl(host, DWMCI_CMD);
if (timeout-- < 0) {
- printf("TIMEOUT error!!\n");
+ printf("dwmci_setup_bus: timeout!\n");
return -ETIMEDOUT;
}
} while (status & DWMCI_CMD_START);
@@ -290,7 +292,7 @@ static void dwmci_set_ios(struct mmc *mmc)
struct dwmci_host *host = (struct dwmci_host *)mmc->priv;
u32 ctype, regs;
- debug("Buswidth = %d, clock: %d\n",mmc->bus_width, mmc->clock);
+ debug("Buswidth = %d, clock: %d\n", mmc->bus_width, mmc->clock);
dwmci_setup_bus(host, mmc->clock);
switch (mmc->bus_width) {
@@ -329,7 +331,7 @@ static int dwmci_init(struct mmc *mmc)
dwmci_writel(host, DWMCI_PWREN, 1);
if (!dwmci_wait_reset(host, DWMCI_RESET_ALL)) {
- debug("%s[%d] Fail-reset!!\n",__func__,__LINE__);
+ printf("%s[%d] Fail-reset!!\n", __func__, __LINE__);
return -1;
}
diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c
index 1f96382..d8da7f5 100644
--- a/drivers/mmc/socfpga_dw_mmc.c
+++ b/drivers/mmc/socfpga_dw_mmc.c
@@ -16,6 +16,8 @@ static const struct socfpga_clock_manager *clock_manager_base =
static const struct socfpga_system_manager *system_manager_base =
(void *)SOCFPGA_SYSMGR_ADDRESS;
+#define CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK (1 << 8)
+
static void socfpga_dwmci_clksel(struct dwmci_host *host)
{
unsigned int drvsel;
@@ -58,7 +60,8 @@ int socfpga_dwmmc_init(u32 regbase, int bus_width, int index)
host->clksel = socfpga_dwmci_clksel;
host->dev_index = index;
/* fixed clock divide by 4 which due to the SDMMC wrapper */
- host->bus_hz = CONFIG_SOCFPGA_DWMMC_BUS_HZ;
+ host->bus_hz = cm_sdmmc_clock;
+ printf("bus_hz: %ld\n", host->bus_hz);
host->fifoth_val = MSIZE(0x2) |
RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) |
TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2);
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 5d7e3be..06a31b0 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -25,8 +25,7 @@ static struct phy_driver KSZ804_driver = {
#ifndef CONFIG_PHY_MICREL_KSZ9021
/*
* I can't believe Micrel used the exact same part number
- * for the KSZ9021
- * Shame Micrel, Shame!!!!!
+ * for the KSZ9021. Shame Micrel, Shame!
*/
static struct phy_driver KS8721_driver = {
.name = "Micrel KS8721BL",
@@ -40,7 +39,7 @@ static struct phy_driver KS8721_driver = {
#endif
-/**
+/*
* KSZ9021 - KSZ9031 common
*/
@@ -69,8 +68,8 @@ static int ksz90xx_startup(struct phy_device *phydev)
phydev->speed = SPEED_10;
return 0;
}
-#ifdef CONFIG_PHY_MICREL_KSZ9021
+#ifdef CONFIG_PHY_MICREL_KSZ9021
/*
* KSZ9021
*/
@@ -113,17 +112,46 @@ static int ksz9021_phy_extwrite(struct phy_device *phydev, int addr,
return ksz9021_phy_extended_write(phydev, regnum, val);
}
+/* FIXME: disable_giga is probably what we want to do */
+
/* Micrel ksz9021 */
static int ksz9021_config(struct phy_device *phydev)
{
unsigned ctrl1000 = 0;
const unsigned master = CTRL1000_PREFER_MASTER |
- CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
+ CTRL1000_CONFIG_MASTER | CTRL1000_MANUAL_CONFIG;
unsigned features = phydev->drv->features;
+ printf("ksz9021: configuring\n");
+
+ printf("Configuring PHY skew timing for %s\n",
+ phydev->drv->name);
+
+ /* min rx data delay */
+ if (ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_RX_DATA_SKEW,
+ getenv_ulong(CONFIG_KSZ9021_DATA_SKEW_ENV, 16,
+ CONFIG_KSZ9021_DATA_SKEW_VAL)) < 0)
+ return -1;
+ /* min tx data delay */
+ if (ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_TX_DATA_SKEW,
+ getenv_ulong(CONFIG_KSZ9021_DATA_SKEW_ENV, 16,
+ CONFIG_KSZ9021_DATA_SKEW_VAL)) < 0)
+ return -1;
+ /* max rx/tx clock delay, min rx/tx control */
+ if (ksz9021_phy_extended_write(phydev,
+ MII_KSZ9021_EXT_RGMII_CLOCK_SKEW,
+ getenv_ulong(CONFIG_KSZ9021_CLK_SKEW_ENV, 16,
+ CONFIG_KSZ9021_CLK_SKEW_VAL)) < 0)
+ return -1;
+
+ printf("ksz9021: skew ok\n");
+
+
if (getenv("disable_giga"))
features &= ~(SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full);
+ SUPPORTED_1000baseT_Full);
/* force master mode for 1000BaseT due to chip errata */
if (features & SUPPORTED_1000baseT_Half)
ctrl1000 |= ADVERTISE_1000HALF | master;
diff --git a/examples/standalone/Makefile b/examples/standalone/Makefile
index 2dacba2..163672f 100644
--- a/examples/standalone/Makefile
+++ b/examples/standalone/Makefile
@@ -5,7 +5,8 @@
# SPDX-License-Identifier: GPL-2.0+
#
-extra-y := hello_world
+extra-y :=
+#extra-y := hello_world
extra-$(CONFIG_SMC91111) += smc91111_eeprom
extra-$(CONFIG_SMC911X) += smc911x_eeprom
extra-$(CONFIG_SPI_FLASH_ATMEL) += atmel_df_pow2
diff --git a/include/altera.h b/include/altera.h
index ae5f7ee..c7f78fc 100644
--- a/include/altera.h
+++ b/include/altera.h
@@ -27,6 +27,7 @@ typedef enum { /* typedef Altera_Family */
Altera_ACEX1K, /* ACEX1K Family */
Altera_CYC2, /* CYCLONII Family */
Altera_StratixII, /* StratixII Family */
+ Altera_SoCFPGA, /* SoCFPGA Family */
/* Add new models here */
max_altera_type /* insert all new types before this */
} Altera_Family; /* end, typedef Altera_Family */
diff --git a/include/configs/axs101.h b/include/configs/axs101.h
index c22d6d0..1bf83907 100644
--- a/include/configs/axs101.h
+++ b/include/configs/axs101.h
@@ -125,7 +125,6 @@
*/
#define CONFIG_DESIGNWARE_ETH
#define CONFIG_DW_AUTONEG
-#define CONFIG_DW_SEARCH_PHY
#define CONFIG_NET_MULTI
/*
diff --git a/include/configs/socfpga_cyclone5.h b/include/configs/socfpga_cyclone5.h
index 5d145cd..d3d1e48 100644
--- a/include/configs/socfpga_cyclone5.h
+++ b/include/configs/socfpga_cyclone5.h
@@ -11,6 +11,8 @@
#include "../../board/altera/socfpga/iocsr_config.h"
#include "../../board/altera/socfpga/pll_config.h"
+#define CONFIG_SYS_GENERIC_BOARD
+
/*
* High level configuration
*/
@@ -23,6 +25,12 @@
#define CONFIG_MISC_INIT_R
#define CONFIG_SINGLE_BOOTLOADER
+
+/* Enable THUMB2 mode to reduce software size which yield better boot time */
+#define CONFIG_SYS_THUMB_BUILD
+
+#define CONFIG_SYS_ARM_CACHE_WRITEBACK_WRITEALLOCATE
+
#define CONFIG_SOCFPGA
/* base address for .text section */
@@ -31,7 +39,7 @@
#else
#define CONFIG_SYS_TEXT_BASE 0x01000040
#endif
-#define CONFIG_SYS_LOAD_ADDR 0x7fc0
+#define CONFIG_SYS_LOAD_ADDR 0x8000
/* Console I/O Buffer Size */
#define CONFIG_SYS_CBSIZE 256
@@ -56,7 +64,8 @@
/* skip updating the FDT blob */
#define CONFIG_FDT_BLOB_SKIP_UPDATE
/* Initial Memory map size for Linux, minus 4k alignment for DFT blob */
-#define CONFIG_SYS_BOOTMAPSZ ((256*1024*1024) - (4*1024))
+#define CONFIG_SYS_BOOTMAPSZ (64 * 1024 * 1024)
+
#define CONFIG_SPL_RAM_DEVICE
#define CONFIG_SPL_STACK CONFIG_SYS_INIT_SP_ADDR
@@ -67,9 +76,9 @@
* Memory allocation (MALLOC)
*/
/* Room required on the stack for the environment data */
-#define CONFIG_ENV_SIZE 1024
+#define CONFIG_ENV_SIZE 4096
/* Size of DRAM reserved for malloc() use */
-#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 128*1024)
+#define CONFIG_SYS_MALLOC_LEN (CONFIG_ENV_SIZE + 256*1024)
/* SP location before relocation, must use scratch RAM */
#define CONFIG_SYS_INIT_RAM_ADDR 0xFFFF0000
@@ -119,7 +128,7 @@
* CONFIG_BOOTARGS goes into the environment value "bootargs".
* Do note the value will overide also the chosen node in FDT blob.
*/
-#define CONFIG_BOOTARGS "console=ttyS0,57600,mem=256M at 0x0"
+#define CONFIG_BOOTARGS "console=ttyS0,115200,mem=256M at 0x0"
#define CONFIG_EXTRA_ENV_SETTINGS \
"verify=n\0" \
@@ -134,7 +143,8 @@
"qspirootfstype=jffs2\0" \
"qspiboot=setenv bootargs " CONFIG_BOOTARGS \
" root=${qspiroot} rw rootfstype=${qspirootfstype};"\
- "bootm ${loadaddr} - ${fdt_addr}\0"
+ "bootm ${loadaddr} - ${fdt_addr}\0" \
+ "ethaddr=12:23:34:46:56:60\0"
/* using environment setting for stdin, stdout, stderr */
#define CONFIG_SYS_CONSOLE_IS_IN_ENV
@@ -159,13 +169,30 @@
/* SDRAM Bank #1 */
#define CONFIG_SYS_SDRAM_BASE 0x00000000
/* SDRAM memory size */
-#define PHYS_SDRAM_1_SIZE 0x40000000
+/* FIXME: rocketboards uses different version */
+#define PHYS_SDRAM_1_SIZE 0x20000000
#define PHYS_SDRAM_1 CONFIG_SYS_SDRAM_BASE
#define CONFIG_SYS_MEMTEST_START 0x00000000
#define CONFIG_SYS_MEMTEST_END PHYS_SDRAM_1_SIZE
/*
+ * FPGA support
+ */
+/* Enables FPGA subsystem */
+#define CONFIG_FPGA
+#ifdef CONFIG_FPGA
+/* Altera FPGA */
+#define CONFIG_FPGA_ALTERA
+/* Family type */
+#define CONFIG_FPGA_SOCFPGA
+/* Only support single device */
+#define CONFIG_FPGA_COUNT (1)
+/* Enable FPGA command at console */
+#define CONFIG_CMD_FPGA
+#endif
+
+/*
* NS16550 Configuration
*/
#define UART0_BASE SOCFPGA_UART0_ADDRESS
@@ -188,6 +215,25 @@
*/
#define CONFIG_SYS_NO_FLASH
+
+/*
+ * MMC support
+ */
+#define CONFIG_MMC
+#ifdef CONFIG_MMC
+#define CONFIG_CMD_MMC
+
+#define CONFIG_BOUNCE_BUFFER
+#define CONFIG_GENERIC_MMC 1
+#define CONFIG_DWMMC 1
+#define CONFIG_SOCFPGA_DWMMC 1
+#define CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH 1024
+#define CONFIG_SOCFPGA_DWMMC_DRVSEL 3
+#define CONFIG_SOCFPGA_DWMMC_SMPSEL 0
+/* using smaller max blk cnt to avoid flooding the limited stack we have */
+#define CONFIG_SYS_MMC_MAX_BLK_COUNT 256
+#endif /* CONFIG_MMC */
+
/*
* L4 OSC1 Timer 0
*/
@@ -225,31 +271,41 @@
/* designware */
#define CONFIG_NET_MULTI
#define CONFIG_DW_ALTDESCRIPTOR
-#define CONFIG_DW_SEARCH_PHY
#define CONFIG_MII
#define CONFIG_PHY_GIGE
-#define CONFIG_DW_AUTONEG
#define CONFIG_AUTONEG_TIMEOUT (15 * CONFIG_SYS_HZ)
#define CONFIG_PHYLIB
#define CONFIG_PHY_MICREL
#define CONFIG_PHY_MICREL_KSZ9021
/* EMAC controller and PHY used */
-#define CONFIG_EMAC_BASE CONFIG_EMAC1_BASE
-#define CONFIG_EPHY_PHY_ADDR CONFIG_EPHY1_PHY_ADDR
+#define CONFIG_EMAC_BASE SOCFPGA_EMAC1_ADDRESS
#define CONFIG_PHY_INTERFACE_MODE PHY_INTERFACE_MODE_RGMII
+
+/* phy */
+#define CONFIG_EPHY0_PHY_ADDR 0
+#define CONFIG_EPHY1_PHY_ADDR 4
+#define CONFIG_KSZ9021_CLK_SKEW_ENV "micrel-ksz9021-clk-skew"
+#define CONFIG_KSZ9021_CLK_SKEW_VAL 0xf0f0
+#define CONFIG_KSZ9021_DATA_SKEW_ENV "micrel-ksz9021-data-skew"
+#define CONFIG_KSZ9021_DATA_SKEW_VAL 0x0
+/* Type of PHY available */
+#define SOCFPGA_PHYSEL_ENUM_GMII 0x0
+#define SOCFPGA_PHYSEL_ENUM_MII 0x1
+#define SOCFPGA_PHYSEL_ENUM_RGMII 0x2
+#define SOCFPGA_PHYSEL_ENUM_RMII 0x3
+
#endif /* CONFIG_DESIGNWARE_ETH */
/*
* L4 Watchdog
*/
#define CONFIG_HW_WATCHDOG
-#define CONFIG_HW_WATCHDOG_TIMEOUT_MS 2000
+#define CONFIG_HW_WATCHDOG_TIMEOUT_MS 12000
#define CONFIG_DESIGNWARE_WATCHDOG
#define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS
/* Clocks source frequency to watchdog timer */
#define CONFIG_DW_WDT_CLOCK_KHZ 25000
-
/*
* SPL "Second Program Loader" aka Initial Software
*/
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
More information about the U-Boot
mailing list