iwl-2000.c 11 KB
Newer Older
1
2
/******************************************************************************
 *
Wey-Yi Guy's avatar
Wey-Yi Guy committed
3
 * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
 *  Intel Linux Wireless <ilw@linux.intel.com>
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *
 *****************************************************************************/

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>
37
#include <linux/stringify.h>
38
39
40
41
42
43
44
45
46
47
48
49
50
51

#include "iwl-eeprom.h"
#include "iwl-dev.h"
#include "iwl-core.h"
#include "iwl-io.h"
#include "iwl-sta.h"
#include "iwl-agn.h"
#include "iwl-helpers.h"
#include "iwl-agn-hw.h"
#include "iwl-6000-hw.h"

/* Highest firmware API version supported */
#define IWL2030_UCODE_API_MAX 5
#define IWL2000_UCODE_API_MAX 5
Wey-Yi Guy's avatar
Wey-Yi Guy committed
52
#define IWL105_UCODE_API_MAX 5
53
#define IWL135_UCODE_API_MAX 5
54
55
56
57

/* Lowest firmware API version supported */
#define IWL2030_UCODE_API_MIN 5
#define IWL2000_UCODE_API_MIN 5
Wey-Yi Guy's avatar
Wey-Yi Guy committed
58
#define IWL105_UCODE_API_MIN 5
59
#define IWL135_UCODE_API_MIN 5
60
61

#define IWL2030_FW_PRE "iwlwifi-2030-"
62
#define IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE __stringify(api) ".ucode"
63
64

#define IWL2000_FW_PRE "iwlwifi-2000-"
65
#define IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE __stringify(api) ".ucode"
66

Wey-Yi Guy's avatar
Wey-Yi Guy committed
67
#define IWL105_FW_PRE "iwlwifi-105-"
68
#define IWL105_MODULE_FIRMWARE(api) IWL105_FW_PRE __stringify(api) ".ucode"
69

70
71
72
#define IWL135_FW_PRE "iwlwifi-135-"
#define IWL135_MODULE_FIRMWARE(api) IWL135_FW_PRE #api ".ucode"

73
74
75
76
77
78
79
80
81
82
static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
{
	/* want Celsius */
	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
	priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
}

/* NIC configuration for 2000 series */
static void iwl2000_nic_config(struct iwl_priv *priv)
{
83
	iwl_rf_config(priv);
84

85
86
87
	if (priv->cfg->iq_invert)
		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
}

static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
	.min_nrg_cck = 97,
	.max_nrg_cck = 0, /* not used, set to 0 */
	.auto_corr_min_ofdm = 80,
	.auto_corr_min_ofdm_mrc = 128,
	.auto_corr_min_ofdm_x1 = 105,
	.auto_corr_min_ofdm_mrc_x1 = 192,

	.auto_corr_max_ofdm = 145,
	.auto_corr_max_ofdm_mrc = 232,
	.auto_corr_max_ofdm_x1 = 110,
	.auto_corr_max_ofdm_mrc_x1 = 232,

	.auto_corr_min_cck = 125,
	.auto_corr_max_cck = 175,
	.auto_corr_min_cck_mrc = 160,
	.auto_corr_max_cck_mrc = 310,
	.nrg_th_cck = 97,
	.nrg_th_ofdm = 100,

	.barker_corr_th_min = 190,
	.barker_corr_th_min_mrc = 390,
	.nrg_th_cca = 62,
};

