]>
git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/net/wireless/ath/ath9k/eeprom.c
2 * Copyright (c) 2008-2009 Atheros Communications Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 static inline u16
ath9k_hw_fbin2freq(u8 fbin
, bool is2GHz
)
21 if (fbin
== AR5416_BCHAN_UNUSED
)
24 return (u16
) ((is2GHz
) ? (2300 + fbin
) : (4800 + 5 * fbin
));
27 void ath9k_hw_analog_shift_rmw(struct ath_hw
*ah
, u32 reg
, u32 mask
,
32 regVal
= REG_READ(ah
, reg
) & ~mask
;
33 regVal
|= (val
<< shift
) & mask
;
35 REG_WRITE(ah
, reg
, regVal
);
37 if (ah
->config
.analog_shiftreg
)
43 int16_t ath9k_hw_interpolate(u16 target
, u16 srcLeft
, u16 srcRight
,
44 int16_t targetLeft
, int16_t targetRight
)
48 if (srcRight
== srcLeft
) {
51 rv
= (int16_t) (((target
- srcLeft
) * targetRight
+
52 (srcRight
- target
) * targetLeft
) /
53 (srcRight
- srcLeft
));
58 bool ath9k_hw_get_lower_upper_index(u8 target
, u8
*pList
, u16 listSize
,
59 u16
*indexL
, u16
*indexR
)
63 if (target
<= pList
[0]) {
64 *indexL
= *indexR
= 0;
67 if (target
>= pList
[listSize
- 1]) {
68 *indexL
= *indexR
= (u16
) (listSize
- 1);
72 for (i
= 0; i
< listSize
- 1; i
++) {
73 if (pList
[i
] == target
) {
74 *indexL
= *indexR
= i
;
77 if (target
< pList
[i
+ 1]) {
79 *indexR
= (u16
) (i
+ 1);
86 bool ath9k_hw_nvram_read(struct ath_common
*common
, u32 off
, u16
*data
)
88 return common
->bus_ops
->eeprom_read(common
, off
, data
);
91 void ath9k_hw_fill_vpd_table(u8 pwrMin
, u8 pwrMax
, u8
*pPwrList
,
92 u8
*pVpdList
, u16 numIntercepts
,
97 u16 idxL
= 0, idxR
= 0;
99 for (i
= 0; i
<= (pwrMax
- pwrMin
) / 2; i
++) {
100 ath9k_hw_get_lower_upper_index(currPwr
, pPwrList
,
101 numIntercepts
, &(idxL
),
105 if (idxL
== numIntercepts
- 1)
106 idxL
= (u16
) (numIntercepts
- 2);
107 if (pPwrList
[idxL
] == pPwrList
[idxR
])
110 k
= (u16
)(((currPwr
- pPwrList
[idxL
]) * pVpdList
[idxR
] +
111 (pPwrList
[idxR
] - currPwr
) * pVpdList
[idxL
]) /
112 (pPwrList
[idxR
] - pPwrList
[idxL
]));
113 pRetVpdList
[i
] = (u8
) k
;
118 void ath9k_hw_get_legacy_target_powers(struct ath_hw
*ah
,
119 struct ath9k_channel
*chan
,
120 struct cal_target_power_leg
*powInfo
,
122 struct cal_target_power_leg
*pNewPower
,
123 u16 numRates
, bool isExtTarget
)
125 struct chan_centers centers
;
128 int matchIndex
= -1, lowIndex
= -1;
131 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
132 freq
= (isExtTarget
) ? centers
.ext_center
: centers
.ctl_center
;
134 if (freq
<= ath9k_hw_fbin2freq(powInfo
[0].bChannel
,
135 IS_CHAN_2GHZ(chan
))) {
138 for (i
= 0; (i
< numChannels
) &&
139 (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
140 if (freq
== ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
141 IS_CHAN_2GHZ(chan
))) {
144 } else if (freq
< ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
145 IS_CHAN_2GHZ(chan
)) && i
> 0 &&
146 freq
> ath9k_hw_fbin2freq(powInfo
[i
- 1].bChannel
,
147 IS_CHAN_2GHZ(chan
))) {
152 if ((matchIndex
== -1) && (lowIndex
== -1))
156 if (matchIndex
!= -1) {
157 *pNewPower
= powInfo
[matchIndex
];
159 clo
= ath9k_hw_fbin2freq(powInfo
[lowIndex
].bChannel
,
161 chi
= ath9k_hw_fbin2freq(powInfo
[lowIndex
+ 1].bChannel
,
164 for (i
= 0; i
< numRates
; i
++) {
165 pNewPower
->tPow2x
[i
] =
166 (u8
)ath9k_hw_interpolate(freq
, clo
, chi
,
167 powInfo
[lowIndex
].tPow2x
[i
],
168 powInfo
[lowIndex
+ 1].tPow2x
[i
]);
173 void ath9k_hw_get_target_powers(struct ath_hw
*ah
,
174 struct ath9k_channel
*chan
,
175 struct cal_target_power_ht
*powInfo
,
177 struct cal_target_power_ht
*pNewPower
,
178 u16 numRates
, bool isHt40Target
)
180 struct chan_centers centers
;
183 int matchIndex
= -1, lowIndex
= -1;
186 ath9k_hw_get_channel_centers(ah
, chan
, ¢ers
);
187 freq
= isHt40Target
? centers
.synth_center
: centers
.ctl_center
;
189 if (freq
<= ath9k_hw_fbin2freq(powInfo
[0].bChannel
, IS_CHAN_2GHZ(chan
))) {
192 for (i
= 0; (i
< numChannels
) &&
193 (powInfo
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
194 if (freq
== ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
195 IS_CHAN_2GHZ(chan
))) {
199 if (freq
< ath9k_hw_fbin2freq(powInfo
[i
].bChannel
,
200 IS_CHAN_2GHZ(chan
)) && i
> 0 &&
201 freq
> ath9k_hw_fbin2freq(powInfo
[i
- 1].bChannel
,
202 IS_CHAN_2GHZ(chan
))) {
207 if ((matchIndex
== -1) && (lowIndex
== -1))
211 if (matchIndex
!= -1) {
212 *pNewPower
= powInfo
[matchIndex
];
214 clo
= ath9k_hw_fbin2freq(powInfo
[lowIndex
].bChannel
,
216 chi
= ath9k_hw_fbin2freq(powInfo
[lowIndex
+ 1].bChannel
,
219 for (i
= 0; i
< numRates
; i
++) {
220 pNewPower
->tPow2x
[i
] = (u8
)ath9k_hw_interpolate(freq
,
222 powInfo
[lowIndex
].tPow2x
[i
],
223 powInfo
[lowIndex
+ 1].tPow2x
[i
]);
228 u16
ath9k_hw_get_max_edge_power(u16 freq
, struct cal_ctl_edges
*pRdEdgesPower
,
229 bool is2GHz
, int num_band_edges
)
231 u16 twiceMaxEdgePower
= AR5416_MAX_RATE_POWER
;
234 for (i
= 0; (i
< num_band_edges
) &&
235 (pRdEdgesPower
[i
].bChannel
!= AR5416_BCHAN_UNUSED
); i
++) {
236 if (freq
== ath9k_hw_fbin2freq(pRdEdgesPower
[i
].bChannel
, is2GHz
)) {
237 twiceMaxEdgePower
= pRdEdgesPower
[i
].tPower
;
239 } else if ((i
> 0) &&
240 (freq
< ath9k_hw_fbin2freq(pRdEdgesPower
[i
].bChannel
,
242 if (ath9k_hw_fbin2freq(pRdEdgesPower
[i
- 1].bChannel
,
244 pRdEdgesPower
[i
- 1].flag
) {
246 pRdEdgesPower
[i
- 1].tPower
;
252 return twiceMaxEdgePower
;
255 int ath9k_hw_eeprom_init(struct ath_hw
*ah
)
259 if (AR_SREV_9287(ah
)) {
260 ah
->eep_map
= EEP_MAP_AR9287
;
261 ah
->eep_ops
= &eep_AR9287_ops
;
262 } else if (AR_SREV_9285(ah
) || AR_SREV_9271(ah
)) {
263 ah
->eep_map
= EEP_MAP_4KBITS
;
264 ah
->eep_ops
= &eep_4k_ops
;
266 ah
->eep_map
= EEP_MAP_DEFAULT
;
267 ah
->eep_ops
= &eep_def_ops
;
270 if (!ah
->eep_ops
->fill_eeprom(ah
))
273 status
= ah
->eep_ops
->check_eeprom(ah
);