iwmc3200wifi: New initial LMAC calibration
authorSamuel Ortiz <sameo@linux.intel.com>
Tue, 1 Sep 2009 13:14:04 +0000 (15:14 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 1 Sep 2009 16:48:27 +0000 (12:48 -0400)
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>
drivers/net/wireless/iwmc3200wifi/fw.c
drivers/net/wireless/iwmc3200wifi/iwm.h
drivers/net/wireless/iwmc3200wifi/lmac.h
drivers/net/wireless/iwmc3200wifi/main.c

index 0f32cab9ced4daab9f418929dd2225eb89b98f12..6b0bcad758ca03c5db8796557a6aff8d90b50c89 100644 (file)
@@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
                        cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0);
 }
 
+static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap,
+                         unsigned long expected_bitmap, u8 rx_iq_cmd)
+{
+       /* Read RX IQ calibration result from EEPROM */
+       if (test_bit(rx_iq_cmd, &cfg_bitmap)) {
+               iwm_store_rxiq_calib_result(iwm);
+               set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
+       }
+
+       iwm_send_prio_table(iwm);
+       iwm_send_init_calib_cfg(iwm, cfg_bitmap);
+
+       while (iwm->calib_done_map != expected_bitmap) {
+               if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
+                                    IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) {
+                       IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n");
+                       return -ETIMEDOUT;
+               }
+
+               IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
+                          "0x%lx, expected calibrations: 0x%lx\n",
+                          iwm->calib_done_map, expected_bitmap);
+       }
+
+       return 0;
+}
+
 /*
  * We currently have to load 3 FWs:
  * 1) The UMAC (Upper MAC).
@@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name)
 int iwm_load_fw(struct iwm_priv *iwm)
 {
        unsigned long init_calib_map, periodic_calib_map;
+       unsigned long expected_calib_map;
        int ret;
 
        /* We first start downloading the UMAC */
@@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm)
        }
 
        init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK;
+       expected_calib_map = iwm->conf.expected_calib_map &
+               IWM_CALIB_MAP_INIT_MSK;
        periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
 
-       /* Read RX IQ calibration result from EEPROM */
-       if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) {
-               iwm_store_rxiq_calib_result(iwm);
-               set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map);
-       }
-
-       iwm_send_prio_table(iwm);
-       iwm_send_init_calib_cfg(iwm, init_calib_map);
-
-       while (iwm->calib_done_map != init_calib_map) {
-               ret = iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION,
-                                      IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT);
-               if (ret) {
-                       IWM_ERR(iwm, "Wait for calibration result timeout\n");
+       ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
+                            CALIB_CFG_RX_IQ_IDX);
+       if (ret < 0) {
+               /* Let's try the old way */
+               ret = iwm_init_calib(iwm, expected_calib_map,
+                                    expected_calib_map,
+                                    PHY_CALIBRATE_RX_IQ_CMD);
+               if (ret < 0) {
+                       IWM_ERR(iwm, "Calibration result timeout\n");
                        goto out;
                }
-               IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: "
-                          "0x%lx, requested calibrations: 0x%lx\n",
-                          iwm->calib_done_map, init_calib_map);
        }
 
        /* Handle LMAC CALIBRATION_COMPLETE notification */
index da49df6f4020c80a70d1b624f12bdf6f2a21e5f2..74964ee93bb7519915baa68bf9d5f35d774d4fda 100644 (file)
@@ -64,6 +64,7 @@
 struct iwm_conf {
        u32 sdio_ior_timeout;
        unsigned long calib_map;
+       unsigned long expected_calib_map;
        bool reset_on_fatal_err;
        bool auto_connect;
        bool wimax_not_present;
index 19213e165f5fa364e74be19df68e9666fa540c0b..6c1a14c4480f7deb654a979fc4455e4ebbb6e0f6 100644 (file)
@@ -396,9 +396,24 @@ enum {
        CALIBRATION_CMD_NUM,
 };
 
+enum {
+       CALIB_CFG_RX_BB_IDX       = 0,
+       CALIB_CFG_DC_IDX          = 1,
+       CALIB_CFG_LO_IDX          = 2,
+       CALIB_CFG_TX_IQ_IDX       = 3,
+       CALIB_CFG_RX_IQ_IDX       = 4,
+       CALIB_CFG_NOISE_IDX       = 5,
+       CALIB_CFG_CRYSTAL_IDX     = 6,
+       CALIB_CFG_TEMPERATURE_IDX = 7,
+       CALIB_CFG_PAPD_IDX        = 8,
+       CALIB_CFG_LAST_IDX        = CALIB_CFG_PAPD_IDX,
+       CALIB_CFG_MODULE_NUM,
+};
+
 #define IWM_CALIB_MAP_INIT_MSK         0xFFFF
 #define IWM_CALIB_MAP_PER_LMAC(m)      ((m & 0xFF0000) >> 16)
 #define IWM_CALIB_MAP_PER_UMAC(m)      ((m & 0xFF000000) >> 24)
+#define IWM_CALIB_OPCODE_TO_INDEX(op)   (op - PHY_CALIBRATE_OPCODES_NUM)
 
 struct iwm_lmac_calib_hdr {
        u8 opcode;
index 6cf2f0c0911eca8ed395bd77843e13c16d418675..fc7fce44a9d795c129d90838ca441bce6682129d 100644 (file)
 static struct iwm_conf def_iwm_conf = {
 
        .sdio_ior_timeout       = 5000,
-       .calib_map              = BIT(PHY_CALIBRATE_DC_CMD)     |
+       .calib_map              = BIT(CALIB_CFG_DC_IDX) |
+                                 BIT(CALIB_CFG_LO_IDX) |
+                                 BIT(CALIB_CFG_TX_IQ_IDX)      |
+                                 BIT(CALIB_CFG_RX_IQ_IDX)      |
+                                 BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD),
+       .expected_calib_map     = BIT(PHY_CALIBRATE_DC_CMD)     |
                                  BIT(PHY_CALIBRATE_LO_CMD)     |
                                  BIT(PHY_CALIBRATE_TX_IQ_CMD)  |
                                  BIT(PHY_CALIBRATE_RX_IQ_CMD)  |