This source file includes following definitions.
- iwl_acpi_get_object
- iwl_acpi_get_wifi_pkg
- iwl_acpi_get_mcc
- iwl_acpi_get_pwr_limit
- iwl_acpi_get_eckv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 #include "iwl-drv.h"
62 #include "iwl-debug.h"
63 #include "acpi.h"
64
65 void *iwl_acpi_get_object(struct device *dev, acpi_string method)
66 {
67 acpi_handle root_handle;
68 acpi_handle handle;
69 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
70 acpi_status status;
71
72 root_handle = ACPI_HANDLE(dev);
73 if (!root_handle) {
74 IWL_DEBUG_DEV_RADIO(dev,
75 "Could not retrieve root port ACPI handle\n");
76 return ERR_PTR(-ENOENT);
77 }
78
79
80 status = acpi_get_handle(root_handle, method, &handle);
81 if (ACPI_FAILURE(status)) {
82 IWL_DEBUG_DEV_RADIO(dev, "%s method not found\n", method);
83 return ERR_PTR(-ENOENT);
84 }
85
86
87 status = acpi_evaluate_object(handle, NULL, NULL, &buf);
88 if (ACPI_FAILURE(status)) {
89 IWL_DEBUG_DEV_RADIO(dev, "%s invocation failed (0x%x)\n",
90 method, status);
91 return ERR_PTR(-ENOENT);
92 }
93
94 return buf.pointer;
95 }
96 IWL_EXPORT_SYMBOL(iwl_acpi_get_object);
97
98 union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev,
99 union acpi_object *data,
100 int data_size, int *tbl_rev)
101 {
102 int i;
103 union acpi_object *wifi_pkg;
104
105
106
107
108
109
110 if (WARN_ON_ONCE(data_size < 2))
111 return ERR_PTR(-EINVAL);
112
113
114
115
116
117
118
119 if (data->type != ACPI_TYPE_PACKAGE ||
120 data->package.count < 2 ||
121 data->package.elements[0].type != ACPI_TYPE_INTEGER ||
122 data->package.elements[0].integer.value > 1) {
123 IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n");
124 return ERR_PTR(-EINVAL);
125 }
126
127 *tbl_rev = data->package.elements[0].integer.value;
128
129
130 for (i = 1; i < data->package.count; i++) {
131 union acpi_object *domain;
132
133 wifi_pkg = &data->package.elements[i];
134
135
136 if (wifi_pkg->type != ACPI_TYPE_PACKAGE ||
137 wifi_pkg->package.count != data_size)
138 continue;
139
140 domain = &wifi_pkg->package.elements[0];
141 if (domain->type == ACPI_TYPE_INTEGER &&
142 domain->integer.value == ACPI_WIFI_DOMAIN)
143 goto found;
144 }
145
146 return ERR_PTR(-ENOENT);
147
148 found:
149 return wifi_pkg;
150 }
151 IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg);
152
153 int iwl_acpi_get_mcc(struct device *dev, char *mcc)
154 {
155 union acpi_object *wifi_pkg, *data;
156 u32 mcc_val;
157 int ret, tbl_rev;
158
159 data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD);
160 if (IS_ERR(data))
161 return PTR_ERR(data);
162
163 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE,
164 &tbl_rev);
165 if (IS_ERR(wifi_pkg)) {
166 ret = PTR_ERR(wifi_pkg);
167 goto out_free;
168 }
169
170 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
171 tbl_rev != 0) {
172 ret = -EINVAL;
173 goto out_free;
174 }
175
176 mcc_val = wifi_pkg->package.elements[1].integer.value;
177
178 mcc[0] = (mcc_val >> 8) & 0xff;
179 mcc[1] = mcc_val & 0xff;
180 mcc[2] = '\0';
181
182 ret = 0;
183 out_free:
184 kfree(data);
185 return ret;
186 }
187 IWL_EXPORT_SYMBOL(iwl_acpi_get_mcc);
188
189 u64 iwl_acpi_get_pwr_limit(struct device *dev)
190 {
191 union acpi_object *data, *wifi_pkg;
192 u64 dflt_pwr_limit;
193 int tbl_rev;
194
195 data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD);
196 if (IS_ERR(data)) {
197 dflt_pwr_limit = 0;
198 goto out;
199 }
200
201 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data,
202 ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev);
203 if (IS_ERR(wifi_pkg) || tbl_rev != 0 ||
204 wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) {
205 dflt_pwr_limit = 0;
206 goto out_free;
207 }
208
209 dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value;
210 out_free:
211 kfree(data);
212 out:
213 return dflt_pwr_limit;
214 }
215 IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit);
216
217 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk)
218 {
219 union acpi_object *wifi_pkg, *data;
220 int ret, tbl_rev;
221
222 data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD);
223 if (IS_ERR(data))
224 return PTR_ERR(data);
225
226 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE,
227 &tbl_rev);
228 if (IS_ERR(wifi_pkg)) {
229 ret = PTR_ERR(wifi_pkg);
230 goto out_free;
231 }
232
233 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER ||
234 tbl_rev != 0) {
235 ret = -EINVAL;
236 goto out_free;
237 }
238
239 *extl_clk = wifi_pkg->package.elements[1].integer.value;
240
241 ret = 0;
242
243 out_free:
244 kfree(data);
245 return ret;
246 }
247 IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv);