soc/intel/apollolake: Add PM methods to power gate PCIe
This implements GNVS variable to store the address of PERST_0, _ON/_OFF methods to power gate PCIe during S0ix entry, and PERST_0 assertion/de-assertion methods. BUG=chrome-os-partner:55877 TEST=Suspend and resume using 'echo freeze > /sys/power/state'. System should resume with PCIE and wifi functional. Change-Id: I9f63ca0b8a6565b6d21deaa6d3dfa34678714c19 Signed-off-by: Vaibhav Shankar <vaibhav.shankar@intel.com> Reviewed-on: https://review.coreboot.org/16351 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin <adurbin@chromium.org> Reviewed-by: Duncan Laurie <dlaurie@chromium.org> Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
This commit is contained in:
parent
9e81540b85
commit
ef8deaffcb
|
@ -29,6 +29,7 @@
|
|||
#include <soc/nvs.h>
|
||||
#include <soc/pci_devs.h>
|
||||
#include <string.h>
|
||||
#include <soc/gpio.h>
|
||||
#include "chip.h"
|
||||
|
||||
#define CSTATE_RES(address_space, width, offset, address) \
|
||||
|
@ -175,6 +176,10 @@ static void acpi_create_gnvs(struct global_nvs_t *gnvs)
|
|||
|
||||
/* Enable DPTF based on mainboard configuration */
|
||||
gnvs->dpte = cfg->dptf_enable;
|
||||
|
||||
/* Assign address of PERST_0 if GPIO is defined in devicetree */
|
||||
if (cfg->prt0_gpio != GPIO_PRT0_UDEF)
|
||||
gnvs->prt0 = (uintptr_t)gpio_dwx_address(cfg->prt0_gpio);
|
||||
}
|
||||
|
||||
/* Save wake source information for calculating ACPI _SWS values */
|
||||
|
|
|
@ -38,6 +38,7 @@ Field (GNVS, ByteAcc, NoLock, Preserve)
|
|||
GPEI, 64, // 0x11 - 0x18 - GPE Wake Source
|
||||
NHLA, 64, // 0x19 - 0x20 - NHLT Address
|
||||
NHLL, 32, // 0x21 - 0x24 - NHLT Length
|
||||
PRT0, 32, // 0x25 - 0x28 - PERST_0 Address
|
||||
|
||||
/* ChromeOS stuff (0x100 -> 0xfff, size 0xeff) */
|
||||
Offset (0x100),
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <soc/gpio_defs.h>
|
||||
#include "gpiolib.asl"
|
||||
|
||||
scope (\_SB) {
|
||||
|
||||
|
@ -141,6 +142,38 @@ scope (\_SB) {
|
|||
Return(0xf)
|
||||
}
|
||||
}
|
||||
|
||||
Scope(\_SB.PCI0) {
|
||||
/* PERST Assertion
|
||||
* Note: PERST is Active High
|
||||
*/
|
||||
Method (PRAS, 0x1, Serialized)
|
||||
{
|
||||
/*
|
||||
* Assert PERST
|
||||
* local1 - to toggle Tx pin of Dw0
|
||||
* local2 - Address of PERST
|
||||
*/
|
||||
Store (Arg0, Local2)
|
||||
Store (\_SB.GPC0 (Local2), Local1)
|
||||
Or (Local1, PAD_CFG0_TX_STATE, Local1)
|
||||
\_SB.SPC0 (Local2, Local1)
|
||||
}
|
||||
|
||||
/* PERST DE-Assertion */
|
||||
Method (PRDA, 0x1, Serialized)
|
||||
{
|
||||
/*
|
||||
* De-assert PERST
|
||||
* local1 - to toggle Tx pin of Dw0
|
||||
* local2 - Address of PERST
|
||||
*/
|
||||
Store (Arg0, Local2)
|
||||
Store (\_SB.GPC0 (Local2), Local1)
|
||||
And (Local1, Not (PAD_CFG0_TX_STATE), Local1)
|
||||
\_SB.SPC0 (Local2, Local1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Scope(\_GPE)
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
Scope (\_SB)
|
||||
{
|
||||
/* Get Pad Configuration DW0 register value */
|
||||
Method (GPC0, 0x1, Serialized)
|
||||
{
|
||||
/* Arg0 - GPIO DW0 address */
|
||||
Store (Arg0, Local0)
|
||||
OperationRegion (PDW0, SystemMemory, Local0, 4)
|
||||
Field (PDW0, AnyAcc, NoLock, Preserve) {
|
||||
TEMP, 32
|
||||
}
|
||||
Return (TEMP)
|
||||
}
|
||||
|
||||
/* Set Pad Configuration DW0 register value */
|
||||
Method (SPC0, 0x2, Serialized)
|
||||
{
|
||||
/* Arg0 - GPIO DW0 address */
|
||||
/* Arg1 - Value for DW0 register */
|
||||
Store (Arg0, Local0)
|
||||
OperationRegion (PDW0, SystemMemory, Local0, 4)
|
||||
Field (PDW0, AnyAcc, NoLock, Preserve) {
|
||||
TEMP,32
|
||||
}
|
||||
Store (Arg1, TEMP)
|
||||
}
|
||||
|
||||
/* Get Pad Configuration DW1 register value */
|
||||
Method (GPC1, 0x1, Serialized)
|
||||
{
|
||||
/* Arg0 - GPIO DW0 address */
|
||||
Store (Add (Arg0, 0x4), Local0)
|
||||
OperationRegion (PDW1, SystemMemory, Local0, 4)
|
||||
Field (PDW1, AnyAcc, NoLock, Preserve) {
|
||||
TEMP, 32
|
||||
}
|
||||
Return (TEMP)
|
||||
}
|
||||
|
||||
/* Set Pad Configuration DW1 register value */
|
||||
Method (SPC1, 0x2, Serialized)
|
||||
{
|
||||
/* Arg0 - GPIO DW0 address */
|
||||
/* Arg1 - Value for DW1 register */
|
||||
Store (Add (Arg0, 0x4), Local0)
|
||||
OperationRegion (PDW1, SystemMemory, Local0, 4)
|
||||
Field(PDW1, AnyAcc, NoLock, Preserve) {
|
||||
TEMP,32
|
||||
}
|
||||
Store (Arg1, TEMP)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (C) 2016 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
|
||||
Device (RP01)
|
||||
{
|
||||
Name (_ADR, 0x00140000)
|
||||
Name (_DDN, "PCIe-B 0")
|
||||
Name (PDST, 0) /* present Detect status */
|
||||
|
||||
/* lowest D-state supported by
|
||||
* PCIe root port during S0 state
|
||||
*/
|
||||
Name (_S0W, 4)
|
||||
|
||||
/* Dynamic Opregion needed to access registers
|
||||
* when the controller is in D3 cold
|
||||
*/
|
||||
OperationRegion (PX01, PCI_Config, 0x00, 0xFF)
|
||||
Field (PX01, AnyAcc, NoLock, Preserve)
|
||||
{
|
||||
Offset(0x5A),
|
||||
, 6,
|
||||
PDS, 1, /* 6, Presence detect Change */
|
||||
Offset(0xE2), /* RPPGEN - Root Port Power Gating Enable */
|
||||
, 2,
|
||||
L23E, 1, /* 2, L23_Rdy Entry Request (L23ER) */
|
||||
L23R, 1, /* 3, L23_Rdy to Detect Transition (L23R2DT) */
|
||||
Offset(0xF4), /* BLKPLLEN */
|
||||
, 10,
|
||||
BPLL, 1,
|
||||
}
|
||||
|
||||
OperationRegion (PX02, PCI_Config, 0x338, 0x4)
|
||||
Field (PX02, AnyAcc, NoLock, Preserve)
|
||||
{
|
||||
, 26,
|
||||
BDQA, 1 /* BLKDQDA */
|
||||
}
|
||||
|
||||
PowerResource (PXP, 0, 0)
|
||||
{
|
||||
/* Define the PowerResource for PCIe slot */
|
||||
Method (_STA, 0, Serialized)
|
||||
{
|
||||
Store (PDS, PDST)
|
||||
If (LEqual (PDS, 1)) {
|
||||
Return (0xf)
|
||||
} Else {
|
||||
Return (0)
|
||||
}
|
||||
}
|
||||
|
||||
Method (_ON, 0, Serialized)
|
||||
{
|
||||
If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
|
||||
/* Enter this condition if device
|
||||
* is connected
|
||||
*/
|
||||
|
||||
/* De-assert PERST */
|
||||
\_SB.PCI0.PRDA (\PRT0)
|
||||
|
||||
Store (0, BDQA) /* Set BLKDQDA to 0 */
|
||||
Store (0, BPLL) /* Set BLKPLLEN to 0 */
|
||||
|
||||
/* Set L23_Rdy to Detect Transition
|
||||
* (L23R2DT)
|
||||
*/
|
||||
Store (1, L23R)
|
||||
Sleep (16)
|
||||
Store (0, Local0)
|
||||
|
||||
/* Delay for transition Detect
|
||||
* and link to train
|
||||
*/
|
||||
While (L23R) {
|
||||
If (Lgreater (Local0, 4)) {
|
||||
Break
|
||||
}
|
||||
Sleep (16)
|
||||
Increment (Local0)
|
||||
}
|
||||
} /* End PDS condition check */
|
||||
}
|
||||
|
||||
Method (_OFF, 0, Serialized)
|
||||
{
|
||||
/* Set L23_Rdy Entry Request (L23ER) */
|
||||
If (LAnd (LEqual (PDST, 1), LNotEqual (\PRT0, 0))) {
|
||||
/* enter this condition if device
|
||||
* is connected
|
||||
*/
|
||||
Store (1, L23E)
|
||||
Sleep (16)
|
||||
Store (0, Local0)
|
||||
While (L23E) {
|
||||
If (Lgreater (Local0, 4)) {
|
||||
Break
|
||||
}
|
||||
Sleep (16)
|
||||
Increment (Local0)
|
||||
}
|
||||
Store (1, BDQA) /* Set BLKDQDA to 1 */
|
||||
Store (1, BPLL) /* Set BLKPLLEN to 1 */
|
||||
|
||||
/* Assert PERST */
|
||||
\_SB.PCI0.PRAS (\PRT0)
|
||||
} /* End PDS condition check */
|
||||
} /* End of Method_OFF */
|
||||
} /* End PXP */
|
||||
|
||||
Name(_PR0, Package() { PXP })
|
||||
Name(_PR3, Package() { PXP })
|
||||
}
|
|
@ -17,6 +17,9 @@
|
|||
|
||||
#include <soc/gpe.h>
|
||||
|
||||
/* PCIE device */
|
||||
#include "pcie.asl"
|
||||
|
||||
/* LPSS device */
|
||||
#include "lpss.asl"
|
||||
|
||||
|
|
|
@ -116,6 +116,9 @@ struct soc_intel_apollolake_config {
|
|||
|
||||
/* SLP S3 minimum assertion width. */
|
||||
int slp_s3_assertion_width_usecs;
|
||||
|
||||
/* GPIO pin for PERST_0 */
|
||||
uint16_t prt0_gpio;
|
||||
};
|
||||
|
||||
#endif /* _SOC_APOLLOLAKE_CHIP_H_ */
|
||||
|
|
|
@ -414,6 +414,9 @@
|
|||
#define LPC_CLKRUNB 243
|
||||
#define LPC_FRAMEB 244
|
||||
|
||||
/* PERST_0 not defined */
|
||||
#define GPIO_PRT0_UDEF 0xFF
|
||||
|
||||
#define TOTAL_PADS 245
|
||||
#define N_OFFSET GPIO_0
|
||||
#define NW_OFFSET GPIO_187
|
||||
|
|
|
@ -38,7 +38,8 @@ typedef struct global_nvs_t {
|
|||
uint64_t gpei; /* 0x11 - 0x18 - GPE Wake Source */
|
||||
uint64_t nhla; /* 0x19 - 0x20 - NHLT Address */
|
||||
uint32_t nhll; /* 0x21 - 0x24 - NHLT Length */
|
||||
uint8_t unused[219];
|
||||
uint32_t prt0; /* 0x25 - 0x28 - PERST_0 Address */
|
||||
uint8_t unused[215];
|
||||
|
||||
/* ChromeOS specific (0x100 - 0xfff) */
|
||||
chromeos_acpi_t chromeos;
|
||||
|
|
Loading…
Reference in New Issue