1e3037485SYan-Hsuan Chuang // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2e3037485SYan-Hsuan Chuang /* Copyright(c) 2018-2019 Realtek Corporation 3e3037485SYan-Hsuan Chuang */ 4e3037485SYan-Hsuan Chuang 5e3037485SYan-Hsuan Chuang #include <linux/debugfs.h> 6e3037485SYan-Hsuan Chuang #include <linux/seq_file.h> 7e3037485SYan-Hsuan Chuang #include "main.h" 81fe188daSYan-Hsuan Chuang #include "coex.h" 9e3037485SYan-Hsuan Chuang #include "sec.h" 10e3037485SYan-Hsuan Chuang #include "fw.h" 11e3037485SYan-Hsuan Chuang #include "debug.h" 128812022cSZong-Zhe Yang #include "phy.h" 1313ce240aSZong-Zhe Yang #include "reg.h" 147b80f3e4SZong-Zhe Yang #include "ps.h" 15*f8509c38SZong-Zhe Yang #include "regd.h" 16e3037485SYan-Hsuan Chuang 17e3037485SYan-Hsuan Chuang #ifdef CONFIG_RTW88_DEBUGFS 18e3037485SYan-Hsuan Chuang 19e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv { 20e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev; 21e3037485SYan-Hsuan Chuang int (*cb_read)(struct seq_file *m, void *v); 22e3037485SYan-Hsuan Chuang ssize_t (*cb_write)(struct file *filp, const char __user *buffer, 23e3037485SYan-Hsuan Chuang size_t count, loff_t *loff); 24e3037485SYan-Hsuan Chuang union { 25e3037485SYan-Hsuan Chuang u32 cb_data; 26e3037485SYan-Hsuan Chuang u8 *buf; 27e3037485SYan-Hsuan Chuang struct { 28e3037485SYan-Hsuan Chuang u32 page_offset; 29e3037485SYan-Hsuan Chuang u32 page_num; 30e3037485SYan-Hsuan Chuang } rsvd_page; 31e3037485SYan-Hsuan Chuang struct { 32e3037485SYan-Hsuan Chuang u8 rf_path; 33e3037485SYan-Hsuan Chuang u32 rf_addr; 34e3037485SYan-Hsuan Chuang u32 rf_mask; 35e3037485SYan-Hsuan Chuang }; 36e3037485SYan-Hsuan Chuang struct { 37e3037485SYan-Hsuan Chuang u32 addr; 38e3037485SYan-Hsuan Chuang u32 len; 39e3037485SYan-Hsuan Chuang } read_reg; 403b25bac8SGuo-Feng Fan struct { 413b25bac8SGuo-Feng Fan u8 bit; 423b25bac8SGuo-Feng Fan } dm_cap; 43e3037485SYan-Hsuan Chuang }; 44e3037485SYan-Hsuan Chuang }; 45e3037485SYan-Hsuan Chuang 463b25bac8SGuo-Feng Fan static const char * const rtw_dm_cap_strs[] = { 473b25bac8SGuo-Feng Fan [RTW_DM_CAP_NA] = "NA", 483b25bac8SGuo-Feng Fan [RTW_DM_CAP_TXGAPK] = "TXGAPK", 493b25bac8SGuo-Feng Fan }; 503b25bac8SGuo-Feng Fan 51e3037485SYan-Hsuan Chuang static int rtw_debugfs_single_show(struct seq_file *m, void *v) 52e3037485SYan-Hsuan Chuang { 53e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 54e3037485SYan-Hsuan Chuang 55e3037485SYan-Hsuan Chuang return debugfs_priv->cb_read(m, v); 56e3037485SYan-Hsuan Chuang } 57e3037485SYan-Hsuan Chuang 58e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_common_write(struct file *filp, 59e3037485SYan-Hsuan Chuang const char __user *buffer, 60e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 61e3037485SYan-Hsuan Chuang { 62e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = filp->private_data; 63e3037485SYan-Hsuan Chuang 64e3037485SYan-Hsuan Chuang return debugfs_priv->cb_write(filp, buffer, count, loff); 65e3037485SYan-Hsuan Chuang } 66e3037485SYan-Hsuan Chuang 67e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_single_write(struct file *filp, 68e3037485SYan-Hsuan Chuang const char __user *buffer, 69e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 70e3037485SYan-Hsuan Chuang { 71e3037485SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 72e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 73e3037485SYan-Hsuan Chuang 74e3037485SYan-Hsuan Chuang return debugfs_priv->cb_write(filp, buffer, count, loff); 75e3037485SYan-Hsuan Chuang } 76e3037485SYan-Hsuan Chuang 77e3037485SYan-Hsuan Chuang static int rtw_debugfs_single_open_rw(struct inode *inode, struct file *filp) 78e3037485SYan-Hsuan Chuang { 79e3037485SYan-Hsuan Chuang return single_open(filp, rtw_debugfs_single_show, inode->i_private); 80e3037485SYan-Hsuan Chuang } 81e3037485SYan-Hsuan Chuang 82e3037485SYan-Hsuan Chuang static int rtw_debugfs_close(struct inode *inode, struct file *filp) 83e3037485SYan-Hsuan Chuang { 84e3037485SYan-Hsuan Chuang return 0; 85e3037485SYan-Hsuan Chuang } 86e3037485SYan-Hsuan Chuang 87e3037485SYan-Hsuan Chuang static const struct file_operations file_ops_single_r = { 88e3037485SYan-Hsuan Chuang .owner = THIS_MODULE, 89e3037485SYan-Hsuan Chuang .open = rtw_debugfs_single_open_rw, 90e3037485SYan-Hsuan Chuang .read = seq_read, 91e3037485SYan-Hsuan Chuang .llseek = seq_lseek, 92eb9affaeSWei Yongjun .release = single_release, 93e3037485SYan-Hsuan Chuang }; 94e3037485SYan-Hsuan Chuang 95e3037485SYan-Hsuan Chuang static const struct file_operations file_ops_single_rw = { 96e3037485SYan-Hsuan Chuang .owner = THIS_MODULE, 97e3037485SYan-Hsuan Chuang .open = rtw_debugfs_single_open_rw, 98e3037485SYan-Hsuan Chuang .release = single_release, 99e3037485SYan-Hsuan Chuang .read = seq_read, 100e3037485SYan-Hsuan Chuang .llseek = seq_lseek, 101e3037485SYan-Hsuan Chuang .write = rtw_debugfs_single_write, 102e3037485SYan-Hsuan Chuang }; 103e3037485SYan-Hsuan Chuang 104e3037485SYan-Hsuan Chuang static const struct file_operations file_ops_common_write = { 105e3037485SYan-Hsuan Chuang .owner = THIS_MODULE, 106e3037485SYan-Hsuan Chuang .write = rtw_debugfs_common_write, 107e3037485SYan-Hsuan Chuang .open = simple_open, 108e3037485SYan-Hsuan Chuang .release = rtw_debugfs_close, 109e3037485SYan-Hsuan Chuang }; 110e3037485SYan-Hsuan Chuang 111e3037485SYan-Hsuan Chuang static int rtw_debugfs_get_read_reg(struct seq_file *m, void *v) 112e3037485SYan-Hsuan Chuang { 113e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 114e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 115e3037485SYan-Hsuan Chuang u32 val, len, addr; 116e3037485SYan-Hsuan Chuang 117e3037485SYan-Hsuan Chuang len = debugfs_priv->read_reg.len; 118e3037485SYan-Hsuan Chuang addr = debugfs_priv->read_reg.addr; 119e3037485SYan-Hsuan Chuang switch (len) { 120e3037485SYan-Hsuan Chuang case 1: 121e3037485SYan-Hsuan Chuang val = rtw_read8(rtwdev, addr); 122e3037485SYan-Hsuan Chuang seq_printf(m, "reg 0x%03x: 0x%02x\n", addr, val); 123e3037485SYan-Hsuan Chuang break; 124e3037485SYan-Hsuan Chuang case 2: 125e3037485SYan-Hsuan Chuang val = rtw_read16(rtwdev, addr); 126e3037485SYan-Hsuan Chuang seq_printf(m, "reg 0x%03x: 0x%04x\n", addr, val); 127e3037485SYan-Hsuan Chuang break; 128e3037485SYan-Hsuan Chuang case 4: 129e3037485SYan-Hsuan Chuang val = rtw_read32(rtwdev, addr); 130e3037485SYan-Hsuan Chuang seq_printf(m, "reg 0x%03x: 0x%08x\n", addr, val); 131e3037485SYan-Hsuan Chuang break; 132e3037485SYan-Hsuan Chuang } 133e3037485SYan-Hsuan Chuang return 0; 134e3037485SYan-Hsuan Chuang } 135e3037485SYan-Hsuan Chuang 136e3037485SYan-Hsuan Chuang static int rtw_debugfs_get_rf_read(struct seq_file *m, void *v) 137e3037485SYan-Hsuan Chuang { 138e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 139e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 140e3037485SYan-Hsuan Chuang u32 val, addr, mask; 141e3037485SYan-Hsuan Chuang u8 path; 142e3037485SYan-Hsuan Chuang 143e3037485SYan-Hsuan Chuang path = debugfs_priv->rf_path; 144e3037485SYan-Hsuan Chuang addr = debugfs_priv->rf_addr; 145e3037485SYan-Hsuan Chuang mask = debugfs_priv->rf_mask; 146e3037485SYan-Hsuan Chuang 147e3037485SYan-Hsuan Chuang val = rtw_read_rf(rtwdev, path, addr, mask); 148e3037485SYan-Hsuan Chuang 149e3037485SYan-Hsuan Chuang seq_printf(m, "rf_read path:%d addr:0x%08x mask:0x%08x val=0x%08x\n", 150e3037485SYan-Hsuan Chuang path, addr, mask, val); 151e3037485SYan-Hsuan Chuang 152e3037485SYan-Hsuan Chuang return 0; 153e3037485SYan-Hsuan Chuang } 154e3037485SYan-Hsuan Chuang 155e3037485SYan-Hsuan Chuang static int rtw_debugfs_copy_from_user(char tmp[], int size, 156e3037485SYan-Hsuan Chuang const char __user *buffer, size_t count, 157e3037485SYan-Hsuan Chuang int num) 158e3037485SYan-Hsuan Chuang { 159e3037485SYan-Hsuan Chuang int tmp_len; 160e3037485SYan-Hsuan Chuang 16174a8c816SDan Carpenter memset(tmp, 0, size); 16274a8c816SDan Carpenter 163e3037485SYan-Hsuan Chuang if (count < num) 164e3037485SYan-Hsuan Chuang return -EFAULT; 165e3037485SYan-Hsuan Chuang 166e3037485SYan-Hsuan Chuang tmp_len = (count > size - 1 ? size - 1 : count); 167e3037485SYan-Hsuan Chuang 168e3037485SYan-Hsuan Chuang if (!buffer || copy_from_user(tmp, buffer, tmp_len)) 169e3037485SYan-Hsuan Chuang return count; 170e3037485SYan-Hsuan Chuang 171e3037485SYan-Hsuan Chuang tmp[tmp_len] = '\0'; 172e3037485SYan-Hsuan Chuang 173e3037485SYan-Hsuan Chuang return 0; 174e3037485SYan-Hsuan Chuang } 175e3037485SYan-Hsuan Chuang 176e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_read_reg(struct file *filp, 177e3037485SYan-Hsuan Chuang const char __user *buffer, 178e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 179e3037485SYan-Hsuan Chuang { 180e3037485SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 181e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 182e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 183e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 184e3037485SYan-Hsuan Chuang u32 addr, len; 185e3037485SYan-Hsuan Chuang int num; 186e3037485SYan-Hsuan Chuang 187e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); 188e3037485SYan-Hsuan Chuang 189e3037485SYan-Hsuan Chuang num = sscanf(tmp, "%x %x", &addr, &len); 190e3037485SYan-Hsuan Chuang 191e3037485SYan-Hsuan Chuang if (num != 2) 192e3037485SYan-Hsuan Chuang return count; 193e3037485SYan-Hsuan Chuang 194e3037485SYan-Hsuan Chuang if (len != 1 && len != 2 && len != 4) { 195e3037485SYan-Hsuan Chuang rtw_warn(rtwdev, "read reg setting wrong len\n"); 196e3037485SYan-Hsuan Chuang return -EINVAL; 197e3037485SYan-Hsuan Chuang } 198e3037485SYan-Hsuan Chuang debugfs_priv->read_reg.addr = addr; 199e3037485SYan-Hsuan Chuang debugfs_priv->read_reg.len = len; 200e3037485SYan-Hsuan Chuang 201e3037485SYan-Hsuan Chuang return count; 202e3037485SYan-Hsuan Chuang } 203e3037485SYan-Hsuan Chuang 204e3037485SYan-Hsuan Chuang static int rtw_debugfs_get_dump_cam(struct seq_file *m, void *v) 205e3037485SYan-Hsuan Chuang { 206e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 207e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 208e3037485SYan-Hsuan Chuang u32 val, command; 209e3037485SYan-Hsuan Chuang u32 hw_key_idx = debugfs_priv->cb_data << RTW_SEC_CAM_ENTRY_SHIFT; 210e3037485SYan-Hsuan Chuang u32 read_cmd = RTW_SEC_CMD_POLLING; 211e3037485SYan-Hsuan Chuang int i; 212e3037485SYan-Hsuan Chuang 213e3037485SYan-Hsuan Chuang seq_printf(m, "cam entry%d\n", debugfs_priv->cb_data); 214e3037485SYan-Hsuan Chuang seq_puts(m, "0x0 0x1 0x2 0x3 "); 215e3037485SYan-Hsuan Chuang seq_puts(m, "0x4 0x5\n"); 216e3037485SYan-Hsuan Chuang mutex_lock(&rtwdev->mutex); 217e3037485SYan-Hsuan Chuang for (i = 0; i <= 5; i++) { 218e3037485SYan-Hsuan Chuang command = read_cmd | (hw_key_idx + i); 219e3037485SYan-Hsuan Chuang rtw_write32(rtwdev, RTW_SEC_CMD_REG, command); 220e3037485SYan-Hsuan Chuang val = rtw_read32(rtwdev, RTW_SEC_READ_REG); 221e3037485SYan-Hsuan Chuang seq_printf(m, "%8.8x", val); 222e3037485SYan-Hsuan Chuang if (i < 2) 223e3037485SYan-Hsuan Chuang seq_puts(m, " "); 224e3037485SYan-Hsuan Chuang } 225e3037485SYan-Hsuan Chuang seq_puts(m, "\n"); 226e3037485SYan-Hsuan Chuang mutex_unlock(&rtwdev->mutex); 227e3037485SYan-Hsuan Chuang return 0; 228e3037485SYan-Hsuan Chuang } 229e3037485SYan-Hsuan Chuang 230e3037485SYan-Hsuan Chuang static int rtw_debugfs_get_rsvd_page(struct seq_file *m, void *v) 231e3037485SYan-Hsuan Chuang { 232e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 233e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 234e3037485SYan-Hsuan Chuang u8 page_size = rtwdev->chip->page_size; 235e3037485SYan-Hsuan Chuang u32 buf_size = debugfs_priv->rsvd_page.page_num * page_size; 236e3037485SYan-Hsuan Chuang u32 offset = debugfs_priv->rsvd_page.page_offset * page_size; 237e3037485SYan-Hsuan Chuang u8 *buf; 238e3037485SYan-Hsuan Chuang int i; 239e3037485SYan-Hsuan Chuang int ret; 240e3037485SYan-Hsuan Chuang 241e3037485SYan-Hsuan Chuang buf = vzalloc(buf_size); 242e3037485SYan-Hsuan Chuang if (!buf) 243e3037485SYan-Hsuan Chuang return -ENOMEM; 244e3037485SYan-Hsuan Chuang 2450fbc2f0fSTzu-En Huang ret = rtw_fw_dump_fifo(rtwdev, RTW_FW_FIFO_SEL_RSVD_PAGE, offset, 2460fbc2f0fSTzu-En Huang buf_size, (u32 *)buf); 247e3037485SYan-Hsuan Chuang if (ret) { 248e3037485SYan-Hsuan Chuang rtw_err(rtwdev, "failed to dump rsvd page\n"); 249e3037485SYan-Hsuan Chuang vfree(buf); 250e3037485SYan-Hsuan Chuang return ret; 251e3037485SYan-Hsuan Chuang } 252e3037485SYan-Hsuan Chuang 253e3037485SYan-Hsuan Chuang for (i = 0 ; i < buf_size ; i += 8) { 254e3037485SYan-Hsuan Chuang if (i % page_size == 0) 255e3037485SYan-Hsuan Chuang seq_printf(m, "PAGE %d\n", (i + offset) / page_size); 256e3037485SYan-Hsuan Chuang seq_printf(m, "%2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", 257e3037485SYan-Hsuan Chuang *(buf + i), *(buf + i + 1), 258e3037485SYan-Hsuan Chuang *(buf + i + 2), *(buf + i + 3), 259e3037485SYan-Hsuan Chuang *(buf + i + 4), *(buf + i + 5), 260e3037485SYan-Hsuan Chuang *(buf + i + 6), *(buf + i + 7)); 261e3037485SYan-Hsuan Chuang } 262e3037485SYan-Hsuan Chuang vfree(buf); 263e3037485SYan-Hsuan Chuang 264e3037485SYan-Hsuan Chuang return 0; 265e3037485SYan-Hsuan Chuang } 266e3037485SYan-Hsuan Chuang 267e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_rsvd_page(struct file *filp, 268e3037485SYan-Hsuan Chuang const char __user *buffer, 269e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 270e3037485SYan-Hsuan Chuang { 271e3037485SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 272e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 273e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 274e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 275e3037485SYan-Hsuan Chuang u32 offset, page_num; 276e3037485SYan-Hsuan Chuang int num; 277e3037485SYan-Hsuan Chuang 278e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 2); 279e3037485SYan-Hsuan Chuang 280e3037485SYan-Hsuan Chuang num = sscanf(tmp, "%d %d", &offset, &page_num); 281e3037485SYan-Hsuan Chuang 282e3037485SYan-Hsuan Chuang if (num != 2) { 283e3037485SYan-Hsuan Chuang rtw_warn(rtwdev, "invalid arguments\n"); 284c9eaee0cSDan Carpenter return -EINVAL; 285e3037485SYan-Hsuan Chuang } 286e3037485SYan-Hsuan Chuang 287e3037485SYan-Hsuan Chuang debugfs_priv->rsvd_page.page_offset = offset; 288e3037485SYan-Hsuan Chuang debugfs_priv->rsvd_page.page_num = page_num; 289e3037485SYan-Hsuan Chuang 290e3037485SYan-Hsuan Chuang return count; 291e3037485SYan-Hsuan Chuang } 292e3037485SYan-Hsuan Chuang 293e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_single_input(struct file *filp, 294e3037485SYan-Hsuan Chuang const char __user *buffer, 295e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 296e3037485SYan-Hsuan Chuang { 297e3037485SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 298e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 299e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 300e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 301e3037485SYan-Hsuan Chuang u32 input; 302e3037485SYan-Hsuan Chuang int num; 303e3037485SYan-Hsuan Chuang 304e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); 305e3037485SYan-Hsuan Chuang 306e3037485SYan-Hsuan Chuang num = kstrtoint(tmp, 0, &input); 307e3037485SYan-Hsuan Chuang 308e3037485SYan-Hsuan Chuang if (num) { 309e3037485SYan-Hsuan Chuang rtw_warn(rtwdev, "kstrtoint failed\n"); 310e3037485SYan-Hsuan Chuang return num; 311e3037485SYan-Hsuan Chuang } 312e3037485SYan-Hsuan Chuang 313e3037485SYan-Hsuan Chuang debugfs_priv->cb_data = input; 314e3037485SYan-Hsuan Chuang 315e3037485SYan-Hsuan Chuang return count; 316e3037485SYan-Hsuan Chuang } 317e3037485SYan-Hsuan Chuang 318e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_write_reg(struct file *filp, 319e3037485SYan-Hsuan Chuang const char __user *buffer, 320e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 321e3037485SYan-Hsuan Chuang { 322e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = filp->private_data; 323e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 324e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 325e3037485SYan-Hsuan Chuang u32 addr, val, len; 326e3037485SYan-Hsuan Chuang int num; 327e3037485SYan-Hsuan Chuang 328e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); 329e3037485SYan-Hsuan Chuang 330e3037485SYan-Hsuan Chuang /* write BB/MAC register */ 331e3037485SYan-Hsuan Chuang num = sscanf(tmp, "%x %x %x", &addr, &val, &len); 332e3037485SYan-Hsuan Chuang 333e3037485SYan-Hsuan Chuang if (num != 3) 334e3037485SYan-Hsuan Chuang return count; 335e3037485SYan-Hsuan Chuang 336e3037485SYan-Hsuan Chuang switch (len) { 337e3037485SYan-Hsuan Chuang case 1: 338e3037485SYan-Hsuan Chuang rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, 339e3037485SYan-Hsuan Chuang "reg write8 0x%03x: 0x%08x\n", addr, val); 340e3037485SYan-Hsuan Chuang rtw_write8(rtwdev, addr, (u8)val); 341e3037485SYan-Hsuan Chuang break; 342e3037485SYan-Hsuan Chuang case 2: 343e3037485SYan-Hsuan Chuang rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, 344e3037485SYan-Hsuan Chuang "reg write16 0x%03x: 0x%08x\n", addr, val); 345e3037485SYan-Hsuan Chuang rtw_write16(rtwdev, addr, (u16)val); 346e3037485SYan-Hsuan Chuang break; 347e3037485SYan-Hsuan Chuang case 4: 348e3037485SYan-Hsuan Chuang rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, 349e3037485SYan-Hsuan Chuang "reg write32 0x%03x: 0x%08x\n", addr, val); 350e3037485SYan-Hsuan Chuang rtw_write32(rtwdev, addr, (u32)val); 351e3037485SYan-Hsuan Chuang break; 352e3037485SYan-Hsuan Chuang default: 353e3037485SYan-Hsuan Chuang rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, 354e3037485SYan-Hsuan Chuang "error write length = %d\n", len); 355e3037485SYan-Hsuan Chuang break; 356e3037485SYan-Hsuan Chuang } 357e3037485SYan-Hsuan Chuang 358e3037485SYan-Hsuan Chuang return count; 359e3037485SYan-Hsuan Chuang } 360e3037485SYan-Hsuan Chuang 361c376c1fcSTzu-En Huang static ssize_t rtw_debugfs_set_h2c(struct file *filp, 362c376c1fcSTzu-En Huang const char __user *buffer, 363c376c1fcSTzu-En Huang size_t count, loff_t *loff) 364c376c1fcSTzu-En Huang { 365c376c1fcSTzu-En Huang struct rtw_debugfs_priv *debugfs_priv = filp->private_data; 366c376c1fcSTzu-En Huang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 367c376c1fcSTzu-En Huang char tmp[32 + 1]; 368c376c1fcSTzu-En Huang u8 param[8]; 369c376c1fcSTzu-En Huang int num; 370c376c1fcSTzu-En Huang 371c376c1fcSTzu-En Huang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); 372c376c1fcSTzu-En Huang 373c376c1fcSTzu-En Huang num = sscanf(tmp, "%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx,%hhx", 374c376c1fcSTzu-En Huang ¶m[0], ¶m[1], ¶m[2], ¶m[3], 375c376c1fcSTzu-En Huang ¶m[4], ¶m[5], ¶m[6], ¶m[7]); 376c376c1fcSTzu-En Huang if (num != 8) { 377c376c1fcSTzu-En Huang rtw_info(rtwdev, "invalid H2C command format for debug\n"); 378c376c1fcSTzu-En Huang return -EINVAL; 379c376c1fcSTzu-En Huang } 380c376c1fcSTzu-En Huang 381c376c1fcSTzu-En Huang rtw_fw_h2c_cmd_dbg(rtwdev, param); 382c376c1fcSTzu-En Huang 383c376c1fcSTzu-En Huang return count; 384c376c1fcSTzu-En Huang } 385c376c1fcSTzu-En Huang 386e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_rf_write(struct file *filp, 387e3037485SYan-Hsuan Chuang const char __user *buffer, 388e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 389e3037485SYan-Hsuan Chuang { 390e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = filp->private_data; 391e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 392e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 393e3037485SYan-Hsuan Chuang u32 path, addr, mask, val; 394e3037485SYan-Hsuan Chuang int num; 395e3037485SYan-Hsuan Chuang 396e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 4); 397e3037485SYan-Hsuan Chuang 398e3037485SYan-Hsuan Chuang num = sscanf(tmp, "%x %x %x %x", &path, &addr, &mask, &val); 399e3037485SYan-Hsuan Chuang 400e3037485SYan-Hsuan Chuang if (num != 4) { 401e3037485SYan-Hsuan Chuang rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); 402e3037485SYan-Hsuan Chuang return count; 403e3037485SYan-Hsuan Chuang } 404e3037485SYan-Hsuan Chuang 405e3037485SYan-Hsuan Chuang rtw_write_rf(rtwdev, path, addr, mask, val); 406e3037485SYan-Hsuan Chuang rtw_dbg(rtwdev, RTW_DBG_DEBUGFS, 407e3037485SYan-Hsuan Chuang "write_rf path:%d addr:0x%08x mask:0x%08x, val:0x%08x\n", 408e3037485SYan-Hsuan Chuang path, addr, mask, val); 409e3037485SYan-Hsuan Chuang 410e3037485SYan-Hsuan Chuang return count; 411e3037485SYan-Hsuan Chuang } 412e3037485SYan-Hsuan Chuang 413e3037485SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_rf_read(struct file *filp, 414e3037485SYan-Hsuan Chuang const char __user *buffer, 415e3037485SYan-Hsuan Chuang size_t count, loff_t *loff) 416e3037485SYan-Hsuan Chuang { 417e3037485SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 418e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 419e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 420e3037485SYan-Hsuan Chuang char tmp[32 + 1]; 421e3037485SYan-Hsuan Chuang u32 path, addr, mask; 422e3037485SYan-Hsuan Chuang int num; 423e3037485SYan-Hsuan Chuang 424e3037485SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 3); 425e3037485SYan-Hsuan Chuang 426e3037485SYan-Hsuan Chuang num = sscanf(tmp, "%x %x %x", &path, &addr, &mask); 427e3037485SYan-Hsuan Chuang 428e3037485SYan-Hsuan Chuang if (num != 3) { 429e3037485SYan-Hsuan Chuang rtw_warn(rtwdev, "invalid args, [path] [addr] [mask] [val]\n"); 430e3037485SYan-Hsuan Chuang return count; 431e3037485SYan-Hsuan Chuang } 432e3037485SYan-Hsuan Chuang 433e3037485SYan-Hsuan Chuang debugfs_priv->rf_path = path; 434e3037485SYan-Hsuan Chuang debugfs_priv->rf_addr = addr; 435e3037485SYan-Hsuan Chuang debugfs_priv->rf_mask = mask; 436e3037485SYan-Hsuan Chuang 437e3037485SYan-Hsuan Chuang return count; 438e3037485SYan-Hsuan Chuang } 439e3037485SYan-Hsuan Chuang 440e3037485SYan-Hsuan Chuang static int rtw_debug_get_mac_page(struct seq_file *m, void *v) 441e3037485SYan-Hsuan Chuang { 442e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 443e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 444e3037485SYan-Hsuan Chuang u32 page = debugfs_priv->cb_data; 445e3037485SYan-Hsuan Chuang int i, n; 446e3037485SYan-Hsuan Chuang int max = 0xff; 447e3037485SYan-Hsuan Chuang 4480e25262bSLee Jones rtw_read32(rtwdev, debugfs_priv->cb_data); 449e3037485SYan-Hsuan Chuang for (n = 0; n <= max; ) { 450e3037485SYan-Hsuan Chuang seq_printf(m, "\n%8.8x ", n + page); 451e3037485SYan-Hsuan Chuang for (i = 0; i < 4 && n <= max; i++, n += 4) 452e3037485SYan-Hsuan Chuang seq_printf(m, "%8.8x ", 453e3037485SYan-Hsuan Chuang rtw_read32(rtwdev, (page | n))); 454e3037485SYan-Hsuan Chuang } 455e3037485SYan-Hsuan Chuang seq_puts(m, "\n"); 456e3037485SYan-Hsuan Chuang return 0; 457e3037485SYan-Hsuan Chuang } 458e3037485SYan-Hsuan Chuang 459e3037485SYan-Hsuan Chuang static int rtw_debug_get_bb_page(struct seq_file *m, void *v) 460e3037485SYan-Hsuan Chuang { 461e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 462e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 463e3037485SYan-Hsuan Chuang u32 page = debugfs_priv->cb_data; 464e3037485SYan-Hsuan Chuang int i, n; 465e3037485SYan-Hsuan Chuang int max = 0xff; 466e3037485SYan-Hsuan Chuang 4670e25262bSLee Jones rtw_read32(rtwdev, debugfs_priv->cb_data); 468e3037485SYan-Hsuan Chuang for (n = 0; n <= max; ) { 469e3037485SYan-Hsuan Chuang seq_printf(m, "\n%8.8x ", n + page); 470e3037485SYan-Hsuan Chuang for (i = 0; i < 4 && n <= max; i++, n += 4) 471e3037485SYan-Hsuan Chuang seq_printf(m, "%8.8x ", 472e3037485SYan-Hsuan Chuang rtw_read32(rtwdev, (page | n))); 473e3037485SYan-Hsuan Chuang } 474e3037485SYan-Hsuan Chuang seq_puts(m, "\n"); 475e3037485SYan-Hsuan Chuang return 0; 476e3037485SYan-Hsuan Chuang } 477e3037485SYan-Hsuan Chuang 478e3037485SYan-Hsuan Chuang static int rtw_debug_get_rf_dump(struct seq_file *m, void *v) 479e3037485SYan-Hsuan Chuang { 480e3037485SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 481e3037485SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 482e3037485SYan-Hsuan Chuang u32 addr, offset, data; 483e3037485SYan-Hsuan Chuang u8 path; 484e3037485SYan-Hsuan Chuang 485e3037485SYan-Hsuan Chuang for (path = 0; path < rtwdev->hal.rf_path_num; path++) { 486e3037485SYan-Hsuan Chuang seq_printf(m, "RF path:%d\n", path); 487e3037485SYan-Hsuan Chuang for (addr = 0; addr < 0x100; addr += 4) { 488e3037485SYan-Hsuan Chuang seq_printf(m, "%8.8x ", addr); 489e3037485SYan-Hsuan Chuang for (offset = 0; offset < 4; offset++) { 490e3037485SYan-Hsuan Chuang data = rtw_read_rf(rtwdev, path, addr + offset, 491e3037485SYan-Hsuan Chuang 0xffffffff); 492e3037485SYan-Hsuan Chuang seq_printf(m, "%8.8x ", data); 493e3037485SYan-Hsuan Chuang } 494e3037485SYan-Hsuan Chuang seq_puts(m, "\n"); 495e3037485SYan-Hsuan Chuang } 496e3037485SYan-Hsuan Chuang seq_puts(m, "\n"); 497e3037485SYan-Hsuan Chuang } 498e3037485SYan-Hsuan Chuang 499e3037485SYan-Hsuan Chuang return 0; 500e3037485SYan-Hsuan Chuang } 501e3037485SYan-Hsuan Chuang 5028812022cSZong-Zhe Yang static void rtw_print_cck_rate_txt(struct seq_file *m, u8 rate) 5038812022cSZong-Zhe Yang { 5048812022cSZong-Zhe Yang static const char * const 5058812022cSZong-Zhe Yang cck_rate[] = {"1M", "2M", "5.5M", "11M"}; 5068812022cSZong-Zhe Yang u8 idx = rate - DESC_RATE1M; 5078812022cSZong-Zhe Yang 5088812022cSZong-Zhe Yang seq_printf(m, " CCK_%-5s", cck_rate[idx]); 5098812022cSZong-Zhe Yang } 5108812022cSZong-Zhe Yang 5118812022cSZong-Zhe Yang static void rtw_print_ofdm_rate_txt(struct seq_file *m, u8 rate) 5128812022cSZong-Zhe Yang { 5138812022cSZong-Zhe Yang static const char * const 5148812022cSZong-Zhe Yang ofdm_rate[] = {"6M", "9M", "12M", "18M", "24M", "36M", "48M", "54M"}; 5158812022cSZong-Zhe Yang u8 idx = rate - DESC_RATE6M; 5168812022cSZong-Zhe Yang 5178812022cSZong-Zhe Yang seq_printf(m, " OFDM_%-4s", ofdm_rate[idx]); 5188812022cSZong-Zhe Yang } 5198812022cSZong-Zhe Yang 5208812022cSZong-Zhe Yang static void rtw_print_ht_rate_txt(struct seq_file *m, u8 rate) 5218812022cSZong-Zhe Yang { 5228812022cSZong-Zhe Yang u8 mcs_n = rate - DESC_RATEMCS0; 5238812022cSZong-Zhe Yang 5248812022cSZong-Zhe Yang seq_printf(m, " MCS%-6u", mcs_n); 5258812022cSZong-Zhe Yang } 5268812022cSZong-Zhe Yang 5278812022cSZong-Zhe Yang static void rtw_print_vht_rate_txt(struct seq_file *m, u8 rate) 5288812022cSZong-Zhe Yang { 5298812022cSZong-Zhe Yang u8 idx = rate - DESC_RATEVHT1SS_MCS0; 5308812022cSZong-Zhe Yang u8 n_ss, mcs_n; 5318812022cSZong-Zhe Yang 5328812022cSZong-Zhe Yang /* n spatial stream */ 5338812022cSZong-Zhe Yang n_ss = 1 + idx / 10; 5348812022cSZong-Zhe Yang /* MCS n */ 5358812022cSZong-Zhe Yang mcs_n = idx % 10; 5368812022cSZong-Zhe Yang seq_printf(m, " VHT%uSMCS%u", n_ss, mcs_n); 5378812022cSZong-Zhe Yang } 5388812022cSZong-Zhe Yang 539082a36dcSTsang-Shian Lin static void rtw_print_rate(struct seq_file *m, u8 rate) 540082a36dcSTsang-Shian Lin { 541082a36dcSTsang-Shian Lin switch (rate) { 542082a36dcSTsang-Shian Lin case DESC_RATE1M...DESC_RATE11M: 543082a36dcSTsang-Shian Lin rtw_print_cck_rate_txt(m, rate); 544082a36dcSTsang-Shian Lin break; 545082a36dcSTsang-Shian Lin case DESC_RATE6M...DESC_RATE54M: 546082a36dcSTsang-Shian Lin rtw_print_ofdm_rate_txt(m, rate); 547082a36dcSTsang-Shian Lin break; 548082a36dcSTsang-Shian Lin case DESC_RATEMCS0...DESC_RATEMCS15: 549082a36dcSTsang-Shian Lin rtw_print_ht_rate_txt(m, rate); 550082a36dcSTsang-Shian Lin break; 551082a36dcSTsang-Shian Lin case DESC_RATEVHT1SS_MCS0...DESC_RATEVHT2SS_MCS9: 552082a36dcSTsang-Shian Lin rtw_print_vht_rate_txt(m, rate); 553082a36dcSTsang-Shian Lin break; 554082a36dcSTsang-Shian Lin default: 555082a36dcSTsang-Shian Lin seq_printf(m, " Unknown rate=0x%x\n", rate); 556082a36dcSTsang-Shian Lin break; 557082a36dcSTsang-Shian Lin } 558082a36dcSTsang-Shian Lin } 559082a36dcSTsang-Shian Lin 560fada0931STzu-En Huang #define case_REGD(src) \ 561fada0931STzu-En Huang case RTW_REGD_##src: return #src 562fada0931STzu-En Huang 563fada0931STzu-En Huang static const char *rtw_get_regd_string(u8 regd) 564fada0931STzu-En Huang { 565fada0931STzu-En Huang switch (regd) { 566fada0931STzu-En Huang case_REGD(FCC); 567fada0931STzu-En Huang case_REGD(MKK); 568fada0931STzu-En Huang case_REGD(ETSI); 569fada0931STzu-En Huang case_REGD(IC); 570fada0931STzu-En Huang case_REGD(KCC); 571fada0931STzu-En Huang case_REGD(ACMA); 572fada0931STzu-En Huang case_REGD(CHILE); 573fada0931STzu-En Huang case_REGD(UKRAINE); 574fada0931STzu-En Huang case_REGD(MEXICO); 575fada0931STzu-En Huang case_REGD(CN); 576fada0931STzu-En Huang case_REGD(WW); 577fada0931STzu-En Huang default: 578fada0931STzu-En Huang return "Unknown"; 579fada0931STzu-En Huang } 580fada0931STzu-En Huang } 581fada0931STzu-En Huang 5828812022cSZong-Zhe Yang static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) 5838812022cSZong-Zhe Yang { 5848812022cSZong-Zhe Yang struct rtw_debugfs_priv *debugfs_priv = m->private; 5858812022cSZong-Zhe Yang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 5868812022cSZong-Zhe Yang struct rtw_hal *hal = &rtwdev->hal; 5878812022cSZong-Zhe Yang u8 path, rate; 5888812022cSZong-Zhe Yang struct rtw_power_params pwr_param = {0}; 5898812022cSZong-Zhe Yang u8 bw = hal->current_band_width; 5908812022cSZong-Zhe Yang u8 ch = hal->current_channel; 591*f8509c38SZong-Zhe Yang u8 regd = rtw_regd_get(rtwdev); 5928812022cSZong-Zhe Yang 593fada0931STzu-En Huang seq_printf(m, "regulatory: %s\n", rtw_get_regd_string(regd)); 594608d2a08SPing-Ke Shih seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", 595608d2a08SPing-Ke Shih "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); 5968812022cSZong-Zhe Yang 5978812022cSZong-Zhe Yang mutex_lock(&hal->tx_power_mutex); 5988812022cSZong-Zhe Yang for (path = RF_PATH_A; path <= RF_PATH_B; path++) { 5998812022cSZong-Zhe Yang /* there is no CCK rates used in 5G */ 6008812022cSZong-Zhe Yang if (hal->current_band_type == RTW_BAND_5G) 6018812022cSZong-Zhe Yang rate = DESC_RATE6M; 6028812022cSZong-Zhe Yang else 6038812022cSZong-Zhe Yang rate = DESC_RATE1M; 6048812022cSZong-Zhe Yang 6058812022cSZong-Zhe Yang /* now, not support vht 3ss and vht 4ss*/ 6068812022cSZong-Zhe Yang for (; rate <= DESC_RATEVHT2SS_MCS9; rate++) { 6078812022cSZong-Zhe Yang /* now, not support ht 3ss and ht 4ss*/ 6088812022cSZong-Zhe Yang if (rate > DESC_RATEMCS15 && 6098812022cSZong-Zhe Yang rate < DESC_RATEVHT1SS_MCS0) 6108812022cSZong-Zhe Yang continue; 6118812022cSZong-Zhe Yang 6128812022cSZong-Zhe Yang rtw_get_tx_power_params(rtwdev, path, rate, bw, 6138812022cSZong-Zhe Yang ch, regd, &pwr_param); 6148812022cSZong-Zhe Yang 6158812022cSZong-Zhe Yang seq_printf(m, "%4c ", path + 'A'); 616082a36dcSTsang-Shian Lin rtw_print_rate(m, rate); 617608d2a08SPing-Ke Shih seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n", 6188812022cSZong-Zhe Yang hal->tx_pwr_tbl[path][rate], 6198812022cSZong-Zhe Yang hal->tx_pwr_tbl[path][rate], 6208812022cSZong-Zhe Yang pwr_param.pwr_base, 6218812022cSZong-Zhe Yang min_t(s8, pwr_param.pwr_offset, 6228812022cSZong-Zhe Yang pwr_param.pwr_limit), 623608d2a08SPing-Ke Shih pwr_param.pwr_offset, pwr_param.pwr_limit, 624608d2a08SPing-Ke Shih pwr_param.pwr_remnant); 6258812022cSZong-Zhe Yang } 6268812022cSZong-Zhe Yang } 6278812022cSZong-Zhe Yang 6288812022cSZong-Zhe Yang mutex_unlock(&hal->tx_power_mutex); 6298812022cSZong-Zhe Yang 6308812022cSZong-Zhe Yang return 0; 6318812022cSZong-Zhe Yang } 6328812022cSZong-Zhe Yang 6331a589bd5SChing-Te Ku void rtw_debugfs_get_simple_phy_info(struct seq_file *m) 6341a589bd5SChing-Te Ku { 6351a589bd5SChing-Te Ku struct rtw_debugfs_priv *debugfs_priv = m->private; 6361a589bd5SChing-Te Ku struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 6371a589bd5SChing-Te Ku struct rtw_hal *hal = &rtwdev->hal; 6381a589bd5SChing-Te Ku struct rtw_dm_info *dm_info = &rtwdev->dm_info; 6391a589bd5SChing-Te Ku struct rtw_traffic_stats *stats = &rtwdev->stats; 6401a589bd5SChing-Te Ku 6411a589bd5SChing-Te Ku seq_printf(m, "%-40s = %ddBm/ %d\n", "RSSI/ STA Channel", 6421a589bd5SChing-Te Ku dm_info->rssi[RF_PATH_A] - 100, hal->current_channel); 6431a589bd5SChing-Te Ku 6441a589bd5SChing-Te Ku seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n", 6451a589bd5SChing-Te Ku stats->tx_throughput, stats->rx_throughput); 6461a589bd5SChing-Te Ku 6471a589bd5SChing-Te Ku seq_puts(m, "[Tx Rate] = "); 6481a589bd5SChing-Te Ku rtw_print_rate(m, dm_info->tx_rate); 6491a589bd5SChing-Te Ku seq_printf(m, "(0x%x)\n", dm_info->tx_rate); 6501a589bd5SChing-Te Ku 6511a589bd5SChing-Te Ku seq_puts(m, "[Rx Rate] = "); 6521a589bd5SChing-Te Ku rtw_print_rate(m, dm_info->curr_rx_rate); 6531a589bd5SChing-Te Ku seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate); 6541a589bd5SChing-Te Ku } 6551a589bd5SChing-Te Ku 656082a36dcSTsang-Shian Lin static int rtw_debugfs_get_phy_info(struct seq_file *m, void *v) 657082a36dcSTsang-Shian Lin { 658082a36dcSTsang-Shian Lin struct rtw_debugfs_priv *debugfs_priv = m->private; 659082a36dcSTsang-Shian Lin struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 660082a36dcSTsang-Shian Lin struct rtw_dm_info *dm_info = &rtwdev->dm_info; 661082a36dcSTsang-Shian Lin struct rtw_traffic_stats *stats = &rtwdev->stats; 662082a36dcSTsang-Shian Lin struct rtw_pkt_count *last_cnt = &dm_info->last_pkt_count; 663082a36dcSTsang-Shian Lin struct rtw_efuse *efuse = &rtwdev->efuse; 664082a36dcSTsang-Shian Lin struct ewma_evm *ewma_evm = dm_info->ewma_evm; 665082a36dcSTsang-Shian Lin struct ewma_snr *ewma_snr = dm_info->ewma_snr; 666082a36dcSTsang-Shian Lin u8 ss, rate_id; 667082a36dcSTsang-Shian Lin 668082a36dcSTsang-Shian Lin seq_puts(m, "==========[Common Info]========\n"); 669082a36dcSTsang-Shian Lin seq_printf(m, "Is link = %c\n", rtw_is_assoc(rtwdev) ? 'Y' : 'N'); 670082a36dcSTsang-Shian Lin seq_printf(m, "Current CH(fc) = %u\n", rtwdev->hal.current_channel); 671082a36dcSTsang-Shian Lin seq_printf(m, "Current BW = %u\n", rtwdev->hal.current_band_width); 672082a36dcSTsang-Shian Lin seq_printf(m, "Current IGI = 0x%x\n", dm_info->igi_history[0]); 673082a36dcSTsang-Shian Lin seq_printf(m, "TP {Tx, Rx} = {%u, %u}Mbps\n\n", 674082a36dcSTsang-Shian Lin stats->tx_throughput, stats->rx_throughput); 675082a36dcSTsang-Shian Lin 676082a36dcSTsang-Shian Lin seq_puts(m, "==========[Tx Phy Info]========\n"); 677082a36dcSTsang-Shian Lin seq_puts(m, "[Tx Rate] = "); 678082a36dcSTsang-Shian Lin rtw_print_rate(m, dm_info->tx_rate); 679082a36dcSTsang-Shian Lin seq_printf(m, "(0x%x)\n\n", dm_info->tx_rate); 680082a36dcSTsang-Shian Lin 681082a36dcSTsang-Shian Lin seq_puts(m, "==========[Rx Phy Info]========\n"); 682082a36dcSTsang-Shian Lin seq_printf(m, "[Rx Beacon Count] = %u\n", last_cnt->num_bcn_pkt); 683082a36dcSTsang-Shian Lin seq_puts(m, "[Rx Rate] = "); 684082a36dcSTsang-Shian Lin rtw_print_rate(m, dm_info->curr_rx_rate); 685082a36dcSTsang-Shian Lin seq_printf(m, "(0x%x)\n", dm_info->curr_rx_rate); 686082a36dcSTsang-Shian Lin 687082a36dcSTsang-Shian Lin seq_puts(m, "[Rx Rate Count]:\n"); 688082a36dcSTsang-Shian Lin seq_printf(m, " * CCK = {%u, %u, %u, %u}\n", 689082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE1M], 690082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE2M], 691082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE5_5M], 692082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE11M]); 693082a36dcSTsang-Shian Lin 694082a36dcSTsang-Shian Lin seq_printf(m, " * OFDM = {%u, %u, %u, %u, %u, %u, %u, %u}\n", 695082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE6M], 696082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE9M], 697082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE12M], 698082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE18M], 699082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE24M], 700082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE36M], 701082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE48M], 702082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[DESC_RATE54M]); 703082a36dcSTsang-Shian Lin 704082a36dcSTsang-Shian Lin for (ss = 0; ss < efuse->hw_cap.nss; ss++) { 705082a36dcSTsang-Shian Lin rate_id = DESC_RATEMCS0 + ss * 8; 706082a36dcSTsang-Shian Lin seq_printf(m, " * HT_MCS[%u:%u] = {%u, %u, %u, %u, %u, %u, %u, %u}\n", 707082a36dcSTsang-Shian Lin ss * 8, ss * 8 + 7, 708082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id], 709082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 1], 710082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 2], 711082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 3], 712082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 4], 713082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 5], 714082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 6], 715082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 7]); 716082a36dcSTsang-Shian Lin } 717082a36dcSTsang-Shian Lin 718082a36dcSTsang-Shian Lin for (ss = 0; ss < efuse->hw_cap.nss; ss++) { 719082a36dcSTsang-Shian Lin rate_id = DESC_RATEVHT1SS_MCS0 + ss * 10; 720082a36dcSTsang-Shian Lin seq_printf(m, " * VHT_MCS-%uss MCS[0:9] = {%u, %u, %u, %u, %u, %u, %u, %u, %u, %u}\n", 721082a36dcSTsang-Shian Lin ss + 1, 722082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id], 723082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 1], 724082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 2], 725082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 3], 726082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 4], 727082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 5], 728082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 6], 729082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 7], 730082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 8], 731082a36dcSTsang-Shian Lin last_cnt->num_qry_pkt[rate_id + 9]); 732082a36dcSTsang-Shian Lin } 733082a36dcSTsang-Shian Lin 734082a36dcSTsang-Shian Lin seq_printf(m, "[RSSI(dBm)] = {%d, %d}\n", 735082a36dcSTsang-Shian Lin dm_info->rssi[RF_PATH_A] - 100, 736082a36dcSTsang-Shian Lin dm_info->rssi[RF_PATH_B] - 100); 737082a36dcSTsang-Shian Lin seq_printf(m, "[Rx EVM(dB)] = {-%d, -%d}\n", 738082a36dcSTsang-Shian Lin dm_info->rx_evm_dbm[RF_PATH_A], 739082a36dcSTsang-Shian Lin dm_info->rx_evm_dbm[RF_PATH_B]); 740082a36dcSTsang-Shian Lin seq_printf(m, "[Rx SNR] = {%d, %d}\n", 741082a36dcSTsang-Shian Lin dm_info->rx_snr[RF_PATH_A], 742082a36dcSTsang-Shian Lin dm_info->rx_snr[RF_PATH_B]); 743082a36dcSTsang-Shian Lin seq_printf(m, "[CFO_tail(KHz)] = {%d, %d}\n", 744082a36dcSTsang-Shian Lin dm_info->cfo_tail[RF_PATH_A], 745082a36dcSTsang-Shian Lin dm_info->cfo_tail[RF_PATH_B]); 746082a36dcSTsang-Shian Lin 747082a36dcSTsang-Shian Lin if (dm_info->curr_rx_rate >= DESC_RATE11M) { 748082a36dcSTsang-Shian Lin seq_puts(m, "[Rx Average Status]:\n"); 749082a36dcSTsang-Shian Lin seq_printf(m, " * OFDM, EVM: {-%d}, SNR: {%d}\n", 750082a36dcSTsang-Shian Lin (u8)ewma_evm_read(&ewma_evm[RTW_EVM_OFDM]), 751082a36dcSTsang-Shian Lin (u8)ewma_snr_read(&ewma_snr[RTW_SNR_OFDM_A])); 752082a36dcSTsang-Shian Lin seq_printf(m, " * 1SS, EVM: {-%d}, SNR: {%d}\n", 753082a36dcSTsang-Shian Lin (u8)ewma_evm_read(&ewma_evm[RTW_EVM_1SS]), 754082a36dcSTsang-Shian Lin (u8)ewma_snr_read(&ewma_snr[RTW_SNR_1SS_A])); 755082a36dcSTsang-Shian Lin seq_printf(m, " * 2SS, EVM: {-%d, -%d}, SNR: {%d, %d}\n", 756082a36dcSTsang-Shian Lin (u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_A]), 757082a36dcSTsang-Shian Lin (u8)ewma_evm_read(&ewma_evm[RTW_EVM_2SS_B]), 758082a36dcSTsang-Shian Lin (u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_A]), 759082a36dcSTsang-Shian Lin (u8)ewma_snr_read(&ewma_snr[RTW_SNR_2SS_B])); 760082a36dcSTsang-Shian Lin } 761082a36dcSTsang-Shian Lin 762082a36dcSTsang-Shian Lin seq_puts(m, "[Rx Counter]:\n"); 763082a36dcSTsang-Shian Lin seq_printf(m, " * CCA (CCK, OFDM, Total) = (%u, %u, %u)\n", 764082a36dcSTsang-Shian Lin dm_info->cck_cca_cnt, 765082a36dcSTsang-Shian Lin dm_info->ofdm_cca_cnt, 766082a36dcSTsang-Shian Lin dm_info->total_cca_cnt); 767082a36dcSTsang-Shian Lin seq_printf(m, " * False Alarm (CCK, OFDM, Total) = (%u, %u, %u)\n", 768082a36dcSTsang-Shian Lin dm_info->cck_fa_cnt, 769082a36dcSTsang-Shian Lin dm_info->ofdm_fa_cnt, 770082a36dcSTsang-Shian Lin dm_info->total_fa_cnt); 771082a36dcSTsang-Shian Lin seq_printf(m, " * CCK cnt (ok, err) = (%u, %u)\n", 772082a36dcSTsang-Shian Lin dm_info->cck_ok_cnt, dm_info->cck_err_cnt); 773082a36dcSTsang-Shian Lin seq_printf(m, " * OFDM cnt (ok, err) = (%u, %u)\n", 774082a36dcSTsang-Shian Lin dm_info->ofdm_ok_cnt, dm_info->ofdm_err_cnt); 775082a36dcSTsang-Shian Lin seq_printf(m, " * HT cnt (ok, err) = (%u, %u)\n", 776082a36dcSTsang-Shian Lin dm_info->ht_ok_cnt, dm_info->ht_err_cnt); 777082a36dcSTsang-Shian Lin seq_printf(m, " * VHT cnt (ok, err) = (%u, %u)\n", 778082a36dcSTsang-Shian Lin dm_info->vht_ok_cnt, dm_info->vht_err_cnt); 7791fe188daSYan-Hsuan Chuang 7801fe188daSYan-Hsuan Chuang return 0; 7811fe188daSYan-Hsuan Chuang } 7821fe188daSYan-Hsuan Chuang 7831fe188daSYan-Hsuan Chuang static int rtw_debugfs_get_coex_info(struct seq_file *m, void *v) 7841fe188daSYan-Hsuan Chuang { 7851fe188daSYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 7861fe188daSYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 7871fe188daSYan-Hsuan Chuang 7881fe188daSYan-Hsuan Chuang rtw_coex_display_coex_info(rtwdev, m); 7891fe188daSYan-Hsuan Chuang 790082a36dcSTsang-Shian Lin return 0; 791082a36dcSTsang-Shian Lin } 792082a36dcSTsang-Shian Lin 793d0555093SYan-Hsuan Chuang static ssize_t rtw_debugfs_set_coex_enable(struct file *filp, 794d0555093SYan-Hsuan Chuang const char __user *buffer, 795d0555093SYan-Hsuan Chuang size_t count, loff_t *loff) 796d0555093SYan-Hsuan Chuang { 797d0555093SYan-Hsuan Chuang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 798d0555093SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 799d0555093SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 800d0555093SYan-Hsuan Chuang struct rtw_coex *coex = &rtwdev->coex; 801d0555093SYan-Hsuan Chuang char tmp[32 + 1]; 802d0555093SYan-Hsuan Chuang bool enable; 803d0555093SYan-Hsuan Chuang int ret; 804d0555093SYan-Hsuan Chuang 805d0555093SYan-Hsuan Chuang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); 806d0555093SYan-Hsuan Chuang 807d0555093SYan-Hsuan Chuang ret = kstrtobool(tmp, &enable); 808d0555093SYan-Hsuan Chuang if (ret) { 809d0555093SYan-Hsuan Chuang rtw_warn(rtwdev, "invalid arguments\n"); 810d0555093SYan-Hsuan Chuang return ret; 811d0555093SYan-Hsuan Chuang } 812d0555093SYan-Hsuan Chuang 813d0555093SYan-Hsuan Chuang mutex_lock(&rtwdev->mutex); 814d3a78c7aSYANG LI coex->manual_control = !enable; 815d0555093SYan-Hsuan Chuang mutex_unlock(&rtwdev->mutex); 816d0555093SYan-Hsuan Chuang 817d0555093SYan-Hsuan Chuang return count; 818d0555093SYan-Hsuan Chuang } 819d0555093SYan-Hsuan Chuang 820d0555093SYan-Hsuan Chuang static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v) 821d0555093SYan-Hsuan Chuang { 822d0555093SYan-Hsuan Chuang struct rtw_debugfs_priv *debugfs_priv = m->private; 823d0555093SYan-Hsuan Chuang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 824d0555093SYan-Hsuan Chuang struct rtw_coex *coex = &rtwdev->coex; 825d0555093SYan-Hsuan Chuang 826d0555093SYan-Hsuan Chuang seq_printf(m, "coex mechanism %s\n", 82732c3a8c7SChing-Te Ku coex->manual_control ? "disabled" : "enabled"); 828d0555093SYan-Hsuan Chuang 829d0555093SYan-Hsuan Chuang return 0; 830d0555093SYan-Hsuan Chuang } 831d0555093SYan-Hsuan Chuang 83213ce240aSZong-Zhe Yang static ssize_t rtw_debugfs_set_fw_crash(struct file *filp, 83313ce240aSZong-Zhe Yang const char __user *buffer, 83413ce240aSZong-Zhe Yang size_t count, loff_t *loff) 83513ce240aSZong-Zhe Yang { 83613ce240aSZong-Zhe Yang struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 83713ce240aSZong-Zhe Yang struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 83813ce240aSZong-Zhe Yang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 83913ce240aSZong-Zhe Yang char tmp[32 + 1]; 84013ce240aSZong-Zhe Yang bool input; 84113ce240aSZong-Zhe Yang int ret; 84213ce240aSZong-Zhe Yang 84313ce240aSZong-Zhe Yang rtw_debugfs_copy_from_user(tmp, sizeof(tmp), buffer, count, 1); 84413ce240aSZong-Zhe Yang 84513ce240aSZong-Zhe Yang ret = kstrtobool(tmp, &input); 84613ce240aSZong-Zhe Yang if (ret) 84713ce240aSZong-Zhe Yang return -EINVAL; 84813ce240aSZong-Zhe Yang 84913ce240aSZong-Zhe Yang if (!input) 85013ce240aSZong-Zhe Yang return -EINVAL; 85113ce240aSZong-Zhe Yang 8527b80f3e4SZong-Zhe Yang if (test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)) 8537b80f3e4SZong-Zhe Yang return -EINPROGRESS; 8547b80f3e4SZong-Zhe Yang 8557b80f3e4SZong-Zhe Yang mutex_lock(&rtwdev->mutex); 8567b80f3e4SZong-Zhe Yang rtw_leave_lps_deep(rtwdev); 85713ce240aSZong-Zhe Yang rtw_write8(rtwdev, REG_HRCV_MSG, 1); 8587b80f3e4SZong-Zhe Yang mutex_unlock(&rtwdev->mutex); 85913ce240aSZong-Zhe Yang 86013ce240aSZong-Zhe Yang return count; 86113ce240aSZong-Zhe Yang } 86213ce240aSZong-Zhe Yang 86313ce240aSZong-Zhe Yang static int rtw_debugfs_get_fw_crash(struct seq_file *m, void *v) 86413ce240aSZong-Zhe Yang { 86513ce240aSZong-Zhe Yang struct rtw_debugfs_priv *debugfs_priv = m->private; 86613ce240aSZong-Zhe Yang struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 86713ce240aSZong-Zhe Yang 86813ce240aSZong-Zhe Yang seq_printf(m, "%d\n", test_bit(RTW_FLAG_RESTARTING, rtwdev->flags)); 86913ce240aSZong-Zhe Yang return 0; 87013ce240aSZong-Zhe Yang } 87113ce240aSZong-Zhe Yang 8723b25bac8SGuo-Feng Fan static ssize_t rtw_debugfs_set_dm_cap(struct file *filp, 8733b25bac8SGuo-Feng Fan const char __user *buffer, 8743b25bac8SGuo-Feng Fan size_t count, loff_t *loff) 8753b25bac8SGuo-Feng Fan { 8763b25bac8SGuo-Feng Fan struct seq_file *seqpriv = (struct seq_file *)filp->private_data; 8773b25bac8SGuo-Feng Fan struct rtw_debugfs_priv *debugfs_priv = seqpriv->private; 8783b25bac8SGuo-Feng Fan struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 8793b25bac8SGuo-Feng Fan struct rtw_dm_info *dm_info = &rtwdev->dm_info; 8803b25bac8SGuo-Feng Fan int bit; 8813b25bac8SGuo-Feng Fan bool en; 8823b25bac8SGuo-Feng Fan 8833b25bac8SGuo-Feng Fan if (kstrtoint_from_user(buffer, count, 10, &bit)) 8843b25bac8SGuo-Feng Fan return -EINVAL; 8853b25bac8SGuo-Feng Fan 8863b25bac8SGuo-Feng Fan en = bit > 0; 8873b25bac8SGuo-Feng Fan bit = abs(bit); 8883b25bac8SGuo-Feng Fan 8893b25bac8SGuo-Feng Fan if (bit >= RTW_DM_CAP_NUM) { 8903b25bac8SGuo-Feng Fan rtw_warn(rtwdev, "unknown DM CAP %d\n", bit); 8913b25bac8SGuo-Feng Fan return -EINVAL; 8923b25bac8SGuo-Feng Fan } 8933b25bac8SGuo-Feng Fan 8943b25bac8SGuo-Feng Fan if (en) 8953b25bac8SGuo-Feng Fan dm_info->dm_flags &= ~BIT(bit); 8963b25bac8SGuo-Feng Fan else 8973b25bac8SGuo-Feng Fan dm_info->dm_flags |= BIT(bit); 8983b25bac8SGuo-Feng Fan 8993b25bac8SGuo-Feng Fan debugfs_priv->dm_cap.bit = bit; 9003b25bac8SGuo-Feng Fan 9013b25bac8SGuo-Feng Fan return count; 9023b25bac8SGuo-Feng Fan } 9033b25bac8SGuo-Feng Fan 9043b25bac8SGuo-Feng Fan static void dump_gapk_status(struct rtw_dev *rtwdev, struct seq_file *m) 9053b25bac8SGuo-Feng Fan { 9063b25bac8SGuo-Feng Fan struct rtw_dm_info *dm_info = &rtwdev->dm_info; 9073b25bac8SGuo-Feng Fan struct rtw_gapk_info *txgapk = &rtwdev->dm_info.gapk; 9083b25bac8SGuo-Feng Fan int i, path; 9093b25bac8SGuo-Feng Fan u32 val; 9103b25bac8SGuo-Feng Fan 9113b25bac8SGuo-Feng Fan seq_printf(m, "\n(%2d) %c%s\n\n", RTW_DM_CAP_TXGAPK, 9123b25bac8SGuo-Feng Fan dm_info->dm_flags & BIT(RTW_DM_CAP_TXGAPK) ? '-' : '+', 9133b25bac8SGuo-Feng Fan rtw_dm_cap_strs[RTW_DM_CAP_TXGAPK]); 9143b25bac8SGuo-Feng Fan 9153b25bac8SGuo-Feng Fan for (path = 0; path < rtwdev->hal.rf_path_num; path++) { 9163b25bac8SGuo-Feng Fan val = rtw_read_rf(rtwdev, path, RF_GAINTX, RFREG_MASK); 9173b25bac8SGuo-Feng Fan seq_printf(m, "path %d:\n0x%x = 0x%x\n", path, RF_GAINTX, val); 9183b25bac8SGuo-Feng Fan 9193b25bac8SGuo-Feng Fan for (i = 0; i < RF_HW_OFFSET_NUM; i++) 9203b25bac8SGuo-Feng Fan seq_printf(m, "[TXGAPK] offset %d %d\n", 9213b25bac8SGuo-Feng Fan txgapk->rf3f_fs[path][i], i); 9223b25bac8SGuo-Feng Fan seq_puts(m, "\n"); 9233b25bac8SGuo-Feng Fan } 9243b25bac8SGuo-Feng Fan } 9253b25bac8SGuo-Feng Fan 9263b25bac8SGuo-Feng Fan static int rtw_debugfs_get_dm_cap(struct seq_file *m, void *v) 9273b25bac8SGuo-Feng Fan { 9283b25bac8SGuo-Feng Fan struct rtw_debugfs_priv *debugfs_priv = m->private; 9293b25bac8SGuo-Feng Fan struct rtw_dev *rtwdev = debugfs_priv->rtwdev; 9303b25bac8SGuo-Feng Fan struct rtw_dm_info *dm_info = &rtwdev->dm_info; 9313b25bac8SGuo-Feng Fan int i; 9323b25bac8SGuo-Feng Fan 9333b25bac8SGuo-Feng Fan switch (debugfs_priv->dm_cap.bit) { 9343b25bac8SGuo-Feng Fan case RTW_DM_CAP_TXGAPK: 9353b25bac8SGuo-Feng Fan dump_gapk_status(rtwdev, m); 9363b25bac8SGuo-Feng Fan break; 9373b25bac8SGuo-Feng Fan default: 9383b25bac8SGuo-Feng Fan for (i = 1; i < RTW_DM_CAP_NUM; i++) { 9393b25bac8SGuo-Feng Fan seq_printf(m, "(%2d) %c%s\n", i, 9403b25bac8SGuo-Feng Fan dm_info->dm_flags & BIT(i) ? '-' : '+', 9413b25bac8SGuo-Feng Fan rtw_dm_cap_strs[i]); 9423b25bac8SGuo-Feng Fan } 9433b25bac8SGuo-Feng Fan break; 9443b25bac8SGuo-Feng Fan } 9453b25bac8SGuo-Feng Fan debugfs_priv->dm_cap.bit = RTW_DM_CAP_NA; 9463b25bac8SGuo-Feng Fan return 0; 9473b25bac8SGuo-Feng Fan } 9483b25bac8SGuo-Feng Fan 949e3037485SYan-Hsuan Chuang #define rtw_debug_impl_mac(page, addr) \ 950e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_mac_ ##page = { \ 951e3037485SYan-Hsuan Chuang .cb_read = rtw_debug_get_mac_page, \ 952e3037485SYan-Hsuan Chuang .cb_data = addr, \ 953e3037485SYan-Hsuan Chuang } 954e3037485SYan-Hsuan Chuang 955e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(0, 0x0000); 956e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(1, 0x0100); 957e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(2, 0x0200); 958e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(3, 0x0300); 959e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(4, 0x0400); 960e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(5, 0x0500); 961e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(6, 0x0600); 962e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(7, 0x0700); 963e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(10, 0x1000); 964e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(11, 0x1100); 965e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(12, 0x1200); 966e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(13, 0x1300); 967e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(14, 0x1400); 968e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(15, 0x1500); 969e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(16, 0x1600); 970e3037485SYan-Hsuan Chuang rtw_debug_impl_mac(17, 0x1700); 971e3037485SYan-Hsuan Chuang 972e3037485SYan-Hsuan Chuang #define rtw_debug_impl_bb(page, addr) \ 973e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_bb_ ##page = { \ 974e3037485SYan-Hsuan Chuang .cb_read = rtw_debug_get_bb_page, \ 975e3037485SYan-Hsuan Chuang .cb_data = addr, \ 976e3037485SYan-Hsuan Chuang } 977e3037485SYan-Hsuan Chuang 978e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(8, 0x0800); 979e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(9, 0x0900); 980e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(a, 0x0a00); 981e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(b, 0x0b00); 982e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(c, 0x0c00); 983e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(d, 0x0d00); 984e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(e, 0x0e00); 985e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(f, 0x0f00); 986e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(18, 0x1800); 987e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(19, 0x1900); 988e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1a, 0x1a00); 989e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1b, 0x1b00); 990e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1c, 0x1c00); 991e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1d, 0x1d00); 992e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1e, 0x1e00); 993e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(1f, 0x1f00); 994e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(2c, 0x2c00); 995e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(2d, 0x2d00); 996e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(40, 0x4000); 997e3037485SYan-Hsuan Chuang rtw_debug_impl_bb(41, 0x4100); 998e3037485SYan-Hsuan Chuang 999e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_rf_dump = { 1000e3037485SYan-Hsuan Chuang .cb_read = rtw_debug_get_rf_dump, 1001e3037485SYan-Hsuan Chuang }; 1002e3037485SYan-Hsuan Chuang 10038812022cSZong-Zhe Yang static struct rtw_debugfs_priv rtw_debug_priv_tx_pwr_tbl = { 10048812022cSZong-Zhe Yang .cb_read = rtw_debugfs_get_tx_pwr_tbl, 10058812022cSZong-Zhe Yang }; 10068812022cSZong-Zhe Yang 1007e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_write_reg = { 1008e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_write_reg, 1009e3037485SYan-Hsuan Chuang }; 1010e3037485SYan-Hsuan Chuang 1011c376c1fcSTzu-En Huang static struct rtw_debugfs_priv rtw_debug_priv_h2c = { 1012c376c1fcSTzu-En Huang .cb_write = rtw_debugfs_set_h2c, 1013c376c1fcSTzu-En Huang }; 1014c376c1fcSTzu-En Huang 1015e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_rf_write = { 1016e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_rf_write, 1017e3037485SYan-Hsuan Chuang }; 1018e3037485SYan-Hsuan Chuang 1019e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_rf_read = { 1020e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_rf_read, 1021e3037485SYan-Hsuan Chuang .cb_read = rtw_debugfs_get_rf_read, 1022e3037485SYan-Hsuan Chuang }; 1023e3037485SYan-Hsuan Chuang 1024e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_read_reg = { 1025e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_read_reg, 1026e3037485SYan-Hsuan Chuang .cb_read = rtw_debugfs_get_read_reg, 1027e3037485SYan-Hsuan Chuang }; 1028e3037485SYan-Hsuan Chuang 1029e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_dump_cam = { 1030e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_single_input, 1031e3037485SYan-Hsuan Chuang .cb_read = rtw_debugfs_get_dump_cam, 1032e3037485SYan-Hsuan Chuang }; 1033e3037485SYan-Hsuan Chuang 1034e3037485SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_rsvd_page = { 1035e3037485SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_rsvd_page, 1036e3037485SYan-Hsuan Chuang .cb_read = rtw_debugfs_get_rsvd_page, 1037e3037485SYan-Hsuan Chuang }; 1038e3037485SYan-Hsuan Chuang 1039082a36dcSTsang-Shian Lin static struct rtw_debugfs_priv rtw_debug_priv_phy_info = { 1040082a36dcSTsang-Shian Lin .cb_read = rtw_debugfs_get_phy_info, 1041082a36dcSTsang-Shian Lin }; 1042082a36dcSTsang-Shian Lin 1043d0555093SYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_coex_enable = { 1044d0555093SYan-Hsuan Chuang .cb_write = rtw_debugfs_set_coex_enable, 1045d0555093SYan-Hsuan Chuang .cb_read = rtw_debugfs_get_coex_enable, 1046d0555093SYan-Hsuan Chuang }; 1047d0555093SYan-Hsuan Chuang 10481fe188daSYan-Hsuan Chuang static struct rtw_debugfs_priv rtw_debug_priv_coex_info = { 10491fe188daSYan-Hsuan Chuang .cb_read = rtw_debugfs_get_coex_info, 10501fe188daSYan-Hsuan Chuang }; 10511fe188daSYan-Hsuan Chuang 105213ce240aSZong-Zhe Yang static struct rtw_debugfs_priv rtw_debug_priv_fw_crash = { 105313ce240aSZong-Zhe Yang .cb_write = rtw_debugfs_set_fw_crash, 105413ce240aSZong-Zhe Yang .cb_read = rtw_debugfs_get_fw_crash, 105513ce240aSZong-Zhe Yang }; 105613ce240aSZong-Zhe Yang 10573b25bac8SGuo-Feng Fan static struct rtw_debugfs_priv rtw_debug_priv_dm_cap = { 10583b25bac8SGuo-Feng Fan .cb_write = rtw_debugfs_set_dm_cap, 10593b25bac8SGuo-Feng Fan .cb_read = rtw_debugfs_get_dm_cap, 10603b25bac8SGuo-Feng Fan }; 10613b25bac8SGuo-Feng Fan 1062e3037485SYan-Hsuan Chuang #define rtw_debugfs_add_core(name, mode, fopname, parent) \ 1063e3037485SYan-Hsuan Chuang do { \ 1064e3037485SYan-Hsuan Chuang rtw_debug_priv_ ##name.rtwdev = rtwdev; \ 1065e3037485SYan-Hsuan Chuang if (!debugfs_create_file(#name, mode, \ 1066e3037485SYan-Hsuan Chuang parent, &rtw_debug_priv_ ##name,\ 1067e3037485SYan-Hsuan Chuang &file_ops_ ##fopname)) \ 1068e3037485SYan-Hsuan Chuang pr_debug("Unable to initialize debugfs:%s\n", \ 1069e3037485SYan-Hsuan Chuang #name); \ 1070e3037485SYan-Hsuan Chuang } while (0) 1071e3037485SYan-Hsuan Chuang 1072e3037485SYan-Hsuan Chuang #define rtw_debugfs_add_w(name) \ 1073e3037485SYan-Hsuan Chuang rtw_debugfs_add_core(name, S_IFREG | 0222, common_write, debugfs_topdir) 1074e3037485SYan-Hsuan Chuang #define rtw_debugfs_add_rw(name) \ 1075e3037485SYan-Hsuan Chuang rtw_debugfs_add_core(name, S_IFREG | 0666, single_rw, debugfs_topdir) 1076e3037485SYan-Hsuan Chuang #define rtw_debugfs_add_r(name) \ 1077e3037485SYan-Hsuan Chuang rtw_debugfs_add_core(name, S_IFREG | 0444, single_r, debugfs_topdir) 1078e3037485SYan-Hsuan Chuang 1079e3037485SYan-Hsuan Chuang void rtw_debugfs_init(struct rtw_dev *rtwdev) 1080e3037485SYan-Hsuan Chuang { 10819f7d65fbSColin Ian King struct dentry *debugfs_topdir; 1082e3037485SYan-Hsuan Chuang 1083e3037485SYan-Hsuan Chuang debugfs_topdir = debugfs_create_dir("rtw88", 1084e3037485SYan-Hsuan Chuang rtwdev->hw->wiphy->debugfsdir); 1085e3037485SYan-Hsuan Chuang rtw_debugfs_add_w(write_reg); 1086e3037485SYan-Hsuan Chuang rtw_debugfs_add_rw(read_reg); 1087e3037485SYan-Hsuan Chuang rtw_debugfs_add_w(rf_write); 1088e3037485SYan-Hsuan Chuang rtw_debugfs_add_rw(rf_read); 1089e3037485SYan-Hsuan Chuang rtw_debugfs_add_rw(dump_cam); 1090e3037485SYan-Hsuan Chuang rtw_debugfs_add_rw(rsvd_page); 1091082a36dcSTsang-Shian Lin rtw_debugfs_add_r(phy_info); 10921fe188daSYan-Hsuan Chuang rtw_debugfs_add_r(coex_info); 1093d0555093SYan-Hsuan Chuang rtw_debugfs_add_rw(coex_enable); 1094c376c1fcSTzu-En Huang rtw_debugfs_add_w(h2c); 1095e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_0); 1096e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_1); 1097e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_2); 1098e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_3); 1099e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_4); 1100e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_5); 1101e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_6); 1102e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_7); 1103e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_8); 1104e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_9); 1105e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_a); 1106e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_b); 1107e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_c); 1108e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_d); 1109e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_e); 1110e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_f); 1111e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_10); 1112e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_11); 1113e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_12); 1114e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_13); 1115e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_14); 1116e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_15); 1117e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_16); 1118e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(mac_17); 1119e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_18); 1120e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_19); 1121e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1a); 1122e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1b); 1123e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1c); 1124e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1d); 1125e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1e); 1126e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_1f); 1127e3037485SYan-Hsuan Chuang if (rtwdev->chip->id == RTW_CHIP_TYPE_8822C) { 1128e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_2c); 1129e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_2d); 1130e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_40); 1131e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(bb_41); 1132e3037485SYan-Hsuan Chuang } 1133e3037485SYan-Hsuan Chuang rtw_debugfs_add_r(rf_dump); 11348812022cSZong-Zhe Yang rtw_debugfs_add_r(tx_pwr_tbl); 113513ce240aSZong-Zhe Yang rtw_debugfs_add_rw(fw_crash); 11363b25bac8SGuo-Feng Fan rtw_debugfs_add_rw(dm_cap); 1137e3037485SYan-Hsuan Chuang } 1138e3037485SYan-Hsuan Chuang 1139e3037485SYan-Hsuan Chuang #endif /* CONFIG_RTW88_DEBUGFS */ 1140e3037485SYan-Hsuan Chuang 1141e3037485SYan-Hsuan Chuang #ifdef CONFIG_RTW88_DEBUG 1142e3037485SYan-Hsuan Chuang 1143e3037485SYan-Hsuan Chuang void __rtw_dbg(struct rtw_dev *rtwdev, enum rtw_debug_mask mask, 1144e3037485SYan-Hsuan Chuang const char *fmt, ...) 1145e3037485SYan-Hsuan Chuang { 1146e3037485SYan-Hsuan Chuang struct va_format vaf = { 1147e3037485SYan-Hsuan Chuang .fmt = fmt, 1148e3037485SYan-Hsuan Chuang }; 1149e3037485SYan-Hsuan Chuang va_list args; 1150e3037485SYan-Hsuan Chuang 1151e3037485SYan-Hsuan Chuang va_start(args, fmt); 1152e3037485SYan-Hsuan Chuang vaf.va = &args; 1153e3037485SYan-Hsuan Chuang 1154e3037485SYan-Hsuan Chuang if (rtw_debug_mask & mask) 1155e3037485SYan-Hsuan Chuang dev_printk(KERN_DEBUG, rtwdev->dev, "%pV", &vaf); 1156e3037485SYan-Hsuan Chuang 1157e3037485SYan-Hsuan Chuang va_end(args); 1158e3037485SYan-Hsuan Chuang } 1159e3037485SYan-Hsuan Chuang EXPORT_SYMBOL(__rtw_dbg); 1160e3037485SYan-Hsuan Chuang 1161e3037485SYan-Hsuan Chuang #endif /* CONFIG_RTW88_DEBUG */ 1162