iwl-2000.c 11.1 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
88
	if (priv->cfg->iq_invert)
		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);

89
90
	if (priv->cfg->disable_otp_refresh)
		iwl_write_prph(priv, APMG_ANALOG_SVR_REG, 0x80000010);
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
117
118
119
}

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
120
121
	if (iwlagn_mod_params.num_of_queues >= IWL_MIN_NUM_QUEUES &&
	    iwlagn_mod_params.num_of_queues <= IWLAGN_NUM_QUEUES)
122
		priv->cfg->base_params->num_of_queues =
Don Fry's avatar
Don Fry committed
123
			iwlagn_mod_params.num_of_queues;
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170

	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)
		priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
	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,
	.rx_handler_setup = iwlagn_rx_handler_setup,
171
172
	.setup_deferred_work = iwlagn_bt_setup_deferred_work,
	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
173
	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
174
	.nic_config = iwl2000_nic_config,
175
176
177
178
179
180
181
182
	.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,
183
			EEPROM_REGULATORY_BAND_NO_HT40,
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
		},
		.query_addr = iwlagn_eeprom_query_addr,
		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
	},
	.temp_ops = {
		.temperature = iwlagn_temperature,
	},
};

static const struct iwl_ops iwl2000_ops = {
	.lib = &iwl2000_lib,
	.utils = &iwlagn_hcmd_utils,
};

static const struct iwl_ops iwl2030_ops = {
	.lib = &iwl2000_lib,
	.utils = &iwlagn_hcmd_utils,
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
203
static const struct iwl_ops iwl105_ops = {
204
205
206
207
	.lib = &iwl2000_lib,
	.utils = &iwlagn_hcmd_utils,
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
208
static const struct iwl_ops iwl135_ops = {
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
253
254
255
256
257
258
259
260
261
	.lib = &iwl2000_lib,
	.utils = &iwlagn_hcmd_utils,
};

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,
262
	.bt_session_2 = true,
263
264
265
266
267
268
269
270
271
272
273
274
};

#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,	\
	.ops = &iwl2000_ops,					\
	.base_params = &iwl2000_base_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
275
	.led_mode = IWL_LED_RF_STATE,				\
276
277
	.iq_invert = true,					\
	.disable_otp_refresh = true				\
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301

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,	\
	.ops = &iwl2030_ops,					\
	.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,				\
302
303
	.adv_pm = true,						\
	.iq_invert = true					\
304
305
306

struct iwl_cfg iwl2030_2bgn_cfg = {
	.name = "2000 Series 2x2 BGN/BT",
307
	IWL_DEVICE_2030,
308
309
310
311
312
	.ht_params = &iwl2000_ht_params,
};

struct iwl_cfg iwl2030_2bg_cfg = {
	.name = "2000 Series 2x2 BG/BT",
313
	IWL_DEVICE_2030,
314
315
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
316
317
318
319
#define IWL_DEVICE_105						\
	.fw_name_pre = IWL105_FW_PRE,				\
	.ucode_api_max = IWL105_UCODE_API_MAX,			\
	.ucode_api_min = IWL105_UCODE_API_MIN,			\
320
321
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
Wey-Yi Guy's avatar
Wey-Yi Guy committed
322
	.ops = &iwl105_ops,					\
323
324
325
326
327
328
329
	.base_params = &iwl2000_base_params,			\
	.need_dc_calib = true,					\
	.need_temp_offset_calib = true,				\
	.led_mode = IWL_LED_RF_STATE,				\
	.adv_pm = true,						\
	.rx_with_siso_diversity = true				\

Wey-Yi Guy's avatar
Wey-Yi Guy committed
330
331
332
struct iwl_cfg iwl105_bg_cfg = {
	.name = "105 Series 1x1 BG",
	IWL_DEVICE_105,
333
334
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
335
336
337
struct iwl_cfg iwl105_bgn_cfg = {
	.name = "105 Series 1x1 BGN",
	IWL_DEVICE_105,
338
339
340
	.ht_params = &iwl2000_ht_params,
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
341
#define IWL_DEVICE_135						\
342
343
344
	.fw_name_pre = IWL135_FW_PRE,				\
	.ucode_api_max = IWL135_UCODE_API_MAX,			\
	.ucode_api_min = IWL135_UCODE_API_MIN,			\
345
346
	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
Wey-Yi Guy's avatar
Wey-Yi Guy committed
347
	.ops = &iwl135_ops,					\
348
349
350
351
352
353
354
355
	.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,						\
	.rx_with_siso_diversity = true				\

Wey-Yi Guy's avatar
Wey-Yi Guy committed
356
struct iwl_cfg iwl135_bg_cfg = {
357
	.name = "135 Series 1x1 BG/BT",
Wey-Yi Guy's avatar
Wey-Yi Guy committed
358
	IWL_DEVICE_135,
359
360
};

Wey-Yi Guy's avatar
Wey-Yi Guy committed
361
struct iwl_cfg iwl135_bgn_cfg = {
362
	.name = "135 Series 1x1 BGN/BT",
Wey-Yi Guy's avatar
Wey-Yi Guy committed
363
	IWL_DEVICE_135,
364
365
366
367
368
	.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
369
MODULE_FIRMWARE(IWL105_MODULE_FIRMWARE(IWL105_UCODE_API_MAX));
370
MODULE_FIRMWARE(IWL135_MODULE_FIRMWARE(IWL135_UCODE_API_MAX));