mainboard/asus/kgpe-d16: Add initial Suspend to RAM (S3) support

Change-Id: I7da84b064287a445fd75a947e2f96ce1ae30d3de
Signed-off-by: Timothy Pearson <tpearson@raptorengineeringinc.com>
Reviewed-on: http://review.coreboot.org/11954
Tested-by: Raptor Engineering Automated Test Stand <noreply@raptorengineeringinc.com>
Reviewed-by: Martin Roth <martinroth@google.com>
Tested-by: build bot (Jenkins)
This commit is contained in:
Timothy Pearson 2015-05-07 01:32:08 -05:00 committed by Ronald G. Minnich
parent 160ad6aa75
commit babb2e67bc
5 changed files with 376 additions and 335 deletions

View File

@ -23,6 +23,9 @@ config BOARD_SPECIFIC_OPTIONS # dummy
select BOARD_ROMSIZE_KB_2048
select ENABLE_APIC_EXT_ID
select MMCONF_SUPPORT_DEFAULT
select SPI_FLASH
select SPI_FLASH_WINBOND
select HAVE_ACPI_RESUME
select DRIVERS_I2C_W83795
select DRIVERS_ASPEED_AST2050
select MAINBOARD_HAS_NATIVE_VGA_INIT_TEXTMODECFG

View File

