1 /* 2 * Copyright (c) 2008-2010 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 "ar9003_mac.h" 19 #include "ar9003_2p2_initvals.h" 20 21 /* General hardware code for the AR9003 hadware family */ 22 23 static bool ar9003_hw_macversion_supported(u32 macversion) 24 { 25 switch (macversion) { 26 case AR_SREV_VERSION_9300: 27 return true; 28 default: 29 break; 30 } 31 return false; 32 } 33 34 /* 35 * The AR9003 family uses a new INI format (pre, core, post 36 * arrays per subsystem). This provides support for the 37 * AR9003 2.2 chipsets. 38 */ 39 static void ar9003_hw_init_mode_regs(struct ath_hw *ah) 40 { 41 /* mac */ 42 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0); 43 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE], 44 ar9300_2p2_mac_core, 45 ARRAY_SIZE(ar9300_2p2_mac_core), 2); 46 INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST], 47 ar9300_2p2_mac_postamble, 48 ARRAY_SIZE(ar9300_2p2_mac_postamble), 5); 49 50 /* bb */ 51 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], NULL, 0, 0); 52 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE], 53 ar9300_2p2_baseband_core, 54 ARRAY_SIZE(ar9300_2p2_baseband_core), 2); 55 INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST], 56 ar9300_2p2_baseband_postamble, 57 ARRAY_SIZE(ar9300_2p2_baseband_postamble), 5); 58 59 /* radio */ 60 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0); 61 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE], 62 ar9300_2p2_radio_core, 63 ARRAY_SIZE(ar9300_2p2_radio_core), 2); 64 INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST], 65 ar9300_2p2_radio_postamble, 66 ARRAY_SIZE(ar9300_2p2_radio_postamble), 5); 67 68 /* soc */ 69 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE], 70 ar9300_2p2_soc_preamble, 71 ARRAY_SIZE(ar9300_2p2_soc_preamble), 2); 72 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0); 73 INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], 74 ar9300_2p2_soc_postamble, 75 ARRAY_SIZE(ar9300_2p2_soc_postamble), 5); 76 77 /* rx/tx gain */ 78 INIT_INI_ARRAY(&ah->iniModesRxGain, 79 ar9300Common_rx_gain_table_2p2, 80 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 2); 81 INIT_INI_ARRAY(&ah->iniModesTxGain, 82 ar9300Modes_lowest_ob_db_tx_gain_table_2p2, 83 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), 84 5); 85 86 /* Load PCIE SERDES settings from INI */ 87 88 /* Awake Setting */ 89 90 INIT_INI_ARRAY(&ah->iniPcieSerdes, 91 ar9300PciePhy_pll_on_clkreq_disable_L1_2p2, 92 ARRAY_SIZE(ar9300PciePhy_pll_on_clkreq_disable_L1_2p2), 93 2); 94 95 /* Sleep Setting */ 96 97 INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower, 98 ar9300PciePhy_clkreq_enable_L1_2p2, 99 ARRAY_SIZE(ar9300PciePhy_clkreq_enable_L1_2p2), 100 2); 101 102 /* Fast clock modal settings */ 103 INIT_INI_ARRAY(&ah->iniModesAdditional, 104 ar9300Modes_fast_clock_2p2, 105 ARRAY_SIZE(ar9300Modes_fast_clock_2p2), 106 3); 107 } 108 109 static void ar9003_tx_gain_table_apply(struct ath_hw *ah) 110 { 111 switch (ar9003_hw_get_tx_gain_idx(ah)) { 112 case 0: 113 default: 114 INIT_INI_ARRAY(&ah->iniModesTxGain, 115 ar9300Modes_lowest_ob_db_tx_gain_table_2p2, 116 ARRAY_SIZE(ar9300Modes_lowest_ob_db_tx_gain_table_2p2), 117 5); 118 break; 119 case 1: 120 INIT_INI_ARRAY(&ah->iniModesTxGain, 121 ar9300Modes_high_ob_db_tx_gain_table_2p2, 122 ARRAY_SIZE(ar9300Modes_high_ob_db_tx_gain_table_2p2), 123 5); 124 break; 125 case 2: 126 INIT_INI_ARRAY(&ah->iniModesTxGain, 127 ar9300Modes_low_ob_db_tx_gain_table_2p2, 128 ARRAY_SIZE(ar9300Modes_low_ob_db_tx_gain_table_2p2), 129 5); 130 break; 131 } 132 } 133 134 static void ar9003_rx_gain_table_apply(struct ath_hw *ah) 135 { 136 switch (ar9003_hw_get_rx_gain_idx(ah)) { 137 case 0: 138 default: 139 INIT_INI_ARRAY(&ah->iniModesRxGain, 140 ar9300Common_rx_gain_table_2p2, 141 ARRAY_SIZE(ar9300Common_rx_gain_table_2p2), 142 2); 143 break; 144 case 1: 145 INIT_INI_ARRAY(&ah->iniModesRxGain, 146 ar9300Common_wo_xlna_rx_gain_table_2p2, 147 ARRAY_SIZE(ar9300Common_wo_xlna_rx_gain_table_2p2), 148 2); 149 break; 150 } 151 } 152 153 /* set gain table pointers according to values read from the eeprom */ 154 static void ar9003_hw_init_mode_gain_regs(struct ath_hw *ah) 155 { 156 ar9003_tx_gain_table_apply(ah); 157 ar9003_rx_gain_table_apply(ah); 158 } 159 160 /* 161 * Helper for ASPM support. 162 * 163 * Disable PLL when in L0s as well as receiver clock when in L1. 164 * This power saving option must be enabled through the SerDes. 165 * 166 * Programming the SerDes must go through the same 288 bit serial shift 167 * register as the other analog registers. Hence the 9 writes. 168 */ 169 static void ar9003_hw_configpcipowersave(struct ath_hw *ah, 170 int restore, 171 int power_off) 172 { 173 if (ah->is_pciexpress != true) 174 return; 175 176 /* Do not touch SerDes registers */ 177 if (ah->config.pcie_powersave_enable == 2) 178 return; 179 180 /* Nothing to do on restore for 11N */ 181 if (!restore) { 182 /* set bit 19 to allow forcing of pcie core into L1 state */ 183 REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); 184 185 /* Several PCIe massages to ensure proper behaviour */ 186 if (ah->config.pcie_waen) 187 REG_WRITE(ah, AR_WA, ah->config.pcie_waen); 188 else 189 REG_WRITE(ah, AR_WA, ah->WARegVal); 190 } 191 192 /* 193 * Configire PCIE after Ini init. SERDES values now come from ini file 194 * This enables PCIe low power mode. 195 */ 196 if (ah->config.pcieSerDesWrite) { 197 unsigned int i; 198 struct ar5416IniArray *array; 199 200 array = power_off ? &ah->iniPcieSerdes : 201 &ah->iniPcieSerdesLowPower; 202 203 for (i = 0; i < array->ia_rows; i++) { 204 REG_WRITE(ah, 205 INI_RA(array, i, 0), 206 INI_RA(array, i, 1)); 207 } 208 } 209 } 210 211 /* Sets up the AR9003 hardware familiy callbacks */ 212 void ar9003_hw_attach_ops(struct ath_hw *ah) 213 { 214 struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); 215 struct ath_hw_ops *ops = ath9k_hw_ops(ah); 216 217 priv_ops->init_mode_regs = ar9003_hw_init_mode_regs; 218 priv_ops->init_mode_gain_regs = ar9003_hw_init_mode_gain_regs; 219 priv_ops->macversion_supported = ar9003_hw_macversion_supported; 220 221 ops->config_pci_powersave = ar9003_hw_configpcipowersave; 222 223 ar9003_hw_attach_phy_ops(ah); 224 ar9003_hw_attach_calib_ops(ah); 225 ar9003_hw_attach_mac_ops(ah); 226 } 227