Do not use ShortGI and STBC with management frames; Atheros cards have problems with...
[ralink_drivers/rt2860_fbsd72.git] / rt2860_read_eeprom.c
blob8fe3ad854019e87978bf1ed8040ee8a61ac05c7a
2 /*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "rt2860_read_eeprom.h"
20 #include "rt2860_reg.h"
21 #include "rt2860_eeprom.h"
22 #include "rt2860_io.h"
23 #include "rt2860_debug.h"
26 * rt2860_read_eeprom
28 void rt2860_read_eeprom(struct rt2860_softc *sc)
30 uint32_t tmp;
31 uint16_t val;
32 int i;
34 /* read EEPROM address number */
36 tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
38 if((tmp & 0x30) == 0)
39 sc->eeprom_addr_num = 6;
40 else if((tmp & 0x30) == 0x10)
41 sc->eeprom_addr_num = 8;
42 else
43 sc->eeprom_addr_num = 8;
45 /* read EEPROM version */
47 sc->eeprom_rev = rt2860_io_eeprom_read(sc, RT2860_EEPROM_VERSION);
49 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
50 "%s: EEPROM rev=0x%04x\n",
51 device_get_nameunit(sc->dev), sc->eeprom_rev);
53 /* read MAC address */
55 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS01);
57 sc->mac_addr[0] = (val & 0xff);
58 sc->mac_addr[1] = (val >> 8);
60 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS23);
62 sc->mac_addr[2] = (val & 0xff);
63 sc->mac_addr[3] = (val >> 8);
65 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS45);
67 sc->mac_addr[4] = (val & 0xff);
68 sc->mac_addr[5] = (val >> 8);
70 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
71 "%s: EEPROM mac address=%s\n",
72 device_get_nameunit(sc->dev), ether_sprintf(sc->mac_addr));
74 /* read RF information */
76 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ANTENNA);
77 if (val == 0xffff)
79 printf("%s: invalid EEPROM antenna info\n",
80 device_get_nameunit(sc->dev));
82 sc->rf_rev = RT2860_EEPROM_RF_2820;
83 sc->ntxpath = 1;
84 sc->nrxpath = 2;
86 else
88 sc->rf_rev = (val >> 8) & 0xf;
89 sc->ntxpath = (val >> 4) & 0xf;
90 sc->nrxpath = (val & 0xf);
93 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
94 "%s: EEPROM RF rev=0x%04x, paths=%dT%dR\n",
95 device_get_nameunit(sc->dev), sc->rf_rev, sc->ntxpath, sc->nrxpath);
97 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_NIC_CONFIG);
99 sc->hw_radio_cntl = ((val & RT2860_EEPROM_HW_RADIO_CNTL) ? 1 : 0);
100 sc->tx_agc_cntl = ((val & RT2860_EEPROM_TX_AGC_CNTL) ? 1 : 0);
101 sc->ext_lna_2ghz = ((val & RT2860_EEPROM_EXT_LNA_2GHZ) ? 1 : 0);
102 sc->ext_lna_5ghz = ((val & RT2860_EEPROM_EXT_LNA_5GHZ) ? 1 : 0);
104 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
105 "%s: EEPROM NIC config: HW radio cntl=%d, Tx AGC cntl=%d, ext LNA gains=%d/%d\n",
106 device_get_nameunit(sc->dev),
107 sc->hw_radio_cntl, sc->tx_agc_cntl, sc->ext_lna_2ghz, sc->ext_lna_5ghz);
109 /* read country code */
111 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_COUNTRY);
113 sc->country_2ghz = (val >> 8) & 0xff;
114 sc->country_5ghz = (val & 0xff);
116 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
117 "%s: EEPROM country code=%d/%d\n",
118 device_get_nameunit(sc->dev), sc->country_2ghz, sc->country_5ghz);
120 /* read RF frequency offset */
122 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RF_FREQ_OFF);
124 if ((val & 0xff) != 0xff)
126 sc->rf_freq_off = (val & 0xff);
128 else
130 printf("%s: invalid EEPROM RF freq offset\n",
131 device_get_nameunit(sc->dev));
133 sc->rf_freq_off = 0;
136 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
137 "%s: EEPROM freq offset=0x%02x\n",
138 device_get_nameunit(sc->dev), sc->rf_freq_off);
140 /* read LEDs operating mode */
142 if (((val >> 8) & 0xff) != 0xff)
144 sc->led_cntl = ((val >> 8) & 0xff);
145 sc->led_off[0] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED1_OFF);
146 sc->led_off[1] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED2_OFF);
147 sc->led_off[2] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED3_OFF);
149 else
151 printf("%s: invalid EEPROM LED settings\n",
152 device_get_nameunit(sc->dev));
154 sc->led_cntl = RT2860_EEPROM_LED_CNTL_DEFAULT;
155 sc->led_off[0] = RT2860_EEPROM_LED1_OFF_DEFAULT;
156 sc->led_off[1] = RT2860_EEPROM_LED2_OFF_DEFAULT;
157 sc->led_off[2] = RT2860_EEPROM_LED3_OFF_DEFAULT;
160 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
161 "%s: EEPROM LED cntl=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
162 device_get_nameunit(sc->dev), sc->led_cntl,
163 sc->led_off[0], sc->led_off[1], sc->led_off[2]);
165 /* read RSSI offsets and LNA gains */
167 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LNA_GAIN);
169 sc->lna_gain[0] = (val & 0xff);
170 sc->lna_gain[1] = (val >> 8) & 0xff;
172 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE);
174 sc->rssi_off_2ghz[0] = (val & 0xff);
175 sc->rssi_off_2ghz[1] = (val >> 8) & 0xff;
177 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE + sizeof(uint16_t));
179 sc->rssi_off_2ghz[2] = (val & 0xff);
180 sc->lna_gain[2] = (val >> 8) & 0xff;
182 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE);
184 sc->rssi_off_5ghz[0] = (val & 0xff);
185 sc->rssi_off_5ghz[1] = (val >> 8) & 0xff;
187 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE + sizeof(uint16_t));
189 sc->rssi_off_5ghz[2] = (val & 0xff);
190 sc->lna_gain[3] = (val >> 8) & 0xff;
192 for (i = 2; i < RT2860_SOFTC_LNA_GAIN_COUNT; i++)
194 if (sc->lna_gain[i] == 0x00 || sc->lna_gain[i] == (int8_t) 0xff)
196 printf("%s: invalid EEPROM LNA gain #%d: 0x%02x\n",
197 device_get_nameunit(sc->dev), i, sc->lna_gain[i]);
199 sc->lna_gain[i] = sc->lna_gain[1];
203 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
204 "%s: EEPROM LNA gains=0x%02x/0x%02x/0x%02x/0x%02x\n",
205 device_get_nameunit(sc->dev),
206 sc->lna_gain[0], sc->lna_gain[1], sc->lna_gain[2], sc->lna_gain[3]);
208 for (i = 0; i < RT2860_SOFTC_RSSI_OFF_COUNT; i++)
210 if (sc->rssi_off_2ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
211 sc->rssi_off_2ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
213 printf("%s: invalid EEPROM RSSI offset #%d (2GHz): 0x%02x\n",
214 device_get_nameunit(sc->dev), i, sc->rssi_off_2ghz[i]);
216 sc->rssi_off_2ghz[i] = 0;
219 if (sc->rssi_off_5ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
220 sc->rssi_off_5ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
222 printf("%s: invalid EEPROM RSSI offset #%d (5GHz): 0x%02x\n",
223 device_get_nameunit(sc->dev), i, sc->rssi_off_5ghz[i]);
225 sc->rssi_off_5ghz[i] = 0;
229 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
230 "%s: EEPROM RSSI offsets 2GHz=%d/%d/%d\n",
231 device_get_nameunit(sc->dev),
232 sc->rssi_off_2ghz[0], sc->rssi_off_2ghz[1], sc->rssi_off_2ghz[2]);
234 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
235 "%s: EEPROM RSSI offsets 5GHz=%d/%d/%d\n",
236 device_get_nameunit(sc->dev),
237 sc->rssi_off_5ghz[0], sc->rssi_off_5ghz[1], sc->rssi_off_5ghz[2]);
239 /* read Tx power settings for 2GHz channels */
241 for (i = 0; i < 14; i += 2)
243 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_2GHZ_BASE + i / 2);
245 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
246 sc->txpow1[i + 1] = (int8_t) (val >> 8);
248 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_2GHZ_BASE + i / 2);
250 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
251 sc->txpow2[i + 1] = (int8_t) (val >> 8);
254 /* read Tx power settings for 5GHz channels */
256 for (; i < RT2860_SOFTC_TXPOW_COUNT; i += 2)
258 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_5GHZ_BASE + i / 2);
260 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
261 sc->txpow1[i + 1] = (int8_t) (val >> 8);
263 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_5GHZ_BASE + i / 2);
265 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
266 sc->txpow2[i + 1] = (int8_t) (val >> 8);
269 /* fix broken Tx power settings */
271 for (i = 0; i < 14; i++)
273 if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
274 sc->txpow1[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
276 printf("%s: invalid EEPROM Tx power1 #%d (2GHz): 0x%02x\n",
277 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
279 sc->txpow1[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
282 if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
283 sc->txpow2[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
285 printf("%s: invalid EEPROM Tx power2 #%d (2GHz): 0x%02x\n",
286 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
288 sc->txpow2[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
292 for (; i < RT2860_SOFTC_TXPOW_COUNT; i++)
294 if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
295 sc->txpow1[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
297 printf("%s: invalid EEPROM Tx power1 #%d (5GHz): 0x%02x\n",
298 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
300 sc->txpow1[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
303 if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
304 sc->txpow2[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
306 printf("%s: invalid EEPROM Tx power2 #%d (5GHz): 0x%02x\n",
307 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
309 sc->txpow2[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
313 /* read Tx power per rate deltas */
315 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW_RATE_DELTA);
317 sc->txpow_rate_delta_2ghz = 0;
318 sc->txpow_rate_delta_5ghz = 0;
320 if ((val & 0xff) != 0xff)
322 if (val & 0x80)
323 sc->txpow_rate_delta_2ghz = (val & 0xf);
325 if (!(val & 0x40))
326 sc->txpow_rate_delta_2ghz = -sc->txpow_rate_delta_2ghz;
329 val >>= 8;
331 if ((val & 0xff) != 0xff)
333 if (val & 0x80)
334 sc->txpow_rate_delta_5ghz = (val & 0xf);
336 if (!(val & 0x40))
337 sc->txpow_rate_delta_5ghz = -sc->txpow_rate_delta_5ghz;
340 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
341 "%s: EEPROM Tx power per rate deltas=%d(2MHz), %d(5MHz)\n",
342 device_get_nameunit(sc->dev),
343 sc->txpow_rate_delta_2ghz, sc->txpow_rate_delta_5ghz);
345 /* read Tx power per rate */
347 for (i = 0; i < RT2860_SOFTC_TXPOW_RATE_COUNT; i++)
349 rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_TXPOW_RATE_BASE + i * sizeof(uint32_t),
350 &tmp, sizeof(uint32_t));
352 sc->txpow_rate_20mhz[i] = tmp;
353 sc->txpow_rate_40mhz_2ghz[i] =
354 rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_2ghz);
355 sc->txpow_rate_40mhz_5ghz[i] =
356 rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_5ghz);
358 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
359 "%s: EEPROM Tx power per rate #%d=0x%08x(20MHz), 0x%08x(40MHz/2GHz), 0x%08x(40MHz/5GHz)\n",
360 device_get_nameunit(sc->dev), i,
361 sc->txpow_rate_20mhz[i], sc->txpow_rate_40mhz_2ghz[i], sc->txpow_rate_40mhz_5ghz[i]);
364 if (sc->tx_agc_cntl)
365 sc->tx_agc_cntl_2ghz = sc->tx_agc_cntl_5ghz = 1;
367 /* read factory-calibrated samples for temperature compensation */
369 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE);
371 sc->tssi_2ghz[0] = (val & 0xff); /* [-4] */
372 sc->tssi_2ghz[1] = (val >> 8); /* [-3] */
374 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + sizeof(uint16_t));
376 sc->tssi_2ghz[2] = (val & 0xff); /* [-2] */
377 sc->tssi_2ghz[3] = (val >> 8); /* [-1] */
379 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 2 * sizeof(uint16_t));
381 sc->tssi_2ghz[4] = (val & 0xff); /* [0] */
382 sc->tssi_2ghz[5] = (val >> 8); /* [+1] */
384 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 3 * sizeof(uint16_t));
386 sc->tssi_2ghz[6] = (val & 0xff); /* [+2] */
387 sc->tssi_2ghz[7] = (val >> 8); /* [+3] */
389 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 4 * sizeof(uint16_t));
391 sc->tssi_2ghz[8] = (val & 0xff); /* [+4] */
392 sc->tssi_step_2ghz = (val >> 8);
394 if (sc->tssi_2ghz[4] == 0xff)
395 sc->tx_agc_cntl_2ghz = 0;
397 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
398 "%s: EEPROM TSSI 2GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
399 "0x%02x, 0x%02x, step=%d\n",
400 device_get_nameunit(sc->dev),
401 sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2],
402 sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5],
403 sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8],
404 sc->tssi_step_2ghz);
406 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE);
408 sc->tssi_5ghz[0] = (val & 0xff); /* [-4] */
409 sc->tssi_5ghz[1] = (val >> 8); /* [-3] */
411 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + sizeof(uint16_t));
413 sc->tssi_5ghz[2] = (val & 0xff); /* [-2] */
414 sc->tssi_5ghz[3] = (val >> 8); /* [-1] */
416 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 2 * sizeof(uint16_t));
418 sc->tssi_5ghz[4] = (val & 0xff); /* [0] */
419 sc->tssi_5ghz[5] = (val >> 8); /* [+1] */
421 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 3 * sizeof(uint16_t));
423 sc->tssi_5ghz[6] = (val & 0xff); /* [+2] */
424 sc->tssi_5ghz[7] = (val >> 8); /* [+3] */
426 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 4 * sizeof(uint16_t));
428 sc->tssi_5ghz[8] = (val & 0xff); /* [+4] */
429 sc->tssi_step_5ghz = (val >> 8);
431 if (sc->tssi_5ghz[4] == 0xff)
432 sc->tx_agc_cntl_5ghz = 0;
434 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
435 "%s: EEPROM TSSI 5GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
436 "0x%02x, 0x%02x, step=%d\n",
437 device_get_nameunit(sc->dev),
438 sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2],
439 sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5],
440 sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8],
441 sc->tssi_step_5ghz);
443 /* read default BBP settings */
445 rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_BBP_BASE,
446 sc->bbp_eeprom, RT2860_SOFTC_BBP_EEPROM_COUNT * sizeof(uint16_t));
448 /* read powersave level */
450 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_POWERSAVE_LEVEL);
452 sc->powersave_level = val & 0xff;
454 if ((sc->powersave_level & 0xff) == 0xff)
455 printf("%s: invalid EEPROM powersave level\n",
456 device_get_nameunit(sc->dev));
458 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
459 "%s: EEPROM powersave level=0x%02x\n",
460 device_get_nameunit(sc->dev), sc->powersave_level);
464 * rt2860_read_eeprom_txpow_rate_add_delta
466 uint32_t rt2860_read_eeprom_txpow_rate_add_delta(uint32_t txpow_rate,
467 int8_t delta)
469 int8_t b4;
470 int i;
472 for (i = 0; i < 8; i++)
474 b4 = txpow_rate & 0xf;
475 b4 += delta;
477 if (b4 < 0)
478 b4 = 0;
479 else if (b4 > 0xf)
480 b4 = 0xf;
482 txpow_rate = (txpow_rate >> 4) | (b4 << 28);
485 return txpow_rate;