aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-5000.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-05-29 04:35:05 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-03 15:00:23 -0400
commit7c616cba240cd0d579c996be3f3603456acfb0ad (patch)
tree9c0a4594423b12138c1c430dac8063b4a437e1cd /drivers/net/wireless/iwlwifi/iwl-5000.c
parentc135475439f75e6eb29e7586d33f3e22a61c1bb4 (diff)
iwlwifi-5000: implement initial calibration for 5000
This patch adds initial calibration framework for 5000 HW faimily. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Signed-off-by: Ron Rindjunsky <ron.rindjunsky@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-5000.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a94cd362fef5..eb6141e6edbc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -395,6 +395,8 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
395 395
396#endif /* CONFIG_IWL5000_RUN_TIME_CALIB */ 396#endif /* CONFIG_IWL5000_RUN_TIME_CALIB */
397 397
398
399
398static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, 400static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
399 size_t offset) 401 size_t offset)
400{ 402{
@@ -404,6 +406,118 @@ static const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv,
404} 406}
405 407
406/* 408/*
409 * Calibration
410 */
411static int iwl5000_send_Xtal_calib(struct iwl_priv *priv)
412{
413 u16 *xtal_calib = (u16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL);
414
415 struct iwl5000_calibration cal_cmd = {
416 .op_code = IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD,
417 .data = {
418 (u8)xtal_calib[0],
419 (u8)xtal_calib[1],
420 }
421 };
422
423 return iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
424 sizeof(cal_cmd), &cal_cmd);
425}
426
427static int iwl5000_send_calib_results(struct iwl_priv *priv)
428{
429 int ret = 0;
430
431 if (priv->calib_results.lo_res)
432 ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
433 priv->calib_results.lo_res_len,
434 priv->calib_results.lo_res);
435 if (ret)
436 goto err;
437
438
439 if (priv->calib_results.tx_iq_res)
440 ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
441 priv->calib_results.tx_iq_res_len,
442 priv->calib_results.tx_iq_res);
443
444 if (ret)
445 goto err;
446
447 if (priv->calib_results.tx_iq_perd_res)
448 ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
449 priv->calib_results.tx_iq_perd_res_len,
450 priv->calib_results.tx_iq_perd_res);
451 if (ret)
452 goto err;
453
454 return 0;
455err:
456 IWL_ERROR("Error %d\n", ret);
457 return ret;
458}
459
460static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
461{
462 struct iwl5000_calib_cfg_cmd calib_cfg_cmd;
463 struct iwl_host_cmd cmd = {
464 .id = CALIBRATION_CFG_CMD,
465 .len = sizeof(struct iwl5000_calib_cfg_cmd),
466 .data = &calib_cfg_cmd,
467 };
468
469 memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
470 calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
471 calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
472 calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
473 calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL;
474
475 return iwl_send_cmd(priv, &cmd);
476}
477
478static void iwl5000_rx_calib_result(struct iwl_priv *priv,
479 struct iwl_rx_mem_buffer *rxb)
480{
481 struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
482 struct iwl5000_calib_hdr *hdr = (struct iwl5000_calib_hdr *)pkt->u.raw;
483 int len = le32_to_cpu(pkt->len) & FH_RSCSR_FRAME_SIZE_MSK;
484
485 iwl_free_calib_results(priv);
486
487 /* reduce the size of the length field itself */
488 len -= 4;
489
490 switch (hdr->op_code) {
491 case IWL5000_PHY_CALIBRATE_LO_CMD:
492 priv->calib_results.lo_res = kzalloc(len, GFP_ATOMIC);
493 priv->calib_results.lo_res_len = len;
494 memcpy(priv->calib_results.lo_res, pkt->u.raw, len);
495 break;
496 case IWL5000_PHY_CALIBRATE_TX_IQ_CMD:
497 priv->calib_results.tx_iq_res = kzalloc(len, GFP_ATOMIC);
498 priv->calib_results.tx_iq_res_len = len;
499 memcpy(priv->calib_results.tx_iq_res, pkt->u.raw, len);
500 break;
501 case IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD:
502 priv->calib_results.tx_iq_perd_res = kzalloc(len, GFP_ATOMIC);
503 priv->calib_results.tx_iq_perd_res_len = len;
504 memcpy(priv->calib_results.tx_iq_perd_res, pkt->u.raw, len);
505 break;
506 default:
507 IWL_ERROR("Unknown calibration notification %d\n",
508 hdr->op_code);
509 return;
510 }
511}
512
513static void iwl5000_rx_calib_complete(struct iwl_priv *priv,
514 struct iwl_rx_mem_buffer *rxb)
515{
516 IWL_DEBUG_INFO("Init. calibration is completed, restarting fw.\n");
517 queue_work(priv->workqueue, &priv->restart);
518}
519
520/*
407 * ucode 521 * ucode
408 */ 522 */
409static int iwl5000_load_section(struct iwl_priv *priv, 523static int iwl5000_load_section(struct iwl_priv *priv,
@@ -565,6 +679,7 @@ static void iwl5000_init_alive_start(struct iwl_priv *priv)
565 goto restart; 679 goto restart;
566 } 680 }
567 681
682 iwl5000_send_calib_cfg(priv);
568 return; 683 return;
569 684
570restart: 685restart:
@@ -684,8 +799,14 @@ static int iwl5000_alive_notify(struct iwl_priv *priv)
684 iwl_release_nic_access(priv); 799 iwl_release_nic_access(priv);
685 spin_unlock_irqrestore(&priv->lock, flags); 800 spin_unlock_irqrestore(&priv->lock, flags);
686 801
802
687 iwl5000_send_wimax_coex(priv); 803 iwl5000_send_wimax_coex(priv);
688 804
805 iwl5000_send_Xtal_calib(priv);
806
807 if (priv->ucode_type == UCODE_RT)
808 iwl5000_send_calib_results(priv);
809
689 return 0; 810 return 0;
690} 811}
691 812
@@ -856,8 +977,14 @@ static u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len)
856 977
857static void iwl5000_rx_handler_setup(struct iwl_priv *priv) 978static void iwl5000_rx_handler_setup(struct iwl_priv *priv)
858{ 979{
980 /* init calibration handlers */
981 priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] =
982 iwl5000_rx_calib_result;
983 priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
984 iwl5000_rx_calib_complete;
859} 985}
860 986
987
861static int iwl5000_hw_valid_rtc_data_addr(u32 addr) 988static int iwl5000_hw_valid_rtc_data_addr(u32 addr)
862{ 989{
863 return (addr >= RTC_DATA_LOWER_BOUND) && 990 return (addr >= RTC_DATA_LOWER_BOUND) &&