soc/intel/common/block/pcie/rtd3: Add PM methods to the device.

Add L23 enter/exit, modPHY power gate, and source clock control methods.
DL23: method for L2/L3 entry.
L23D: method for L2/L3 exit.
PSD0: method for modPHY power gate.
SRCK: method for enabling/disable source clock.
These optional methods are to be used in the device ACPI to construct
flows with root port's power management functions.

Test:
Enable and verify DL23, L23D, PSD0, SRCK methods in ssdt.

Signed-off-by: Cliff Huang <cliff.huang@intel.com>
Change-Id: I79de76f26c8424b036cb7d2719df68937599ca2f
Reviewed-on: https://review.coreboot.org/c/coreboot/+/61352
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Tim Wawrzynczak <twawrzynczak@chromium.org>
This commit is contained in:
Cliff Huang 2022-01-21 00:23:15 -08:00 committed by Felix Held
parent d5ae3f908a
commit 4bc9ac7c29
2 changed files with 100 additions and 0 deletions

View File

@ -5,6 +5,17 @@
#include <acpi/acpi_device.h>
enum acpi_pcie_rp_pm_emit {
ACPI_PCIE_RP_EMIT_NONE = 0x00, /* None */
ACPI_PCIE_RP_EMIT_L23 = 0x01, /* L23 */
ACPI_PCIE_RP_EMIT_PSD0 = 0x02, /* PSD0 */
ACPI_PCIE_RP_EMIT_SRCK = 0x04, /* SRCK */
ACPI_PCIE_RP_EMIT_L23_PSD0 = 0x03, /* L23, PSD0 */
ACPI_PCIE_RP_EMIT_L23_SRCK = 0x05, /* L23, SRCK */
ACPI_PCIE_RP_EMIT_PSD0_SRCK = 0x06, /* PSD0, SRCK */
ACPI_PCIE_RP_EMIT_ALL = 0x07 /* L23, PSD0, SRCK */
};
/* Device support at least one of enable/reset GPIO. */
struct soc_intel_common_block_pcie_rtd3_config {
const char *desc;
@ -45,6 +56,26 @@ struct soc_intel_common_block_pcie_rtd3_config {
* Disable the ACPI-driven L23 Ready-to-Detect transition for the root port.
*/
bool disable_l23;
/*
* Provides L23, modPHY gating, source clock enabling methods to the device
* connected root port, mainly used in the device ACPI methods such as reset.
* The methods to export are following this table:
*-----------------------------------------------------------------------------------*
| ext_pm_support | disable_l123 | srcclk_pin | rp_type | exported methods |
*----------------+--------------+------------+-------------+------------------------*
| false | - | - | - | None |
| true | true | =0 | PCIE_RP_CPU | None |
| true | true | =0 | PCIE_RP_PCH | SRCK |
| true | true | >0 | PCIE_RP_CPU | PSD0 |
| true | true | >0 | PCIE_RP_PCH | PSD0, SRCK |
| true | false | =0 | PCIE_RP_CPU | L23D, LD23 |
| true | false | =0 | PCIE_RP_PCH | L23D, LD23, SRCK |
| true | false | >0 | PCIE_RP_CPU | L23D, LD23, PSD0 |
| true | false | >0 | PCIE_RP_PCH | L23D, LD23, PSD0, SRCK |
*-----------------------------------------------------------------------------------*
*/
enum acpi_pcie_rp_pm_emit ext_pm_support;
};
#endif /* __SOC_INTEL_COMMON_BLOCK_PCIE_RTD3_CHIP_H__ */

View File

@ -100,6 +100,46 @@ static void pcie_rtd3_enable_modphy_pg(unsigned int pcie_rp, enum modphy_pg_stat
acpigen_emit_namestring(RTD3_MUTEX_PATH);
}
/* Method to enter L2/L3 */
static void pcie_rtd3_acpi_method_dl23(void)
{
acpigen_write_method_serialized("DL23", 0);
pcie_rtd3_acpi_l23_entry();
acpigen_pop_len(); /* Method */
}
/* Method to exit L2/L3 */
static void pcie_rtd3_acpi_method_l23d(void)
{
acpigen_write_method_serialized("L23D", 0);
pcie_rtd3_acpi_l23_exit();
acpigen_pop_len(); /* Method */
}
/* Method to disable PCH modPHY power gating */
static void pcie_rtd3_acpi_method_pds0(unsigned int pcie_rp)
{
acpigen_write_method_serialized("PSD0", 0);
pcie_rtd3_enable_modphy_pg(pcie_rp, PG_DISABLE);
acpigen_pop_len(); /* Method */
}
/* Method to enable/disable the source clock */
static void pcie_rtd3_acpi_method_srck(unsigned int pcie_rp,
const struct soc_intel_common_block_pcie_rtd3_config *config)
{
acpigen_write_method_serialized("SRCK", 1);
if (config->srcclk_pin >= 0) {
acpigen_write_if_lequal_op_op(ARG0_OP, 0);
pmc_ipc_acpi_set_pci_clock(pcie_rp, config->srcclk_pin, false);
acpigen_write_else();
pmc_ipc_acpi_set_pci_clock(pcie_rp, config->srcclk_pin, true);
acpigen_pop_len(); /* If */
}
acpigen_pop_len(); /* Method */
}
static void
pcie_rtd3_acpi_method_on(unsigned int pcie_rp,
const struct soc_intel_common_block_pcie_rtd3_config *config,
@ -293,6 +333,24 @@ static void pcie_rtd3_acpi_fill_ssdt(const struct device *dev)
printk(BIOS_ERR, "%s: Unknown PCIe root port\n", __func__);
return;
}
if (config->disable_l23) {
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_L23) {
printk(BIOS_ERR, "%s: Can not export L23 methods\n", __func__);
return;
}
}
if (rp_type != PCIE_RP_PCH) {
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_PSD0) {
printk(BIOS_ERR, "%s: Can not export PSD0 method\n", __func__);
return;
}
}
if (config->srcclk_pin == 0) {
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_SRCK) {
printk(BIOS_ERR, "%s: Can not export SRCK method\n", __func__);
return;
}
}
printk(BIOS_INFO, "%s: Enable RTD3 for %s (%s)\n", scope, dev_path(parent),
config->desc ?: dev->chip_ops->name);
@ -316,10 +374,21 @@ static void pcie_rtd3_acpi_fill_ssdt(const struct device *dev)
acpigen_write_field("PXCS", fieldlist, ARRAY_SIZE(fieldlist),
FIELD_ANYACC | FIELD_NOLOCK | FIELD_PRESERVE);
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_L23) {
pcie_rtd3_acpi_method_dl23();
pcie_rtd3_acpi_method_l23d();
}
/* Create the OpRegion to access the ModPHY PG registers (PCH RPs only) */
if (rp_type == PCIE_RP_PCH)
write_modphy_opregion(pcie_rp);
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_PSD0)
pcie_rtd3_acpi_method_pds0(pcie_rp);
if (config->ext_pm_support | ACPI_PCIE_RP_EMIT_SRCK)
pcie_rtd3_acpi_method_srck(pcie_rp, config);
/* ACPI Power Resource for controlling the attached device power. */
acpigen_write_power_res("RTD3", 0, 0, power_res_states, ARRAY_SIZE(power_res_states));
pcie_rtd3_acpi_method_status(config);