uboot/arch/x86/cpu/intel_common/generic_wifi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Generic WiFi ACPI info
   4 *
   5 * Copyright 2019 Google LLC
   6 * Modified from coreboot src/drivers/wifi/generic.c
   7 */
   8
   9#include <common.h>
  10#include <log.h>
  11#include <acpi/acpigen.h>
  12#include <acpi/acpi_device.h>
  13#include <dm.h>
  14#include <dm/acpi.h>
  15
  16/* WRDS Spec Revision */
  17#define WRDS_REVISION 0x0
  18
  19/* EWRD Spec Revision */
  20#define EWRD_REVISION 0x0
  21
  22/* WRDS Domain type */
  23#define WRDS_DOMAIN_TYPE_WIFI 0x7
  24
  25/* EWRD Domain type */
  26#define EWRD_DOMAIN_TYPE_WIFI 0x7
  27
  28/* WGDS Domain type */
  29#define WGDS_DOMAIN_TYPE_WIFI 0x7
  30
  31/*
  32 * WIFI ACPI NAME = "WF" + hex value of last 8 bits of dev_path_encode + '\0'
  33 * The above representation returns unique and consistent name every time
  34 * generate_wifi_acpi_name is invoked. The last 8 bits of dev_path_encode is
  35 * chosen since it contains the bus address of the device.
  36 */
  37#define WIFI_ACPI_NAME_MAX_LEN 5
  38
  39/**
  40 * struct generic_wifi_config - Data structure to contain common wifi config
  41 * @wake: Wake pin for ACPI _PRW
  42 * @maxsleep: Maximum sleep state to wake from
  43 */
  44struct generic_wifi_config {
  45        unsigned int wake;
  46        unsigned int maxsleep;
  47};
  48
  49static int generic_wifi_fill_ssdt(struct acpi_ctx *ctx,
  50                                  const struct udevice *dev,
  51                                  const struct generic_wifi_config *config)
  52{
  53        char name[ACPI_NAME_MAX];
  54        char path[ACPI_PATH_MAX];
  55        pci_dev_t bdf;
  56        u32 address;
  57        int ret;
  58
  59        ret = acpi_device_path(dev_get_parent(dev), path, sizeof(path));
  60        if (ret)
  61                return log_msg_ret("path", ret);
  62        ret = acpi_get_name(dev, name);
  63        if (ret)
  64                return log_msg_ret("name", ret);
  65
  66        /* Device */
  67        acpigen_write_scope(ctx, path);
  68        acpigen_write_device(ctx, name);
  69        acpigen_write_name_integer(ctx, "_UID", 0);
  70        acpigen_write_name_string(ctx, "_DDN",
  71                                  dev_read_string(dev, "acpi,ddn"));
  72
  73        /* Address */
  74        bdf = dm_pci_get_bdf(dev);
  75        address = (PCI_DEV(bdf) << 16) | PCI_FUNC(bdf);
  76        acpigen_write_name_dword(ctx, "_ADR", address);
  77
  78        /* Wake capabilities */
  79        if (config)
  80                acpigen_write_prw(ctx, config->wake, config->maxsleep);
  81
  82        acpigen_pop_len(ctx); /* Device */
  83        acpigen_pop_len(ctx); /* Scope */
  84
  85        return 0;
  86}
  87
  88static int intel_wifi_acpi_fill_ssdt(const struct udevice *dev,
  89                                     struct acpi_ctx *ctx)
  90{
  91        struct generic_wifi_config config;
  92        bool have_config;
  93        int ret;
  94
  95        ret = dev_read_u32(dev, "acpi,wake", &config.wake);
  96        have_config = !ret;
  97        /* By default, all intel wifi chips wake from S3 */
  98        config.maxsleep = 3;
  99        ret = generic_wifi_fill_ssdt(ctx, dev, have_config ? &config : NULL);
 100        if (ret)
 101                return log_msg_ret("wifi", ret);
 102
 103        return 0;
 104}
 105
 106struct acpi_ops wifi_acpi_ops = {
 107        .fill_ssdt      = intel_wifi_acpi_fill_ssdt,
 108};
 109
 110static const struct udevice_id intel_wifi_ids[] = {
 111        { .compatible = "intel,generic-wifi" },
 112        { }
 113};
 114
 115U_BOOT_DRIVER(intel_wifi) = {
 116        .name           = "intel_wifi",
 117        .id             = UCLASS_MISC,
 118        .of_match       = intel_wifi_ids,
 119        ACPI_OPS_PTR(&wifi_acpi_ops)
 120};
 121