blob: 59e48bb61bd5edb27ce04dc26f39fdbd6c54e8d9 [file] [log] [blame]
developerfd40db22021-04-29 10:08:25 +08001/*
2 * Copyright (C) 2018 MediaTek Inc.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * Copyright (C) 2009-2016 John Crispin <blogic@openwrt.org>
14 * Copyright (C) 2009-2016 Felix Fietkau <nbd@openwrt.org>
15 * Copyright (C) 2013-2016 Michael Lee <igvtee@gmail.com>
16 */
17
18#include <linux/trace_seq.h>
19#include <linux/seq_file.h>
20#include <linux/proc_fs.h>
21#include <linux/u64_stats_sync.h>
22#include <linux/dma-mapping.h>
23#include <linux/netdevice.h>
24#include <linux/ctype.h>
25#include <linux/debugfs.h>
26#include <linux/of_mdio.h>
27
28#include "mtk_eth_soc.h"
29#include "mtk_eth_dbg.h"
30
31struct mtk_eth_debug {
32 struct dentry *root;
33};
34
35struct mtk_eth *g_eth;
36
37struct mtk_eth_debug eth_debug;
38
developer3957a912021-05-13 16:44:31 +080039void mt7530_mdio_w32(struct mtk_eth *eth, u16 reg, u32 val)
developerfd40db22021-04-29 10:08:25 +080040{
41 mutex_lock(&eth->mii_bus->mdio_lock);
42
43 _mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
44 _mtk_mdio_write(eth, 0x1f, (reg >> 2) & 0xf, val & 0xffff);
45 _mtk_mdio_write(eth, 0x1f, 0x10, val >> 16);
46
47 mutex_unlock(&eth->mii_bus->mdio_lock);
48}
49
50u32 mt7530_mdio_r32(struct mtk_eth *eth, u32 reg)
51{
52 u16 high, low;
53
54 mutex_lock(&eth->mii_bus->mdio_lock);
55
56 _mtk_mdio_write(eth, 0x1f, 0x1f, (reg >> 6) & 0x3ff);
57 low = _mtk_mdio_read(eth, 0x1f, (reg >> 2) & 0xf);
58 high = _mtk_mdio_read(eth, 0x1f, 0x10);
59
60 mutex_unlock(&eth->mii_bus->mdio_lock);
61
62 return (high << 16) | (low & 0xffff);
63}
64
65void mtk_switch_w32(struct mtk_eth *eth, u32 val, unsigned reg)
66{
67 mtk_w32(eth, val, reg + 0x10000);
68}
69EXPORT_SYMBOL(mtk_switch_w32);
70
71u32 mtk_switch_r32(struct mtk_eth *eth, unsigned reg)
72{
73 return mtk_r32(eth, reg + 0x10000);
74}
75EXPORT_SYMBOL(mtk_switch_r32);
76
77static int mtketh_debug_show(struct seq_file *m, void *private)
78{
79 struct mtk_eth *eth = m->private;
80 struct mtk_mac *mac = 0;
81 u32 d;
82 int i, j = 0;
83
84 for (i = 0 ; i < MTK_MAX_DEVS ; i++) {
85 if (!eth->mac[i] ||
86 of_phy_is_fixed_link(eth->mac[i]->of_node))
87 continue;
88 mac = eth->mac[i];
89#if 0 //FIXME
90 while (j < 30) {
91 d = _mtk_mdio_read(eth, mac->phy_dev->addr, j);
92
93 seq_printf(m, "phy=%d, reg=0x%08x, data=0x%08x\n",
94 mac->phy_dev->addr, j, d);
95 j++;
96 }
97#endif
98 }
99 return 0;
100}
101
102static int mtketh_debug_open(struct inode *inode, struct file *file)
103{
104 return single_open(file, mtketh_debug_show, inode->i_private);
105}
106
107static const struct file_operations mtketh_debug_fops = {
108 .open = mtketh_debug_open,
109 .read = seq_read,
110 .llseek = seq_lseek,
111 .release = single_release,
112};
113
114static int mtketh_mt7530sw_debug_show(struct seq_file *m, void *private)
115{
116 struct mtk_eth *eth = m->private;
117 u32 offset, data;
118 int i;
119 struct mt7530_ranges {
120 u32 start;
121 u32 end;
122 } ranges[] = {
123 {0x0, 0xac},
124 {0x1000, 0x10e0},
125 {0x1100, 0x1140},
126 {0x1200, 0x1240},
127 {0x1300, 0x1340},
128 {0x1400, 0x1440},
129 {0x1500, 0x1540},
130 {0x1600, 0x1640},
131 {0x1800, 0x1848},
132 {0x1900, 0x1948},
133 {0x1a00, 0x1a48},
134 {0x1b00, 0x1b48},
135 {0x1c00, 0x1c48},
136 {0x1d00, 0x1d48},
137 {0x1e00, 0x1e48},
138 {0x1f60, 0x1ffc},
139 {0x2000, 0x212c},
140 {0x2200, 0x222c},
141 {0x2300, 0x232c},
142 {0x2400, 0x242c},
143 {0x2500, 0x252c},
144 {0x2600, 0x262c},
145 {0x3000, 0x3014},
146 {0x30c0, 0x30f8},
147 {0x3100, 0x3114},
148 {0x3200, 0x3214},
149 {0x3300, 0x3314},
150 {0x3400, 0x3414},
151 {0x3500, 0x3514},
152 {0x3600, 0x3614},
153 {0x4000, 0x40d4},
154 {0x4100, 0x41d4},
155 {0x4200, 0x42d4},
156 {0x4300, 0x43d4},
157 {0x4400, 0x44d4},
158 {0x4500, 0x45d4},
159 {0x4600, 0x46d4},
160 {0x4f00, 0x461c},
161 {0x7000, 0x7038},
162 {0x7120, 0x7124},
163 {0x7800, 0x7804},
164 {0x7810, 0x7810},
165 {0x7830, 0x7830},
166 {0x7a00, 0x7a7c},
167 {0x7b00, 0x7b04},
168 {0x7e00, 0x7e04},
169 {0x7ffc, 0x7ffc},
170 };
171
172 if (!mt7530_exist(eth))
173 return -EOPNOTSUPP;
174
175 if ((!eth->mac[0] || !of_phy_is_fixed_link(eth->mac[0]->of_node)) &&
176 (!eth->mac[1] || !of_phy_is_fixed_link(eth->mac[1]->of_node))) {
177 seq_puts(m, "no switch found\n");
178 return 0;
179 }
180
181 for (i = 0 ; i < ARRAY_SIZE(ranges) ; i++) {
182 for (offset = ranges[i].start;
183 offset <= ranges[i].end; offset += 4) {
184 data = mt7530_mdio_r32(eth, offset);
185 seq_printf(m, "mt7530 switch reg=0x%08x, data=0x%08x\n",
186 offset, data);
187 }
188 }
189
190 return 0;
191}
192
193static int mtketh_debug_mt7530sw_open(struct inode *inode, struct file *file)
194{
195 return single_open(file, mtketh_mt7530sw_debug_show, inode->i_private);
196}
197
198static const struct file_operations mtketh_debug_mt7530sw_fops = {
199 .open = mtketh_debug_mt7530sw_open,
200 .read = seq_read,
201 .llseek = seq_lseek,
202 .release = single_release,
203};
204
205static ssize_t mtketh_mt7530sw_debugfs_write(struct file *file,
206 const char __user *ptr,
207 size_t len, loff_t *off)
208{
209 struct mtk_eth *eth = file->private_data;
210 char buf[32], *token, *p = buf;
211 u32 reg, value, phy;
212 int ret;
213
214 if (!mt7530_exist(eth))
215 return -EOPNOTSUPP;
216
217 if (*off != 0)
218 return 0;
219
220 if (len > sizeof(buf) - 1)
221 len = sizeof(buf) - 1;
222
223 ret = strncpy_from_user(buf, ptr, len);
224 if (ret < 0)
225 return ret;
226 buf[len] = '\0';
227
228 token = strsep(&p, " ");
229 if (!token)
230 return -EINVAL;
231 if (kstrtoul(token, 16, (unsigned long *)&phy))
232 return -EINVAL;
233
234 token = strsep(&p, " ");
235 if (!token)
236 return -EINVAL;
237 if (kstrtoul(token, 16, (unsigned long *)&reg))
238 return -EINVAL;
239
240 token = strsep(&p, " ");
241 if (!token)
242 return -EINVAL;
243 if (kstrtoul(token, 16, (unsigned long *)&value))
244 return -EINVAL;
245
246 pr_info("%s:phy=%d, reg=0x%x, val=0x%x\n", __func__,
247 0x1f, reg, value);
248 mt7530_mdio_w32(eth, reg, value);
249 pr_info("%s:phy=%d, reg=0x%x, val=0x%x confirm..\n", __func__,
250 0x1f, reg, mt7530_mdio_r32(eth, reg));
251
252 return len;
253}
254
255static ssize_t mtketh_debugfs_write(struct file *file, const char __user *ptr,
256 size_t len, loff_t *off)
257{
258 struct mtk_eth *eth = file->private_data;
259 char buf[32], *token, *p = buf;
260 u32 reg, value, phy;
261 int ret;
262
263 if (*off != 0)
264 return 0;
265
266 if (len > sizeof(buf) - 1)
267 len = sizeof(buf) - 1;
268
269 ret = strncpy_from_user(buf, ptr, len);
270 if (ret < 0)
271 return ret;
272 buf[len] = '\0';
273
274 token = strsep(&p, " ");
275 if (!token)
276 return -EINVAL;
277 if (kstrtoul(token, 16, (unsigned long *)&phy))
278 return -EINVAL;
279
280 token = strsep(&p, " ");
281
282 if (!token)
283 return -EINVAL;
284 if (kstrtoul(token, 16, (unsigned long *)&reg))
285 return -EINVAL;
286
287 token = strsep(&p, " ");
288
289 if (!token)
290 return -EINVAL;
291 if (kstrtoul(token, 16, (unsigned long *)&value))
292 return -EINVAL;
293
294 pr_info("%s:phy=%d, reg=0x%x, val=0x%x\n", __func__,
295 phy, reg, value);
296
297 _mtk_mdio_write(eth, phy, reg, value);
298
299 pr_info("%s:phy=%d, reg=0x%x, val=0x%x confirm..\n", __func__,
300 phy, reg, _mtk_mdio_read(eth, phy, reg));
301
302 return len;
303}
304
305static ssize_t mtketh_debugfs_reset(struct file *file, const char __user *ptr,
306 size_t len, loff_t *off)
307{
308 struct mtk_eth *eth = file->private_data;
309
310 schedule_work(&eth->pending_work);
311 return len;
312}
313
314static const struct file_operations fops_reg_w = {
315 .owner = THIS_MODULE,
316 .open = simple_open,
317 .write = mtketh_debugfs_write,
318 .llseek = noop_llseek,
319};
320
321static const struct file_operations fops_eth_reset = {
322 .owner = THIS_MODULE,
323 .open = simple_open,
324 .write = mtketh_debugfs_reset,
325 .llseek = noop_llseek,
326};
327
328static const struct file_operations fops_mt7530sw_reg_w = {
329 .owner = THIS_MODULE,
330 .open = simple_open,
331 .write = mtketh_mt7530sw_debugfs_write,
332 .llseek = noop_llseek,
333};
334
335void mtketh_debugfs_exit(struct mtk_eth *eth)
336{
337 debugfs_remove_recursive(eth_debug.root);
338}
339
340int mtketh_debugfs_init(struct mtk_eth *eth)
341{
342 int ret = 0;
343
344 eth_debug.root = debugfs_create_dir("mtketh", NULL);
345 if (!eth_debug.root) {
346 dev_notice(eth->dev, "%s:err at %d\n", __func__, __LINE__);
347 ret = -ENOMEM;
348 }
349
350 debugfs_create_file("phy_regs", S_IRUGO,
351 eth_debug.root, eth, &mtketh_debug_fops);
352 debugfs_create_file("phy_reg_w", S_IFREG | S_IWUSR,
353 eth_debug.root, eth, &fops_reg_w);
354 debugfs_create_file("reset", S_IFREG | S_IWUSR,
355 eth_debug.root, eth, &fops_eth_reset);
356 if (mt7530_exist(eth)) {
357 debugfs_create_file("mt7530sw_regs", S_IRUGO,
358 eth_debug.root, eth,
359 &mtketh_debug_mt7530sw_fops);
360 debugfs_create_file("mt7530sw_reg_w", S_IFREG | S_IWUSR,
361 eth_debug.root, eth,
362 &fops_mt7530sw_reg_w);
363 }
364 return ret;
365}
366
367void mii_mgr_read_combine(struct mtk_eth *eth, u32 phy_addr, u32 phy_register,
368 u32 *read_data)
369{
370 if (mt7530_exist(eth) && phy_addr == 31)
371 *read_data = mt7530_mdio_r32(eth, phy_register);
372
373 else
374 *read_data = _mtk_mdio_read(eth, phy_addr, phy_register);
375}
376
developer3957a912021-05-13 16:44:31 +0800377void mii_mgr_write_combine(struct mtk_eth *eth, u16 phy_addr, u16 phy_register,
developerfd40db22021-04-29 10:08:25 +0800378 u32 write_data)
379{
380 if (mt7530_exist(eth) && phy_addr == 31)
381 mt7530_mdio_w32(eth, phy_register, write_data);
382
383 else
384 _mtk_mdio_write(eth, phy_addr, phy_register, write_data);
385}
386
developer3957a912021-05-13 16:44:31 +0800387static void mii_mgr_read_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 *data)
developerfd40db22021-04-29 10:08:25 +0800388{
389 mtk_cl45_ind_read(eth, port, devad, reg, data);
390}
391
developer3957a912021-05-13 16:44:31 +0800392static void mii_mgr_write_cl45(struct mtk_eth *eth, u16 port, u16 devad, u16 reg, u16 data)
developerfd40db22021-04-29 10:08:25 +0800393{
394 mtk_cl45_ind_write(eth, port, devad, reg, data);
395}
396
397int mtk_do_priv_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
398{
399 struct mtk_mac *mac = netdev_priv(dev);
400 struct mtk_eth *eth = mac->hw;
401 struct mtk_mii_ioctl_data mii;
402 struct mtk_esw_reg reg;
developerba2d1eb2021-05-25 19:26:45 +0800403 u16 val;
developerfd40db22021-04-29 10:08:25 +0800404
405 switch (cmd) {
406 case MTKETH_MII_READ:
407 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
408 goto err_copy;
409 mii_mgr_read_combine(eth, mii.phy_id, mii.reg_num,
410 &mii.val_out);
411 if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
412 goto err_copy;
413
414 return 0;
415 case MTKETH_MII_WRITE:
416 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
417 goto err_copy;
418 mii_mgr_write_combine(eth, mii.phy_id, mii.reg_num,
419 mii.val_in);
developerfd40db22021-04-29 10:08:25 +0800420 return 0;
421 case MTKETH_MII_READ_CL45:
422 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
423 goto err_copy;
developer3957a912021-05-13 16:44:31 +0800424 mii_mgr_read_cl45(eth,
425 mdio_phy_id_prtad(mii.phy_id),
426 mdio_phy_id_devad(mii.phy_id),
427 mii.reg_num,
developerba2d1eb2021-05-25 19:26:45 +0800428 &val);
429 mii.val_out = val;
developerfd40db22021-04-29 10:08:25 +0800430 if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
431 goto err_copy;
432
433 return 0;
434 case MTKETH_MII_WRITE_CL45:
435 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
436 goto err_copy;
developerba2d1eb2021-05-25 19:26:45 +0800437 val = mii.val_in;
developer3957a912021-05-13 16:44:31 +0800438 mii_mgr_write_cl45(eth,
439 mdio_phy_id_prtad(mii.phy_id),
440 mdio_phy_id_devad(mii.phy_id),
441 mii.reg_num,
developerba2d1eb2021-05-25 19:26:45 +0800442 val);
developerfd40db22021-04-29 10:08:25 +0800443 return 0;
444 case MTKETH_ESW_REG_READ:
445 if (!mt7530_exist(eth))
446 return -EOPNOTSUPP;
447 if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
448 goto err_copy;
449 if (reg.off > REG_ESW_MAX)
450 return -EINVAL;
451 reg.val = mtk_switch_r32(eth, reg.off);
452
453 if (copy_to_user(ifr->ifr_data, &reg, sizeof(reg)))
454 goto err_copy;
455
456 return 0;
457 case MTKETH_ESW_REG_WRITE:
458 if (!mt7530_exist(eth))
459 return -EOPNOTSUPP;
460 if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
461 goto err_copy;
462 if (reg.off > REG_ESW_MAX)
463 return -EINVAL;
464 mtk_switch_w32(eth, reg.val, reg.off);
465
466 return 0;
467 default:
468 break;
469 }
470
471 return -EOPNOTSUPP;
472err_copy:
473 return -EFAULT;
474}
475
476int esw_cnt_read(struct seq_file *seq, void *v)
477{
478 unsigned int pkt_cnt = 0;
479 int i = 0;
480 struct mtk_eth *eth = g_eth;
481 unsigned int mib_base = MTK_GDM1_TX_GBCNT;
482
483 seq_puts(seq, "\n <<CPU>>\n");
484 seq_puts(seq, " |\n");
485 seq_puts(seq, "+-----------------------------------------------+\n");
486 seq_puts(seq, "| <<PSE>> |\n");
487 seq_puts(seq, "+-----------------------------------------------+\n");
488 seq_puts(seq, " |\n");
489 seq_puts(seq, "+-----------------------------------------------+\n");
490 seq_puts(seq, "| <<GDMA>> |\n");
491 seq_printf(seq, "| GDMA1_RX_GBCNT : %010u (Rx Good Bytes) |\n",
492 mtk_r32(eth, mib_base));
493 seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n",
494 mtk_r32(eth, mib_base+0x08));
495 seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error) |\n",
496 mtk_r32(eth, mib_base+0x10));
497 seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n",
498 mtk_r32(eth, mib_base+0x14));
499 seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n",
500 mtk_r32(eth, mib_base+0x18));
501 seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n",
502 mtk_r32(eth, mib_base+0x1C));
503 seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error) |\n",
504 mtk_r32(eth, mib_base+0x20));
505 seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n",
506 mtk_r32(eth, mib_base+0x24));
507 seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count) |\n",
508 mtk_r32(eth, mib_base+0x28));
509 seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count) |\n",
510 mtk_r32(eth, mib_base+0x2C));
511 seq_printf(seq, "| GDMA1_TX_GBCNT : %010u (Tx Good Bytes) |\n",
512 mtk_r32(eth, mib_base+0x30));
513 seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n",
514 mtk_r32(eth, mib_base+0x38));
515 seq_puts(seq, "| |\n");
516 seq_printf(seq, "| GDMA2_RX_GBCNT : %010u (Rx Good Bytes) |\n",
517 mtk_r32(eth, mib_base+0x40));
518 seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n",
519 mtk_r32(eth, mib_base+0x48));
520 seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error) |\n",
521 mtk_r32(eth, mib_base+0x50));
522 seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n",
523 mtk_r32(eth, mib_base+0x54));
524 seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n",
525 mtk_r32(eth, mib_base+0x58));
526 seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n",
527 mtk_r32(eth, mib_base+0x5C));
528 seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error) |\n",
529 mtk_r32(eth, mib_base+0x60));
530 seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n",
531 mtk_r32(eth, mib_base+0x64));
532 seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n",
533 mtk_r32(eth, mib_base+0x68));
534 seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n",
535 mtk_r32(eth, mib_base+0x6C));
536 seq_printf(seq, "| GDMA2_TX_GBCNT : %010u (Tx Good Bytes) |\n",
537 mtk_r32(eth, mib_base+0x70));
538 seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n",
539 mtk_r32(eth, mib_base+0x78));
540 seq_puts(seq, "+-----------------------------------------------+\n");
541
542 if (!mt7530_exist(eth))
543 return 0;
544
545#define DUMP_EACH_PORT(base) \
546 do { \
547 for (i = 0; i < 7; i++) { \
548 pkt_cnt = mt7530_mdio_r32(eth, (base) + (i * 0x100));\
549 seq_printf(seq, "%8u ", pkt_cnt); \
550 } \
551 seq_puts(seq, "\n"); \
552 } while (0)
553
554 seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n",
555 "Port0", "Port1", "Port2", "Port3", "Port4", "Port5",
556 "Port6");
557 seq_puts(seq, "Tx Drop Packet :");
558 DUMP_EACH_PORT(0x4000);
559 seq_puts(seq, "Tx CRC Error :");
560 DUMP_EACH_PORT(0x4004);
561 seq_puts(seq, "Tx Unicast Packet :");
562 DUMP_EACH_PORT(0x4008);
563 seq_puts(seq, "Tx Multicast Packet :");
564 DUMP_EACH_PORT(0x400C);
565 seq_puts(seq, "Tx Broadcast Packet :");
566 DUMP_EACH_PORT(0x4010);
567 seq_puts(seq, "Tx Collision Event :");
568 DUMP_EACH_PORT(0x4014);
569 seq_puts(seq, "Tx Pause Packet :");
570 DUMP_EACH_PORT(0x402C);
571 seq_puts(seq, "Rx Drop Packet :");
572 DUMP_EACH_PORT(0x4060);
573 seq_puts(seq, "Rx Filtering Packet :");
574 DUMP_EACH_PORT(0x4064);
575 seq_puts(seq, "Rx Unicast Packet :");
576 DUMP_EACH_PORT(0x4068);
577 seq_puts(seq, "Rx Multicast Packet :");
578 DUMP_EACH_PORT(0x406C);
579 seq_puts(seq, "Rx Broadcast Packet :");
580 DUMP_EACH_PORT(0x4070);
581 seq_puts(seq, "Rx Alignment Error :");
582 DUMP_EACH_PORT(0x4074);
583 seq_puts(seq, "Rx CRC Error :");
584 DUMP_EACH_PORT(0x4078);
585 seq_puts(seq, "Rx Undersize Error :");
586 DUMP_EACH_PORT(0x407C);
587 seq_puts(seq, "Rx Fragment Error :");
588 DUMP_EACH_PORT(0x4080);
589 seq_puts(seq, "Rx Oversize Error :");
590 DUMP_EACH_PORT(0x4084);
591 seq_puts(seq, "Rx Jabber Error :");
592 DUMP_EACH_PORT(0x4088);
593 seq_puts(seq, "Rx Pause Packet :");
594 DUMP_EACH_PORT(0x408C);
595 mt7530_mdio_w32(eth, 0x4fe0, 0xf0);
596 mt7530_mdio_w32(eth, 0x4fe0, 0x800000f0);
597
598 seq_puts(seq, "\n");
599
600 return 0;
601}
602
603static int switch_count_open(struct inode *inode, struct file *file)
604{
605 return single_open(file, esw_cnt_read, 0);
606}
607
608static const struct file_operations switch_count_fops = {
609 .owner = THIS_MODULE,
610 .open = switch_count_open,
611 .read = seq_read,
612 .llseek = seq_lseek,
613 .release = single_release
614};
615
616static struct proc_dir_entry *proc_tx_ring, *proc_rx_ring;
617
618int tx_ring_read(struct seq_file *seq, void *v)
619{
620 struct mtk_tx_ring *ring = &g_eth->tx_ring;
621 struct mtk_tx_dma *tx_ring;
622 int i = 0;
623
624 tx_ring =
625 kmalloc(sizeof(struct mtk_tx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
626 if (!tx_ring) {
627 seq_puts(seq, " allocate temp tx_ring fail.\n");
628 return 0;
629 }
630
631 for (i = 0; i < MTK_DMA_SIZE; i++)
632 tx_ring[i] = ring->dma[i];
633
634 seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count));
635 seq_printf(seq, "cpu next free: %d\n", (int)(ring->next_free - ring->dma));
636 seq_printf(seq, "cpu last free: %d\n", (int)(ring->last_free - ring->dma));
637 for (i = 0; i < MTK_DMA_SIZE; i++) {
638 dma_addr_t tmp = ring->phys + i * sizeof(*tx_ring);
639
640 seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &tmp,
641 *(int *)&tx_ring[i].txd1, *(int *)&tx_ring[i].txd2,
642 *(int *)&tx_ring[i].txd3, *(int *)&tx_ring[i].txd4);
643#if defined(CONFIG_MEDIATEK_NETSYS_V2)
644 seq_printf(seq, " %08x %08x %08x %08x",
645 *(int *)&tx_ring[i].txd5, *(int *)&tx_ring[i].txd6,
646 *(int *)&tx_ring[i].txd7, *(int *)&tx_ring[i].txd8);
647#endif
648 seq_printf(seq, "\n");
649 }
650
651 kfree(tx_ring);
652 return 0;
653}
654
655static int tx_ring_open(struct inode *inode, struct file *file)
656{
657 return single_open(file, tx_ring_read, NULL);
658}
659
660static const struct file_operations tx_ring_fops = {
661 .owner = THIS_MODULE,
662 .open = tx_ring_open,
663 .read = seq_read,
664 .llseek = seq_lseek,
665 .release = single_release
666};
667
668int rx_ring_read(struct seq_file *seq, void *v)
669{
670 struct mtk_rx_ring *ring = &g_eth->rx_ring[0];
671 struct mtk_rx_dma *rx_ring;
672
673 int i = 0;
674
675 rx_ring =
676 kmalloc(sizeof(struct mtk_rx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
677 if (!rx_ring) {
678 seq_puts(seq, " allocate temp rx_ring fail.\n");
679 return 0;
680 }
681
682 for (i = 0; i < MTK_DMA_SIZE; i++)
683 rx_ring[i] = ring->dma[i];
684
685 seq_printf(seq, "next to read: %d\n",
686 NEXT_DESP_IDX(ring->calc_idx, MTK_DMA_SIZE));
687 for (i = 0; i < MTK_DMA_SIZE; i++) {
688 seq_printf(seq, "%d: %08x %08x %08x %08x", i,
689 *(int *)&rx_ring[i].rxd1, *(int *)&rx_ring[i].rxd2,
690 *(int *)&rx_ring[i].rxd3, *(int *)&rx_ring[i].rxd4);
691#ifdef CONFIG_MEDIATEK_NETSYS_RX_V2
692 seq_printf(seq, " %08x %08x %08x %08x",
693 *(int *)&rx_ring[i].rxd5, *(int *)&rx_ring[i].rxd6,
694 *(int *)&rx_ring[i].rxd7, *(int *)&rx_ring[i].rxd8);
695#endif
696 seq_printf(seq, "\n");
697 }
698
699 kfree(rx_ring);
700 return 0;
701}
702
703static int rx_ring_open(struct inode *inode, struct file *file)
704{
705 return single_open(file, rx_ring_read, NULL);
706}
707
708static const struct file_operations rx_ring_fops = {
709 .owner = THIS_MODULE,
710 .open = rx_ring_open,
711 .read = seq_read,
712 .llseek = seq_lseek,
713 .release = single_release
714};
715
716int dbg_regs_read(struct seq_file *seq, void *v)
717{
718 struct mtk_eth *eth = g_eth;
719
720 seq_puts(seq, " <<PSE DEBUG REG DUMP>>\n");
721 seq_printf(seq, "| PSE_FQFC_CFG : %08x |\n",
722 mtk_r32(eth, MTK_PSE_FQFC_CFG));
723 seq_printf(seq, "| PSE_IQ_STA1 : %08x |\n",
724 mtk_r32(eth, MTK_PSE_IQ_STA(0)));
725 seq_printf(seq, "| PSE_IQ_STA2 : %08x |\n",
726 mtk_r32(eth, MTK_PSE_IQ_STA(1)));
727
728 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
729 seq_printf(seq, "| PSE_IQ_STA3 : %08x |\n",
730 mtk_r32(eth, MTK_PSE_IQ_STA(2)));
731 seq_printf(seq, "| PSE_IQ_STA4 : %08x |\n",
732 mtk_r32(eth, MTK_PSE_IQ_STA(3)));
733 }
734
735 seq_printf(seq, "| PSE_OQ_STA1 : %08x |\n",
736 mtk_r32(eth, MTK_PSE_OQ_STA(0)));
737 seq_printf(seq, "| PSE_OQ_STA2 : %08x |\n",
738 mtk_r32(eth, MTK_PSE_OQ_STA(1)));
739
740 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
741 seq_printf(seq, "| PSE_OQ_STA3 : %08x |\n",
742 mtk_r32(eth, MTK_PSE_OQ_STA(2)));
743 seq_printf(seq, "| PSE_OQ_STA4 : %08x |\n",
744 mtk_r32(eth, MTK_PSE_OQ_STA(3)));
745 }
746
747 seq_printf(seq, "| QDMA_FQ_CNT : %08x |\n",
748 mtk_r32(eth, MTK_QDMA_FQ_CNT));
749 seq_printf(seq, "| FE_PSE_FREE : %08x |\n",
750 mtk_r32(eth, MTK_FE_PSE_FREE));
751 seq_printf(seq, "| FE_DROP_FQ : %08x |\n",
752 mtk_r32(eth, MTK_FE_DROP_FQ));
753 seq_printf(seq, "| FE_DROP_FC : %08x |\n",
754 mtk_r32(eth, MTK_FE_DROP_FC));
755 seq_printf(seq, "| FE_DROP_PPE : %08x |\n",
756 mtk_r32(eth, MTK_FE_DROP_PPE));
757 seq_printf(seq, "| GDM1_IG_CTRL : %08x |\n",
758 mtk_r32(eth, MTK_GDMA_FWD_CFG(0)));
759 seq_printf(seq, "| GDM2_IG_CTRL : %08x |\n",
760 mtk_r32(eth, MTK_GDMA_FWD_CFG(1)));
761 seq_printf(seq, "| MAC_P1_MCR : %08x |\n",
762 mtk_r32(eth, MTK_MAC_MCR(0)));
763 seq_printf(seq, "| MAC_P2_MCR : %08x |\n",
764 mtk_r32(eth, MTK_MAC_MCR(1)));
765
766 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
767 seq_printf(seq, "| FE_CDM1_FSM : %08x |\n",
768 mtk_r32(eth, MTK_FE_CDM1_FSM));
769 seq_printf(seq, "| FE_CDM2_FSM : %08x |\n",
770 mtk_r32(eth, MTK_FE_CDM2_FSM));
771 seq_printf(seq, "| FE_GDM1_FSM : %08x |\n",
772 mtk_r32(eth, MTK_FE_GDM1_FSM));
773 seq_printf(seq, "| FE_GDM2_FSM : %08x |\n",
774 mtk_r32(eth, MTK_FE_GDM2_FSM));
775 }
776
777 return 0;
778}
779
780static int dbg_regs_open(struct inode *inode, struct file *file)
781{
782 return single_open(file, dbg_regs_read, 0);
783}
784
785static const struct file_operations dbg_regs_fops = {
786 .owner = THIS_MODULE,
787 .open = dbg_regs_open,
788 .read = seq_read,
789 .llseek = seq_lseek,
790 .release = single_release
791};
792
793#define PROCREG_ESW_CNT "esw_cnt"
794#define PROCREG_TXRING "tx_ring"
795#define PROCREG_RXRING "rx_ring"
796#define PROCREG_DIR "mtketh"
797#define PROCREG_DBG_REGS "dbg_regs"
798
799struct proc_dir_entry *proc_reg_dir;
800static struct proc_dir_entry *proc_esw_cnt, *proc_dbg_regs;
801
802int debug_proc_init(struct mtk_eth *eth)
803{
804 g_eth = eth;
805
806 if (!proc_reg_dir)
807 proc_reg_dir = proc_mkdir(PROCREG_DIR, NULL);
808
809 proc_tx_ring =
810 proc_create(PROCREG_TXRING, 0, proc_reg_dir, &tx_ring_fops);
811 if (!proc_tx_ring)
812 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_TXRING);
813
814 proc_rx_ring =
815 proc_create(PROCREG_RXRING, 0, proc_reg_dir, &rx_ring_fops);
816 if (!proc_rx_ring)
817 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_RXRING);
818
819 proc_esw_cnt =
820 proc_create(PROCREG_ESW_CNT, 0, proc_reg_dir, &switch_count_fops);
821 if (!proc_esw_cnt)
822 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
823
824 proc_dbg_regs =
825 proc_create(PROCREG_DBG_REGS, 0, proc_reg_dir, &dbg_regs_fops);
826 if (!proc_dbg_regs)
827 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS);
828
829 return 0;
830}
831
832void debug_proc_exit(void)
833{
834 if (proc_tx_ring)
835 remove_proc_entry(PROCREG_TXRING, proc_reg_dir);
836 if (proc_rx_ring)
837 remove_proc_entry(PROCREG_RXRING, proc_reg_dir);
838
839 if (proc_esw_cnt)
840 remove_proc_entry(PROCREG_ESW_CNT, proc_reg_dir);
841
842 if (proc_reg_dir)
843 remove_proc_entry(PROCREG_DIR, 0);
844
845 if (proc_dbg_regs)
846 remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir);
847}
848