cmd_ddrphy.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * Copyright (C) 2014 Panasonic Corporation
  3. * Copyright (C) 2015-2016 Socionext Inc.
  4. * Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  5. *
  6. * SPDX-License-Identifier: GPL-2.0+
  7. */
  8. #include <common.h>
  9. #include <linux/io.h>
  10. #include <linux/sizes.h>
  11. #include "../soc-info.h"
  12. #include "ddrphy-regs.h"
  13. /* Select either decimal or hexadecimal */
  14. #if 1
  15. #define PRINTF_FORMAT "%2d"
  16. #else
  17. #define PRINTF_FORMAT "%02x"
  18. #endif
  19. /* field separator */
  20. #define FS " "
  21. static unsigned long uniphier_ld4_base[] = {
  22. 0x5bc01000,
  23. 0x5be01000,
  24. 0 /* sentinel */
  25. };
  26. static unsigned long uniphier_pro4_base[] = {
  27. 0x5bc01000,
  28. 0x5be01000,
  29. 0 /* sentinel */
  30. };
  31. static unsigned long uniphier_sld8_base[] = {
  32. 0x5bc01000,
  33. 0x5be01000,
  34. 0 /* sentinel */
  35. };
  36. static u32 read_bdl(struct ddrphy_datx8 __iomem *dx, int index)
  37. {
  38. return (readl(&dx->bdlr[index / 5]) >> (index % 5 * 6)) & 0x3f;
  39. }
  40. static void dump_loop(unsigned long *base,
  41. void (*callback)(struct ddrphy_datx8 __iomem *))
  42. {
  43. struct ddrphy __iomem *phy;
  44. int p, dx;
  45. for (p = 0; *base; base++, p++) {
  46. phy = ioremap(*base, SZ_4K);
  47. for (dx = 0; dx < NR_DATX8_PER_DDRPHY; dx++) {
  48. printf("PHY%dDX%d:", p, dx);
  49. (*callback)(&phy->dx[dx]);
  50. printf("\n");
  51. }
  52. iounmap(phy);
  53. }
  54. }
  55. static void __wbdl_dump(struct ddrphy_datx8 __iomem *dx)
  56. {
  57. int i;
  58. for (i = 0; i < 10; i++)
  59. printf(FS PRINTF_FORMAT, read_bdl(dx, i));
  60. printf(FS "(+" PRINTF_FORMAT ")", readl(&dx->lcdlr[1]) & 0xff);
  61. }
  62. static void wbdl_dump(unsigned long *base)
  63. {
  64. printf("\n--- Write Bit Delay Line ---\n");
  65. printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM DQS (WDQD)\n");
  66. dump_loop(base, &__wbdl_dump);
  67. }
  68. static void __rbdl_dump(struct ddrphy_datx8 __iomem *dx)
  69. {
  70. int i;
  71. for (i = 15; i < 24; i++)
  72. printf(FS PRINTF_FORMAT, read_bdl(dx, i));
  73. printf(FS "(+" PRINTF_FORMAT ")", (readl(&dx->lcdlr[1]) >> 8) & 0xff);
  74. }
  75. static void rbdl_dump(unsigned long *base)
  76. {
  77. printf("\n--- Read Bit Delay Line ---\n");
  78. printf(" DQ0 DQ1 DQ2 DQ3 DQ4 DQ5 DQ6 DQ7 DM (RDQSD)\n");
  79. dump_loop(base, &__rbdl_dump);
  80. }
  81. static void __wld_dump(struct ddrphy_datx8 __iomem *dx)
  82. {
  83. int rank;
  84. u32 lcdlr0 = readl(&dx->lcdlr[0]);
  85. u32 gtr = readl(&dx->gtr);
  86. for (rank = 0; rank < 4; rank++) {
  87. u32 wld = (lcdlr0 >> (8 * rank)) & 0xff; /* Delay */
  88. u32 wlsl = (gtr >> (12 + 2 * rank)) & 0x3; /* System Latency */
  89. printf(FS PRINTF_FORMAT "%sT", wld,
  90. wlsl == 0 ? "-1" : wlsl == 1 ? "+0" : "+1");
  91. }
  92. }
  93. static void wld_dump(unsigned long *base)
  94. {
  95. printf("\n--- Write Leveling Delay ---\n");
  96. printf(" Rank0 Rank1 Rank2 Rank3\n");
  97. dump_loop(base, &__wld_dump);
  98. }
  99. static void __dqsgd_dump(struct ddrphy_datx8 __iomem *dx)
  100. {
  101. int rank;
  102. u32 lcdlr2 = readl(&dx->lcdlr[2]);
  103. u32 gtr = readl(&dx->gtr);
  104. for (rank = 0; rank < 4; rank++) {
  105. u32 dqsgd = (lcdlr2 >> (8 * rank)) & 0xff; /* Delay */
  106. u32 dgsl = (gtr >> (3 * rank)) & 0x7; /* System Latency */
  107. printf(FS PRINTF_FORMAT "+%dT", dqsgd, dgsl);
  108. }
  109. }
  110. static void dqsgd_dump(unsigned long *base)
  111. {
  112. printf("\n--- DQS Gating Delay ---\n");
  113. printf(" Rank0 Rank1 Rank2 Rank3\n");
  114. dump_loop(base, &__dqsgd_dump);
  115. }
  116. static void __mdl_dump(struct ddrphy_datx8 __iomem *dx)
  117. {
  118. int i;
  119. u32 mdl = readl(&dx->mdlr);
  120. for (i = 0; i < 3; i++)
  121. printf(FS PRINTF_FORMAT, (mdl >> (8 * i)) & 0xff);
  122. }
  123. static void mdl_dump(unsigned long *base)
  124. {
  125. printf("\n--- Master Delay Line ---\n");
  126. printf(" IPRD TPRD MDLD\n");
  127. dump_loop(base, &__mdl_dump);
  128. }
  129. #define REG_DUMP(x) \
  130. { u32 __iomem *p = &phy->x; printf("%3d: %-10s: %p : %08x\n", \
  131. p - (u32 *)phy, #x, p, readl(p)); }
  132. static void reg_dump(unsigned long *base)
  133. {
  134. struct ddrphy __iomem *phy;
  135. int p;
  136. printf("\n--- DDR PHY registers ---\n");
  137. for (p = 0; *base; base++, p++) {
  138. phy = ioremap(*base, SZ_4K);
  139. printf("== PHY%d (base: %p) ==\n", p, phy);
  140. printf(" No: Name : Address : Data\n");
  141. REG_DUMP(ridr);
  142. REG_DUMP(pir);
  143. REG_DUMP(pgcr[0]);
  144. REG_DUMP(pgcr[1]);
  145. REG_DUMP(pgsr[0]);
  146. REG_DUMP(pgsr[1]);
  147. REG_DUMP(pllcr);
  148. REG_DUMP(ptr[0]);
  149. REG_DUMP(ptr[1]);
  150. REG_DUMP(ptr[2]);
  151. REG_DUMP(ptr[3]);
  152. REG_DUMP(ptr[4]);
  153. REG_DUMP(acmdlr);
  154. REG_DUMP(acbdlr);
  155. REG_DUMP(dxccr);
  156. REG_DUMP(dsgcr);
  157. REG_DUMP(dcr);
  158. REG_DUMP(dtpr[0]);
  159. REG_DUMP(dtpr[1]);
  160. REG_DUMP(dtpr[2]);
  161. REG_DUMP(mr0);
  162. REG_DUMP(mr1);
  163. REG_DUMP(mr2);
  164. REG_DUMP(mr3);
  165. REG_DUMP(dx[0].gcr);
  166. REG_DUMP(dx[0].gtr);
  167. REG_DUMP(dx[1].gcr);
  168. REG_DUMP(dx[1].gtr);
  169. iounmap(phy);
  170. }
  171. }
  172. static int do_ddr(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
  173. {
  174. char *cmd = argv[1];
  175. unsigned long *base;
  176. switch (uniphier_get_soc_type()) {
  177. case SOC_UNIPHIER_LD4:
  178. base = uniphier_ld4_base;
  179. break;
  180. case SOC_UNIPHIER_PRO4:
  181. base = uniphier_pro4_base;
  182. break;
  183. case SOC_UNIPHIER_SLD8:
  184. base = uniphier_sld8_base;
  185. break;
  186. default:
  187. printf("unsupported SoC\n");
  188. return CMD_RET_FAILURE;
  189. }
  190. if (argc == 1)
  191. cmd = "all";
  192. if (!strcmp(cmd, "wbdl") || !strcmp(cmd, "all"))
  193. wbdl_dump(base);
  194. if (!strcmp(cmd, "rbdl") || !strcmp(cmd, "all"))
  195. rbdl_dump(base);
  196. if (!strcmp(cmd, "wld") || !strcmp(cmd, "all"))
  197. wld_dump(base);
  198. if (!strcmp(cmd, "dqsgd") || !strcmp(cmd, "all"))
  199. dqsgd_dump(base);
  200. if (!strcmp(cmd, "mdl") || !strcmp(cmd, "all"))
  201. mdl_dump(base);
  202. if (!strcmp(cmd, "reg") || !strcmp(cmd, "all"))
  203. reg_dump(base);
  204. return CMD_RET_SUCCESS;
  205. }
  206. U_BOOT_CMD(
  207. ddr, 2, 1, do_ddr,
  208. "UniPhier DDR PHY parameters dumper",
  209. "- dump all of the following\n"
  210. "ddr wbdl - dump Write Bit Delay\n"
  211. "ddr rbdl - dump Read Bit Delay\n"
  212. "ddr wld - dump Write Leveling\n"
  213. "ddr dqsgd - dump DQS Gating Delay\n"
  214. "ddr mdl - dump Master Delay Line\n"
  215. "ddr reg - dump registers\n"
  216. );