Commit d04bd628 authored by Samuel Ortiz's avatar Samuel Ortiz Committed by John W. Linville

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: default avatarSamuel Ortiz <sameo@linux.intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 31452420
...@@ -261,6 +261,33 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) ...@@ -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); 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: * We currently have to load 3 FWs:
* 1) The UMAC (Upper MAC). * 1) The UMAC (Upper MAC).
...@@ -276,6 +303,7 @@ static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) ...@@ -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) int iwm_load_fw(struct iwm_priv *iwm)
{ {
unsigned long init_calib_map, periodic_calib_map; unsigned long init_calib_map, periodic_calib_map;
unsigned long expected_calib_map;
int ret; int ret;
/* We first start downloading the UMAC */ /* We first start downloading the UMAC */
...@@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm) ...@@ -317,27 +345,21 @@ int iwm_load_fw(struct iwm_priv *iwm)
} }
init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; 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); periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map);
/* Read RX IQ calibration result from EEPROM */ ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map,
if (test_bit(PHY_CALIBRATE_RX_IQ_CMD, &init_calib_map)) { CALIB_CFG_RX_IQ_IDX);
iwm_store_rxiq_calib_result(iwm); if (ret < 0) {
set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); /* Let's try the old way */
} ret = iwm_init_calib(iwm, expected_calib_map,
expected_calib_map,
iwm_send_prio_table(iwm); PHY_CALIBRATE_RX_IQ_CMD);
iwm_send_init_calib_cfg(iwm, init_calib_map); if (ret < 0) {
IWM_ERR(iwm, "Calibration result timeout\n");
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");
goto out; 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 */ /* Handle LMAC CALIBRATION_COMPLETE notification */
......
...@@ -64,6 +64,7 @@ ...@@ -64,6 +64,7 @@
struct iwm_conf { struct iwm_conf {
u32 sdio_ior_timeout; u32 sdio_ior_timeout;
unsigned long calib_map; unsigned long calib_map;
unsigned long expected_calib_map;
bool reset_on_fatal_err; bool reset_on_fatal_err;
bool auto_connect; bool auto_connect;
bool wimax_not_present; bool wimax_not_present;
......
...@@ -396,9 +396,24 @@ enum { ...@@ -396,9 +396,24 @@ enum {
CALIBRATION_CMD_NUM, 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_INIT_MSK 0xFFFF
#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) #define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16)
#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) #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 { struct iwm_lmac_calib_hdr {
u8 opcode; u8 opcode;
......
...@@ -53,7 +53,12 @@ ...@@ -53,7 +53,12 @@
static struct iwm_conf def_iwm_conf = { static struct iwm_conf def_iwm_conf = {
.sdio_ior_timeout = 5000, .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_LO_CMD) |
BIT(PHY_CALIBRATE_TX_IQ_CMD) | BIT(PHY_CALIBRATE_TX_IQ_CMD) |
BIT(PHY_CALIBRATE_RX_IQ_CMD) | BIT(PHY_CALIBRATE_RX_IQ_CMD) |
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment