David Ruth has uploaded this change for review.

View Change

Add MTCL function to ACPI SSDT tables.

The MTCL function provides a country list to the Linux kernel via an
ACPI function in SSDT tables for MediaTek 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 chips for MediaTek chipsets.

BUG=b:295544553
TEST=Add Kconfig entry USE_MTCL for pujjo
TEST=Add wifi_mtcl_defaults.hex 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
---
M src/acpi/acpigen.c
M src/drivers/wifi/generic/Kconfig
M src/drivers/wifi/generic/Makefile.inc
M src/drivers/wifi/generic/acpi.c
M src/include/acpi/acpigen.h
M src/include/device/pci_ids.h
A src/include/mtcl.h
M src/vendorcode/google/chromeos/Makefile.inc
A src/vendorcode/google/chromeos/mtcl.c
9 files changed, 219 insertions(+), 1 deletion(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/70/80170/1
diff --git a/src/acpi/acpigen.c b/src/acpi/acpigen.c
index 64ec734..372660a 100644
--- a/src/acpi/acpigen.c
+++ b/src/acpi/acpigen.c
@@ -1925,6 +1925,44 @@
acpigen_pop_len(); /* Method _DSM */
}

+/*
+ * 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 acpigen_write_mtcl(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 */
+}
+
void acpigen_write_CPPC_package(const struct cppc_config *config)
{
u32 i;
diff --git a/src/drivers/wifi/generic/Kconfig b/src/drivers/wifi/generic/Kconfig
index 1d0e19f..18d9d84 100644
--- a/src/drivers/wifi/generic/Kconfig
+++ b/src/drivers/wifi/generic/Kconfig
@@ -14,6 +14,15 @@
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,21 @@
There can be up to 3 optional SAR table sets.

endif # DRIVERS_WIFI_GENERIC
+
+if DRIVERS_MTK_WIFI
+
+config USE_MTCL
+ bool
+ default n
+ 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 ""
+
+endif # DRIVERS_MTK_WIFI
diff --git a/src/drivers/wifi/generic/Makefile.inc b/src/drivers/wifi/generic/Makefile.inc
index 337b8fe..82c2cd9 100644
--- a/src/drivers/wifi/generic/Makefile.inc
+++ b/src/drivers/wifi/generic/Makefile.inc
@@ -19,4 +19,14 @@

endif

+CONFIG_WIFI_MTCL_CBFS_FILEPATH := $(call strip_quotes,$(CONFIG_WIFI_MTCL_CBFS_FILEPATH))
+
+ifneq ($(CONFIG_WIFI_MTCL_CBFS_FILEPATH),)
+
+cbfs-files-$(CONFIG_USE_MTCL) += wifi_mtcl_defaults.hex
+wifi_mtcl_defaults.hex-file := $(CONFIG_WIFI_MTCL_CBFS_FILEPATH)
+wifi_mtcl_defaults.hex-type := raw
+
+endif
+
endif
diff --git a/src/drivers/wifi/generic/acpi.c b/src/drivers/wifi/generic/acpi.c
index f37a084..3747aa8 100644
--- a/src/drivers/wifi/generic/acpi.c
+++ b/src/drivers/wifi/generic/acpi.c
@@ -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>
@@ -38,6 +39,11 @@
return -1;
}

+__weak int get_wifi_mtcl(uint8_t *mtcl_package)
+{
+ return -1;
+}
+
/*
* Function 1: Allow PC OEMs to set ETSI 5.8GHz SRD in Passive/Disabled ESTI SRD
* Channels: 149, 153, 157, 161, 165
@@ -576,7 +582,20 @@

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 (dev->path.type == DEVICE_PATH_PCI &&
+ dev->vendor == PCI_VID_MEDIATEK && CONFIG(USE_MTCL)) {
+ uint8_t mtcl_package[sizeof(struct wifi_mtcl)];
+ size_t mtcl_size = get_wifi_mtcl(mtcl_package);
+ if (mtcl_size > 0)
+ acpigen_write_mtcl(mtcl_package, mtcl_size);
+ }
+
+ acpigen_write_scope_end(); /* Scope */

printk(BIOS_INFO, "%s: %s %s\n", scope, dev->chip_ops ? dev->chip_ops->name : "",
dev_path(dev));
diff --git a/src/include/acpi/acpigen.h b/src/include/acpi/acpigen.h
index 7a5be51..0875fde 100644
--- a/src/include/acpi/acpigen.h
+++ b/src/include/acpi/acpigen.h
@@ -550,6 +550,13 @@

