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