drivers/wifi: Add generic WiFi driver

Add generic WiFi driver to support common device operations across
multiple types of WiFi controller.

BUG=None
BRANCH=None
TEST=Boot to ChromeOS. Ensure that the SSDT table contains SAR tables
and wakeup GPE information. Ensure that the SSDT table is same after the
change.

Change-Id: Ica5edf95a37c8ed60f7e159d94fd58af5d41c0ef
Signed-off-by: Karthikeyan Ramasubramanian <kramasub@google.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/33155
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Furquan Shaikh <furquan@google.com>
This commit is contained in:
Karthikeyan Ramasubramanian 2019-05-29 15:09:42 -06:00 committed by Martin Roth
parent 328c8bbd23
commit fd5d788f5e
7 changed files with 367 additions and 252 deletions

View File

@ -2,52 +2,7 @@ config DRIVERS_INTEL_WIFI
bool "Support Intel PCI-e WiFi adapters" bool "Support Intel PCI-e WiFi adapters"
depends on ARCH_X86 depends on ARCH_X86
default y if PCIEXP_PLUGIN_SUPPORT default y if PCIEXP_PLUGIN_SUPPORT
select DRIVERS_GENERIC_WIFI if HAVE_ACPI_TABLES
help help
When enabled, add identifiers in ACPI and SMBIOS tables to When enabled, add identifiers in ACPI and SMBIOS tables to
make OS drivers work with certain Intel PCI-e WiFi chipsets. make OS drivers work with certain Intel PCI-e WiFi chipsets.
config USE_SAR
bool
default n
help
Enable it when wifi driver uses SAR configuration feature.
VPD entry "wifi_sar" is read to get SAR settings, if its
not found driver may look into CBFS for default settigs.
WIFI_SAR_CBFS is option to enable CBFS lookup.
config SAR_ENABLE
bool
default n
depends on USE_SAR
config DSAR_ENABLE
bool
default n
depends on USE_SAR
config GEO_SAR_ENABLE
bool
default n
depends on USE_SAR
config WIFI_SAR_CBFS
bool "Enable SAR table addition to CBFS"
default n
depends on USE_SAR
help
wifi driver would look for "wifi_sar" vpd key and load SAR settings from
it, if the vpd key is not found then the driver tries to look for sar
settings from CBFS with file name wifi_sar_defaults.hex.
So OEM/ODM can override wifi sar with VPD.
config WIFI_SAR_CBFS_FILEPATH
string "The cbfs file which has WIFI SAR defaults"
depends on WIFI_SAR_CBFS
default "src/mainboard/$(MAINBOARDDIR)/wifi_sar_defaults.hex"
config DSAR_SET_NUM
hex "Number of SAR sets when D-SAR is enabled"
default 0x3
depends on USE_SAR
help
There can be up to 3 optional SAR table sets.

View File

@ -13,26 +13,11 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#ifndef _WIFI_CHIP_H_ #ifndef _INTEL_WIFI_CHIP_H_
#define _WIFI_CHIP_H_ #define _INTEL_WIFI_CHIP_H_
/* WRDS Spec Revision */
#define WRDS_REVISION 0x0
/* EWRD Spec Revision */
#define EWRD_REVISION 0x0
/* WRDS Domain type */
#define WRDS_DOMAIN_TYPE_WIFI 0x7
/* EWRD Domain type */
#define EWRD_DOMAIN_TYPE_WIFI 0x7
/* WGDS Domain type */
#define WGDS_DOMAIN_TYPE_WIFI 0x7
struct drivers_intel_wifi_config { struct drivers_intel_wifi_config {
unsigned wake; /* Wake pin for ACPI _PRW */ unsigned int wake; /* Wake pin for ACPI _PRW */
}; };
#endif /* _WIFI_CHIP_H_ */ #endif /* _INTEL_WIFI_CHIP_H_ */

View File

