cmd_ddrmphy.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. /*
  2. * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
  3. *
  4. * SPDX-License-Identifier: GPL-2.0+
  5. */
  6. #include <common.h>
  7. #include <linux/io.h>
  8. #include "../init.h"
  9. #include "ddrmphy-regs.h"
  10. /* Select either decimal or hexadecimal */
  11. #if 1
  12. #define PRINTF_FORMAT "%2d"
  13. #else
  14. #define PRINTF_FORMAT "%02x"
  15. #endif
  16. /* field separator */
  17. #define FS " "
  18. static void __iomem *get_phy_base(int ch)
  19. {
  20. return (void __iomem *)(0x5b830000 + ch * 0x00200000);
  21. }
  22. static int get_nr_ch(void)
  23. {
  24. const struct uniphier_board_data *bd = uniphier_get_board_param();
  25. return bd->dram_ch[2].size ? 3 : 2;
  26. }
  27. static int get_nr_datx8(int ch)
  28. {
  29. const struct uniphier_board_data *bd = uniphier_get_board_param();
  30. return bd->dram_ch[ch].width / 8;
  31. }
  32. static void print_bdl(void __iomem *reg, int n)
  33. {
  34. u32 val = readl(reg);
  35. int i;
  36. for (i = 0; i < n; i++)
  37. printf(FS PRINTF_FORMAT, (val >> i * 8) & 0x1f);
  38. }
  39. static void dump_loop(void (*callback)(void __iomem *))
  40. {
  41. int ch, dx, nr_ch, nr_dx;
  42. void __iomem *dx_base;
  43. nr_ch = get_nr_ch();
  44. for (ch = 0; ch < nr_ch; ch++) {
  45. dx_base = get_phy_base(ch) + DMPHY_DX_BASE;
  46. nr_dx = get_nr_datx8(ch);
  47. for (dx = 0; dx < nr_dx; dx++) {
  48. printf("CH%dDX%d:", ch, dx);
  49. (*callback)(dx_base);
  50. dx_base += DMPHY_DX_STRIDE;
  51. printf("\n");
  52. }
  53. }
  54. }
  55. static void zq_dump(void)
  56. {
  57. int ch, zq, nr_ch, nr_zq, i;
  58. void __iomem *zq_base;
  59. u32 dr, pr;
  60. printf("\n--- Impedance Data ---\n");
  61. printf(" ZPD ZPU OPD OPU ZDV ODV\n");
  62. nr_ch = get_nr_ch();
  63. for (ch = 0; ch < nr_ch; ch++) {
  64. zq_base = get_phy_base(ch) + DMPHY_ZQ_BASE;
  65. nr_zq = 3;
  66. for (zq = 0; zq < nr_zq; zq++) {
  67. printf("CH%dZQ%d:", ch, zq);
  68. dr = readl(zq_base + DMPHY_ZQ_DR);
  69. for (i = 0; i < 4; i++) {
  70. printf(FS PRINTF_FORMAT, dr & 0x7f);
  71. dr >>= 7;
  72. }
  73. pr = readl(zq_base + DMPHY_ZQ_PR);
  74. for (i = 0; i < 2; i++) {
  75. printf(FS PRINTF_FORMAT, pr & 0xf);
  76. pr >>= 4;
  77. }
  78. zq_base += DMPHY_ZQ_STRIDE;
  79. printf("\n");
  80. }
  81. }
  82. }
  83. static void __wbdl_dump(void __iomem *dx_base)
  84. {
  85. print_bdl(dx_base + DMPHY_DX_BDLR0, 4);
  86. print_bdl(dx_base + DMPHY_DX_BDLR1, 4);
  87. print_bdl(dx_base + DMPHY_DX_BDLR2, 2);
  88. printf(FS "(+" PRINTF_FORMAT ")",
  89. readl(dx_base + DMPHY_DX_LCDLR1) & 0xff);
  90. }
  91. static void wbdl_dump(void)
  92. {
  93. printf("\n--- Write Bit Delay Line ---\n");
  94. printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n");
  95. dump_loop(&__wbdl_dump);
  96. }
  97. static void __rbdl_dump(void __iomem *dx_base)
  98. {
  99. print_bdl(dx_base + DMPHY_DX_BDLR3, 4);
  100. print_bdl(dx_base + DMPHY_DX_BDLR4, 4);
  101. print_bdl(dx_base + DMPHY_DX_BDLR5, 1);
  102. printf(FS "(+" PRINTF_FORMAT ")",
  103. (readl(dx_base + DMPHY_DX_LCDLR1) >> 8) & 0xff);
  104. printf(FS "(+" PRINTF_FORMAT ")",
  105. (readl(dx_base + DMPHY_DX_LCDLR1) >> 16) & 0xff);
  106. }
  107. static void rbdl_dump(void)
  108. {
  109. printf("\n--- Read Bit Delay Line ---\n");
  110. printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD) (RDQSND)\n");
  111. dump_loop(&__rbdl_dump);
  112. }
  113. static void __wld_dump(void __iomem *dx_base)
  114. {
  115. int rank;
  116. u32 lcdlr0 = readl(dx_base + DMPHY_DX_LCDLR0);
  117. u32 gtr = readl(dx_base + DMPHY_DX_GTR);
  118. for (rank = 0; rank < 4; rank++) {
  119. u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */
  120. u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */
  121. printf(FS PRINTF_FORMAT "%sT", wld,
  122. wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1");
  123. }
  124. }
  125. static void wld_dump(void)
  126. {
  127. printf("\n--- Write Leveling Delay ---\n");
  128. printf(" Rank0 Rank1 Rank2 Rank3\n");
  129. dump_loop(&__wld_dump);
  130. }
  131. static void __dqsgd_dump(void __iomem *dx_base)
  132. {
  133. int rank;
  134. u32 lcdlr2 = readl(dx_base + DMPHY_DX_LCDLR2);
  135. u32 gtr = readl(dx_base + DMPHY_DX_GTR);
  136. for (rank = 0; rank < 4; rank++) {
  137. u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
  138. u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */
  139. printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl);
  140. }
  141. }
  142. static void dqsgd_dump(void)
  143. {
  144. printf("\n--- DQS Gating Delay ---\n");
  145. printf(" Rank0 Rank1 Rank2 Rank3\n");
  146. dump_loop(&__dqsgd_dump);
  147. }
  148. static void __mdl_dump(void __iomem *dx_base)
  149. {
  150. int i;
  151. u32 mdl = readl(dx_base + DMPHY_DX_MDLR);
  152. for (i = 0; i < 3; i++)
  153. printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
  154. }
  155. static void mdl_dump(void)
  156. {
  157. printf("\n--- Master Delay Line ---\n");
  158. printf(" IPRD TPRD MDLD\n");
  159. dump_loop(&__mdl_dump);
  160. }
  161. #define REG_DUMP(x) \
  162. { int ofst = DMPHY_ ## x; void __iomem *reg = phy_base + ofst; \
  163. printf("%3d: %-10s: %p : %08x\n", \
  164. ofst >> DMPHY_SHIFT, #x, reg, readl(reg)); }
  165. #define DX_REG_DUMP(dx, x) \
  166. { int ofst = DMPHY_DX_BASE + DMPHY_DX_STRIDE * (dx) + \
  167. DMPHY_DX_## x; \
  168. void __iomem *reg = phy_base + ofst; \
  169. printf("%3d: DX%d%-7s: %p : %08x\n", \
  170. ofst >> DMPHY_SHIFT, (dx), #x, reg, readl(reg)); }
  171. static void reg_dump(void)
  172. {
  173. int ch, dx, nr_ch, nr_dx;
  174. void __iomem *phy_base;
  175. printf("\n--- DDR PHY registers ---\n");
  176. nr_ch = get_nr_ch();
  177. for (ch = 0; ch < nr_ch; ch++) {
  178. phy_base = get_phy_base(ch);
  179. nr_dx = get_nr_datx8(ch);
  180. printf("== Ch%d ==\n", ch);
  181. printf(" No: Name : Address : Data\n");
  182. REG_DUMP(RIDR);
  183. REG_DUMP(PIR);
  184. REG_DUMP(PGCR0);
  185. REG_DUMP(PGCR1);
  186. REG_DUMP(PGCR2);
  187. REG_DUMP(PGCR3);
  188. REG_DUMP(PGSR0);
  189. REG_DUMP(PGSR1);
  190. REG_DUMP(PLLCR);
  191. REG_DUMP(PTR0);
  192. REG_DUMP(PTR1);
  193. REG_DUMP(PTR2);
  194. REG_DUMP(PTR3);
  195. REG_DUMP(PTR4);
  196. REG_DUMP(ACMDLR);
  197. REG_DUMP(ACBDLR0);
  198. REG_DUMP(DXCCR);
  199. REG_DUMP(DSGCR);
  200. REG_DUMP(DCR);
  201. REG_DUMP(DTPR0);
  202. REG_DUMP(DTPR1);
  203. REG_DUMP(DTPR2);
  204. REG_DUMP(DTPR3);
  205. REG_DUMP(MR0);
  206. REG_DUMP(MR1);
  207. REG_DUMP(MR2);
  208. REG_DUMP(MR3);
  209. for (dx = 0; dx < nr_dx; dx++) {
  210. DX_REG_DUMP(dx, GCR0);
  211. DX_REG_DUMP(dx, GCR1);
  212. DX_REG_DUMP(dx, GCR2);
  213. DX_REG_DUMP(dx, GCR3);
  214. DX_REG_DUMP(dx, GTR);
  215. }
  216. }
  217. }
  218. static int do_ddrm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  219. {
  220. char *cmd = argv[1];
  221. if (argc == 1)
  222. cmd = "all";
  223. if (!strcmp(cmd, "zq") || !strcmp(cmd, "all"))
  224. zq_dump();
  225. if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all"))
  226. wbdl_dump();
  227. if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all"))
  228. rbdl_dump();
  229. if (!strcmp(cmd, "wld") || !strcmp(cmd, "all"))
  230. wld_dump();
  231. if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all"))
  232. dqsgd_dump();
  233. if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all"))
  234. mdl_dump();
  235. if (!strcmp(cmd, "reg") || !strcmp(cmd, "all"))
  236. reg_dump();
  237. return 0;
  238. }
  239. U_BOOT_CMD(
  240. ddrm, 2, 1, do_ddrm,
  241. "UniPhier DDR PHY parameters dumper",
  242. "- dump all of the following\n"
  243. "ddrm zq - dump Impedance Data\n"
  244. "ddrm wbdl - dump Write Bit Delay\n"
  245. "ddrm rbdl - dump Read Bit Delay\n"
  246. "ddrm wld - dump Write Leveling\n"
  247. "ddrm dqsgd - dump DQS Gating Delay\n"
  248. "ddrm mdl - dump Master Delay Line\n"
  249. "ddrm reg - dump registers\n"
  250. );