#include <cpu/x86/cache.h>
#include <cpu/x86/smm.h>
#include <device/pci_def.h>
+#include <pc80/mc146818rtc.h>
#include "i82801gx.h"
-#define APM_CNT 0xb2
-#define CST_CONTROL 0x85
-#define PST_CONTROL 0x80
-#define ACPI_DISABLE 0x1e
-#define ACPI_ENABLE 0xe1
-#define GNVS_UPDATE 0xea
-#define APM_STS 0xb3
-
/* I945 */
#define SMRAM 0x9d
#define D_OPEN (1 << 6)
u8 reg8;
u32 reg32;
u8 slp_typ;
- /* FIXME: the power state on boot should be read from
- * CMOS or even better from GNVS. Right now it's hard
- * coded at compile time.
- */
u8 s5pwr = CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
+ // save and recover RTC port values
+ u8 tmp70, tmp72;
+ tmp70 = inb(0x70);
+ tmp72 = inb(0x72);
+ get_option(&s5pwr, "power_on_after_fail");
+ outb(tmp70, 0x70);
+ outb(tmp72, 0x72);
+
/* First, disable further SMIs */
reg8 = inb(pmbase + SMI_EN);
reg8 &= ~SLP_SMI_EN;
default: printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); break;
}
+ /* Unlock the SMI semaphore. We're currently in SMM, and the semaphore
+ * will never be unlocked because the next outl will switch off the CPU.
+ * This might open a small race between the smi_release_lock() and the outl()
+ * for other SMI handlers. Not sure if this could cause trouble. */
+ if (slp_typ == 5)
+ smi_release_lock();
+
/* Write back to the SLP register to cause the originally intended
* event again. We need to set BIT13 (SLP_EN) though to make the
* sleep happen.
/* Emulate B2 register as the FADT / Linux expects it */
reg8 = inb(APM_CNT);
+ if (mainboard_apm_cnt && mainboard_apm_cnt(reg8))
+ return;
+
switch (reg8) {
- case CST_CONTROL:
+ case APM_CNT_CST_CONTROL:
/* Calling this function seems to cause
* some kind of race condition in Linux
* and causes a kernel oops
*/
printk(BIOS_DEBUG, "C-state control\n");
break;
- case PST_CONTROL:
+ case APM_CNT_PST_CONTROL:
/* Calling this function seems to cause
* some kind of race condition in Linux
* and causes a kernel oops
*/
printk(BIOS_DEBUG, "P-state control\n");
break;
- case ACPI_DISABLE:
+ case APM_CNT_ACPI_DISABLE:
pmctrl = inl(pmbase + PM1_CNT);
pmctrl &= ~SCI_EN;
outl(pmctrl, pmbase + PM1_CNT);
printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
break;
- case ACPI_ENABLE:
+ case APM_CNT_ACPI_ENABLE:
pmctrl = inl(pmbase + PM1_CNT);
pmctrl |= SCI_EN;
outl(pmctrl, pmbase + PM1_CNT);
printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
break;
- case GNVS_UPDATE:
+ case APM_CNT_GNVS_UPDATE:
if (smm_initialized) {
printk(BIOS_DEBUG, "SMI#: SMM structures already initialized!\n");
return;
static void southbridge_smi_pm1(unsigned int node, smm_state_save_area_t *state_save)
{
u16 pm1_sts;
+ volatile u8 cmos_status;
pm1_sts = reset_pm1_status();
dump_pm1_status(pm1_sts);
reg32 = (7 << 10) | (1 << 13);
outl(reg32, pmbase + PM1_CNT);
}
+
+ if (pm1_sts & RTC_STS) {
+ /* read RTC status register to disable the interrupt */
+ cmos_status = cmos_read(RTC_REG_C);
+ printk(BIOS_DEBUG, "RTC IRQ status: %02X\n", cmos_status);
+ }
}
static void southbridge_smi_gpe0(unsigned int node, smm_state_save_area_t *state_save)