aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h9
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c88
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h12
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00config.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00lib.h13
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00link.c39
10 files changed, 171 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index 06acabd0298..62e697ffc6d 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -965,6 +965,7 @@
965 * TX_PIN_CFG: 965 * TX_PIN_CFG:
966 */ 966 */
967#define TX_PIN_CFG 0x1328 967#define TX_PIN_CFG 0x1328
968#define TX_PIN_CFG_PA_PE_DISABLE 0xfcfffff0
968#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) 969#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001)
969#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) 970#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002)
970#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) 971#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004)
@@ -985,6 +986,14 @@
985#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) 986#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000)
986#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) 987#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000)
987#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) 988#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000)
989#define TX_PIN_CFG_PA_PE_A2_EN FIELD32(0x01000000)
990#define TX_PIN_CFG_PA_PE_G2_EN FIELD32(0x02000000)
991#define TX_PIN_CFG_PA_PE_A2_POL FIELD32(0x04000000)
992#define TX_PIN_CFG_PA_PE_G2_POL FIELD32(0x08000000)
993#define TX_PIN_CFG_LNA_PE_A2_EN FIELD32(0x10000000)
994#define TX_PIN_CFG_LNA_PE_G2_EN FIELD32(0x20000000)
995#define TX_PIN_CFG_LNA_PE_A2_POL FIELD32(0x40000000)
996#define TX_PIN_CFG_LNA_PE_G2_POL FIELD32(0x80000000)
988 997
989/* 998/*
990 * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz 999 * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index f1df929e97a..6104a14e4ff 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -2497,6 +2497,80 @@ void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev)
2497} 2497}
2498EXPORT_SYMBOL_GPL(rt2800_gain_calibration); 2498EXPORT_SYMBOL_GPL(rt2800_gain_calibration);
2499 2499
2500void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev)
2501{
2502 u32 tx_pin;
2503 u8 rfcsr;
2504
2505 /*
2506 * A voltage-controlled oscillator(VCO) is an electronic oscillator
2507 * designed to be controlled in oscillation frequency by a voltage
2508 * input. Maybe the temperature will affect the frequency of
2509 * oscillation to be shifted. The VCO calibration will be called
2510 * periodically to adjust the frequency to be precision.
2511 */
2512
2513 rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
2514 tx_pin &= TX_PIN_CFG_PA_PE_DISABLE;
2515 rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
2516
2517 switch (rt2x00dev->chip.rf) {
2518 case RF2020:
2519 case RF3020:
2520 case RF3021:
2521 case RF3022:
2522 case RF3320:
2523 case RF3052:
2524 rt2800_rfcsr_read(rt2x00dev, 7, &rfcsr);
2525 rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1);
2526 rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
2527 break;
2528 case RF5370:
2529 case RF5372:
2530 case RF5390:
2531 rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
2532 rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
2533 rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
2534 break;
2535 default:
2536 return;
2537 }
2538
2539 mdelay(1);
2540
2541 rt2800_register_read(rt2x00dev, TX_PIN_CFG, &tx_pin);
2542 if (rt2x00dev->rf_channel <= 14) {
2543 switch (rt2x00dev->default_ant.tx_chain_num) {
2544 case 3:
2545 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G2_EN, 1);
2546 /* fall through */
2547 case 2:
2548 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1);
2549 /* fall through */
2550 case 1:
2551 default:
2552 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, 1);
2553 break;
2554 }
2555 } else {
2556 switch (rt2x00dev->default_ant.tx_chain_num) {
2557 case 3:
2558 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A2_EN, 1);
2559 /* fall through */
2560 case 2:
2561 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1);
2562 /* fall through */
2563 case 1:
2564 default:
2565 rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, 1);
2566 break;
2567 }
2568 }
2569 rt2800_register_write(rt2x00dev, TX_PIN_CFG, tx_pin);
2570
2571}
2572EXPORT_SYMBOL_GPL(rt2800_vco_calibration);
2573
2500static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev, 2574static void rt2800_config_retry_limit(struct rt2x00_dev *rt2x00dev,
2501 struct rt2x00lib_conf *libconf) 2575 struct rt2x00lib_conf *libconf)
2502{ 2576{
@@ -4451,6 +4525,20 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
4451 } 4525 }
4452 } 4526 }
4453 4527
4528 switch (rt2x00dev->chip.rf) {
4529 case RF2020:
4530 case RF3020:
4531 case RF3021:
4532 case RF3022:
4533 case RF3320:
4534 case RF3052:
4535 case RF5370:
4536 case RF5372:
4537 case RF5390:
4538 __set_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags);
4539 break;
4540 }
4541
4454 return 0; 4542 return 0;
4455} 4543}
4456EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode); 4544EXPORT_SYMBOL_GPL(rt2800_probe_hw_mode);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.h b/drivers/net/wireless/rt2x00/rt2800lib.h
index 8c3c281904f..419e36cb06b 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.h
+++ b/drivers/net/wireless/rt2x00/rt2800lib.h
@@ -184,6 +184,7 @@ void rt2800_reset_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual);
184void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual, 184void rt2800_link_tuner(struct rt2x00_dev *rt2x00dev, struct link_qual *qual,
185 const u32 count); 185 const u32 count);
186void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev); 186void rt2800_gain_calibration(struct rt2x00_dev *rt2x00dev);
187void rt2800_vco_calibration(struct rt2x00_dev *rt2x00dev);
187 188
188int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev); 189int rt2800_enable_radio(struct rt2x00_dev *rt2x00dev);
189void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev); 190void rt2800_disable_radio(struct rt2x00_dev *rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 6ad692914ee..fc9acc299b1 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -1050,6 +1050,7 @@ static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
1050 .reset_tuner = rt2800_reset_tuner, 1050 .reset_tuner = rt2800_reset_tuner,
1051 .link_tuner = rt2800_link_tuner, 1051 .link_tuner = rt2800_link_tuner,
1052 .gain_calibration = rt2800_gain_calibration, 1052 .gain_calibration = rt2800_gain_calibration,
1053 .vco_calibration = rt2800_vco_calibration,
1053 .start_queue = rt2800pci_start_queue, 1054 .start_queue = rt2800pci_start_queue,
1054 .kick_queue = rt2800pci_kick_queue, 1055 .kick_queue = rt2800pci_kick_queue,
1055 .stop_queue = rt2800pci_stop_queue, 1056 .stop_queue = rt2800pci_stop_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 0074c4e18d2..f997f0056d7 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -781,6 +781,7 @@ static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = {
781 .reset_tuner = rt2800_reset_tuner, 781 .reset_tuner = rt2800_reset_tuner,
782 .link_tuner = rt2800_link_tuner, 782 .link_tuner = rt2800_link_tuner,
783 .gain_calibration = rt2800_gain_calibration, 783 .gain_calibration = rt2800_gain_calibration,
784 .vco_calibration = rt2800_vco_calibration,
784 .watchdog = rt2800usb_watchdog, 785 .watchdog = rt2800usb_watchdog,
785 .start_queue = rt2800usb_start_queue, 786 .start_queue = rt2800usb_start_queue,
786 .kick_queue = rt2x00usb_kick_queue, 787 .kick_queue = rt2x00usb_kick_queue,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index ed2ae6efcaa..1906a94e448 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -355,6 +355,11 @@ struct link {
355 * Work structure for scheduling periodic AGC adjustments. 355 * Work structure for scheduling periodic AGC adjustments.
356 */ 356 */
357 struct delayed_work agc_work; 357 struct delayed_work agc_work;
358
359 /*
360 * Work structure for scheduling periodic VCO calibration.
361 */
362 struct delayed_work vco_work;
358}; 363};
359 364
360enum rt2x00_delayed_flags { 365enum rt2x00_delayed_flags {
@@ -579,6 +584,7 @@ struct rt2x00lib_ops {
579 void (*link_tuner) (struct rt2x00_dev *rt2x00dev, 584 void (*link_tuner) (struct rt2x00_dev *rt2x00dev,
580 struct link_qual *qual, const u32 count); 585 struct link_qual *qual, const u32 count);
581 void (*gain_calibration) (struct rt2x00_dev *rt2x00dev); 586 void (*gain_calibration) (struct rt2x00_dev *rt2x00dev);
587 void (*vco_calibration) (struct rt2x00_dev *rt2x00dev);
582 588
583 /* 589 /*
584 * Data queue handlers. 590 * Data queue handlers.
@@ -722,6 +728,7 @@ enum rt2x00_capability_flags {
722 CAPABILITY_EXTERNAL_LNA_BG, 728 CAPABILITY_EXTERNAL_LNA_BG,
723 CAPABILITY_DOUBLE_ANTENNA, 729 CAPABILITY_DOUBLE_ANTENNA,
724 CAPABILITY_BT_COEXIST, 730 CAPABILITY_BT_COEXIST,
731 CAPABILITY_VCO_RECALIBRATION,
725}; 732};
726 733
727/* 734/*
@@ -978,6 +985,11 @@ struct rt2x00_dev {
978 struct tasklet_struct autowake_tasklet; 985 struct tasklet_struct autowake_tasklet;
979 986
980 /* 987 /*
988 * Used for VCO periodic calibration.
989 */
990 int rf_channel;
991
992 /*
981 * Protect the interrupt mask register. 993 * Protect the interrupt mask register.
982 */ 994 */
983 spinlock_t irqmask_lock; 995 spinlock_t irqmask_lock;
diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c
index b704e5b183d..d7c0f86c9e4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00config.c
+++ b/drivers/net/wireless/rt2x00/rt2x00config.c
@@ -232,6 +232,9 @@ void rt2x00lib_config(struct rt2x00_dev *rt2x00dev,
232 memcpy(&libconf.channel, 232 memcpy(&libconf.channel,
233 &rt2x00dev->spec.channels_info[hw_value], 233 &rt2x00dev->spec.channels_info[hw_value],
234 sizeof(libconf.channel)); 234 sizeof(libconf.channel));
235
236 /* Used for VCO periodic calibration */
237 rt2x00dev->rf_channel = libconf.rf.channel;
235 } 238 }
236 239
237 if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) && 240 if (test_bit(REQUIRE_PS_AUTOWAKE, &rt2x00dev->cap_flags) &&
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index bae5b01299e..dfe485a872f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -88,6 +88,8 @@ int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev)
88 rt2x00queue_start_queues(rt2x00dev); 88 rt2x00queue_start_queues(rt2x00dev);
89 rt2x00link_start_tuner(rt2x00dev); 89 rt2x00link_start_tuner(rt2x00dev);
90 rt2x00link_start_agc(rt2x00dev); 90 rt2x00link_start_agc(rt2x00dev);
91 if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags))
92 rt2x00link_start_vcocal(rt2x00dev);
91 93
92 /* 94 /*
93 * Start watchdog monitoring. 95 * Start watchdog monitoring.
@@ -111,6 +113,8 @@ void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev)
111 * Stop all queues 113 * Stop all queues
112 */ 114 */
113 rt2x00link_stop_agc(rt2x00dev); 115 rt2x00link_stop_agc(rt2x00dev);
116 if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags))
117 rt2x00link_stop_vcocal(rt2x00dev);
114 rt2x00link_stop_tuner(rt2x00dev); 118 rt2x00link_stop_tuner(rt2x00dev);
115 rt2x00queue_stop_queues(rt2x00dev); 119 rt2x00queue_stop_queues(rt2x00dev);
116 rt2x00queue_flush_queues(rt2x00dev, true); 120 rt2x00queue_flush_queues(rt2x00dev, true);
diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h
index 4cdf247a870..78bd43b8961 100644
--- a/drivers/net/wireless/rt2x00/rt2x00lib.h
+++ b/drivers/net/wireless/rt2x00/rt2x00lib.h
@@ -33,6 +33,7 @@
33#define WATCHDOG_INTERVAL round_jiffies_relative(HZ) 33#define WATCHDOG_INTERVAL round_jiffies_relative(HZ)
34#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) 34#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ)
35#define AGC_INTERVAL round_jiffies_relative(4 * HZ) 35#define AGC_INTERVAL round_jiffies_relative(4 * HZ)
36#define VCO_INTERVAL round_jiffies_relative(10 * HZ) /* 10 sec */
36 37
37/* 38/*
38 * rt2x00_rate: Per rate device information 39 * rt2x00_rate: Per rate device information
@@ -278,12 +279,24 @@ void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev);
278void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev); 279void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev);
279 280
280/** 281/**
282 * rt2x00link_start_vcocal - Start periodic VCO calibration
283 * @rt2x00dev: Pointer to &struct rt2x00_dev.
284 */
285void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev);
286
287/**
281 * rt2x00link_stop_agc - Stop periodic gain calibration 288 * rt2x00link_stop_agc - Stop periodic gain calibration
282 * @rt2x00dev: Pointer to &struct rt2x00_dev. 289 * @rt2x00dev: Pointer to &struct rt2x00_dev.
283 */ 290 */
284void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev); 291void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev);
285 292
286/** 293/**
294 * rt2x00link_stop_vcocal - Stop periodic VCO calibration
295 * @rt2x00dev: Pointer to &struct rt2x00_dev.
296 */
297void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev);
298
299/**
287 * rt2x00link_register - Initialize link tuning & watchdog functionality 300 * rt2x00link_register - Initialize link tuning & watchdog functionality
288 * @rt2x00dev: Pointer to &struct rt2x00_dev. 301 * @rt2x00dev: Pointer to &struct rt2x00_dev.
289 * 302 *
diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c
index ea10b0068f8..8368aab86f2 100644
--- a/drivers/net/wireless/rt2x00/rt2x00link.c
+++ b/drivers/net/wireless/rt2x00/rt2x00link.c
@@ -447,11 +447,27 @@ void rt2x00link_start_agc(struct rt2x00_dev *rt2x00dev)
447 AGC_INTERVAL); 447 AGC_INTERVAL);
448} 448}
449 449
450void rt2x00link_start_vcocal(struct rt2x00_dev *rt2x00dev)
451{
452 struct link *link = &rt2x00dev->link;
453
454 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) &&
455 rt2x00dev->ops->lib->vco_calibration)
456 ieee80211_queue_delayed_work(rt2x00dev->hw,
457 &link->vco_work,
458 VCO_INTERVAL);
459}
460
450void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev) 461void rt2x00link_stop_agc(struct rt2x00_dev *rt2x00dev)
451{ 462{
452 cancel_delayed_work_sync(&rt2x00dev->link.agc_work); 463 cancel_delayed_work_sync(&rt2x00dev->link.agc_work);
453} 464}
454 465
466void rt2x00link_stop_vcocal(struct rt2x00_dev *rt2x00dev)
467{
468 cancel_delayed_work_sync(&rt2x00dev->link.vco_work);
469}
470
455static void rt2x00link_agc(struct work_struct *work) 471static void rt2x00link_agc(struct work_struct *work)
456{ 472{
457 struct rt2x00_dev *rt2x00dev = 473 struct rt2x00_dev *rt2x00dev =
@@ -473,9 +489,32 @@ static void rt2x00link_agc(struct work_struct *work)
473 AGC_INTERVAL); 489 AGC_INTERVAL);
474} 490}
475 491
492static void rt2x00link_vcocal(struct work_struct *work)
493{
494 struct rt2x00_dev *rt2x00dev =
495 container_of(work, struct rt2x00_dev, link.vco_work.work);
496 struct link *link = &rt2x00dev->link;
497
498 /*
499 * When the radio is shutting down we should
500 * immediately cease the VCO calibration.
501 */
502 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
503 return;
504
505 rt2x00dev->ops->lib->vco_calibration(rt2x00dev);
506
507 if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
508 ieee80211_queue_delayed_work(rt2x00dev->hw,
509 &link->vco_work,
510 VCO_INTERVAL);
511}
512
476void rt2x00link_register(struct rt2x00_dev *rt2x00dev) 513void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
477{ 514{
478 INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc); 515 INIT_DELAYED_WORK(&rt2x00dev->link.agc_work, rt2x00link_agc);
516 if (test_bit(CAPABILITY_VCO_RECALIBRATION, &rt2x00dev->cap_flags))
517 INIT_DELAYED_WORK(&rt2x00dev->link.vco_work, rt2x00link_vcocal);
479 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog); 518 INIT_DELAYED_WORK(&rt2x00dev->link.watchdog_work, rt2x00link_watchdog);
480 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); 519 INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner);
481} 520}