blob: f0c913fcaa39e79b7d7257dc1d14205649684ea1 [file] [log] [blame]
Hannah Williamsba0fc472016-05-04 18:15:49 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2013 Google Inc.
5 * Copyright (C) 2015-2016 Intel Corp.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <arch/hlt.h>
18#include <arch/io.h>
19#include <console/console.h>
20#include <cpu/x86/cache.h>
21#include <cpu/x86/smm.h>
22#include <device/pci_def.h>
23#include <elog.h>
24#include <soc/nvs.h>
25#include <soc/pm.h>
26#include <soc/gpio.h>
27#include <soc/iomap.h>
28#include <spi-generic.h>
29#include <stdint.h>
30#include <stdlib.h>
31#include "smi.h"
32
33/* GNVS needs to be set by coreboot initiating a software SMI. */
34static struct global_nvs_t *gnvs;
35
36__attribute__((weak)) int smm_disable_busmaster(device_t dev)
37{
38 return 1;
39}
40
41static void *find_save_state(const struct smm_save_state_ops *save_state_ops,
42 int cmd)
43{
44 int node;
45 void *state = NULL;
46 uint32_t io_misc_info;
47 uint8_t reg_al;
48
49 /* Check all nodes looking for the one that issued the IO */
50 for (node = 0; node < CONFIG_MAX_CPUS; node++) {
51 state = smm_get_save_state(node);
52
53 io_misc_info = save_state_ops->get_io_misc_info(state);
54
55 /* Check for Synchronous IO (bit0==1) */
56 if (!(io_misc_info & (1 << 0)))
57 continue;
58 /* Make sure it was a write (bit4==0) */
59 if (io_misc_info & (1 << 4))
60 continue;
61 /* Check for APMC IO port */
62 if (((io_misc_info >> 16) & 0xff) != APM_CNT)
63 continue;
64 /* Check AL against the requested command */
65 reg_al = save_state_ops->get_reg(state, RAX);
66 if (reg_al != cmd)
67 continue;
68 break;
69 }
70 return state;
71}
72
73void southbridge_smi_set_eos(void)
74{
75 enable_smi(EOS);
76}
77
78struct global_nvs_t *smm_get_gnvs(void)
79{
80 return gnvs;
81}
82
83static void busmaster_disable_on_bus(int bus)
84{
85 int slot, func;
86 unsigned int val;
87 unsigned char hdr;
88
89 for (slot = 0; slot < 0x20; slot++) {
90 for (func = 0; func < 8; func++) {
91 u32 reg32;
92 device_t dev = PCI_DEV(bus, slot, func);
93
94 if (!smm_disable_busmaster(dev))
95 continue;
96 val = pci_read_config32(dev, PCI_VENDOR_ID);
97
98 if (val == 0xffffffff || val == 0x00000000 ||
99 val == 0x0000ffff || val == 0xffff0000)
100 continue;
101
102 /* Disable Bus Mastering for this one device */
103 reg32 = pci_read_config32(dev, PCI_COMMAND);
104 reg32 &= ~PCI_COMMAND_MASTER;
105 pci_write_config32(dev, PCI_COMMAND, reg32);
106
Aaron Durbin065b6832016-06-10 21:44:26 -0500107 /* If it's not a bridge, move on. */
Hannah Williamsba0fc472016-05-04 18:15:49 -0700108 hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
109 hdr &= 0x7f;
Aaron Durbin065b6832016-06-10 21:44:26 -0500110 if (hdr != PCI_HEADER_TYPE_BRIDGE &&
111 hdr != PCI_HEADER_TYPE_CARDBUS)
112 continue;
113
114 /*
115 * If secondary bus is equal to current bus bypass
116 * the bridge because it's likely unconfigured and
117 * would cause infinite recursion.
118 */
119 int secbus = pci_read_config8(dev, PCI_SECONDARY_BUS);
120
121 if (secbus == bus)
122 continue;
123
124 busmaster_disable_on_bus(secbus);
Hannah Williamsba0fc472016-05-04 18:15:49 -0700125 }
126 }
127}
128
129
130void southbridge_smi_sleep(const struct smm_save_state_ops *save_state_ops)
131{
132 uint32_t reg32;
133 uint8_t slp_typ;
134
135 /* First, disable further SMIs */
136 disable_smi(SLP_SMI_EN);
137 /* Figure out SLP_TYP */
138 reg32 = inl(ACPI_PMIO_BASE + PM1_CNT);
139 printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
Aaron Durbin56db47f2016-07-13 23:19:46 -0500140 slp_typ = acpi_sleep_from_pm1(reg32);
Hannah Williamsba0fc472016-05-04 18:15:49 -0700141
142 /* Do any mainboard sleep handling */
Aaron Durbin56db47f2016-07-13 23:19:46 -0500143 mainboard_smi_sleep(slp_typ);
Hannah Williamsba0fc472016-05-04 18:15:49 -0700144
145 /* Log S3, S4, and S5 entry */
Aaron Durbin56db47f2016-07-13 23:19:46 -0500146 if (slp_typ >= ACPI_S3 && IS_ENABLED(CONFIG_ELOG_GSMI))
147 elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
Hannah Williamsba0fc472016-05-04 18:15:49 -0700148
149 /* Clear pending GPE events */
150 clear_gpe_status();
151
152 /* Next, do the deed. */
153
154 switch (slp_typ) {
Aaron Durbin56db47f2016-07-13 23:19:46 -0500155 case ACPI_S0:
Hannah Williamsba0fc472016-05-04 18:15:49 -0700156 printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
157 break;
Aaron Durbin56db47f2016-07-13 23:19:46 -0500158 case ACPI_S3:
Hannah Williamsba0fc472016-05-04 18:15:49 -0700159 printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
160
161 /* Invalidate the cache before going to S3 */
162 wbinvd();
163 break;
Aaron Durbin56db47f2016-07-13 23:19:46 -0500164 case ACPI_S4:
Hannah Williamsba0fc472016-05-04 18:15:49 -0700165 printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
166 break;
Aaron Durbin56db47f2016-07-13 23:19:46 -0500167 case ACPI_S5:
Hannah Williamsba0fc472016-05-04 18:15:49 -0700168 printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
169
170 /* Disable all GPE */
171 disable_all_gpe();
172 /* also iterates over all bridges on bus 0 */
173 busmaster_disable_on_bus(0);
174 break;
175 default:
176 printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
177 break;
178 }
179 /* Clear pending wake status bit to avoid immediate wake */
180
181 /* Tri-state specific GPIOS to avoid leakage during S3/S5 */
182
183 /*
184 * Write back to the SLP register to cause the originally intended
185 * event again. We need to set BIT13 (SLP_EN) though to make the
186 * sleep happen.
187 */
188 enable_pm1_control(SLP_EN);
189
190 /* Make sure to stop executing code here for S3/S4/S5 */
Aaron Durbin56db47f2016-07-13 23:19:46 -0500191 if (slp_typ >= ACPI_S3)
Hannah Williamsba0fc472016-05-04 18:15:49 -0700192 hlt();
193
194 /*
195 * In most sleep states, the code flow of this function ends at
196 * the line above. However, if we entered sleep state S1 and wake
197 * up again, we will continue to execute code in this function.
198 */
199 reg32 = inl(ACPI_PMIO_BASE + PM1_CNT);
200 if (reg32 & SCI_EN) {
201 /* The OS is not an ACPI OS, so we set the state to S0 */
202 disable_pm1_control(SLP_EN | SLP_TYP);
203 }
204}
205
206static void southbridge_smi_gsmi(const struct
207 smm_save_state_ops *save_state_ops)
208{
209 u8 sub_command, ret;
210 void *io_smi = NULL;
211 uint32_t reg_ebx;
212
213 io_smi = find_save_state(save_state_ops, ELOG_GSMI_APM_CNT);
214 if (!io_smi)
215 return;
216 /* Command and return value in EAX */
217 sub_command = (save_state_ops->get_reg(io_smi, RAX) >> 8)
218 & 0xff;
219
220 /* Parameter buffer in EBX */
221 reg_ebx = save_state_ops->get_reg(io_smi, RBX);
222
223 /* drivers/elog/gsmi.c */
224 ret = gsmi_exec(sub_command, (u32 *)(uintptr_t)reg_ebx);
225 save_state_ops->set_reg(io_smi, RAX, ret);
226}
227
228static void finalize(void)
229{
230 static int finalize_done;
231
232 if (finalize_done) {
233 printk(BIOS_DEBUG, "SMM already finalized.\n");
234 return;
235 }
236 finalize_done = 1;
237
238}
239
240void southbridge_smi_apmc(const struct smm_save_state_ops *save_state_ops)
241{
242 uint8_t reg8;
243 void *state = NULL;
244 static int smm_initialized = 0;
245
246 /* Emulate B2 register as the FADT / Linux expects it */
247
248 reg8 = inb(APM_CNT);
249 switch (reg8) {
250 case APM_CNT_CST_CONTROL:
251 /*
252 * Calling this function seems to cause
253 * some kind of race condition in Linux
254 * and causes a kernel oops
255 */
256 printk(BIOS_DEBUG, "C-state control\n");
257 break;
258 case APM_CNT_PST_CONTROL:
259 /*
260 * Calling this function seems to cause
261 * some kind of race condition in Linux
262 * and causes a kernel oops
263 */
264 printk(BIOS_DEBUG, "P-state control\n");
265 break;
266 case APM_CNT_ACPI_DISABLE:
267 disable_pm1_control(SCI_EN);
268 printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
269 break;
270 case APM_CNT_ACPI_ENABLE:
271 enable_pm1_control(SCI_EN);
272 printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
273 break;
274 case APM_CNT_GNVS_UPDATE:
275 if (smm_initialized) {
276 printk(BIOS_DEBUG,
277 "SMI#: SMM structures already initialized!\n");
278 return;
279 }
280 state = find_save_state(save_state_ops, reg8);
281 if (state) {
282 /* EBX in the state save contains the GNVS pointer */
283 uint32_t reg_ebx = save_state_ops->get_reg(state, RBX);
284 gnvs = (struct global_nvs_t *)(uintptr_t)reg_ebx;
285 smm_initialized = 1;
286 printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
287 }
288 break;
289 case ELOG_GSMI_APM_CNT:
290 if (IS_ENABLED(CONFIG_ELOG_GSMI))
291 southbridge_smi_gsmi(save_state_ops);
292 break;
293 case APM_CNT_FINALIZE:
294 finalize();
295 break;
296 }
297
298 mainboard_smi_apmc(reg8);
299}
300
301void southbridge_smi_pm1(const struct smm_save_state_ops *save_state_ops)
302{
303 uint16_t pm1_sts = clear_pm1_status();
304
305 /*
306 * While OSPM is not active, poweroff immediately
307 * on a power button event.
308 */
309 if (pm1_sts & PWRBTN_STS) {
310 /* power button pressed */
311 if (IS_ENABLED(CONFIG_ELOG_GSMI))
312 elog_add_event(ELOG_TYPE_POWER_BUTTON);
313 disable_pm1_control(-1UL);
314 enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));
315 }
316}
317
318void southbridge_smi_gpe0(const struct smm_save_state_ops *save_state_ops)
319{
320 clear_gpe_status();
321}
322
323void southbridge_smi_tco(const struct smm_save_state_ops *save_state_ops)
324{
325 uint32_t tco_sts = clear_tco_status();
326
327 /* Any TCO event? */
328 if (!tco_sts)
329 return;
330
331 if (tco_sts & TCO_TIMEOUT) { /* TIMEOUT */
332 /* Handle TCO timeout */
333 printk(BIOS_DEBUG, "TCO Timeout.\n");
334 }
335}
336
337void southbridge_smi_periodic(const struct smm_save_state_ops *save_state_ops)
338{
339 uint32_t reg32;
340
341 reg32 = get_smi_en();
342
343 /* Are periodic SMIs enabled? */
344 if ((reg32 & PERIODIC_EN) == 0)
345 return;
346 printk(BIOS_DEBUG, "Periodic SMI.\n");
347}
348
349void southbridge_smi_handler(void)
350{
351 int i;
352 uint32_t smi_sts;
353 const struct smm_save_state_ops *save_state_ops;
354
355 /*
356 * We need to clear the SMI status registers, or we won't see what's
357 * happening in the following calls.
358 */
359 smi_sts = clear_smi_status();
360
361 save_state_ops = get_smm_save_state_ops();
362
363 /* Call SMI sub handler for each of the status bits */
364 for (i = 0; i < ARRAY_SIZE(southbridge_smi); i++) {
365 if (!(smi_sts & (1 << i)))
366 continue;
367
368 if (southbridge_smi[i] != NULL) {
369 southbridge_smi[i](save_state_ops);
370 } else {
371 printk(BIOS_DEBUG,
372 "SMI_STS[%d] occurred, but no "
373 "handler available.\n", i);
374 }
375 }
376}
377
378static uint32_t em64t100_smm_save_state_get_io_misc_info(void *state)
379{
380 em64t100_smm_state_save_area_t *smm_state = state;
381 return smm_state->io_misc_info;
382}
383
384static uint64_t em64t100_smm_save_state_get_reg(void *state, enum smm_reg reg)
385{
386 uintptr_t value = 0;
387 em64t100_smm_state_save_area_t *smm_state = state;
388
389 switch(reg) {
390 case RAX:
391 value = smm_state->rax;
392 break;
393 case RBX:
394 value = smm_state->rbx;
395 break;
396 case RCX:
397 value = smm_state->rcx;
398 break;
399 case RDX:
400 value = smm_state->rdx;
401 break;
402 default:
403 break;
404 }
405 return value;
406}
407
408static void em64t100_smm_save_state_set_reg(void *state, enum smm_reg reg, uint64_t val)
409{
410 em64t100_smm_state_save_area_t *smm_state = state;
411 switch(reg) {
412 case RAX:
413 smm_state->rax = val;
414 break;
415 case RBX:
416 smm_state->rbx = val;
417 break;
418 case RCX:
419 smm_state->rcx = val;
420 break;
421 case RDX:
422 smm_state->rdx = val;
423 break;
424 default:
425 break;
426 }
427}
428
429static uint32_t em64t101_smm_save_state_get_io_misc_info(void *state)
430{
431 em64t101_smm_state_save_area_t *smm_state = state;
432 return smm_state->io_misc_info;
433}
434
435static uint64_t em64t101_smm_save_state_get_reg(void *state, enum smm_reg reg)
436{
437 uintptr_t value = 0;
438 em64t101_smm_state_save_area_t *smm_state = state;
439
440 switch(reg) {
441 case RAX:
442 value = smm_state->rax;
443 break;
444 case RBX:
445 value = smm_state->rbx;
446 break;
447 case RCX:
448 value = smm_state->rcx;
449 break;
450 case RDX:
451 value = smm_state->rdx;
452 break;
453 default:
454 break;
455 }
456 return value;
457}
458
459static void em64t101_smm_save_state_set_reg(void *state, enum smm_reg reg, uint64_t val)
460{
461 em64t101_smm_state_save_area_t *smm_state = state;
462 switch(reg) {
463 case RAX:
464 smm_state->rax = val;
465 break;
466 case RBX:
467 smm_state->rbx = val;
468 break;
469 case RCX:
470 smm_state->rcx = val;
471 break;
472 case RDX:
473 smm_state->rdx = val;
474 break;
475 default:
476 break;
477 }
478}
479
480const struct smm_save_state_ops em64t100_smm_ops = {
481 .get_io_misc_info = em64t100_smm_save_state_get_io_misc_info,
482 .get_reg = em64t100_smm_save_state_get_reg,
483 .set_reg = em64t100_smm_save_state_set_reg,
484};
485
486const struct smm_save_state_ops em64t101_smm_ops = {
487 .get_io_misc_info = em64t101_smm_save_state_get_io_misc_info,
488 .get_reg = em64t101_smm_save_state_get_reg,
489 .set_reg = em64t101_smm_save_state_set_reg,
490};