• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/cpu.h>
4 #include <console/console.h>
5 #include <cpu/intel/model_206ax/model_206ax.h>
6 #include <northbridge/intel/sandybridge/sandybridge.h>
7 #include <southbridge/intel/bd82x6x/pch.h>
8 
dmi_recipe(void)9 static void dmi_recipe(void)
10 {
11 	const u32 cpuid = cpu_get_cpuid();
12 
13 	int i;
14 
15 	/* The DMI recipe is only needed on Ivy Bridge */
16 	if (!IS_IVY_CPU(cpuid))
17 		return;
18 
19 	for (i = 0; i < 2; i++) {
20 		dmibar_setbits32(0x0914 + (i << 5), 1 << 31);
21 	}
22 
23 	for (i = 0; i < 4; i++) {
24 		dmibar_clrbits32(0x0a00 + (i << 4), 3 << 26);
25 		dmibar_setbits32(0x0a04 + (i << 4), 1 << 11);
26 	}
27 	dmibar_clrsetbits32(0x0c30, 0xf << 28, 1 << 30);
28 
29 	for (i = 0; i < 2; i++) {
30 		dmibar_clrbits32(0x0904 + (i << 5), 7 << 22);
31 		dmibar_clrbits32(0x090c + (i << 5), 7 << 17);
32 	}
33 
34 	for (i = 0; i < 2; i++) {
35 		dmibar_clrbits32(0x090c + (i << 5), 0xf << 21);
36 	}
37 
38 	for (i = 0; i < 2; i++) {
39 		dmibar_read32(0x0904 + (i << 5));	// !!! = 0x7a1842ec
40 		dmibar_write32(0x0904 + (i << 5), 0x7a1842ec);
41 		dmibar_read32(0x090c + (i << 5));	// !!! = 0x00000208
42 		dmibar_write32(0x090c + (i << 5), 0x00000128);
43 	}
44 
45 	for (i = 0; i < 2; i++) {
46 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x46139008
47 		dmibar_write32(0x0700 + (i << 5), 0x46139008);
48 	}
49 
50 	dmibar_read32(0x0c04);	// !!! = 0x2e680008
51 	dmibar_write32(0x0c04, 0x2e680008);
52 
53 	for (i = 0; i < 2; i++) {
54 		dmibar_read32(0x0904 + (i << 5));	// !!! = 0x7a1842ec
55 		dmibar_write32(0x0904 + (i << 5), 0x3a1842ec);
56 	}
57 
58 	for (i = 0; i < 2; i++) {
59 		dmibar_read32(0x0910 + (i << 5));	// !!! = 0x00006300
60 		dmibar_write32(0x0910 + (i << 5), 0x00004300);
61 	}
62 
63 	for (i = 0; i < 4; i++) {
64 		dmibar_read32(0x0a00 + (i << 4));	// !!! = 0x03042010
65 		dmibar_write32(0x0a00 + (i << 4), 0x03042018);
66 	}
67 
68 	dmibar_read32(0x0c00);	// !!! = 0x29700c08
69 	dmibar_write32(0x0c00, 0x29700c08);
70 
71 	for (i = 0; i < 4; i++) {
72 		dmibar_read32(0x0a04 + (i << 4));	// !!! = 0x0c0708f0
73 		dmibar_write32(0x0a04 + (i << 4), 0x0c0718f0);
74 	}
75 
76 	for (i = 0; i < 2; i++) {
77 		dmibar_read32(0x0900 + (i << 5));	// !!! = 0x50000000
78 		dmibar_write32(0x0900 + (i << 5), 0x50000000);
79 	}
80 
81 	for (i = 0; i < 2; i++) {
82 		dmibar_read32(0x0908 + (i << 5));	// !!! = 0x51ffffff
83 		dmibar_write32(0x0908 + (i << 5), 0x51ffffff);
84 	}
85 
86 	for (i = 0; i < 4; i++) {
87 		dmibar_read32(0x0a00 + (i << 4));	// !!! = 0x03042018
88 		dmibar_write32(0x0a00 + (i << 4), 0x03042018);
89 	}
90 
91 	for (i = 0; i < 2; i++) {
92 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x46139008
93 		dmibar_write32(0x0700 + (i << 5), 0x46139008);
94 	}
95 
96 	for (i = 0; i < 2; i++) {
97 		dmibar_read32(0x0904 + (i << 5));	// !!! = 0x3a1842ec
98 		dmibar_write32(0x0904 + (i << 5), 0x3a1846ec);
99 	}
100 
101 	for (i = 0; i < 4; i++) {
102 		dmibar_read32(0x0a00 + (i << 4));	// !!! = 0x03042018
103 		dmibar_write32(0x0a00 + (i << 4), 0x03042018);
104 	}
105 
106 	for (i = 0; i < 2; i++) {
107 		dmibar_read32(0x0908 + (i << 5));	// !!! = 0x51ffffff
108 		dmibar_write32(0x0908 + (i << 5), 0x51ffffff);
109 	}
110 
111 	dmibar_read32(0x0c00);	// !!! = 0x29700c08
112 	dmibar_write32(0x0c00, 0x29700c08);
113 
114 	dmibar_read32(0x0c0c);	// !!! = 0x16063400
115 	dmibar_write32(0x0c0c, 0x00063400);
116 
117 	for (i = 0; i < 2; i++) {
118 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x46139008
119 		dmibar_write32(0x0700 + (i << 5), 0x46339008);
120 	}
121 
122 	for (i = 0; i < 2; i++) {
123 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x46339008
124 		dmibar_write32(0x0700 + (i << 5), 0x45339008);
125 	}
126 
127 	for (i = 0; i < 2; i++) {
128 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x45339008
129 		dmibar_write32(0x0700 + (i << 5), 0x453b9008);
130 	}
131 
132 	for (i = 0; i < 2; i++) {
133 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x453b9008
134 		dmibar_write32(0x0700 + (i << 5), 0x45bb9008);
135 	}
136 
137 	for (i = 0; i < 2; i++) {
138 		dmibar_read32(0x0700 + (i << 5));	// !!! = 0x45bb9008
139 		dmibar_write32(0x0700 + (i << 5), 0x45fb9008);
140 	}
141 
142 	for (i = 0; i < 2; i++) {
143 		dmibar_read32(0x0914 + (i << 5));	// !!! = 0x9021a080
144 		dmibar_write32(0x0914 + (i << 5), 0x9021a280);
145 	}
146 
147 	for (i = 0; i < 2; i++) {
148 		dmibar_read32(0x0914 + (i << 5));	// !!! = 0x9021a080
149 		dmibar_write32(0x0914 + (i << 5), 0x9821a280);
150 	}
151 
152 	for (i = 0; i < 4; i++) {
153 		dmibar_read32(0x0a00 + (i << 4));	// !!! = 0x03042018
154 		dmibar_write32(0x0a00 + (i << 4), 0x03242018);
155 	}
156 
157 	dmibar_read32(0x0258);	// !!! = 0x40000600
158 	dmibar_write32(0x0258, 0x60000600);
159 
160 	for (i = 0; i < 2; i++) {
161 		dmibar_read32(0x0904 + (i << 5));	// !!! = 0x3a1846ec
162 		dmibar_write32(0x0904 + (i << 5), 0x2a1846ec);
163 		dmibar_read32(0x0914 + (i << 5));	// !!! = 0x9821a280
164 		dmibar_write32(0x0914 + (i << 5), 0x98200280);
165 	}
166 
167 	dmibar_read32(DMIL0SLAT);	// !!! = 0x00c26460
168 	dmibar_write32(DMIL0SLAT, 0x00c2403c);
169 }
170 
early_init_dmi(void)171 void early_init_dmi(void)
172 {
173 	dmi_recipe();
174 
175 	early_pch_init_native_dmi_pre();
176 
177 	/* Write once settings */
178 	dmibar_clrsetbits32(DMILCAP, 0x3f00f,
179 			    (2 <<  0) |	// 5GT/s
180 			    (2 << 12) |	// L0s 128 ns to less than 256 ns
181 			    (2 << 15));	// L1 2 us to less than 4 us
182 
183 	dmibar_setbits8(DMILCTL, 1 << 5);	// Retrain link
184 	while (dmibar_read16(DMILSTS) & TXTRN)
185 		;
186 
187 	dmibar_setbits8(DMILCTL, 1 << 5);	// Retrain link
188 	while (dmibar_read16(DMILSTS) & TXTRN)
189 		;
190 
191 	const u8  w = (dmibar_read16(DMILSTS) >> 4) & 0x1f;
192 	const u16 t = (dmibar_read16(DMILSTS) & 0x0f) * 2500;
193 
194 	printk(BIOS_DEBUG, "DMI: Running at X%x @ %dMT/s\n", w, t);
195 	/*
196 	 * Virtual Channel resources must match settings in RCBA!
197 	 *
198 	 * Channel Vp and Vm are documented in:
199 	 * "Desktop 4th Generation Intel Core Processor Family, Desktop Intel Pentium
200 	 *  Processor Family, and Desktop Intel Celeron Processor Family Vol. 2"
201 	 */
202 
203 	/* Channel 0: Enable, Set ID to 0, map TC0 and TC3 and TC4 to VC0. */
204 	dmibar_write32(DMIVC0RCTL, 1 << 31 | 0 << 24 | 0x0c << 1 | 1);
205 	/* Channel 1: Enable, Set ID to 1, map TC1 and TC5 to VC1. */
206 	dmibar_write32(DMIVC1RCTL, 1 << 31 | 1 << 24 | 0x11 << 1);
207 	/* Channel p: Enable, Set ID to 2, map TC2 and TC6 to VCp  */
208 	dmibar_write32(DMIVCPRCTL, 1 << 31 | 2 << 24 | 0x22 << 1);
209 	/* Channel m: Enable, Set ID to 0, map TC7 to VCm */
210 	dmibar_write32(DMIVCMRCTL, 1 << 31 | 7 << 24 | 0x40 << 1);
211 
212 	/* Set Extended VC Count (EVCC) to 1 as Channel 1 is active. */
213 	dmibar_setbits8(DMIPVCCAP1, 1 << 0);
214 
215 	early_pch_init_native_dmi_post();
216 
217 	/*
218 	 * BIOS Requirement: Check if DMI VC Negotiation was successful.
219 	 * Wait for virtual channels negotiation pending.
220 	 */
221 	while (dmibar_read16(DMIVC0RSTS) & VC0NP)
222 		;
223 	while (dmibar_read16(DMIVC1RSTS) & VC1NP)
224 		;
225 	while (dmibar_read16(DMIVCPRSTS) & VCPNP)
226 		;
227 	while (dmibar_read16(DMIVCMRSTS) & VCMNP)
228 		;
229 }
230