mv_ddr_spd.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) Marvell International Ltd. and its affiliates
  4. */
  5. #include "mv_ddr_spd.h"
  6. #define MV_DDR_SPD_DATA_MTB 125 /* medium timebase, ps */
  7. #define MV_DDR_SPD_DATA_FTB 1 /* fine timebase, ps */
  8. #define MV_DDR_SPD_MSB_OFFS 8 /* most significant byte offset, bits */
  9. #define MV_DDR_SPD_SUPPORTED_CLS_NUM 30
  10. static unsigned int mv_ddr_spd_supported_cls[MV_DDR_SPD_SUPPORTED_CLS_NUM];
  11. int mv_ddr_spd_supported_cls_calc(union mv_ddr_spd_data *spd_data)
  12. {
  13. unsigned int byte, bit, start_cl;
  14. start_cl = (spd_data->all_bytes[23] & 0x8) ? 23 : 7;
  15. for (byte = 20; byte < 23; byte++) {
  16. for (bit = 0; bit < 8; bit++) {
  17. if (spd_data->all_bytes[byte] & (1 << bit))
  18. mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
  19. else
  20. mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
  21. }
  22. }
  23. for (byte = 23, bit = 0; bit < 6; bit++) {
  24. if (spd_data->all_bytes[byte] & (1 << bit))
  25. mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = start_cl + (byte - 20) * 8 + bit;
  26. else
  27. mv_ddr_spd_supported_cls[(byte - 20) * 8 + bit] = 0;
  28. }
  29. return 0;
  30. }
  31. unsigned int mv_ddr_spd_supported_cl_get(unsigned int cl)
  32. {
  33. unsigned int supported_cl;
  34. int i = 0;
  35. while (i < MV_DDR_SPD_SUPPORTED_CLS_NUM &&
  36. mv_ddr_spd_supported_cls[i] < cl)
  37. i++;
  38. if (i < MV_DDR_SPD_SUPPORTED_CLS_NUM)
  39. supported_cl = mv_ddr_spd_supported_cls[i];
  40. else
  41. supported_cl = 0;
  42. return supported_cl;
  43. }
  44. int mv_ddr_spd_timing_calc(union mv_ddr_spd_data *spd_data, unsigned int timing_data[])
  45. {
  46. int calc_val;
  47. /* t ck avg min, ps */
  48. calc_val = spd_data->byte_fields.byte_18 * MV_DDR_SPD_DATA_MTB +
  49. (signed char)spd_data->byte_fields.byte_125 * MV_DDR_SPD_DATA_FTB;
  50. if (calc_val < 0)
  51. return 1;
  52. timing_data[MV_DDR_TCK_AVG_MIN] = calc_val;
  53. /* t aa min, ps */
  54. calc_val = spd_data->byte_fields.byte_24 * MV_DDR_SPD_DATA_MTB +
  55. (signed char)spd_data->byte_fields.byte_123 * MV_DDR_SPD_DATA_FTB;
  56. if (calc_val < 0)
  57. return 1;
  58. timing_data[MV_DDR_TAA_MIN] = calc_val;
  59. /* t rfc1 min, ps */
  60. timing_data[MV_DDR_TRFC1_MIN] = (spd_data->byte_fields.byte_30 +
  61. (spd_data->byte_fields.byte_31 << MV_DDR_SPD_MSB_OFFS)) * MV_DDR_SPD_DATA_MTB;
  62. /* t wr min, ps */
  63. timing_data[MV_DDR_TWR_MIN] = (spd_data->byte_fields.byte_42 +
  64. (spd_data->byte_fields.byte_41.bit_fields.t_wr_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  65. MV_DDR_SPD_DATA_MTB;
  66. /* FIXME: wa: set twr to a default value, if it's unset on spd */
  67. if (timing_data[MV_DDR_TWR_MIN] == 0)
  68. timing_data[MV_DDR_TWR_MIN] = 15000;
  69. /* t rcd min, ps */
  70. calc_val = spd_data->byte_fields.byte_25 * MV_DDR_SPD_DATA_MTB +
  71. (signed char)spd_data->byte_fields.byte_122 * MV_DDR_SPD_DATA_FTB;
  72. if (calc_val < 0)
  73. return 1;
  74. timing_data[MV_DDR_TRCD_MIN] = calc_val;
  75. /* t rp min, ps */
  76. calc_val = spd_data->byte_fields.byte_26 * MV_DDR_SPD_DATA_MTB +
  77. (signed char)spd_data->byte_fields.byte_121 * MV_DDR_SPD_DATA_FTB;
  78. if (calc_val < 0)
  79. return 1;
  80. timing_data[MV_DDR_TRP_MIN] = calc_val;
  81. /* t rc min, ps */
  82. calc_val = (spd_data->byte_fields.byte_29 +
  83. (spd_data->byte_fields.byte_27.bit_fields.t_rc_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  84. MV_DDR_SPD_DATA_MTB +
  85. (signed char)spd_data->byte_fields.byte_120 * MV_DDR_SPD_DATA_FTB;
  86. if (calc_val < 0)
  87. return 1;
  88. timing_data[MV_DDR_TRC_MIN] = calc_val;
  89. /* t ras min, ps */
  90. timing_data[MV_DDR_TRAS_MIN] = (spd_data->byte_fields.byte_28 +
  91. (spd_data->byte_fields.byte_27.bit_fields.t_ras_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  92. MV_DDR_SPD_DATA_MTB;
  93. /* t rrd s min, ps */
  94. calc_val = spd_data->byte_fields.byte_38 * MV_DDR_SPD_DATA_MTB +
  95. (signed char)spd_data->byte_fields.byte_119 * MV_DDR_SPD_DATA_FTB;
  96. if (calc_val < 0)
  97. return 1;
  98. timing_data[MV_DDR_TRRD_S_MIN] = calc_val;
  99. /* t rrd l min, ps */
  100. calc_val = spd_data->byte_fields.byte_39 * MV_DDR_SPD_DATA_MTB +
  101. (signed char)spd_data->byte_fields.byte_118 * MV_DDR_SPD_DATA_FTB;
  102. if (calc_val < 0)
  103. return 1;
  104. timing_data[MV_DDR_TRRD_L_MIN] = calc_val;
  105. /* t faw min, ps */
  106. timing_data[MV_DDR_TFAW_MIN] = (spd_data->byte_fields.byte_37 +
  107. (spd_data->byte_fields.byte_36.bit_fields.t_faw_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  108. MV_DDR_SPD_DATA_MTB;
  109. /* t wtr s min, ps */
  110. timing_data[MV_DDR_TWTR_S_MIN] = (spd_data->byte_fields.byte_44 +
  111. (spd_data->byte_fields.byte_43.bit_fields.t_wtr_s_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  112. MV_DDR_SPD_DATA_MTB;
  113. /* FIXME: wa: set twtr_s to a default value, if it's unset on spd */
  114. if (timing_data[MV_DDR_TWTR_S_MIN] == 0)
  115. timing_data[MV_DDR_TWTR_S_MIN] = 2500;
  116. /* t wtr l min, ps */
  117. timing_data[MV_DDR_TWTR_L_MIN] = (spd_data->byte_fields.byte_45 +
  118. (spd_data->byte_fields.byte_43.bit_fields.t_wtr_l_min_msn << MV_DDR_SPD_MSB_OFFS)) *
  119. MV_DDR_SPD_DATA_MTB;
  120. /* FIXME: wa: set twtr_l to a default value, if it's unset on spd */
  121. if (timing_data[MV_DDR_TWTR_L_MIN] == 0)
  122. timing_data[MV_DDR_TWTR_L_MIN] = 7500;
  123. return 0;
  124. }
  125. enum mv_ddr_dev_width mv_ddr_spd_dev_width_get(union mv_ddr_spd_data *spd_data)
  126. {
  127. unsigned char dev_width = spd_data->byte_fields.byte_12.bit_fields.device_width;
  128. enum mv_ddr_dev_width ret_val;
  129. switch (dev_width) {
  130. case 0x00:
  131. ret_val = MV_DDR_DEV_WIDTH_4BIT;
  132. break;
  133. case 0x01:
  134. ret_val = MV_DDR_DEV_WIDTH_8BIT;
  135. break;
  136. case 0x02:
  137. ret_val = MV_DDR_DEV_WIDTH_16BIT;
  138. break;
  139. case 0x03:
  140. ret_val = MV_DDR_DEV_WIDTH_32BIT;
  141. break;
  142. default:
  143. ret_val = MV_DDR_DEV_WIDTH_LAST;
  144. }
  145. return ret_val;
  146. }
  147. enum mv_ddr_die_capacity mv_ddr_spd_die_capacity_get(union mv_ddr_spd_data *spd_data)
  148. {
  149. unsigned char die_cap = spd_data->byte_fields.byte_4.bit_fields.die_capacity;
  150. enum mv_ddr_die_capacity ret_val;
  151. switch (die_cap) {
  152. case 0x00:
  153. ret_val = MV_DDR_DIE_CAP_256MBIT;
  154. break;
  155. case 0x01:
  156. ret_val = MV_DDR_DIE_CAP_512MBIT;
  157. break;
  158. case 0x02:
  159. ret_val = MV_DDR_DIE_CAP_1GBIT;
  160. break;
  161. case 0x03:
  162. ret_val = MV_DDR_DIE_CAP_2GBIT;
  163. break;
  164. case 0x04:
  165. ret_val = MV_DDR_DIE_CAP_4GBIT;
  166. break;
  167. case 0x05:
  168. ret_val = MV_DDR_DIE_CAP_8GBIT;
  169. break;
  170. case 0x06:
  171. ret_val = MV_DDR_DIE_CAP_16GBIT;
  172. break;
  173. case 0x07:
  174. ret_val = MV_DDR_DIE_CAP_32GBIT;
  175. break;
  176. case 0x08:
  177. ret_val = MV_DDR_DIE_CAP_12GBIT;
  178. break;
  179. case 0x09:
  180. ret_val = MV_DDR_DIE_CAP_24GBIT;
  181. break;
  182. default:
  183. ret_val = MV_DDR_DIE_CAP_LAST;
  184. }
  185. return ret_val;
  186. }
  187. unsigned char mv_ddr_spd_mem_mirror_get(union mv_ddr_spd_data *spd_data)
  188. {
  189. unsigned char mem_mirror = spd_data->byte_fields.byte_131.bit_fields.rank_1_mapping;
  190. return mem_mirror;
  191. }
  192. enum mv_ddr_pkg_rank mv_ddr_spd_pri_bus_width_get(union mv_ddr_spd_data *spd_data)
  193. {
  194. unsigned char pri_bus_width = spd_data->byte_fields.byte_13.bit_fields.primary_bus_width;
  195. enum mv_ddr_pri_bus_width ret_val;
  196. switch (pri_bus_width) {
  197. case 0x00:
  198. ret_val = MV_DDR_PRI_BUS_WIDTH_8;
  199. break;
  200. case 0x01:
  201. ret_val = MV_DDR_PRI_BUS_WIDTH_16;
  202. break;
  203. case 0x02:
  204. ret_val = MV_DDR_PRI_BUS_WIDTH_32;
  205. break;
  206. case 0x03:
  207. ret_val = MV_DDR_PRI_BUS_WIDTH_64;
  208. break;
  209. default:
  210. ret_val = MV_DDR_PRI_BUS_WIDTH_LAST;
  211. }
  212. return ret_val;
  213. }
  214. enum mv_ddr_pkg_rank mv_ddr_spd_bus_width_ext_get(union mv_ddr_spd_data *spd_data)
  215. {
  216. unsigned char bus_width_ext = spd_data->byte_fields.byte_13.bit_fields.bus_width_ext;
  217. enum mv_ddr_bus_width_ext ret_val;
  218. switch (bus_width_ext) {
  219. case 0x00:
  220. ret_val = MV_DDR_BUS_WIDTH_EXT_0;
  221. break;
  222. case 0x01:
  223. ret_val = MV_DDR_BUS_WIDTH_EXT_8;
  224. break;
  225. default:
  226. ret_val = MV_DDR_BUS_WIDTH_EXT_LAST;
  227. }
  228. return ret_val;
  229. }
  230. static enum mv_ddr_pkg_rank mv_ddr_spd_pkg_rank_get(union mv_ddr_spd_data *spd_data)
  231. {
  232. unsigned char pkg_rank = spd_data->byte_fields.byte_12.bit_fields.dimm_pkg_ranks_num;
  233. enum mv_ddr_pkg_rank ret_val;
  234. switch (pkg_rank) {
  235. case 0x00:
  236. ret_val = MV_DDR_PKG_RANK_1;
  237. break;
  238. case 0x01:
  239. ret_val = MV_DDR_PKG_RANK_2;
  240. break;
  241. case 0x02:
  242. ret_val = MV_DDR_PKG_RANK_3;
  243. break;
  244. case 0x03:
  245. ret_val = MV_DDR_PKG_RANK_4;
  246. break;
  247. case 0x04:
  248. ret_val = MV_DDR_PKG_RANK_5;
  249. break;
  250. case 0x05:
  251. ret_val = MV_DDR_PKG_RANK_6;
  252. break;
  253. case 0x06:
  254. ret_val = MV_DDR_PKG_RANK_7;
  255. break;
  256. case 0x07:
  257. ret_val = MV_DDR_PKG_RANK_8;
  258. break;
  259. default:
  260. ret_val = MV_DDR_PKG_RANK_LAST;
  261. }
  262. return ret_val;
  263. }
  264. static enum mv_ddr_die_count mv_ddr_spd_die_count_get(union mv_ddr_spd_data *spd_data)
  265. {
  266. unsigned char die_count = spd_data->byte_fields.byte_6.bit_fields.die_count;
  267. enum mv_ddr_die_count ret_val;
  268. switch (die_count) {
  269. case 0x00:
  270. ret_val = MV_DDR_DIE_CNT_1;
  271. break;
  272. case 0x01:
  273. ret_val = MV_DDR_DIE_CNT_2;
  274. break;
  275. case 0x02:
  276. ret_val = MV_DDR_DIE_CNT_3;
  277. break;
  278. case 0x03:
  279. ret_val = MV_DDR_DIE_CNT_4;
  280. break;
  281. case 0x04:
  282. ret_val = MV_DDR_DIE_CNT_5;
  283. break;
  284. case 0x05:
  285. ret_val = MV_DDR_DIE_CNT_6;
  286. break;
  287. case 0x06:
  288. ret_val = MV_DDR_DIE_CNT_7;
  289. break;
  290. case 0x07:
  291. ret_val = MV_DDR_DIE_CNT_8;
  292. break;
  293. default:
  294. ret_val = MV_DDR_DIE_CNT_LAST;
  295. }
  296. return ret_val;
  297. }
  298. unsigned char mv_ddr_spd_cs_bit_mask_get(union mv_ddr_spd_data *spd_data)
  299. {
  300. unsigned char cs_bit_mask = 0x0;
  301. enum mv_ddr_pkg_rank pkg_rank = mv_ddr_spd_pkg_rank_get(spd_data);
  302. enum mv_ddr_die_count die_cnt = mv_ddr_spd_die_count_get(spd_data);
  303. if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_1)
  304. cs_bit_mask = 0x1;
  305. else if (pkg_rank == MV_DDR_PKG_RANK_1 && die_cnt == MV_DDR_DIE_CNT_2)
  306. cs_bit_mask = 0x3;
  307. else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_1)
  308. cs_bit_mask = 0x3;
  309. else if (pkg_rank == MV_DDR_PKG_RANK_2 && die_cnt == MV_DDR_DIE_CNT_2)
  310. cs_bit_mask = 0xf;
  311. return cs_bit_mask;
  312. }
  313. unsigned char mv_ddr_spd_dev_type_get(union mv_ddr_spd_data *spd_data)
  314. {
  315. unsigned char dev_type = spd_data->byte_fields.byte_2;
  316. return dev_type;
  317. }
  318. unsigned char mv_ddr_spd_module_type_get(union mv_ddr_spd_data *spd_data)
  319. {
  320. unsigned char module_type = spd_data->byte_fields.byte_3.bit_fields.module_type;
  321. return module_type;
  322. }