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