1 // SPDX-License-Identifier: ISC 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 dev->test_mtd.offset = offset; 105 #endif 106 107 out_put_node: 108 of_node_put(np); 109 return ret; 110 #endif 111 } 112 EXPORT_SYMBOL_GPL(mt76_get_of_data_from_mtd); 113 114 int mt76_get_of_data_from_nvmem(struct mt76_dev *dev, void *eep, 115 const char *cell_name, int len) 116 { 117 #if !defined(CONFIG_OF) 118 return -EOPNOTSUPP; 119 #else 120 struct device_node *np = dev->dev->of_node; 121 struct nvmem_cell *cell; 122 const void *data; 123 size_t retlen; 124 int ret = 0; 125 126 cell = of_nvmem_cell_get(np, cell_name); 127 if (IS_ERR(cell)) 128 return PTR_ERR(cell); 129 130 data = nvmem_cell_read(cell, &retlen); 131 nvmem_cell_put(cell); 132 133 if (IS_ERR(data)) 134 return PTR_ERR(data); 135 136 if (retlen < len) { 137 ret = -EINVAL; 138 goto exit; 139 } 140 141 memcpy(eep, data, len); 142 143 exit: 144 kfree(data); 145 146 return ret; 147 #endif 148 } 149 EXPORT_SYMBOL_GPL(mt76_get_of_data_from_nvmem); 150 151 static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len) 152 { 153 #if !defined(CONFIG_MTD) || !defined(CONFIG_OF) 154 return -ENOENT; 155 #else 156 struct device_node *np = dev->dev->of_node; 157 int ret; 158 159 if (!np) 160 return -ENOENT; 161 162 ret = mt76_get_of_eeprom_data(dev, eep, len); 163 if (!ret) 164 return 0; 165 166 ret = mt76_get_of_data_from_mtd(dev, eep, 0, len); 167 if (!ret) 168 return 0; 169 170 return mt76_get_of_data_from_nvmem(dev, eep, "eeprom", len); 171 #endif 172 } 173 174 void 175 mt76_eeprom_override(struct mt76_phy *phy) 176 { 177 struct mt76_dev *dev = phy->dev; 178 #if defined(CONFIG_OF) 179 struct device_node *np = dev->dev->of_node; 180 181 of_get_mac_address(np, phy->macaddr); 182 183 if (!is_valid_ether_addr(phy->macaddr)) { 184 #endif 185 eth_random_addr(phy->macaddr); 186 dev_info(dev->dev, 187 "Invalid MAC address, using random address %pM\n", 188 phy->macaddr); 189 #if defined(CONFIG_OF) 190 } 191 #endif 192 } 193 EXPORT_SYMBOL_GPL(mt76_eeprom_override); 194 195 #if defined(CONFIG_OF) 196 static bool mt76_string_prop_find(struct property *prop, const char *str) 197 { 198 const char *cp = NULL; 199 200 if (!prop || !str || !str[0]) 201 return false; 202 203 while ((cp = of_prop_next_string(prop, cp)) != NULL) 204 if (!strcasecmp(cp, str)) 205 return true; 206 return false; 207 } 208 #endif 209 210 struct device_node * 211 mt76_find_power_limits_node(struct mt76_dev *dev) 212 { 213 #if !defined(CONFIG_OF) 214 return NULL; 215 #else 216 struct device_node *np = dev->dev->of_node; 217 const char *const region_names[] = { 218 [NL80211_DFS_UNSET] = "ww", 219 [NL80211_DFS_ETSI] = "etsi", 220 [NL80211_DFS_FCC] = "fcc", 221 [NL80211_DFS_JP] = "jp", 222 }; 223 struct device_node *cur, *fallback = NULL; 224 const char *region_name = NULL; 225 226 if (dev->region < ARRAY_SIZE(region_names)) 227 region_name = region_names[dev->region]; 228 229 np = of_get_child_by_name(np, "power-limits"); 230 if (!np) 231 return NULL; 232 233 for_each_child_of_node(np, cur) { 234 struct property *country = of_find_property(cur, "country", NULL); 235 struct property *regd = of_find_property(cur, "regdomain", NULL); 236 237 if (!country && !regd) { 238 fallback = cur; 239 continue; 240 } 241 242 if (mt76_string_prop_find(country, dev->alpha2) || 243 mt76_string_prop_find(regd, region_name)) { 244 of_node_put(np); 245 return cur; 246 } 247 } 248 249 of_node_put(np); 250 return fallback; 251 #endif 252 } 253 EXPORT_SYMBOL_GPL(mt76_find_power_limits_node); 254 255 #if defined(CONFIG_OF) 256 static const __be32 * 257 mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min) 258 { 259 struct property *prop = of_find_property(np, name, NULL); 260 261 if (!prop || !prop->value || prop->length < min * 4) 262 return NULL; 263 264 *len = prop->length; 265 266 return prop->value; 267 } 268 #endif 269 270 struct device_node * 271 mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan) 272 { 273 #if defined(CONFIG_OF) 274 struct device_node *cur; 275 const __be32 *val; 276 size_t len; 277 278 for_each_child_of_node(np, cur) { 279 val = mt76_get_of_array(cur, "channels", &len, 2); 280 if (!val) 281 continue; 282 283 while (len >= 2 * sizeof(*val)) { 284 if (chan->hw_value >= be32_to_cpu(val[0]) && 285 chan->hw_value <= be32_to_cpu(val[1])) 286 return cur; 287 288 val += 2; 289 len -= 2 * sizeof(*val); 290 } 291 } 292 #endif 293 return NULL; 294 } 295 EXPORT_SYMBOL_GPL(mt76_find_channel_node); 296 297 #if defined(CONFIG_OF) 298 static s8 299 mt76_get_txs_delta(struct device_node *np, u8 nss) 300 { 301 const __be32 *val; 302 size_t len; 303 304 val = mt76_get_of_array(np, "txs-delta", &len, nss); 305 if (!val) 306 return 0; 307 308 return be32_to_cpu(val[nss - 1]); 309 } 310 311 static void 312 mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data, 313 s8 target_power, s8 nss_delta, s8 *max_power) 314 { 315 int i; 316 317 if (!data) 318 return; 319 320 for (i = 0; i < pwr_len; i++) { 321 pwr[i] = min_t(s8, target_power, 322 be32_to_cpu(data[i]) + nss_delta); 323 *max_power = max(*max_power, pwr[i]); 324 } 325 } 326 327 static void 328 mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, 329 const __be32 *data, size_t len, s8 target_power, 330 s8 nss_delta, s8 *max_power) 331 { 332 int i, cur; 333 334 if (!data) 335 return; 336 337 len /= 4; 338 cur = be32_to_cpu(data[0]); 339 for (i = 0; i < pwr_num; i++) { 340 if (len < pwr_len + 1) 341 break; 342 343 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1, 344 target_power, nss_delta, max_power); 345 if (--cur > 0) 346 continue; 347 348 data += pwr_len + 1; 349 len -= pwr_len + 1; 350 if (!len) 351 break; 352 353 cur = be32_to_cpu(data[0]); 354 } 355 } 356 #endif 357 358 s8 mt76_get_rate_power_limits(struct mt76_phy *phy, 359 struct ieee80211_channel *chan, 360 struct mt76_power_limits *dest, 361 s8 target_power) 362 { 363 struct mt76_dev *dev = phy->dev; 364 #if defined(CONFIG_OF) 365 struct device_node *np; 366 const __be32 *val; 367 char name[16]; 368 #endif 369 u32 mcs_rates = dev->drv->mcs_rates; 370 #if defined(CONFIG_OF) 371 u32 ru_rates = ARRAY_SIZE(dest->ru[0]); 372 char band; 373 size_t len; 374 #endif 375 s8 max_power = 0; 376 #if defined(CONFIG_OF) 377 s8 txs_delta; 378 #endif 379 380 if (!mcs_rates) 381 mcs_rates = 10; 382 383 memset(dest, target_power, sizeof(*dest)); 384 385 if (!IS_ENABLED(CONFIG_OF)) 386 return target_power; 387 388 #if defined(CONFIG_OF) 389 np = mt76_find_power_limits_node(dev); 390 if (!np) 391 return target_power; 392 393 switch (chan->band) { 394 case NL80211_BAND_2GHZ: 395 band = '2'; 396 break; 397 case NL80211_BAND_5GHZ: 398 band = '5'; 399 break; 400 case NL80211_BAND_6GHZ: 401 band = '6'; 402 break; 403 default: 404 return target_power; 405 } 406 407 snprintf(name, sizeof(name), "txpower-%cg", band); 408 np = of_get_child_by_name(np, name); 409 if (!np) 410 return target_power; 411 412 np = mt76_find_channel_node(np, chan); 413 if (!np) 414 return target_power; 415 416 txs_delta = mt76_get_txs_delta(np, hweight16(phy->chainmask)); 417 418 val = mt76_get_of_array(np, "rates-cck", &len, ARRAY_SIZE(dest->cck)); 419 mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val, 420 target_power, txs_delta, &max_power); 421 422 val = mt76_get_of_array(np, "rates-ofdm", 423 &len, ARRAY_SIZE(dest->ofdm)); 424 mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val, 425 target_power, txs_delta, &max_power); 426 427 val = mt76_get_of_array(np, "rates-mcs", &len, mcs_rates + 1); 428 mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]), 429 ARRAY_SIZE(dest->mcs), val, len, 430 target_power, txs_delta, &max_power); 431 432 val = mt76_get_of_array(np, "rates-ru", &len, ru_rates + 1); 433 mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]), 434 ARRAY_SIZE(dest->ru), val, len, 435 target_power, txs_delta, &max_power); 436 437 #endif 438 return max_power; 439 } 440 EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits); 441 442 int 443 mt76_eeprom_init(struct mt76_dev *dev, int len) 444 { 445 dev->eeprom.size = len; 446 dev->eeprom.data = devm_kzalloc(dev->dev, len, GFP_KERNEL); 447 if (!dev->eeprom.data) 448 return -ENOMEM; 449 450 return !mt76_get_of_eeprom(dev, dev->eeprom.data, len); 451 } 452 EXPORT_SYMBOL_GPL(mt76_eeprom_init); 453