@ -14,350 +14,359 @@
* GNU General Public License for more details.
*/
/* Port 80 POST card debug */
OperationRegion (DBG0, SystemIO, 0x80, One)
Field (DBG0, ByteAcc, NoLock, Preserve) {
DBG8, 8
}
/* SuperIO control port */
Name (SPIO, 0x2E)
/* SuperIO control map */
OperationRegion (SPIM, SystemIO, SPIO, 0x02)
Field (SPIM, ByteAcc, NoLock, Preserve) {
INDX, 8,
DATA, 8
}
/* SuperIO control registers */
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
Offset (0x07),
CR07, 8, /* Logical device number */
Offset (0x2C),
CR2C, 8, /* GPIO3 multiplexed pin selection */
Offset (0x30),
CR30, 8, /* Logical device activation control register */
Offset (0xE0),
CRE0, 8, /* Wake control register */
Offset (0xE4),
CRE4, 8, /* Standby power control register */
Offset (0xE6),
CRE6, 8, /* Mouse wake event configuration register */
Offset (0xF1),
CRF1, 8, /* GPIO3 data register */
Offset (0xF3),
CRF3, 8, /* SUSLED mode register */
Offset (0xF6),
CRF6, 8, /* SMI/PME event generation control register */
Offset (0xF9),
CRF9, 8, /* ACPI PME configuration register */
}
/* Power Management I/O registers */
OperationRegion(PIOR, SystemIO, 0x00000CD6, 0x00000002)
Field(PIOR, ByteAcc, NoLock, Preserve) {
PIOI, 0x00000008,
PIOD, 0x00000008,
}
IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) {
Offset(0x00), /* MiscControl */
, 1,
T1EE, 1,
T2EE, 1,
Offset(0x01), /* MiscStatus */
, 1,
T1E, 1,
T2E, 1,
Offset(0x04), /* SmiWakeUpEventEnable3 */
, 7,
SSEN, 1,
Offset(0x07), /* SmiWakeUpEventStatus3 */
, 7,
CSSM, 1,
Offset(0x10), /* AcpiEnable */
, 6,
PWDE, 1,
Offset(0x1C), /* ProgramIoEnable */
, 3,
MKME, 1,
IO3E, 1,
IO2E, 1,
IO1E, 1,
IO0E, 1,
Offset(0x1D), /* IOMonitorStatus */
, 3,
MKMS, 1,
IO3S, 1,
IO2S, 1,
IO1S, 1,
IO0S,1,
Offset(0x20), /* AcpiPmEvtBlk */
APEB, 16,
Offset(0x36), /* GEvtLevelConfig */
, 6,
ELC6, 1,
ELC7, 1,
Offset(0x37), /* GPMLevelConfig0 */
, 3,
PLC0, 1,
PLC1, 1,
PLC2, 1,
PLC3, 1,
PLC8, 1,
Offset(0x38), /* GPMLevelConfig1 */
, 1,
PLC4, 1,
PLC5, 1,
, 1,
PLC6, 1,
PLC7, 1,
Offset(0x3B), /* PMEStatus1 */
GP0S, 1,
GM4S, 1,
GM5S, 1,
APS, 1,
GM6S, 1,
GM7S, 1,
GP2S, 1,
STSS, 1,
Offset(0x55), /* SoftPciRst */
SPRE, 1,
, 1,
, 1,
PNAT, 1,
PWMK, 1,
PWNS, 1,
/* Offset(0x61), */ /* Options_1 */
/* ,7, */
/* R617,1, */
Offset(0x65), /* UsbPMControl */
, 4,
URRE, 1,
, 2,
BCDL, 1,
Offset(0x68), /* MiscEnable68 */
, 2,
MAPC, 1,
TMTE, 1,
, 1,
Offset(0x7C), /* MiscEnable7C */
, 2,
BLNK, 2,
Offset(0x92), /* GEVENTIN */
, 7,
E7IS, 1,
Offset(0x96), /* GPM98IN */
G8IS, 1,
G9IS, 1,
Offset(0x9A), /* EnhanceControl */
,7,
HPDE, 1,
Offset(0xA8), /* PIO7654Enable */
IO4E, 1,
IO5E, 1,
IO6E, 1,
IO7E, 1,
Offset(0xA9), /* PIO7654Status */
IO4S, 1,
IO5S, 1,
IO6S, 1,
IO7S, 1,
}
/* PM1 Event Block
* First word is PM1_Status, Second word is PM1_Enable
*/
OperationRegion(P1EB, SystemIO, APEB, 0x04)
Field(P1EB, ByteAcc, NoLock, Preserve) {
TMST, 1,
, 3,
BMST, 1,
GBST, 1,
Offset(0x01),
PBST, 1,
, 1,
RTST, 1,
, 3,
PWST, 1,
SPWS, 1,
Offset(0x02),
TMEN, 1,
, 4,
GBEN, 1,
Offset(0x03),
PBEN, 1,
, 1,
RTEN, 1,
, 3,
PWDA, 1,
}
/* Wake status package */
Name(WKST,Package() {Zero, Zero})
/*
* WARNING: Sleep/Wake is a work in progress and is still somewhat flaky!
* \_WAK System Wake method
*
* Entry:
* Arg0=The value of the sleeping state S1=1, S2=2
*
* Exit:
* Return package of 2 DWords
* Dword 1 - Status
* 0x00000000 wake succeeded
* 0x00000001 Wake was signaled but failed due to lack of power
* 0x00000002 Wake was signaled but failed due to thermal condition
* Dword 2 - Power Supply state
* if non-zero the effective S-state the power supply entered
*/
Method(\_WAK, 1) {
Store (0x20, DBG8)
/* Port 80 POST card debug */
OperationRegion (DBG0, SystemIO, 0x80, One)
Field (DBG0, ByteAcc, NoLock, Preserve) {
DBG8, 8
/* Set up LEDs */
/* Set power LED to steady on */
Store(0x3, BLNK)
/* Configure SuperIO for wake */
/* Access SuperIO ACPI device */
Store(0x87, INDX)
Store(0x87, INDX)
Store(0x0A, CR07)
if (LEqual(Arg0, One)) /* Resuming from power state S1 */
{
/* Deactivate the ACPI device */
Store(Zero, CR30)
/* Disable PS/2 SMI/PME events */
And(CRF6, 0xCF, CRF6)
}
if (Lor(LEqual(Arg0, 0x03), LEqual(Arg0, 0x04))) /* Resuming from power state S3 or S4 */
{
/* Disable PS/2 wake */
And(CRE0, 0x1D, CRE0)
And(CRE6, 0x7F, CRE6)
}
/* SuperIO control port */
Name (SPIO, 0x2E)
/* Restore default SuperIO access */
Store(0xAA, INDX)
/* SuperIO control map */
OperationRegion (SPIM, SystemIO, SPIO, 0x02)
Field (SPIM, ByteAcc, NoLock, Preserve) {
INDX, 8,
DATA, 8
Store (0x21, DBG8)
/* Re-enable HPET */
Store(1, HPDE)
/* Restore PCIRST# so it resets USB */
if (LEqual(Arg0, 3)){
Store(1, URRE)
}
/* SuperIO control registers */
IndexField (INDX, DATA, ByteAcc, NoLock, Preserve) {
Offset (0x07),
CR07, 8, /* Logical device number */
Offset (0x2C),
CR2C, 8, /* GPIO3 multiplexed pin selection */
Offset (0x30),
CR30, 8, /* Logical device activation control register */
Offset (0xE0),
CRE0, 8, /* Wake control register */
Offset (0xE6),
CRE6, 8, /* Mouse wake event configuration register */
Offset (0xF1),
CRF1, 8, /* GPIO3 data register */
Offset (0xF3),
CRF3, 8, /* SUSLED mode register */
Offset (0xF6),
CRF6, 8, /* SMI/PME event generation control register */
Offset (0xF9),
CRF9, 8, /* ACPI PME configuration register */
/* Configure southbridge for wake */
/* Arbitrarily clear PciExpWakeStatus */
Store(PWST, PWST)
Store (0x22, DBG8)
Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */
Return(WKST)
}
/*
* \_PTS - Prepare to Sleep method
*
* Entry:
* Arg0=The value of the sleeping state S1=1, S2=2, etc
*
* Exit:
* -none-
*
* The _PTS control method is executed at the beginning of the sleep process
* for S1-S5. The sleeping value is passed to the _PTS control method. This
* control method may be executed a relatively long time before entering the
* sleep state and the OS may abort the operation without notification to
* the ACPI driver. This method cannot modify the configuration or power
* state of any device in the system.
*/
Method(\_PTS, 1) {
Store (Arg0, DBG8)
/* Set up LEDs */
if (LEqual(Arg0, One)) /* Power state S1 requested */
{
/* Set suspend LED to 0.25Hz toggle pulse with 50% duty cycle */
Store(0x2, BLNK)
}
if (LEqual(Arg0, 0x3)) /* Power state S3 requested */
{
/* Set suspend LED to 0.25Hz toggle pulse with 25% duty cycle */
Store(0x1, BLNK)
}
/* Power Management I/O registers */
OperationRegion(PIOR, SystemIO, 0x00000CD6, 0x00000002)
Field(PIOR, ByteAcc, NoLock, Preserve) {
PIOI, 0x00000008,
PIOD, 0x00000008,
}
IndexField (PIOI, PIOD, ByteAcc, NoLock, Preserve) {
Offset(0x00), /* MiscControl */
, 1,
T1EE, 1,
T2EE, 1,
Offset(0x01), /* MiscStatus */
, 1,
T1E, 1,
T2E, 1,
Offset(0x04), /* SmiWakeUpEventEnable3 */
, 7,
SSEN, 1,
Offset(0x07), /* SmiWakeUpEventStatus3 */
, 7,
CSSM, 1,
Offset(0x10), /* AcpiEnable */
, 6,
PWDE, 1,
Offset(0x1C), /* ProgramIoEnable */
, 3,
MKME, 1,
IO3E, 1,
IO2E, 1,
IO1E, 1,
IO0E, 1,
Offset(0x1D), /* IOMonitorStatus */
, 3,
MKMS, 1,
IO3S, 1,
IO2S, 1,
IO1S, 1,
IO0S,1,
Offset(0x20), /* AcpiPmEvtBlk */
APEB, 16,
Offset(0x36), /* GEvtLevelConfig */
, 6,
ELC6, 1,
ELC7, 1,
Offset(0x37), /* GPMLevelConfig0 */
, 3,
PLC0, 1,
PLC1, 1,
PLC2, 1,
PLC3, 1,
PLC8, 1,
Offset(0x38), /* GPMLevelConfig1 */
, 1,
PLC4, 1,
PLC5, 1,
, 1,
PLC6, 1,
PLC7, 1,
Offset(0x3B), /* PMEStatus1 */
GP0S, 1,
GM4S, 1,
GM5S, 1,
APS, 1,
GM6S, 1,
GM7S, 1,
GP2S, 1,
STSS, 1,
Offset(0x55), /* SoftPciRst */
SPRE, 1,
, 1,
, 1,
PNAT, 1,
PWMK, 1,
PWNS, 1,
/* Configure SuperIO for sleep */
/* Access SuperIO ACPI device */
Store(0x87, INDX)
Store(0x87, INDX)
Store(0x0A, CR07)
/* Offset(0x61), */ /* Options_1 */
/* ,7, */
/* R617,1, */
/* Disable PS/2 wakeup and connect PANSW_IN to PANSW_OUT */
And(CRE0, 0x1F, CRE0)
Offset(0x65), /* UsbPMControl */
, 4,
URRE, 1,
Offset(0x68), /* MiscEnable68 */
, 3,
TMTE, 1,
, 1,
Offset(0x7C), /* MiscEnable7C */
, 2,
BLNK, 2,
Offset(0x92), /* GEVENTIN */
, 7,
E7IS, 1,
Offset(0x96), /* GPM98IN */
G8IS, 1,
G9IS, 1,
Offset(0x9A), /* EnhanceControl */
,7,
HPDE, 1,
Offset(0xA8), /* PIO7654Enable */
IO4E, 1,
IO5E, 1,
IO6E, 1,
IO7E, 1,
Offset(0xA9), /* PIO7654Status */
IO4S, 1,
IO5S, 1,
IO6S, 1,
IO7S, 1,
}
if (LEqual(Arg0, One)) /* Power state S1 requested */
{
/* Activate the ACPI device */
Store(One, CR30)
/* PM1 Event Block
* First word is PM1_Status, Second word is PM1_Enable
*/
OperationRegion(P1EB, SystemIO, APEB, 0x04)
Field(P1EB, ByteAcc, NoLock, Preserve) {
TMST, 1,
, 3,
BMST, 1,
GBST, 1,
Offset(0x01),
PBST, 1,
, 1,
RTST, 1,
, 3,
PWST, 1,
SPWS, 1,
Offset(0x02),
TMEN, 1,
, 4,
GBEN, 1,
Offset(0x03),
PBEN, 1,
, 1,
RTEN, 1,
, 3,
PWDA, 1,
}
/* Disable SMI/PME events for:
* LPT
* FDC
* UART
*/
Store(0x00, CRF6)
/* Wake status package */
Name(WKST,Package(){Zero, Zero})
/* Enable PS/2 keyboard SMI/PME events */
Or(CRF6, 0x10, CRF6)
/*
* \_WAK System Wake method
*
* Entry:
* Arg0=The value of the sleeping state S1=1, S2=2
*
* Exit:
* Return package of 2 DWords
* Dword 1 - Status
* 0x00000000 wake succeeded
* 0x00000001 Wake was signaled but failed due to lack of power
* 0x00000002 Wake was signaled but failed due to thermal condition
* Dword 2 - Power Supply state
* if non-zero the effective S-state the power supply entered
*/
Method(\_WAK, 1) {
Store (0x20, DBG8)
/* Enable PS/2 keyboard wake */
Or(CRE0, 0x40, CRE0)
/* Set up LEDs */
/* Set power LED to steady on */
Store(0x3, BLNK)
/* Enable PS/2 mouse SMI/PME events */
Or(CRF6, 0x20, CRF6)
/* Configure SuperIO for wake */
/* Access SuperIO ACPI device */
Store(0x87, INDX)
Store(0x87, INDX)
Store(0x0A, CR07)
/* Enable PS/2 mouse wake */
Or(CRE0, 0x20, CRE0)
} else {
/* Enable PS/2 keyboard wake on any keypress */
Or(CRE0, 0x41, CRE0)
if (LEqual(Arg0, One)) /* Resuming from power state S1 */
/* Enable PS/2 mouse wake on any click */
Or(CRE0, 0x22, CRE0)
Or(CRE6, 0x80, CRE6)
if (LEqual(Arg0, 0x03)) /* Power state S3 requested */
{
/* Deactivate the ACPI device */
Store(Zero, CR30)
/* Disable PS/2 SMI/PME events */
And(CRF6, 0xCF, CRF6)
/* Set VSBGATE# to provide standby power during S3 */
Or(CRE4, 0x10, CRE4)
}
if (Lor(LEqual(Arg0, 0x03), LEqual(Arg0, 0x04))) /* Resuming from power state S3 or S4 */
{
/* Disable PS/2 wake */
And(CRE0, 0x1D, CRE0)
And(CRE6, 0x7F, CRE6)
}
/* Restore default SuperIO access */
Store(0xAA, INDX)
Store (0x21, DBG8)
/* Re-enable HPET */
Store(1, HPDE)
/* Restore PCIRST# so it resets USB */
if (LEqual(Arg0, 3)){
Store(1, URRE)
}
/* Configure southbridge for wake */
/* Arbitrarily clear PciExpWakeStatus */
Store(PWST, PWST)
Store (0x22, DBG8)
Notify(\_SB.PWRB, 0x02) /* NOTIFY_DEVICE_WAKE */
Return(WKST)
}
/*
* \_PTS - Prepare to Sleep method
*
* Entry:
* Arg0=The value of the sleeping state S1=1, S2=2, etc
*
* Exit:
* -none-
*
* The _PTS control method is executed at the beginning of the sleep process
* for S1-S5. The sleeping value is passed to the _PTS control method. This
* control method may be executed a relatively long time before entering the
* sleep state and the OS may abort the operation without notification to
* the ACPI driver. This method cannot modify the configuration or power
* state of any device in the system.
*/
Method(\_PTS, 1) {
Store (Arg0, DBG8)
/* Restore default SuperIO access */
Store(0xAA, INDX)
/* Set up LEDs */
if (LEqual(Arg0, One)) /* Power state S1 requested */
{
/* Set suspend LED to 0.25Hz toggle pulse with 50% duty cycle */
Store(0x2, BLNK)
}
if (LEqual(Arg0, 0x3)) /* Power state S3 requested */
{
/* Set suspend LED to 0.25Hz toggle pulse with 25% duty cycle */
Store(0x1, BLNK)
}
Store (0x10, DBG8)
/* Configure SuperIO for sleep */
/* Access SuperIO ACPI device */
Store(0x87, INDX)
Store(0x87, INDX)
Store(0x0A, CR07)
/* Disable PS/2 wakeup and connect PANSW_IN to PANSW_OUT */
And(CRE0, 0x1F, CRE0)
if (LEqual(Arg0, One)) /* Power state S1 requested */
{
/* Activate the ACPI device */
Store(One, CR30)
/* Disable SMI/PME events for:
* LPT
* FDC
* UART
Store(0x00, CRF6)
/* Enable PS/2 keyboard SMI/PME events */
Or(CRF6, 0x10, CRF6)
/* Enable PS/2 keyboard wake */
Or(CRE0, 0x40, CRE0)
/* Enable PS/2 mouse SMI/PME events */
Or(CRF6, 0x20, CRF6)
/* Enable PS/2 mouse wake */
Or(CRE0, 0x20, CRE0)
} else {
/* Enable PS/2 keyboard wake on any keypress */
Or(CRE0, 0x41, CRE0)
/* Enable PS/2 mouse wake on any click */
Or(CRE0, 0x22, CRE0)
Or(CRE6, 0x80, CRE6)
}
/* Restore default SuperIO access */
Store(0xAA, INDX)
Store (0x10, DBG8)
/* Don't allow PCIRST# to reset USB */
if (LEqual(Arg0, 3)){
Store(0, URRE)
}
/* Configure southbridge for sleep */
/* Clear sleep SMI status flag and enable sleep SMI trap. */
// Store(One, CSSM) /* Set ExtEvent0 as SMI# source */
// Store(One, SSEN) /* Enable wake on external event 0 */
/* On older chips, clear PciExpWakeDisEn */
// if (LLessEqual(SBRI, 0x13)) {
// Store(0, PWDE)
// }
Store (0x11, DBG8)
/* Clear wake status structure. */
Store(0, Index(WKST,0))
Store(0, Index(WKST,1))
/* Don't allow PCIRST# to reset USB */
if (LEqual(Arg0, 3)){
Store(0, URRE)
}
/* Configure southbridge for sleep */
/* Use bus clock for delay timebase */
Store(0, BCDL)
/* Defer APIC interrupts until first ACPI access */
Store(One, MAPC)
/* On older chips, clear PciExpWakeDisEn */
// if (LLessEqual(SBRI, 0x13)) {
// Store(0, PWDE)
// }
Store (0x11, DBG8)
/* Clear wake status structure. */
Store(0, Index(WKST,0))
Store(0, Index(WKST,1))
}

View File

@ -54,9 +54,8 @@ DefinitionBlock (
/* Define power states */
Name (\_S0, Package () { 0x00, 0x00, 0x00, 0x00 }) /* Normal operation */
Name (\_S1, Package () { 0x01, 0x01, 0x00, 0x00 }) /* Standby */
Name (\_S2, Package () { 0x02, 0x02, 0x00, 0x00 }) /* Standby w/ CPU shutdown */
Name (\_S3, Package () { 0x03, 0x00, 0x00, 0x00 }) /* Suspend */
/* Name (\_S4, Package () { 0x04, 0x04, 0x00, 0x00 }) */
Name (\_S3, Package () { 0x03, 0x03, 0x00, 0x00 }) /* Suspend to RAM */
Name (\_S4, Package () { 0x04, 0x04, 0x00, 0x00 }) /* Suspend to disk */
Name (\_S5, Package () { 0x05, 0x05, 0x00, 0x00 }) /* Hard power off */
/* The _PIC method is called by the OS to choose between interrupt

View File

@ -220,12 +220,15 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
{
struct sys_info *sysinfo = &sysinfo_car;
u32 bsp_apicid = 0, val;
uint32_t bsp_apicid = 0, val;
uint8_t byte;
msr_t msr;
timestamp_init(timestamp_get());
timestamp_add_now(TS_START_ROMSTAGE);
int s3resume = acpi_is_wakeup_s3();
if (!cpu_init_detectedx && boot_cpu()) {
/* Nothing special needs to be done to find bus 0 */
/* Allow the HT devices to be found */
@ -243,6 +246,11 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
/* Initialize early serial */
nuvoton_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
console_init();
/* Disable LPC legacy DMA support to prevent lockup */
byte = pci_read_config8(PCI_DEV(0, 0x14, 3), 0x78);
byte &= ~(1 << 0);
pci_write_config8(PCI_DEV(0, 0x14, 3), 0x78, byte);
}
post_code(0x30);
@ -281,14 +289,6 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
amd_ht_fixup(sysinfo);
post_code(0x35);
/* Set DDR memory voltage
* FIXME
* This should be set based on the output of the DIMM SPDs
* For now it is locked to 1.5V
*/
set_ddr3_voltage(0, 0); /* Node 0 */
set_ddr3_voltage(1, 0); /* Node 1 */
/* Setup nodes PCI space and start core 0 AP init. */
finalize_node_setup(sysinfo);
@ -351,6 +351,17 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
die("After soft_reset_x - shouldn't see this message!!!\n");
}
/* Set DDR memory voltage
* FIXME
* This should be set based on the output of the DIMM SPDs
* For now it is locked to 1.5V
*/
set_lpc_sticky_ctl(1); /* Retain LPC/IMC GPIO configuration during S3 sleep */
if (!s3resume) { /* Avoid supply voltage glitches while the DIMMs are retaining data */
set_ddr3_voltage(0, 0); /* Node 0 */
set_ddr3_voltage(1, 0); /* Node 1 */
}
/* Set up peripheral control lines */
set_peripheral_control_lines();
@ -380,7 +391,10 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx)
timestamp_add_now(TS_AFTER_INITRAM);
#if !IS_ENABLED(CONFIG_LATE_CBMEM_INIT)
cbmem_initialize_empty();
if (s3resume)
cbmem_initialize();
else
cbmem_initialize_empty();
post_code(0x41);
amdmct_cbmem_store_info(sysinfo);

View File

@ -28,3 +28,19 @@ Other hardware
RECOVERY1 middle pin is connected to southbridge (AMD SP5100) GPIO 61
Normal is HIGH, recovery is LOW.
+12VSB is generated using a charge pump attached to pin 7 of PU24 (APW7145).
The +12VSB standby voltage to each bank of DIMMs is switched by a bank of small FETs located close to each RAM power regulator control chip.
The +12V primary voltage (lower left pin of the FET placed on the upper left of the control chip of the second node) is also connected to the 232GE located near the PCI slot.
The control line running to the gates of the +12VSB control FETs is connected to the +5VSB power for the USB ports.
That line in turn is connected to +5VSB via the lone P06P03G PMOS transistor on the reverse side of the board, near the center on the lower half.
The gate of that transistor is connected via a resistor to the source of the P06P03G PMOS transistor located adjacent to the unpopulated SMA clock header.
The gate of that transistor is connected directly to the drain of the small FET directly below it.
After that, there's a cascade of small FETs and resistors in that region, eventually leading to SuperIO pin 81.
SuperIO pin 81 (VSBGATE#) enables the standby voltage rails when set LOW.
VSBGATE# is reset on every assertion of PWRGOOD.
Setting SuperIO LDN 9 CRF4 bits 1 or 0 (or both) to 0 disables NICB.