From 801ccc8a60381f76810b5da9b22f9fe47076a6e9 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Mon, 22 Oct 2018 23:42:13 +0200 Subject: [PATCH] mt76x0: pci: add DFS support Introduce dfs support in mt76x0e driver and unlock radar channels Signed-off-by: Lorenzo Bianconi Signed-off-by: Felix Fietkau --- .../net/wireless/mediatek/mt76/mt76x0/main.c | 11 +++++-- .../net/wireless/mediatek/mt76/mt76x0/phy.c | 4 +++ .../net/wireless/mediatek/mt76/mt76x02_dfs.c | 31 +++++++++++++++++-- .../net/wireless/mediatek/mt76/mt76x02_dfs.h | 1 + .../net/wireless/mediatek/mt76/mt76x02_util.c | 5 +++ .../wireless/mediatek/mt76/mt76x2/pci_init.c | 7 ----- .../net/wireless/mediatek/mt76/mt76x2/phy.c | 23 +------------- 7 files changed, 49 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c index cd1a1225ad8b..a803a9b6a4c5 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/main.c @@ -22,7 +22,10 @@ mt76x0_set_channel(struct mt76x02_dev *dev, struct cfg80211_chan_def *chandef) int ret; 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); ret = mt76x0_phy_set_channel(dev, 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_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); return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c index b33074b783dc..c734987a344c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x0/phy.c @@ -719,6 +719,10 @@ static void mt76x0_phy_set_gain_val(struct mt76x02_dev *dev) mt76_wr(dev, MT_BBP(AGC, 8), 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 diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c index 21e7b8c9f824..527e530d480a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.c @@ -802,6 +802,35 @@ static void mt76x02_dfs_set_bbp_params(struct mt76x02_dev *dev) 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) { struct cfg80211_chan_def *chandef = &dev->mt76.chandef; @@ -841,7 +870,6 @@ void mt76x02_dfs_init_detector(struct mt76x02_dev *dev) tasklet_init(&dfs_pd->dfs_tasklet, mt76x02_dfs_tasklet, (unsigned long)dev); } -EXPORT_SYMBOL_GPL(mt76x02_dfs_init_detector); static void mt76x02_dfs_set_domain(struct mt76x02_dev *dev, @@ -865,4 +893,3 @@ void mt76x02_regd_notifier(struct wiphy *wiphy, mt76x02_dfs_set_domain(dev, request->dfs_region); } -EXPORT_SYMBOL_GPL(mt76x02_regd_notifier); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h index 59e1524ff98b..70b394e17340 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_dfs.h @@ -141,4 +141,5 @@ void mt76x02_dfs_init_params(struct mt76x02_dev *dev); void mt76x02_dfs_init_detector(struct mt76x02_dev *dev); void mt76x02_regd_notifier(struct wiphy *wiphy, struct regulatory_request *request); +void mt76x02_phy_dfs_adjust_agc(struct mt76x02_dev *dev); #endif /* __MT76x02_DFS_H */ diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c index 4c3b8392b2b7..9f083008dbd4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_util.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_util.c @@ -93,6 +93,9 @@ void mt76x02_init_device(struct mt76x02_dev *dev) MT_DMA_HDR_LEN; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); } else { + mt76x02_dfs_init_detector(dev); + + wiphy->reg_notifier = mt76x02_regd_notifier; wiphy->iface_combinations = mt76x02_if_comb; wiphy->n_iface_combinations = ARRAY_SIZE(mt76x02_if_comb); wiphy->interface_modes = @@ -635,6 +638,8 @@ void mt76x02_init_beacon_config(struct mt76x02_dev *dev) /* Fire a pre-TBTT interrupt 8 ms before TBTT */ mt76_rmw_field(dev, MT_INT_TIMER_CFG, MT_INT_TIMER_CFG_PRE_TBTT, 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_BCN_BYPASS_MASK, 0xffff); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index b6144e03047f..f6e8af6432c1 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -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_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); if (!hard) return 0; @@ -414,12 +411,8 @@ int mt76x2_register_device(struct mt76x02_dev *dev) wiphy->addresses = 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); - mt76x02_dfs_init_detector(dev); - /* init led callbacks */ dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c index 0f9f54569147..bbeff9c19997 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/phy.c @@ -251,27 +251,6 @@ void mt76x2_phy_tssi_compensate(struct mt76x02_dev *dev, bool wait) } 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 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])); 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)