blob: d305635398dde348c70520b73d5545b419c766de [file] [log] [blame]
Vladimir Serbinenko888d5592013-11-13 17:53:38 +01001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2008-2009 coresystems GmbH
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; version 2 of
9 * 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.
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010015 */
16
17#include <types.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010018#include <arch/io.h>
19#include <console/console.h>
20#include <cpu/x86/cache.h>
21#include <device/pci_def.h>
22#include <cpu/x86/smm.h>
23#include <elog.h>
Patrick Georgi546953c2014-11-29 10:38:17 +010024#include <halt.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010025#include <pc80/mc146818rtc.h>
Patrick Rudolph63952e12018-06-28 14:29:49 +020026#include <southbridge/intel/common/pmbase.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010027#include "pch.h"
28
29#include "nvs.h"
30
31/* We are using PCIe accesses for now
32 * 1. the chipset can do it
33 * 2. we don't need to worry about how we leave 0xcf8/0xcfc behind
34 */
Elyes HAOUAS10b65dc2018-06-16 18:39:26 +020035#include <northbridge/intel/nehalem/nehalem.h>
Patrick Rudolph10104682016-02-06 18:12:28 +010036#include <southbridge/intel/common/gpio.h>
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010037
38/* While we read PMBASE dynamically in case it changed, let's
39 * initialize it with a sane value
40 */
41static u16 pmbase = DEFAULT_PMBASE;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010042
43static u8 smm_initialized = 0;
44
45/* GNVS needs to be updated by an 0xEA PM Trap (B2) after it has been located
46 * by coreboot.
47 */
Vladimir Serbinenko456f4952015-05-28 20:42:32 +020048static global_nvs_t *gnvs;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010049global_nvs_t *smm_get_gnvs(void)
50{
51 return gnvs;
52}
53
Kyösti Mälkkib85a87b2014-12-29 11:32:27 +020054static void alt_gpi_mask(u16 clr, u16 set)
55{
56 u16 alt_gp = inw(pmbase + ALT_GP_SMI_EN);
57 alt_gp &= ~clr;
58 alt_gp |= set;
59 outw(alt_gp, pmbase + ALT_GP_SMI_EN);
60}
61
62static void gpe0_mask(u32 clr, u32 set)
63{
64 u32 gpe0 = inl(pmbase + GPE0_EN);
65 gpe0 &= ~clr;
66 gpe0 |= set;
67 outl(gpe0, pmbase + GPE0_EN);
68}
69
70void gpi_route_interrupt(u8 gpi, u8 mode)
71{
72 u32 gpi_rout;
73 if (gpi >= 16)
74 return;
75
76 alt_gpi_mask(1 << gpi, 0);
77 gpe0_mask(1 << (gpi+16), 0);
78
79 gpi_rout = pci_read_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT);
80 gpi_rout &= ~(3 << (2 * gpi));
81 gpi_rout |= ((mode & 3) << (2 * gpi));
82 pci_write_config32(PCI_DEV(0, 0x1f, 0), GPIO_ROUT, gpi_rout);
83
84 if (mode == GPI_IS_SCI)
85 gpe0_mask(0, 1 << (gpi+16));
86 else if (mode == GPI_IS_SMI)
87 alt_gpi_mask(0, 1 << gpi);
88}
89
Vladimir Serbinenko888d5592013-11-13 17:53:38 +010090/**
91 * @brief read and clear PM1_STS
92 * @return PM1_STS register
93 */
94static u16 reset_pm1_status(void)
95{
96 u16 reg16;
97
98 reg16 = inw(pmbase + PM1_STS);
99 /* set status bits are cleared by writing 1 to them */
100 outw(reg16, pmbase + PM1_STS);
101
102 return reg16;
103}
104
105static void dump_pm1_status(u16 pm1_sts)
106{
107 printk(BIOS_SPEW, "PM1_STS: ");
108 if (pm1_sts & (1 << 15)) printk(BIOS_SPEW, "WAK ");
109 if (pm1_sts & (1 << 14)) printk(BIOS_SPEW, "PCIEXPWAK ");
110 if (pm1_sts & (1 << 11)) printk(BIOS_SPEW, "PRBTNOR ");
111 if (pm1_sts & (1 << 10)) printk(BIOS_SPEW, "RTC ");
112 if (pm1_sts & (1 << 8)) printk(BIOS_SPEW, "PWRBTN ");
113 if (pm1_sts & (1 << 5)) printk(BIOS_SPEW, "GBL ");
114 if (pm1_sts & (1 << 4)) printk(BIOS_SPEW, "BM ");
115 if (pm1_sts & (1 << 0)) printk(BIOS_SPEW, "TMROF ");
116 printk(BIOS_SPEW, "\n");
117 int reg16 = inw(pmbase + PM1_EN);
118 printk(BIOS_SPEW, "PM1_EN: %x\n", reg16);
119}
120
121/**
122 * @brief read and clear SMI_STS
123 * @return SMI_STS register
124 */
125static u32 reset_smi_status(void)
126{
127 u32 reg32;
128
129 reg32 = inl(pmbase + SMI_STS);
130 /* set status bits are cleared by writing 1 to them */
131 outl(reg32, pmbase + SMI_STS);
132
133 return reg32;
134}
135
136static void dump_smi_status(u32 smi_sts)
137{
138 printk(BIOS_DEBUG, "SMI_STS: ");
139 if (smi_sts & (1 << 26)) printk(BIOS_DEBUG, "SPI ");
140 if (smi_sts & (1 << 21)) printk(BIOS_DEBUG, "MONITOR ");
141 if (smi_sts & (1 << 20)) printk(BIOS_DEBUG, "PCI_EXP_SMI ");
142 if (smi_sts & (1 << 18)) printk(BIOS_DEBUG, "INTEL_USB2 ");
143 if (smi_sts & (1 << 17)) printk(BIOS_DEBUG, "LEGACY_USB2 ");
144 if (smi_sts & (1 << 16)) printk(BIOS_DEBUG, "SMBUS_SMI ");
145 if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "SERIRQ_SMI ");
146 if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "PERIODIC ");
147 if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "TCO ");
148 if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "DEVMON ");
149 if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "MCSMI ");
150 if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "GPI ");
151 if (smi_sts & (1 << 9)) printk(BIOS_DEBUG, "GPE0 ");
152 if (smi_sts & (1 << 8)) printk(BIOS_DEBUG, "PM1 ");
153 if (smi_sts & (1 << 6)) printk(BIOS_DEBUG, "SWSMI_TMR ");
154 if (smi_sts & (1 << 5)) printk(BIOS_DEBUG, "APM ");
155 if (smi_sts & (1 << 4)) printk(BIOS_DEBUG, "SLP_SMI ");
156 if (smi_sts & (1 << 3)) printk(BIOS_DEBUG, "LEGACY_USB ");
157 if (smi_sts & (1 << 2)) printk(BIOS_DEBUG, "BIOS ");
158 printk(BIOS_DEBUG, "\n");
159}
160
161
162/**
163 * @brief read and clear GPE0_STS
164 * @return GPE0_STS register
165 */
166static u32 reset_gpe0_status(void)
167{
168 u32 reg32;
169
170 reg32 = inl(pmbase + GPE0_STS);
171 /* set status bits are cleared by writing 1 to them */
172 outl(reg32, pmbase + GPE0_STS);
173
174 return reg32;
175}
176
177static void dump_gpe0_status(u32 gpe0_sts)
178{
179 int i;
180 printk(BIOS_DEBUG, "GPE0_STS: ");
181 for (i=31; i>= 16; i--) {
182 if (gpe0_sts & (1 << i)) printk(BIOS_DEBUG, "GPIO%d ", (i-16));
183 }
184 if (gpe0_sts & (1 << 14)) printk(BIOS_DEBUG, "USB4 ");
185 if (gpe0_sts & (1 << 13)) printk(BIOS_DEBUG, "PME_B0 ");
186 if (gpe0_sts & (1 << 12)) printk(BIOS_DEBUG, "USB3 ");
187 if (gpe0_sts & (1 << 11)) printk(BIOS_DEBUG, "PME ");
188 if (gpe0_sts & (1 << 10)) printk(BIOS_DEBUG, "BATLOW ");
189 if (gpe0_sts & (1 << 9)) printk(BIOS_DEBUG, "PCI_EXP ");
190 if (gpe0_sts & (1 << 8)) printk(BIOS_DEBUG, "RI ");
191 if (gpe0_sts & (1 << 7)) printk(BIOS_DEBUG, "SMB_WAK ");
192 if (gpe0_sts & (1 << 6)) printk(BIOS_DEBUG, "TCO_SCI ");
193 if (gpe0_sts & (1 << 5)) printk(BIOS_DEBUG, "AC97 ");
194 if (gpe0_sts & (1 << 4)) printk(BIOS_DEBUG, "USB2 ");
195 if (gpe0_sts & (1 << 3)) printk(BIOS_DEBUG, "USB1 ");
196 if (gpe0_sts & (1 << 2)) printk(BIOS_DEBUG, "SWGPE ");
197 if (gpe0_sts & (1 << 1)) printk(BIOS_DEBUG, "HOTPLUG ");
198 if (gpe0_sts & (1 << 0)) printk(BIOS_DEBUG, "THRM ");
199 printk(BIOS_DEBUG, "\n");
200}
201
202
203/**
204 * @brief read and clear TCOx_STS
205 * @return TCOx_STS registers
206 */
207static u32 reset_tco_status(void)
208{
209 u32 tcobase = pmbase + 0x60;
210 u32 reg32;
211
212 reg32 = inl(tcobase + 0x04);
213 /* set status bits are cleared by writing 1 to them */
Elyes HAOUAS98587962017-07-03 21:43:18 +0200214 outl(reg32 & ~(1 << 18), tcobase + 0x04); // Don't clear BOOT_STS before SECOND_TO_STS
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100215 if (reg32 & (1 << 18))
Elyes HAOUAS98587962017-07-03 21:43:18 +0200216 outl(reg32 & (1 << 18), tcobase + 0x04); // clear BOOT_STS
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100217
218 return reg32;
219}
220
221
222static void dump_tco_status(u32 tco_sts)
223{
224 printk(BIOS_DEBUG, "TCO_STS: ");
225 if (tco_sts & (1 << 20)) printk(BIOS_DEBUG, "SMLINK_SLV ");
226 if (tco_sts & (1 << 18)) printk(BIOS_DEBUG, "BOOT ");
227 if (tco_sts & (1 << 17)) printk(BIOS_DEBUG, "SECOND_TO ");
228 if (tco_sts & (1 << 16)) printk(BIOS_DEBUG, "INTRD_DET ");
229 if (tco_sts & (1 << 12)) printk(BIOS_DEBUG, "DMISERR ");
230 if (tco_sts & (1 << 10)) printk(BIOS_DEBUG, "DMISMI ");
231 if (tco_sts & (1 << 9)) printk(BIOS_DEBUG, "DMISCI ");
232 if (tco_sts & (1 << 8)) printk(BIOS_DEBUG, "BIOSWR ");
233 if (tco_sts & (1 << 7)) printk(BIOS_DEBUG, "NEWCENTURY ");
234 if (tco_sts & (1 << 3)) printk(BIOS_DEBUG, "TIMEOUT ");
235 if (tco_sts & (1 << 2)) printk(BIOS_DEBUG, "TCO_INT ");
236 if (tco_sts & (1 << 1)) printk(BIOS_DEBUG, "SW_TCO ");
237 if (tco_sts & (1 << 0)) printk(BIOS_DEBUG, "NMI2SMI ");
238 printk(BIOS_DEBUG, "\n");
239}
240
241int southbridge_io_trap_handler(int smif)
242{
243 switch (smif) {
244 case 0x32:
245 printk(BIOS_DEBUG, "OS Init\n");
246 /* gnvs->smif:
247 * On success, the IO Trap Handler returns 0
248 * On failure, the IO Trap Handler returns a value != 0
249 */
250 gnvs->smif = 0;
251 return 1; /* IO trap handled */
252 }
253
254 /* Not handled */
255 return 0;
256}
257
258/**
259 * @brief Set the EOS bit
260 */
261void southbridge_smi_set_eos(void)
262{
263 u8 reg8;
264
265 reg8 = inb(pmbase + SMI_EN);
266 reg8 |= EOS;
267 outb(reg8, pmbase + SMI_EN);
268}
269
270static void busmaster_disable_on_bus(int bus)
271{
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200272 int slot, func;
273 unsigned int val;
274 unsigned char hdr;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100275
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200276 for (slot = 0; slot < 0x20; slot++) {
277 for (func = 0; func < 8; func++) {
278 u32 reg32;
Antonello Dettori040117a2016-09-02 09:15:33 +0200279 pci_devfn_t dev = PCI_DEV(bus, slot, func);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100280
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200281 val = pci_read_config32(dev, PCI_VENDOR_ID);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100282
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200283 if (val == 0xffffffff || val == 0x00000000 ||
284 val == 0x0000ffff || val == 0xffff0000)
285 continue;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100286
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200287 /* Disable Bus Mastering for this one device */
288 reg32 = pci_read_config32(dev, PCI_COMMAND);
289 reg32 &= ~PCI_COMMAND_MASTER;
290 pci_write_config32(dev, PCI_COMMAND, reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100291
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200292 /* If this is a bridge, then follow it. */
293 hdr = pci_read_config8(dev, PCI_HEADER_TYPE);
294 hdr &= 0x7f;
295 if (hdr == PCI_HEADER_TYPE_BRIDGE ||
296 hdr == PCI_HEADER_TYPE_CARDBUS) {
297 unsigned int buses;
298 buses = pci_read_config32(dev, PCI_PRIMARY_BUS);
299 busmaster_disable_on_bus((buses >> 8) & 0xff);
300 }
301 }
302 }
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100303}
304
Vladimir Serbinenko6a7aeb32014-01-05 11:37:32 +0100305static void southbridge_gate_memory_reset_real(int offset,
306 u16 use, u16 io, u16 lvl)
307{
308 u32 reg32;
309
310 /* Make sure it is set as GPIO */
311 reg32 = inl(use);
312 if (!(reg32 & (1 << offset))) {
313 reg32 |= (1 << offset);
314 outl(reg32, use);
315 }
316
317 /* Make sure it is set as output */
318 reg32 = inl(io);
319 if (reg32 & (1 << offset)) {
320 reg32 &= ~(1 << offset);
321 outl(reg32, io);
322 }
323
324 /* Drive the output low */
325 reg32 = inl(lvl);
326 reg32 &= ~(1 << offset);
327 outl(reg32, lvl);
328}
329
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100330/*
331 * Drive GPIO 60 low to gate memory reset in S3.
332 *
333 * Intel reference designs all use GPIO 60 but it is
334 * not a requirement and boards could use a different pin.
335 */
336static void southbridge_gate_memory_reset(void)
337{
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100338 u16 gpiobase;
339
340 gpiobase = pci_read_config16(PCI_DEV(0, 0x1f, 0), GPIOBASE) & 0xfffc;
341 if (!gpiobase)
342 return;
343
Vladimir Serbinenko6a7aeb32014-01-05 11:37:32 +0100344 if (CONFIG_DRAM_RESET_GATE_GPIO >= 32)
345 southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO - 32,
346 gpiobase + GPIO_USE_SEL2,
347 gpiobase + GP_IO_SEL2,
348 gpiobase + GP_LVL2);
349 else
350 southbridge_gate_memory_reset_real(CONFIG_DRAM_RESET_GATE_GPIO,
351 gpiobase + GPIO_USE_SEL,
352 gpiobase + GP_IO_SEL,
353 gpiobase + GP_LVL);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100354}
355
356static void xhci_sleep(u8 slp_typ)
357{
358 u32 reg32, xhci_bar;
359 u16 reg16;
360
361 switch (slp_typ) {
Aaron Durbin78c68432016-07-13 23:23:54 -0500362 case ACPI_S3:
363 case ACPI_S4:
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100364 reg16 = pci_read_config16(PCH_XHCI_DEV, 0x74);
365 reg16 &= ~0x03UL;
366 pci_write_config32(PCH_XHCI_DEV, 0x74, reg16);
367
368 reg32 = pci_read_config32(PCH_XHCI_DEV, PCI_COMMAND);
369 reg32 |= (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
370 pci_write_config32(PCH_XHCI_DEV, PCI_COMMAND, reg32);
371
372 xhci_bar = pci_read_config32(PCH_XHCI_DEV,
373 PCI_BASE_ADDRESS_0) & ~0xFUL;
374
375 if ((xhci_bar + 0x4C0) & 1)
376 pch_iobp_update(0xEC000082, ~0UL, (3 << 2));
377 if ((xhci_bar + 0x4D0) & 1)
378 pch_iobp_update(0xEC000182, ~0UL, (3 << 2));
379 if ((xhci_bar + 0x4E0) & 1)
380 pch_iobp_update(0xEC000282, ~0UL, (3 << 2));
381 if ((xhci_bar + 0x4F0) & 1)
382 pch_iobp_update(0xEC000382, ~0UL, (3 << 2));
383
384 reg32 = pci_read_config32(PCH_XHCI_DEV, PCI_COMMAND);
385 reg32 &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
386 pci_write_config32(PCH_XHCI_DEV, PCI_COMMAND, reg32);
387
388 reg16 = pci_read_config16(PCH_XHCI_DEV, 0x74);
389 reg16 |= 0x03;
390 pci_write_config16(PCH_XHCI_DEV, 0x74, reg16);
391 break;
392
Aaron Durbin78c68432016-07-13 23:23:54 -0500393 case ACPI_S5:
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100394 reg16 = pci_read_config16(PCH_XHCI_DEV, 0x74);
395 reg16 |= ((1 << 8) | 0x03);
396 pci_write_config16(PCH_XHCI_DEV, 0x74, reg16);
397 break;
398 }
399}
400
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200401static void southbridge_smi_sleep(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100402{
403 u8 reg8;
404 u32 reg32;
405 u8 slp_typ;
Nico Huber9faae2b2018-11-14 00:00:35 +0100406 u8 s5pwr = CONFIG_MAINBOARD_POWER_FAILURE_STATE;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100407
408 // save and recover RTC port values
409 u8 tmp70, tmp72;
410 tmp70 = inb(0x70);
411 tmp72 = inb(0x72);
412 get_option(&s5pwr, "power_on_after_fail");
413 outb(tmp70, 0x70);
414 outb(tmp72, 0x72);
415
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100416 /* First, disable further SMIs */
417 reg8 = inb(pmbase + SMI_EN);
418 reg8 &= ~SLP_SMI_EN;
419 outb(reg8, pmbase + SMI_EN);
420
421 /* Figure out SLP_TYP */
422 reg32 = inl(pmbase + PM1_CNT);
423 printk(BIOS_SPEW, "SMI#: SLP = 0x%08x\n", reg32);
Aaron Durbin78c68432016-07-13 23:23:54 -0500424 slp_typ = acpi_sleep_from_pm1(reg32);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100425
426 if (smm_get_gnvs()->xhci)
427 xhci_sleep(slp_typ);
428
429 /* Do any mainboard sleep handling */
Aaron Durbin78c68432016-07-13 23:23:54 -0500430 mainboard_smi_sleep(slp_typ);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100431
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600432#if IS_ENABLED(CONFIG_ELOG_GSMI)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100433 /* Log S3, S4, and S5 entry */
Aaron Durbin78c68432016-07-13 23:23:54 -0500434 if (slp_typ >= ACPI_S3)
435 elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100436#endif
437
438 /* Next, do the deed.
439 */
440
441 switch (slp_typ) {
Aaron Durbin78c68432016-07-13 23:23:54 -0500442 case ACPI_S0: printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); break;
443 case ACPI_S1: printk(BIOS_DEBUG, "SMI#: Entering S1 (Assert STPCLK#)\n"); break;
444 case ACPI_S3:
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100445 printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
446
447 /* Gate memory reset */
448 southbridge_gate_memory_reset();
449
450 /* Invalidate the cache before going to S3 */
451 wbinvd();
452 break;
Aaron Durbin78c68432016-07-13 23:23:54 -0500453 case ACPI_S4: printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); break;
454 case ACPI_S5:
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100455 printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
456
457 outl(0, pmbase + GPE0_EN);
458
459 /* Always set the flag in case CMOS was changed on runtime. For
460 * "KEEP", switch to "OFF" - KEEP is software emulated
461 */
462 reg8 = pci_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3);
463 if (s5pwr == MAINBOARD_POWER_ON) {
464 reg8 &= ~1;
465 } else {
466 reg8 |= 1;
467 }
468 pci_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, reg8);
469
470 /* also iterates over all bridges on bus 0 */
471 busmaster_disable_on_bus(0);
472 break;
473 default: printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); break;
474 }
475
476 /* Write back to the SLP register to cause the originally intended
477 * event again. We need to set BIT13 (SLP_EN) though to make the
478 * sleep happen.
479 */
480 outl(reg32 | SLP_EN, pmbase + PM1_CNT);
481
482 /* Make sure to stop executing code here for S3/S4/S5 */
Aaron Durbin78c68432016-07-13 23:23:54 -0500483 if (slp_typ >= ACPI_S3)
Patrick Georgi546953c2014-11-29 10:38:17 +0100484 halt();
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100485
486 /* In most sleep states, the code flow of this function ends at
487 * the line above. However, if we entered sleep state S1 and wake
488 * up again, we will continue to execute code in this function.
489 */
490 reg32 = inl(pmbase + PM1_CNT);
491 if (reg32 & SCI_EN) {
492 /* The OS is not an ACPI OS, so we set the state to S0 */
493 reg32 &= ~(SLP_EN | SLP_TYP);
494 outl(reg32, pmbase + PM1_CNT);
495 }
496}
497
498/*
499 * Look for Synchronous IO SMI and use save state from that
500 * core in case we are not running on the same core that
501 * initiated the IO transaction.
502 */
503static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd)
504{
505 em64t101_smm_state_save_area_t *state;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100506 int node;
507
508 /* Check all nodes looking for the one that issued the IO */
509 for (node = 0; node < CONFIG_MAX_CPUS; node++) {
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200510 state = smm_get_save_state(node);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100511
Elyes HAOUAS581fe582018-04-26 09:57:07 +0200512 /* Check for Synchronous IO (bit0 == 1) */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100513 if (!(state->io_misc_info & (1 << 0)))
514 continue;
515
Elyes HAOUAS581fe582018-04-26 09:57:07 +0200516 /* Make sure it was a write (bit4 == 0) */
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100517 if (state->io_misc_info & (1 << 4))
518 continue;
519
520 /* Check for APMC IO port */
521 if (((state->io_misc_info >> 16) & 0xff) != APM_CNT)
522 continue;
523
524 /* Check AX against the requested command */
525 if ((state->rax & 0xff) != cmd)
526 continue;
527
528 return state;
529 }
530
531 return NULL;
532}
533
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600534#if IS_ENABLED(CONFIG_ELOG_GSMI)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100535static void southbridge_smi_gsmi(void)
536{
537 u32 *ret, *param;
538 u8 sub_command;
539 em64t101_smm_state_save_area_t *io_smi =
Patrick Georgid61839c2018-12-03 16:10:33 +0100540 smi_apmc_find_state_save(APM_CNT_ELOG_GSMI);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100541
542 if (!io_smi)
543 return;
544
545 /* Command and return value in EAX */
546 ret = (u32*)&io_smi->rax;
547 sub_command = (u8)(*ret >> 8);
548
549 /* Parameter buffer in EBX */
550 param = (u32*)&io_smi->rbx;
551
552 /* drivers/elog/gsmi.c */
553 *ret = gsmi_exec(sub_command, param);
554}
555#endif
556
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200557static void southbridge_smi_apmc(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100558{
559 u32 pmctrl;
560 u8 reg8;
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100561 em64t101_smm_state_save_area_t *state;
562
563 /* Emulate B2 register as the FADT / Linux expects it */
564
565 reg8 = inb(APM_CNT);
566 switch (reg8) {
567 case APM_CNT_CST_CONTROL:
568 /* Calling this function seems to cause
569 * some kind of race condition in Linux
570 * and causes a kernel oops
571 */
572 printk(BIOS_DEBUG, "C-state control\n");
573 break;
574 case APM_CNT_PST_CONTROL:
575 /* Calling this function seems to cause
576 * some kind of race condition in Linux
577 * and causes a kernel oops
578 */
579 printk(BIOS_DEBUG, "P-state control\n");
580 break;
581 case APM_CNT_ACPI_DISABLE:
582 pmctrl = inl(pmbase + PM1_CNT);
583 pmctrl &= ~SCI_EN;
584 outl(pmctrl, pmbase + PM1_CNT);
585 printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
586 break;
587 case APM_CNT_ACPI_ENABLE:
588 pmctrl = inl(pmbase + PM1_CNT);
589 pmctrl |= SCI_EN;
590 outl(pmctrl, pmbase + PM1_CNT);
591 printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
592 break;
593 case APM_CNT_GNVS_UPDATE:
594 if (smm_initialized) {
595 printk(BIOS_DEBUG, "SMI#: SMM structures already initialized!\n");
596 return;
597 }
598 state = smi_apmc_find_state_save(reg8);
599 if (state) {
600 /* EBX in the state save contains the GNVS pointer */
601 gnvs = (global_nvs_t *)((u32)state->rbx);
602 smm_initialized = 1;
603 printk(BIOS_DEBUG, "SMI#: Setting GNVS to %p\n", gnvs);
604 }
605 break;
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600606#if IS_ENABLED(CONFIG_ELOG_GSMI)
Patrick Georgid61839c2018-12-03 16:10:33 +0100607 case APM_CNT_ELOG_GSMI:
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100608 southbridge_smi_gsmi();
609 break;
610#endif
611 }
612
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200613 mainboard_smi_apmc(reg8);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100614}
615
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200616static void southbridge_smi_pm1(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100617{
618 u16 pm1_sts;
619
620 pm1_sts = reset_pm1_status();
621 dump_pm1_status(pm1_sts);
622
623 /* While OSPM is not active, poweroff immediately
624 * on a power button event.
625 */
626 if (pm1_sts & PWRBTN_STS) {
627 // power button pressed
628 u32 reg32;
629 reg32 = (7 << 10) | (1 << 13);
Martin Roth7a1a3ad2017-06-24 21:29:38 -0600630#if IS_ENABLED(CONFIG_ELOG_GSMI)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100631 elog_add_event(ELOG_TYPE_POWER_BUTTON);
632#endif
633 outl(reg32, pmbase + PM1_CNT);
634 }
635}
636
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200637static void southbridge_smi_gpe0(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100638{
639 u32 gpe0_sts;
640
641 gpe0_sts = reset_gpe0_status();
642 dump_gpe0_status(gpe0_sts);
643}
644
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200645static void southbridge_smi_gpi(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100646{
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100647 u16 reg16;
648 reg16 = inw(pmbase + ALT_GP_SMI_STS);
649 outw(reg16, pmbase + ALT_GP_SMI_STS);
650
651 reg16 &= inw(pmbase + ALT_GP_SMI_EN);
652
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200653 mainboard_smi_gpi(reg16);
Kyösti Mälkki48b3dbc2014-12-29 19:36:50 +0200654
655 if (reg16)
656 printk(BIOS_DEBUG, "GPI (mask %04x)\n",reg16);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100657
658 outw(reg16, pmbase + ALT_GP_SMI_STS);
659}
660
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200661static void southbridge_smi_mc(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100662{
663 u32 reg32;
664
665 reg32 = inl(pmbase + SMI_EN);
666
667 /* Are periodic SMIs enabled? */
668 if ((reg32 & MCSMI_EN) == 0)
669 return;
670
671 printk(BIOS_DEBUG, "Microcontroller SMI.\n");
672}
673
674
675
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200676static void southbridge_smi_tco(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100677{
678 u32 tco_sts;
679
680 tco_sts = reset_tco_status();
681
682 /* Any TCO event? */
683 if (!tco_sts)
684 return;
685
686 if (tco_sts & (1 << 8)) { // BIOSWR
687 u8 bios_cntl;
688
689 bios_cntl = pci_read_config16(PCI_DEV(0, 0x1f, 0), 0xdc);
690
691 if (bios_cntl & 1) {
692 /* BWE is RW, so the SMI was caused by a
693 * write to BWE, not by a write to the BIOS
694 */
695
696 /* This is the place where we notice someone
697 * is trying to tinker with the BIOS. We are
698 * trying to be nice and just ignore it. A more
699 * resolute answer would be to power down the
700 * box.
701 */
702 printk(BIOS_DEBUG, "Switching back to RO\n");
703 pci_write_config32(PCI_DEV(0, 0x1f, 0), 0xdc, (bios_cntl & ~1));
704 } /* No else for now? */
705 } else if (tco_sts & (1 << 3)) { /* TIMEOUT */
706 /* Handle TCO timeout */
707 printk(BIOS_DEBUG, "TCO Timeout.\n");
Martin Roth3e3b8582017-01-11 10:10:17 -0700708 } else {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100709 dump_tco_status(tco_sts);
710 }
711}
712
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200713static void southbridge_smi_periodic(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100714{
715 u32 reg32;
716
717 reg32 = inl(pmbase + SMI_EN);
718
719 /* Are periodic SMIs enabled? */
720 if ((reg32 & PERIODIC_EN) == 0)
721 return;
722
723 printk(BIOS_DEBUG, "Periodic SMI.\n");
724}
725
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200726static void southbridge_smi_monitor(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100727{
728#define IOTRAP(x) (trap_sts & (1 << x))
729 u32 trap_sts, trap_cycle;
730 u32 data, mask = 0;
731 int i;
732
733 trap_sts = RCBA32(0x1e00); // TRSR - Trap Status Register
734 RCBA32(0x1e00) = trap_sts; // Clear trap(s) in TRSR
735
736 trap_cycle = RCBA32(0x1e10);
737 for (i=16; i<20; i++) {
738 if (trap_cycle & (1 << i))
739 mask |= (0xff << ((i - 16) << 2));
740 }
741
742
743 /* IOTRAP(3) SMI function call */
744 if (IOTRAP(3)) {
745 if (gnvs && gnvs->smif)
746 io_trap_handler(gnvs->smif); // call function smif
747 return;
748 }
749
750 /* IOTRAP(2) currently unused
751 * IOTRAP(1) currently unused */
752
753 /* IOTRAP(0) SMIC */
754 if (IOTRAP(0)) {
755 if (!(trap_cycle & (1 << 24))) { // It's a write
756 printk(BIOS_DEBUG, "SMI1 command\n");
757 data = RCBA32(0x1e18);
758 data &= mask;
759 // if (smi1)
760 // southbridge_smi_command(data);
761 // return;
762 }
763 // Fall through to debug
764 }
765
766 printk(BIOS_DEBUG, " trapped io address = 0x%x\n", trap_cycle & 0xfffc);
Elyes HAOUAS70d79a42016-08-21 18:36:06 +0200767 for (i=0; i < 4; i++) if (IOTRAP(i)) printk(BIOS_DEBUG, " TRAP = %d\n", i);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100768 printk(BIOS_DEBUG, " AHBE = %x\n", (trap_cycle >> 16) & 0xf);
769 printk(BIOS_DEBUG, " MASK = 0x%08x\n", mask);
770 printk(BIOS_DEBUG, " read/write: %s\n", (trap_cycle & (1 << 24)) ? "read" : "write");
771
772 if (!(trap_cycle & (1 << 24))) {
773 /* Write Cycle */
774 data = RCBA32(0x1e18);
775 printk(BIOS_DEBUG, " iotrap written data = 0x%08x\n", data);
776 }
777#undef IOTRAP
778}
779
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200780typedef void (*smi_handler_t)(void);
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100781
782static smi_handler_t southbridge_smi[32] = {
783 NULL, // [0] reserved
784 NULL, // [1] reserved
785 NULL, // [2] BIOS_STS
786 NULL, // [3] LEGACY_USB_STS
787 southbridge_smi_sleep, // [4] SLP_SMI_STS
788 southbridge_smi_apmc, // [5] APM_STS
789 NULL, // [6] SWSMI_TMR_STS
790 NULL, // [7] reserved
791 southbridge_smi_pm1, // [8] PM1_STS
792 southbridge_smi_gpe0, // [9] GPE0_STS
793 southbridge_smi_gpi, // [10] GPI_STS
794 southbridge_smi_mc, // [11] MCSMI_STS
795 NULL, // [12] DEVMON_STS
796 southbridge_smi_tco, // [13] TCO_STS
797 southbridge_smi_periodic, // [14] PERIODIC_STS
798 NULL, // [15] SERIRQ_SMI_STS
799 NULL, // [16] SMBUS_SMI_STS
800 NULL, // [17] LEGACY_USB2_STS
801 NULL, // [18] INTEL_USB2_STS
802 NULL, // [19] reserved
803 NULL, // [20] PCI_EXP_SMI_STS
804 southbridge_smi_monitor, // [21] MONITOR_STS
805 NULL, // [22] reserved
806 NULL, // [23] reserved
807 NULL, // [24] reserved
808 NULL, // [25] EL_SMI_STS
809 NULL, // [26] SPI_STS
810 NULL, // [27] reserved
811 NULL, // [28] reserved
812 NULL, // [29] reserved
813 NULL, // [30] reserved
814 NULL // [31] reserved
815};
816
817/**
818 * @brief Interrupt handler for SMI#
Martin Roth182e551f2014-12-29 22:29:08 -0700819 * @param node
820 * @param state_save
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100821 */
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200822void southbridge_smi_handler(void)
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100823{
824 int i, dump = 0;
825 u32 smi_sts;
826
827 /* Update global variable pmbase */
Patrick Rudolph63952e12018-06-28 14:29:49 +0200828 pmbase = lpc_get_pmbase();
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100829
830 /* We need to clear the SMI status registers, or we won't see what's
831 * happening in the following calls.
832 */
833 smi_sts = reset_smi_status();
834
835 /* Call SMI sub handler for each of the status bits */
836 for (i = 0; i < 31; i++) {
837 if (smi_sts & (1 << i)) {
838 if (southbridge_smi[i]) {
Vladimir Serbinenko456f4952015-05-28 20:42:32 +0200839 southbridge_smi[i]();
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100840 } else {
Martin Roth2ed0aa22016-01-05 20:58:58 -0700841 printk(BIOS_DEBUG, "SMI_STS[%d] occurred, but no "
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100842 "handler available.\n", i);
843 dump = 1;
844 }
845 }
846 }
847
Elyes HAOUASba28e8d2016-08-31 19:22:16 +0200848 if (dump) {
Vladimir Serbinenko888d5592013-11-13 17:53:38 +0100849 dump_smi_status(smi_sts);
850 }
851
852}