iwl-5000.c 17.5 KB
Newer Older
1
2
/******************************************************************************
 *
Wey-Yi Guy's avatar
Wey-Yi Guy committed
3
 * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 *
 * 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:
22
 *  Intel Linux Wireless <ilw@linux.intel.com>
23
24
25
26
27
28
29
30
31
32
 * 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/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
33
#include <linux/sched.h>
34
35
36
37
38
39
40
41
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/wireless.h>
#include <net/mac80211.h>
#include <linux/etherdevice.h>
#include <asm/unaligned.h>

#include "iwl-eeprom.h"
42
#include "iwl-dev.h"
43
44
#include "iwl-core.h"
#include "iwl-io.h"
45
#include "iwl-sta.h"
46
#include "iwl-helpers.h"
47
#include "iwl-agn.h"
48
#include "iwl-agn-hw.h"
49
#include "iwl-5000-hw.h"
50
#include "iwl-agn-debugfs.h"
51

52
/* Highest firmware API version supported */
53
#define IWL5000_UCODE_API_MAX 5
54
#define IWL5150_UCODE_API_MAX 2
55

56
57
58
59
60
/* Lowest firmware API version supported */
#define IWL5000_UCODE_API_MIN 1
#define IWL5150_UCODE_API_MIN 1

#define IWL5000_FW_PRE "iwlwifi-5000-"
61
#define IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode"
62
63

#define IWL5150_FW_PRE "iwlwifi-5150-"
64
#define IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode"
65

66
/* NIC configuration for 5000 series */
67
static void iwl5000_nic_config(struct iwl_priv *priv)
68
69
70
71
72
73
74
75
76
{
	unsigned long flags;
	u16 radio_cfg;

	spin_lock_irqsave(&priv->lock, flags);

	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);

	/* write radio config values to register */
77
	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_RF_CONFIG_TYPE_MAX)
78
79
80
81
82
83
84
85
86
87
		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));

	/* set CSR_HW_CONFIG_REG for uCode use */
	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);

Tomas Winkler's avatar
Tomas Winkler committed
88
89
90
91
	/* W/A : NIC is stuck in a reset state after Early PCIe power off
	 * (PCIe power is lost before PERST# is asserted),
	 * causing ME FW to lose ownership and not being able to obtain it back.
	 */
92
	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
Tomas Winkler's avatar
Tomas Winkler committed
93
94
95
				APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS,
				~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS);

96

97
98
99
	spin_unlock_irqrestore(&priv->lock, flags);
}

100
101
static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
	.min_nrg_cck = 95,
102
	.max_nrg_cck = 0, /* not used, set to 0 */
103
104
105
106
107
108
109
	.auto_corr_min_ofdm = 90,
	.auto_corr_min_ofdm_mrc = 170,
	.auto_corr_min_ofdm_x1 = 120,
	.auto_corr_min_ofdm_mrc_x1 = 240,

	.auto_corr_max_ofdm = 120,
	.auto_corr_max_ofdm_mrc = 210,
110
111
	.auto_corr_max_ofdm_x1 = 120,
	.auto_corr_max_ofdm_mrc_x1 = 240,
112
113
114
115
116
117
118

	.auto_corr_min_cck = 125,
	.auto_corr_max_cck = 200,
	.auto_corr_min_cck_mrc = 170,
	.auto_corr_max_cck_mrc = 400,
	.nrg_th_cck = 95,
	.nrg_th_ofdm = 95,
119
120
121
122

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

125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
static struct iwl_sensitivity_ranges iwl5150_sensitivity = {
	.min_nrg_cck = 95,
	.max_nrg_cck = 0, /* not used, set to 0 */
	.auto_corr_min_ofdm = 90,
	.auto_corr_min_ofdm_mrc = 170,
	.auto_corr_min_ofdm_x1 = 105,
	.auto_corr_min_ofdm_mrc_x1 = 220,

