162306a36Sopenharmony_ci// SPDX-License-Identifier: ISC 262306a36Sopenharmony_ci/* Copyright (C) 2020 MediaTek Inc. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "mt7921.h" 562306a36Sopenharmony_ci 662306a36Sopenharmony_cistatic int 762306a36Sopenharmony_cimt7921_reg_set(void *data, u64 val) 862306a36Sopenharmony_ci{ 962306a36Sopenharmony_ci struct mt792x_dev *dev = data; 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 1262306a36Sopenharmony_ci mt76_wr(dev, dev->mt76.debugfs_reg, val); 1362306a36Sopenharmony_ci mt792x_mutex_release(dev); 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci return 0; 1662306a36Sopenharmony_ci} 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_cistatic int 1962306a36Sopenharmony_cimt7921_reg_get(void *data, u64 *val) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci struct mt792x_dev *dev = data; 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 2462306a36Sopenharmony_ci *val = mt76_rr(dev, dev->mt76.debugfs_reg); 2562306a36Sopenharmony_ci mt792x_mutex_release(dev); 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci return 0; 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7921_reg_get, mt7921_reg_set, 3162306a36Sopenharmony_ci "0x%08llx\n"); 3262306a36Sopenharmony_cistatic int 3362306a36Sopenharmony_cimt7921_fw_debug_set(void *data, u64 val) 3462306a36Sopenharmony_ci{ 3562306a36Sopenharmony_ci struct mt792x_dev *dev = data; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci dev->fw_debug = (u8)val; 4062306a36Sopenharmony_ci mt7921_mcu_fw_log_2_host(dev, dev->fw_debug); 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci mt792x_mutex_release(dev); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci return 0; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_cistatic int 4862306a36Sopenharmony_cimt7921_fw_debug_get(void *data, u64 *val) 4962306a36Sopenharmony_ci{ 5062306a36Sopenharmony_ci struct mt792x_dev *dev = data; 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci *val = dev->fw_debug; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci return 0; 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7921_fw_debug_get, 5862306a36Sopenharmony_ci mt7921_fw_debug_set, "%lld\n"); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(mt792x_tx_stats); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic void 6362306a36Sopenharmony_cimt7921_seq_puts_array(struct seq_file *file, const char *str, 6462306a36Sopenharmony_ci s8 *val, int len) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci int i; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci seq_printf(file, "%-16s:", str); 6962306a36Sopenharmony_ci for (i = 0; i < len; i++) 7062306a36Sopenharmony_ci if (val[i] == 127) 7162306a36Sopenharmony_ci seq_printf(file, " %6s", "N.A"); 7262306a36Sopenharmony_ci else 7362306a36Sopenharmony_ci seq_printf(file, " %6d", val[i]); 7462306a36Sopenharmony_ci seq_puts(file, "\n"); 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci#define mt7921_print_txpwr_entry(prefix, rate) \ 7862306a36Sopenharmony_ci({ \ 7962306a36Sopenharmony_ci mt7921_seq_puts_array(s, #prefix " (user)", \ 8062306a36Sopenharmony_ci txpwr.data[TXPWR_USER].rate, \ 8162306a36Sopenharmony_ci ARRAY_SIZE(txpwr.data[TXPWR_USER].rate)); \ 8262306a36Sopenharmony_ci mt7921_seq_puts_array(s, #prefix " (eeprom)", \ 8362306a36Sopenharmony_ci txpwr.data[TXPWR_EEPROM].rate, \ 8462306a36Sopenharmony_ci ARRAY_SIZE(txpwr.data[TXPWR_EEPROM].rate)); \ 8562306a36Sopenharmony_ci mt7921_seq_puts_array(s, #prefix " (tmac)", \ 8662306a36Sopenharmony_ci txpwr.data[TXPWR_MAC].rate, \ 8762306a36Sopenharmony_ci ARRAY_SIZE(txpwr.data[TXPWR_MAC].rate)); \ 8862306a36Sopenharmony_ci}) 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic int 9162306a36Sopenharmony_cimt7921_txpwr(struct seq_file *s, void *data) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci struct mt792x_dev *dev = dev_get_drvdata(s->private); 9462306a36Sopenharmony_ci struct mt7921_txpwr txpwr; 9562306a36Sopenharmony_ci int ret; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 9862306a36Sopenharmony_ci ret = mt7921_get_txpwr_info(dev, &txpwr); 9962306a36Sopenharmony_ci mt792x_mutex_release(dev); 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci if (ret) 10262306a36Sopenharmony_ci return ret; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch); 10562306a36Sopenharmony_ci seq_printf(s, "%-16s %6s %6s %6s %6s\n", 10662306a36Sopenharmony_ci " ", "1m", "2m", "5m", "11m"); 10762306a36Sopenharmony_ci mt7921_print_txpwr_entry(CCK, cck); 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", 11062306a36Sopenharmony_ci " ", "6m", "9m", "12m", "18m", "24m", "36m", 11162306a36Sopenharmony_ci "48m", "54m"); 11262306a36Sopenharmony_ci mt7921_print_txpwr_entry(OFDM, ofdm); 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n", 11562306a36Sopenharmony_ci " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 11662306a36Sopenharmony_ci "mcs6", "mcs7"); 11762306a36Sopenharmony_ci mt7921_print_txpwr_entry(HT20, ht20); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", 12062306a36Sopenharmony_ci " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 12162306a36Sopenharmony_ci "mcs6", "mcs7", "mcs32"); 12262306a36Sopenharmony_ci mt7921_print_txpwr_entry(HT40, ht40); 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n", 12562306a36Sopenharmony_ci " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5", 12662306a36Sopenharmony_ci "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11"); 12762306a36Sopenharmony_ci mt7921_print_txpwr_entry(VHT20, vht20); 12862306a36Sopenharmony_ci mt7921_print_txpwr_entry(VHT40, vht40); 12962306a36Sopenharmony_ci mt7921_print_txpwr_entry(VHT80, vht80); 13062306a36Sopenharmony_ci mt7921_print_txpwr_entry(VHT160, vht160); 13162306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE26, he26); 13262306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE52, he52); 13362306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE106, he106); 13462306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE242, he242); 13562306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE484, he484); 13662306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE996, he996); 13762306a36Sopenharmony_ci mt7921_print_txpwr_entry(HE996x2, he996x2); 13862306a36Sopenharmony_ci 13962306a36Sopenharmony_ci return 0; 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_cistatic int 14362306a36Sopenharmony_cimt7921_pm_set(void *data, u64 val) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct mt792x_dev *dev = data; 14662306a36Sopenharmony_ci struct mt76_connac_pm *pm = &dev->pm; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (mt76_is_usb(&dev->mt76)) 14962306a36Sopenharmony_ci return -EOPNOTSUPP; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci mutex_lock(&dev->mt76.mutex); 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci if (val == pm->enable_user) 15462306a36Sopenharmony_ci goto out; 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci if (!pm->enable_user) { 15762306a36Sopenharmony_ci pm->stats.last_wake_event = jiffies; 15862306a36Sopenharmony_ci pm->stats.last_doze_event = jiffies; 15962306a36Sopenharmony_ci } 16062306a36Sopenharmony_ci /* make sure the chip is awake here and ps_work is scheduled 16162306a36Sopenharmony_ci * just at end of the this routine. 16262306a36Sopenharmony_ci */ 16362306a36Sopenharmony_ci pm->enable = false; 16462306a36Sopenharmony_ci mt76_connac_pm_wake(&dev->mphy, pm); 16562306a36Sopenharmony_ci 16662306a36Sopenharmony_ci pm->enable_user = val; 16762306a36Sopenharmony_ci mt7921_set_runtime_pm(dev); 16862306a36Sopenharmony_ci mt76_connac_power_save_sched(&dev->mphy, pm); 16962306a36Sopenharmony_ciout: 17062306a36Sopenharmony_ci mutex_unlock(&dev->mt76.mutex); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci return 0; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic int 17662306a36Sopenharmony_cimt7921_pm_get(void *data, u64 *val) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci struct mt792x_dev *dev = data; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci *val = dev->pm.enable_user; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci return 0; 18362306a36Sopenharmony_ci} 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7921_pm_get, mt7921_pm_set, "%lld\n"); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_cistatic int 18862306a36Sopenharmony_cimt7921_deep_sleep_set(void *data, u64 val) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct mt792x_dev *dev = data; 19162306a36Sopenharmony_ci struct mt76_connac_pm *pm = &dev->pm; 19262306a36Sopenharmony_ci bool monitor = !!(dev->mphy.hw->conf.flags & IEEE80211_CONF_MONITOR); 19362306a36Sopenharmony_ci bool enable = !!val; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci if (mt76_is_usb(&dev->mt76)) 19662306a36Sopenharmony_ci return -EOPNOTSUPP; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 19962306a36Sopenharmony_ci if (pm->ds_enable_user == enable) 20062306a36Sopenharmony_ci goto out; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci pm->ds_enable_user = enable; 20362306a36Sopenharmony_ci pm->ds_enable = enable && !monitor; 20462306a36Sopenharmony_ci mt76_connac_mcu_set_deep_sleep(&dev->mt76, pm->ds_enable); 20562306a36Sopenharmony_ciout: 20662306a36Sopenharmony_ci mt792x_mutex_release(dev); 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci return 0; 20962306a36Sopenharmony_ci} 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_cistatic int 21262306a36Sopenharmony_cimt7921_deep_sleep_get(void *data, u64 *val) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct mt792x_dev *dev = data; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci *val = dev->pm.ds_enable_user; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci return 0; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7921_deep_sleep_get, 22262306a36Sopenharmony_ci mt7921_deep_sleep_set, "%lld\n"); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get, 22562306a36Sopenharmony_ci mt792x_pm_idle_timeout_set, "%lld\n"); 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic int mt7921_chip_reset(void *data, u64 val) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct mt792x_dev *dev = data; 23062306a36Sopenharmony_ci int ret = 0; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci switch (val) { 23362306a36Sopenharmony_ci case 1: 23462306a36Sopenharmony_ci /* Reset wifisys directly. */ 23562306a36Sopenharmony_ci mt792x_reset(&dev->mt76); 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci default: 23862306a36Sopenharmony_ci /* Collect the core dump before reset wifisys. */ 23962306a36Sopenharmony_ci mt792x_mutex_acquire(dev); 24062306a36Sopenharmony_ci ret = mt76_connac_mcu_chip_config(&dev->mt76); 24162306a36Sopenharmony_ci mt792x_mutex_release(dev); 24262306a36Sopenharmony_ci break; 24362306a36Sopenharmony_ci } 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci return ret; 24662306a36Sopenharmony_ci} 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ciDEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7921_chip_reset, "%lld\n"); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic int 25162306a36Sopenharmony_cimt7921s_sched_quota_read(struct seq_file *s, void *data) 25262306a36Sopenharmony_ci{ 25362306a36Sopenharmony_ci struct mt792x_dev *dev = dev_get_drvdata(s->private); 25462306a36Sopenharmony_ci struct mt76_sdio *sdio = &dev->mt76.sdio; 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci seq_printf(s, "pse_data_quota\t%d\n", sdio->sched.pse_data_quota); 25762306a36Sopenharmony_ci seq_printf(s, "ple_data_quota\t%d\n", sdio->sched.ple_data_quota); 25862306a36Sopenharmony_ci seq_printf(s, "pse_mcu_quota\t%d\n", sdio->sched.pse_mcu_quota); 25962306a36Sopenharmony_ci seq_printf(s, "sched_deficit\t%d\n", sdio->sched.deficit); 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci return 0; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ciint mt7921_init_debugfs(struct mt792x_dev *dev) 26562306a36Sopenharmony_ci{ 26662306a36Sopenharmony_ci struct dentry *dir; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci dir = mt76_register_debugfs_fops(&dev->mphy, &fops_regval); 26962306a36Sopenharmony_ci if (!dir) 27062306a36Sopenharmony_ci return -ENOMEM; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (mt76_is_mmio(&dev->mt76)) 27362306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", 27462306a36Sopenharmony_ci dir, mt792x_queues_read); 27562306a36Sopenharmony_ci else 27662306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "xmit-queues", 27762306a36Sopenharmony_ci dir, mt76_queues_read); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir, 28062306a36Sopenharmony_ci mt792x_queues_acq); 28162306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir, 28262306a36Sopenharmony_ci mt7921_txpwr); 28362306a36Sopenharmony_ci debugfs_create_file("tx_stats", 0400, dir, dev, &mt792x_tx_stats_fops); 28462306a36Sopenharmony_ci debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug); 28562306a36Sopenharmony_ci debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm); 28662306a36Sopenharmony_ci debugfs_create_file("idle-timeout", 0600, dir, dev, 28762306a36Sopenharmony_ci &fops_pm_idle_timeout); 28862306a36Sopenharmony_ci debugfs_create_file("chip_reset", 0600, dir, dev, &fops_reset); 28962306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "runtime_pm_stats", dir, 29062306a36Sopenharmony_ci mt792x_pm_stats); 29162306a36Sopenharmony_ci debugfs_create_file("deep-sleep", 0600, dir, dev, &fops_ds); 29262306a36Sopenharmony_ci if (mt76_is_sdio(&dev->mt76)) 29362306a36Sopenharmony_ci debugfs_create_devm_seqfile(dev->mt76.dev, "sched-quota", dir, 29462306a36Sopenharmony_ci mt7921s_sched_quota_read); 29562306a36Sopenharmony_ci return 0; 29662306a36Sopenharmony_ci} 297