summaryrefslogtreecommitdiff
path: root/src/northbridge/intel/haswell/early_dmi.c
diff options
context:
space:
mode:
authorAngel Pons <th3fanbus@gmail.com>2022-05-06 21:56:48 +0200
committerFelix Held <felix-coreboot@felixheld.de>2022-12-16 17:08:00 +0000
commit567ece44eafaee3e1a3fef644efd018a877b533b (patch)
tree0ae5eea3cb7b2d6e94f77a18dd5b43d24b8ef0b3 /src/northbridge/intel/haswell/early_dmi.c
parentb739fd287dc70aa253de946541b91d12afce8da3 (diff)
haswell/lynxpoint: Add native DMI init
Implement native DMI init for Haswell and Lynx Point. This is only needed on non-ULT platforms, and only when MRC.bin is not used. TEST=Verify DMI initialises correctly on Asrock B85M Pro4. Change-Id: I5fb1a2adc4ffbf0ebbf0d2d3a444055c53765faa Signed-off-by: Angel Pons <th3fanbus@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/64177 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Arthur Heymans <arthur@aheymans.xyz>
Diffstat (limited to 'src/northbridge/intel/haswell/early_dmi.c')
-rw-r--r--src/northbridge/intel/haswell/early_dmi.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/northbridge/intel/haswell/early_dmi.c b/src/northbridge/intel/haswell/early_dmi.c
new file mode 100644
index 0000000000..9941242fd5
--- /dev/null
+++ b/src/northbridge/intel/haswell/early_dmi.c
@@ -0,0 +1,96 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <console/console.h>
+#include <northbridge/intel/haswell/haswell.h>
+#include <southbridge/intel/lynxpoint/pch.h>
+#include <types.h>
+
+static void dmi_print_link_status(int loglevel)
+{
+ const uint16_t dmilsts = dmibar_read16(DMILSTS);
+ printk(loglevel, "DMI: Running at Gen%u x%u\n", dmilsts & 0xf, dmilsts >> 4 & 0x1f);
+}
+
+#define RETRAIN (1 << 5)
+
+#define LTRN (1 << 11)
+
+static void dmi_setup_physical_layer(void)
+{
+ /* Program DMI AFE settings, which are needed for DMI to work */
+ peg_dmi_recipe(false, 0);
+
+ /* Additional DMI programming steps */
+ dmibar_setbits32(0x258, 1 << 29);
+ dmibar_clrsetbits32(0x208, 0x7ff, 0x6b5);
+ dmibar_clrsetbits32(0x22c, 0xffff, 0x2020);
+
+ /* Write SA reference code version */
+ dmibar_write32(0x71c, 0x0000000f);
+ dmibar_write32(0x720, 0x01060200);
+
+ /* We also have to bring up the PCH side of the DMI link */
+ pch_dmi_setup_physical_layer();
+
+ /* Write-once settings */
+ dmibar_clrsetbits32(DMILCAP, 0x3f00f, 2 << 0);
+
+ printk(BIOS_DEBUG, "Retraining DMI at Gen2 speeds...\n");
+ dmi_print_link_status(BIOS_DEBUG);
+
+ /* Retrain link */
+ dmibar_setbits16(DMILCTL, RETRAIN);
+ do {} while (dmibar_read16(DMILSTS) & LTRN);
+ dmi_print_link_status(BIOS_DEBUG);
+
+ /* Retrain link again for DMI Gen2 speeds */
+ dmibar_setbits16(DMILCTL, RETRAIN);
+ do {} while (dmibar_read16(DMILSTS) & LTRN);
+ dmi_print_link_status(BIOS_INFO);
+}
+
+#define VC_ACTIVE (1U << 31)
+
+#define VCNEGPND (1 << 1)
+
+#define DMI_VC_CFG(vcid, tcmap) (VC_ACTIVE | ((vcid) << 24) | (tcmap))
+
+static void dmi_tc_vc_mapping(void)
+{
+ printk(BIOS_DEBUG, "Programming SA DMI VC/TC mappings...\n");
+
+ if (CONFIG(INTEL_LYNXPOINT_LP))
+ dmibar_setbits8(0xa78, 1 << 1);
+
+ /* Each TC is mapped to one and only one VC */
+ const u32 vc0 = DMI_VC_CFG(0, (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 0));
+ const u32 vc1 = DMI_VC_CFG(1, (1 << 1));
+ const u32 vcp = DMI_VC_CFG(2, (1 << 2));
+ const u32 vcm = DMI_VC_CFG(7, (1 << 7));
+ dmibar_write32(DMIVC0RCTL, vc0);
+ dmibar_write32(DMIVC1RCTL, vc1);
+ dmibar_write32(DMIVCPRCTL, vcp);
+ dmibar_write32(DMIVCMRCTL, vcm);
+
+ /* Set Extended VC Count (EVCC) to 1 if VC1 is active */
+ dmibar_clrsetbits8(DMIPVCCAP1, 7, !!(vc1 & VC_ACTIVE));
+
+ /*
+ * We also have to program the PCH side of the DMI link. Since both ends
+ * must use the same Virtual Channel settings, we pass them as arguments.
+ */
+ pch_dmi_tc_vc_mapping(vc0, vc1, vcp, vcm);
+
+ printk(BIOS_DEBUG, "Waiting for SA DMI VC negotiation... ");
+ do {} while (dmibar_read16(DMIVC0RSTS) & VCNEGPND);
+ do {} while (dmibar_read16(DMIVC1RSTS) & VCNEGPND);
+ do {} while (dmibar_read16(DMIVCPRSTS) & VCNEGPND);
+ do {} while (dmibar_read16(DMIVCMRSTS) & VCNEGPND);
+ printk(BIOS_DEBUG, "done!\n");
+}
+
+void dmi_early_init(void)
+{
+ dmi_setup_physical_layer();
+ dmi_tc_vc_mapping();
+}