Fixed Tx hang issue with DMA segment length = 0
[ralink_drivers/rt2860_fbsd8.git] / rt2860_read_eeprom.c
blob55ad361b677fa7c43ae9903745b02b470449bf50
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 if ((sc->mac_rev != 0x28830300) && (sc->nrxpath > 2))
95 /* only 2 Rx streams for RT2860 series */
97 sc->nrxpath = 2;
100 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
101 "%s: EEPROM RF rev=0x%04x, paths=%dT%dR\n",
102 device_get_nameunit(sc->dev), sc->rf_rev, sc->ntxpath, sc->nrxpath);
104 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_NIC_CONFIG);
106 sc->hw_radio_cntl = ((val & RT2860_EEPROM_HW_RADIO_CNTL) ? 1 : 0);
107 sc->tx_agc_cntl = ((val & RT2860_EEPROM_TX_AGC_CNTL) ? 1 : 0);
108 sc->ext_lna_2ghz = ((val & RT2860_EEPROM_EXT_LNA_2GHZ) ? 1 : 0);
109 sc->ext_lna_5ghz = ((val & RT2860_EEPROM_EXT_LNA_5GHZ) ? 1 : 0);
111 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
112 "%s: EEPROM NIC config: HW radio cntl=%d, Tx AGC cntl=%d, ext LNA gains=%d/%d\n",
113 device_get_nameunit(sc->dev),
114 sc->hw_radio_cntl, sc->tx_agc_cntl, sc->ext_lna_2ghz, sc->ext_lna_5ghz);
116 /* read country code */
118 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_COUNTRY);
120 sc->country_2ghz = (val >> 8) & 0xff;
121 sc->country_5ghz = (val & 0xff);
123 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
124 "%s: EEPROM country code=%d/%d\n",
125 device_get_nameunit(sc->dev), sc->country_2ghz, sc->country_5ghz);
127 /* read RF frequency offset */
129 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RF_FREQ_OFF);
131 if ((val & 0xff) != 0xff)
133 sc->rf_freq_off = (val & 0xff);
135 else
137 printf("%s: invalid EEPROM RF freq offset\n",
138 device_get_nameunit(sc->dev));
140 sc->rf_freq_off = 0;
143 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
144 "%s: EEPROM freq offset=0x%02x\n",
145 device_get_nameunit(sc->dev), sc->rf_freq_off);
147 /* read LEDs operating mode */
149 if (((val >> 8) & 0xff) != 0xff)
151 sc->led_cntl = ((val >> 8) & 0xff);
152 sc->led_off[0] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED1_OFF);
153 sc->led_off[1] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED2_OFF);
154 sc->led_off[2] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED3_OFF);
156 else
158 printf("%s: invalid EEPROM LED settings\n",
159 device_get_nameunit(sc->dev));
161 sc->led_cntl = RT2860_EEPROM_LED_CNTL_DEFAULT;
162 sc->led_off[0] = RT2860_EEPROM_LED1_OFF_DEFAULT;
163 sc->led_off[1] = RT2860_EEPROM_LED2_OFF_DEFAULT;
164 sc->led_off[2] = RT2860_EEPROM_LED3_OFF_DEFAULT;
167 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
168 "%s: EEPROM LED cntl=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
169 device_get_nameunit(sc->dev), sc->led_cntl,
170 sc->led_off[0], sc->led_off[1], sc->led_off[2]);
172 /* read RSSI offsets and LNA gains */
174 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LNA_GAIN);
176 sc->lna_gain[0] = (val & 0xff);
177 sc->lna_gain[1] = (val >> 8) & 0xff;
179 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE);
181 sc->rssi_off_2ghz[0] = (val & 0xff);
182 sc->rssi_off_2ghz[1] = (val >> 8) & 0xff;
184 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE + sizeof(uint16_t));
186 sc->rssi_off_2ghz[2] = (val & 0xff);
187 sc->lna_gain[2] = (val >> 8) & 0xff;
189 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE);
191 sc->rssi_off_5ghz[0] = (val & 0xff);
192 sc->rssi_off_5ghz[1] = (val >> 8) & 0xff;
194 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE + sizeof(uint16_t));
196 sc->rssi_off_5ghz[2] = (val & 0xff);
197 sc->lna_gain[3] = (val >> 8) & 0xff;
199 for (i = 2; i < RT2860_SOFTC_LNA_GAIN_COUNT; i++)
201 if (sc->lna_gain[i] == 0x00 || sc->lna_gain[i] == (int8_t) 0xff)
203 printf("%s: invalid EEPROM LNA gain #%d: 0x%02x\n",
204 device_get_nameunit(sc->dev), i, sc->lna_gain[i]);
206 sc->lna_gain[i] = sc->lna_gain[1];
210 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
211 "%s: EEPROM LNA gains=0x%02x/0x%02x/0x%02x/0x%02x\n",
212 device_get_nameunit(sc->dev),
213 sc->lna_gain[0], sc->lna_gain[1], sc->lna_gain[2], sc->lna_gain[3]);
215 for (i = 0; i < RT2860_SOFTC_RSSI_OFF_COUNT; i++)
217 if (sc->rssi_off_2ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
218 sc->rssi_off_2ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
220 printf("%s: invalid EEPROM RSSI offset #%d (2GHz): 0x%02x\n",
221 device_get_nameunit(sc->dev), i, sc->rssi_off_2ghz[i]);
223 sc->rssi_off_2ghz[i] = 0;
226 if (sc->rssi_off_5ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
227 sc->rssi_off_5ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
229 printf("%s: invalid EEPROM RSSI offset #%d (5GHz): 0x%02x\n",
230 device_get_nameunit(sc->dev), i, sc->rssi_off_5ghz[i]);
232 sc->rssi_off_5ghz[i] = 0;
236 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
237 "%s: EEPROM RSSI offsets 2GHz=%d/%d/%d\n",
238 device_get_nameunit(sc->dev),
239 sc->rssi_off_2ghz[0], sc->rssi_off_2ghz[1], sc->rssi_off_2ghz[2]);
241 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
242 "%s: EEPROM RSSI offsets 5GHz=%d/%d/%d\n",
243 device_get_nameunit(sc->dev),
244 sc->rssi_off_5ghz[0], sc->rssi_off_5ghz[1], sc->rssi_off_5ghz[2]);
246 /* read Tx power settings for 2GHz channels */
248 for (i = 0; i < 14; i += 2)
250 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_2GHZ_BASE + i / 2);
252 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
253 sc->txpow1[i + 1] = (int8_t) (val >> 8);
255 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_2GHZ_BASE + i / 2);
257 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
258 sc->txpow2[i + 1] = (int8_t) (val >> 8);
261 /* read Tx power settings for 5GHz channels */
263 for (; i < RT2860_SOFTC_TXPOW_COUNT; i += 2)
265 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_5GHZ_BASE + i / 2);
267 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
268 sc->txpow1[i + 1] = (int8_t) (val >> 8);
270 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_5GHZ_BASE + i / 2);
272 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
273 sc->txpow2[i + 1] = (int8_t) (val >> 8);
276 /* fix broken Tx power settings */
278 for (i = 0; i < 14; i++)
280 if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
281 sc->txpow1[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
283 printf("%s: invalid EEPROM Tx power1 #%d (2GHz): 0x%02x\n",
284 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
286 sc->txpow1[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
289 if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
290 sc->txpow2[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
292 printf("%s: invalid EEPROM Tx power2 #%d (2GHz): 0x%02x\n",
293 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
295 sc->txpow2[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
299 for (; i < RT2860_SOFTC_TXPOW_COUNT; i++)
301 if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
302 sc->txpow1[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
304 printf("%s: invalid EEPROM Tx power1 #%d (5GHz): 0x%02x\n",
305 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
307 sc->txpow1[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
310 if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
311 sc->txpow2[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
313 printf("%s: invalid EEPROM Tx power2 #%d (5GHz): 0x%02x\n",
314 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
316 sc->txpow2[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
320 /* read Tx power per rate deltas */
322 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW_RATE_DELTA);
324 sc->txpow_rate_delta_2ghz = 0;
325 sc->txpow_rate_delta_5ghz = 0;
327 if ((val & 0xff) != 0xff)
329 if (val & 0x80)
330 sc->txpow_rate_delta_2ghz = (val & 0xf);
332 if (!(val & 0x40))
333 sc->txpow_rate_delta_2ghz = -sc->txpow_rate_delta_2ghz;
336 val >>= 8;
338 if ((val & 0xff) != 0xff)
340 if (val & 0x80)
341 sc->txpow_rate_delta_5ghz = (val & 0xf);
343 if (!(val & 0x40))
344 sc->txpow_rate_delta_5ghz = -sc->txpow_rate_delta_5ghz;
347 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
348 "%s: EEPROM Tx power per rate deltas=%d(2MHz), %d(5MHz)\n",
349 device_get_nameunit(sc->dev),
350 sc->txpow_rate_delta_2ghz, sc->txpow_rate_delta_5ghz);
352 /* read Tx power per rate */
354 for (i = 0; i < RT2860_SOFTC_TXPOW_RATE_COUNT; i++)
356 rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_TXPOW_RATE_BASE + i * sizeof(uint32_t),
357 &tmp, sizeof(uint32_t));
359 sc->txpow_rate_20mhz[i] = tmp;
360 sc->txpow_rate_40mhz_2ghz[i] =
361 rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_2ghz);
362 sc->txpow_rate_40mhz_5ghz[i] =
363 rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_5ghz);
365 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
366 "%s: EEPROM Tx power per rate #%d=0x%08x(20MHz), 0x%08x(40MHz/2GHz), 0x%08x(40MHz/5GHz)\n",
367 device_get_nameunit(sc->dev), i,
368 sc->txpow_rate_20mhz[i], sc->txpow_rate_40mhz_2ghz[i], sc->txpow_rate_40mhz_5ghz[i]);
371 if (sc->tx_agc_cntl)
372 sc->tx_agc_cntl_2ghz = sc->tx_agc_cntl_5ghz = 1;
374 /* read factory-calibrated samples for temperature compensation */
376 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE);
378 sc->tssi_2ghz[0] = (val & 0xff); /* [-4] */
379 sc->tssi_2ghz[1] = (val >> 8); /* [-3] */
381 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + sizeof(uint16_t));
383 sc->tssi_2ghz[2] = (val & 0xff); /* [-2] */
384 sc->tssi_2ghz[3] = (val >> 8); /* [-1] */
386 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 2 * sizeof(uint16_t));
388 sc->tssi_2ghz[4] = (val & 0xff); /* [0] */
389 sc->tssi_2ghz[5] = (val >> 8); /* [+1] */
391 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 3 * sizeof(uint16_t));
393 sc->tssi_2ghz[6] = (val & 0xff); /* [+2] */
394 sc->tssi_2ghz[7] = (val >> 8); /* [+3] */
396 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 4 * sizeof(uint16_t));
398 sc->tssi_2ghz[8] = (val & 0xff); /* [+4] */
399 sc->tssi_step_2ghz = (val >> 8);
401 if (sc->tssi_2ghz[4] == 0xff)
402 sc->tx_agc_cntl_2ghz = 0;
404 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
405 "%s: EEPROM TSSI 2GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
406 "0x%02x, 0x%02x, step=%d\n",
407 device_get_nameunit(sc->dev),
408 sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2],
409 sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5],
410 sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8],
411 sc->tssi_step_2ghz);
413 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE);
415 sc->tssi_5ghz[0] = (val & 0xff); /* [-4] */
416 sc->tssi_5ghz[1] = (val >> 8); /* [-3] */
418 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + sizeof(uint16_t));
420 sc->tssi_5ghz[2] = (val & 0xff); /* [-2] */
421 sc->tssi_5ghz[3] = (val >> 8); /* [-1] */
423 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 2 * sizeof(uint16_t));
425 sc->tssi_5ghz[4] = (val & 0xff); /* [0] */
426 sc->tssi_5ghz[5] = (val >> 8); /* [+1] */
428 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 3 * sizeof(uint16_t));
430 sc->tssi_5ghz[6] = (val & 0xff); /* [+2] */
431 sc->tssi_5ghz[7] = (val >> 8); /* [+3] */
433 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 4 * sizeof(uint16_t));
435 sc->tssi_5ghz[8] = (val & 0xff); /* [+4] */
436 sc->tssi_step_5ghz = (val >> 8);
438 if (sc->tssi_5ghz[4] == 0xff)
439 sc->tx_agc_cntl_5ghz = 0;
441 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
442 "%s: EEPROM TSSI 5GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
443 "0x%02x, 0x%02x, step=%d\n",
444 device_get_nameunit(sc->dev),
445 sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2],
446 sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5],
447 sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8],
448 sc->tssi_step_5ghz);
450 /* read default BBP settings */
452 rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_BBP_BASE,
453 sc->bbp_eeprom, RT2860_SOFTC_BBP_EEPROM_COUNT * sizeof(uint16_t));
455 /* read powersave level */
457 val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_POWERSAVE_LEVEL);
459 sc->powersave_level = val & 0xff;
461 if ((sc->powersave_level & 0xff) == 0xff)
462 printf("%s: invalid EEPROM powersave level\n",
463 device_get_nameunit(sc->dev));
465 RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
466 "%s: EEPROM powersave level=0x%02x\n",
467 device_get_nameunit(sc->dev), sc->powersave_level);
471 * rt2860_read_eeprom_txpow_rate_add_delta
473 uint32_t rt2860_read_eeprom_txpow_rate_add_delta(uint32_t txpow_rate,
474 int8_t delta)
476 int8_t b4;
477 int i;
479 for (i = 0; i < 8; i++)
481 b4 = txpow_rate & 0xf;
482 b4 += delta;
484 if (b4 < 0)
485 b4 = 0;
486 else if (b4 > 0xf)
487 b4 = 0xf;
489 txpow_rate = (txpow_rate >> 4) | (b4 << 28);
492 return txpow_rate;