Merge branch 'master' of git://git.denx.de/u-boot-socfpga

- Gen 5 and Watchdog fixes
This commit is contained in:
Tom Rini 2020-02-06 23:18:42 -05:00
commit 457faef262
17 changed files with 398 additions and 108 deletions

View File

@ -56,3 +56,7 @@
&portc {
bank-name = "portc";
};
&watchdog0 {
u-boot,dm-pre-reloc;
};

View File

@ -31,3 +31,7 @@
&sysmgr {
u-boot,dm-pre-reloc;
};
&watchdog0 {
u-boot,dm-pre-reloc;
};

View File

@ -146,24 +146,51 @@ struct socfpga_sdram_rw_mgr_config {
u8 lfsr_wr_rd_dm_bank_0_nop;
u8 lfsr_wr_rd_dm_bank_0_wait;
u8 lfsr_wr_rd_dm_bank_0_wl_1;
u8 mrs0_dll_reset;
u8 mrs0_dll_reset_mirr;
u8 mrs0_user;
u8 mrs0_user_mirr;
u8 mrs1;
union {
u8 mrs0_dll_reset;
u8 mr_dll_reset;
};
union {
u8 mrs0_dll_reset_mirr;
u8 emr_ocd_enable;
};
union {
u8 mrs0_user;
u8 mr_user;
};
union {
u8 mrs0_user_mirr;
u8 mr_calib;
};
union {
u8 mrs1;
u8 emr;
};
union {
u8 mrs2;
u8 emr2;
};
union {
u8 mrs3;
u8 emr3;
};
u8 mrs1_mirr;
u8 mrs2;
u8 mrs2_mirr;
u8 mrs3;
u8 mrs3_mirr;
u8 precharge_all;
u8 read_b2b;
u8 read_b2b_wait1;
u8 read_b2b_wait2;
u8 refresh_all;
union {
u8 refresh;
u8 refresh_all;
};
u8 rreturn;
u8 sgle_read;
u8 zqcl;
union {
u8 zqcl;
u8 nop;
};
u8 true_mem_data_mask_width;
u8 mem_address_mirroring;
@ -199,6 +226,7 @@ struct socfpga_sdram_io_config {
struct socfpga_sdram_misc_config {
u32 reg_file_init_seq_signature;
u16 afi_clk_freq;
u8 afi_rate_ratio;
u8 calib_lfifo_offset;
u8 calib_vfifo_offset;

File diff suppressed because one or more lines are too long

View File

@ -138,10 +138,7 @@ void board_init_f(ulong dummy)
debug("Reset init failed: %d\n", ret);
#ifdef CONFIG_SPL_NAND_DENALI
struct socfpga_reset_manager *reset_manager_base =
(struct socfpga_reset_manager *)SOCFPGA_RSTMGR_ADDRESS;
clrbits_le32(&reset_manager_base->per_mod_reset, BIT(4));
clrbits_le32(SOCFPGA_RSTMGR_ADDRESS + RSTMGR_GEN5_PERMODRST, BIT(4));
#endif
/* enable console uart printing */

View File

@ -80,13 +80,15 @@ static const struct socfpga_sdram_config sdram_config = {
SDR_CTRLGRP_DRAMODT_READ_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_DRAMODT_WRITE <<
SDR_CTRLGRP_DRAMODT_WRITE_LSB),
#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 2) /* DDR3 */
.extratime1 =
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_BC_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_DIFF_LSB),
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_BC <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_BC_LSB) |
(CONFIG_HPS_SDR_CTRLCFG_EXTRATIME1_CFG_EXTRA_CTL_CLK_RD_TO_WR_DIFF_CHIP <<
SDR_CTRLGRP_EXTRATIME1_RD_TO_WR_DIFF_LSB),
#endif
.dram_addrw =
(CONFIG_HPS_SDR_CTRLCFG_DRAMADDRW_COLBITS <<
SDR_CTRLGRP_DRAMADDRW_COLBITS_LSB) |
@ -190,7 +192,6 @@ static const struct socfpga_sdram_rw_mgr_config rw_mgr_config = {
.activate_0_and_1 = RW_MGR_ACTIVATE_0_AND_1,
.activate_0_and_1_wait1 = RW_MGR_ACTIVATE_0_AND_1_WAIT1,
.activate_0_and_1_wait2 = RW_MGR_ACTIVATE_0_AND_1_WAIT2,
.activate_1 = RW_MGR_ACTIVATE_1,
.clear_dqs_enable = RW_MGR_CLEAR_DQS_ENABLE,
.guaranteed_read = RW_MGR_GUARANTEED_READ,
.guaranteed_read_cont = RW_MGR_GUARANTEED_READ_CONT,
@ -199,11 +200,41 @@ static const struct socfpga_sdram_rw_mgr_config rw_mgr_config = {
.guaranteed_write_wait1 = RW_MGR_GUARANTEED_WRITE_WAIT1,
.guaranteed_write_wait2 = RW_MGR_GUARANTEED_WRITE_WAIT2,
.guaranteed_write_wait3 = RW_MGR_GUARANTEED_WRITE_WAIT3,
.idle = RW_MGR_IDLE,
.idle_loop1 = RW_MGR_IDLE_LOOP1,
.idle_loop2 = RW_MGR_IDLE_LOOP2,
#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 1) /* DDR2 */
.emr = RW_MGR_EMR,
.emr2 = RW_MGR_EMR2,
.emr3 = RW_MGR_EMR3,
.init_reset_0_cke_0 = RW_MGR_INIT_CKE_0,
.nop = RW_MGR_NOP,
.refresh = RW_MGR_REFRESH,
.mr_calib = RW_MGR_MR_CALIB,
.mr_user = RW_MGR_MR_USER,
.mr_dll_reset = RW_MGR_MR_DLL_RESET,
.emr_ocd_enable = RW_MGR_EMR_OCD_ENABLE,
#elif (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 2) /* DDR3 */
.activate_1 = RW_MGR_ACTIVATE_1,
.idle = RW_MGR_IDLE,
.init_reset_0_cke_0 = RW_MGR_INIT_RESET_0_CKE_0,
.init_reset_1_cke_0 = RW_MGR_INIT_RESET_1_CKE_0,
.mrs1 = RW_MGR_MRS1,
.mrs1_mirr = RW_MGR_MRS1_MIRR,
.mrs2 = RW_MGR_MRS2,
.mrs2_mirr = RW_MGR_MRS2_MIRR,
.mrs3 = RW_MGR_MRS3,
.mrs3_mirr = RW_MGR_MRS3_MIRR,
.refresh_all = RW_MGR_REFRESH_ALL,
.rreturn = RW_MGR_RETURN,
.sgle_read = RW_MGR_SGLE_READ,
.zqcl = RW_MGR_ZQCL,
.mrs0_dll_reset = RW_MGR_MRS0_DLL_RESET,
.mrs0_dll_reset_mirr = RW_MGR_MRS0_DLL_RESET_MIRR,
.mrs0_user = RW_MGR_MRS0_USER,
.mrs0_user_mirr = RW_MGR_MRS0_USER_MIRR,
#else
#error LPDDR2 and other DRAM types are not yet supported
#endif
.lfsr_wr_rd_bank_0 = RW_MGR_LFSR_WR_RD_BANK_0,
.lfsr_wr_rd_bank_0_data = RW_MGR_LFSR_WR_RD_BANK_0_DATA,
.lfsr_wr_rd_bank_0_dqs = RW_MGR_LFSR_WR_RD_BANK_0_DQS,
@ -216,24 +247,10 @@ static const struct socfpga_sdram_rw_mgr_config rw_mgr_config = {
.lfsr_wr_rd_dm_bank_0_nop = RW_MGR_LFSR_WR_RD_DM_BANK_0_NOP,
.lfsr_wr_rd_dm_bank_0_wait = RW_MGR_LFSR_WR_RD_DM_BANK_0_WAIT,
.lfsr_wr_rd_dm_bank_0_wl_1 = RW_MGR_LFSR_WR_RD_DM_BANK_0_WL_1,
.mrs0_dll_reset = RW_MGR_MRS0_DLL_RESET,
.mrs0_dll_reset_mirr = RW_MGR_MRS0_DLL_RESET_MIRR,
.mrs0_user = RW_MGR_MRS0_USER,
.mrs0_user_mirr = RW_MGR_MRS0_USER_MIRR,
.mrs1 = RW_MGR_MRS1,
.mrs1_mirr = RW_MGR_MRS1_MIRR,
.mrs2 = RW_MGR_MRS2,
.mrs2_mirr = RW_MGR_MRS2_MIRR,
.mrs3 = RW_MGR_MRS3,
.mrs3_mirr = RW_MGR_MRS3_MIRR,
.precharge_all = RW_MGR_PRECHARGE_ALL,
.read_b2b = RW_MGR_READ_B2B,
.read_b2b_wait1 = RW_MGR_READ_B2B_WAIT1,
.read_b2b_wait2 = RW_MGR_READ_B2B_WAIT2,
.refresh_all = RW_MGR_REFRESH_ALL,
.rreturn = RW_MGR_RETURN,
.sgle_read = RW_MGR_SGLE_READ,
.zqcl = RW_MGR_ZQCL,
.true_mem_data_mask_width = RW_MGR_TRUE_MEM_DATA_MASK_WIDTH,
.mem_address_mirroring = RW_MGR_MEM_ADDRESS_MIRRORING,
@ -270,6 +287,9 @@ static const struct socfpga_sdram_io_config io_config = {
};
static const struct socfpga_sdram_misc_config misc_config = {
#if (CONFIG_HPS_SDR_CTRLCFG_CTRLCFG_MEMTYPE == 1) /* DDR2 */
.afi_clk_freq = AFI_CLK_FREQ,
#endif
.afi_rate_ratio = AFI_RATE_RATIO,
.calib_lfifo_offset = CALIB_LFIFO_OFFSET,
.calib_vfifo_offset = CALIB_VFIFO_OFFSET,

View File

@ -58,4 +58,6 @@ CONFIG_USB=y
CONFIG_DM_USB=y
CONFIG_USB_DWC2=y
CONFIG_USB_STORAGE=y
CONFIG_DESIGNWARE_WATCHDOG=y
CONFIG_WDT=y
# CONFIG_SPL_USE_TINY_PRINTF is not set

View File

@ -96,4 +96,5 @@ CONFIG_USB_GADGET_VENDOR_NUM=0x0525
CONFIG_USB_GADGET_PRODUCT_NUM=0xa4a5
CONFIG_USB_GADGET_DWC2_OTG=y
CONFIG_USB_GADGET_DOWNLOAD=y
# CONFIG_SPL_WDT is not set
CONFIG_DESIGNWARE_WATCHDOG=y
CONFIG_WDT=y

View File

@ -434,8 +434,10 @@ static void sdr_load_regs(struct socfpga_sdr_ctrl *sdr_ctrl,
debug("Configuring DRAMODT\n");
writel(cfg->dram_odt, &sdr_ctrl->dram_odt);
debug("Configuring EXTRATIME1\n");
writel(cfg->extratime1, &sdr_ctrl->extratime1);
if (dram_is_ddr(3)) {
debug("Configuring EXTRATIME1\n");
writel(cfg->extratime1, &sdr_ctrl->extratime1);
}
}
/**

View File

@ -7,6 +7,7 @@
#include <asm/io.h>
#include <asm/arch/sdram.h>
#include <errno.h>
#include <hang.h>
#include "sequencer.h"
static const struct socfpga_sdr_rw_load_manager *sdr_rw_load_mgr_regs =
@ -54,6 +55,21 @@ static const struct socfpga_sdr_ctrl *sdr_ctrl =
#define SKIP_DELAY_LOOP_VALUE_OR_ZERO(non_skip_value) \
((non_skip_value) & seq->skip_delay_mask)
bool dram_is_ddr(const u8 ddr)
{
const struct socfpga_sdram_config *cfg = socfpga_get_sdram_config();
const u8 type = (cfg->ctrl_cfg >> SDR_CTRLGRP_CTRLCFG_MEMTYPE_LSB) &
SDR_CTRLGRP_CTRLCFG_MEMTYPE_MASK;
if (ddr == 2 && type == 1) /* DDR2 */
return true;
if (ddr == 3 && type == 2) /* DDR3 */
return true;
return false;
}
static void set_failing_group_stage(struct socfpga_sdrseq *seq,
u32 group, u32 stage, u32 substage)
{
@ -164,6 +180,8 @@ static void set_rank_and_odt_mask(struct socfpga_sdrseq *seq,
*/
odt_mask_0 = 0x3 & ~(1 << rank);
odt_mask_1 = 0x3;
if (dram_is_ddr(2))
odt_mask_1 &= ~(1 << rank);
} else {
/*
* - Single-Slot , Dual-Rank (2 CS per DIMM)
@ -176,10 +194,11 @@ static void set_rank_and_odt_mask(struct socfpga_sdrseq *seq,
}
break;
case 4: /* 4 Ranks */
/* Read:
/*
* DDR3 Read, DDR2 Read/Write:
* ----------+-----------------------+
* | ODT |
* Read From +-----------------------+
* +-----------------------+
* Rank | 3 | 2 | 1 | 0 |
* ----------+-----+-----+-----+-----+
* 0 | 0 | 1 | 0 | 0 |
@ -188,7 +207,7 @@ static void set_rank_and_odt_mask(struct socfpga_sdrseq *seq,
* 3 | 0 | 0 | 1 | 0 |
* ----------+-----+-----+-----+-----+
*
* Write:
* DDR3 Write:
* ----------+-----------------------+
* | ODT |
* Write To +-----------------------+
@ -203,19 +222,31 @@ static void set_rank_and_odt_mask(struct socfpga_sdrseq *seq,
switch (rank) {
case 0:
odt_mask_0 = 0x4;
odt_mask_1 = 0x5;
if (dram_is_ddr(2))
odt_mask_1 = 0x4;
else if (dram_is_ddr(3))
odt_mask_1 = 0x5;
break;
case 1:
odt_mask_0 = 0x8;
odt_mask_1 = 0xA;
if (dram_is_ddr(2))
odt_mask_1 = 0x8;
else if (dram_is_ddr(3))
odt_mask_1 = 0xA;
break;
case 2:
odt_mask_0 = 0x1;
odt_mask_1 = 0x5;
if (dram_is_ddr(2))
odt_mask_1 = 0x1;
else if (dram_is_ddr(3))
odt_mask_1 = 0x5;
break;
case 3:
odt_mask_0 = 0x2;
odt_mask_1 = 0xA;
if (dram_is_ddr(2))
odt_mask_1 = 0x2;
else if (dram_is_ddr(3))
odt_mask_1 = 0xA;
break;
}
break;
@ -839,6 +870,12 @@ static void delay_for_n_mem_clocks(struct socfpga_sdrseq *seq,
debug("%s:%d clocks=%u ... end\n", __func__, __LINE__, clocks);
}
static void delay_for_n_ns(struct socfpga_sdrseq *seq, const u32 ns)
{
delay_for_n_mem_clocks(seq, (ns * seq->misccfg->afi_clk_freq *
seq->misccfg->afi_rate_ratio) / 1000);
}
/**
* rw_mgr_mem_init_load_regs() - Load instruction registers
* @cntr0: Counter 0 value
@ -872,14 +909,59 @@ static void rw_mgr_mem_init_load_regs(struct socfpga_sdrseq *seq,
}
/**
* rw_mgr_mem_load_user() - Load user calibration values
* rw_mgr_mem_load_user_ddr2() - Load user calibration values for DDR2
* @handoff: Indicate whether this is initialization or handoff phase
*
* Load user calibration values and optionally precharge the banks.
*/
static void rw_mgr_mem_load_user_ddr2(struct socfpga_sdrseq *seq,
const int handoff)
{
u32 grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
RW_MGR_RUN_SINGLE_GROUP_OFFSET;
u32 r;
for (r = 0; r < seq->rwcfg->mem_number_of_ranks; r++) {
/* set rank */
set_rank_and_odt_mask(seq, r, RW_MGR_ODT_MODE_OFF);
/* precharge all banks ... */
writel(seq->rwcfg->precharge_all, grpaddr);
writel(seq->rwcfg->emr2, grpaddr);
writel(seq->rwcfg->emr3, grpaddr);
writel(seq->rwcfg->emr, grpaddr);
if (handoff) {
writel(seq->rwcfg->mr_user, grpaddr);
continue;
}
writel(seq->rwcfg->mr_dll_reset, grpaddr);
writel(seq->rwcfg->precharge_all, grpaddr);
writel(seq->rwcfg->refresh, grpaddr);
delay_for_n_ns(seq, 200);
writel(seq->rwcfg->refresh, grpaddr);
delay_for_n_ns(seq, 200);
writel(seq->rwcfg->mr_calib, grpaddr);
writel(/*seq->rwcfg->*/0x0b, grpaddr); // EMR_OCD_ENABLE
writel(seq->rwcfg->emr, grpaddr);
delay_for_n_mem_clocks(seq, 200);
}
}
/**
* rw_mgr_mem_load_user_ddr3() - Load user calibration values
* @fin1: Final instruction 1
* @fin2: Final instruction 2
* @precharge: If 1, precharge the banks at the end
*
* Load user calibration values and optionally precharge the banks.
*/
static void rw_mgr_mem_load_user(struct socfpga_sdrseq *seq,
static void rw_mgr_mem_load_user_ddr3(struct socfpga_sdrseq *seq,
const u32 fin1, const u32 fin2,
const int precharge)
{
@ -935,6 +1017,25 @@ static void rw_mgr_mem_load_user(struct socfpga_sdrseq *seq,
}
}
/**
* rw_mgr_mem_load_user() - Load user calibration values
* @fin1: Final instruction 1
* @fin2: Final instruction 2
* @precharge: If 1, precharge the banks at the end
*
* Load user calibration values and optionally precharge the banks.
*/
static void rw_mgr_mem_load_user(struct socfpga_sdrseq *seq,
const u32 fin1, const u32 fin2,
const int precharge)
{
if (dram_is_ddr(2))
rw_mgr_mem_load_user_ddr2(seq, precharge);
else if (dram_is_ddr(3))
rw_mgr_mem_load_user_ddr3(seq, fin1, fin2, precharge);
else
hang();
}
/**
* rw_mgr_mem_initialize() - Initialize RW Manager
*
@ -945,8 +1046,10 @@ static void rw_mgr_mem_initialize(struct socfpga_sdrseq *seq)
debug("%s:%d\n", __func__, __LINE__);
/* The reset / cke part of initialization is broadcasted to all ranks */
writel(RW_MGR_RANK_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
if (dram_is_ddr(3)) {
writel(RW_MGR_RANK_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
}
/*
* Here's how you load register for a loop
@ -979,29 +1082,38 @@ static void rw_mgr_mem_initialize(struct socfpga_sdrseq *seq)
/* Indicate that memory is stable. */
writel(1, &phy_mgr_cfg->reset_mem_stbl);
/*
* transition the RESET to high
* Wait for 500us
*/
if (dram_is_ddr(2)) {
writel(seq->rwcfg->nop, SDR_PHYGRP_RWMGRGRP_ADDRESS |
RW_MGR_RUN_SINGLE_GROUP_OFFSET);
/*
* 500us @ 266MHz (3.75 ns) ~ 134000 clock cycles
* If a and b are the number of iteration in 2 nested loops
* it takes the following number of cycles to complete the operation
* number_of_cycles = ((2 + n) * a + 2) * b
* where n is the number of instruction in the inner loop
* One possible solution is n = 2 , a = 131 , b = 256 => a = 83,
* b = FF
*/
rw_mgr_mem_init_load_regs(seq, seq->misccfg->treset_cntr0_val,
seq->misccfg->treset_cntr1_val,
seq->misccfg->treset_cntr2_val,
seq->rwcfg->init_reset_1_cke_0);
/* Bring up clock enable. */
/* Bring up clock enable. */
/* tXRP < 400 ck cycles */
delay_for_n_ns(seq, 400);
} else if (dram_is_ddr(3)) {
/*
* transition the RESET to high
* Wait for 500us
*/
/* tXRP < 250 ck cycles */
delay_for_n_mem_clocks(seq, 250);
/*
* 500us @ 266MHz (3.75 ns) ~ 134000 clock cycles
* If a and b are the number of iteration in 2 nested loops
* it takes the following number of cycles to complete the
* operation number_of_cycles = ((2 + n) * a + 2) * b
* where n is the number of instruction in the inner loop
* One possible solution is
* n = 2 , a = 131 , b = 256 => a = 83, b = FF
*/
rw_mgr_mem_init_load_regs(seq, seq->misccfg->treset_cntr0_val,
seq->misccfg->treset_cntr1_val,
seq->misccfg->treset_cntr2_val,
seq->rwcfg->init_reset_1_cke_0);
/* Bring up clock enable. */
/* tXRP < 250 ck cycles */
delay_for_n_mem_clocks(seq, 250);
}
rw_mgr_mem_load_user(seq, seq->rwcfg->mrs0_dll_reset_mirr,
seq->rwcfg->mrs0_dll_reset, 0);
@ -3769,16 +3881,26 @@ static void initialize_tracking(struct socfpga_sdrseq *seq)
&sdr_reg_file->delays);
/* mux delay */
writel((seq->rwcfg->idle << 24) | (seq->rwcfg->activate_1 << 16) |
(seq->rwcfg->sgle_read << 8) | (seq->rwcfg->precharge_all << 0),
&sdr_reg_file->trk_rw_mgr_addr);
if (dram_is_ddr(2)) {
writel(0, &sdr_reg_file->trk_rw_mgr_addr);
} else if (dram_is_ddr(3)) {
writel((seq->rwcfg->idle << 24) |
(seq->rwcfg->activate_1 << 16) |
(seq->rwcfg->sgle_read << 8) |
(seq->rwcfg->precharge_all << 0),
&sdr_reg_file->trk_rw_mgr_addr);
}
writel(seq->rwcfg->mem_if_read_dqs_width,
&sdr_reg_file->trk_read_dqs_width);
/* trefi [7:0] */
writel((seq->rwcfg->refresh_all << 24) | (1000 << 0),
&sdr_reg_file->trk_rfsh);
if (dram_is_ddr(2)) {
writel(1000 << 0, &sdr_reg_file->trk_rfsh);
} else if (dram_is_ddr(3)) {
writel((seq->rwcfg->refresh_all << 24) | (1000 << 0),
&sdr_reg_file->trk_rfsh);
}
}
int sdram_calibration_full(struct socfpga_sdr *sdr)

View File

@ -279,5 +279,6 @@ struct socfpga_sdrseq {
};
int sdram_calibration_full(struct socfpga_sdr *sdr);
bool dram_is_ddr(const u8 ddr);
#endif /* _SEQUENCER_H_ */

View File

@ -18,6 +18,7 @@
#include <dm/of_access.h>
#include <env.h>
#include <reset-uclass.h>
#include <wait_bit.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/sizes.h>
@ -80,7 +81,10 @@ static int socfpga_reset_deassert(struct reset_ctl *reset_ctl)
int offset = id % (reg_width * BITS_PER_BYTE);
clrbits_le32(data->modrst_base + (bank * BANK_INCREMENT), BIT(offset));
return 0;
return wait_for_bit_le32(data->modrst_base + (bank * BANK_INCREMENT),
BIT(offset),
false, 500, false);
}
static int socfpga_reset_request(struct reset_ctl *reset_ctl)

View File

@ -45,6 +45,13 @@ config ULP_WATCHDOG
help
Say Y here to enable i.MX7ULP watchdog driver.
config DESIGNWARE_WATCHDOG
bool "Designware watchdog timer support"
select HW_WATCHDOG if !WDT
help
Enable this to support Designware Watchdog Timer IP, present e.g.
on Altera SoCFPGA SoCs.
config WDT
bool "Enable driver model for watchdog timer drivers"
depends on DM

View File

@ -3,8 +3,11 @@
* Copyright (C) 2013 Altera Corporation <www.altera.com>
*/
#include <clk.h>
#include <common.h>
#include <watchdog.h>
#include <dm.h>
#include <reset.h>
#include <wdt.h>
#include <asm/io.h>
#include <asm/utils.h>
@ -14,49 +17,52 @@
#define DW_WDT_CR_EN_OFFSET 0x00
#define DW_WDT_CR_RMOD_OFFSET 0x01
#define DW_WDT_CR_RMOD_VAL 0x00
#define DW_WDT_CRR_RESTART_VAL 0x76
struct designware_wdt_priv {
void __iomem *base;
unsigned int clk_khz;
};
/*
* Set the watchdog time interval.
* Counter is 32 bit.
*/
static int designware_wdt_settimeout(unsigned int timeout)
static int designware_wdt_settimeout(void __iomem *base, unsigned int clk_khz,
unsigned int timeout)
{
signed int i;
/* calculate the timeout range value */
i = (log_2_n_round_up(timeout * CONFIG_DW_WDT_CLOCK_KHZ)) - 16;
if (i > 15)
i = 15;
if (i < 0)
i = 0;
i = log_2_n_round_up(timeout * clk_khz) - 16;
i = clamp(i, 0, 15);
writel(i | (i << 4), base + DW_WDT_TORR);
writel((i | (i << 4)), (CONFIG_DW_WDT_BASE + DW_WDT_TORR));
return 0;
}
static void designware_wdt_enable(void)
static void designware_wdt_enable(void __iomem *base)
{
writel(((DW_WDT_CR_RMOD_VAL << DW_WDT_CR_RMOD_OFFSET) |
(0x1 << DW_WDT_CR_EN_OFFSET)),
(CONFIG_DW_WDT_BASE + DW_WDT_CR));
writel(BIT(DW_WDT_CR_EN_OFFSET), base + DW_WDT_CR);
}
static unsigned int designware_wdt_is_enabled(void)
static unsigned int designware_wdt_is_enabled(void __iomem *base)
{
unsigned long val;
val = readl((CONFIG_DW_WDT_BASE + DW_WDT_CR));
return val & 0x1;
return readl(base + DW_WDT_CR) & BIT(0);
}
#if defined(CONFIG_HW_WATCHDOG)
static void designware_wdt_reset_common(void __iomem *base)
{
if (designware_wdt_is_enabled(base))
/* restart the watchdog counter */
writel(DW_WDT_CRR_RESTART_VAL, base + DW_WDT_CRR);
}
#if !CONFIG_IS_ENABLED(WDT)
void hw_watchdog_reset(void)
{
if (designware_wdt_is_enabled())
/* restart the watchdog counter */
writel(DW_WDT_CRR_RESTART_VAL,
(CONFIG_DW_WDT_BASE + DW_WDT_CRR));
designware_wdt_reset_common((void __iomem *)CONFIG_DW_WDT_BASE);
}
void hw_watchdog_init(void)
@ -64,10 +70,106 @@ void hw_watchdog_init(void)
/* reset to disable the watchdog */
hw_watchdog_reset();
/* set timer in miliseconds */
designware_wdt_settimeout(CONFIG_WATCHDOG_TIMEOUT_MSECS);
designware_wdt_settimeout((void __iomem *)CONFIG_DW_WDT_BASE,
CONFIG_DW_WDT_CLOCK_KHZ,
CONFIG_WATCHDOG_TIMEOUT_MSECS);
/* enable the watchdog */
designware_wdt_enable();
designware_wdt_enable((void __iomem *)CONFIG_DW_WDT_BASE);
/* reset the watchdog */
hw_watchdog_reset();
}
#else
static int designware_wdt_reset(struct udevice *dev)
{
struct designware_wdt_priv *priv = dev_get_priv(dev);
designware_wdt_reset_common(priv->base);
return 0;
}
static int designware_wdt_stop(struct udevice *dev)
{
struct designware_wdt_priv *priv = dev_get_priv(dev);
designware_wdt_reset(dev);
writel(0, priv->base + DW_WDT_CR);
return 0;
}
static int designware_wdt_start(struct udevice *dev, u64 timeout, ulong flags)
{
struct designware_wdt_priv *priv = dev_get_priv(dev);
designware_wdt_stop(dev);
/* set timer in miliseconds */
designware_wdt_settimeout(priv->base, priv->clk_khz, timeout);
designware_wdt_enable(priv->base);
/* reset the watchdog */
return designware_wdt_reset(dev);
}
static int designware_wdt_probe(struct udevice *dev)
{
struct designware_wdt_priv *priv = dev_get_priv(dev);
__maybe_unused int ret;
priv->base = dev_remap_addr(dev);
if (!priv->base)
return -EINVAL;
#if CONFIG_IS_ENABLED(CLK)
struct clk clk;
ret = clk_get_by_index(dev, 0, &clk);
if (ret)
return ret;
priv->clk_khz = clk_get_rate(&clk);
if (!priv->clk_khz)
return -EINVAL;
#else
priv->clk_khz = CONFIG_DW_WDT_CLOCK_KHZ;
#endif
#if CONFIG_IS_ENABLED(DM_RESET)
struct reset_ctl_bulk resets;
ret = reset_get_bulk(dev, &resets);
if (ret)
return ret;
ret = reset_deassert_bulk(&resets);
if (ret)
return ret;
#endif
/* reset to disable the watchdog */
return designware_wdt_stop(dev);
}
static const struct wdt_ops designware_wdt_ops = {
.start = designware_wdt_start,
.reset = designware_wdt_reset,
.stop = designware_wdt_stop,
};
static const struct udevice_id designware_wdt_ids[] = {
{ .compatible = "snps,dw-wdt"},
{}
};
U_BOOT_DRIVER(designware_wdt) = {
.name = "designware_wdt",
.id = UCLASS_WDT,
.of_match = designware_wdt_ids,
.priv_auto_alloc_size = sizeof(struct designware_wdt_priv),
.probe = designware_wdt_probe,
.ops = &designware_wdt_ops,
.flags = DM_FLAG_PRE_RELOC,
};
#endif

View File

@ -104,11 +104,8 @@
/*
* L4 Watchdog
*/
#ifdef CONFIG_HW_WATCHDOG
#define CONFIG_DESIGNWARE_WATCHDOG
#define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS
#define CONFIG_DW_WDT_CLOCK_KHZ 25000
#endif
/*
* MMC Driver

View File

@ -150,9 +150,10 @@ unsigned int cm_get_qspi_controller_clk_hz(void);
/*
* L4 Watchdog
*/
#ifdef CONFIG_SPL_BUILD
#define CONFIG_HW_WATCHDOG
#define CONFIG_DESIGNWARE_WATCHDOG
#ifndef CONFIG_SPL_BUILD
#undef CONFIG_HW_WATCHDOG
#undef CONFIG_DESIGNWARE_WATCHDOG
#endif
#define CONFIG_DW_WDT_BASE SOCFPGA_L4WD0_ADDRESS
#ifdef CONFIG_TARGET_SOCFPGA_STRATIX10
#ifndef __ASSEMBLY__
@ -162,7 +163,6 @@ unsigned int cm_get_l4_sys_free_clk_hz(void);
#else
#define CONFIG_DW_WDT_CLOCK_KHZ 100000
#endif
#endif
/*
* SPL memory layout

View File

@ -311,7 +311,6 @@ CONFIG_DEFAULT_IMMR
CONFIG_DEF_HWCONFIG
CONFIG_DELAY_ENVIRONMENT
CONFIG_DESIGNWARE_ETH
CONFIG_DESIGNWARE_WATCHDOG
CONFIG_DEVELOP
CONFIG_DEVICE_TREE_LIST
CONFIG_DFU_ALT