Commit 64773964 authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville

ath9k_hw: add a private callback for PLL control computation

The PLL control computation used to program the AR_RTC_PLL_CONTROL
register varies between our harware so just add a private callback for it.
AR9003 will use its own callback.
Signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent bbd79af5
...@@ -967,6 +967,54 @@ static void ar5008_set_diversity(struct ath_hw *ah, bool value) ...@@ -967,6 +967,54 @@ static void ar5008_set_diversity(struct ath_hw *ah, bool value)
REG_WRITE(ah, AR_PHY_CCK_DETECT, v); REG_WRITE(ah, AR_PHY_CCK_DETECT, v);
} }
static u32 ar9100_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
if (chan && IS_CHAN_5GHZ(chan))
return 0x1450;
return 0x1458;
}
static u32 ar9160_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
u32 pll;
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan))
pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
else
pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
return pll;
}
static u32 ar5008_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
u32 pll;
pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan))
pll |= SM(0xa, AR_RTC_PLL_DIV);
else
pll |= SM(0xb, AR_RTC_PLL_DIV);
return pll;
}
void ar5008_hw_attach_phy_ops(struct ath_hw *ah) void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
{ {
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
...@@ -988,4 +1036,11 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah) ...@@ -988,4 +1036,11 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->enable_rfkill = ar5008_hw_enable_rfkill; priv_ops->enable_rfkill = ar5008_hw_enable_rfkill;
priv_ops->restore_chainmask = ar5008_restore_chainmask; priv_ops->restore_chainmask = ar5008_restore_chainmask;
priv_ops->set_diversity = ar5008_set_diversity; priv_ops->set_diversity = ar5008_set_diversity;
if (AR_SREV_9100(ah))
priv_ops->compute_pll_control = ar9100_hw_compute_pll_control;
else if (AR_SREV_9160_10_OR_LATER(ah))
priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
else
priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;
} }
...@@ -437,6 +437,36 @@ static void ar9002_olc_init(struct ath_hw *ah) ...@@ -437,6 +437,36 @@ static void ar9002_olc_init(struct ath_hw *ah)
} }
} }
static u32 ar9002_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
u32 pll;
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan)) {
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
if (AR_SREV_9280_20(ah)) {
if (((chan->channel % 20) == 0)
|| ((chan->channel % 10) == 0))
pll = 0x2850;
else
pll = 0x142c;
}
} else {
pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
}
return pll;
}
void ar9002_hw_attach_phy_ops(struct ath_hw *ah) void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
{ {
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah); struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
...@@ -447,4 +477,5 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah) ...@@ -447,4 +477,5 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
priv_ops->rf_set_freq = ar9002_hw_set_channel; priv_ops->rf_set_freq = ar9002_hw_set_channel;
priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate; priv_ops->spur_mitigate_freq = ar9002_hw_spur_mitigate;
priv_ops->olc_init = ar9002_olc_init; priv_ops->olc_init = ar9002_olc_init;
priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
} }
...@@ -66,6 +66,12 @@ static bool ath9k_hw_macversion_supported(struct ath_hw *ah) ...@@ -66,6 +66,12 @@ static bool ath9k_hw_macversion_supported(struct ath_hw *ah)
return priv_ops->macversion_supported(ah->hw_version.macVersion); return priv_ops->macversion_supported(ah->hw_version.macVersion);
} }
static u32 ath9k_hw_compute_pll_control(struct ath_hw *ah,
struct ath9k_channel *chan)
{
return ath9k_hw_private_ops(ah)->compute_pll_control(ah, chan);
}
/********************/ /********************/
/* Helper Functions */ /* Helper Functions */
/********************/ /********************/
...@@ -1023,64 +1029,8 @@ static void ath9k_hw_init_qos(struct ath_hw *ah) ...@@ -1023,64 +1029,8 @@ static void ath9k_hw_init_qos(struct ath_hw *ah)
static void ath9k_hw_init_pll(struct ath_hw *ah, static void ath9k_hw_init_pll(struct ath_hw *ah,
struct ath9k_channel *chan) struct ath9k_channel *chan)
{ {
u32 pll; u32 pll = ath9k_hw_compute_pll_control(ah, chan);
if (AR_SREV_9100(ah)) {
if (chan && IS_CHAN_5GHZ(chan))
pll = 0x1450;
else
pll = 0x1458;
} else {
if (AR_SREV_9280_10_OR_LATER(ah)) {
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan)) {
pll |= SM(0x28, AR_RTC_9160_PLL_DIV);
if (AR_SREV_9280_20(ah)) {
if (((chan->channel % 20) == 0)
|| ((chan->channel % 10) == 0))
pll = 0x2850;
else
pll = 0x142c;
}
} else {
pll |= SM(0x2c, AR_RTC_9160_PLL_DIV);
}
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
pll = SM(0x5, AR_RTC_9160_PLL_REFDIV);
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan))
pll |= SM(0x50, AR_RTC_9160_PLL_DIV);
else
pll |= SM(0x58, AR_RTC_9160_PLL_DIV);
} else {
pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2;
if (chan && IS_CHAN_HALF_RATE(chan))
pll |= SM(0x1, AR_RTC_PLL_CLKSEL);
else if (chan && IS_CHAN_QUARTER_RATE(chan))
pll |= SM(0x2, AR_RTC_PLL_CLKSEL);
if (chan && IS_CHAN_5GHZ(chan))
pll |= SM(0xa, AR_RTC_PLL_DIV);
else
pll |= SM(0xb, AR_RTC_PLL_DIV);
}
}
REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll);
/* Switch the core clock for ar9271 to 117Mhz */ /* Switch the core clock for ar9271 to 117Mhz */
......
...@@ -454,6 +454,8 @@ struct ath_gen_timer_table { ...@@ -454,6 +454,8 @@ struct ath_gen_timer_table {
* @rf_alloc_ext_banks: * @rf_alloc_ext_banks:
* @rf_free_ext_banks: * @rf_free_ext_banks:
* @set_rf_regs: * @set_rf_regs:
* @compute_pll_control: compute the PLL control value to use for
* AR_RTC_PLL_CONTROL for a given channel
*/ */
struct ath_hw_private_ops { struct ath_hw_private_ops {
void (*init_cal_settings)(struct ath_hw *ah); void (*init_cal_settings)(struct ath_hw *ah);
...@@ -483,6 +485,8 @@ struct ath_hw_private_ops { ...@@ -483,6 +485,8 @@ struct ath_hw_private_ops {
void (*enable_rfkill)(struct ath_hw *ah); void (*enable_rfkill)(struct ath_hw *ah);
void (*restore_chainmask)(struct ath_hw *ah); void (*restore_chainmask)(struct ath_hw *ah);
void (*set_diversity)(struct ath_hw *ah, bool value); void (*set_diversity)(struct ath_hw *ah, bool value);
u32 (*compute_pll_control)(struct ath_hw *ah,
struct ath9k_channel *chan);
}; };
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment