diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2010-04-15 17:38:40 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-04-16 15:43:25 -0400 |
commit | af914a9ffd60a841054e9fd248f12630df0698c5 (patch) | |
tree | 460379e2c7f959865b796e3e608be84666767f14 /drivers/net/wireless/ath/ath9k/ar9003_phy.c | |
parent | c16fcb49b3849b4dceec9e4bbeb013b0713c7b38 (diff) |
ath9k_hw: add all the AR9003 PHY callbacks
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/ar9003_phy.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_phy.c | 300 |
1 files changed, 289 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 356e03db9cf1..c938b85c174e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -225,7 +225,30 @@ static void ar9003_hw_set_channel_regs(struct ath_hw *ah, | |||
225 | static void ar9003_hw_init_bb(struct ath_hw *ah, | 225 | static void ar9003_hw_init_bb(struct ath_hw *ah, |
226 | struct ath9k_channel *chan) | 226 | struct ath9k_channel *chan) |
227 | { | 227 | { |
228 | /* TODO */ | 228 | u32 synthDelay; |
229 | |||
230 | /* | ||
231 | * Wait for the frequency synth to settle (synth goes on | ||
232 | * via AR_PHY_ACTIVE_EN). Read the phy active delay register. | ||
233 | * Value is in 100ns increments. | ||
234 | */ | ||
235 | synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; | ||
236 | if (IS_CHAN_B(chan)) | ||
237 | synthDelay = (4 * synthDelay) / 22; | ||
238 | else | ||
239 | synthDelay /= 10; | ||
240 | |||
241 | /* Activate the PHY (includes baseband activate + synthesizer on) */ | ||
242 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); | ||
243 | |||
244 | /* | ||
245 | * There is an issue if the AP starts the calibration before | ||
246 | * the base band timeout completes. This could result in the | ||
247 | * rx_clear false triggering. As a workaround we add delay an | ||
248 | * extra BASE_ACTIVATE_DELAY usecs to ensure this condition | ||
249 | * does not happen. | ||
250 | */ | ||
251 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | ||
229 | } | 252 | } |
230 | 253 | ||
231 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | 254 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) |
@@ -385,46 +408,301 @@ static int ar9003_hw_process_ini(struct ath_hw *ah, | |||
385 | static void ar9003_hw_set_rfmode(struct ath_hw *ah, | 408 | static void ar9003_hw_set_rfmode(struct ath_hw *ah, |
386 | struct ath9k_channel *chan) | 409 | struct ath9k_channel *chan) |
387 | { | 410 | { |
388 | /* TODO */ | 411 | u32 rfMode = 0; |
412 | |||
413 | if (chan == NULL) | ||
414 | return; | ||
415 | |||
416 | rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) | ||
417 | ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; | ||
418 | |||
419 | if (IS_CHAN_A_5MHZ_SPACED(chan)) | ||
420 | rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); | ||
421 | |||
422 | REG_WRITE(ah, AR_PHY_MODE, rfMode); | ||
389 | } | 423 | } |
390 | 424 | ||
391 | static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah) | 425 | static void ar9003_hw_mark_phy_inactive(struct ath_hw *ah) |
392 | { | 426 | { |
393 | /* TODO */ | 427 | REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); |
394 | } | 428 | } |
395 | 429 | ||
396 | static void ar9003_hw_set_delta_slope(struct ath_hw *ah, | 430 | static void ar9003_hw_set_delta_slope(struct ath_hw *ah, |
397 | struct ath9k_channel *chan) | 431 | struct ath9k_channel *chan) |
398 | { | 432 | { |
399 | /* TODO */ | 433 | u32 coef_scaled, ds_coef_exp, ds_coef_man; |
434 | u32 clockMhzScaled = 0x64000000; | ||
435 | struct chan_centers centers; | ||
436 | |||
437 | /* | ||
438 | * half and quarter rate can divide the scaled clock by 2 or 4 | ||
439 | * scale for selected channel bandwidth | ||
440 | */ | ||
441 | if (IS_CHAN_HALF_RATE(chan)) | ||
442 | clockMhzScaled = clockMhzScaled >> 1; | ||
443 | else if (IS_CHAN_QUARTER_RATE(chan)) | ||
444 | clockMhzScaled = clockMhzScaled >> 2; | ||
445 | |||
446 | /* | ||
447 | * ALGO -> coef = 1e8/fcarrier*fclock/40; | ||
448 | * scaled coef to provide precision for this floating calculation | ||
449 | */ | ||
450 | ath9k_hw_get_channel_centers(ah, chan, ¢ers); | ||
451 | coef_scaled = clockMhzScaled / centers.synth_center; | ||
452 | |||
453 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
454 | &ds_coef_exp); | ||
455 | |||
456 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
457 | AR_PHY_TIMING3_DSC_MAN, ds_coef_man); | ||
458 | REG_RMW_FIELD(ah, AR_PHY_TIMING3, | ||
459 | AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); | ||
460 | |||
461 | /* | ||
462 | * For Short GI, | ||
463 | * scaled coeff is 9/10 that of normal coeff | ||
464 | */ | ||
465 | coef_scaled = (9 * coef_scaled) / 10; | ||
466 | |||
467 | ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, | ||
468 | &ds_coef_exp); | ||
469 | |||
470 | /* for short gi */ | ||
471 | REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, | ||
472 | AR_PHY_SGI_DSC_MAN, ds_coef_man); | ||
473 | REG_RMW_FIELD(ah, AR_PHY_SGI_DELTA, | ||
474 | AR_PHY_SGI_DSC_EXP, ds_coef_exp); | ||
400 | } | 475 | } |
401 | 476 | ||
402 | static bool ar9003_hw_rfbus_req(struct ath_hw *ah) | 477 | static bool ar9003_hw_rfbus_req(struct ath_hw *ah) |
403 | { | 478 | { |
404 | /* TODO */ | 479 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); |
405 | return false; | 480 | return ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, |
481 | AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT); | ||
406 | } | 482 | } |
407 | 483 | ||
484 | /* | ||
485 | * Wait for the frequency synth to settle (synth goes on via PHY_ACTIVE_EN). | ||
486 | * Read the phy active delay register. Value is in 100ns increments. | ||
487 | */ | ||
408 | static void ar9003_hw_rfbus_done(struct ath_hw *ah) | 488 | static void ar9003_hw_rfbus_done(struct ath_hw *ah) |
409 | { | 489 | { |
410 | /* TODO */ | 490 | u32 synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; |
491 | if (IS_CHAN_B(ah->curchan)) | ||
492 | synthDelay = (4 * synthDelay) / 22; | ||
493 | else | ||
494 | synthDelay /= 10; | ||
495 | |||
496 | udelay(synthDelay + BASE_ACTIVATE_DELAY); | ||
497 | |||
498 | REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); | ||
411 | } | 499 | } |
412 | 500 | ||
501 | /* | ||
502 | * Set the interrupt and GPIO values so the ISR can disable RF | ||
503 | * on a switch signal. Assumes GPIO port and interrupt polarity | ||
504 | * are set prior to call. | ||
505 | */ | ||
413 | static void ar9003_hw_enable_rfkill(struct ath_hw *ah) | 506 | static void ar9003_hw_enable_rfkill(struct ath_hw *ah) |
414 | { | 507 | { |
415 | /* TODO */ | 508 | /* Connect rfsilent_bb_l to baseband */ |
509 | REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, | ||
510 | AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); | ||
511 | /* Set input mux for rfsilent_bb_l to GPIO #0 */ | ||
512 | REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, | ||
513 | AR_GPIO_INPUT_MUX2_RFSILENT); | ||
514 | |||
515 | /* | ||
516 | * Configure the desired GPIO port for input and | ||
517 | * enable baseband rf silence. | ||
518 | */ | ||
519 | ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); | ||
520 | REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); | ||
416 | } | 521 | } |
417 | 522 | ||
418 | static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) | 523 | static void ar9003_hw_set_diversity(struct ath_hw *ah, bool value) |
419 | { | 524 | { |
420 | /* TODO */ | 525 | u32 v = REG_READ(ah, AR_PHY_CCK_DETECT); |
526 | if (value) | ||
527 | v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
528 | else | ||
529 | v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; | ||
530 | REG_WRITE(ah, AR_PHY_CCK_DETECT, v); | ||
421 | } | 531 | } |
422 | 532 | ||
423 | static bool ar9003_hw_ani_control(struct ath_hw *ah, | 533 | static bool ar9003_hw_ani_control(struct ath_hw *ah, |
424 | enum ath9k_ani_cmd cmd, int param) | 534 | enum ath9k_ani_cmd cmd, int param) |
425 | { | 535 | { |
426 | /* TODO */ | 536 | struct ar5416AniState *aniState = ah->curani; |
427 | return false; | 537 | struct ath_common *common = ath9k_hw_common(ah); |
538 | |||
539 | switch (cmd & ah->ani_function) { | ||
540 | case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ | ||
541 | u32 level = param; | ||
542 | |||
543 | if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { | ||
544 | ath_print(common, ATH_DBG_ANI, | ||
545 | "level out of range (%u > %u)\n", | ||
546 | level, | ||
547 | (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); | ||
548 | return false; | ||
549 | } | ||
550 | |||
551 | REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, | ||
552 | AR_PHY_DESIRED_SZ_TOT_DES, | ||
553 | ah->totalSizeDesired[level]); | ||
554 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
555 | AR_PHY_AGC_COARSE_LOW, | ||
556 | ah->coarse_low[level]); | ||
557 | REG_RMW_FIELD(ah, AR_PHY_AGC, | ||
558 | AR_PHY_AGC_COARSE_HIGH, | ||
559 | ah->coarse_high[level]); | ||
560 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
561 | AR_PHY_FIND_SIG_FIRPWR, ah->firpwr[level]); | ||
562 | |||
563 | if (level > aniState->noiseImmunityLevel) | ||
564 | ah->stats.ast_ani_niup++; | ||
565 | else if (level < aniState->noiseImmunityLevel) | ||
566 | ah->stats.ast_ani_nidown++; | ||
567 | aniState->noiseImmunityLevel = level; | ||
568 | break; | ||
569 | } | ||
570 | case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ | ||
571 | const int m1ThreshLow[] = { 127, 50 }; | ||
572 | const int m2ThreshLow[] = { 127, 40 }; | ||
573 | const int m1Thresh[] = { 127, 0x4d }; | ||
574 | const int m2Thresh[] = { 127, 0x40 }; | ||
575 | const int m2CountThr[] = { 31, 16 }; | ||
576 | const int m2CountThrLow[] = { 63, 48 }; | ||
577 | u32 on = param ? 1 : 0; | ||
578 | |||
579 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
580 | AR_PHY_SFCORR_LOW_M1_THRESH_LOW, | ||
581 | m1ThreshLow[on]); | ||
582 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
583 | AR_PHY_SFCORR_LOW_M2_THRESH_LOW, | ||
584 | m2ThreshLow[on]); | ||
585 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
586 | AR_PHY_SFCORR_M1_THRESH, m1Thresh[on]); | ||
587 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
588 | AR_PHY_SFCORR_M2_THRESH, m2Thresh[on]); | ||
589 | REG_RMW_FIELD(ah, AR_PHY_SFCORR, | ||
590 | AR_PHY_SFCORR_M2COUNT_THR, m2CountThr[on]); | ||
591 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, | ||
592 | AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, | ||
593 | m2CountThrLow[on]); | ||
594 | |||
595 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
596 | AR_PHY_SFCORR_EXT_M1_THRESH_LOW, m1ThreshLow[on]); | ||
597 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
598 | AR_PHY_SFCORR_EXT_M2_THRESH_LOW, m2ThreshLow[on]); | ||
599 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
600 | AR_PHY_SFCORR_EXT_M1_THRESH, m1Thresh[on]); | ||
601 | REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, | ||
602 | AR_PHY_SFCORR_EXT_M2_THRESH, m2Thresh[on]); | ||
603 | |||
604 | if (on) | ||
605 | REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, | ||
606 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
607 | else | ||
608 | REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, | ||
609 | AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); | ||
610 | |||
611 | if (!on != aniState->ofdmWeakSigDetectOff) { | ||
612 | if (on) | ||
613 | ah->stats.ast_ani_ofdmon++; | ||
614 | else | ||
615 | ah->stats.ast_ani_ofdmoff++; | ||
616 | aniState->ofdmWeakSigDetectOff = !on; | ||
617 | } | ||
618 | break; | ||
619 | } | ||
620 | case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ | ||
621 | const int weakSigThrCck[] = { 8, 6 }; | ||
622 | u32 high = param ? 1 : 0; | ||
623 | |||
624 | REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, | ||
625 | AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, | ||
626 | weakSigThrCck[high]); | ||
627 | if (high != aniState->cckWeakSigThreshold) { | ||
628 | if (high) | ||
629 | ah->stats.ast_ani_cckhigh++; | ||
630 | else | ||
631 | ah->stats.ast_ani_ccklow++; | ||
632 | aniState->cckWeakSigThreshold = high; | ||
633 | } | ||
634 | break; | ||
635 | } | ||
636 | case ATH9K_ANI_FIRSTEP_LEVEL:{ | ||
637 | const int firstep[] = { 0, 4, 8 }; | ||
638 | u32 level = param; | ||
639 | |||
640 | if (level >= ARRAY_SIZE(firstep)) { | ||
641 | ath_print(common, ATH_DBG_ANI, | ||
642 | "level out of range (%u > %u)\n", | ||
643 | level, | ||
644 | (unsigned) ARRAY_SIZE(firstep)); | ||
645 | return false; | ||
646 | } | ||
647 | REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, | ||
648 | AR_PHY_FIND_SIG_FIRSTEP, | ||
649 | firstep[level]); | ||
650 | if (level > aniState->firstepLevel) | ||
651 | ah->stats.ast_ani_stepup++; | ||
652 | else if (level < aniState->firstepLevel) | ||
653 | ah->stats.ast_ani_stepdown++; | ||
654 | aniState->firstepLevel = level; | ||
655 | break; | ||
656 | } | ||
657 | case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ | ||
658 | const int cycpwrThr1[] = { 2, 4, 6, 8, 10, 12, 14, 16 }; | ||
659 | u32 level = param; | ||
660 | |||
661 | if (level >= ARRAY_SIZE(cycpwrThr1)) { | ||
662 | ath_print(common, ATH_DBG_ANI, | ||
663 | "level out of range (%u > %u)\n", | ||
664 | level, | ||
665 | (unsigned) ARRAY_SIZE(cycpwrThr1)); | ||
666 | return false; | ||
667 | } | ||
668 | REG_RMW_FIELD(ah, AR_PHY_TIMING5, | ||
669 | AR_PHY_TIMING5_CYCPWR_THR1, | ||
670 | cycpwrThr1[level]); | ||
671 | if (level > aniState->spurImmunityLevel) | ||
672 | ah->stats.ast_ani_spurup++; | ||
673 | else if (level < aniState->spurImmunityLevel) | ||
674 | ah->stats.ast_ani_spurdown++; | ||
675 | aniState->spurImmunityLevel = level; | ||
676 | break; | ||
677 | } | ||
678 | case ATH9K_ANI_PRESENT: | ||
679 | break; | ||
680 | default: | ||
681 | ath_print(common, ATH_DBG_ANI, | ||
682 | "invalid cmd %u\n", cmd); | ||
683 | return false; | ||
684 | } | ||
685 | |||
686 | ath_print(common, ATH_DBG_ANI, "ANI parameters:\n"); | ||
687 | ath_print(common, ATH_DBG_ANI, | ||
688 | "noiseImmunityLevel=%d, spurImmunityLevel=%d, " | ||
689 | "ofdmWeakSigDetectOff=%d\n", | ||
690 | aniState->noiseImmunityLevel, | ||
691 | aniState->spurImmunityLevel, | ||
692 | !aniState->ofdmWeakSigDetectOff); | ||
693 | ath_print(common, ATH_DBG_ANI, | ||
694 | "cckWeakSigThreshold=%d, " | ||
695 | "firstepLevel=%d, listenTime=%d\n", | ||
696 | aniState->cckWeakSigThreshold, | ||
697 | aniState->firstepLevel, | ||
698 | aniState->listenTime); | ||
699 | ath_print(common, ATH_DBG_ANI, | ||
700 | "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", | ||
701 | aniState->cycleCount, | ||
702 | aniState->ofdmPhyErrCount, | ||
703 | aniState->cckPhyErrCount); | ||
704 | |||
705 | return true; | ||
428 | } | 706 | } |
429 | 707 | ||
430 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) | 708 | void ar9003_hw_attach_phy_ops(struct ath_hw *ah) |