static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
{
Don Fry's avatar
Don Fry committed
117
118
	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
119
		priv->cfg->base_params->num_of_queues =
Don Fry's avatar
Don Fry committed
120
			iwlagn_mod_params.num_of_queues;
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
	priv->hw_params.scd_bc_tbls_size =
		priv->cfg->base_params->num_of_queues *
		sizeof(struct iwlagn_scd_bc_tbl);
	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
	priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;

	priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
	priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;

	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
					BIT(IEEE80211_BAND_5GHZ);

	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
	if (priv->cfg->rx_with_siso_diversity)
		priv->hw_params.rx_chains_num = 1;
	else
		priv->hw_params.rx_chains_num =
			num_of_ant(priv->cfg->valid_rx_ant);
	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;

	iwl2000_set_ct_threshold(priv);

	/* Set initial sensitivity parameters */
	/* Set initial calibration set */
	priv->hw_params.sens = &iwl2000_sensitivity;
	priv->hw_params.calib_init_cfg =
		BIT(IWL_CALIB_XTAL)             |
		BIT(IWL_CALIB_LO)               |
		BIT(IWL_CALIB_TX_IQ)            |
		BIT(IWL_CALIB_BASE_BAND);
	if (priv->cfg->need_dc_calib)
Wey-Yi Guy's avatar
Wey-Yi Guy committed
156
		priv->hw_params.calib_rt_cfg |= IWL_CALIB_CFG_DC_IDX;
157
158
159
160
161
162
163
164
165
166
	if (priv->cfg->need_temp_offset_calib)
		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);

	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;

	return 0;
}

static struct iwl_lib_ops iwl2000_lib = {
	.set_hw_params = iwl2000_hw_set_hw_params,
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
	.nic_config = iwl2000_nic_config,
	.eeprom_ops = {
		.regulatory_bands = {
			EEPROM_REG_BAND_1_CHANNELS,
			EEPROM_REG_BAND_2_CHANNELS,
			EEPROM_REG_BAND_3_CHANNELS,
			EEPROM_REG_BAND_4_CHANNELS,
			EEPROM_REG_BAND_5_CHANNELS,
			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
			EEPROM_REGULATORY_BAND_NO_HT40,
		},
		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
	},
	.temperature = iwlagn_temperature,
};

static struct iwl_lib_ops iwl2030_lib = {
	.set_hw_params = iwl2000_hw_set_hw_params,
185
	.bt_rx_handler_setup = iwlagn_bt_rx_handler_setup,
186
	.bt_setup_deferred_work = iwlagn_bt_setup_deferred_work,
187
	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
188
	.nic_config = iwl2000_nic_config,
189
190
191
192
193
194
195
196
	.eeprom_ops = {
		.regulatory_bands = {
			EEPROM_REG_BAND_1_CHANNELS,
			EEPROM_REG_BAND_2_CHANNELS,
			EEPROM_REG_BAND_3_CHANNELS,
			EEPROM_REG_BAND_4_CHANNELS,
			EEPROM_REG_BAND_5_CHANNELS,
			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
197
			EEPROM_REGULATORY_BAND_NO_HT40,
198
199
200
		},
		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
	},
201
	.temperature = iwlagn_temperature,
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
};

static struct iwl_base_params iwl2000_base_params = {
	.eeprom_size = OTP_LOW_IMAGE_SIZE,
	.num_of_queues = IWLAGN_NUM_QUEUES,
	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
	.pll_cfg_val = 0,
	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
	.shadow_ram_support = true,
	.led_compensation = 51,
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
	.adv_thermal_throttle = true,
	.support_ct_kill_exit = true,
	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
	.chain_noise_scale = 1000,
	.wd_timeout = IWL_DEF_WD_TIMEOUT,
	.max_event_log_size = 512,
	.shadow_reg_enable = true,
};


static struct iwl_base_params iwl2030_base_params = {
	.eeprom_size = OTP_LOW_IMAGE_SIZE,
	.num_of_queues = IWLAGN_NUM_QUEUES,
	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
	.pll_cfg_val = 0,
	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
	.shadow_ram_support = true,
	.led_compensation = 57,
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
	.adv_thermal_throttle = true,
	.support_ct_kill_exit = true,
	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
	.chain_noise_scale = 1000,
	.wd_timeout = IWL_LONG_WD_TIMEOUT,
	.max_event_log_size = 512,
	.shadow_reg_enable = true,
};

static struct iwl_ht_params iwl2000_ht_params = {
	.ht_greenfield_support = true,
	.use_rts_for_aggregation = true, /* use rts/cts protection */
};

static struct iwl_bt_params iwl2030_bt_params = {
	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
	.advanced_bt_coexist = true,
	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
	.bt_sco_disable = true,
253
	.bt_session_2 = true,
254
255
256
257
258
259
260
261
};

