1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name> 4 */ 5 #if defined(CONFIG_OF) && defined(CONFIG_MTD) 6 #include <linux/of.h> 7 #include <linux/of_net.h> 8 #include <linux/mtd/mtd.h> 9 #include <linux/mtd/partitions.h> 10 #include <linux/nvmem-consumer.h> 11 #endif 12 #include <linux/etherdevice.h> 13 #include "mt76.h" 14 15 #if defined(CONFIG_OF) 16 static int mt76_get_of_eeprom_data(struct mt76_dev *dev, void *eep, int len) 17 { 18 struct device_node *np = dev->dev->of_node; 19 const void *data; 20 int size; 21 22 data = of_get_property(np, "mediatek,eeprom-data", &size); 23 if (!data) 24 return -ENOENT; 25 26 if (size > len) 27 return -EINVAL; 28 29 memcpy(eep, data, size); 30 31 return 0; 32 } 33 #endif 34 35 int mt76_get_of_data_from_mtd(struct mt76_dev *dev, void *eep, int offset, int len) 36 { 37 #if !defined(CONFIG_MTD) || !defined(CONFIG_OF) 38 return -ENOENT; 39 #else 40 struct device_node *np = dev->dev->of_node; 41 struct mtd_info *mtd; 42 const __be32 *list; 43 const char *part; 44 phandle phandle; 45 size_t retlen; 46 int size; 47 int ret; 48 49 list = of_get_property(np, "mediatek,mtd-eeprom", &size); 50 if (!list) 51 return -ENOENT; 52 53 phandle = be32_to_cpup(list++); 54 if (!phandle) 55 return -ENOENT; 56 57 np = of_find_node_by_phandle(phandle); 58 if (!np) 59 return -EINVAL; 60 61 part = of_get_property(np, "label", NULL); 62 if (!part) 63 part = np->name; 64 65 mtd = get_mtd_device_nm(part); 66 if (IS_ERR(mtd)) { 67 ret = PTR_ERR(mtd); 68 goto out_put_node; 69 } 70 71 if (size <= sizeof(*list)) { 72 ret = -EINVAL; 73 goto out_put_node; 74 } 75 76 offset += be32_to_cpup(list); 77 ret = mtd_read(mtd, offset, len, &retlen, eep); 78 put_mtd_device(mtd); 79 if (mtd_is_bitflip(ret)) 80 ret = 0; 81 if (ret) { 82 dev_err(dev->dev, "reading EEPROM from mtd %s failed: %i\n", 83 part, ret); 84 goto out_put_node; 85 } 86 87 if (retlen < len) { 88 ret = -EINVAL; 89 goto out_put_node; 90 } 91 92 if (of_property_read_bool(dev->dev->of_node, "big-endian")) { 93 u8 *data = (u8 *)eep; 94 int i; 95 96 /* convert eeprom data in Little Endian */ 97 for (i = 0; i < round_down(len, 2); i += 2) 98 put_unaligned_le16(get_unaligned_be16(&data[i]), 99 &data[i]); 100 } 101 102 #ifdef CONFIG_NL80211_TESTMODE 103 dev->test_mtd.name = devm_kstrdup(dev->dev, part, GFP_KERNEL); 104 if (!dev->test_mtd.name) { 105 ret = -ENOMEM; 106 goto out_put_node; 107 } 108 dev->test_mtd.offset = offset; 109 #endif 110 111 out_put_node: 112 of_node_put(np); 113 return ret; 114 #endif 115 } 116 EXPORT_SYMBOL_GPL(mt76_get_of_data_from_mtd); 117 118 int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep, 119 const char *cell_name, int len) 120 { 121 #if !defined(CONFIG_OF) 122 return -EOPNOTSUPP; 123 #else 124 struct device_node *np = dev->dev->of_node; 125 struct nvmem_cell *cell; 126 const void *data; 127 size_t retlen; 128 int ret = 0; 129 130 cell = of_nvmem_cell_get(np, cell_name); 131 if (IS_ERR(cell)) 132 return PTR_ERR(cell); 133 134 data = nvmem_cell_read(cell, &retlen); 135 nvmem_cell_put(cell); 136 137 if (IS_ERR(data)) 138 return PTR_ERR(data); 139 140 if (retlen < len) { 141 ret = -EINVAL; 142 goto exit; 143 } 144 145 memcpy(eep, data, len); 146 147 exit: 148 kfree(data); 149 150 return ret; 151 #endif 152 } 153 EXPORT_SYMBOL_GPL(mt76_get_of_data_from_nvmem); 154 155 static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len) 156 { 157 #if !defined(CONFIG_MTD) || !defined(CONFIG_OF) 158 return -ENOENT; 159 #else 160 struct device_node *np = dev->dev->of_node; 161 int ret; 162 163 if (!np) 164 return -ENOENT; 165 166 ret = mt76_get_of_eeprom_data(dev, eep, len); 167 if (!ret) 168 return 0; 169 170 ret = mt76_get_of_data_from_mtd(dev, eep, 0, len); 171 if (!ret) 172 return 0; 173 174 return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len); 175 #endif 176 } 177 178 int 179 mt76_eeprom_override(struct mt76_phy *phy) 180 { 181 struct mt76_dev *dev = phy->dev; 182 #if defined(CONFIG_OF) 183 struct device_node *np = dev->dev->of_node; 184 int err; 185 186 err = of_get_mac_address(np, phy->macaddr); 187 if (err == -EPROBE_DEFER) 188 return err; 189 #endif 190 191 if (!is_valid_ether_addr(phy->macaddr)) { 192 eth_random_addr(phy->macaddr); 193 dev_info(dev->dev, 194 #if defined(__linux__) 195 "Invalid MAC address, using random address %pM\n", 196 phy->macaddr); 197 #elif defined(__FreeBSD__) 198 "Invalid MAC address, using random address %6D\n", 199 phy->macaddr, ":"); 200 #endif 201 } 202 203 return 0; 204 } 205 EXPORT_SYMBOL_GPL(mt76_eeprom_override); 206 207 #if defined(CONFIG_OF) 208 static bool mt76_string_prop_find(struct property *prop, const char *str) 209 { 210 const char *cp = NULL; 211 212 if (!prop || !str || !str[0]) 213 return false; 214 215 while ((cp = of_prop_next_string(prop, cp)) != NULL) 216 if (!strcasecmp(cp, str)) 217 return true; 218 return false; 219 } 220 #endif 221 222 struct device_node * 223 mt76_find_power_limits_node(struct mt76_dev *dev) 224 { 225 #if !defined(CONFIG_OF) 226 return NULL; 227 #else 228 struct device_node *np = dev->dev->of_node; 229 const char *const region_names[] = { 230 [NL80211_DFS_UNSET] = "ww", 231 [NL80211_DFS_ETSI] = "etsi", 232 [NL80211_DFS_FCC] = "fcc", 233 [NL80211_DFS_JP] = "jp", 234 }; 235 struct device_node *cur, *fallback = NULL; 236 const char *region_name = NULL; 237 238 if (dev->region < ARRAY_SIZE(region_names)) 239 region_name = region_names[dev->region]; 240 241 np = of_get_child_by_name(np, "power-limits"); 242 if (!np) 243 return NULL; 244 245 for_each_child_of_node(np, cur) { 246 struct property *country = of_find_property(cur, "country", NULL); 247 struct property *regd = of_find_property(cur, "regdomain", NULL); 248 249 if (!country && !regd) { 250 fallback = cur; 251 continue; 252 } 253 254 if (mt76_string_prop_find(country, dev->alpha2) || 255 mt76_string_prop_find(regd, region_name)) { 256 of_node_put(np); 257 return cur; 258 } 259 } 260 261 of_node_put(np); 262 return fallback; 263 #endif 264 } 265 EXPORT_SYMBOL_GPL(mt76_find_power_limits_node); 266 267 #if defined(CONFIG_OF) 268 static const __be32 * 269 mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min) 270 { 271 struct property *prop = of_find_property(np, name, NULL); 272 273 if (!prop || !prop->value || prop->length < min * 4) 274 return NULL; 275 276 *len = prop->length; 277 278 return prop->value; 279 } 280 281 static const s8 * 282 mt76_get_of_array_s8(struct device_node *np, char *name, size_t *len, int min) 283 { 284 struct property *prop = of_find_property(np, name, NULL); 285 286 if (!prop || !prop->value || prop->length < min) 287 return NULL; 288 289 *len = prop->length; 290 291 return prop->value; 292 } 293 #endif 294 295 struct device_node * 296 mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) 297 { 298 #if defined(CONFIG_OF) 299 struct device_node *cur; 300 const __be32 *val; 301 size_t len; 302 303 for_each_child_of_node(np, cur) { 304 val = mt76_get_of_array(cur, "channels", &len, 2); 305 if (!val) 306 continue; 307 308 while (len >= 2 * sizeof(*val)) { 309 if (chan->hw_value >= be32_to_cpu(val[0]) && 310 chan->hw_value <= be32_to_cpu(val[1])) 311 return cur; 312 313 val += 2; 314 len -= 2 * sizeof(*val); 315 } 316 } 317 #endif 318 return NULL; 319 } 320 EXPORT_SYMBOL_GPL(mt76_find_channel_node); 321 322 #if defined(CONFIG_OF) 323 static s8 324 mt76_get_txs_delta(struct device_node *np, u8 nss) 325 { 326 const __be32 *val; 327 size_t len; 328 329 val = mt76_get_of_array(np, "txs-delta", &len, nss); 330 if (!val) 331 return 0; 332 333 return be32_to_cpu(val[nss - 1]); 334 } 335 336 static void 337 mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const s8 *data, 338 s8 target_power, s8 nss_delta, s8 *max_power) 339 { 340 int i; 341 342 if (!data) 343 return; 344 345 for (i = 0; i < pwr_len; i++) { 346 pwr[i] = min_t(s8, target_power, data[i] + nss_delta); 347 *max_power = max(*max_power, pwr[i]); 348 } 349 } 350 351 static void 352 mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, 353 const s8 *data, size_t len, s8 target_power, 354 s8 nss_delta) 355 { 356 int i, cur; 357 s8 max_power = -128; 358 359 if (!data) 360 return; 361 362 cur = data[0]; 363 for (i = 0; i < pwr_num; i++) { 364 if (len < pwr_len + 1) 365 break; 366 367 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1, 368 target_power, nss_delta, &max_power); 369 if (--cur > 0) 370 continue; 371 372 data += pwr_len + 1; 373 len -= pwr_len + 1; 374 if (!len) 375 break; 376 377 cur = data[0]; 378 } 379 } 380 #endif 381 382 s8 mt76_get_rate_power_limits(struct mt76_phy *phy, 383 struct ieee80211_channel *chan, 384 struct mt76_power_limits *dest, 385 s8 target_power) 386 { 387 struct mt76_dev *dev = phy->dev; 388 #if defined(CONFIG_OF) 389 struct device_node *np; 390 const s8 *val; 391 char name[16]; 392 #endif 393 u32 mcs_rates = dev->drv->mcs_rates; 394 #if defined(CONFIG_OF) 395 u32 ru_rates = ARRAY_SIZE(dest->ru[0]); 396 char band; 397 size_t len; 398 #endif 399 s8 max_power = 0; 400 #if defined(CONFIG_OF) 401 s8 txs_delta; 402 s8 max_power_backoff = -127; 403 s8 txs_delta; 404 int n_chains = hweight16(phy->chainmask); 405 s8 target_power_combine = target_power + mt76_tx_power_path_delta(n_chains); 406 #endif 407 408 if (!mcs_rates) 409 mcs_rates = 10; 410 411 memset(dest, target_power, sizeof(*dest) - sizeof(dest->path)); 412 memset(&dest->path, 0, sizeof(dest->path)); 413 414 if (!IS_ENABLED(CONFIG_OF)) 415 return target_power; 416 417 #if defined(CONFIG_OF) 418 np = mt76_find_power_limits_node(dev); 419 if (!np) 420 return target_power; 421 422 switch (chan->band) { 423 case NL80211_BAND_2GHZ: 424 band = '2'; 425 break; 426 case NL80211_BAND_5GHZ: 427 band = '5'; 428 break; 429 case NL80211_BAND_6GHZ: 430 band = '6'; 431 break; 432 default: 433 return target_power; 434 } 435 436 snprintf(name, sizeof(name), "txpower-%cg", band); 437 np = of_get_child_by_name(np, name); 438 if (!np) 439 return target_power; 440 441 np = mt76_find_channel_node(np, chan); 442 if (!np) 443 return target_power; 444 445 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask)); 446 447 val = mt76_get_of_array_s8(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); 448 mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val, 449 target_power, txs_delta, &max_power); 450 451 val = mt76_get_of_array_s8(np, "rates-ofdm", 452 &len, ARRAY_SIZE(dest->ofdm)); 453 mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val, 454 target_power, txs_delta, &max_power); 455 456 val = mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1); 457 mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), 458 ARRAY_SIZE(dest->mcs), val, len, 459 target_power, txs_delta); 460 461 val = mt76_get_of_array_s8(np, "rates-ru", &len, ru_rates + 1); 462 mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]), 463 ARRAY_SIZE(dest->ru), val, len, 464 target_power, txs_delta); 465 466 max_power_backoff = max_power; 467 val = mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path.cck)); 468 mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val, 469 target_power_combine, txs_delta, &max_power_backoff); 470 471 val = mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->path.ofdm)); 472 mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val, 473 target_power_combine, txs_delta, &max_power_backoff); 474 475 val = mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->path.ofdm_bf)); 476 mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf), val, 477 target_power_combine, txs_delta, &max_power_backoff); 478 479 val = mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.ru[0]) + 1); 480 mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0]), 481 ARRAY_SIZE(dest->path.ru), val, len, 482 target_power_combine, txs_delta); 483 484 val = mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->path.ru_bf[0]) + 1); 485 mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.ru_bf[0]), 486 ARRAY_SIZE(dest->path.ru_bf), val, len, 487 target_power_combine, txs_delta); 488 489 #endif 490 return max_power; 491 } 492 EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits); 493 494 int 495 mt76_eeprom_init(struct mt76_dev *dev, int len) 496 { 497 dev->eeprom.size = len; 498 dev->eeprom.data = devm_kzalloc(dev->dev, len, GFP_KERNEL); 499 if (!dev->eeprom.data) 500 return -ENOMEM; 501 502 return !mt76_get_of_eeprom(dev, dev->eeprom.data, len); 503 } 504 EXPORT_SYMBOL_GPL(mt76_eeprom_init); 505