The Geode companion chip, part of which attaches as glxpcib(4), can be
configured to restart automatically after a power failure, when power is
restored.

The following diff enables this functionality. Tested on a Lemote
Fuloong (where it works) and on a Lemote Yeeloong (where this feature is
disabled in hardware) only. Tests on x86 systems based upon the Geode,
such as the Soekris 5501 or the ALIX boards, would be appreciated.

Running a kernel with this diff, if you `shutdown -h now', remove the
power plug, and plug it back, your system should restart immediately,
unless some other part of the hardware forces this feature to be
disabled (e.g. on laptops such as the Lemote Yeeloong).

Note that this feature might have already been enabled by the BIOS on
the Soekrisens or the ALIXes, but this was definitely not the case on
Fuloongs.

Regardless of your kind system, this diff should not break anything. If
it does, please let me know.

Miod

Index: glxpcib.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/glxpcib.c,v
retrieving revision 1.9
diff -u -p -r1.9 glxpcib.c
--- glxpcib.c   16 Jan 2013 07:17:59 -0000      1.9
+++ glxpcib.c   12 Mar 2013 21:30:28 -0000
@@ -166,6 +166,15 @@
 #define AMD5536_SMB_CTL2_FREQ  0x78 /* 100 kHz */
 #define AMD5536_SMB_CTL3       0x06 /* control 3 */
 
+/* PMS */
+#define        MSR_LBAR_PMS            DIVIL_LBAR_PMS
+#define        MSR_PMS_SIZE            0x80
+#define        MSR_PMS_ADDR_MASK       0xff80
+#define        AMD5536_PMS_SSC         0x54
+#define        AMD5536_PMS_SSC_PI      0x00040000
+#define        AMD5536_PMS_SSC_CLR_PI  0x00020000
+#define        AMD5536_PMS_SSC_SET_PI  0x00010000
+
 /*
  * MSR registers we want to preserve accross suspend/resume
  */
@@ -275,6 +284,7 @@ glxpcib_attach(struct device *parent, st
        u_int64_t sa;
        struct i2cbus_attach_args iba;
        int i2c = 0;
+       bus_space_handle_t tmpioh;
 #endif
        tc->tc_get_timecount = glxpcib_get_timecount;
        tc->tc_counter_mask = 0xffffffff;
@@ -383,6 +393,18 @@ glxpcib_attach(struct device *parent, st
                iba.iba_name = "iic";
                iba.iba_tag = &sc->sc_smb_ic;
                i2c = 1;
+       }
+
+       /* Map PMS I/O space and enable the ``Power Immediate'' feature */
+       sa = rdmsr(MSR_LBAR_PMS);
+       if (sa & MSR_LBAR_ENABLE &&
+           !bus_space_map(pa->pa_iot, sa & MSR_PMS_ADDR_MASK,
+           MSR_PMS_SIZE, 0, &tmpioh)) {
+               bus_space_write_4(pa->pa_iot, tmpioh, AMD5536_PMS_SSC,
+                   AMD5536_PMS_SSC_SET_PI);
+               bus_space_barrier(pa->pa_iot, tmpioh, AMD5536_PMS_SSC, 4,
+                   BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+               bus_space_unmap(pa->pa_iot, tmpioh, MSR_PMS_SIZE);
        }
 #endif /* SMALL_KERNEL */
        pcibattach(parent, self, aux);

Reply via email to