#define IWL_DEVICE_2000						\
	.fw_name_pre = IWL2000_FW_PRE,				\
	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
262
	.lib = &iwl2000_lib,					\
263
264
265
	.base_params = &iwl2000_base_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
266
	.led_mode = IWL_LED_RF_STATE,				\
267
	.iq_invert = true					\
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285

struct iwl_cfg iwl2000_2bgn_cfg = {
	.name = "2000 Series 2x2 BGN",
	IWL_DEVICE_2000,
	.ht_params = &iwl2000_ht_params,
};

struct iwl_cfg iwl2000_2bg_cfg = {
	.name = "2000 Series 2x2 BG",
	IWL_DEVICE_2000,
};

#define IWL_DEVICE_2030						\
	.fw_name_pre = IWL2030_FW_PRE,				\
	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
286
	.lib = &iwl2030_lib,					\
287
288
289
290
291
	.base_params = &iwl2030_base_params,			\
	.bt_params = &iwl2030_bt_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
	.led_mode = IWL_LED_RF_STATE,				\
292
293
	.adv_pm = true,						\
	.iq_invert = true					\
294
295
296

struct iwl_cfg iwl2030_2bgn_cfg = {
	.name = "2000 Series 2x2 BGN/BT",
297
	IWL_DEVICE_2030,
298
299
300
301
302
	.ht_params = &iwl2000_ht_params,
};

struct iwl_cfg iwl2030_2bg_cfg = {
	.name = "2000 Series 2x2 BG/BT",
303
	IWL_DEVICE_2030,
304
305
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
306
307
308
309
#define IWL_DEVICE_105						\
	.fw_name_pre = IWL105_FW_PRE,				\
	.ucode_api_max = IWL105_UCODE_API_MAX,			\
	.ucode_api_min = IWL105_UCODE_API_MIN,			\
310
311
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
312
	.lib = &iwl2000_lib,					\
313
314
315
316
317
	.base_params = &iwl2000_base_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
	.led_mode = IWL_LED_RF_STATE,				\
	.adv_pm = true,						\
318
319
	.rx_with_siso_diversity = true,				\
	.iq_invert = true					\
320

Wey-Yi Guy's avatar
Wey-Yi Guy committed
321
322
323
struct iwl_cfg iwl105_bg_cfg = {
	.name = "105 Series 1x1 BG",
	IWL_DEVICE_105,
324
325
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
326
327
328
struct iwl_cfg iwl105_bgn_cfg = {
	.name = "105 Series 1x1 BGN",
	IWL_DEVICE_105,
329
330
331
	.ht_params = &iwl2000_ht_params,
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
332
#define IWL_DEVICE_135						\
333
334
335
	.fw_name_pre = IWL135_FW_PRE,				\
	.ucode_api_max = IWL135_UCODE_API_MAX,			\
	.ucode_api_min = IWL135_UCODE_API_MIN,			\
336
337
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
338
	.lib = &iwl2030_lib,					\
339
340
341
342
343
344
	.base_params = &iwl2030_base_params,			\
	.bt_params = &iwl2030_bt_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
	.led_mode = IWL_LED_RF_STATE,				\
	.adv_pm = true,						\
345
346
	.rx_with_siso_diversity = true,				\
	.iq_invert = true					\
347

Wey-Yi Guy's avatar
Wey-Yi Guy committed
348
struct iwl_cfg iwl135_bg_cfg = {
349
	.name = "135 Series 1x1 BG/BT",
Wey-Yi Guy's avatar
Wey-Yi Guy committed
350
	IWL_DEVICE_135,
351
352
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
353
struct iwl_cfg iwl135_bgn_cfg = {
354
	.name = "135 Series 1x1 BGN/BT",
Wey-Yi Guy's avatar
Wey-Yi Guy committed
355
	IWL_DEVICE_135,
356
357
358
359
360
	.ht_params = &iwl2000_ht_params,
};

MODULE_FIRMWARE(IWL2000_MODULE_FIRMWARE(IWL2000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL2030_MODULE_FIRMWARE(IWL2030_UCODE_API_MAX));
Wey-Yi Guy's avatar
Wey-Yi Guy committed
361
MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
362
MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));