dra7xx_iodelay.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * (C) Copyright 2015
  4. * Texas Instruments Incorporated, <www.ti.com>
  5. *
  6. * Lokesh Vutla <lokeshvutla@ti.com>
  7. */
  8. #include <common.h>
  9. #include <hang.h>
  10. #include <log.h>
  11. #include <asm/utils.h>
  12. #include <asm/arch/dra7xx_iodelay.h>
  13. #include <asm/arch/omap.h>
  14. #include <asm/arch/sys_proto.h>
  15. #include <asm/arch/clock.h>
  16. #include <asm/arch/mux_dra7xx.h>
  17. #include <asm/omap_common.h>
  18. static int isolate_io(u32 isolate)
  19. {
  20. if (isolate) {
  21. clrsetbits_le32((*ctrl)->control_pbias, SDCARD_PWRDNZ,
  22. SDCARD_PWRDNZ);
  23. clrsetbits_le32((*ctrl)->control_pbias, SDCARD_BIAS_PWRDNZ,
  24. SDCARD_BIAS_PWRDNZ);
  25. }
  26. /* Override control on ISOCLKIN signal to IO pad ring. */
  27. clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK,
  28. PMCTRL_ISOCLK_OVERRIDE_CTRL);
  29. if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK, PMCTRL_ISOCLK_STATUS_MASK,
  30. (u32 *)(*prcm)->prm_io_pmctrl, LDELAY))
  31. return ERR_DEISOLATE_IO << isolate;
  32. /* Isolate/Deisolate IO */
  33. clrsetbits_le32((*ctrl)->ctrl_core_sma_sw_0, CTRL_ISOLATE_MASK,
  34. isolate << CTRL_ISOLATE_SHIFT);
  35. /* Dummy read to add delay t > 10ns */
  36. readl((*ctrl)->ctrl_core_sma_sw_0);
  37. /* Return control on ISOCLKIN to hardware */
  38. clrsetbits_le32((*prcm)->prm_io_pmctrl, PMCTRL_ISOCLK_OVERRIDE_MASK,
  39. PMCTRL_ISOCLK_NOT_OVERRIDE_CTRL);
  40. if (!wait_on_value(PMCTRL_ISOCLK_STATUS_MASK,
  41. 0 << PMCTRL_ISOCLK_STATUS_SHIFT,
  42. (u32 *)(*prcm)->prm_io_pmctrl, LDELAY))
  43. return ERR_DEISOLATE_IO << isolate;
  44. return 0;
  45. }
  46. static int calibrate_iodelay(u32 base)
  47. {
  48. u32 reg;
  49. /* Configure REFCLK period */
  50. reg = readl(base + CFG_REG_2_OFFSET);
  51. reg &= ~CFG_REG_REFCLK_PERIOD_MASK;
  52. reg |= CFG_REG_REFCLK_PERIOD;
  53. writel(reg, base + CFG_REG_2_OFFSET);
  54. /* Initiate Calibration */
  55. clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_CALIB_STRT_MASK,
  56. CFG_REG_CALIB_STRT << CFG_REG_CALIB_STRT_SHIFT);
  57. if (!wait_on_value(CFG_REG_CALIB_STRT_MASK, CFG_REG_CALIB_END,
  58. (u32 *)(base + CFG_REG_0_OFFSET), LDELAY))
  59. return ERR_CALIBRATE_IODELAY;
  60. return 0;
  61. }
  62. static int update_delay_mechanism(u32 base)
  63. {
  64. /* Initiate the reload of calibrated values. */
  65. clrsetbits_le32(base + CFG_REG_0_OFFSET, CFG_REG_ROM_READ_MASK,
  66. CFG_REG_ROM_READ_START);
  67. if (!wait_on_value(CFG_REG_ROM_READ_MASK, CFG_REG_ROM_READ_END,
  68. (u32 *)(base + CFG_REG_0_OFFSET), LDELAY))
  69. return ERR_UPDATE_DELAY;
  70. return 0;
  71. }
  72. static u32 calculate_delay(u32 base, u16 offset, u16 den)
  73. {
  74. u16 refclk_period, dly_cnt, ref_cnt;
  75. u32 reg, q, r;
  76. refclk_period = readl(base + CFG_REG_2_OFFSET) &
  77. CFG_REG_REFCLK_PERIOD_MASK;
  78. reg = readl(base + offset);
  79. dly_cnt = (reg & CFG_REG_DLY_CNT_MASK) >> CFG_REG_DLY_CNT_SHIFT;
  80. ref_cnt = (reg & CFG_REG_REF_CNT_MASK) >> CFG_REG_REF_CNT_SHIFT;
  81. if (!dly_cnt || !den)
  82. return 0;
  83. /*
  84. * To avoid overflow and integer truncation, delay value
  85. * is calculated as quotient + remainder.
  86. */
  87. q = 5 * ((ref_cnt * refclk_period) / (dly_cnt * den));
  88. r = (10 * ((ref_cnt * refclk_period) % (dly_cnt * den))) /
  89. (2 * dly_cnt * den);
  90. return q + r;
  91. }
  92. static u32 get_cfg_reg(u16 a_delay, u16 g_delay, u32 cpde, u32 fpde)
  93. {
  94. u32 g_delay_coarse, g_delay_fine;
  95. u32 a_delay_coarse, a_delay_fine;
  96. u32 c_elements, f_elements;
  97. u32 total_delay, reg = 0;
  98. g_delay_coarse = g_delay / 920;
  99. g_delay_fine = ((g_delay % 920) * 10) / 60;
  100. a_delay_coarse = a_delay / cpde;
  101. a_delay_fine = ((a_delay % cpde) * 10) / fpde;
  102. c_elements = g_delay_coarse + a_delay_coarse;
  103. f_elements = (g_delay_fine + a_delay_fine) / 10;
  104. if (f_elements > 22) {
  105. total_delay = c_elements * cpde + f_elements * fpde;
  106. c_elements = total_delay / cpde;
  107. f_elements = (total_delay % cpde) / fpde;
  108. }
  109. reg = (c_elements << CFG_X_COARSE_DLY_SHIFT) & CFG_X_COARSE_DLY_MASK;
  110. reg |= (f_elements << CFG_X_FINE_DLY_SHIFT) & CFG_X_FINE_DLY_MASK;
  111. reg |= CFG_X_SIGNATURE << CFG_X_SIGNATURE_SHIFT;
  112. reg |= CFG_X_LOCK << CFG_X_LOCK_SHIFT;
  113. return reg;
  114. }
  115. int do_set_iodelay(u32 base, struct iodelay_cfg_entry const *array,
  116. int niodelays)
  117. {
  118. struct iodelay_cfg_entry *iodelay = (struct iodelay_cfg_entry *)array;
  119. u32 reg, cpde, fpde, i;
  120. if (!niodelays)
  121. return 0;
  122. cpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_3_OFFSET,
  123. 88);
  124. if (!cpde)
  125. return ERR_CPDE;
  126. fpde = calculate_delay((*ctrl)->iodelay_config_base, CFG_REG_4_OFFSET,
  127. 264);
  128. if (!fpde)
  129. return ERR_FPDE;
  130. for (i = 0; i < niodelays; i++, iodelay++) {
  131. reg = get_cfg_reg(iodelay->a_delay, iodelay->g_delay, cpde,
  132. fpde);
  133. writel(reg, base + iodelay->offset);
  134. }
  135. return 0;
  136. }
  137. int __recalibrate_iodelay_start(void)
  138. {
  139. int ret = 0;
  140. /* IO recalibration should be done only from SRAM */
  141. if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
  142. puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
  143. return -1;
  144. }
  145. /* unlock IODELAY CONFIG registers */
  146. writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base +
  147. CFG_REG_8_OFFSET);
  148. ret = calibrate_iodelay((*ctrl)->iodelay_config_base);
  149. if (ret)
  150. goto err;
  151. ret = isolate_io(ISOLATE_IO);
  152. if (ret)
  153. goto err;
  154. ret = update_delay_mechanism((*ctrl)->iodelay_config_base);
  155. err:
  156. return ret;
  157. }
  158. void __recalibrate_iodelay_end(int ret)
  159. {
  160. /* IO recalibration should be done only from SRAM */
  161. if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
  162. puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
  163. return;
  164. }
  165. /* Deisolate IO if it is already isolated */
  166. if (readl((*ctrl)->ctrl_core_sma_sw_0) & CTRL_ISOLATE_MASK)
  167. isolate_io(DEISOLATE_IO);
  168. /* lock IODELAY CONFIG registers */
  169. writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
  170. CFG_REG_8_OFFSET);
  171. /*
  172. * UART cannot be used during IO recalibration sequence as IOs are in
  173. * isolation. So error handling and debug prints are done after
  174. * complete IO delay recalibration sequence
  175. */
  176. switch (ret) {
  177. case ERR_CALIBRATE_IODELAY:
  178. puts("IODELAY: IO delay calibration sequence failed\n");
  179. break;
  180. case ERR_ISOLATE_IO:
  181. puts("IODELAY: Isolation of Device IOs failed\n");
  182. break;
  183. case ERR_UPDATE_DELAY:
  184. puts("IODELAY: Delay mechanism update with new calibrated values failed\n");
  185. break;
  186. case ERR_DEISOLATE_IO:
  187. puts("IODELAY: De-isolation of Device IOs failed\n");
  188. break;
  189. case ERR_CPDE:
  190. puts("IODELAY: CPDE calculation failed\n");
  191. break;
  192. case ERR_FPDE:
  193. puts("IODELAY: FPDE calculation failed\n");
  194. break;
  195. case -1:
  196. puts("IODELAY: Wrong Context call?\n");
  197. break;
  198. default:
  199. debug("IODELAY: IO delay recalibration successfully completed\n");
  200. }
  201. /* If there is an error during iodelay recalibration, SoC is in a bad
  202. * state. Do not progress any further.
  203. */
  204. if (ret)
  205. hang();
  206. return;
  207. }
  208. void __recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
  209. struct iodelay_cfg_entry const *iodelay,
  210. int niodelays)
  211. {
  212. int ret = 0;
  213. /* IO recalibration should be done only from SRAM */
  214. if (OMAP_INIT_CONTEXT_SPL != omap_hw_init_context()) {
  215. puts("IODELAY recalibration called from invalid context - use only from SPL in SRAM\n");
  216. return;
  217. }
  218. ret = __recalibrate_iodelay_start();
  219. if (ret)
  220. goto err;
  221. /* Configure Mux settings */
  222. do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
  223. /* Configure Manual IO timing modes */
  224. ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays);
  225. if (ret)
  226. goto err;
  227. err:
  228. __recalibrate_iodelay_end(ret);
  229. }
  230. void late_recalibrate_iodelay(struct pad_conf_entry const *pad, int npads,
  231. struct iodelay_cfg_entry const *iodelay,
  232. int niodelays)
  233. {
  234. int ret = 0;
  235. /* unlock IODELAY CONFIG registers */
  236. writel(CFG_IODELAY_UNLOCK_KEY, (*ctrl)->iodelay_config_base +
  237. CFG_REG_8_OFFSET);
  238. ret = calibrate_iodelay((*ctrl)->iodelay_config_base);
  239. if (ret)
  240. goto err;
  241. ret = update_delay_mechanism((*ctrl)->iodelay_config_base);
  242. /* Configure Mux settings */
  243. do_set_mux32((*ctrl)->control_padconf_core_base, pad, npads);
  244. /* Configure Manual IO timing modes */
  245. ret = do_set_iodelay((*ctrl)->iodelay_config_base, iodelay, niodelays);
  246. if (ret)
  247. goto err;
  248. err:
  249. /* lock IODELAY CONFIG registers */
  250. writel(CFG_IODELAY_LOCK_KEY, (*ctrl)->iodelay_config_base +
  251. CFG_REG_8_OFFSET);
  252. }