162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC
262306a36Sopenharmony_ci/* Copyright (C) 2023 MediaTek Inc. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/module.h>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "mt792x.h"
762306a36Sopenharmony_ci#include "mt792x_regs.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_civoid mt792x_mac_work(struct work_struct *work)
1062306a36Sopenharmony_ci{
1162306a36Sopenharmony_ci	struct mt792x_phy *phy;
1262306a36Sopenharmony_ci	struct mt76_phy *mphy;
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci	mphy = (struct mt76_phy *)container_of(work, struct mt76_phy,
1562306a36Sopenharmony_ci					       mac_work.work);
1662306a36Sopenharmony_ci	phy = mphy->priv;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	mt792x_mutex_acquire(phy->dev);
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci	mt76_update_survey(mphy);
2162306a36Sopenharmony_ci	if (++mphy->mac_work_count == 2) {
2262306a36Sopenharmony_ci		mphy->mac_work_count = 0;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci		mt792x_mac_update_mib_stats(phy);
2562306a36Sopenharmony_ci	}
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	mt792x_mutex_release(phy->dev);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	mt76_tx_status_check(mphy->dev, false);
3062306a36Sopenharmony_ci	ieee80211_queue_delayed_work(phy->mt76->hw, &mphy->mac_work,
3162306a36Sopenharmony_ci				     MT792x_WATCHDOG_TIME);
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_work);
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_civoid mt792x_mac_set_timeing(struct mt792x_phy *phy)
3662306a36Sopenharmony_ci{
3762306a36Sopenharmony_ci	s16 coverage_class = phy->coverage_class;
3862306a36Sopenharmony_ci	struct mt792x_dev *dev = phy->dev;
3962306a36Sopenharmony_ci	u32 val, reg_offset;
4062306a36Sopenharmony_ci	u32 cck = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 231) |
4162306a36Sopenharmony_ci		  FIELD_PREP(MT_TIMEOUT_VAL_CCA, 48);
4262306a36Sopenharmony_ci	u32 ofdm = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, 60) |
4362306a36Sopenharmony_ci		   FIELD_PREP(MT_TIMEOUT_VAL_CCA, 28);
4462306a36Sopenharmony_ci	bool is_2ghz = phy->mt76->chandef.chan->band == NL80211_BAND_2GHZ;
4562306a36Sopenharmony_ci	int sifs = is_2ghz ? 10 : 16, offset;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state))
4862306a36Sopenharmony_ci		return;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	mt76_set(dev, MT_ARB_SCR(0),
5162306a36Sopenharmony_ci		 MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
5262306a36Sopenharmony_ci	udelay(1);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	offset = 3 * coverage_class;
5562306a36Sopenharmony_ci	reg_offset = FIELD_PREP(MT_TIMEOUT_VAL_PLCP, offset) |
5662306a36Sopenharmony_ci		     FIELD_PREP(MT_TIMEOUT_VAL_CCA, offset);
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	mt76_wr(dev, MT_TMAC_CDTR(0), cck + reg_offset);
5962306a36Sopenharmony_ci	mt76_wr(dev, MT_TMAC_ODTR(0), ofdm + reg_offset);
6062306a36Sopenharmony_ci	mt76_wr(dev, MT_TMAC_ICR0(0),
6162306a36Sopenharmony_ci		FIELD_PREP(MT_IFS_EIFS, 360) |
6262306a36Sopenharmony_ci		FIELD_PREP(MT_IFS_RIFS, 2) |
6362306a36Sopenharmony_ci		FIELD_PREP(MT_IFS_SIFS, sifs) |
6462306a36Sopenharmony_ci		FIELD_PREP(MT_IFS_SLOT, phy->slottime));
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	if (phy->slottime < 20 || !is_2ghz)
6762306a36Sopenharmony_ci		val = MT792x_CFEND_RATE_DEFAULT;
6862306a36Sopenharmony_ci	else
6962306a36Sopenharmony_ci		val = MT792x_CFEND_RATE_11B;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	mt76_rmw_field(dev, MT_AGG_ACR0(0), MT_AGG_ACR_CFEND_RATE, val);
7262306a36Sopenharmony_ci	mt76_clear(dev, MT_ARB_SCR(0),
7362306a36Sopenharmony_ci		   MT_ARB_SCR_TX_DISABLE | MT_ARB_SCR_RX_DISABLE);
7462306a36Sopenharmony_ci}
7562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_set_timeing);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_civoid mt792x_mac_update_mib_stats(struct mt792x_phy *phy)
7862306a36Sopenharmony_ci{
7962306a36Sopenharmony_ci	struct mt76_mib_stats *mib = &phy->mib;
8062306a36Sopenharmony_ci	struct mt792x_dev *dev = phy->dev;
8162306a36Sopenharmony_ci	int i, aggr0 = 0, aggr1;
8262306a36Sopenharmony_ci	u32 val;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	mib->fcs_err_cnt += mt76_get_field(dev, MT_MIB_SDR3(0),
8562306a36Sopenharmony_ci					   MT_MIB_SDR3_FCS_ERR_MASK);
8662306a36Sopenharmony_ci	mib->ack_fail_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR3(0),
8762306a36Sopenharmony_ci					    MT_MIB_ACK_FAIL_COUNT_MASK);
8862306a36Sopenharmony_ci	mib->ba_miss_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR2(0),
8962306a36Sopenharmony_ci					   MT_MIB_BA_FAIL_COUNT_MASK);
9062306a36Sopenharmony_ci	mib->rts_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR0(0),
9162306a36Sopenharmony_ci				       MT_MIB_RTS_COUNT_MASK);
9262306a36Sopenharmony_ci	mib->rts_retries_cnt += mt76_get_field(dev, MT_MIB_MB_BSDR1(0),
9362306a36Sopenharmony_ci					       MT_MIB_RTS_FAIL_COUNT_MASK);
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	mib->tx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR12(0));
9662306a36Sopenharmony_ci	mib->tx_mpdu_attempts_cnt += mt76_rr(dev, MT_MIB_SDR14(0));
9762306a36Sopenharmony_ci	mib->tx_mpdu_success_cnt += mt76_rr(dev, MT_MIB_SDR15(0));
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_ci	val = mt76_rr(dev, MT_MIB_SDR32(0));
10062306a36Sopenharmony_ci	mib->tx_pkt_ebf_cnt += FIELD_GET(MT_MIB_SDR9_EBF_CNT_MASK, val);
10162306a36Sopenharmony_ci	mib->tx_pkt_ibf_cnt += FIELD_GET(MT_MIB_SDR9_IBF_CNT_MASK, val);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	val = mt76_rr(dev, MT_ETBF_TX_APP_CNT(0));
10462306a36Sopenharmony_ci	mib->tx_bf_ibf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_IBF_CNT, val);
10562306a36Sopenharmony_ci	mib->tx_bf_ebf_ppdu_cnt += FIELD_GET(MT_ETBF_TX_EBF_CNT, val);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	val = mt76_rr(dev, MT_ETBF_RX_FB_CNT(0));
10862306a36Sopenharmony_ci	mib->tx_bf_rx_fb_all_cnt += FIELD_GET(MT_ETBF_RX_FB_ALL, val);
10962306a36Sopenharmony_ci	mib->tx_bf_rx_fb_he_cnt += FIELD_GET(MT_ETBF_RX_FB_HE, val);
11062306a36Sopenharmony_ci	mib->tx_bf_rx_fb_vht_cnt += FIELD_GET(MT_ETBF_RX_FB_VHT, val);
11162306a36Sopenharmony_ci	mib->tx_bf_rx_fb_ht_cnt += FIELD_GET(MT_ETBF_RX_FB_HT, val);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	mib->rx_mpdu_cnt += mt76_rr(dev, MT_MIB_SDR5(0));
11462306a36Sopenharmony_ci	mib->rx_ampdu_cnt += mt76_rr(dev, MT_MIB_SDR22(0));
11562306a36Sopenharmony_ci	mib->rx_ampdu_bytes_cnt += mt76_rr(dev, MT_MIB_SDR23(0));
11662306a36Sopenharmony_ci	mib->rx_ba_cnt += mt76_rr(dev, MT_MIB_SDR31(0));
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(mib->tx_amsdu); i++) {
11962306a36Sopenharmony_ci		val = mt76_rr(dev, MT_PLE_AMSDU_PACK_MSDU_CNT(i));
12062306a36Sopenharmony_ci		mib->tx_amsdu[i] += val;
12162306a36Sopenharmony_ci		mib->tx_amsdu_cnt += val;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	for (i = 0, aggr1 = aggr0 + 8; i < 4; i++) {
12562306a36Sopenharmony_ci		u32 val2;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		val = mt76_rr(dev, MT_TX_AGG_CNT(0, i));
12862306a36Sopenharmony_ci		val2 = mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		phy->mt76->aggr_stats[aggr0++] += val & 0xffff;
13162306a36Sopenharmony_ci		phy->mt76->aggr_stats[aggr0++] += val >> 16;
13262306a36Sopenharmony_ci		phy->mt76->aggr_stats[aggr1++] += val2 & 0xffff;
13362306a36Sopenharmony_ci		phy->mt76->aggr_stats[aggr1++] += val2 >> 16;
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_update_mib_stats);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_cistruct mt76_wcid *mt792x_rx_get_wcid(struct mt792x_dev *dev, u16 idx,
13962306a36Sopenharmony_ci				     bool unicast)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	struct mt792x_sta *sta;
14262306a36Sopenharmony_ci	struct mt76_wcid *wcid;
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	if (idx >= ARRAY_SIZE(dev->mt76.wcid))
14562306a36Sopenharmony_ci		return NULL;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	wcid = rcu_dereference(dev->mt76.wcid[idx]);
14862306a36Sopenharmony_ci	if (unicast || !wcid)
14962306a36Sopenharmony_ci		return wcid;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	if (!wcid->sta)
15262306a36Sopenharmony_ci		return NULL;
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	sta = container_of(wcid, struct mt792x_sta, wcid);
15562306a36Sopenharmony_ci	if (!sta->vif)
15662306a36Sopenharmony_ci		return NULL;
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ci	return &sta->vif->sta.wcid;
15962306a36Sopenharmony_ci}
16062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_rx_get_wcid);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_cistatic void
16362306a36Sopenharmony_cimt792x_mac_rssi_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	struct sk_buff *skb = priv;
16662306a36Sopenharmony_ci	struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
16762306a36Sopenharmony_ci	struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
16862306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci	if (status->signal > 0)
17162306a36Sopenharmony_ci		return;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (!ether_addr_equal(vif->addr, hdr->addr1))
17462306a36Sopenharmony_ci		return;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	ewma_rssi_add(&mvif->rssi, -status->signal);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_civoid mt792x_mac_assoc_rssi(struct mt792x_dev *dev, struct sk_buff *skb)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	struct ieee80211_hdr *hdr = mt76_skb_get_hdr(skb);
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	if (!ieee80211_is_assoc_resp(hdr->frame_control) &&
18462306a36Sopenharmony_ci	    !ieee80211_is_auth(hdr->frame_control))
18562306a36Sopenharmony_ci		return;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
18862306a36Sopenharmony_ci		IEEE80211_IFACE_ITER_RESUME_ALL,
18962306a36Sopenharmony_ci		mt792x_mac_rssi_iter, skb);
19062306a36Sopenharmony_ci}
19162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_assoc_rssi);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_civoid mt792x_mac_reset_counters(struct mt792x_phy *phy)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	struct mt792x_dev *dev = phy->dev;
19662306a36Sopenharmony_ci	int i;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
19962306a36Sopenharmony_ci		mt76_rr(dev, MT_TX_AGG_CNT(0, i));
20062306a36Sopenharmony_ci		mt76_rr(dev, MT_TX_AGG_CNT2(0, i));
20162306a36Sopenharmony_ci	}
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci	dev->mt76.phy.survey_time = ktime_get_boottime();
20462306a36Sopenharmony_ci	memset(phy->mt76->aggr_stats, 0, sizeof(phy->mt76->aggr_stats));
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	/* reset airtime counters */
20762306a36Sopenharmony_ci	mt76_rr(dev, MT_MIB_SDR9(0));
20862306a36Sopenharmony_ci	mt76_rr(dev, MT_MIB_SDR36(0));
20962306a36Sopenharmony_ci	mt76_rr(dev, MT_MIB_SDR37(0));
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
21262306a36Sopenharmony_ci	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_reset_counters);
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_cistatic u8
21762306a36Sopenharmony_cimt792x_phy_get_nf(struct mt792x_phy *phy, int idx)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	return 0;
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic void
22362306a36Sopenharmony_cimt792x_phy_update_channel(struct mt76_phy *mphy, int idx)
22462306a36Sopenharmony_ci{
22562306a36Sopenharmony_ci	struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
22662306a36Sopenharmony_ci	struct mt792x_phy *phy = (struct mt792x_phy *)mphy->priv;
22762306a36Sopenharmony_ci	struct mt76_channel_state *state;
22862306a36Sopenharmony_ci	u64 busy_time, tx_time, rx_time, obss_time;
22962306a36Sopenharmony_ci	int nf;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	busy_time = mt76_get_field(dev, MT_MIB_SDR9(idx),
23262306a36Sopenharmony_ci				   MT_MIB_SDR9_BUSY_MASK);
23362306a36Sopenharmony_ci	tx_time = mt76_get_field(dev, MT_MIB_SDR36(idx),
23462306a36Sopenharmony_ci				 MT_MIB_SDR36_TXTIME_MASK);
23562306a36Sopenharmony_ci	rx_time = mt76_get_field(dev, MT_MIB_SDR37(idx),
23662306a36Sopenharmony_ci				 MT_MIB_SDR37_RXTIME_MASK);
23762306a36Sopenharmony_ci	obss_time = mt76_get_field(dev, MT_WF_RMAC_MIB_AIRTIME14(idx),
23862306a36Sopenharmony_ci				   MT_MIB_OBSSTIME_MASK);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	nf = mt792x_phy_get_nf(phy, idx);
24162306a36Sopenharmony_ci	if (!phy->noise)
24262306a36Sopenharmony_ci		phy->noise = nf << 4;
24362306a36Sopenharmony_ci	else if (nf)
24462306a36Sopenharmony_ci		phy->noise += nf - (phy->noise >> 4);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	state = mphy->chan_state;
24762306a36Sopenharmony_ci	state->cc_busy += busy_time;
24862306a36Sopenharmony_ci	state->cc_tx += tx_time;
24962306a36Sopenharmony_ci	state->cc_rx += rx_time + obss_time;
25062306a36Sopenharmony_ci	state->cc_bss_rx += rx_time;
25162306a36Sopenharmony_ci	state->noise = -(phy->noise >> 4);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_civoid mt792x_update_channel(struct mt76_phy *mphy)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	struct mt792x_dev *dev = container_of(mphy->dev, struct mt792x_dev, mt76);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	if (mt76_connac_pm_wake(mphy, &dev->pm))
25962306a36Sopenharmony_ci		return;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	mt792x_phy_update_channel(mphy, 0);
26262306a36Sopenharmony_ci	/* reset obss airtime */
26362306a36Sopenharmony_ci	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(0), MT_WF_RMAC_MIB_RXTIME_CLR);
26462306a36Sopenharmony_ci	mt76_connac_power_save_sched(mphy, &dev->pm);
26562306a36Sopenharmony_ci}
26662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_update_channel);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_civoid mt792x_reset(struct mt76_dev *mdev)
26962306a36Sopenharmony_ci{
27062306a36Sopenharmony_ci	struct mt792x_dev *dev = container_of(mdev, struct mt792x_dev, mt76);
27162306a36Sopenharmony_ci	struct mt76_connac_pm *pm = &dev->pm;
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	if (!dev->hw_init_done)
27462306a36Sopenharmony_ci		return;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	if (dev->hw_full_reset)
27762306a36Sopenharmony_ci		return;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	if (pm->suspended)
28062306a36Sopenharmony_ci		return;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	queue_work(dev->mt76.wq, &dev->reset_work);
28362306a36Sopenharmony_ci}
28462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_reset);
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_civoid mt792x_mac_init_band(struct mt792x_dev *dev, u8 band)
28762306a36Sopenharmony_ci{
28862306a36Sopenharmony_ci	u32 mask, set;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	mt76_rmw_field(dev, MT_TMAC_CTCR0(band),
29162306a36Sopenharmony_ci		       MT_TMAC_CTCR0_INS_DDLMT_REFTIME, 0x3f);
29262306a36Sopenharmony_ci	mt76_set(dev, MT_TMAC_CTCR0(band),
29362306a36Sopenharmony_ci		 MT_TMAC_CTCR0_INS_DDLMT_VHT_SMPDU_EN |
29462306a36Sopenharmony_ci		 MT_TMAC_CTCR0_INS_DDLMT_EN);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	mt76_set(dev, MT_WF_RMAC_MIB_TIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
29762306a36Sopenharmony_ci	mt76_set(dev, MT_WF_RMAC_MIB_AIRTIME0(band), MT_WF_RMAC_MIB_RXTIME_EN);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	/* enable MIB tx-rx time reporting */
30062306a36Sopenharmony_ci	mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_TXDUR_EN);
30162306a36Sopenharmony_ci	mt76_set(dev, MT_MIB_SCR1(band), MT_MIB_RXDUR_EN);
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	mt76_rmw_field(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_MAX_RX_LEN, 1536);
30462306a36Sopenharmony_ci	/* disable rx rate report by default due to hw issues */
30562306a36Sopenharmony_ci	mt76_clear(dev, MT_DMA_DCR0(band), MT_DMA_DCR0_RXD_G5_EN);
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	/* filter out non-resp frames and get instantaneous signal reporting */
30862306a36Sopenharmony_ci	mask = MT_WTBLOFF_TOP_RSCR_RCPI_MODE | MT_WTBLOFF_TOP_RSCR_RCPI_PARAM;
30962306a36Sopenharmony_ci	set = FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_MODE, 0) |
31062306a36Sopenharmony_ci	      FIELD_PREP(MT_WTBLOFF_TOP_RSCR_RCPI_PARAM, 0x3);
31162306a36Sopenharmony_ci	mt76_rmw(dev, MT_WTBLOFF_TOP_RSCR(band), mask, set);
31262306a36Sopenharmony_ci}
31362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_mac_init_band);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_civoid mt792x_pm_wake_work(struct work_struct *work)
31662306a36Sopenharmony_ci{
31762306a36Sopenharmony_ci	struct mt792x_dev *dev;
31862306a36Sopenharmony_ci	struct mt76_phy *mphy;
31962306a36Sopenharmony_ci
32062306a36Sopenharmony_ci	dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
32162306a36Sopenharmony_ci						pm.wake_work);
32262306a36Sopenharmony_ci	mphy = dev->phy.mt76;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_ci	if (!mt792x_mcu_drv_pmctrl(dev)) {
32562306a36Sopenharmony_ci		struct mt76_dev *mdev = &dev->mt76;
32662306a36Sopenharmony_ci		int i;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci		if (mt76_is_sdio(mdev)) {
32962306a36Sopenharmony_ci			mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
33062306a36Sopenharmony_ci			mt76_worker_schedule(&mdev->sdio.txrx_worker);
33162306a36Sopenharmony_ci		} else {
33262306a36Sopenharmony_ci			local_bh_disable();
33362306a36Sopenharmony_ci			mt76_for_each_q_rx(mdev, i)
33462306a36Sopenharmony_ci				napi_schedule(&mdev->napi[i]);
33562306a36Sopenharmony_ci			local_bh_enable();
33662306a36Sopenharmony_ci			mt76_connac_pm_dequeue_skbs(mphy, &dev->pm);
33762306a36Sopenharmony_ci			mt76_connac_tx_cleanup(mdev);
33862306a36Sopenharmony_ci		}
33962306a36Sopenharmony_ci		if (test_bit(MT76_STATE_RUNNING, &mphy->state))
34062306a36Sopenharmony_ci			ieee80211_queue_delayed_work(mphy->hw, &mphy->mac_work,
34162306a36Sopenharmony_ci						     MT792x_WATCHDOG_TIME);
34262306a36Sopenharmony_ci	}
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	ieee80211_wake_queues(mphy->hw);
34562306a36Sopenharmony_ci	wake_up(&dev->pm.wait);
34662306a36Sopenharmony_ci}
34762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_pm_wake_work);
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_civoid mt792x_pm_power_save_work(struct work_struct *work)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	struct mt792x_dev *dev;
35262306a36Sopenharmony_ci	unsigned long delta;
35362306a36Sopenharmony_ci	struct mt76_phy *mphy;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	dev = (struct mt792x_dev *)container_of(work, struct mt792x_dev,
35662306a36Sopenharmony_ci						pm.ps_work.work);
35762306a36Sopenharmony_ci	mphy = dev->phy.mt76;
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	delta = dev->pm.idle_timeout;
36062306a36Sopenharmony_ci	if (test_bit(MT76_HW_SCANNING, &mphy->state) ||
36162306a36Sopenharmony_ci	    test_bit(MT76_HW_SCHED_SCANNING, &mphy->state) ||
36262306a36Sopenharmony_ci	    dev->fw_assert)
36362306a36Sopenharmony_ci		goto out;
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ci	if (mutex_is_locked(&dev->mt76.mutex))
36662306a36Sopenharmony_ci		/* if mt76 mutex is held we should not put the device
36762306a36Sopenharmony_ci		 * to sleep since we are currently accessing device
36862306a36Sopenharmony_ci		 * register map. We need to wait for the next power_save
36962306a36Sopenharmony_ci		 * trigger.
37062306a36Sopenharmony_ci		 */
37162306a36Sopenharmony_ci		goto out;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	if (time_is_after_jiffies(dev->pm.last_activity + delta)) {
37462306a36Sopenharmony_ci		delta = dev->pm.last_activity + delta - jiffies;
37562306a36Sopenharmony_ci		goto out;
37662306a36Sopenharmony_ci	}
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	if (!mt792x_mcu_fw_pmctrl(dev)) {
37962306a36Sopenharmony_ci		cancel_delayed_work_sync(&mphy->mac_work);
38062306a36Sopenharmony_ci		return;
38162306a36Sopenharmony_ci	}
38262306a36Sopenharmony_ciout:
38362306a36Sopenharmony_ci	queue_delayed_work(dev->mt76.wq, &dev->pm.ps_work, delta);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt792x_pm_power_save_work);
386