summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Compostella <jeremy.compostella@intel.com>2024-10-30 11:26:27 -0700
committerJérémy Compostella <jeremy.compostella@intel.com>2024-11-27 21:28:28 +0000
commitc8ab1db0c65f4ffbdebd384abba455af005bd0a5 (patch)
tree3596a893fb98ec8ebd55fbfa22ea1e34e7578f19
parent386b5a9ddfab9c0a2855c4a9f90e9d5ecd0483b0 (diff)
drivers/wifi: Support Extended Bluetooth Regulatory Descriptor
Extended Bluetooth Regulatory Descriptor (EBRD) SAR/RFE are safety regulations for limiting antenna radiation near human contact. EBRD provides option to provide up to three sets of TX power limits and power restrictions. As the EBRD table is related to the revision 2 of the BRDS, this commit also adds support for this new revision. The implementation follows document 559910 Intel Connectivity Platforms BIOS Guideline revision 9.2 specification. BUG=b:346600091 TEST=EBRD method is added to the bluetooth companion device and return the data supplied by the SAR binary blob Change-Id: Iebe95815c944d045f4cf686abcd1874a8a45e250 Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/84947 Reviewed-by: Subrata Banik <subratabanik@google.com> Reviewed-by: Kapil Porwal <kapilporwal@google.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
-rw-r--r--src/drivers/wifi/generic/acpi.c62
-rw-r--r--src/include/sar.h46
-rw-r--r--src/vendorcode/google/chromeos/sar.c15
3 files changed, 108 insertions, 15 deletions
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c
index 3cd55e36fe..be44f6b907 100644
--- a/src/drivers/wifi/generic/acpi.c
+++ b/src/drivers/wifi/generic/acpi.c
@@ -599,7 +599,7 @@ static void sar_emit_brds(const struct bsar_profile *bsar)
* }
* })
*/
- if (bsar->revision != BSAR_REVISION) {
+ if (bsar->revision == 0 || bsar->revision > MAX_BSAR_REVISION) {
printk(BIOS_ERR, "Unsupported BSAR table revision: %d\n",
bsar->revision);
return;
@@ -609,11 +609,14 @@ static void sar_emit_brds(const struct bsar_profile *bsar)
acpigen_write_package(2);
acpigen_write_dword(bsar->revision);
- table_size = sizeof(*bsar) -
- offsetof(struct bsar_profile, sar_lb_power_restriction);
+ if (bsar->revision == 1)
+ table_size = sizeof(bsar->revs.rev1);
+ else
+ table_size = sizeof(bsar->revs.rev2);
+
/*
* Emit 'Domain Type' + 'Dynamic SAR Enable' + 'Increase Power Mode'
- * + ('SAR Power Restriction' + SAR table).
+ * + ('SAR Power Restriction' + SAR table) | (Chain A and B SAR tables).
*/
package_size = 1 + 1 + 1 + table_size;
acpigen_write_package(package_size);
@@ -621,7 +624,7 @@ static void sar_emit_brds(const struct bsar_profile *bsar)
acpigen_write_dword(1);
acpigen_write_dword(bsar->increased_power_mode_limitation);
- set = (const uint8_t *)&bsar->sar_lb_power_restriction;
+ set = (const uint8_t *)&bsar->revs;
for (int i = 0; i < table_size; i++)
acpigen_write_byte(set[i]);
@@ -876,6 +879,54 @@ static void sar_emit_bdmm(const struct bdmm_profile *bdmm)
acpigen_write_package_end();
}
+static void sar_emit_ebrd(const struct ebrd_profile *ebrd)
+{
+ if (ebrd == NULL)
+ return;
+
+ size_t package_size, table_size;
+ const uint8_t *set;
+
+ /*
+ * Name ("EBRD", Package () {
+ * Revision,
+ * Package () {
+ * Domain Type, // 0x12:Bluetooth
+ * Dynamic SAR Enable,
+ * Number of Optional SAR,
+ * Three SAR Sets
+ * }
+ * })
+ */
+ if (ebrd->revision != EBRD_REVISION) {
+ printk(BIOS_ERR, "Unsupported EBRD table revision: %d\n",
+ ebrd->revision);
+ return;
+ }
+
+ acpigen_write_name("EBRD");
+ acpigen_write_package(2);
+ acpigen_write_dword(ebrd->revision);
+
+ /*
+ * Emit 'Domain Type' + 'Dynamic Sar Enabled' + 'Number of Optional SAR' +
+ * 'Three SAR Sets'
+ */
+ table_size = sizeof(*ebrd) - offsetof(struct ebrd_profile, sar_table_sets);
+ package_size = 1 + 1 + 1 + table_size;
+ acpigen_write_package(package_size);
+ acpigen_write_dword(DOMAIN_TYPE_BLUETOOTH);
+ acpigen_write_dword(ebrd->dynamic_sar_enable);
+ acpigen_write_dword(ebrd->number_of_optional_sar);
+
+ set = (const uint8_t *)&ebrd->sar_table_sets;
+ for (size_t i = 0; i < table_size; i++)
+ acpigen_write_byte(set[i]);
+
+ acpigen_write_package_end();
+ acpigen_write_package_end();
+}
+
static void emit_wifi_sar_acpi_structures(const struct device *dev,
union wifi_sar_limits *sar_limits)
{
@@ -1014,6 +1065,7 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco
sar_emit_bbsm(sar_limits.bbsm);
sar_emit_bucs(sar_limits.bucs);
sar_emit_bdmm(sar_limits.bdmm);
+ sar_emit_ebrd(sar_limits.ebrd);
acpigen_write_scope_end();
} else {
printk(BIOS_ERR, "Failed to get %s Bluetooth companion ACPI path\n",
diff --git a/src/include/sar.h b/src/include/sar.h
index 4643b24f86..44fcd1e322 100644
--- a/src/include/sar.h
+++ b/src/include/sar.h
@@ -9,9 +9,9 @@
#define MAX_DENYLIST_ENTRY 16
#define MAX_DSAR_SET_COUNT 3
#define MAX_GEO_OFFSET_REVISION 3
-#define MAX_PROFILE_COUNT 13
+#define MAX_PROFILE_COUNT 14
#define MAX_SAR_REVISION 2
-#define BSAR_REVISION 1
+#define MAX_BSAR_REVISION 2
#define WBEM_REVISION 0
#define BPAG_REVISION 2
#define BBFB_REVISION 1
@@ -19,6 +19,7 @@
#define BBSM_REVISION 1
#define BUCS_REVISION 1
#define BDMM_REVISION 1
+#define EBRD_REVISION 1
#define REVISION_SIZE 1
#define SAR_REV0_CHAINS_COUNT 2
#define SAR_REV0_SUBBANDS_COUNT 5
@@ -70,16 +71,32 @@ struct dsm_profile {
uint32_t rfi_mitigation;
};
+struct sar_power_table {
+ uint8_t restriction_for_2g4;
+ uint8_t restriction_for_5g2;
+ uint8_t restriction_for_5g8_5g9;
+ uint8_t restriction_for_6g1;
+ uint8_t restriction_for_6g3;
+} __packed;
+
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;
+ union {
+ struct rev1 {
+ 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;
+ } rev1;
+ struct rev2 {
+ struct sar_power_table set_1_chain_a;
+ struct sar_power_table set_1_chain_b;
+ } rev2;
+ } revs;
} __packed;
struct wbem_profile {
@@ -117,6 +134,16 @@ struct bdmm_profile {
uint8_t dual_mac_enable;
} __packed;
+struct ebrd_profile {
+ uint8_t revision;
+ uint32_t dynamic_sar_enable;
+ uint32_t number_of_optional_sar;
+ struct {
+ struct sar_power_table chain_a;
+ struct sar_power_table chain_b;
+ } sar_table_sets[3];
+} __packed;
+
struct sar_header {
char marker[SAR_STR_PREFIX_SIZE];
uint8_t version;
@@ -139,6 +166,7 @@ union wifi_sar_limits {
struct bbsm_profile *bbsm;
struct bucs_profile *bucs;
struct bdmm_profile *bdmm;
+ struct ebrd_profile *ebrd;
};
void *profile[MAX_PROFILE_COUNT];
};
diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c
index dd43c977df..6ebf931d7d 100644
--- a/src/vendorcode/google/chromeos/sar.c
+++ b/src/vendorcode/google/chromeos/sar.c
@@ -96,10 +96,14 @@ static size_t dsm_table_size(const struct dsm_profile *dsm)
static size_t bsar_table_size(const struct bsar_profile *bsar)
{
+ int revs_offset = offsetof(struct bsar_profile, revs);
+
if (bsar == NULL)
return 0;
- return sizeof(struct bsar_profile);
+ if (bsar->revision == 2)
+ return revs_offset + sizeof(bsar->revs.rev2);
+ return revs_offset + sizeof(bsar->revs.rev1);
}
static size_t wbem_table_size(const struct wbem_profile *wbem)
@@ -158,6 +162,14 @@ static size_t bdmm_table_size(const struct bdmm_profile *bdmm)
return sizeof(struct bdmm_profile);
}
+static size_t ebrd_table_size(const struct ebrd_profile *ebrd)
+{
+ if (ebrd == NULL)
+ return 0;
+
+ return sizeof(struct ebrd_profile);
+}
+
static bool valid_legacy_length(size_t bin_len)
{
if (bin_len == LEGACY_SAR_WGDS_BIN_SIZE)
@@ -217,6 +229,7 @@ static int fill_wifi_sar_limits(union wifi_sar_limits *sar_limits, const uint8_t
expected_sar_bin_size += bbsm_table_size(sar_limits->bbsm);
expected_sar_bin_size += bucs_table_size(sar_limits->bucs);
expected_sar_bin_size += bdmm_table_size(sar_limits->bdmm);
+ expected_sar_bin_size += ebrd_table_size(sar_limits->ebrd);
if (sar_bin_size != expected_sar_bin_size) {
printk(BIOS_ERR, "Invalid SAR size, expected: %zu, obtained: %zu\n",