@ -15,19 +15,16 @@
* GNU General Public License for more details. * GNU General Public License for more details.
*/ */
#include <arch/acpi_device.h>
#include <arch/acpigen.h>
#include <console/console.h> #include <console/console.h>
#include <device/device.h> #include <device/device.h>
#include <device/pci.h> #include <device/pci.h>
#include <device/pci_ops.h> #include <device/pci_ops.h>
#include <device/pci_ids.h> #include <device/pci_ids.h>
#include <elog.h> #include <elog.h>
#include <sar.h>
#include <smbios.h> #include <smbios.h>
#include <string.h> #include <string.h>
#include <wrdd.h>
#include "chip.h" #include "chip.h"
#include "drivers/wifi/generic_wifi.h"
#define PMCS_DR 0xcc #define PMCS_DR 0xcc
#define PME_STS (1 << 15) #define PME_STS (1 << 15)
@ -65,194 +62,18 @@ static int smbios_write_wifi(struct device *dev, int *handle,
} }
#endif #endif
__weak
int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
{
return -1;
}
#if CONFIG(HAVE_ACPI_TABLES) #if CONFIG(HAVE_ACPI_TABLES)
static void emit_sar_acpi_structures(void)
{
int i, j, package_size;
struct wifi_sar_limits sar_limits;
struct wifi_sar_delta_table *wgds;
/* Retrieve the sar limits data */
if (get_wifi_sar_limits(&sar_limits) < 0) {
printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
return;
}
/*
* Name ("WRDS", Package () {
* Revision,
* Package () {
* Domain Type, // 0x7:WiFi
* WiFi SAR BIOS, // BIOS SAR Enable/disable
* SAR Table Set // Set#1 of SAR Table (10 bytes)
* }
* })
*/
acpigen_write_name("WRDS");
acpigen_write_package(2);
acpigen_write_dword(WRDS_REVISION);
/* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
acpigen_write_package(package_size);
acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
acpigen_write_dword(CONFIG(SAR_ENABLE));
for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
acpigen_write_byte(sar_limits.sar_limit[0][i]);
acpigen_pop_len();
acpigen_pop_len();
/*
* Name ("EWRD", Package () {
* Revision,
* Package () {
* Domain Type, // 0x7:WiFi
* Dynamic SAR Enable, // Dynamic SAR Enable/disable
* Extended SAR sets, // Number of optional SAR table sets
* SAR Table Set, // Set#2 of SAR Table (10 bytes)
* SAR Table Set, // Set#3 of SAR Table (10 bytes)
* SAR Table Set // Set#4 of SAR Table (10 bytes)
* }
* })
*/
acpigen_write_name("EWRD");
acpigen_write_package(2);
acpigen_write_dword(EWRD_REVISION);
/*
* Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
* + number of bytes for Set#2 & 3 & 4
*/
package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
acpigen_write_package(package_size);
acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
acpigen_write_dword(CONFIG(DSAR_ENABLE));
acpigen_write_dword(CONFIG_DSAR_SET_NUM);
for (i = 1; i < NUM_SAR_LIMITS; i++)
for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
acpigen_write_byte(sar_limits.sar_limit[i][j]);
acpigen_pop_len();
acpigen_pop_len();
if (!CONFIG(GEO_SAR_ENABLE))
return;
/*
* Name ("WGDS", Package() {
* Revision,
* Package() {
* DomainType, // 0x7:WiFi
* WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
* WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
* WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
* WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
* WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
* WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
* WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
* WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
* WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
* WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
* WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
* WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
* WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
* WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
* WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
* WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
* WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
* WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
* }
* })
*/
wgds = &sar_limits.wgds;
acpigen_write_name("WGDS");
acpigen_write_package(2);
acpigen_write_dword(wgds->version);
/* Emit 'Domain Type' +
* Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
*/
package_size = sizeof(sar_limits.wgds.group) + 1;
acpigen_write_package(package_size);
acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
acpigen_write_byte(wgds->group[i].power_max_2400mhz);
acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
acpigen_write_byte(wgds->group[i].power_max_5200mhz);
acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
}
acpigen_pop_len();
acpigen_pop_len();
}
static void intel_wifi_fill_ssdt(struct device *dev) static void intel_wifi_fill_ssdt(struct device *dev)
{ {
struct drivers_intel_wifi_config *config = dev->chip_info; struct drivers_intel_wifi_config *config = dev->chip_info;
const char *path = acpi_device_path(dev->bus->dev); struct generic_wifi_config generic_config;
u32 address;
if (!path || !dev->enabled) if (config) {
return; generic_config.wake = config->wake;
/* By default, all intel wifi chips wake from S3 */
/* Device */ generic_config.maxsleep = 3;
acpigen_write_scope(path);
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name_integer("_UID", 0);
if (dev->chip_ops)
acpigen_write_name_string("_DDN", dev->chip_ops->name);
/* Address */
address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
address <<= 16;
address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
acpigen_write_name_dword("_ADR", address);
/* Wake capabilities */
if (config && config->wake)
acpigen_write_PRW(config->wake, 3);
/* Fill regulatory domain structure */
if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
/*
* Name ("WRDD", Package () {
* WRDD_REVISION, // Revision
* Package () {
* WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
* wifi_regulatory_domain() // Country Identifier
* }
* })
*/
acpigen_write_name("WRDD");
acpigen_write_package(2);
acpigen_write_integer(WRDD_REVISION);
acpigen_write_package(2);
acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
acpigen_write_dword(wifi_regulatory_domain());
acpigen_pop_len();
acpigen_pop_len();
} }
generic_wifi_fill_ssdt(dev, config ? &generic_config : NULL);
/* Fill Wifi sar related ACPI structures */
if (CONFIG(USE_SAR))
emit_sar_acpi_structures();
acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */
printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
}
static const char *intel_wifi_acpi_name(const struct device *dev)
{
return "WIFI";
} }
#endif #endif
@ -282,7 +103,7 @@ struct device_operations device_ops = {
#endif #endif
.ops_pci = &pci_ops, .ops_pci = &pci_ops,
#if CONFIG(HAVE_ACPI_TABLES) #if CONFIG(HAVE_ACPI_TABLES)
.acpi_name = intel_wifi_acpi_name, .acpi_name = generic_wifi_acpi_name,
.acpi_fill_ssdt_generator = intel_wifi_fill_ssdt, .acpi_fill_ssdt_generator = intel_wifi_fill_ssdt,
#endif #endif
}; };

