diff options
author | Pratik Prajapati <pratikkumar.v.prajapati@intel.com> | 2017-08-11 14:06:57 -0700 |
---|---|---|
committer | Patrick Georgi <pgeorgi@google.com> | 2018-07-13 10:42:04 +0000 |
commit | 7fd1e4b9b1f992b67a0bb2628130db42c0ab4dac (patch) | |
tree | 4880eab63f09b0c086ed72275094a2b8dd713bd8 /src/vendorcode | |
parent | 8919ac726bf9bbbd87bdbf806ecfe8c33cddec50 (diff) | |
download | coreboot-7fd1e4b9b1f992b67a0bb2628130db42c0ab4dac.tar.xz |
intel/wifi: Add WGDS ACPI method for Geo Aware SAR
To comply with all relevant bodies throughout the world, SAR settings
take into account the lowest common denominator Tx power settings. This
setup may lead to non-optimal performance when the user location is in a
country that may allow higher power setting. The purpose of Wireless Geo
Delta Settings (WGDS) is to provide offset settings for FCC, Europe,
Japan and Rest of the world. These offsets would be added (by Intel wifi
driver) to the base SAR Tx Power as defined in WRDS and EWRD
BUG=b:65155728
BRANCH=none
TEST=WGDS ACPI table gets created as expected.
Change-Id: I4f602e3f95ff3545db6cc6e428beb9a36abd9296
Signed-off-by: Pratik Prajapati <pratikkumar.v.prajapati@intel.com>
Reviewed-on: https://review.coreboot.org/21098
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Diffstat (limited to 'src/vendorcode')
-rw-r--r-- | src/vendorcode/google/chromeos/sar.c | 107 |
1 files changed, 83 insertions, 24 deletions
diff --git a/src/vendorcode/google/chromeos/sar.c b/src/vendorcode/google/chromeos/sar.c index 954492b822..fc72dc1348 100644 --- a/src/vendorcode/google/chromeos/sar.c +++ b/src/vendorcode/google/chromeos/sar.c @@ -1,7 +1,7 @@ /* * This file is part of the coreboot project. * - * Copyright (C) 2017 Intel Corp. + * Copyright (C) 2017-2018 Intel Corp. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -12,6 +12,8 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ + +#include <cbfs.h> #include <console/console.h> #include <lib.h> #include <types.h> @@ -19,44 +21,101 @@ #include <sar.h> #include "cros_vpd.h" -/* Retrieve the wifi SAR limits data from VPD and decode it */ +#define WIFI_SAR_CBFS_FILENAME "wifi_sar_defaults.hex" + +static int load_sar_file_from_cbfs(void *buf, size_t buffer_size) +{ + return cbfs_boot_load_file(WIFI_SAR_CBFS_FILENAME, buf, + buffer_size, CBFS_TYPE_RAW); +} + +/* Retrieve the wifi SAR limits data from VPD and decode it + +For VPD: key,value pair is in this format +"wifi_sar"=[<WRDD><EWRD>][WGDS] + +WIFI SAR data in CBFS file is expected in same format: [<WRDD><EWRD>][WGDS] + +[<WRDD><EWRD>] = NUM_SAR_LIMITS * BYTES_PER_SAR_LIMIT bytes. +[WGDS]=[WGDS_VERSION][WGDS_DATA] + +For [WGDS_VERSION] 0x00, +[WGDS_DATA] = [GROUP#0][GROUP#1][GROUP#2] + +[GROUP#<i>] = + [2.4Ghz – Max Allowed][2.4Ghz – Chain A Offset] + [2.4Ghz – Chain B Offset][5Ghz – Max Allowed] + [5Ghz – Chain A Offset][5Ghz – Chain B Offset] + +[GROUP#0] is for FCC +[GROUP#1] is for Europe/Japan +[GROUP#2] is for ROW + +*/ int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits) { const char *wifi_sar_limit_key = CROS_VPD_WIFI_SAR_NAME; - /* - * cros_vpd_gets() reads in one less than size characters from the VPD + /* cros_vpd_gets() reads in one less than size characters from the VPD * with a terminating null byte ('\0') stored as the last character into - * the buffer, thus the increasing by 1 for buffer_size. - */ + * the buffer, thus the increasing by 1 for buffer_size. */ const size_t buffer_size = (sizeof(struct wifi_sar_limits) / - sizeof(uint8_t)) * 2 + 1; + sizeof(uint8_t)) * 2 + 1; char wifi_sar_limit_str[buffer_size]; uint8_t bin_buffer[sizeof(struct wifi_sar_limits)]; - int i; + size_t sar_cbfs_len, sar_expected_len, bin_buff_adjusted_size; + + /* keep it backward compatible. Some older platform are shipping + without GEO SAR and so older wifi_sar VPD key */ + + sar_expected_len = buffer_size; + bin_buff_adjusted_size = sizeof(struct wifi_sar_limits); + + if (!IS_ENABLED(CONFIG_GEO_SAR_ENABLE)) { + sar_expected_len = buffer_size - + sizeof(struct wifi_sar_delta_table) * + sizeof(uint8_t) * 2; + bin_buff_adjusted_size = sizeof(struct wifi_sar_limits) - + sizeof(struct wifi_sar_delta_table); + } /* Try to read the SAR limit entry from VPD */ if (!cros_vpd_gets(wifi_sar_limit_key, wifi_sar_limit_str, - ARRAY_SIZE(wifi_sar_limit_str))) { - printk(BIOS_ERR, - "Error: Could not locate '%s' in VPD\n", - wifi_sar_limit_key); - return -1; + buffer_size)) { + printk(BIOS_ERR, "Error: Could not locate '%s' in VPD.\n", + wifi_sar_limit_key); + + if (!IS_ENABLED(CONFIG_WIFI_SAR_CBFS)) + return -1; + + printk(BIOS_DEBUG, "Checking CBFS for default SAR values\n"); + + sar_cbfs_len = load_sar_file_from_cbfs( + (void *) wifi_sar_limit_str, + sar_expected_len); + + if (sar_cbfs_len != sar_expected_len) { + printk(BIOS_ERR, "%s has bad len in CBFS\n", + WIFI_SAR_CBFS_FILENAME); + return -1; + } + } else { + /* VPD key "wifi_sar" found. strlen is checked with addition of + * 1 as we have created buffer size 1 char larger for the reason + * mentioned at start of this function itself */ + if (strlen(wifi_sar_limit_str) + 1 != sar_expected_len) { + printk(BIOS_ERR, "WIFI SAR key has bad len in VPD\n"); + return -1; + } } - printk(BIOS_DEBUG, "VPD wifi_sar = %s\n", wifi_sar_limit_str); /* Decode the heximal encoded string to binary values */ - if (hexstrtobin(wifi_sar_limit_str, bin_buffer, - sizeof(struct wifi_sar_limits)) - < sizeof(struct wifi_sar_limits)) { - printk(BIOS_ERR, - "Error: VPD wifi_sar contains non-heximal value!\n"); + if (hexstrtobin(wifi_sar_limit_str, bin_buffer, bin_buff_adjusted_size) + < bin_buff_adjusted_size) { + printk(BIOS_ERR, "Error: wifi_sar contains non-hex value!\n"); return -1; } - /* Fill the sar_limits structure with the decoded data */ - for (i = 0; i < NUM_SAR_LIMITS; i++) - memcpy(sar_limits->sar_limit[i], - &bin_buffer[BYTES_PER_SAR_LIMIT * i], - BYTES_PER_SAR_LIMIT); + memset(sar_limits, 0, sizeof(*sar_limits)); + memcpy(sar_limits, bin_buffer, bin_buff_adjusted_size); return 0; } |