Blame view

drivers/ddr/altera/sequencer.c 105 KB
3da428595   Dinh Nguyen   driver/ddr/altera...
1
2
3
4
5
6
7
8
9
  /*
   * Copyright Altera Corporation (C) 2012-2015
   *
   * SPDX-License-Identifier:    BSD-3-Clause
   */
  
  #include <common.h>
  #include <asm/io.h>
  #include <asm/arch/sdram.h>
04372fb89   Marek Vasut   ddr: altera: Extr...
10
  #include <errno.h>
3da428595   Dinh Nguyen   driver/ddr/altera...
11
  #include "sequencer.h"
9c76df518   Marek Vasut   ddr: altera: sequ...
12

3da428595   Dinh Nguyen   driver/ddr/altera...
13
  static struct socfpga_sdr_rw_load_manager *sdr_rw_load_mgr_regs =
139823ecb   Marek Vasut   ddr: altera: sequ...
14
15
  	(struct socfpga_sdr_rw_load_manager *)
  		(SDR_PHYGRP_RWMGRGRP_ADDRESS | 0x800);
3da428595   Dinh Nguyen   driver/ddr/altera...
16
  static struct socfpga_sdr_rw_load_jump_manager *sdr_rw_load_jump_mgr_regs =
139823ecb   Marek Vasut   ddr: altera: sequ...
17
18
  	(struct socfpga_sdr_rw_load_jump_manager *)
  		(SDR_PHYGRP_RWMGRGRP_ADDRESS | 0xC00);
3da428595   Dinh Nguyen   driver/ddr/altera...
19
  static struct socfpga_sdr_reg_file *sdr_reg_file =
a1c654a89   Marek Vasut   ddr: altera: Diss...
20
  	(struct socfpga_sdr_reg_file *)SDR_PHYGRP_REGFILEGRP_ADDRESS;
3da428595   Dinh Nguyen   driver/ddr/altera...
21
  static struct socfpga_sdr_scc_mgr *sdr_scc_mgr =
139823ecb   Marek Vasut   ddr: altera: sequ...
22
23
  	(struct socfpga_sdr_scc_mgr *)
  		(SDR_PHYGRP_SCCGRP_ADDRESS | 0xe00);
3da428595   Dinh Nguyen   driver/ddr/altera...
24
  static struct socfpga_phy_mgr_cmd *phy_mgr_cmd =
1bc6f14a6   Marek Vasut   ddr: altera: Diss...
25
  	(struct socfpga_phy_mgr_cmd *)SDR_PHYGRP_PHYMGRGRP_ADDRESS;
3da428595   Dinh Nguyen   driver/ddr/altera...
26
  static struct socfpga_phy_mgr_cfg *phy_mgr_cfg =
139823ecb   Marek Vasut   ddr: altera: sequ...
27
28
  	(struct socfpga_phy_mgr_cfg *)
  		(SDR_PHYGRP_PHYMGRGRP_ADDRESS | 0x40);
3da428595   Dinh Nguyen   driver/ddr/altera...
29
  static struct socfpga_data_mgr *data_mgr =
c4815f767   Marek Vasut   ddr: altera: Pluc...
30
  	(struct socfpga_data_mgr *)SDR_PHYGRP_DATAMGRGRP_ADDRESS;
6cb9f1678   Marek Vasut   ddr: altera: Stop...
31
32
  static struct socfpga_sdr_ctrl *sdr_ctrl =
  	(struct socfpga_sdr_ctrl *)SDR_CTRLGRP_ADDRESS;
d718a26b0   Marek Vasut   ddr: altera: sequ...
33
  const struct socfpga_sdram_rw_mgr_config *rwcfg;
10c14261f   Marek Vasut   ddr: altera: sequ...
34
  const struct socfpga_sdram_io_config *iocfg;
042ff2d0f   Marek Vasut   ddr: altera: sequ...
35
  const struct socfpga_sdram_misc_config *misccfg;
d718a26b0   Marek Vasut   ddr: altera: sequ...
36

3da428595   Dinh Nguyen   driver/ddr/altera...
37
  #define DELTA_D		1
3da428595   Dinh Nguyen   driver/ddr/altera...
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  
  /*
   * In order to reduce ROM size, most of the selectable calibration steps are
   * decided at compile time based on the user's calibration mode selection,
   * as captured by the STATIC_CALIB_STEPS selection below.
   *
   * However, to support simulation-time selection of fast simulation mode, where
   * we skip everything except the bare minimum, we need a few of the steps to
   * be dynamic.  In those cases, we either use the DYNAMIC_CALIB_STEPS for the
   * check, which is based on the rtl-supplied value, or we dynamically compute
   * the value to use based on the dynamically-chosen calibration mode
   */
  
  #define DLEVEL 0
  #define STATIC_IN_RTL_SIM 0
  #define STATIC_SKIP_DELAY_LOOPS 0
  
  #define STATIC_CALIB_STEPS (STATIC_IN_RTL_SIM | CALIB_SKIP_FULL_TEST | \
  	STATIC_SKIP_DELAY_LOOPS)
  
  /* calibration steps requested by the rtl */
5ded7320c   Marek Vasut   ddr: altera: sequ...
59
  u16 dyn_calib_steps;
3da428595   Dinh Nguyen   driver/ddr/altera...
60
61
62
63
64
65
66
67
68
  
  /*
   * To make CALIB_SKIP_DELAY_LOOPS a dynamic conditional option
   * instead of static, we use boolean logic to select between
   * non-skip and skip values
   *
   * The mask is set to include all bits when not-skipping, but is
   * zero when skipping
   */
5ded7320c   Marek Vasut   ddr: altera: sequ...
69
  u16 skip_delay_mask;	/* mask off bits when skipping/not-skipping */
3da428595   Dinh Nguyen   driver/ddr/altera...
70
71
72
73
74
75
  
  #define SKIP_DELAY_LOOP_VALUE_OR_ZERO(non_skip_value) \
  	((non_skip_value) & skip_delay_mask)
  
  struct gbl_type *gbl;
  struct param_type *param;
3da428595   Dinh Nguyen   driver/ddr/altera...
76

5ded7320c   Marek Vasut   ddr: altera: sequ...
77
78
  static void set_failing_group_stage(u32 group, u32 stage,
  	u32 substage)
3da428595   Dinh Nguyen   driver/ddr/altera...
79
80
81
82
83
84
85
86
87
88
89
  {
  	/*
  	 * Only set the global stage if there was not been any other
  	 * failing group
  	 */
  	if (gbl->error_stage == CAL_STAGE_NIL)	{
  		gbl->error_substage = substage;
  		gbl->error_stage = stage;
  		gbl->error_group = group;
  	}
  }
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
90
  static void reg_file_set_group(u16 set_group)
3da428595   Dinh Nguyen   driver/ddr/altera...
91
  {
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
92
  	clrsetbits_le32(&sdr_reg_file->cur_stage, 0xffff0000, set_group << 16);
3da428595   Dinh Nguyen   driver/ddr/altera...
93
  }
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
94
  static void reg_file_set_stage(u8 set_stage)
3da428595   Dinh Nguyen   driver/ddr/altera...
95
  {
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
96
  	clrsetbits_le32(&sdr_reg_file->cur_stage, 0xffff, set_stage & 0xff);
3da428595   Dinh Nguyen   driver/ddr/altera...
97
  }
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
98
  static void reg_file_set_sub_stage(u8 set_sub_stage)
3da428595   Dinh Nguyen   driver/ddr/altera...
99
  {
2c0d2d9c4   Marek Vasut   ddr: altera: Clea...
100
101
  	set_sub_stage &= 0xff;
  	clrsetbits_le32(&sdr_reg_file->cur_stage, 0xff00, set_sub_stage << 8);
3da428595   Dinh Nguyen   driver/ddr/altera...
102
  }
7c89c2d9c   Marek Vasut   ddr: altera: Clea...
103
104
105
106
107
  /**
   * phy_mgr_initialize() - Initialize PHY Manager
   *
   * Initialize PHY Manager.
   */
9fa9c90e7   Marek Vasut   ddr: altera: Rena...
108
  static void phy_mgr_initialize(void)
