aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
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
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')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c127
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-eeprom.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-hcmd.c4
7 files changed, 211 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index a94cd362fef..eb6141e6edb 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) &&
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index a637abe6efe..6f62beb1e4b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2778,10 +2778,59 @@ enum {
2778 IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD = 14, 2778 IWL5000_PHY_CALIBRATE_AGC_TABLE_CMD = 14,
2779 IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, 2779 IWL5000_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15,
2780 IWL5000_PHY_CALIBRATE_BASE_BAND_CMD = 16, 2780 IWL5000_PHY_CALIBRATE_BASE_BAND_CMD = 16,
2781 IWL5000_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17,
2781 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18, 2782 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18,
2782 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19, 2783 IWL5000_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19,
2783}; 2784};
2784 2785
2786enum {
2787 CALIBRATION_CFG_CMD = 0x65,
2788 CALIBRATION_RES_NOTIFICATION = 0x66,
2789 CALIBRATION_COMPLETE_NOTIFICATION = 0x67
2790};
2791
2792struct iwl_cal_crystal_freq_cmd {
2793 u8 cap_pin1;
2794 u8 cap_pin2;
2795} __attribute__ ((packed));
2796
2797struct iwl5000_calibration {
2798 u8 op_code;
2799 u8 first_group;
2800 u8 num_groups;
2801 u8 all_data_valid;
2802 struct iwl_cal_crystal_freq_cmd data;
2803} __attribute__ ((packed));
2804
2805#define IWL_CALIB_INIT_CFG_ALL __constant_cpu_to_le32(0xffffffff)
2806
2807struct iwl_calib_cfg_elmnt_s {
2808 __le32 is_enable;
2809 __le32 start;
2810 __le32 send_res;
2811 __le32 apply_res;
2812 __le32 reserved;
2813} __attribute__ ((packed));
2814
2815struct iwl_calib_cfg_status_s {
2816 struct iwl_calib_cfg_elmnt_s once;
2817 struct iwl_calib_cfg_elmnt_s perd;
2818 __le32 flags;
2819} __attribute__ ((packed));
2820
2821struct iwl5000_calib_cfg_cmd {
2822 struct iwl_calib_cfg_status_s ucd_calib_cfg;
2823 struct iwl_calib_cfg_status_s drv_calib_cfg;
2824 __le32 reserved1;
2825} __attribute__ ((packed));
2826
2827struct iwl5000_calib_hdr {
2828 u8 op_code;
2829 u8 first_group;
2830 u8 groups_num;
2831 u8 data_valid;
2832} __attribute__ ((packed));
2833
2785struct iwl5000_calibration_chain_noise_reset_cmd { 2834struct iwl5000_calibration_chain_noise_reset_cmd {
2786 u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ 2835 u8 op_code; /* IWL5000_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */
2787 u8 flags; /* not used */ 2836 u8 flags; /* not used */
@@ -2894,6 +2943,7 @@ struct iwl_rx_packet {
2894 struct iwl4965_notif_statistics stats; 2943 struct iwl4965_notif_statistics stats;
2895 struct iwl4965_compressed_ba_resp compressed_ba; 2944 struct iwl4965_compressed_ba_resp compressed_ba;
2896 struct iwl4965_missed_beacon_notif missed_beacon; 2945 struct iwl4965_missed_beacon_notif missed_beacon;
2946 struct iwl5000_calibration calib;
2897 __le32 status; 2947 __le32 status;
2898 u8 raw[0]; 2948 u8 raw[0];
2899 } u; 2949 } u;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 373e9847c37..010085aee5d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -871,9 +871,25 @@ err:
871} 871}
872EXPORT_SYMBOL(iwl_init_drv); 872EXPORT_SYMBOL(iwl_init_drv);
873 873
874void iwl_free_calib_results(struct iwl_priv *priv)
875{
876 kfree(priv->calib_results.lo_res);
877 priv->calib_results.lo_res = NULL;
878 priv->calib_results.lo_res_len = 0;
879
880 kfree(priv->calib_results.tx_iq_res);
881 priv->calib_results.tx_iq_res = NULL;
882 priv->calib_results.tx_iq_res_len = 0;
883
884 kfree(priv->calib_results.tx_iq_perd_res);
885 priv->calib_results.tx_iq_perd_res = NULL;
886 priv->calib_results.tx_iq_perd_res_len = 0;
887}
888EXPORT_SYMBOL(iwl_free_calib_results);
874 889
875void iwl_uninit_drv(struct iwl_priv *priv) 890void iwl_uninit_drv(struct iwl_priv *priv)
876{ 891{
892 iwl_free_calib_results(priv);
877 iwlcore_free_geos(priv); 893 iwlcore_free_geos(priv);
878 iwl_free_channel_map(priv); 894 iwl_free_channel_map(priv);
879} 895}
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 050549131c4..9d43085ead9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -172,6 +172,7 @@ struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg,
172void iwl_hw_detect(struct iwl_priv *priv); 172void iwl_hw_detect(struct iwl_priv *priv);
173 173
174void iwlcore_clear_stations_table(struct iwl_priv *priv); 174void iwlcore_clear_stations_table(struct iwl_priv *priv);
175void iwl_free_calib_results(struct iwl_priv *priv);
175void iwl_reset_qos(struct iwl_priv *priv); 176void iwl_reset_qos(struct iwl_priv *priv);
176void iwl_set_rxon_chain(struct iwl_priv *priv); 177void iwl_set_rxon_chain(struct iwl_priv *priv);
177int iwl_set_rxon_channel(struct iwl_priv *priv, 178int iwl_set_rxon_channel(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 2c92e55850c..291c1ec9b0d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -876,6 +876,15 @@ struct statistics_general_data {
876 u32 beacon_energy_c; 876 u32 beacon_energy_c;
877}; 877};
878 878
879struct iwl_calib_results {
880 void *tx_iq_res;
881 void *tx_iq_perd_res;
882 void *lo_res;
883 u32 tx_iq_res_len;
884 u32 tx_iq_perd_res_len;
885 u32 lo_res_len;
886};
887
879enum ucode_type { 888enum ucode_type {
880 UCODE_NONE = 0, 889 UCODE_NONE = 0,
881 UCODE_INIT, 890 UCODE_INIT,
@@ -983,6 +992,9 @@ struct iwl_priv {
983 s32 temperature; /* degrees Kelvin */ 992 s32 temperature; /* degrees Kelvin */
984 s32 last_temperature; 993 s32 last_temperature;
985 994
995 /* init calibration results */
996 struct iwl_calib_results calib_results;
997
986 /* Scan related variables */ 998 /* Scan related variables */
987 unsigned long last_scan_jiffies; 999 unsigned long last_scan_jiffies;
988 unsigned long next_scan_jiffies; 1000 unsigned long next_scan_jiffies;
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
index dc1f027c66a..d3a2a5b4ac5 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.h
@@ -146,6 +146,7 @@ struct iwl_eeprom_channel {
146 146
147/*5000 calibrations */ 147/*5000 calibrations */
148#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) 148#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION)
149#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL)
149 150
150/* 5000 links */ 151/* 5000 links */
151#define EEPROM_5000_LINK_HOST (2*0x64) 152#define EEPROM_5000_LINK_HOST (2*0x64)
diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
index dab4a0eff96..6c537360820 100644
--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
@@ -56,6 +56,7 @@ const char *get_cmd_string(u8 cmd)
56 IWL_CMD(REPLY_RATE_SCALE); 56 IWL_CMD(REPLY_RATE_SCALE);
57 IWL_CMD(REPLY_LEDS_CMD); 57 IWL_CMD(REPLY_LEDS_CMD);
58 IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); 58 IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
59 IWL_CMD(COEX_PRIORITY_TABLE_CMD);
59 IWL_CMD(RADAR_NOTIFICATION); 60 IWL_CMD(RADAR_NOTIFICATION);
60 IWL_CMD(REPLY_QUIET_CMD); 61 IWL_CMD(REPLY_QUIET_CMD);
61 IWL_CMD(REPLY_CHANNEL_SWITCH); 62 IWL_CMD(REPLY_CHANNEL_SWITCH);
@@ -89,6 +90,9 @@ const char *get_cmd_string(u8 cmd)
89 IWL_CMD(REPLY_RX_MPDU_CMD); 90 IWL_CMD(REPLY_RX_MPDU_CMD);
90 IWL_CMD(REPLY_RX); 91 IWL_CMD(REPLY_RX);
91 IWL_CMD(REPLY_COMPRESSED_BA); 92 IWL_CMD(REPLY_COMPRESSED_BA);
93 IWL_CMD(CALIBRATION_CFG_CMD);
94 IWL_CMD(CALIBRATION_RES_NOTIFICATION);
95 IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION);
92 default: 96 default:
93 return "UNKNOWN"; 97 return "UNKNOWN";
94 98