iwl-5000.c revision 706c4ff67cb86134a3a93413a595a7c5559b7cc2
1/******************************************************************************
2 *
3 * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
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#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/init.h>
30#include <linux/delay.h>
31#include <linux/sched.h>
32#include <linux/skbuff.h>
33#include <linux/netdevice.h>
34#include <net/mac80211.h>
35#include <linux/etherdevice.h>
36#include <asm/unaligned.h>
37#include <linux/stringify.h>
38
39#include "iwl-eeprom.h"
40#include "iwl-dev.h"
41#include "iwl-core.h"
42#include "iwl-io.h"
43#include "iwl-agn.h"
44#include "iwl-agn-hw.h"
45#include "iwl-trans.h"
46#include "iwl-shared.h"
47#include "iwl-cfg.h"
48
49/* Highest firmware API version supported */
50#define IWL5000_UCODE_API_MAX 5
51#define IWL5150_UCODE_API_MAX 2
52
53/* Lowest firmware API version supported */
54#define IWL5000_UCODE_API_MIN 1
55#define IWL5150_UCODE_API_MIN 1
56
57#define IWL5000_FW_PRE "iwlwifi-5000-"
58#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE __stringify(api) ".ucode"
59
60#define IWL5150_FW_PRE "iwlwifi-5150-"
61#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE __stringify(api) ".ucode"
62
63/* NIC configuration for 5000 series */
64static void iwl5000_nic_config(struct iwl_priv *priv)
65{
66	iwl_rf_config(priv);
67
68	/* W/A : NIC is stuck in a reset state after Early PCIe power off
69	 * (PCIe power is lost before PERST# is asserted),
70	 * causing ME FW to lose ownership and not being able to obtain it back.
71	 */
72	iwl_set_bits_mask_prph(trans(priv), APMG_PS_CTRL_REG,
73				APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
74				~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);
75}
76
77static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
78	.min_nrg_cck = 100,
79	.max_nrg_cck = 0, /* not used, set to 0 */
80	.auto_corr_min_ofdm = 90,
81	.auto_corr_min_ofdm_mrc = 170,
82	.auto_corr_min_ofdm_x1 = 105,
83	.auto_corr_min_ofdm_mrc_x1 = 220,
84
85	.auto_corr_max_ofdm = 120,
86	.auto_corr_max_ofdm_mrc = 210,
87	.auto_corr_max_ofdm_x1 = 120,
88	.auto_corr_max_ofdm_mrc_x1 = 240,
89
90	.auto_corr_min_cck = 125,
91	.auto_corr_max_cck = 200,
92	.auto_corr_min_cck_mrc = 200,
93	.auto_corr_max_cck_mrc = 400,
94	.nrg_th_cck = 100,
95	.nrg_th_ofdm = 100,
96
97	.barker_corr_th_min = 190,
98	.barker_corr_th_min_mrc = 390,
99	.nrg_th_cca = 62,
100};
101
102static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
103	.min_nrg_cck = 95,
104	.max_nrg_cck = 0, /* not used, set to 0 */
105	.auto_corr_min_ofdm = 90,
106	.auto_corr_min_ofdm_mrc = 170,
107	.auto_corr_min_ofdm_x1 = 105,
108	.auto_corr_min_ofdm_mrc_x1 = 220,
109
110	.auto_corr_max_ofdm = 120,
111	.auto_corr_max_ofdm_mrc = 210,
112	/* max = min for performance bug in 5150 DSP */
113	.auto_corr_max_ofdm_x1 = 105,
114	.auto_corr_max_ofdm_mrc_x1 = 220,
115
116	.auto_corr_min_cck = 125,
117	.auto_corr_max_cck = 200,
118	.auto_corr_min_cck_mrc = 170,
119	.auto_corr_max_cck_mrc = 400,
120	.nrg_th_cck = 95,
121	.nrg_th_ofdm = 95,
122
123	.barker_corr_th_min = 190,
124	.barker_corr_th_min_mrc = 390,
125	.nrg_th_cca = 62,
126};
127
128#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF	(-5)
129
130static s32 iwl_temp_calib_to_offset(struct iwl_shared *shrd)
131{
132	u16 temperature, voltage;
133	__le16 *temp_calib = (__le16 *)iwl_eeprom_query_addr(shrd,
134				EEPROM_KELVIN_TEMPERATURE);
135
136	temperature = le16_to_cpu(temp_calib[0]);
137	voltage = le16_to_cpu(temp_calib[1]);
138
139	/* offset = temp - volt / coeff */
140	return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF);
141}
142
143static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
144{
145	const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
146	s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
147			iwl_temp_calib_to_offset(priv->shrd);
148
149	hw_params(priv).ct_kill_threshold = threshold * volt2temp_coef;
150}
151
152static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
153{
154	/* want Celsius */
155	hw_params(priv).ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
156}
157
158static void iwl5000_hw_set_hw_params(struct iwl_priv *priv)
159{
160	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
161	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
162		cfg(priv)->base_params->num_of_queues =
163			iwlagn_mod_params.num_of_queues;
164
165	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
166
167	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
168					BIT(IEEE80211_BAND_5GHZ);
169
170	hw_params(priv).tx_chains_num =
171		num_of_ant(hw_params(priv).valid_tx_ant);
172	hw_params(priv).rx_chains_num =
173		num_of_ant(hw_params(priv).valid_rx_ant);
174
175	iwl5000_set_ct_threshold(priv);
176
177	/* Set initial sensitivity parameters */
178	hw_params(priv).sens = &iwl5000_sensitivity;
179}
180
181static void iwl5150_hw_set_hw_params(struct iwl_priv *priv)
182{
183	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
184	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
185		cfg(priv)->base_params->num_of_queues =
186			iwlagn_mod_params.num_of_queues;
187
188	hw_params(priv).max_txq_num = cfg(priv)->base_params->num_of_queues;
189
190	hw_params(priv).ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
191					BIT(IEEE80211_BAND_5GHZ);
192
193	hw_params(priv).tx_chains_num =
194		num_of_ant(hw_params(priv).valid_tx_ant);
195	hw_params(priv).rx_chains_num =
196		num_of_ant(hw_params(priv).valid_rx_ant);
197
198	iwl5150_set_ct_threshold(priv);
199
200	/* Set initial sensitivity parameters */
201	hw_params(priv).sens = &iwl5150_sensitivity;
202}
203
204static void iwl5150_temperature(struct iwl_priv *priv)
205{
206	u32 vt = 0;
207	s32 offset =  iwl_temp_calib_to_offset(priv->shrd);
208
209	vt = le32_to_cpu(priv->statistics.common.temperature);
210	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
211	/* now vt hold the temperature in Kelvin */
212	priv->temperature = KELVIN_TO_CELSIUS(vt);
213	iwl_tt_handler(priv);
214}
215
216static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
217				     struct ieee80211_channel_switch *ch_switch)
218{
219	/*
220	 * MULTI-FIXME
221	 * See iwlagn_mac_channel_switch.
222	 */
223	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
224	struct iwl5000_channel_switch_cmd cmd;
225	const struct iwl_channel_info *ch_info;
226	u32 switch_time_in_usec, ucode_switch_time;
227	u16 ch;
228	u32 tsf_low;
229	u8 switch_count;
230	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
231	struct ieee80211_vif *vif = ctx->vif;
232	struct iwl_host_cmd hcmd = {
233		.id = REPLY_CHANNEL_SWITCH,
234		.len = { sizeof(cmd), },
235		.flags = CMD_SYNC,
236		.data = { &cmd, },
237	};
238
239	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
240	ch = ch_switch->channel->hw_value;
241	IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
242		      ctx->active.channel, ch);
243	cmd.channel = cpu_to_le16(ch);
244	cmd.rxon_flags = ctx->staging.flags;
245	cmd.rxon_filter_flags = ctx->staging.filter_flags;
246	switch_count = ch_switch->count;
247	tsf_low = ch_switch->timestamp & 0x0ffffffff;
248	/*
249	 * calculate the ucode channel switch time
250	 * adding TSF as one of the factor for when to switch
251	 */
252	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
253		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
254		    beacon_interval)) {
255			switch_count -= (priv->ucode_beacon_time -
256				tsf_low) / beacon_interval;
257		} else
258			switch_count = 0;
259	}
260	if (switch_count <= 1)
261		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
262	else {
263		switch_time_in_usec =
264			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
265		ucode_switch_time = iwl_usecs_to_beacons(priv,
266							 switch_time_in_usec,
267							 beacon_interval);
268		cmd.switch_time = iwl_add_beacon_time(priv,
269						      priv->ucode_beacon_time,
270						      ucode_switch_time,
271						      beacon_interval);
272	}
273	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
274		      cmd.switch_time);
275	ch_info = iwl_get_channel_info(priv, priv->band, ch);
276	if (ch_info)
277		cmd.expect_beacon = is_channel_radar(ch_info);
278	else {
279		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
280			ctx->active.channel, ch);
281		return -EFAULT;
282	}
283
284	return iwl_trans_send_cmd(trans(priv), &hcmd);
285}
286
287static struct iwl_lib_ops iwl5000_lib = {
288	.set_hw_params = iwl5000_hw_set_hw_params,
289	.set_channel_switch = iwl5000_hw_channel_switch,
290	.nic_config = iwl5000_nic_config,
291	.eeprom_ops = {
292		.regulatory_bands = {
293			EEPROM_REG_BAND_1_CHANNELS,
294			EEPROM_REG_BAND_2_CHANNELS,
295			EEPROM_REG_BAND_3_CHANNELS,
296			EEPROM_REG_BAND_4_CHANNELS,
297			EEPROM_REG_BAND_5_CHANNELS,
298			EEPROM_REG_BAND_24_HT40_CHANNELS,
299			EEPROM_REG_BAND_52_HT40_CHANNELS
300		},
301	},
302	.temperature = iwlagn_temperature,
303};
304
305static struct iwl_lib_ops iwl5150_lib = {
306	.set_hw_params = iwl5150_hw_set_hw_params,
307	.set_channel_switch = iwl5000_hw_channel_switch,
308	.nic_config = iwl5000_nic_config,
309	.eeprom_ops = {
310		.regulatory_bands = {
311			EEPROM_REG_BAND_1_CHANNELS,
312			EEPROM_REG_BAND_2_CHANNELS,
313			EEPROM_REG_BAND_3_CHANNELS,
314			EEPROM_REG_BAND_4_CHANNELS,
315			EEPROM_REG_BAND_5_CHANNELS,
316			EEPROM_REG_BAND_24_HT40_CHANNELS,
317			EEPROM_REG_BAND_52_HT40_CHANNELS
318		},
319	},
320	.temperature = iwl5150_temperature,
321};
322
323static struct iwl_base_params iwl5000_base_params = {
324	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
325	.num_of_queues = IWLAGN_NUM_QUEUES,
326	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
327	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
328	.led_compensation = 51,
329	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
330	.chain_noise_scale = 1000,
331	.wd_timeout = IWL_LONG_WD_TIMEOUT,
332	.max_event_log_size = 512,
333	.no_idle_support = true,
334	.wd_disable = true,
335};
336static struct iwl_ht_params iwl5000_ht_params = {
337	.ht_greenfield_support = true,
338};
339
340#define IWL_DEVICE_5000						\
341	.fw_name_pre = IWL5000_FW_PRE,				\
342	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
343	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
344	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
345	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
346	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\
347	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
348	.lib = &iwl5000_lib,					\
349	.base_params = &iwl5000_base_params,			\
350	.led_mode = IWL_LED_BLINK
351
352const struct iwl_cfg iwl5300_agn_cfg = {
353	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
354	IWL_DEVICE_5000,
355	/* at least EEPROM 0x11A has wrong info */
356	.valid_tx_ant = ANT_ABC,	/* .cfg overwrite */
357	.valid_rx_ant = ANT_ABC,	/* .cfg overwrite */
358	.ht_params = &iwl5000_ht_params,
359};
360
361const struct iwl_cfg iwl5100_bgn_cfg = {
362	.name = "Intel(R) WiFi Link 5100 BGN",
363	IWL_DEVICE_5000,
364	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
365	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
366	.ht_params = &iwl5000_ht_params,
367};
368
369const struct iwl_cfg iwl5100_abg_cfg = {
370	.name = "Intel(R) WiFi Link 5100 ABG",
371	IWL_DEVICE_5000,
372	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
373	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
374};
375
376const struct iwl_cfg iwl5100_agn_cfg = {
377	.name = "Intel(R) WiFi Link 5100 AGN",
378	IWL_DEVICE_5000,
379	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
380	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
381	.ht_params = &iwl5000_ht_params,
382};
383
384const struct iwl_cfg iwl5350_agn_cfg = {
385	.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
386	.fw_name_pre = IWL5000_FW_PRE,
387	.ucode_api_max = IWL5000_UCODE_API_MAX,
388	.ucode_api_min = IWL5000_UCODE_API_MIN,
389	.max_inst_size = IWLAGN_RTC_INST_SIZE,
390	.max_data_size = IWLAGN_RTC_DATA_SIZE,
391	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
392	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
393	.lib = &iwl5000_lib,
394	.base_params = &iwl5000_base_params,
395	.ht_params = &iwl5000_ht_params,
396	.led_mode = IWL_LED_BLINK,
397	.internal_wimax_coex = true,
398};
399
400#define IWL_DEVICE_5150						\
401	.fw_name_pre = IWL5150_FW_PRE,				\
402	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
403	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
404	.max_inst_size = IWLAGN_RTC_INST_SIZE,			\
405	.max_data_size = IWLAGN_RTC_DATA_SIZE,			\
406	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\
407	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
408	.lib = &iwl5150_lib,					\
409	.base_params = &iwl5000_base_params,			\
410	.no_xtal_calib = true,					\
411	.led_mode = IWL_LED_BLINK,				\
412	.internal_wimax_coex = true
413
414const struct iwl_cfg iwl5150_agn_cfg = {
415	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
416	IWL_DEVICE_5150,
417	.ht_params = &iwl5000_ht_params,
418
419};
420
421const struct iwl_cfg iwl5150_abg_cfg = {
422	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
423	IWL_DEVICE_5150,
424};
425
426MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
427MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));
428