10e3d6777SRyder Lee /* SPDX-License-Identifier: ISC */
27a07adcdSLorenzo Bianconi /*
37a07adcdSLorenzo Bianconi * Copyright (C) 2016 Felix Fietkau <nbd@nbd.name>
47a07adcdSLorenzo Bianconi * Copyright (C) 2018 Stanislaw Gruszka <stf_xl@wp.pl>
57a07adcdSLorenzo Bianconi */
67a07adcdSLorenzo Bianconi
731217429SLorenzo Bianconi #ifndef __MT76x02_H
831217429SLorenzo Bianconi #define __MT76x02_H
97a07adcdSLorenzo Bianconi
107a07adcdSLorenzo Bianconi #include <linux/kfifo.h>
117a07adcdSLorenzo Bianconi
127a07adcdSLorenzo Bianconi #include "mt76.h"
137a07adcdSLorenzo Bianconi #include "mt76x02_regs.h"
147a07adcdSLorenzo Bianconi #include "mt76x02_mac.h"
157a07adcdSLorenzo Bianconi #include "mt76x02_dfs.h"
167a07adcdSLorenzo Bianconi #include "mt76x02_dma.h"
177a07adcdSLorenzo Bianconi
189e47a683SFelix Fietkau #define MT76x02_TX_RING_SIZE 512
199e47a683SFelix Fietkau #define MT76x02_PSD_RING_SIZE 128
20238f5d6fSFelix Fietkau #define MT76x02_N_WCIDS 128
217dd73588SLorenzo Bianconi #define MT_CALIBRATE_INTERVAL HZ
222e405024SFelix Fietkau #define MT_MAC_WORK_INTERVAL (HZ / 10)
237a07adcdSLorenzo Bianconi
24c1e0d2beSLorenzo Bianconi #define MT_WATCHDOG_TIME (HZ / 10)
25c1e0d2beSLorenzo Bianconi #define MT_TX_HANG_TH 10
26c1e0d2beSLorenzo Bianconi
277a07adcdSLorenzo Bianconi #define MT_MAX_CHAINS 2
287a07adcdSLorenzo Bianconi struct mt76x02_rx_freq_cal {
297a07adcdSLorenzo Bianconi s8 high_gain[MT_MAX_CHAINS];
307a07adcdSLorenzo Bianconi s8 rssi_offset[MT_MAX_CHAINS];
317a07adcdSLorenzo Bianconi s8 lna_gain;
327a07adcdSLorenzo Bianconi u32 mcu_gain;
337a07adcdSLorenzo Bianconi s16 temp_offset;
347a07adcdSLorenzo Bianconi u8 freq_offset;
357a07adcdSLorenzo Bianconi };
367a07adcdSLorenzo Bianconi
377a07adcdSLorenzo Bianconi struct mt76x02_calibration {
387a07adcdSLorenzo Bianconi struct mt76x02_rx_freq_cal rx;
397a07adcdSLorenzo Bianconi
407a07adcdSLorenzo Bianconi u8 agc_gain_init[MT_MAX_CHAINS];
417a07adcdSLorenzo Bianconi u8 agc_gain_cur[MT_MAX_CHAINS];
427a07adcdSLorenzo Bianconi
437a07adcdSLorenzo Bianconi u16 false_cca;
447a07adcdSLorenzo Bianconi s8 avg_rssi_all;
457a07adcdSLorenzo Bianconi s8 agc_gain_adjust;
46a0ac8061SFelix Fietkau s8 agc_lowest_gain;
477a07adcdSLorenzo Bianconi s8 low_gain;
487a07adcdSLorenzo Bianconi
4966a34c66SLorenzo Bianconi s8 temp_vco;
5066a34c66SLorenzo Bianconi s8 temp;
517a07adcdSLorenzo Bianconi
527a07adcdSLorenzo Bianconi bool init_cal_done;
537a07adcdSLorenzo Bianconi bool tssi_cal_done;
547a07adcdSLorenzo Bianconi bool tssi_comp_pending;
557a07adcdSLorenzo Bianconi bool dpd_cal_done;
567a07adcdSLorenzo Bianconi bool channel_cal_done;
57f1b8ee35SStanislaw Gruszka bool gain_init_done;
583548a9ddSLorenzo Bianconi
593548a9ddSLorenzo Bianconi int tssi_target;
603548a9ddSLorenzo Bianconi s8 tssi_dc;
617a07adcdSLorenzo Bianconi };
627a07adcdSLorenzo Bianconi
63c004b881SStanislaw Gruszka struct mt76x02_beacon_ops {
64f2276c29SStanislaw Gruszka unsigned int nslots;
65f2276c29SStanislaw Gruszka unsigned int slot_size;
66ff97c52aSRyder Lee void (*pre_tbtt_enable)(struct mt76x02_dev *dev, bool en);
67ff97c52aSRyder Lee void (*beacon_enable)(struct mt76x02_dev *dev, bool en);
68c004b881SStanislaw Gruszka };
69c004b881SStanislaw Gruszka
701920a0ccSLorenzo Bianconi #define mt76x02_beacon_enable(dev, enable) \
711920a0ccSLorenzo Bianconi (dev)->beacon_ops->beacon_enable(dev, enable)
721920a0ccSLorenzo Bianconi #define mt76x02_pre_tbtt_enable(dev, enable) \
731920a0ccSLorenzo Bianconi (dev)->beacon_ops->pre_tbtt_enable(dev, enable)
741920a0ccSLorenzo Bianconi
75b376d963SFelix Fietkau struct mt76x02_rate_power {
76b376d963SFelix Fietkau union {
77b376d963SFelix Fietkau struct {
78b376d963SFelix Fietkau s8 cck[4];
79b376d963SFelix Fietkau s8 ofdm[8];
80b376d963SFelix Fietkau s8 ht[16];
81ba45841cSFelix Fietkau s8 vht[2];
82b376d963SFelix Fietkau };
83ba45841cSFelix Fietkau s8 all[30];
84b376d963SFelix Fietkau };
85b376d963SFelix Fietkau };
86b376d963SFelix Fietkau
877a07adcdSLorenzo Bianconi struct mt76x02_dev {
88ac24dd35SFelix Fietkau union { /* must be first */
89ac24dd35SFelix Fietkau struct mt76_dev mt76;
90ac24dd35SFelix Fietkau struct mt76_phy mphy;
91ac24dd35SFelix Fietkau };
927a07adcdSLorenzo Bianconi
937a07adcdSLorenzo Bianconi struct mac_address macaddr_list[8];
947a07adcdSLorenzo Bianconi
957a07adcdSLorenzo Bianconi struct mutex phy_mutex;
967a07adcdSLorenzo Bianconi
977a07adcdSLorenzo Bianconi u8 txdone_seq;
987a07adcdSLorenzo Bianconi DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status);
996fe53337SFelix Fietkau spinlock_t txstatus_fifo_lock;
100355f8d00SFelix Fietkau u32 tx_airtime;
10130684481SFelix Fietkau u32 ampdu_ref;
1027a07adcdSLorenzo Bianconi
1037a07adcdSLorenzo Bianconi struct sk_buff *rx_head;
1047a07adcdSLorenzo Bianconi
1057a07adcdSLorenzo Bianconi struct delayed_work cal_work;
106c1e0d2beSLorenzo Bianconi struct delayed_work wdt_work;
1077a07adcdSLorenzo Bianconi
1085a3f1cc2SStanislaw Gruszka struct hrtimer pre_tbtt_timer;
1095a3f1cc2SStanislaw Gruszka struct work_struct pre_tbtt_work;
1105a3f1cc2SStanislaw Gruszka
111c004b881SStanislaw Gruszka const struct mt76x02_beacon_ops *beacon_ops;
112c004b881SStanislaw Gruszka
113f27469a9SMarkus Theil u8 beacon_data_count;
1147a07adcdSLorenzo Bianconi
1157a07adcdSLorenzo Bianconi u8 tbtt_count;
1167a07adcdSLorenzo Bianconi
117c1e0d2beSLorenzo Bianconi u32 tx_hang_reset;
118c007ef8cSFelix Fietkau u8 tx_hang_check[4];
1192aa6c0fbSFelix Fietkau u8 beacon_hang_check;
12072e5d479SFelix Fietkau u8 mcu_timeout;
121c1e0d2beSLorenzo Bianconi
122b376d963SFelix Fietkau struct mt76x02_rate_power rate_power;
123b376d963SFelix Fietkau
1247a07adcdSLorenzo Bianconi struct mt76x02_calibration cal;
1257a07adcdSLorenzo Bianconi
1269e5f6dd7SFelix Fietkau int txpower_conf;
1277a07adcdSLorenzo Bianconi s8 target_power;
1287a07adcdSLorenzo Bianconi s8 target_power_delta[2];
1297a07adcdSLorenzo Bianconi bool enable_tpc;
1307a07adcdSLorenzo Bianconi
1317a07adcdSLorenzo Bianconi bool no_2ghz;
1327a07adcdSLorenzo Bianconi
133bae76a1eSLorenzo Bianconi s16 coverage_class;
1347a07adcdSLorenzo Bianconi u8 slottime;
1357a07adcdSLorenzo Bianconi
1367a07adcdSLorenzo Bianconi struct mt76x02_dfs_pattern_detector dfs_pd;
137f82ce8d9SLorenzo Bianconi
138f82ce8d9SLorenzo Bianconi /* edcca monitor */
139a0ac8061SFelix Fietkau unsigned long ed_trigger_timeout;
140f82ce8d9SLorenzo Bianconi bool ed_tx_blocked;
141f82ce8d9SLorenzo Bianconi bool ed_monitor;
142643749d4SFelix Fietkau u8 ed_monitor_enabled;
143a0ac8061SFelix Fietkau u8 ed_monitor_learning;
144f82ce8d9SLorenzo Bianconi u8 ed_trigger;
145f82ce8d9SLorenzo Bianconi u8 ed_silent;
146ccdaf7b4SFelix Fietkau ktime_t ed_time;
1477a07adcdSLorenzo Bianconi };
1487a07adcdSLorenzo Bianconi
1497a07adcdSLorenzo Bianconi extern struct ieee80211_rate mt76x02_rates[12];
1507a07adcdSLorenzo Bianconi
151633f77b5SLorenzo Bianconi int mt76x02_init_device(struct mt76x02_dev *dev);
1527a07adcdSLorenzo Bianconi void mt76x02_configure_filter(struct ieee80211_hw *hw,
1537a07adcdSLorenzo Bianconi unsigned int changed_flags,
1547a07adcdSLorenzo Bianconi unsigned int *total_flags, u64 multicast);
155e28487eaSFelix Fietkau int mt76x02_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,
1567a07adcdSLorenzo Bianconi struct ieee80211_sta *sta);
157e28487eaSFelix Fietkau void mt76x02_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,
1587a07adcdSLorenzo Bianconi struct ieee80211_sta *sta);
1597a07adcdSLorenzo Bianconi
160269906acSLorenzo Bianconi void mt76x02_config_mac_addr_list(struct mt76x02_dev *dev);
161f9a043c5SStanislaw Gruszka
1627a07adcdSLorenzo Bianconi int mt76x02_add_interface(struct ieee80211_hw *hw,
1637a07adcdSLorenzo Bianconi struct ieee80211_vif *vif);
1647a07adcdSLorenzo Bianconi void mt76x02_remove_interface(struct ieee80211_hw *hw,
1657a07adcdSLorenzo Bianconi struct ieee80211_vif *vif);
1667a07adcdSLorenzo Bianconi
1677a07adcdSLorenzo Bianconi int mt76x02_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
1687a07adcdSLorenzo Bianconi struct ieee80211_ampdu_params *params);
1697a07adcdSLorenzo Bianconi int mt76x02_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1707a07adcdSLorenzo Bianconi struct ieee80211_vif *vif, struct ieee80211_sta *sta,
1717a07adcdSLorenzo Bianconi struct ieee80211_key_conf *key);
1727a07adcdSLorenzo Bianconi int mt76x02_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
173b3e2130bSJohannes Berg unsigned int link_id, u16 queue,
174b3e2130bSJohannes Berg const struct ieee80211_tx_queue_params *params);
1757a07adcdSLorenzo Bianconi void mt76x02_sta_rate_tbl_update(struct ieee80211_hw *hw,
1767a07adcdSLorenzo Bianconi struct ieee80211_vif *vif,
1777a07adcdSLorenzo Bianconi struct ieee80211_sta *sta);
17891be8e8aSLorenzo Bianconi s8 mt76x02_tx_get_max_txpwr_adj(struct mt76x02_dev *dev,
1797a07adcdSLorenzo Bianconi const struct ieee80211_tx_rate *rate);
18091be8e8aSLorenzo Bianconi s8 mt76x02_tx_get_txpwr_adj(struct mt76x02_dev *dev, s8 txpwr,
18191be8e8aSLorenzo Bianconi s8 max_txpwr_adj);
182c1e0d2beSLorenzo Bianconi void mt76x02_wdt_work(struct work_struct *work);
1831ea0a1b1SLorenzo Bianconi void mt76x02_tx_set_txpwr_auto(struct mt76x02_dev *dev, s8 txpwr);
18436704051SLorenzo Bianconi void mt76x02_set_tx_ackto(struct mt76x02_dev *dev);
18536704051SLorenzo Bianconi void mt76x02_set_coverage_class(struct ieee80211_hw *hw,
18636704051SLorenzo Bianconi s16 coverage_class);
187317ed42bSLorenzo Bianconi int mt76x02_set_rts_threshold(struct ieee80211_hw *hw, u32 val);
1887a07adcdSLorenzo Bianconi void mt76x02_remove_hdr_pad(struct sk_buff *skb, int len);
1898d66af49SLorenzo Bianconi bool mt76x02_tx_status_data(struct mt76_dev *mdev, u8 *update);
1907a07adcdSLorenzo Bianconi void mt76x02_queue_rx_skb(struct mt76_dev *mdev, enum mt76_rxq_id q,
191*c3137942SSujuan Chen struct sk_buff *skb, u32 *info);
1929b43960bSLorenzo Bianconi void mt76x02_rx_poll_complete(struct mt76_dev *mdev, enum mt76_rxq_id q);
1939b43960bSLorenzo Bianconi irqreturn_t mt76x02_irq_handler(int irq, void *dev_instance);
1947a07adcdSLorenzo Bianconi void mt76x02_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
1957a07adcdSLorenzo Bianconi struct sk_buff *skb);
1965ec57485SLorenzo Bianconi int mt76x02_tx_prepare_skb(struct mt76_dev *mdev, void *txwi,
197cfaae9e6SLorenzo Bianconi enum mt76_txq_id qid, struct mt76_wcid *wcid,
198cfaae9e6SLorenzo Bianconi struct ieee80211_sta *sta,
199b5903c47SLorenzo Bianconi struct mt76_tx_info *tx_info);
200c2756a1cSLorenzo Bianconi void mt76x02_sw_scan_complete(struct ieee80211_hw *hw,
201c2756a1cSLorenzo Bianconi struct ieee80211_vif *vif);
202f7c8a0f2SLorenzo Bianconi void mt76x02_sta_ps(struct mt76_dev *dev, struct ieee80211_sta *sta, bool ps);
203cc726268SLorenzo Bianconi void mt76x02_bss_info_changed(struct ieee80211_hw *hw,
204cc726268SLorenzo Bianconi struct ieee80211_vif *vif,
2057b7090b4SJohannes Berg struct ieee80211_bss_conf *info, u64 changed);
206fd6c2dfaSFelix Fietkau void mt76x02_reconfig_complete(struct ieee80211_hw *hw,
207fd6c2dfaSFelix Fietkau enum ieee80211_reconfig_type reconfig_type);
2087a07adcdSLorenzo Bianconi
20931cdd442SStanislaw Gruszka struct beacon_bc_data {
21031cdd442SStanislaw Gruszka struct mt76x02_dev *dev;
21131cdd442SStanislaw Gruszka struct sk_buff_head q;
21231cdd442SStanislaw Gruszka struct sk_buff *tail[8];
21331cdd442SStanislaw Gruszka };
214ff97c52aSRyder Lee
215fc245983SLorenzo Bianconi void mt76x02_init_beacon_config(struct mt76x02_dev *dev);
2168d71aef9SStanislaw Gruszka void mt76x02e_init_beacon_config(struct mt76x02_dev *dev);
21731cdd442SStanislaw Gruszka void mt76x02_resync_beacon_timer(struct mt76x02_dev *dev);
21831cdd442SStanislaw Gruszka void mt76x02_update_beacon_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
21931cdd442SStanislaw Gruszka void mt76x02_enqueue_buffered_bc(struct mt76x02_dev *dev,
22031cdd442SStanislaw Gruszka struct beacon_bc_data *data,
22131cdd442SStanislaw Gruszka int max_nframes);
22231cdd442SStanislaw Gruszka
223a23fde09SLorenzo Bianconi void mt76x02_mac_start(struct mt76x02_dev *dev);
2247a07adcdSLorenzo Bianconi
22576055413SLorenzo Bianconi void mt76x02_init_debugfs(struct mt76x02_dev *dev);
22676055413SLorenzo Bianconi
is_mt76x0(struct mt76x02_dev * dev)22740b94161SStanislaw Gruszka static inline bool is_mt76x0(struct mt76x02_dev *dev)
22840b94161SStanislaw Gruszka {
22940b94161SStanislaw Gruszka return mt76_chip(&dev->mt76) == 0x7610 ||
23040b94161SStanislaw Gruszka mt76_chip(&dev->mt76) == 0x7630 ||
23140b94161SStanislaw Gruszka mt76_chip(&dev->mt76) == 0x7650;
23240b94161SStanislaw Gruszka }
23340b94161SStanislaw Gruszka
is_mt76x2(struct mt76x02_dev * dev)234320c85e6SLorenzo Bianconi static inline bool is_mt76x2(struct mt76x02_dev *dev)
235320c85e6SLorenzo Bianconi {
236320c85e6SLorenzo Bianconi return mt76_chip(&dev->mt76) == 0x7612 ||
237b2934279SMatthew Garrett mt76_chip(&dev->mt76) == 0x7632 ||
238320c85e6SLorenzo Bianconi mt76_chip(&dev->mt76) == 0x7662 ||
239320c85e6SLorenzo Bianconi mt76_chip(&dev->mt76) == 0x7602;
240320c85e6SLorenzo Bianconi }
241320c85e6SLorenzo Bianconi
mt76x02_irq_enable(struct mt76x02_dev * dev,u32 mask)242a23fde09SLorenzo Bianconi static inline void mt76x02_irq_enable(struct mt76x02_dev *dev, u32 mask)
2437a07adcdSLorenzo Bianconi {
2449220f695SLorenzo Bianconi mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, 0, mask);
2457a07adcdSLorenzo Bianconi }
2467a07adcdSLorenzo Bianconi
mt76x02_irq_disable(struct mt76x02_dev * dev,u32 mask)247a23fde09SLorenzo Bianconi static inline void mt76x02_irq_disable(struct mt76x02_dev *dev, u32 mask)
2487a07adcdSLorenzo Bianconi {
2499220f695SLorenzo Bianconi mt76_set_irq_mask(&dev->mt76, MT_INT_MASK_CSR, mask, 0);
2507a07adcdSLorenzo Bianconi }
2517a07adcdSLorenzo Bianconi
2527a07adcdSLorenzo Bianconi static inline bool
mt76x02_wait_for_txrx_idle(struct mt76_dev * dev)2537a07adcdSLorenzo Bianconi mt76x02_wait_for_txrx_idle(struct mt76_dev *dev)
2547a07adcdSLorenzo Bianconi {
2557a07adcdSLorenzo Bianconi return __mt76_poll_msec(dev, MT_MAC_STATUS,
2567a07adcdSLorenzo Bianconi MT_MAC_STATUS_TX | MT_MAC_STATUS_RX,
2577a07adcdSLorenzo Bianconi 0, 100);
2587a07adcdSLorenzo Bianconi }
2597a07adcdSLorenzo Bianconi
2607a07adcdSLorenzo Bianconi static inline struct mt76x02_sta *
mt76x02_rx_get_sta(struct mt76_dev * dev,u8 idx)2617a07adcdSLorenzo Bianconi mt76x02_rx_get_sta(struct mt76_dev *dev, u8 idx)
2627a07adcdSLorenzo Bianconi {
2637a07adcdSLorenzo Bianconi struct mt76_wcid *wcid;
2647a07adcdSLorenzo Bianconi
265238f5d6fSFelix Fietkau if (idx >= MT76x02_N_WCIDS)
2667a07adcdSLorenzo Bianconi return NULL;
2677a07adcdSLorenzo Bianconi
2687a07adcdSLorenzo Bianconi wcid = rcu_dereference(dev->wcid[idx]);
2697a07adcdSLorenzo Bianconi if (!wcid)
2707a07adcdSLorenzo Bianconi return NULL;
2717a07adcdSLorenzo Bianconi
2727a07adcdSLorenzo Bianconi return container_of(wcid, struct mt76x02_sta, wcid);
2737a07adcdSLorenzo Bianconi }
2747a07adcdSLorenzo Bianconi
2757a07adcdSLorenzo Bianconi static inline struct mt76_wcid *
mt76x02_rx_get_sta_wcid(struct mt76x02_sta * sta,bool unicast)2767a07adcdSLorenzo Bianconi mt76x02_rx_get_sta_wcid(struct mt76x02_sta *sta, bool unicast)
2777a07adcdSLorenzo Bianconi {
2787a07adcdSLorenzo Bianconi if (!sta)
2797a07adcdSLorenzo Bianconi return NULL;
2807a07adcdSLorenzo Bianconi
2817a07adcdSLorenzo Bianconi if (unicast)
2827a07adcdSLorenzo Bianconi return &sta->wcid;
2837a07adcdSLorenzo Bianconi else
2847a07adcdSLorenzo Bianconi return &sta->vif->group_wcid;
2857a07adcdSLorenzo Bianconi }
2867a07adcdSLorenzo Bianconi
28731217429SLorenzo Bianconi #endif /* __MT76x02_H */
288