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:
Vaibhav Shankar 2016-08-23 17:56:17 -07:00 committed by Aaron Durbin
parent 9e81540b85
commit ef8deaffcb
9 changed files with 243 additions and 1 deletions

View File

@ -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 */

View File

@ -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),

View File

@ -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)

View File

@ -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)
}
}

View File

@ -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 })
}

View File

@ -17,6 +17,9 @@
#include <soc/gpe.h>
/* PCIE device */
#include "pcie.asl"
/* LPSS device */
#include "lpss.asl"

View File

@ -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_ */

View File

@ -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

View File

@ -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;