Commit 801ccc8a authored by Lorenzo Bianconi's avatar Lorenzo Bianconi Committed by Felix Fietkau

mt76x0: pci: add DFS support

Introduce dfs support in mt76x0e driver and unlock radar channels
Signed-off-by: default avatarLorenzo Bianconi <lorenzo.bianconi@redhat.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent e6cb3291
...@@ -22,7 +22,10 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) ...@@ -22,7 +22,10 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
int ret; int ret;
cancel_delayed_work_sync(&dev->cal_work); cancel_delayed_work_sync(&dev->cal_work);
tasklet_disable(&dev->pre_tbtt_tasklet); if (mt76_is_mmio(dev)) {
tasklet_disable(&dev->pre_tbtt_tasklet);
tasklet_disable(&dev->dfs_pd.dfs_tasklet);
}
mt76_set_channel(&dev->mt76); mt76_set_channel(&dev->mt76);
ret = mt76x0_phy_set_channel(dev, chandef); ret = mt76x0_phy_set_channel(dev, chandef);
...@@ -31,7 +34,11 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) ...@@ -31,7 +34,11 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef)
mt76_rr(dev, MT_CH_IDLE); mt76_rr(dev, MT_CH_IDLE);
mt76_rr(dev, MT_CH_BUSY); mt76_rr(dev, MT_CH_BUSY);
tasklet_enable(&dev->pre_tbtt_tasklet); if (mt76_is_mmio(dev)) {
mt76x02_dfs_init_params(dev);
tasklet_enable(&dev->pre_tbtt_tasklet);
tasklet_enable(&dev->dfs_pd.dfs_tasklet);
}
mt76_txq_schedule_all(&dev->mt76); mt76_txq_schedule_all(&dev->mt76);
return ret; return ret;
......
...@@ -719,6 +719,10 @@ static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) ...@@ -719,6 +719,10 @@ static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev)
mt76_wr(dev, MT_BBP(AGC, 8), mt76_wr(dev, MT_BBP(AGC, 8),
val | FIELD_PREP(MT_BBP_AGC_GAIN, gain)); val | FIELD_PREP(MT_BBP_AGC_GAIN, gain));
if ((dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) &&
!is_mt7630(dev))
mt76x02_phy_dfs_adjust_agc(dev);
} }
static void static void
......
...@@ -802,6 +802,35 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) ...@@ -802,6 +802,35 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev)
mt76_wr(dev, 0x212c, 0x0c350001); mt76_wr(dev, 0x212c, 0x0c350001);
} }
void mt76x02_phy_dfs_adjust_agc(struct mt76x02_dev *dev)
{
u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31;
agc_r8 = mt76_rr(dev, MT_BBP(AGC, 8));
agc_r4 = mt76_rr(dev, MT_BBP(AGC, 4));
val_r8 = (agc_r8 & 0x00007e00) >> 9;
val_r4 = agc_r4 & ~0x1f000000;
val_r4 += (((val_r8 + 1) >> 1) << 24);
mt76_wr(dev, MT_BBP(AGC, 4), val_r4);
dfs_r31 = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, val_r4);
dfs_r31 += val_r8;
dfs_r31 -= (agc_r8 & 0x00000038) >> 3;
dfs_r31 = (dfs_r31 << 16) | 0x00000307;
mt76_wr(dev, MT_BBP(DFS, 31), dfs_r31);
if (is_mt76x2(dev)) {
mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071);
} else {
/* disable hw detector */
mt76_wr(dev, MT_BBP(DFS, 0), 0);
/* enable hw detector */
mt76_wr(dev, MT_BBP(DFS, 0), MT_DFS_CH_EN << 16);
}
}
EXPORT_SYMBOL_GPL(mt76x02_phy_dfs_adjust_agc);
void mt76x02_dfs_init_params(struct mt76x02_dev *dev) void mt76x02_dfs_init_params(struct mt76x02_dev *dev)
{ {
struct cfg80211_chan_def *chandef = &dev->mt76.chandef; struct cfg80211_chan_def *chandef = &dev->mt76.chandef;
...@@ -841,7 +870,6 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev) ...@@ -841,7 +870,6 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev)
tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet,
(unsigned long)dev); (unsigned long)dev);
} }
EXPORT_SYMBOL_GPL(mt76x02_dfs_init_detector);
static void static void
mt76x02_dfs_set_domain(struct mt76x02_dev *dev, mt76x02_dfs_set_domain(struct mt76x02_dev *dev,
...@@ -865,4 +893,3 @@ void mt76x02_regd_notifier(struct wiphy *wiphy, ...@@ -865,4 +893,3 @@ void mt76x02_regd_notifier(struct wiphy *wiphy,
mt76x02_dfs_set_domain(dev, request->dfs_region); mt76x02_dfs_set_domain(dev, request->dfs_region);
} }
EXPORT_SYMBOL_GPL(mt76x02_regd_notifier);
...@@ -141,4 +141,5 @@ void mt76x02_dfs_init_params(struct mt76x02_dev *dev); ...@@ -141,4 +141,5 @@ void mt76x02_dfs_init_params(struct mt76x02_dev *dev);
void mt76x02_dfs_init_detector(struct mt76x02_dev *dev); void mt76x02_dfs_init_detector(struct mt76x02_dev *dev);
void mt76x02_regd_notifier(struct wiphy *wiphy, void mt76x02_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request); struct regulatory_request *request);
void mt76x02_phy_dfs_adjust_agc(struct mt76x02_dev *dev);
#endif /* __MT76x02_DFS_H */ #endif /* __MT76x02_DFS_H */
...@@ -93,6 +93,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) ...@@ -93,6 +93,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev)
MT_DMA_HDR_LEN; MT_DMA_HDR_LEN;
wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
} else { } else {
mt76x02_dfs_init_detector(dev);
wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy->iface_combinations = mt76x02_if_comb; wiphy->iface_combinations = mt76x02_if_comb;
wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb);
wiphy->interface_modes = wiphy->interface_modes =
...@@ -635,6 +638,8 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) ...@@ -635,6 +638,8 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev)
/* Fire a pre-TBTT interrupt 8 ms before TBTT */ /* Fire a pre-TBTT interrupt 8 ms before TBTT */
mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT,
8 << 4); 8 << 4);
mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
MT_DFS_GP_INTERVAL);
mt76_wr(dev, MT_INT_TIMER_EN, 0); mt76_wr(dev, MT_INT_TIMER_EN, 0);
mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff); mt76_wr(dev, MT_BCN_BYPASS_MASK, 0xffff);
......
...@@ -122,9 +122,6 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard) ...@@ -122,9 +122,6 @@ static int mt76x2_mac_reset(struct mt76x02_dev *dev, bool hard)
mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr)); mt76_wr(dev, MT_MAC_ADDR_DW0, get_unaligned_le32(macaddr));
mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4)); mt76_wr(dev, MT_MAC_ADDR_DW1, get_unaligned_le16(macaddr + 4));
mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_GP_TIMER,
MT_DFS_GP_INTERVAL);
mt76x02_init_beacon_config(dev); mt76x02_init_beacon_config(dev);
if (!hard) if (!hard)
return 0; return 0;
...@@ -414,12 +411,8 @@ int mt76x2_register_device(struct mt76x02_dev *dev) ...@@ -414,12 +411,8 @@ int mt76x2_register_device(struct mt76x02_dev *dev)
wiphy->addresses = dev->macaddr_list; wiphy->addresses = dev->macaddr_list;
wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list); wiphy->n_addresses = ARRAY_SIZE(dev->macaddr_list);
wiphy->reg_notifier = mt76x02_regd_notifier;
wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS); wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_VHT_IBSS);
mt76x02_dfs_init_detector(dev);
/* init led callbacks */ /* init led callbacks */
dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness;
dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink;
......
...@@ -251,27 +251,6 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait) ...@@ -251,27 +251,6 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait)
} }
EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate); EXPORT_SYMBOL_GPL(mt76x2_phy_tssi_compensate);
static void mt76x2_phy_dfs_adjust_agc(struct mt76x02_dev *dev)
{
u32 agc_r8, agc_r4, val_r8, val_r4, dfs_r31;
agc_r8 = mt76_rr(dev, MT_BBP(AGC, 8));
agc_r4 = mt76_rr(dev, MT_BBP(AGC, 4));
val_r8 = (agc_r8 & 0x00007e00) >> 9;
val_r4 = agc_r4 & ~0x1f000000;
val_r4 += (((val_r8 + 1) >> 1) << 24);
mt76_wr(dev, MT_BBP(AGC, 4), val_r4);
dfs_r31 = FIELD_GET(MT_BBP_AGC_LNA_HIGH_GAIN, val_r4);
dfs_r31 += val_r8;
dfs_r31 -= (agc_r8 & 0x00000038) >> 3;
dfs_r31 = (dfs_r31 << 16) | 0x00000307;
mt76_wr(dev, MT_BBP(DFS, 31), dfs_r31);
mt76_wr(dev, MT_BBP(DFS, 32), 0x00040071);
}
static void static void
mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)
{ {
...@@ -294,7 +273,7 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev) ...@@ -294,7 +273,7 @@ mt76x2_phy_set_gain_val(struct mt76x02_dev *dev)
val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1])); val | FIELD_PREP(MT_BBP_AGC_GAIN, gain_val[1]));
if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR) if (dev->mt76.chandef.chan->flags & IEEE80211_CHAN_RADAR)
mt76x2_phy_dfs_adjust_agc(dev); mt76x02_phy_dfs_adjust_agc(dev);
} }
void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev) void mt76x2_phy_update_channel_gain(struct mt76x02_dev *dev)
......
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