i82801gx: Support power-on-after-power-fail better
[coreboot.git] / src / southbridge / intel / i82801gx / smihandler.c
index 48375e451d63bbcaef1f1054ad2ef94aa0590c38..401c9adcf83493b1f2f4201bf3bdb338d6cf777e 100644 (file)
@@ -279,12 +279,16 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
        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;
@@ -312,16 +316,16 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat
 
                outl(0, pmbase + GPE0_EN);
 
-               /* Should we keep the power state after a power loss?
-                * In case the setting is "ON" or "OFF" we don't have
-                * to do anything. But if it's "KEEP" we have to switch
-                * to "OFF" before entering S5.
+               /* Always set the flag in case CMOS was changed on runtime. For
+                * "KEEP", switch to "OFF" - KEEP is software emulated
                 */
-               if (s5pwr == MAINBOARD_POWER_KEEP) {
-                       reg8 = pcie_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3);
+               reg8 = pcie_read_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3);
+               if (s5pwr == MAINBOARD_POWER_ON) {
+                       reg8 &= ~1;
+               } else {
                        reg8 |= 1;
-                       pcie_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, reg8);
                }
+               pcie_write_config8(PCI_DEV(0, 0x1f, 0), GEN_PMCON_3, reg8);
 
                /* also iterates over all bridges on bus 0 */
                busmaster_disable_on_bus(0);