void acpigen_write_dsm_uuid_arr(struct dsm_uuid *ids, 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.
+ */
+void acpigen_write_mtcl(uint8_t *bytes, size_t count);
+/*
* Generate ACPI AML code for _CPC (Continuous Performance Control).
* Execute the package function once to create a global table, then
* execute the method function within each processor object to
diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
index ae74901..7e3910a 100644
--- a/src/include/device/pci_ids.h
+++ b/src/include/device/pci_ids.h
@@ -4785,6 +4785,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
diff --git a/src/include/mtcl.h b/src/include/mtcl.h
new file mode 100644
index 0000000..17db32a
--- /dev/null
+++ b/src/include/mtcl.h
@@ -0,0 +1,23 @@
+#ifndef _MTCL_H_
+#define _MTCL_H_
+
+#include <stdint.h>
+
+#define MAX_VERSION 2
+#define MAX_SUPPORT_STATE 2
+#define COUNTRY_LIST_SIZE 6
+#define NAME_SIZE 4
+#define MTCL_NAME "MTCL"
+
+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;
+
+int get_wifi_mtcl(uint8_t *mtcl);
+
+#endif /* _MTCL_H_ */
diff --git a/src/vendorcode/google/chromeos/Makefile.inc b/src/vendorcode/google/chromeos/Makefile.inc
index dce4d9c..b689829 100644
--- a/src/vendorcode/google/chromeos/Makefile.inc
+++ b/src/vendorcode/google/chromeos/Makefile.inc
@@ -8,6 +8,7 @@
ramstage-$(CONFIG_CHROMEOS_DISABLE_PLATFORM_HIERARCHY_ON_RESUME) += tpm2.c
ramstage-$(CONFIG_HAVE_REGULATORY_DOMAIN) += wrdd.c
ramstage-$(CONFIG_USE_SAR) += sar.c
+ramstage-$(CONFIG_USE_MTCL) += mtcl.c
ramstage-$(CONFIG_TPM_GOOGLE) += cr50_enable_update.c
ramstage-$(CONFIG_TPM_GOOGLE) += tpm_factory_config.c

diff --git a/src/vendorcode/google/chromeos/mtcl.c b/src/vendorcode/google/chromeos/mtcl.c
new file mode 100644
index 0000000..31a3c08
--- /dev/null
+++ b/src/vendorcode/google/chromeos/mtcl.c
@@ -0,0 +1,91 @@
+#include <cbfs.h>
+#include <mtcl.h>
+#include <string.h>
+
+#define WIFI_MTCL_CBFS_DEFAULT_FILENAME "wifi_mtcl.hex"
+
+/*
+ * Retrieve WiFi MTCL data from CBFS and decode it.
+ * 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 the number of bytes read.
+ */
+int get_wifi_mtcl(uint8_t *mtcl_package)
+{
+ size_t mtcl_bin_len;
+ uint8_t *mtcl_bin;
+ struct wifi_mtcl *mtcl;
+ int ret = -1;
+
+ mtcl_bin = cbfs_map(WIFI_MTCL_CBFS_DEFAULT_FILENAME, &mtcl_bin_len);
+ if (!mtcl_bin) {
+ printk(BIOS_ERR, "Failed to get the %s file size!\n",
+ WIFI_MTCL_CBFS_DEFAULT_FILENAME);
+ return ret;
+ }
+
+ if (mtcl_bin_len != sizeof(struct wifi_mtcl)) {
+ printk(BIOS_ERR, "Size of file read was: %lu, expected: %lu\n",
+ mtcl_bin_len, sizeof(struct wifi_mtcl));
+ goto error;
+ }
+
+ mtcl_package = memcpy(mtcl_package, mtcl_bin, sizeof(struct wifi_mtcl));
+ mtcl = (struct wifi_mtcl *)mtcl_package;
+
+ if (strncmp(((char *)mtcl->name), MTCL_NAME, NAME_SIZE)) {
+ printk(BIOS_ERR, "MTCL string not present but expected\n");
+ goto error;
+ }
+
+ if (mtcl->revision > MAX_VERSION) {
+ printk(BIOS_ERR, "MTCL version too high\n");
+ goto error;
+ }
+
+ if (mtcl->support_6ghz > MAX_SUPPORT_STATE) {
+ printk(BIOS_ERR, "MTCL 6GHz support state too high\n");
+ goto error;
+ }
+
+ if (mtcl->support_5p9ghz > MAX_SUPPORT_STATE) {
+ printk(BIOS_ERR, "MTCL 5.9GHz support state too high\n");
+ goto error;
+ }
+
+ ret = mtcl_bin_len;
+
+error:
+ cbfs_unmap(mtcl_bin);
+ return ret;
+}

To view, visit change 80170. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: main
Gerrit-Change-Id: I9b5e7312a44e114270e664b983626faa6cfee350
Gerrit-Change-Number: 80170
Gerrit-PatchSet: 1
Gerrit-Owner: David Ruth <druth@chromium.org>
Gerrit-MessageType: newchange