drivers/wifi: Add MTCL function to ACPI SSDT

The MTCL function provides a country list to the Linux kernel via an
ACPI function in SSDT for MediaTek WiFi chipsets that are capable of
operating on the 6GHz band. The country list is used to selectively
disable 6GHz and 5.9GHz operation based on the country the device is
operating in.

The function needs to read a binary file and send it as a package via
the MTCL method in SSDT for PCIe WiFi with MediaTek chipsets.

Change Summary:
* Add src/drivers/wifi/generic/mtcl.c to abstract functionaltity related
  to MTCL
  * Add write_mtcl_aml function to convert the byte data into the format
    expected by the MTCL functionality in the Linux kernel.
  * Add validate_mtcl function to validate that the byte data read in
    from a file is in the expected format.
  * Add write_mtcl_function function to read a binary file called
    "wifi_mtcl".bin" from cbfs, then call validate_mtcl to verify that
    it is in an expected format, and if so write the aml via acpigen
* Add config flag DRIVERS_MTK_WIFI to src/drivers/wifi/generic in order
  to include MediaTek WiFi specific functionality
  * Add config flag USE_MTCL which depends on DRIVERS_MTK_WIFI and
    enables including the specific ACPI function defined in SSDT
  * Add config flag CONFIG_MTCL_CBFS_FILEPATH which depends on
    DRIVERS_MTK_WIFI which enables configuring the file to add as
    "wifi_mtcl.bin"
* Add a call to write_mtcl_function to src/drivers/wifi/generic/acpi.c
  to include the MTCL function in SSDT for MTK WiFi devices when
  USE_MTCL is enabled.
* Add MediaTek VID to src/include/device/pci_ids.h.

BUG=b:295544553
TEST=Add Kconfig entry USE_MTCL for pujjo
TEST=Add wifi_mtcl_defaults.bin blob to cbfs
TEST=Build coreboot for pujjo `emerge-nissa coreboot chromeos-bootimage`
TEST=Verify that MTCL defined in the file is present:
TEST=`acpidump -b`
TEST=`iasl ssdt.dat`
TEST=`less ssdt.dsl`
TEST=Search for MTCL

Signed-off-by: David Ruth <druth@chromium.org>
Change-Id: I9b5e7312a44e114270e664b983626faa6cfee350
Reviewed-on: https://review.coreboot.org/c/coreboot/+/80170
Reviewed-by: Subrata Banik <subratabanik@google.com>
Reviewed-by: Martin L Roth <gaumless@gmail.com>
Reviewed-by: Kapil Porwal <kapilporwal@google.com>
Reviewed-by: Nico Huber <nico.h@gmx.de>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Eric Lai <ericllai@google.com>
This commit is contained in:
David Ruth 2023-12-06 21:39:54 +00:00 committed by Subrata Banik
parent 7201602a18
commit ea8330ed81
6 changed files with 223 additions and 1 deletions

View File

@ -14,6 +14,15 @@ config DRIVERS_INTEL_WIFI
When enabled, add identifiers in ACPI and SMBIOS tables to
make OS drivers work with certain Intel PCI-e WiFi chipsets.
config DRIVERS_MTK_WIFI
bool "Support MediaTek PCI-e WiFi adapters"
depends on PCI
default y if PCIEXP_PLUGIN_SUPPORT
select DRIVERS_WIFI_GENERIC
help
When enabled, add identifiers in ACPI tables to make OS
drivers work with certain MediaTek PCI-e WiFi chipsets.
if DRIVERS_WIFI_GENERIC
config USE_SAR
@ -50,3 +59,17 @@ config DSAR_SET_NUM
There can be up to 3 optional SAR table sets.
endif # DRIVERS_WIFI_GENERIC
config USE_MTCL
bool
default n
depends on DRIVERS_MTK_WIFI
help
When enabled, adds the MTCL function for MediaTek WiFi chipsets.
This function supplies country list information used to enable or
disable operation on 5.9GHz and 6GHz bands.
config WIFI_MTCL_CBFS_FILEPATH
string "The cbfs file which has WIFI MTCL defaults"
depends on USE_MTCL
default ""

View File

