The current bridge reset code, which de-asserted the bridge reset, was activelly polling whether the FPGA is programmed and ready and in case it was (!), the code called hang(). This makes no sense at all. Repair it such that the code instead checks whether the FPGA is programmed, but without any polling involved, and only if it is programmed, it de-asserts the reset. Signed-off-by: Marek Vasut <marex@denx.de>
101 lines
2.3 KiB
C
101 lines
2.3 KiB
C
/*
|
|
* Copyright (C) 2013 Altera Corporation <www.altera.com>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0+
|
|
*/
|
|
|
|
|
|
#include <common.h>
|
|
#include <asm/io.h>
|
|
#include <asm/arch/reset_manager.h>
|
|
#include <asm/arch/fpga_manager.h>
|
|
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
static const struct socfpga_reset_manager *reset_manager_base =
|
|
(void *)SOCFPGA_RSTMGR_ADDRESS;
|
|
|
|
/* Assert or de-assert SoCFPGA reset manager reset. */
|
|
void socfpga_per_reset(u32 reset, int set)
|
|
{
|
|
const void *reg;
|
|
|
|
if (RSTMGR_BANK(reset) == 0)
|
|
reg = &reset_manager_base->mpu_mod_reset;
|
|
else if (RSTMGR_BANK(reset) == 1)
|
|
reg = &reset_manager_base->per_mod_reset;
|
|
else if (RSTMGR_BANK(reset) == 2)
|
|
reg = &reset_manager_base->per2_mod_reset;
|
|
else if (RSTMGR_BANK(reset) == 3)
|
|
reg = &reset_manager_base->brg_mod_reset;
|
|
else if (RSTMGR_BANK(reset) == 4)
|
|
reg = &reset_manager_base->misc_mod_reset;
|
|
else /* Invalid reset register, do nothing */
|
|
return;
|
|
|
|
if (set)
|
|
setbits_le32(reg, 1 << RSTMGR_RESET(reset));
|
|
else
|
|
clrbits_le32(reg, 1 << RSTMGR_RESET(reset));
|
|
}
|
|
|
|
/*
|
|
* Write the reset manager register to cause reset
|
|
*/
|
|
void reset_cpu(ulong addr)
|
|
{
|
|
/* request a warm reset */
|
|
writel((1 << RSTMGR_CTRL_SWWARMRSTREQ_LSB),
|
|
&reset_manager_base->ctrl);
|
|
/*
|
|
* infinite loop here as watchdog will trigger and reset
|
|
* the processor
|
|
*/
|
|
while (1)
|
|
;
|
|
}
|
|
|
|
/*
|
|
* Release peripherals from reset based on handoff
|
|
*/
|
|
void reset_deassert_peripherals_handoff(void)
|
|
{
|
|
writel(0, &reset_manager_base->per_mod_reset);
|
|
}
|
|
|
|
#if defined(CONFIG_SOCFPGA_VIRTUAL_TARGET)
|
|
void socfpga_bridges_reset(int enable)
|
|
{
|
|
/* For SoCFPGA-VT, this is NOP. */
|
|
}
|
|
#else
|
|
|
|
#define L3REGS_REMAP_LWHPS2FPGA_MASK 0x10
|
|
#define L3REGS_REMAP_HPS2FPGA_MASK 0x08
|
|
#define L3REGS_REMAP_OCRAM_MASK 0x01
|
|
|
|
void socfpga_bridges_reset(int enable)
|
|
{
|
|
const uint32_t l3mask = L3REGS_REMAP_LWHPS2FPGA_MASK |
|
|
L3REGS_REMAP_HPS2FPGA_MASK |
|
|
L3REGS_REMAP_OCRAM_MASK;
|
|
|
|
if (enable) {
|
|
/* brdmodrst */
|
|
writel(0xffffffff, &reset_manager_base->brg_mod_reset);
|
|
} else {
|
|
/* Check signal from FPGA. */
|
|
if (!fpgamgr_test_fpga_ready()) {
|
|
/* FPGA not ready, do nothing. */
|
|
printf("%s: FPGA not ready, aborting.\n", __func__);
|
|
return;
|
|
}
|
|
|
|
/* brdmodrst */
|
|
writel(0, &reset_manager_base->brg_mod_reset);
|
|
|
|
/* Remap the bridges into memory map */
|
|
writel(l3mask, SOCFPGA_L3REGS_ADDRESS);
|
|
}
|
|
}
|
|
#endif
|