1 // SPDX-License-Identifier: GPL-2.0-only 2 /****************************************************************************** 3 * 4 * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. 5 * Copyright(c) 2015 Intel Deutschland GmbH 6 * 7 * Contact Information: 8 * Intel Linux Wireless <linuxwifi@intel.com> 9 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 10 * 11 *****************************************************************************/ 12 13 #include <linux/kernel.h> 14 15 #include "iwl-io.h" 16 #include "iwl-agn-hw.h" 17 #include "iwl-trans.h" 18 #include "iwl-fh.h" 19 #include "iwl-op-mode.h" 20 21 #include "dev.h" 22 #include "agn.h" 23 #include "calib.h" 24 25 /****************************************************************************** 26 * 27 * uCode download functions 28 * 29 ******************************************************************************/ 30 31 /* 32 * Calibration 33 */ 34 static int iwl_set_Xtal_calib(struct iwl_priv *priv) 35 { 36 struct iwl_calib_xtal_freq_cmd cmd; 37 __le16 *xtal_calib = priv->nvm_data->xtal_calib; 38 39 iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD); 40 cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); 41 cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); 42 return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); 43 } 44 45 static int iwl_set_temperature_offset_calib(struct iwl_priv *priv) 46 { 47 struct iwl_calib_temperature_offset_cmd cmd; 48 49 memset(&cmd, 0, sizeof(cmd)); 50 iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); 51 cmd.radio_sensor_offset = priv->nvm_data->raw_temperature; 52 if (!(cmd.radio_sensor_offset)) 53 cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET; 54 55 IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n", 56 le16_to_cpu(cmd.radio_sensor_offset)); 57 return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); 58 } 59 60 static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv) 61 { 62 struct iwl_calib_temperature_offset_v2_cmd cmd; 63 64 memset(&cmd, 0, sizeof(cmd)); 65 iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD); 66 cmd.radio_sensor_offset_high = priv->nvm_data->kelvin_temperature; 67 cmd.radio_sensor_offset_low = priv->nvm_data->raw_temperature; 68 if (!cmd.radio_sensor_offset_low) { 69 IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n"); 70 cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET; 71 cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET; 72 } 73 cmd.burntVoltageRef = priv->nvm_data->calib_voltage; 74 75 IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n", 76 le16_to_cpu(cmd.radio_sensor_offset_high)); 77 IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n", 78 le16_to_cpu(cmd.radio_sensor_offset_low)); 79 IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n", 80 le16_to_cpu(cmd.burntVoltageRef)); 81 82 return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd)); 83 } 84 85 static int iwl_send_calib_cfg(struct iwl_priv *priv) 86 { 87 struct iwl_calib_cfg_cmd calib_cfg_cmd; 88 struct iwl_host_cmd cmd = { 89 .id = CALIBRATION_CFG_CMD, 90 .len = { sizeof(struct iwl_calib_cfg_cmd), }, 91 .data = { &calib_cfg_cmd, }, 92 }; 93 94 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); 95 calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; 96 calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; 97 calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; 98 calib_cfg_cmd.ucd_calib_cfg.flags = 99 IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK; 100 101 return iwl_dvm_send_cmd(priv, &cmd); 102 } 103 104 int iwl_init_alive_start(struct iwl_priv *priv) 105 { 106 int ret; 107 108 if (priv->lib->bt_params && 109 priv->lib->bt_params->advanced_bt_coexist) { 110 /* 111 * Tell uCode we are ready to perform calibration 112 * need to perform this before any calibration 113 * no need to close the envlope since we are going 114 * to load the runtime uCode later. 115 */ 116 ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN, 117 BT_COEX_PRIO_TBL_EVT_INIT_CALIB2); 118 if (ret) 119 return ret; 120 121 } 122 123 ret = iwl_send_calib_cfg(priv); 124 if (ret) 125 return ret; 126 127 /** 128 * temperature offset calibration is only needed for runtime ucode, 129 * so prepare the value now. 130 */ 131 if (priv->lib->need_temp_offset_calib) { 132 if (priv->lib->temp_offset_v2) 133 return iwl_set_temperature_offset_calib_v2(priv); 134 else 135 return iwl_set_temperature_offset_calib(priv); 136 } 137 138 return 0; 139 } 140 141 static int iwl_send_wimax_coex(struct iwl_priv *priv) 142 { 143 struct iwl_wimax_coex_cmd coex_cmd; 144 145 /* coexistence is disabled */ 146 memset(&coex_cmd, 0, sizeof(coex_cmd)); 147 148 return iwl_dvm_send_cmd_pdu(priv, 149 COEX_PRIORITY_TABLE_CMD, 0, 150 sizeof(coex_cmd), &coex_cmd); 151 } 152 153 static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { 154 ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 155 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 156 ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 157 (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 158 ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 159 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 160 ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 161 (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 162 ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 163 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 164 ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 165 (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 166 ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 167 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 168 ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 169 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 170 ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) | 171 (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)), 172 0, 0, 0, 0, 0, 0, 0 173 }; 174 175 void iwl_send_prio_tbl(struct iwl_priv *priv) 176 { 177 struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd; 178 179 memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl, 180 sizeof(iwl_bt_prio_tbl)); 181 if (iwl_dvm_send_cmd_pdu(priv, 182 REPLY_BT_COEX_PRIO_TABLE, 0, 183 sizeof(prio_tbl_cmd), &prio_tbl_cmd)) 184 IWL_ERR(priv, "failed to send BT prio tbl command\n"); 185 } 186 187 int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type) 188 { 189 struct iwl_bt_coex_prot_env_cmd env_cmd; 190 int ret; 191 192 env_cmd.action = action; 193 env_cmd.type = type; 194 ret = iwl_dvm_send_cmd_pdu(priv, 195 REPLY_BT_COEX_PROT_ENV, 0, 196 sizeof(env_cmd), &env_cmd); 197 if (ret) 198 IWL_ERR(priv, "failed to send BT env command\n"); 199 return ret; 200 } 201 202 static const u8 iwlagn_default_queue_to_tx_fifo[] = { 203 IWL_TX_FIFO_VO, 204 IWL_TX_FIFO_VI, 205 IWL_TX_FIFO_BE, 206 IWL_TX_FIFO_BK, 207 }; 208 209 static const u8 iwlagn_ipan_queue_to_tx_fifo[] = { 210 IWL_TX_FIFO_VO, 211 IWL_TX_FIFO_VI, 212 IWL_TX_FIFO_BE, 213 IWL_TX_FIFO_BK, 214 IWL_TX_FIFO_BK_IPAN, 215 IWL_TX_FIFO_BE_IPAN, 216 IWL_TX_FIFO_VI_IPAN, 217 IWL_TX_FIFO_VO_IPAN, 218 IWL_TX_FIFO_BE_IPAN, 219 IWL_TX_FIFO_UNUSED, 220 IWL_TX_FIFO_AUX, 221 }; 222 223 static int iwl_alive_notify(struct iwl_priv *priv) 224 { 225 const u8 *queue_to_txf; 226 u8 n_queues; 227 int ret; 228 int i; 229 230 iwl_trans_fw_alive(priv->trans, 0); 231 232 if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN && 233 priv->nvm_data->sku_cap_ipan_enable) { 234 n_queues = ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo); 235 queue_to_txf = iwlagn_ipan_queue_to_tx_fifo; 236 } else { 237 n_queues = ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo); 238 queue_to_txf = iwlagn_default_queue_to_tx_fifo; 239 } 240 241 for (i = 0; i < n_queues; i++) 242 if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED) 243 iwl_trans_ac_txq_enable(priv->trans, i, 244 queue_to_txf[i], 0); 245 246 priv->passive_no_rx = false; 247 priv->transport_queue_stop = 0; 248 249 ret = iwl_send_wimax_coex(priv); 250 if (ret) 251 return ret; 252 253 if (!priv->lib->no_xtal_calib) { 254 ret = iwl_set_Xtal_calib(priv); 255 if (ret) 256 return ret; 257 } 258 259 return iwl_send_calib_results(priv); 260 } 261 262 struct iwl_alive_data { 263 bool valid; 264 u8 subtype; 265 }; 266 267 static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait, 268 struct iwl_rx_packet *pkt, void *data) 269 { 270 struct iwl_priv *priv = 271 container_of(notif_wait, struct iwl_priv, notif_wait); 272 struct iwl_alive_data *alive_data = data; 273 struct iwl_alive_resp *palive; 274 275 palive = (void *)pkt->data; 276 277 IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision " 278 "0x%01X 0x%01X\n", 279 palive->is_valid, palive->ver_type, 280 palive->ver_subtype); 281 282 priv->device_pointers.error_event_table = 283 le32_to_cpu(palive->error_event_table_ptr); 284 priv->device_pointers.log_event_table = 285 le32_to_cpu(palive->log_event_table_ptr); 286 287 alive_data->subtype = palive->ver_subtype; 288 alive_data->valid = palive->is_valid == UCODE_VALID_OK; 289 290 return true; 291 } 292 293 #define UCODE_ALIVE_TIMEOUT HZ 294 #define UCODE_CALIB_TIMEOUT (2*HZ) 295 296 int iwl_load_ucode_wait_alive(struct iwl_priv *priv, 297 enum iwl_ucode_type ucode_type) 298 { 299 struct iwl_notification_wait alive_wait; 300 struct iwl_alive_data alive_data; 301 const struct fw_img *fw; 302 int ret; 303 enum iwl_ucode_type old_type; 304 static const u16 alive_cmd[] = { REPLY_ALIVE }; 305 306 fw = iwl_get_ucode_image(priv->fw, ucode_type); 307 if (WARN_ON(!fw)) 308 return -EINVAL; 309 310 old_type = priv->cur_ucode; 311 priv->cur_ucode = ucode_type; 312 priv->ucode_loaded = false; 313 314 iwl_init_notification_wait(&priv->notif_wait, &alive_wait, 315 alive_cmd, ARRAY_SIZE(alive_cmd), 316 iwl_alive_fn, &alive_data); 317 318 ret = iwl_trans_start_fw(priv->trans, fw, false); 319 if (ret) { 320 priv->cur_ucode = old_type; 321 iwl_remove_notification(&priv->notif_wait, &alive_wait); 322 return ret; 323 } 324 325 /* 326 * Some things may run in the background now, but we 327 * just wait for the ALIVE notification here. 328 */ 329 ret = iwl_wait_notification(&priv->notif_wait, &alive_wait, 330 UCODE_ALIVE_TIMEOUT); 331 if (ret) { 332 priv->cur_ucode = old_type; 333 return ret; 334 } 335 336 if (!alive_data.valid) { 337 IWL_ERR(priv, "Loaded ucode is not valid!\n"); 338 priv->cur_ucode = old_type; 339 return -EIO; 340 } 341 342 priv->ucode_loaded = true; 343 344 if (ucode_type != IWL_UCODE_WOWLAN) { 345 /* delay a bit to give rfkill time to run */ 346 msleep(5); 347 } 348 349 ret = iwl_alive_notify(priv); 350 if (ret) { 351 IWL_WARN(priv, 352 "Could not complete ALIVE transition: %d\n", ret); 353 priv->cur_ucode = old_type; 354 return ret; 355 } 356 357 return 0; 358 } 359 360 static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait, 361 struct iwl_rx_packet *pkt, void *data) 362 { 363 struct iwl_priv *priv = data; 364 struct iwl_calib_hdr *hdr; 365 366 if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) { 367 WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION); 368 return true; 369 } 370 371 hdr = (struct iwl_calib_hdr *)pkt->data; 372 373 if (iwl_calib_set(priv, hdr, iwl_rx_packet_payload_len(pkt))) 374 IWL_ERR(priv, "Failed to record calibration data %d\n", 375 hdr->op_code); 376 377 return false; 378 } 379 380 int iwl_run_init_ucode(struct iwl_priv *priv) 381 { 382 struct iwl_notification_wait calib_wait; 383 static const u16 calib_complete[] = { 384 CALIBRATION_RES_NOTIFICATION, 385 CALIBRATION_COMPLETE_NOTIFICATION 386 }; 387 int ret; 388 389 lockdep_assert_held(&priv->mutex); 390 391 /* No init ucode required? Curious, but maybe ok */ 392 if (!priv->fw->img[IWL_UCODE_INIT].num_sec) 393 return 0; 394 395 iwl_init_notification_wait(&priv->notif_wait, &calib_wait, 396 calib_complete, ARRAY_SIZE(calib_complete), 397 iwlagn_wait_calib, priv); 398 399 /* Will also start the device */ 400 ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT); 401 if (ret) 402 goto error; 403 404 ret = iwl_init_alive_start(priv); 405 if (ret) 406 goto error; 407 408 /* 409 * Some things may run in the background now, but we 410 * just wait for the calibration complete notification. 411 */ 412 ret = iwl_wait_notification(&priv->notif_wait, &calib_wait, 413 UCODE_CALIB_TIMEOUT); 414 415 goto out; 416 417 error: 418 iwl_remove_notification(&priv->notif_wait, &calib_wait); 419 out: 420 /* Whatever happened, stop the device */ 421 iwl_trans_stop_device(priv->trans); 422 priv->ucode_loaded = false; 423 424 return ret; 425 } 426