57
src/drivers/wifi/Kconfig Normal file
View File

@ -0,0 +1,57 @@
config DRIVERS_GENERIC_WIFI
bool
default n
depends on HAVE_ACPI_TABLES
help
When enabled, add identifiers in ACPI tables that are common
to WiFi chipsets from multiple vendors.
if DRIVERS_GENERIC_WIFI
config USE_SAR
bool
default n
help
Enable it when wifi driver uses SAR configuration feature.
VPD entry "wifi_sar" is read to get SAR settings, if its
not found driver may look into CBFS for default settigs.
WIFI_SAR_CBFS is option to enable CBFS lookup.
config SAR_ENABLE
bool
default n
depends on USE_SAR
config DSAR_ENABLE
bool
default n
depends on USE_SAR
config GEO_SAR_ENABLE
bool
default n
depends on USE_SAR
config WIFI_SAR_CBFS
bool "Enable SAR table addition to CBFS"
default n
depends on USE_SAR
help
wifi driver would look for "wifi_sar" vpd key and load SAR settings from
it, if the vpd key is not found then the driver tries to look for sar
settings from CBFS with file name wifi_sar_defaults.hex.
So OEM/ODM can override wifi sar with VPD.
config WIFI_SAR_CBFS_FILEPATH
string "The cbfs file which has WIFI SAR defaults"
depends on WIFI_SAR_CBFS
default "src/mainboard/$(MAINBOARDDIR)/wifi_sar_defaults.hex"
config DSAR_SET_NUM
hex "Number of SAR sets when D-SAR is enabled"
default 0x3
depends on USE_SAR
help
There can be up to 3 optional SAR table sets.
endif # DRIVERS_GENERIC_WIFI

View File

@ -0,0 +1 @@
ramstage-$(CONFIG_DRIVERS_GENERIC_WIFI) += generic.c

245
src/drivers/wifi/generic.c Normal file
View File

