0011-haswell-NRI-Initialise-MPLL.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. From 77a89d55ab7a715dc20c34a6edacaaf781b56087 Mon Sep 17 00:00:00 2001
  2. From: Angel Pons <th3fanbus@gmail.com>
  3. Date: Sat, 7 May 2022 14:36:10 +0200
  4. Subject: [PATCH 11/26] haswell NRI: Initialise MPLL
  5. Add code to initialise the MPLL (Memory PLL). The procedure is similar
  6. to the one for Sandy/Ivy Bridge, but it is not worth factoring out.
  7. Change-Id: I978c352de68f6d8cecc76f4ae3c12daaf4be9ed6
  8. Signed-off-by: Angel Pons <th3fanbus@gmail.com>
  9. ---
  10. .../intel/haswell/native_raminit/Makefile.inc | 2 +
  11. .../intel/haswell/native_raminit/init_mpll.c | 210 ++++++++++++++++++
  12. .../haswell/native_raminit/io_comp_control.c | 22 ++
  13. .../haswell/native_raminit/raminit_main.c | 1 +
  14. .../haswell/native_raminit/raminit_native.h | 11 +
  15. .../intel/haswell/registers/mchbar.h | 3 +
  16. 6 files changed, 249 insertions(+)
  17. create mode 100644 src/northbridge/intel/haswell/native_raminit/init_mpll.c
  18. create mode 100644 src/northbridge/intel/haswell/native_raminit/io_comp_control.c
  19. diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.inc b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  20. index ebf7abc6ec..c125d84f0b 100644
  21. --- a/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  22. +++ b/src/northbridge/intel/haswell/native_raminit/Makefile.inc
  23. @@ -1,5 +1,7 @@
  24. ## SPDX-License-Identifier: GPL-2.0-or-later
  25. +romstage-y += init_mpll.c
  26. +romstage-y += io_comp_control.c
  27. romstage-y += raminit_main.c
  28. romstage-y += raminit_native.c
  29. romstage-y += spd_bitmunching.c
  30. diff --git a/src/northbridge/intel/haswell/native_raminit/init_mpll.c b/src/northbridge/intel/haswell/native_raminit/init_mpll.c
  31. new file mode 100644
  32. index 0000000000..2faa183724
  33. --- /dev/null
  34. +++ b/src/northbridge/intel/haswell/native_raminit/init_mpll.c
  35. @@ -0,0 +1,210 @@
  36. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  37. +
  38. +#include <commonlib/clamp.h>
  39. +#include <console/console.h>
  40. +#include <delay.h>
  41. +#include <device/pci_ops.h>
  42. +#include <northbridge/intel/haswell/haswell.h>
  43. +#include <types.h>
  44. +
  45. +#include "raminit_native.h"
  46. +
  47. +static uint32_t get_mem_multiplier(const struct sysinfo *ctrl)
  48. +{
  49. + const uint32_t mult = NS2MHZ_DIV256 / (ctrl->tCK * ctrl->base_freq);
  50. +
  51. + if (ctrl->base_freq == 100)
  52. + return clamp_u32(7, mult, 12);
  53. +
  54. + if (ctrl->base_freq == 133)
  55. + return clamp_u32(3, mult, 10);
  56. +
  57. + die("Unsupported base frequency\n");
  58. +}
  59. +
  60. +static void normalize_tck(struct sysinfo *ctrl, const bool pll_ref100)
  61. +{
  62. + /** TODO: Haswell supports up to DDR3-2600 **/
  63. + if (ctrl->tCK <= TCK_1200MHZ) {
  64. + ctrl->tCK = TCK_1200MHZ;
  65. + ctrl->base_freq = 133;
  66. + ctrl->mem_clock_mhz = 1200;
  67. +
  68. + } else if (ctrl->tCK <= TCK_1100MHZ) {
  69. + ctrl->tCK = TCK_1100MHZ;
  70. + ctrl->base_freq = 100;
  71. + ctrl->mem_clock_mhz = 1100;
  72. +
  73. + } else if (ctrl->tCK <= TCK_1066MHZ) {
  74. + ctrl->tCK = TCK_1066MHZ;
  75. + ctrl->base_freq = 133;
  76. + ctrl->mem_clock_mhz = 1066;
  77. +
  78. + } else if (ctrl->tCK <= TCK_1000MHZ) {
  79. + ctrl->tCK = TCK_1000MHZ;
  80. + ctrl->base_freq = 100;
  81. + ctrl->mem_clock_mhz = 1000;
  82. +
  83. + } else if (ctrl->tCK <= TCK_933MHZ) {
  84. + ctrl->tCK = TCK_933MHZ;
  85. + ctrl->base_freq = 133;
  86. + ctrl->mem_clock_mhz = 933;
  87. +
  88. + } else if (ctrl->tCK <= TCK_900MHZ) {
  89. + ctrl->tCK = TCK_900MHZ;
  90. + ctrl->base_freq = 100;
  91. + ctrl->mem_clock_mhz = 900;
  92. +
  93. + } else if (ctrl->tCK <= TCK_800MHZ) {
  94. + ctrl->tCK = TCK_800MHZ;
  95. + ctrl->base_freq = 133;
  96. + ctrl->mem_clock_mhz = 800;
  97. +
  98. + } else if (ctrl->tCK <= TCK_700MHZ) {
  99. + ctrl->tCK = TCK_700MHZ;
  100. + ctrl->base_freq = 100;
  101. + ctrl->mem_clock_mhz = 700;
  102. +
  103. + } else if (ctrl->tCK <= TCK_666MHZ) {
  104. + ctrl->tCK = TCK_666MHZ;
  105. + ctrl->base_freq = 133;
  106. + ctrl->mem_clock_mhz = 666;
  107. +
  108. + } else if (ctrl->tCK <= TCK_533MHZ) {
  109. + ctrl->tCK = TCK_533MHZ;
  110. + ctrl->base_freq = 133;
  111. + ctrl->mem_clock_mhz = 533;
  112. +
  113. + } else if (ctrl->tCK <= TCK_400MHZ) {
  114. + ctrl->tCK = TCK_400MHZ;
  115. + ctrl->base_freq = 133;
  116. + ctrl->mem_clock_mhz = 400;
  117. +
  118. + } else {
  119. + ctrl->tCK = 0;
  120. + ctrl->base_freq = 1;
  121. + ctrl->mem_clock_mhz = 0;
  122. + return;
  123. + }
  124. + if (!pll_ref100 && ctrl->base_freq == 100) {
  125. + /* Skip unsupported frequency */
  126. + ctrl->tCK++;
  127. + normalize_tck(ctrl, pll_ref100);
  128. + }
  129. +}
  130. +
  131. +#define MIN_CAS 4
  132. +#define MAX_CAS 24
  133. +
  134. +static uint8_t find_compatible_cas(struct sysinfo *ctrl)
  135. +{
  136. + printk(RAM_DEBUG, "With tCK %u, try CAS: ", ctrl->tCK);
  137. + const uint8_t cas_lower = MAX(MIN_CAS, DIV_ROUND_UP(ctrl->tAA, ctrl->tCK));
  138. + const uint8_t cas_upper = MIN(MAX_CAS, 19); /* JEDEC MR0 limit */
  139. +
  140. + if (!(ctrl->cas_supported >> (cas_lower - MIN_CAS))) {
  141. + printk(RAM_DEBUG, "DIMMs do not support CAS >= %u\n", cas_lower);
  142. + ctrl->tCK++;
  143. + return 0;
  144. + }
  145. + for (uint8_t cas = cas_lower; cas <= cas_upper; cas++) {
  146. + printk(RAM_DEBUG, "%u ", cas);
  147. + if (ctrl->cas_supported & BIT(cas - MIN_CAS)) {
  148. + printk(RAM_DEBUG, "OK\n");
  149. + return cas;
  150. + }
  151. + }
  152. + return 0;
  153. +}
  154. +
  155. +static enum raminit_status find_cas_tck(struct sysinfo *ctrl)
  156. +{
  157. + /** TODO: Honor all possible PLL_REF100_CFG values **/
  158. + uint8_t pll_ref100 = (pci_read_config32(HOST_BRIDGE, CAPID0_B) >> 21) & 0x7;
  159. + printk(RAM_DEBUG, "PLL_REF100_CFG value: 0x%x\n", pll_ref100);
  160. + printk(RAM_DEBUG, "100MHz reference clock support: %s\n", pll_ref100 ? "yes" : "no");
  161. +
  162. + uint8_t selected_cas;
  163. + while (true) {
  164. + /* Round tCK up so that it is a multiple of either 133 or 100 MHz */
  165. + normalize_tck(ctrl, pll_ref100);
  166. + if (!ctrl->tCK) {
  167. + printk(BIOS_ERR, "Couldn't find compatible clock / CAS settings\n");
  168. + return RAMINIT_STATUS_MPLL_INIT_FAILURE;
  169. + }
  170. + selected_cas = find_compatible_cas(ctrl);
  171. + if (selected_cas)
  172. + break;
  173. +
  174. + ctrl->tCK++;
  175. + }
  176. + printk(BIOS_DEBUG, "Found compatible clock / CAS settings\n");
  177. + printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", NS2MHZ_DIV256 / ctrl->tCK);
  178. + printk(BIOS_DEBUG, "Selected CAS latency : %uT\n", selected_cas);
  179. + ctrl->multiplier = get_mem_multiplier(ctrl);
  180. + return RAMINIT_STATUS_SUCCESS;
  181. +}
  182. +
  183. +enum raminit_status initialise_mpll(struct sysinfo *ctrl)
  184. +{
  185. + if (ctrl->tCK > TCK_400MHZ) {
  186. + printk(BIOS_ERR, "tCK is too slow. Increasing to 400 MHz as last resort\n");
  187. + ctrl->tCK = TCK_400MHZ;
  188. + }
  189. + while (true) {
  190. + if (!ctrl->qclkps) {
  191. + const enum raminit_status status = find_cas_tck(ctrl);
  192. + if (status)
  193. + return status;
  194. + }
  195. +
  196. + /*
  197. + * Unlike previous generations, Haswell's MPLL won't shut down if the
  198. + * requested frequency isn't supported. But we cannot reinitialize it.
  199. + * Another different thing: MPLL registers are 4-bit instead of 8-bit.
  200. + */
  201. +
  202. + /** FIXME: Obtain current clock frequency if we want to skip this **/
  203. + //if (mchbar_read32(MC_BIOS_DATA) != 0)
  204. + // break;
  205. +
  206. + uint32_t mc_bios_req = ctrl->multiplier;
  207. + if (ctrl->base_freq == 100) {
  208. + /* Use 100 MHz reference clock */
  209. + mc_bios_req |= BIT(4);
  210. + }
  211. + mc_bios_req |= BIT(31);
  212. + printk(RAM_DEBUG, "MC_BIOS_REQ = 0x%08x\n", mc_bios_req);
  213. + printk(BIOS_DEBUG, "MPLL busy... ");
  214. + mchbar_write32(MC_BIOS_REQ, mc_bios_req);
  215. +
  216. + for (unsigned int i = 0; i <= 5000; i++) {
  217. + if (!(mchbar_read32(MC_BIOS_REQ) & BIT(31))) {
  218. + printk(BIOS_DEBUG, "done in %u us\n", i);
  219. + break;
  220. + }
  221. + udelay(1);
  222. + }
  223. + if (mchbar_read32(MC_BIOS_REQ) & BIT(31))
  224. + printk(BIOS_DEBUG, "did not lock\n");
  225. +
  226. + /* Verify locked frequency */
  227. + const uint32_t mc_bios_data = mchbar_read32(MC_BIOS_DATA);
  228. + printk(RAM_DEBUG, "MC_BIOS_DATA = 0x%08x\n", mc_bios_data);
  229. + if ((mc_bios_data & 0xf) >= ctrl->multiplier)
  230. + break;
  231. +
  232. + printk(BIOS_DEBUG, "Retrying at a lower frequency\n\n");
  233. + ctrl->tCK++;
  234. + }
  235. + if (!ctrl->mem_clock_mhz) {
  236. + printk(BIOS_ERR, "Could not program MPLL frequency\n");
  237. + return RAMINIT_STATUS_MPLL_INIT_FAILURE;
  238. + }
  239. + printk(BIOS_DEBUG, "MPLL frequency is set to: %u MHz ", ctrl->mem_clock_mhz);
  240. + ctrl->mem_clock_fs = 1000000000 / ctrl->mem_clock_mhz;
  241. + printk(BIOS_DEBUG, "(period: %u femtoseconds)\n", ctrl->mem_clock_fs);
  242. + ctrl->qclkps = ctrl->mem_clock_fs / 2000;
  243. + printk(BIOS_DEBUG, "Quadrature clock period: %u picoseconds\n", ctrl->qclkps);
  244. + return wait_for_first_rcomp();
  245. +}
  246. diff --git a/src/northbridge/intel/haswell/native_raminit/io_comp_control.c b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c
  247. new file mode 100644
  248. index 0000000000..7e96c08938
  249. --- /dev/null
  250. +++ b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c
  251. @@ -0,0 +1,22 @@
  252. +/* SPDX-License-Identifier: GPL-2.0-or-later */
  253. +
  254. +#include <commonlib/clamp.h>
  255. +#include <console/console.h>
  256. +#include <northbridge/intel/haswell/haswell.h>
  257. +#include <timer.h>
  258. +#include <types.h>
  259. +
  260. +#include "raminit_native.h"
  261. +
  262. +enum raminit_status wait_for_first_rcomp(void)
  263. +{
  264. + struct stopwatch timer;
  265. + stopwatch_init_msecs_expire(&timer, 2000);
  266. + do {
  267. + if (mchbar_read32(RCOMP_TIMER) & BIT(16))
  268. + return RAMINIT_STATUS_SUCCESS;
  269. +
  270. + } while (!stopwatch_expired(&timer));
  271. + printk(BIOS_ERR, "Timed out waiting for RCOMP to complete\n");
  272. + return RAMINIT_STATUS_POLL_TIMEOUT;
  273. +}
  274. diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
  275. index 2d2cfa48bb..09545422c0 100644
  276. --- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c
  277. +++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c
  278. @@ -21,6 +21,7 @@ struct task_entry {
  279. static const struct task_entry cold_boot[] = {
  280. { collect_spd_info, true, "PROCSPD", },
  281. + { initialise_mpll, true, "INITMPLL", },
  282. };
  283. /* Return a generic stepping value to make stepping checks simpler */
  284. diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
  285. index 1a0793947e..a54581abc7 100644
  286. --- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h
  287. +++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h
  288. @@ -23,6 +23,8 @@ enum raminit_status {
  289. RAMINIT_STATUS_SUCCESS = 0,
  290. RAMINIT_STATUS_NO_MEMORY_INSTALLED,
  291. RAMINIT_STATUS_UNSUPPORTED_MEMORY,
  292. + RAMINIT_STATUS_MPLL_INIT_FAILURE,
  293. + RAMINIT_STATUS_POLL_TIMEOUT,
  294. RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/
  295. };
  296. @@ -82,10 +84,19 @@ struct sysinfo {
  297. uint8_t rankmap[NUM_CHANNELS];
  298. uint8_t rank_mirrored[NUM_CHANNELS];
  299. uint32_t channel_size_mb[NUM_CHANNELS];
  300. +
  301. + uint8_t base_freq; /* Memory base frequency, either 100 or 133 MHz */
  302. + uint32_t multiplier;
  303. + uint32_t mem_clock_mhz;
  304. + uint32_t mem_clock_fs; /* Memory clock period in femtoseconds */
  305. + uint32_t qclkps; /* Quadrature clock period in picoseconds */
  306. };
  307. void raminit_main(enum raminit_boot_mode bootmode);
  308. enum raminit_status collect_spd_info(struct sysinfo *ctrl);
  309. +enum raminit_status initialise_mpll(struct sysinfo *ctrl);
  310. +
  311. +enum raminit_status wait_for_first_rcomp(void);
  312. #endif
  313. diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h
  314. index 5610e7089a..45f8174995 100644
  315. --- a/src/northbridge/intel/haswell/registers/mchbar.h
  316. +++ b/src/northbridge/intel/haswell/registers/mchbar.h
  317. @@ -13,6 +13,8 @@
  318. #define MC_INIT_STATE_G 0x5030
  319. #define MRC_REVISION 0x5034 /* MRC Revision */
  320. +#define RCOMP_TIMER 0x5084
  321. +
  322. #define MC_LOCK 0x50fc /* Memory Controller Lock register */
  323. #define GFXVTBAR 0x5400 /* Base address for IGD */
  324. @@ -61,6 +63,7 @@
  325. #define BIOS_RESET_CPL 0x5da8 /* 8-bit */
  326. +#define MC_BIOS_REQ 0x5e00 /* Memory frequency request register */
  327. #define MC_BIOS_DATA 0x5e04 /* Miscellaneous information for BIOS */
  328. #define SAPMCTL 0x5f00
  329. --
  330. 2.39.2