summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCliff Huang <cliff.huang@intel.com>2022-01-21 00:23:15 -0800
committerFelix Held <felix-coreboot@felixheld.de>2022-02-07 14:10:14 +0000
commit4bc9ac7c292c806228c826b5971bf23c47b4f39f (patch)
tree6e9556d8cb08657dda909bf2228e6f4cd815fa83
parentd5ae3f908af3c5201bd42fe411b32f97ac35ea4d (diff)
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>
-rw-r--r--src/soc/intel/common/block/pcie/rtd3/chip.h31
-rw-r--r--src/soc/intel/common/block/pcie/rtd3/rtd3.c69
2 files changed, 100 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/pcie/rtd3/chip.h b/src/soc/intel/common/block/pcie/rtd3/chip.h
index 15b8f64891..7541bc326d 100644
--- a/src/soc/intel/common/block/pcie/rtd3/chip.h
+++ b/src/soc/intel/common/block/pcie/rtd3/chip.h
@@ -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__ */
diff --git a/src/soc/intel/common/block/pcie/rtd3/rtd3.c b/src/soc/intel/common/block/pcie/rtd3/rtd3.c
index 9f91d21d3e..260aa6592c 100644
--- a/src/soc/intel/common/block/pcie/rtd3/rtd3.c
+++ b/src/soc/intel/common/block/pcie/rtd3/rtd3.c
@@ -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);