diff options
| author | Leah Rowe <leah@libreboot.org> | 2025-04-21 02:22:40 +0100 | 
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2025-04-21 03:26:54 +0100 | 
| commit | 762c7ff43ebd065de62f26fbe5729d221110c5a0 (patch) | |
| tree | e61a91b987761e52cca04f3a2b6dc0d0c26c2d47 /config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch | |
| parent | 86e7aa80c51979767208b858dac5f38d7e83914e (diff) | |
coreboot/default: Update, c247f62749b (8 Feb 2025)
This is currently the latest revision of coreboot.
Other coreboot trees to follow. The "next" tree will
also be merged with coreboot/default, in a follow-up
commit.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch')
| -rw-r--r-- | config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch | 348 | 
1 files changed, 0 insertions, 348 deletions
diff --git a/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch b/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch deleted file mode 100644 index a1cf9b75..00000000 --- a/config/coreboot/default/patches/0030-haswell-NRI-Initialise-MPLL.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 0966980e52286985fcd0fac6325bdd99f35ebcb8 Mon Sep 17 00:00:00 2001 -From: Angel Pons <th3fanbus@gmail.com> -Date: Thu, 11 Apr 2024 17:25:07 +0200 -Subject: [PATCH 30/51] haswell NRI: Initialise MPLL - -Add code to initialise the MPLL (Memory PLL). The procedure is similar -to the one for Sandy/Ivy Bridge, but it is not worth factoring out. - -Change-Id: I978c352de68f6d8cecc76f4ae3c12daaf4be9ed6 -Signed-off-by: Angel Pons <th3fanbus@gmail.com> ---- - .../intel/haswell/native_raminit/Makefile.mk  |   2 + - .../intel/haswell/native_raminit/init_mpll.c  | 210 ++++++++++++++++++ - .../haswell/native_raminit/io_comp_control.c  |  22 ++ - .../haswell/native_raminit/raminit_main.c     |   3 +- - .../haswell/native_raminit/raminit_native.h   |  11 + - .../intel/haswell/registers/mchbar.h          |   3 + - 6 files changed, 250 insertions(+), 1 deletion(-) - create mode 100644 src/northbridge/intel/haswell/native_raminit/init_mpll.c - create mode 100644 src/northbridge/intel/haswell/native_raminit/io_comp_control.c - -diff --git a/src/northbridge/intel/haswell/native_raminit/Makefile.mk b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -index ebf7abc6ec..c125d84f0b 100644 ---- a/src/northbridge/intel/haswell/native_raminit/Makefile.mk -+++ b/src/northbridge/intel/haswell/native_raminit/Makefile.mk -@@ -1,5 +1,7 @@ - ## SPDX-License-Identifier: GPL-2.0-or-later -  -+romstage-y += init_mpll.c -+romstage-y += io_comp_control.c - romstage-y += raminit_main.c - romstage-y += raminit_native.c - romstage-y += spd_bitmunching.c -diff --git a/src/northbridge/intel/haswell/native_raminit/init_mpll.c b/src/northbridge/intel/haswell/native_raminit/init_mpll.c -new file mode 100644 -index 0000000000..1f3f2c29a9 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/init_mpll.c -@@ -0,0 +1,210 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <delay.h> -+#include <device/pci_ops.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+static uint32_t get_mem_multiplier(const struct sysinfo *ctrl) -+{ -+	const uint32_t mult = NS2MHZ_DIV256 / (ctrl->tCK * ctrl->base_freq); -+ -+	if (ctrl->base_freq == 100) -+		return clamp_u32(7, mult, 12); -+ -+	if (ctrl->base_freq == 133) -+		return clamp_u32(3, mult, 10); -+ -+	die("Unsupported base frequency\n"); -+} -+ -+static void normalize_tck(struct sysinfo *ctrl, const bool pll_ref100) -+{ -+	/** TODO: Haswell supports up to DDR3-2600 **/ -+	if (ctrl->tCK <= TCK_1200MHZ) { -+		ctrl->tCK = TCK_1200MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 1200; -+ -+	} else if (ctrl->tCK <= TCK_1100MHZ) { -+		ctrl->tCK = TCK_1100MHZ; -+		ctrl->base_freq = 100; -+		ctrl->mem_clock_mhz = 1100; -+ -+	} else if (ctrl->tCK <= TCK_1066MHZ) { -+		ctrl->tCK = TCK_1066MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 1066; -+ -+	} else if (ctrl->tCK <= TCK_1000MHZ) { -+		ctrl->tCK = TCK_1000MHZ; -+		ctrl->base_freq = 100; -+		ctrl->mem_clock_mhz = 1000; -+ -+	} else if (ctrl->tCK <= TCK_933MHZ) { -+		ctrl->tCK = TCK_933MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 933; -+ -+	} else if (ctrl->tCK <= TCK_900MHZ) { -+		ctrl->tCK = TCK_900MHZ; -+		ctrl->base_freq = 100; -+		ctrl->mem_clock_mhz = 900; -+ -+	} else if (ctrl->tCK <= TCK_800MHZ) { -+		ctrl->tCK = TCK_800MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 800; -+ -+	} else if (ctrl->tCK <= TCK_700MHZ) { -+		ctrl->tCK = TCK_700MHZ; -+		ctrl->base_freq = 100; -+		ctrl->mem_clock_mhz = 700; -+ -+	} else if (ctrl->tCK <= TCK_666MHZ) { -+		ctrl->tCK = TCK_666MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 666; -+ -+	} else if (ctrl->tCK <= TCK_533MHZ) { -+		ctrl->tCK = TCK_533MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 533; -+ -+	} else if (ctrl->tCK <= TCK_400MHZ) { -+		ctrl->tCK = TCK_400MHZ; -+		ctrl->base_freq = 133; -+		ctrl->mem_clock_mhz = 400; -+ -+	} else { -+		ctrl->tCK = 0; -+		ctrl->base_freq = 1; -+		ctrl->mem_clock_mhz = 0; -+		return; -+	} -+	if (!pll_ref100 && ctrl->base_freq == 100) { -+		/* Skip unsupported frequency */ -+		ctrl->tCK++; -+		normalize_tck(ctrl, pll_ref100); -+	} -+} -+ -+#define MIN_CAS	4 -+#define MAX_CAS	24 -+ -+static uint8_t find_compatible_cas(struct sysinfo *ctrl) -+{ -+	printk(RAM_DEBUG, "With tCK %u, try CAS: ", ctrl->tCK); -+	const uint8_t cas_lower = MAX(MIN_CAS, DIV_ROUND_UP(ctrl->tAA, ctrl->tCK)); -+	const uint8_t cas_upper = MIN(MAX_CAS, 19); /* JEDEC MR0 limit */ -+ -+	if (!(ctrl->cas_supported >> (cas_lower - MIN_CAS))) { -+		printk(RAM_DEBUG, "DIMMs do not support CAS >= %u\n", cas_lower); -+		ctrl->tCK++; -+		return 0; -+	} -+	for (uint8_t cas = cas_lower; cas <= cas_upper; cas++) { -+		printk(RAM_DEBUG, "%u ", cas); -+		if (ctrl->cas_supported & BIT(cas - MIN_CAS)) { -+			printk(RAM_DEBUG, "OK\n"); -+			return cas; -+		} -+	} -+	return 0; -+} -+ -+static enum raminit_status find_cas_tck(struct sysinfo *ctrl) -+{ -+	/** TODO: Honor all possible PLL_REF100_CFG values **/ -+	uint8_t pll_ref100 = (pci_read_config32(HOST_BRIDGE, CAPID0_B) >> 21) & 0x7; -+	printk(RAM_DEBUG, "PLL_REF100_CFG value: 0x%x\n", pll_ref100); -+	printk(RAM_DEBUG, "100MHz reference clock support: %s\n", pll_ref100 ? "yes" : "no"); -+ -+	uint8_t selected_cas; -+	while (true) { -+		/* Round tCK up so that it is a multiple of either 133 or 100 MHz */ -+		normalize_tck(ctrl, pll_ref100); -+		if (!ctrl->tCK) { -+			printk(BIOS_ERR, "Couldn't find compatible clock / CAS settings\n"); -+			return RAMINIT_STATUS_MPLL_INIT_FAILURE; -+		} -+		selected_cas = find_compatible_cas(ctrl); -+		if (selected_cas) -+			break; -+ -+		ctrl->tCK++; -+	} -+	printk(BIOS_DEBUG, "Found compatible clock / CAS settings\n"); -+	printk(BIOS_DEBUG, "Selected DRAM frequency: %u MHz\n", NS2MHZ_DIV256 / ctrl->tCK); -+	printk(BIOS_DEBUG, "Selected CAS latency   : %uT\n", selected_cas); -+	ctrl->multiplier = get_mem_multiplier(ctrl); -+	return RAMINIT_STATUS_SUCCESS; -+} -+ -+enum raminit_status initialise_mpll(struct sysinfo *ctrl) -+{ -+	if (ctrl->tCK > TCK_400MHZ) { -+		printk(BIOS_ERR, "tCK is too slow. Increasing to 400 MHz as last resort\n"); -+		ctrl->tCK = TCK_400MHZ; -+	} -+	while (true) { -+		if (!ctrl->qclkps) { -+			const enum raminit_status status = find_cas_tck(ctrl); -+			if (status) -+				return status; -+		} -+ -+		/* -+		 * Unlike previous generations, Haswell's MPLL won't shut down if the -+		 * requested frequency isn't supported. But we cannot reinitialize it. -+		 * Another different thing: MPLL registers are 4-bit instead of 8-bit. -+		 */ -+ -+		/** FIXME: Obtain current clock frequency if we want to skip this **/ -+		//if (mchbar_read32(MC_BIOS_DATA) != 0) -+		//	break; -+ -+		uint32_t mc_bios_req = ctrl->multiplier; -+		if (ctrl->base_freq == 100) { -+			/* Use 100 MHz reference clock */ -+			mc_bios_req |= BIT(4); -+		} -+		mc_bios_req |= BIT(31); -+		printk(RAM_DEBUG, "MC_BIOS_REQ = 0x%08x\n", mc_bios_req); -+		printk(BIOS_DEBUG, "MPLL busy... "); -+		mchbar_write32(MC_BIOS_REQ, mc_bios_req); -+ -+		for (unsigned int i = 0; i <= 5000; i++) { -+			if (!(mchbar_read32(MC_BIOS_REQ) & BIT(31))) { -+				printk(BIOS_DEBUG, "done in %u us\n", i); -+				break; -+			} -+			udelay(1); -+		} -+		if (mchbar_read32(MC_BIOS_REQ) & BIT(31)) -+			printk(BIOS_DEBUG, "did not lock\n"); -+ -+		/* Verify locked frequency */ -+		const uint32_t mc_bios_data = mchbar_read32(MC_BIOS_DATA); -+		printk(RAM_DEBUG, "MC_BIOS_DATA = 0x%08x\n", mc_bios_data); -+		if ((mc_bios_data & 0xf) >= ctrl->multiplier) -+			break; -+ -+		printk(BIOS_DEBUG, "Retrying at a lower frequency\n\n"); -+		ctrl->tCK++; -+	} -+	if (!ctrl->mem_clock_mhz) { -+		printk(BIOS_ERR, "Could not program MPLL frequency\n"); -+		return RAMINIT_STATUS_MPLL_INIT_FAILURE; -+	} -+	printk(BIOS_DEBUG, "MPLL frequency is set to: %u MHz ", ctrl->mem_clock_mhz); -+	ctrl->mem_clock_fs = 1000000000 / ctrl->mem_clock_mhz; -+	printk(BIOS_DEBUG, "(period: %u femtoseconds)\n", ctrl->mem_clock_fs); -+	ctrl->qclkps = ctrl->mem_clock_fs / 2000; -+	printk(BIOS_DEBUG, "Quadrature clock period: %u picoseconds\n", ctrl->qclkps); -+	return wait_for_first_rcomp(); -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/io_comp_control.c b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -new file mode 100644 -index 0000000000..d45b608dd3 ---- /dev/null -+++ b/src/northbridge/intel/haswell/native_raminit/io_comp_control.c -@@ -0,0 +1,22 @@ -+/* SPDX-License-Identifier: GPL-2.0-or-later */ -+ -+#include <commonlib/bsd/clamp.h> -+#include <console/console.h> -+#include <northbridge/intel/haswell/haswell.h> -+#include <timer.h> -+#include <types.h> -+ -+#include "raminit_native.h" -+ -+enum raminit_status wait_for_first_rcomp(void) -+{ -+	struct stopwatch timer; -+	stopwatch_init_msecs_expire(&timer, 2000); -+	do { -+		if (mchbar_read32(RCOMP_TIMER) & BIT(16)) -+			return RAMINIT_STATUS_SUCCESS; -+ -+	} while (!stopwatch_expired(&timer)); -+	printk(BIOS_ERR, "Timed out waiting for RCOMP to complete\n"); -+	return RAMINIT_STATUS_POLL_TIMEOUT; -+} -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_main.c b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -index 19ec5859ac..bf745e943f 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_main.c -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_main.c -@@ -19,7 +19,8 @@ struct task_entry { - }; -  - static const struct task_entry cold_boot[] = { --	{ collect_spd_info,           true, "PROCSPD",    }, -+	{ collect_spd_info,                                       true, "PROCSPD",    }, -+	{ initialise_mpll,                                        true, "INITMPLL",   }, - }; -  - /* Return a generic stepping value to make stepping checks simpler */ -diff --git a/src/northbridge/intel/haswell/native_raminit/raminit_native.h b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -index 8078c9c386..15a1550424 100644 ---- a/src/northbridge/intel/haswell/native_raminit/raminit_native.h -+++ b/src/northbridge/intel/haswell/native_raminit/raminit_native.h -@@ -24,6 +24,8 @@ enum raminit_status { - 	RAMINIT_STATUS_SUCCESS = 0, - 	RAMINIT_STATUS_NO_MEMORY_INSTALLED, - 	RAMINIT_STATUS_UNSUPPORTED_MEMORY, -+	RAMINIT_STATUS_MPLL_INIT_FAILURE, -+	RAMINIT_STATUS_POLL_TIMEOUT, - 	RAMINIT_STATUS_UNSPECIFIED_ERROR, /** TODO: Deprecated in favor of specific values **/ - }; -  -@@ -83,10 +85,19 @@ struct sysinfo { - 	uint8_t rankmap[NUM_CHANNELS]; - 	uint8_t rank_mirrored[NUM_CHANNELS]; - 	uint32_t channel_size_mb[NUM_CHANNELS]; -+ -+	uint8_t base_freq;		/* Memory base frequency, either 100 or 133 MHz */ -+	uint32_t multiplier; -+	uint32_t mem_clock_mhz; -+	uint32_t mem_clock_fs;		/* Memory clock period in femtoseconds */ -+	uint32_t qclkps;		/* Quadrature clock period in picoseconds */ - }; -  - void raminit_main(enum raminit_boot_mode bootmode); -  - enum raminit_status collect_spd_info(struct sysinfo *ctrl); -+enum raminit_status initialise_mpll(struct sysinfo *ctrl); -+ -+enum raminit_status wait_for_first_rcomp(void); -  - #endif -diff --git a/src/northbridge/intel/haswell/registers/mchbar.h b/src/northbridge/intel/haswell/registers/mchbar.h -index 5610e7089a..45f8174995 100644 ---- a/src/northbridge/intel/haswell/registers/mchbar.h -+++ b/src/northbridge/intel/haswell/registers/mchbar.h -@@ -13,6 +13,8 @@ - #define MC_INIT_STATE_G		0x5030 - #define MRC_REVISION		0x5034 /* MRC Revision */ -  -+#define RCOMP_TIMER		0x5084 -+ - #define MC_LOCK			0x50fc /* Memory Controller Lock register */ -  - #define GFXVTBAR		0x5400 /* Base address for IGD */ -@@ -61,6 +63,7 @@ -  - #define BIOS_RESET_CPL		0x5da8 /* 8-bit */ -  -+#define MC_BIOS_REQ		0x5e00 /* Memory frequency request register */ - #define MC_BIOS_DATA		0x5e04 /* Miscellaneous information for BIOS */ - #define SAPMCTL			0x5f00 -  ---  -2.39.5 -  | 