	.auto_corr_max_ofdm = 120,
	.auto_corr_max_ofdm_mrc = 210,
	/* max = min for performance bug in 5150 DSP */
	.auto_corr_max_ofdm_x1 = 105,
	.auto_corr_max_ofdm_mrc_x1 = 220,

	.auto_corr_min_cck = 125,
	.auto_corr_max_cck = 200,
	.auto_corr_min_cck_mrc = 170,
	.auto_corr_max_cck_mrc = 400,
	.nrg_th_cck = 95,
	.nrg_th_ofdm = 95,
145
146
147
148

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

151
static void iwl5150_set_ct_threshold(struct iwl_priv *priv)
152
{
153
	const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF;
154
	s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) -
155
156
157
158
159
160
161
162
			iwl_temp_calib_to_offset(priv);

	priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef;
}

static void iwl5000_set_ct_threshold(struct iwl_priv *priv)
{
	/* want Celsius */
163
	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY;
164
165
}

166
static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
167
{
168
	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
169
	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
170
		priv->cfg->base_params->num_of_queues =
171
			priv->cfg->mod_params->num_of_queues;
172

173
	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
174
	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
175
	priv->hw_params.scd_bc_tbls_size =
176
			priv->cfg->base_params->num_of_queues *
177
			sizeof(struct iwlagn_scd_bc_tbl);
178
	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
179
	priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
180
	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
181

182
183
	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
184

185
	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
186
					BIT(IEEE80211_BAND_5GHZ);
187
188
	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;

189
190
191
192
	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
	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;
193

194
	iwl5000_set_ct_threshold(priv);
195

196
	/* Set initial sensitivity parameters */
197
	/* Set initial calibration set */
198
199
200
201
202
203
204
205
	priv->hw_params.sens = &iwl5000_sensitivity;
	priv->hw_params.calib_init_cfg =
		BIT(IWL_CALIB_XTAL)		|
		BIT(IWL_CALIB_LO)		|
		BIT(IWL_CALIB_TX_IQ)		|
		BIT(IWL_CALIB_TX_IQ_PERD)	|
		BIT(IWL_CALIB_BASE_BAND);

206
207
	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;

208
209
210
211
212
213
214
	return 0;
}

static int iwl5150_hw_set_hw_params(struct iwl_priv *priv)
{
	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
215
		priv->cfg->base_params->num_of_queues =
216
217
			priv->cfg->mod_params->num_of_queues;

218
	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
219
220
	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
	priv->hw_params.scd_bc_tbls_size =
221
			priv->cfg->base_params->num_of_queues *
222
223
			sizeof(struct iwlagn_scd_bc_tbl);
	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
224
	priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
225
	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
226
227
228
229
230
231
232
233
234
235
236
237
238

	priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
	priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;

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

	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
	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;

239
	iwl5150_set_ct_threshold(priv);
240
241
242
243
244
245
246
247

	/* Set initial sensitivity parameters */
	/* Set initial calibration set */
	priv->hw_params.sens = &iwl5150_sensitivity;
	priv->hw_params.calib_init_cfg =
		BIT(IWL_CALIB_LO)		|
		BIT(IWL_CALIB_TX_IQ)		|
		BIT(IWL_CALIB_BASE_BAND);
248
249
	if (priv->cfg->need_dc_calib)
		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_DC);
250

251
252
	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;

253
254
	return 0;
}
255

256
257
258
259
260
static void iwl5150_temperature(struct iwl_priv *priv)
{
	u32 vt = 0;
	s32 offset =  iwl_temp_calib_to_offset(priv);

261
	vt = le32_to_cpu(priv->statistics.common.temperature);
262
263
264
	vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset;
	/* now vt hold the temperature in Kelvin */
	priv->temperature = KELVIN_TO_CELSIUS(vt);
265
	iwl_tt_handler(priv);
266
267
}

268
269
static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
				     struct ieee80211_channel_switch *ch_switch)
