source: grub-pc/trunk/fuentes/debian/grub-extras/disabled/gpxe/src/drivers/net/ath5k/ath5k_eeprom.c @ 22

Last change on this file since 22 was 22, checked in by mabarracus, 4 years ago

updated version and apply net.ifnames=0 into debian/rules

File size: 46.4 KB
Line 
1/*
2 * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org>
3 * Copyright (c) 2006-2009 Nick Kossifidis <mickflemm@gmail.com>
4 * Copyright (c) 2008-2009 Felix Fietkau <nbd@openwrt.org>
5 *
6 * Lightly modified for gPXE, July 2009, by Joshua Oreman <oremanj@rwcr.net>.
7 *
8 * Permission to use, copy, modify, and distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *
20 */
21
22FILE_LICENCE ( MIT );
23
24/*************************************\
25* EEPROM access functions and helpers *
26\*************************************/
27
28#include <unistd.h>
29#include <stdlib.h>
30
31#include "ath5k.h"
32#include "reg.h"
33#include "base.h"
34
35/*
36 * Read from eeprom
37 */
38static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data)
39{
40        u32 status, timeout;
41
42        /*
43         * Initialize EEPROM access
44         */
45        if (ah->ah_version == AR5K_AR5210) {
46                AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE);
47                (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset));
48        } else {
49                ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE);
50                AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD,
51                                AR5K_EEPROM_CMD_READ);
52        }
53
54        for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) {
55                status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
56                if (status & AR5K_EEPROM_STAT_RDDONE) {
57                        if (status & AR5K_EEPROM_STAT_RDERR)
58                                return -EIO;
59                        *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
60                                        0xffff);
61                        return 0;
62                }
63                udelay(15);
64        }
65
66        return -ETIMEDOUT;
67}
68
69/*
70 * Translate binary channel representation in EEPROM to frequency
71 */
72static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin,
73                                 unsigned int mode)
74{
75        u16 val;
76
77        if (bin == AR5K_EEPROM_CHANNEL_DIS)
78                return bin;
79
80        if (mode == AR5K_EEPROM_MODE_11A) {
81                if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
82                        val = (5 * bin) + 4800;
83                else
84                        val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 :
85                                (bin * 10) + 5100;
86        } else {
87                if (ee->ee_version > AR5K_EEPROM_VERSION_3_2)
88                        val = bin + 2300;
89                else
90                        val = bin + 2400;
91        }
92
93        return val;
94}
95
96/*
97 * Initialize eeprom & capabilities structs
98 */
99static int
100ath5k_eeprom_init_header(struct ath5k_hw *ah)
101{
102        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
103        int ret;
104        u16 val;
105
106        /*
107         * Read values from EEPROM and store them in the capability structure
108         */
109        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic);
110        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect);
111        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain);
112        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version);
113        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header);
114
115        /* Return if we have an old EEPROM */
116        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0)
117                return 0;
118
119        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version),
120            ee_ant_gain);
121
122        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) {
123                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0);
124                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1);
125
126                /* XXX: Don't know which versions include these two */
127                AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2);
128
129                if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3)
130                        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3);
131
132                if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) {
133                        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4);
134                        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5);
135                        AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6);
136                }
137        }
138
139        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) {
140                AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val);
141                ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7;
142                ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7;
143
144                AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val);
145                ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7;
146                ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7;
147        }
148
149        return 0;
150}
151
152
153/*
154 * Read antenna infos from eeprom
155 */
156static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset,
157                unsigned int mode)
158{
159        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
160        u32 o = *offset;
161        u16 val;
162        int ret, i = 0;
163
164        AR5K_EEPROM_READ(o++, val);
165        ee->ee_switch_settling[mode]    = (val >> 8) & 0x7f;
166        ee->ee_atn_tx_rx[mode]          = (val >> 2) & 0x3f;
167        ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
168
169        AR5K_EEPROM_READ(o++, val);
170        ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
171        ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
172        ee->ee_ant_control[mode][i++]   = val & 0x3f;
173
174        AR5K_EEPROM_READ(o++, val);
175        ee->ee_ant_control[mode][i++]   = (val >> 10) & 0x3f;
176        ee->ee_ant_control[mode][i++]   = (val >> 4) & 0x3f;
177        ee->ee_ant_control[mode][i]     = (val << 2) & 0x3f;
178
179        AR5K_EEPROM_READ(o++, val);
180        ee->ee_ant_control[mode][i++]   |= (val >> 14) & 0x3;
181        ee->ee_ant_control[mode][i++]   = (val >> 8) & 0x3f;
182        ee->ee_ant_control[mode][i++]   = (val >> 2) & 0x3f;
183        ee->ee_ant_control[mode][i]     = (val << 4) & 0x3f;
184
185        AR5K_EEPROM_READ(o++, val);
186        ee->ee_ant_control[mode][i++]   |= (val >> 12) & 0xf;
187        ee->ee_ant_control[mode][i++]   = (val >> 6) & 0x3f;
188        ee->ee_ant_control[mode][i++]   = val & 0x3f;
189
190        /* Get antenna modes */
191        ah->ah_antenna[mode][0] =
192            (ee->ee_ant_control[mode][0] << 4);
193        ah->ah_antenna[mode][AR5K_ANT_FIXED_A] =
194             ee->ee_ant_control[mode][1]        |
195            (ee->ee_ant_control[mode][2] << 6)  |
196            (ee->ee_ant_control[mode][3] << 12) |
197            (ee->ee_ant_control[mode][4] << 18) |
198            (ee->ee_ant_control[mode][5] << 24);
199        ah->ah_antenna[mode][AR5K_ANT_FIXED_B] =
200             ee->ee_ant_control[mode][6]        |
201            (ee->ee_ant_control[mode][7] << 6)  |
202            (ee->ee_ant_control[mode][8] << 12) |
203            (ee->ee_ant_control[mode][9] << 18) |
204            (ee->ee_ant_control[mode][10] << 24);
205
206        /* return new offset */
207        *offset = o;
208
209        return 0;
210}
211
212/*
213 * Read supported modes and some mode-specific calibration data
214 * from eeprom
215 */
216static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset,
217                unsigned int mode)
218{
219        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
220        u32 o = *offset;
221        u16 val;
222        int ret;
223
224        ee->ee_n_piers[mode] = 0;
225        AR5K_EEPROM_READ(o++, val);
226        ee->ee_adc_desired_size[mode]   = (s8)((val >> 8) & 0xff);
227        switch(mode) {
228        case AR5K_EEPROM_MODE_11A:
229                ee->ee_ob[mode][3]      = (val >> 5) & 0x7;
230                ee->ee_db[mode][3]      = (val >> 2) & 0x7;
231                ee->ee_ob[mode][2]      = (val << 1) & 0x7;
232
233                AR5K_EEPROM_READ(o++, val);
234                ee->ee_ob[mode][2]      |= (val >> 15) & 0x1;
235                ee->ee_db[mode][2]      = (val >> 12) & 0x7;
236                ee->ee_ob[mode][1]      = (val >> 9) & 0x7;
237                ee->ee_db[mode][1]      = (val >> 6) & 0x7;
238                ee->ee_ob[mode][0]      = (val >> 3) & 0x7;
239                ee->ee_db[mode][0]      = val & 0x7;
240                break;
241        case AR5K_EEPROM_MODE_11G:
242        case AR5K_EEPROM_MODE_11B:
243                ee->ee_ob[mode][1]      = (val >> 4) & 0x7;
244                ee->ee_db[mode][1]      = val & 0x7;
245                break;
246        }
247
248        AR5K_EEPROM_READ(o++, val);
249        ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff;
250        ee->ee_thr_62[mode]             = val & 0xff;
251
252        if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
253                ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28;
254
255        AR5K_EEPROM_READ(o++, val);
256        ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff;
257        ee->ee_tx_frm2xpa_enable[mode]  = val & 0xff;
258
259        AR5K_EEPROM_READ(o++, val);
260        ee->ee_pga_desired_size[mode]   = (val >> 8) & 0xff;
261
262        if ((val & 0xff) & 0x80)
263                ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1);
264        else
265                ee->ee_noise_floor_thr[mode] = val & 0xff;
266
267        if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2)
268                ee->ee_noise_floor_thr[mode] =
269                    mode == AR5K_EEPROM_MODE_11A ? -54 : -1;
270
271        AR5K_EEPROM_READ(o++, val);
272        ee->ee_xlna_gain[mode]          = (val >> 5) & 0xff;
273        ee->ee_x_gain[mode]             = (val >> 1) & 0xf;
274        ee->ee_xpd[mode]                = val & 0x1;
275
276        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0)
277                ee->ee_fixed_bias[mode] = (val >> 13) & 0x1;
278
279        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) {
280                AR5K_EEPROM_READ(o++, val);
281                ee->ee_false_detect[mode] = (val >> 6) & 0x7f;
282
283                if (mode == AR5K_EEPROM_MODE_11A)
284                        ee->ee_xr_power[mode] = val & 0x3f;
285                else {
286                        ee->ee_ob[mode][0] = val & 0x7;
287                        ee->ee_db[mode][0] = (val >> 3) & 0x7;
288                }
289        }
290
291        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) {
292                ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN;
293                ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA;
294        } else {
295                ee->ee_i_gain[mode] = (val >> 13) & 0x7;
296
297                AR5K_EEPROM_READ(o++, val);
298                ee->ee_i_gain[mode] |= (val << 3) & 0x38;
299
300                if (mode == AR5K_EEPROM_MODE_11G) {
301                        ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff;
302                        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6)
303                                ee->ee_scaled_cck_delta = (val >> 11) & 0x1f;
304                }
305        }
306
307        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 &&
308                        mode == AR5K_EEPROM_MODE_11A) {
309                ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
310                ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
311        }
312
313        if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0)
314                goto done;
315
316        /* Note: >= v5 have bg freq piers on another location
317         * so these freq piers are ignored for >= v5 (should be 0xff
318         * anyway) */
319        switch(mode) {
320        case AR5K_EEPROM_MODE_11A:
321                if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1)
322                        break;
323
324                AR5K_EEPROM_READ(o++, val);
325                ee->ee_margin_tx_rx[mode] = val & 0x3f;
326                break;
327        case AR5K_EEPROM_MODE_11B:
328                AR5K_EEPROM_READ(o++, val);
329
330                ee->ee_pwr_cal_b[0].freq =
331                        ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
332                if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS)
333                        ee->ee_n_piers[mode]++;
334
335                ee->ee_pwr_cal_b[1].freq =
336                        ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
337                if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS)
338                        ee->ee_n_piers[mode]++;
339
340                AR5K_EEPROM_READ(o++, val);
341                ee->ee_pwr_cal_b[2].freq =
342                        ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
343                if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS)
344                        ee->ee_n_piers[mode]++;
345
346                if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
347                        ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
348                break;
349        case AR5K_EEPROM_MODE_11G:
350                AR5K_EEPROM_READ(o++, val);
351
352                ee->ee_pwr_cal_g[0].freq =
353                        ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
354                if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS)
355                        ee->ee_n_piers[mode]++;
356
357                ee->ee_pwr_cal_g[1].freq =
358                        ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
359                if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS)
360                        ee->ee_n_piers[mode]++;
361
362                AR5K_EEPROM_READ(o++, val);
363                ee->ee_turbo_max_power[mode] = val & 0x7f;
364                ee->ee_xr_power[mode] = (val >> 7) & 0x3f;
365
366                AR5K_EEPROM_READ(o++, val);
367                ee->ee_pwr_cal_g[2].freq =
368                        ath5k_eeprom_bin2freq(ee, val & 0xff, mode);
369                if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS)
370                        ee->ee_n_piers[mode]++;
371
372                if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1)
373                        ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f;
374
375                AR5K_EEPROM_READ(o++, val);
376                ee->ee_i_cal[mode] = (val >> 8) & 0x3f;
377                ee->ee_q_cal[mode] = (val >> 3) & 0x1f;
378
379                if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) {
380                        AR5K_EEPROM_READ(o++, val);
381                        ee->ee_cck_ofdm_gain_delta = val & 0xff;
382                }
383                break;
384        }
385
386done:
387        /* return new offset */
388        *offset = o;
389
390        return 0;
391}
392
393/*
394 * Read turbo mode information on newer EEPROM versions
395 */
396static int
397ath5k_eeprom_read_turbo_modes(struct ath5k_hw *ah,
398                              u32 *offset, unsigned int mode)
399{
400        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
401        u32 o = *offset;
402        u16 val;
403        int ret;
404
405        if (ee->ee_version < AR5K_EEPROM_VERSION_5_0)
406                return 0;
407
408        switch (mode){
409        case AR5K_EEPROM_MODE_11A:
410                ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f;
411
412                ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7;
413                AR5K_EEPROM_READ(o++, val);
414                ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3;
415                ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f;
416
417                ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f;
418                AR5K_EEPROM_READ(o++, val);
419                ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7;
420                ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff;
421
422                if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2)
423                        ee->ee_pd_gain_overlap = (val >> 9) & 0xf;
424                break;
425        case AR5K_EEPROM_MODE_11G:
426                ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f;
427
428                ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7;
429                AR5K_EEPROM_READ(o++, val);
430                ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1;
431                ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f;
432
433                ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f;
434                AR5K_EEPROM_READ(o++, val);
435                ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5;
436                ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff;
437                break;
438        }
439
440        /* return new offset */
441        *offset = o;
442
443        return 0;
444}
445
446/* Read mode-specific data (except power calibration data) */
447static int
448ath5k_eeprom_init_modes(struct ath5k_hw *ah)
449{
450        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
451        u32 mode_offset[3];
452        unsigned int mode;
453        u32 offset;
454        int ret;
455
456        /*
457         * Get values for all modes
458         */
459        mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version);
460        mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version);
461        mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version);
462
463        ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] =
464                AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header);
465
466        for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) {
467                offset = mode_offset[mode];
468
469                ret = ath5k_eeprom_read_ants(ah, &offset, mode);
470                if (ret)
471                        return ret;
472
473                ret = ath5k_eeprom_read_modes(ah, &offset, mode);
474                if (ret)
475                        return ret;
476
477                ret = ath5k_eeprom_read_turbo_modes(ah, &offset, mode);
478                if (ret)
479                        return ret;
480        }
481
482        /* override for older eeprom versions for better performance */
483        if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) {
484                ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15;
485                ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28;
486                ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28;
487        }
488
489        return 0;
490}
491
492/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff
493 * frequency mask) */
494static inline int
495ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max,
496                        struct ath5k_chan_pcal_info *pc, unsigned int mode)
497{
498        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
499        int o = *offset;
500        int i = 0;
501        u8 freq1, freq2;
502        int ret;
503        u16 val;
504
505        ee->ee_n_piers[mode] = 0;
506        while(i < max) {
507                AR5K_EEPROM_READ(o++, val);
508
509                freq1 = val & 0xff;
510                if (!freq1)
511                        break;
512
513                pc[i++].freq = ath5k_eeprom_bin2freq(ee,
514                                freq1, mode);
515                ee->ee_n_piers[mode]++;
516
517                freq2 = (val >> 8) & 0xff;
518                if (!freq2)
519                        break;
520
521                pc[i++].freq = ath5k_eeprom_bin2freq(ee,
522                                freq2, mode);
523                ee->ee_n_piers[mode]++;
524        }
525
526        /* return new offset */
527        *offset = o;
528
529        return 0;
530}
531
532/* Read frequency piers for 802.11a */
533static int
534ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset)
535{
536        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
537        struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
538        int i, ret;
539        u16 val;
540        u8 mask;
541
542        if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
543                ath5k_eeprom_read_freq_list(ah, &offset,
544                        AR5K_EEPROM_N_5GHZ_CHAN, pcal,
545                        AR5K_EEPROM_MODE_11A);
546        } else {
547                mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version);
548
549                AR5K_EEPROM_READ(offset++, val);
550                pcal[0].freq  = (val >> 9) & mask;
551                pcal[1].freq  = (val >> 2) & mask;
552                pcal[2].freq  = (val << 5) & mask;
553
554                AR5K_EEPROM_READ(offset++, val);
555                pcal[2].freq |= (val >> 11) & 0x1f;
556                pcal[3].freq  = (val >> 4) & mask;
557                pcal[4].freq  = (val << 3) & mask;
558
559                AR5K_EEPROM_READ(offset++, val);
560                pcal[4].freq |= (val >> 13) & 0x7;
561                pcal[5].freq  = (val >> 6) & mask;
562                pcal[6].freq  = (val << 1) & mask;
563
564                AR5K_EEPROM_READ(offset++, val);
565                pcal[6].freq |= (val >> 15) & 0x1;
566                pcal[7].freq  = (val >> 8) & mask;
567                pcal[8].freq  = (val >> 1) & mask;
568                pcal[9].freq  = (val << 6) & mask;
569
570                AR5K_EEPROM_READ(offset++, val);
571                pcal[9].freq |= (val >> 10) & 0x3f;
572
573                /* Fixed number of piers */
574                ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10;
575
576                for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) {
577                        pcal[i].freq = ath5k_eeprom_bin2freq(ee,
578                                pcal[i].freq, AR5K_EEPROM_MODE_11A);
579                }
580        }
581
582        return 0;
583}
584
585/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */
586static inline int
587ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset)
588{
589        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
590        struct ath5k_chan_pcal_info *pcal;
591
592        switch(mode) {
593        case AR5K_EEPROM_MODE_11B:
594                pcal = ee->ee_pwr_cal_b;
595                break;
596        case AR5K_EEPROM_MODE_11G:
597                pcal = ee->ee_pwr_cal_g;
598                break;
599        default:
600                return -EINVAL;
601        }
602
603        ath5k_eeprom_read_freq_list(ah, &offset,
604                AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal,
605                mode);
606
607        return 0;
608}
609
610/*
611 * Read power calibration for RF5111 chips
612 *
613 * For RF5111 we have an XPD -eXternal Power Detector- curve
614 * for each calibrated channel. Each curve has 0,5dB Power steps
615 * on x axis and PCDAC steps (offsets) on y axis and looks like an
616 * exponential function. To recreate the curve we read 11 points
617 * here and interpolate later.
618 */
619
620/* Used to match PCDAC steps with power values on RF5111 chips
621 * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC
622 * steps that match with the power values we read from eeprom. On
623 * older eeprom versions (< 3.2) these steps are equaly spaced at
624 * 10% of the pcdac curve -until the curve reaches it's maximum-
625 * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2)
626 * these 11 steps are spaced in a different way. This function returns
627 * the pcdac steps based on eeprom version and curve min/max so that we
628 * can have pcdac/pwr points.
629 */
630static inline void
631ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp)
632{
633        static const u16 intercepts3[] =
634                { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 };
635        static const u16 intercepts3_2[] =
636                { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };
637        const u16 *ip;
638        unsigned i;
639
640        if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2)
641                ip = intercepts3_2;
642        else
643                ip = intercepts3;
644
645        for (i = 0; i < ARRAY_SIZE(intercepts3); i++)
646                vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100;
647}
648
649/* Convert RF5111 specific data to generic raw data
650 * used by interpolation code */
651static int
652ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode,
653                                struct ath5k_chan_pcal_info *chinfo)
654{
655        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
656        struct ath5k_chan_pcal_info_rf5111 *pcinfo;
657        struct ath5k_pdgain_info *pd;
658        u8 pier, point, idx;
659        u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
660
661        /* Fill raw data for each calibration pier */
662        for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
663
664                pcinfo = &chinfo[pier].rf5111_info;
665
666                /* Allocate pd_curves for this cal pier */
667                chinfo[pier].pd_curves =
668                        calloc(AR5K_EEPROM_N_PD_CURVES,
669                               sizeof(struct ath5k_pdgain_info));
670
671                if (!chinfo[pier].pd_curves)
672                        return -ENOMEM;
673
674                /* Only one curve for RF5111
675                 * find out which one and place
676                 * in in pd_curves.
677                 * Note: ee_x_gain is reversed here */
678                for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) {
679
680                        if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) {
681                                pdgain_idx[0] = idx;
682                                break;
683                        }
684                }
685
686                ee->ee_pd_gains[mode] = 1;
687
688                pd = &chinfo[pier].pd_curves[idx];
689
690                pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111;
691
692                /* Allocate pd points for this curve */
693                pd->pd_step = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(u8));
694                if (!pd->pd_step)
695                        return -ENOMEM;
696
697                pd->pd_pwr = calloc(AR5K_EEPROM_N_PWR_POINTS_5111, sizeof(s16));
698                if (!pd->pd_pwr)
699                        return -ENOMEM;
700
701                /* Fill raw dataset
702                 * (convert power to 0.25dB units
703                 * for RF5112 combatibility) */
704                for (point = 0; point < pd->pd_points; point++) {
705
706                        /* Absolute values */
707                        pd->pd_pwr[point] = 2 * pcinfo->pwr[point];
708
709                        /* Already sorted */
710                        pd->pd_step[point] = pcinfo->pcdac[point];
711                }
712
713                /* Set min/max pwr */
714                chinfo[pier].min_pwr = pd->pd_pwr[0];
715                chinfo[pier].max_pwr = pd->pd_pwr[10];
716
717        }
718
719        return 0;
720}
721
722/* Parse EEPROM data */
723static int
724ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode)
725{
726        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
727        struct ath5k_chan_pcal_info *pcal;
728        int offset, ret;
729        int i;
730        u16 val;
731
732        offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
733        switch(mode) {
734        case AR5K_EEPROM_MODE_11A:
735                if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
736                        return 0;
737
738                ret = ath5k_eeprom_init_11a_pcal_freq(ah,
739                        offset + AR5K_EEPROM_GROUP1_OFFSET);
740                if (ret < 0)
741                        return ret;
742
743                offset += AR5K_EEPROM_GROUP2_OFFSET;
744                pcal = ee->ee_pwr_cal_a;
745                break;
746        case AR5K_EEPROM_MODE_11B:
747                if (!AR5K_EEPROM_HDR_11B(ee->ee_header) &&
748                    !AR5K_EEPROM_HDR_11G(ee->ee_header))
749                        return 0;
750
751                pcal = ee->ee_pwr_cal_b;
752                offset += AR5K_EEPROM_GROUP3_OFFSET;
753
754                /* fixed piers */
755                pcal[0].freq = 2412;
756                pcal[1].freq = 2447;
757                pcal[2].freq = 2484;
758                ee->ee_n_piers[mode] = 3;
759                break;
760        case AR5K_EEPROM_MODE_11G:
761                if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
762                        return 0;
763
764                pcal = ee->ee_pwr_cal_g;
765                offset += AR5K_EEPROM_GROUP4_OFFSET;
766
767                /* fixed piers */
768                pcal[0].freq = 2312;
769                pcal[1].freq = 2412;
770                pcal[2].freq = 2484;
771                ee->ee_n_piers[mode] = 3;
772                break;
773        default:
774                return -EINVAL;
775        }
776
777        for (i = 0; i < ee->ee_n_piers[mode]; i++) {
778                struct ath5k_chan_pcal_info_rf5111 *cdata =
779                        &pcal[i].rf5111_info;
780
781                AR5K_EEPROM_READ(offset++, val);
782                cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M);
783                cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M);
784                cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M);
785
786                AR5K_EEPROM_READ(offset++, val);
787                cdata->pwr[0] |= ((val >> 14) & 0x3);
788                cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M);
789                cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M);
790                cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M);
791
792                AR5K_EEPROM_READ(offset++, val);
793                cdata->pwr[3] |= ((val >> 12) & 0xf);
794                cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M);
795                cdata->pwr[5] = (val  & AR5K_EEPROM_POWER_M);
796
797                AR5K_EEPROM_READ(offset++, val);
798                cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M);
799                cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M);
800                cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M);
801
802                AR5K_EEPROM_READ(offset++, val);
803                cdata->pwr[8] |= ((val >> 14) & 0x3);
804                cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M);
805                cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M);
806
807                ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min,
808                        cdata->pcdac_max, cdata->pcdac);
809        }
810
811        return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal);
812}
813
814
815/*
816 * Read power calibration for RF5112 chips
817 *
818 * For RF5112 we have 4 XPD -eXternal Power Detector- curves
819 * for each calibrated channel on 0, -6, -12 and -18dbm but we only
820 * use the higher (3) and the lower (0) curves. Each curve has 0.5dB
821 * power steps on x axis and PCDAC steps on y axis and looks like a
822 * linear function. To recreate the curve and pass the power values
823 * on hw, we read 4 points for xpd 0 (lower gain -> max power)
824 * and 3 points for xpd 3 (higher gain -> lower power) here and
825 * interpolate later.
826 *
827 * Note: Many vendors just use xpd 0 so xpd 3 is zeroed.
828 */
829
830/* Convert RF5112 specific data to generic raw data
831 * used by interpolation code */
832static int
833ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode,
834                                struct ath5k_chan_pcal_info *chinfo)
835{
836        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
837        struct ath5k_chan_pcal_info_rf5112 *pcinfo;
838        u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
839        unsigned int pier, pdg, point;
840
841        /* Fill raw data for each calibration pier */
842        for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
843
844                pcinfo = &chinfo[pier].rf5112_info;
845
846                /* Allocate pd_curves for this cal pier */
847                chinfo[pier].pd_curves =
848                                calloc(AR5K_EEPROM_N_PD_CURVES,
849                                       sizeof(struct ath5k_pdgain_info));
850
851                if (!chinfo[pier].pd_curves)
852                        return -ENOMEM;
853
854                /* Fill pd_curves */
855                for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
856
857                        u8 idx = pdgain_idx[pdg];
858                        struct ath5k_pdgain_info *pd =
859                                        &chinfo[pier].pd_curves[idx];
860
861                        /* Lowest gain curve (max power) */
862                        if (pdg == 0) {
863                                /* One more point for better accuracy */
864                                pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS;
865
866                                /* Allocate pd points for this curve */
867                                pd->pd_step = calloc(pd->pd_points, sizeof(u8));
868
869                                if (!pd->pd_step)
870                                        return -ENOMEM;
871
872                                pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
873
874                                if (!pd->pd_pwr)
875                                        return -ENOMEM;
876
877
878                                /* Fill raw dataset
879                                 * (all power levels are in 0.25dB units) */
880                                pd->pd_step[0] = pcinfo->pcdac_x0[0];
881                                pd->pd_pwr[0] = pcinfo->pwr_x0[0];
882
883                                for (point = 1; point < pd->pd_points;
884                                point++) {
885                                        /* Absolute values */
886                                        pd->pd_pwr[point] =
887                                                pcinfo->pwr_x0[point];
888
889                                        /* Deltas */
890                                        pd->pd_step[point] =
891                                                pd->pd_step[point - 1] +
892                                                pcinfo->pcdac_x0[point];
893                                }
894
895                                /* Set min power for this frequency */
896                                chinfo[pier].min_pwr = pd->pd_pwr[0];
897
898                        /* Highest gain curve (min power) */
899                        } else if (pdg == 1) {
900
901                                pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS;
902
903                                /* Allocate pd points for this curve */
904                                pd->pd_step = calloc(pd->pd_points, sizeof(u8));
905
906                                if (!pd->pd_step)
907                                        return -ENOMEM;
908
909                                pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
910
911                                if (!pd->pd_pwr)
912                                        return -ENOMEM;
913
914                                /* Fill raw dataset
915                                 * (all power levels are in 0.25dB units) */
916                                for (point = 0; point < pd->pd_points;
917                                point++) {
918                                        /* Absolute values */
919                                        pd->pd_pwr[point] =
920                                                pcinfo->pwr_x3[point];
921
922                                        /* Fixed points */
923                                        pd->pd_step[point] =
924                                                pcinfo->pcdac_x3[point];
925                                }
926
927                                /* Since we have a higher gain curve
928                                 * override min power */
929                                chinfo[pier].min_pwr = pd->pd_pwr[0];
930                        }
931                }
932        }
933
934        return 0;
935}
936
937/* Parse EEPROM data */
938static int
939ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode)
940{
941        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
942        struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info;
943        struct ath5k_chan_pcal_info *gen_chan_info;
944        u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
945        u32 offset;
946        u8 i, c;
947        u16 val;
948        int ret;
949        u8 pd_gains = 0;
950
951        /* Count how many curves we have and
952         * identify them (which one of the 4
953         * available curves we have on each count).
954         * Curves are stored from lower (x0) to
955         * higher (x3) gain */
956        for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) {
957                /* ee_x_gain[mode] is x gain mask */
958                if ((ee->ee_x_gain[mode] >> i) & 0x1)
959                        pdgain_idx[pd_gains++] = i;
960        }
961        ee->ee_pd_gains[mode] = pd_gains;
962
963        if (pd_gains == 0 || pd_gains > 2)
964                return -EINVAL;
965
966        switch (mode) {
967        case AR5K_EEPROM_MODE_11A:
968                /*
969                 * Read 5GHz EEPROM channels
970                 */
971                offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
972                ath5k_eeprom_init_11a_pcal_freq(ah, offset);
973
974                offset += AR5K_EEPROM_GROUP2_OFFSET;
975                gen_chan_info = ee->ee_pwr_cal_a;
976                break;
977        case AR5K_EEPROM_MODE_11B:
978                offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
979                if (AR5K_EEPROM_HDR_11A(ee->ee_header))
980                        offset += AR5K_EEPROM_GROUP3_OFFSET;
981
982                /* NB: frequency piers parsed during mode init */
983                gen_chan_info = ee->ee_pwr_cal_b;
984                break;
985        case AR5K_EEPROM_MODE_11G:
986                offset = AR5K_EEPROM_GROUPS_START(ee->ee_version);
987                if (AR5K_EEPROM_HDR_11A(ee->ee_header))
988                        offset += AR5K_EEPROM_GROUP4_OFFSET;
989                else if (AR5K_EEPROM_HDR_11B(ee->ee_header))
990                        offset += AR5K_EEPROM_GROUP2_OFFSET;
991
992                /* NB: frequency piers parsed during mode init */
993                gen_chan_info = ee->ee_pwr_cal_g;
994                break;
995        default:
996                return -EINVAL;
997        }
998
999        for (i = 0; i < ee->ee_n_piers[mode]; i++) {
1000                chan_pcal_info = &gen_chan_info[i].rf5112_info;
1001
1002                /* Power values in quarter dB
1003                 * for the lower xpd gain curve
1004                 * (0 dBm -> higher output power) */
1005                for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) {
1006                        AR5K_EEPROM_READ(offset++, val);
1007                        chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff);
1008                        chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff);
1009                }
1010
1011                /* PCDAC steps
1012                 * corresponding to the above power
1013                 * measurements */
1014                AR5K_EEPROM_READ(offset++, val);
1015                chan_pcal_info->pcdac_x0[1] = (val & 0x1f);
1016                chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f);
1017                chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f);
1018
1019                /* Power values in quarter dB
1020                 * for the higher xpd gain curve
1021                 * (18 dBm -> lower output power) */
1022                AR5K_EEPROM_READ(offset++, val);
1023                chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff);
1024                chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff);
1025
1026                AR5K_EEPROM_READ(offset++, val);
1027                chan_pcal_info->pwr_x3[2] = (val & 0xff);
1028
1029                /* PCDAC steps
1030                 * corresponding to the above power
1031                 * measurements (fixed) */
1032                chan_pcal_info->pcdac_x3[0] = 20;
1033                chan_pcal_info->pcdac_x3[1] = 35;
1034                chan_pcal_info->pcdac_x3[2] = 63;
1035
1036                if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) {
1037                        chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f);
1038
1039                        /* Last xpd0 power level is also channel maximum */
1040                        gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3];
1041                } else {
1042                        chan_pcal_info->pcdac_x0[0] = 1;
1043                        gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff);
1044                }
1045
1046        }
1047
1048        return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info);
1049}
1050
1051
1052/*
1053 * Read power calibration for RF2413 chips
1054 *
1055 * For RF2413 we have a Power to PDDAC table (Power Detector)
1056 * instead of a PCDAC and 4 pd gain curves for each calibrated channel.
1057 * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y
1058 * axis and looks like an exponential function like the RF5111 curve.
1059 *
1060 * To recreate the curves we read here the points and interpolate
1061 * later. Note that in most cases only 2 (higher and lower) curves are
1062 * used (like RF5112) but vendors have the oportunity to include all
1063 * 4 curves on eeprom. The final curve (higher power) has an extra
1064 * point for better accuracy like RF5112.
1065 */
1066
1067/* For RF2413 power calibration data doesn't start on a fixed location and
1068 * if a mode is not supported, it's section is missing -not zeroed-.
1069 * So we need to calculate the starting offset for each section by using
1070 * these two functions */
1071
1072/* Return the size of each section based on the mode and the number of pd
1073 * gains available (maximum 4). */
1074static inline unsigned int
1075ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode)
1076{
1077        static const unsigned int pdgains_size[] = { 4, 6, 9, 12 };
1078        unsigned int sz;
1079
1080        sz = pdgains_size[ee->ee_pd_gains[mode] - 1];
1081        sz *= ee->ee_n_piers[mode];
1082
1083        return sz;
1084}
1085
1086/* Return the starting offset for a section based on the modes supported
1087 * and each section's size. */
1088static unsigned int
1089ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode)
1090{
1091        u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4);
1092
1093        switch(mode) {
1094        case AR5K_EEPROM_MODE_11G:
1095                if (AR5K_EEPROM_HDR_11B(ee->ee_header))
1096                        offset += ath5k_pdgains_size_2413(ee,
1097                                        AR5K_EEPROM_MODE_11B) +
1098                                        AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1099                /* fall through */
1100        case AR5K_EEPROM_MODE_11B:
1101                if (AR5K_EEPROM_HDR_11A(ee->ee_header))
1102                        offset += ath5k_pdgains_size_2413(ee,
1103                                        AR5K_EEPROM_MODE_11A) +
1104                                        AR5K_EEPROM_N_5GHZ_CHAN / 2;
1105                /* fall through */
1106        case AR5K_EEPROM_MODE_11A:
1107                break;
1108        default:
1109                break;
1110        }
1111
1112        return offset;
1113}
1114
1115/* Convert RF2413 specific data to generic raw data
1116 * used by interpolation code */
1117static int
1118ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode,
1119                                struct ath5k_chan_pcal_info *chinfo)
1120{
1121        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1122        struct ath5k_chan_pcal_info_rf2413 *pcinfo;
1123        u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
1124        unsigned int pier, point;
1125        int pdg;
1126
1127        /* Fill raw data for each calibration pier */
1128        for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1129
1130                pcinfo = &chinfo[pier].rf2413_info;
1131
1132                /* Allocate pd_curves for this cal pier */
1133                chinfo[pier].pd_curves =
1134                                calloc(AR5K_EEPROM_N_PD_CURVES,
1135                                       sizeof(struct ath5k_pdgain_info));
1136
1137                if (!chinfo[pier].pd_curves)
1138                        return -ENOMEM;
1139
1140                /* Fill pd_curves */
1141                for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1142
1143                        u8 idx = pdgain_idx[pdg];
1144                        struct ath5k_pdgain_info *pd =
1145                                        &chinfo[pier].pd_curves[idx];
1146
1147                        /* One more point for the highest power
1148                         * curve (lowest gain) */
1149                        if (pdg == ee->ee_pd_gains[mode] - 1)
1150                                pd->pd_points = AR5K_EEPROM_N_PD_POINTS;
1151                        else
1152                                pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1;
1153
1154                        /* Allocate pd points for this curve */
1155                        pd->pd_step = calloc(pd->pd_points, sizeof(u8));
1156
1157                        if (!pd->pd_step)
1158                                return -ENOMEM;
1159
1160                        pd->pd_pwr = calloc(pd->pd_points, sizeof(s16));
1161
1162                        if (!pd->pd_pwr)
1163                                return -ENOMEM;
1164
1165                        /* Fill raw dataset
1166                         * convert all pwr levels to
1167                         * quarter dB for RF5112 combatibility */
1168                        pd->pd_step[0] = pcinfo->pddac_i[pdg];
1169                        pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg];
1170
1171                        for (point = 1; point < pd->pd_points; point++) {
1172
1173                                pd->pd_pwr[point] = pd->pd_pwr[point - 1] +
1174                                        2 * pcinfo->pwr[pdg][point - 1];
1175
1176                                pd->pd_step[point] = pd->pd_step[point - 1] +
1177                                                pcinfo->pddac[pdg][point - 1];
1178
1179                        }
1180
1181                        /* Highest gain curve -> min power */
1182                        if (pdg == 0)
1183                                chinfo[pier].min_pwr = pd->pd_pwr[0];
1184
1185                        /* Lowest gain curve -> max power */
1186                        if (pdg == ee->ee_pd_gains[mode] - 1)
1187                                chinfo[pier].max_pwr =
1188                                        pd->pd_pwr[pd->pd_points - 1];
1189                }
1190        }
1191
1192        return 0;
1193}
1194
1195/* Parse EEPROM data */
1196static int
1197ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode)
1198{
1199        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1200        struct ath5k_chan_pcal_info_rf2413 *pcinfo;
1201        struct ath5k_chan_pcal_info *chinfo;
1202        u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
1203        u32 offset;
1204        int idx, i, ret;
1205        u16 val;
1206        u8 pd_gains = 0;
1207
1208        /* Count how many curves we have and
1209         * identify them (which one of the 4
1210         * available curves we have on each count).
1211         * Curves are stored from higher to
1212         * lower gain so we go backwards */
1213        for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) {
1214                /* ee_x_gain[mode] is x gain mask */
1215                if ((ee->ee_x_gain[mode] >> idx) & 0x1)
1216                        pdgain_idx[pd_gains++] = idx;
1217
1218        }
1219        ee->ee_pd_gains[mode] = pd_gains;
1220
1221        if (pd_gains == 0)
1222                return -EINVAL;
1223
1224        offset = ath5k_cal_data_offset_2413(ee, mode);
1225        switch (mode) {
1226        case AR5K_EEPROM_MODE_11A:
1227                if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1228                        return 0;
1229
1230                ath5k_eeprom_init_11a_pcal_freq(ah, offset);
1231                offset += AR5K_EEPROM_N_5GHZ_CHAN / 2;
1232                chinfo = ee->ee_pwr_cal_a;
1233                break;
1234        case AR5K_EEPROM_MODE_11B:
1235                if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1236                        return 0;
1237
1238                ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1239                offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1240                chinfo = ee->ee_pwr_cal_b;
1241                break;
1242        case AR5K_EEPROM_MODE_11G:
1243                if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1244                        return 0;
1245
1246                ath5k_eeprom_init_11bg_2413(ah, mode, offset);
1247                offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2;
1248                chinfo = ee->ee_pwr_cal_g;
1249                break;
1250        default:
1251                return -EINVAL;
1252        }
1253
1254        for (i = 0; i < ee->ee_n_piers[mode]; i++) {
1255                pcinfo = &chinfo[i].rf2413_info;
1256
1257                /*
1258                 * Read pwr_i, pddac_i and the first
1259                 * 2 pd points (pwr, pddac)
1260                 */
1261                AR5K_EEPROM_READ(offset++, val);
1262                pcinfo->pwr_i[0] = val & 0x1f;
1263                pcinfo->pddac_i[0] = (val >> 5) & 0x7f;
1264                pcinfo->pwr[0][0] = (val >> 12) & 0xf;
1265
1266                AR5K_EEPROM_READ(offset++, val);
1267                pcinfo->pddac[0][0] = val & 0x3f;
1268                pcinfo->pwr[0][1] = (val >> 6) & 0xf;
1269                pcinfo->pddac[0][1] = (val >> 10) & 0x3f;
1270
1271                AR5K_EEPROM_READ(offset++, val);
1272                pcinfo->pwr[0][2] = val & 0xf;
1273                pcinfo->pddac[0][2] = (val >> 4) & 0x3f;
1274
1275                pcinfo->pwr[0][3] = 0;
1276                pcinfo->pddac[0][3] = 0;
1277
1278                if (pd_gains > 1) {
1279                        /*
1280                         * Pd gain 0 is not the last pd gain
1281                         * so it only has 2 pd points.
1282                         * Continue wih pd gain 1.
1283                         */
1284                        pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
1285
1286                        pcinfo->pddac_i[1] = (val >> 15) & 0x1;
1287                        AR5K_EEPROM_READ(offset++, val);
1288                        pcinfo->pddac_i[1] |= (val & 0x3F) << 1;
1289
1290                        pcinfo->pwr[1][0] = (val >> 6) & 0xf;
1291                        pcinfo->pddac[1][0] = (val >> 10) & 0x3f;
1292
1293                        AR5K_EEPROM_READ(offset++, val);
1294                        pcinfo->pwr[1][1] = val & 0xf;
1295                        pcinfo->pddac[1][1] = (val >> 4) & 0x3f;
1296                        pcinfo->pwr[1][2] = (val >> 10) & 0xf;
1297
1298                        pcinfo->pddac[1][2] = (val >> 14) & 0x3;
1299                        AR5K_EEPROM_READ(offset++, val);
1300                        pcinfo->pddac[1][2] |= (val & 0xF) << 2;
1301
1302                        pcinfo->pwr[1][3] = 0;
1303                        pcinfo->pddac[1][3] = 0;
1304                } else if (pd_gains == 1) {
1305                        /*
1306                         * Pd gain 0 is the last one so
1307                         * read the extra point.
1308                         */
1309                        pcinfo->pwr[0][3] = (val >> 10) & 0xf;
1310
1311                        pcinfo->pddac[0][3] = (val >> 14) & 0x3;
1312                        AR5K_EEPROM_READ(offset++, val);
1313                        pcinfo->pddac[0][3] |= (val & 0xF) << 2;
1314                }
1315
1316                /*
1317                 * Proceed with the other pd_gains
1318                 * as above.
1319                 */
1320                if (pd_gains > 2) {
1321                        pcinfo->pwr_i[2] = (val >> 4) & 0x1f;
1322                        pcinfo->pddac_i[2] = (val >> 9) & 0x7f;
1323
1324                        AR5K_EEPROM_READ(offset++, val);
1325                        pcinfo->pwr[2][0] = (val >> 0) & 0xf;
1326                        pcinfo->pddac[2][0] = (val >> 4) & 0x3f;
1327                        pcinfo->pwr[2][1] = (val >> 10) & 0xf;
1328
1329                        pcinfo->pddac[2][1] = (val >> 14) & 0x3;
1330                        AR5K_EEPROM_READ(offset++, val);
1331                        pcinfo->pddac[2][1] |= (val & 0xF) << 2;
1332
1333                        pcinfo->pwr[2][2] = (val >> 4) & 0xf;
1334                        pcinfo->pddac[2][2] = (val >> 8) & 0x3f;
1335
1336                        pcinfo->pwr[2][3] = 0;
1337                        pcinfo->pddac[2][3] = 0;
1338                } else if (pd_gains == 2) {
1339                        pcinfo->pwr[1][3] = (val >> 4) & 0xf;
1340                        pcinfo->pddac[1][3] = (val >> 8) & 0x3f;
1341                }
1342
1343                if (pd_gains > 3) {
1344                        pcinfo->pwr_i[3] = (val >> 14) & 0x3;
1345                        AR5K_EEPROM_READ(offset++, val);
1346                        pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2;
1347
1348                        pcinfo->pddac_i[3] = (val >> 3) & 0x7f;
1349                        pcinfo->pwr[3][0] = (val >> 10) & 0xf;
1350                        pcinfo->pddac[3][0] = (val >> 14) & 0x3;
1351
1352                        AR5K_EEPROM_READ(offset++, val);
1353                        pcinfo->pddac[3][0] |= (val & 0xF) << 2;
1354                        pcinfo->pwr[3][1] = (val >> 4) & 0xf;
1355                        pcinfo->pddac[3][1] = (val >> 8) & 0x3f;
1356
1357                        pcinfo->pwr[3][2] = (val >> 14) & 0x3;
1358                        AR5K_EEPROM_READ(offset++, val);
1359                        pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2;
1360
1361                        pcinfo->pddac[3][2] = (val >> 2) & 0x3f;
1362                        pcinfo->pwr[3][3] = (val >> 8) & 0xf;
1363
1364                        pcinfo->pddac[3][3] = (val >> 12) & 0xF;
1365                        AR5K_EEPROM_READ(offset++, val);
1366                        pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4;
1367                } else if (pd_gains == 3) {
1368                        pcinfo->pwr[2][3] = (val >> 14) & 0x3;
1369                        AR5K_EEPROM_READ(offset++, val);
1370                        pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2;
1371
1372                        pcinfo->pddac[2][3] = (val >> 2) & 0x3f;
1373                }
1374        }
1375
1376        return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo);
1377}
1378
1379
1380/*
1381 * Read per rate target power (this is the maximum tx power
1382 * supported by the card). This info is used when setting
1383 * tx power, no matter the channel.
1384 *
1385 * This also works for v5 EEPROMs.
1386 */
1387static int
1388ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
1389{
1390        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1391        struct ath5k_rate_pcal_info *rate_pcal_info;
1392        u8 *rate_target_pwr_num;
1393        u32 offset;
1394        u16 val;
1395        int ret, i;
1396
1397        offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
1398        rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
1399        switch (mode) {
1400        case AR5K_EEPROM_MODE_11A:
1401                offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
1402                rate_pcal_info = ee->ee_rate_tpwr_a;
1403                ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
1404                break;
1405        case AR5K_EEPROM_MODE_11B:
1406                offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
1407                rate_pcal_info = ee->ee_rate_tpwr_b;
1408                ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */
1409                break;
1410        case AR5K_EEPROM_MODE_11G:
1411                offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version);
1412                rate_pcal_info = ee->ee_rate_tpwr_g;
1413                ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN;
1414                break;
1415        default:
1416                return -EINVAL;
1417        }
1418
1419        /* Different freq mask for older eeproms (<= v3.2) */
1420        if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) {
1421                for (i = 0; i < (*rate_target_pwr_num); i++) {
1422                        AR5K_EEPROM_READ(offset++, val);
1423                        rate_pcal_info[i].freq =
1424                            ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode);
1425
1426                        rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f);
1427                        rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f;
1428
1429                        AR5K_EEPROM_READ(offset++, val);
1430
1431                        if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
1432                            val == 0) {
1433                                (*rate_target_pwr_num) = i;
1434                                break;
1435                        }
1436
1437                        rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7);
1438                        rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f);
1439                        rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f);
1440                }
1441        } else {
1442                for (i = 0; i < (*rate_target_pwr_num); i++) {
1443                        AR5K_EEPROM_READ(offset++, val);
1444                        rate_pcal_info[i].freq =
1445                            ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode);
1446
1447                        rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f);
1448                        rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f;
1449
1450                        AR5K_EEPROM_READ(offset++, val);
1451
1452                        if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS ||
1453                            val == 0) {
1454                                (*rate_target_pwr_num) = i;
1455                                break;
1456                        }
1457
1458                        rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf;
1459                        rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f);
1460                        rate_pcal_info[i].target_power_54 = (val & 0x3f);
1461                }
1462        }
1463
1464        return 0;
1465}
1466
1467/*
1468 * Read per channel calibration info from EEPROM
1469 *
1470 * This info is used to calibrate the baseband power table. Imagine
1471 * that for each channel there is a power curve that's hw specific
1472 * (depends on amplifier etc) and we try to "correct" this curve using
1473 * offests we pass on to phy chip (baseband -> before amplifier) so that
1474 * it can use accurate power values when setting tx power (takes amplifier's
1475 * performance on each channel into account).
1476 *
1477 * EEPROM provides us with the offsets for some pre-calibrated channels
1478 * and we have to interpolate to create the full table for these channels and
1479 * also the table for any channel.
1480 */
1481static int
1482ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah)
1483{
1484        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1485        int (*read_pcal)(struct ath5k_hw *hw, int mode);
1486        int mode;
1487        int err;
1488
1489        if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) &&
1490                        (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1))
1491                read_pcal = ath5k_eeprom_read_pcal_info_5112;
1492        else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) &&
1493                        (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2))
1494                read_pcal = ath5k_eeprom_read_pcal_info_2413;
1495        else
1496                read_pcal = ath5k_eeprom_read_pcal_info_5111;
1497
1498
1499        for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G;
1500        mode++) {
1501                err = read_pcal(ah, mode);
1502                if (err)
1503                        return err;
1504
1505                err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode);
1506                if (err < 0)
1507                        return err;
1508        }
1509
1510        return 0;
1511}
1512
1513static int
1514ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode)
1515{
1516        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1517        struct ath5k_chan_pcal_info *chinfo;
1518        u8 pier, pdg;
1519
1520        switch (mode) {
1521        case AR5K_EEPROM_MODE_11A:
1522                if (!AR5K_EEPROM_HDR_11A(ee->ee_header))
1523                        return 0;
1524                chinfo = ee->ee_pwr_cal_a;
1525                break;
1526        case AR5K_EEPROM_MODE_11B:
1527                if (!AR5K_EEPROM_HDR_11B(ee->ee_header))
1528                        return 0;
1529                chinfo = ee->ee_pwr_cal_b;
1530                break;
1531        case AR5K_EEPROM_MODE_11G:
1532                if (!AR5K_EEPROM_HDR_11G(ee->ee_header))
1533                        return 0;
1534                chinfo = ee->ee_pwr_cal_g;
1535                break;
1536        default:
1537                return -EINVAL;
1538        }
1539
1540        for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) {
1541                if (!chinfo[pier].pd_curves)
1542                        continue;
1543
1544                for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) {
1545                        struct ath5k_pdgain_info *pd =
1546                                        &chinfo[pier].pd_curves[pdg];
1547
1548                        if (pd != NULL) {
1549                                free(pd->pd_step);
1550                                free(pd->pd_pwr);
1551                        }
1552                }
1553
1554                free(chinfo[pier].pd_curves);
1555        }
1556
1557        return 0;
1558}
1559
1560void
1561ath5k_eeprom_detach(struct ath5k_hw *ah)
1562{
1563        u8 mode;
1564
1565        for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++)
1566                ath5k_eeprom_free_pcal_info(ah, mode);
1567}
1568
1569/* Read conformance test limits used for regulatory control */
1570static int
1571ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah)
1572{
1573        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
1574        struct ath5k_edge_power *rep;
1575        unsigned int fmask, pmask;
1576        unsigned int ctl_mode;
1577        int ret, i, j;
1578        u32 offset;
1579        u16 val;
1580
1581        pmask = AR5K_EEPROM_POWER_M;
1582        fmask = AR5K_EEPROM_FREQ_M(ee->ee_version);
1583        offset = AR5K_EEPROM_CTL(ee->ee_version);
1584        ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version);
1585        for (i = 0; i < ee->ee_ctls; i += 2) {
1586                AR5K_EEPROM_READ(offset++, val);
1587                ee->ee_ctl[i] = (val >> 8) & 0xff;
1588                ee->ee_ctl[i + 1] = val & 0xff;
1589        }
1590
1591        offset = AR5K_EEPROM_GROUP8_OFFSET;
1592        if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0)
1593                offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) -
1594                        AR5K_EEPROM_GROUP5_OFFSET;
1595        else
1596                offset += AR5K_EEPROM_GROUPS_START(ee->ee_version);
1597
1598        rep = ee->ee_ctl_pwr;
1599        for(i = 0; i < ee->ee_ctls; i++) {
1600                switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) {
1601                case AR5K_CTL_11A:
1602                case AR5K_CTL_TURBO:
1603                        ctl_mode = AR5K_EEPROM_MODE_11A;
1604                        break;
1605                default:
1606                        ctl_mode = AR5K_EEPROM_MODE_11G;
1607                        break;
1608                }
1609                if (ee->ee_ctl[i] == 0) {
1610                        if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3)
1611                                offset += 8;
1612                        else
1613                                offset += 7;
1614                        rep += AR5K_EEPROM_N_EDGES;
1615                        continue;
1616                }
1617                if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) {
1618                        for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
1619                                AR5K_EEPROM_READ(offset++, val);
1620                                rep[j].freq = (val >> 8) & fmask;
1621                                rep[j + 1].freq = val & fmask;
1622                        }
1623                        for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) {
1624                                AR5K_EEPROM_READ(offset++, val);
1625                                rep[j].edge = (val >> 8) & pmask;
1626                                rep[j].flag = (val >> 14) & 1;
1627                                rep[j + 1].edge = val & pmask;
1628                                rep[j + 1].flag = (val >> 6) & 1;
1629                        }
1630                } else {
1631                        AR5K_EEPROM_READ(offset++, val);
1632                        rep[0].freq = (val >> 9) & fmask;
1633                        rep[1].freq = (val >> 2) & fmask;
1634                        rep[2].freq = (val << 5) & fmask;
1635
1636                        AR5K_EEPROM_READ(offset++, val);
1637                        rep[2].freq |= (val >> 11) & 0x1f;
1638                        rep[3].freq = (val >> 4) & fmask;
1639                        rep[4].freq = (val << 3) & fmask;
1640
1641                        AR5K_EEPROM_READ(offset++, val);
1642                        rep[4].freq |= (val >> 13) & 0x7;
1643                        rep[5].freq = (val >> 6) & fmask;
1644                        rep[6].freq = (val << 1) & fmask;
1645
1646                        AR5K_EEPROM_READ(offset++, val);
1647                        rep[6].freq |= (val >> 15) & 0x1;
1648                        rep[7].freq = (val >> 8) & fmask;
1649
1650                        rep[0].edge = (val >> 2) & pmask;
1651                        rep[1].edge = (val << 4) & pmask;
1652
1653                        AR5K_EEPROM_READ(offset++, val);
1654                        rep[1].edge |= (val >> 12) & 0xf;
1655                        rep[2].edge = (val >> 6) & pmask;
1656                        rep[3].edge = val & pmask;
1657
1658                        AR5K_EEPROM_READ(offset++, val);
1659                        rep[4].edge = (val >> 10) & pmask;
1660                        rep[5].edge = (val >> 4) & pmask;
1661                        rep[6].edge = (val << 2) & pmask;
1662
1663                        AR5K_EEPROM_READ(offset++, val);
1664                        rep[6].edge |= (val >> 14) & 0x3;
1665                        rep[7].edge = (val >> 8) & pmask;
1666                }
1667                for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) {
1668                        rep[j].freq = ath5k_eeprom_bin2freq(ee,
1669                                rep[j].freq, ctl_mode);
1670                }
1671                rep += AR5K_EEPROM_N_EDGES;
1672        }
1673
1674        return 0;
1675}
1676
1677
1678/*
1679 * Initialize eeprom power tables
1680 */
1681int
1682ath5k_eeprom_init(struct ath5k_hw *ah)
1683{
1684        int err;
1685
1686        err = ath5k_eeprom_init_header(ah);
1687        if (err < 0)
1688                return err;
1689
1690        err = ath5k_eeprom_init_modes(ah);
1691        if (err < 0)
1692                return err;
1693
1694        err = ath5k_eeprom_read_pcal_info(ah);
1695        if (err < 0)
1696                return err;
1697
1698        err = ath5k_eeprom_read_ctl_info(ah);
1699        if (err < 0)
1700                return err;
1701
1702        return 0;
1703}
1704
1705/*
1706 * Read the MAC address from eeprom
1707 */
1708int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
1709{
1710        u8 mac_d[ETH_ALEN] = {};
1711        u32 total, offset;
1712        u16 data;
1713        int octet, ret;
1714
1715        ret = ath5k_hw_eeprom_read(ah, 0x20, &data);
1716        if (ret)
1717                return ret;
1718
1719        for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
1720                ret = ath5k_hw_eeprom_read(ah, offset, &data);
1721                if (ret)
1722                        return ret;
1723
1724                total += data;
1725                mac_d[octet + 1] = data & 0xff;
1726                mac_d[octet] = data >> 8;
1727                octet += 2;
1728        }
1729
1730        if (!total || total == 3 * 0xffff)
1731                return -EINVAL;
1732
1733        memcpy(mac, mac_d, ETH_ALEN);
1734
1735        return 0;
1736}
1737
1738int ath5k_eeprom_is_hb63(struct ath5k_hw *ah)
1739{
1740        u16 data;
1741
1742        ath5k_hw_eeprom_read(ah, AR5K_EEPROM_IS_HB63, &data);
1743
1744        if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && data)
1745                return 1;
1746        else
1747                return 0;
1748}
1749
Note: See TracBrowser for help on using the repository browser.