1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2023 MediaTek Inc. */
3
4 #include <linux/acpi.h>
5 #include "mt792x.h"
6
7 static const char * const cc_list_all[] = {
8 "00", "EU", "AR", "AU", "AZ", "BY", "BO", "BR",
9 "CA", "CL", "CN", "ID", "JP", "MY", "MX", "ME",
10 "MA", "NZ", "NG", "PH", "RU", "RS", "SG", "KR",
11 "TW", "TH", "UA", "GB", "US", "VN", "KH", "PY",
12 };
13
14 static const char * const cc_list_eu[] = {
15 "AD", "AT", "BE", "BG", "CY", "CZ", "HR", "DK",
16 "EE", "FI", "FR", "DE", "GR", "HU", "IS", "IE",
17 "IT", "LV", "LI", "LT", "LU", "MC", "MT", "NL",
18 "NO", "PL", "PT", "RO", "SK", "SI", "ES", "SE",
19 "CH",
20 };
21
22 static const char * const cc_list_be[] = {
23 "AR", "BR", "BY", "CL", "IQ", "MX", "OM", "RU",
24 "RW", "VN", "KR", "UA", "", "", "", "",
25 "EU", "AT", "CN", "CA", "TW", "NZ", "PH", "UK",
26 "US",
27 };
28
29 static int
mt792x_acpi_read(struct mt792x_dev * dev,u8 * method,u8 ** tbl,u32 * len)30 mt792x_acpi_read(struct mt792x_dev *dev, u8 *method, u8 **tbl, u32 *len)
31 {
32 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
33 struct mt76_dev *mdev = &dev->mt76;
34 union acpi_object *sar_root;
35 acpi_handle root, handle;
36 acpi_status status;
37 u32 i = 0;
38 int ret;
39
40 root = ACPI_HANDLE(mdev->dev);
41 if (!root)
42 return -EOPNOTSUPP;
43
44 status = acpi_get_handle(root, method, &handle);
45 if (ACPI_FAILURE(status))
46 return -EIO;
47
48 status = acpi_evaluate_object(handle, NULL, NULL, &buf);
49 if (ACPI_FAILURE(status))
50 return -EIO;
51
52 sar_root = buf.pointer;
53 if (sar_root->type != ACPI_TYPE_PACKAGE ||
54 sar_root->package.count < 4 ||
55 sar_root->package.elements[0].type != ACPI_TYPE_INTEGER) {
56 dev_err(mdev->dev, "sar cnt = %d\n",
57 sar_root->package.count);
58 ret = -EINVAL;
59 goto free;
60 }
61
62 if (!*tbl) {
63 *tbl = devm_kzalloc(mdev->dev, sar_root->package.count,
64 GFP_KERNEL);
65 if (!*tbl) {
66 ret = -ENOMEM;
67 goto free;
68 }
69 }
70
71 if (len)
72 *len = sar_root->package.count;
73
74 for (i = 0; i < sar_root->package.count; i++) {
75 union acpi_object *sar_unit = &sar_root->package.elements[i];
76
77 if (sar_unit->type != ACPI_TYPE_INTEGER)
78 break;
79
80 *(*tbl + i) = (u8)sar_unit->integer.value;
81 }
82
83 ret = i == sar_root->package.count ? 0 : -EINVAL;
84 free:
85 kfree(sar_root);
86
87 return ret;
88 }
89
90 /* MTCL : Country List Table for 6G band */
91 /* MTCL : Country List Table for 6G band and 11BE */
92 static int
mt792x_asar_acpi_read_mtcl(struct mt792x_dev * dev,u8 ** table,u8 * version)93 mt792x_asar_acpi_read_mtcl(struct mt792x_dev *dev, u8 **table, u8 *version)
94 {
95 int len, ret;
96
97 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTCL, table, &len);
98 if (ret)
99 return ret;
100
101 if (len == sizeof(struct mt792x_asar_cl))
102 *version = ((struct mt792x_asar_cl *)*table)->version;
103 else if (len == sizeof(struct mt792x_asar_cl_v3))
104 *version = ((struct mt792x_asar_cl_v3 *)*table)->version;
105 else
106 return -EINVAL;
107
108 return ret;
109 }
110
111 /* MTDS : Dynamic SAR Power Table */
112 static int
mt792x_asar_acpi_read_mtds(struct mt792x_dev * dev,u8 ** table,u8 version)113 mt792x_asar_acpi_read_mtds(struct mt792x_dev *dev, u8 **table, u8 version)
114 {
115 int len, ret, sarlen, prelen, tblcnt;
116 bool enable;
117
118 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTDS, table, &len);
119 if (ret)
120 return ret;
121
122 /* Table content validation */
123 switch (version) {
124 case 1:
125 enable = ((struct mt792x_asar_dyn *)*table)->enable;
126 sarlen = sizeof(struct mt792x_asar_dyn_limit);
127 prelen = sizeof(struct mt792x_asar_dyn);
128 break;
129 case 2:
130 enable = ((struct mt792x_asar_dyn_v2 *)*table)->enable;
131 sarlen = sizeof(struct mt792x_asar_dyn_limit_v2);
132 prelen = sizeof(struct mt792x_asar_dyn_v2);
133 break;
134 default:
135 return -EINVAL;
136 }
137
138 tblcnt = (len - prelen) / sarlen;
139 if (!enable ||
140 tblcnt > MT792x_ASAR_MAX_DYN || tblcnt < MT792x_ASAR_MIN_DYN)
141 return -EINVAL;
142
143 return 0;
144 }
145
146 /* MTGS : Geo SAR Power Table */
147 static int
mt792x_asar_acpi_read_mtgs(struct mt792x_dev * dev,u8 ** table,u8 version)148 mt792x_asar_acpi_read_mtgs(struct mt792x_dev *dev, u8 **table, u8 version)
149 {
150 int len, ret, sarlen, prelen, tblcnt;
151
152 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTGS, table, &len);
153 if (ret)
154 return ret;
155
156 /* Table content validation */
157 switch (version) {
158 case 1:
159 sarlen = sizeof(struct mt792x_asar_geo_limit);
160 prelen = sizeof(struct mt792x_asar_geo);
161 break;
162 case 2:
163 sarlen = sizeof(struct mt792x_asar_geo_limit_v2);
164 prelen = sizeof(struct mt792x_asar_geo_v2);
165 break;
166 default:
167 return -EINVAL;
168 }
169
170 tblcnt = (len - prelen) / sarlen;
171 if (tblcnt > MT792x_ASAR_MAX_GEO || tblcnt < MT792x_ASAR_MIN_GEO)
172 return -EINVAL;
173
174 return 0;
175 }
176
177 /* MTFG : Flag Table */
178 static int
mt792x_asar_acpi_read_mtfg(struct mt792x_dev * dev,u8 ** table)179 mt792x_asar_acpi_read_mtfg(struct mt792x_dev *dev, u8 **table)
180 {
181 int len, ret;
182
183 ret = mt792x_acpi_read(dev, MT792x_ACPI_MTFG, table, &len);
184 if (ret)
185 return ret;
186
187 if (len < MT792x_ASAR_MIN_FG)
188 return -EINVAL;
189
190 return 0;
191 }
192
mt792x_init_acpi_sar(struct mt792x_dev * dev)193 int mt792x_init_acpi_sar(struct mt792x_dev *dev)
194 {
195 struct mt792x_acpi_sar *asar;
196 int ret;
197
198 asar = devm_kzalloc(dev->mt76.dev, sizeof(*asar), GFP_KERNEL);
199 if (!asar)
200 return -ENOMEM;
201
202 ret = mt792x_asar_acpi_read_mtcl(dev, (u8 **)&asar->countrylist, &asar->ver);
203 if (ret) {
204 devm_kfree(dev->mt76.dev, asar->countrylist);
205 asar->countrylist = NULL;
206 }
207
208 ret = mt792x_asar_acpi_read_mtds(dev, (u8 **)&asar->dyn, asar->ver);
209 if (ret) {
210 devm_kfree(dev->mt76.dev, asar->dyn);
211 asar->dyn = NULL;
212 }
213
214 /* MTGS is optional */
215 ret = mt792x_asar_acpi_read_mtgs(dev, (u8 **)&asar->geo, asar->ver);
216 if (ret) {
217 devm_kfree(dev->mt76.dev, asar->geo);
218 asar->geo = NULL;
219 }
220
221 /* MTFG is optional */
222 ret = mt792x_asar_acpi_read_mtfg(dev, (u8 **)&asar->fg);
223 if (ret) {
224 devm_kfree(dev->mt76.dev, asar->fg);
225 asar->fg = NULL;
226 }
227 dev->phy.acpisar = asar;
228
229 return 0;
230 }
231 EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar);
232
233 static s8
mt792x_asar_get_geo_pwr(struct mt792x_phy * phy,enum nl80211_band band,s8 dyn_power)234 mt792x_asar_get_geo_pwr(struct mt792x_phy *phy,
235 enum nl80211_band band, s8 dyn_power)
236 {
237 struct mt792x_acpi_sar *asar = phy->acpisar;
238 struct mt792x_asar_geo_band *band_pwr;
239 s8 geo_power;
240 u8 idx, max;
241
242 if (!asar->geo)
243 return dyn_power;
244
245 switch (phy->mt76->dev->region) {
246 case NL80211_DFS_FCC:
247 idx = 0;
248 break;
249 case NL80211_DFS_ETSI:
250 idx = 1;
251 break;
252 default: /* WW */
253 idx = 2;
254 break;
255 }
256
257 if (asar->ver == 1) {
258 band_pwr = &asar->geo->tbl[idx].band[0];
259 max = ARRAY_SIZE(asar->geo->tbl[idx].band);
260 } else {
261 band_pwr = &asar->geo_v2->tbl[idx].band[0];
262 max = ARRAY_SIZE(asar->geo_v2->tbl[idx].band);
263 }
264
265 switch (band) {
266 case NL80211_BAND_2GHZ:
267 idx = 0;
268 break;
269 case NL80211_BAND_5GHZ:
270 idx = 1;
271 break;
272 case NL80211_BAND_6GHZ:
273 idx = 2;
274 break;
275 default:
276 return dyn_power;
277 }
278
279 if (idx >= max)
280 return dyn_power;
281
282 geo_power = (band_pwr + idx)->pwr;
283 dyn_power += (band_pwr + idx)->offset;
284
285 return min(geo_power, dyn_power);
286 }
287
288 static s8
mt792x_asar_range_pwr(struct mt792x_phy * phy,const struct cfg80211_sar_freq_ranges * range,u8 idx)289 mt792x_asar_range_pwr(struct mt792x_phy *phy,
290 const struct cfg80211_sar_freq_ranges *range,
291 u8 idx)
292 {
293 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
294 struct mt792x_acpi_sar *asar = phy->acpisar;
295 u8 *limit, band, max;
296
297 if (!capa)
298 return 127;
299
300 if (asar->ver == 1) {
301 limit = &asar->dyn->tbl[0].frp[0];
302 max = ARRAY_SIZE(asar->dyn->tbl[0].frp);
303 } else {
304 limit = &asar->dyn_v2->tbl[0].frp[0];
305 max = ARRAY_SIZE(asar->dyn_v2->tbl[0].frp);
306 }
307
308 if (idx >= max)
309 return 127;
310
311 if (range->start_freq >= 5945)
312 band = NL80211_BAND_6GHZ;
313 else if (range->start_freq >= 5150)
314 band = NL80211_BAND_5GHZ;
315 else
316 band = NL80211_BAND_2GHZ;
317
318 return mt792x_asar_get_geo_pwr(phy, band, limit[idx]);
319 }
320
mt792x_init_acpi_sar_power(struct mt792x_phy * phy,bool set_default)321 int mt792x_init_acpi_sar_power(struct mt792x_phy *phy, bool set_default)
322 {
323 const struct cfg80211_sar_capa *capa = phy->mt76->hw->wiphy->sar_capa;
324 int i;
325
326 if (!phy->acpisar || !((struct mt792x_acpi_sar *)phy->acpisar)->dyn)
327 return 0;
328
329 /* When ACPI SAR enabled in HW, we should apply rules for .frp
330 * 1. w/o .sar_specs : set ACPI SAR power as the defatul value
331 * 2. w/ .sar_specs : set power with min(.sar_specs, ACPI_SAR)
332 */
333 for (i = 0; i < capa->num_freq_ranges; i++) {
334 struct mt76_freq_range_power *frp = &phy->mt76->frp[i];
335
336 frp->range = set_default ? &capa->freq_ranges[i] : frp->range;
337 if (!frp->range)
338 continue;
339
340 frp->power = min_t(s8, set_default ? 127 : frp->power,
341 mt792x_asar_range_pwr(phy, frp->range, i));
342 }
343
344 return 0;
345 }
346 EXPORT_SYMBOL_GPL(mt792x_init_acpi_sar_power);
347
mt792x_acpi_get_flags(struct mt792x_phy * phy)348 u8 mt792x_acpi_get_flags(struct mt792x_phy *phy)
349 {
350 struct mt792x_acpi_sar *acpisar = phy->acpisar;
351 struct mt792x_asar_fg *fg;
352 struct {
353 u8 acpi_idx;
354 u8 chip_idx;
355 } map[] = {
356 { 1, 1 },
357 { 4, 2 },
358 };
359 u8 flags = BIT(0);
360 int i, j;
361
362 if (!acpisar)
363 return 0;
364
365 fg = acpisar->fg;
366 if (!fg)
367 return flags;
368
369 /* pickup necessary settings per device and
370 * translate the index of bitmap for chip command.
371 */
372 for (i = 0; i < fg->nr_flag; i++) {
373 for (j = 0; j < ARRAY_SIZE(map); j++) {
374 if (fg->flag[i] == map[j].acpi_idx) {
375 flags |= BIT(map[j].chip_idx);
376 break;
377 }
378 }
379 }
380
381 return flags;
382 }
383 EXPORT_SYMBOL_GPL(mt792x_acpi_get_flags);
384
385 static u32
mt792x_acpi_get_mtcl_map_v3(int row,int column,struct mt792x_asar_cl_v3 * cl)386 mt792x_acpi_get_mtcl_map_v3(int row, int column, struct mt792x_asar_cl_v3 *cl)
387 {
388 u32 config = 0;
389 u8 mode_be = 0;
390
391 mode_be = (cl->mode_be > 0x02) ? 0 : cl->mode_be;
392
393 if (cl->version > 2 && cl->clbe[row] & BIT(column))
394 config |= (mode_be & 0x3) << 4;
395
396 return config;
397 }
398
399 static u32
mt792x_acpi_get_mtcl_map(int row,int column,struct mt792x_asar_cl * cl)400 mt792x_acpi_get_mtcl_map(int row, int column, struct mt792x_asar_cl *cl)
401 {
402 u32 config = 0;
403 u8 mode_6g, mode_5g9;
404
405 mode_6g = (cl->mode_6g > 0x02) ? 0 : cl->mode_6g;
406 mode_5g9 = (cl->mode_5g9 > 0x01) ? 0 : cl->mode_5g9;
407
408 if ((cl->cl6g[row] & BIT(column)) || cl->mode_6g == 0x02)
409 config |= (mode_6g & 0x3) << 2;
410 if (cl->version > 1 && cl->cl5g9[row] & BIT(column))
411 config |= (mode_5g9 & 0x3);
412
413 return config;
414 }
415
416 static u32
mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy * phy,char * alpha2)417 mt792x_acpi_parse_mtcl_tbl_v3(struct mt792x_phy *phy, char *alpha2)
418 {
419 struct mt792x_acpi_sar *sar = phy->acpisar;
420 struct mt792x_asar_cl_v3 *cl = sar->countrylist_v3;
421 int col, row, i;
422
423 if (sar->ver != 3)
424 goto out;
425
426 if (!cl)
427 return MT792X_ACPI_MTCL_INVALID;
428
429 for (i = 0; i < ARRAY_SIZE(cc_list_be); i++) {
430 col = 7 - i % 8;
431 row = i / 8;
432 if (!memcmp(cc_list_be[i], alpha2, 2))
433 return mt792x_acpi_get_mtcl_map_v3(row, col, cl);
434 }
435 for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++) {
436 if (!memcmp(cc_list_eu[i], alpha2, 2))
437 return mt792x_acpi_get_mtcl_map_v3(3, 7, cl);
438 }
439
440 out:
441 /* Depends on driver */
442 return 0x20;
443 }
444
445 static u32
mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy * phy,char * alpha2)446 mt792x_acpi_parse_mtcl_tbl(struct mt792x_phy *phy, char *alpha2)
447 {
448 struct mt792x_acpi_sar *sar = phy->acpisar;
449 struct mt792x_asar_cl *cl = sar->countrylist;
450 int col, row, i;
451
452 if (!cl)
453 return MT792X_ACPI_MTCL_INVALID;
454
455 for (i = 0; i < ARRAY_SIZE(cc_list_all); i++) {
456 col = 7 - i % 8;
457 row = i / 8;
458 if (!memcmp(cc_list_all[i], alpha2, 2))
459 return mt792x_acpi_get_mtcl_map(row, col, cl);
460 }
461
462 for (i = 0; i < ARRAY_SIZE(cc_list_eu); i++)
463 if (!memcmp(cc_list_eu[i], alpha2, 2))
464 return mt792x_acpi_get_mtcl_map(0, 6, cl);
465
466 return mt792x_acpi_get_mtcl_map(0, 7, cl);
467 }
468
mt792x_acpi_get_mtcl_conf(struct mt792x_phy * phy,char * alpha2)469 u32 mt792x_acpi_get_mtcl_conf(struct mt792x_phy *phy, char *alpha2)
470 {
471 struct mt792x_acpi_sar *sar = phy->acpisar;
472 u32 config = 0;
473
474 if (!sar)
475 return MT792X_ACPI_MTCL_INVALID;
476
477 config = mt792x_acpi_parse_mtcl_tbl_v3(phy, alpha2);
478
479 if (config == MT792X_ACPI_MTCL_INVALID)
480 return MT792X_ACPI_MTCL_INVALID;
481
482 config |= mt792x_acpi_parse_mtcl_tbl(phy, alpha2);
483
484 return config;
485 }
486 EXPORT_SYMBOL_GPL(mt792x_acpi_get_mtcl_conf);
487