1
2/*-
3 * Copyright (c) 2009-2010 Alexander Egorenkov <egorenar@gmail.com>
4 * Copyright (c) 2009 Damien Bergamini <damien.bergamini@free.fr>
5 *
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.
9 *
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.
17 */
18
19#include <dev/rt2860/rt2860_read_eeprom.h>
20#include <dev/rt2860/rt2860_reg.h>
21#include <dev/rt2860/rt2860_eeprom.h>
22#include <dev/rt2860/rt2860_io.h>
23#include <dev/rt2860/rt2860_debug.h>
24
25/*
26 * rt2860_read_eeprom
27 */
28void rt2860_read_eeprom(struct rt2860_softc *sc)
29{
30	uint32_t tmp;
31	uint16_t val;
32	int i;
33
34	/* read EEPROM address number */
35
36	tmp = rt2860_io_mac_read(sc, RT2860_REG_EEPROM_CSR);
37
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;
44
45	/* read EEPROM version */
46
47	sc->eeprom_rev = rt2860_io_eeprom_read(sc, RT2860_EEPROM_VERSION);
48
49	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
50		"%s: EEPROM rev=0x%04x\n",
51		device_get_nameunit(sc->dev), sc->eeprom_rev);
52
53	/* read MAC address */
54
55	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS01);
56
57	sc->mac_addr[0] = (val & 0xff);
58	sc->mac_addr[1] = (val >> 8);
59
60	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS23);
61
62	sc->mac_addr[2] = (val & 0xff);
63	sc->mac_addr[3] = (val >> 8);
64
65	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ADDRESS45);
66
67	sc->mac_addr[4] = (val & 0xff);
68	sc->mac_addr[5] = (val >> 8);
69
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));
73
74	/* read RF information */
75
76	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_ANTENNA);
77	if (val == 0xffff)
78	{
79		printf("%s: invalid EEPROM antenna info\n",
80			device_get_nameunit(sc->dev));
81
82		sc->rf_rev = RT2860_EEPROM_RF_2820;
83		sc->ntxpath = 1;
84		sc->nrxpath = 2;
85	}
86	else
87	{
88		sc->rf_rev = (val >> 8) & 0xf;
89		sc->ntxpath = (val >> 4) & 0xf;
90		sc->nrxpath = (val & 0xf);
91	}
92
93	if ((sc->mac_rev != 0x28830300) && (sc->nrxpath > 2))
94	{
95		/* only 2 Rx streams for RT2860 series */
96
97		sc->nrxpath = 2;
98	}
99
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);
103
104	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_NIC_CONFIG);
105	if ((val & 0xff00) != 0xff00)
106		sc->patch_dac = (val >> 15) & 1;
107
108	sc->hw_radio_cntl = ((val & RT2860_EEPROM_HW_RADIO_CNTL) ? 1 : 0);
109	sc->tx_agc_cntl = ((val & RT2860_EEPROM_TX_AGC_CNTL) ? 1 : 0);
110	sc->ext_lna_2ghz = ((val & RT2860_EEPROM_EXT_LNA_2GHZ) ? 1 : 0);
111	sc->ext_lna_5ghz = ((val & RT2860_EEPROM_EXT_LNA_5GHZ) ? 1 : 0);
112
113	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
114		"%s: EEPROM NIC config: HW radio cntl=%d, Tx AGC cntl=%d, ext LNA gains=%d/%d\n",
115		device_get_nameunit(sc->dev),
116		sc->hw_radio_cntl, sc->tx_agc_cntl, sc->ext_lna_2ghz, sc->ext_lna_5ghz);
117
118	/* read country code */
119
120	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_COUNTRY);
121
122	sc->country_2ghz = (val >> 8) & 0xff;
123	sc->country_5ghz = (val & 0xff);
124
125	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
126		"%s: EEPROM country code=%d/%d\n",
127		device_get_nameunit(sc->dev), sc->country_2ghz, sc->country_5ghz);
128
129	/* read RF frequency offset */
130
131	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RF_FREQ_OFF);
132
133	if ((val & 0xff) != 0xff)
134	{
135		sc->rf_freq_off = (val & 0xff);
136	}
137	else
138	{
139		printf("%s: invalid EEPROM RF freq offset\n",
140			device_get_nameunit(sc->dev));
141
142		sc->rf_freq_off = 0;
143	}
144
145	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
146		"%s: EEPROM freq offset=0x%02x\n",
147		device_get_nameunit(sc->dev), sc->rf_freq_off);
148
149	/* read LEDs operating mode */
150
151	if (((val >> 8) & 0xff) != 0xff)
152	{
153		sc->led_cntl = ((val >> 8) & 0xff);
154		sc->led_off[0] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED1_OFF);
155		sc->led_off[1] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED2_OFF);
156		sc->led_off[2] = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LED3_OFF);
157	}
158	else
159	{
160		printf("%s: invalid EEPROM LED settings\n",
161			device_get_nameunit(sc->dev));
162
163		sc->led_cntl = RT2860_EEPROM_LED_CNTL_DEFAULT;
164		sc->led_off[0] = RT2860_EEPROM_LED1_OFF_DEFAULT;
165		sc->led_off[1] = RT2860_EEPROM_LED2_OFF_DEFAULT;
166		sc->led_off[2] = RT2860_EEPROM_LED3_OFF_DEFAULT;
167	}
168
169	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
170		"%s: EEPROM LED cntl=0x%02x, LEDs=0x%04x/0x%04x/0x%04x\n",
171		device_get_nameunit(sc->dev), sc->led_cntl,
172		sc->led_off[0], sc->led_off[1], sc->led_off[2]);
173
174	/* read RSSI offsets and LNA gains */
175
176	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_LNA_GAIN);
177	if ((sc->mac_rev & 0xffff0000) >= 0x30710000)
178		sc->lna_gain[0] = RT3090_DEF_LNA;
179	else				/* channel group 0 */
180		sc->lna_gain[0] = val & 0xff;
181
182//	sc->lna_gain[0] = (val & 0xff);
183	sc->lna_gain[1] = (val >> 8) & 0xff;
184
185	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE);
186
187	sc->rssi_off_2ghz[0] = (val & 0xff);
188	sc->rssi_off_2ghz[1] = (val >> 8) & 0xff;
189
190	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_2GHZ_BASE + 2);
191
192	//sc->rssi_off_2ghz[2] = (val & 0xff);
193	sc->lna_gain[2] = (val >> 8) & 0xff;
194	if ((sc->mac_rev & 0xffff0000) >= 0x30710000) {
195		/*
196		 * On RT3090 chips (limited to 2 Rx chains), this ROM
197		 * field contains the Tx mixer gain for the 2GHz band.
198		 */
199		if ((val & 0xff) != 0xff)
200			sc->txmixgain_2ghz = val & 0x7;
201		//DPRINTF(("tx mixer gain=%u (2GHz)\n", sc->txmixgain_2ghz));
202	} else
203		sc->rssi_off_2ghz[2] = val & 0xff;	/* Ant C */
204
205	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE);
206
207	sc->rssi_off_5ghz[0] = (val & 0xff);
208	sc->rssi_off_5ghz[1] = (val >> 8) & 0xff;
209
210	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_RSSI_OFF_5GHZ_BASE + 2);
211
212	sc->rssi_off_5ghz[2] = (val & 0xff);
213	sc->lna_gain[3] = (val >> 8) & 0xff;
214
215	for (i = 2; i < RT2860_SOFTC_LNA_GAIN_COUNT; i++)
216	{
217		if (sc->lna_gain[i] == 0x00 || sc->lna_gain[i] == (int8_t) 0xff)
218		{
219			printf("%s: invalid EEPROM LNA gain #%d: 0x%02x\n",
220				device_get_nameunit(sc->dev), i, sc->lna_gain[i]);
221
222			sc->lna_gain[i] = sc->lna_gain[1];
223		}
224	}
225
226	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
227		"%s: EEPROM LNA gains=0x%02x/0x%02x/0x%02x/0x%02x\n",
228		device_get_nameunit(sc->dev),
229		sc->lna_gain[0], sc->lna_gain[1], sc->lna_gain[2], sc->lna_gain[3]);
230
231	for (i = 0; i < RT2860_SOFTC_RSSI_OFF_COUNT; i++)
232	{
233		if (sc->rssi_off_2ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
234			sc->rssi_off_2ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
235		{
236			printf("%s: invalid EEPROM RSSI offset #%d (2GHz): 0x%02x\n",
237				device_get_nameunit(sc->dev), i, sc->rssi_off_2ghz[i]);
238
239			sc->rssi_off_2ghz[i] = 0;
240		}
241
242		if (sc->rssi_off_5ghz[i] < RT2860_EEPROM_RSSI_OFF_MIN ||
243			sc->rssi_off_5ghz[i] > RT2860_EEPROM_RSSI_OFF_MAX)
244		{
245			printf("%s: invalid EEPROM RSSI offset #%d (5GHz): 0x%02x\n",
246				device_get_nameunit(sc->dev), i, sc->rssi_off_5ghz[i]);
247
248			sc->rssi_off_5ghz[i] = 0;
249		}
250	}
251
252	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
253		"%s: EEPROM RSSI offsets 2GHz=%d/%d/%d\n",
254		device_get_nameunit(sc->dev),
255		sc->rssi_off_2ghz[0], sc->rssi_off_2ghz[1], sc->rssi_off_2ghz[2]);
256
257	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
258		"%s: EEPROM RSSI offsets 5GHz=%d/%d/%d\n",
259		device_get_nameunit(sc->dev),
260		sc->rssi_off_5ghz[0], sc->rssi_off_5ghz[1], sc->rssi_off_5ghz[2]);
261
262	/* read Tx power settings for 2GHz channels */
263
264	for (i = 0; i < 14; i += 2)
265	{
266		val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_2GHZ_BASE + i / 2);
267
268		sc->txpow1[i + 0] = (int8_t) (val & 0xff);
269		sc->txpow1[i + 1] = (int8_t) (val >> 8);
270
271		val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_2GHZ_BASE + i / 2);
272
273		sc->txpow2[i + 0] = (int8_t) (val & 0xff);
274		sc->txpow2[i + 1] = (int8_t) (val >> 8);
275	}
276
277	/* read Tx power settings for 5GHz channels */
278
279	for (; i < RT2860_SOFTC_TXPOW_COUNT; i += 2)
280	{
281		val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW1_5GHZ_BASE + i / 2);
282
283		sc->txpow1[i + 0] = (int8_t) (val & 0xff);
284		sc->txpow1[i + 1] = (int8_t) (val >> 8);
285
286		val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW2_5GHZ_BASE + i / 2);
287
288		sc->txpow2[i + 0] = (int8_t) (val & 0xff);
289		sc->txpow2[i + 1] = (int8_t) (val >> 8);
290	}
291
292	/* fix broken Tx power settings */
293
294    for (i = 0; i < 14; i++)
295	{
296		if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
297			sc->txpow1[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
298		{
299			printf("%s: invalid EEPROM Tx power1 #%d (2GHz): 0x%02x\n",
300				device_get_nameunit(sc->dev), i, sc->txpow1[i]);
301
302			sc->txpow1[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
303		}
304
305		if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_2GHZ_MIN ||
306			sc->txpow2[i] > RT2860_EEPROM_TXPOW_2GHZ_MAX)
307		{
308			printf("%s: invalid EEPROM Tx power2 #%d (2GHz): 0x%02x\n",
309				device_get_nameunit(sc->dev), i, sc->txpow2[i]);
310
311			sc->txpow2[i] = RT2860_EEPROM_TXPOW_2GHZ_DEFAULT;
312		}
313	}
314
315	for (; i < RT2860_SOFTC_TXPOW_COUNT; i++)
316	{
317		if (sc->txpow1[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
318			sc->txpow1[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
319		{
320			printf("%s: invalid EEPROM Tx power1 #%d (5GHz): 0x%02x\n",
321				device_get_nameunit(sc->dev), i, sc->txpow1[i]);
322
323			sc->txpow1[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
324		}
325
326		if (sc->txpow2[i] < RT2860_EEPROM_TXPOW_5GHZ_MIN ||
327			sc->txpow2[i] > RT2860_EEPROM_TXPOW_5GHZ_MAX)
328		{
329			printf("%s: invalid EEPROM Tx power2 #%d (5GHz): 0x%02x\n",
330				device_get_nameunit(sc->dev), i, sc->txpow2[i]);
331
332			sc->txpow2[i] = RT2860_EEPROM_TXPOW_5GHZ_DEFAULT;
333		}
334	}
335
336	/* read Tx power per rate deltas */
337
338	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TXPOW_RATE_DELTA);
339
340	sc->txpow_rate_delta_2ghz = 0;
341	sc->txpow_rate_delta_5ghz = 0;
342
343	if ((val & 0xff) != 0xff)
344	{
345		if (val & 0x80)
346			sc->txpow_rate_delta_2ghz = (val & 0xf);
347
348		if (!(val & 0x40))
349			sc->txpow_rate_delta_2ghz = -sc->txpow_rate_delta_2ghz;
350	}
351
352	val >>= 8;
353
354	if ((val & 0xff) != 0xff)
355	{
356		if (val & 0x80)
357			sc->txpow_rate_delta_5ghz = (val & 0xf);
358
359		if (!(val & 0x40))
360			sc->txpow_rate_delta_5ghz = -sc->txpow_rate_delta_5ghz;
361	}
362
363	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
364		"%s: EEPROM Tx power per rate deltas=%d(2MHz), %d(5MHz)\n",
365		device_get_nameunit(sc->dev),
366		sc->txpow_rate_delta_2ghz, sc->txpow_rate_delta_5ghz);
367
368	/* read Tx power per rate */
369
370	for (i = 0; i < RT2860_SOFTC_TXPOW_RATE_COUNT; i++)
371	{
372		rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_TXPOW_RATE_BASE + i * sizeof(uint32_t),
373			&tmp, sizeof(uint32_t));
374
375		sc->txpow_rate_20mhz[i] = tmp;
376		sc->txpow_rate_40mhz_2ghz[i] =
377			rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_2ghz);
378		sc->txpow_rate_40mhz_5ghz[i] =
379			rt2860_read_eeprom_txpow_rate_add_delta(tmp, sc->txpow_rate_delta_5ghz);
380
381		RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
382			"%s: EEPROM Tx power per rate #%d=0x%08x(20MHz), 0x%08x(40MHz/2GHz), 0x%08x(40MHz/5GHz)\n",
383			device_get_nameunit(sc->dev), i,
384			sc->txpow_rate_20mhz[i], sc->txpow_rate_40mhz_2ghz[i], sc->txpow_rate_40mhz_5ghz[i]);
385	}
386
387	if (sc->tx_agc_cntl)
388		sc->tx_agc_cntl_2ghz = sc->tx_agc_cntl_5ghz = 1;
389
390	/* read factory-calibrated samples for temperature compensation */
391
392	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE);
393
394	sc->tssi_2ghz[0] = (val & 0xff);	/* [-4] */
395	sc->tssi_2ghz[1] = (val >> 8);		/* [-3] */
396
397	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 2);
398
399	sc->tssi_2ghz[2] = (val & 0xff);	/* [-2] */
400	sc->tssi_2ghz[3] = (val >> 8);		/* [-1] */
401
402	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 2 * 2);
403
404	sc->tssi_2ghz[4] = (val & 0xff);	/* [0] */
405	sc->tssi_2ghz[5] = (val >> 8);		/* [+1] */
406
407	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 3 * 2);
408
409	sc->tssi_2ghz[6] = (val & 0xff);	/* [+2] */
410	sc->tssi_2ghz[7] = (val >> 8);		/* [+3] */
411
412	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_2GHZ_BASE + 4 * 2);
413
414	sc->tssi_2ghz[8] = (val & 0xff);	/* [+4] */
415	sc->tssi_step_2ghz = (val >> 8);
416
417	if (sc->tssi_2ghz[4] == 0xff)
418		sc->tx_agc_cntl_2ghz = 0;
419
420	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
421		"%s: EEPROM TSSI 2GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
422		"0x%02x, 0x%02x, step=%d\n",
423		device_get_nameunit(sc->dev),
424		sc->tssi_2ghz[0], sc->tssi_2ghz[1], sc->tssi_2ghz[2],
425		sc->tssi_2ghz[3], sc->tssi_2ghz[4], sc->tssi_2ghz[5],
426		sc->tssi_2ghz[6], sc->tssi_2ghz[7], sc->tssi_2ghz[8],
427		sc->tssi_step_2ghz);
428
429	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE);
430
431	sc->tssi_5ghz[0] = (val & 0xff);	/* [-4] */
432	sc->tssi_5ghz[1] = (val >> 8);		/* [-3] */
433
434	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 2);
435
436	sc->tssi_5ghz[2] = (val & 0xff);	/* [-2] */
437	sc->tssi_5ghz[3] = (val >> 8);		/* [-1] */
438
439	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 2 * 2);
440
441	sc->tssi_5ghz[4] = (val & 0xff);	/* [0] */
442	sc->tssi_5ghz[5] = (val >> 8);		/* [+1] */
443
444	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 3 * 2);
445
446	sc->tssi_5ghz[6] = (val & 0xff);	/* [+2] */
447	sc->tssi_5ghz[7] = (val >> 8);		/* [+3] */
448
449	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_TSSI_5GHZ_BASE + 4 * 2);
450
451	sc->tssi_5ghz[8] = (val & 0xff);	/* [+4] */
452	sc->tssi_step_5ghz = (val >> 8);
453
454	if (sc->tssi_5ghz[4] == 0xff)
455		sc->tx_agc_cntl_5ghz = 0;
456
457	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
458		"%s: EEPROM TSSI 5GHz: 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, 0x%02x, "
459		"0x%02x, 0x%02x, step=%d\n",
460		device_get_nameunit(sc->dev),
461		sc->tssi_5ghz[0], sc->tssi_5ghz[1], sc->tssi_5ghz[2],
462		sc->tssi_5ghz[3], sc->tssi_5ghz[4], sc->tssi_5ghz[5],
463		sc->tssi_5ghz[6], sc->tssi_5ghz[7], sc->tssi_5ghz[8],
464		sc->tssi_step_5ghz);
465
466	/* read default BBP settings */
467
468	rt2860_io_eeprom_read_multi(sc, RT2860_EEPROM_BBP_BASE,
469		sc->bbp_eeprom, RT2860_SOFTC_BBP_EEPROM_COUNT * 2);
470
471	if ((sc->mac_rev & 0xffff0000) >= 0x30710000) {
472		/* read vendor RF settings */
473		for (i = 0; i < 10; i++) {
474			val = rt2860_io_eeprom_read(sc, RT3071_EEPROM_RF_BASE + i);
475			sc->rf[i].val = val & 0xff;
476			sc->rf[i].reg = val >> 8;
477//			DPRINTF(("RF%d=0x%02x\n", sc->rf[i].reg,
478//			    sc->rf[i].val));
479		}
480	}
481	/* read powersave level */
482
483	val = rt2860_io_eeprom_read(sc, RT2860_EEPROM_POWERSAVE_LEVEL);
484
485	sc->powersave_level = val & 0xff;
486
487	if ((sc->powersave_level & 0xff) == 0xff)
488		printf("%s: invalid EEPROM powersave level\n",
489			device_get_nameunit(sc->dev));
490
491	RT2860_DPRINTF(sc, RT2860_DEBUG_EEPROM,
492		"%s: EEPROM powersave level=0x%02x\n",
493		device_get_nameunit(sc->dev), sc->powersave_level);
494}
495
496/*
497 * rt2860_read_eeprom_txpow_rate_add_delta
498 */
499uint32_t rt2860_read_eeprom_txpow_rate_add_delta(uint32_t txpow_rate,
500	int8_t delta)
501{
502	int8_t b4;
503	int i;
504
505	for (i = 0; i < 8; i++)
506	{
507		b4 = txpow_rate & 0xf;
508		b4 += delta;
509
510		if (b4 < 0)
511			b4 = 0;
512		else if (b4 > 0xf)
513			b4 = 0xf;
514
515		txpow_rate = (txpow_rate >> 4) | (b4 << 28);
516	}
517
518	return txpow_rate;
519}
520