From efa24540b09c1e70f6b3110f5f56bdd023efb85a Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Mon, 16 Jun 2025 15:42:50 -0700 Subject: [PATCH] drivers/wifi/generic: Implement Bluetooth PRR DSM functions This commit introduces Bluetooth Device-Specific Methods (DSM) "7266172c-220b-4b29-814f-75e4dd26b5fd" functions 5, 6 and 7, enabling access to the Power Resource for Reset (PRR) mode, status and reset delay. It meets the DSM requirements listed in Intel Document number 559910. The Power Resource Advanced Configuration and Power Interface (ACPI) code was adapted from Panther Lake (PTL) Firmware Support Package (FSP) revision 3144.01 (IntelBtDsmFunc5.asl, IntelBtDsmFunc6.asl and IntelBtDsmFunc7.asl). TEST=The following sequence of acpidbg commands was used to verify functions 5, 6 and 7 behavior on a Fatcat device. acpidbg -b "evaluate \_SB.PCI0.CNVB._DSM \ (2c 17 66 72 0b 22 29 4b 81 4f 75 e4 dd 26 b5 fd) \ 0 6 0" # Get PRR mode and status: [0x0 0x0] acpidbg -b "evaluate \_SB.PCI0.CNVB._DSM \ (2c 17 66 72 0b 22 29 4b 81 4f 75 e4 dd 26 b5 fd) \ 0 5 (01 00 01 00)" # Set PRR mode (type) to 0x1 acpidbg -b "evaluate \_SB.PCI0.CNVB._DSM \ (2c 17 66 72 0b 22 29 4b 81 4f 75 e4 dd 26 b5 fd) \ 0 6 0" # Get PRR mode and status: [0x1 0x0] acpidbg -b 'evaluate \_SB.PCI0.CNVB.BTDL' # 0x32 acpidbg -b "evaluate \_SB.PCI0.CNVB._DSM \ (2c 17 66 72 0b 22 29 4b 81 4f 75 e4 dd 26 b5 fd) \ 0 7 60" acpidbg -b 'evaluate \_SB.PCI0.CNVB.BTDL' # 0x3C Change-Id: I3b0a77f3c2b7bec5dcb909a1266c7d5f4d5a8d1e Signed-off-by: Jeremy Compostella Reviewed-on: https://review.coreboot.org/c/coreboot/+/88115 Reviewed-by: Paul Menzel Tested-by: build bot (Jenkins) Reviewed-by: Bora Guvendik --- src/drivers/wifi/generic/acpi.c | 96 ++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c index 7c53b247ab..753492abad 100644 --- a/src/drivers/wifi/generic/acpi.c +++ b/src/drivers/wifi/generic/acpi.c @@ -362,6 +362,89 @@ static void (*wifi_dsm2_callbacks[])(void *) = { wifi_dsm_set_prr_reset_delay, /* Function 5 */ }; +/* + * Function 5: Set Power Resource for Reset (PRR) mode for Bluetooth + * + * Args3 is a buffer comparable to the following C structure: + * struct pldr_mode { + * uint16_t cmd_type; + * uint16_t cmd_payload; + * }; + * + * cmd_type can take one of the following values: + * 1 - Set PRR mode to cmd_payload; + */ +static void bluetooth_dsm_set_power_resource_for_reset(__always_unused void *args) +{ + acpigen_write_create_word_field(ARG3_OP, 0, "BCMT"); + acpigen_write_create_word_field(ARG3_OP, 2, "BCMP"); + + /* Set PRR mode */ + acpigen_write_if_lequal_namestr_int("BCMT", 1); + { + acpigen_write_if_cond_ref_of("RSTT"); + { + acpigen_write_store(); + acpigen_emit_namestring("BCMP"); + acpigen_emit_namestring("RSTT"); + + } + acpigen_pop_len(); + } + acpigen_pop_len(); + + acpigen_write_return_integer(0); +} + +/* + * Function 6: Get Power Resource for Reset (PRR) mode and status for Bluetooth + */ +static void bluetooth_dsm_get_power_resource_for_reset(__always_unused void *args) +{ + /* Get PRR mode and status */ + acpigen_write_if_cond_ref_of("RSTT"); + { + acpigen_write_if_cond_ref_of("PRRS"); + { + acpigen_emit_byte(RETURN_OP); + acpigen_write_package(2); + acpigen_emit_namestring("RSTT"); + acpigen_emit_namestring("PRRS"); + acpigen_pop_len(); + } + acpigen_pop_len(); + } + acpigen_pop_len(); + + acpigen_write_return_integer(0); +} + +/* + * Function 7: Set Power Resource for Reset (PRR) reset delay for Bluetooth + */ +static void bluetooth_dsm_set_prr_reset_delay(__always_unused void *args) +{ + acpigen_write_if_cond_ref_of("BTDL"); + { + acpigen_write_store(); + acpigen_emit_byte(ARG3_OP); + acpigen_emit_namestring("BTDL"); + } + acpigen_pop_len(); +} + + +static void (*bluetooth_dsm_callbacks[])(void *) = { + NULL, /* Function 0 */ + NULL, /* Function 1 */ + NULL, /* Function 2 */ + NULL, /* Function 3 */ + NULL, /* Function 4 */ + bluetooth_dsm_set_power_resource_for_reset, /* Function 5 */ + bluetooth_dsm_get_power_resource_for_reset, /* Function 6 */ + bluetooth_dsm_set_prr_reset_delay, /* Function 7 */ +}; + static const uint8_t *sar_fetch_set(const struct sar_profile *sar, size_t set_num) { const uint8_t *sar_table = &sar->sar_table[0]; @@ -1212,7 +1295,7 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco acpigen_write_scope_end(); /* Scope */ - /* Fill Bluetooth companion SAR related ACPI structures */ + /* Fill Bluetooth companion SAR related ACPI structures and DSM functions. */ if (sar_loaded && is_dev_enabled(config->bluetooth_companion)) { const char *path = acpi_device_path(config->bluetooth_companion); if (path) { /* Bluetooth device under USB Hub scope or PCIe root port */ @@ -1226,6 +1309,17 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco sar_emit_bdmm(sar_limits.bdmm); sar_emit_ebrd(sar_limits.ebrd); sar_emit_dsbr(sar_limits.dsbr, DOMAIN_TYPE_BLUETOOTH); + + if (config->bluetooth_companion->path.type == DEVICE_PATH_PCI && + config->bluetooth_companion->vendor == PCI_VID_INTEL) { + struct dsm_uuid bt_dsm_ids = { + .uuid = ACPI_DSM_RFIM_WIFI_UUID, + .callbacks = bluetooth_dsm_callbacks, + .count = ARRAY_SIZE(bluetooth_dsm_callbacks) + }; + acpigen_write_dsm_uuid_arr(&bt_dsm_ids, 1); + } + acpigen_write_scope_end(); } else { printk(BIOS_ERR, "Failed to get %s Bluetooth companion ACPI path\n",