blob: 6630a12e2abc7c8092281b6559561fe27b5f0038 [file] [log] [blame]
Mate Kukri13e20422024-03-04 12:47:02 +00001/* SPDX-License-Identifier: GPL-2.0-only */
2
Mate Kukri75dd8062024-04-23 18:04:38 +01003#include <bootstate.h>
4#include <cpu/x86/msr.h>
Mate Kukri13e20422024-03-04 12:47:02 +00005#include <device/device.h>
6#include <drivers/intel/gma/int15.h>
Mate Kukri75dd8062024-04-23 18:04:38 +01007#include <option.h>
8#include <southbridge/intel/common/gpio.h>
9#include "sch5555_ec.h"
Mate Kukri13e20422024-03-04 12:47:02 +000010
11static void mainboard_enable(struct device *dev)
12{
13 install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_NONE,
14 GMA_INT15_PANEL_FIT_DEFAULT,
15 GMA_INT15_BOOT_DISPLAY_DEFAULT, 0);
16}
17
18struct chip_operations mainboard_ops = {
19 .enable_dev = mainboard_enable,
20};
Mate Kukri75dd8062024-04-23 18:04:38 +010021
22#define HWM_TAB_ADD_TEMP_TARGET 1
23#define HWM_TAB_PKG_POWER_ANY 0xffff
24#define CHASSIS_TYPE_UNKNOWN 0xff
25
26struct hwm_tab_entry {
27 uint16_t addr;
28 uint8_t val;
29 uint8_t flags;
30 uint16_t pkg_power;
31};
32
33struct hwm_tab_entry HWM_TAB3[] = {
34 { 0x005, 0x33, 0, 0xffff },
35 { 0x018, 0x2f, 0, 0xffff },
36 { 0x019, 0x2f, 0, 0xffff },
37 { 0x01a, 0x2f, 0, 0xffff },
38 { 0x080, 0x00, 0, 0xffff },
39 { 0x081, 0x00, 0, 0xffff },
40 { 0x083, 0xbb, 0, 0xffff },
41 { 0x085, 0x8a, 0, 0x0010 },
42 { 0x086, 0x4c, 0, 0x0010 },
43 { 0x08a, 0x66, 0, 0x0010 },
44 { 0x08b, 0x5b, 0, 0x0010 },
45 { 0x090, 0x65, 0, 0xffff },
46 { 0x091, 0x70, 0, 0xffff },
47 { 0x092, 0x86, 0, 0xffff },
48 { 0x096, 0xa4, 0, 0xffff },
49 { 0x097, 0xa4, 0, 0xffff },
50 { 0x098, 0xa4, 0, 0xffff },
51 { 0x09b, 0xa4, 0, 0xffff },
52 { 0x0a0, 0x0e, 0, 0xffff },
53 { 0x0a1, 0x0e, 0, 0xffff },
54 { 0x0ae, 0x7c, 0, 0xffff },
55 { 0x0af, 0x86, 0, 0xffff },
56 { 0x0b0, 0x9a, 0, 0xffff },
57 { 0x0b3, 0x9a, 0, 0xffff },
58 { 0x0b6, 0x08, 0, 0xffff },
59 { 0x0b7, 0x08, 0, 0xffff },
60 { 0x0ea, 0x64, 0, 0x0020 },
61 { 0x0ea, 0x5c, 0, 0x0010 },
62 { 0x0ef, 0xff, 0, 0xffff },
63 { 0x0f8, 0x15, 0, 0xffff },
64 { 0x0f9, 0x00, 0, 0xffff },
65 { 0x0f0, 0x30, 0, 0xffff },
66 { 0x0fd, 0x01, 0, 0xffff },
67 { 0x1a1, 0x00, 0, 0xffff },
68 { 0x1a2, 0x00, 0, 0xffff },
69 { 0x1b1, 0x08, 0, 0xffff },
70 { 0x1be, 0x99, 0, 0xffff },
71 { 0x280, 0xa0, 0, 0x0010 },
72 { 0x281, 0x0f, 0, 0x0010 },
73 { 0x282, 0x03, 0, 0xffff },
74 { 0x283, 0x0a, 0, 0xffff },
75 { 0x284, 0x80, 0, 0xffff },
76 { 0x285, 0x03, 0, 0xffff },
77 { 0x288, 0x68, 0, 0x0010 },
78 { 0x289, 0x10, 0, 0x0010 },
79 { 0x28a, 0x03, 0, 0xffff },
80 { 0x28b, 0x0a, 0, 0xffff },
81 { 0x28c, 0x80, 0, 0xffff },
82 { 0x28d, 0x03, 0, 0xffff },
83};
84
85struct hwm_tab_entry HWM_TAB4[] = {
86 { 0x005, 0x33, 0, 0xffff },
87 { 0x018, 0x2f, 0, 0xffff },
88 { 0x019, 0x2f, 0, 0xffff },
89 { 0x01a, 0x2f, 0, 0xffff },
90 { 0x080, 0x00, 0, 0xffff },
91 { 0x081, 0x00, 0, 0xffff },
92 { 0x083, 0xbb, 0, 0xffff },
93 { 0x085, 0x99, 0, 0x0020 },
94 { 0x085, 0xad, 0, 0x0010 },
95 { 0x086, 0x1c, 0, 0xffff },
96 { 0x08a, 0x39, 0, 0x0020 },
97 { 0x08a, 0x41, 0, 0x0010 },
98 { 0x08b, 0x76, 0, 0x0020 },
99 { 0x08b, 0x8b, 0, 0x0010 },
100 { 0x090, 0x5e, 0, 0xffff },
101 { 0x091, 0x5e, 0, 0xffff },
102 { 0x092, 0x86, 0, 0xffff },
103 { 0x096, 0xa4, 0, 0xffff },
104 { 0x097, 0xa4, 0, 0xffff },
105 { 0x098, 0xa4, 0, 0xffff },
106 { 0x09b, 0xa4, 0, 0xffff },
107 { 0x0a0, 0x0a, 0, 0xffff },
108 { 0x0a1, 0x0a, 0, 0xffff },
109 { 0x0ae, 0x7c, 0, 0xffff },
110 { 0x0af, 0x7c, 0, 0xffff },
111 { 0x0b0, 0x9a, 0, 0xffff },
112 { 0x0b3, 0x7c, 0, 0xffff },
113 { 0x0b6, 0x08, 0, 0xffff },
114 { 0x0b7, 0x08, 0, 0xffff },
115 { 0x0ea, 0x64, 0, 0x0020 },
116 { 0x0ea, 0x5c, 0, 0x0010 },
117 { 0x0ef, 0xff, 0, 0xffff },
118 { 0x0f8, 0x15, 0, 0xffff },
119 { 0x0f9, 0x00, 0, 0xffff },
120 { 0x0f0, 0x30, 0, 0xffff },
121 { 0x0fd, 0x01, 0, 0xffff },
122 { 0x1a1, 0x00, 0, 0xffff },
123 { 0x1a2, 0x00, 0, 0xffff },
124 { 0x1b1, 0x08, 0, 0xffff },
125 { 0x1be, 0x90, 0, 0xffff },
126 { 0x280, 0x94, 0, 0x0020 },
127 { 0x281, 0x11, 0, 0x0020 },
128 { 0x280, 0x94, 0, 0x0010 },
129 { 0x281, 0x11, 0, 0x0010 },
130 { 0x282, 0x03, 0, 0xffff },
131 { 0x283, 0x0a, 0, 0xffff },
132 { 0x284, 0x80, 0, 0xffff },
133 { 0x285, 0x03, 0, 0xffff },
134 { 0x288, 0x28, 0, 0x0020 },
135 { 0x289, 0x0a, 0, 0x0020 },
136 { 0x288, 0x28, 0, 0x0010 },
137 { 0x289, 0x0a, 0, 0x0010 },
138 { 0x28a, 0x03, 0, 0xffff },
139 { 0x28b, 0x0a, 0, 0xffff },
140 { 0x28c, 0x80, 0, 0xffff },
141 { 0x28d, 0x03, 0, 0xffff },
142};
143
144struct hwm_tab_entry HWM_TAB5[] = {
145 { 0x005, 0x33, 0, 0xffff },
146 { 0x018, 0x2f, 0, 0xffff },
147 { 0x019, 0x2f, 0, 0xffff },
148 { 0x01a, 0x2f, 0, 0xffff },
149 { 0x080, 0x00, 0, 0xffff },
150 { 0x081, 0x00, 0, 0xffff },
151 { 0x083, 0xbb, 0, 0xffff },
152 { 0x085, 0x66, 0, 0x0020 },
153 { 0x085, 0x5d, 0, 0x0010 },
154 { 0x086, 0x1c, 0, 0xffff },
155 { 0x08a, 0x39, 0, 0x0020 },
156 { 0x08a, 0x41, 0, 0x0010 },
157 { 0x08b, 0x76, 0, 0x0020 },
158 { 0x08b, 0x80, 0, 0x0010 },
159 { 0x090, 0x5d, 0, 0x0020 },
160 { 0x090, 0x5e, 0, 0x0010 },
161 { 0x091, 0x5e, 0, 0xffff },
162 { 0x092, 0x86, 0, 0xffff },
163 { 0x096, 0xa4, 0, 0xffff },
164 { 0x097, 0xa4, 0, 0xffff },
165 { 0x098, 0xa3, 0, 0x0020 },
166 { 0x098, 0xa4, 0, 0x0010 },
167 { 0x09b, 0xa4, 0, 0xffff },
168 { 0x0a0, 0x08, 0, 0xffff },
169 { 0x0a1, 0x0a, 0, 0xffff },
170 { 0x0ae, 0x7c, 0, 0xffff },
171 { 0x0af, 0x7c, 0, 0xffff },
172 { 0x0b0, 0x9a, 0, 0xffff },
173 { 0x0b3, 0x7c, 0, 0xffff },
174 { 0x0b6, 0x08, 0, 0xffff },
175 { 0x0b7, 0x08, 0, 0xffff },
176 { 0x0ea, 0x64, 0, 0x0020 },
177 { 0x0ea, 0x5c, 0, 0x0010 },
178 { 0x0ef, 0xff, 0, 0xffff },
179 { 0x0f8, 0x15, 0, 0xffff },
180 { 0x0f9, 0x00, 0, 0xffff },
181 { 0x0f0, 0x30, 0, 0xffff },
182 { 0x0fd, 0x01, 0, 0xffff },
183 { 0x1a1, 0x00, 0, 0xffff },
184 { 0x1a2, 0x00, 0, 0xffff },
185 { 0x1b1, 0x08, 0, 0xffff },
186 { 0x1be, 0x98, 0, 0x0020 },
187 { 0x1be, 0x90, 0, 0x0010 },
188 { 0x280, 0x94, 0, 0x0020 },
189 { 0x281, 0x11, 0, 0x0020 },
190 { 0x280, 0x94, 0, 0x0010 },
191 { 0x281, 0x11, 0, 0x0010 },
192 { 0x282, 0x03, 0, 0xffff },
193 { 0x283, 0x0a, 0, 0xffff },
194 { 0x284, 0x80, 0, 0xffff },
195 { 0x285, 0x03, 0, 0xffff },
196 { 0x288, 0x28, 0, 0x0020 },
197 { 0x289, 0x0a, 0, 0x0020 },
198 { 0x288, 0x28, 0, 0x0010 },
199 { 0x289, 0x0a, 0, 0x0010 },
200 { 0x28a, 0x03, 0, 0xffff },
201 { 0x28b, 0x0a, 0, 0xffff },
202 { 0x28c, 0x80, 0, 0xffff },
203 { 0x28d, 0x03, 0, 0xffff },
204};
205
206struct hwm_tab_entry HWM_TAB6[] = {
207 { 0x005, 0x33, 0, 0xffff },
208 { 0x018, 0x2f, 0, 0xffff },
209 { 0x019, 0x2f, 0, 0xffff },
210 { 0x01a, 0x2f, 0, 0xffff },
211 { 0x080, 0x00, 0, 0xffff },
212 { 0x081, 0x00, 0, 0xffff },
213 { 0x083, 0xbb, 0, 0xffff },
214 { 0x085, 0x98, 0, 0xffff },
215 { 0x086, 0x3c, 0, 0xffff },
216 { 0x08a, 0x39, 0, 0x0020 },
217 { 0x08a, 0x3d, 0, 0x0010 },
218 { 0x08b, 0x44, 0, 0x0020 },
219 { 0x08b, 0x51, 0, 0x0010 },
220 { 0x090, 0x61, 0, 0xffff },
221 { 0x091, 0x6d, 0, 0xffff },
222 { 0x092, 0x86, 0, 0xffff },
223 { 0x096, 0xa4, 0, 0xffff },
224 { 0x097, 0xa4, 0, 0xffff },
225 { 0x098, 0x9f, 0, 0x0020 },
226 { 0x098, 0xa4, 0, 0x0010 },
227 { 0x09b, 0xa4, 0, 0xffff },
228 { 0x0a0, 0x0e, 0, 0xffff },
229 { 0x0a1, 0x0e, 0, 0xffff },
230 { 0x0ae, 0x7c, 0, 0xffff },
231 { 0x0af, 0x7c, 0, 0xffff },
232 { 0x0b0, 0x9b, 0, 0x0020 },
233 { 0x0b0, 0x98, 0, 0x0010 },
234 { 0x0b3, 0x9a, 0, 0xffff },
235 { 0x0b6, 0x08, 0, 0xffff },
236 { 0x0b7, 0x08, 0, 0xffff },
237 { 0x0ea, 0x64, 0, 0x0020 },
238 { 0x0ea, 0x5c, 0, 0x0010 },
239 { 0x0ef, 0xff, 0, 0xffff },
240 { 0x0f8, 0x15, 0, 0xffff },
241 { 0x0f9, 0x00, 0, 0xffff },
242 { 0x0f0, 0x30, 0, 0xffff },
243 { 0x0fd, 0x01, 0, 0xffff },
244 { 0x1a1, 0x00, 0, 0xffff },
245 { 0x1a2, 0x00, 0, 0xffff },
246 { 0x1b1, 0x08, 0, 0xffff },
247 { 0x1be, 0x9a, 0, 0x0020 },
248 { 0x1be, 0x96, 0, 0x0010 },
249 { 0x280, 0x94, 0, 0x0020 },
250 { 0x281, 0x11, 0, 0x0020 },
251 { 0x280, 0x94, 0, 0x0010 },
252 { 0x281, 0x11, 0, 0x0010 },
253 { 0x282, 0x03, 0, 0xffff },
254 { 0x283, 0x0a, 0, 0xffff },
255 { 0x284, 0x80, 0, 0xffff },
256 { 0x285, 0x03, 0, 0xffff },
257 { 0x288, 0x94, 0, 0x0020 },
258 { 0x289, 0x11, 0, 0x0020 },
259 { 0x288, 0x94, 0, 0x0010 },
260 { 0x289, 0x11, 0, 0x0010 },
261 { 0x28a, 0x03, 0, 0xffff },
262 { 0x28b, 0x0a, 0, 0xffff },
263 { 0x28c, 0x80, 0, 0xffff },
264 { 0x28d, 0x03, 0, 0xffff },
265};
266
267static uint8_t get_chassis_type(void)
268{
269 uint8_t gpio_chassis_type;
270
271 // Read chassis type from GPIO
272 gpio_chassis_type = get_gpio(70) << 3 | get_gpio(38) << 2 |
273 get_gpio(17) << 1 | get_gpio(1);
274
275 printk(BIOS_DEBUG, "GPIO chassis type = %#x\n", gpio_chassis_type);
276
277 // Turn it into internal chassis index
278 switch (gpio_chassis_type) {
279 case 0x08:
280 case 0x0a:
281 return 4;
282 case 0x0b:
283 return 3;
284 case 0x0c:
285 return 5;
286 case 0x0d: // SFF
287 case 0x0e:
288 case 0x0f:
289 return 6;
290 default:
291 return CHASSIS_TYPE_UNKNOWN;
292 }
293
294}
295
296static uint8_t get_temp_target(void)
297{
298 uint8_t val = rdmsr(0x1a2).lo >> 8 & 0xff;
299 if (!val)
300 val = 20;
301 return 0x95 - val;
302}
303
304static uint16_t get_pkg_power(void)
305{
306 uint8_t rapl_power_unit = rdmsr(0x606).lo & 0xf;
307 if (rapl_power_unit)
308 rapl_power_unit = 2 << (rapl_power_unit - 1);
309 uint16_t pkg_power_info = rdmsr(0x614).lo & 0x7fff;
310 if (pkg_power_info / rapl_power_unit > 0x41)
311 return 32;
312 else
313 return 16;
314}
315
316static void apply_hwm_tab(struct hwm_tab_entry *arr, size_t size)
317{
318 uint8_t temp_target = get_temp_target();
319 uint16_t pkg_power = get_pkg_power();
320
321 printk(BIOS_DEBUG, "Temp target = %#x\n", temp_target);
322 printk(BIOS_DEBUG, "Package power = %#x\n", pkg_power);
323
324 for (size_t i = 0; i < size; ++i) {
325 // Skip entry if it doesn't apply for this package power
326 if (arr[i].pkg_power != pkg_power &&
327 arr[i].pkg_power != HWM_TAB_PKG_POWER_ANY)
328 continue;
329
330 uint8_t val = arr[i].val;
331
332 // Add temp target to value if requested (current tables never do)
333 if (arr[i].flags & HWM_TAB_ADD_TEMP_TARGET)
334 val += temp_target;
335
336 // Perform write
337 sch5555_mbox_write(1, arr[i].addr, val);
338
339 }
340}
341
342static void sch5555_ec_hwm_init(void *arg)
343{
344 uint8_t chassis_type, saved_2fc;
345
346 printk(BIOS_DEBUG, "OptiPlex 9020 late HWM init\n");
347
348 saved_2fc = sch5555_mbox_read(1, 0x2fc);
349 sch5555_mbox_write(1, 0x2fc, 0xa0);
350 sch5555_mbox_write(1, 0x2fd, 0x32);
351
352 chassis_type = get_chassis_type();
353
354 if (chassis_type != CHASSIS_TYPE_UNKNOWN) {
355 printk(BIOS_DEBUG, "Chassis type = %#x\n", chassis_type);
356 } else {
357 printk(BIOS_DEBUG, "WARNING: Unknown chassis type\n");
358 }
359
360 // Apply HWM table based on chassis type
361 switch (chassis_type) {
362 case 3:
363 apply_hwm_tab(HWM_TAB3, ARRAY_SIZE(HWM_TAB3));
364 break;
365 case 4:
366 apply_hwm_tab(HWM_TAB4, ARRAY_SIZE(HWM_TAB4));
367 break;
368 case 5:
369 apply_hwm_tab(HWM_TAB5, ARRAY_SIZE(HWM_TAB5));
370 break;
371 case 6:
372 apply_hwm_tab(HWM_TAB6, ARRAY_SIZE(HWM_TAB6));
373 break;
374 }
375
376 // NOTE: vendor firmware applies these when "max core address" > 2
377 // i think this is always the case
378 sch5555_mbox_write(1, 0x9e, 0x30);
379 sch5555_mbox_write(1, 0xeb, sch5555_mbox_read(1, 0xea));
380
381 sch5555_mbox_write(1, 0x2fc, saved_2fc);
382
383 // Apply full speed fan config if requested or if the chassis type is unknown
384 if (chassis_type == CHASSIS_TYPE_UNKNOWN || get_uint_option("fan_full_speed", 0)) {
385 printk(BIOS_DEBUG, "Setting full fan speed\n");
386 sch5555_mbox_write(1, 0x80, 0x60 | sch5555_mbox_read(1, 0x80));
387 sch5555_mbox_write(1, 0x81, 0x60 | sch5555_mbox_read(1, 0x81));
388 }
389
390 sch5555_mbox_read(1, 0xb8);
391
392 if ((chassis_type == 4 || chassis_type == 5) && sch5555_mbox_read(1, 0x26) == 0) {
393 sch5555_mbox_write(1, 0xa0, sch5555_mbox_read(1, 0xa0) & 0xfb);
394 sch5555_mbox_write(1, 0xa1, sch5555_mbox_read(1, 0xa1) & 0xfb);
395 sch5555_mbox_write(1, 0xa2, sch5555_mbox_read(1, 0xa2) & 0xfb);
396 sch5555_mbox_write(1, 0x8a, 0x99);
397 sch5555_mbox_write(1, 0x8b, 0x47);
398 sch5555_mbox_write(1, 0x8c, 0x91);
399 }
400}
401
402BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, sch5555_ec_hwm_init, NULL);