270
{
271
272
273
274
275
	/*
	 * MULTI-FIXME
	 * See iwl_mac_channel_switch.
	 */
	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
276
277
	struct iwl5000_channel_switch_cmd cmd;
	const struct iwl_channel_info *ch_info;
278
279
280
281
	u32 switch_time_in_usec, ucode_switch_time;
	u16 ch;
	u32 tsf_low;
	u8 switch_count;
282
	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
283
	struct ieee80211_vif *vif = ctx->vif;
284
285
286
	struct iwl_host_cmd hcmd = {
		.id = REPLY_CHANNEL_SWITCH,
		.len = sizeof(cmd),
287
		.flags = CMD_SYNC,
288
289
290
291
		.data = &cmd,
	};

	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
292
	ch = ch_switch->channel->hw_value;
293
	IWL_DEBUG_11H(priv, "channel switch from %d to %d\n",
294
		      ctx->active.channel, ch);
295
	cmd.channel = cpu_to_le16(ch);
296
297
	cmd.rxon_flags = ctx->staging.flags;
	cmd.rxon_filter_flags = ctx->staging.filter_flags;
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
	switch_count = ch_switch->count;
	tsf_low = ch_switch->timestamp & 0x0ffffffff;
	/*
	 * calculate the ucode channel switch time
	 * adding TSF as one of the factor for when to switch
	 */
	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
		    beacon_interval)) {
			switch_count -= (priv->ucode_beacon_time -
				tsf_low) / beacon_interval;
		} else
			switch_count = 0;
	}
	if (switch_count <= 1)
		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
	else {
		switch_time_in_usec =
			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
		ucode_switch_time = iwl_usecs_to_beacons(priv,
							 switch_time_in_usec,
							 beacon_interval);
		cmd.switch_time = iwl_add_beacon_time(priv,
						      priv->ucode_beacon_time,
						      ucode_switch_time,
						      beacon_interval);
	}
	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
		      cmd.switch_time);
	ch_info = iwl_get_channel_info(priv, priv->band, ch);
328
329
330
331
	if (ch_info)
		cmd.expect_beacon = is_channel_radar(ch_info);
	else {
		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
332
			ctx->active.channel, ch);
333
334
		return -EFAULT;
	}
335
	priv->switch_rxon.channel = cmd.channel;
Wey-Yi Guy's avatar
Wey-Yi Guy committed
336
	priv->switch_rxon.switch_in_progress = true;
337
338
339
340

	return iwl_send_cmd_sync(priv, &hcmd);
}

341
static struct iwl_lib_ops iwl5000_lib = {
342
	.set_hw_params = iwl5000_hw_set_hw_params,
343
344
345
	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
	.txq_set_sched = iwlagn_txq_set_sched,
346
347
	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
	.txq_free_tfd = iwl_hw_txq_free_tfd,
348
	.txq_init = iwl_hw_tx_queue_init,
349
350
351
352
	.rx_handler_setup = iwlagn_rx_handler_setup,
	.setup_deferred_work = iwlagn_setup_deferred_work,
	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
	.send_tx_power = iwlagn_send_tx_power,
353
	.update_chain_flags = iwl_update_chain_flags,
354
	.set_channel_switch = iwl5000_hw_channel_switch,
355
	.apm_ops = {
356
		.init = iwl_apm_init,
357
		.config = iwl5000_nic_config,
358
	},
359
	.eeprom_ops = {
360
		.regulatory_bands = {
361
362
363
364
365
366
367
			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_REG_BAND_24_HT40_CHANNELS,
			EEPROM_REG_BAND_52_HT40_CHANNELS
368
		},
369
370
		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
		.release_semaphore = iwlcore_eeprom_release_semaphore,
371
372
		.calib_version	= iwlagn_eeprom_calib_version,
		.query_addr = iwlagn_eeprom_query_addr,
373
	},
374
	.temp_ops = {
375
		.temperature = iwlagn_temperature,
376
	 },
377
378
379
380
	.debugfs_ops = {
		.rx_stats_read = iwl_ucode_rx_stats_read,
		.tx_stats_read = iwl_ucode_tx_stats_read,
		.general_stats_read = iwl_ucode_general_stats_read,
381
		.bt_stats_read = iwl_ucode_bt_stats_read,
382
		.reply_tx_error = iwl_reply_tx_error_read,
383
	},
384
	.txfifo_flush = iwlagn_txfifo_flush,
385
	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
386
387
388
389
390
	.tt_ops = {
		.lower_power_detection = iwl_tt_is_low_power_state,
		.tt_power_mode = iwl_tt_current_power_mode,
		.ct_kill_check = iwl_check_for_ct_kill,
	}
391
392
393
};

