Commit | Line | Data |
---|---|---|
e9676695 JB |
1 | /****************************************************************************** |
2 | * | |
51368bf7 | 3 | * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. |
e9676695 JB |
4 | * |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
12 | * more details. | |
13 | * | |
14 | * You should have received a copy of the GNU General Public License along with | |
15 | * this program; if not, write to the Free Software Foundation, Inc., | |
16 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA | |
17 | * | |
18 | * The full GNU General Public License is included in this distribution in the | |
19 | * file called LICENSE. | |
20 | * | |
21 | * Contact Information: | |
22 | * Intel Linux Wireless <ilw@linux.intel.com> | |
23 | * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | |
24 | * | |
25 | *****************************************************************************/ | |
26 | ||
27 | /* | |
28 | * DVM device-specific data & functions | |
29 | */ | |
e9676695 JB |
30 | #include "iwl-io.h" |
31 | #include "iwl-prph.h" | |
26a7ca9a | 32 | #include "iwl-eeprom-parse.h" |
e9676695 | 33 | |
1023fdc4 JB |
34 | #include "agn.h" |
35 | #include "dev.h" | |
36 | #include "commands.h" | |
37 | ||
26a7ca9a | 38 | |
e9676695 JB |
39 | /* |
40 | * 1000 series | |
41 | * =========== | |
42 | */ | |
43 | ||
44 | /* | |
45 | * For 1000, use advance thermal throttling critical temperature threshold, | |
46 | * but legacy thermal management implementation for now. | |
47 | * This is for the reason of 1000 uCode using advance thermal throttling API | |
48 | * but not implement ct_kill_exit based on ct_kill exit temperature | |
49 | * so the thermal throttling will still based on legacy thermal throttling | |
50 | * management. | |
51 | * The code here need to be modified once 1000 uCode has the advanced thermal | |
52 | * throttling algorithm in place | |
53 | */ | |
54 | static void iwl1000_set_ct_threshold(struct iwl_priv *priv) | |
55 | { | |
56 | /* want Celsius */ | |
57 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | |
58 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | |
59 | } | |
60 | ||
61 | /* NIC configuration for 1000 series */ | |
62 | static void iwl1000_nic_config(struct iwl_priv *priv) | |
63 | { | |
e9676695 JB |
64 | /* Setting digital SVR for 1000 card to 1.32V */ |
65 | /* locking is acquired in iwl_set_bits_mask_prph() function */ | |
68e8dfda | 66 | iwl_set_bits_mask_prph(priv->trans, APMG_DIGITAL_SVR_REG, |
e9676695 JB |
67 | APMG_SVR_DIGITAL_VOLTAGE_1_32, |
68 | ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); | |
69 | } | |
70 | ||
e381b214 MV |
71 | /** |
72 | * iwl_beacon_time_mask_low - mask of lower 32 bit of beacon time | |
73 | * @priv -- pointer to iwl_priv data structure | |
74 | * @tsf_bits -- number of bits need to shift for masking) | |
75 | */ | |
76 | static inline u32 iwl_beacon_time_mask_low(struct iwl_priv *priv, | |
77 | u16 tsf_bits) | |
78 | { | |
79 | return (1 << tsf_bits) - 1; | |
80 | } | |
81 | ||
82 | /** | |
83 | * iwl_beacon_time_mask_high - mask of higher 32 bit of beacon time | |
84 | * @priv -- pointer to iwl_priv data structure | |
85 | * @tsf_bits -- number of bits need to shift for masking) | |
86 | */ | |
87 | static inline u32 iwl_beacon_time_mask_high(struct iwl_priv *priv, | |
88 | u16 tsf_bits) | |
89 | { | |
90 | return ((1 << (32 - tsf_bits)) - 1) << tsf_bits; | |
91 | } | |
92 | ||
93 | /* | |
94 | * extended beacon time format | |
95 | * time in usec will be changed into a 32-bit value in extended:internal format | |
96 | * the extended part is the beacon counts | |
97 | * the internal part is the time in usec within one beacon interval | |
98 | */ | |
99 | static u32 iwl_usecs_to_beacons(struct iwl_priv *priv, u32 usec, | |
100 | u32 beacon_interval) | |
101 | { | |
102 | u32 quot; | |
103 | u32 rem; | |
104 | u32 interval = beacon_interval * TIME_UNIT; | |
105 | ||
106 | if (!interval || !usec) | |
107 | return 0; | |
108 | ||
109 | quot = (usec / interval) & | |
110 | (iwl_beacon_time_mask_high(priv, IWLAGN_EXT_BEACON_TIME_POS) >> | |
111 | IWLAGN_EXT_BEACON_TIME_POS); | |
112 | rem = (usec % interval) & iwl_beacon_time_mask_low(priv, | |
113 | IWLAGN_EXT_BEACON_TIME_POS); | |
114 | ||
115 | return (quot << IWLAGN_EXT_BEACON_TIME_POS) + rem; | |
116 | } | |
117 | ||
118 | /* base is usually what we get from ucode with each received frame, | |
119 | * the same as HW timer counter counting down | |
120 | */ | |
121 | static __le32 iwl_add_beacon_time(struct iwl_priv *priv, u32 base, | |
122 | u32 addon, u32 beacon_interval) | |
123 | { | |
124 | u32 base_low = base & iwl_beacon_time_mask_low(priv, | |
125 | IWLAGN_EXT_BEACON_TIME_POS); | |
126 | u32 addon_low = addon & iwl_beacon_time_mask_low(priv, | |
127 | IWLAGN_EXT_BEACON_TIME_POS); | |
128 | u32 interval = beacon_interval * TIME_UNIT; | |
129 | u32 res = (base & iwl_beacon_time_mask_high(priv, | |
130 | IWLAGN_EXT_BEACON_TIME_POS)) + | |
131 | (addon & iwl_beacon_time_mask_high(priv, | |
132 | IWLAGN_EXT_BEACON_TIME_POS)); | |
133 | ||
134 | if (base_low > addon_low) | |
135 | res += base_low - addon_low; | |
136 | else if (base_low < addon_low) { | |
137 | res += interval + base_low - addon_low; | |
138 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | |
139 | } else | |
140 | res += (1 << IWLAGN_EXT_BEACON_TIME_POS); | |
141 | ||
142 | return cpu_to_le32(res); | |
143 | } | |
144 | ||
e9676695 JB |
145 | static const struct iwl_sensitivity_ranges iwl1000_sensitivity = { |
146 | .min_nrg_cck = 95, | |
147 | .auto_corr_min_ofdm = 90, | |
148 | .auto_corr_min_ofdm_mrc = 170, | |
149 | .auto_corr_min_ofdm_x1 = 120, | |
150 | .auto_corr_min_ofdm_mrc_x1 = 240, | |
151 | ||
152 | .auto_corr_max_ofdm = 120, | |
153 | .auto_corr_max_ofdm_mrc = 210, | |
154 | .auto_corr_max_ofdm_x1 = 155, | |
155 | .auto_corr_max_ofdm_mrc_x1 = 290, | |
156 | ||
157 | .auto_corr_min_cck = 125, | |
158 | .auto_corr_max_cck = 200, | |
159 | .auto_corr_min_cck_mrc = 170, | |
160 | .auto_corr_max_cck_mrc = 400, | |
161 | .nrg_th_cck = 95, | |
162 | .nrg_th_ofdm = 95, | |
163 | ||
164 | .barker_corr_th_min = 190, | |
165 | .barker_corr_th_min_mrc = 390, | |
166 | .nrg_th_cca = 62, | |
167 | }; | |
168 | ||
169 | static void iwl1000_hw_set_hw_params(struct iwl_priv *priv) | |
170 | { | |
e9676695 JB |
171 | iwl1000_set_ct_threshold(priv); |
172 | ||
173 | /* Set initial sensitivity parameters */ | |
174 | priv->hw_params.sens = &iwl1000_sensitivity; | |
175 | } | |
176 | ||
129219c0 | 177 | const struct iwl_dvm_cfg iwl_dvm_1000_cfg = { |
e9676695 JB |
178 | .set_hw_params = iwl1000_hw_set_hw_params, |
179 | .nic_config = iwl1000_nic_config, | |
e9676695 | 180 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
181 | .support_ct_kill_exit = true, |
182 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF, | |
183 | .chain_noise_scale = 1000, | |
e9676695 JB |
184 | }; |
185 | ||
186 | ||
187 | /* | |
188 | * 2000 series | |
189 | * =========== | |
190 | */ | |
191 | ||
192 | static void iwl2000_set_ct_threshold(struct iwl_priv *priv) | |
193 | { | |
194 | /* want Celsius */ | |
195 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | |
196 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | |
197 | } | |
198 | ||
199 | /* NIC configuration for 2000 series */ | |
200 | static void iwl2000_nic_config(struct iwl_priv *priv) | |
201 | { | |
68e8dfda | 202 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
e9676695 JB |
203 | CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER); |
204 | } | |
205 | ||
206 | static const struct iwl_sensitivity_ranges iwl2000_sensitivity = { | |
207 | .min_nrg_cck = 97, | |
208 | .auto_corr_min_ofdm = 80, | |
209 | .auto_corr_min_ofdm_mrc = 128, | |
210 | .auto_corr_min_ofdm_x1 = 105, | |
211 | .auto_corr_min_ofdm_mrc_x1 = 192, | |
212 | ||
213 | .auto_corr_max_ofdm = 145, | |
214 | .auto_corr_max_ofdm_mrc = 232, | |
215 | .auto_corr_max_ofdm_x1 = 110, | |
216 | .auto_corr_max_ofdm_mrc_x1 = 232, | |
217 | ||
218 | .auto_corr_min_cck = 125, | |
219 | .auto_corr_max_cck = 175, | |
220 | .auto_corr_min_cck_mrc = 160, | |
221 | .auto_corr_max_cck_mrc = 310, | |
222 | .nrg_th_cck = 97, | |
223 | .nrg_th_ofdm = 100, | |
224 | ||
225 | .barker_corr_th_min = 190, | |
226 | .barker_corr_th_min_mrc = 390, | |
227 | .nrg_th_cca = 62, | |
228 | }; | |
229 | ||
230 | static void iwl2000_hw_set_hw_params(struct iwl_priv *priv) | |
231 | { | |
e9676695 JB |
232 | iwl2000_set_ct_threshold(priv); |
233 | ||
234 | /* Set initial sensitivity parameters */ | |
235 | priv->hw_params.sens = &iwl2000_sensitivity; | |
236 | } | |
237 | ||
129219c0 | 238 | const struct iwl_dvm_cfg iwl_dvm_2000_cfg = { |
e9676695 JB |
239 | .set_hw_params = iwl2000_hw_set_hw_params, |
240 | .nic_config = iwl2000_nic_config, | |
e9676695 | 241 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
242 | .adv_thermal_throttle = true, |
243 | .support_ct_kill_exit = true, | |
244 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
245 | .chain_noise_scale = 1000, | |
246 | .hd_v2 = true, | |
247 | .need_temp_offset_calib = true, | |
248 | .temp_offset_v2 = true, | |
249 | }; | |
250 | ||
129219c0 | 251 | const struct iwl_dvm_cfg iwl_dvm_105_cfg = { |
0d8877a1 JB |
252 | .set_hw_params = iwl2000_hw_set_hw_params, |
253 | .nic_config = iwl2000_nic_config, | |
254 | .temperature = iwlagn_temperature, | |
255 | .adv_thermal_throttle = true, | |
256 | .support_ct_kill_exit = true, | |
257 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
258 | .chain_noise_scale = 1000, | |
259 | .hd_v2 = true, | |
260 | .need_temp_offset_calib = true, | |
261 | .temp_offset_v2 = true, | |
262 | .adv_pm = true, | |
263 | }; | |
264 | ||
265 | static const struct iwl_dvm_bt_params iwl2030_bt_params = { | |
266 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | |
267 | .advanced_bt_coexist = true, | |
268 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | |
269 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | |
270 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT32, | |
271 | .bt_sco_disable = true, | |
272 | .bt_session_2 = true, | |
e9676695 JB |
273 | }; |
274 | ||
129219c0 | 275 | const struct iwl_dvm_cfg iwl_dvm_2030_cfg = { |
e9676695 JB |
276 | .set_hw_params = iwl2000_hw_set_hw_params, |
277 | .nic_config = iwl2000_nic_config, | |
e9676695 | 278 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
279 | .adv_thermal_throttle = true, |
280 | .support_ct_kill_exit = true, | |
281 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
282 | .chain_noise_scale = 1000, | |
283 | .hd_v2 = true, | |
284 | .bt_params = &iwl2030_bt_params, | |
285 | .need_temp_offset_calib = true, | |
286 | .temp_offset_v2 = true, | |
287 | .adv_pm = true, | |
e9676695 JB |
288 | }; |
289 | ||
290 | /* | |
291 | * 5000 series | |
292 | * =========== | |
293 | */ | |
294 | ||
295 | /* NIC configuration for 5000 series */ | |
e9676695 JB |
296 | static const struct iwl_sensitivity_ranges iwl5000_sensitivity = { |
297 | .min_nrg_cck = 100, | |
298 | .auto_corr_min_ofdm = 90, | |
299 | .auto_corr_min_ofdm_mrc = 170, | |
300 | .auto_corr_min_ofdm_x1 = 105, | |
301 | .auto_corr_min_ofdm_mrc_x1 = 220, | |
302 | ||
303 | .auto_corr_max_ofdm = 120, | |
304 | .auto_corr_max_ofdm_mrc = 210, | |
305 | .auto_corr_max_ofdm_x1 = 120, | |
306 | .auto_corr_max_ofdm_mrc_x1 = 240, | |
307 | ||
308 | .auto_corr_min_cck = 125, | |
309 | .auto_corr_max_cck = 200, | |
310 | .auto_corr_min_cck_mrc = 200, | |
311 | .auto_corr_max_cck_mrc = 400, | |
312 | .nrg_th_cck = 100, | |
313 | .nrg_th_ofdm = 100, | |
314 | ||
315 | .barker_corr_th_min = 190, | |
316 | .barker_corr_th_min_mrc = 390, | |
317 | .nrg_th_cca = 62, | |
318 | }; | |
319 | ||
e5209263 | 320 | static const struct iwl_sensitivity_ranges iwl5150_sensitivity = { |
e9676695 JB |
321 | .min_nrg_cck = 95, |
322 | .auto_corr_min_ofdm = 90, | |
323 | .auto_corr_min_ofdm_mrc = 170, | |
324 | .auto_corr_min_ofdm_x1 = 105, | |
325 | .auto_corr_min_ofdm_mrc_x1 = 220, | |
326 | ||
327 | .auto_corr_max_ofdm = 120, | |
328 | .auto_corr_max_ofdm_mrc = 210, | |
329 | /* max = min for performance bug in 5150 DSP */ | |
330 | .auto_corr_max_ofdm_x1 = 105, | |
331 | .auto_corr_max_ofdm_mrc_x1 = 220, | |
332 | ||
333 | .auto_corr_min_cck = 125, | |
334 | .auto_corr_max_cck = 200, | |
335 | .auto_corr_min_cck_mrc = 170, | |
336 | .auto_corr_max_cck_mrc = 400, | |
337 | .nrg_th_cck = 95, | |
338 | .nrg_th_ofdm = 95, | |
339 | ||
340 | .barker_corr_th_min = 190, | |
341 | .barker_corr_th_min_mrc = 390, | |
342 | .nrg_th_cca = 62, | |
343 | }; | |
344 | ||
345 | #define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) | |
346 | ||
347 | static s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) | |
348 | { | |
349 | u16 temperature, voltage; | |
e9676695 | 350 | |
b7998c8b EL |
351 | temperature = le16_to_cpu(priv->nvm_data->kelvin_temperature); |
352 | voltage = le16_to_cpu(priv->nvm_data->kelvin_voltage); | |
e9676695 JB |
353 | |
354 | /* offset = temp - volt / coeff */ | |
355 | return (s32)(temperature - | |
356 | voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); | |
357 | } | |
358 | ||
359 | static void iwl5150_set_ct_threshold(struct iwl_priv *priv) | |
360 | { | |
361 | const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; | |
362 | s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - | |
363 | iwl_temp_calib_to_offset(priv); | |
364 | ||
365 | priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; | |
366 | } | |
367 | ||
368 | static void iwl5000_set_ct_threshold(struct iwl_priv *priv) | |
369 | { | |
370 | /* want Celsius */ | |
371 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; | |
372 | } | |
373 | ||
374 | static void iwl5000_hw_set_hw_params(struct iwl_priv *priv) | |
375 | { | |
e9676695 JB |
376 | iwl5000_set_ct_threshold(priv); |
377 | ||
378 | /* Set initial sensitivity parameters */ | |
379 | priv->hw_params.sens = &iwl5000_sensitivity; | |
380 | } | |
381 | ||
382 | static void iwl5150_hw_set_hw_params(struct iwl_priv *priv) | |
383 | { | |
e9676695 JB |
384 | iwl5150_set_ct_threshold(priv); |
385 | ||
386 | /* Set initial sensitivity parameters */ | |
387 | priv->hw_params.sens = &iwl5150_sensitivity; | |
388 | } | |
389 | ||
390 | static void iwl5150_temperature(struct iwl_priv *priv) | |
391 | { | |
392 | u32 vt = 0; | |
393 | s32 offset = iwl_temp_calib_to_offset(priv); | |
394 | ||
395 | vt = le32_to_cpu(priv->statistics.common.temperature); | |
396 | vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; | |
397 | /* now vt hold the temperature in Kelvin */ | |
398 | priv->temperature = KELVIN_TO_CELSIUS(vt); | |
399 | iwl_tt_handler(priv); | |
400 | } | |
401 | ||
402 | static int iwl5000_hw_channel_switch(struct iwl_priv *priv, | |
403 | struct ieee80211_channel_switch *ch_switch) | |
404 | { | |
405 | /* | |
406 | * MULTI-FIXME | |
407 | * See iwlagn_mac_channel_switch. | |
408 | */ | |
409 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | |
410 | struct iwl5000_channel_switch_cmd cmd; | |
e9676695 JB |
411 | u32 switch_time_in_usec, ucode_switch_time; |
412 | u16 ch; | |
413 | u32 tsf_low; | |
414 | u8 switch_count; | |
415 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | |
416 | struct ieee80211_vif *vif = ctx->vif; | |
417 | struct iwl_host_cmd hcmd = { | |
418 | .id = REPLY_CHANNEL_SWITCH, | |
419 | .len = { sizeof(cmd), }, | |
e9676695 JB |
420 | .data = { &cmd, }, |
421 | }; | |
422 | ||
423 | cmd.band = priv->band == IEEE80211_BAND_2GHZ; | |
85220d71 | 424 | ch = ch_switch->chandef.chan->hw_value; |
e9676695 JB |
425 | IWL_DEBUG_11H(priv, "channel switch from %d to %d\n", |
426 | ctx->active.channel, ch); | |
427 | cmd.channel = cpu_to_le16(ch); | |
428 | cmd.rxon_flags = ctx->staging.flags; | |
429 | cmd.rxon_filter_flags = ctx->staging.filter_flags; | |
430 | switch_count = ch_switch->count; | |
431 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | |
432 | /* | |
433 | * calculate the ucode channel switch time | |
434 | * adding TSF as one of the factor for when to switch | |
435 | */ | |
436 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | |
437 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | |
438 | beacon_interval)) { | |
439 | switch_count -= (priv->ucode_beacon_time - | |
440 | tsf_low) / beacon_interval; | |
441 | } else | |
442 | switch_count = 0; | |
443 | } | |
444 | if (switch_count <= 1) | |
445 | cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); | |
446 | else { | |
447 | switch_time_in_usec = | |
448 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | |
449 | ucode_switch_time = iwl_usecs_to_beacons(priv, | |
450 | switch_time_in_usec, | |
451 | beacon_interval); | |
452 | cmd.switch_time = iwl_add_beacon_time(priv, | |
453 | priv->ucode_beacon_time, | |
454 | ucode_switch_time, | |
455 | beacon_interval); | |
456 | } | |
457 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | |
458 | cmd.switch_time); | |
85220d71 JB |
459 | cmd.expect_beacon = |
460 | ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR; | |
e9676695 JB |
461 | |
462 | return iwl_dvm_send_cmd(priv, &hcmd); | |
463 | } | |
464 | ||
129219c0 | 465 | const struct iwl_dvm_cfg iwl_dvm_5000_cfg = { |
e9676695 JB |
466 | .set_hw_params = iwl5000_hw_set_hw_params, |
467 | .set_channel_switch = iwl5000_hw_channel_switch, | |
e9676695 | 468 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
469 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
470 | .chain_noise_scale = 1000, | |
471 | .no_idle_support = true, | |
e9676695 JB |
472 | }; |
473 | ||
129219c0 | 474 | const struct iwl_dvm_cfg iwl_dvm_5150_cfg = { |
e9676695 JB |
475 | .set_hw_params = iwl5150_hw_set_hw_params, |
476 | .set_channel_switch = iwl5000_hw_channel_switch, | |
e9676695 | 477 | .temperature = iwl5150_temperature, |
0d8877a1 JB |
478 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF, |
479 | .chain_noise_scale = 1000, | |
480 | .no_idle_support = true, | |
481 | .no_xtal_calib = true, | |
e9676695 JB |
482 | }; |
483 | ||
484 | ||
485 | ||
486 | /* | |
487 | * 6000 series | |
488 | * =========== | |
489 | */ | |
490 | ||
491 | static void iwl6000_set_ct_threshold(struct iwl_priv *priv) | |
492 | { | |
493 | /* want Celsius */ | |
494 | priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; | |
495 | priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; | |
496 | } | |
497 | ||
498 | /* NIC configuration for 6000 series */ | |
499 | static void iwl6000_nic_config(struct iwl_priv *priv) | |
500 | { | |
2152268f | 501 | switch (priv->cfg->device_family) { |
e9676695 JB |
502 | case IWL_DEVICE_FAMILY_6005: |
503 | case IWL_DEVICE_FAMILY_6030: | |
504 | case IWL_DEVICE_FAMILY_6000: | |
505 | break; | |
506 | case IWL_DEVICE_FAMILY_6000i: | |
507 | /* 2x2 IPA phy type */ | |
68e8dfda | 508 | iwl_write32(priv->trans, CSR_GP_DRIVER_REG, |
e9676695 JB |
509 | CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); |
510 | break; | |
511 | case IWL_DEVICE_FAMILY_6050: | |
512 | /* Indicate calibration version to uCode. */ | |
b7998c8b | 513 | if (priv->nvm_data->calib_version >= 6) |
68e8dfda | 514 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
e9676695 JB |
515 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
516 | break; | |
517 | case IWL_DEVICE_FAMILY_6150: | |
518 | /* Indicate calibration version to uCode. */ | |
b7998c8b | 519 | if (priv->nvm_data->calib_version >= 6) |
68e8dfda | 520 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
e9676695 | 521 | CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6); |
68e8dfda | 522 | iwl_set_bit(priv->trans, CSR_GP_DRIVER_REG, |
e9676695 JB |
523 | CSR_GP_DRIVER_REG_BIT_6050_1x2); |
524 | break; | |
525 | default: | |
526 | WARN_ON(1); | |
527 | } | |
528 | } | |
529 | ||
530 | static const struct iwl_sensitivity_ranges iwl6000_sensitivity = { | |
531 | .min_nrg_cck = 110, | |
532 | .auto_corr_min_ofdm = 80, | |
533 | .auto_corr_min_ofdm_mrc = 128, | |
534 | .auto_corr_min_ofdm_x1 = 105, | |
535 | .auto_corr_min_ofdm_mrc_x1 = 192, | |
536 | ||
537 | .auto_corr_max_ofdm = 145, | |
538 | .auto_corr_max_ofdm_mrc = 232, | |
539 | .auto_corr_max_ofdm_x1 = 110, | |
540 | .auto_corr_max_ofdm_mrc_x1 = 232, | |
541 | ||
542 | .auto_corr_min_cck = 125, | |
543 | .auto_corr_max_cck = 175, | |
544 | .auto_corr_min_cck_mrc = 160, | |
545 | .auto_corr_max_cck_mrc = 310, | |
546 | .nrg_th_cck = 110, | |
547 | .nrg_th_ofdm = 110, | |
548 | ||
549 | .barker_corr_th_min = 190, | |
550 | .barker_corr_th_min_mrc = 336, | |
551 | .nrg_th_cca = 62, | |
552 | }; | |
553 | ||
554 | static void iwl6000_hw_set_hw_params(struct iwl_priv *priv) | |
555 | { | |
e9676695 JB |
556 | iwl6000_set_ct_threshold(priv); |
557 | ||
558 | /* Set initial sensitivity parameters */ | |
559 | priv->hw_params.sens = &iwl6000_sensitivity; | |
560 | ||
561 | } | |
562 | ||
563 | static int iwl6000_hw_channel_switch(struct iwl_priv *priv, | |
564 | struct ieee80211_channel_switch *ch_switch) | |
565 | { | |
566 | /* | |
567 | * MULTI-FIXME | |
568 | * See iwlagn_mac_channel_switch. | |
569 | */ | |
570 | struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS]; | |
8f7b8db6 | 571 | struct iwl6000_channel_switch_cmd *cmd; |
e9676695 JB |
572 | u32 switch_time_in_usec, ucode_switch_time; |
573 | u16 ch; | |
574 | u32 tsf_low; | |
575 | u8 switch_count; | |
576 | u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval); | |
577 | struct ieee80211_vif *vif = ctx->vif; | |
578 | struct iwl_host_cmd hcmd = { | |
579 | .id = REPLY_CHANNEL_SWITCH, | |
8f7b8db6 | 580 | .len = { sizeof(*cmd), }, |
8f7b8db6 | 581 | .dataflags[0] = IWL_HCMD_DFL_NOCOPY, |
e9676695 | 582 | }; |
8f7b8db6 | 583 | int err; |
e9676695 | 584 | |
8f7b8db6 JB |
585 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
586 | if (!cmd) | |
587 | return -ENOMEM; | |
588 | ||
589 | hcmd.data[0] = cmd; | |
590 | ||
591 | cmd->band = priv->band == IEEE80211_BAND_2GHZ; | |
85220d71 | 592 | ch = ch_switch->chandef.chan->hw_value; |
e9676695 JB |
593 | IWL_DEBUG_11H(priv, "channel switch from %u to %u\n", |
594 | ctx->active.channel, ch); | |
8f7b8db6 JB |
595 | cmd->channel = cpu_to_le16(ch); |
596 | cmd->rxon_flags = ctx->staging.flags; | |
597 | cmd->rxon_filter_flags = ctx->staging.filter_flags; | |
e9676695 JB |
598 | switch_count = ch_switch->count; |
599 | tsf_low = ch_switch->timestamp & 0x0ffffffff; | |
600 | /* | |
601 | * calculate the ucode channel switch time | |
602 | * adding TSF as one of the factor for when to switch | |
603 | */ | |
604 | if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) { | |
605 | if (switch_count > ((priv->ucode_beacon_time - tsf_low) / | |
606 | beacon_interval)) { | |
607 | switch_count -= (priv->ucode_beacon_time - | |
608 | tsf_low) / beacon_interval; | |
609 | } else | |
610 | switch_count = 0; | |
611 | } | |
612 | if (switch_count <= 1) | |
8f7b8db6 | 613 | cmd->switch_time = cpu_to_le32(priv->ucode_beacon_time); |
e9676695 JB |
614 | else { |
615 | switch_time_in_usec = | |
616 | vif->bss_conf.beacon_int * switch_count * TIME_UNIT; | |
617 | ucode_switch_time = iwl_usecs_to_beacons(priv, | |
618 | switch_time_in_usec, | |
619 | beacon_interval); | |
8f7b8db6 JB |
620 | cmd->switch_time = iwl_add_beacon_time(priv, |
621 | priv->ucode_beacon_time, | |
622 | ucode_switch_time, | |
623 | beacon_interval); | |
e9676695 JB |
624 | } |
625 | IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n", | |
8f7b8db6 | 626 | cmd->switch_time); |
85220d71 JB |
627 | cmd->expect_beacon = |
628 | ch_switch->chandef.chan->flags & IEEE80211_CHAN_RADAR; | |
e9676695 | 629 | |
8f7b8db6 JB |
630 | err = iwl_dvm_send_cmd(priv, &hcmd); |
631 | kfree(cmd); | |
632 | return err; | |
e9676695 JB |
633 | } |
634 | ||
129219c0 | 635 | const struct iwl_dvm_cfg iwl_dvm_6000_cfg = { |
e9676695 JB |
636 | .set_hw_params = iwl6000_hw_set_hw_params, |
637 | .set_channel_switch = iwl6000_hw_channel_switch, | |
638 | .nic_config = iwl6000_nic_config, | |
e9676695 | 639 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
640 | .adv_thermal_throttle = true, |
641 | .support_ct_kill_exit = true, | |
642 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
643 | .chain_noise_scale = 1000, | |
644 | }; | |
645 | ||
646 | const struct iwl_dvm_cfg iwl_dvm_6005_cfg = { | |
647 | .set_hw_params = iwl6000_hw_set_hw_params, | |
648 | .set_channel_switch = iwl6000_hw_channel_switch, | |
649 | .nic_config = iwl6000_nic_config, | |
650 | .temperature = iwlagn_temperature, | |
651 | .adv_thermal_throttle = true, | |
652 | .support_ct_kill_exit = true, | |
653 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
654 | .chain_noise_scale = 1000, | |
655 | .need_temp_offset_calib = true, | |
656 | }; | |
657 | ||
129219c0 | 658 | const struct iwl_dvm_cfg iwl_dvm_6050_cfg = { |
0d8877a1 JB |
659 | .set_hw_params = iwl6000_hw_set_hw_params, |
660 | .set_channel_switch = iwl6000_hw_channel_switch, | |
661 | .nic_config = iwl6000_nic_config, | |
662 | .temperature = iwlagn_temperature, | |
663 | .adv_thermal_throttle = true, | |
664 | .support_ct_kill_exit = true, | |
665 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
666 | .chain_noise_scale = 1500, | |
667 | }; | |
668 | ||
669 | static const struct iwl_dvm_bt_params iwl6000_bt_params = { | |
670 | /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ | |
671 | .advanced_bt_coexist = true, | |
672 | .agg_time_limit = BT_AGG_THRESHOLD_DEF, | |
673 | .bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE, | |
674 | .bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT, | |
675 | .bt_sco_disable = true, | |
e9676695 JB |
676 | }; |
677 | ||
129219c0 | 678 | const struct iwl_dvm_cfg iwl_dvm_6030_cfg = { |
e9676695 JB |
679 | .set_hw_params = iwl6000_hw_set_hw_params, |
680 | .set_channel_switch = iwl6000_hw_channel_switch, | |
681 | .nic_config = iwl6000_nic_config, | |
e9676695 | 682 | .temperature = iwlagn_temperature, |
0d8877a1 JB |
683 | .adv_thermal_throttle = true, |
684 | .support_ct_kill_exit = true, | |
685 | .plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF, | |
686 | .chain_noise_scale = 1000, | |
687 | .bt_params = &iwl6000_bt_params, | |
688 | .need_temp_offset_calib = true, | |
689 | .adv_pm = true, | |
e9676695 | 690 | }; |