summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Compostella <jeremy.compostella@intel.com>2024-06-24 10:16:41 -0700
committerJérémy Compostella <jeremy.compostella@intel.com>2024-07-03 17:01:17 +0000
commit71dda74fe8addc0beffffc5a039c896c3f910640 (patch)
tree8f47e92bdb6b2e89bd5dbf145910450c9e5c549d
parent2721846dab2c5e7a207e985cb634588f380744bd (diff)
drivers/wifi: Support Bluetooth Regulator Domain Settings
The 'Bluetooth Increased Power Mode - SAR Limitation' feature provides ability to utilize increased device Transmit power capability for Bluetooth applications in coordination with Wi-Fi adhering to product SAR limit when Bluetooth and Wi-Fi run together. This commit introduces a `bluetooth_companion' field to the generic Wi-Fi drivers chip data. This field can be set in the board design device tree to supply the bluetooth device for which the BRDS function must be created. This feature is required for Meteor Lake rex karis variant. The implementation follows document 559910 Intel Connectivity Platforms BIOS Guideline revision 8.3 specification. BUG=b:348345301 BRANCH=firmware-rex-15709.B TEST=BRDS method is added to the CNVW device and return the data supplied by the SAR binary blob Change-Id: Iebe95815c944d045f4cf686abcd1874a8a45e209 Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/83200 Reviewed-by: Eric Lai <ericllai@google.com> Reviewed-by: Subrata Banik <subratabanik@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--src/drivers/wifi/generic/acpi.c81
-rw-r--r--src/drivers/wifi/generic/chip.h3
-rw-r--r--src/include/sar.h16
-rw-r--r--src/vendorcode/google/chromeos/sar.c10
4 files changed, 105 insertions, 5 deletions
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c
index d3da51b116..e303589660 100644
--- a/src/drivers/wifi/generic/acpi.c
+++ b/src/drivers/wifi/generic/acpi.c
@@ -15,8 +15,9 @@
#include "wifi.h"
#include "wifi_private.h"
-/* WIFI Domain type */
+/* Domain type */
#define DOMAIN_TYPE_WIFI 0x7
+#define DOMAIN_TYPE_BLUETOOTH 0x12
/* Maximum number DSM UUID bifurcations in _DSM */
#define MAX_DSM_FUNCS 2
@@ -489,9 +490,59 @@ static void sar_emit_wtas(struct avg_profile *wtas)
acpigen_write_package_end();
}
-static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profile *dsm)
+static void sar_emit_brds(const struct bsar_profile *bsar)
{
- union wifi_sar_limits sar_limits = {{NULL, NULL, NULL, NULL, NULL} };
+ size_t package_size, table_size;
+ const uint8_t *set;
+
+ /*
+ * Name ("BRDS", Package () {
+ * Revision,
+ * Package () {
+ * Domain Type, // 0x12:Bluetooth
+ * Bluetooth SAR BIOS, // BIOS SAR Enable/disable
+ * Bluetooth Increase Power Mode // SAR Limitation Enable/disable
+ * Bluetooth SAR Power Restriction, // 00000000 - 0dBm
+ * // 11111111 - 31.875dBm
+ * // (Step 0.125dBm)
+ * Bluetooth SAR Table // SAR Tx power limit table
+ * }
+ * })
+ */
+ if (bsar->revision != BSAR_REVISION) {
+ printk(BIOS_ERR, "Unsupported BSAR table revision: %d\n",
+ bsar->revision);
+ return;
+ }
+
+ acpigen_write_name("BRDS");
+ acpigen_write_package(2);
+ acpigen_write_dword(bsar->revision);
+
+ table_size = sizeof(*bsar) -
+ offsetof(struct bsar_profile, sar_lb_power_restriction);
+ /*
+ * Emit 'Domain Type' + 'Dynamic SAR Enable' + 'Increase Power Mode'
+ * + ('SAR Power Restriction' + SAR table).
+ */
+ package_size = 1 + 1 + 1 + table_size;
+ acpigen_write_package(package_size);
+ acpigen_write_dword(DOMAIN_TYPE_BLUETOOTH);
+ acpigen_write_dword(1);
+ acpigen_write_dword(bsar->increased_power_mode_limitation);
+
+ set = (const uint8_t *)&bsar->sar_lb_power_restriction;
+ for (int i = 0; i < table_size; i++)
+ acpigen_write_byte(set[i]);
+
+ acpigen_write_package_end();
+ acpigen_write_package_end();
+}
+
+static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profile *dsm,
+ struct bsar_profile *bsar, bool *bsar_loaded)
+{
+ union wifi_sar_limits sar_limits = {0};
/*
* If device type is PCI, ensure that the device has Intel vendor ID. CBFS SAR and SAR
@@ -516,6 +567,12 @@ static void emit_sar_acpi_structures(const struct device *dev, struct dsm_profil
if (sar_limits.dsm != NULL)
memcpy(dsm, sar_limits.dsm, sizeof(struct dsm_profile));
+ /* copy the bsar data to be later used for creating Bluetooth BRDS method */
+ if (sar_limits.bsar != NULL) {
+ memcpy(bsar, sar_limits.bsar, sizeof(struct bsar_profile));
+ *bsar_loaded = true;
+ }
+
free(sar_limits.sar);
}
@@ -576,11 +633,14 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco
struct dsm_uuid dsm_ids[MAX_DSM_FUNCS];
/* We will need a copy dsm data to be used later for creating _DSM function */
struct dsm_profile dsm = {0};
+ /* We will need a copy of bsar data to be used later for creating BRDS function */
+ struct bsar_profile bsar = {0};
+ bool bsar_loaded = false;
uint8_t dsm_count = 0;
/* Fill Wifi SAR related ACPI structures */
if (CONFIG(USE_SAR)) {
- emit_sar_acpi_structures(dev, &dsm);
+ emit_sar_acpi_structures(dev, &dsm, &bsar, &bsar_loaded);
if (dsm.supported_functions != 0) {
for (int i = 1; i < ARRAY_SIZE(wifi_dsm_callbacks); i++)
@@ -618,6 +678,19 @@ 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 */
+ if (bsar_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 */
+ acpigen_write_scope(path);
+ sar_emit_brds(&bsar);
+ acpigen_write_scope_end();
+ } else {
+ printk(BIOS_ERR, "Failed to get %s Bluetooth companion ACPI path\n",
+ dev_path(dev));
+ }
+ }
+
printk(BIOS_INFO, "%s: %s %s\n", scope, dev->chip_ops ? dev->chip_ops->name : "",
dev_path(dev));
}
diff --git a/src/drivers/wifi/generic/chip.h b/src/drivers/wifi/generic/chip.h
index 2729a35663..302dd144ef 100644
--- a/src/drivers/wifi/generic/chip.h
+++ b/src/drivers/wifi/generic/chip.h
@@ -19,6 +19,9 @@ struct drivers_wifi_generic_config {
* SoC code propagates this value the applicable FSP UPD.
*/
bool enable_cnvi_ddr_rfim;
+
+ /* Pointer to the Bluetooth companion device */
+ DEVTREE_CONST struct device *bluetooth_companion;
};
#endif /* _GENERIC_WIFI_H_ */
diff --git a/src/include/sar.h b/src/include/sar.h
index c201cea2f4..7c1b95d530 100644
--- a/src/include/sar.h
+++ b/src/include/sar.h
@@ -9,8 +9,9 @@
#define MAX_DENYLIST_ENTRY 16
#define MAX_DSAR_SET_COUNT 3
#define MAX_GEO_OFFSET_REVISION 3
-#define MAX_PROFILE_COUNT 5
+#define MAX_PROFILE_COUNT 6
#define MAX_SAR_REVISION 2
+#define BSAR_REVISION 1
#define REVISION_SIZE 1
#define SAR_REV0_CHAINS_COUNT 2
#define SAR_REV0_SUBBANDS_COUNT 5
@@ -60,6 +61,18 @@ struct dsm_profile {
uint32_t enablement_11be;
};
+struct bsar_profile {
+ uint8_t revision;
+ uint8_t increased_power_mode_limitation;
+ uint8_t sar_lb_power_restriction;
+ uint8_t br_modulation;
+ uint8_t edr2_modulation;
+ uint8_t edr3_modulation;
+ uint8_t le_modulation;
+ uint8_t le2_mhz_modulation;
+ uint8_t le_lr_modulation;
+} __packed;
+
struct sar_header {
char marker[SAR_STR_PREFIX_SIZE];
uint8_t version;
@@ -74,6 +87,7 @@ union wifi_sar_limits {
struct gain_profile *ppag;
struct avg_profile *wtas;
struct dsm_profile *dsm;
+ struct bsar_profile *bsar;
};
void *profile[MAX_PROFILE_COUNT];
};
diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c
index c42bf65437..8195886ebc 100644
--- a/src/vendorcode/google/chromeos/sar.c
+++ b/src/vendorcode/google/chromeos/sar.c
@@ -94,6 +94,14 @@ static int dsm_table_size(const struct dsm_profile *dsm)
return sizeof(struct dsm_profile);
}
+static int bsar_table_size(const struct bsar_profile *bsar)
+{
+ if (bsar == NULL)
+ return 0;
+
+ return sizeof(struct bsar_profile);
+}
+
static bool valid_legacy_length(size_t bin_len)
{
if (bin_len == LEGACY_SAR_WGDS_BIN_SIZE)
@@ -145,6 +153,7 @@ static int fill_wifi_sar_limits(union wifi_sar_limits *sar_limits, const uint8_t
expected_sar_bin_size += gain_table_size(sar_limits->ppag);
expected_sar_bin_size += sar_avg_table_size(sar_limits->wtas);
expected_sar_bin_size += dsm_table_size(sar_limits->dsm);
+ expected_sar_bin_size += bsar_table_size(sar_limits->bsar);
if (sar_bin_size != expected_sar_bin_size) {
printk(BIOS_ERR, "Invalid SAR size, expected: %zu, obtained: %zu\n",
@@ -210,6 +219,7 @@ static int fill_wifi_sar_limits_legacy(union wifi_sar_limits *sar_limits,
* [PPAG_REVISION,MODE,CHAINS_COUNT,SUBBANDS_COUNT<PPAG_DATA>]
* [WTAS_REVISION, WTAS_DATA]
* [DSM_RETURN_VALUES]
+ * [BSAR_REVISION,IPML,LB,BR,EDR2,EDR3,LE,LE2,LE_LR]
*
* The configuration data will always have the revision added in the file for each of the
* block, based on the revision number and validity, size of the specific block will be