static struct iwl_lib_ops iwl5150_lib = {
394
	.set_hw_params = iwl5150_hw_set_hw_params,
395
396
397
	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
	.txq_set_sched = iwlagn_txq_set_sched,
398
399
400
	.txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd,
	.txq_free_tfd = iwl_hw_txq_free_tfd,
	.txq_init = iwl_hw_tx_queue_init,
401
402
403
404
	.rx_handler_setup = iwlagn_rx_handler_setup,
	.setup_deferred_work = iwlagn_setup_deferred_work,
	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
	.send_tx_power = iwlagn_send_tx_power,
405
	.update_chain_flags = iwl_update_chain_flags,
406
	.set_channel_switch = iwl5000_hw_channel_switch,
407
	.apm_ops = {
408
		.init = iwl_apm_init,
409
410
411
412
		.config = iwl5000_nic_config,
	},
	.eeprom_ops = {
		.regulatory_bands = {
413
414
415
416
417
418
419
			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_REG_BAND_24_HT40_CHANNELS,
			EEPROM_REG_BAND_52_HT40_CHANNELS
420
421
422
		},
		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
		.release_semaphore = iwlcore_eeprom_release_semaphore,
423
424
		.calib_version	= iwlagn_eeprom_calib_version,
		.query_addr = iwlagn_eeprom_query_addr,
425
426
427
428
	},
	.temp_ops = {
		.temperature = iwl5150_temperature,
	 },
429
430
431
432
	.debugfs_ops = {
		.rx_stats_read = iwl_ucode_rx_stats_read,
		.tx_stats_read = iwl_ucode_tx_stats_read,
		.general_stats_read = iwl_ucode_general_stats_read,
433
		.bt_stats_read = iwl_ucode_bt_stats_read,
434
		.reply_tx_error = iwl_reply_tx_error_read,
435
	},
436
	.txfifo_flush = iwlagn_txfifo_flush,
437
	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
438
439
440
441
442
	.tt_ops = {
		.lower_power_detection = iwl_tt_is_low_power_state,
		.tt_power_mode = iwl_tt_current_power_mode,
		.ct_kill_check = iwl_check_for_ct_kill,
	}
443
444
};

Emese Revfy's avatar
Emese Revfy committed
445
static const struct iwl_ops iwl5000_ops = {
446
	.lib = &iwl5000_lib,
447
448
	.hcmd = &iwlagn_hcmd,
	.utils = &iwlagn_hcmd_utils,
449
	.ieee80211_ops = &iwlagn_hw_ops,
450
451
};

Emese Revfy's avatar
Emese Revfy committed
452
static const struct iwl_ops iwl5150_ops = {
453
	.lib = &iwl5150_lib,
454
455
	.hcmd = &iwlagn_hcmd,
	.utils = &iwlagn_hcmd_utils,
456
	.ieee80211_ops = &iwlagn_hw_ops,
457
458
};

459
static struct iwl_base_params iwl5000_base_params = {
460
461
462
	.eeprom_size = IWLAGN_EEPROM_IMG_SIZE,
	.num_of_queues = IWLAGN_NUM_QUEUES,
	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
463
	.pll_cfg_val = CSR50_ANA_PLL_CFG_VAL,
464
	.led_compensation = 51,
465
	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
466
	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
467
	.chain_noise_scale = 1000,
468
	.wd_timeout = IWL_LONG_WD_TIMEOUT,
469
	.max_event_log_size = 512,
470
};
471
472
473
474
475
static struct iwl_ht_params iwl5000_ht_params = {
	.ht_greenfield_support = true,
	.use_rts_for_aggregation = true, /* use rts/cts protection */
};

