umc-ld20.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636
  1. /*
  2. * Copyright (C) 2016-2017 Socionext Inc.
  3. *
  4. * based on commit 5ffd75ecd4929f22361ef65a35f0331d2fbc0f35 of Diag
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <linux/bitops.h>
  10. #include <linux/compat.h>
  11. #include <linux/errno.h>
  12. #include <linux/io.h>
  13. #include <linux/sizes.h>
  14. #include <asm/processor.h>
  15. #include "../init.h"
  16. #include "ddruqphy-regs.h"
  17. #include "umc64-regs.h"
  18. #define DRAM_CH_NR 3
  19. enum dram_freq {
  20. DRAM_FREQ_1866M,
  21. DRAM_FREQ_NR,
  22. };
  23. enum dram_size {
  24. DRAM_SZ_256M,
  25. DRAM_SZ_512M,
  26. DRAM_SZ_NR,
  27. };
  28. enum dram_board { /* board type */
  29. DRAM_BOARD_LD20_REF, /* LD20 reference */
  30. DRAM_BOARD_LD20_GLOBAL, /* LD20 TV */
  31. DRAM_BOARD_LD20_C1, /* LD20 TV C1 */
  32. DRAM_BOARD_LD21_REF, /* LD21 reference */
  33. DRAM_BOARD_LD21_GLOBAL, /* LD21 TV */
  34. DRAM_BOARD_NR,
  35. };
  36. /* PHY */
  37. static const int ddrphy_adrctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
  38. {268 - 262, 268 - 263, 268 - 378}, /* LD20 reference */
  39. {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV */
  40. {268 - 262, 268 - 263, 268 - 378}, /* LD20 TV C1 */
  41. {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 reference */
  42. {268 - 212, 268 - 268, /* No CH2 */}, /* LD21 TV */
  43. };
  44. static const int ddrphy_dlltrimclk[DRAM_BOARD_NR][DRAM_CH_NR] = {
  45. {268, 268, 268}, /* LD20 reference */
  46. {268, 268, 268}, /* LD20 TV */
  47. {189, 189, 189}, /* LD20 TV C1 */
  48. {268, 268 + 252, /* No CH2 */}, /* LD21 reference */
  49. {268, 268 + 202, /* No CH2 */}, /* LD21 TV */
  50. };
  51. static const int ddrphy_dllrecalib[DRAM_BOARD_NR][DRAM_CH_NR] = {
  52. {268 - 378, 268 - 263, 268 - 378}, /* LD20 reference */
  53. {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV */
  54. {268 - 378, 268 - 263, 268 - 378}, /* LD20 TV C1 */
  55. {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 reference */
  56. {268 - 212, 268 - 536, /* No CH2 */}, /* LD21 TV */
  57. };
  58. static const u32 ddrphy_phy_pad_ctrl[DRAM_BOARD_NR][DRAM_CH_NR] = {
  59. {0x50B840B1, 0x50B840B1, 0x50B840B1}, /* LD20 reference */
  60. {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV */
  61. {0x50BB40B1, 0x50BB40B1, 0x50BB40B1}, /* LD20 TV C1 */
  62. {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 reference */
  63. {0x50BB40B4, 0x50B840B1, /* No CH2 */}, /* LD21 TV */
  64. };
  65. static const u32 ddrphy_scl_gate_timing[DRAM_CH_NR] = {
  66. 0x00000140, 0x00000180, 0x00000140
  67. };
  68. static const short ddrphy_op_dq_shift_val_ld20[DRAM_CH_NR][32] = {
  69. {
  70. 2, 1, 0, 1, 2, 1, 1, 1,
  71. 2, 1, 1, 2, 1, 1, 1, 1,
  72. 1, 2, 1, 1, 1, 2, 1, 1,
  73. 2, 2, 0, 1, 1, 2, 2, 1,
  74. },
  75. {
  76. 1, 1, 0, 1, 2, 2, 1, 1,
  77. 1, 1, 1, 1, 1, 1, 1, 1,
  78. 1, 1, 0, 0, 1, 1, 0, 0,
  79. 0, 1, 1, 1, 2, 1, 2, 1,
  80. },
  81. {
  82. 2, 2, 0, 2, 1, 1, 2, 1,
  83. 1, 1, 0, 1, 1, -1, 1, 1,
  84. 2, 2, 2, 2, 1, 1, 1, 1,
  85. 1, 1, 1, 0, 2, 2, 1, 2,
  86. },
  87. };
  88. static const short ddrphy_op_dq_shift_val_ld21[DRAM_CH_NR][32] = {
  89. {
  90. 1, 1, 0, 1, 1, 1, 1, 1,
  91. 1, 0, 0, 0, 1, 1, 0, 2,
  92. 1, 1, 0, 0, 1, 1, 1, 1,
  93. 1, 0, 0, 0, 1, 0, 0, 1,
  94. },
  95. { 1, 0, 2, 1, 1, 1, 1, 0,
  96. 1, 0, 0, 1, 0, 1, 0, 0,
  97. 1, 0, 1, 0, 1, 1, 1, 0,
  98. 1, 1, 1, 1, 0, 1, 0, 0,
  99. },
  100. /* No CH2 */
  101. };
  102. static const short (* const ddrphy_op_dq_shift_val[DRAM_BOARD_NR])[32] = {
  103. ddrphy_op_dq_shift_val_ld20, /* LD20 reference */
  104. ddrphy_op_dq_shift_val_ld20, /* LD20 TV */
  105. ddrphy_op_dq_shift_val_ld20, /* LD20 TV C */
  106. ddrphy_op_dq_shift_val_ld21, /* LD21 reference */
  107. ddrphy_op_dq_shift_val_ld21, /* LD21 TV */
  108. };
  109. static const short ddrphy_ip_dq_shift_val_ld20[DRAM_CH_NR][32] = {
  110. {
  111. 3, 3, 3, 2, 3, 2, 0, 2,
  112. 2, 3, 3, 1, 2, 2, 2, 2,
  113. 2, 2, 2, 2, 0, 1, 1, 1,
  114. 2, 2, 2, 2, 3, 0, 2, 2,
  115. },
  116. {
  117. 2, 2, 1, 1, -1, 1, 1, 1,
  118. 2, 0, 2, 2, 2, 1, 0, 2,
  119. 2, 1, 2, 1, 0, 1, 1, 1,
  120. 2, 2, 2, 2, 2, 2, 2, 2,
  121. },
  122. {
  123. 2, 2, 3, 2, 1, 2, 2, 2,
  124. 2, 3, 4, 2, 3, 4, 3, 3,
  125. 2, 2, 1, 2, 1, 1, 1, 1,
  126. 2, 2, 2, 2, 1, 2, 2, 1,
  127. },
  128. };
  129. static const short ddrphy_ip_dq_shift_val_ld21[DRAM_CH_NR][32] = {
  130. {
  131. 2, 2, 2, 2, 1, 2, 2, 2,
  132. 2, 3, 3, 2, 2, 2, 2, 2,
  133. 2, 1, 2, 2, 1, 1, 1, 1,
  134. 2, 2, 2, 3, 1, 2, 2, 2,
  135. },
  136. {
  137. 3, 4, 4, 1, 0, 1, 1, 1,
  138. 1, 2, 1, 2, 2, 3, 3, 2,
  139. 1, 0, 2, 1, 1, 0, 1, 0,
  140. 0, 1, 0, 0, 1, 1, 0, 1,
  141. },
  142. /* No CH2 */
  143. };
  144. static const short (* const ddrphy_ip_dq_shift_val[DRAM_BOARD_NR])[32] = {
  145. ddrphy_ip_dq_shift_val_ld20, /* LD20 reference */
  146. ddrphy_ip_dq_shift_val_ld20, /* LD20 TV */
  147. ddrphy_ip_dq_shift_val_ld20, /* LD20 TV C */
  148. ddrphy_ip_dq_shift_val_ld21, /* LD21 reference */
  149. ddrphy_ip_dq_shift_val_ld21, /* LD21 TV */
  150. };
  151. static void ddrphy_select_lane(void __iomem *phy_base, unsigned int lane,
  152. unsigned int bit)
  153. {
  154. WARN_ON(lane >= 1 << PHY_LANE_SEL_LANE_WIDTH);
  155. WARN_ON(bit >= 1 << PHY_LANE_SEL_BIT_WIDTH);
  156. writel((bit << PHY_LANE_SEL_BIT_SHIFT) |
  157. (lane << PHY_LANE_SEL_LANE_SHIFT),
  158. phy_base + PHY_LANE_SEL);
  159. }
  160. #define DDRPHY_EFUSEMON (void *)0x5f900118
  161. static void ddrphy_init(void __iomem *phy_base, enum dram_board board, int ch)
  162. {
  163. writel(0x0C001001, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
  164. while (!(readl(phy_base + PHY_UNIQUIFY_TSMC_IO_1) & BIT(1)))
  165. cpu_relax();
  166. if (readl(DDRPHY_EFUSEMON) & BIT(ch))
  167. writel(0x00000000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
  168. else
  169. writel(0x0C001000, phy_base + PHY_UNIQUIFY_TSMC_IO_1);
  170. writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_3);
  171. writel(0x00000000, phy_base + PHY_DLL_INCR_TRIM_1);
  172. ddrphy_select_lane(phy_base, 0, 0);
  173. writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
  174. writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
  175. ddrphy_select_lane(phy_base, 6, 0);
  176. writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
  177. writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
  178. ddrphy_select_lane(phy_base, 12, 0);
  179. writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
  180. writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
  181. ddrphy_select_lane(phy_base, 18, 0);
  182. writel(0x00000005, phy_base + PHY_DLL_TRIM_1);
  183. writel(0x0000000a, phy_base + PHY_DLL_TRIM_3);
  184. writel(0x00000001, phy_base + PHY_SCL_WINDOW_TRIM);
  185. writel(0x00000000, phy_base + PHY_UNQ_ANALOG_DLL_1);
  186. writel(ddrphy_phy_pad_ctrl[board][ch], phy_base + PHY_PAD_CTRL);
  187. writel(0x00000070, phy_base + PHY_VREF_TRAINING);
  188. writel(0x01000075, phy_base + PHY_SCL_CONFIG_1);
  189. writel(0x00000501, phy_base + PHY_SCL_CONFIG_2);
  190. writel(0x00000000, phy_base + PHY_SCL_CONFIG_3);
  191. writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
  192. writel(0x00000000, phy_base + PHY_SCL_CONFIG_4);
  193. writel(ddrphy_scl_gate_timing[ch], phy_base + PHY_SCL_GATE_TIMING);
  194. writel(0x02a000a0, phy_base + PHY_WRLVL_DYN_ODT);
  195. writel(0x00840004, phy_base + PHY_WRLVL_ON_OFF);
  196. writel(0x0000020d, phy_base + PHY_DLL_ADRCTRL);
  197. ddrphy_select_lane(phy_base, 0, 0);
  198. writel(0x0000008d, phy_base + PHY_DLL_TRIM_CLK);
  199. writel(0xa800100d, phy_base + PHY_DLL_RECALIB);
  200. writel(0x00005076, phy_base + PHY_SCL_LATENCY);
  201. }
  202. static int ddrphy_to_dly_step(void __iomem *phy_base, unsigned int freq,
  203. int delay)
  204. {
  205. int mdl;
  206. mdl = (readl(phy_base + PHY_DLL_ADRCTRL) & PHY_DLL_ADRCTRL_MDL_MASK) >>
  207. PHY_DLL_ADRCTRL_MDL_SHIFT;
  208. return DIV_ROUND_CLOSEST((long)freq * delay * mdl, 2 * 1000000L);
  209. }
  210. static void ddrphy_set_delay(void __iomem *phy_base, unsigned int reg,
  211. u32 mask, u32 incr, int dly_step)
  212. {
  213. u32 tmp;
  214. tmp = readl(phy_base + reg);
  215. tmp &= ~mask;
  216. tmp |= min_t(u32, abs(dly_step), mask);
  217. if (dly_step >= 0)
  218. tmp |= incr;
  219. else
  220. tmp &= ~incr;
  221. writel(tmp, phy_base + reg);
  222. }
  223. static void ddrphy_set_dll_recalib(void __iomem *phy_base, int dly_step)
  224. {
  225. ddrphy_set_delay(phy_base, PHY_DLL_RECALIB,
  226. PHY_DLL_RECALIB_TRIM_MASK, PHY_DLL_RECALIB_INCR,
  227. dly_step);
  228. }
  229. static void ddrphy_set_dll_adrctrl(void __iomem *phy_base, int dly_step)
  230. {
  231. ddrphy_set_delay(phy_base, PHY_DLL_ADRCTRL,
  232. PHY_DLL_ADRCTRL_TRIM_MASK, PHY_DLL_ADRCTRL_INCR,
  233. dly_step);
  234. }
  235. static void ddrphy_set_dll_trim_clk(void __iomem *phy_base, int dly_step)
  236. {
  237. ddrphy_select_lane(phy_base, 0, 0);
  238. ddrphy_set_delay(phy_base, PHY_DLL_TRIM_CLK,
  239. PHY_DLL_TRIM_CLK_MASK, PHY_DLL_TRIM_CLK_INCR,
  240. dly_step);
  241. }
  242. static void ddrphy_init_tail(void __iomem *phy_base, enum dram_board board,
  243. unsigned int freq, int ch)
  244. {
  245. int step;
  246. step = ddrphy_to_dly_step(phy_base, freq, ddrphy_adrctrl[board][ch]);
  247. ddrphy_set_dll_adrctrl(phy_base, step);
  248. step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dlltrimclk[board][ch]);
  249. ddrphy_set_dll_trim_clk(phy_base, step);
  250. step = ddrphy_to_dly_step(phy_base, freq, ddrphy_dllrecalib[board][ch]);
  251. ddrphy_set_dll_recalib(phy_base, step);
  252. }
  253. static void ddrphy_shift_one_dq(void __iomem *phy_base, unsigned int reg,
  254. u32 mask, u32 incr, short shift_val)
  255. {
  256. u32 tmp;
  257. int val;
  258. tmp = readl(phy_base + reg);
  259. val = tmp & mask;
  260. if (!(tmp & incr))
  261. val = -val;
  262. val += shift_val;
  263. tmp &= ~(incr | mask);
  264. tmp |= min_t(u32, abs(val), mask);
  265. if (val >= 0)
  266. tmp |= incr;
  267. writel(tmp, phy_base + reg);
  268. }
  269. static void ddrphy_shift_dq(void __iomem *phy_base, unsigned int reg,
  270. u32 mask, u32 incr, u32 override,
  271. const short *shift_val_array)
  272. {
  273. u32 tmp;
  274. int dx, bit;
  275. tmp = readl(phy_base + reg);
  276. tmp |= override;
  277. writel(tmp, phy_base + reg);
  278. for (dx = 0; dx < 4; dx++) {
  279. for (bit = 0; bit < 8; bit++) {
  280. ddrphy_select_lane(phy_base,
  281. (PHY_BITLVL_DLY_WIDTH + 1) * dx,
  282. bit);
  283. ddrphy_shift_one_dq(phy_base, reg, mask, incr,
  284. shift_val_array[dx * 8 + bit]);
  285. }
  286. }
  287. ddrphy_select_lane(phy_base, 0, 0);
  288. }
  289. static int ddrphy_training(void __iomem *phy_base, enum dram_board board,
  290. int ch)
  291. {
  292. writel(0x0000000f, phy_base + PHY_WRLVL_AUTOINC_TRIM);
  293. writel(0x00010000, phy_base + PHY_DLL_TRIM_2);
  294. writel(0x50000000, phy_base + PHY_SCL_START);
  295. while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
  296. cpu_relax();
  297. writel(0x00000000, phy_base + PHY_DISABLE_GATING_FOR_SCL);
  298. writel(0xff00ff00, phy_base + PHY_SCL_DATA_0);
  299. writel(0xff00ff00, phy_base + PHY_SCL_DATA_1);
  300. writel(0xFBF8FFFF, phy_base + PHY_SCL_START_ADDR);
  301. writel(0x11000000, phy_base + PHY_SCL_START);
  302. while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
  303. cpu_relax();
  304. writel(0xFBF0FFFF, phy_base + PHY_SCL_START_ADDR);
  305. writel(0x30500000, phy_base + PHY_SCL_START);
  306. while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
  307. cpu_relax();
  308. writel(0x00000001, phy_base + PHY_DISABLE_GATING_FOR_SCL);
  309. writel(0x00000010, phy_base + PHY_SCL_MAIN_CLK_DELTA);
  310. writel(0x789b3de0, phy_base + PHY_SCL_DATA_0);
  311. writel(0xf10e4a56, phy_base + PHY_SCL_DATA_1);
  312. writel(0x11000000, phy_base + PHY_SCL_START);
  313. while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
  314. cpu_relax();
  315. writel(0x34000000, phy_base + PHY_SCL_START);
  316. while (readl(phy_base + PHY_SCL_START) & PHY_SCL_START_GO_DONE)
  317. cpu_relax();
  318. writel(0x00000003, phy_base + PHY_DISABLE_GATING_FOR_SCL);
  319. writel(0x000261c0, phy_base + PHY_DYNAMIC_WRITE_BIT_LVL);
  320. writel(0x00003270, phy_base + PHY_DYNAMIC_BIT_LVL);
  321. writel(0x011BD0C4, phy_base + PHY_DSCL_CNT);
  322. /* shift ip_dq trim */
  323. ddrphy_shift_dq(phy_base,
  324. PHY_IP_DQ_DQS_BITWISE_TRIM,
  325. PHY_IP_DQ_DQS_BITWISE_TRIM_MASK,
  326. PHY_IP_DQ_DQS_BITWISE_TRIM_INC,
  327. PHY_IP_DQ_DQS_BITWISE_TRIM_OVERRIDE,
  328. ddrphy_ip_dq_shift_val[board][ch]);
  329. /* shift op_dq trim */
  330. ddrphy_shift_dq(phy_base,
  331. PHY_OP_DQ_DM_DQS_BITWISE_TRIM,
  332. PHY_OP_DQ_DM_DQS_BITWISE_TRIM_MASK,
  333. PHY_OP_DQ_DM_DQS_BITWISE_TRIM_INC,
  334. PHY_OP_DQ_DM_DQS_BITWISE_TRIM_OVERRIDE,
  335. ddrphy_op_dq_shift_val[board][ch]);
  336. return 0;
  337. }
  338. /* UMC */
  339. static const u32 umc_initctla[DRAM_FREQ_NR] = {0x71016D11};
  340. static const u32 umc_initctlb[DRAM_FREQ_NR] = {0x07E390AC};
  341. static const u32 umc_initctlc[DRAM_FREQ_NR] = {0x00FF00FF};
  342. static const u32 umc_drmmr0[DRAM_FREQ_NR] = {0x00000114};
  343. static const u32 umc_drmmr2[DRAM_FREQ_NR] = {0x000002a0};
  344. static const u32 umc_memconf0a[DRAM_FREQ_NR][DRAM_SZ_NR] = {
  345. /* 256MB 512MB */
  346. {0x00000601, 0x00000801}, /* 1866 MHz */
  347. };
  348. static const u32 umc_memconf0b[DRAM_FREQ_NR][DRAM_SZ_NR] = {
  349. /* 256MB 512MB */
  350. {0x00000120, 0x00000130}, /* 1866 MHz */
  351. };
  352. static const u32 umc_memconfch[DRAM_FREQ_NR][DRAM_SZ_NR] = {
  353. /* 256MB 512MB */
  354. {0x00033603, 0x00033803}, /* 1866 MHz */
  355. };
  356. static const u32 umc_cmdctla[DRAM_FREQ_NR] = {0x060D0D20};
  357. static const u32 umc_cmdctlb[DRAM_FREQ_NR] = {0x2D211C08};
  358. static const u32 umc_cmdctlc[DRAM_FREQ_NR] = {0x00150C04};
  359. static const u32 umc_cmdctle[DRAM_FREQ_NR][DRAM_SZ_NR] = {
  360. /* 256MB 512MB */
  361. {0x0049071D, 0x0078071D}, /* 1866 MHz */
  362. };
  363. static const u32 umc_rdatactl[DRAM_FREQ_NR] = {0x00000610};
  364. static const u32 umc_wdatactl[DRAM_FREQ_NR] = {0x00000204};
  365. static const u32 umc_odtctl[DRAM_FREQ_NR] = {0x02000002};
  366. static const u32 umc_dataset[DRAM_FREQ_NR] = {0x04000000};
  367. static const u32 umc_flowctla[DRAM_FREQ_NR] = {0x0081E01E};
  368. static const u32 umc_directbusctrla[DRAM_CH_NR] = {
  369. 0x00000000, 0x00000001, 0x00000001
  370. };
  371. static void umc_poll_phy_init_complete(void __iomem *dc_base)
  372. {
  373. /* Wait for PHY Init Complete */
  374. while (!(readl(dc_base + UMC_DFISTCTLC) & BIT(0)))
  375. cpu_relax();
  376. }
  377. static int umc_dc_init(void __iomem *dc_base, unsigned int freq,
  378. unsigned long size, int ch)
  379. {
  380. enum dram_freq freq_e;
  381. enum dram_size size_e;
  382. switch (freq) {
  383. case 1866:
  384. freq_e = DRAM_FREQ_1866M;
  385. break;
  386. default:
  387. pr_err("unsupported DRAM frequency %ud MHz\n", freq);
  388. return -EINVAL;
  389. }
  390. switch (size) {
  391. case 0:
  392. return 0;
  393. case SZ_256M:
  394. size_e = DRAM_SZ_256M;
  395. break;
  396. case SZ_512M:
  397. size_e = DRAM_SZ_512M;
  398. break;
  399. default:
  400. pr_err("unsupported DRAM size 0x%08lx (per 16bit) for ch%d\n",
  401. size, ch);
  402. return -EINVAL;
  403. }
  404. writel(0x00000001, dc_base + UMC_DFICSOVRRD);
  405. writel(0x00000000, dc_base + UMC_DFITURNOFF);
  406. writel(umc_initctla[freq_e], dc_base + UMC_INITCTLA);
  407. writel(umc_initctlb[freq_e], dc_base + UMC_INITCTLB);
  408. writel(umc_initctlc[freq_e], dc_base + UMC_INITCTLC);
  409. writel(umc_drmmr0[freq_e], dc_base + UMC_DRMMR0);
  410. writel(0x00000004, dc_base + UMC_DRMMR1);
  411. writel(umc_drmmr2[freq_e], dc_base + UMC_DRMMR2);
  412. writel(0x00000000, dc_base + UMC_DRMMR3);
  413. writel(umc_memconf0a[freq_e][size_e], dc_base + UMC_MEMCONF0A);
  414. writel(umc_memconf0b[freq_e][size_e], dc_base + UMC_MEMCONF0B);
  415. writel(umc_memconfch[freq_e][size_e], dc_base + UMC_MEMCONFCH);
  416. writel(0x00000000, dc_base + UMC_MEMMAPSET);
  417. writel(umc_cmdctla[freq_e], dc_base + UMC_CMDCTLA);
  418. writel(umc_cmdctlb[freq_e], dc_base + UMC_CMDCTLB);
  419. writel(umc_cmdctlc[freq_e], dc_base + UMC_CMDCTLC);
  420. writel(umc_cmdctle[freq_e][size_e], dc_base + UMC_CMDCTLE);
  421. writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D0);
  422. writel(umc_rdatactl[freq_e], dc_base + UMC_RDATACTL_D1);
  423. writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D0);
  424. writel(umc_wdatactl[freq_e], dc_base + UMC_WDATACTL_D1);
  425. writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D0);
  426. writel(umc_odtctl[freq_e], dc_base + UMC_ODTCTL_D1);
  427. writel(umc_dataset[freq_e], dc_base + UMC_DATASET);
  428. writel(0x00400020, dc_base + UMC_DCCGCTL);
  429. writel(0x00000003, dc_base + UMC_ACSSETA);
  430. writel(0x00000103, dc_base + UMC_FLOWCTLG);
  431. writel(0x00010200, dc_base + UMC_ACSSETB);
  432. writel(umc_flowctla[freq_e], dc_base + UMC_FLOWCTLA);
  433. writel(0x00004444, dc_base + UMC_FLOWCTLC);
  434. writel(0x00000000, dc_base + UMC_DFICUPDCTLA);
  435. writel(0x00202000, dc_base + UMC_FLOWCTLB);
  436. writel(0x00000000, dc_base + UMC_BSICMAPSET);
  437. writel(0x00000000, dc_base + UMC_ERRMASKA);
  438. writel(0x00000000, dc_base + UMC_ERRMASKB);
  439. writel(umc_directbusctrla[ch], dc_base + UMC_DIRECTBUSCTRLA);
  440. writel(0x00000001, dc_base + UMC_INITSET);
  441. /* Wait for PHY Init Complete */
  442. while (readl(dc_base + UMC_INITSTAT) & BIT(0))
  443. cpu_relax();
  444. writel(0x2A0A0A00, dc_base + UMC_SPCSETB);
  445. writel(0x00000000, dc_base + UMC_DFICSOVRRD);
  446. return 0;
  447. }
  448. static int umc_ch_init(void __iomem *umc_ch_base, void __iomem *phy_ch_base,
  449. enum dram_board board, unsigned int freq,
  450. unsigned long size, int ch)
  451. {
  452. void __iomem *dc_base = umc_ch_base + 0x00011000;
  453. void __iomem *phy_base = phy_ch_base;
  454. int ret;
  455. /* PHY Update Mode (ON) */
  456. writel(0x8000003f, dc_base + UMC_DFIPUPDCTLA);
  457. /* deassert PHY reset signals */
  458. writel(UMC_DIOCTLA_CTL_NRST | UMC_DIOCTLA_CFG_NRST,
  459. dc_base + UMC_DIOCTLA);
  460. ddrphy_init(phy_base, board, ch);
  461. umc_poll_phy_init_complete(dc_base);
  462. ddrphy_init_tail(phy_base, board, freq, ch);
  463. ret = umc_dc_init(dc_base, freq, size, ch);
  464. if (ret)
  465. return ret;
  466. ret = ddrphy_training(phy_base, board, ch);
  467. if (ret)
  468. return ret;
  469. return 0;
  470. }
  471. static void um_init(void __iomem *um_base)
  472. {
  473. writel(0x000000ff, um_base + UMC_MBUS0);
  474. writel(0x000000ff, um_base + UMC_MBUS1);
  475. writel(0x000000ff, um_base + UMC_MBUS2);
  476. writel(0x00000001, um_base + UMC_MBUS3);
  477. writel(0x00000001, um_base + UMC_MBUS4);
  478. writel(0x00000001, um_base + UMC_MBUS5);
  479. writel(0x00000001, um_base + UMC_MBUS6);
  480. writel(0x00000001, um_base + UMC_MBUS7);
  481. writel(0x00000001, um_base + UMC_MBUS8);
  482. writel(0x00000001, um_base + UMC_MBUS9);
  483. writel(0x00000001, um_base + UMC_MBUS10);
  484. }
  485. int uniphier_ld20_umc_init(const struct uniphier_board_data *bd)
  486. {
  487. void __iomem *um_base = (void __iomem *)0x5b600000;
  488. void __iomem *umc_ch_base = (void __iomem *)0x5b800000;
  489. void __iomem *phy_ch_base = (void __iomem *)0x6e200000;
  490. enum dram_board board;
  491. int ch, ret;
  492. switch (UNIPHIER_BD_BOARD_GET_TYPE(bd->flags)) {
  493. case UNIPHIER_BD_BOARD_LD20_REF:
  494. board = DRAM_BOARD_LD20_REF;
  495. break;
  496. case UNIPHIER_BD_BOARD_LD20_GLOBAL:
  497. board = DRAM_BOARD_LD20_GLOBAL;
  498. break;
  499. case UNIPHIER_BD_BOARD_LD20_C1:
  500. board = DRAM_BOARD_LD20_C1;
  501. break;
  502. case UNIPHIER_BD_BOARD_LD21_REF:
  503. board = DRAM_BOARD_LD21_REF;
  504. break;
  505. case UNIPHIER_BD_BOARD_LD21_GLOBAL:
  506. board = DRAM_BOARD_LD21_GLOBAL;
  507. break;
  508. default:
  509. pr_err("unsupported board type %d\n",
  510. UNIPHIER_BD_BOARD_GET_TYPE(bd->flags));
  511. return -EINVAL;
  512. }
  513. for (ch = 0; ch < DRAM_CH_NR; ch++) {
  514. unsigned long size = bd->dram_ch[ch].size;
  515. unsigned int width = bd->dram_ch[ch].width;
  516. if (size) {
  517. ret = umc_ch_init(umc_ch_base, phy_ch_base, board,
  518. bd->dram_freq, size / (width / 16),
  519. ch);
  520. if (ret) {
  521. pr_err("failed to initialize UMC ch%d\n", ch);
  522. return ret;
  523. }
  524. }
  525. umc_ch_base += 0x00200000;
  526. phy_ch_base += 0x00004000;
  527. }
  528. um_init(um_base);
  529. return 0;
  530. }