1  /*
2   * Copyright (c) 2008-2011 Atheros Communications Inc.
3   *
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.
7   *
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.
15   */
16  
17  #include "hw.h"
18  #include <linux/ath9k_platform.h>
19  
ath9k_hw_analog_shift_regwrite(struct ath_hw * ah,u32 reg,u32 val)20  void ath9k_hw_analog_shift_regwrite(struct ath_hw *ah, u32 reg, u32 val)
21  {
22          REG_WRITE(ah, reg, val);
23  
24          if (ah->config.analog_shiftreg)
25  		udelay(100);
26  }
27  
ath9k_hw_analog_shift_rmw(struct ath_hw * ah,u32 reg,u32 mask,u32 shift,u32 val)28  void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask,
29  			       u32 shift, u32 val)
30  {
31  	REG_RMW(ah, reg, ((val << shift) & mask), mask);
32  
33  	if (ah->config.analog_shiftreg)
34  		udelay(100);
35  }
36  
ath9k_hw_interpolate(u16 target,u16 srcLeft,u16 srcRight,int16_t targetLeft,int16_t targetRight)37  int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight,
38  			     int16_t targetLeft, int16_t targetRight)
39  {
40  	int16_t rv;
41  
42  	if (srcRight == srcLeft) {
43  		rv = targetLeft;
44  	} else {
45  		rv = (int16_t) (((target - srcLeft) * targetRight +
46  				 (srcRight - target) * targetLeft) /
47  				(srcRight - srcLeft));
48  	}
49  	return rv;
50  }
51  
ath9k_hw_get_lower_upper_index(u8 target,u8 * pList,u16 listSize,u16 * indexL,u16 * indexR)52  bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
53  				    u16 *indexL, u16 *indexR)
54  {
55  	u16 i;
56  
57  	if (target <= pList[0]) {
58  		*indexL = *indexR = 0;
59  		return true;
60  	}
61  	if (target >= pList[listSize - 1]) {
62  		*indexL = *indexR = (u16) (listSize - 1);
63  		return true;
64  	}
65  
66  	for (i = 0; i < listSize - 1; i++) {
67  		if (pList[i] == target) {
68  			*indexL = *indexR = i;
69  			return true;
70  		}
71  		if (target < pList[i + 1]) {
72  			*indexL = i;
73  			*indexR = (u16) (i + 1);
74  			return false;
75  		}
76  	}
77  	return false;
78  }
79  
ath9k_hw_usb_gen_fill_eeprom(struct ath_hw * ah,u16 * eep_data,int eep_start_loc,int size)80  void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
81  				  int eep_start_loc, int size)
82  {
83  	int i = 0, j, addr;
84  	u32 addrdata[8];
85  	u32 data[8];
86  
87  	for (addr = 0; addr < size; addr++) {
88  		addrdata[i] = AR5416_EEPROM_OFFSET +
89  			((addr + eep_start_loc) << AR5416_EEPROM_S);
90  		i++;
91  		if (i == 8) {
92  			REG_READ_MULTI(ah, addrdata, data, i);
93  
94  			for (j = 0; j < i; j++) {
95  				*eep_data = data[j];
96  				eep_data++;
97  			}
98  			i = 0;
99  		}
100  	}
101  
102  	if (i != 0) {
103  		REG_READ_MULTI(ah, addrdata, data, i);
104  
105  		for (j = 0; j < i; j++) {
106  			*eep_data = data[j];
107  			eep_data++;
108  		}
109  	}
110  }
111  
ath9k_hw_nvram_read_array(u16 * blob,size_t blob_size,off_t offset,u16 * data)112  static bool ath9k_hw_nvram_read_array(u16 *blob, size_t blob_size,
113  				      off_t offset, u16 *data)
114  {
115  	if (offset >= blob_size)
116  		return false;
117  
118  	*data =  blob[offset];
119  	return true;
120  }
121  
ath9k_hw_nvram_read_pdata(struct ath9k_platform_data * pdata,off_t offset,u16 * data)122  static bool ath9k_hw_nvram_read_pdata(struct ath9k_platform_data *pdata,
123  				      off_t offset, u16 *data)
124  {
125  	return ath9k_hw_nvram_read_array(pdata->eeprom_data,
126  					 ARRAY_SIZE(pdata->eeprom_data),
127  					 offset, data);
128  }
129  
ath9k_hw_nvram_read_firmware(const struct firmware * eeprom_blob,off_t offset,u16 * data)130  static bool ath9k_hw_nvram_read_firmware(const struct firmware *eeprom_blob,
131  					 off_t offset, u16 *data)
132  {
133  	return ath9k_hw_nvram_read_array((u16 *) eeprom_blob->data,
134  					 eeprom_blob->size / sizeof(u16),
135  					 offset, data);
136  }
137  
ath9k_hw_nvram_read_nvmem(struct ath_hw * ah,off_t offset,u16 * data)138  static bool ath9k_hw_nvram_read_nvmem(struct ath_hw *ah, off_t offset,
139  				      u16 *data)
140  {
141  	return ath9k_hw_nvram_read_array(ah->nvmem_blob,
142  					 ah->nvmem_blob_len / sizeof(u16),
143  					 offset, data);
144  }
145  
ath9k_hw_nvram_read(struct ath_hw * ah,u32 off,u16 * data)146  bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data)
147  {
148  	struct ath_common *common = ath9k_hw_common(ah);
149  	struct ath9k_platform_data *pdata = ah->dev->platform_data;
150  	bool ret;
151  
152  	if (ah->nvmem_blob)
153  		ret = ath9k_hw_nvram_read_nvmem(ah, off, data);
154  	else if (ah->eeprom_blob)
155  		ret = ath9k_hw_nvram_read_firmware(ah->eeprom_blob, off, data);
156  	else if (pdata && !pdata->use_eeprom)
157  		ret = ath9k_hw_nvram_read_pdata(pdata, off, data);
158  	else
159  		ret = common->bus_ops->eeprom_read(common, off, data);
160  
161  	if (!ret)
162  		ath_dbg(common, EEPROM,
163  			"unable to read eeprom region at offset %u\n", off);
164  
165  	return ret;
166  }
167  
ath9k_hw_nvram_swap_data(struct ath_hw * ah,bool * swap_needed,int size)168  int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size)
169  {
170  	u16 magic;
171  	u16 *eepdata;
172  	int i;
173  	bool needs_byteswap = false;
174  	struct ath_common *common = ath9k_hw_common(ah);
175  
176  	if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) {
177  		ath_err(common, "Reading Magic # failed\n");
178  		return -EIO;
179  	}
180  
181  	if (swab16(magic) == AR5416_EEPROM_MAGIC) {
182  		needs_byteswap = true;
183  		ath_dbg(common, EEPROM,
184  			"EEPROM needs byte-swapping to correct endianness.\n");
185  	} else if (magic != AR5416_EEPROM_MAGIC) {
186  		if (ath9k_hw_use_flash(ah)) {
187  			ath_dbg(common, EEPROM,
188  				"Ignoring invalid EEPROM magic (0x%04x).\n",
189  				magic);
190  		} else {
191  			ath_err(common,
192  				"Invalid EEPROM magic (0x%04x).\n", magic);
193  			return -EINVAL;
194  		}
195  	}
196  
197  	if (needs_byteswap) {
198  		if (ah->ah_flags & AH_NO_EEP_SWAP) {
199  			ath_info(common,
200  				 "Ignoring endianness difference in EEPROM magic bytes.\n");
201  		} else {
202  			eepdata = (u16 *)(&ah->eeprom);
203  
204  			for (i = 0; i < size; i++)
205  				eepdata[i] = swab16(eepdata[i]);
206  		}
207  	}
208  
209  	if (ah->eep_ops->get_eepmisc(ah) & AR5416_EEPMISC_BIG_ENDIAN) {
210  		*swap_needed = true;
211  		ath_dbg(common, EEPROM,
212  			"Big Endian EEPROM detected according to EEPMISC register.\n");
213  	} else {
214  		*swap_needed = false;
215  	}
216  
217  	return 0;
218  }
219  
ath9k_hw_nvram_validate_checksum(struct ath_hw * ah,int size)220  bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size)
221  {
222  	u32 i, sum = 0;
223  	u16 *eepdata = (u16 *)(&ah->eeprom);
224  	struct ath_common *common = ath9k_hw_common(ah);
225  
226  	for (i = 0; i < size; i++)
227  		sum ^= eepdata[i];
228  
229  	if (sum != 0xffff) {
230  		ath_err(common, "Bad EEPROM checksum 0x%x\n", sum);
231  		return false;
232  	}
233  
234  	return true;
235  }
236  
ath9k_hw_nvram_check_version(struct ath_hw * ah,int version,int minrev)237  bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev)
238  {
239  	struct ath_common *common = ath9k_hw_common(ah);
240  
241  	if (ah->eep_ops->get_eeprom_ver(ah) != version ||
242  	    ah->eep_ops->get_eeprom_rev(ah) < minrev) {
243  		ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n",
244  			ah->eep_ops->get_eeprom_ver(ah),
245  			ah->eep_ops->get_eeprom_rev(ah));
246  		return false;
247  	}
248  
249  	return true;
250  }
251  
ath9k_hw_fill_vpd_table(u8 pwrMin,u8 pwrMax,u8 * pPwrList,u8 * pVpdList,u16 numIntercepts,u8 * pRetVpdList)252  void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
253  			     u8 *pVpdList, u16 numIntercepts,
254  			     u8 *pRetVpdList)
255  {
256  	u16 i, k;
257  	u8 currPwr = pwrMin;
258  	u16 idxL = 0, idxR = 0;
259  
260  	for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) {
261  		ath9k_hw_get_lower_upper_index(currPwr, pPwrList,
262  					       numIntercepts, &(idxL),
263  					       &(idxR));
264  		if (idxR < 1)
265  			idxR = 1;
266  		if (idxL == numIntercepts - 1)
267  			idxL = (u16) (numIntercepts - 2);
268  		if (pPwrList[idxL] == pPwrList[idxR])
269  			k = pVpdList[idxL];
270  		else
271  			k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] +
272  				   (pPwrList[idxR] - currPwr) * pVpdList[idxL]) /
273  				  (pPwrList[idxR] - pPwrList[idxL]));
274  		pRetVpdList[i] = (u8) k;
275  		currPwr += 2;
276  	}
277  }
278  
ath9k_hw_get_legacy_target_powers(struct ath_hw * ah,struct ath9k_channel * chan,struct cal_target_power_leg * powInfo,u16 numChannels,struct cal_target_power_leg * pNewPower,u16 numRates,bool isExtTarget)279  void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah,
280  				       struct ath9k_channel *chan,
281  				       struct cal_target_power_leg *powInfo,
282  				       u16 numChannels,
283  				       struct cal_target_power_leg *pNewPower,
284  				       u16 numRates, bool isExtTarget)
285  {
286  	struct chan_centers centers;
287  	u16 clo, chi;
288  	int i;
289  	int matchIndex = -1, lowIndex = -1;
290  	u16 freq;
291  
292  	ath9k_hw_get_channel_centers(ah, chan, &centers);
293  	freq = (isExtTarget) ? centers.ext_center : centers.ctl_center;
294  
295  	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel,
296  				       IS_CHAN_2GHZ(chan))) {
297  		matchIndex = 0;
298  	} else {
299  		for (i = 0; (i < numChannels) &&
300  			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
301  			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
302  						       IS_CHAN_2GHZ(chan))) {
303  				matchIndex = i;
304  				break;
305  			} else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
306  						IS_CHAN_2GHZ(chan)) && i > 0 &&
307  				   freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
308  						IS_CHAN_2GHZ(chan))) {
309  				lowIndex = i - 1;
310  				break;
311  			}
312  		}
313  		if ((matchIndex == -1) && (lowIndex == -1))
314  			matchIndex = i - 1;
315  	}
316  
317  	if (matchIndex != -1) {
318  		*pNewPower = powInfo[matchIndex];
319  	} else {
320  		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
321  					 IS_CHAN_2GHZ(chan));
322  		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
323  					 IS_CHAN_2GHZ(chan));
324  
325  		for (i = 0; i < numRates; i++) {
326  			pNewPower->tPow2x[i] =
327  				(u8)ath9k_hw_interpolate(freq, clo, chi,
328  						powInfo[lowIndex].tPow2x[i],
329  						powInfo[lowIndex + 1].tPow2x[i]);
330  		}
331  	}
332  }
333  
ath9k_hw_get_target_powers(struct ath_hw * ah,struct ath9k_channel * chan,struct cal_target_power_ht * powInfo,u16 numChannels,struct cal_target_power_ht * pNewPower,u16 numRates,bool isHt40Target)334  void ath9k_hw_get_target_powers(struct ath_hw *ah,
335  				struct ath9k_channel *chan,
336  				struct cal_target_power_ht *powInfo,
337  				u16 numChannels,
338  				struct cal_target_power_ht *pNewPower,
339  				u16 numRates, bool isHt40Target)
340  {
341  	struct chan_centers centers;
342  	u16 clo, chi;
343  	int i;
344  	int matchIndex = -1, lowIndex = -1;
345  	u16 freq;
346  
347  	ath9k_hw_get_channel_centers(ah, chan, &centers);
348  	freq = isHt40Target ? centers.synth_center : centers.ctl_center;
349  
350  	if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) {
351  		matchIndex = 0;
352  	} else {
353  		for (i = 0; (i < numChannels) &&
354  			     (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
355  			if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel,
356  						       IS_CHAN_2GHZ(chan))) {
357  				matchIndex = i;
358  				break;
359  			} else
360  				if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel,
361  						IS_CHAN_2GHZ(chan)) && i > 0 &&
362  				    freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel,
363  						IS_CHAN_2GHZ(chan))) {
364  					lowIndex = i - 1;
365  					break;
366  				}
367  		}
368  		if ((matchIndex == -1) && (lowIndex == -1))
369  			matchIndex = i - 1;
370  	}
371  
372  	if (matchIndex != -1) {
373  		*pNewPower = powInfo[matchIndex];
374  	} else {
375  		clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel,
376  					 IS_CHAN_2GHZ(chan));
377  		chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel,
378  					 IS_CHAN_2GHZ(chan));
379  
380  		for (i = 0; i < numRates; i++) {
381  			pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq,
382  						clo, chi,
383  						powInfo[lowIndex].tPow2x[i],
384  						powInfo[lowIndex + 1].tPow2x[i]);
385  		}
386  	}
387  }
388  
ath9k_hw_get_max_edge_power(u16 freq,struct cal_ctl_edges * pRdEdgesPower,bool is2GHz,int num_band_edges)389  u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower,
390  				bool is2GHz, int num_band_edges)
391  {
392  	u16 twiceMaxEdgePower = MAX_RATE_POWER;
393  	int i;
394  
395  	for (i = 0; (i < num_band_edges) &&
396  		     (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) {
397  		if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) {
398  			twiceMaxEdgePower = CTL_EDGE_TPOWER(pRdEdgesPower[i].ctl);
399  			break;
400  		} else if ((i > 0) &&
401  			   (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel,
402  						      is2GHz))) {
403  			if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel,
404  					       is2GHz) < freq &&
405  			    CTL_EDGE_FLAGS(pRdEdgesPower[i - 1].ctl)) {
406  				twiceMaxEdgePower =
407  					CTL_EDGE_TPOWER(pRdEdgesPower[i - 1].ctl);
408  			}
409  			break;
410  		}
411  	}
412  
413  	return twiceMaxEdgePower;
414  }
415  
ath9k_hw_get_scaled_power(struct ath_hw * ah,u16 power_limit,u8 antenna_reduction)416  u16 ath9k_hw_get_scaled_power(struct ath_hw *ah, u16 power_limit,
417  			      u8 antenna_reduction)
418  {
419  	u16 reduction = antenna_reduction;
420  
421  	/*
422  	 * Reduce scaled Power by number of chains active
423  	 * to get the per chain tx power level.
424  	 */
425  	switch (ar5416_get_ntxchains(ah->txchainmask)) {
426  	case 1:
427  		break;
428  	case 2:
429  		reduction += POWER_CORRECTION_FOR_TWO_CHAIN;
430  		break;
431  	case 3:
432  		reduction += POWER_CORRECTION_FOR_THREE_CHAIN;
433  		break;
434  	}
435  
436  	if (power_limit > reduction)
437  		power_limit -= reduction;
438  	else
439  		power_limit = 0;
440  
441  	return min_t(u16, power_limit, MAX_RATE_POWER);
442  }
443  
ath9k_hw_update_regulatory_maxpower(struct ath_hw * ah)444  void ath9k_hw_update_regulatory_maxpower(struct ath_hw *ah)
445  {
446  	struct ath_common *common = ath9k_hw_common(ah);
447  	struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
448  
449  	switch (ar5416_get_ntxchains(ah->txchainmask)) {
450  	case 1:
451  		break;
452  	case 2:
453  		regulatory->max_power_level += POWER_CORRECTION_FOR_TWO_CHAIN;
454  		break;
455  	case 3:
456  		regulatory->max_power_level += POWER_CORRECTION_FOR_THREE_CHAIN;
457  		break;
458  	default:
459  		ath_dbg(common, EEPROM, "Invalid chainmask configuration\n");
460  		break;
461  	}
462  }
463  
ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw * ah,struct ath9k_channel * chan,void * pRawDataSet,u8 * bChans,u16 availPiers,u16 tPdGainOverlap,u16 * pPdGainBoundaries,u8 * pPDADCValues,u16 numXpdGains)464  void ath9k_hw_get_gain_boundaries_pdadcs(struct ath_hw *ah,
465  				struct ath9k_channel *chan,
466  				void *pRawDataSet,
467  				u8 *bChans, u16 availPiers,
468  				u16 tPdGainOverlap,
469  				u16 *pPdGainBoundaries, u8 *pPDADCValues,
470  				u16 numXpdGains)
471  {
472  	int i, j, k;
473  	int16_t ss;
474  	u16 idxL = 0, idxR = 0, numPiers;
475  	static u8 vpdTableL[AR5416_NUM_PD_GAINS]
476  		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
477  	static u8 vpdTableR[AR5416_NUM_PD_GAINS]
478  		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
479  	static u8 vpdTableI[AR5416_NUM_PD_GAINS]
480  		[AR5416_MAX_PWR_RANGE_IN_HALF_DB];
481  
482  	u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR;
483  	u8 minPwrT4[AR5416_NUM_PD_GAINS];
484  	u8 maxPwrT4[AR5416_NUM_PD_GAINS];
485  	int16_t vpdStep;
486  	int16_t tmpVal;
487  	u16 sizeCurrVpdTable, maxIndex, tgtIndex;
488  	bool match;
489  	int16_t minDelta = 0;
490  	struct chan_centers centers;
491  	int pdgain_boundary_default;
492  	struct cal_data_per_freq *data_def = pRawDataSet;
493  	struct cal_data_per_freq_4k *data_4k = pRawDataSet;
494  	struct cal_data_per_freq_ar9287 *data_9287 = pRawDataSet;
495  	bool eeprom_4k = AR_SREV_9285(ah) || AR_SREV_9271(ah);
496  	int intercepts;
497  
498  	if (AR_SREV_9287(ah))
499  		intercepts = AR9287_PD_GAIN_ICEPTS;
500  	else
501  		intercepts = AR5416_PD_GAIN_ICEPTS;
502  
503  	memset(&minPwrT4, 0, AR5416_NUM_PD_GAINS);
504  	ath9k_hw_get_channel_centers(ah, chan, &centers);
505  
506  	for (numPiers = 0; numPiers < availPiers; numPiers++) {
507  		if (bChans[numPiers] == AR5416_BCHAN_UNUSED)
508  			break;
509  	}
510  
511  	match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center,
512  							     IS_CHAN_2GHZ(chan)),
513  					       bChans, numPiers, &idxL, &idxR);
514  
515  	if (match) {
516  		if (AR_SREV_9287(ah)) {
517  			for (i = 0; i < numXpdGains; i++) {
518  				minPwrT4[i] = data_9287[idxL].pwrPdg[i][0];
519  				maxPwrT4[i] = data_9287[idxL].pwrPdg[i][intercepts - 1];
520  				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
521  						data_9287[idxL].pwrPdg[i],
522  						data_9287[idxL].vpdPdg[i],
523  						intercepts,
524  						vpdTableI[i]);
525  			}
526  		} else if (eeprom_4k) {
527  			for (i = 0; i < numXpdGains; i++) {
528  				minPwrT4[i] = data_4k[idxL].pwrPdg[i][0];
529  				maxPwrT4[i] = data_4k[idxL].pwrPdg[i][intercepts - 1];
530  				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
531  						data_4k[idxL].pwrPdg[i],
532  						data_4k[idxL].vpdPdg[i],
533  						intercepts,
534  						vpdTableI[i]);
535  			}
536  		} else {
537  			for (i = 0; i < numXpdGains; i++) {
538  				minPwrT4[i] = data_def[idxL].pwrPdg[i][0];
539  				maxPwrT4[i] = data_def[idxL].pwrPdg[i][intercepts - 1];
540  				ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
541  						data_def[idxL].pwrPdg[i],
542  						data_def[idxL].vpdPdg[i],
543  						intercepts,
544  						vpdTableI[i]);
545  			}
546  		}
547  	} else {
548  		for (i = 0; i < numXpdGains; i++) {
549  			if (AR_SREV_9287(ah)) {
550  				pVpdL = data_9287[idxL].vpdPdg[i];
551  				pPwrL = data_9287[idxL].pwrPdg[i];
552  				pVpdR = data_9287[idxR].vpdPdg[i];
553  				pPwrR = data_9287[idxR].pwrPdg[i];
554  			} else if (eeprom_4k) {
555  				pVpdL = data_4k[idxL].vpdPdg[i];
556  				pPwrL = data_4k[idxL].pwrPdg[i];
557  				pVpdR = data_4k[idxR].vpdPdg[i];
558  				pPwrR = data_4k[idxR].pwrPdg[i];
559  			} else {
560  				pVpdL = data_def[idxL].vpdPdg[i];
561  				pPwrL = data_def[idxL].pwrPdg[i];
562  				pVpdR = data_def[idxR].vpdPdg[i];
563  				pPwrR = data_def[idxR].pwrPdg[i];
564  			}
565  
566  			minPwrT4[i] = max(pPwrL[0], pPwrR[0]);
567  
568  			maxPwrT4[i] =
569  				min(pPwrL[intercepts - 1],
570  				    pPwrR[intercepts - 1]);
571  
572  
573  			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
574  						pPwrL, pVpdL,
575  						intercepts,
576  						vpdTableL[i]);
577  			ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i],
578  						pPwrR, pVpdR,
579  						intercepts,
580  						vpdTableR[i]);
581  
582  			for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) {
583  				vpdTableI[i][j] =
584  					(u8)(ath9k_hw_interpolate((u16)
585  					     FREQ2FBIN(centers.
586  						       synth_center,
587  						       IS_CHAN_2GHZ
588  						       (chan)),
589  					     bChans[idxL], bChans[idxR],
590  					     vpdTableL[i][j], vpdTableR[i][j]));
591  			}
592  		}
593  	}
594  
595  	k = 0;
596  
597  	for (i = 0; i < numXpdGains; i++) {
598  		if (i == (numXpdGains - 1))
599  			pPdGainBoundaries[i] =
600  				(u16)(maxPwrT4[i] / 2);
601  		else
602  			pPdGainBoundaries[i] =
603  				(u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4);
604  
605  		pPdGainBoundaries[i] =
606  			min((u16)MAX_RATE_POWER, pPdGainBoundaries[i]);
607  
608  		minDelta = 0;
609  
610  		if (i == 0) {
611  			if (AR_SREV_9280_20_OR_LATER(ah))
612  				ss = (int16_t)(0 - (minPwrT4[i] / 2));
613  			else
614  				ss = 0;
615  		} else {
616  			ss = (int16_t)((pPdGainBoundaries[i - 1] -
617  					(minPwrT4[i] / 2)) -
618  				       tPdGainOverlap + 1 + minDelta);
619  		}
620  		vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]);
621  		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
622  
623  		while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
624  			tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep);
625  			pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal);
626  			ss++;
627  		}
628  
629  		sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1);
630  		tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap -
631  				(minPwrT4[i] / 2));
632  		maxIndex = (tgtIndex < sizeCurrVpdTable) ?
633  			tgtIndex : sizeCurrVpdTable;
634  
635  		while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) {
636  			pPDADCValues[k++] = vpdTableI[i][ss++];
637  		}
638  
639  		vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] -
640  				    vpdTableI[i][sizeCurrVpdTable - 2]);
641  		vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep);
642  
643  		if (tgtIndex >= maxIndex) {
644  			while ((ss <= tgtIndex) &&
645  			       (k < (AR5416_NUM_PDADC_VALUES - 1))) {
646  				tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] +
647  						    (ss - maxIndex + 1) * vpdStep));
648  				pPDADCValues[k++] = (u8)((tmpVal > 255) ?
649  							 255 : tmpVal);
650  				ss++;
651  			}
652  		}
653  	}
654  
655  	if (eeprom_4k)
656  		pdgain_boundary_default = 58;
657  	else
658  		pdgain_boundary_default = pPdGainBoundaries[i - 1];
659  
660  	while (i < AR5416_PD_GAINS_IN_MASK) {
661  		pPdGainBoundaries[i] = pdgain_boundary_default;
662  		i++;
663  	}
664  
665  	while (k < AR5416_NUM_PDADC_VALUES) {
666  		pPDADCValues[k] = pPDADCValues[k - 1];
667  		k++;
668  	}
669  }
670  
ath9k_hw_eeprom_init(struct ath_hw * ah)671  int ath9k_hw_eeprom_init(struct ath_hw *ah)
672  {
673  	if (AR_SREV_9300_20_OR_LATER(ah))
674  		ah->eep_ops = &eep_ar9300_ops;
675  	else if (AR_SREV_9287(ah)) {
676  		ah->eep_ops = &eep_ar9287_ops;
677  	} else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) {
678  		ah->eep_ops = &eep_4k_ops;
679  	} else {
680  		ah->eep_ops = &eep_def_ops;
681  	}
682  
683  	if (!ah->eep_ops->fill_eeprom(ah))
684  		return -EIO;
685  
686  	return ah->eep_ops->check_eeprom(ah);
687  }
688