LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath/ath9k - eeprom.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 104 361 28.8 %
Date: 2022-03-28 13:20:08 Functions: 9 17 52.9 %
Branches: 58 265 21.9 %

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

Generated by: LCOV version 1.14