diff --git a/src/soc/intel/common/block/pcie/rtd3/chip.h b/src/soc/intel/common/block/pcie/rtd3/chip.h index ff22adcf49..f247028a61 100644 --- a/src/soc/intel/common/block/pcie/rtd3/chip.h +++ b/src/soc/intel/common/block/pcie/rtd3/chip.h @@ -5,6 +5,8 @@ #include +#define RP_MUTEX_NAME "RPMX" + enum acpi_pcie_rp_pm_emit { ACPI_PCIE_RP_EMIT_NONE = 0x00, /* None */ ACPI_PCIE_RP_EMIT_L23 = 0x01, /* L23 */ @@ -86,6 +88,13 @@ struct soc_intel_common_block_pcie_rtd3_config { * the device driver. */ bool skip_on_off_support; + + /* + * Indicates the root port mutex is used for _ON and _OFF, the companion device driver + * such as WWAN driver should also acquire this mutex in methods that access the same HW + * resource, such as PERST# GPIO pin. + */ + bool use_rp_mutex; }; #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 1519e6fd50..8b372ed839 100644 --- a/src/soc/intel/common/block/pcie/rtd3/rtd3.c +++ b/src/soc/intel/common/block/pcie/rtd3/rtd3.c @@ -154,6 +154,10 @@ pcie_rtd3_acpi_method_on(unsigned int pcie_rp, acpigen_write_return_op(ONE_OP); acpigen_write_if_end(); + if (config->use_rp_mutex) + acpigen_write_acquire(acpi_device_path_join(parent, RP_MUTEX_NAME), + ACPI_MUTEX_NO_TIMEOUT); + /* Disable modPHY power gating for PCH RPs. */ if (rp_type == PCIE_RP_PCH) pcie_rtd3_enable_modphy_pg(pcie_rp, PG_DISABLE); @@ -180,6 +184,9 @@ pcie_rtd3_acpi_method_on(unsigned int pcie_rp, if (!config->disable_l23) pcie_rtd3_acpi_l23_exit(); + if (config->use_rp_mutex) + acpigen_write_release(acpi_device_path_join(parent, RP_MUTEX_NAME)); + if (config->skip_on_off_support) { /* If current _ON is skipped, ONSK is decremented so that _ON will be * executed normally until _OFF is skipped again. @@ -196,8 +203,12 @@ pcie_rtd3_acpi_method_on(unsigned int pcie_rp, static void pcie_rtd3_acpi_method_off(int pcie_rp, const struct soc_intel_common_block_pcie_rtd3_config *config, - enum pcie_rp_type rp_type) + enum pcie_rp_type rp_type, + const struct device *dev) + { + const struct device *parent = dev->bus->dev; + acpigen_write_method_serialized("_OFF", 0); /* When this feature is enabled, ONSK is checked to see if the device @@ -208,6 +219,10 @@ pcie_rtd3_acpi_method_off(int pcie_rp, if (config->skip_on_off_support) acpigen_write_if_lequal_namestr_int("OFSK", 0); + if (config->use_rp_mutex) + acpigen_write_acquire(acpi_device_path_join(parent, RP_MUTEX_NAME), + ACPI_MUTEX_NO_TIMEOUT); + /* Trigger L23 ready entry flow unless disabled by config. */ if (!config->disable_l23) pcie_rtd3_acpi_l23_entry(); @@ -234,6 +249,9 @@ pcie_rtd3_acpi_method_off(int pcie_rp, acpigen_write_sleep(config->enable_off_delay_ms); } + if (config->use_rp_mutex) + acpigen_write_release(acpi_device_path_join(parent, RP_MUTEX_NAME)); + if (config->skip_on_off_support) { /* If current _OFF is skipped, ONSK is incremented so that the * following _ON will also be skipped. In addition, OFSK is decremented @@ -422,6 +440,9 @@ static void pcie_rtd3_acpi_fill_ssdt(const struct device *dev) /* The RTD3 power resource is added to the root port, not the device. */ acpigen_write_scope(scope); + if (config->use_rp_mutex) + acpigen_write_mutex(RP_MUTEX_NAME, 0); + if (config->desc) acpigen_write_name_string("_DDN", config->desc); @@ -464,7 +485,7 @@ static void pcie_rtd3_acpi_fill_ssdt(const struct device *dev) pcie_rtd3_acpi_method_status(config); pcie_rtd3_acpi_method_on(pcie_rp, config, rp_type, dev); - pcie_rtd3_acpi_method_off(pcie_rp, config, rp_type); + pcie_rtd3_acpi_method_off(pcie_rp, config, rp_type, dev); acpigen_pop_len(); /* PowerResource */ /* Indicate to the OS that device supports hotplug in D3. */