@ -0,0 +1,245 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2019 Google LLC
*
* 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
* the Free Software Foundation; version 2 or (at your option)
* any later version of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <arch/acpi_device.h>
#include <arch/acpigen.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci_def.h>
#include <sar.h>
#include <string.h>
#include <wrdd.h>
#include "generic_wifi.h"
/* WRDS Spec Revision */
#define WRDS_REVISION 0x0
/* EWRD Spec Revision */
#define EWRD_REVISION 0x0
/* WRDS Domain type */
#define WRDS_DOMAIN_TYPE_WIFI 0x7
/* EWRD Domain type */
#define EWRD_DOMAIN_TYPE_WIFI 0x7
/* WGDS Domain type */
#define WGDS_DOMAIN_TYPE_WIFI 0x7
/*
* WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
* The above representation returns unique and consistent name every time
* generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
* chosen since it contains the bus address of the device.
*/
#define WIFI_ACPI_NAME_MAX_LEN 5
__weak
int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
{
return -1;
}
static void emit_sar_acpi_structures(void)
{
int i, j, package_size;
struct wifi_sar_limits sar_limits;
struct wifi_sar_delta_table *wgds;
/* Retrieve the sar limits data */
if (get_wifi_sar_limits(&sar_limits) < 0) {
printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
return;
}
/*
* Name ("WRDS", Package () {
* Revision,
* Package () {
* Domain Type, // 0x7:WiFi
* WiFi SAR BIOS, // BIOS SAR Enable/disable
* SAR Table Set // Set#1 of SAR Table (10 bytes)
* }
* })
*/
acpigen_write_name("WRDS");
acpigen_write_package(2);
acpigen_write_dword(WRDS_REVISION);
/* Emit 'Domain Type' + 'WiFi SAR BIOS' + 10 bytes for Set#1 */
package_size = 1 + 1 + BYTES_PER_SAR_LIMIT;
acpigen_write_package(package_size);
acpigen_write_dword(WRDS_DOMAIN_TYPE_WIFI);
acpigen_write_dword(CONFIG(SAR_ENABLE));
for (i = 0; i < BYTES_PER_SAR_LIMIT; i++)
acpigen_write_byte(sar_limits.sar_limit[0][i]);
acpigen_pop_len();
acpigen_pop_len();
/*
* Name ("EWRD", Package () {
* Revision,
* Package () {
* Domain Type, // 0x7:WiFi
* Dynamic SAR Enable, // Dynamic SAR Enable/disable
* Extended SAR sets, // Number of optional SAR table sets
* SAR Table Set, // Set#2 of SAR Table (10 bytes)
* SAR Table Set, // Set#3 of SAR Table (10 bytes)
* SAR Table Set // Set#4 of SAR Table (10 bytes)
* }
* })
*/
acpigen_write_name("EWRD");
acpigen_write_package(2);
acpigen_write_dword(EWRD_REVISION);
/*
* Emit 'Domain Type' + "Dynamic SAR Enable' + 'Extended SAR sets'
* + number of bytes for Set#2 & 3 & 4
*/
package_size = 1 + 1 + 1 + (NUM_SAR_LIMITS - 1) * BYTES_PER_SAR_LIMIT;
acpigen_write_package(package_size);
acpigen_write_dword(EWRD_DOMAIN_TYPE_WIFI);
acpigen_write_dword(CONFIG(DSAR_ENABLE));
acpigen_write_dword(CONFIG_DSAR_SET_NUM);
for (i = 1; i < NUM_SAR_LIMITS; i++)
for (j = 0; j < BYTES_PER_SAR_LIMIT; j++)
acpigen_write_byte(sar_limits.sar_limit[i][j]);
acpigen_pop_len();
acpigen_pop_len();
if (!CONFIG(GEO_SAR_ENABLE))
return;
/*
* Name ("WGDS", Package() {
* Revision,
* Package() {
* DomainType, // 0x7:WiFi
* WgdsWiFiSarDeltaGroup1PowerMax1, // Group 1 FCC 2400 Max
* WgdsWiFiSarDeltaGroup1PowerChainA1, // Group 1 FCC 2400 A Offset
* WgdsWiFiSarDeltaGroup1PowerChainB1, // Group 1 FCC 2400 B Offset
* WgdsWiFiSarDeltaGroup1PowerMax2, // Group 1 FCC 5200 Max
* WgdsWiFiSarDeltaGroup1PowerChainA2, // Group 1 FCC 5200 A Offset
* WgdsWiFiSarDeltaGroup1PowerChainB2, // Group 1 FCC 5200 B Offset
* WgdsWiFiSarDeltaGroup2PowerMax1, // Group 2 EC Jap 2400 Max
* WgdsWiFiSarDeltaGroup2PowerChainA1, // Group 2 EC Jap 2400 A Offset
* WgdsWiFiSarDeltaGroup2PowerChainB1, // Group 2 EC Jap 2400 B Offset
* WgdsWiFiSarDeltaGroup2PowerMax2, // Group 2 EC Jap 5200 Max
* WgdsWiFiSarDeltaGroup2PowerChainA2, // Group 2 EC Jap 5200 A Offset
* WgdsWiFiSarDeltaGroup2PowerChainB2, // Group 2 EC Jap 5200 B Offset
* WgdsWiFiSarDeltaGroup3PowerMax1, // Group 3 ROW 2400 Max
* WgdsWiFiSarDeltaGroup3PowerChainA1, // Group 3 ROW 2400 A Offset
* WgdsWiFiSarDeltaGroup3PowerChainB1, // Group 3 ROW 2400 B Offset
* WgdsWiFiSarDeltaGroup3PowerMax2, // Group 3 ROW 5200 Max
* WgdsWiFiSarDeltaGroup3PowerChainA2, // Group 3 ROW 5200 A Offset
* WgdsWiFiSarDeltaGroup3PowerChainB2, // Group 3 ROW 5200 B Offset
* }
* })
*/
wgds = &sar_limits.wgds;
acpigen_write_name("WGDS");
acpigen_write_package(2);
acpigen_write_dword(wgds->version);
/* Emit 'Domain Type' +
* Group specific delta of power (6 bytes * NUM_WGDS_SAR_GROUPS)
*/
package_size = sizeof(sar_limits.wgds.group) + 1;
acpigen_write_package(package_size);
acpigen_write_dword(WGDS_DOMAIN_TYPE_WIFI);
for (i = 0; i < SAR_NUM_WGDS_GROUPS; i++) {
acpigen_write_byte(wgds->group[i].power_max_2400mhz);
acpigen_write_byte(wgds->group[i].power_chain_a_2400mhz);
acpigen_write_byte(wgds->group[i].power_chain_b_2400mhz);
acpigen_write_byte(wgds->group[i].power_max_5200mhz);
acpigen_write_byte(wgds->group[i].power_chain_a_5200mhz);
acpigen_write_byte(wgds->group[i].power_chain_b_5200mhz);
}
acpigen_pop_len();
acpigen_pop_len();
}
void generic_wifi_fill_ssdt(struct device *dev,
const struct generic_wifi_config *config)
{
const char *path;
u32 address;
if (!dev->enabled)
return;
path = acpi_device_path(dev->bus->dev);
if (!path)
return;
/* Device */
acpigen_write_scope(path);
acpigen_write_device(acpi_device_name(dev));
acpigen_write_name_integer("_UID", 0);
if (dev->chip_ops)
acpigen_write_name_string("_DDN", dev->chip_ops->name);
/* Address */
address = PCI_SLOT(dev->path.pci.devfn) & 0xffff;
address <<= 16;
address |= PCI_FUNC(dev->path.pci.devfn) & 0xffff;
acpigen_write_name_dword("_ADR", address);
/* Wake capabilities */
if (config)
acpigen_write_PRW(config->wake, config->maxsleep);
/* Fill regulatory domain structure */
if (CONFIG(HAVE_REGULATORY_DOMAIN)) {
/*
* Name ("WRDD", Package () {
* WRDD_REVISION, // Revision
* Package () {
* WRDD_DOMAIN_TYPE_WIFI, // Domain Type, 7:WiFi
* wifi_regulatory_domain() // Country Identifier
* }
* })
*/
acpigen_write_name("WRDD");
acpigen_write_package(2);
acpigen_write_integer(WRDD_REVISION);
acpigen_write_package(2);
acpigen_write_dword(WRDD_DOMAIN_TYPE_WIFI);
acpigen_write_dword(wifi_regulatory_domain());
acpigen_pop_len();
acpigen_pop_len();
}
/* Fill Wifi sar related ACPI structures */
if (CONFIG(USE_SAR))
emit_sar_acpi_structures();
acpigen_pop_len(); /* Device */
acpigen_pop_len(); /* Scope */
printk(BIOS_INFO, "%s.%s: %s %s\n", path, acpi_device_name(dev),
dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
}
const char *generic_wifi_acpi_name(const struct device *dev)
{
static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
snprintf(wifi_acpi_name, sizeof(wifi_acpi_name), "WF%02x",
(dev_path_encode(dev) & 0xff));
return wifi_acpi_name;
}

View File

@ -0,0 +1,51 @@
/*
* This file is part of the coreboot project.
*
* Copyright 2019 Google LLC
*
* 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
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _GENERIC_WIFI_H_
#define _GENERIC_WIFI_H_
/**
* struct generic_wifi_config - Data structure to contain common wifi config
* @wake: Wake pin for ACPI _PRW
* @maxsleep: Maximum sleep state to wake from
*/
struct generic_wifi_config {
unsigned int wake;
unsigned int maxsleep;
};
/**
* wifi_fill_ssdt() - Fill ACPI SSDT table for WiFi controller
* @dev: Device structure corresponding to WiFi controller.
* @config: Common wifi config required to fill ACPI SSDT table.
*
* This function implements common device operation to help fill ACPI SSDT
* table for WiFi controller.
*/
void generic_wifi_fill_ssdt(struct device *dev,
const struct generic_wifi_config *config);
/**
* wifi_acpi_name() - Get ACPI name for WiFi controller
* @dev: Device structure corresponding to WiFi controller.
*
* This function implements common device operation to get the ACPI name for
* WiFi controller.
*
* Return: string representing the ACPI name for WiFi controller.
*/
const char *generic_wifi_acpi_name(const struct device *dev);
#endif /* _GENERIC_WIFI_H_ */