mb/google/nissa/var/rull: add ssd timing and modify ssd GPIO pins of rtd3
[coreboot2.git] / src / mainboard / dell / optiplex_9020 / mainboard.c
blob1cb850c46cbbefd862a78813226dcf9c5c930ece
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <bootstate.h>
4 #include <cpu/x86/msr.h>
5 #include <device/device.h>
6 #include <drivers/intel/gma/int15.h>
7 #include <option.h>
8 #include <southbridge/intel/common/gpio.h>
9 #include "sch5555_ec.h"
11 static void mainboard_enable(struct device *dev)
13 install_intel_vga_int15_handler(GMA_INT15_ACTIVE_LFP_NONE,
14 GMA_INT15_PANEL_FIT_DEFAULT,
15 GMA_INT15_BOOT_DISPLAY_DEFAULT, 0);
18 struct chip_operations mainboard_ops = {
19 .enable_dev = mainboard_enable,
22 #define HWM_TAB_ADD_TEMP_TARGET 1
23 #define HWM_TAB_PKG_POWER_ANY 0xffff
24 #define CHASSIS_TYPE_UNKNOWN 0xff
26 struct hwm_tab_entry {
27 uint16_t addr;
28 uint8_t val;
29 uint8_t flags;
30 uint16_t pkg_power;
33 struct 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 },
85 struct 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 },
144 struct 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 },
206 struct 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 },
267 static uint8_t get_chassis_type(void)
269 uint8_t gpio_chassis_type;
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);
275 printk(BIOS_DEBUG, "GPIO chassis type = %#x\n", gpio_chassis_type);
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;
296 static uint8_t get_temp_target(void)
298 uint8_t val = rdmsr(0x1a2).lo >> 8 & 0xff;
299 if (!val)
300 val = 20;
301 return 0x95 - val;
304 static uint16_t get_pkg_power(void)
306 const unsigned int pkg_power = rdmsr(0x614).lo & 0x7fff;
307 const unsigned int power_unit = 1 << (rdmsr(0x606).lo & 0xf);
308 if (pkg_power / power_unit > 65)
309 return 32;
310 else
311 return 16;
314 static void apply_hwm_tab(struct hwm_tab_entry *arr, size_t size)
316 uint8_t temp_target = get_temp_target();
317 uint16_t pkg_power = get_pkg_power();
319 printk(BIOS_DEBUG, "Temp target = %#x\n", temp_target);
320 printk(BIOS_DEBUG, "Package power = %#x\n", pkg_power);
322 for (size_t i = 0; i < size; ++i) {
323 // Skip entry if it doesn't apply for this package power
324 if (arr[i].pkg_power != pkg_power &&
325 arr[i].pkg_power != HWM_TAB_PKG_POWER_ANY)
326 continue;
328 uint8_t val = arr[i].val;
330 // Add temp target to value if requested (current tables never do)
331 if (arr[i].flags & HWM_TAB_ADD_TEMP_TARGET)
332 val += temp_target;
334 // Perform write
335 sch5555_mbox_write(1, arr[i].addr, val);
340 static void sch5555_ec_hwm_init(void *arg)
342 uint8_t chassis_type, saved_2fc;
344 printk(BIOS_DEBUG, "OptiPlex 9020 late HWM init\n");
346 saved_2fc = sch5555_mbox_read(1, 0x2fc);
347 sch5555_mbox_write(1, 0x2fc, 0xa0);
348 sch5555_mbox_write(1, 0x2fd, 0x32);
350 chassis_type = get_chassis_type();
352 if (chassis_type != CHASSIS_TYPE_UNKNOWN) {
353 printk(BIOS_DEBUG, "Chassis type = %#x\n", chassis_type);
354 } else {
355 printk(BIOS_DEBUG, "WARNING: Unknown chassis type\n");
358 // Apply HWM table based on chassis type
359 switch (chassis_type) {
360 case 3:
361 apply_hwm_tab(HWM_TAB3, ARRAY_SIZE(HWM_TAB3));
362 break;
363 case 4:
364 apply_hwm_tab(HWM_TAB4, ARRAY_SIZE(HWM_TAB4));
365 break;
366 case 5:
367 apply_hwm_tab(HWM_TAB5, ARRAY_SIZE(HWM_TAB5));
368 break;
369 case 6:
370 apply_hwm_tab(HWM_TAB6, ARRAY_SIZE(HWM_TAB6));
371 break;
374 // NOTE: vendor firmware applies these when "max core address" > 2
375 // i think this is always the case
376 sch5555_mbox_write(1, 0x9e, 0x30);
377 sch5555_mbox_write(1, 0xeb, sch5555_mbox_read(1, 0xea));
379 sch5555_mbox_write(1, 0x2fc, saved_2fc);
381 // Apply full speed fan config if requested or if the chassis type is unknown
382 if (chassis_type == CHASSIS_TYPE_UNKNOWN || get_uint_option("fan_full_speed", 0)) {
383 printk(BIOS_DEBUG, "Setting full fan speed\n");
384 sch5555_mbox_write(1, 0x80, 0x60 | sch5555_mbox_read(1, 0x80));
385 sch5555_mbox_write(1, 0x81, 0x60 | sch5555_mbox_read(1, 0x81));
388 sch5555_mbox_read(1, 0xb8);
390 if ((chassis_type == 4 || chassis_type == 5) && sch5555_mbox_read(1, 0x26) == 0) {
391 sch5555_mbox_write(1, 0xa0, sch5555_mbox_read(1, 0xa0) & 0xfb);
392 sch5555_mbox_write(1, 0xa1, sch5555_mbox_read(1, 0xa1) & 0xfb);
393 sch5555_mbox_write(1, 0xa2, sch5555_mbox_read(1, 0xa2) & 0xfb);
394 sch5555_mbox_write(1, 0x8a, 0x99);
395 sch5555_mbox_write(1, 0x8b, 0x47);
396 sch5555_mbox_write(1, 0x8c, 0x91);
400 BOOT_STATE_INIT_ENTRY(BS_POST_DEVICE, BS_ON_EXIT, sch5555_ec_hwm_init, NULL);