1 /* SPDX-License-Identifier: GPL-2.0-only */
6 #include <console/console.h>
7 #include <cpu/intel/em64t101_save_state.h>
8 #include <cpu/x86/cache.h>
9 #include <cpu/x86/smm.h>
10 #include <device/mmio.h>
11 #include <device/pci_def.h>
12 #include <device/pci_ops.h>
13 #include <drivers/intel/gma/i915_reg.h>
14 #include <spi-generic.h>
21 #include <soc/pci_devs.h>
27 * @brief Set the EOS bit
29 void southbridge_smi_set_eos(void)
34 static void busmaster_disable_on_bus(int bus
)
40 for (slot
= 0; slot
< 0x20; slot
++) {
41 for (func
= 0; func
< 8; func
++) {
42 pci_devfn_t dev
= PCI_DEV(bus
, slot
, func
);
44 val
= pci_read_config32(dev
, PCI_VENDOR_ID
);
46 if (val
== 0xffffffff || val
== 0x00000000 ||
47 val
== 0x0000ffff || val
== 0xffff0000)
50 /* Disable Bus Mastering for this one device */
51 pci_and_config16(dev
, PCI_COMMAND
, ~PCI_COMMAND_MASTER
);
53 /* If this is a bridge, then follow it. */
54 hdr
= pci_read_config8(dev
, PCI_HEADER_TYPE
);
56 if (hdr
== PCI_HEADER_TYPE_BRIDGE
||
57 hdr
== PCI_HEADER_TYPE_CARDBUS
) {
59 buses
= pci_read_config32(dev
, PCI_PRIMARY_BUS
);
60 busmaster_disable_on_bus((buses
>> 8) & 0xff);
67 * Turn off the backlight if it is on, and wait for the specified
68 * backlight off delay. This will allow panel power timings to meet
69 * spec and prevent brief garbage on the screen when turned off
70 * during firmware with power button triggered SMI.
72 static void backlight_off(void)
76 uint32_t bl_off_delay
;
78 reg_base
= (void *)((uintptr_t)pci_read_config32(SA_DEV_IGD
,
79 PCI_BASE_ADDRESS_0
) & ~0xf);
81 /* Validate pointer before using it */
82 if (smm_points_to_smram(reg_base
, PCH_PP_OFF_DELAYS
+ sizeof(uint32_t)))
85 /* Check if backlight is enabled */
86 pp_ctrl
= read32(reg_base
+ PCH_PP_CONTROL
);
87 if (!(pp_ctrl
& EDP_BLC_ENABLE
))
90 /* Enable writes to this register */
91 pp_ctrl
&= ~PANEL_UNLOCK_MASK
;
92 pp_ctrl
|= PANEL_UNLOCK_REGS
;
94 /* Turn off backlight */
95 pp_ctrl
&= ~EDP_BLC_ENABLE
;
97 write32(reg_base
+ PCH_PP_CONTROL
, pp_ctrl
);
98 read32(reg_base
+ PCH_PP_CONTROL
);
100 /* Read backlight off delay in 100us units */
101 bl_off_delay
= read32(reg_base
+ PCH_PP_OFF_DELAYS
);
102 bl_off_delay
&= PANEL_LIGHT_OFF_DELAY_MASK
;
105 /* Wait for backlight to turn off */
106 udelay(bl_off_delay
);
108 printk(BIOS_INFO
, "Backlight turned off\n");
111 static int power_on_after_fail(void)
113 /* save and recover RTC port values */
117 const unsigned int s5pwr
= get_uint_option("power_on_after_fail",
118 CONFIG_MAINBOARD_POWER_FAILURE_STATE
);
122 /* For "KEEP", switch to "OFF" - KEEP is software emulated. */
123 return (s5pwr
== MAINBOARD_POWER_ON
);
126 static void southbridge_smi_sleep(void)
130 u16 pmbase
= get_pmbase();
132 /* First, disable further SMIs */
133 disable_smi(SLP_SMI_EN
);
135 /* Figure out SLP_TYP */
136 reg32
= inl(pmbase
+ PM1_CNT
);
137 printk(BIOS_SPEW
, "SMI#: SLP = 0x%08x\n", reg32
);
138 slp_typ
= acpi_sleep_from_pm1(reg32
);
140 /* Do any mainboard sleep handling */
141 mainboard_smi_sleep(slp_typ
);
143 /* USB sleep preparations */
144 usb_xhci_sleep_prepare(PCH_DEV_XHCI
, slp_typ
);
146 /* Log S3, S4, and S5 entry */
147 if (slp_typ
>= ACPI_S3
)
148 elog_gsmi_add_event_byte(ELOG_TYPE_ACPI_ENTER
, slp_typ
);
150 /* Clear pending GPE events */
153 /* Next, do the deed.
158 printk(BIOS_DEBUG
, "SMI#: Entering S0 (On)\n");
161 printk(BIOS_DEBUG
, "SMI#: Entering S1 (Assert STPCLK#)\n");
164 printk(BIOS_DEBUG
, "SMI#: Entering S3 (Suspend-To-RAM)\n");
166 /* Invalidate the cache before going to S3 */
170 printk(BIOS_DEBUG
, "SMI#: Entering S4 (Suspend-To-Disk)\n");
173 printk(BIOS_DEBUG
, "SMI#: Entering S5 (Soft Power off)\n");
175 /* Turn off backlight if needed */
178 /* Disable all GPE */
181 /* Always set the flag in case CMOS was changed on runtime. */
182 if (power_on_after_fail())
183 pci_and_config8(PCH_DEV_LPC
, GEN_PMCON_3
, ~1);
185 pci_or_config8(PCH_DEV_LPC
, GEN_PMCON_3
, 1);
187 /* also iterates over all bridges on bus 0 */
188 busmaster_disable_on_bus(0);
191 printk(BIOS_DEBUG
, "SMI#: ERROR: SLP_TYP reserved\n");
196 * Write back to the SLP register to cause the originally intended
197 * event again. We need to set BIT13 (SLP_EN) though to make the
200 enable_pm1_control(SLP_EN
);
202 /* Make sure to stop executing code here for S3/S4/S5 */
203 if (slp_typ
>= ACPI_S3
)
207 * In most sleep states, the code flow of this function ends at
208 * the line above. However, if we entered sleep state S1 and wake
209 * up again, we will continue to execute code in this function.
211 reg32
= inl(pmbase
+ PM1_CNT
);
212 if (reg32
& SCI_EN
) {
213 /* The OS is not an ACPI OS, so we set the state to S0 */
214 disable_pm1_control(SLP_EN
| SLP_TYP
);
219 * Look for Synchronous IO SMI and use save state from that
220 * core in case we are not running on the same core that
221 * initiated the IO transaction.
223 static em64t101_smm_state_save_area_t
*smi_apmc_find_state_save(u8 cmd
)
225 em64t101_smm_state_save_area_t
*state
;
228 /* Check all nodes looking for the one that issued the IO */
229 for (node
= 0; node
< CONFIG_MAX_CPUS
; node
++) {
230 state
= smm_get_save_state(node
);
232 /* Check for Synchronous IO (bit0 == 1) */
233 if (!(state
->io_misc_info
& (1 << 0)))
236 /* Make sure it was a write (bit4 == 0) */
237 if (state
->io_misc_info
& (1 << 4))
240 /* Check for APMC IO port */
241 if (((state
->io_misc_info
>> 16) & 0xff) != APM_CNT
)
244 /* Check AX against the requested command */
245 if ((state
->rax
& 0xff) != cmd
)
254 static void southbridge_smi_gsmi(void)
258 em64t101_smm_state_save_area_t
*io_smi
=
259 smi_apmc_find_state_save(APM_CNT_ELOG_GSMI
);
264 /* Command and return value in EAX */
265 ret
= (u32
*)&io_smi
->rax
;
266 sub_command
= (u8
)(*ret
>> 8);
268 /* Parameter buffer in EBX */
269 param
= (u32
*)&io_smi
->rbx
;
271 /* drivers/elog/gsmi.c */
272 *ret
= gsmi_exec(sub_command
, param
);
275 static void southbridge_smi_store(void)
278 em64t101_smm_state_save_area_t
*io_smi
=
279 smi_apmc_find_state_save(APM_CNT_SMMSTORE
);
284 /* Command and return value in EAX */
285 sub_command
= (io_smi
->rax
>> 8) & 0xff;
287 /* Parameter buffer in EBX */
288 reg_ebx
= io_smi
->rbx
;
290 /* drivers/smmstore/smi.c */
291 ret
= smmstore_exec(sub_command
, (void *)reg_ebx
);
295 static void southbridge_smi_apmc(void)
299 reg8
= apm_get_apmc();
301 case APM_CNT_ACPI_DISABLE
:
302 disable_pm1_control(SCI_EN
);
304 case APM_CNT_ACPI_ENABLE
:
305 enable_pm1_control(SCI_EN
);
307 case APM_CNT_ELOG_GSMI
:
308 if (CONFIG(ELOG_GSMI
))
309 southbridge_smi_gsmi();
311 case APM_CNT_SMMSTORE
:
312 if (CONFIG(SMMSTORE
))
313 southbridge_smi_store();
317 mainboard_smi_apmc(reg8
);
320 static void southbridge_smi_pm1(void)
322 u16 pm1_sts
= clear_pm1_status();
324 /* While OSPM is not active, poweroff immediately
325 * on a power button event.
327 if (pm1_sts
& PWRBTN_STS
) {
328 /* power button pressed */
329 elog_gsmi_add_event(ELOG_TYPE_POWER_BUTTON
);
330 disable_pm1_control(-1UL);
331 enable_pm1_control(SLP_EN
| (SLP_TYP_S5
<< 10));
335 static void southbridge_smi_gpe0(void)
340 static void southbridge_smi_gpi(void)
342 mainboard_smi_gpi(clear_alt_smi_status());
344 /* Clear again after mainboard handler */
345 clear_alt_smi_status();
348 static void southbridge_smi_mc(void)
350 u32 reg32
= inl(get_pmbase() + SMI_EN
);
352 /* Are microcontroller SMIs enabled? */
353 if ((reg32
& MCSMI_EN
) == 0)
356 printk(BIOS_DEBUG
, "Microcontroller SMI.\n");
359 static void southbridge_smi_tco(void)
361 u32 tco_sts
= clear_tco_status();
368 if (tco_sts
& (1 << 8)) {
369 u8 bios_cntl
= pci_read_config16(PCH_DEV_LPC
, BIOS_CNTL
);
373 * BWE is RW, so the SMI was caused by a
374 * write to BWE, not by a write to the BIOS
376 * This is the place where we notice someone
377 * is trying to tinker with the BIOS. We are
378 * trying to be nice and just ignore it. A more
379 * resolute answer would be to power down the
382 printk(BIOS_DEBUG
, "Switching back to RO\n");
383 pci_write_config32(PCH_DEV_LPC
, BIOS_CNTL
, (bios_cntl
& ~1));
384 } /* No else for now? */
385 } else if (tco_sts
& (1 << 3)) { /* TIMEOUT */
386 /* Handle TCO timeout */
387 printk(BIOS_DEBUG
, "TCO Timeout.\n");
391 static void southbridge_smi_periodic(void)
393 u32 reg32
= inl(get_pmbase() + SMI_EN
);
395 /* Are periodic SMIs enabled? */
396 if ((reg32
& PERIODIC_EN
) == 0)
399 printk(BIOS_DEBUG
, "Periodic SMI.\n");
402 static void southbridge_smi_monitor(void)
404 #define IOTRAP(x) (trap_sts & (1 << x))
405 u32 trap_sts
, trap_cycle
;
409 trap_sts
= RCBA32(0x1e00); // TRSR - Trap Status Register
410 RCBA32(0x1e00) = trap_sts
; // Clear trap(s) in TRSR
412 trap_cycle
= RCBA32(0x1e10);
413 for (i
= 16; i
< 20; i
++) {
414 if (trap_cycle
& (1 << i
))
415 mask
|= (0xff << ((i
- 16) << 3));
418 /* IOTRAP(3) SMI function call */
420 if (gnvs
&& gnvs
->smif
)
421 io_trap_handler(gnvs
->smif
); // call function smif
425 /* IOTRAP(2) currently unused
426 * IOTRAP(1) currently unused */
431 if (!(trap_cycle
& (1 << 24))) {
432 printk(BIOS_DEBUG
, "SMI1 command\n");
433 (void)RCBA32(0x1e18);
434 // data = RCBA32(0x1e18);
437 // southbridge_smi_command(data);
440 // Fall through to debug
443 printk(BIOS_DEBUG
, " trapped io address = 0x%x\n",
444 trap_cycle
& 0xfffc);
445 for (i
= 0; i
< 4; i
++)
447 printk(BIOS_DEBUG
, " TRAP = %d\n", i
);
448 printk(BIOS_DEBUG
, " AHBE = %x\n", (trap_cycle
>> 16) & 0xf);
449 printk(BIOS_DEBUG
, " MASK = 0x%08x\n", mask
);
450 printk(BIOS_DEBUG
, " read/write: %s\n",
451 (trap_cycle
& (1 << 24)) ? "read" : "write");
453 if (!(trap_cycle
& (1 << 24))) {
455 printk(BIOS_DEBUG
, " iotrap written data = 0x%08x\n", RCBA32(0x1e18));
460 typedef void (*smi_handler_t
)(void);
462 static smi_handler_t southbridge_smi
[32] = {
463 NULL
, // [0] reserved
464 NULL
, // [1] reserved
465 NULL
, // [2] BIOS_STS
466 NULL
, // [3] LEGACY_USB_STS
467 southbridge_smi_sleep
, // [4] SLP_SMI_STS
468 southbridge_smi_apmc
, // [5] APM_STS
469 NULL
, // [6] SWSMI_TMR_STS
470 NULL
, // [7] reserved
471 southbridge_smi_pm1
, // [8] PM1_STS
472 southbridge_smi_gpe0
, // [9] GPE0_STS
473 southbridge_smi_gpi
, // [10] GPI_STS
474 southbridge_smi_mc
, // [11] MCSMI_STS
475 NULL
, // [12] DEVMON_STS
476 southbridge_smi_tco
, // [13] TCO_STS
477 southbridge_smi_periodic
, // [14] PERIODIC_STS
478 NULL
, // [15] SERIRQ_SMI_STS
479 NULL
, // [16] SMBUS_SMI_STS
480 NULL
, // [17] LEGACY_USB2_STS
481 NULL
, // [18] INTEL_USB2_STS
482 NULL
, // [19] reserved
483 NULL
, // [20] PCI_EXP_SMI_STS
484 southbridge_smi_monitor
, // [21] MONITOR_STS
485 NULL
, // [22] reserved
486 NULL
, // [23] reserved
487 NULL
, // [24] reserved
488 NULL
, // [25] EL_SMI_STS
489 NULL
, // [26] SPI_STS
490 NULL
, // [27] reserved
491 NULL
, // [28] reserved
492 NULL
, // [29] reserved
493 NULL
, // [30] reserved
494 NULL
// [31] reserved
498 * @brief Interrupt handler for SMI#
500 void southbridge_smi_handler(void)
505 /* We need to clear the SMI status registers, or we won't see what's
506 * happening in the following calls.
508 smi_sts
= clear_smi_status();
510 /* Call SMI sub handler for each of the status bits */
511 for (i
= 0; i
< 31; i
++) {
512 if (smi_sts
& (1 << i
)) {
513 if (southbridge_smi
[i
]) {
514 southbridge_smi
[i
]();
517 "SMI_STS[%d] occurred, but no "
518 "handler available.\n", i
);