diff options
author | Samuel Ortiz <sameo@linux.intel.com> | 2009-09-01 09:14:04 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-09-01 12:48:27 -0400 |
commit | d04bd6283cf7433d56f3d8f648f1d6963fda4fdc (patch) | |
tree | c67d1898aa854b7edf6ede235327e9feae7e96a2 | |
parent | 31452420ca956f2cf37f705c869e265c33894f07 (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.c | 56 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/iwm.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/lmac.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/iwmc3200wifi/main.c | 7 |
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 | ||
264 | static 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) | |||
276 | int iwm_load_fw(struct iwm_priv *iwm) | 303 | int 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 @@ | |||
64 | struct iwm_conf { | 64 | struct 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 | ||
399 | enum { | ||
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 | ||
403 | struct iwm_lmac_calib_hdr { | 418 | struct 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 @@ | |||
53 | static struct iwm_conf def_iwm_conf = { | 53 | static 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) | |