aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-04-24 14:55:30 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-05-07 15:02:24 -0400
commit33fd503346ad86bd7470a0f8c4c3080393d14233 (patch)
tree5753cf92656fa885f80cb8cab2b8b14c4c45f085 /drivers/net
parentc031bf806fef4854b02266a4105f55ed31f2d1a8 (diff)
iwlwifi-5000: add run time calibrations for 5000
This patch adds support for run time calibrations for the 5000 family HW. Those calibrations are sensitivity calibration, and chain noise calibration. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965-commands.h31
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c101
3 files changed, 141 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 2bc7a9bfc56..cc0006900b3 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -119,6 +119,15 @@ config IWL5000
119 This option enables support for Intel Wireless WiFi Link 5000AGN Family 119 This option enables support for Intel Wireless WiFi Link 5000AGN Family
120 Dependency on 4965 is temporary 120 Dependency on 4965 is temporary
121 121
122config IWL5000_RUN_TIME_CALIB
123 bool "Enable run time Calibration for 5000 NIC"
124 select IWLWIFI_RUN_TIME_CALIB
125 depends on IWL5000
126 default y
127 ---help---
128 This option will enable run time calibration for the iwl5000 driver.
129 These calibrations are Sensitivity and Chain Noise. If unsure, say yes
130
122 131
123config IWLWIFI_DEBUGFS 132config IWLWIFI_DEBUGFS
124 bool "Iwlwifi debugfs support" 133 bool "Iwlwifi debugfs support"
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
index d0e3f35d498..a5c33f35417 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-4965-commands.h
@@ -2671,6 +2671,37 @@ struct iwl4965_calibration_cmd {
2671 u8 reserved1; 2671 u8 reserved1;
2672} __attribute__ ((packed)); 2672} __attribute__ ((packed));
2673 2673
2674/* Phy calibration command for 5000 series */
2675
2676enum {
2677 IWL5000_PHY_CALIBRATE_DC_CMD = 8,
2678 IWL5000_PHY_CALIBRATE_LO_CMD = 9,
2679 IWL5000_PHY_CALIBRATE_RX_BB_CMD = 10,
2680 IWL5000_PHY_CALIBRATE_TX_IQ_CMD = 11,
2681 IWL5000_PHY_CALIBRATE_RX_IQ_CMD = 12,
2682 IWL5000_PHY_CALIBRATION_NOISE_CMD = 13,
2683 IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
2684 IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
2685 IWL5000_PHY_CALIBRATE_BASE_BAND_CMD = 16,
2686 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
2687 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
2688};
2689
2690struct iwl5000_calibration_chain_noise_reset_cmd {
2691 u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
2692 u8 flags; /* not used */
2693 __le16 reserved;
2694} __attribute__ ((packed));
2695
2696struct iwl5000_calibration_chain_noise_gain_cmd {
2697 u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */
2698 u8 flags; /* not used */
2699 __le16 reserved;
2700 u8 delta_gain_1;
2701 u8 delta_gain_2;
2702 __le16 reserved1;
2703} __attribute__ ((packed));
2704
2674/****************************************************************************** 2705/******************************************************************************
2675 * (12) 2706 * (12)
2676 * Miscellaneous Commands: 2707 * Miscellaneous Commands:
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index 7c42bbffff5..1a18ac187cb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -125,6 +125,100 @@ static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
125 return (address & ADDRESS_MSK) + (offset << 1); 125 return (address & ADDRESS_MSK) + (offset << 1);
126} 126}
127 127
128#ifdef CONFIG_IWL5000_RUN_TIME_CALIB
129
130static void iwl5000_gain_computation(struct iwl_priv *priv,
131 u32 average_noise[NUM_RX_CHAINS],
132 u16 min_average_noise_antenna_i,
133 u32 min_average_noise)
134{
135 int i;
136 s32 delta_g;
137 struct iwl_chain_noise_data *data = &priv->chain_noise_data;
138
139 /* Find Gain Code for the antennas B and C */
140 for (i = 1; i < NUM_RX_CHAINS; i++) {
141 if ((data->disconn_array[i])) {
142 data->delta_gain_code[i] = 0;
143 continue;
144 }
145 delta_g = (1000 * ((s32)average_noise[0] -
146 (s32)average_noise[i])) / 1500;
147 /* bound gain by 2 bits value max, 3rd bit is sign */
148 data->delta_gain_code[i] =
149 min(abs(delta_g), CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
150
151 if (delta_g < 0)
152 /* set negative sign */
153 data->delta_gain_code[i] |= (1 << 2);
154 }
155
156 IWL_DEBUG_CALIB("Delta gains: ANT_B = %d ANT_C = %d\n",
157 data->delta_gain_code[1], data->delta_gain_code[2]);
158
159 if (!data->radio_write) {
160 struct iwl5000_calibration_chain_noise_gain_cmd cmd;
161 memset(&cmd, 0, sizeof(cmd));
162
163 cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD;
164 cmd.delta_gain_1 = data->delta_gain_code[1];
165 cmd.delta_gain_2 = data->delta_gain_code[2];
166 iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD,
167 sizeof(cmd), &cmd, NULL);
168
169 data->radio_write = 1;
170 data->state = IWL_CHAIN_NOISE_CALIBRATED;
171 }
172
173 data->chain_noise_a = 0;
174 data->chain_noise_b = 0;
175 data->chain_noise_c = 0;
176 data->chain_signal_a = 0;
177 data->chain_signal_b = 0;
178 data->chain_signal_c = 0;
179 data->beacon_count = 0;
180}
181
182static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
183{
184 struct iwl_chain_noise_data *data = &priv->chain_noise_data;
185
186 if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) {
187 struct iwl5000_calibration_chain_noise_reset_cmd cmd;
188
189 memset(&cmd, 0, sizeof(cmd));
190 cmd.op_code = IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD;
191 if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
192 sizeof(cmd), &cmd))
193 IWL_ERROR("Could not send REPLY_PHY_CALIBRATION_CMD\n");
194 data->state = IWL_CHAIN_NOISE_ACCUMULATE;
195 IWL_DEBUG_CALIB("Run chain_noise_calibrate\n");
196 }
197}
198
199static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
200 .min_nrg_cck = 95,
201 .max_nrg_cck = 0,
202 .auto_corr_min_ofdm = 90,
203 .auto_corr_min_ofdm_mrc = 170,
204 .auto_corr_min_ofdm_x1 = 120,
205 .auto_corr_min_ofdm_mrc_x1 = 240,
206
207 .auto_corr_max_ofdm = 120,
208 .auto_corr_max_ofdm_mrc = 210,
209 .auto_corr_max_ofdm_x1 = 155,
210 .auto_corr_max_ofdm_mrc_x1 = 290,
211
212 .auto_corr_min_cck = 125,
213 .auto_corr_max_cck = 200,
214 .auto_corr_min_cck_mrc = 170,
215 .auto_corr_max_cck_mrc = 400,
216 .nrg_th_cck = 95,
217 .nrg_th_ofdm = 95,
218};
219
220#endif /* CONFIG_IWL5000_RUN_TIME_CALIB */
221
128static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, 222static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
129 size_t offset) 223 size_t offset)
130{ 224{
@@ -159,6 +253,9 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
159 priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; 253 priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
160 priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) | 254 priv->hw_params.fat_channel = BIT(IEEE80211_BAND_2GHZ) |
161 BIT(IEEE80211_BAND_5GHZ); 255 BIT(IEEE80211_BAND_5GHZ);
256#ifdef CONFIG_IWL5000_RUN_TIME_CALIB
257 priv->hw_params.sens = &iwl5000_sensitivity;
258#endif
162 259
163 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { 260 switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) {
164 case CSR_HW_REV_TYPE_5100: 261 case CSR_HW_REV_TYPE_5100:
@@ -202,6 +299,10 @@ static struct iwl_hcmd_ops iwl5000_hcmd = {
202}; 299};
203 300
204static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { 301static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
302#ifdef CONFIG_IWL5000_RUN_TIME_CALIB
303 .gain_computation = iwl5000_gain_computation,
304 .chain_noise_reset = iwl5000_chain_noise_reset,
305#endif
205}; 306};
206 307
207static struct iwl_lib_ops iwl5000_lib = { 308static struct iwl_lib_ops iwl5000_lib = {