ddr3_training_hw_algo.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. /*
  2. * Copyright (C) Marvell International Ltd. and its affiliates
  3. *
  4. * SPDX-License-Identifier: GPL-2.0
  5. */
  6. #include <common.h>
  7. #include <spl.h>
  8. #include <asm/io.h>
  9. #include <asm/arch/cpu.h>
  10. #include <asm/arch/soc.h>
  11. #include "ddr3_init.h"
  12. #define VREF_INITIAL_STEP 3
  13. #define VREF_SECOND_STEP 1
  14. #define VREF_MAX_INDEX 7
  15. #define MAX_VALUE (1024 - 1)
  16. #define MIN_VALUE (-MAX_VALUE)
  17. #define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0xf)
  18. u32 ck_delay = (u32)-1, ck_delay_16 = (u32)-1;
  19. u32 ca_delay;
  20. int ddr3_tip_centr_skip_min_win_check = 0;
  21. u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  22. u8 last_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  23. u16 current_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  24. u16 last_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  25. u8 lim_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  26. u8 interface_state[MAX_INTERFACE_NUM];
  27. u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
  28. u8 vref_window_size_th = 12;
  29. static u8 pup_st[MAX_BUS_NUM][MAX_INTERFACE_NUM];
  30. static u32 rd_sample_mask[] = {
  31. 0,
  32. 8,
  33. 16,
  34. 24
  35. };
  36. #define VREF_STEP_1 0
  37. #define VREF_STEP_2 1
  38. #define VREF_CONVERGE 2
  39. /*
  40. * ODT additional timing
  41. */
  42. int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id)
  43. {
  44. u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0;
  45. u32 data_read[MAX_INTERFACE_NUM] = { 0 };
  46. u32 read_sample[MAX_CS_NUM];
  47. u32 val;
  48. u32 pup_index;
  49. int max_phase = MIN_VALUE, current_phase;
  50. enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
  51. struct hws_topology_map *tm = ddr3_get_topology_map();
  52. CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
  53. DUNIT_ODT_CONTROL_REG,
  54. 0 << 8, 0x3 << 8));
  55. CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id,
  56. READ_DATA_SAMPLE_DELAY,
  57. data_read, MASK_ALL_BITS));
  58. val = data_read[if_id];
  59. for (cs_num = 0; cs_num < MAX_CS_NUM; cs_num++) {
  60. read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num);
  61. /* find maximum of read_samples */
  62. if (read_sample[cs_num] >= max_read_sample) {
  63. if (read_sample[cs_num] == max_read_sample)
  64. max_phase = MIN_VALUE;
  65. else
  66. max_read_sample = read_sample[cs_num];
  67. for (pup_index = 0;
  68. pup_index < tm->num_of_bus_per_interface;
  69. pup_index++) {
  70. CHECK_STATUS(ddr3_tip_bus_read
  71. (dev_num, if_id,
  72. ACCESS_TYPE_UNICAST, pup_index,
  73. DDR_PHY_DATA,
  74. RL_PHY_REG + CS_REG_VALUE(cs_num),
  75. &val));
  76. current_phase = ((int)val & 0xe0) >> 6;
  77. if (current_phase >= max_phase)
  78. max_phase = current_phase;
  79. }
  80. }
  81. /* find minimum */
  82. if (read_sample[cs_num] < min_read_sample)
  83. min_read_sample = read_sample[cs_num];
  84. }
  85. min_read_sample = min_read_sample - 1;
  86. max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1;
  87. if (min_read_sample >= 0xf)
  88. min_read_sample = 0xf;
  89. if (max_read_sample >= 0x1f)
  90. max_read_sample = 0x1f;
  91. CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
  92. ODT_TIMING_LOW,
  93. ((min_read_sample - 1) << 12),
  94. 0xf << 12));
  95. CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
  96. ODT_TIMING_LOW,
  97. (max_read_sample << 16),
  98. 0x1f << 16));
  99. return MV_OK;
  100. }
  101. int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4])
  102. {
  103. u32 reg_pup = RESULT_DB_PHY_REG_ADDR;
  104. u32 reg_data;
  105. u32 cs_num;
  106. int i;
  107. cs_num = 0;
  108. /* TBD */
  109. reg_pup += cs_num;
  110. for (i = 0; i < 4; i++) {
  111. CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
  112. ACCESS_TYPE_UNICAST, i,
  113. DDR_PHY_DATA, reg_pup,
  114. &reg_data));
  115. res[i] = (reg_data >> RESULT_DB_PHY_REG_RX_OFFSET) & 0x1f;
  116. }
  117. return 0;
  118. }
  119. /*
  120. * This algorithm deals with the vertical optimum from Voltage point of view
  121. * of the sample signal.
  122. * Voltage sample point can improve the Eye / window size of the bit and the
  123. * pup.
  124. * The problem is that it is tune for all DQ the same so there isn't any
  125. * PBS like code.
  126. * It is more like centralization.
  127. * But because we don't have The training SM support we do it a bit more
  128. * smart search to save time.
  129. */
  130. int ddr3_tip_vref(u32 dev_num)
  131. {
  132. /*
  133. * The Vref register have non linear order. Need to check what will be
  134. * in future projects.
  135. */
  136. u32 vref_map[8] = {
  137. 1, 2, 3, 4, 5, 6, 7, 0
  138. };
  139. /* State and parameter definitions */
  140. u32 initial_step = VREF_INITIAL_STEP;
  141. /* need to be assign with minus ????? */
  142. u32 second_step = VREF_SECOND_STEP;
  143. u32 algo_run_flag = 0, currrent_vref = 0;
  144. u32 while_count = 0;
  145. u32 pup = 0, if_id = 0, num_pup = 0, rep = 0;
  146. u32 val = 0;
  147. u32 reg_addr = 0xa8;
  148. u32 copy_start_pattern, copy_end_pattern;
  149. enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
  150. u8 res[4];
  151. struct hws_topology_map *tm = ddr3_get_topology_map();
  152. CHECK_STATUS(ddr3_tip_special_rx(dev_num));
  153. /* save start/end pattern */
  154. copy_start_pattern = start_pattern;
  155. copy_end_pattern = end_pattern;
  156. /* set vref as centralization pattern */
  157. start_pattern = PATTERN_VREF;
  158. end_pattern = PATTERN_VREF;
  159. /* init params */
  160. for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
  161. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  162. for (pup = 0;
  163. pup < tm->num_of_bus_per_interface; pup++) {
  164. current_vref[pup][if_id] = 0;
  165. last_vref[pup][if_id] = 0;
  166. lim_vref[pup][if_id] = 0;
  167. current_valid_window[pup][if_id] = 0;
  168. last_valid_window[pup][if_id] = 0;
  169. if (vref_window_size[if_id][pup] >
  170. vref_window_size_th) {
  171. pup_st[pup][if_id] = VREF_CONVERGE;
  172. DEBUG_TRAINING_HW_ALG(
  173. DEBUG_LEVEL_INFO,
  174. ("VREF config, IF[ %d ]pup[ %d ] - Vref tune not requered (%d)\n",
  175. if_id, pup, __LINE__));
  176. } else {
  177. pup_st[pup][if_id] = VREF_STEP_1;
  178. CHECK_STATUS(ddr3_tip_bus_read
  179. (dev_num, if_id,
  180. ACCESS_TYPE_UNICAST, pup,
  181. DDR_PHY_DATA, reg_addr, &val));
  182. CHECK_STATUS(ddr3_tip_bus_write
  183. (dev_num, ACCESS_TYPE_UNICAST,
  184. if_id, ACCESS_TYPE_UNICAST,
  185. pup, DDR_PHY_DATA, reg_addr,
  186. (val & (~0xf)) | vref_map[0]));
  187. DEBUG_TRAINING_HW_ALG(
  188. DEBUG_LEVEL_INFO,
  189. ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
  190. if_id, pup,
  191. (val & (~0xf)) | vref_map[0],
  192. __LINE__));
  193. }
  194. }
  195. interface_state[if_id] = 0;
  196. }
  197. /* TODO: Set number of active interfaces */
  198. num_pup = tm->num_of_bus_per_interface * MAX_INTERFACE_NUM;
  199. while ((algo_run_flag <= num_pup) & (while_count < 10)) {
  200. while_count++;
  201. for (rep = 1; rep < 4; rep++) {
  202. ddr3_tip_centr_skip_min_win_check = 1;
  203. ddr3_tip_centralization_rx(dev_num);
  204. ddr3_tip_centr_skip_min_win_check = 0;
  205. /* Read Valid window results only for non converge pups */
  206. for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
  207. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  208. if (interface_state[if_id] != 4) {
  209. get_valid_win_rx(dev_num, if_id, res);
  210. for (pup = 0;
  211. pup < tm->num_of_bus_per_interface;
  212. pup++) {
  213. VALIDATE_ACTIVE
  214. (tm->bus_act_mask, pup);
  215. if (pup_st[pup]
  216. [if_id] ==
  217. VREF_CONVERGE)
  218. continue;
  219. current_valid_window[pup]
  220. [if_id] =
  221. (current_valid_window[pup]
  222. [if_id] * (rep - 1) +
  223. 1000 * res[pup]) / rep;
  224. }
  225. }
  226. }
  227. }
  228. for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
  229. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  230. DEBUG_TRAINING_HW_ALG(
  231. DEBUG_LEVEL_TRACE,
  232. ("current_valid_window: IF[ %d ] - ", if_id));
  233. for (pup = 0;
  234. pup < tm->num_of_bus_per_interface; pup++) {
  235. VALIDATE_ACTIVE(tm->bus_act_mask, pup);
  236. DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
  237. ("%d ",
  238. current_valid_window
  239. [pup][if_id]));
  240. }
  241. DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("\n"));
  242. }
  243. /* Compare results and respond as function of state */
  244. for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
  245. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  246. for (pup = 0;
  247. pup < tm->num_of_bus_per_interface; pup++) {
  248. VALIDATE_ACTIVE(tm->bus_act_mask, pup);
  249. DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
  250. ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n",
  251. if_id, pup,
  252. pup_st[pup]
  253. [if_id], __LINE__));
  254. if (pup_st[pup][if_id] == VREF_CONVERGE)
  255. continue;
  256. DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
  257. ("I/F[ %d ], pup[ %d ] CHECK progress - Current %d Last %d, limit VREF %d (%d)\n",
  258. if_id, pup,
  259. current_valid_window[pup]
  260. [if_id],
  261. last_valid_window[pup]
  262. [if_id], lim_vref[pup]
  263. [if_id], __LINE__));
  264. /*
  265. * The -1 is for solution resolution +/- 1 tap
  266. * of ADLL
  267. */
  268. if (current_valid_window[pup][if_id] + 200 >=
  269. (last_valid_window[pup][if_id])) {
  270. if (pup_st[pup][if_id] == VREF_STEP_1) {
  271. /*
  272. * We stay in the same state and
  273. * step just update the window
  274. * size (take the max) and Vref
  275. */
  276. if (current_vref[pup]
  277. [if_id] == VREF_MAX_INDEX) {
  278. /*
  279. * If we step to the end
  280. * and didn't converge
  281. * to some particular
  282. * better Vref value
  283. * define the pup as
  284. * converge and step
  285. * back to nominal
  286. * Vref.
  287. */
  288. pup_st[pup]
  289. [if_id] =
  290. VREF_CONVERGE;
  291. algo_run_flag++;
  292. interface_state
  293. [if_id]++;
  294. DEBUG_TRAINING_HW_ALG
  295. (DEBUG_LEVEL_TRACE,
  296. ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
  297. if_id, pup,
  298. current_vref[pup]
  299. [if_id],
  300. __LINE__));
  301. } else {
  302. /* continue to update the Vref index */
  303. current_vref[pup]
  304. [if_id] =
  305. ((current_vref[pup]
  306. [if_id] +
  307. initial_step) >
  308. VREF_MAX_INDEX) ?
  309. VREF_MAX_INDEX
  310. : (current_vref[pup]
  311. [if_id] +
  312. initial_step);
  313. if (current_vref[pup]
  314. [if_id] ==
  315. VREF_MAX_INDEX) {
  316. pup_st[pup]
  317. [if_id]
  318. =
  319. VREF_STEP_2;
  320. }
  321. lim_vref[pup]
  322. [if_id] =
  323. last_vref[pup]
  324. [if_id] =
  325. current_vref[pup]
  326. [if_id];
  327. }
  328. last_valid_window[pup]
  329. [if_id] =
  330. GET_MAX(current_valid_window
  331. [pup][if_id],
  332. last_valid_window
  333. [pup]
  334. [if_id]);
  335. /* update the Vref for next stage */
  336. currrent_vref =
  337. current_vref[pup]
  338. [if_id];
  339. CHECK_STATUS
  340. (ddr3_tip_bus_read
  341. (dev_num, if_id,
  342. ACCESS_TYPE_UNICAST, pup,
  343. DDR_PHY_DATA, reg_addr,
  344. &val));
  345. CHECK_STATUS
  346. (ddr3_tip_bus_write
  347. (dev_num,
  348. ACCESS_TYPE_UNICAST,
  349. if_id,
  350. ACCESS_TYPE_UNICAST, pup,
  351. DDR_PHY_DATA, reg_addr,
  352. (val & (~0xf)) |
  353. vref_map[currrent_vref]));
  354. DEBUG_TRAINING_HW_ALG
  355. (DEBUG_LEVEL_TRACE,
  356. ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
  357. if_id, pup,
  358. (val & (~0xf)) |
  359. vref_map[currrent_vref],
  360. __LINE__));
  361. } else if (pup_st[pup][if_id]
  362. == VREF_STEP_2) {
  363. /*
  364. * We keep on search back with
  365. * the same step size.
  366. */
  367. last_valid_window[pup]
  368. [if_id] =
  369. GET_MAX(current_valid_window
  370. [pup][if_id],
  371. last_valid_window
  372. [pup]
  373. [if_id]);
  374. last_vref[pup][if_id] =
  375. current_vref[pup]
  376. [if_id];
  377. /* we finish all search space */
  378. if ((current_vref[pup]
  379. [if_id] - second_step) == lim_vref[pup][if_id]) {
  380. /*
  381. * If we step to the end
  382. * and didn't converge
  383. * to some particular
  384. * better Vref value
  385. * define the pup as
  386. * converge and step
  387. * back to nominal
  388. * Vref.
  389. */
  390. pup_st[pup]
  391. [if_id] =
  392. VREF_CONVERGE;
  393. algo_run_flag++;
  394. interface_state
  395. [if_id]++;
  396. current_vref[pup]
  397. [if_id] =
  398. (current_vref[pup]
  399. [if_id] -
  400. second_step);
  401. DEBUG_TRAINING_HW_ALG
  402. (DEBUG_LEVEL_TRACE,
  403. ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
  404. if_id, pup,
  405. current_vref[pup]
  406. [if_id],
  407. __LINE__));
  408. } else
  409. /* we finish all search space */
  410. if (current_vref[pup]
  411. [if_id] ==
  412. lim_vref[pup]
  413. [if_id]) {
  414. /*
  415. * If we step to the end
  416. * and didn't converge
  417. * to some particular
  418. * better Vref value
  419. * define the pup as
  420. * converge and step
  421. * back to nominal
  422. * Vref.
  423. */
  424. pup_st[pup]
  425. [if_id] =
  426. VREF_CONVERGE;
  427. algo_run_flag++;
  428. interface_state
  429. [if_id]++;
  430. DEBUG_TRAINING_HW_ALG
  431. (DEBUG_LEVEL_TRACE,
  432. ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
  433. if_id, pup,
  434. current_vref[pup]
  435. [if_id],
  436. __LINE__));
  437. } else {
  438. current_vref[pup]
  439. [if_id] =
  440. current_vref[pup]
  441. [if_id] -
  442. second_step;
  443. }
  444. /* Update the Vref for next stage */
  445. currrent_vref =
  446. current_vref[pup]
  447. [if_id];
  448. CHECK_STATUS
  449. (ddr3_tip_bus_read
  450. (dev_num, if_id,
  451. ACCESS_TYPE_UNICAST, pup,
  452. DDR_PHY_DATA, reg_addr,
  453. &val));
  454. CHECK_STATUS
  455. (ddr3_tip_bus_write
  456. (dev_num,
  457. ACCESS_TYPE_UNICAST,
  458. if_id,
  459. ACCESS_TYPE_UNICAST, pup,
  460. DDR_PHY_DATA, reg_addr,
  461. (val & (~0xf)) |
  462. vref_map[currrent_vref]));
  463. DEBUG_TRAINING_HW_ALG
  464. (DEBUG_LEVEL_TRACE,
  465. ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
  466. if_id, pup,
  467. (val & (~0xf)) |
  468. vref_map[currrent_vref],
  469. __LINE__));
  470. }
  471. } else {
  472. /* we change state and change step */
  473. if (pup_st[pup][if_id] == VREF_STEP_1) {
  474. pup_st[pup][if_id] =
  475. VREF_STEP_2;
  476. lim_vref[pup][if_id] =
  477. current_vref[pup]
  478. [if_id] - initial_step;
  479. last_valid_window[pup]
  480. [if_id] =
  481. current_valid_window[pup]
  482. [if_id];
  483. last_vref[pup][if_id] =
  484. current_vref[pup]
  485. [if_id];
  486. current_vref[pup][if_id] =
  487. last_vref[pup][if_id] -
  488. second_step;
  489. /* Update the Vref for next stage */
  490. CHECK_STATUS
  491. (ddr3_tip_bus_read
  492. (dev_num, if_id,
  493. ACCESS_TYPE_UNICAST, pup,
  494. DDR_PHY_DATA, reg_addr,
  495. &val));
  496. CHECK_STATUS
  497. (ddr3_tip_bus_write
  498. (dev_num,
  499. ACCESS_TYPE_UNICAST,
  500. if_id,
  501. ACCESS_TYPE_UNICAST, pup,
  502. DDR_PHY_DATA, reg_addr,
  503. (val & (~0xf)) |
  504. vref_map[current_vref[pup]
  505. [if_id]]));
  506. DEBUG_TRAINING_HW_ALG
  507. (DEBUG_LEVEL_TRACE,
  508. ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
  509. if_id, pup,
  510. (val & (~0xf)) |
  511. vref_map[current_vref[pup]
  512. [if_id]],
  513. __LINE__));
  514. } else if (pup_st[pup][if_id] == VREF_STEP_2) {
  515. /*
  516. * The last search was the max
  517. * point set value and exit
  518. */
  519. CHECK_STATUS
  520. (ddr3_tip_bus_read
  521. (dev_num, if_id,
  522. ACCESS_TYPE_UNICAST, pup,
  523. DDR_PHY_DATA, reg_addr,
  524. &val));
  525. CHECK_STATUS
  526. (ddr3_tip_bus_write
  527. (dev_num,
  528. ACCESS_TYPE_UNICAST,
  529. if_id,
  530. ACCESS_TYPE_UNICAST, pup,
  531. DDR_PHY_DATA, reg_addr,
  532. (val & (~0xf)) |
  533. vref_map[last_vref[pup]
  534. [if_id]]));
  535. DEBUG_TRAINING_HW_ALG
  536. (DEBUG_LEVEL_TRACE,
  537. ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
  538. if_id, pup,
  539. (val & (~0xf)) |
  540. vref_map[last_vref[pup]
  541. [if_id]],
  542. __LINE__));
  543. pup_st[pup][if_id] =
  544. VREF_CONVERGE;
  545. algo_run_flag++;
  546. interface_state[if_id]++;
  547. DEBUG_TRAINING_HW_ALG
  548. (DEBUG_LEVEL_TRACE,
  549. ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
  550. if_id, pup,
  551. current_vref[pup]
  552. [if_id], __LINE__));
  553. }
  554. }
  555. }
  556. }
  557. }
  558. for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
  559. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  560. for (pup = 0;
  561. pup < tm->num_of_bus_per_interface; pup++) {
  562. VALIDATE_ACTIVE(tm->bus_act_mask, pup);
  563. CHECK_STATUS(ddr3_tip_bus_read
  564. (dev_num, if_id,
  565. ACCESS_TYPE_UNICAST, pup,
  566. DDR_PHY_DATA, reg_addr, &val));
  567. DEBUG_TRAINING_HW_ALG(
  568. DEBUG_LEVEL_INFO,
  569. ("FINAL values: I/F[ %d ], pup[ %d ] - Vref = %X (%d)\n",
  570. if_id, pup, val, __LINE__));
  571. }
  572. }
  573. flow_result[if_id] = TEST_SUCCESS;
  574. /* restore start/end pattern */
  575. start_pattern = copy_start_pattern;
  576. end_pattern = copy_end_pattern;
  577. return 0;
  578. }
  579. /*
  580. * CK/CA Delay
  581. */
  582. int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap)
  583. {
  584. u32 if_id = 0;
  585. u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0;
  586. struct hws_topology_map *tm = ddr3_get_topology_map();
  587. /*
  588. * ck_delay_table is delaying the of the clock signal only.
  589. * (to overcome timing issues between_c_k & command/address signals)
  590. */
  591. /*
  592. * ca_delay is delaying the of the entire command & Address signals
  593. * (include Clock signal to overcome DGL error on the Clock versus
  594. * the DQS).
  595. */
  596. /* Calc ADLL Tap */
  597. if ((ck_delay == -1) || (ck_delay_16 == -1)) {
  598. DEBUG_TRAINING_HW_ALG(
  599. DEBUG_LEVEL_ERROR,
  600. ("ERROR: One of ck_delay values not initialized!!!\n"));
  601. }
  602. for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
  603. VALIDATE_ACTIVE(tm->if_act_mask, if_id);
  604. /* Calc delay ps in ADLL tap */
  605. if (tm->interface_params[if_id].bus_width ==
  606. BUS_WIDTH_16)
  607. ck_num_adll_tap = ck_delay_16 / adll_tap;
  608. else
  609. ck_num_adll_tap = ck_delay / adll_tap;
  610. ca_num_adll_tap = ca_delay / adll_tap;
  611. data = (ck_num_adll_tap & 0x3f) +
  612. ((ca_num_adll_tap & 0x3f) << 10);
  613. /*
  614. * Set the ADLL number to the CK ADLL for Interfaces for
  615. * all Pup
  616. */
  617. DEBUG_TRAINING_HW_ALG(
  618. DEBUG_LEVEL_TRACE,
  619. ("ck_num_adll_tap %d ca_num_adll_tap %d adll_tap %d\n",
  620. ck_num_adll_tap, ca_num_adll_tap, adll_tap));
  621. CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
  622. if_id, ACCESS_TYPE_MULTICAST,
  623. PARAM_NOT_CARE, DDR_PHY_CONTROL,
  624. 0x0, data));
  625. }
  626. return MV_OK;
  627. }