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 */
44 struct generic_wifi_config {
45 unsigned int wake;
46 unsigned int maxsleep;
47 };
48
generic_wifi_fill_ssdt(struct acpi_ctx * ctx,const struct udevice * dev,const struct generic_wifi_config * config)49 static 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
intel_wifi_acpi_fill_ssdt(const struct udevice * dev,struct acpi_ctx * ctx)88 static 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
106 struct acpi_ops wifi_acpi_ops = {
107 .fill_ssdt = intel_wifi_acpi_fill_ssdt,
108 };
109
110 static const struct udevice_id intel_wifi_ids[] = {
111 { .compatible = "intel,generic-wifi" },
112 { }
113 };
114
115 U_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