Cliff Huang has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/61353 )
Change subject: soc/intel/common/block/pcie/rtd3: Add optional _OFF and _ON skip control ......................................................................
soc/intel/common/block/pcie/rtd3: Add optional _OFF and _ON skip control
- Optional feature to provide mechanism to skip _OFF and _On execution. - It is used for the device to skip _OFF and _ON during device driver reload. - _OFS is used to skip _OFF Method at the end of device driver removal. - _ONS is used to skip _ON Method at the beginning of driver loading. - General flow use case: 1. Device driver is removed by 'rmmod' command. 2. Device _RST is called. _RST perform reset. 3. Device sets _OFS in _RST to skip the following _OFF invoked by OSPM. 4. OSPM invokes _OFF at the end of driver removal. 5. _OFF sees _OFS and skips current execution and clears _OFS so that _OFF will be executed normally next time. 6. _OFF sets _ONS to skip the following _ON invoked by OSPM. 7. Device driver is reloading by 'insmod/modprobe' command. 8. OSPM invokes _ON at the beginning of driver loading. 9. _ON sees _ONS and skip current execution and clears _ONS so that _ON will be executed normally next time.
- In normal case: When supspend, OSPM invokes _OFF and _OFS is not set, so the device go to deeper state as expected.
When resume, OSPM invokes _ON and _ONS is not set, so the device go to active state as expected.
- Generated changes:
PowerResource (RTD3, 0x00, 0x0000) Name (_ONS, Zero) Name (_OFS, Zero) ...
Method (_ON, 0, Serialized) // _ON_: Power On { If ((_ONS == Zero)) { ... } ElseIf ((_ONS == One)) { _ONS = Zero } }
Method (_OFF, 0, Serialized) // _OFF: Power Off { If ((_OFS == Zero)) { ... } ElseIf ((_OFS == One)) { _OFS = Zero _ONS = One } }
Test: Enable and verify _OFS and _ONS Name objects and the if-condition logic inside _OFF and _ON metheds is added.
Signed-off-by: Cliff Huang cliff.huang@intel.com Change-Id: Ic32d151d65107bfc220258c383a575e40a496b6f --- M src/soc/intel/common/block/pcie/rtd3/chip.h M src/soc/intel/common/block/pcie/rtd3/rtd3.c 2 files changed, 58 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/53/61353/1
diff --git a/src/soc/intel/common/block/pcie/rtd3/chip.h b/src/soc/intel/common/block/pcie/rtd3/chip.h index c2bad63..10470fe 100644 --- a/src/soc/intel/common/block/pcie/rtd3/chip.h +++ b/src/soc/intel/common/block/pcie/rtd3/chip.h @@ -51,6 +51,12 @@ * connected root port, mainly used in the device ACPI methods such as reset. */ bool ext_pm_support; + + /* + * Add support to skip _OFF and _ON execution when needed, such as reloading + * the device driver. + */ + bool skip_on_off_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 a9df72a..0a96574 100644 --- a/src/soc/intel/common/block/pcie/rtd3/rtd3.c +++ b/src/soc/intel/common/block/pcie/rtd3/rtd3.c @@ -151,6 +151,13 @@ { acpigen_write_method_serialized("_ON", 0);
+ /* When this feature is enabled, _ONS indicates if the previous _OFF was + * skipped. If so, since the device was not in Off state, and the current + * _ON can be skipped as well. + */ + if (config->skip_on_off_support) + acpigen_write_if_lequal_namestr_int("_ONS", 0); + /* Disable modPHY power gating for PCH RPs. */ if (rp_type == PCIE_RP_PCH) pcie_rtd3_enable_modphy_pg(pcie_rp, PG_DISABLE); @@ -177,6 +184,17 @@ if (!config->disable_l23) pcie_rtd3_acpi_l23_exit();
+ if (config->skip_on_off_support) { + /* If current _ON is skipped, _ONS is clear so that _ON will be + * executed normally until _OFF is skipped again. + */ + acpigen_write_else(); + acpigen_write_if_lequal_namestr_int("_ONS", 1); + acpigen_write_store_int_to_namestr(0, "_ONS"); + + acpigen_pop_len(); /* If */ + acpigen_pop_len(); /* Else */ + } acpigen_pop_len(); /* Method */ }
@@ -187,6 +205,14 @@ { acpigen_write_method_serialized("_OFF", 0);
+ /* When this feature is enabled, _ONS is checked to see if the device + * wants _OFF to be skipped for once. _ONS is normally set in the device + * method, such as reset _RST, which is invoked during driver reload. In + * such case, _OFF needs to be avoided at the end of driver removal. + */ + if (config->skip_on_off_support) + acpigen_write_if_lequal_namestr_int("_OFS", 0); + /* Trigger L23 ready entry flow unless disabled by config. */ if (!config->disable_l23) pcie_rtd3_acpi_l23_entry(); @@ -213,6 +239,18 @@ acpigen_write_sleep(config->enable_off_delay_ms); }
+ if (config->skip_on_off_support) { + /* If current _OFF is skipped, _ONS is set so that the following _ON + * will also be skipped. In addition, _OFS is clear so that next _OFF + * will be executed normally until the device method sets _OFS again. + */ + acpigen_write_else(); + acpigen_write_if_lequal_namestr_int("_OFS", 1); + acpigen_write_store_int_to_namestr(0, "_OFS"); + acpigen_write_store_int_to_namestr(1, "_ONS"); + acpigen_pop_len(); /* If */ + acpigen_pop_len(); /* Else */ + } acpigen_pop_len(); /* Method */ }
@@ -377,6 +415,20 @@
/* ACPI Power Resource for controlling the attached device power. */ acpigen_write_power_res("RTD3", 0, 0, power_res_states, ARRAY_SIZE(power_res_states)); + + if (config->skip_on_off_support) { + /* _OFS: 0 = _OFF Method will be executed normally when called; + * 1 = _OFF will be skipped once. + * _OFF Method to clear _OFS and set _ONS if the current execution + * is skipped. + * _ONS: 0 = _ON Method will be executed normally when called; + * 1 = _ONF will be skipped once. + * _ON Method to clear _ONS if the current execution is skipped. + */ + acpigen_write_name_integer("_ONS", 0); + acpigen_write_name_integer("_OFS", 0); + } + pcie_rtd3_acpi_method_status(config); pcie_rtd3_acpi_method_on(pcie_rp, config, rp_type); pcie_rtd3_acpi_method_off(pcie_rp, config, rp_type);