162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci#include "mt7615.h"
462306a36Sopenharmony_ci
562306a36Sopenharmony_cistatic int
662306a36Sopenharmony_cimt7615_reg_set(void *data, u64 val)
762306a36Sopenharmony_ci{
862306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
1162306a36Sopenharmony_ci	mt76_wr(dev, dev->mt76.debugfs_reg, val);
1262306a36Sopenharmony_ci	mt7615_mutex_release(dev);
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci	return 0;
1562306a36Sopenharmony_ci}
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_cistatic int
1862306a36Sopenharmony_cimt7615_reg_get(void *data, u64 *val)
1962306a36Sopenharmony_ci{
2062306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
2362306a36Sopenharmony_ci	*val = mt76_rr(dev, dev->mt76.debugfs_reg);
2462306a36Sopenharmony_ci	mt7615_mutex_release(dev);
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	return 0;
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7615_reg_get, mt7615_reg_set,
3062306a36Sopenharmony_ci			 "0x%08llx\n");
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic int
3362306a36Sopenharmony_cimt7615_radar_pattern_set(void *data, u64 val)
3462306a36Sopenharmony_ci{
3562306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
3662306a36Sopenharmony_ci	int err;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
3962306a36Sopenharmony_ci		return 0;
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
4262306a36Sopenharmony_ci	err = mt7615_mcu_rdd_send_pattern(dev);
4362306a36Sopenharmony_ci	mt7615_mutex_release(dev);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	return err;
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_radar_pattern, NULL,
4962306a36Sopenharmony_ci			 mt7615_radar_pattern_set, "%lld\n");
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int mt7615_config(void *data, u64 val)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
5462306a36Sopenharmony_ci	int ret;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
5762306a36Sopenharmony_ci	ret = mt76_connac_mcu_chip_config(&dev->mt76);
5862306a36Sopenharmony_ci	mt7615_mutex_release(dev);
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	return ret;
6162306a36Sopenharmony_ci}
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_config, NULL, mt7615_config, "%lld\n");
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic int
6662306a36Sopenharmony_cimt7615_scs_set(void *data, u64 val)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
6962306a36Sopenharmony_ci	struct mt7615_phy *ext_phy;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
7262306a36Sopenharmony_ci		return 0;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	mt7615_mac_set_scs(&dev->phy, val);
7562306a36Sopenharmony_ci	ext_phy = mt7615_ext_phy(dev);
7662306a36Sopenharmony_ci	if (ext_phy)
7762306a36Sopenharmony_ci		mt7615_mac_set_scs(ext_phy, val);
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	return 0;
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic int
8362306a36Sopenharmony_cimt7615_scs_get(void *data, u64 *val)
8462306a36Sopenharmony_ci{
8562306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	*val = dev->phy.scs_en;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	return 0;
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_scs, mt7615_scs_get,
9362306a36Sopenharmony_ci			 mt7615_scs_set, "%lld\n");
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic int
9662306a36Sopenharmony_cimt7615_pm_set(void *data, u64 val)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
9962306a36Sopenharmony_ci	struct mt76_connac_pm *pm = &dev->pm;
10062306a36Sopenharmony_ci	int ret = 0;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
10362306a36Sopenharmony_ci		return 0;
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci	if (!mt7615_firmware_offload(dev) || mt76_is_usb(&dev->mt76))
10662306a36Sopenharmony_ci		return -EOPNOTSUPP;
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci	mutex_lock(&dev->mt76.mutex);
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	if (val == pm->enable)
11162306a36Sopenharmony_ci		goto out;
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci	if (dev->phy.n_beacon_vif) {
11462306a36Sopenharmony_ci		ret = -EBUSY;
11562306a36Sopenharmony_ci		goto out;
11662306a36Sopenharmony_ci	}
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	if (!pm->enable) {
11962306a36Sopenharmony_ci		pm->stats.last_wake_event = jiffies;
12062306a36Sopenharmony_ci		pm->stats.last_doze_event = jiffies;
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci	/* make sure the chip is awake here and ps_work is scheduled
12362306a36Sopenharmony_ci	 * just at end of the this routine.
12462306a36Sopenharmony_ci	 */
12562306a36Sopenharmony_ci	pm->enable = false;
12662306a36Sopenharmony_ci	mt76_connac_pm_wake(&dev->mphy, pm);
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ci	pm->enable = val;
12962306a36Sopenharmony_ci	mt76_connac_power_save_sched(&dev->mphy, pm);
13062306a36Sopenharmony_ciout:
13162306a36Sopenharmony_ci	mutex_unlock(&dev->mt76.mutex);
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci	return ret;
13462306a36Sopenharmony_ci}
13562306a36Sopenharmony_ci
13662306a36Sopenharmony_cistatic int
13762306a36Sopenharmony_cimt7615_pm_get(void *data, u64 *val)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	*val = dev->pm.enable;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	return 0;
14462306a36Sopenharmony_ci}
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7615_pm_get, mt7615_pm_set, "%lld\n");
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic int
14962306a36Sopenharmony_cimt7615_pm_stats(struct seq_file *s, void *data)
15062306a36Sopenharmony_ci{
15162306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
15262306a36Sopenharmony_ci	struct mt76_connac_pm *pm = &dev->pm;
15362306a36Sopenharmony_ci	unsigned long awake_time = pm->stats.awake_time;
15462306a36Sopenharmony_ci	unsigned long doze_time = pm->stats.doze_time;
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	if (!test_bit(MT76_STATE_PM, &dev->mphy.state))
15762306a36Sopenharmony_ci		awake_time += jiffies - pm->stats.last_wake_event;
15862306a36Sopenharmony_ci	else
15962306a36Sopenharmony_ci		doze_time += jiffies - pm->stats.last_doze_event;
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	seq_printf(s, "awake time: %14u\ndoze time: %15u\n",
16262306a36Sopenharmony_ci		   jiffies_to_msecs(awake_time),
16362306a36Sopenharmony_ci		   jiffies_to_msecs(doze_time));
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci	return 0;
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic int
16962306a36Sopenharmony_cimt7615_pm_idle_timeout_set(void *data, u64 val)
17062306a36Sopenharmony_ci{
17162306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	dev->pm.idle_timeout = msecs_to_jiffies(val);
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	return 0;
17662306a36Sopenharmony_ci}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_cistatic int
17962306a36Sopenharmony_cimt7615_pm_idle_timeout_get(void *data, u64 *val)
18062306a36Sopenharmony_ci{
18162306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	*val = jiffies_to_msecs(dev->pm.idle_timeout);
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	return 0;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt7615_pm_idle_timeout_get,
18962306a36Sopenharmony_ci			 mt7615_pm_idle_timeout_set, "%lld\n");
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic int
19262306a36Sopenharmony_cimt7615_dbdc_set(void *data, u64 val)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
19762306a36Sopenharmony_ci		return 0;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if (val)
20062306a36Sopenharmony_ci		mt7615_register_ext_phy(dev);
20162306a36Sopenharmony_ci	else
20262306a36Sopenharmony_ci		mt7615_unregister_ext_phy(dev);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	return 0;
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistatic int
20862306a36Sopenharmony_cimt7615_dbdc_get(void *data, u64 *val)
20962306a36Sopenharmony_ci{
21062306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	*val = !!mt7615_ext_phy(dev);
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return 0;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_dbdc, mt7615_dbdc_get,
21862306a36Sopenharmony_ci			 mt7615_dbdc_set, "%lld\n");
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_cistatic int
22162306a36Sopenharmony_cimt7615_fw_debug_set(void *data, u64 val)
22262306a36Sopenharmony_ci{
22362306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
22662306a36Sopenharmony_ci		return 0;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	dev->fw_debug = val;
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
23162306a36Sopenharmony_ci	mt7615_mcu_fw_log_2_host(dev, dev->fw_debug ? 2 : 0);
23262306a36Sopenharmony_ci	mt7615_mutex_release(dev);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	return 0;
23562306a36Sopenharmony_ci}
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_cistatic int
23862306a36Sopenharmony_cimt7615_fw_debug_get(void *data, u64 *val)
23962306a36Sopenharmony_ci{
24062306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
24162306a36Sopenharmony_ci
24262306a36Sopenharmony_ci	*val = dev->fw_debug;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	return 0;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7615_fw_debug_get,
24862306a36Sopenharmony_ci			 mt7615_fw_debug_set, "%lld\n");
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_cistatic int
25162306a36Sopenharmony_cimt7615_reset_test_set(void *data, u64 val)
25262306a36Sopenharmony_ci{
25362306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
25462306a36Sopenharmony_ci	struct sk_buff *skb;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	if (!mt7615_wait_for_mcu_init(dev))
25762306a36Sopenharmony_ci		return 0;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	skb = alloc_skb(1, GFP_KERNEL);
26062306a36Sopenharmony_ci	if (!skb)
26162306a36Sopenharmony_ci		return -ENOMEM;
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	skb_put(skb, 1);
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
26662306a36Sopenharmony_ci	mt76_tx_queue_skb_raw(dev, dev->mphy.q_tx[0], skb, 0);
26762306a36Sopenharmony_ci	mt7615_mutex_release(dev);
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_ci	return 0;
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_reset_test, NULL,
27362306a36Sopenharmony_ci			 mt7615_reset_test_set, "%lld\n");
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_cistatic void
27662306a36Sopenharmony_cimt7615_ampdu_stat_read_phy(struct mt7615_phy *phy,
27762306a36Sopenharmony_ci			   struct seq_file *file)
27862306a36Sopenharmony_ci{
27962306a36Sopenharmony_ci	struct mt7615_dev *dev = file->private;
28062306a36Sopenharmony_ci	u32 reg = is_mt7663(&dev->mt76) ? MT_MIB_ARNG(0) : MT_AGG_ASRCR0;
28162306a36Sopenharmony_ci	int bound[7], i, range;
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	if (!phy)
28462306a36Sopenharmony_ci		return;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	range = mt76_rr(dev, reg);
28762306a36Sopenharmony_ci	for (i = 0; i < 4; i++)
28862306a36Sopenharmony_ci		bound[i] = MT_AGG_ASRCR_RANGE(range, i) + 1;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	range = mt76_rr(dev, reg + 4);
29162306a36Sopenharmony_ci	for (i = 0; i < 3; i++)
29262306a36Sopenharmony_ci		bound[i + 4] = MT_AGG_ASRCR_RANGE(range, i) + 1;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	seq_printf(file, "\nPhy %d\n", phy != &dev->phy);
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	seq_printf(file, "Length: %8d | ", bound[0]);
29762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bound) - 1; i++)
29862306a36Sopenharmony_ci		seq_printf(file, "%3d -%3d | ",
29962306a36Sopenharmony_ci			   bound[i], bound[i + 1]);
30062306a36Sopenharmony_ci	seq_puts(file, "\nCount:  ");
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(bound); i++)
30362306a36Sopenharmony_ci		seq_printf(file, "%8d | ", phy->mt76->aggr_stats[i]);
30462306a36Sopenharmony_ci	seq_puts(file, "\n");
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	seq_printf(file, "BA miss count: %d\n", phy->mib.ba_miss_cnt);
30762306a36Sopenharmony_ci	seq_printf(file, "PER: %ld.%1ld%%\n",
30862306a36Sopenharmony_ci		   phy->mib.aggr_per / 10, phy->mib.aggr_per % 10);
30962306a36Sopenharmony_ci}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_cistatic int
31262306a36Sopenharmony_cimt7615_ampdu_stat_show(struct seq_file *file, void *data)
31362306a36Sopenharmony_ci{
31462306a36Sopenharmony_ci	struct mt7615_dev *dev = file->private;
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci	mt7615_ampdu_stat_read_phy(&dev->phy, file);
31962306a36Sopenharmony_ci	mt7615_ampdu_stat_read_phy(mt7615_ext_phy(dev), file);
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	mt7615_mutex_release(dev);
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	return 0;
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mt7615_ampdu_stat);
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic void
32962306a36Sopenharmony_cimt7615_radio_read_phy(struct mt7615_phy *phy, struct seq_file *s)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
33262306a36Sopenharmony_ci	bool ext_phy = phy != &dev->phy;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	if (!phy)
33562306a36Sopenharmony_ci		return;
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	seq_printf(s, "Radio %d sensitivity: ofdm=%d cck=%d\n", ext_phy,
33862306a36Sopenharmony_ci		   phy->ofdm_sensitivity, phy->cck_sensitivity);
33962306a36Sopenharmony_ci	seq_printf(s, "Radio %d false CCA: ofdm=%d cck=%d\n", ext_phy,
34062306a36Sopenharmony_ci		   phy->false_cca_ofdm, phy->false_cca_cck);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic int
34462306a36Sopenharmony_cimt7615_radio_read(struct seq_file *s, void *data)
34562306a36Sopenharmony_ci{
34662306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	mt7615_radio_read_phy(&dev->phy, s);
34962306a36Sopenharmony_ci	mt7615_radio_read_phy(mt7615_ext_phy(dev), s);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci	return 0;
35262306a36Sopenharmony_ci}
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_cistatic int
35562306a36Sopenharmony_cimt7615_queues_acq(struct seq_file *s, void *data)
35662306a36Sopenharmony_ci{
35762306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
35862306a36Sopenharmony_ci	int i;
35962306a36Sopenharmony_ci
36062306a36Sopenharmony_ci	mt7615_mutex_acquire(dev);
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	for (i = 0; i < 16; i++) {
36362306a36Sopenharmony_ci		int j, wmm_idx = i % MT7615_MAX_WMM_SETS;
36462306a36Sopenharmony_ci		int acs = i / MT7615_MAX_WMM_SETS;
36562306a36Sopenharmony_ci		u32 ctrl, val, qlen = 0;
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci		if (wmm_idx == 3 && is_mt7663(&dev->mt76))
36862306a36Sopenharmony_ci			continue;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci		val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx));
37162306a36Sopenharmony_ci		ctrl = BIT(31) | BIT(15) | (acs << 8);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci		for (j = 0; j < 32; j++) {
37462306a36Sopenharmony_ci			if (val & BIT(j))
37562306a36Sopenharmony_ci				continue;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci			mt76_wr(dev, MT_PLE_FL_Q0_CTRL,
37862306a36Sopenharmony_ci				ctrl | (j + (wmm_idx << 5)));
37962306a36Sopenharmony_ci			qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL,
38062306a36Sopenharmony_ci					       GENMASK(11, 0));
38162306a36Sopenharmony_ci		}
38262306a36Sopenharmony_ci		seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen);
38362306a36Sopenharmony_ci	}
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	mt7615_mutex_release(dev);
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	return 0;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_cistatic int
39162306a36Sopenharmony_cimt7615_queues_read(struct seq_file *s, void *data)
39262306a36Sopenharmony_ci{
39362306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
39462306a36Sopenharmony_ci	struct {
39562306a36Sopenharmony_ci		struct mt76_queue *q;
39662306a36Sopenharmony_ci		char *queue;
39762306a36Sopenharmony_ci	} queue_map[] = {
39862306a36Sopenharmony_ci		{ dev->mphy.q_tx[MT_TXQ_BE], "PDMA0" },
39962306a36Sopenharmony_ci		{ dev->mt76.q_mcu[MT_MCUQ_WM], "MCUQ" },
40062306a36Sopenharmony_ci		{ dev->mt76.q_mcu[MT_MCUQ_FWDL], "MCUFWQ" },
40162306a36Sopenharmony_ci	};
40262306a36Sopenharmony_ci	int i;
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(queue_map); i++) {
40562306a36Sopenharmony_ci		struct mt76_queue *q = queue_map[i].q;
40662306a36Sopenharmony_ci
40762306a36Sopenharmony_ci		seq_printf(s,
40862306a36Sopenharmony_ci			   "%s:	queued=%d head=%d tail=%d\n",
40962306a36Sopenharmony_ci			   queue_map[i].queue, q->queued, q->head,
41062306a36Sopenharmony_ci			   q->tail);
41162306a36Sopenharmony_ci	}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	return 0;
41462306a36Sopenharmony_ci}
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_cistatic int
41762306a36Sopenharmony_cimt7615_rf_reg_set(void *data, u64 val)
41862306a36Sopenharmony_ci{
41962306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	mt7615_rf_wr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg, val);
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	return 0;
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic int
42762306a36Sopenharmony_cimt7615_rf_reg_get(void *data, u64 *val)
42862306a36Sopenharmony_ci{
42962306a36Sopenharmony_ci	struct mt7615_dev *dev = data;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	*val = mt7615_rf_rr(dev, dev->debugfs_rf_wf, dev->debugfs_rf_reg);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	return 0;
43462306a36Sopenharmony_ci}
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_rf_reg, mt7615_rf_reg_get, mt7615_rf_reg_set,
43762306a36Sopenharmony_ci			 "0x%08llx\n");
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic ssize_t
44062306a36Sopenharmony_cimt7615_ext_mac_addr_read(struct file *file, char __user *userbuf,
44162306a36Sopenharmony_ci			 size_t count, loff_t *ppos)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	struct mt7615_dev *dev = file->private_data;
44462306a36Sopenharmony_ci	u32 len = 32 * ((ETH_ALEN * 3) + 4) + 1;
44562306a36Sopenharmony_ci	u8 addr[ETH_ALEN];
44662306a36Sopenharmony_ci	char *buf;
44762306a36Sopenharmony_ci	int ofs = 0;
44862306a36Sopenharmony_ci	int i;
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	buf = kzalloc(len, GFP_KERNEL);
45162306a36Sopenharmony_ci	if (!buf)
45262306a36Sopenharmony_ci		return -ENOMEM;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	for (i = 0; i < 32; i++) {
45562306a36Sopenharmony_ci		if (!(dev->muar_mask & BIT(i)))
45662306a36Sopenharmony_ci			continue;
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci		mt76_wr(dev, MT_WF_RMAC_MAR1,
45962306a36Sopenharmony_ci			FIELD_PREP(MT_WF_RMAC_MAR1_IDX, i * 2) |
46062306a36Sopenharmony_ci			MT_WF_RMAC_MAR1_START);
46162306a36Sopenharmony_ci		put_unaligned_le32(mt76_rr(dev, MT_WF_RMAC_MAR0), addr);
46262306a36Sopenharmony_ci		put_unaligned_le16((mt76_rr(dev, MT_WF_RMAC_MAR1) &
46362306a36Sopenharmony_ci				    MT_WF_RMAC_MAR1_ADDR), addr + 4);
46462306a36Sopenharmony_ci		ofs += snprintf(buf + ofs, len - ofs, "%d=%pM\n", i, addr);
46562306a36Sopenharmony_ci	}
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	ofs = simple_read_from_buffer(userbuf, count, ppos, buf, ofs);
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci	kfree(buf);
47062306a36Sopenharmony_ci	return ofs;
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic ssize_t
47462306a36Sopenharmony_cimt7615_ext_mac_addr_write(struct file *file, const char __user *userbuf,
47562306a36Sopenharmony_ci			  size_t count, loff_t *ppos)
47662306a36Sopenharmony_ci{
47762306a36Sopenharmony_ci	struct mt7615_dev *dev = file->private_data;
47862306a36Sopenharmony_ci	unsigned long idx = 0;
47962306a36Sopenharmony_ci	u8 addr[ETH_ALEN];
48062306a36Sopenharmony_ci	char buf[32];
48162306a36Sopenharmony_ci	char *p;
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_ci	if (count > sizeof(buf))
48462306a36Sopenharmony_ci		return -EINVAL;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	if (copy_from_user(buf, userbuf, count))
48762306a36Sopenharmony_ci		return -EFAULT;
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci	buf[sizeof(buf) - 1] = '\0';
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	p = strchr(buf, '=');
49262306a36Sopenharmony_ci	if (p) {
49362306a36Sopenharmony_ci		*p = 0;
49462306a36Sopenharmony_ci		p++;
49562306a36Sopenharmony_ci
49662306a36Sopenharmony_ci		if (kstrtoul(buf, 0, &idx) || idx > 31)
49762306a36Sopenharmony_ci			return -EINVAL;
49862306a36Sopenharmony_ci	} else {
49962306a36Sopenharmony_ci		idx = 0;
50062306a36Sopenharmony_ci		p = buf;
50162306a36Sopenharmony_ci	}
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	if (!mac_pton(p, addr))
50462306a36Sopenharmony_ci		return -EINVAL;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	if (is_valid_ether_addr(addr)) {
50762306a36Sopenharmony_ci		dev->muar_mask |= BIT(idx);
50862306a36Sopenharmony_ci	} else {
50962306a36Sopenharmony_ci		memset(addr, 0, sizeof(addr));
51062306a36Sopenharmony_ci		dev->muar_mask &= ~BIT(idx);
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci	mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, 1);
51462306a36Sopenharmony_ci	mt76_wr(dev, MT_WF_RMAC_MAR0, get_unaligned_le32(addr));
51562306a36Sopenharmony_ci	mt76_wr(dev, MT_WF_RMAC_MAR1,
51662306a36Sopenharmony_ci		get_unaligned_le16(addr + 4) |
51762306a36Sopenharmony_ci		FIELD_PREP(MT_WF_RMAC_MAR1_IDX, idx * 2) |
51862306a36Sopenharmony_ci		MT_WF_RMAC_MAR1_START |
51962306a36Sopenharmony_ci		MT_WF_RMAC_MAR1_WRITE);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	mt76_rmw_field(dev, MT_WF_RMAC_MORE(0), MT_WF_RMAC_MORE_MUAR_MODE, !!dev->muar_mask);
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci	return count;
52462306a36Sopenharmony_ci}
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_cistatic const struct file_operations fops_ext_mac_addr = {
52762306a36Sopenharmony_ci	.open = simple_open,
52862306a36Sopenharmony_ci	.llseek = generic_file_llseek,
52962306a36Sopenharmony_ci	.read = mt7615_ext_mac_addr_read,
53062306a36Sopenharmony_ci	.write = mt7615_ext_mac_addr_write,
53162306a36Sopenharmony_ci	.owner = THIS_MODULE,
53262306a36Sopenharmony_ci};
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_cistatic int
53562306a36Sopenharmony_cimt7663s_sched_quota_read(struct seq_file *s, void *data)
53662306a36Sopenharmony_ci{
53762306a36Sopenharmony_ci	struct mt7615_dev *dev = dev_get_drvdata(s->private);
53862306a36Sopenharmony_ci	struct mt76_sdio *sdio = &dev->mt76.sdio;
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota);
54162306a36Sopenharmony_ci	seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota);
54262306a36Sopenharmony_ci	seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota);
54362306a36Sopenharmony_ci	seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit);
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	return 0;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ciint mt7615_init_debugfs(struct mt7615_dev *dev)
54962306a36Sopenharmony_ci{
55062306a36Sopenharmony_ci	struct dentry *dir;
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval);
55362306a36Sopenharmony_ci	if (!dir)
55462306a36Sopenharmony_ci		return -ENOMEM;
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (is_mt7615(&dev->mt76))
55762306a36Sopenharmony_ci		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
55862306a36Sopenharmony_ci					    mt7615_queues_read);
55962306a36Sopenharmony_ci	else
56062306a36Sopenharmony_ci		debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", dir,
56162306a36Sopenharmony_ci					    mt76_queues_read);
56262306a36Sopenharmony_ci	debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
56362306a36Sopenharmony_ci				    mt7615_queues_acq);
56462306a36Sopenharmony_ci	debugfs_create_file("ampdu_stat", 0400, dir, dev, &mt7615_ampdu_stat_fops);
56562306a36Sopenharmony_ci	debugfs_create_file("scs", 0600, dir, dev, &fops_scs);
56662306a36Sopenharmony_ci	debugfs_create_file("dbdc", 0600, dir, dev, &fops_dbdc);
56762306a36Sopenharmony_ci	debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
56862306a36Sopenharmony_ci	debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
56962306a36Sopenharmony_ci	debugfs_create_file("idle-timeout", 0600, dir, dev,
57062306a36Sopenharmony_ci			    &fops_pm_idle_timeout);
57162306a36Sopenharmony_ci	debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir,
57262306a36Sopenharmony_ci				    mt7615_pm_stats);
57362306a36Sopenharmony_ci	debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir,
57462306a36Sopenharmony_ci				    mt7615_radio_read);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	if (is_mt7615(&dev->mt76)) {
57762306a36Sopenharmony_ci		debugfs_create_u32("dfs_hw_pattern", 0400, dir,
57862306a36Sopenharmony_ci				   &dev->hw_pattern);
57962306a36Sopenharmony_ci		/* test pattern knobs */
58062306a36Sopenharmony_ci		debugfs_create_u8("pattern_len", 0600, dir,
58162306a36Sopenharmony_ci				  &dev->radar_pattern.n_pulses);
58262306a36Sopenharmony_ci		debugfs_create_u32("pulse_period", 0600, dir,
58362306a36Sopenharmony_ci				   &dev->radar_pattern.period);
58462306a36Sopenharmony_ci		debugfs_create_u16("pulse_width", 0600, dir,
58562306a36Sopenharmony_ci				   &dev->radar_pattern.width);
58662306a36Sopenharmony_ci		debugfs_create_u16("pulse_power", 0600, dir,
58762306a36Sopenharmony_ci				   &dev->radar_pattern.power);
58862306a36Sopenharmony_ci		debugfs_create_file("radar_trigger", 0200, dir, dev,
58962306a36Sopenharmony_ci				    &fops_radar_pattern);
59062306a36Sopenharmony_ci	}
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	debugfs_create_file("reset_test", 0200, dir, dev,
59362306a36Sopenharmony_ci			    &fops_reset_test);
59462306a36Sopenharmony_ci	debugfs_create_file("ext_mac_addr", 0600, dir, dev, &fops_ext_mac_addr);
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	debugfs_create_u32("rf_wfidx", 0600, dir, &dev->debugfs_rf_wf);
59762306a36Sopenharmony_ci	debugfs_create_u32("rf_regidx", 0600, dir, &dev->debugfs_rf_reg);
59862306a36Sopenharmony_ci	debugfs_create_file_unsafe("rf_regval", 0600, dir, dev,
59962306a36Sopenharmony_ci				   &fops_rf_reg);
60062306a36Sopenharmony_ci	if (is_mt7663(&dev->mt76))
60162306a36Sopenharmony_ci		debugfs_create_file("chip_config", 0600, dir, dev,
60262306a36Sopenharmony_ci				    &fops_config);
60362306a36Sopenharmony_ci	if (mt76_is_sdio(&dev->mt76))
60462306a36Sopenharmony_ci		debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir,
60562306a36Sopenharmony_ci					    mt7663s_sched_quota_read);
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	return 0;
60862306a36Sopenharmony_ci}
60962306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(mt7615_init_debugfs);
610