blob: 61ec5391b0942f9dd8c862b080f299237b84b8e4 [file] [log] [blame]
Simon Glass4c69a5f2020-09-22 12:45:04 -06001// 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};