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>
diff --git a/src/southbridge/intel/lynxpoint/early_pch_native.c b/src/southbridge/intel/lynxpoint/early_pch_native.c
new file mode 100644
index 0000000..5ddaba0
--- /dev/null
+++ b/src/southbridge/intel/lynxpoint/early_pch_native.c
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+#include <console/console.h>
+#include <device/pci_ops.h>
+#include <southbridge/intel/lynxpoint/pch.h>
+#include <types.h>
+
+void pch_dmi_setup_physical_layer(void)
+{
+	/** FIXME: We need to make sure the SA supports Gen2 as well **/
+	if ((RCBA32(0x21a4) & 0x0f) == 0x02) {
+		/* Set Gen 2 Common Clock N_FTS */
+		RCBA32_AND_OR(0x2340, ~0x00ff0000, 0x3a << 16);
+
+		/* Set Target Link Speed to DMI Gen2 */
+		RCBA8_AND_OR(DLCTL2, ~0x07, 0x02);
+	}
+}
+
+#define VC_ACTIVE	(1U << 31)
+
+#define VCNEGPND	(1 << 1)
+
+void pch_dmi_tc_vc_mapping(const u32 vc0, const u32 vc1, const u32 vcp, const u32 vcm)
+{
+	printk(BIOS_DEBUG, "Programming PCH DMI VC/TC mappings...\n");
+
+	RCBA32_AND_OR(CIR0050, ~(0xf << 20), 2 << 20);
+	if (vcp & VC_ACTIVE)
+		RCBA32_OR(CIR0050, 1 << 19 | 1 << 17);
+
+	RCBA32(CIR0050);	/* Ensure posted write hits */
+
+	/* Use the same virtual channel mapping on both ends of the DMI link */
+	RCBA32(V0CTL) = vc0;
+	RCBA32(V1CTL) = vc1;
+	RCBA32(V1CTL);		/* Ensure posted write hits */
+	RCBA32(VPCTL) = vcp;
+	RCBA32(VPCTL);		/* Ensure posted write hits */
+	RCBA32(VMCTL) = vcm;
+
+	/* Lock the registers */
+	RCBA32_OR(CIR0050, 1U << 31);
+	RCBA32(CIR0050);	/* Ensure posted write hits */
+
+	printk(BIOS_DEBUG, "Waiting for PCH DMI VC negotiation... ");
+	do {} while (RCBA16(V0STS) & VCNEGPND);
+	do {} while (RCBA16(V1STS) & VCNEGPND);
+	do {} while (RCBA16(VPSTS) & VCNEGPND);
+	do {} while (RCBA16(VMSTS) & VCNEGPND);
+	printk(BIOS_DEBUG, "done!\n");
+}