Merge commit 'v2.6.28-rc2' into core/locking
[pandora-kernel.git] / drivers / net / wireless / ath5k / eeprom.c
1 /*
2  * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3  * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  *
17  */
18
19 /*************************************\
20 * EEPROM access functions and helpers *
21 \*************************************/
22
23 #include "ath5k.h"
24 #include "reg.h"
25 #include "debug.h"
26 #include "base.h"
27
28 /*
29  * Read from eeprom
30  */
31 static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
32 {
33         u32 status, timeout;
34
35         ATH5K_TRACE(ah->ah_sc);
36         /*
37          * Initialize EEPROM access
38          */
39         if (ah->ah_version == AR5K_AR5210) {
40                 AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
41                 (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
42         } else {
43                 ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
44                 AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
45                                 AR5K_EEPROM_CMD_READ);
46         }
47
48         for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
49                 status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
50                 if (status & AR5K_EEPROM_STAT_RDDONE) {
51                         if (status & AR5K_EEPROM_STAT_RDERR)
52                                 return -EIO;
53                         *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
54                                         0xffff);
55                         return 0;
56                 }
57                 udelay(15);
58         }
59
60         return -ETIMEDOUT;
61 }
62
63 /*
64  * Translate binary channel representation in EEPROM to frequency
65  */
66 static u16 ath5k_eeprom_bin2freq(struct ath5k_hw *ah, u16 bin,
67                                 unsigned int mode)
68 {
69         u16 val;
70
71         if (bin == AR5K_EEPROM_CHANNEL_DIS)
72                 return bin;
73
74         if (mode == AR5K_EEPROM_MODE_11A) {
75                 if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
76                         val = (5 * bin) + 4800;
77                 else
78                         val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
79                                 (bin * 10) + 5100;
80         } else {
81                 if (ah->ah_ee_version > AR5K_EEPROM_VERSION_3_2)
82                         val = bin + 2300;
83                 else
84                         val = bin + 2400;
85         }
86
87         return val;
88 }
89
90 /*
91  * Read antenna infos from eeprom
92  */
93 static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
94                 unsigned int mode)
95 {
96         struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
97         u32 o = *offset;
98         u16 val;
99         int ret, i = 0;
100
101         AR5K_EEPROM_READ(o++, val);
102         ee->ee_switch_settling[mode]    = (val >> 8) & 0x7f;
103         ee->ee_ant_tx_rx[mode]          = (val >> 2) & 0x3f;
104         ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
105
106         AR5K_EEPROM_READ(o++, val);
107         ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
108         ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
109         ee->ee_ant_control[mode][i++]   = val & 0x3f;
110
111         AR5K_EEPROM_READ(o++, val);
112         ee->ee_ant_control[mode][i++]   = (val >> 10) & 0x3f;
113         ee->ee_ant_control[mode][i++]   = (val >> 4) & 0x3f;
114         ee->ee_ant_control[mode][i]     = (val << 2) & 0x3f;
115
116         AR5K_EEPROM_READ(o++, val);
117         ee->ee_ant_control[mode][i++]   |= (val >> 14) & 0x3;
118         ee->ee_ant_control[mode][i++]   = (val >> 8) & 0x3f;
119         ee->ee_ant_control[mode][i++]   = (val >> 2) & 0x3f;
120         ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
121
122         AR5K_EEPROM_READ(o++, val);
123         ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
124         ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
125         ee->ee_ant_control[mode][i++]   = val & 0x3f;
126
127         /* Get antenna modes */
128         ah->ah_antenna[mode][0] =
129             (ee->ee_ant_control[mode][0] << 4) | 0x1;
130         ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
131              ee->ee_ant_control[mode][1]        |
132             (ee->ee_ant_control[mode][2] << 6)  |
133             (ee->ee_ant_control[mode][3] << 12) |
134             (ee->ee_ant_control[mode][4] << 18) |
135             (ee->ee_ant_control[mode][5] << 24);
136         ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
137              ee->ee_ant_control[mode][6]        |
138             (ee->ee_ant_control[mode][7] << 6)  |
139             (ee->ee_ant_control[mode][8] << 12) |
140             (ee->ee_ant_control[mode][9] << 18) |
141             (ee->ee_ant_control[mode][10] << 24);
142
143         /* return new offset */
144         *offset = o;
145
146         return 0;
147 }
148
149 /*
150  * Read supported modes from eeprom
151  */
152 static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
153                 unsigned int mode)
154 {
155         struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
156         u32 o = *offset;
157         u16 val;
158         int ret;
159
160         AR5K_EEPROM_READ(o++, val);
161         ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
162         ee->ee_thr_62[mode]             = val & 0xff;
163
164         if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
165                 ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
166
167         AR5K_EEPROM_READ(o++, val);
168         ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
169         ee->ee_tx_frm2xpa_enable[mode]  = val & 0xff;
170
171         AR5K_EEPROM_READ(o++, val);
172         ee->ee_pga_desired_size[mode]   = (val >> 8) & 0xff;
173
174         if ((val & 0xff) & 0x80)
175                 ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
176         else
177                 ee->ee_noise_floor_thr[mode] = val & 0xff;
178
179         if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
180                 ee->ee_noise_floor_thr[mode] =
181                     mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
182
183         AR5K_EEPROM_READ(o++, val);
184         ee->ee_xlna_gain[mode]          = (val >> 5) & 0xff;
185         ee->ee_x_gain[mode]             = (val >> 1) & 0xf;
186         ee->ee_xpd[mode]                = val & 0x1;
187
188         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
189                 ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
190
191         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
192                 AR5K_EEPROM_READ(o++, val);
193                 ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
194
195                 if (mode == AR5K_EEPROM_MODE_11A)
196                         ee->ee_xr_power[mode] = val & 0x3f;
197                 else {
198                         ee->ee_ob[mode][0] = val & 0x7;
199                         ee->ee_db[mode][0] = (val >> 3) & 0x7;
200                 }
201         }
202
203         if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
204                 ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
205                 ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
206         } else {
207                 ee->ee_i_gain[mode] = (val >> 13) & 0x7;
208
209                 AR5K_EEPROM_READ(o++, val);
210                 ee->ee_i_gain[mode] |= (val << 3) & 0x38;
211
212                 if (mode == AR5K_EEPROM_MODE_11G)
213                         ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
214         }
215
216         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
217                         mode == AR5K_EEPROM_MODE_11A) {
218                 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
219                 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
220         }
221
222         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6 &&
223             mode == AR5K_EEPROM_MODE_11G)
224                 ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
225
226         /* return new offset */
227         *offset = o;
228
229         return 0;
230 }
231
232 /*
233  * Initialize eeprom & capabilities structs
234  */
235 int ath5k_eeprom_init(struct ath5k_hw *ah)
236 {
237         struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
238         unsigned int mode, i;
239         int ret;
240         u32 offset;
241         u16 val;
242
243         /* Initial TX thermal adjustment values */
244         ee->ee_tx_clip = 4;
245         ee->ee_pwd_84 = ee->ee_pwd_90 = 1;
246         ee->ee_gain_select = 1;
247
248         /*
249          * Read values from EEPROM and store them in the capability structure
250          */
251         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
252         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
253         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
254         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
255         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
256
257         /* Return if we have an old EEPROM */
258         if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
259                 return 0;
260
261 #ifdef notyet
262         /*
263          * Validate the checksum of the EEPROM date. There are some
264          * devices with invalid EEPROMs.
265          */
266         for (cksum = 0, offset = 0; offset < AR5K_EEPROM_INFO_MAX; offset++) {
267                 AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val);
268                 cksum ^= val;
269         }
270         if (cksum != AR5K_EEPROM_INFO_CKSUM) {
271                 ATH5K_ERR(ah->ah_sc, "Invalid EEPROM checksum 0x%04x\n", cksum);
272                 return -EIO;
273         }
274 #endif
275
276         AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
277             ee_ant_gain);
278
279         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
280                 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
281                 AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
282         }
283
284         if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
285                 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
286                 ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
287                 ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
288
289                 AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
290                 ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
291                 ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
292         }
293
294         /*
295          * Get conformance test limit values
296          */
297         offset = AR5K_EEPROM_CTL(ah->ah_ee_version);
298         ee->ee_ctls = AR5K_EEPROM_N_CTLS(ah->ah_ee_version);
299
300         for (i = 0; i < ee->ee_ctls; i++) {
301                 AR5K_EEPROM_READ(offset++, val);
302                 ee->ee_ctl[i] = (val >> 8) & 0xff;
303                 ee->ee_ctl[i + 1] = val & 0xff;
304         }
305
306         /*
307          * Get values for 802.11a (5GHz)
308          */
309         mode = AR5K_EEPROM_MODE_11A;
310
311         ee->ee_turbo_max_power[mode] =
312                         AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
313
314         offset = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
315
316         ret = ath5k_eeprom_read_ants(ah, &offset, mode);
317         if (ret)
318                 return ret;
319
320         AR5K_EEPROM_READ(offset++, val);
321         ee->ee_adc_desired_size[mode]   = (s8)((val >> 8) & 0xff);
322         ee->ee_ob[mode][3]              = (val >> 5) & 0x7;
323         ee->ee_db[mode][3]              = (val >> 2) & 0x7;
324         ee->ee_ob[mode][2]              = (val << 1) & 0x7;
325
326         AR5K_EEPROM_READ(offset++, val);
327         ee->ee_ob[mode][2]              |= (val >> 15) & 0x1;
328         ee->ee_db[mode][2]              = (val >> 12) & 0x7;
329         ee->ee_ob[mode][1]              = (val >> 9) & 0x7;
330         ee->ee_db[mode][1]              = (val >> 6) & 0x7;
331         ee->ee_ob[mode][0]              = (val >> 3) & 0x7;
332         ee->ee_db[mode][0]              = val & 0x7;
333
334         ret = ath5k_eeprom_read_modes(ah, &offset, mode);
335         if (ret)
336                 return ret;
337
338         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) {
339                 AR5K_EEPROM_READ(offset++, val);
340                 ee->ee_margin_tx_rx[mode] = val & 0x3f;
341         }
342
343         /*
344          * Get values for 802.11b (2.4GHz)
345          */
346         mode = AR5K_EEPROM_MODE_11B;
347         offset = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
348
349         ret = ath5k_eeprom_read_ants(ah, &offset, mode);
350         if (ret)
351                 return ret;
352
353         AR5K_EEPROM_READ(offset++, val);
354         ee->ee_adc_desired_size[mode]   = (s8)((val >> 8) & 0xff);
355         ee->ee_ob[mode][1]              = (val >> 4) & 0x7;
356         ee->ee_db[mode][1]              = val & 0x7;
357
358         ret = ath5k_eeprom_read_modes(ah, &offset, mode);
359         if (ret)
360                 return ret;
361
362         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
363                 AR5K_EEPROM_READ(offset++, val);
364                 ee->ee_cal_pier[mode][0] =
365                         ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
366                 ee->ee_cal_pier[mode][1] =
367                         ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
368
369                 AR5K_EEPROM_READ(offset++, val);
370                 ee->ee_cal_pier[mode][2] =
371                         ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
372         }
373
374         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
375                 ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
376
377         /*
378          * Get values for 802.11g (2.4GHz)
379          */
380         mode = AR5K_EEPROM_MODE_11G;
381         offset = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
382
383         ret = ath5k_eeprom_read_ants(ah, &offset, mode);
384         if (ret)
385                 return ret;
386
387         AR5K_EEPROM_READ(offset++, val);
388         ee->ee_adc_desired_size[mode]   = (s8)((val >> 8) & 0xff);
389         ee->ee_ob[mode][1]              = (val >> 4) & 0x7;
390         ee->ee_db[mode][1]              = val & 0x7;
391
392         ret = ath5k_eeprom_read_modes(ah, &offset, mode);
393         if (ret)
394                 return ret;
395
396         if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
397                 AR5K_EEPROM_READ(offset++, val);
398                 ee->ee_cal_pier[mode][0] =
399                         ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
400                 ee->ee_cal_pier[mode][1] =
401                         ath5k_eeprom_bin2freq(ah, (val >> 8) & 0xff, mode);
402
403                 AR5K_EEPROM_READ(offset++, val);
404                 ee->ee_turbo_max_power[mode] = val & 0x7f;
405                 ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
406
407                 AR5K_EEPROM_READ(offset++, val);
408                 ee->ee_cal_pier[mode][2] =
409                         ath5k_eeprom_bin2freq(ah, val & 0xff, mode);
410
411                 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
412                         ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
413
414                 AR5K_EEPROM_READ(offset++, val);
415                 ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
416                 ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
417
418                 if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
419                         AR5K_EEPROM_READ(offset++, val);
420                         ee->ee_cck_ofdm_gain_delta = val & 0xff;
421                 }
422         }
423
424         /*
425          * Read 5GHz EEPROM channels
426          */
427
428         return 0;
429 }
430
431 /*
432  * Read the MAC address from eeprom
433  */
434 int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
435 {
436         u8 mac_d[ETH_ALEN];
437         u32 total, offset;
438         u16 data;
439         int octet, ret;
440
441         memset(mac, 0, ETH_ALEN);
442         memset(mac_d, 0, ETH_ALEN);
443
444         ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
445         if (ret)
446                 return ret;
447
448         for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
449                 ret = ath5k_hw_eeprom_read(ah, offset, &data);
450                 if (ret)
451                         return ret;
452
453                 total += data;
454                 mac_d[octet + 1] = data & 0xff;
455                 mac_d[octet] = data >> 8;
456                 octet += 2;
457         }
458
459         memcpy(mac, mac_d, ETH_ALEN);
460
461         if (!total || total == 3 * 0xffff)
462                 return -EINVAL;
463
464         return 0;
465 }
466