This function will be needed by the upcoming Designware master SPI driver. As the SPI master controller is held in reset by the current Preloader implementation. So we need to release the reset for the driver to communicate with the controller. This function is called from arch_early_init_r() if the SPI driver is enabled. Signed-off-by: Stefan Roese <sr@denx.de> Cc: Chin Liang See <clsee@altera.com> Cc: Dinh Nguyen <dinguyen@altera.com> Cc: Vince Bridgers <vbridger@altera.com> Cc: Marek Vasut <marex@denx.de> Cc: Pavel Machek <pavel@denx.de>
280 lines
6.7 KiB
C
280 lines
6.7 KiB
C
/*
|
|
* Copyright (C) 2012 Altera Corporation <www.altera.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
#include <common.h>
|
|
#include <asm/io.h>
|
|
#include <altera.h>
|
|
#include <miiphy.h>
|
|
#include <netdev.h>
|
|
#include <asm/arch/reset_manager.h>
|
|
#include <asm/arch/system_manager.h>
|
|
#include <asm/arch/dwmmc.h>
|
|
#include <asm/arch/nic301.h>
|
|
#include <asm/arch/scu.h>
|
|
#include <asm/pl310.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static struct pl310_regs *const pl310 =
|
|
(struct pl310_regs *)CONFIG_SYS_PL310_BASE;
|
|
static struct socfpga_system_manager *sysmgr_regs =
|
|
(struct socfpga_system_manager *)SOCFPGA_SYSMGR_ADDRESS;
|
|
static struct socfpga_reset_manager *reset_manager_base =
|
|
(struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS;
|
|
static struct nic301_registers *nic301_regs =
|
|
(struct nic301_registers *)SOCFPGA_L3REGS_ADDRESS;
|
|
static struct scu_registers *scu_regs =
|
|
(struct scu_registers *)SOCFPGA_MPUSCU_ADDRESS;
|
|
|
|
int dram_init(void)
|
|
{
|
|
gd->ram_size = get_ram_size((long *)PHYS_SDRAM_1, PHYS_SDRAM_1_SIZE);
|
|
return 0;
|
|
}
|
|
|
|
void enable_caches(void)
|
|
{
|
|
#ifndef CONFIG_SYS_ICACHE_OFF
|
|
icache_enable();
|
|
#endif
|
|
#ifndef CONFIG_SYS_DCACHE_OFF
|
|
dcache_enable();
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* DesignWare Ethernet initialization
|
|
*/
|
|
#ifdef CONFIG_DESIGNWARE_ETH
|
|
int cpu_eth_init(bd_t *bis)
|
|
{
|
|
#if CONFIG_EMAC_BASE == SOCFPGA_EMAC0_ADDRESS
|
|
const int physhift = SYSMGR_EMACGRP_CTRL_PHYSEL0_LSB;
|
|
#elif CONFIG_EMAC_BASE == SOCFPGA_EMAC1_ADDRESS
|
|
const int physhift = SYSMGR_EMACGRP_CTRL_PHYSEL1_LSB;
|
|
#else
|
|
#error "Incorrect CONFIG_EMAC_BASE value!"
|
|
#endif
|
|
|
|
/* 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
|
|
*/
|
|
socfpga_emac_reset(1);
|
|
|
|
/* Clearing emac0 PHY interface select to 0 */
|
|
clrbits_le32(&sysmgr_regs->emacgrp_ctrl,
|
|
SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << physhift);
|
|
|
|
/* configure to PHY interface select choosed */
|
|
setbits_le32(&sysmgr_regs->emacgrp_ctrl,
|
|
SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII << physhift);
|
|
|
|
/* Release the EMAC controller from reset */
|
|
socfpga_emac_reset(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,
|
|
CONFIG_HPS_SDMMC_BUSWIDTH, 0);
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_DISPLAY_CPUINFO)
|
|
/*
|
|
* Print CPU information
|
|
*/
|
|
int print_cpuinfo(void)
|
|
{
|
|
puts("CPU: Altera SoCFPGA Platform\n");
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
|
|
defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
|
|
int overwrite_console(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_FPGA
|
|
/*
|
|
* FPGA programming support for SoC FPGA Cyclone V
|
|
*/
|
|
static Altera_desc altera_fpga[] = {
|
|
{
|
|
/* Family */
|
|
Altera_SoCFPGA,
|
|
/* Interface type */
|
|
fast_passive_parallel,
|
|
/* No limitation as additional data will be ignored */
|
|
-1,
|
|
/* No device function table */
|
|
NULL,
|
|
/* Base interface address specified in driver */
|
|
NULL,
|
|
/* No cookie implementation */
|
|
0
|
|
},
|
|
};
|
|
|
|
/* add device descriptor to FPGA device table */
|
|
static void socfpga_fpga_add(void)
|
|
{
|
|
int i;
|
|
fpga_init();
|
|
for (i = 0; i < ARRAY_SIZE(altera_fpga); i++)
|
|
fpga_add(fpga_altera, &altera_fpga[i]);
|
|
}
|
|
#else
|
|
static inline void socfpga_fpga_add(void) {}
|
|
#endif
|
|
|
|
int arch_cpu_init(void)
|
|
{
|
|
/*
|
|
* If the HW watchdog is NOT enabled, make sure it is not running,
|
|
* for example because it was enabled in the preloader. This might
|
|
* trigger a watchdog-triggered reboot of Linux kernel later.
|
|
*/
|
|
#ifndef CONFIG_HW_WATCHDOG
|
|
socfpga_watchdog_reset();
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* Convert all NIC-301 AMBA slaves from secure to non-secure
|
|
*/
|
|
static void socfpga_nic301_slave_ns(void)
|
|
{
|
|
writel(0x1, &nic301_regs->lwhps2fpgaregs);
|
|
writel(0x1, &nic301_regs->hps2fpgaregs);
|
|
writel(0x1, &nic301_regs->acp);
|
|
writel(0x1, &nic301_regs->rom);
|
|
writel(0x1, &nic301_regs->ocram);
|
|
writel(0x1, &nic301_regs->sdrdata);
|
|
}
|
|
|
|
static uint32_t iswgrp_handoff[8];
|
|
|
|
int arch_early_init_r(void)
|
|
{
|
|
int i;
|
|
for (i = 0; i < 8; i++) /* Cache initial SW setting regs */
|
|
iswgrp_handoff[i] = readl(&sysmgr_regs->iswgrp_handoff[i]);
|
|
|
|
socfpga_bridges_reset(1);
|
|
socfpga_nic301_slave_ns();
|
|
|
|
/*
|
|
* Private components security:
|
|
* U-Boot : configure private timer, global timer and cpu component
|
|
* access as non secure for kernel stage (as required by Linux)
|
|
*/
|
|
setbits_le32(&scu_regs->sacr, 0xfff);
|
|
|
|
/* Configure the L2 controller to make SDRAM start at 0 */
|
|
#ifdef CONFIG_SOCFPGA_VIRTUAL_TARGET
|
|
writel(0x2, &nic301_regs->remap);
|
|
#else
|
|
writel(0x1, &nic301_regs->remap); /* remap.mpuzero */
|
|
writel(0x1, &pl310->pl310_addr_filter_start);
|
|
#endif
|
|
|
|
/* Add device descriptor to FPGA device table */
|
|
socfpga_fpga_add();
|
|
|
|
#ifdef CONFIG_DESIGNWARE_SPI
|
|
/* Get Designware SPI controller out of reset */
|
|
socfpga_spim_enable();
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void socfpga_sdram_apply_static_cfg(void)
|
|
{
|
|
const uint32_t staticcfg = SOCFPGA_SDR_ADDRESS + 0x505c;
|
|
const uint32_t applymask = 0x8;
|
|
uint32_t val = readl(staticcfg) | applymask;
|
|
|
|
/*
|
|
* SDRAM staticcfg register specific:
|
|
* When applying the register setting, the CPU must not access
|
|
* SDRAM. Luckily for us, we can abuse i-cache here to help us
|
|
* circumvent the SDRAM access issue. The idea is to make sure
|
|
* that the code is in one full i-cache line by branching past
|
|
* it and back. Once it is in the i-cache, we execute the core
|
|
* of the code and apply the register settings.
|
|
*
|
|
* The code below uses 7 instructions, while the Cortex-A9 has
|
|
* 32-byte cachelines, thus the limit is 8 instructions total.
|
|
*/
|
|
asm volatile(
|
|
".align 5 \n"
|
|
" b 2f \n"
|
|
"1: str %0, [%1] \n"
|
|
" dsb \n"
|
|
" isb \n"
|
|
" b 3f \n"
|
|
"2: b 1b \n"
|
|
"3: nop \n"
|
|
: : "r"(val), "r"(staticcfg) : "memory", "cc");
|
|
}
|
|
|
|
int do_bridge(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
|
{
|
|
if (argc != 2)
|
|
return CMD_RET_USAGE;
|
|
|
|
argv++;
|
|
|
|
switch (*argv[0]) {
|
|
case 'e': /* Enable */
|
|
writel(iswgrp_handoff[2], &sysmgr_regs->fpgaintfgrp_module);
|
|
socfpga_sdram_apply_static_cfg();
|
|
writel(iswgrp_handoff[3], SOCFPGA_SDR_ADDRESS + 0x5080);
|
|
writel(iswgrp_handoff[0], &reset_manager_base->brg_mod_reset);
|
|
writel(iswgrp_handoff[1], &nic301_regs->remap);
|
|
break;
|
|
case 'd': /* Disable */
|
|
writel(0, &sysmgr_regs->fpgaintfgrp_module);
|
|
writel(0, SOCFPGA_SDR_ADDRESS + 0x5080);
|
|
socfpga_sdram_apply_static_cfg();
|
|
writel(0, &reset_manager_base->brg_mod_reset);
|
|
writel(1, &nic301_regs->remap);
|
|
break;
|
|
default:
|
|
return CMD_RET_USAGE;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
U_BOOT_CMD(
|
|
bridge, 2, 1, do_bridge,
|
|
"SoCFPGA HPS FPGA bridge control",
|
|
"enable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
|
|
"bridge disable - Enable HPS-to-FPGA, FPGA-to-HPS, LWHPS-to-FPGA bridges\n"
|
|
""
|
|
);
|