Kapil Porwal has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/74169 )
Change subject: drivers/wwan/fm: Add ACPI power management for Fibocom modem ......................................................................
drivers/wwan/fm: Add ACPI power management for Fibocom modem
1. Add power resource object 2. Use existing methods such as SHRF & FHRF to power on/off the modem 3. Do not use RTD3 object if it is not provided in devicetree
BUG=b:253467124 TEST=Verify ACPI code for Fibocom moden in the OS.
SSDT snippet: Scope (_SB.PCI0.XHCI.RHUB.HS05) { Method (FHRF, 1, Serialized) { 0x22 = _SB.PCI0.GTXS /* External reference */ Local0 Local0 ^= One If ((Local0 == Zero)) { _SB.PCI0.CTXS (0x22) }
Sleep (0x0A) _SB.PCI0.CTXS (0x44) If ((Arg0 == Zero)) { Sleep (0x0A) } ElseIf ((Arg0 == One)) { Sleep (0x0A) _SB.PCI0.CTXS (0x55) Sleep (0x01F4) } }
Method (SHRF, 0, Serialized) { _SB.PCI0.STXS (0x55) Sleep (0x14) _SB.PCI0.STXS (0x44) Sleep (0x50) _SB.PCI0.STXS (0x22) Sleep (0x64) }
Method (_RST, 0, Serialized) // _RST: Device Reset { FHRF (Zero) SHRF () }
Method (DPTS, 1, Serialized) { FHRF (One) }
Device (MRST) { Name (_ADR, 0x0000000000000000) // _ADR: Address Method (_RST, 0, Serialized) // _RST: Device Reset { FHRF (One) SHRF () } }
Name (_PR0, Package (0x01) // _PR0: Power Resources for D0 { PR00 }) Name (_PR3, Package (0x01) // _PR3: Power Resources for D3hot { PR00 }) PowerResource (PR00, 0x00, 0x0000) { Method (_STA, 0, Serialized) // _STA: Status { 0x22 = _SB.PCI0.GTXS /* External reference */ Local0 Local0 ^= One If (Local0) { Return (Zero) }
Return (One) }
Method (_ON, 0, Serialized) // _ON_: Power On { Local0 = _STA () If ((Local0 == One)) { Return (Zero) }
SHRF () }
Method (_OFF, 0, Serialized) // _OFF: Power Off { FHRF (One) } } }
Signed-off-by: Kapil Porwal kapilporwal@google.com Change-Id: I9024ec420425c5bf7d0605e961d08afe6f15eda6 --- M src/drivers/wwan/fm/acpi_fm350gl.c M src/drivers/wwan/fm/chip.h 2 files changed, 185 insertions(+), 13 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/69/74169/1
diff --git a/src/drivers/wwan/fm/acpi_fm350gl.c b/src/drivers/wwan/fm/acpi_fm350gl.c index df91389..711d1d5 100644 --- a/src/drivers/wwan/fm/acpi_fm350gl.c +++ b/src/drivers/wwan/fm/acpi_fm350gl.c @@ -5,6 +5,9 @@ #include "chip.h" #include "soc/intel/common/block/pcie/rtd3/chip.h"
+#define ACPI_POWER_RESOURCE_STATUS_ON_OP ONE_OP +#define ACPI_POWER_RESOURCE_STATUS_OFF_OP ZERO_OP + /* FCPO# to RESET# delay time during WWAN ON */ #define FM350GL_TN2B 20 /* RESET# to PERST# delay time during WWAN ON */ @@ -41,6 +44,9 @@ { const struct soc_intel_common_block_pcie_rtd3_config *rtd3_config;
+ if (!config->rtd3dev) + return ACPI_PCIE_RP_EMIT_NONE; + rtd3_config = config_of(config->rtd3dev);
return rtd3_config->ext_pm_support; @@ -155,9 +161,11 @@ acpigen_emit_byte(RESET_TYPE_WARM); /* Perform 2nd Half of FLDR Flow: SHRF() */ acpigen_emit_namestring("SHRF"); - /* Indicates that the following _Off will be skipped. */ - acpigen_emit_byte(INCREMENT_OP); - acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK")); + if (wwan_fm350gl_get_rtd3_method_support(config)) { + /* Indicates that the following _Off will be skipped. */ + acpigen_emit_byte(INCREMENT_OP); + acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK")); + } } acpigen_write_method_end(); /* Method */ } @@ -176,10 +184,12 @@ acpigen_emit_byte(RESET_TYPE_COLD); /* Perform 2nd Half of FLDR Flow: SHRF () */ acpigen_emit_namestring("SHRF"); - /* Indicate kernel ACPI PM to skip _off RTD3 after reset at the end of - driver removal */ - acpigen_emit_byte(INCREMENT_OP); - acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK")); + if (wwan_fm350gl_get_rtd3_method_support(config)) { + /* Indicate kernel ACPI PM to skip _off RTD3 after reset at the end of + driver removal */ + acpigen_emit_byte(INCREMENT_OP); + acpigen_emit_namestring(acpi_device_path_join(parent_dev, "RTD3.OFSK")); + } } acpigen_write_method_end(); /* Method */ } @@ -230,21 +240,22 @@ config->desc ?: dev->chip_ops->name); acpigen_write_scope(scope); { - acpigen_write_device(wwan_fm350gl_acpi_name(dev)); - { + if (wwan_fm350gl_get_rtd3_method_support(config)) { + acpigen_write_device(wwan_fm350gl_acpi_name(dev)); acpigen_write_ADR(0); if (config->name) acpigen_write_name_string("_DDN", config->name); if (config->desc) acpigen_write_name_unicode("_STR", config->desc); + if (config->add_acpi_dma_property) + acpi_device_add_dma_property(NULL); + } + wwan_fm350gl_acpi_method_fhrf(parent, config); wwan_fm350gl_acpi_method_shrf(parent, config); wwan_fm350gl_acpi_method_rst(parent, config); wwan_fm350gl_acpi_method_dpts(parent, config);
- if (config->add_acpi_dma_property) - acpi_device_add_dma_property(NULL); - /* NOTE: the 5G driver will call MRST._RST to trigger a cold reset * during firmware update. */ @@ -255,8 +266,49 @@ }
acpigen_write_device_end(); /* Device */ + + if (config->has_power_resource) { + static const char * const power_res_dev_states[] = { "_PR0", "_PR3" }; + /* PowerResource (PR##, 0, 0) */ + acpigen_write_power_res("PR00", 0, 0, power_res_dev_states, + ARRAY_SIZE(power_res_dev_states)); + + acpigen_write_method_serialized("_STA", 0); + /* Read GPIO status into Local0. */ + acpigen_get_tx_gpio(&config->perst_gpio); + acpigen_write_if(); + acpigen_emit_byte(LOCAL0_OP); + acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_OFF_OP); + acpigen_write_if_end(); + acpigen_write_return_op(ACPI_POWER_RESOURCE_STATUS_ON_OP); + acpigen_pop_len(); /* Method */ + + /* Method (_ON, 0, Serialized) */ + acpigen_write_method_serialized("_ON", 0); + /* Local0 = _STA () */ + acpigen_write_store(); + acpigen_emit_namestring("_STA"); + acpigen_emit_byte(LOCAL0_OP); + /* If (( Local0 == ACPI_POWER_RESOURCE_STATUS_ON_OP)) */ + acpigen_write_if_lequal_op_op(LOCAL0_OP, ACPI_POWER_RESOURCE_STATUS_ON_OP); + acpigen_write_return_op(ZERO_OP); + acpigen_write_if_end(); + // Call SHRF i.e. Modem ON + acpigen_emit_namestring("SHRF"); + acpigen_pop_len(); /* _ON method */ + + /* Method (_OFF, 0, Serialized) */ + acpigen_write_method_serialized("_OFF", 0); + // Call FHRF i.e. Modem OFF + acpigen_emit_namestring("FHRF"); + acpigen_emit_byte(RESET_TYPE_COLD); + acpigen_pop_len(); /* _OFF method */ + + acpigen_pop_len(); /* PowerResource PR## */ } - acpigen_write_device_end(); /* Device */ + + if (wwan_fm350gl_get_rtd3_method_support(config)) + acpigen_write_device_end(); /* Device */ } acpigen_write_scope_end(); /* Scope */ } diff --git a/src/drivers/wwan/fm/chip.h b/src/drivers/wwan/fm/chip.h index 19bc4c9..2ffe5d8 100644 --- a/src/drivers/wwan/fm/chip.h +++ b/src/drivers/wwan/fm/chip.h @@ -23,6 +23,9 @@
/* Add `DmaProperty` in _DSD */ bool add_acpi_dma_property; + + /* Add ACPI Power Resource object(s) */ + bool has_power_resource; };
#endif /* __DRIVERS_WWAN_FM_CHIP_H__ */