utility.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright 2021-2022 NXP
  3. *
  4. * SPDX-License-Identifier: BSD-3-Clause
  5. *
  6. */
  7. #include <errno.h>
  8. #include <stdint.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <common/debug.h>
  12. #include <ddr.h>
  13. #include <immap.h>
  14. #include <lib/mmio.h>
  15. #define UL_5POW12 244140625UL
  16. #define ULL_2E12 2000000000000ULL
  17. #define UL_2POW13 (1UL << 13)
  18. #define ULL_8FS 0xFFFFFFFFULL
  19. #define do_div(n, base) ({ \
  20. unsigned int __base = (base); \
  21. unsigned int __rem; \
  22. __rem = ((unsigned long long)(n)) % __base; \
  23. (n) = ((unsigned long long)(n)) / __base; \
  24. __rem; \
  25. })
  26. #define CCN_HN_F_SAM_NODEID_MASK 0x7f
  27. #ifdef NXP_HAS_CCN504
  28. #define CCN_HN_F_SAM_NODEID_DDR0 0x4
  29. #define CCN_HN_F_SAM_NODEID_DDR1 0xe
  30. #elif defined(NXP_HAS_CCN508)
  31. #define CCN_HN_F_SAM_NODEID_DDR0_0 0x3
  32. #define CCN_HN_F_SAM_NODEID_DDR0_1 0x8
  33. #define CCN_HN_F_SAM_NODEID_DDR1_0 0x13
  34. #define CCN_HN_F_SAM_NODEID_DDR1_1 0x18
  35. #endif
  36. unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num)
  37. {
  38. if (sys->freq_ddr_pll0 == 0) {
  39. get_clocks(sys);
  40. }
  41. switch (ctrl_num) {
  42. case 0:
  43. return sys->freq_ddr_pll0;
  44. case 1:
  45. return sys->freq_ddr_pll0;
  46. case 2:
  47. return sys->freq_ddr_pll1;
  48. }
  49. return 0;
  50. }
  51. unsigned int get_memory_clk_ps(const unsigned long data_rate)
  52. {
  53. unsigned int result;
  54. /* Round to nearest 10ps, being careful about 64-bit multiply/divide */
  55. unsigned long long rem, mclk_ps = ULL_2E12;
  56. /* Now perform the big divide, the result fits in 32-bits */
  57. rem = do_div(mclk_ps, data_rate);
  58. result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps;
  59. return result;
  60. }
  61. unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos)
  62. {
  63. unsigned long long clks, clks_rem;
  64. /* Short circuit for zero picos */
  65. if ((picos == 0U) || (data_rate == 0UL)) {
  66. return 0U;
  67. }
  68. /* First multiply the time by the data rate (32x32 => 64) */
  69. clks = picos * (unsigned long long)data_rate;
  70. /*
  71. * Now divide by 5^12 and track the 32-bit remainder, then divide
  72. * by 2*(2^12) using shifts (and updating the remainder).
  73. */
  74. clks_rem = do_div(clks, UL_5POW12);
  75. clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12;
  76. clks >>= 13U;
  77. /* If we had a remainder greater than the 1ps error, then round up */
  78. if (clks_rem > data_rate) {
  79. clks++;
  80. }
  81. /* Clamp to the maximum representable value */
  82. if (clks > ULL_8FS) {
  83. clks = ULL_8FS;
  84. }
  85. return (unsigned int) clks;
  86. }
  87. /* valid_spd_mask has been checked by parse_spd */
  88. int disable_unused_ddrc(struct ddr_info *priv,
  89. int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr)
  90. {
  91. #if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508)
  92. void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL);
  93. uint32_t val, nodeid;
  94. #ifdef NXP_HAS_CCN504
  95. uint32_t num_hnf_nodes = 4U;
  96. #else
  97. uint32_t num_hnf_nodes = 8U;
  98. #endif
  99. int disable_ddrc = 0;
  100. int i;
  101. if (priv->num_ctlrs < 2) {
  102. debug("%s: nothing to do.\n", __func__);
  103. }
  104. switch (priv->dimm_on_ctlr) {
  105. case 1:
  106. disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0;
  107. disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
  108. break;
  109. case 2:
  110. disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0;
  111. disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc;
  112. break;
  113. default:
  114. ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr);
  115. return -EINVAL;
  116. }
  117. if (disable_ddrc != 0) {
  118. debug("valid_spd_mask = 0x%x\n", valid_spd_mask);
  119. }
  120. switch (disable_ddrc) {
  121. case 1:
  122. priv->num_ctlrs = 1;
  123. priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr];
  124. priv->ddr[0] = priv->ddr[1];
  125. priv->ddr[1] = NULL;
  126. priv->phy[0] = priv->phy[0];
  127. priv->phy[1] = NULL;
  128. debug("Disable first DDR controller\n");
  129. break;
  130. case 2:
  131. priv->num_ctlrs = 1;
  132. priv->ddr[1] = NULL;
  133. priv->phy[1] = NULL;
  134. debug("Disable second DDR controller\n");
  135. /* fallthrough */
  136. case 0:
  137. break;
  138. default:
  139. ERROR("Program error.\n");
  140. return -EINVAL;
  141. }
  142. if (disable_ddrc == 0) {
  143. debug("Both controllers in use.\n");
  144. return 0;
  145. }
  146. for (i = 0; i < num_hnf_nodes; i++) {
  147. val = mmio_read_64((uintptr_t)hnf_sam_ctrl);
  148. #ifdef NXP_HAS_CCN504
  149. nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 :
  150. (disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 :
  151. 0x0); /*Failure condition. never hit */
  152. #elif defined(NXP_HAS_CCN508)
  153. if (disable_ddrc == 1) {
  154. nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR1_1 :
  155. CCN_HN_F_SAM_NODEID_DDR1_0;
  156. } else if (disable_ddrc == 2) {
  157. nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR0_0 :
  158. CCN_HN_F_SAM_NODEID_DDR0_1;
  159. } else {
  160. nodeid = 0; /* Failure condition. never hit */
  161. }
  162. #endif
  163. if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) {
  164. debug("Setting HN-F node %d\n", i);
  165. debug("nodeid = 0x%x\n", nodeid);
  166. val &= ~CCN_HN_F_SAM_NODEID_MASK;
  167. val |= nodeid;
  168. mmio_write_64((uintptr_t)hnf_sam_ctrl, val);
  169. }
  170. hnf_sam_ctrl += CCN_HN_F_REGION_SIZE;
  171. }
  172. #endif
  173. return 0;
  174. }
  175. unsigned int get_ddrc_version(const struct ccsr_ddr *ddr)
  176. {
  177. unsigned int ver;
  178. ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U;
  179. ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U;
  180. return ver;
  181. }
  182. void print_ddr_info(struct ccsr_ddr *ddr)
  183. {
  184. unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]);
  185. unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg);
  186. int cas_lat;
  187. if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) {
  188. printf(" (DDR not enabled)\n");
  189. return;
  190. }
  191. printf("DDR");
  192. switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >>
  193. SDRAM_CFG_SDRAM_TYPE_SHIFT) {
  194. case SDRAM_TYPE_DDR4:
  195. printf("4");
  196. break;
  197. default:
  198. printf("?");
  199. break;
  200. }
  201. switch (sdram_cfg & SDRAM_CFG_DBW_MASK) {
  202. case SDRAM_CFG_32_BW:
  203. printf(", 32-bit");
  204. break;
  205. case SDRAM_CFG_16_BW:
  206. printf(", 16-bit");
  207. break;
  208. case SDRAM_CFG_8_BW:
  209. printf(", 8-bit");
  210. break;
  211. default:
  212. printf(", 64-bit");
  213. break;
  214. }
  215. /* Calculate CAS latency based on timing cfg values */
  216. cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf);
  217. cas_lat += 2; /* for DDRC newer than 4.4 */
  218. cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4;
  219. printf(", CL=%d", cas_lat >> 1);
  220. if ((cas_lat & 0x1) != 0) {
  221. printf(".5");
  222. }
  223. if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) {
  224. printf(", ECC on");
  225. } else {
  226. printf(", ECC off");
  227. }
  228. if ((cs0_config & 0x20000000) != 0) {
  229. printf(", ");
  230. switch ((cs0_config >> 24) & 0xf) {
  231. case DDR_256B_INTLV:
  232. printf("256B");
  233. break;
  234. default:
  235. printf("invalid");
  236. break;
  237. }
  238. }
  239. if (((sdram_cfg >> 8) & 0x7f) != 0) {
  240. printf(", ");
  241. switch (sdram_cfg >> 8 & 0x7f) {
  242. case DDR_BA_INTLV_CS0123:
  243. printf("CS0+CS1+CS2+CS3");
  244. break;
  245. case DDR_BA_INTLV_CS01:
  246. printf("CS0+CS1");
  247. break;
  248. default:
  249. printf("invalid");
  250. break;
  251. }
  252. }
  253. printf("\n");
  254. }