aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Ortiz <sameo@linux.intel.com>2009-09-01 09:14:04 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-09-01 12:48:27 -0400
commitd04bd6283cf7433d56f3d8f648f1d6963fda4fdc (patch)
treec67d1898aa854b7edf6ede235327e9feae7e96a2
parent31452420ca956f2cf37f705c869e265c33894f07 (diff)
iwmc3200wifi: New initial LMAC calibration
The LMAC calibration API got broken mostly by having a configuration bitmap being different than the result one. This patch tries to address that issue by correctly running calibrations with the newest firmwares, and keeping a backward compatibility fallback path for older firmwares, where the configuration and result bitmaps were identical. Signed-off-by: Samuel Ortiz <sameo@linux.intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/iwmc3200wifi/fw.c56
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h1
-rw-r--r--drivers/net/wireless/iwmc3200wifi/lmac.h15
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c7
4 files changed, 61 insertions, 18 deletions
diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c
index 0f32cab9ced4..6b0bcad758ca 100644
--- a/drivers/net/wireless/iwmc3200wifi/fw.c
+++ b/drivers/net/wireless/iwmc3200wifi/fw.c
@@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
261 cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); 261 cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
262} 262}
263 263
264static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap,
265 unsigned long expected_bitmap, u8 rx_iq_cmd)
266{
267 /* Read RX IQ calibration result from EEPROM */
268 if (test_bit(rx_iq_cmd, &cfg_bitmap)) {
269 iwm_store_rxiq_calib_result(iwm);
270 set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
271 }
272
273 iwm_send_prio_table(iwm);
274 iwm_send_init_calib_cfg(iwm, cfg_bitmap);
275
276 while (iwm->calib_done_map != expected_bitmap) {
277 if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
278 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) {
279 IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n");
280 return -ETIMEDOUT;
281 }
282
283 IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
284 "0x%lx, expected calibrations: 0x%lx\n",
285 iwm->calib_done_map, expected_bitmap);
286 }
287
288 return 0;
289}
290
264/* 291/*
265 * We currently have to load 3 FWs: 292 * We currently have to load 3 FWs:
266 * 1) The UMAC (Upper MAC). 293 * 1) The UMAC (Upper MAC).
@@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
276int iwm_load_fw(struct iwm_priv *iwm) 303int iwm_load_fw(struct iwm_priv *iwm)
277{ 304{
278 unsigned long init_calib_map, periodic_calib_map; 305 unsigned long init_calib_map, periodic_calib_map;
306 unsigned long expected_calib_map;
279 int ret; 307 int ret;
280 308
281 /* We first start downloading the UMAC */ 309 /* We first start downloading the UMAC */
@@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm)
317 } 345 }
318 346
319 init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; 347 init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
348 expected_calib_map = iwm->conf.expected_calib_map &
349 IWM_CALIB_MAP_INIT_MSK;
320 periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); 350 periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
321 351
322 /* Read RX IQ calibration result from EEPROM */ 352 ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
323 if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) { 353 CALIB_CFG_RX_IQ_IDX);
324 iwm_store_rxiq_calib_result(iwm); 354 if (ret < 0) {
325 set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); 355 /* Let's try the old way */
326 } 356 ret = iwm_init_calib(iwm, expected_calib_map,
327 357 expected_calib_map,
328 iwm_send_prio_table(iwm); 358 PHY_CALIBRATE_RX_IQ_CMD);
329 iwm_send_init_calib_cfg(iwm, init_calib_map); 359 if (ret < 0) {
330 360 IWM_ERR(iwm, "Calibration result timeout\n");
331 while (iwm->calib_done_map != init_calib_map) {
332 ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
333 IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
334 if (ret) {
335 IWM_ERR(iwm, "Wait for calibration result timeout\n");
336 goto out; 361 goto out;
337 } 362 }
338 IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
339 "0x%lx, requested calibrations: 0x%lx\n",
340 iwm->calib_done_map, init_calib_map);
341 } 363 }
342 364
343 /* Handle LMAC CALIBRATION_COMPLETE notification */ 365 /* Handle LMAC CALIBRATION_COMPLETE notification */
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
index da49df6f4020..74964ee93bb7 100644
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -64,6 +64,7 @@
64struct iwm_conf { 64struct iwm_conf {
65 u32 sdio_ior_timeout; 65 u32 sdio_ior_timeout;
66 unsigned long calib_map; 66 unsigned long calib_map;
67 unsigned long expected_calib_map;
67 bool reset_on_fatal_err; 68 bool reset_on_fatal_err;
68 bool auto_connect; 69 bool auto_connect;
69 bool wimax_not_present; 70 bool wimax_not_present;
diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h
index 19213e165f5f..6c1a14c4480f 100644
--- a/drivers/net/wireless/iwmc3200wifi/lmac.h
+++ b/drivers/net/wireless/iwmc3200wifi/lmac.h
@@ -396,9 +396,24 @@ enum {
396 CALIBRATION_CMD_NUM, 396 CALIBRATION_CMD_NUM,
397}; 397};
398 398
399enum {
400 CALIB_CFG_RX_BB_IDX = 0,
401 CALIB_CFG_DC_IDX = 1,
402 CALIB_CFG_LO_IDX = 2,
403 CALIB_CFG_TX_IQ_IDX = 3,
404 CALIB_CFG_RX_IQ_IDX = 4,
405 CALIB_CFG_NOISE_IDX = 5,
406 CALIB_CFG_CRYSTAL_IDX = 6,
407 CALIB_CFG_TEMPERATURE_IDX = 7,
408 CALIB_CFG_PAPD_IDX = 8,
409 CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX,
410 CALIB_CFG_MODULE_NUM,
411};
412
399#define IWM_CALIB_MAP_INIT_MSK 0xFFFF 413#define IWM_CALIB_MAP_INIT_MSK 0xFFFF
400#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) 414#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
401#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) 415#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24)
416#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM)
402 417
403struct iwm_lmac_calib_hdr { 418struct iwm_lmac_calib_hdr {
404 u8 opcode; 419 u8 opcode;
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index 6cf2f0c0911e..fc7fce44a9d7 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -53,7 +53,12 @@
53static struct iwm_conf def_iwm_conf = { 53static struct iwm_conf def_iwm_conf = {
54 54
55 .sdio_ior_timeout = 5000, 55 .sdio_ior_timeout = 5000,
56 .calib_map = BIT(PHY_CALIBRATE_DC_CMD) | 56 .calib_map = BIT(CALIB_CFG_DC_IDX) |
57 BIT(CALIB_CFG_LO_IDX) |
58 BIT(CALIB_CFG_TX_IQ_IDX) |
59 BIT(CALIB_CFG_RX_IQ_IDX) |
60 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
61 .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) |
57 BIT(PHY_CALIBRATE_LO_CMD) | 62 BIT(PHY_CALIBRATE_LO_CMD) |
58 BIT(PHY_CALIBRATE_TX_IQ_CMD) | 63 BIT(PHY_CALIBRATE_TX_IQ_CMD) |
59 BIT(PHY_CALIBRATE_RX_IQ_CMD) | 64 BIT(PHY_CALIBRATE_RX_IQ_CMD) |