Added BBP tuning
[ralink_drivers/rt2870_fbsd72.git] / rt2870_read_eeprom.c
blob3dbd9ca43858eda7a9b38ebab686f49b11ce81aa
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 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
66 "%s: EEPROM RF rev=0x%04x, paths=%dT%dR\n",
67 device_get_nameunit(sc->dev), sc->rf_rev, sc->ntxpath, sc->nrxpath);
69 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_NIC_CONFIG);
71 sc->hw_radio_cntl = ((val & RT2870_EEPROM_HW_RADIO_CNTL) ? 1 : 0);
72 sc->tx_agc_cntl = ((val & RT2870_EEPROM_TX_AGC_CNTL) ? 1 : 0);
73 sc->ext_lna_2ghz = ((val & RT2870_EEPROM_EXT_LNA_2GHZ) ? 1 : 0);
74 sc->ext_lna_5ghz = ((val & RT2870_EEPROM_EXT_LNA_5GHZ) ? 1 : 0);
76 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
77 "%s: EEPROM NIC config: HW radio cntl=%d, Tx AGC cntl=%d, ext LNA gains=%d/%d\n",
78 device_get_nameunit(sc->dev),
79 sc->hw_radio_cntl, sc->tx_agc_cntl, sc->ext_lna_2ghz, sc->ext_lna_5ghz);
81 /* read country code */
83 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_COUNTRY);
85 sc->country_2ghz = (val >> 8) & 0xff;
86 sc->country_5ghz = (val & 0xff);
88 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
89 "%s: EEPROM country code=%d/%d\n",
90 device_get_nameunit(sc->dev), sc->country_2ghz, sc->country_5ghz);
92 /* read RF frequency offset */
94 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RF_FREQ_OFF);
96 if ((val & 0xff) != 0xff)
98 sc->rf_freq_off = (val & 0xff);
100 else
102 printf("%s: invalid EEPROM RF freq offset\n",
103 device_get_nameunit(sc->dev));
105 sc->rf_freq_off = 0;
108 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
109 "%s: EEPROM freq offset=0x%02x\n",
110 device_get_nameunit(sc->dev), sc->rf_freq_off);
112 /* read LEDs operating mode */
114 if (((val >> 8) & 0xff) != 0xff)
116 sc->led_cntl = ((val >> 8) & 0xff);
117 sc->led_off[0] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED1_OFF);
118 sc->led_off[1] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED2_OFF);
119 sc->led_off[2] = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LED3_OFF);
121 else
123 printf("%s: invalid EEPROM LED settings\n",
124 device_get_nameunit(sc->dev));
126 sc->led_cntl = RT2870_EEPROM_LED_CNTL_DEFAULT;
127 sc->led_off[0] = RT2870_EEPROM_LED1_OFF_DEFAULT;
128 sc->led_off[1] = RT2870_EEPROM_LED2_OFF_DEFAULT;
129 sc->led_off[2] = RT2870_EEPROM_LED3_OFF_DEFAULT;
132 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
133 "%s: EEPROM LED cntl=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
134 device_get_nameunit(sc->dev), sc->led_cntl,
135 sc->led_off[0], sc->led_off[1], sc->led_off[2]);
137 /* read RSSI offsets and LNA gains */
139 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_LNA_GAIN);
141 sc->lna_gain[0] = (val & 0xff);
142 sc->lna_gain[1] = (val >> 8) & 0xff;
144 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_2GHZ_BASE);
146 sc->rssi_off_2ghz[0] = (val & 0xff);
147 sc->rssi_off_2ghz[1] = (val >> 8) & 0xff;
149 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_2GHZ_BASE + sizeof(uint16_t));
151 sc->rssi_off_2ghz[2] = (val & 0xff);
152 sc->lna_gain[2] = (val >> 8) & 0xff;
154 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_5GHZ_BASE);
156 sc->rssi_off_5ghz[0] = (val & 0xff);
157 sc->rssi_off_5ghz[1] = (val >> 8) & 0xff;
159 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_RSSI_OFF_5GHZ_BASE + sizeof(uint16_t));
161 sc->rssi_off_5ghz[2] = (val & 0xff);
162 sc->lna_gain[3] = (val >> 8) & 0xff;
164 for (i = 2; i < RT2870_SOFTC_LNA_GAIN_COUNT; i++)
166 if (sc->lna_gain[i] == 0x00 || sc->lna_gain[i] == (int8_t) 0xff)
168 printf("%s: invalid EEPROM LNA gain #%d: 0x%02x\n",
169 device_get_nameunit(sc->dev), i, sc->lna_gain[i]);
171 sc->lna_gain[i] = sc->lna_gain[1];
175 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
176 "%s: EEPROM LNA gains=0x%02x/0x%02x/0x%02x/0x%02x\n",
177 device_get_nameunit(sc->dev),
178 sc->lna_gain[0], sc->lna_gain[1], sc->lna_gain[2], sc->lna_gain[3]);
180 for (i = 0; i < RT2870_SOFTC_RSSI_OFF_COUNT; i++)
182 if (sc->rssi_off_2ghz[i] < RT2870_EEPROM_RSSI_OFF_MIN ||
183 sc->rssi_off_2ghz[i] > RT2870_EEPROM_RSSI_OFF_MAX)
185 printf("%s: invalid EEPROM RSSI offset #%d (2GHz): 0x%02x\n",
186 device_get_nameunit(sc->dev), i, sc->rssi_off_2ghz[i]);
188 sc->rssi_off_2ghz[i] = 0;
191 if (sc->rssi_off_5ghz[i] < RT2870_EEPROM_RSSI_OFF_MIN ||
192 sc->rssi_off_5ghz[i] > RT2870_EEPROM_RSSI_OFF_MAX)
194 printf("%s: invalid EEPROM RSSI offset #%d (5GHz): 0x%02x\n",
195 device_get_nameunit(sc->dev), i, sc->rssi_off_5ghz[i]);
197 sc->rssi_off_5ghz[i] = 0;
201 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
202 "%s: EEPROM RSSI offsets 2GHz=%d/%d/%d\n",
203 device_get_nameunit(sc->dev),
204 sc->rssi_off_2ghz[0], sc->rssi_off_2ghz[1], sc->rssi_off_2ghz[2]);
206 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
207 "%s: EEPROM RSSI offsets 5GHz=%d/%d/%d\n",
208 device_get_nameunit(sc->dev),
209 sc->rssi_off_5ghz[0], sc->rssi_off_5ghz[1], sc->rssi_off_5ghz[2]);
211 /* read Tx power settings for 2GHz channels */
213 for (i = 0; i < 14; i += 2)
215 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW1_2GHZ_BASE + i / 2);
217 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
218 sc->txpow1[i + 1] = (int8_t) (val >> 8);
220 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW2_2GHZ_BASE + i / 2);
222 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
223 sc->txpow2[i + 1] = (int8_t) (val >> 8);
226 /* read Tx power settings for 5GHz channels */
228 for (; i < RT2870_SOFTC_TXPOW_COUNT; i += 2)
230 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW1_5GHZ_BASE + i / 2);
232 sc->txpow1[i + 0] = (int8_t) (val & 0xff);
233 sc->txpow1[i + 1] = (int8_t) (val >> 8);
235 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW2_5GHZ_BASE + i / 2);
237 sc->txpow2[i + 0] = (int8_t) (val & 0xff);
238 sc->txpow2[i + 1] = (int8_t) (val >> 8);
241 /* fix broken Tx power settings */
243 for (i = 0; i < 14; i++)
245 if (sc->txpow1[i] < RT2870_EEPROM_TXPOW_2GHZ_MIN ||
246 sc->txpow1[i] > RT2870_EEPROM_TXPOW_2GHZ_MAX)
248 printf("%s: invalid EEPROM Tx power1 #%d (2GHz): 0x%02x\n",
249 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
251 sc->txpow1[i] = RT2870_EEPROM_TXPOW_2GHZ_DEFAULT;
254 if (sc->txpow2[i] < RT2870_EEPROM_TXPOW_2GHZ_MIN ||
255 sc->txpow2[i] > RT2870_EEPROM_TXPOW_2GHZ_MAX)
257 printf("%s: invalid EEPROM Tx power2 #%d (2GHz): 0x%02x\n",
258 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
260 sc->txpow2[i] = RT2870_EEPROM_TXPOW_2GHZ_DEFAULT;
264 for (; i < RT2870_SOFTC_TXPOW_COUNT; i++)
266 if (sc->txpow1[i] < RT2870_EEPROM_TXPOW_5GHZ_MIN ||
267 sc->txpow1[i] > RT2870_EEPROM_TXPOW_5GHZ_MAX)
269 printf("%s: invalid EEPROM Tx power1 #%d (5GHz): 0x%02x\n",
270 device_get_nameunit(sc->dev), i, sc->txpow1[i]);
272 sc->txpow1[i] = RT2870_EEPROM_TXPOW_5GHZ_DEFAULT;
275 if (sc->txpow2[i] < RT2870_EEPROM_TXPOW_5GHZ_MIN ||
276 sc->txpow2[i] > RT2870_EEPROM_TXPOW_5GHZ_MAX)
278 printf("%s: invalid EEPROM Tx power2 #%d (5GHz): 0x%02x\n",
279 device_get_nameunit(sc->dev), i, sc->txpow2[i]);
281 sc->txpow2[i] = RT2870_EEPROM_TXPOW_5GHZ_DEFAULT;
285 /* read Tx power per rate deltas */
287 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TXPOW_RATE_DELTA);
289 sc->txpow_rate_delta_2ghz = 0;
290 sc->txpow_rate_delta_5ghz = 0;
292 if ((val & 0xff) != 0xff)
294 if (val & 0x80)
295 sc->txpow_rate_delta_2ghz = (val & 0xf);
297 if (!(val & 0x40))
298 sc->txpow_rate_delta_2ghz = -sc->txpow_rate_delta_2ghz;
301 val >>= 8;
303 if ((val & 0xff) != 0xff)
305 if (val & 0x80)
306 sc->txpow_rate_delta_5ghz = (val & 0xf);
308 if (!(val & 0x40))
309 sc->txpow_rate_delta_5ghz = -sc->txpow_rate_delta_5ghz;
312 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
313 "%s: EEPROM Tx power per rate deltas=%d(2MHz), %d(5MHz)\n",
314 device_get_nameunit(sc->dev),
315 sc->txpow_rate_delta_2ghz, sc->txpow_rate_delta_5ghz);
317 /* read Tx power per rate */
319 for (i = 0; i < RT2870_SOFTC_TXPOW_RATE_COUNT; i++)
321 rt2870_io_eeprom_read_multi(sc, RT2870_EEPROM_TXPOW_RATE_BASE + i * sizeof(uint32_t),
322 &tmp, sizeof(uint32_t));
324 sc->txpow_rate_20mhz[i] = tmp;
325 sc->txpow_rate_40mhz_2ghz[i] =
326 rt2870_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_2ghz);
327 sc->txpow_rate_40mhz_5ghz[i] =
328 rt2870_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_5ghz);
330 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
331 "%s: EEPROM Tx power per rate #%d=0x%08x(20MHz), 0x%08x(40MHz/2GHz), 0x%08x(40MHz/5GHz)\n",
332 device_get_nameunit(sc->dev), i,
333 sc->txpow_rate_20mhz[i], sc->txpow_rate_40mhz_2ghz[i], sc->txpow_rate_40mhz_5ghz[i]);
336 if (sc->tx_agc_cntl)
337 sc->tx_agc_cntl_2ghz = sc->tx_agc_cntl_5ghz = 1;
339 /* read factory-calibrated samples for temperature compensation */
341 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE);
343 sc->tssi_2ghz[0] = (val & 0xff); /* [-4] */
344 sc->tssi_2ghz[1] = (val >> 8); /* [-3] */
346 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + sizeof(uint16_t));
348 sc->tssi_2ghz[2] = (val & 0xff); /* [-2] */
349 sc->tssi_2ghz[3] = (val >> 8); /* [-1] */
351 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 2 * sizeof(uint16_t));
353 sc->tssi_2ghz[4] = (val & 0xff); /* [0] */
354 sc->tssi_2ghz[5] = (val >> 8); /* [+1] */
356 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 3 * sizeof(uint16_t));
358 sc->tssi_2ghz[6] = (val & 0xff); /* [+2] */
359 sc->tssi_2ghz[7] = (val >> 8); /* [+3] */
361 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_2GHZ_BASE + 4 * sizeof(uint16_t));
363 sc->tssi_2ghz[8] = (val & 0xff); /* [+4] */
364 sc->tssi_step_2ghz = (val >> 8);
366 if (sc->tssi_2ghz[4] == 0xff)
367 sc->tx_agc_cntl_2ghz = 0;
369 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
370 "%s: EEPROM TSSI 2GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
371 "0x%02x, 0x%02x, step=%d\n",
372 device_get_nameunit(sc->dev),
373 sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2],
374 sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5],
375 sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8],
376 sc->tssi_step_2ghz);
378 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE);
380 sc->tssi_5ghz[0] = (val & 0xff); /* [-4] */
381 sc->tssi_5ghz[1] = (val >> 8); /* [-3] */
383 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + sizeof(uint16_t));
385 sc->tssi_5ghz[2] = (val & 0xff); /* [-2] */
386 sc->tssi_5ghz[3] = (val >> 8); /* [-1] */
388 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 2 * sizeof(uint16_t));
390 sc->tssi_5ghz[4] = (val & 0xff); /* [0] */
391 sc->tssi_5ghz[5] = (val >> 8); /* [+1] */
393 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 3 * sizeof(uint16_t));
395 sc->tssi_5ghz[6] = (val & 0xff); /* [+2] */
396 sc->tssi_5ghz[7] = (val >> 8); /* [+3] */
398 val = rt2870_io_eeprom_read(sc, RT2870_EEPROM_TSSI_5GHZ_BASE + 4 * sizeof(uint16_t));
400 sc->tssi_5ghz[8] = (val & 0xff); /* [+4] */
401 sc->tssi_step_5ghz = (val >> 8);
403 if (sc->tssi_5ghz[4] == 0xff)
404 sc->tx_agc_cntl_5ghz = 0;
406 RT2870_DPRINTF(sc, RT2870_DEBUG_EEPROM,
407 "%s: EEPROM TSSI 5GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
408 "0x%02x, 0x%02x, step=%d\n",
409 device_get_nameunit(sc->dev),
410 sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2],
411 sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5],
412 sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8],
413 sc->tssi_step_5ghz);
415 /* read default BBP settings */
417 rt2870_io_eeprom_read_multi(sc, RT2870_EEPROM_BBP_BASE,
418 sc->bbp_eeprom, RT2870_SOFTC_BBP_EEPROM_COUNT * sizeof(uint16_t));
422 * rt2870_read_eeprom_txpow_rate_add_delta
424 uint32_t rt2870_read_eeprom_txpow_rate_add_delta(uint32_t txpow_rate,
425 int8_t delta)
427 int8_t b4;
428 int i;
430 for (i = 0; i < 8; i++)
432 b4 = txpow_rate & 0xf;
433 b4 += delta;
435 if (b4 < 0)
436 b4 = 0;
437 else if (b4 > 0xf)
438 b4 = 0xf;
440 txpow_rate = (txpow_rate >> 4) | (b4 << 28);
443 return txpow_rate;