Added new USB device Ralink RT2870
[ralink_drivers/rt2870_fbsd8.git] / rt2870_read_eeprom.c
blob86f7518d5267d20f7142e19072ccc5f9a46a2ef9
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 "rt2870_read_eeprom.h"
20 #include "rt2870_eeprom.h"
21 #include "rt2870_io.h"
22 #include "rt2870_debug.h"
25 * rt2870_read_eeprom
27 void rt2870_read_eeprom(struct rt2870_softc *sc)
29 uint16_t val;
30 uint32_t tmp;
31 int i;
33 /* read EEPROM version */
35 sc->eeprom_rev = rt2870_io_eeprom_read(sc, RT2870_EEPROM_VERSION);
37 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
38 "%s: EEPROM rev=0x%04x\n",
39 device_get_nameunit(sc->dev), sc->eeprom_rev);
41 /* read MAC address */
43 rt2870_io_eeprom_read_multi(sc, RT2870_EEPROM_ADDRESS,
44 sc->mac_addr, IEEE80211_ADDR_LEN);
46 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
47 "%s: EEPROM mac address=%s\n",
48 device_get_nameunit(sc->dev), ether_sprintf(sc->mac_addr));
50 /* read RF information */
52 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_ANTENNA);
53 if (val == 0xffff)
55 printf("%s: invalid EEPROM antenna info\n",
56 device_get_nameunit(sc->dev));
58 else
60 sc->rf_rev = (val >> 8) & 0xf;
61 sc->ntxpath = (val >> 4) & 0xf;
62 sc->nrxpath = (val & 0xf);
65 if ((sc->mac_rev != 0x28830300) && (sc->nrxpath > 2))
67 /* only 2 Rx streams for RT2860 series */
69 sc->nrxpath = 2;
72 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
73 "%s: EEPROM RF rev=0x%04x, paths=%dT%dR\n",
74 device_get_nameunit(sc->dev), sc->rf_rev, sc->ntxpath, sc->nrxpath);
76 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_NIC_CONFIG);
78 sc->hw_radio_cntl = ((val & RT2870_EEPROM_HW_RADIO_CNTL) ? 1 : 0);
79 sc->tx_agc_cntl = ((val & RT2870_EEPROM_TX_AGC_CNTL) ? 1 : 0);
80 sc->ext_lna_2ghz = ((val & RT2870_EEPROM_EXT_LNA_2GHZ) ? 1 : 0);
81 sc->ext_lna_5ghz = ((val & RT2870_EEPROM_EXT_LNA_5GHZ) ? 1 : 0);
83 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
84 "%s: EEPROM NIC config: HW radio cntl=%d, Tx AGC cntl=%d, ext LNA gains=%d/%d\n",
85 device_get_nameunit(sc->dev),
86 sc->hw_radio_cntl, sc->tx_agc_cntl, sc->ext_lna_2ghz, sc->ext_lna_5ghz);
88 /* read country code */
90 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_COUNTRY);
92 sc->country_2ghz = (val >> 8) & 0xff;
93 sc->country_5ghz = (val & 0xff);
95 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
96 "%s: EEPROM country code=%d/%d\n",
97 device_get_nameunit(sc->dev), sc->country_2ghz, sc->country_5ghz);
99 /* read RF frequency offset */
101 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RF_FREQ_OFF);
103 if ((val & 0xff) != 0xff)
105 sc->rf_freq_off = (val & 0xff);
107 else
109 printf("%s: invalid EEPROM RF freq offset\n",
110 device_get_nameunit(sc->dev));
112 sc->rf_freq_off = 0;
115 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
116 "%s: EEPROM freq offset=0x%02x\n",
117 device_get_nameunit(sc->dev), sc->rf_freq_off);
119 /* read LEDs operating mode */
121 if (((val >> 8) & 0xff) != 0xff)
123 sc->led_cntl = ((val >> 8) & 0xff);
124 sc->led_off[0] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED1_OFF);
125 sc->led_off[1] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED2_OFF);
126 sc->led_off[2] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED3_OFF);
128 else
130 printf("%s: invalid EEPROM LED settings\n",
131 device_get_nameunit(sc->dev));
133 sc->led_cntl = RT2870_EEPROM_LED_CNTL_DEFAULT;
134 sc->led_off[0] = RT2870_EEPROM_LED1_OFF_DEFAULT;
135 sc->led_off[1] = RT2870_EEPROM_LED2_OFF_DEFAULT;
136 sc->led_off[2] = RT2870_EEPROM_LED3_OFF_DEFAULT;
139 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
140 "%s: EEPROM LED cntl=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
141 device_get_nameunit(sc->dev), sc->led_cntl,
142 sc->led_off[0], sc->led_off[1], sc->led_off[2]);
144 /* read RSSI offsets and LNA gains */
146 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LNA_GAIN);
148 sc->lna_gain[0] = (val & 0xff);
149 sc->lna_gain[1] = (val >> 8) & 0xff;
151 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_2GHZ_BASE);
153 sc->rssi_off_2ghz[0] = (val & 0xff);
154 sc->rssi_off_2ghz[1] = (val >> 8) & 0xff;
156 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_2GHZ_BASE + sizeof(uint16_t));
158 sc->rssi_off_2ghz[2] = (val & 0xff);
159 sc->lna_gain[2] = (val >> 8) & 0xff;
161 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_5GHZ_BASE);
163 sc->rssi_off_5ghz[0] = (val & 0xff);
164 sc->rssi_off_5ghz[1] = (val >> 8) & 0xff;
166 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_5GHZ_BASE + sizeof(uint16_t));
168 sc->rssi_off_5ghz[2] = (val & 0xff);
169 sc->lna_gain[3] = (val >> 8) & 0xff;
171 for (i = 2; i < RT2870_SOFTC_LNA_GAIN_COUNT; i++)
173 if (sc->lna_gain[i] == 0x00 || sc->lna_gain[i] == (int8_t) 0xff)
175 printf("%s: invalid EEPROM LNA gain #%d: 0x%02x\n",
176 device_get_nameunit(sc->dev), i, sc->lna_gain[i]);
178 sc->lna_gain[i] = sc->lna_gain[1];
182 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
183 "%s: EEPROM LNA gains=0x%02x/0x%02x/0x%02x/0x%02x\n",
184 device_get_nameunit(sc->dev),
185 sc->lna_gain[0], sc->lna_gain[1], sc->lna_gain[2], sc->lna_gain[3]);
187 for (i = 0; i < RT2870_SOFTC_RSSI_OFF_COUNT; i++)
189 if (sc->rssi_off_2ghz[i] < RT2870_EEPROM_RSSI_OFF_MIN ||
190 sc->rssi_off_2ghz[i] > RT2870_EEPROM_RSSI_OFF_MAX)
192 printf("%s: invalid EEPROM RSSI offset #%d (2GHz): 0x%02x\n",
193 device_get_nameunit(sc->dev), i, sc->rssi_off_2ghz[i]);
195 sc->rssi_off_2ghz[i] = 0;
198 if (sc->rssi_off_5ghz[i] < RT2870_EEPROM_RSSI_OFF_MIN ||
199 sc->rssi_off_5ghz[i] > RT2870_EEPROM_RSSI_OFF_MAX)
201 printf("%s: invalid EEPROM RSSI offset #%d (5GHz): 0x%02x\n",
202 device_get_nameunit(sc->dev), i, sc->rssi_off_5ghz[i]);
204 sc->rssi_off_5ghz[i] = 0;
208 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
209 "%s: EEPROM RSSI offsets 2GHz=%d/%d/%d\n",
210 device_get_nameunit(sc->dev),
211 sc->rssi_off_2ghz[0], sc->rssi_off_2ghz[1], sc->rssi_off_2ghz[2]);
213 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
214 "%s: EEPROM RSSI offsets 5GHz=%d/%d/%d\n",
215 device_get_nameunit(sc->dev),
216 sc->rssi_off_5ghz[0], sc->rssi_off_5ghz[1], sc->rssi_off_5ghz[2]);
218 /* read Tx power settings for 2GHz channels */
220 for (i = 0; i < 14; i += 2)
222 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW1_2GHZ_BASE + i / 2);
224 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
225 sc->txpow1[i + 1] = (int8_t) (val >> 8);
227 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW2_2GHZ_BASE + i / 2);
229 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
230 sc->txpow2[i + 1] = (int8_t) (val >> 8);
233 /* read Tx power settings for 5GHz channels */
235 for (; i < RT2870_SOFTC_TXPOW_COUNT; i += 2)
237 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW1_5GHZ_BASE + i / 2);
239 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
240 sc->txpow1[i + 1] = (int8_t) (val >> 8);
242 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW2_5GHZ_BASE + i / 2);
244 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
245 sc->txpow2[i + 1] = (int8_t) (val >> 8);
248 /* fix broken Tx power settings */
250 for (i = 0; i < 14; i++)
252 if (sc->txpow1[i] < RT2870_EEPROM_TXPOW_2GHZ_MIN ||
253 sc->txpow1[i] > RT2870_EEPROM_TXPOW_2GHZ_MAX)
255 printf("%s: invalid EEPROM Tx power1 #%d (2GHz): 0x%02x\n",
256 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
258 sc->txpow1[i] = RT2870_EEPROM_TXPOW_2GHZ_DEFAULT;
261 if (sc->txpow2[i] < RT2870_EEPROM_TXPOW_2GHZ_MIN ||
262 sc->txpow2[i] > RT2870_EEPROM_TXPOW_2GHZ_MAX)
264 printf("%s: invalid EEPROM Tx power2 #%d (2GHz): 0x%02x\n",
265 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
267 sc->txpow2[i] = RT2870_EEPROM_TXPOW_2GHZ_DEFAULT;
271 for (; i < RT2870_SOFTC_TXPOW_COUNT; i++)
273 if (sc->txpow1[i] < RT2870_EEPROM_TXPOW_5GHZ_MIN ||
274 sc->txpow1[i] > RT2870_EEPROM_TXPOW_5GHZ_MAX)
276 printf("%s: invalid EEPROM Tx power1 #%d (5GHz): 0x%02x\n",
277 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
279 sc->txpow1[i] = RT2870_EEPROM_TXPOW_5GHZ_DEFAULT;
282 if (sc->txpow2[i] < RT2870_EEPROM_TXPOW_5GHZ_MIN ||
283 sc->txpow2[i] > RT2870_EEPROM_TXPOW_5GHZ_MAX)
285 printf("%s: invalid EEPROM Tx power2 #%d (5GHz): 0x%02x\n",
286 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
288 sc->txpow2[i] = RT2870_EEPROM_TXPOW_5GHZ_DEFAULT;
292 /* read Tx power per rate deltas */
294 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW_RATE_DELTA);
296 sc->txpow_rate_delta_2ghz = 0;
297 sc->txpow_rate_delta_5ghz = 0;
299 if ((val & 0xff) != 0xff)
301 if (val & 0x80)
302 sc->txpow_rate_delta_2ghz = (val & 0xf);
304 if (!(val & 0x40))
305 sc->txpow_rate_delta_2ghz = -sc->txpow_rate_delta_2ghz;
308 val >>= 8;
310 if ((val & 0xff) != 0xff)
312 if (val & 0x80)
313 sc->txpow_rate_delta_5ghz = (val & 0xf);
315 if (!(val & 0x40))
316 sc->txpow_rate_delta_5ghz = -sc->txpow_rate_delta_5ghz;
319 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
320 "%s: EEPROM Tx power per rate deltas=%d(2MHz), %d(5MHz)\n",
321 device_get_nameunit(sc->dev),
322 sc->txpow_rate_delta_2ghz, sc->txpow_rate_delta_5ghz);
324 /* read Tx power per rate */
326 for (i = 0; i < RT2870_SOFTC_TXPOW_RATE_COUNT; i++)
328 rt2870_io_eeprom_read_multi(sc, RT2870_EEPROM_TXPOW_RATE_BASE + i * sizeof(uint32_t),
329 &tmp, sizeof(uint32_t));
331 sc->txpow_rate_20mhz[i] = tmp;
332 sc->txpow_rate_40mhz_2ghz[i] =
333 rt2870_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_2ghz);
334 sc->txpow_rate_40mhz_5ghz[i] =
335 rt2870_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_5ghz);
337 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
338 "%s: EEPROM Tx power per rate #%d=0x%08x(20MHz), 0x%08x(40MHz/2GHz), 0x%08x(40MHz/5GHz)\n",
339 device_get_nameunit(sc->dev), i,
340 sc->txpow_rate_20mhz[i], sc->txpow_rate_40mhz_2ghz[i], sc->txpow_rate_40mhz_5ghz[i]);
343 if (sc->tx_agc_cntl)
344 sc->tx_agc_cntl_2ghz = sc->tx_agc_cntl_5ghz = 1;
346 /* read factory-calibrated samples for temperature compensation */
348 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE);
350 sc->tssi_2ghz[0] = (val & 0xff); /* [-4] */
351 sc->tssi_2ghz[1] = (val >> 8); /* [-3] */
353 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + sizeof(uint16_t));
355 sc->tssi_2ghz[2] = (val & 0xff); /* [-2] */
356 sc->tssi_2ghz[3] = (val >> 8); /* [-1] */
358 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 2 * sizeof(uint16_t));
360 sc->tssi_2ghz[4] = (val & 0xff); /* [0] */
361 sc->tssi_2ghz[5] = (val >> 8); /* [+1] */
363 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 3 * sizeof(uint16_t));
365 sc->tssi_2ghz[6] = (val & 0xff); /* [+2] */
366 sc->tssi_2ghz[7] = (val >> 8); /* [+3] */
368 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 4 * sizeof(uint16_t));
370 sc->tssi_2ghz[8] = (val & 0xff); /* [+4] */
371 sc->tssi_step_2ghz = (val >> 8);
373 if (sc->tssi_2ghz[4] == 0xff)
374 sc->tx_agc_cntl_2ghz = 0;
376 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
377 "%s: EEPROM TSSI 2GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
378 "0x%02x, 0x%02x, step=%d\n",
379 device_get_nameunit(sc->dev),
380 sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2],
381 sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5],
382 sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8],
383 sc->tssi_step_2ghz);
385 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE);
387 sc->tssi_5ghz[0] = (val & 0xff); /* [-4] */
388 sc->tssi_5ghz[1] = (val >> 8); /* [-3] */
390 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + sizeof(uint16_t));
392 sc->tssi_5ghz[2] = (val & 0xff); /* [-2] */
393 sc->tssi_5ghz[3] = (val >> 8); /* [-1] */
395 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 2 * sizeof(uint16_t));
397 sc->tssi_5ghz[4] = (val & 0xff); /* [0] */
398 sc->tssi_5ghz[5] = (val >> 8); /* [+1] */
400 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 3 * sizeof(uint16_t));
402 sc->tssi_5ghz[6] = (val & 0xff); /* [+2] */
403 sc->tssi_5ghz[7] = (val >> 8); /* [+3] */
405 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 4 * sizeof(uint16_t));
407 sc->tssi_5ghz[8] = (val & 0xff); /* [+4] */
408 sc->tssi_step_5ghz = (val >> 8);
410 if (sc->tssi_5ghz[4] == 0xff)
411 sc->tx_agc_cntl_5ghz = 0;
413 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
414 "%s: EEPROM TSSI 5GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
415 "0x%02x, 0x%02x, step=%d\n",
416 device_get_nameunit(sc->dev),
417 sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2],
418 sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5],
419 sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8],
420 sc->tssi_step_5ghz);
422 /* read default BBP settings */
424 rt2870_io_eeprom_read_multi(sc, RT2870_EEPROM_BBP_BASE,
425 sc->bbp_eeprom, RT2870_SOFTC_BBP_EEPROM_COUNT * sizeof(uint16_t));
429 * rt2870_read_eeprom_txpow_rate_add_delta
431 uint32_t rt2870_read_eeprom_txpow_rate_add_delta(uint32_t txpow_rate,
432 int8_t delta)
434 int8_t b4;
435 int i;
437 for (i = 0; i < 8; i++)
439 b4 = txpow_rate & 0xf;
440 b4 += delta;
442 if (b4 < 0)
443 b4 = 0;
444 else if (b4 > 0xf)
445 b4 = 0xf;
447 txpow_rate = (txpow_rate >> 4) | (b4 << 28);
450 return txpow_rate;