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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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