3da428595   Dinh Nguyen   driver/ddr/altera...
109
  {
7c89c2d9c   Marek Vasut   ddr: altera: Clea...
110
  	u32 ratio;
3da428595   Dinh Nguyen   driver/ddr/altera...
111
112
  	debug("%s:%d
  ", __func__, __LINE__);
7c89c2d9c   Marek Vasut   ddr: altera: Clea...
113
  	/* Calibration has control over path to memory */
3da428595   Dinh Nguyen   driver/ddr/altera...
114
115
116
117
118
  	/*
  	 * In Hard PHY this is a 2-bit control:
  	 * 0: AFI Mux Select
  	 * 1: DDIO Mux Select
  	 */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
119
  	writel(0x3, &phy_mgr_cfg->mux_sel);
3da428595   Dinh Nguyen   driver/ddr/altera...
120
121
  
  	/* USER memory clock is not stable we begin initialization  */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
122
  	writel(0, &phy_mgr_cfg->reset_mem_stbl);
3da428595   Dinh Nguyen   driver/ddr/altera...
123
124
  
  	/* USER calibration status all set to zero */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
125
  	writel(0, &phy_mgr_cfg->cal_status);
3da428595   Dinh Nguyen   driver/ddr/altera...
126

1273dd9ea   Marek Vasut   ddr: altera: Mass...
127
  	writel(0, &phy_mgr_cfg->cal_debug_info);
3da428595   Dinh Nguyen   driver/ddr/altera...
128

7c89c2d9c   Marek Vasut   ddr: altera: Clea...
129
130
131
  	/* Init params only if we do NOT skip calibration. */
  	if ((dyn_calib_steps & CALIB_SKIP_ALL) == CALIB_SKIP_ALL)
  		return;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
132
133
  	ratio = rwcfg->mem_dq_per_read_dqs /
  		rwcfg->mem_virtual_groups_per_read_dqs;
7c89c2d9c   Marek Vasut   ddr: altera: Clea...
134
135
  	param->read_correct_mask_vg = (1 << ratio) - 1;
  	param->write_correct_mask_vg = (1 << ratio) - 1;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
136
137
  	param->read_correct_mask = (1 << rwcfg->mem_dq_per_read_dqs) - 1;
  	param->write_correct_mask = (1 << rwcfg->mem_dq_per_write_dqs) - 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
138
  }
080bf64ef   Marek Vasut   ddr: altera: Clea...
139
140
141
142
143
144
145
  /**
   * set_rank_and_odt_mask() - Set Rank and ODT mask
   * @rank:	Rank mask
   * @odt_mode:	ODT mode, OFF or READ_WRITE
   *
   * Set Rank and ODT mask (On-Die Termination).
   */
b2dfd100b   Marek Vasut   ddr: altera: Clea...
146
  static void set_rank_and_odt_mask(const u32 rank, const u32 odt_mode)
3da428595   Dinh Nguyen   driver/ddr/altera...
147
  {
b2dfd100b   Marek Vasut   ddr: altera: Clea...
148
149
150
  	u32 odt_mask_0 = 0;
  	u32 odt_mask_1 = 0;
  	u32 cs_and_odt_mask;
3da428595   Dinh Nguyen   driver/ddr/altera...
151

b2dfd100b   Marek Vasut   ddr: altera: Clea...
152
153
154
155
  	if (odt_mode == RW_MGR_ODT_MODE_OFF) {
  		odt_mask_0 = 0x0;
  		odt_mask_1 = 0x0;
  	} else {	/* RW_MGR_ODT_MODE_READ_WRITE */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
156
  		switch (rwcfg->mem_number_of_ranks) {
287cdf6be   Marek Vasut   ddr: altera: Clea...
157
158
  		case 1:	/* 1 Rank */
  			/* Read: ODT = 0 ; Write: ODT = 1 */
3da428595   Dinh Nguyen   driver/ddr/altera...
159
160
  			odt_mask_0 = 0x0;
  			odt_mask_1 = 0x1;
287cdf6be   Marek Vasut   ddr: altera: Clea...
161
162
  			break;
  		case 2:	/* 2 Ranks */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
163
  			if (rwcfg->mem_number_of_cs_per_dimm == 1) {
080bf64ef   Marek Vasut   ddr: altera: Clea...
164
165
166
167
168
169
170
171
172
  				/*
  				 * - Dual-Slot , Single-Rank (1 CS per DIMM)
  				 *   OR
  				 * - RDIMM, 4 total CS (2 CS per DIMM, 2 DIMM)
  				 *
  				 * Since MEM_NUMBER_OF_RANKS is 2, they
  				 * are both single rank with 2 CS each
  				 * (special for RDIMM).
  				 *
3da428595   Dinh Nguyen   driver/ddr/altera...
173
174
175
176
177
178
179
  				 * Read: Turn on ODT on the opposite rank
  				 * Write: Turn on ODT on all ranks
  				 */
  				odt_mask_0 = 0x3 & ~(1 << rank);
  				odt_mask_1 = 0x3;
  			} else {
  				/*
080bf64ef   Marek Vasut   ddr: altera: Clea...
180
181
182
183
  				 * - Single-Slot , Dual-Rank (2 CS per DIMM)
  				 *
  				 * Read: Turn on ODT off on all ranks
  				 * Write: Turn on ODT on active rank
3da428595   Dinh Nguyen   driver/ddr/altera...
184
185
186
187
  				 */
  				odt_mask_0 = 0x0;
  				odt_mask_1 = 0x3 & (1 << rank);
  			}
287cdf6be   Marek Vasut   ddr: altera: Clea...
188
189
190
  			break;
  		case 4:	/* 4 Ranks */
  			/* Read:
3da428595   Dinh Nguyen   driver/ddr/altera...
191
  			 * ----------+-----------------------+
3da428595   Dinh Nguyen   driver/ddr/altera...
192
193
194
195
196
197
198
199
200
201
202
203
  			 *           |         ODT           |
  			 * Read From +-----------------------+
  			 *   Rank    |  3  |  2  |  1  |  0  |
  			 * ----------+-----+-----+-----+-----+
  			 *     0     |  0  |  1  |  0  |  0  |
  			 *     1     |  1  |  0  |  0  |  0  |
  			 *     2     |  0  |  0  |  0  |  1  |
  			 *     3     |  0  |  0  |  1  |  0  |
  			 * ----------+-----+-----+-----+-----+
  			 *
  			 * Write:
  			 * ----------+-----------------------+
3da428595   Dinh Nguyen   driver/ddr/altera...
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  			 *           |         ODT           |
  			 * Write To  +-----------------------+
  			 *   Rank    |  3  |  2  |  1  |  0  |
  			 * ----------+-----+-----+-----+-----+
  			 *     0     |  0  |  1  |  0  |  1  |
  			 *     1     |  1  |  0  |  1  |  0  |
  			 *     2     |  0  |  1  |  0  |  1  |
  			 *     3     |  1  |  0  |  1  |  0  |
  			 * ----------+-----+-----+-----+-----+
  			 */
  			switch (rank) {
  			case 0:
  				odt_mask_0 = 0x4;
  				odt_mask_1 = 0x5;
  				break;
  			case 1:
  				odt_mask_0 = 0x8;
  				odt_mask_1 = 0xA;
  				break;
  			case 2:
  				odt_mask_0 = 0x1;
  				odt_mask_1 = 0x5;
  				break;
  			case 3:
  				odt_mask_0 = 0x2;
  				odt_mask_1 = 0xA;
  				break;
  			}
287cdf6be   Marek Vasut   ddr: altera: Clea...
232
  			break;
3da428595   Dinh Nguyen   driver/ddr/altera...
233
  		}
3da428595   Dinh Nguyen   driver/ddr/altera...
234
  	}
b2dfd100b   Marek Vasut   ddr: altera: Clea...
235
236
237
  	cs_and_odt_mask = (0xFF & ~(1 << rank)) |
  			  ((0xFF & odt_mask_0) << 8) |
  			  ((0xFF & odt_mask_1) << 16);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
238
239
  	writel(cs_and_odt_mask, SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
240
  }
c76976d98   Marek Vasut   ddr: altera: Impl...
241
242
243
244
245
246
247
248
249
  /**
   * scc_mgr_set() - Set SCC Manager register
   * @off:	Base offset in SCC Manager space
   * @grp:	Read/Write group
   * @val:	Value to be set
   *
   * This function sets the SCC Manager (Scan Chain Control Manager) register.
   */
  static void scc_mgr_set(u32 off, u32 grp, u32 val)
3da428595   Dinh Nguyen   driver/ddr/altera...
250
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
251
252
  	writel(val, SDR_PHYGRP_SCCGRP_ADDRESS | off | (grp << 2));
  }
3da428595   Dinh Nguyen   driver/ddr/altera...
253

e893f4dc2   Marek Vasut   ddr: altera: Clea...
254
255
256
257
258
  /**
   * scc_mgr_initialize() - Initialize SCC Manager registers
   *
   * Initialize SCC Manager registers.
   */
c76976d98   Marek Vasut   ddr: altera: Impl...
259
260
  static void scc_mgr_initialize(void)
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
261
  	/*
e893f4dc2   Marek Vasut   ddr: altera: Clea...
262
263
264
265
  	 * Clear register file for HPS. 16 (2^4) is the size of the
  	 * full register file in the scc mgr:
  	 *	RFILE_DEPTH = 1 + log2(MEM_DQ_PER_DQS + 1 + MEM_DM_PER_DQS +
  	 *                             MEM_IF_READ_DQS_WIDTH - 1);
3da428595   Dinh Nguyen   driver/ddr/altera...
266
  	 */
c76976d98   Marek Vasut   ddr: altera: Impl...
267
  	int i;
e893f4dc2   Marek Vasut   ddr: altera: Clea...
268

3da428595   Dinh Nguyen   driver/ddr/altera...
269
  	for (i = 0; i < 16; i++) {
7ac40d25c   Marek Vasut   ddr: altera: Fix ...
270
271
  		debug_cond(DLEVEL == 1, "%s:%d: Clearing SCC RFILE index %u
  ",
3da428595   Dinh Nguyen   driver/ddr/altera...
272
  			   __func__, __LINE__, i);
8e9e62c94   Marek Vasut   ddr: altera: Fix ...
273
  		scc_mgr_set(SCC_MGR_HHP_RFILE_OFFSET, i, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
274
275
  	}
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
276
  static void scc_mgr_set_dqdqs_output_phase(u32 write_group, u32 phase)
5ff825b85   Marek Vasut   ddr: altera: Reor...
277
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
278
  	scc_mgr_set(SCC_MGR_DQDQS_OUT_PHASE_OFFSET, write_group, phase);
5ff825b85   Marek Vasut   ddr: altera: Reor...
279
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
280
  static void scc_mgr_set_dqs_bus_in_delay(u32 read_group, u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
281
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
282
  	scc_mgr_set(SCC_MGR_DQS_IN_DELAY_OFFSET, read_group, delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
283
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
284
  static void scc_mgr_set_dqs_en_phase(u32 read_group, u32 phase)
5ff825b85   Marek Vasut   ddr: altera: Reor...
285
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
286
  	scc_mgr_set(SCC_MGR_DQS_EN_PHASE_OFFSET, read_group, phase);
5ff825b85   Marek Vasut   ddr: altera: Reor...
287
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
288
  static void scc_mgr_set_dqs_en_delay(u32 read_group, u32 delay)
5ff825b85   Marek Vasut   ddr: altera: Reor...
289
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
290
  	scc_mgr_set(SCC_MGR_DQS_EN_DELAY_OFFSET, read_group, delay);
5ff825b85   Marek Vasut   ddr: altera: Reor...
291
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
292
  static void scc_mgr_set_dqs_io_in_delay(u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
293
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
294
  	scc_mgr_set(SCC_MGR_IO_IN_DELAY_OFFSET, rwcfg->mem_dq_per_write_dqs,
c76976d98   Marek Vasut   ddr: altera: Impl...
295
  		    delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
296
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
297
  static void scc_mgr_set_dq_in_delay(u32 dq_in_group, u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
298
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
299
  	scc_mgr_set(SCC_MGR_IO_IN_DELAY_OFFSET, dq_in_group, delay);
5ff825b85   Marek Vasut   ddr: altera: Reor...
300
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
301
  static void scc_mgr_set_dq_out1_delay(u32 dq_in_group, u32 delay)
5ff825b85   Marek Vasut   ddr: altera: Reor...
302
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
303
  	scc_mgr_set(SCC_MGR_IO_OUT1_DELAY_OFFSET, dq_in_group, delay);
5ff825b85   Marek Vasut   ddr: altera: Reor...
304
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
305
  static void scc_mgr_set_dqs_out1_delay(u32 delay)
5ff825b85   Marek Vasut   ddr: altera: Reor...
306
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
307
  	scc_mgr_set(SCC_MGR_IO_OUT1_DELAY_OFFSET, rwcfg->mem_dq_per_write_dqs,
c76976d98   Marek Vasut   ddr: altera: Impl...
308
  		    delay);
5ff825b85   Marek Vasut   ddr: altera: Reor...
309
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
310
  static void scc_mgr_set_dm_out1_delay(u32 dm, u32 delay)
5ff825b85   Marek Vasut   ddr: altera: Reor...
311
  {
c76976d98   Marek Vasut   ddr: altera: Impl...
312
  	scc_mgr_set(SCC_MGR_IO_OUT1_DELAY_OFFSET,
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
313
  		    rwcfg->mem_dq_per_write_dqs + 1 + dm,
c76976d98   Marek Vasut   ddr: altera: Impl...
314
  		    delay);
5ff825b85   Marek Vasut   ddr: altera: Reor...
315
316
317
  }
  
  /* load up dqs config settings */
5ded7320c   Marek Vasut   ddr: altera: sequ...
318
  static void scc_mgr_load_dqs(u32 dqs)
5ff825b85   Marek Vasut   ddr: altera: Reor...
319
320
321
322
323
324
325
326
327
328
329
  {
  	writel(dqs, &sdr_scc_mgr->dqs_ena);
  }
  
  /* load up dqs io config settings */
  static void scc_mgr_load_dqs_io(void)
  {
  	writel(0, &sdr_scc_mgr->dqs_io_ena);
  }
  
  /* load up dq config settings */
5ded7320c   Marek Vasut   ddr: altera: sequ...
330
  static void scc_mgr_load_dq(u32 dq_in_group)
5ff825b85   Marek Vasut   ddr: altera: Reor...
331
332
333
334
335
  {
  	writel(dq_in_group, &sdr_scc_mgr->dq_ena);
  }
  
  /* load up dm config settings */
5ded7320c   Marek Vasut   ddr: altera: sequ...
336
  static void scc_mgr_load_dm(u32 dm)
5ff825b85   Marek Vasut   ddr: altera: Reor...
337
338
  {
  	writel(dm, &sdr_scc_mgr->dm_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
339
  }
0b69b807d   Marek Vasut   ddr: altera: Impl...
340
341
342
343
344
345
346
347
348
349
350
351
  /**
   * 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)
3da428595   Dinh Nguyen   driver/ddr/altera...
352
  {
0b69b807d   Marek Vasut   ddr: altera: Impl...
353
  	u32 r;
3da428595   Dinh Nguyen   driver/ddr/altera...
354

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
355
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
3da428595   Dinh Nguyen   driver/ddr/altera...
356
  	     r += NUM_RANKS_PER_SHADOW_REG) {
0b69b807d   Marek Vasut   ddr: altera: Impl...
357
358
359
360
  		scc_mgr_set(off, grp, val);
  
  		if (update || (r == 0)) {
  			writel(grp, &sdr_scc_mgr->dqs_ena);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
361
  			writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
362
363
364
  		}
  	}
  }
0b69b807d   Marek Vasut   ddr: altera: Impl...
365
366
367
368
369
370
371
372
373
374
375
376
377
  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);
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
378
379
  static void scc_mgr_set_dqdqs_output_phase_all_ranks(u32 write_group,
  						     u32 phase)
3da428595   Dinh Nguyen   driver/ddr/altera...
380
  {
0b69b807d   Marek Vasut   ddr: altera: Impl...
381
382
383
384
385
386
387
388
389
390
  	/*
  	 * 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);
3da428595   Dinh Nguyen   driver/ddr/altera...
391
  }
5ded7320c   Marek Vasut   ddr: altera: sequ...
392
393
  static void scc_mgr_set_dqs_en_delay_all_ranks(u32 read_group,
  					       u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
394
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
395
396
397
398
399
400
401
402
  	/*
  	 * 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.
  	 */
0b69b807d   Marek Vasut   ddr: altera: Impl...
403
404
  	scc_mgr_set_all_ranks(SCC_MGR_DQS_EN_DELAY_OFFSET,
  			      read_group, delay, 1);
3da428595   Dinh Nguyen   driver/ddr/altera...
405
  }
5be355c10   Marek Vasut   ddr: altera: Clea...
406
407
408
409
410
411
412
413
  /**
   * scc_mgr_set_oct_out1_delay() - Set OCT output delay
   * @write_group:	Write group
   * @delay:		Delay value
   *
   * This function sets the OCT output delay in SCC manager.
   */
  static void scc_mgr_set_oct_out1_delay(const u32 write_group, const u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
414
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
415
416
  	const int ratio = rwcfg->mem_if_read_dqs_width /
  			  rwcfg->mem_if_write_dqs_width;
5be355c10   Marek Vasut   ddr: altera: Clea...
417
418
  	const int base = write_group * ratio;
  	int i;
3da428595   Dinh Nguyen   driver/ddr/altera...
419
420
421
422
423
424
425
  	/*
  	 * Load the setting in the SCC manager
  	 * Although OCT affects only write data, the OCT delay is controlled
  	 * by the DQS logic block which is instantiated once per read group.
  	 * For protocols where a write group consists of multiple read groups,
  	 * the setting must be set multiple times.
  	 */
5be355c10   Marek Vasut   ddr: altera: Clea...
426
427
  	for (i = 0; i < ratio; i++)
  		scc_mgr_set(SCC_MGR_OCT_OUT1_DELAY_OFFSET, base + i, delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
428
  }
37a37ca7f   Marek Vasut   ddr: altera: Clea...
429
430
431
432
433
  /**
   * scc_mgr_set_hhp_extras() - Set HHP extras.
   *
   * Load the fixed setting in the SCC manager HHP extras.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
434
435
436
437
  static void scc_mgr_set_hhp_extras(void)
  {
  	/*
  	 * Load the fixed setting in the SCC manager
37a37ca7f   Marek Vasut   ddr: altera: Clea...
438
439
440
441
442
443
  	 * bits: 0:0 = 1'b1	- DQS bypass
  	 * bits: 1:1 = 1'b1	- DQ bypass
  	 * bits: 4:2 = 3'b001	- rfifo_mode
  	 * bits: 6:5 = 2'b01	- rfifo clock_select
  	 * bits: 7:7 = 1'b0	- separate gating from ungating setting
  	 * bits: 8:8 = 1'b0	- separate OE from Output delay setting
3da428595   Dinh Nguyen   driver/ddr/altera...
444
  	 */
37a37ca7f   Marek Vasut   ddr: altera: Clea...
445
446
447
448
449
450
451
452
453
454
455
456
457
  	const u32 value = (0 << 8) | (0 << 7) | (1 << 5) |
  			  (1 << 2) | (1 << 1) | (1 << 0);
  	const u32 addr = SDR_PHYGRP_SCCGRP_ADDRESS |
  			 SCC_MGR_HHP_GLOBALS_OFFSET |
  			 SCC_MGR_HHP_EXTRAS_OFFSET;
  
  	debug_cond(DLEVEL == 1, "%s:%d Setting HHP Extras
  ",
  		   __func__, __LINE__);
  	writel(value, addr);
  	debug_cond(DLEVEL == 1, "%s:%d Done Setting HHP Extras
  ",
  		   __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
458
  }
f42af35bd   Marek Vasut   ddr: altera: Clea...
459
460
461
462
  /**
   * scc_mgr_zero_all() - Zero all DQS config
   *
   * Zero all DQS config.
3da428595   Dinh Nguyen   driver/ddr/altera...
463
464
465
   */
  static void scc_mgr_zero_all(void)
  {
f42af35bd   Marek Vasut   ddr: altera: Clea...
466
  	int i, r;
3da428595   Dinh Nguyen   driver/ddr/altera...
467
468
469
470
471
  
  	/*
  	 * USER Zero all DQS config settings, across all groups and all
  	 * shadow registers
  	 */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
472
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
f42af35bd   Marek Vasut   ddr: altera: Clea...
473
  	     r += NUM_RANKS_PER_SHADOW_REG) {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
474
  		for (i = 0; i < rwcfg->mem_if_read_dqs_width; i++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
475
476
477
478
479
  			/*
  			 * The phases actually don't exist on a per-rank basis,
  			 * but there's no harm updating them several times, so
  			 * let's keep the code simple.
  			 */
160695d88   Marek Vasut   ddr: altera: sequ...
480
  			scc_mgr_set_dqs_bus_in_delay(i, iocfg->dqs_in_reserve);
3da428595   Dinh Nguyen   driver/ddr/altera...
481
482
483
  			scc_mgr_set_dqs_en_phase(i, 0);
  			scc_mgr_set_dqs_en_delay(i, 0);
  		}
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
484
  		for (i = 0; i < rwcfg->mem_if_write_dqs_width; i++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
485
  			scc_mgr_set_dqdqs_output_phase(i, 0);
f42af35bd   Marek Vasut   ddr: altera: Clea...
486
  			/* Arria V/Cyclone V don't have out2. */
160695d88   Marek Vasut   ddr: altera: sequ...
487
  			scc_mgr_set_oct_out1_delay(i, iocfg->dqs_out_reserve);
3da428595   Dinh Nguyen   driver/ddr/altera...
488
489
  		}
  	}
f42af35bd   Marek Vasut   ddr: altera: Clea...
490
  	/* Multicast to all DQS group enables. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
491
492
  	writel(0xff, &sdr_scc_mgr->dqs_ena);
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
493
  }
c5c5f5378   Marek Vasut   ddr: altera: Clea...
494
495
496
497
498
499
500
  /**
   * scc_set_bypass_mode() - Set bypass mode and trigger SCC update
   * @write_group:	Write group
   *
   * Set bypass mode and trigger SCC update.
   */
  static void scc_set_bypass_mode(const u32 write_group)
3da428595   Dinh Nguyen   driver/ddr/altera...
501
  {
c5c5f5378   Marek Vasut   ddr: altera: Clea...
502
  	/* Multicast to all DQ enables. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
503
504
  	writel(0xff, &sdr_scc_mgr->dq_ena);
  	writel(0xff, &sdr_scc_mgr->dm_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
505

c5c5f5378   Marek Vasut   ddr: altera: Clea...
506
  	/* Update current DQS IO enable. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
507
  	writel(0, &sdr_scc_mgr->dqs_io_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
508

c5c5f5378   Marek Vasut   ddr: altera: Clea...
509
  	/* Update the DQS logic. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
510
  	writel(write_group, &sdr_scc_mgr->dqs_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
511

c5c5f5378   Marek Vasut   ddr: altera: Clea...
512
  	/* Hit update. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
513
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
514
  }
5e8378963   Marek Vasut   ddr: altera: Clea...
515
516
517
518
519
520
521
  /**
   * scc_mgr_load_dqs_for_write_group() - Load DQS settings for Write Group
   * @write_group:	Write group
   *
   * Load DQS settings for Write Group, do not trigger SCC update.
   */
  static void scc_mgr_load_dqs_for_write_group(const u32 write_group)
5ff825b85   Marek Vasut   ddr: altera: Reor...
522
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
523
524
  	const int ratio = rwcfg->mem_if_read_dqs_width /
  			  rwcfg->mem_if_write_dqs_width;
5e8378963   Marek Vasut   ddr: altera: Clea...
525
526
  	const int base = write_group * ratio;
  	int i;
5ff825b85   Marek Vasut   ddr: altera: Reor...
527
  	/*
5e8378963   Marek Vasut   ddr: altera: Clea...
528
  	 * Load the setting in the SCC manager
5ff825b85   Marek Vasut   ddr: altera: Reor...
529
530
531
  	 * Although OCT affects only write data, the OCT delay is controlled
  	 * by the DQS logic block which is instantiated once per read group.
  	 * For protocols where a write group consists of multiple read groups,
5e8378963   Marek Vasut   ddr: altera: Clea...
532
  	 * the setting must be set multiple times.
5ff825b85   Marek Vasut   ddr: altera: Reor...
533
  	 */
5e8378963   Marek Vasut   ddr: altera: Clea...
534
535
  	for (i = 0; i < ratio; i++)
  		writel(base + i, &sdr_scc_mgr->dqs_ena);
5ff825b85   Marek Vasut   ddr: altera: Reor...
536
  }
d41ea93a3   Marek Vasut   ddr: altera: Clea...
537
538
539
540
541
542
  /**
   * scc_mgr_zero_group() - Zero all configs for a group
   *
   * Zero DQ, DM, DQS and OCT configs for a group.
   */
  static void scc_mgr_zero_group(const u32 write_group, const int out_only)
3da428595   Dinh Nguyen   driver/ddr/altera...
543
  {
d41ea93a3   Marek Vasut   ddr: altera: Clea...
544
  	int i, r;
3da428595   Dinh Nguyen   driver/ddr/altera...
545

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
546
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
d41ea93a3   Marek Vasut   ddr: altera: Clea...
547
548
  	     r += NUM_RANKS_PER_SHADOW_REG) {
  		/* Zero all DQ config settings. */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
549
  		for (i = 0; i < rwcfg->mem_dq_per_write_dqs; i++) {
07aee5bd9   Marek Vasut   ddr: altera: Clea...
550
  			scc_mgr_set_dq_out1_delay(i, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
551
  			if (!out_only)
07aee5bd9   Marek Vasut   ddr: altera: Clea...
552
  				scc_mgr_set_dq_in_delay(i, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
553
  		}
d41ea93a3   Marek Vasut   ddr: altera: Clea...
554
  		/* Multicast to all DQ enables. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
555
  		writel(0xff, &sdr_scc_mgr->dq_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
556

d41ea93a3   Marek Vasut   ddr: altera: Clea...
557
558
  		/* Zero all DM config settings. */
  		for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++)
07aee5bd9   Marek Vasut   ddr: altera: Clea...
559
  			scc_mgr_set_dm_out1_delay(i, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
560

d41ea93a3   Marek Vasut   ddr: altera: Clea...
561
  		/* Multicast to all DM enables. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
562
  		writel(0xff, &sdr_scc_mgr->dm_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
563

d41ea93a3   Marek Vasut   ddr: altera: Clea...
564
  		/* Zero all DQS IO settings. */
3da428595   Dinh Nguyen   driver/ddr/altera...
565
  		if (!out_only)
326752496   Marek Vasut   ddr: altera: Clea...
566
  			scc_mgr_set_dqs_io_in_delay(0);
d41ea93a3   Marek Vasut   ddr: altera: Clea...
567
568
  
  		/* Arria V/Cyclone V don't have out2. */
160695d88   Marek Vasut   ddr: altera: sequ...
569
570
  		scc_mgr_set_dqs_out1_delay(iocfg->dqs_out_reserve);
  		scc_mgr_set_oct_out1_delay(write_group, iocfg->dqs_out_reserve);
3da428595   Dinh Nguyen   driver/ddr/altera...
571
  		scc_mgr_load_dqs_for_write_group(write_group);
d41ea93a3   Marek Vasut   ddr: altera: Clea...
572
  		/* Multicast to all DQS IO enables (only 1 in total). */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
573
  		writel(0, &sdr_scc_mgr->dqs_io_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
574

d41ea93a3   Marek Vasut   ddr: altera: Clea...
575
  		/* Hit update to zero everything. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
576
  		writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
577
578
  	}
  }
3da428595   Dinh Nguyen   driver/ddr/altera...
579
580
581
582
  /*
   * apply and load a particular input delay for the DQ pins in a group
   * group_bgn is the index of the first dq pin (in the write group)
   */
5ded7320c   Marek Vasut   ddr: altera: sequ...
583
  static void scc_mgr_apply_group_dq_in_delay(u32 group_bgn, u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
584
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
585
  	u32 i, p;
3da428595   Dinh Nguyen   driver/ddr/altera...
586

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
587
  	for (i = 0, p = group_bgn; i < rwcfg->mem_dq_per_read_dqs; i++, p++) {
07aee5bd9   Marek Vasut   ddr: altera: Clea...
588
  		scc_mgr_set_dq_in_delay(p, delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
589
590
591
  		scc_mgr_load_dq(p);
  	}
  }
300c2e626   Marek Vasut   ddr: altera: Clea...
592
593
594
595
596
597
598
  /**
   * scc_mgr_apply_group_dq_out1_delay() - Apply and load an output delay for the DQ pins in a group
   * @delay:		Delay value
   *
   * Apply and load a particular output delay for the DQ pins in a group.
   */
  static void scc_mgr_apply_group_dq_out1_delay(const u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
599
  {
300c2e626   Marek Vasut   ddr: altera: Clea...
600
  	int i;
3da428595   Dinh Nguyen   driver/ddr/altera...
601

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
602
  	for (i = 0; i < rwcfg->mem_dq_per_write_dqs; i++) {
300c2e626   Marek Vasut   ddr: altera: Clea...
603
  		scc_mgr_set_dq_out1_delay(i, delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
604
605
606
607
608
  		scc_mgr_load_dq(i);
  	}
  }
  
  /* apply and load a particular output delay for the DM pins in a group */
5ded7320c   Marek Vasut   ddr: altera: sequ...
609
  static void scc_mgr_apply_group_dm_out1_delay(u32 delay1)
3da428595   Dinh Nguyen   driver/ddr/altera...
610
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
611
  	u32 i;
3da428595   Dinh Nguyen   driver/ddr/altera...
612
613
  
  	for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++) {
07aee5bd9   Marek Vasut   ddr: altera: Clea...
614
  		scc_mgr_set_dm_out1_delay(i, delay1);
3da428595   Dinh Nguyen   driver/ddr/altera...
615
616
617
618
619
620
  		scc_mgr_load_dm(i);
  	}
  }
  
  
  /* apply and load delay on both DQS and OCT out1 */
5ded7320c   Marek Vasut   ddr: altera: sequ...
621
622
  static void scc_mgr_apply_group_dqs_io_and_oct_out1(u32 write_group,
  						    u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
623
  {
326752496   Marek Vasut   ddr: altera: Clea...
624
  	scc_mgr_set_dqs_out1_delay(delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
625
626
627
628
629
  	scc_mgr_load_dqs_io();
  
  	scc_mgr_set_oct_out1_delay(write_group, delay);
  	scc_mgr_load_dqs_for_write_group(write_group);
  }
5cb1b5087   Marek Vasut   ddr: altera: Inte...
630
631
632
633
634
635
636
  /**
   * scc_mgr_apply_group_all_out_delay_add() - Apply a delay to the entire output side: DQ, DM, DQS, OCT
   * @write_group:	Write group
   * @delay:		Delay value
   *
   * Apply a delay to the entire output side: DQ, DM, DQS, OCT.
   */
8eccde3eb   Marek Vasut   ddr: altera: Inte...
637
  static void scc_mgr_apply_group_all_out_delay_add(const u32 write_group,
8eccde3eb   Marek Vasut   ddr: altera: Inte...
638
639
640
  						  const u32 delay)
  {
  	u32 i, new_delay;
3da428595   Dinh Nguyen   driver/ddr/altera...
641

8eccde3eb   Marek Vasut   ddr: altera: Inte...
642
  	/* DQ shift */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
643
  	for (i = 0; i < rwcfg->mem_dq_per_write_dqs; i++)
3da428595   Dinh Nguyen   driver/ddr/altera...
644
  		scc_mgr_load_dq(i);
3da428595   Dinh Nguyen   driver/ddr/altera...
645

8eccde3eb   Marek Vasut   ddr: altera: Inte...
646
647
  	/* DM shift */
  	for (i = 0; i < RW_MGR_NUM_DM_PER_WRITE_GROUP; i++)
3da428595   Dinh Nguyen   driver/ddr/altera...
648
  		scc_mgr_load_dm(i);
3da428595   Dinh Nguyen   driver/ddr/altera...
649

5cb1b5087   Marek Vasut   ddr: altera: Inte...
650
651
  	/* DQS shift */
  	new_delay = READ_SCC_DQS_IO_OUT2_DELAY + delay;
160695d88   Marek Vasut   ddr: altera: sequ...
652
  	if (new_delay > iocfg->io_out2_delay_max) {
5cb1b5087   Marek Vasut   ddr: altera: Inte...
653
654
655
656
  		debug_cond(DLEVEL == 1,
  			   "%s:%d (%u, %u) DQS: %u > %d; adding %u to OUT1
  ",
  			   __func__, __LINE__, write_group, delay, new_delay,
160695d88   Marek Vasut   ddr: altera: sequ...
657
658
659
  			   iocfg->io_out2_delay_max,
  			   new_delay - iocfg->io_out2_delay_max);
  		new_delay -= iocfg->io_out2_delay_max;
5cb1b5087   Marek Vasut   ddr: altera: Inte...
660
  		scc_mgr_set_dqs_out1_delay(new_delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
661
662
663
  	}
  
  	scc_mgr_load_dqs_io();
5cb1b5087   Marek Vasut   ddr: altera: Inte...
664
665
  	/* OCT shift */
  	new_delay = READ_SCC_OCT_OUT2_DELAY + delay;
160695d88   Marek Vasut   ddr: altera: sequ...
666
  	if (new_delay > iocfg->io_out2_delay_max) {
5cb1b5087   Marek Vasut   ddr: altera: Inte...
667
668
669
670
  		debug_cond(DLEVEL == 1,
  			   "%s:%d (%u, %u) DQS: %u > %d; adding %u to OUT1
  ",
  			   __func__, __LINE__, write_group, delay,
160695d88   Marek Vasut   ddr: altera: sequ...
671
672
673
  			   new_delay, iocfg->io_out2_delay_max,
  			   new_delay - iocfg->io_out2_delay_max);
  		new_delay -= iocfg->io_out2_delay_max;
5cb1b5087   Marek Vasut   ddr: altera: Inte...
674
  		scc_mgr_set_oct_out1_delay(write_group, new_delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
675
676
677
678
  	}
  
  	scc_mgr_load_dqs_for_write_group(write_group);
  }
f51a7d359   Marek Vasut   ddr: altera: Clea...
679
680
681
682
683
684
  /**
   * scc_mgr_apply_group_all_out_delay_add() - Apply a delay to the entire output side to all ranks
   * @write_group:	Write group
   * @delay:		Delay value
   *
   * Apply a delay to the entire output side (DQ, DM, DQS, OCT) to all ranks.
3da428595   Dinh Nguyen   driver/ddr/altera...
685
   */
f51a7d359   Marek Vasut   ddr: altera: Clea...
686
687
688
  static void
  scc_mgr_apply_group_all_out_delay_add_all_ranks(const u32 write_group,
  						const u32 delay)
3da428595   Dinh Nguyen   driver/ddr/altera...
689
  {
f51a7d359   Marek Vasut   ddr: altera: Clea...
690
  	int r;
3da428595   Dinh Nguyen   driver/ddr/altera...
691

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
692
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
f51a7d359   Marek Vasut   ddr: altera: Clea...
693
  	     r += NUM_RANKS_PER_SHADOW_REG) {
5cb1b5087   Marek Vasut   ddr: altera: Inte...
694
  		scc_mgr_apply_group_all_out_delay_add(write_group, delay);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
695
  		writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
696
697
  	}
  }
f936f94f8   Marek Vasut   ddr: altera: Mino...
698
699
700
701
702
703
  /**
   * set_jump_as_return() - Return instruction optimization
   *
   * Optimization used to recover some slots in ddr3 inst_rom could be
   * applied to other protocols if we wanted to
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
704
705
  static void set_jump_as_return(void)
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
706
  	/*
f936f94f8   Marek Vasut   ddr: altera: Mino...
707
  	 * To save space, we replace return with jump to special shared
3da428595   Dinh Nguyen   driver/ddr/altera...
708
  	 * RETURN instruction so we set the counter to large value so that
f936f94f8   Marek Vasut   ddr: altera: Mino...
709
  	 * we always jump.
3da428595   Dinh Nguyen   driver/ddr/altera...
710
  	 */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
711
  	writel(0xff, &sdr_rw_load_mgr_regs->load_cntr0);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
712
  	writel(rwcfg->rreturn, &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
713
  }
3de9622e9   Marek Vasut   ddr: altera: Clea...
714
715
716
717
718
  /**
   * delay_for_n_mem_clocks() - Delay for N memory clocks
   * @clocks:	Length of the delay
   *
   * Delay for N memory clocks.
3da428595   Dinh Nguyen   driver/ddr/altera...
719
   */
90a584b76   Marek Vasut   ddr: altera: Clea...
720
  static void delay_for_n_mem_clocks(const u32 clocks)
3da428595   Dinh Nguyen   driver/ddr/altera...
721
  {
90a584b76   Marek Vasut   ddr: altera: Clea...
722
  	u32 afi_clocks;
6a39be6ca   Marek Vasut   ddr: altera: Clea...
723
724
725
  	u16 c_loop;
  	u8 inner;
  	u8 outer;
3da428595   Dinh Nguyen   driver/ddr/altera...
726
727
728
  
  	debug("%s:%d: clocks=%u ... start
  ", __func__, __LINE__, clocks);
cbcaf4604   Marek Vasut   ddr: altera: Clea...
729
  	/* Scale (rounding up) to get afi clocks. */
96fd4362c   Marek Vasut   ddr: altera: sequ...
730
  	afi_clocks = DIV_ROUND_UP(clocks, misccfg->afi_rate_ratio);
cbcaf4604   Marek Vasut   ddr: altera: Clea...
731
732
  	if (afi_clocks)	/* Temporary underflow protection */
  		afi_clocks--;
3da428595   Dinh Nguyen   driver/ddr/altera...
733
734
  
  	/*
90a584b76   Marek Vasut   ddr: altera: Clea...
735
736
737
738
  	 * Note, we don't bother accounting for being off a little
  	 * bit because of a few extra instructions in outer loops.
  	 * Note, the loops have a test at the end, and do the test
  	 * before the decrement, and so always perform the loop
3da428595   Dinh Nguyen   driver/ddr/altera...
739
740
  	 * 1 time more than the counter value
  	 */
6a39be6ca   Marek Vasut   ddr: altera: Clea...
741
742
743
  	c_loop = afi_clocks >> 16;
  	outer = c_loop ? 0xff : (afi_clocks >> 8);
  	inner = outer ? 0xff : afi_clocks;
3da428595   Dinh Nguyen   driver/ddr/altera...
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
  
  	/*
  	 * rom instructions are structured as follows:
  	 *
  	 *    IDLE_LOOP2: jnz cntr0, TARGET_A
  	 *    IDLE_LOOP1: jnz cntr1, TARGET_B
  	 *                return
  	 *
  	 * so, when doing nested loops, TARGET_A is set to IDLE_LOOP2, and
  	 * TARGET_B is set to IDLE_LOOP2 as well
  	 *
  	 * if we have no outer loop, though, then we can use IDLE_LOOP1 only,
  	 * and set TARGET_B to IDLE_LOOP1 and we skip IDLE_LOOP2 entirely
  	 *
  	 * a little confusing, but it helps save precious space in the inst_rom
  	 * and sequencer rom and keeps the delays more accurate and reduces
  	 * overhead
  	 */
cbcaf4604   Marek Vasut   ddr: altera: Clea...
762
  	if (afi_clocks < 0x100) {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
763
  		writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(inner),
139823ecb   Marek Vasut   ddr: altera: sequ...
764
  		       &sdr_rw_load_mgr_regs->load_cntr1);
3da428595   Dinh Nguyen   driver/ddr/altera...
765

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
766
  		writel(rwcfg->idle_loop1,
139823ecb   Marek Vasut   ddr: altera: sequ...
767
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
768

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
769
  		writel(rwcfg->idle_loop1, SDR_PHYGRP_RWMGRGRP_ADDRESS |
1273dd9ea   Marek Vasut   ddr: altera: Mass...
770
  					  RW_MGR_RUN_SINGLE_GROUP_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
771
  	} else {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
772
  		writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(inner),
139823ecb   Marek Vasut   ddr: altera: sequ...
773
  		       &sdr_rw_load_mgr_regs->load_cntr0);
3da428595   Dinh Nguyen   driver/ddr/altera...
774

1273dd9ea   Marek Vasut   ddr: altera: Mass...
775
  		writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(outer),
139823ecb   Marek Vasut   ddr: altera: sequ...
776
  		       &sdr_rw_load_mgr_regs->load_cntr1);
3da428595   Dinh Nguyen   driver/ddr/altera...
777

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
778
  		writel(rwcfg->idle_loop2,
139823ecb   Marek Vasut   ddr: altera: sequ...
779
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
780

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
781
  		writel(rwcfg->idle_loop2,
139823ecb   Marek Vasut   ddr: altera: sequ...
782
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
783

0c1b81bdf   Marek Vasut   ddr: altera: Clea...
784
  		do {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
785
  			writel(rwcfg->idle_loop2,
139823ecb   Marek Vasut   ddr: altera: sequ...
786
787
  			       SDR_PHYGRP_RWMGRGRP_ADDRESS |
  			       RW_MGR_RUN_SINGLE_GROUP_OFFSET);
0c1b81bdf   Marek Vasut   ddr: altera: Clea...
788
  		} while (c_loop-- != 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
789
790
791
792
  	}
  	debug("%s:%d clocks=%u ... end
  ", __func__, __LINE__, clocks);
  }
944fe7193   Marek Vasut   ddr: altera: Fact...
793
794
795
796
797
798
799
800
801
802
803
  /**
   * rw_mgr_mem_init_load_regs() - Load instruction registers
   * @cntr0:	Counter 0 value
   * @cntr1:	Counter 1 value
   * @cntr2:	Counter 2 value
   * @jump:	Jump instruction value
   *
   * Load instruction registers.
   */
  static void rw_mgr_mem_init_load_regs(u32 cntr0, u32 cntr1, u32 cntr2, u32 jump)
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
804
  	u32 grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
944fe7193   Marek Vasut   ddr: altera: Fact...
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
  			   RW_MGR_RUN_SINGLE_GROUP_OFFSET;
  
  	/* Load counters */
  	writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr0),
  	       &sdr_rw_load_mgr_regs->load_cntr0);
  	writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr1),
  	       &sdr_rw_load_mgr_regs->load_cntr1);
  	writel(SKIP_DELAY_LOOP_VALUE_OR_ZERO(cntr2),
  	       &sdr_rw_load_mgr_regs->load_cntr2);
  
  	/* Load jump address */
  	writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add0);
  	writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add1);
  	writel(jump, &sdr_rw_load_jump_mgr_regs->load_jump_add2);
  
  	/* Execute count instruction */
  	writel(jump, grpaddr);
  }
ecd2334a1   Marek Vasut   ddr: altera: Fact...
823
824
825
826
827
828
829
830
831
832
  /**
   * 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(const u32 fin1, const u32 fin2,
  				 const int precharge)
3da428595   Dinh Nguyen   driver/ddr/altera...
833
  {
ecd2334a1   Marek Vasut   ddr: altera: Fact...
834
835
836
  	u32 grpaddr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
  		      RW_MGR_RUN_SINGLE_GROUP_OFFSET;
  	u32 r;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
837
  	for (r = 0; r < rwcfg->mem_number_of_ranks; r++) {
ecd2334a1   Marek Vasut   ddr: altera: Fact...
838
839
840
841
842
  		/* set rank */
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
  
  		/* precharge all banks ... */
  		if (precharge)
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
843
  			writel(rwcfg->precharge_all, grpaddr);
3da428595   Dinh Nguyen   driver/ddr/altera...
844

ecd2334a1   Marek Vasut   ddr: altera: Fact...
845
846
847
848
  		/*
  		 * USER Use Mirror-ed commands for odd ranks if address
  		 * mirrorring is on
  		 */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
849
  		if ((rwcfg->mem_address_mirroring >> r) & 0x1) {
ecd2334a1   Marek Vasut   ddr: altera: Fact...
850
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
851
  			writel(rwcfg->mrs2_mirr, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
852
853
  			delay_for_n_mem_clocks(4);
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
854
  			writel(rwcfg->mrs3_mirr, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
855
856
  			delay_for_n_mem_clocks(4);
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
857
  			writel(rwcfg->mrs1_mirr, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
858
859
860
861
862
  			delay_for_n_mem_clocks(4);
  			set_jump_as_return();
  			writel(fin1, grpaddr);
  		} else {
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
863
  			writel(rwcfg->mrs2, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
864
865
  			delay_for_n_mem_clocks(4);
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
866
  			writel(rwcfg->mrs3, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
867
868
  			delay_for_n_mem_clocks(4);
  			set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
869
  			writel(rwcfg->mrs1, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
870
871
872
873
874
875
876
877
  			set_jump_as_return();
  			writel(fin2, grpaddr);
  		}
  
  		if (precharge)
  			continue;
  
  		set_jump_as_return();
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
878
  		writel(rwcfg->zqcl, grpaddr);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
879
880
881
882
883
  
  		/* tZQinit = tDLLK = 512 ck cycles */
  		delay_for_n_mem_clocks(512);
  	}
  }
8e9d7d04b   Marek Vasut   ddr: altera: Mino...
884
885
886
887
888
  /**
   * rw_mgr_mem_initialize() - Initialize RW Manager
   *
   * Initialize RW Manager.
   */
ecd2334a1   Marek Vasut   ddr: altera: Fact...
889
890
  static void rw_mgr_mem_initialize(void)
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
891
892
893
894
  	debug("%s:%d
  ", __func__, __LINE__);
  
  	/* The reset / cke part of initialization is broadcasted to all ranks */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
895
896
  	writel(RW_MGR_RANK_ALL, SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				RW_MGR_SET_CS_AND_ODT_MASK_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
897
898
899
900
901
902
903
904
905
906
  
  	/*
  	 * Here's how you load register for a loop
  	 * Counters are located @ 0x800
  	 * Jump address are located @ 0xC00
  	 * For both, registers 0 to 3 are selected using bits 3 and 2, like
  	 * in 0x800, 0x804, 0x808, 0x80C and 0xC00, 0xC04, 0xC08, 0xC0C
  	 * I know this ain't pretty, but Avalon bus throws away the 2 least
  	 * significant bits
  	 */
8e9d7d04b   Marek Vasut   ddr: altera: Mino...
907
  	/* Start with memory RESET activated */
3da428595   Dinh Nguyen   driver/ddr/altera...
908
909
910
911
912
913
914
915
916
917
918
919
  
  	/* tINIT = 200us */
  
  	/*
  	 * 200us @ 266MHz (3.75 ns) ~ 54000 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 = 0 , a = 256 , b = 106 => a = FF,
  	 * b = 6A
  	 */
139823ecb   Marek Vasut   ddr: altera: sequ...
920
921
  	rw_mgr_mem_init_load_regs(misccfg->tinit_cntr0_val,
  				  misccfg->tinit_cntr1_val,
96fd4362c   Marek Vasut   ddr: altera: sequ...
922
  				  misccfg->tinit_cntr2_val,
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
923
  				  rwcfg->init_reset_0_cke_0);
3da428595   Dinh Nguyen   driver/ddr/altera...
924

8e9d7d04b   Marek Vasut   ddr: altera: Mino...
925
  	/* Indicate that memory is stable. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
926
  	writel(1, &phy_mgr_cfg->reset_mem_stbl);
3da428595   Dinh Nguyen   driver/ddr/altera...
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
  
  	/*
  	 * transition the RESET to high
  	 * Wait for 500us
  	 */
  
  	/*
  	 * 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
  	 */
139823ecb   Marek Vasut   ddr: altera: sequ...
942
943
  	rw_mgr_mem_init_load_regs(misccfg->treset_cntr0_val,
  				  misccfg->treset_cntr1_val,
96fd4362c   Marek Vasut   ddr: altera: sequ...
944
  				  misccfg->treset_cntr2_val,
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
945
  				  rwcfg->init_reset_1_cke_0);
3da428595   Dinh Nguyen   driver/ddr/altera...
946

8e9d7d04b   Marek Vasut   ddr: altera: Mino...
947
  	/* Bring up clock enable. */
3da428595   Dinh Nguyen   driver/ddr/altera...
948
949
950
  
  	/* tXRP < 250 ck cycles */
  	delay_for_n_mem_clocks(250);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
951
  	rw_mgr_mem_load_user(rwcfg->mrs0_dll_reset_mirr, rwcfg->mrs0_dll_reset,
ecd2334a1   Marek Vasut   ddr: altera: Fact...
952
  			     0);
3da428595   Dinh Nguyen   driver/ddr/altera...
953
  }
f1f22f720   Marek Vasut   ddr: altera: Mino...
954
955
956
957
958
  /**
   * rw_mgr_mem_handoff() - Hand off the memory to user
   *
   * At the end of calibration we have to program the user settings in
   * and hand off the memory to the user.
3da428595   Dinh Nguyen   driver/ddr/altera...
959
960
961
   */
  static void rw_mgr_mem_handoff(void)
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
962
  	rw_mgr_mem_load_user(rwcfg->mrs0_user_mirr, rwcfg->mrs0_user, 1);
ecd2334a1   Marek Vasut   ddr: altera: Fact...
963
  	/*
f1f22f720   Marek Vasut   ddr: altera: Mino...
964
965
966
  	 * Need to wait tMOD (12CK or 15ns) time before issuing other
  	 * commands, but we will have plenty of NIOS cycles before actual
  	 * handoff so its okay.
ecd2334a1   Marek Vasut   ddr: altera: Fact...
967
  	 */
3da428595   Dinh Nguyen   driver/ddr/altera...
968
  }
8371c2ee6   Marek Vasut   ddr: altera: Clea...
969
970
971
972
973
974
975
  /**
   * rw_mgr_mem_calibrate_write_test_issue() - Issue write test command
   * @group:	Write Group
   * @use_dm:	Use DM
   *
   * Issue write test command. Two variants are provided, one that just tests
   * a write pattern and another that tests datamask functionality.
ad64769ce   Marek Vasut   ddr: altera: Clea...
976
   */
8371c2ee6   Marek Vasut   ddr: altera: Clea...
977
978
  static void rw_mgr_mem_calibrate_write_test_issue(u32 group,
  						  u32 test_dm)
ad64769ce   Marek Vasut   ddr: altera: Clea...
979
  {
8371c2ee6   Marek Vasut   ddr: altera: Clea...
980
981
  	const u32 quick_write_mode =
  		(STATIC_CALIB_STEPS & CALIB_SKIP_WRITES) &&
96fd4362c   Marek Vasut   ddr: altera: sequ...
982
  		misccfg->enable_super_quick_calibration;
8371c2ee6   Marek Vasut   ddr: altera: Clea...
983
984
  	u32 mcc_instruction;
  	u32 rw_wl_nop_cycles;
ad64769ce   Marek Vasut   ddr: altera: Clea...
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
  
  	/*
  	 * Set counter and jump addresses for the right
  	 * number of NOP cycles.
  	 * The number of supported NOP cycles can range from -1 to infinity
  	 * Three different cases are handled:
  	 *
  	 * 1. For a number of NOP cycles greater than 0, the RW Mgr looping
  	 *    mechanism will be used to insert the right number of NOPs
  	 *
  	 * 2. For a number of NOP cycles equals to 0, the micro-instruction
  	 *    issuing the write command will jump straight to the
  	 *    micro-instruction that turns on DQS (for DDRx), or outputs write
  	 *    data (for RLD), skipping
  	 *    the NOP micro-instruction all together
  	 *
  	 * 3. A number of NOP cycles equal to -1 indicates that DQS must be
  	 *    turned on in the same micro-instruction that issues the write
  	 *    command. Then we need
  	 *    to directly jump to the micro-instruction that sends out the data
  	 *
  	 * NOTE: Implementing this mechanism uses 2 RW Mgr jump-counters
  	 *       (2 and 3). One jump-counter (0) is used to perform multiple
  	 *       write-read operations.
  	 *       one counter left to issue this command in "multiple-group" mode
  	 */
  
  	rw_wl_nop_cycles = gbl->rw_wl_nop_cycles;
  
  	if (rw_wl_nop_cycles == -1) {
  		/*
  		 * CNTR 2 - We want to execute the special write operation that
  		 * turns on DQS right away and then skip directly to the
  		 * instruction that sends out the data. We set the counter to a
  		 * large number so that the jump is always taken.
  		 */
  		writel(0xFF, &sdr_rw_load_mgr_regs->load_cntr2);
  
  		/* CNTR 3 - Not used */
  		if (test_dm) {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1025
1026
  			mcc_instruction = rwcfg->lfsr_wr_rd_dm_bank_0_wl_1;
  			writel(rwcfg->lfsr_wr_rd_dm_bank_0_data,
ad64769ce   Marek Vasut   ddr: altera: Clea...
1027
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1028
  			writel(rwcfg->lfsr_wr_rd_dm_bank_0_nop,
ad64769ce   Marek Vasut   ddr: altera: Clea...
1029
1030
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
  		} else {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1031
1032
  			mcc_instruction = rwcfg->lfsr_wr_rd_bank_0_wl_1;
  			writel(rwcfg->lfsr_wr_rd_bank_0_data,
139823ecb   Marek Vasut   ddr: altera: sequ...
1033
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1034
  			writel(rwcfg->lfsr_wr_rd_bank_0_nop,
139823ecb   Marek Vasut   ddr: altera: sequ...
1035
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
  		}
  	} else if (rw_wl_nop_cycles == 0) {
  		/*
  		 * CNTR 2 - We want to skip the NOP operation and go straight
  		 * to the DQS enable instruction. We set the counter to a large
  		 * number so that the jump is always taken.
  		 */
  		writel(0xFF, &sdr_rw_load_mgr_regs->load_cntr2);
  
  		/* CNTR 3 - Not used */
  		if (test_dm) {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1047
1048
  			mcc_instruction = rwcfg->lfsr_wr_rd_dm_bank_0;
  			writel(rwcfg->lfsr_wr_rd_dm_bank_0_dqs,
ad64769ce   Marek Vasut   ddr: altera: Clea...
1049
1050
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
  		} else {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1051
1052
  			mcc_instruction = rwcfg->lfsr_wr_rd_bank_0;
  			writel(rwcfg->lfsr_wr_rd_bank_0_dqs,
139823ecb   Marek Vasut   ddr: altera: sequ...
1053
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
  		}
  	} else {
  		/*
  		 * CNTR 2 - In this case we want to execute the next instruction
  		 * and NOT take the jump. So we set the counter to 0. The jump
  		 * address doesn't count.
  		 */
  		writel(0x0, &sdr_rw_load_mgr_regs->load_cntr2);
  		writel(0x0, &sdr_rw_load_jump_mgr_regs->load_jump_add2);
  
  		/*
  		 * CNTR 3 - Set the nop counter to the number of cycles we
  		 * need to loop for, minus 1.
  		 */
  		writel(rw_wl_nop_cycles - 1, &sdr_rw_load_mgr_regs->load_cntr3);
  		if (test_dm) {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1070
1071
  			mcc_instruction = rwcfg->lfsr_wr_rd_dm_bank_0;
  			writel(rwcfg->lfsr_wr_rd_dm_bank_0_nop,
139823ecb   Marek Vasut   ddr: altera: sequ...
1072
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1073
  		} else {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1074
1075
  			mcc_instruction = rwcfg->lfsr_wr_rd_bank_0;
  			writel(rwcfg->lfsr_wr_rd_bank_0_nop,
139823ecb   Marek Vasut   ddr: altera: sequ...
1076
  			       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
  		}
  	}
  
  	writel(0, SDR_PHYGRP_RWMGRGRP_ADDRESS |
  		  RW_MGR_RESET_READ_DATAPATH_OFFSET);
  
  	if (quick_write_mode)
  		writel(0x08, &sdr_rw_load_mgr_regs->load_cntr0);
  	else
  		writel(0x40, &sdr_rw_load_mgr_regs->load_cntr0);
  
  	writel(mcc_instruction, &sdr_rw_load_jump_mgr_regs->load_jump_add0);
  
  	/*
  	 * CNTR 1 - This is used to ensure enough time elapses
  	 * for read data to come back.
  	 */
  	writel(0x30, &sdr_rw_load_mgr_regs->load_cntr1);
  
  	if (test_dm) {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1097
  		writel(rwcfg->lfsr_wr_rd_dm_bank_0_wait,
139823ecb   Marek Vasut   ddr: altera: sequ...
1098
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1099
  	} else {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1100
  		writel(rwcfg->lfsr_wr_rd_bank_0_wait,
139823ecb   Marek Vasut   ddr: altera: sequ...
1101
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1102
  	}
8371c2ee6   Marek Vasut   ddr: altera: Clea...
1103
1104
1105
  	writel(mcc_instruction, (SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				RW_MGR_RUN_SINGLE_GROUP_OFFSET) +
  				(group << 2));
ad64769ce   Marek Vasut   ddr: altera: Clea...
1106
  }
4a82854b0   Marek Vasut   ddr: altera: Clea...
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
  /**
   * rw_mgr_mem_calibrate_write_test() - Test writes, check for single/multiple pass
   * @rank_bgn:		Rank number
   * @write_group:	Write Group
   * @use_dm:		Use DM
   * @all_correct:	All bits must be correct in the mask
   * @bit_chk:		Resulting bit mask after the test
   * @all_ranks:		Test all ranks
   *
   * Test writes, can check for a single bit pass or multiple bit pass.
   */
b9452ea09   Marek Vasut   ddr: altera: Clea...
1118
1119
1120
1121
  static int
  rw_mgr_mem_calibrate_write_test(const u32 rank_bgn, const u32 write_group,
  				const u32 use_dm, const u32 all_correct,
  				u32 *bit_chk, const u32 all_ranks)
ad64769ce   Marek Vasut   ddr: altera: Clea...
1122
  {
b9452ea09   Marek Vasut   ddr: altera: Clea...
1123
  	const u32 rank_end = all_ranks ?
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1124
  				rwcfg->mem_number_of_ranks :
b9452ea09   Marek Vasut   ddr: altera: Clea...
1125
  				(rank_bgn + NUM_RANKS_PER_SHADOW_REG);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1126
1127
  	const u32 shift_ratio = rwcfg->mem_dq_per_write_dqs /
  				rwcfg->mem_virtual_groups_per_write_dqs;
b9452ea09   Marek Vasut   ddr: altera: Clea...
1128
1129
1130
1131
  	const u32 correct_mask_vg = param->write_correct_mask_vg;
  
  	u32 tmp_bit_chk, base_rw_mgr;
  	int vg, r;
ad64769ce   Marek Vasut   ddr: altera: Clea...
1132
1133
  
  	*bit_chk = param->write_correct_mask;
ad64769ce   Marek Vasut   ddr: altera: Clea...
1134
1135
  
  	for (r = rank_bgn; r < rank_end; r++) {
b9452ea09   Marek Vasut   ddr: altera: Clea...
1136
  		/* Set rank */
ad64769ce   Marek Vasut   ddr: altera: Clea...
1137
1138
1139
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
  
  		tmp_bit_chk = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1140
  		for (vg = rwcfg->mem_virtual_groups_per_write_dqs - 1;
b9452ea09   Marek Vasut   ddr: altera: Clea...
1141
1142
  		     vg >= 0; vg--) {
  			/* Reset the FIFOs to get pointers to known state. */
ad64769ce   Marek Vasut   ddr: altera: Clea...
1143
  			writel(0, &phy_mgr_cmd->fifo_reset);
b9452ea09   Marek Vasut   ddr: altera: Clea...
1144
1145
  			rw_mgr_mem_calibrate_write_test_issue(
  				write_group *
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1146
  				rwcfg->mem_virtual_groups_per_write_dqs + vg,
ad64769ce   Marek Vasut   ddr: altera: Clea...
1147
  				use_dm);
b9452ea09   Marek Vasut   ddr: altera: Clea...
1148
1149
1150
  			base_rw_mgr = readl(SDR_PHYGRP_RWMGRGRP_ADDRESS);
  			tmp_bit_chk <<= shift_ratio;
  			tmp_bit_chk |= (correct_mask_vg & ~(base_rw_mgr));
ad64769ce   Marek Vasut   ddr: altera: Clea...
1151
  		}
b9452ea09   Marek Vasut   ddr: altera: Clea...
1152

ad64769ce   Marek Vasut   ddr: altera: Clea...
1153
1154
  		*bit_chk &= tmp_bit_chk;
  	}
b9452ea09   Marek Vasut   ddr: altera: Clea...
1155
  	set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1156
  	if (all_correct) {
b9452ea09   Marek Vasut   ddr: altera: Clea...
1157
1158
1159
1160
1161
1162
  		debug_cond(DLEVEL == 2,
  			   "write_test(%u,%u,ALL) : %u == %u => %i
  ",
  			   write_group, use_dm, *bit_chk,
  			   param->write_correct_mask,
  			   *bit_chk == param->write_correct_mask);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1163
1164
  		return *bit_chk == param->write_correct_mask;
  	} else {
b9452ea09   Marek Vasut   ddr: altera: Clea...
1165
1166
1167
1168
  		debug_cond(DLEVEL == 2,
  			   "write_test(%u,%u,ONE) : %u != %i => %i
  ",
  			   write_group, use_dm, *bit_chk, 0, *bit_chk != 0);
ad64769ce   Marek Vasut   ddr: altera: Clea...
1169
1170
1171
  		return *bit_chk != 0x00;
  	}
  }
d844c7d43   Marek Vasut   ddr: altera: Clea...
1172
1173
1174
1175
1176
1177
1178
1179
  /**
   * rw_mgr_mem_calibrate_read_test_patterns() - Read back test patterns
   * @rank_bgn:	Rank number
   * @group:	Read/Write Group
   * @all_ranks:	Test all ranks
   *
   * Performs a guaranteed read on the patterns we are going to use during a
   * read test to ensure memory works.
3da428595   Dinh Nguyen   driver/ddr/altera...
1180
   */
d844c7d43   Marek Vasut   ddr: altera: Clea...
1181
1182
1183
  static int
  rw_mgr_mem_calibrate_read_test_patterns(const u32 rank_bgn, const u32 group,
  					const u32 all_ranks)
3da428595   Dinh Nguyen   driver/ddr/altera...
1184
  {
d844c7d43   Marek Vasut   ddr: altera: Clea...
1185
1186
1187
  	const u32 addr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
  			 RW_MGR_RUN_SINGLE_GROUP_OFFSET;
  	const u32 addr_offset =
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1188
  			 (group * rwcfg->mem_virtual_groups_per_read_dqs) << 2;
d844c7d43   Marek Vasut   ddr: altera: Clea...
1189
  	const u32 rank_end = all_ranks ?
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1190
  				rwcfg->mem_number_of_ranks :
d844c7d43   Marek Vasut   ddr: altera: Clea...
1191
  				(rank_bgn + NUM_RANKS_PER_SHADOW_REG);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1192
1193
  	const u32 shift_ratio = rwcfg->mem_dq_per_read_dqs /
  				rwcfg->mem_virtual_groups_per_read_dqs;
d844c7d43   Marek Vasut   ddr: altera: Clea...
1194
  	const u32 correct_mask_vg = param->read_correct_mask_vg;
3da428595   Dinh Nguyen   driver/ddr/altera...
1195

d844c7d43   Marek Vasut   ddr: altera: Clea...
1196
1197
1198
1199
1200
  	u32 tmp_bit_chk, base_rw_mgr, bit_chk;
  	int vg, r;
  	int ret = 0;
  
  	bit_chk = param->read_correct_mask;
3da428595   Dinh Nguyen   driver/ddr/altera...
1201
1202
  
  	for (r = rank_bgn; r < rank_end; r++) {
d844c7d43   Marek Vasut   ddr: altera: Clea...
1203
  		/* Set rank */
3da428595   Dinh Nguyen   driver/ddr/altera...
1204
1205
1206
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
  
  		/* Load up a constant bursts of read commands */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1207
  		writel(0x20, &sdr_rw_load_mgr_regs->load_cntr0);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1208
  		writel(rwcfg->guaranteed_read,
139823ecb   Marek Vasut   ddr: altera: sequ...
1209
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1210

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1211
  		writel(0x20, &sdr_rw_load_mgr_regs->load_cntr1);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1212
  		writel(rwcfg->guaranteed_read_cont,
139823ecb   Marek Vasut   ddr: altera: sequ...
1213
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1214
1215
  
  		tmp_bit_chk = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1216
  		for (vg = rwcfg->mem_virtual_groups_per_read_dqs - 1;
d844c7d43   Marek Vasut   ddr: altera: Clea...
1217
1218
  		     vg >= 0; vg--) {
  			/* Reset the FIFOs to get pointers to known state. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1219
1220
1221
  			writel(0, &phy_mgr_cmd->fifo_reset);
  			writel(0, SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				  RW_MGR_RESET_READ_DATAPATH_OFFSET);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1222
  			writel(rwcfg->guaranteed_read,
d844c7d43   Marek Vasut   ddr: altera: Clea...
1223
  			       addr + addr_offset + (vg << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
1224

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1225
  			base_rw_mgr = readl(SDR_PHYGRP_RWMGRGRP_ADDRESS);
d844c7d43   Marek Vasut   ddr: altera: Clea...
1226
1227
  			tmp_bit_chk <<= shift_ratio;
  			tmp_bit_chk |= correct_mask_vg & ~base_rw_mgr;
3da428595   Dinh Nguyen   driver/ddr/altera...
1228
  		}
d844c7d43   Marek Vasut   ddr: altera: Clea...
1229
1230
  
  		bit_chk &= tmp_bit_chk;
3da428595   Dinh Nguyen   driver/ddr/altera...
1231
  	}
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1232
  	writel(rwcfg->clear_dqs_enable, addr + (group << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
1233
1234
  
  	set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
d844c7d43   Marek Vasut   ddr: altera: Clea...
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
  
  	if (bit_chk != param->read_correct_mask)
  		ret = -EIO;
  
  	debug_cond(DLEVEL == 1,
  		   "%s:%d test_load_patterns(%u,ALL) => (%u == %u) => %i
  ",
  		   __func__, __LINE__, group, bit_chk,
  		   param->read_correct_mask, ret);
  
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1246
  }
b6cb7f9ed   Marek Vasut   ddr: altera: Mino...
1247
1248
1249
1250
1251
1252
1253
1254
1255
  /**
   * rw_mgr_mem_calibrate_read_load_patterns() - Load up the patterns for read test
   * @rank_bgn:	Rank number
   * @all_ranks:	Test all ranks
   *
   * Load up the patterns we are going to use during a read test.
   */
  static void rw_mgr_mem_calibrate_read_load_patterns(const u32 rank_bgn,
  						    const int all_ranks)
3da428595   Dinh Nguyen   driver/ddr/altera...
1256
  {
b6cb7f9ed   Marek Vasut   ddr: altera: Mino...
1257
  	const u32 rank_end = all_ranks ?
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1258
  			rwcfg->mem_number_of_ranks :
b6cb7f9ed   Marek Vasut   ddr: altera: Mino...
1259
1260
  			(rank_bgn + NUM_RANKS_PER_SHADOW_REG);
  	u32 r;
3da428595   Dinh Nguyen   driver/ddr/altera...
1261
1262
1263
  
  	debug("%s:%d
  ", __func__, __LINE__);
b6cb7f9ed   Marek Vasut   ddr: altera: Mino...
1264

3da428595   Dinh Nguyen   driver/ddr/altera...
1265
  	for (r = rank_bgn; r < rank_end; r++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
1266
1267
1268
1269
  		/* set rank */
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
  
  		/* Load up a constant bursts */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1270
  		writel(0x20, &sdr_rw_load_mgr_regs->load_cntr0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1271

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1272
  		writel(rwcfg->guaranteed_write_wait0,
139823ecb   Marek Vasut   ddr: altera: sequ...
1273
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1274

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1275
  		writel(0x20, &sdr_rw_load_mgr_regs->load_cntr1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1276

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1277
  		writel(rwcfg->guaranteed_write_wait1,
139823ecb   Marek Vasut   ddr: altera: sequ...
1278
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1279

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1280
  		writel(0x04, &sdr_rw_load_mgr_regs->load_cntr2);
3da428595   Dinh Nguyen   driver/ddr/altera...
1281

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1282
  		writel(rwcfg->guaranteed_write_wait2,
139823ecb   Marek Vasut   ddr: altera: sequ...
1283
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
3da428595   Dinh Nguyen   driver/ddr/altera...
1284

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1285
  		writel(0x04, &sdr_rw_load_mgr_regs->load_cntr3);
3da428595   Dinh Nguyen   driver/ddr/altera...
1286

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1287
  		writel(rwcfg->guaranteed_write_wait3,
139823ecb   Marek Vasut   ddr: altera: sequ...
1288
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
3da428595   Dinh Nguyen   driver/ddr/altera...
1289

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1290
  		writel(rwcfg->guaranteed_write, SDR_PHYGRP_RWMGRGRP_ADDRESS |
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1291
  						RW_MGR_RUN_SINGLE_GROUP_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
1292
1293
1294
1295
  	}
  
  	set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
  }
783fcf59b   Marek Vasut   ddr: altera: Clea...
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
  /**
   * rw_mgr_mem_calibrate_read_test() - Perform READ test on single rank
   * @rank_bgn:		Rank number
   * @group:		Read/Write group
   * @num_tries:		Number of retries of the test
   * @all_correct:	All bits must be correct in the mask
   * @bit_chk:		Resulting bit mask after the test
   * @all_groups:		Test all R/W groups
   * @all_ranks:		Test all ranks
   *
   * Try a read and see if it returns correct data back. Test has dummy reads
   * inserted into the mix used to align DQS enable. Test has more thorough
   * checks than the regular read test.
3da428595   Dinh Nguyen   driver/ddr/altera...
1309
   */
3cb8bf3fc   Marek Vasut   ddr: altera: Clea...
1310
1311
1312
1313
1314
  static int
  rw_mgr_mem_calibrate_read_test(const u32 rank_bgn, const u32 group,
  			       const u32 num_tries, const u32 all_correct,
  			       u32 *bit_chk,
  			       const u32 all_groups, const u32 all_ranks)
3da428595   Dinh Nguyen   driver/ddr/altera...
1315
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1316
  	const u32 rank_end = all_ranks ? rwcfg->mem_number_of_ranks :
3da428595   Dinh Nguyen   driver/ddr/altera...
1317
  		(rank_bgn + NUM_RANKS_PER_SHADOW_REG);
3cb8bf3fc   Marek Vasut   ddr: altera: Clea...
1318
1319
  	const u32 quick_read_mode =
  		((STATIC_CALIB_STEPS & CALIB_SKIP_DELAY_SWEEPS) &&
96fd4362c   Marek Vasut   ddr: altera: sequ...
1320
  		 misccfg->enable_super_quick_calibration);
3cb8bf3fc   Marek Vasut   ddr: altera: Clea...
1321
1322
1323
1324
  	u32 correct_mask_vg = param->read_correct_mask_vg;
  	u32 tmp_bit_chk;
  	u32 base_rw_mgr;
  	u32 addr;
3da428595   Dinh Nguyen   driver/ddr/altera...
1325

3cb8bf3fc   Marek Vasut   ddr: altera: Clea...
1326
  	int r, vg, ret;
3853d65e2   Marek Vasut   ddr: altera: Clea...
1327

3cb8bf3fc   Marek Vasut   ddr: altera: Clea...
1328
  	*bit_chk = param->read_correct_mask;
3da428595   Dinh Nguyen   driver/ddr/altera...
1329
1330
  
  	for (r = rank_bgn; r < rank_end; r++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
1331
1332
  		/* set rank */
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_READ_WRITE);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1333
  		writel(0x10, &sdr_rw_load_mgr_regs->load_cntr1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1334

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1335
  		writel(rwcfg->read_b2b_wait1,
139823ecb   Marek Vasut   ddr: altera: sequ...
1336
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1337

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1338
  		writel(0x10, &sdr_rw_load_mgr_regs->load_cntr2);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1339
  		writel(rwcfg->read_b2b_wait2,
139823ecb   Marek Vasut   ddr: altera: sequ...
1340
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add2);
3da428595   Dinh Nguyen   driver/ddr/altera...
1341

3da428595   Dinh Nguyen   driver/ddr/altera...
1342
  		if (quick_read_mode)
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1343
  			writel(0x1, &sdr_rw_load_mgr_regs->load_cntr0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1344
1345
  			/* need at least two (1+1) reads to capture failures */
  		else if (all_groups)
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1346
  			writel(0x06, &sdr_rw_load_mgr_regs->load_cntr0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1347
  		else
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1348
  			writel(0x32, &sdr_rw_load_mgr_regs->load_cntr0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1349

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1350
  		writel(rwcfg->read_b2b,
139823ecb   Marek Vasut   ddr: altera: sequ...
1351
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1352
  		if (all_groups)
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1353
1354
  			writel(rwcfg->mem_if_read_dqs_width *
  			       rwcfg->mem_virtual_groups_per_read_dqs - 1,
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1355
  			       &sdr_rw_load_mgr_regs->load_cntr3);
3da428595   Dinh Nguyen   driver/ddr/altera...
1356
  		else
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1357
  			writel(0x0, &sdr_rw_load_mgr_regs->load_cntr3);
3da428595   Dinh Nguyen   driver/ddr/altera...
1358

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1359
  		writel(rwcfg->read_b2b,
139823ecb   Marek Vasut   ddr: altera: sequ...
1360
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add3);
3da428595   Dinh Nguyen   driver/ddr/altera...
1361
1362
  
  		tmp_bit_chk = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1363
  		for (vg = rwcfg->mem_virtual_groups_per_read_dqs - 1; vg >= 0;
7ce23bb6e   Marek Vasut   ddr: altera: Clea...
1364
  		     vg--) {
ba522c769   Marek Vasut   ddr: altera: Clea...
1365
  			/* Reset the FIFOs to get pointers to known state. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1366
1367
1368
  			writel(0, &phy_mgr_cmd->fifo_reset);
  			writel(0, SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				  RW_MGR_RESET_READ_DATAPATH_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
1369

ba522c769   Marek Vasut   ddr: altera: Clea...
1370
1371
1372
1373
1374
1375
1376
  			if (all_groups) {
  				addr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				       RW_MGR_RUN_ALL_GROUPS_OFFSET;
  			} else {
  				addr = SDR_PHYGRP_RWMGRGRP_ADDRESS |
  				       RW_MGR_RUN_SINGLE_GROUP_OFFSET;
  			}
c4815f767   Marek Vasut   ddr: altera: Pluc...
1377

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1378
  			writel(rwcfg->read_b2b, addr +
139823ecb   Marek Vasut   ddr: altera: sequ...
1379
1380
1381
  			       ((group *
  				 rwcfg->mem_virtual_groups_per_read_dqs +
  				 vg) << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
1382

1273dd9ea   Marek Vasut   ddr: altera: Mass...
1383
  			base_rw_mgr = readl(SDR_PHYGRP_RWMGRGRP_ADDRESS);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1384
1385
  			tmp_bit_chk <<= rwcfg->mem_dq_per_read_dqs /
  					rwcfg->mem_virtual_groups_per_read_dqs;
ba522c769   Marek Vasut   ddr: altera: Clea...
1386
  			tmp_bit_chk |= correct_mask_vg & ~(base_rw_mgr);
3da428595   Dinh Nguyen   driver/ddr/altera...
1387
  		}
7ce23bb6e   Marek Vasut   ddr: altera: Clea...
1388

3da428595   Dinh Nguyen   driver/ddr/altera...
1389
1390
  		*bit_chk &= tmp_bit_chk;
  	}
c4815f767   Marek Vasut   ddr: altera: Pluc...
1391
  	addr = SDR_PHYGRP_RWMGRGRP_ADDRESS | RW_MGR_RUN_SINGLE_GROUP_OFFSET;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1392
  	writel(rwcfg->clear_dqs_enable, addr + (group << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
1393

3853d65e2   Marek Vasut   ddr: altera: Clea...
1394
  	set_rank_and_odt_mask(0, RW_MGR_ODT_MODE_OFF);
3da428595   Dinh Nguyen   driver/ddr/altera...
1395
  	if (all_correct) {
3853d65e2   Marek Vasut   ddr: altera: Clea...
1396
1397
1398
1399
1400
1401
  		ret = (*bit_chk == param->read_correct_mask);
  		debug_cond(DLEVEL == 2,
  			   "%s:%d read_test(%u,ALL,%u) => (%u == %u) => %i
  ",
  			   __func__, __LINE__, group, all_groups, *bit_chk,
  			   param->read_correct_mask, ret);
3da428595   Dinh Nguyen   driver/ddr/altera...
1402
  	} else	{
3853d65e2   Marek Vasut   ddr: altera: Clea...
1403
1404
1405
1406
1407
1408
  		ret = (*bit_chk != 0x00);
  		debug_cond(DLEVEL == 2,
  			   "%s:%d read_test(%u,ONE,%u) => (%u != %u) => %i
  ",
  			   __func__, __LINE__, group, all_groups, *bit_chk,
  			   0, ret);
3da428595   Dinh Nguyen   driver/ddr/altera...
1409
  	}
3853d65e2   Marek Vasut   ddr: altera: Clea...
1410
1411
  
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1412
  }
96df60364   Marek Vasut   ddr: altera: Clea...
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
  /**
   * rw_mgr_mem_calibrate_read_test_all_ranks() - Perform READ test on all ranks
   * @grp:		Read/Write group
   * @num_tries:		Number of retries of the test
   * @all_correct:	All bits must be correct in the mask
   * @all_groups:		Test all R/W groups
   *
   * Perform a READ test across all memory ranks.
   */
  static int
  rw_mgr_mem_calibrate_read_test_all_ranks(const u32 grp, const u32 num_tries,
  					 const u32 all_correct,
  					 const u32 all_groups)
3da428595   Dinh Nguyen   driver/ddr/altera...
1426
  {
96df60364   Marek Vasut   ddr: altera: Clea...
1427
1428
1429
  	u32 bit_chk;
  	return rw_mgr_mem_calibrate_read_test(0, grp, num_tries, all_correct,
  					      &bit_chk, all_groups, 1);
3da428595   Dinh Nguyen   driver/ddr/altera...
1430
  }
60bb8a8a7   Marek Vasut   ddr: altera: Clea...
1431
1432
1433
  /**
   * rw_mgr_incr_vfifo() - Increase VFIFO value
   * @grp:	Read/Write group
60bb8a8a7   Marek Vasut   ddr: altera: Clea...
1434
1435
1436
   *
   * Increase VFIFO value.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1437
  static void rw_mgr_incr_vfifo(const u32 grp)
3da428595   Dinh Nguyen   driver/ddr/altera...
1438
  {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1439
  	writel(grp, &phy_mgr_cmd->inc_vfifo_hard_phy);
3da428595   Dinh Nguyen   driver/ddr/altera...
1440
  }
60bb8a8a7   Marek Vasut   ddr: altera: Clea...
1441
1442
1443
  /**
   * rw_mgr_decr_vfifo() - Decrease VFIFO value
   * @grp:	Read/Write group
60bb8a8a7   Marek Vasut   ddr: altera: Clea...
1444
1445
1446
   *
   * Decrease VFIFO value.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1447
  static void rw_mgr_decr_vfifo(const u32 grp)
3da428595   Dinh Nguyen   driver/ddr/altera...
1448
  {
60bb8a8a7   Marek Vasut   ddr: altera: Clea...
1449
  	u32 i;
3da428595   Dinh Nguyen   driver/ddr/altera...
1450

96fd4362c   Marek Vasut   ddr: altera: sequ...
1451
  	for (i = 0; i < misccfg->read_valid_fifo_size - 1; i++)
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1452
  		rw_mgr_incr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1453
  }
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1454
1455
1456
1457
1458
1459
1460
  /**
   * find_vfifo_failing_read() - Push VFIFO to get a failing read
   * @grp:	Read/Write group
   *
   * Push VFIFO until a failing read happens.
   */
  static int find_vfifo_failing_read(const u32 grp)
3da428595   Dinh Nguyen   driver/ddr/altera...
1461
  {
96df60364   Marek Vasut   ddr: altera: Clea...
1462
  	u32 v, ret, fail_cnt = 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
1463

96fd4362c   Marek Vasut   ddr: altera: sequ...
1464
  	for (v = 0; v < misccfg->read_valid_fifo_size; v++) {
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1465
1466
  		debug_cond(DLEVEL == 2, "%s:%d: vfifo %u
  ",
3da428595   Dinh Nguyen   driver/ddr/altera...
1467
  			   __func__, __LINE__, v);
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1468
  		ret = rw_mgr_mem_calibrate_read_test_all_ranks(grp, 1,
96df60364   Marek Vasut   ddr: altera: Clea...
1469
  						PASS_ONE_BIT, 0);
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1470
  		if (!ret) {
3da428595   Dinh Nguyen   driver/ddr/altera...
1471
1472
1473
  			fail_cnt++;
  
  			if (fail_cnt == 2)
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1474
  				return v;
3da428595   Dinh Nguyen   driver/ddr/altera...
1475
  		}
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1476
  		/* Fiddle with FIFO. */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1477
  		rw_mgr_incr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1478
  	}
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1479
1480
1481
1482
  	/* No failing read found! Something must have gone wrong. */
  	debug_cond(DLEVEL == 2, "%s:%d: vfifo failed
  ", __func__, __LINE__);
  	return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
1483
  }
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1484
  /**
52e8f217f   Marek Vasut   ddr: altera: Clea...
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
   * sdr_find_phase_delay() - Find DQS enable phase or delay
   * @working:	If 1, look for working phase/delay, if 0, look for non-working
   * @delay:	If 1, look for delay, if 0, look for phase
   * @grp:	Read/Write group
   * @work:	Working window position
   * @work_inc:	Working window increment
   * @pd:		DQS Phase/Delay Iterator
   *
   * Find working or non-working DQS enable phase setting.
   */
  static int sdr_find_phase_delay(int working, int delay, const u32 grp,
  				u32 *work, const u32 work_inc, u32 *pd)
  {
139823ecb   Marek Vasut   ddr: altera: sequ...
1498
1499
  	const u32 max = delay ? iocfg->dqs_en_delay_max :
  				iocfg->dqs_en_phase_max;
96df60364   Marek Vasut   ddr: altera: Clea...
1500
  	u32 ret;
52e8f217f   Marek Vasut   ddr: altera: Clea...
1501
1502
1503
1504
1505
1506
1507
1508
  
  	for (; *pd <= max; (*pd)++) {
  		if (delay)
  			scc_mgr_set_dqs_en_delay_all_ranks(grp, *pd);
  		else
  			scc_mgr_set_dqs_en_phase_all_ranks(grp, *pd);
  
  		ret = rw_mgr_mem_calibrate_read_test_all_ranks(grp, 1,
96df60364   Marek Vasut   ddr: altera: Clea...
1509
  					PASS_ONE_BIT, 0);
52e8f217f   Marek Vasut   ddr: altera: Clea...
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
  		if (!working)
  			ret = !ret;
  
  		if (ret)
  			return 0;
  
  		if (work)
  			*work += work_inc;
  	}
  
  	return -EINVAL;
  }
  /**
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1523
1524
1525
   * sdr_find_phase() - Find DQS enable phase
   * @working:	If 1, look for working phase, if 0, look for non-working phase
   * @grp:	Read/Write group
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1526
1527
1528
   * @work:	Working window position
   * @i:		Iterator
   * @p:		DQS Phase Iterator
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1529
1530
1531
   *
   * Find working or non-working DQS enable phase setting.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1532
  static int sdr_find_phase(int working, const u32 grp, u32 *work,
86a39dc76   Marek Vasut   ddr: altera: Clea...
1533
  			  u32 *i, u32 *p)
3da428595   Dinh Nguyen   driver/ddr/altera...
1534
  {
96fd4362c   Marek Vasut   ddr: altera: sequ...
1535
  	const u32 end = misccfg->read_valid_fifo_size + (working ? 0 : 1);
52e8f217f   Marek Vasut   ddr: altera: Clea...
1536
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1537

192d6f9fa   Marek Vasut   ddr: altera: Clea...
1538
1539
1540
  	for (; *i < end; (*i)++) {
  		if (working)
  			*p = 0;
52e8f217f   Marek Vasut   ddr: altera: Clea...
1541
  		ret = sdr_find_phase_delay(working, 0, grp, work,
160695d88   Marek Vasut   ddr: altera: sequ...
1542
  					   iocfg->delay_per_opa_tap, p);
52e8f217f   Marek Vasut   ddr: altera: Clea...
1543
1544
  		if (!ret)
  			return 0;
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1545

160695d88   Marek Vasut   ddr: altera: sequ...
1546
  		if (*p > iocfg->dqs_en_phase_max) {
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1547
  			/* Fiddle with FIFO. */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1548
  			rw_mgr_incr_vfifo(grp);
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1549
1550
  			if (!working)
  				*p = 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
1551
  		}
3da428595   Dinh Nguyen   driver/ddr/altera...
1552
  	}
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1553
1554
  	return -EINVAL;
  }
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1555
1556
1557
1558
  /**
   * sdr_working_phase() - Find working DQS enable phase
   * @grp:	Read/Write group
   * @work_bgn:	Working window start position
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1559
1560
1561
1562
1563
1564
   * @d:		dtaps output value
   * @p:		DQS Phase Iterator
   * @i:		Iterator
   *
   * Find working DQS enable phase setting.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1565
  static int sdr_working_phase(const u32 grp, u32 *work_bgn, u32 *d,
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1566
  			     u32 *p, u32 *i)
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1567
  {
160695d88   Marek Vasut   ddr: altera: sequ...
1568
1569
  	const u32 dtaps_per_ptap = iocfg->delay_per_opa_tap /
  				   iocfg->delay_per_dqs_en_dchain_tap;
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1570
1571
1572
1573
1574
1575
1576
  	int ret;
  
  	*work_bgn = 0;
  
  	for (*d = 0; *d <= dtaps_per_ptap; (*d)++) {
  		*i = 0;
  		scc_mgr_set_dqs_en_delay_all_ranks(grp, *d);
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1577
  		ret = sdr_find_phase(1, grp, work_bgn, i, p);
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1578
1579
  		if (!ret)
  			return 0;
160695d88   Marek Vasut   ddr: altera: sequ...
1580
  		*work_bgn += iocfg->delay_per_dqs_en_dchain_tap;
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1581
  	}
38ed69223   Marek Vasut   ddr: altera: Clea...
1582
  	/* Cannot find working solution */
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1583
1584
1585
1586
  	debug_cond(DLEVEL == 2, "%s:%d find_dqs_en_phase: no vfifo/ptap/dtap
  ",
  		   __func__, __LINE__);
  	return -EINVAL;
3da428595   Dinh Nguyen   driver/ddr/altera...
1587
  }
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1588
1589
1590
1591
  /**
   * sdr_backup_phase() - Find DQS enable backup phase
   * @grp:	Read/Write group
   * @work_bgn:	Working window start position
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1592
1593
1594
1595
   * @p:		DQS Phase Iterator
   *
   * Find DQS enable backup phase setting.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1596
  static void sdr_backup_phase(const u32 grp, u32 *work_bgn, u32 *p)
3da428595   Dinh Nguyen   driver/ddr/altera...
1597
  {
96df60364   Marek Vasut   ddr: altera: Clea...
1598
  	u32 tmp_delay, d;
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1599
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1600
1601
1602
  
  	/* Special case code for backing up a phase */
  	if (*p == 0) {
160695d88   Marek Vasut   ddr: altera: sequ...
1603
  		*p = iocfg->dqs_en_phase_max;
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1604
  		rw_mgr_decr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1605
1606
1607
  	} else {
  		(*p)--;
  	}
160695d88   Marek Vasut   ddr: altera: sequ...
1608
  	tmp_delay = *work_bgn - iocfg->delay_per_opa_tap;
521fe39c5   Marek Vasut   ddr: altera: Clea...
1609
  	scc_mgr_set_dqs_en_phase_all_ranks(grp, *p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1610

139823ecb   Marek Vasut   ddr: altera: sequ...
1611
1612
  	for (d = 0; d <= iocfg->dqs_en_delay_max && tmp_delay < *work_bgn;
  	     d++) {
49891df66   Marek Vasut   ddr: altera: Clea...
1613
  		scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
3da428595   Dinh Nguyen   driver/ddr/altera...
1614

4c5e584b2   Marek Vasut   ddr: altera: Clea...
1615
  		ret = rw_mgr_mem_calibrate_read_test_all_ranks(grp, 1,
96df60364   Marek Vasut   ddr: altera: Clea...
1616
  					PASS_ONE_BIT, 0);
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1617
  		if (ret) {
3da428595   Dinh Nguyen   driver/ddr/altera...
1618
1619
1620
  			*work_bgn = tmp_delay;
  			break;
  		}
49891df66   Marek Vasut   ddr: altera: Clea...
1621

160695d88   Marek Vasut   ddr: altera: sequ...
1622
  		tmp_delay += iocfg->delay_per_dqs_en_dchain_tap;
3da428595   Dinh Nguyen   driver/ddr/altera...
1623
  	}
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1624
  	/* Restore VFIFO to old state before we decremented it (if needed). */
3da428595   Dinh Nguyen   driver/ddr/altera...
1625
  	(*p)++;
160695d88   Marek Vasut   ddr: altera: sequ...
1626
  	if (*p > iocfg->dqs_en_phase_max) {
3da428595   Dinh Nguyen   driver/ddr/altera...
1627
  		*p = 0;
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1628
  		rw_mgr_incr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1629
  	}
521fe39c5   Marek Vasut   ddr: altera: Clea...
1630
  	scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
1631
  }
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1632
1633
1634
1635
  /**
   * sdr_nonworking_phase() - Find non-working DQS enable phase
   * @grp:	Read/Write group
   * @work_end:	Working window end position
4c5e584b2   Marek Vasut   ddr: altera: Clea...
1636
1637
1638
1639
1640
   * @p:		DQS Phase Iterator
   * @i:		Iterator
   *
   * Find non-working DQS enable phase setting.
   */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1641
  static int sdr_nonworking_phase(const u32 grp, u32 *work_end, u32 *p, u32 *i)
3da428595   Dinh Nguyen   driver/ddr/altera...
1642
  {
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1643
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1644
1645
  
  	(*p)++;
160695d88   Marek Vasut   ddr: altera: sequ...
1646
1647
  	*work_end += iocfg->delay_per_opa_tap;
  	if (*p > iocfg->dqs_en_phase_max) {
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1648
  		/* Fiddle with FIFO. */
3da428595   Dinh Nguyen   driver/ddr/altera...
1649
  		*p = 0;
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1650
  		rw_mgr_incr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1651
  	}
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1652
  	ret = sdr_find_phase(0, grp, work_end, i, p);
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1653
1654
1655
1656
1657
  	if (ret) {
  		/* Cannot see edge of failing read. */
  		debug_cond(DLEVEL == 2, "%s:%d: end: failed
  ",
  			   __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
1658
  	}
192d6f9fa   Marek Vasut   ddr: altera: Clea...
1659
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1660
  }
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1661
1662
1663
1664
1665
  /**
   * sdr_find_window_center() - Find center of the working DQS window.
   * @grp:	Read/Write group
   * @work_bgn:	First working settings
   * @work_end:	Last working settings
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1666
1667
1668
1669
   *
   * Find center of the working DQS enable window.
   */
  static int sdr_find_window_center(const u32 grp, const u32 work_bgn,
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1670
  				  const u32 work_end)
3da428595   Dinh Nguyen   driver/ddr/altera...
1671
  {
96df60364   Marek Vasut   ddr: altera: Clea...
1672
  	u32 work_mid;
3da428595   Dinh Nguyen   driver/ddr/altera...
1673
  	int tmp_delay = 0;
28fd242a1   Marek Vasut   ddr: altera: Clea...
1674
  	int i, p, d;
3da428595   Dinh Nguyen   driver/ddr/altera...
1675

28fd242a1   Marek Vasut   ddr: altera: Clea...
1676
  	work_mid = (work_bgn + work_end) / 2;
3da428595   Dinh Nguyen   driver/ddr/altera...
1677
1678
1679
  
  	debug_cond(DLEVEL == 2, "work_bgn=%d work_end=%d work_mid=%d
  ",
28fd242a1   Marek Vasut   ddr: altera: Clea...
1680
  		   work_bgn, work_end, work_mid);
3da428595   Dinh Nguyen   driver/ddr/altera...
1681
  	/* Get the middle delay to be less than a VFIFO delay */
160695d88   Marek Vasut   ddr: altera: sequ...
1682
  	tmp_delay = (iocfg->dqs_en_phase_max + 1) * iocfg->delay_per_opa_tap;
28fd242a1   Marek Vasut   ddr: altera: Clea...
1683

3da428595   Dinh Nguyen   driver/ddr/altera...
1684
1685
  	debug_cond(DLEVEL == 2, "vfifo ptap delay %d
  ", tmp_delay);
cbb0b7e03   Marek Vasut   ddr: altera: Clea...
1686
  	work_mid %= tmp_delay;
28fd242a1   Marek Vasut   ddr: altera: Clea...
1687
1688
  	debug_cond(DLEVEL == 2, "new work_mid %d
  ", work_mid);
3da428595   Dinh Nguyen   driver/ddr/altera...
1689

160695d88   Marek Vasut   ddr: altera: sequ...
1690
1691
1692
1693
  	tmp_delay = rounddown(work_mid, iocfg->delay_per_opa_tap);
  	if (tmp_delay > iocfg->dqs_en_phase_max * iocfg->delay_per_opa_tap)
  		tmp_delay = iocfg->dqs_en_phase_max * iocfg->delay_per_opa_tap;
  	p = tmp_delay / iocfg->delay_per_opa_tap;
cbb0b7e03   Marek Vasut   ddr: altera: Clea...
1694
1695
1696
  
  	debug_cond(DLEVEL == 2, "new p %d, tmp_delay=%d
  ", p, tmp_delay);
139823ecb   Marek Vasut   ddr: altera: sequ...
1697
1698
  	d = DIV_ROUND_UP(work_mid - tmp_delay,
  			 iocfg->delay_per_dqs_en_dchain_tap);
160695d88   Marek Vasut   ddr: altera: sequ...
1699
1700
1701
  	if (d > iocfg->dqs_en_delay_max)
  		d = iocfg->dqs_en_delay_max;
  	tmp_delay += d * iocfg->delay_per_dqs_en_dchain_tap;
28fd242a1   Marek Vasut   ddr: altera: Clea...
1702

28fd242a1   Marek Vasut   ddr: altera: Clea...
1703
1704
  	debug_cond(DLEVEL == 2, "new d %d, tmp_delay=%d
  ", d, tmp_delay);
3da428595   Dinh Nguyen   driver/ddr/altera...
1705

cbb0b7e03   Marek Vasut   ddr: altera: Clea...
1706
  	scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
28fd242a1   Marek Vasut   ddr: altera: Clea...
1707
  	scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
3da428595   Dinh Nguyen   driver/ddr/altera...
1708
1709
1710
1711
1712
  
  	/*
  	 * push vfifo until we can successfully calibrate. We can do this
  	 * because the largest possible margin in 1 VFIFO cycle.
  	 */
96fd4362c   Marek Vasut   ddr: altera: sequ...
1713
  	for (i = 0; i < misccfg->read_valid_fifo_size; i++) {
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1714
1715
  		debug_cond(DLEVEL == 2, "find_dqs_en_phase: center
  ");
28fd242a1   Marek Vasut   ddr: altera: Clea...
1716
  		if (rw_mgr_mem_calibrate_read_test_all_ranks(grp, 1,
3da428595   Dinh Nguyen   driver/ddr/altera...
1717
  							     PASS_ONE_BIT,
96df60364   Marek Vasut   ddr: altera: Clea...
1718
  							     0)) {
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1719
  			debug_cond(DLEVEL == 2,
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1720
1721
1722
  				   "%s:%d center: found: ptap=%u dtap=%u
  ",
  				   __func__, __LINE__, p, d);
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1723
  			return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
1724
  		}
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1725
  		/* Fiddle with FIFO. */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1726
  		rw_mgr_incr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1727
  	}
0a13a0fb7   Marek Vasut   ddr: altera: Clea...
1728
1729
1730
1731
  	debug_cond(DLEVEL == 2, "%s:%d center: failed.
  ",
  		   __func__, __LINE__);
  	return -EINVAL;
3da428595   Dinh Nguyen   driver/ddr/altera...
1732
  }
33756893a   Marek Vasut   ddr: altera: Clea...
1733
1734
1735
1736
1737
1738
  /**
   * rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase() - Find a good DQS enable to use
   * @grp:	Read/Write Group
   *
   * Find a good DQS enable to use.
   */
914546e7f   Marek Vasut   ddr: altera: Clea...
1739
  static int rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(const u32 grp)
3da428595   Dinh Nguyen   driver/ddr/altera...
1740
  {
5735540fd   Marek Vasut   ddr: altera: Clea...
1741
1742
1743
  	u32 d, p, i;
  	u32 dtaps_per_ptap;
  	u32 work_bgn, work_end;
35e47b713   Marek Vasut   ddr: altera: Repa...
1744
  	u32 found_passing_read, found_failing_read = 0, initial_failing_dtap;
5735540fd   Marek Vasut   ddr: altera: Clea...
1745
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1746
1747
1748
1749
1750
1751
1752
1753
  
  	debug("%s:%d %u
  ", __func__, __LINE__, grp);
  
  	reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
  
  	scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
  	scc_mgr_set_dqs_en_phase_all_ranks(grp, 0);
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1754
  	/* Step 0: Determine number of delay taps for each phase tap. */
139823ecb   Marek Vasut   ddr: altera: sequ...
1755
1756
  	dtaps_per_ptap = iocfg->delay_per_opa_tap /
  			 iocfg->delay_per_dqs_en_dchain_tap;
3da428595   Dinh Nguyen   driver/ddr/altera...
1757

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1758
  	/* Step 1: First push vfifo until we get a failing read. */
d145ca9fc   Marek Vasut   ddr: altera: Clea...
1759
  	find_vfifo_failing_read(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1760

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1761
  	/* Step 2: Find first working phase, increment in ptaps. */
3da428595   Dinh Nguyen   driver/ddr/altera...
1762
  	work_bgn = 0;
914546e7f   Marek Vasut   ddr: altera: Clea...
1763
1764
1765
  	ret = sdr_working_phase(grp, &work_bgn, &d, &p, &i);
  	if (ret)
  		return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1766
1767
1768
1769
  
  	work_end = work_bgn;
  
  	/*
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1770
1771
  	 * If d is 0 then the working window covers a phase tap and we can
  	 * follow the old procedure. Otherwise, we've found the beginning
3da428595   Dinh Nguyen   driver/ddr/altera...
1772
1773
1774
  	 * and we need to increment the dtaps until we find the end.
  	 */
  	if (d == 0) {
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1775
1776
1777
1778
  		/*
  		 * Step 3a: If we have room, back off by one and
  		 *          increment in dtaps.
  		 */
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1779
  		sdr_backup_phase(grp, &work_bgn, &p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1780

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1781
1782
1783
1784
  		/*
  		 * Step 4a: go forward from working phase to non working
  		 * phase, increment in ptaps.
  		 */
914546e7f   Marek Vasut   ddr: altera: Clea...
1785
1786
1787
  		ret = sdr_nonworking_phase(grp, &work_end, &p, &i);
  		if (ret)
  			return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1788

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1789
  		/* Step 5a: Back off one from last, increment in dtaps. */
3da428595   Dinh Nguyen   driver/ddr/altera...
1790
1791
1792
  
  		/* Special case code for backing up a phase */
  		if (p == 0) {
160695d88   Marek Vasut   ddr: altera: sequ...
1793
  			p = iocfg->dqs_en_phase_max;
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1794
  			rw_mgr_decr_vfifo(grp);
3da428595   Dinh Nguyen   driver/ddr/altera...
1795
1796
1797
  		} else {
  			p = p - 1;
  		}
160695d88   Marek Vasut   ddr: altera: sequ...
1798
  		work_end -= iocfg->delay_per_opa_tap;
3da428595   Dinh Nguyen   driver/ddr/altera...
1799
  		scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1800
  		d = 0;
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1801
1802
1803
  		debug_cond(DLEVEL == 2, "%s:%d p: ptap=%u
  ",
  			   __func__, __LINE__, p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1804
  	}
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1805
  	/* The dtap increment to find the failing edge is done here. */
52e8f217f   Marek Vasut   ddr: altera: Clea...
1806
  	sdr_find_phase_delay(0, 1, grp, &work_end,
160695d88   Marek Vasut   ddr: altera: sequ...
1807
  			     iocfg->delay_per_dqs_en_dchain_tap, &d);
3da428595   Dinh Nguyen   driver/ddr/altera...
1808
1809
1810
  
  	/* Go back to working dtap */
  	if (d != 0)
160695d88   Marek Vasut   ddr: altera: sequ...
1811
  		work_end -= iocfg->delay_per_dqs_en_dchain_tap;
3da428595   Dinh Nguyen   driver/ddr/altera...
1812

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1813
1814
1815
1816
  	debug_cond(DLEVEL == 2,
  		   "%s:%d p/d: ptap=%u dtap=%u end=%u
  ",
  		   __func__, __LINE__, p, d - 1, work_end);
3da428595   Dinh Nguyen   driver/ddr/altera...
1817
1818
1819
  
  	if (work_end < work_bgn) {
  		/* nil range */
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1820
1821
1822
  		debug_cond(DLEVEL == 2, "%s:%d end-2: failed
  ",
  			   __func__, __LINE__);
914546e7f   Marek Vasut   ddr: altera: Clea...
1823
  		return -EINVAL;
3da428595   Dinh Nguyen   driver/ddr/altera...
1824
  	}
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1825
1826
  	debug_cond(DLEVEL == 2, "%s:%d found range [%u,%u]
  ",
3da428595   Dinh Nguyen   driver/ddr/altera...
1827
  		   __func__, __LINE__, work_bgn, work_end);
3da428595   Dinh Nguyen   driver/ddr/altera...
1828
  	/*
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1829
1830
1831
  	 * We need to calculate the number of dtaps that equal a ptap.
  	 * To do that we'll back up a ptap and re-find the edge of the
  	 * window using dtaps
3da428595   Dinh Nguyen   driver/ddr/altera...
1832
  	 */
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1833
1834
1835
  	debug_cond(DLEVEL == 2, "%s:%d calculate dtaps_per_ptap for tracking
  ",
  		   __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
1836
1837
1838
  
  	/* Special case code for backing up a phase */
  	if (p == 0) {
160695d88   Marek Vasut   ddr: altera: sequ...
1839
  		p = iocfg->dqs_en_phase_max;
8c887b6ec   Marek Vasut   ddr: altera: Clea...
1840
  		rw_mgr_decr_vfifo(grp);
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1841
1842
1843
  		debug_cond(DLEVEL == 2, "%s:%d backedup cycle/phase: p=%u
  ",
  			   __func__, __LINE__, p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1844
1845
  	} else {
  		p = p - 1;
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1846
1847
  		debug_cond(DLEVEL == 2, "%s:%d backedup phase only: p=%u",
  			   __func__, __LINE__, p);
3da428595   Dinh Nguyen   driver/ddr/altera...
1848
1849
1850
1851
1852
1853
  	}
  
  	scc_mgr_set_dqs_en_phase_all_ranks(grp, p);
  
  	/*
  	 * Increase dtap until we first see a passing read (in case the
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1854
1855
  	 * window is smaller than a ptap), and then a failing read to
  	 * mark the edge of the window again.
3da428595   Dinh Nguyen   driver/ddr/altera...
1856
  	 */
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1857
1858
1859
  	/* Find a passing read. */
  	debug_cond(DLEVEL == 2, "%s:%d find passing read
  ",
3da428595   Dinh Nguyen   driver/ddr/altera...
1860
  		   __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
1861

52e8f217f   Marek Vasut   ddr: altera: Clea...
1862
  	initial_failing_dtap = d;
3da428595   Dinh Nguyen   driver/ddr/altera...
1863

52e8f217f   Marek Vasut   ddr: altera: Clea...
1864
  	found_passing_read = !sdr_find_phase_delay(1, 1, grp, NULL, 0, &d);
3da428595   Dinh Nguyen   driver/ddr/altera...
1865
  	if (found_passing_read) {
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1866
1867
1868
1869
  		/* Find a failing read. */
  		debug_cond(DLEVEL == 2, "%s:%d find failing read
  ",
  			   __func__, __LINE__);
52e8f217f   Marek Vasut   ddr: altera: Clea...
1870
1871
1872
  		d++;
  		found_failing_read = !sdr_find_phase_delay(0, 1, grp, NULL, 0,
  							   &d);
3da428595   Dinh Nguyen   driver/ddr/altera...
1873
  	} else {
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1874
1875
1876
1877
  		debug_cond(DLEVEL == 1,
  			   "%s:%d failed to calculate dtaps per ptap. Fall back on static value
  ",
  			   __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
1878
1879
1880
1881
1882
  	}
  
  	/*
  	 * The dynamically calculated dtaps_per_ptap is only valid if we
  	 * found a passing/failing read. If we didn't, it means d hit the max
160695d88   Marek Vasut   ddr: altera: sequ...
1883
  	 * (iocfg->dqs_en_delay_max). Otherwise, dtaps_per_ptap retains its
3da428595   Dinh Nguyen   driver/ddr/altera...
1884
1885
1886
1887
  	 * statically calculated value.
  	 */
  	if (found_passing_read && found_failing_read)
  		dtaps_per_ptap = d - initial_failing_dtap;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
1888
  	writel(dtaps_per_ptap, &sdr_reg_file->dtaps_per_ptap);
2f3589ca5   Marek Vasut   ddr: altera: Clea...
1889
1890
  	debug_cond(DLEVEL == 2, "%s:%d dtaps_per_ptap=%u - %u = %u",
  		   __func__, __LINE__, d, initial_failing_dtap, dtaps_per_ptap);
3da428595   Dinh Nguyen   driver/ddr/altera...
1891

2f3589ca5   Marek Vasut   ddr: altera: Clea...
1892
  	/* Step 6: Find the centre of the window. */
914546e7f   Marek Vasut   ddr: altera: Clea...
1893
  	ret = sdr_find_window_center(grp, work_bgn, work_end);
3da428595   Dinh Nguyen   driver/ddr/altera...
1894

914546e7f   Marek Vasut   ddr: altera: Clea...
1895
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
1896
  }
c4907898a   Marek Vasut   ddr: altera: Clea...
1897
  /**
901dc36e7   Marek Vasut   ddr: altera: Clea...
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
   * search_stop_check() - Check if the detected edge is valid
   * @write:		Perform read (Stage 2) or write (Stage 3) calibration
   * @d:			DQS delay
   * @rank_bgn:		Rank number
   * @write_group:	Write Group
   * @read_group:		Read Group
   * @bit_chk:		Resulting bit mask after the test
   * @sticky_bit_chk:	Resulting sticky bit mask after the test
   * @use_read_test:	Perform read test
   *
   * Test if the found edge is valid.
   */
  static u32 search_stop_check(const int write, const int d, const int rank_bgn,
  			     const u32 write_group, const u32 read_group,
  			     u32 *bit_chk, u32 *sticky_bit_chk,
  			     const u32 use_read_test)
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1915
1916
  	const u32 ratio = rwcfg->mem_if_read_dqs_width /
  			  rwcfg->mem_if_write_dqs_width;
901dc36e7   Marek Vasut   ddr: altera: Clea...
1917
1918
  	const u32 correct_mask = write ? param->write_correct_mask :
  					 param->read_correct_mask;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1919
1920
  	const u32 per_dqs = write ? rwcfg->mem_dq_per_write_dqs :
  				    rwcfg->mem_dq_per_read_dqs;
901dc36e7   Marek Vasut   ddr: altera: Clea...
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
  	u32 ret;
  	/*
  	 * Stop searching when the read test doesn't pass AND when
  	 * we've seen a passing read on every bit.
  	 */
  	if (write) {			/* WRITE-ONLY */
  		ret = !rw_mgr_mem_calibrate_write_test(rank_bgn, write_group,
  							 0, PASS_ONE_BIT,
  							 bit_chk, 0);
  	} else if (use_read_test) {	/* READ-ONLY */
  		ret = !rw_mgr_mem_calibrate_read_test(rank_bgn, read_group,
  							NUM_READ_PB_TESTS,
  							PASS_ONE_BIT, bit_chk,
  							0, 0);
  	} else {			/* READ-ONLY */
  		rw_mgr_mem_calibrate_write_test(rank_bgn, write_group, 0,
  						PASS_ONE_BIT, bit_chk, 0);
  		*bit_chk = *bit_chk >> (per_dqs *
  			(read_group - (write_group * ratio)));
  		ret = (*bit_chk == 0);
  	}
  	*sticky_bit_chk = *sticky_bit_chk | *bit_chk;
  	ret = ret && (*sticky_bit_chk == correct_mask);
  	debug_cond(DLEVEL == 2,
  		   "%s:%d center(left): dtap=%u => %u == %u && %u",
  		   __func__, __LINE__, d,
  		   *sticky_bit_chk, correct_mask, ret);
  	return ret;
  }
  
  /**
71120773b   Marek Vasut   ddr: altera: Clea...
1952
1953
1954
1955
1956
1957
   * search_left_edge() - Find left edge of DQ/DQS working phase
   * @write:		Perform read (Stage 2) or write (Stage 3) calibration
   * @rank_bgn:		Rank number
   * @write_group:	Write Group
   * @read_group:		Read Group
   * @test_bgn:		Rank number to begin the test
71120773b   Marek Vasut   ddr: altera: Clea...
1958
1959
1960
1961
1962
1963
1964
1965
1966
   * @sticky_bit_chk:	Resulting sticky bit mask after the test
   * @left_edge:		Left edge of the DQ/DQS phase
   * @right_edge:		Right edge of the DQ/DQS phase
   * @use_read_test:	Perform read test
   *
   * Find left edge of DQ/DQS working phase.
   */
  static void search_left_edge(const int write, const int rank_bgn,
  	const u32 write_group, const u32 read_group, const u32 test_bgn,
0c4be198f   Marek Vasut   ddr: altera: Clea...
1967
  	u32 *sticky_bit_chk,
71120773b   Marek Vasut   ddr: altera: Clea...
1968
1969
  	int *left_edge, int *right_edge, const u32 use_read_test)
  {
139823ecb   Marek Vasut   ddr: altera: sequ...
1970
1971
1972
1973
  	const u32 delay_max = write ? iocfg->io_out1_delay_max :
  				      iocfg->io_in_delay_max;
  	const u32 dqs_max = write ? iocfg->io_out1_delay_max :
  				    iocfg->dqs_in_delay_max;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
1974
1975
  	const u32 per_dqs = write ? rwcfg->mem_dq_per_write_dqs :
  				    rwcfg->mem_dq_per_read_dqs;
0c4be198f   Marek Vasut   ddr: altera: Clea...
1976
  	u32 stop, bit_chk;
71120773b   Marek Vasut   ddr: altera: Clea...
1977
1978
1979
1980
1981
1982
1983
1984
1985
  	int i, d;
  
  	for (d = 0; d <= dqs_max; d++) {
  		if (write)
  			scc_mgr_apply_group_dq_out1_delay(d);
  		else
  			scc_mgr_apply_group_dq_in_delay(test_bgn, d);
  
  		writel(0, &sdr_scc_mgr->update);
901dc36e7   Marek Vasut   ddr: altera: Clea...
1986
  		stop = search_stop_check(write, d, rank_bgn, write_group,
0c4be198f   Marek Vasut   ddr: altera: Clea...
1987
  					 read_group, &bit_chk, sticky_bit_chk,
901dc36e7   Marek Vasut   ddr: altera: Clea...
1988
  					 use_read_test);
71120773b   Marek Vasut   ddr: altera: Clea...
1989
1990
1991
1992
1993
  		if (stop == 1)
  			break;
  
  		/* stop != 1 */
  		for (i = 0; i < per_dqs; i++) {
0c4be198f   Marek Vasut   ddr: altera: Clea...
1994
  			if (bit_chk & 1) {
71120773b   Marek Vasut   ddr: altera: Clea...
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
  				/*
  				 * Remember a passing test as
  				 * the left_edge.
  				 */
  				left_edge[i] = d;
  			} else {
  				/*
  				 * If a left edge has not been seen
  				 * yet, then a future passing test
  				 * will mark this edge as the right
  				 * edge.
  				 */
  				if (left_edge[i] == delay_max + 1)
  					right_edge[i] = -(d + 1);
  			}
0c4be198f   Marek Vasut   ddr: altera: Clea...
2010
  			bit_chk >>= 1;
71120773b   Marek Vasut   ddr: altera: Clea...
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
  		}
  	}
  
  	/* Reset DQ delay chains to 0 */
  	if (write)
  		scc_mgr_apply_group_dq_out1_delay(0);
  	else
  		scc_mgr_apply_group_dq_in_delay(test_bgn, 0);
  
  	*sticky_bit_chk = 0;
  	for (i = per_dqs - 1; i >= 0; i--) {
  		debug_cond(DLEVEL == 2,
  			   "%s:%d vfifo_center: left_edge[%u]: %d right_edge[%u]: %d
  ",
  			   __func__, __LINE__, i, left_edge[i],
  			   i, right_edge[i]);
  
  		/*
  		 * Check for cases where we haven't found the left edge,
  		 * which makes our assignment of the the right edge invalid.
  		 * Reset it to the illegal value.
  		 */
  		if ((left_edge[i] == delay_max + 1) &&
  		    (right_edge[i] != delay_max + 1)) {
  			right_edge[i] = delay_max + 1;
  			debug_cond(DLEVEL == 2,
  				   "%s:%d vfifo_center: reset right_edge[%u]: %d
  ",
  				   __func__, __LINE__, i, right_edge[i]);
  		}
  
  		/*
  		 * Reset sticky bit
  		 * READ: except for bits where we have seen both
  		 *       the left and right edge.
  		 * WRITE: except for bits where we have seen the
  		 *        left edge.
  		 */
  		*sticky_bit_chk <<= 1;
  		if (write) {
  			if (left_edge[i] != delay_max + 1)
  				*sticky_bit_chk |= 1;
  		} else {
  			if ((left_edge[i] != delay_max + 1) &&
  			    (right_edge[i] != delay_max + 1))
  				*sticky_bit_chk |= 1;
  		}
  	}
71120773b   Marek Vasut   ddr: altera: Clea...
2059
2060
2061
  }
  
  /**
c4907898a   Marek Vasut   ddr: altera: Clea...
2062
2063
2064
2065
2066
2067
2068
   * search_right_edge() - Find right edge of DQ/DQS working phase
   * @write:		Perform read (Stage 2) or write (Stage 3) calibration
   * @rank_bgn:		Rank number
   * @write_group:	Write Group
   * @read_group:		Read Group
   * @start_dqs:		DQS start phase
   * @start_dqs_en:	DQS enable start phase
c4907898a   Marek Vasut   ddr: altera: Clea...
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
   * @sticky_bit_chk:	Resulting sticky bit mask after the test
   * @left_edge:		Left edge of the DQ/DQS phase
   * @right_edge:		Right edge of the DQ/DQS phase
   * @use_read_test:	Perform read test
   *
   * Find right edge of DQ/DQS working phase.
   */
  static int search_right_edge(const int write, const int rank_bgn,
  	const u32 write_group, const u32 read_group,
  	const int start_dqs, const int start_dqs_en,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2079
  	u32 *sticky_bit_chk,
c4907898a   Marek Vasut   ddr: altera: Clea...
2080
2081
  	int *left_edge, int *right_edge, const u32 use_read_test)
  {
139823ecb   Marek Vasut   ddr: altera: sequ...
2082
2083
2084
2085
  	const u32 delay_max = write ? iocfg->io_out1_delay_max :
  				      iocfg->io_in_delay_max;
  	const u32 dqs_max = write ? iocfg->io_out1_delay_max :
  				    iocfg->dqs_in_delay_max;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2086
2087
  	const u32 per_dqs = write ? rwcfg->mem_dq_per_write_dqs :
  				    rwcfg->mem_dq_per_read_dqs;
0c4be198f   Marek Vasut   ddr: altera: Clea...
2088
  	u32 stop, bit_chk;
c4907898a   Marek Vasut   ddr: altera: Clea...
2089
2090
2091
2092
2093
2094
2095
2096
  	int i, d;
  
  	for (d = 0; d <= dqs_max - start_dqs; d++) {
  		if (write) {	/* WRITE-ONLY */
  			scc_mgr_apply_group_dqs_io_and_oct_out1(write_group,
  								d + start_dqs);
  		} else {	/* READ-ONLY */
  			scc_mgr_set_dqs_bus_in_delay(read_group, d + start_dqs);
160695d88   Marek Vasut   ddr: altera: sequ...
2097
  			if (iocfg->shift_dqs_en_when_shift_dqs) {
5ded7320c   Marek Vasut   ddr: altera: sequ...
2098
  				u32 delay = d + start_dqs_en;
160695d88   Marek Vasut   ddr: altera: sequ...
2099
2100
  				if (delay > iocfg->dqs_en_delay_max)
  					delay = iocfg->dqs_en_delay_max;
c4907898a   Marek Vasut   ddr: altera: Clea...
2101
2102
2103
2104
2105
2106
  				scc_mgr_set_dqs_en_delay(read_group, delay);
  			}
  			scc_mgr_load_dqs(read_group);
  		}
  
  		writel(0, &sdr_scc_mgr->update);
901dc36e7   Marek Vasut   ddr: altera: Clea...
2107
  		stop = search_stop_check(write, d, rank_bgn, write_group,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2108
  					 read_group, &bit_chk, sticky_bit_chk,
901dc36e7   Marek Vasut   ddr: altera: Clea...
2109
  					 use_read_test);
c4907898a   Marek Vasut   ddr: altera: Clea...
2110
2111
  		if (stop == 1) {
  			if (write && (d == 0)) {	/* WRITE-ONLY */
139823ecb   Marek Vasut   ddr: altera: sequ...
2112
2113
  				for (i = 0; i < rwcfg->mem_dq_per_write_dqs;
  				     i++) {
c4907898a   Marek Vasut   ddr: altera: Clea...
2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
  					/*
  					 * d = 0 failed, but it passed when
  					 * testing the left edge, so it must be
  					 * marginal, set it to -1
  					 */
  					if (right_edge[i] == delay_max + 1 &&
  					    left_edge[i] != delay_max + 1)
  						right_edge[i] = -1;
  				}
  			}
  			break;
  		}
  
  		/* stop != 1 */
  		for (i = 0; i < per_dqs; i++) {
0c4be198f   Marek Vasut   ddr: altera: Clea...
2129
  			if (bit_chk & 1) {
c4907898a   Marek Vasut   ddr: altera: Clea...
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
  				/*
  				 * Remember a passing test as
  				 * the right_edge.
  				 */
  				right_edge[i] = d;
  			} else {
  				if (d != 0) {
  					/*
  					 * If a right edge has not
  					 * been seen yet, then a future
  					 * passing test will mark this
  					 * edge as the left edge.
  					 */
  					if (right_edge[i] == delay_max + 1)
  						left_edge[i] = -(d + 1);
  				} else {
  					/*
  					 * d = 0 failed, but it passed
  					 * when testing the left edge,
  					 * so it must be marginal, set
  					 * it to -1
  					 */
  					if (right_edge[i] == delay_max + 1 &&
  					    left_edge[i] != delay_max + 1)
  						right_edge[i] = -1;
  					/*
  					 * If a right edge has not been
  					 * seen yet, then a future
  					 * passing test will mark this
  					 * edge as the left edge.
  					 */
  					else if (right_edge[i] == delay_max + 1)
  						left_edge[i] = -(d + 1);
  				}
  			}
  
  			debug_cond(DLEVEL == 2, "%s:%d center[r,d=%u]: ",
  				   __func__, __LINE__, d);
  			debug_cond(DLEVEL == 2,
  				   "bit_chk_test=%i left_edge[%u]: %d ",
0c4be198f   Marek Vasut   ddr: altera: Clea...
2170
  				   bit_chk & 1, i, left_edge[i]);
c4907898a   Marek Vasut   ddr: altera: Clea...
2171
2172
2173
  			debug_cond(DLEVEL == 2, "right_edge[%u]: %d
  ", i,
  				   right_edge[i]);
0c4be198f   Marek Vasut   ddr: altera: Clea...
2174
  			bit_chk >>= 1;
c4907898a   Marek Vasut   ddr: altera: Clea...
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
  		}
  	}
  
  	/* Check that all bits have a window */
  	for (i = 0; i < per_dqs; i++) {
  		debug_cond(DLEVEL == 2,
  			   "%s:%d write_center: left_edge[%u]: %d right_edge[%u]: %d",
  			   __func__, __LINE__, i, left_edge[i],
  			   i, right_edge[i]);
  		if ((left_edge[i] == dqs_max + 1) ||
  		    (right_edge[i] == dqs_max + 1))
  			return i + 1;	/* FIXME: If we fail, retval > 0 */
  	}
  
  	return 0;
  }
afb3eb84b   Marek Vasut   ddr: altera: Clea...
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
  /**
   * get_window_mid_index() - Find the best middle setting of DQ/DQS phase
   * @write:		Perform read (Stage 2) or write (Stage 3) calibration
   * @left_edge:		Left edge of the DQ/DQS phase
   * @right_edge:		Right edge of the DQ/DQS phase
   * @mid_min:		Best DQ/DQS phase middle setting
   *
   * Find index and value of the middle of the DQ/DQS working phase.
   */
  static int get_window_mid_index(const int write, int *left_edge,
  				int *right_edge, int *mid_min)
  {
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2203
2204
  	const u32 per_dqs = write ? rwcfg->mem_dq_per_write_dqs :
  				    rwcfg->mem_dq_per_read_dqs;
afb3eb84b   Marek Vasut   ddr: altera: Clea...
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
  	int i, mid, min_index;
  
  	/* Find middle of window for each DQ bit */
  	*mid_min = left_edge[0] - right_edge[0];
  	min_index = 0;
  	for (i = 1; i < per_dqs; i++) {
  		mid = left_edge[i] - right_edge[i];
  		if (mid < *mid_min) {
  			*mid_min = mid;
  			min_index = i;
  		}
  	}
  
  	/*
  	 * -mid_min/2 represents the amount that we need to move DQS.
  	 * If mid_min is odd and positive we'll need to add one to make
  	 * sure the rounding in further calculations is correct (always
  	 * bias to the right), so just add 1 for all positive values.
  	 */
  	if (*mid_min > 0)
  		(*mid_min)++;
  	*mid_min = *mid_min / 2;
  
  	debug_cond(DLEVEL == 1, "%s:%d vfifo_center: *mid_min=%d (index=%u)
  ",
  		   __func__, __LINE__, *mid_min, min_index);
  	return min_index;
  }
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
  /**
   * center_dq_windows() - Center the DQ/DQS windows
   * @write:		Perform read (Stage 2) or write (Stage 3) calibration
   * @left_edge:		Left edge of the DQ/DQS phase
   * @right_edge:		Right edge of the DQ/DQS phase
   * @mid_min:		Adjusted DQ/DQS phase middle setting
   * @orig_mid_min:	Original DQ/DQS phase middle setting
   * @min_index:		DQ/DQS phase middle setting index
   * @test_bgn:		Rank number to begin the test
   * @dq_margin:		Amount of shift for the DQ
   * @dqs_margin:		Amount of shift for the DQS
   *
   * Align the DQ/DQS windows in each group.
   */
  static void center_dq_windows(const int write, int *left_edge, int *right_edge,
  			      const int mid_min, const int orig_mid_min,
  			      const int min_index, const int test_bgn,
  			      int *dq_margin, int *dqs_margin)
  {
139823ecb   Marek Vasut   ddr: altera: sequ...
2252
2253
  	const u32 delay_max = write ? iocfg->io_out1_delay_max :
  				      iocfg->io_in_delay_max;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2254
2255
  	const u32 per_dqs = write ? rwcfg->mem_dq_per_write_dqs :
  				    rwcfg->mem_dq_per_read_dqs;
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
  	const u32 delay_off = write ? SCC_MGR_IO_OUT1_DELAY_OFFSET :
  				      SCC_MGR_IO_IN_DELAY_OFFSET;
  	const u32 addr = SDR_PHYGRP_SCCGRP_ADDRESS | delay_off;
  
  	u32 temp_dq_io_delay1, temp_dq_io_delay2;
  	int shift_dq, i, p;
  
  	/* Initialize data for export structures */
  	*dqs_margin = delay_max + 1;
  	*dq_margin  = delay_max + 1;
  
  	/* add delay to bring centre of all DQ windows to the same "level" */
  	for (i = 0, p = test_bgn; i < per_dqs; i++, p++) {
  		/* Use values before divide by 2 to reduce round off error */
  		shift_dq = (left_edge[i] - right_edge[i] -
  			(left_edge[min_index] - right_edge[min_index]))/2  +
  			(orig_mid_min - mid_min);
  
  		debug_cond(DLEVEL == 2,
  			   "vfifo_center: before: shift_dq[%u]=%d
  ",
  			   i, shift_dq);
  
  		temp_dq_io_delay1 = readl(addr + (p << 2));
  		temp_dq_io_delay2 = readl(addr + (i << 2));
  
  		if (shift_dq + temp_dq_io_delay1 > delay_max)
  			shift_dq = delay_max - temp_dq_io_delay2;
  		else if (shift_dq + temp_dq_io_delay1 < 0)
  			shift_dq = -temp_dq_io_delay1;
  
  		debug_cond(DLEVEL == 2,
  			   "vfifo_center: after: shift_dq[%u]=%d
  ",
  			   i, shift_dq);
  
  		if (write)
139823ecb   Marek Vasut   ddr: altera: sequ...
2293
2294
  			scc_mgr_set_dq_out1_delay(i,
  						  temp_dq_io_delay1 + shift_dq);
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2295
  		else
139823ecb   Marek Vasut   ddr: altera: sequ...
2296
2297
  			scc_mgr_set_dq_in_delay(p,
  						temp_dq_io_delay1 + shift_dq);
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
  
  		scc_mgr_load_dq(p);
  
  		debug_cond(DLEVEL == 2,
  			   "vfifo_center: margin[%u]=[%d,%d]
  ", i,
  			   left_edge[i] - shift_dq + (-mid_min),
  			   right_edge[i] + shift_dq - (-mid_min));
  
  		/* To determine values for export structures */
  		if (left_edge[i] - shift_dq + (-mid_min) < *dq_margin)
  			*dq_margin = left_edge[i] - shift_dq + (-mid_min);
  
  		if (right_edge[i] + shift_dq - (-mid_min) < *dqs_margin)
  			*dqs_margin = right_edge[i] + shift_dq - (-mid_min);
  	}
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2314
  }
ac63b9ada   Marek Vasut   ddr: altera: Clea...
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
  /**
   * rw_mgr_mem_calibrate_vfifo_center() - Per-bit deskew DQ and centering
   * @rank_bgn:		Rank number
   * @rw_group:		Read/Write Group
   * @test_bgn:		Rank at which the test begins
   * @use_read_test:	Perform a read test
   * @update_fom:		Update FOM
   *
   * Per-bit deskew DQ and centering.
   */
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2325
2326
2327
  static int rw_mgr_mem_calibrate_vfifo_center(const u32 rank_bgn,
  			const u32 rw_group, const u32 test_bgn,
  			const int use_read_test, const int update_fom)
3da428595   Dinh Nguyen   driver/ddr/altera...
2328
  {
5d6db4448   Marek Vasut   ddr: altera: Clea...
2329
2330
  	const u32 addr =
  		SDR_PHYGRP_SCCGRP_ADDRESS + SCC_MGR_DQS_IN_DELAY_OFFSET +
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2331
  		(rw_group << 2);
3da428595   Dinh Nguyen   driver/ddr/altera...
2332
2333
2334
2335
  	/*
  	 * Store these as signed since there are comparisons with
  	 * signed numbers.
  	 */
5ded7320c   Marek Vasut   ddr: altera: sequ...
2336
  	u32 sticky_bit_chk;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2337
2338
  	int32_t left_edge[rwcfg->mem_dq_per_read_dqs];
  	int32_t right_edge[rwcfg->mem_dq_per_read_dqs];
3da428595   Dinh Nguyen   driver/ddr/altera...
2339
  	int32_t orig_mid_min, mid_min;
160695d88   Marek Vasut   ddr: altera: sequ...
2340
  	int32_t new_dqs, start_dqs, start_dqs_en = 0, final_dqs_en;
3da428595   Dinh Nguyen   driver/ddr/altera...
2341
  	int32_t dq_margin, dqs_margin;
5d6db4448   Marek Vasut   ddr: altera: Clea...
2342
  	int i, min_index;
c4907898a   Marek Vasut   ddr: altera: Clea...
2343
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
2344

0113c3e1f   Marek Vasut   ddr: altera: Clea...
2345
  	debug("%s:%d: %u %u", __func__, __LINE__, rw_group, test_bgn);
3da428595   Dinh Nguyen   driver/ddr/altera...
2346

5d6db4448   Marek Vasut   ddr: altera: Clea...
2347
  	start_dqs = readl(addr);
160695d88   Marek Vasut   ddr: altera: sequ...
2348
2349
  	if (iocfg->shift_dqs_en_when_shift_dqs)
  		start_dqs_en = readl(addr - iocfg->dqs_en_delay_offset);
3da428595   Dinh Nguyen   driver/ddr/altera...
2350
2351
  
  	/* set the left and right edge of each bit to an illegal value */
160695d88   Marek Vasut   ddr: altera: sequ...
2352
  	/* use (iocfg->io_in_delay_max + 1) as an illegal value */
3da428595   Dinh Nguyen   driver/ddr/altera...
2353
  	sticky_bit_chk = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2354
  	for (i = 0; i < rwcfg->mem_dq_per_read_dqs; i++) {
160695d88   Marek Vasut   ddr: altera: sequ...
2355
2356
  		left_edge[i]  = iocfg->io_in_delay_max + 1;
  		right_edge[i] = iocfg->io_in_delay_max + 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
2357
  	}
3da428595   Dinh Nguyen   driver/ddr/altera...
2358
  	/* Search for the left edge of the window for each bit */
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2359
  	search_left_edge(0, rank_bgn, rw_group, rw_group, test_bgn,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2360
  			 &sticky_bit_chk,
71120773b   Marek Vasut   ddr: altera: Clea...
2361
  			 left_edge, right_edge, use_read_test);
3da428595   Dinh Nguyen   driver/ddr/altera...
2362

f0712c350   Marek Vasut   ddr: altera: Clea...
2363

3da428595   Dinh Nguyen   driver/ddr/altera...
2364
  	/* Search for the right edge of the window for each bit */
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2365
  	ret = search_right_edge(0, rank_bgn, rw_group, rw_group,
c4907898a   Marek Vasut   ddr: altera: Clea...
2366
  				start_dqs, start_dqs_en,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2367
  				&sticky_bit_chk,
c4907898a   Marek Vasut   ddr: altera: Clea...
2368
2369
  				left_edge, right_edge, use_read_test);
  	if (ret) {
3da428595   Dinh Nguyen   driver/ddr/altera...
2370
  		/*
c4907898a   Marek Vasut   ddr: altera: Clea...
2371
2372
2373
  		 * Restore delay chain settings before letting the loop
  		 * in rw_mgr_mem_calibrate_vfifo to retry different
  		 * dqs/ck relationships.
3da428595   Dinh Nguyen   driver/ddr/altera...
2374
  		 */
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2375
  		scc_mgr_set_dqs_bus_in_delay(rw_group, start_dqs);
160695d88   Marek Vasut   ddr: altera: sequ...
2376
  		if (iocfg->shift_dqs_en_when_shift_dqs)
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2377
  			scc_mgr_set_dqs_en_delay(rw_group, start_dqs_en);
3da428595   Dinh Nguyen   driver/ddr/altera...
2378

0113c3e1f   Marek Vasut   ddr: altera: Clea...
2379
  		scc_mgr_load_dqs(rw_group);
c4907898a   Marek Vasut   ddr: altera: Clea...
2380
  		writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
2381

c4907898a   Marek Vasut   ddr: altera: Clea...
2382
2383
2384
2385
  		debug_cond(DLEVEL == 1,
  			   "%s:%d vfifo_center: failed to find edge [%u]: %d %d",
  			   __func__, __LINE__, i, left_edge[i], right_edge[i]);
  		if (use_read_test) {
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2386
  			set_failing_group_stage(rw_group *
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2387
  				rwcfg->mem_dq_per_read_dqs + i,
c4907898a   Marek Vasut   ddr: altera: Clea...
2388
2389
  				CAL_STAGE_VFIFO,
  				CAL_SUBSTAGE_VFIFO_CENTER);
3da428595   Dinh Nguyen   driver/ddr/altera...
2390
  		} else {
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2391
  			set_failing_group_stage(rw_group *
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2392
  				rwcfg->mem_dq_per_read_dqs + i,
c4907898a   Marek Vasut   ddr: altera: Clea...
2393
2394
  				CAL_STAGE_VFIFO_AFTER_WRITES,
  				CAL_SUBSTAGE_VFIFO_CENTER);
3da428595   Dinh Nguyen   driver/ddr/altera...
2395
  		}
986682479   Marek Vasut   ddr: altera: Clea...
2396
  		return -EIO;
3da428595   Dinh Nguyen   driver/ddr/altera...
2397
  	}
afb3eb84b   Marek Vasut   ddr: altera: Clea...
2398
  	min_index = get_window_mid_index(0, left_edge, right_edge, &mid_min);
3da428595   Dinh Nguyen   driver/ddr/altera...
2399
2400
2401
2402
  
  	/* Determine the amount we can change DQS (which is -mid_min) */
  	orig_mid_min = mid_min;
  	new_dqs = start_dqs - mid_min;
160695d88   Marek Vasut   ddr: altera: sequ...
2403
2404
  	if (new_dqs > iocfg->dqs_in_delay_max)
  		new_dqs = iocfg->dqs_in_delay_max;
3da428595   Dinh Nguyen   driver/ddr/altera...
2405
2406
2407
2408
2409
2410
2411
  	else if (new_dqs < 0)
  		new_dqs = 0;
  
  	mid_min = start_dqs - new_dqs;
  	debug_cond(DLEVEL == 1, "vfifo_center: new mid_min=%d new_dqs=%d
  ",
  		   mid_min, new_dqs);
160695d88   Marek Vasut   ddr: altera: sequ...
2412
2413
  	if (iocfg->shift_dqs_en_when_shift_dqs) {
  		if (start_dqs_en - mid_min > iocfg->dqs_en_delay_max)
139823ecb   Marek Vasut   ddr: altera: sequ...
2414
2415
  			mid_min += start_dqs_en - mid_min -
  				   iocfg->dqs_en_delay_max;
3da428595   Dinh Nguyen   driver/ddr/altera...
2416
2417
2418
2419
  		else if (start_dqs_en - mid_min < 0)
  			mid_min += start_dqs_en - mid_min;
  	}
  	new_dqs = start_dqs - mid_min;
f0712c350   Marek Vasut   ddr: altera: Clea...
2420
2421
2422
2423
  	debug_cond(DLEVEL == 1,
  		   "vfifo_center: start_dqs=%d start_dqs_en=%d new_dqs=%d mid_min=%d
  ",
  		   start_dqs,
160695d88   Marek Vasut   ddr: altera: sequ...
2424
  		   iocfg->shift_dqs_en_when_shift_dqs ? start_dqs_en : -1,
3da428595   Dinh Nguyen   driver/ddr/altera...
2425
  		   new_dqs, mid_min);
ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2426
2427
2428
  	/* Add delay to bring centre of all DQ windows to the same "level". */
  	center_dq_windows(0, left_edge, right_edge, mid_min, orig_mid_min,
  			  min_index, test_bgn, &dq_margin, &dqs_margin);
3da428595   Dinh Nguyen   driver/ddr/altera...
2429

3da428595   Dinh Nguyen   driver/ddr/altera...
2430
  	/* Move DQS-en */
160695d88   Marek Vasut   ddr: altera: sequ...
2431
  	if (iocfg->shift_dqs_en_when_shift_dqs) {
5d6db4448   Marek Vasut   ddr: altera: Clea...
2432
  		final_dqs_en = start_dqs_en - mid_min;
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2433
2434
  		scc_mgr_set_dqs_en_delay(rw_group, final_dqs_en);
  		scc_mgr_load_dqs(rw_group);
3da428595   Dinh Nguyen   driver/ddr/altera...
2435
2436
2437
  	}
  
  	/* Move DQS */
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2438
2439
  	scc_mgr_set_dqs_bus_in_delay(rw_group, new_dqs);
  	scc_mgr_load_dqs(rw_group);
f0712c350   Marek Vasut   ddr: altera: Clea...
2440
2441
2442
  	debug_cond(DLEVEL == 2,
  		   "%s:%d vfifo_center: dq_margin=%d dqs_margin=%d",
  		   __func__, __LINE__, dq_margin, dqs_margin);
3da428595   Dinh Nguyen   driver/ddr/altera...
2443
2444
2445
2446
2447
  
  	/*
  	 * Do not remove this line as it makes sure all of our decisions
  	 * have been applied. Apply the update bit.
  	 */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2448
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
2449

986682479   Marek Vasut   ddr: altera: Clea...
2450
2451
2452
2453
  	if ((dq_margin < 0) || (dqs_margin < 0))
  		return -EINVAL;
  
  	return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
2454
  }
bce24efa1   Marek Vasut   ddr: altera: Inte...
2455
  /**
04372fb89   Marek Vasut   ddr: altera: Extr...
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
   * rw_mgr_mem_calibrate_guaranteed_write() - Perform guaranteed write into the device
   * @rw_group:	Read/Write Group
   * @phase:	DQ/DQS phase
   *
   * Because initially no communication ca be reliably performed with the memory
   * device, the sequencer uses a guaranteed write mechanism to write data into
   * the memory device.
   */
  static int rw_mgr_mem_calibrate_guaranteed_write(const u32 rw_group,
  						 const u32 phase)
  {
04372fb89   Marek Vasut   ddr: altera: Extr...
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
  	int ret;
  
  	/* Set a particular DQ/DQS phase. */
  	scc_mgr_set_dqdqs_output_phase_all_ranks(rw_group, phase);
  
  	debug_cond(DLEVEL == 1, "%s:%d guaranteed write: g=%u p=%u
  ",
  		   __func__, __LINE__, rw_group, phase);
  
  	/*
  	 * Altera EMI_RM 2015.05.04 :: Figure 1-25
  	 * Load up the patterns used by read calibration using the
  	 * current DQDQS phase.
  	 */
  	rw_mgr_mem_calibrate_read_load_patterns(0, 1);
  
  	if (gbl->phy_debug_mode_flags & PHY_DEBUG_DISABLE_GUARANTEED_READ)
  		return 0;
  
  	/*
  	 * Altera EMI_RM 2015.05.04 :: Figure 1-26
  	 * Back-to-Back reads of the patterns used for calibration.
  	 */
d844c7d43   Marek Vasut   ddr: altera: Clea...
2490
2491
  	ret = rw_mgr_mem_calibrate_read_test_patterns(0, rw_group, 1);
  	if (ret)
04372fb89   Marek Vasut   ddr: altera: Extr...
2492
2493
2494
2495
  		debug_cond(DLEVEL == 1,
  			   "%s:%d Guaranteed read test failed: g=%u p=%u
  ",
  			   __func__, __LINE__, rw_group, phase);
d844c7d43   Marek Vasut   ddr: altera: Clea...
2496
  	return ret;
04372fb89   Marek Vasut   ddr: altera: Extr...
2497
2498
2499
  }
  
  /**
f09da11e6   Marek Vasut   ddr: altera: Extr...
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
   * rw_mgr_mem_calibrate_dqs_enable_calibration() - DQS Enable Calibration
   * @rw_group:	Read/Write Group
   * @test_bgn:	Rank at which the test begins
   *
   * DQS enable calibration ensures reliable capture of the DQ signal without
   * glitches on the DQS line.
   */
  static int rw_mgr_mem_calibrate_dqs_enable_calibration(const u32 rw_group,
  						       const u32 test_bgn)
  {
f09da11e6   Marek Vasut   ddr: altera: Extr...
2510
2511
2512
2513
  	/*
  	 * Altera EMI_RM 2015.05.04 :: Figure 1-27
  	 * DQS and DQS Eanble Signal Relationships.
  	 */
28ea827d9   Marek Vasut   ddr: altera: Clea...
2514
2515
  
  	/* We start at zero, so have one less dq to devide among */
160695d88   Marek Vasut   ddr: altera: sequ...
2516
  	const u32 delay_step = iocfg->io_in_delay_max /
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2517
  			       (rwcfg->mem_dq_per_read_dqs - 1);
914546e7f   Marek Vasut   ddr: altera: Clea...
2518
  	int ret;
28ea827d9   Marek Vasut   ddr: altera: Clea...
2519
2520
2521
2522
2523
2524
  	u32 i, p, d, r;
  
  	debug("%s:%d (%u,%u)
  ", __func__, __LINE__, rw_group, test_bgn);
  
  	/* Try different dq_in_delays since the DQ path is shorter than DQS. */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2525
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
28ea827d9   Marek Vasut   ddr: altera: Clea...
2526
2527
  	     r += NUM_RANKS_PER_SHADOW_REG) {
  		for (i = 0, p = test_bgn, d = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2528
  		     i < rwcfg->mem_dq_per_read_dqs;
28ea827d9   Marek Vasut   ddr: altera: Clea...
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
  		     i++, p++, d += delay_step) {
  			debug_cond(DLEVEL == 1,
  				   "%s:%d: g=%u r=%u i=%u p=%u d=%u
  ",
  				   __func__, __LINE__, rw_group, r, i, p, d);
  
  			scc_mgr_set_dq_in_delay(p, d);
  			scc_mgr_load_dq(p);
  		}
  
  		writel(0, &sdr_scc_mgr->update);
  	}
  
  	/*
  	 * Try rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase across different
  	 * dq_in_delay values
  	 */
914546e7f   Marek Vasut   ddr: altera: Clea...
2546
  	ret = rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(rw_group);
28ea827d9   Marek Vasut   ddr: altera: Clea...
2547
2548
2549
2550
  
  	debug_cond(DLEVEL == 1,
  		   "%s:%d: g=%u found=%u; Reseting delay chain to zero
  ",
914546e7f   Marek Vasut   ddr: altera: Clea...
2551
  		   __func__, __LINE__, rw_group, !ret);
28ea827d9   Marek Vasut   ddr: altera: Clea...
2552

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2553
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
28ea827d9   Marek Vasut   ddr: altera: Clea...
2554
2555
2556
2557
  	     r += NUM_RANKS_PER_SHADOW_REG) {
  		scc_mgr_apply_group_dq_in_delay(test_bgn, 0);
  		writel(0, &sdr_scc_mgr->update);
  	}
914546e7f   Marek Vasut   ddr: altera: Clea...
2558
  	return ret;
f09da11e6   Marek Vasut   ddr: altera: Extr...
2559
2560
2561
  }
  
  /**
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
   * rw_mgr_mem_calibrate_dq_dqs_centering() - Centering DQ/DQS
   * @rw_group:		Read/Write Group
   * @test_bgn:		Rank at which the test begins
   * @use_read_test:	Perform a read test
   * @update_fom:		Update FOM
   *
   * The centerin DQ/DQS stage attempts to align DQ and DQS signals on reads
   * within a group.
   */
  static int
  rw_mgr_mem_calibrate_dq_dqs_centering(const u32 rw_group, const u32 test_bgn,
  				      const int use_read_test,
  				      const int update_fom)
  
  {
  	int ret, grp_calibrated;
  	u32 rank_bgn, sr;
  
  	/*
  	 * Altera EMI_RM 2015.05.04 :: Figure 1-28
  	 * Read per-bit deskew can be done on a per shadow register basis.
  	 */
  	grp_calibrated = 1;
  	for (rank_bgn = 0, sr = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2586
  	     rank_bgn < rwcfg->mem_number_of_ranks;
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2587
  	     rank_bgn += NUM_RANKS_PER_SHADOW_REG, sr++) {
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2588
  		ret = rw_mgr_mem_calibrate_vfifo_center(rank_bgn, rw_group,
0113c3e1f   Marek Vasut   ddr: altera: Clea...
2589
  							test_bgn,
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2590
2591
  							use_read_test,
  							update_fom);
986682479   Marek Vasut   ddr: altera: Clea...
2592
  		if (!ret)
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
  			continue;
  
  		grp_calibrated = 0;
  	}
  
  	if (!grp_calibrated)
  		return -EIO;
  
  	return 0;
  }
  
  /**
bce24efa1   Marek Vasut   ddr: altera: Inte...
2605
2606
2607
2608
2609
2610
2611
2612
   * rw_mgr_mem_calibrate_vfifo() - Calibrate the read valid prediction FIFO
   * @rw_group:		Read/Write Group
   * @test_bgn:		Rank at which the test begins
   *
   * Stage 1: Calibrate the read valid prediction FIFO.
   *
   * This function implements UniPHY calibration Stage 1, as explained in
   * detail in Altera EMI_RM 2015.05.04 , "UniPHY Calibration Stages".
3da428595   Dinh Nguyen   driver/ddr/altera...
2613
   *
bce24efa1   Marek Vasut   ddr: altera: Inte...
2614
2615
2616
   * - read valid prediction will consist of finding:
   *   - DQS enable phase and DQS enable delay (DQS Enable Calibration)
   *   - DQS input phase  and DQS input delay (DQ/DQS Centering)
3da428595   Dinh Nguyen   driver/ddr/altera...
2617
2618
   *  - we also do a per-bit deskew on the DQ lines.
   */
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2619
  static int rw_mgr_mem_calibrate_vfifo(const u32 rw_group, const u32 test_bgn)
3da428595   Dinh Nguyen   driver/ddr/altera...
2620
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
2621
2622
2623
  	u32 p, d;
  	u32 dtaps_per_ptap;
  	u32 failed_substage;
3da428595   Dinh Nguyen   driver/ddr/altera...
2624

04372fb89   Marek Vasut   ddr: altera: Extr...
2625
  	int ret;
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2626
2627
  	debug("%s:%d: %u %u
  ", __func__, __LINE__, rw_group, test_bgn);
3da428595   Dinh Nguyen   driver/ddr/altera...
2628

7c0a9df36   Marek Vasut   ddr: altera: Inte...
2629
2630
  	/* Update info for sims */
  	reg_file_set_group(rw_group);
3da428595   Dinh Nguyen   driver/ddr/altera...
2631
  	reg_file_set_stage(CAL_STAGE_VFIFO);
7c0a9df36   Marek Vasut   ddr: altera: Inte...
2632
  	reg_file_set_sub_stage(CAL_SUBSTAGE_GUARANTEED_READ);
3da428595   Dinh Nguyen   driver/ddr/altera...
2633

7c0a9df36   Marek Vasut   ddr: altera: Inte...
2634
2635
2636
  	failed_substage = CAL_SUBSTAGE_GUARANTEED_READ;
  
  	/* USER Determine number of delay taps for each phase tap. */
160695d88   Marek Vasut   ddr: altera: sequ...
2637
2638
  	dtaps_per_ptap = DIV_ROUND_UP(iocfg->delay_per_opa_tap,
  				      iocfg->delay_per_dqs_en_dchain_tap) - 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
2639

fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2640
  	for (d = 0; d <= dtaps_per_ptap; d += 2) {
3da428595   Dinh Nguyen   driver/ddr/altera...
2641
2642
  		/*
  		 * In RLDRAMX we may be messing the delay of pins in
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2643
2644
  		 * the same write rw_group but outside of the current read
  		 * the rw_group, but that's ok because we haven't calibrated
ac70d2f38   Marek Vasut   ddr: altera: Inte...
2645
  		 * output side yet.
3da428595   Dinh Nguyen   driver/ddr/altera...
2646
2647
  		 */
  		if (d > 0) {
f51a7d359   Marek Vasut   ddr: altera: Clea...
2648
  			scc_mgr_apply_group_all_out_delay_add_all_ranks(
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2649
  								rw_group, d);
3da428595   Dinh Nguyen   driver/ddr/altera...
2650
  		}
160695d88   Marek Vasut   ddr: altera: sequ...
2651
  		for (p = 0; p <= iocfg->dqdqs_out_phase_max; p++) {
04372fb89   Marek Vasut   ddr: altera: Extr...
2652
2653
2654
2655
  			/* 1) Guaranteed Write */
  			ret = rw_mgr_mem_calibrate_guaranteed_write(rw_group, p);
  			if (ret)
  				break;
3da428595   Dinh Nguyen   driver/ddr/altera...
2656

f09da11e6   Marek Vasut   ddr: altera: Extr...
2657
2658
2659
2660
  			/* 2) DQS Enable Calibration */
  			ret = rw_mgr_mem_calibrate_dqs_enable_calibration(rw_group,
  									  test_bgn);
  			if (ret) {
3da428595   Dinh Nguyen   driver/ddr/altera...
2661
  				failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2662
2663
  				continue;
  			}
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2664
  			/* 3) Centering DQ/DQS */
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2665
  			/*
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2666
2667
  			 * If doing read after write calibration, do not update
  			 * FOM now. Do it then.
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2668
  			 */
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2669
2670
2671
  			ret = rw_mgr_mem_calibrate_dq_dqs_centering(rw_group,
  								test_bgn, 1, 0);
  			if (ret) {
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2672
  				failed_substage = CAL_SUBSTAGE_VFIFO_CENTER;
16cfc4b98   Marek Vasut   ddr: altera: Extr...
2673
  				continue;
3da428595   Dinh Nguyen   driver/ddr/altera...
2674
  			}
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2675

16cfc4b98   Marek Vasut   ddr: altera: Extr...
2676
2677
  			/* All done. */
  			goto cal_done_ok;
3da428595   Dinh Nguyen   driver/ddr/altera...
2678
2679
  		}
  	}
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2680
  	/* Calibration Stage 1 failed. */
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2681
  	set_failing_group_stage(rw_group, CAL_STAGE_VFIFO, failed_substage);
fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2682
  	return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
2683

fe2d0a2da   Marek Vasut   ddr: altera: Inte...
2684
2685
  	/* Calibration Stage 1 completed OK. */
  cal_done_ok:
3da428595   Dinh Nguyen   driver/ddr/altera...
2686
2687
2688
2689
2690
2691
  	/*
  	 * Reset the delay chains back to zero if they have moved > 1
  	 * (check for > 1 because loop will increase d even when pass in
  	 * first case).
  	 */
  	if (d > 2)
c336ca3e5   Marek Vasut   ddr: altera: Inte...
2692
  		scc_mgr_zero_group(rw_group, 1);
3da428595   Dinh Nguyen   driver/ddr/altera...
2693
2694
2695
  
  	return 1;
  }
78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
  /**
   * rw_mgr_mem_calibrate_vfifo_end() - DQ/DQS Centering.
   * @rw_group:		Read/Write Group
   * @test_bgn:		Rank at which the test begins
   *
   * Stage 3: DQ/DQS Centering.
   *
   * This function implements UniPHY calibration Stage 3, as explained in
   * detail in Altera EMI_RM 2015.05.04 , "UniPHY Calibration Stages".
   */
  static int rw_mgr_mem_calibrate_vfifo_end(const u32 rw_group,
  					  const u32 test_bgn)
3da428595   Dinh Nguyen   driver/ddr/altera...
2708
  {
78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2709
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
2710

78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2711
  	debug("%s:%d %u %u", __func__, __LINE__, rw_group, test_bgn);
3da428595   Dinh Nguyen   driver/ddr/altera...
2712

78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2713
2714
  	/* Update info for sims. */
  	reg_file_set_group(rw_group);
3da428595   Dinh Nguyen   driver/ddr/altera...
2715
2716
  	reg_file_set_stage(CAL_STAGE_VFIFO_AFTER_WRITES);
  	reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2717
2718
2719
  	ret = rw_mgr_mem_calibrate_dq_dqs_centering(rw_group, test_bgn, 0, 1);
  	if (ret)
  		set_failing_group_stage(rw_group,
3da428595   Dinh Nguyen   driver/ddr/altera...
2720
2721
  					CAL_STAGE_VFIFO_AFTER_WRITES,
  					CAL_SUBSTAGE_VFIFO_CENTER);
78cdd7d0c   Marek Vasut   ddr: altera: Clea...
2722
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
2723
  }
c984278a6   Marek Vasut   ddr: altera: Clea...
2724
2725
2726
2727
2728
2729
2730
2731
2732
  /**
   * rw_mgr_mem_calibrate_lfifo() - Minimize latency
   *
   * Stage 4: Minimize latency.
   *
   * This function implements UniPHY calibration Stage 4, as explained in
   * detail in Altera EMI_RM 2015.05.04 , "UniPHY Calibration Stages".
   * Calibrate LFIFO to find smallest read latency.
   */
5ded7320c   Marek Vasut   ddr: altera: sequ...
2733
  static u32 rw_mgr_mem_calibrate_lfifo(void)
3da428595   Dinh Nguyen   driver/ddr/altera...
2734
  {
c984278a6   Marek Vasut   ddr: altera: Clea...
2735
  	int found_one = 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
2736
2737
2738
  
  	debug("%s:%d
  ", __func__, __LINE__);
c984278a6   Marek Vasut   ddr: altera: Clea...
2739
  	/* Update info for sims. */
3da428595   Dinh Nguyen   driver/ddr/altera...
2740
2741
2742
2743
2744
  	reg_file_set_stage(CAL_STAGE_LFIFO);
  	reg_file_set_sub_stage(CAL_SUBSTAGE_READ_LATENCY);
  
  	/* Load up the patterns used by read calibration for all ranks */
  	rw_mgr_mem_calibrate_read_load_patterns(0, 1);
3da428595   Dinh Nguyen   driver/ddr/altera...
2745

3da428595   Dinh Nguyen   driver/ddr/altera...
2746
  	do {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2747
  		writel(gbl->curr_read_lat, &phy_mgr_cfg->phy_rlat);
3da428595   Dinh Nguyen   driver/ddr/altera...
2748
2749
  		debug_cond(DLEVEL == 2, "%s:%d lfifo: read_lat=%u",
  			   __func__, __LINE__, gbl->curr_read_lat);
c984278a6   Marek Vasut   ddr: altera: Clea...
2750
2751
  		if (!rw_mgr_mem_calibrate_read_test_all_ranks(0, NUM_READ_TESTS,
  							      PASS_ALL_BITS, 1))
3da428595   Dinh Nguyen   driver/ddr/altera...
2752
  			break;
3da428595   Dinh Nguyen   driver/ddr/altera...
2753
2754
  
  		found_one = 1;
c984278a6   Marek Vasut   ddr: altera: Clea...
2755
2756
2757
2758
  		/*
  		 * Reduce read latency and see if things are
  		 * working correctly.
  		 */
3da428595   Dinh Nguyen   driver/ddr/altera...
2759
2760
  		gbl->curr_read_lat--;
  	} while (gbl->curr_read_lat > 0);
c984278a6   Marek Vasut   ddr: altera: Clea...
2761
  	/* Reset the fifos to get pointers to known state. */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2762
  	writel(0, &phy_mgr_cmd->fifo_reset);
3da428595   Dinh Nguyen   driver/ddr/altera...
2763
2764
  
  	if (found_one) {
c984278a6   Marek Vasut   ddr: altera: Clea...
2765
  		/* Add a fudge factor to the read latency that was determined */
3da428595   Dinh Nguyen   driver/ddr/altera...
2766
  		gbl->curr_read_lat += 2;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2767
  		writel(gbl->curr_read_lat, &phy_mgr_cfg->phy_rlat);
c984278a6   Marek Vasut   ddr: altera: Clea...
2768
2769
2770
2771
  		debug_cond(DLEVEL == 2,
  			   "%s:%d lfifo: success: using read_lat=%u
  ",
  			   __func__, __LINE__, gbl->curr_read_lat);
3da428595   Dinh Nguyen   driver/ddr/altera...
2772
2773
2774
  	} else {
  		set_failing_group_stage(0xff, CAL_STAGE_LFIFO,
  					CAL_SUBSTAGE_READ_LATENCY);
c984278a6   Marek Vasut   ddr: altera: Clea...
2775
2776
2777
2778
  		debug_cond(DLEVEL == 2,
  			   "%s:%d lfifo: failed at initial read_lat=%u
  ",
  			   __func__, __LINE__, gbl->curr_read_lat);
3da428595   Dinh Nguyen   driver/ddr/altera...
2779
  	}
c984278a6   Marek Vasut   ddr: altera: Clea...
2780
2781
  
  	return found_one;
3da428595   Dinh Nguyen   driver/ddr/altera...
2782
  }
c8570afa0   Marek Vasut   ddr: altera: Clea...
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
  /**
   * search_window() - Search for the/part of the window with DM/DQS shift
   * @search_dm:		If 1, search for the DM shift, if 0, search for DQS shift
   * @rank_bgn:		Rank number
   * @write_group:	Write Group
   * @bgn_curr:		Current window begin
   * @end_curr:		Current window end
   * @bgn_best:		Current best window begin
   * @end_best:		Current best window end
   * @win_best:		Size of the best window
   * @new_dqs:		New DQS value (only applicable if search_dm = 0).
   *
   * Search for the/part of the window with DM/DQS shift.
   */
  static void search_window(const int search_dm,
  			  const u32 rank_bgn, const u32 write_group,
  			  int *bgn_curr, int *end_curr, int *bgn_best,
  			  int *end_best, int *win_best, int new_dqs)
  {
  	u32 bit_chk;
160695d88   Marek Vasut   ddr: altera: sequ...
2803
  	const int max = iocfg->io_out1_delay_max - new_dqs;
c8570afa0   Marek Vasut   ddr: altera: Clea...
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
  	int d, di;
  
  	/* Search for the/part of the window with DM/DQS shift. */
  	for (di = max; di >= 0; di -= DELTA_D) {
  		if (search_dm) {
  			d = di;
  			scc_mgr_apply_group_dm_out1_delay(d);
  		} else {
  			/* For DQS, we go from 0...max */
  			d = max - di;
  			/*
139823ecb   Marek Vasut   ddr: altera: sequ...
2815
2816
  			 * Note: This only shifts DQS, so are we limiting
  			 *       ourselves to width of DQ unnecessarily.
c8570afa0   Marek Vasut   ddr: altera: Clea...
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
  			 */
  			scc_mgr_apply_group_dqs_io_and_oct_out1(write_group,
  								d + new_dqs);
  		}
  
  		writel(0, &sdr_scc_mgr->update);
  
  		if (rw_mgr_mem_calibrate_write_test(rank_bgn, write_group, 1,
  						    PASS_ALL_BITS, &bit_chk,
  						    0)) {
  			/* Set current end of the window. */
  			*end_curr = search_dm ? -d : d;
  
  			/*
  			 * If a starting edge of our window has not been seen
  			 * this is our current start of the DM window.
  			 */
160695d88   Marek Vasut   ddr: altera: sequ...
2834
  			if (*bgn_curr == iocfg->io_out1_delay_max + 1)
c8570afa0   Marek Vasut   ddr: altera: Clea...
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
  				*bgn_curr = search_dm ? -d : d;
  
  			/*
  			 * If current window is bigger than best seen.
  			 * Set best seen to be current window.
  			 */
  			if ((*end_curr - *bgn_curr + 1) > *win_best) {
  				*win_best = *end_curr - *bgn_curr + 1;
  				*bgn_best = *bgn_curr;
  				*end_best = *end_curr;
  			}
  		} else {
  			/* We just saw a failing test. Reset temp edge. */
160695d88   Marek Vasut   ddr: altera: sequ...
2848
2849
  			*bgn_curr = iocfg->io_out1_delay_max + 1;
  			*end_curr = iocfg->io_out1_delay_max + 1;
c8570afa0   Marek Vasut   ddr: altera: Clea...
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
  
  			/* Early exit is only applicable to DQS. */
  			if (search_dm)
  				continue;
  
  			/*
  			 * Early exit optimization: if the remaining delay
  			 * chain space is less than already seen largest
  			 * window we can exit.
  			 */
160695d88   Marek Vasut   ddr: altera: sequ...
2860
  			if (*win_best - 1 > iocfg->io_out1_delay_max - new_dqs - d)
c8570afa0   Marek Vasut   ddr: altera: Clea...
2861
2862
2863
2864
  				break;
  		}
  	}
  }
3da428595   Dinh Nguyen   driver/ddr/altera...
2865
  /*
a386a50eb   Marek Vasut   ddr: altera: Clea...
2866
2867
2868
2869
2870
2871
   * rw_mgr_mem_calibrate_writes_center() - Center all windows
   * @rank_bgn:		Rank number
   * @write_group:	Write group
   * @test_bgn:		Rank at which the test begins
   *
   * Center all windows. Do per-bit-deskew to possibly increase size of
3da428595   Dinh Nguyen   driver/ddr/altera...
2872
2873
   * certain windows.
   */
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2874
2875
2876
  static int
  rw_mgr_mem_calibrate_writes_center(const u32 rank_bgn, const u32 write_group,
  				   const u32 test_bgn)
3da428595   Dinh Nguyen   driver/ddr/altera...
2877
  {
c8570afa0   Marek Vasut   ddr: altera: Clea...
2878
  	int i;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2879
2880
  	u32 sticky_bit_chk;
  	u32 min_index;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2881
2882
  	int left_edge[rwcfg->mem_dq_per_write_dqs];
  	int right_edge[rwcfg->mem_dq_per_write_dqs];
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2883
2884
2885
2886
  	int mid;
  	int mid_min, orig_mid_min;
  	int new_dqs, start_dqs;
  	int dq_margin, dqs_margin, dm_margin;
160695d88   Marek Vasut   ddr: altera: sequ...
2887
2888
2889
2890
  	int bgn_curr = iocfg->io_out1_delay_max + 1;
  	int end_curr = iocfg->io_out1_delay_max + 1;
  	int bgn_best = iocfg->io_out1_delay_max + 1;
  	int end_best = iocfg->io_out1_delay_max + 1;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2891
  	int win_best = 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
2892

c4907898a   Marek Vasut   ddr: altera: Clea...
2893
  	int ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
2894
2895
2896
  	debug("%s:%d %u %u", __func__, __LINE__, write_group, test_bgn);
  
  	dm_margin = 0;
c65408720   Marek Vasut   ddr: altera: Clea...
2897
2898
  	start_dqs = readl((SDR_PHYGRP_SCCGRP_ADDRESS |
  			  SCC_MGR_IO_OUT1_DELAY_OFFSET) +
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2899
  			  (rwcfg->mem_dq_per_write_dqs << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
2900

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2901
  	/* Per-bit deskew. */
3da428595   Dinh Nguyen   driver/ddr/altera...
2902
2903
  
  	/*
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2904
  	 * Set the left and right edge of each bit to an illegal value.
160695d88   Marek Vasut   ddr: altera: sequ...
2905
  	 * Use (iocfg->io_out1_delay_max + 1) as an illegal value.
3da428595   Dinh Nguyen   driver/ddr/altera...
2906
2907
  	 */
  	sticky_bit_chk = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
2908
  	for (i = 0; i < rwcfg->mem_dq_per_write_dqs; i++) {
160695d88   Marek Vasut   ddr: altera: sequ...
2909
2910
  		left_edge[i]  = iocfg->io_out1_delay_max + 1;
  		right_edge[i] = iocfg->io_out1_delay_max + 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
2911
  	}
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2912
  	/* Search for the left edge of the window for each bit. */
71120773b   Marek Vasut   ddr: altera: Clea...
2913
  	search_left_edge(1, rank_bgn, write_group, 0, test_bgn,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2914
  			 &sticky_bit_chk,
71120773b   Marek Vasut   ddr: altera: Clea...
2915
  			 left_edge, right_edge, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
2916

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2917
  	/* Search for the right edge of the window for each bit. */
c4907898a   Marek Vasut   ddr: altera: Clea...
2918
2919
  	ret = search_right_edge(1, rank_bgn, write_group, 0,
  				start_dqs, 0,
0c4be198f   Marek Vasut   ddr: altera: Clea...
2920
  				&sticky_bit_chk,
c4907898a   Marek Vasut   ddr: altera: Clea...
2921
2922
2923
2924
  				left_edge, right_edge, 0);
  	if (ret) {
  		set_failing_group_stage(test_bgn + ret - 1, CAL_STAGE_WRITES,
  					CAL_SUBSTAGE_WRITES_CENTER);
d043ee5b4   Marek Vasut   ddr: altera: Clea...
2925
  		return -EINVAL;
3da428595   Dinh Nguyen   driver/ddr/altera...
2926
  	}
afb3eb84b   Marek Vasut   ddr: altera: Clea...
2927
  	min_index = get_window_mid_index(1, left_edge, right_edge, &mid_min);
3da428595   Dinh Nguyen   driver/ddr/altera...
2928

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2929
  	/* Determine the amount we can change DQS (which is -mid_min). */
3da428595   Dinh Nguyen   driver/ddr/altera...
2930
2931
2932
  	orig_mid_min = mid_min;
  	new_dqs = start_dqs;
  	mid_min = 0;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2933
2934
2935
2936
  	debug_cond(DLEVEL == 1,
  		   "%s:%d write_center: start_dqs=%d new_dqs=%d mid_min=%d
  ",
  		   __func__, __LINE__, start_dqs, new_dqs, mid_min);
3da428595   Dinh Nguyen   driver/ddr/altera...
2937

ffb8b66ea   Marek Vasut   ddr: altera: Clea...
2938
2939
2940
  	/* Add delay to bring centre of all DQ windows to the same "level". */
  	center_dq_windows(1, left_edge, right_edge, mid_min, orig_mid_min,
  			  min_index, 0, &dq_margin, &dqs_margin);
3da428595   Dinh Nguyen   driver/ddr/altera...
2941
2942
2943
  
  	/* Move DQS */
  	scc_mgr_apply_group_dqs_io_and_oct_out1(write_group, new_dqs);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2944
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
2945
2946
2947
2948
2949
2950
  
  	/* Centre DM */
  	debug_cond(DLEVEL == 2, "%s:%d write_center: DM
  ", __func__, __LINE__);
  
  	/*
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2951
  	 * Set the left and right edge of each bit to an illegal value.
160695d88   Marek Vasut   ddr: altera: sequ...
2952
  	 * Use (iocfg->io_out1_delay_max + 1) as an illegal value.
3da428595   Dinh Nguyen   driver/ddr/altera...
2953
  	 */
160695d88   Marek Vasut   ddr: altera: sequ...
2954
2955
  	left_edge[0]  = iocfg->io_out1_delay_max + 1;
  	right_edge[0] = iocfg->io_out1_delay_max + 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
2956

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2957
  	/* Search for the/part of the window with DM shift. */
c8570afa0   Marek Vasut   ddr: altera: Clea...
2958
2959
  	search_window(1, rank_bgn, write_group, &bgn_curr, &end_curr,
  		      &bgn_best, &end_best, &win_best, 0);
3da428595   Dinh Nguyen   driver/ddr/altera...
2960

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2961
  	/* Reset DM delay chains to 0. */
326752496   Marek Vasut   ddr: altera: Clea...
2962
  	scc_mgr_apply_group_dm_out1_delay(0);
3da428595   Dinh Nguyen   driver/ddr/altera...
2963
2964
2965
2966
  
  	/*
  	 * Check to see if the current window nudges up aganist 0 delay.
  	 * If so we need to continue the search by shifting DQS otherwise DQS
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2967
2968
  	 * search begins as a new search.
  	 */
3da428595   Dinh Nguyen   driver/ddr/altera...
2969
  	if (end_curr != 0) {
160695d88   Marek Vasut   ddr: altera: sequ...
2970
2971
  		bgn_curr = iocfg->io_out1_delay_max + 1;
  		end_curr = iocfg->io_out1_delay_max + 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
2972
  	}
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2973
  	/* Search for the/part of the window with DQS shifts. */
c8570afa0   Marek Vasut   ddr: altera: Clea...
2974
2975
  	search_window(0, rank_bgn, write_group, &bgn_curr, &end_curr,
  		      &bgn_best, &end_best, &win_best, new_dqs);
3da428595   Dinh Nguyen   driver/ddr/altera...
2976

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2977
2978
  	/* Assign left and right edge for cal and reporting. */
  	left_edge[0] = -1 * bgn_best;
3da428595   Dinh Nguyen   driver/ddr/altera...
2979
  	right_edge[0] = end_best;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2980
2981
2982
  	debug_cond(DLEVEL == 2, "%s:%d dm_calib: left=%d right=%d
  ",
  		   __func__, __LINE__, left_edge[0], right_edge[0]);
3da428595   Dinh Nguyen   driver/ddr/altera...
2983

3b44f55c3   Marek Vasut   ddr: altera: Clea...
2984
  	/* Move DQS (back to orig). */
3da428595   Dinh Nguyen   driver/ddr/altera...
2985
2986
2987
  	scc_mgr_apply_group_dqs_io_and_oct_out1(write_group, new_dqs);
  
  	/* Move DM */
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2988
  	/* Find middle of window for the DM bit. */
3da428595   Dinh Nguyen   driver/ddr/altera...
2989
  	mid = (left_edge[0] - right_edge[0]) / 2;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2990
  	/* Only move right, since we are not moving DQS/DQ. */
3da428595   Dinh Nguyen   driver/ddr/altera...
2991
2992
  	if (mid < 0)
  		mid = 0;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
2993
  	/* dm_marign should fail if we never find a window. */
3da428595   Dinh Nguyen   driver/ddr/altera...
2994
2995
2996
2997
  	if (win_best == 0)
  		dm_margin = -1;
  	else
  		dm_margin = left_edge[0] - mid;
326752496   Marek Vasut   ddr: altera: Clea...
2998
  	scc_mgr_apply_group_dm_out1_delay(mid);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
2999
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
3000

3b44f55c3   Marek Vasut   ddr: altera: Clea...
3001
3002
3003
3004
3005
3006
  	debug_cond(DLEVEL == 2,
  		   "%s:%d dm_calib: left=%d right=%d mid=%d dm_margin=%d
  ",
  		   __func__, __LINE__, left_edge[0], right_edge[0],
  		   mid, dm_margin);
  	/* Export values. */
3da428595   Dinh Nguyen   driver/ddr/altera...
3007
  	gbl->fom_out += dq_margin + dqs_margin;
3b44f55c3   Marek Vasut   ddr: altera: Clea...
3008
3009
3010
3011
  	debug_cond(DLEVEL == 2,
  		   "%s:%d write_center: dq_margin=%d dqs_margin=%d dm_margin=%d
  ",
  		   __func__, __LINE__, dq_margin, dqs_margin, dm_margin);
3da428595   Dinh Nguyen   driver/ddr/altera...
3012
3013
3014
3015
3016
  
  	/*
  	 * Do not remove this line as it makes sure all of our
  	 * decisions have been applied.
  	 */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3017
  	writel(0, &sdr_scc_mgr->update);
3b44f55c3   Marek Vasut   ddr: altera: Clea...
3018

d043ee5b4   Marek Vasut   ddr: altera: Clea...
3019
3020
3021
3022
  	if ((dq_margin < 0) || (dqs_margin < 0) || (dm_margin < 0))
  		return -EINVAL;
  
  	return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
3023
  }
db3a60615   Marek Vasut   ddr: altera: Clea...
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
  /**
   * rw_mgr_mem_calibrate_writes() - Write Calibration Part One
   * @rank_bgn:		Rank number
   * @group:		Read/Write Group
   * @test_bgn:		Rank at which the test begins
   *
   * Stage 2: Write Calibration Part One.
   *
   * This function implements UniPHY calibration Stage 2, as explained in
   * detail in Altera EMI_RM 2015.05.04 , "UniPHY Calibration Stages".
   */
  static int rw_mgr_mem_calibrate_writes(const u32 rank_bgn, const u32 group,
  				       const u32 test_bgn)
3da428595   Dinh Nguyen   driver/ddr/altera...
3037
  {
db3a60615   Marek Vasut   ddr: altera: Clea...
3038
3039
3040
3041
3042
  	int ret;
  
  	/* Update info for sims */
  	debug("%s:%d %u %u
  ", __func__, __LINE__, group, test_bgn);
3da428595   Dinh Nguyen   driver/ddr/altera...
3043

db3a60615   Marek Vasut   ddr: altera: Clea...
3044
  	reg_file_set_group(group);
3da428595   Dinh Nguyen   driver/ddr/altera...
3045
3046
  	reg_file_set_stage(CAL_STAGE_WRITES);
  	reg_file_set_sub_stage(CAL_SUBSTAGE_WRITES_CENTER);
db3a60615   Marek Vasut   ddr: altera: Clea...
3047
  	ret = rw_mgr_mem_calibrate_writes_center(rank_bgn, group, test_bgn);
d043ee5b4   Marek Vasut   ddr: altera: Clea...
3048
  	if (ret)
db3a60615   Marek Vasut   ddr: altera: Clea...
3049
  		set_failing_group_stage(group, CAL_STAGE_WRITES,
3da428595   Dinh Nguyen   driver/ddr/altera...
3050
  					CAL_SUBSTAGE_WRITES_CENTER);
3da428595   Dinh Nguyen   driver/ddr/altera...
3051

d043ee5b4   Marek Vasut   ddr: altera: Clea...
3052
  	return ret;
3da428595   Dinh Nguyen   driver/ddr/altera...
3053
  }
4b0ac26a1   Marek Vasut   ddr: altera: Clea...
3054
3055
3056
3057
3058
  /**
   * mem_precharge_and_activate() - Precharge all banks and activate
   *
   * Precharge all banks and activate row 0 in bank "000..." and bank "111...".
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3059
3060
  static void mem_precharge_and_activate(void)
  {
4b0ac26a1   Marek Vasut   ddr: altera: Clea...
3061
  	int r;
3da428595   Dinh Nguyen   driver/ddr/altera...
3062

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3063
  	for (r = 0; r < rwcfg->mem_number_of_ranks; r++) {
4b0ac26a1   Marek Vasut   ddr: altera: Clea...
3064
  		/* Set rank. */
3da428595   Dinh Nguyen   driver/ddr/altera...
3065
  		set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
4b0ac26a1   Marek Vasut   ddr: altera: Clea...
3066
  		/* Precharge all banks. */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3067
  		writel(rwcfg->precharge_all, SDR_PHYGRP_RWMGRGRP_ADDRESS |
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3068
  					     RW_MGR_RUN_SINGLE_GROUP_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
3069

1273dd9ea   Marek Vasut   ddr: altera: Mass...
3070
  		writel(0x0F, &sdr_rw_load_mgr_regs->load_cntr0);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3071
  		writel(rwcfg->activate_0_and_1_wait1,
139823ecb   Marek Vasut   ddr: altera: sequ...
3072
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add0);
3da428595   Dinh Nguyen   driver/ddr/altera...
3073

1273dd9ea   Marek Vasut   ddr: altera: Mass...
3074
  		writel(0x0F, &sdr_rw_load_mgr_regs->load_cntr1);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3075
  		writel(rwcfg->activate_0_and_1_wait2,
139823ecb   Marek Vasut   ddr: altera: sequ...
3076
  		       &sdr_rw_load_jump_mgr_regs->load_jump_add1);
3da428595   Dinh Nguyen   driver/ddr/altera...
3077

4b0ac26a1   Marek Vasut   ddr: altera: Clea...
3078
  		/* Activate rows. */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3079
  		writel(rwcfg->activate_0_and_1, SDR_PHYGRP_RWMGRGRP_ADDRESS |
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3080
  						RW_MGR_RUN_SINGLE_GROUP_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
3081
3082
  	}
  }
16502a0b2   Marek Vasut   ddr: altera: Clea...
3083
3084
3085
3086
3087
3088
  /**
   * mem_init_latency() - Configure memory RLAT and WLAT settings
   *
   * Configure memory RLAT and WLAT parameters.
   */
  static void mem_init_latency(void)
3da428595   Dinh Nguyen   driver/ddr/altera...
3089
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
3090
  	/*
16502a0b2   Marek Vasut   ddr: altera: Clea...
3091
3092
3093
  	 * For AV/CV, LFIFO is hardened and always runs at full rate
  	 * so max latency in AFI clocks, used here, is correspondingly
  	 * smaller.
3da428595   Dinh Nguyen   driver/ddr/altera...
3094
  	 */
96fd4362c   Marek Vasut   ddr: altera: sequ...
3095
  	const u32 max_latency = (1 << misccfg->max_latency_count_width) - 1;
16502a0b2   Marek Vasut   ddr: altera: Clea...
3096
  	u32 rlat, wlat;
3da428595   Dinh Nguyen   driver/ddr/altera...
3097

16502a0b2   Marek Vasut   ddr: altera: Clea...
3098
3099
  	debug("%s:%d
  ", __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
3100
3101
  
  	/*
16502a0b2   Marek Vasut   ddr: altera: Clea...
3102
3103
  	 * Read in write latency.
  	 * WL for Hard PHY does not include additive latency.
3da428595   Dinh Nguyen   driver/ddr/altera...
3104
  	 */
16502a0b2   Marek Vasut   ddr: altera: Clea...
3105
3106
  	wlat = readl(&data_mgr->t_wl_add);
  	wlat += readl(&data_mgr->mem_t_add);
3da428595   Dinh Nguyen   driver/ddr/altera...
3107

16502a0b2   Marek Vasut   ddr: altera: Clea...
3108
  	gbl->rw_wl_nop_cycles = wlat - 1;
3da428595   Dinh Nguyen   driver/ddr/altera...
3109

16502a0b2   Marek Vasut   ddr: altera: Clea...
3110
3111
  	/* Read in readl latency. */
  	rlat = readl(&data_mgr->t_rl_add);
3da428595   Dinh Nguyen   driver/ddr/altera...
3112

16502a0b2   Marek Vasut   ddr: altera: Clea...
3113
3114
  	/* Set a pretty high read latency initially. */
  	gbl->curr_read_lat = rlat + 16;
3da428595   Dinh Nguyen   driver/ddr/altera...
3115
3116
  	if (gbl->curr_read_lat > max_latency)
  		gbl->curr_read_lat = max_latency;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3117
  	writel(gbl->curr_read_lat, &phy_mgr_cfg->phy_rlat);
3da428595   Dinh Nguyen   driver/ddr/altera...
3118

16502a0b2   Marek Vasut   ddr: altera: Clea...
3119
3120
  	/* Advertise write latency. */
  	writel(wlat, &phy_mgr_cfg->afi_wlat);
3da428595   Dinh Nguyen   driver/ddr/altera...
3121
  }
51cea0b6c   Marek Vasut   ddr: altera: Mino...
3122
3123
3124
3125
3126
  /**
   * @mem_skip_calibrate() - Set VFIFO and LFIFO to instant-on settings
   *
   * Set VFIFO and LFIFO to instant-on settings in skip calibration mode.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3127
3128
  static void mem_skip_calibrate(void)
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
3129
3130
  	u32 vfifo_offset;
  	u32 i, j, r;
3da428595   Dinh Nguyen   driver/ddr/altera...
3131
3132
3133
3134
  
  	debug("%s:%d
  ", __func__, __LINE__);
  	/* Need to update every shadow register set used by the interface */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3135
  	for (r = 0; r < rwcfg->mem_number_of_ranks;
51cea0b6c   Marek Vasut   ddr: altera: Mino...
3136
  	     r += NUM_RANKS_PER_SHADOW_REG) {
3da428595   Dinh Nguyen   driver/ddr/altera...
3137
3138
3139
3140
  		/*
  		 * Set output phase alignment settings appropriate for
  		 * skip calibration.
  		 */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3141
  		for (i = 0; i < rwcfg->mem_if_read_dqs_width; i++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
3142
  			scc_mgr_set_dqs_en_phase(i, 0);
160695d88   Marek Vasut   ddr: altera: sequ...
3143
3144
3145
3146
  			if (iocfg->dll_chain_length == 6)
  				scc_mgr_set_dqdqs_output_phase(i, 6);
  			else
  				scc_mgr_set_dqdqs_output_phase(i, 7);
3da428595   Dinh Nguyen   driver/ddr/altera...
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
  			/*
  			 * Case:33398
  			 *
  			 * Write data arrives to the I/O two cycles before write
  			 * latency is reached (720 deg).
  			 *   -> due to bit-slip in a/c bus
  			 *   -> to allow board skew where dqs is longer than ck
  			 *      -> how often can this happen!?
  			 *      -> can claim back some ptaps for high freq
  			 *       support if we can relax this, but i digress...
  			 *
  			 * The write_clk leads mem_ck by 90 deg
  			 * The minimum ptap of the OPA is 180 deg
  			 * Each ptap has (360 / IO_DLL_CHAIN_LENGH) deg of delay
  			 * The write_clk is always delayed by 2 ptaps
  			 *
  			 * Hence, to make DQS aligned to CK, we need to delay
  			 * DQS by:
139823ecb   Marek Vasut   ddr: altera: sequ...
3165
3166
  			 *    (720 - 90 - 180 - 2) *
  			 *      (360 / iocfg->dll_chain_length)
3da428595   Dinh Nguyen   driver/ddr/altera...
3167
  			 *
160695d88   Marek Vasut   ddr: altera: sequ...
3168
  			 * Dividing the above by (360 / iocfg->dll_chain_length)
3da428595   Dinh Nguyen   driver/ddr/altera...
3169
3170
  			 * gives us the number of ptaps, which simplies to:
  			 *
160695d88   Marek Vasut   ddr: altera: sequ...
3171
  			 *    (1.25 * iocfg->dll_chain_length - 2)
3da428595   Dinh Nguyen   driver/ddr/altera...
3172
  			 */
51cea0b6c   Marek Vasut   ddr: altera: Mino...
3173
  			scc_mgr_set_dqdqs_output_phase(i,
6d7a33301   Marek Vasut   ddr: altera: Repl...
3174
  				       ((125 * iocfg->dll_chain_length) / 100) - 2);
3da428595   Dinh Nguyen   driver/ddr/altera...
3175
  		}
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3176
3177
  		writel(0xff, &sdr_scc_mgr->dqs_ena);
  		writel(0xff, &sdr_scc_mgr->dqs_io_ena);
3da428595   Dinh Nguyen   driver/ddr/altera...
3178

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3179
  		for (i = 0; i < rwcfg->mem_if_write_dqs_width; i++) {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3180
3181
  			writel(i, SDR_PHYGRP_SCCGRP_ADDRESS |
  				  SCC_MGR_GROUP_COUNTER_OFFSET);
3da428595   Dinh Nguyen   driver/ddr/altera...
3182
  		}
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3183
3184
3185
  		writel(0xff, &sdr_scc_mgr->dq_ena);
  		writel(0xff, &sdr_scc_mgr->dm_ena);
  		writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
3186
3187
3188
  	}
  
  	/* Compensate for simulation model behaviour */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3189
  	for (i = 0; i < rwcfg->mem_if_read_dqs_width; i++) {
3da428595   Dinh Nguyen   driver/ddr/altera...
3190
3191
3192
  		scc_mgr_set_dqs_bus_in_delay(i, 10);
  		scc_mgr_load_dqs(i);
  	}
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3193
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
3194
3195
3196
3197
3198
  
  	/*
  	 * ArriaV has hard FIFOs that can only be initialized by incrementing
  	 * in sequencer.
  	 */
96fd4362c   Marek Vasut   ddr: altera: sequ...
3199
  	vfifo_offset = misccfg->calib_vfifo_offset;
51cea0b6c   Marek Vasut   ddr: altera: Mino...
3200
  	for (j = 0; j < vfifo_offset; j++)
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3201
  		writel(0xff, &phy_mgr_cmd->inc_vfifo_hard_phy);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3202
  	writel(0, &phy_mgr_cmd->fifo_reset);
3da428595   Dinh Nguyen   driver/ddr/altera...
3203
3204
  
  	/*
51cea0b6c   Marek Vasut   ddr: altera: Mino...
3205
3206
  	 * For Arria V and Cyclone V with hard LFIFO, we get the skip-cal
  	 * setting from generation-time constant.
3da428595   Dinh Nguyen   driver/ddr/altera...
3207
  	 */
96fd4362c   Marek Vasut   ddr: altera: sequ...
3208
  	gbl->curr_read_lat = misccfg->calib_lfifo_offset;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3209
  	writel(gbl->curr_read_lat, &phy_mgr_cfg->phy_rlat);
3da428595   Dinh Nguyen   driver/ddr/altera...
3210
  }
3589fbfbc   Marek Vasut   ddr: altera: Inte...
3211
3212
3213
3214
3215
  /**
   * mem_calibrate() - Memory calibration entry point.
   *
   * Perform memory calibration.
   */
5ded7320c   Marek Vasut   ddr: altera: sequ...
3216
  static u32 mem_calibrate(void)
3da428595   Dinh Nguyen   driver/ddr/altera...
3217
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
3218
3219
3220
3221
3222
3223
3224
  	u32 i;
  	u32 rank_bgn, sr;
  	u32 write_group, write_test_bgn;
  	u32 read_group, read_test_bgn;
  	u32 run_groups, current_run;
  	u32 failing_groups = 0;
  	u32 group_failed = 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
3225

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3226
3227
  	const u32 rwdqs_ratio = rwcfg->mem_if_read_dqs_width /
  				rwcfg->mem_if_write_dqs_width;
33c42bb88   Marek Vasut   ddr: altera: Inte...
3228

3da428595   Dinh Nguyen   driver/ddr/altera...
3229
3230
  	debug("%s:%d
  ", __func__, __LINE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
3231

16502a0b2   Marek Vasut   ddr: altera: Clea...
3232
  	/* Initialize the data settings */
3da428595   Dinh Nguyen   driver/ddr/altera...
3233
3234
3235
3236
3237
  	gbl->error_substage = CAL_SUBSTAGE_NIL;
  	gbl->error_stage = CAL_STAGE_NIL;
  	gbl->error_group = 0xff;
  	gbl->fom_in = 0;
  	gbl->fom_out = 0;
16502a0b2   Marek Vasut   ddr: altera: Clea...
3238
3239
3240
3241
3242
  	/* Initialize WLAT and RLAT. */
  	mem_init_latency();
  
  	/* Initialize bit slips. */
  	mem_precharge_and_activate();
3da428595   Dinh Nguyen   driver/ddr/altera...
3243

1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3244
  	for (i = 0; i < rwcfg->mem_if_read_dqs_width; i++) {
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3245
3246
  		writel(i, SDR_PHYGRP_SCCGRP_ADDRESS |
  			  SCC_MGR_GROUP_COUNTER_OFFSET);
fa5d821b6   Marek Vasut   ddr: altera: Extr...
3247
3248
3249
  		/* Only needed once to set all groups, pins, DQ, DQS, DM. */
  		if (i == 0)
  			scc_mgr_set_hhp_extras();
c5c5f5378   Marek Vasut   ddr: altera: Clea...
3250
  		scc_set_bypass_mode(i);
3da428595   Dinh Nguyen   driver/ddr/altera...
3251
  	}
722c96857   Marek Vasut   ddr: altera: Triv...
3252
  	/* Calibration is skipped. */
3da428595   Dinh Nguyen   driver/ddr/altera...
3253
3254
3255
3256
3257
3258
  	if ((dyn_calib_steps & CALIB_SKIP_ALL) == CALIB_SKIP_ALL) {
  		/*
  		 * Set VFIFO and LFIFO to instant-on settings in skip
  		 * calibration mode.
  		 */
  		mem_skip_calibrate();
3da428595   Dinh Nguyen   driver/ddr/altera...
3259

722c96857   Marek Vasut   ddr: altera: Triv...
3260
3261
3262
3263
3264
3265
3266
  		/*
  		 * Do not remove this line as it makes sure all of our
  		 * decisions have been applied.
  		 */
  		writel(0, &sdr_scc_mgr->update);
  		return 1;
  	}
3da428595   Dinh Nguyen   driver/ddr/altera...
3267

722c96857   Marek Vasut   ddr: altera: Triv...
3268
3269
3270
3271
3272
3273
3274
  	/* Calibration is not skipped. */
  	for (i = 0; i < NUM_CALIB_REPEAT; i++) {
  		/*
  		 * Zero all delay chain/phase settings for all
  		 * groups and all shadow register sets.
  		 */
  		scc_mgr_zero_all();
f085ac3b1   Marek Vasut   ddr: altera: sequ...
3275
  		run_groups = ~0;
722c96857   Marek Vasut   ddr: altera: Triv...
3276
3277
  
  		for (write_group = 0, write_test_bgn = 0; write_group
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3278
3279
  			< rwcfg->mem_if_write_dqs_width; write_group++,
  			write_test_bgn += rwcfg->mem_dq_per_write_dqs) {
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3280
  			/* Initialize the group failure */
722c96857   Marek Vasut   ddr: altera: Triv...
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
  			group_failed = 0;
  
  			current_run = run_groups & ((1 <<
  				RW_MGR_NUM_DQS_PER_WRITE_GROUP) - 1);
  			run_groups = run_groups >>
  				RW_MGR_NUM_DQS_PER_WRITE_GROUP;
  
  			if (current_run == 0)
  				continue;
  
  			writel(write_group, SDR_PHYGRP_SCCGRP_ADDRESS |
  					    SCC_MGR_GROUP_COUNTER_OFFSET);
  			scc_mgr_zero_group(write_group, 0);
33c42bb88   Marek Vasut   ddr: altera: Inte...
3294
3295
  			for (read_group = write_group * rwdqs_ratio,
  			     read_test_bgn = 0;
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3296
  			     read_group < (write_group + 1) * rwdqs_ratio;
33c42bb88   Marek Vasut   ddr: altera: Inte...
3297
  			     read_group++,
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3298
  			     read_test_bgn += rwcfg->mem_dq_per_read_dqs) {
33c42bb88   Marek Vasut   ddr: altera: Inte...
3299
3300
  				if (STATIC_CALIB_STEPS & CALIB_SKIP_VFIFO)
  					continue;
722c96857   Marek Vasut   ddr: altera: Triv...
3301
  				/* Calibrate the VFIFO */
33c42bb88   Marek Vasut   ddr: altera: Inte...
3302
3303
3304
  				if (rw_mgr_mem_calibrate_vfifo(read_group,
  							       read_test_bgn))
  					continue;
139823ecb   Marek Vasut   ddr: altera: sequ...
3305
3306
  				if (!(gbl->phy_debug_mode_flags &
  				      PHY_DEBUG_SWEEP_ALL_GROUPS))
33c42bb88   Marek Vasut   ddr: altera: Inte...
3307
  					return 0;
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3308
3309
3310
  
  				/* The group failed, we're done. */
  				goto grp_failed;
722c96857   Marek Vasut   ddr: altera: Triv...
3311
  			}
3da428595   Dinh Nguyen   driver/ddr/altera...
3312

722c96857   Marek Vasut   ddr: altera: Triv...
3313
  			/* Calibrate the output side */
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3314
  			for (rank_bgn = 0, sr = 0;
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3315
  			     rank_bgn < rwcfg->mem_number_of_ranks;
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3316
3317
3318
  			     rank_bgn += NUM_RANKS_PER_SHADOW_REG, sr++) {
  				if (STATIC_CALIB_STEPS & CALIB_SKIP_WRITES)
  					continue;
4ac216101   Marek Vasut   ddr: altera: Inte...
3319

c452dcd0b   Marek Vasut   ddr: altera: Inte...
3320
  				/* Not needed in quick mode! */
139823ecb   Marek Vasut   ddr: altera: sequ...
3321
3322
  				if (STATIC_CALIB_STEPS &
  				    CALIB_SKIP_DELAY_SWEEPS)
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3323
  					continue;
4ac216101   Marek Vasut   ddr: altera: Inte...
3324

c452dcd0b   Marek Vasut   ddr: altera: Inte...
3325
  				/* Calibrate WRITEs */
db3a60615   Marek Vasut   ddr: altera: Clea...
3326
  				if (!rw_mgr_mem_calibrate_writes(rank_bgn,
139823ecb   Marek Vasut   ddr: altera: sequ...
3327
3328
  								 write_group,
  								 write_test_bgn))
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3329
  					continue;
4ac216101   Marek Vasut   ddr: altera: Inte...
3330

c452dcd0b   Marek Vasut   ddr: altera: Inte...
3331
  				group_failed = 1;
139823ecb   Marek Vasut   ddr: altera: sequ...
3332
3333
  				if (!(gbl->phy_debug_mode_flags &
  				      PHY_DEBUG_SWEEP_ALL_GROUPS))
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3334
  					return 0;
722c96857   Marek Vasut   ddr: altera: Triv...
3335
  			}
3da428595   Dinh Nguyen   driver/ddr/altera...
3336

c452dcd0b   Marek Vasut   ddr: altera: Inte...
3337
3338
3339
3340
3341
3342
3343
3344
  			/* Some group failed, we're done. */
  			if (group_failed)
  				goto grp_failed;
  
  			for (read_group = write_group * rwdqs_ratio,
  			     read_test_bgn = 0;
  			     read_group < (write_group + 1) * rwdqs_ratio;
  			     read_group++,
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3345
  			     read_test_bgn += rwcfg->mem_dq_per_read_dqs) {
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3346
3347
  				if (STATIC_CALIB_STEPS & CALIB_SKIP_WRITES)
  					continue;
78cdd7d0c   Marek Vasut   ddr: altera: Clea...
3348
  				if (!rw_mgr_mem_calibrate_vfifo_end(read_group,
139823ecb   Marek Vasut   ddr: altera: sequ...
3349
  								    read_test_bgn))
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3350
  					continue;
139823ecb   Marek Vasut   ddr: altera: sequ...
3351
3352
  				if (!(gbl->phy_debug_mode_flags &
  				      PHY_DEBUG_SWEEP_ALL_GROUPS))
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3353
3354
3355
3356
  					return 0;
  
  				/* The group failed, we're done. */
  				goto grp_failed;
3da428595   Dinh Nguyen   driver/ddr/altera...
3357
  			}
c452dcd0b   Marek Vasut   ddr: altera: Inte...
3358
3359
3360
3361
3362
  			/* No group failed, continue as usual. */
  			continue;
  
  grp_failed:		/* A group failed, increment the counter. */
  			failing_groups++;
722c96857   Marek Vasut   ddr: altera: Triv...
3363
3364
3365
3366
3367
3368
3369
3370
  		}
  
  		/*
  		 * USER If there are any failing groups then report
  		 * the failure.
  		 */
  		if (failing_groups != 0)
  			return 0;
c50ae3034   Marek Vasut   ddr: altera: Inte...
3371
3372
  		if (STATIC_CALIB_STEPS & CALIB_SKIP_LFIFO)
  			continue;
722c96857   Marek Vasut   ddr: altera: Triv...
3373
  		/* Calibrate the LFIFO */
c50ae3034   Marek Vasut   ddr: altera: Inte...
3374
3375
  		if (!rw_mgr_mem_calibrate_lfifo())
  			return 0;
3da428595   Dinh Nguyen   driver/ddr/altera...
3376
3377
3378
3379
3380
3381
  	}
  
  	/*
  	 * Do not remove this line as it makes sure all of our decisions
  	 * have been applied.
  	 */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3382
  	writel(0, &sdr_scc_mgr->update);
3da428595   Dinh Nguyen   driver/ddr/altera...
3383
3384
  	return 1;
  }
23a040c04   Marek Vasut   ddr: altera: Clea...
3385
3386
3387
3388
3389
3390
  /**
   * run_mem_calibrate() - Perform memory calibration
   *
   * This function triggers the entire memory calibration procedure.
   */
  static int run_mem_calibrate(void)
3da428595   Dinh Nguyen   driver/ddr/altera...
3391
  {
23a040c04   Marek Vasut   ddr: altera: Clea...
3392
  	int pass;
bba771109   Marek Vasut   ddr: altera: Twea...
3393
  	u32 ctrl_cfg;
3da428595   Dinh Nguyen   driver/ddr/altera...
3394
3395
3396
3397
3398
  
  	debug("%s:%d
  ", __func__, __LINE__);
  
  	/* Reset pass/fail status shown on afi_cal_success/fail */
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3399
  	writel(PHY_MGR_CAL_RESET, &phy_mgr_cfg->cal_status);
3da428595   Dinh Nguyen   driver/ddr/altera...
3400

23a040c04   Marek Vasut   ddr: altera: Clea...
3401
  	/* Stop tracking manager. */
bba771109   Marek Vasut   ddr: altera: Twea...
3402
3403
3404
  	ctrl_cfg = readl(&sdr_ctrl->ctrl_cfg);
  	writel(ctrl_cfg & ~SDR_CTRLGRP_CTRLCFG_DQSTRKEN_MASK,
  	       &sdr_ctrl->ctrl_cfg);
3da428595   Dinh Nguyen   driver/ddr/altera...
3405

9fa9c90e7   Marek Vasut   ddr: altera: Rena...
3406
  	phy_mgr_initialize();
3da428595   Dinh Nguyen   driver/ddr/altera...
3407
  	rw_mgr_mem_initialize();
23a040c04   Marek Vasut   ddr: altera: Clea...
3408
  	/* Perform the actual memory calibration. */
3da428595   Dinh Nguyen   driver/ddr/altera...
3409
3410
3411
  	pass = mem_calibrate();
  
  	mem_precharge_and_activate();
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3412
  	writel(0, &phy_mgr_cmd->fifo_reset);
3da428595   Dinh Nguyen   driver/ddr/altera...
3413

23a040c04   Marek Vasut   ddr: altera: Clea...
3414
3415
  	/* Handoff. */
  	rw_mgr_mem_handoff();
3da428595   Dinh Nguyen   driver/ddr/altera...
3416
  	/*
23a040c04   Marek Vasut   ddr: altera: Clea...
3417
3418
3419
  	 * In Hard PHY this is a 2-bit control:
  	 * 0: AFI Mux Select
  	 * 1: DDIO Mux Select
3da428595   Dinh Nguyen   driver/ddr/altera...
3420
  	 */
23a040c04   Marek Vasut   ddr: altera: Clea...
3421
  	writel(0x2, &phy_mgr_cfg->mux_sel);
3da428595   Dinh Nguyen   driver/ddr/altera...
3422

23a040c04   Marek Vasut   ddr: altera: Clea...
3423
  	/* Start tracking manager. */
bba771109   Marek Vasut   ddr: altera: Twea...
3424
  	writel(ctrl_cfg, &sdr_ctrl->ctrl_cfg);
23a040c04   Marek Vasut   ddr: altera: Clea...
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
3436
3437
  
  	return pass;
  }
  
  /**
   * debug_mem_calibrate() - Report result of memory calibration
   * @pass:	Value indicating whether calibration passed or failed
   *
   * This function reports the results of the memory calibration
   * and writes debug information into the register file.
   */
  static void debug_mem_calibrate(int pass)
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
3438
  	u32 debug_info;
3da428595   Dinh Nguyen   driver/ddr/altera...
3439
3440
3441
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
  
  	if (pass) {
  		printf("%s: CALIBRATION PASSED
  ", __FILE__);
  
  		gbl->fom_in /= 2;
  		gbl->fom_out /= 2;
  
  		if (gbl->fom_in > 0xff)
  			gbl->fom_in = 0xff;
  
  		if (gbl->fom_out > 0xff)
  			gbl->fom_out = 0xff;
  
  		/* Update the FOM in the register file */
  		debug_info = gbl->fom_in;
  		debug_info |= gbl->fom_out << 8;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3456
  		writel(debug_info, &sdr_reg_file->fom);
3da428595   Dinh Nguyen   driver/ddr/altera...
3457

1273dd9ea   Marek Vasut   ddr: altera: Mass...
3458
3459
  		writel(debug_info, &phy_mgr_cfg->cal_debug_info);
  		writel(PHY_MGR_CAL_SUCCESS, &phy_mgr_cfg->cal_status);
3da428595   Dinh Nguyen   driver/ddr/altera...
3460
3461
3462
3463
3464
3465
3466
  	} else {
  		printf("%s: CALIBRATION FAILED
  ", __FILE__);
  
  		debug_info = gbl->error_stage;
  		debug_info |= gbl->error_substage << 8;
  		debug_info |= gbl->error_group << 16;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3467
3468
3469
  		writel(debug_info, &sdr_reg_file->failing_stage);
  		writel(debug_info, &phy_mgr_cfg->cal_debug_info);
  		writel(PHY_MGR_CAL_FAIL, &phy_mgr_cfg->cal_status);
3da428595   Dinh Nguyen   driver/ddr/altera...
3470
3471
3472
3473
3474
  
  		/* Update the failing group/stage in the register file */
  		debug_info = gbl->error_stage;
  		debug_info |= gbl->error_substage << 8;
  		debug_info |= gbl->error_group << 16;
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3475
  		writel(debug_info, &sdr_reg_file->failing_stage);
3da428595   Dinh Nguyen   driver/ddr/altera...
3476
  	}
23a040c04   Marek Vasut   ddr: altera: Clea...
3477
3478
  	printf("%s: Calibration complete
  ", __FILE__);
3da428595   Dinh Nguyen   driver/ddr/altera...
3479
  }
bb06434bb   Marek Vasut   ddr: altera: Clea...
3480
3481
3482
3483
3484
  /**
   * hc_initialize_rom_data() - Initialize ROM data
   *
   * Initialize ROM data.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3485
3486
  static void hc_initialize_rom_data(void)
  {
04955cf24   Marek Vasut   ddr: altera: sequ...
3487
3488
  	unsigned int nelem = 0;
  	const u32 *rom_init;
bb06434bb   Marek Vasut   ddr: altera: Clea...
3489
  	u32 i, addr;
3da428595   Dinh Nguyen   driver/ddr/altera...
3490

04955cf24   Marek Vasut   ddr: altera: sequ...
3491
  	socfpga_get_seq_inst_init(&rom_init, &nelem);
c4815f767   Marek Vasut   ddr: altera: Pluc...
3492
  	addr = SDR_PHYGRP_RWMGRGRP_ADDRESS | RW_MGR_INST_ROM_WRITE_OFFSET;
04955cf24   Marek Vasut   ddr: altera: sequ...
3493
3494
  	for (i = 0; i < nelem; i++)
  		writel(rom_init[i], addr + (i << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
3495

04955cf24   Marek Vasut   ddr: altera: sequ...
3496
  	socfpga_get_seq_ac_init(&rom_init, &nelem);
c4815f767   Marek Vasut   ddr: altera: Pluc...
3497
  	addr = SDR_PHYGRP_RWMGRGRP_ADDRESS | RW_MGR_AC_ROM_WRITE_OFFSET;
04955cf24   Marek Vasut   ddr: altera: sequ...
3498
3499
  	for (i = 0; i < nelem; i++)
  		writel(rom_init[i], addr + (i << 2));
3da428595   Dinh Nguyen   driver/ddr/altera...
3500
  }
9c1ab2ca1   Marek Vasut   ddr: altera: Clea...
3501
3502
3503
3504
3505
  /**
   * initialize_reg_file() - Initialize SDR register file
   *
   * Initialize SDR register file.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3506
3507
  static void initialize_reg_file(void)
  {
3da428595   Dinh Nguyen   driver/ddr/altera...
3508
  	/* Initialize the register file with the correct data */
96fd4362c   Marek Vasut   ddr: altera: sequ...
3509
  	writel(misccfg->reg_file_init_seq_signature, &sdr_reg_file->signature);
1273dd9ea   Marek Vasut   ddr: altera: Mass...
3510
3511
3512
3513
3514
3515
  	writel(0, &sdr_reg_file->debug_data_addr);
  	writel(0, &sdr_reg_file->cur_stage);
  	writel(0, &sdr_reg_file->fom);
  	writel(0, &sdr_reg_file->failing_stage);
  	writel(0, &sdr_reg_file->debug1);
  	writel(0, &sdr_reg_file->debug2);
3da428595   Dinh Nguyen   driver/ddr/altera...
3516
  }
2ca151f86   Marek Vasut   ddr: altera: Clea...
3517
3518
3519
3520
3521
  /**
   * initialize_hps_phy() - Initialize HPS PHY
   *
   * Initialize HPS PHY.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3522
3523
  static void initialize_hps_phy(void)
  {
5ded7320c   Marek Vasut   ddr: altera: sequ...
3524
  	u32 reg;
3da428595   Dinh Nguyen   driver/ddr/altera...
3525
3526
3527
3528
  	/*
  	 * Tracking also gets configured here because it's in the
  	 * same register.
  	 */
5ded7320c   Marek Vasut   ddr: altera: sequ...
3529
3530
  	u32 trk_sample_count = 7500;
  	u32 trk_long_idle_sample_count = (10 << 16) | 100;
3da428595   Dinh Nguyen   driver/ddr/altera...
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
  	/*
  	 * Format is number of outer loops in the 16 MSB, sample
  	 * count in 16 LSB.
  	 */
  
  	reg = 0;
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ACDELAYEN_SET(2);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQDELAYEN_SET(1);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQSDELAYEN_SET(1);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_DQSLOGICDELAYEN_SET(1);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_RESETDELAYEN_SET(0);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_LPDDRDIS_SET(1);
  	/*
  	 * This field selects the intrinsic latency to RDATA_EN/FULL path.
  	 * 00-bypass, 01- add 5 cycles, 10- add 10 cycles, 11- add 15 cycles.
  	 */
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_ADDLATSEL_SET(0);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_SAMPLECOUNT_19_0_SET(
  		trk_sample_count);
6cb9f1678   Marek Vasut   ddr: altera: Stop...
3550
  	writel(reg, &sdr_ctrl->phy_ctrl0);
3da428595   Dinh Nguyen   driver/ddr/altera...
3551
3552
3553
3554
3555
3556
3557
  
  	reg = 0;
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_SAMPLECOUNT_31_20_SET(
  		trk_sample_count >>
  		SDR_CTRLGRP_PHYCTRL_PHYCTRL_0_SAMPLECOUNT_19_0_WIDTH);
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_LONGIDLESAMPLECOUNT_19_0_SET(
  		trk_long_idle_sample_count);
6cb9f1678   Marek Vasut   ddr: altera: Stop...
3558
  	writel(reg, &sdr_ctrl->phy_ctrl1);
3da428595   Dinh Nguyen   driver/ddr/altera...
3559
3560
3561
3562
3563
  
  	reg = 0;
  	reg |= SDR_CTRLGRP_PHYCTRL_PHYCTRL_2_LONGIDLESAMPLECOUNT_31_20_SET(
  		trk_long_idle_sample_count >>
  		SDR_CTRLGRP_PHYCTRL_PHYCTRL_1_LONGIDLESAMPLECOUNT_19_0_WIDTH);
6cb9f1678   Marek Vasut   ddr: altera: Stop...
3564
  	writel(reg, &sdr_ctrl->phy_ctrl2);
3da428595   Dinh Nguyen   driver/ddr/altera...
3565
  }
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3566
3567
3568
3569
3570
  /**
   * initialize_tracking() - Initialize tracking
   *
   * Initialize the register file with usable initial data.
   */
3da428595   Dinh Nguyen   driver/ddr/altera...
3571
3572
  static void initialize_tracking(void)
  {
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3573
3574
3575
3576
3577
  	/*
  	 * Initialize the register file with the correct data.
  	 * Compute usable version of value in case we skip full
  	 * computation later.
  	 */
139823ecb   Marek Vasut   ddr: altera: sequ...
3578
3579
  	writel(DIV_ROUND_UP(iocfg->delay_per_opa_tap,
  			    iocfg->delay_per_dchain_tap) - 1,
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3580
3581
3582
3583
3584
3585
3586
  	       &sdr_reg_file->dtaps_per_ptap);
  
  	/* trk_sample_count */
  	writel(7500, &sdr_reg_file->trk_sample_count);
  
  	/* longidle outer loop [15:0] */
  	writel((10 << 16) | (100 << 0), &sdr_reg_file->trk_longidle);
3da428595   Dinh Nguyen   driver/ddr/altera...
3587
3588
  
  	/*
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3589
3590
3591
3592
  	 * longidle sample count [31:24]
  	 * trfc, worst case of 933Mhz 4Gb [23:16]
  	 * trcd, worst case [15:8]
  	 * vfifo wait [7:0]
3da428595   Dinh Nguyen   driver/ddr/altera...
3593
  	 */
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3594
3595
  	writel((243 << 24) | (14 << 16) | (10 << 8) | (4 << 0),
  	       &sdr_reg_file->delays);
3da428595   Dinh Nguyen   driver/ddr/altera...
3596

880e46f2d   Marek Vasut   ddr: altera: Rewo...
3597
  	/* mux delay */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3598
3599
  	writel((rwcfg->idle << 24) | (rwcfg->activate_1 << 16) |
  	       (rwcfg->sgle_read << 8) | (rwcfg->precharge_all << 0),
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3600
  	       &sdr_reg_file->trk_rw_mgr_addr);
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3601
  	writel(rwcfg->mem_if_read_dqs_width,
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3602
3603
3604
  	       &sdr_reg_file->trk_read_dqs_width);
  
  	/* trefi [7:0] */
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3605
  	writel((rwcfg->refresh_all << 24) | (1000 << 0),
880e46f2d   Marek Vasut   ddr: altera: Rewo...
3606
  	       &sdr_reg_file->trk_rfsh);
3da428595   Dinh Nguyen   driver/ddr/altera...
3607
3608
3609
3610
3611
3612
  }
  
  int sdram_calibration_full(void)
  {
  	struct param_type my_param;
  	struct gbl_type my_gbl;
5ded7320c   Marek Vasut   ddr: altera: sequ...
3613
  	u32 pass;
84e0b0cf2   Marek Vasut   ddr: altera: Init...
3614
3615
3616
  
  	memset(&my_param, 0, sizeof(my_param));
  	memset(&my_gbl, 0, sizeof(my_gbl));
3da428595   Dinh Nguyen   driver/ddr/altera...
3617
3618
3619
  
  	param = &my_param;
  	gbl = &my_gbl;
d718a26b0   Marek Vasut   ddr: altera: sequ...
3620
  	rwcfg = socfpga_get_sdram_rwmgr_config();
10c14261f   Marek Vasut   ddr: altera: sequ...
3621
  	iocfg = socfpga_get_sdram_io_config();
042ff2d0f   Marek Vasut   ddr: altera: sequ...
3622
  	misccfg = socfpga_get_sdram_misc_config();
d718a26b0   Marek Vasut   ddr: altera: sequ...
3623

3da428595   Dinh Nguyen   driver/ddr/altera...
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
  	/* Set the calibration enabled by default */
  	gbl->phy_debug_mode_flags |= PHY_DEBUG_ENABLE_CAL_RPT;
  	/*
  	 * Only sweep all groups (regardless of fail state) by default
  	 * Set enabled read test by default.
  	 */
  #if DISABLE_GUARANTEED_READ
  	gbl->phy_debug_mode_flags |= PHY_DEBUG_DISABLE_GUARANTEED_READ;
  #endif
  	/* Initialize the register file */
  	initialize_reg_file();
  
  	/* Initialize any PHY CSR */
  	initialize_hps_phy();
  
  	scc_mgr_initialize();
  
  	initialize_tracking();
3da428595   Dinh Nguyen   driver/ddr/altera...
3642
3643
3644
3645
3646
  	printf("%s: Preparing to start memory calibration
  ", __FILE__);
  
  	debug("%s:%d
  ", __func__, __LINE__);
23f62b36d   Marek Vasut   ddr: altera: Clea...
3647
3648
  	debug_cond(DLEVEL == 1,
  		   "DDR3 FULL_RATE ranks=%u cs/dimm=%u dq/dqs=%u,%u vg/dqs=%u,%u ",
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3649
3650
3651
3652
  		   rwcfg->mem_number_of_ranks, rwcfg->mem_number_of_cs_per_dimm,
  		   rwcfg->mem_dq_per_read_dqs, rwcfg->mem_dq_per_write_dqs,
  		   rwcfg->mem_virtual_groups_per_read_dqs,
  		   rwcfg->mem_virtual_groups_per_write_dqs);
23f62b36d   Marek Vasut   ddr: altera: Clea...
3653
3654
  	debug_cond(DLEVEL == 1,
  		   "dqs=%u,%u dq=%u dm=%u ptap_delay=%u dtap_delay=%u ",
1fa0c8c4e   Marek Vasut   ddr: altera: sequ...
3655
3656
  		   rwcfg->mem_if_read_dqs_width, rwcfg->mem_if_write_dqs_width,
  		   rwcfg->mem_data_width, rwcfg->mem_data_mask_width,
160695d88   Marek Vasut   ddr: altera: sequ...
3657
  		   iocfg->delay_per_opa_tap, iocfg->delay_per_dchain_tap);
23f62b36d   Marek Vasut   ddr: altera: Clea...
3658
  	debug_cond(DLEVEL == 1, "dtap_dqsen_delay=%u, dll=%u",
160695d88   Marek Vasut   ddr: altera: sequ...
3659
  		   iocfg->delay_per_dqs_en_dchain_tap, iocfg->dll_chain_length);
139823ecb   Marek Vasut   ddr: altera: sequ...
3660
3661
  	debug_cond(DLEVEL == 1,
  		   "max values: en_p=%u dqdqs_p=%u en_d=%u dqs_in_d=%u ",
160695d88   Marek Vasut   ddr: altera: sequ...
3662
3663
  		   iocfg->dqs_en_phase_max, iocfg->dqdqs_out_phase_max,
  		   iocfg->dqs_en_delay_max, iocfg->dqs_in_delay_max);
23f62b36d   Marek Vasut   ddr: altera: Clea...
3664
  	debug_cond(DLEVEL == 1, "io_in_d=%u io_out1_d=%u io_out2_d=%u ",
160695d88   Marek Vasut   ddr: altera: sequ...
3665
3666
  		   iocfg->io_in_delay_max, iocfg->io_out1_delay_max,
  		   iocfg->io_out2_delay_max);
23f62b36d   Marek Vasut   ddr: altera: Clea...
3667
3668
  	debug_cond(DLEVEL == 1, "dqs_in_reserve=%u dqs_out_reserve=%u
  ",
160695d88   Marek Vasut   ddr: altera: sequ...
3669
  		   iocfg->dqs_in_reserve, iocfg->dqs_out_reserve);
3da428595   Dinh Nguyen   driver/ddr/altera...
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
3680
3681
3682
3683
3684
3685
3686
3687
3688
3689
3690
3691
  
  	hc_initialize_rom_data();
  
  	/* update info for sims */
  	reg_file_set_stage(CAL_STAGE_NIL);
  	reg_file_set_group(0);
  
  	/*
  	 * Load global needed for those actions that require
  	 * some dynamic calibration support.
  	 */
  	dyn_calib_steps = STATIC_CALIB_STEPS;
  	/*
  	 * Load global to allow dynamic selection of delay loop settings
  	 * based on calibration mode.
  	 */
  	if (!(dyn_calib_steps & CALIB_SKIP_DELAY_LOOPS))
  		skip_delay_mask = 0xff;
  	else
  		skip_delay_mask = 0x0;
  
  	pass = run_mem_calibrate();
23a040c04   Marek Vasut   ddr: altera: Clea...
3692
  	debug_mem_calibrate(pass);
3da428595   Dinh Nguyen   driver/ddr/altera...
3693
3694
  	return pass;
  }