summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2021-01-16 11:27:33 +0100
committerAngel Pons <th3fanbus@gmail.com>2021-02-24 22:35:38 +0000
commit56823f53dc6de5a804f7c88b9f24847133ddc876 (patch)
treec864d408f6ef6d975c531400c6f8efff7255714e /src/northbridge
parent91947604af3b9759fa7bff9ca5a5d4ca61df36b9 (diff)
nb/intel/ironlake: Rewrite early QPI init
Rewrite early QPI initialisation to account for variables in the register values. Trace replays did not capture these relationships. Tested on out-of-tree HP 630, still boots. Change-Id: I5d393e8222be286ab4d4dc074d85f721b07bbca4 Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/49586 Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/intel/ironlake/quickpath.c166
-rw-r--r--src/northbridge/intel/ironlake/raminit.c2
-rw-r--r--src/northbridge/intel/ironlake/raminit.h2
3 files changed, 102 insertions, 68 deletions
diff --git a/src/northbridge/intel/ironlake/quickpath.c b/src/northbridge/intel/ironlake/quickpath.c
index 068afeb5b2..a3455db6d9 100644
--- a/src/northbridge/intel/ironlake/quickpath.c
+++ b/src/northbridge/intel/ironlake/quickpath.c
@@ -429,37 +429,65 @@ static void set_2dxx_series(struct raminfo *info, int s3resume)
MCHBAR32(0x2db8) = ((info->fsb_frequency - 1) << 16) | 0x77;
}
-#define gav(x) (x)
-
-void early_quickpath_init(const u8 x2ca8)
+static u16 quickpath_configure_pll_ratio(struct raminfo *info, const u8 x2ca8)
{
- if (x2ca8 == 0) {
- gav(MCHBAR8(0x164));
- MCHBAR8(0x164) = 0x26;
- MCHBAR16(0x2c20) = 0x10;
- }
-
MCHBAR32_OR(0x18b4, 0x210000);
MCHBAR32_OR(0x1890, 0x2000000);
MCHBAR32_OR(0x18b4, 0x8000);
- gav(pci_read_config32(QPI_PHY_0, QPI_PLL_STATUS)); // !!!!
- pci_write_config8(QPI_PHY_0, QPI_PLL_RATIO, 0x12);
+ /* Get maximum supported PLL ratio */
+ u16 qpi_pll_ratio = (pci_read_config32(QPI_PHY_0, QPI_PLL_STATUS) >> 24 & 0x7f);
+
+ /* Adjust value if invalid */
+ if (qpi_pll_ratio == 0 || qpi_pll_ratio > 40)
+ qpi_pll_ratio = 40;
+
+ if (qpi_pll_ratio == 16)
+ qpi_pll_ratio = 12;
+
+ while (qpi_pll_ratio >= 12) {
+ if (qpi_pll_ratio <= (info->clock_speed_index + 3) * 8)
+ break;
+
+ qpi_pll_ratio -= 2;
+ }
+
+ /* Finally, program the ratio */
+ pci_write_config8(QPI_PHY_0, QPI_PLL_RATIO, qpi_pll_ratio);
+
+ const u16 csipll0 = MCHBAR16(0x2c10);
+ MCHBAR16(0x2c10) = (qpi_pll_ratio > 26) << 11 | 0x400 | qpi_pll_ratio;
+
+ if (csipll0 != MCHBAR16(0x2c10) && x2ca8 == 0)
+ MCHBAR8_OR(0x2ca8, 1);
- gav(MCHBAR16(0x2c10));
- MCHBAR16(0x2c10) = 0x412;
- gav(MCHBAR16(0x2c10));
MCHBAR16_OR(0x2c12, 0x100);
- gav(MCHBAR8(0x2ca8)); // !!!!
+ return qpi_pll_ratio;
+}
+
+void early_quickpath_init(struct raminfo *info, const u8 x2ca8)
+{
+ u8 reg8;
+ u32 reg32;
+
+ /* Initialize DDR MPLL first */
+ if (x2ca8 == 0) {
+ MCHBAR8_AND_OR(0x164, 0xd9, info->clock_speed_index == 0 ? 0x24 : 0x26);
+
+ /* Program DDR MPLL feedback divider ratio */
+ MCHBAR16(0x2c20) = (info->clock_speed_index + 3) * 4;
+ }
+
+ const u16 qpi_pll_ratio = quickpath_configure_pll_ratio(info, x2ca8);
+
MCHBAR32_AND_OR(0x1804, 0xfffffffc, 0x8400080);
+ pci_update_config32(QPI_PHY_0, QPI_PHY_CONTROL, 0xfffffffc, 0x400080);
- pci_read_config32(QPI_PHY_0, QPI_PHY_CONTROL); // !!!!
- pci_write_config32(QPI_PHY_0, QPI_PHY_CONTROL, 0x40a0a0);
- gav(MCHBAR32(0x1c04)); // !!!!
- gav(MCHBAR32(0x1804)); // !!!!
+ const u32 x1c04 = MCHBAR32(0x1c04) & 0xc01080;
+ const u32 x1804 = MCHBAR32(0x1804) & 0xc01080;
- if (x2ca8 == 0)
+ if (x1c04 != x1804 && x2ca8 == 0)
MCHBAR8_OR(0x2ca8, 1);
MCHBAR32(0x18d8) = 0x120000;
@@ -476,62 +504,68 @@ void early_quickpath_init(const u8 x2ca8)
pci_write_config32(QPI_PHY_0, QPI_PHY_EP_MCTR, 0x142);
MCHBAR32(0x18d8) = 0x1e0000;
- gav(MCHBAR32(0x18dc)); // !!!!
- MCHBAR32(0x18dc) = 0x3;
- gav(MCHBAR32(0x18dc)); // !!!!
+ const u32 x18dc = MCHBAR32(0x18dc);
+ MCHBAR32(0x18dc) = qpi_pll_ratio < 18 ? 2 : 3;
- if (x2ca8 == 0)
- MCHBAR8_OR(0x2ca8, 1); // guess
+ if (x18dc != MCHBAR32(0x18dc) && x2ca8 == 0)
+ MCHBAR8_OR(0x2ca8, 1);
+
+ reg8 = qpi_pll_ratio > 20 ? 10 : 9;
+
+ MCHBAR32(0x188c) = 0x20bc00 | reg8;
+ pci_write_config32(QPI_PHY_0, QPI_PHY_PWR_MGMT, 0x40b0c00 | reg8);
- MCHBAR32(0x188c) = 0x20bc09;
- pci_write_config32(QPI_PHY_0, QPI_PHY_PWR_MGMT, 0x40b0c09);
- MCHBAR32(0x1a10) = 0x4200010e;
+ if (qpi_pll_ratio <= 14)
+ reg8 = 0x33;
+ else if (qpi_pll_ratio <= 26)
+ reg8 = 0x42;
+ else
+ reg8 = 0x51;
+
+ MCHBAR32(0x1a10) = reg8 << 24 | qpi_pll_ratio * 60;
MCHBAR32_OR(0x18b8, 0x200);
- gav(MCHBAR32(0x1918)); // !!!!
- MCHBAR32(0x1918) = 0x332;
-
- gav(MCHBAR32(0x18b8)); // !!!!
- MCHBAR32(0x18b8) = 0xe00;
- gav(MCHBAR32(0x182c)); // !!!!
- MCHBAR32(0x182c) = 0x10202;
- gav(pci_read_config32(QPI_PHY_0, QPI_PHY_PRIM_TIMEOUT)); // !!!!
- pci_write_config32(QPI_PHY_0, QPI_PHY_PRIM_TIMEOUT, 0x10202);
+ MCHBAR32_OR(0x1918, 0x300);
+
+ if (info->revision > 0x17)
+ MCHBAR32_OR(0x18b8, 0xc00);
+
+ reg32 = ((qpi_pll_ratio > 20) + 1) << 16;
+
+ MCHBAR32_AND_OR(0x182c, 0xfff0f0ff, reg32 | 0x200);
+ pci_update_config32(QPI_PHY_0, QPI_PHY_PRIM_TIMEOUT, 0xfff0f0ff, reg32 | 0x200);
MCHBAR32_AND(0x1a1c, 0x8fffffff);
MCHBAR32_OR(0x1a70, 0x100000);
MCHBAR32_AND(0x18b4, 0xffff7fff);
- gav(MCHBAR32(0x1a68)); // !!!!
- MCHBAR32(0x1a68) = 0x343800;
- gav(MCHBAR32(0x1e68)); // !!!!
- gav(MCHBAR32(0x1a68)); // !!!!
-
- if (x2ca8 == 0)
- MCHBAR8_OR(0x2ca8, 1); // guess
-
- pci_read_config32(QPI_LINK_0, QPI_QPILCL); // !!!!
- pci_write_config32(QPI_LINK_0, QPI_QPILCL, 0x140000);
- pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS); // !!!!
- pci_write_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS, 0x64555);
- pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS); // !!!!
- pci_read_config32(QPI_NON_CORE, MIRROR_PORT_CTL); // !!!!
- pci_write_config32(QPI_NON_CORE, MIRROR_PORT_CTL, 0x180);
- gav(MCHBAR32(0x1af0)); // !!!!
- gav(MCHBAR32(0x1af0)); // !!!!
- MCHBAR32(0x1af0) = 0x1f020003;
- gav(MCHBAR32(0x1af0)); // !!!!
-
- if (x2ca8 == 0)
- MCHBAR8_OR(0x2ca8, 1); // guess
-
- gav(MCHBAR32(0x1890)); // !!!!
- MCHBAR32(0x1890) = 0x80102;
- gav(MCHBAR32(0x18b4)); // !!!!
- MCHBAR32(0x18b4) = 0x216000;
+ MCHBAR32_AND_OR(0x1a68, 0xffebc03f, 0x143800);
+
+ const u32 x1e68 = MCHBAR32(0x1e68) & 0x143fc0;
+ const u32 x1a68 = MCHBAR32(0x1a68) & 0x143fc0;
+
+ if (x1e68 != x1a68 && x2ca8 == 0)
+ MCHBAR8_OR(0x2ca8, 1);
+
+ pci_update_config32(QPI_LINK_0, QPI_QPILCL, 0xffffff3f, 0x140000);
+
+ reg32 = pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS);
+ pci_write_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS, (reg32 & 0xfffe4555) | 0x64555);
+
+ if (reg32 != pci_read_config32(QPI_LINK_0, QPI_DEF_RMT_VN_CREDITS) && x2ca8 == 0)
+ MCHBAR8_OR(0x2ca8, 1);
+
+ pci_update_config32(QPI_NON_CORE, MIRROR_PORT_CTL, ~3, 0x80 * 3);
+
+ reg32 = MCHBAR32(0x1af0);
+ MCHBAR32(0x1af0) = (reg32 & 0xfdffcf) | 0x1f020000;
+
+ if (reg32 != MCHBAR32(0x1af0) && x2ca8 == 0)
+ MCHBAR8_OR(0x2ca8, 1);
+
+ MCHBAR32_AND(0x1890, 0xfdffffff);
+ MCHBAR32_AND_OR(0x18b4, 0xffff6fff, 0x600);
MCHBAR32(0x18a4) = 0x22222222;
MCHBAR32(0x18a8) = 0x22222222;
MCHBAR32(0x18ac) = 0x22222;
-
- udelay(1000);
}
void late_quickpath_init(struct raminfo *info, const int s3resume)
diff --git a/src/northbridge/intel/ironlake/raminit.c b/src/northbridge/intel/ironlake/raminit.c
index 747b1712af..9ba21d06b8 100644
--- a/src/northbridge/intel/ironlake/raminit.c
+++ b/src/northbridge/intel/ironlake/raminit.c
@@ -3353,7 +3353,7 @@ void raminit(const int s3resume, const u8 *spd_addrmap)
compute_derived_timings(&info);
- early_quickpath_init(x2ca8);
+ early_quickpath_init(&info, x2ca8);
info.cached_training = get_cached_training();
diff --git a/src/northbridge/intel/ironlake/raminit.h b/src/northbridge/intel/ironlake/raminit.h
index e75fa5182b..edfce51125 100644
--- a/src/northbridge/intel/ironlake/raminit.h
+++ b/src/northbridge/intel/ironlake/raminit.h
@@ -103,7 +103,7 @@ void chipset_init(const int s3resume);
void raminit(const int s3resume, const u8 *spd_addrmap);
u16 get_max_timing(struct raminfo *info, int channel);
-void early_quickpath_init(const u8 x2ca8);
+void early_quickpath_init(struct raminfo *info, const u8 x2ca8);
void late_quickpath_init(struct raminfo *info, const int s3resume);
#endif /* RAMINIT_H */