@ -8,6 +8,7 @@ romstage-y += generic.c
ramstage-y += generic.c
ramstage-$(CONFIG_GENERATE_SMBIOS_TABLES) += smbios.c
ramstage-$(CONFIG_HAVE_ACPI_TABLES) += acpi.c
ramstage-$(CONFIG_USE_MTCL) += mtcl.c
CONFIG_WIFI_SAR_CBFS_FILEPATH := $(call strip_quotes,$(CONFIG_WIFI_SAR_CBFS_FILEPATH))
@ -19,4 +20,14 @@ wifi_sar_defaults.hex-type := raw
endif
CONFIG_MTCL_CBFS_FILEPATH := $(call strip_quotes,$(CONFIG_MTCL_CBFS_FILEPATH))
ifneq ($(CONFIG_MTCL_CBFS_FILEPATH),)
cbfs-files-$(CONFIG_USE_MTCL) += wifi_mtcl.bin
wifi_mtcl.bin-file := $(CONFIG_MTCL_CBFS_FILEPATH)
wifi_mtcl.bin-type := raw
endif
endif

View File

@ -5,6 +5,7 @@
#include <acpi/acpigen_pci.h>
#include <console/console.h>
#include <device/pci_ids.h>
#include <mtcl.h>
#include <sar.h>
#include <stdlib.h>
#include <wrdd.h>
@ -576,7 +577,18 @@ static void wifi_ssdt_write_properties(const struct device *dev, const char *sco
acpigen_write_dsm_uuid_arr(dsm_ids, dsm_count);
acpigen_pop_len(); /* Scope */
/*
* Fill MediaTek MTCL related ACPI structure iff the device type is PCI,
* the device has the MediaTek vendor ID, and the MTCL feature is
* configured.
*/
if (CONFIG(USE_MTCL)) {
if (dev->path.type == DEVICE_PATH_PCI &&
dev->vendor == PCI_VID_MEDIATEK)
write_mtcl_function();
}
acpigen_write_scope_end(); /* Scope */
printk(BIOS_INFO, "%s: %s %s\n", scope, dev->chip_ops ? dev->chip_ops->name : "",
dev_path(dev));

View File

@ -0,0 +1,166 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <acpi/acpigen.h>
#include <cbfs.h>
#include <mtcl.h>
#include <stdint.h>
#include <string.h>
#define WIFI_MTCL_CBFS_DEFAULT_FILENAME "wifi_mtcl.bin"
#define MAX_VERSION 2
#define MAX_SUPPORT_STATE 2
#define COUNTRY_LIST_SIZE 6
#define NAME_SIZE 4
#define MTCL_NAME "MTCL"
/*
* Represent the structured MTCL data.
* This struct is used to cast from an array of uint8_t in order to help
* understand the semantic purpose of individual bytes. This struct is used in
* order to verify that the bytes included match the known MTCL data format.
* This struct is explicitly __packed because it is explicitly cast to from an
* array of uint8_t.
*/
struct wifi_mtcl {
uint8_t name[NAME_SIZE];
uint8_t revision;
uint8_t support_6ghz;
uint8_t country_list_6ghz[COUNTRY_LIST_SIZE];
uint8_t support_5p9ghz;
uint8_t country_list_5p9ghz[COUNTRY_LIST_SIZE];
} __packed;
void write_mtcl_aml(uint8_t *bytes, size_t count);
int validate_mtcl(uint8_t *mtcl_bytes, size_t count);
/*
* Generate ACPI AML code for MTCL method.
* This function takes as input an array of bytes that correspond to the value
* map to be passed as a package, as well as the count of bytes to be written.
*
* AML code generate would look like:
* Method(MTCL, 0, Serialized)
* {
* Name (LIST, Package()
* {
* // data table
* })
* Return (LIST)
* }
*/
void write_mtcl_aml(uint8_t *bytes, size_t count)
{
/* Method (MTCL, 0, Serialized) */
acpigen_write_method_serialized("MTCL", 0x0);
/* Name (LIST */
acpigen_write_name("LIST");
/* Package () */
acpigen_write_package(count);
/* Write the provided bytes. */
for (int i = 0; i < count; ++i)
acpigen_write_byte(bytes[i]);
acpigen_write_package_end(); /* Package */
/* Return MTCL */
acpigen_write_return_namestr("LIST");
acpigen_write_method_end(); /* Method MTCL */
}
/*
* Validate the WiFi MTCL data that is passed in from CBFS.
*
* Data is expected in the format:
* [Revision,
* 6GHz Support,
* 6GHz Country List,
* 5.9GHz Support,
* 5.9GHz Country List]
*
* The revision is expected to be "2".
*
* 6GHz support is a byte with the following states:
* - 0 - 6GHz operation disabled
* - 1 - 6GHz operation dictated by the country list and Operating System
* - 2 - 6GHz operation dictated by the Operating System
*
* 6GHz Country List is a set of 6 bytes that represent a bitmask of countries
* in which 6GHz operation is enabled.
*
* 5.9GHz Support is a byte with the following known states:
* - 0 - 5.9GHz operation disabled
* - 1 - 5.9GHz operation dictated by the country list and Operating System
* - 2 - 5.9GHz operation dictated by the Operating System
*
* 5.9GHz Country List is a set of 6 bytes that represent a bitmask of countries
* in which 5.9GHz operation is enabled
*
* Validation:
* - Verify that there are MTCL_SIZE bytes.
* - Verify that the name is MTCL_NAME.
* - Verify that the version is less than or equal to MAX_MTCL_VERSION.
* - Verify that the support bytes are less than or equal to the
* MAX_SUPPORT_STATE.
*
* Returns 0 for a valid file, -1 for an invalid file.
*/
int validate_mtcl(uint8_t *mtcl_bytes, size_t count)
{
if (!mtcl_bytes) {
printk(BIOS_ERR, "Failed to get the %s file size!\n",
WIFI_MTCL_CBFS_DEFAULT_FILENAME);
return -1;
}
if (count != sizeof(struct wifi_mtcl)) {
printk(BIOS_ERR, "Size of file read was: %zu, expected: %zu\n",
count, sizeof(struct wifi_mtcl));
return -1;
}
struct wifi_mtcl *mtcl = (struct wifi_mtcl *)mtcl_bytes;
if (strncmp(((char *)mtcl->name), MTCL_NAME, NAME_SIZE)) {
printk(BIOS_ERR, "MTCL string not present but expected\n");
return -1;
}
if (mtcl->revision > MAX_VERSION) {
printk(BIOS_ERR, "MTCL version too high\n");
return -1;
}
if (mtcl->support_6ghz > MAX_SUPPORT_STATE) {
printk(BIOS_ERR, "MTCL 6GHz support state too high\n");
return -1;
}
if (mtcl->support_5p9ghz > MAX_SUPPORT_STATE) {
printk(BIOS_ERR, "MTCL 5.9GHz support state too high\n");
return -1;
}
return 0;
}
/*
* Retrieve WiFi MTCL data from CBFS, decode it, validate it and write it to
* AML.
*
* Returns the number of bytes read.
*/
void write_mtcl_function(void)
{
size_t mtcl_bin_len;
uint8_t *mtcl_bin;
mtcl_bin = cbfs_map(WIFI_MTCL_CBFS_DEFAULT_FILENAME, &mtcl_bin_len);
if (validate_mtcl(mtcl_bin, mtcl_bin_len) == 0)
write_mtcl_aml(mtcl_bin, mtcl_bin_len);
cbfs_unmap(mtcl_bin);
}

View File

@ -4857,6 +4857,8 @@
#define PCI_DID_SIS_SIS968_PCIE 0x000a /* D6F0,D7F0 */
#define PCI_DID_SIS_SIS968_HD_AUDIO 0x7502 /* DfF0 */
#define PCI_VID_MEDIATEK 0x14c3
/* OLD USAGE FOR COREBOOT */
#define PCI_VID_ACER 0x10b9
#define PCI_DID_ACER_M1535D 0x1533

8
src/include/mtcl.h Normal file
View File

@ -0,0 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _MTCL_H_
#define _MTCL_H_
void write_mtcl_function(void);
#endif /* _MTCL_H_ */