iPXE
ath9k_ar9003_hw.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008-2011 Atheros Communications Inc.
00003  *
00004  * Modified for iPXE by Scott K Logan <logans@cottsay.net> July 2011
00005  * Original from Linux kernel 3.0.1
00006  *
00007  * Permission to use, copy, modify, and/or distribute this software for any
00008  * purpose with or without fee is hereby granted, provided that the above
00009  * copyright notice and this permission notice appear in all copies.
00010  *
00011  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
00012  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
00013  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
00014  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
00015  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
00016  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
00017  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
00018  */
00019 
00020 #include "hw.h"
00021 #include "ar9003_mac.h"
00022 #include "ar9003_2p2_initvals.h"
00023 #include "ar9485_initvals.h"
00024 #include "ar9340_initvals.h"
00025 
00026 /* General hardware code for the AR9003 hadware family */
00027 
00028 /*
00029  * The AR9003 family uses a new INI format (pre, core, post
00030  * arrays per subsystem). This provides support for the
00031  * AR9003 2.2 chipsets.
00032  */
00033 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
00034 {
00035         if (AR_SREV_9340(ah)) {
00036                 /* mac */
00037                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
00038                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
00039                                 ar9340_1p0_mac_core,
00040                                 ARRAY_SIZE(ar9340_1p0_mac_core), 2);
00041                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
00042                                 ar9340_1p0_mac_postamble,
00043                                 ARRAY_SIZE(ar9340_1p0_mac_postamble), 5);
00044 
00045                 /* bb */
00046                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
00047                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
00048                                 ar9340_1p0_baseband_core,
00049                                 ARRAY_SIZE(ar9340_1p0_baseband_core), 2);
00050                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
00051                                 ar9340_1p0_baseband_postamble,
00052                                 ARRAY_SIZE(ar9340_1p0_baseband_postamble), 5);
00053 
00054                 /* radio */
00055                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
00056                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
00057                                 ar9340_1p0_radio_core,
00058                                 ARRAY_SIZE(ar9340_1p0_radio_core), 2);
00059                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
00060                                 ar9340_1p0_radio_postamble,
00061                                 ARRAY_SIZE(ar9340_1p0_radio_postamble), 5);
00062 
00063                 /* soc */
00064                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
00065                                 ar9340_1p0_soc_preamble,
00066                                 ARRAY_SIZE(ar9340_1p0_soc_preamble), 2);
00067                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
00068                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
00069                                 ar9340_1p0_soc_postamble,
00070                                 ARRAY_SIZE(ar9340_1p0_soc_postamble), 5);
00071 
00072                 /* rx/tx gain */
00073                 INIT_INI_ARRAY(&ah->iniModesRxGain,
00074                                 ar9340Common_wo_xlna_rx_gain_table_1p0,
00075                                 ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
00076                                 5);
00077                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00078                                 ar9340Modes_high_ob_db_tx_gain_table_1p0,
00079                                 ARRAY_SIZE(ar9340Modes_high_ob_db_tx_gain_table_1p0),
00080                                 5);
00081 
00082                 INIT_INI_ARRAY(&ah->iniModesAdditional,
00083                                 ar9340Modes_fast_clock_1p0,
00084                                 ARRAY_SIZE(ar9340Modes_fast_clock_1p0),
00085                                 3);
00086 
00087                 INIT_INI_ARRAY(&ah->iniModesAdditional_40M,
00088                                 ar9340_1p0_radio_core_40M,
00089                                 ARRAY_SIZE(ar9340_1p0_radio_core_40M),
00090                                 2);
00091         } else if (AR_SREV_9485_11(ah)) {
00092                 /* mac */
00093                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
00094                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
00095                                 ar9485_1_1_mac_core,
00096                                 ARRAY_SIZE(ar9485_1_1_mac_core), 2);
00097                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
00098                                 ar9485_1_1_mac_postamble,
00099                                 ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
00100 
00101                 /* bb */
00102                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
00103                                 ARRAY_SIZE(ar9485_1_1), 2);
00104                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
00105                                 ar9485_1_1_baseband_core,
00106                                 ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
00107                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
00108                                 ar9485_1_1_baseband_postamble,
00109                                 ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
00110 
00111                 /* radio */
00112                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
00113                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
00114                                 ar9485_1_1_radio_core,
00115                                 ARRAY_SIZE(ar9485_1_1_radio_core), 2);
00116                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
00117                                 ar9485_1_1_radio_postamble,
00118                                 ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
00119 
00120                 /* soc */
00121                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
00122                                 ar9485_1_1_soc_preamble,
00123                                 ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
00124                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
00125                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
00126 
00127                 /* rx/tx gain */
00128                 INIT_INI_ARRAY(&ah->iniModesRxGain,
00129                                 ar9485Common_wo_xlna_rx_gain_1_1,
00130                                 ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1), 2);
00131                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00132                                 ar9485_modes_lowest_ob_db_tx_gain_1_1,
00133                                 ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
00134                                 5);
00135 
00136                 /* Load PCIE SERDES settings from INI */
00137 
00138                 /* Awake Setting */
00139 
00140                 INIT_INI_ARRAY(&ah->iniPcieSerdes,
00141                                 ar9485_1_1_pcie_phy_clkreq_disable_L1,
00142                                 ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
00143                                 2);
00144 
00145                 /* Sleep Setting */
00146 
00147                 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
00148                                 ar9485_1_1_pcie_phy_clkreq_disable_L1,
00149                                 ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
00150                                 2);
00151         } else {
00152                 /* mac */
00153                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
00154                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
00155                                 ar9300_2p2_mac_core,
00156                                 ARRAY_SIZE(ar9300_2p2_mac_core), 2);
00157                 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
00158                                 ar9300_2p2_mac_postamble,
00159                                 ARRAY_SIZE(ar9300_2p2_mac_postamble), 5);
00160 
00161                 /* bb */
00162                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0);
00163                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
00164                                 ar9300_2p2_baseband_core,
00165                                 ARRAY_SIZE(ar9300_2p2_baseband_core), 2);
00166                 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
00167                                 ar9300_2p2_baseband_postamble,
00168                                 ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5);
00169 
00170                 /* radio */
00171                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
00172                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
00173                                 ar9300_2p2_radio_core,
00174                                 ARRAY_SIZE(ar9300_2p2_radio_core), 2);
00175                 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
00176                                 ar9300_2p2_radio_postamble,
00177                                 ARRAY_SIZE(ar9300_2p2_radio_postamble), 5);
00178 
00179                 /* soc */
00180                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
00181                                 ar9300_2p2_soc_preamble,
00182                                 ARRAY_SIZE(ar9300_2p2_soc_preamble), 2);
00183                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
00184                 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
00185                                 ar9300_2p2_soc_postamble,
00186                                 ARRAY_SIZE(ar9300_2p2_soc_postamble), 5);
00187 
00188                 /* rx/tx gain */
00189                 INIT_INI_ARRAY(&ah->iniModesRxGain,
00190                                 ar9300Common_rx_gain_table_2p2,
00191                                 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2);
00192                 INIT_INI_ARRAY(&ah->iniModesTxGain,
00193                                 ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
00194                                 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
00195                                 5);
00196 
00197                 /* Load PCIE SERDES settings from INI */
00198 
00199                 /* Awake Setting */
00200 
00201                 INIT_INI_ARRAY(&ah->iniPcieSerdes,
00202                                 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
00203                                 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
00204                                 2);
00205 
00206                 /* Sleep Setting */
00207 
00208                 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
00209                                 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2,
00210                                 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2),
00211                                 2);
00212 
00213                 /* Fast clock modal settings */
00214                 INIT_INI_ARRAY(&ah->iniModesAdditional,
00215                                 ar9300Modes_fast_clock_2p2,
00216                                 ARRAY_SIZE(ar9300Modes_fast_clock_2p2),
00217                                 3);
00218         }
00219 }
00220 
00221 static void ar9003_tx_gain_table_apply(struct ath_hw *ah)
00222 {
00223         switch (ar9003_hw_get_tx_gain_idx(ah)) {
00224         case 0:
00225         default:
00226                 if (AR_SREV_9340(ah))
00227                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00228                                         ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
00229                                        ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
00230                                        5);
00231                 else if (AR_SREV_9485_11(ah))
00232                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00233                                        ar9485_modes_lowest_ob_db_tx_gain_1_1,
00234                                        ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
00235                                        5);
00236                 else
00237                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00238                                        ar9300Modes_lowest_ob_db_tx_gain_table_2p2,
00239                                        ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2),
00240                                        5);
00241                 break;
00242         case 1:
00243                 if (AR_SREV_9340(ah))
00244                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00245                                         ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
00246                                        ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
00247                                        5);
00248                 else if (AR_SREV_9485_11(ah))
00249                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00250                                        ar9485Modes_high_ob_db_tx_gain_1_1,
00251                                        ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
00252                                        5);
00253                 else
00254                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00255                                        ar9300Modes_high_ob_db_tx_gain_table_2p2,
00256                                        ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2),
00257                                        5);
00258                 break;
00259         case 2:
00260                 if (AR_SREV_9340(ah))
00261                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00262                                         ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
00263                                        ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
00264                                        5);
00265                 else if (AR_SREV_9485_11(ah))
00266                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00267                                        ar9485Modes_low_ob_db_tx_gain_1_1,
00268                                        ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
00269                                        5);
00270                 else
00271                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00272                                        ar9300Modes_low_ob_db_tx_gain_table_2p2,
00273                                        ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2),
00274                                        5);
00275                 break;
00276         case 3:
00277                 if (AR_SREV_9340(ah))
00278                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00279                                         ar9340Modes_lowest_ob_db_tx_gain_table_1p0,
00280                                        ARRAY_SIZE(ar9340Modes_lowest_ob_db_tx_gain_table_1p0),
00281                                        5);
00282                 else if (AR_SREV_9485_11(ah))
00283                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00284                                        ar9485Modes_high_power_tx_gain_1_1,
00285                                        ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
00286                                        5);
00287                 else
00288                         INIT_INI_ARRAY(&ah->iniModesTxGain,
00289                                        ar9300Modes_high_power_tx_gain_table_2p2,
00290                                        ARRAY_SIZE(ar9300Modes_high_power_tx_gain_table_2p2),
00291                                        5);
00292                 break;
00293         }
00294 }
00295 
00296 static void ar9003_rx_gain_table_apply(struct ath_hw *ah)
00297 {
00298         switch (ar9003_hw_get_rx_gain_idx(ah)) {
00299         case 0:
00300         default:
00301                 if (AR_SREV_9340(ah))
00302                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00303                                        ar9340Common_rx_gain_table_1p0,
00304                                        ARRAY_SIZE(ar9340Common_rx_gain_table_1p0),
00305                                        2);
00306                 else if (AR_SREV_9485_11(ah))
00307                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00308                                        ar9485Common_wo_xlna_rx_gain_1_1,
00309                                        ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
00310                                        2);
00311                 else
00312                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00313                                        ar9300Common_rx_gain_table_2p2,
00314                                        ARRAY_SIZE(ar9300Common_rx_gain_table_2p2),
00315                                        2);
00316                 break;
00317         case 1:
00318                 if (AR_SREV_9340(ah))
00319                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00320                                        ar9340Common_wo_xlna_rx_gain_table_1p0,
00321                                        ARRAY_SIZE(ar9340Common_wo_xlna_rx_gain_table_1p0),
00322                                        2);
00323                 else if (AR_SREV_9485_11(ah))
00324                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00325                                        ar9485Common_wo_xlna_rx_gain_1_1,
00326                                        ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
00327                                        2);
00328                 else
00329                         INIT_INI_ARRAY(&ah->iniModesRxGain,
00330                                        ar9300Common_wo_xlna_rx_gain_table_2p2,
00331                                        ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2),
00332                                        2);
00333                 break;
00334         }
00335 }
00336 
00337 /* set gain table pointers according to values read from the eeprom */
00338 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah)
00339 {
00340         ar9003_tx_gain_table_apply(ah);
00341         ar9003_rx_gain_table_apply(ah);
00342 }
00343 
00344 /*
00345  * Helper for ASPM support.
00346  *
00347  * Disable PLL when in L0s as well as receiver clock when in L1.
00348  * This power saving option must be enabled through the SerDes.
00349  *
00350  * Programming the SerDes must go through the same 288 bit serial shift
00351  * register as the other analog registers.  Hence the 9 writes.
00352  */
00353 static void ar9003_hw_configpcipowersave(struct ath_hw *ah,
00354                                          int restore,
00355                                          int power_off)
00356 {
00357         if (ah->is_pciexpress != 1)
00358                 return;
00359 
00360         /* Do not touch SerDes registers */
00361         if (ah->config.pcie_powersave_enable == 2)
00362                 return;
00363 
00364         /* Nothing to do on restore for 11N */
00365         if (!restore) {
00366                 /* set bit 19 to allow forcing of pcie core into L1 state */
00367                 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA);
00368 
00369                 /* Several PCIe massages to ensure proper behaviour */
00370                 if (ah->config.pcie_waen)
00371                         REG_WRITE(ah, AR_WA, ah->config.pcie_waen);
00372                 else
00373                         REG_WRITE(ah, AR_WA, ah->WARegVal);
00374         }
00375 
00376         /*
00377          * Configire PCIE after Ini init. SERDES values now come from ini file
00378          * This enables PCIe low power mode.
00379          */
00380         if (ah->config.pcieSerDesWrite) {
00381                 unsigned int i;
00382                 struct ar5416IniArray *array;
00383 
00384                 array = power_off ? &ah->iniPcieSerdes :
00385                                     &ah->iniPcieSerdesLowPower;
00386 
00387                 for (i = 0; i < array->ia_rows; i++) {
00388                         REG_WRITE(ah,
00389                                   INI_RA(array, i, 0),
00390                                   INI_RA(array, i, 1));
00391                 }
00392         }
00393 }
00394 
00395 /* Sets up the AR9003 hardware familiy callbacks */
00396 void ar9003_hw_attach_ops(struct ath_hw *ah)
00397 {
00398         struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
00399         struct ath_hw_ops *ops = ath9k_hw_ops(ah);
00400 
00401         priv_ops->init_mode_regs = ar9003_hw_init_mode_regs;
00402         priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs;
00403 
00404         ops->config_pci_powersave = ar9003_hw_configpcipowersave;
00405 
00406         ar9003_hw_attach_phy_ops(ah);
00407         ar9003_hw_attach_calib_ops(ah);
00408         ar9003_hw_attach_mac_ops(ah);
00409 }