blob: 9941242fd503093cc87a0e848e2e600d41406377 [file] [log] [blame]
Angel Pons567ece42022-05-06 21:56:48 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
2
3#include <console/console.h>
4#include <northbridge/intel/haswell/haswell.h>
5#include <southbridge/intel/lynxpoint/pch.h>
6#include <types.h>
7
8static void dmi_print_link_status(int loglevel)
9{
10 const uint16_t dmilsts = dmibar_read16(DMILSTS);
11 printk(loglevel, "DMI: Running at Gen%u x%u\n", dmilsts & 0xf, dmilsts >> 4 & 0x1f);
12}
13
14#define RETRAIN (1 << 5)
15
16#define LTRN (1 << 11)
17
18static void dmi_setup_physical_layer(void)
19{
20 /* Program DMI AFE settings, which are needed for DMI to work */
21 peg_dmi_recipe(false, 0);
22
23 /* Additional DMI programming steps */
24 dmibar_setbits32(0x258, 1 << 29);
25 dmibar_clrsetbits32(0x208, 0x7ff, 0x6b5);
26 dmibar_clrsetbits32(0x22c, 0xffff, 0x2020);
27
28 /* Write SA reference code version */
29 dmibar_write32(0x71c, 0x0000000f);
30 dmibar_write32(0x720, 0x01060200);
31
32 /* We also have to bring up the PCH side of the DMI link */
33 pch_dmi_setup_physical_layer();
34
35 /* Write-once settings */
36 dmibar_clrsetbits32(DMILCAP, 0x3f00f, 2 << 0);
37
38 printk(BIOS_DEBUG, "Retraining DMI at Gen2 speeds...\n");
39 dmi_print_link_status(BIOS_DEBUG);
40
41 /* Retrain link */
42 dmibar_setbits16(DMILCTL, RETRAIN);
43 do {} while (dmibar_read16(DMILSTS) & LTRN);
44 dmi_print_link_status(BIOS_DEBUG);
45
46 /* Retrain link again for DMI Gen2 speeds */
47 dmibar_setbits16(DMILCTL, RETRAIN);
48 do {} while (dmibar_read16(DMILSTS) & LTRN);
49 dmi_print_link_status(BIOS_INFO);
50}
51
52#define VC_ACTIVE (1U << 31)
53
54#define VCNEGPND (1 << 1)
55
56#define DMI_VC_CFG(vcid, tcmap) (VC_ACTIVE | ((vcid) << 24) | (tcmap))
57
58static void dmi_tc_vc_mapping(void)
59{
60 printk(BIOS_DEBUG, "Programming SA DMI VC/TC mappings...\n");
61
62 if (CONFIG(INTEL_LYNXPOINT_LP))
63 dmibar_setbits8(0xa78, 1 << 1);
64
65 /* Each TC is mapped to one and only one VC */
66 const u32 vc0 = DMI_VC_CFG(0, (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 0));
67 const u32 vc1 = DMI_VC_CFG(1, (1 << 1));
68 const u32 vcp = DMI_VC_CFG(2, (1 << 2));
69 const u32 vcm = DMI_VC_CFG(7, (1 << 7));
70 dmibar_write32(DMIVC0RCTL, vc0);
71 dmibar_write32(DMIVC1RCTL, vc1);
72 dmibar_write32(DMIVCPRCTL, vcp);
73 dmibar_write32(DMIVCMRCTL, vcm);
74
75 /* Set Extended VC Count (EVCC) to 1 if VC1 is active */
76 dmibar_clrsetbits8(DMIPVCCAP1, 7, !!(vc1 & VC_ACTIVE));
77
78 /*
79 * We also have to program the PCH side of the DMI link. Since both ends
80 * must use the same Virtual Channel settings, we pass them as arguments.
81 */
82 pch_dmi_tc_vc_mapping(vc0, vc1, vcp, vcm);
83
84 printk(BIOS_DEBUG, "Waiting for SA DMI VC negotiation... ");
85 do {} while (dmibar_read16(DMIVC0RSTS) & VCNEGPND);
86 do {} while (dmibar_read16(DMIVC1RSTS) & VCNEGPND);
87 do {} while (dmibar_read16(DMIVCPRSTS) & VCNEGPND);
88 do {} while (dmibar_read16(DMIVCMRSTS) & VCNEGPND);
89 printk(BIOS_DEBUG, "done!\n");
90}
91
92void dmi_early_init(void)
93{
94 dmi_setup_physical_layer();
95 dmi_tc_vc_mapping();
96}