coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
early_dmi.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <arch/cpu.h>
4 #include <console/console.h>
8 
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 
171 void early_init_dmi(void)
172 {
173  dmi_recipe();
174 
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 
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 }
#define printk(level,...)
Definition: stdlib.h:16
uint32_t cpu_get_cpuid(void)
Definition: cpu_common.c:63
static void dmi_recipe(void)
Definition: early_dmi.c:9
void early_init_dmi(void)
Definition: early_dmi.c:171
#define dmibar_clrbits32(addr, clear)
Definition: fixed_bars.h:117
static __always_inline uint32_t dmibar_read32(const uintptr_t offset)
Definition: fixed_bars.h:76
#define dmibar_setbits8(addr, set)
Definition: fixed_bars.h:111
static __always_inline void dmibar_write32(const uintptr_t offset, const uint32_t value)
Definition: fixed_bars.h:91
static __always_inline uint16_t dmibar_read16(const uintptr_t offset)
Definition: fixed_bars.h:71
#define dmibar_setbits32(addr, set)
Definition: fixed_bars.h:113
static __always_inline void dmibar_clrsetbits32(uintptr_t offset, uint32_t clear, uint32_t set)
Definition: fixed_bars.h:106
#define VC1NP
Definition: gm45.h:354
#define DMIVC0RCTL
Definition: gm45.h:347
#define DMIPVCCAP1
Definition: gm45.h:344
#define DMIVC1RSTS
Definition: gm45.h:353
#define DMILCTL
Definition: gm45.h:364
#define DMIVC1RCTL
Definition: gm45.h:352
#define VC0NP
Definition: gm45.h:349
#define DMIVC0RSTS
Definition: gm45.h:348
#define DMILCAP
Definition: gm45.h:363
#define DMILSTS
Definition: gm45.h:365
#define VCPNP
Definition: dmibar.h:24
#define DMIVCPRCTL
Definition: dmibar.h:22
#define DMIVCMRSTS
Definition: dmibar.h:28
#define VCMNP
Definition: dmibar.h:29
#define DMIL0SLAT
Definition: dmibar.h:51
#define DMIVCMRCTL
Definition: dmibar.h:27
#define DMIVCPRSTS
Definition: dmibar.h:23
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define IS_IVY_CPU(x)
Definition: model_206ax.h:31
#define TXTRN
Definition: dmibar.h:42
u32 cpuid
void early_pch_init_native_dmi_pre(void)
Definition: early_pch.c:56
void early_pch_init_native_dmi_post(void)
Definition: early_pch.c:68
uint32_t u32
Definition: stdint.h:51
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45