476
477
478
479
480
481
482
483
484
485
486
#define IWL_DEVICE_5000						\
	.fw_name_pre = IWL5000_FW_PRE,				\
	.ucode_api_max = IWL5000_UCODE_API_MAX,			\
	.ucode_api_min = IWL5000_UCODE_API_MIN,			\
	.eeprom_ver = EEPROM_5000_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION,	\
	.ops = &iwl5000_ops,					\
	.mod_params = &iwlagn_mod_params,			\
	.base_params = &iwl5000_base_params,			\
	.led_mode = IWL_LED_BLINK

487
488
struct iwl_cfg iwl5300_agn_cfg = {
	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
489
	IWL_DEVICE_5000,
490
491
492
	/* at least EEPROM 0x11A has wrong info */
	.valid_tx_ant = ANT_ABC,	/* .cfg overwrite */
	.valid_rx_ant = ANT_ABC,	/* .cfg overwrite */
493
494
	.ht_params = &iwl5000_ht_params,
};
495

496
struct iwl_cfg iwl5100_bgn_cfg = {
497
	.name = "Intel(R) WiFi Link 5100 BGN",
498
	IWL_DEVICE_5000,
499
500
	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
501
	.ht_params = &iwl5000_ht_params,
502
503
504
};

struct iwl_cfg iwl5100_abg_cfg = {
505
	.name = "Intel(R) WiFi Link 5100 ABG",
506
	IWL_DEVICE_5000,
507
508
	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
509
510
};

511
struct iwl_cfg iwl5100_agn_cfg = {
512
	.name = "Intel(R) WiFi Link 5100 AGN",
513
	IWL_DEVICE_5000,
514
515
	.valid_tx_ant = ANT_B,		/* .cfg overwrite */
	.valid_rx_ant = ANT_AB,		/* .cfg overwrite */
516
	.ht_params = &iwl5000_ht_params,
517
518
519
};

struct iwl_cfg iwl5350_agn_cfg = {
520
	.name = "Intel(R) WiMAX/WiFi Link 5350 AGN",
521
522
523
	.fw_name_pre = IWL5000_FW_PRE,
	.ucode_api_max = IWL5000_UCODE_API_MAX,
	.ucode_api_min = IWL5000_UCODE_API_MIN,
524
525
	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,
	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,
526
	.ops = &iwl5000_ops,
527
	.mod_params = &iwlagn_mod_params,
528
529
	.base_params = &iwl5000_base_params,
	.ht_params = &iwl5000_ht_params,
530
	.led_mode = IWL_LED_BLINK,
531
	.internal_wimax_coex = true,
532
533
};

534
535
536
537
538
539
540
541
542
543
544
545
546
#define IWL_DEVICE_5150						\
	.fw_name_pre = IWL5150_FW_PRE,				\
	.ucode_api_max = IWL5150_UCODE_API_MAX,			\
	.ucode_api_min = IWL5150_UCODE_API_MIN,			\
	.eeprom_ver = EEPROM_5050_EEPROM_VERSION,		\
	.eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION,	\
	.ops = &iwl5150_ops,					\
	.mod_params = &iwlagn_mod_params,			\
	.base_params = &iwl5000_base_params,			\
	.need_dc_calib = true,					\
	.led_mode = IWL_LED_BLINK,				\
	.internal_wimax_coex = true

547
struct iwl_cfg iwl5150_agn_cfg = {
548
	.name = "Intel(R) WiMAX/WiFi Link 5150 AGN",
549
	IWL_DEVICE_5150,
550
	.ht_params = &iwl5000_ht_params,
551

552
553
};

554
struct iwl_cfg iwl5150_abg_cfg = {
555
	.name = "Intel(R) WiMAX/WiFi Link 5150 ABG",
556
	IWL_DEVICE_5150,
557
558
};

559
560
MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX));
MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX));