[U-Boot] [RFC] mainline u-boot on socfpga

Hi!
I know coding style leaves something to be desired.
But.. it recognizes MMC/ethernet, and can load linux kernel.
Unfortunately, linux kernel then fails to mount / filesystem (or fails to launch init if filesystem is clean); same kernel works with rocketboards u-boot. Ideas what could be a problem are welcome.
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..c062f1f 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,165 @@ 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)); + +} + +void cm_derive_clocks_for_drivers(void) +{ + cm_l4_sp_clock = cm_get_l4_sp_clk_hz(); +#if 0 /* FIXME */ + cm_sdmmc_clock = cm_get_mmc_controller_clk_hz(); + 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..71aaaec --- /dev/null +++ b/arch/arm/cpu/armv7/socfpga/fpga_manager.c @@ -0,0 +1,335 @@ +/* + * + * 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 +#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 + 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; + + /* 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); + + /* 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); + + /* (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) + return -1; + + /* release FPGA from reset phase */ + clrbits_le32(&fpga_manager_base->ctrl, + FPGAMGRREGS_CTRL_NCONFIGPULL_MASK); + + /* (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 interrupt 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); + + return 0; +} + +/* Write the RBF data to FPGA Manager */ +void fpgamgr_program_write(const unsigned long *rbf_data, + unsigned long rbf_size) +{ + fpgamgr_axi_write(rbf_data, SOCFPGA_FPGAMGRDATA_ADDRESS, rbf_size); +} + +/* Ensure the FPGA entering config done */ +int fpgamgr_program_poll_cd(void) +{ + unsigned long reg, i; + + /* (3) wait until full config done */ + for (i = 0; i < FPGA_TIMEOUT_CNT; i++) { + 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) + 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; + + /* 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); + + /* disable all signals from fpga to hps sdram */ + writel(0, (SOCFPGA_SDR_ADDRESS + SDR_CTRLGRP_FPGAPORTRST_ADDRESS)); + + /* disable all axi bridge (hps2fpga, lwhps2fpga & fpga2hps) */ + reset_assert_all_bridges(); + /* unmap the bridges from NIC-301 */ + writel(0x1, SOCFPGA_L3REGS_ADDRESS); + + /* initialize the FPGA Manager */ + status = fpgamgr_program_init(); + if (status) + return status; + + /* Write the RBF data to FPGA Manager */ + fpgamgr_program_write(rbf_data, rbf_size); + + /* Ensure the FPGA entering config done */ + status = fpgamgr_program_poll_cd(); + if (status) + return status; + + /* Ensure the FPGA entering init phase */ + status = fpgamgr_program_poll_initphase(); + if (status) + return status; + + /* 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..32bdc45 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,100 @@ lowlevel_init: str r2, [r1] #endif /* #ifdef CONFIG_SPL_BUILD */ mov pc, lr + + +#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 + +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 + */ + +.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..4b5cd99 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 0 /* FIXME */ + printf("Turning off all the bridges\n"); + reset_assert_all_bridges();
+ reset_deassert_all_bridges(); + printf("non-secure access to everyone\n"); + nic301_slave_ns(); +#endif + +#if 0 /* 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 (0) /* 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..7ae61f6 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,61 @@ 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 0 /* 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 */ + 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..aef3fd7 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@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,16 @@ int board_early_init_f(void) */ int board_init(void) { - icache_enable(); + /* adress of boot parameters for ATAG (if ATAG is used) */ + gd->bd->bi_boot_params = 0x00000100; + + // icache_enable(); + puts("derive_clocks_for_drivers... \n"); +#if 0 /* FIXME */ + /* calculate the clock frequencies required for drivers */ + cm_derive_clocks_for_drivers(); + + puts("derive_clocks_for_drivers... done\n"); +#endif 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@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/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c index 1f96382..1c285bc 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; 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..b700ba7 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@0x0" +#define CONFIG_BOOTARGS "console=ttyS0,115200,mem=256M@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,26 @@ */ #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_BUS_HZ 400000 +#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 +272,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 */

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@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@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@0x0" +#define CONFIG_BOOTARGS "console=ttyS0,115200,mem=256M@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 */

Hi Pavel,
On 09/08/2014 02:08 PM, Pavel Machek wrote:
Hi!
I know coding style leaves something to be desired.
It is more than this. Also SPDX license headers, etc.
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.
I have quickly looked at this patch and there are a lot of things in one patch and it is not possible to even quickly review. Please create patches with proper description and then we can review.
For drivers/fpga/altera.c please look at xilinx wrappers and change altera code based on that. Hopefully you can add all fpga code to drivers/fpga.
Thanks, Michal

Hi Pavel,
On Mon, 2014-09-08 at 14:08 +0200, ZY - pavel wrote:
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.
The lowest 1MB region is configurable based on the ARM interconnect NIC-301 / L3REGS setting. I saw in this patch, there is a code which setup the PL310 / L2 controller address filter start address. This code will convert the lowest 1MB region as SDRAM. If the next 1MB memory is working, the lowest 1MB should work too.
At same time, I noticed that the L2 controller address filter start address configuration is done at cpu_eth_init. I am wonder the failure you spotted is happening before this function is called?
Chin Liang

Hi Pavel,
On Mon, 2014-09-08 at 14:08 +0200, ZY - pavel wrote:
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.
This assembly version works well for me as I got daily test run to test this functionality. We got around 77% improvement using this assembly compared to C code previously. Having that said, probably you can share with me the details of your bug.
Chin Liang
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

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.
This assembly version works well for me as I got daily test run to test this functionality. We got around 77% improvement using this assembly compared to C code previously. Having that said, probably you can share with me the details of your bug.
It seems that if CONFIG_THUMB is enabled (as is in some versions, IIRC), it crashes and burns.
Compared with MMC speed, it seems to be fast enough, but ok, 77% speedup is nice. We have fixed version in tree, Marek will post it soon.
Best regards, Pavel
participants (3)
-
Chin Liang See
-
Michal Simek
-
Pavel Machek