summaryrefslogtreecommitdiff
path: root/drivers/ddr
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2015-07-12 23:25:21 +0200
committerMarek Vasut <marex@denx.de>2015-08-08 14:14:12 +0200
commit0b69b807d841ae39d41f27b96542219211bcec4e (patch)
treebb5c857375085edb24b2e12a65d927fd254e7c6f /drivers/ddr
parent162d60ef733a1878eee85cf1f3ed5e56f2a26903 (diff)
ddr: altera: Implement universal scc_mgr_set_all_ranks()
Implement universal scc_mgr_set_all_ranks() function and convert various ad-hoc implementations of similar functionality to use this single function. Document the function in kerneldoc. Signed-off-by: Marek Vasut <marex@denx.de>
Diffstat (limited to 'drivers/ddr')
-rw-r--r--drivers/ddr/altera/sequencer.c95
1 files changed, 42 insertions, 53 deletions
diff --git a/drivers/ddr/altera/sequencer.c b/drivers/ddr/altera/sequencer.c
index 1718ebf1c4..df78146241 100644
--- a/drivers/ddr/altera/sequencer.c
+++ b/drivers/ddr/altera/sequencer.c
@@ -361,77 +361,64 @@ static void scc_mgr_load_dm(uint32_t dm)
writel(dm, &sdr_scc_mgr->dm_ena);
}
-static void scc_mgr_set_dqs_en_phase_all_ranks(uint32_t read_group,
- uint32_t phase)
+/**
+ * scc_mgr_set_all_ranks() - Set SCC Manager register for all ranks
+ * @off: Base offset in SCC Manager space
+ * @grp: Read/Write group
+ * @val: Value to be set
+ * @update: If non-zero, trigger SCC Manager update for all ranks
+ *
+ * This function sets the SCC Manager (Scan Chain Control Manager) register
+ * and optionally triggers the SCC update for all ranks.
+ */
+static void scc_mgr_set_all_ranks(const u32 off, const u32 grp, const u32 val,
+ const int update)
{
- uint32_t r;
+ u32 r;
for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS;
r += NUM_RANKS_PER_SHADOW_REG) {
- scc_mgr_set_dqs_en_phase(read_group, phase);
-
- /*
- * USER although the h/w doesn't support different phases per
- * shadow register, for simplicity our scc manager modeling
- * keeps different phase settings per shadow reg, and it's
- * important for us to keep them in sync to match h/w.
- * for efficiency, the scan chain update should occur only
- * once to sr0.
- */
+ scc_mgr_set(off, grp, val);
- if (r == 0) {
- writel(read_group, &sdr_scc_mgr->dqs_ena);
+ if (update || (r == 0)) {
+ writel(grp, &sdr_scc_mgr->dqs_ena);
writel(0, &sdr_scc_mgr->update);
}
}
}
+static void scc_mgr_set_dqs_en_phase_all_ranks(u32 read_group, u32 phase)
+{
+ /*
+ * USER although the h/w doesn't support different phases per
+ * shadow register, for simplicity our scc manager modeling
+ * keeps different phase settings per shadow reg, and it's
+ * important for us to keep them in sync to match h/w.
+ * for efficiency, the scan chain update should occur only
+ * once to sr0.
+ */
+ scc_mgr_set_all_ranks(SCC_MGR_DQS_EN_PHASE_OFFSET,
+ read_group, phase, 0);
+}
+
static void scc_mgr_set_dqdqs_output_phase_all_ranks(uint32_t write_group,
uint32_t phase)
{
- uint32_t r;
-
- for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS;
- r += NUM_RANKS_PER_SHADOW_REG) {
- scc_mgr_set_dqdqs_output_phase(write_group, phase);
-
- /*
- * USER although the h/w doesn't support different phases per
- * shadow register, for simplicity our scc manager modeling
- * keeps different phase settings per shadow reg, and it's
- * important for us to keep them in sync to match h/w.
- * for efficiency, the scan chain update should occur only
- * once to sr0.
- */
-
- if (r == 0) {
- writel(write_group, &sdr_scc_mgr->dqs_ena);
- writel(0, &sdr_scc_mgr->update);
- }
- }
+ /*
+ * USER although the h/w doesn't support different phases per
+ * shadow register, for simplicity our scc manager modeling
+ * keeps different phase settings per shadow reg, and it's
+ * important for us to keep them in sync to match h/w.
+ * for efficiency, the scan chain update should occur only
+ * once to sr0.
+ */
+ scc_mgr_set_all_ranks(SCC_MGR_DQDQS_OUT_PHASE_OFFSET,
+ write_group, phase, 0);
}
static void scc_mgr_set_dqs_en_delay_all_ranks(uint32_t read_group,
uint32_t delay)
{
- uint32_t r;
-
- for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS;
- r += NUM_RANKS_PER_SHADOW_REG) {
- scc_mgr_set_dqs_en_delay(read_group, delay);
-
- /*
- * In shadow register mode, the T11 settings are stored in
- * registers in the core, which are updated by the DQS_ENA
- * signals. Not issuing the SCC_MGR_UPD command allows us to
- * save lots of rank switching overhead, by calling
- * select_shadow_regs_for_update with update_scan_chains
- * set to 0.
- */
-
- writel(read_group, &sdr_scc_mgr->dqs_ena);
- writel(0, &sdr_scc_mgr->update);
- }
/*
* In shadow register mode, the T11 settings are stored in
* registers in the core, which are updated by the DQS_ENA
@@ -440,6 +427,8 @@ static void scc_mgr_set_dqs_en_delay_all_ranks(uint32_t read_group,
* select_shadow_regs_for_update with update_scan_chains
* set to 0.
*/
+ scc_mgr_set_all_ranks(SCC_MGR_DQS_EN_DELAY_OFFSET,
+ read_group, delay, 1);
writel(0, &sdr_scc_mgr->update);
}