blob: ab5e1f804e5e217a321c5365029d1f7e9520b690 [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;
403
404 switch (cmd) {
405 case MTKETH_MII_READ:
406 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
407 goto err_copy;
408 mii_mgr_read_combine(eth, mii.phy_id, mii.reg_num,
409 &mii.val_out);
410 if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
411 goto err_copy;
412
413 return 0;
414 case MTKETH_MII_WRITE:
415 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
416 goto err_copy;
417 mii_mgr_write_combine(eth, mii.phy_id, mii.reg_num,
418 mii.val_in);
developerfd40db22021-04-29 10:08:25 +0800419 return 0;
420 case MTKETH_MII_READ_CL45:
421 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
422 goto err_copy;
developer3957a912021-05-13 16:44:31 +0800423 mii_mgr_read_cl45(eth,
424 mdio_phy_id_prtad(mii.phy_id),
425 mdio_phy_id_devad(mii.phy_id),
426 mii.reg_num,
developerfd40db22021-04-29 10:08:25 +0800427 &mii.val_out);
428 if (copy_to_user(ifr->ifr_data, &mii, sizeof(mii)))
429 goto err_copy;
430
431 return 0;
432 case MTKETH_MII_WRITE_CL45:
433 if (copy_from_user(&mii, ifr->ifr_data, sizeof(mii)))
434 goto err_copy;
developer3957a912021-05-13 16:44:31 +0800435 mii_mgr_write_cl45(eth,
436 mdio_phy_id_prtad(mii.phy_id),
437 mdio_phy_id_devad(mii.phy_id),
438 mii.reg_num,
439 mii.val_in);
developerfd40db22021-04-29 10:08:25 +0800440 return 0;
441 case MTKETH_ESW_REG_READ:
442 if (!mt7530_exist(eth))
443 return -EOPNOTSUPP;
444 if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
445 goto err_copy;
446 if (reg.off > REG_ESW_MAX)
447 return -EINVAL;
448 reg.val = mtk_switch_r32(eth, reg.off);
449
450 if (copy_to_user(ifr->ifr_data, &reg, sizeof(reg)))
451 goto err_copy;
452
453 return 0;
454 case MTKETH_ESW_REG_WRITE:
455 if (!mt7530_exist(eth))
456 return -EOPNOTSUPP;
457 if (copy_from_user(&reg, ifr->ifr_data, sizeof(reg)))
458 goto err_copy;
459 if (reg.off > REG_ESW_MAX)
460 return -EINVAL;
461 mtk_switch_w32(eth, reg.val, reg.off);
462
463 return 0;
464 default:
465 break;
466 }
467
468 return -EOPNOTSUPP;
469err_copy:
470 return -EFAULT;
471}
472
473int esw_cnt_read(struct seq_file *seq, void *v)
474{
475 unsigned int pkt_cnt = 0;
476 int i = 0;
477 struct mtk_eth *eth = g_eth;
478 unsigned int mib_base = MTK_GDM1_TX_GBCNT;
479
480 seq_puts(seq, "\n <<CPU>>\n");
481 seq_puts(seq, " |\n");
482 seq_puts(seq, "+-----------------------------------------------+\n");
483 seq_puts(seq, "| <<PSE>> |\n");
484 seq_puts(seq, "+-----------------------------------------------+\n");
485 seq_puts(seq, " |\n");
486 seq_puts(seq, "+-----------------------------------------------+\n");
487 seq_puts(seq, "| <<GDMA>> |\n");
488 seq_printf(seq, "| GDMA1_RX_GBCNT : %010u (Rx Good Bytes) |\n",
489 mtk_r32(eth, mib_base));
490 seq_printf(seq, "| GDMA1_RX_GPCNT : %010u (Rx Good Pkts) |\n",
491 mtk_r32(eth, mib_base+0x08));
492 seq_printf(seq, "| GDMA1_RX_OERCNT : %010u (overflow error) |\n",
493 mtk_r32(eth, mib_base+0x10));
494 seq_printf(seq, "| GDMA1_RX_FERCNT : %010u (FCS error) |\n",
495 mtk_r32(eth, mib_base+0x14));
496 seq_printf(seq, "| GDMA1_RX_SERCNT : %010u (too short) |\n",
497 mtk_r32(eth, mib_base+0x18));
498 seq_printf(seq, "| GDMA1_RX_LERCNT : %010u (too long) |\n",
499 mtk_r32(eth, mib_base+0x1C));
500 seq_printf(seq, "| GDMA1_RX_CERCNT : %010u (checksum error) |\n",
501 mtk_r32(eth, mib_base+0x20));
502 seq_printf(seq, "| GDMA1_RX_FCCNT : %010u (flow control) |\n",
503 mtk_r32(eth, mib_base+0x24));
504 seq_printf(seq, "| GDMA1_TX_SKIPCNT: %010u (about count) |\n",
505 mtk_r32(eth, mib_base+0x28));
506 seq_printf(seq, "| GDMA1_TX_COLCNT : %010u (collision count) |\n",
507 mtk_r32(eth, mib_base+0x2C));
508 seq_printf(seq, "| GDMA1_TX_GBCNT : %010u (Tx Good Bytes) |\n",
509 mtk_r32(eth, mib_base+0x30));
510 seq_printf(seq, "| GDMA1_TX_GPCNT : %010u (Tx Good Pkts) |\n",
511 mtk_r32(eth, mib_base+0x38));
512 seq_puts(seq, "| |\n");
513 seq_printf(seq, "| GDMA2_RX_GBCNT : %010u (Rx Good Bytes) |\n",
514 mtk_r32(eth, mib_base+0x40));
515 seq_printf(seq, "| GDMA2_RX_GPCNT : %010u (Rx Good Pkts) |\n",
516 mtk_r32(eth, mib_base+0x48));
517 seq_printf(seq, "| GDMA2_RX_OERCNT : %010u (overflow error) |\n",
518 mtk_r32(eth, mib_base+0x50));
519 seq_printf(seq, "| GDMA2_RX_FERCNT : %010u (FCS error) |\n",
520 mtk_r32(eth, mib_base+0x54));
521 seq_printf(seq, "| GDMA2_RX_SERCNT : %010u (too short) |\n",
522 mtk_r32(eth, mib_base+0x58));
523 seq_printf(seq, "| GDMA2_RX_LERCNT : %010u (too long) |\n",
524 mtk_r32(eth, mib_base+0x5C));
525 seq_printf(seq, "| GDMA2_RX_CERCNT : %010u (checksum error) |\n",
526 mtk_r32(eth, mib_base+0x60));
527 seq_printf(seq, "| GDMA2_RX_FCCNT : %010u (flow control) |\n",
528 mtk_r32(eth, mib_base+0x64));
529 seq_printf(seq, "| GDMA2_TX_SKIPCNT: %010u (skip) |\n",
530 mtk_r32(eth, mib_base+0x68));
531 seq_printf(seq, "| GDMA2_TX_COLCNT : %010u (collision) |\n",
532 mtk_r32(eth, mib_base+0x6C));
533 seq_printf(seq, "| GDMA2_TX_GBCNT : %010u (Tx Good Bytes) |\n",
534 mtk_r32(eth, mib_base+0x70));
535 seq_printf(seq, "| GDMA2_TX_GPCNT : %010u (Tx Good Pkts) |\n",
536 mtk_r32(eth, mib_base+0x78));
537 seq_puts(seq, "+-----------------------------------------------+\n");
538
539 if (!mt7530_exist(eth))
540 return 0;
541
542#define DUMP_EACH_PORT(base) \
543 do { \
544 for (i = 0; i < 7; i++) { \
545 pkt_cnt = mt7530_mdio_r32(eth, (base) + (i * 0x100));\
546 seq_printf(seq, "%8u ", pkt_cnt); \
547 } \
548 seq_puts(seq, "\n"); \
549 } while (0)
550
551 seq_printf(seq, "===================== %8s %8s %8s %8s %8s %8s %8s\n",
552 "Port0", "Port1", "Port2", "Port3", "Port4", "Port5",
553 "Port6");
554 seq_puts(seq, "Tx Drop Packet :");
555 DUMP_EACH_PORT(0x4000);
556 seq_puts(seq, "Tx CRC Error :");
557 DUMP_EACH_PORT(0x4004);
558 seq_puts(seq, "Tx Unicast Packet :");
559 DUMP_EACH_PORT(0x4008);
560 seq_puts(seq, "Tx Multicast Packet :");
561 DUMP_EACH_PORT(0x400C);
562 seq_puts(seq, "Tx Broadcast Packet :");
563 DUMP_EACH_PORT(0x4010);
564 seq_puts(seq, "Tx Collision Event :");
565 DUMP_EACH_PORT(0x4014);
566 seq_puts(seq, "Tx Pause Packet :");
567 DUMP_EACH_PORT(0x402C);
568 seq_puts(seq, "Rx Drop Packet :");
569 DUMP_EACH_PORT(0x4060);
570 seq_puts(seq, "Rx Filtering Packet :");
571 DUMP_EACH_PORT(0x4064);
572 seq_puts(seq, "Rx Unicast Packet :");
573 DUMP_EACH_PORT(0x4068);
574 seq_puts(seq, "Rx Multicast Packet :");
575 DUMP_EACH_PORT(0x406C);
576 seq_puts(seq, "Rx Broadcast Packet :");
577 DUMP_EACH_PORT(0x4070);
578 seq_puts(seq, "Rx Alignment Error :");
579 DUMP_EACH_PORT(0x4074);
580 seq_puts(seq, "Rx CRC Error :");
581 DUMP_EACH_PORT(0x4078);
582 seq_puts(seq, "Rx Undersize Error :");
583 DUMP_EACH_PORT(0x407C);
584 seq_puts(seq, "Rx Fragment Error :");
585 DUMP_EACH_PORT(0x4080);
586 seq_puts(seq, "Rx Oversize Error :");
587 DUMP_EACH_PORT(0x4084);
588 seq_puts(seq, "Rx Jabber Error :");
589 DUMP_EACH_PORT(0x4088);
590 seq_puts(seq, "Rx Pause Packet :");
591 DUMP_EACH_PORT(0x408C);
592 mt7530_mdio_w32(eth, 0x4fe0, 0xf0);
593 mt7530_mdio_w32(eth, 0x4fe0, 0x800000f0);
594
595 seq_puts(seq, "\n");
596
597 return 0;
598}
599
600static int switch_count_open(struct inode *inode, struct file *file)
601{
602 return single_open(file, esw_cnt_read, 0);
603}
604
605static const struct file_operations switch_count_fops = {
606 .owner = THIS_MODULE,
607 .open = switch_count_open,
608 .read = seq_read,
609 .llseek = seq_lseek,
610 .release = single_release
611};
612
613static struct proc_dir_entry *proc_tx_ring, *proc_rx_ring;
614
615int tx_ring_read(struct seq_file *seq, void *v)
616{
617 struct mtk_tx_ring *ring = &g_eth->tx_ring;
618 struct mtk_tx_dma *tx_ring;
619 int i = 0;
620
621 tx_ring =
622 kmalloc(sizeof(struct mtk_tx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
623 if (!tx_ring) {
624 seq_puts(seq, " allocate temp tx_ring fail.\n");
625 return 0;
626 }
627
628 for (i = 0; i < MTK_DMA_SIZE; i++)
629 tx_ring[i] = ring->dma[i];
630
631 seq_printf(seq, "free count = %d\n", (int)atomic_read(&ring->free_count));
632 seq_printf(seq, "cpu next free: %d\n", (int)(ring->next_free - ring->dma));
633 seq_printf(seq, "cpu last free: %d\n", (int)(ring->last_free - ring->dma));
634 for (i = 0; i < MTK_DMA_SIZE; i++) {
635 dma_addr_t tmp = ring->phys + i * sizeof(*tx_ring);
636
637 seq_printf(seq, "%d (%pad): %08x %08x %08x %08x", i, &tmp,
638 *(int *)&tx_ring[i].txd1, *(int *)&tx_ring[i].txd2,
639 *(int *)&tx_ring[i].txd3, *(int *)&tx_ring[i].txd4);
640#if defined(CONFIG_MEDIATEK_NETSYS_V2)
641 seq_printf(seq, " %08x %08x %08x %08x",
642 *(int *)&tx_ring[i].txd5, *(int *)&tx_ring[i].txd6,
643 *(int *)&tx_ring[i].txd7, *(int *)&tx_ring[i].txd8);
644#endif
645 seq_printf(seq, "\n");
646 }
647
648 kfree(tx_ring);
649 return 0;
650}
651
652static int tx_ring_open(struct inode *inode, struct file *file)
653{
654 return single_open(file, tx_ring_read, NULL);
655}
656
657static const struct file_operations tx_ring_fops = {
658 .owner = THIS_MODULE,
659 .open = tx_ring_open,
660 .read = seq_read,
661 .llseek = seq_lseek,
662 .release = single_release
663};
664
665int rx_ring_read(struct seq_file *seq, void *v)
666{
667 struct mtk_rx_ring *ring = &g_eth->rx_ring[0];
668 struct mtk_rx_dma *rx_ring;
669
670 int i = 0;
671
672 rx_ring =
673 kmalloc(sizeof(struct mtk_rx_dma) * MTK_DMA_SIZE, GFP_KERNEL);
674 if (!rx_ring) {
675 seq_puts(seq, " allocate temp rx_ring fail.\n");
676 return 0;
677 }
678
679 for (i = 0; i < MTK_DMA_SIZE; i++)
680 rx_ring[i] = ring->dma[i];
681
682 seq_printf(seq, "next to read: %d\n",
683 NEXT_DESP_IDX(ring->calc_idx, MTK_DMA_SIZE));
684 for (i = 0; i < MTK_DMA_SIZE; i++) {
685 seq_printf(seq, "%d: %08x %08x %08x %08x", i,
686 *(int *)&rx_ring[i].rxd1, *(int *)&rx_ring[i].rxd2,
687 *(int *)&rx_ring[i].rxd3, *(int *)&rx_ring[i].rxd4);
688#ifdef CONFIG_MEDIATEK_NETSYS_RX_V2
689 seq_printf(seq, " %08x %08x %08x %08x",
690 *(int *)&rx_ring[i].rxd5, *(int *)&rx_ring[i].rxd6,
691 *(int *)&rx_ring[i].rxd7, *(int *)&rx_ring[i].rxd8);
692#endif
693 seq_printf(seq, "\n");
694 }
695
696 kfree(rx_ring);
697 return 0;
698}
699
700static int rx_ring_open(struct inode *inode, struct file *file)
701{
702 return single_open(file, rx_ring_read, NULL);
703}
704
705static const struct file_operations rx_ring_fops = {
706 .owner = THIS_MODULE,
707 .open = rx_ring_open,
708 .read = seq_read,
709 .llseek = seq_lseek,
710 .release = single_release
711};
712
713int dbg_regs_read(struct seq_file *seq, void *v)
714{
715 struct mtk_eth *eth = g_eth;
716
717 seq_puts(seq, " <<PSE DEBUG REG DUMP>>\n");
718 seq_printf(seq, "| PSE_FQFC_CFG : %08x |\n",
719 mtk_r32(eth, MTK_PSE_FQFC_CFG));
720 seq_printf(seq, "| PSE_IQ_STA1 : %08x |\n",
721 mtk_r32(eth, MTK_PSE_IQ_STA(0)));
722 seq_printf(seq, "| PSE_IQ_STA2 : %08x |\n",
723 mtk_r32(eth, MTK_PSE_IQ_STA(1)));
724
725 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
726 seq_printf(seq, "| PSE_IQ_STA3 : %08x |\n",
727 mtk_r32(eth, MTK_PSE_IQ_STA(2)));
728 seq_printf(seq, "| PSE_IQ_STA4 : %08x |\n",
729 mtk_r32(eth, MTK_PSE_IQ_STA(3)));
730 }
731
732 seq_printf(seq, "| PSE_OQ_STA1 : %08x |\n",
733 mtk_r32(eth, MTK_PSE_OQ_STA(0)));
734 seq_printf(seq, "| PSE_OQ_STA2 : %08x |\n",
735 mtk_r32(eth, MTK_PSE_OQ_STA(1)));
736
737 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
738 seq_printf(seq, "| PSE_OQ_STA3 : %08x |\n",
739 mtk_r32(eth, MTK_PSE_OQ_STA(2)));
740 seq_printf(seq, "| PSE_OQ_STA4 : %08x |\n",
741 mtk_r32(eth, MTK_PSE_OQ_STA(3)));
742 }
743
744 seq_printf(seq, "| QDMA_FQ_CNT : %08x |\n",
745 mtk_r32(eth, MTK_QDMA_FQ_CNT));
746 seq_printf(seq, "| FE_PSE_FREE : %08x |\n",
747 mtk_r32(eth, MTK_FE_PSE_FREE));
748 seq_printf(seq, "| FE_DROP_FQ : %08x |\n",
749 mtk_r32(eth, MTK_FE_DROP_FQ));
750 seq_printf(seq, "| FE_DROP_FC : %08x |\n",
751 mtk_r32(eth, MTK_FE_DROP_FC));
752 seq_printf(seq, "| FE_DROP_PPE : %08x |\n",
753 mtk_r32(eth, MTK_FE_DROP_PPE));
754 seq_printf(seq, "| GDM1_IG_CTRL : %08x |\n",
755 mtk_r32(eth, MTK_GDMA_FWD_CFG(0)));
756 seq_printf(seq, "| GDM2_IG_CTRL : %08x |\n",
757 mtk_r32(eth, MTK_GDMA_FWD_CFG(1)));
758 seq_printf(seq, "| MAC_P1_MCR : %08x |\n",
759 mtk_r32(eth, MTK_MAC_MCR(0)));
760 seq_printf(seq, "| MAC_P2_MCR : %08x |\n",
761 mtk_r32(eth, MTK_MAC_MCR(1)));
762
763 if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_TX_V2)) {
764 seq_printf(seq, "| FE_CDM1_FSM : %08x |\n",
765 mtk_r32(eth, MTK_FE_CDM1_FSM));
766 seq_printf(seq, "| FE_CDM2_FSM : %08x |\n",
767 mtk_r32(eth, MTK_FE_CDM2_FSM));
768 seq_printf(seq, "| FE_GDM1_FSM : %08x |\n",
769 mtk_r32(eth, MTK_FE_GDM1_FSM));
770 seq_printf(seq, "| FE_GDM2_FSM : %08x |\n",
771 mtk_r32(eth, MTK_FE_GDM2_FSM));
772 }
773
774 return 0;
775}
776
777static int dbg_regs_open(struct inode *inode, struct file *file)
778{
779 return single_open(file, dbg_regs_read, 0);
780}
781
782static const struct file_operations dbg_regs_fops = {
783 .owner = THIS_MODULE,
784 .open = dbg_regs_open,
785 .read = seq_read,
786 .llseek = seq_lseek,
787 .release = single_release
788};
789
790#define PROCREG_ESW_CNT "esw_cnt"
791#define PROCREG_TXRING "tx_ring"
792#define PROCREG_RXRING "rx_ring"
793#define PROCREG_DIR "mtketh"
794#define PROCREG_DBG_REGS "dbg_regs"
795
796struct proc_dir_entry *proc_reg_dir;
797static struct proc_dir_entry *proc_esw_cnt, *proc_dbg_regs;
798
799int debug_proc_init(struct mtk_eth *eth)
800{
801 g_eth = eth;
802
803 if (!proc_reg_dir)
804 proc_reg_dir = proc_mkdir(PROCREG_DIR, NULL);
805
806 proc_tx_ring =
807 proc_create(PROCREG_TXRING, 0, proc_reg_dir, &tx_ring_fops);
808 if (!proc_tx_ring)
809 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_TXRING);
810
811 proc_rx_ring =
812 proc_create(PROCREG_RXRING, 0, proc_reg_dir, &rx_ring_fops);
813 if (!proc_rx_ring)
814 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_RXRING);
815
816 proc_esw_cnt =
817 proc_create(PROCREG_ESW_CNT, 0, proc_reg_dir, &switch_count_fops);
818 if (!proc_esw_cnt)
819 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_ESW_CNT);
820
821 proc_dbg_regs =
822 proc_create(PROCREG_DBG_REGS, 0, proc_reg_dir, &dbg_regs_fops);
823 if (!proc_dbg_regs)
824 pr_notice("!! FAIL to create %s PROC !!\n", PROCREG_DBG_REGS);
825
826 return 0;
827}
828
829void debug_proc_exit(void)
830{
831 if (proc_tx_ring)
832 remove_proc_entry(PROCREG_TXRING, proc_reg_dir);
833 if (proc_rx_ring)
834 remove_proc_entry(PROCREG_RXRING, proc_reg_dir);
835
836 if (proc_esw_cnt)
837 remove_proc_entry(PROCREG_ESW_CNT, proc_reg_dir);
838
839 if (proc_reg_dir)
840 remove_proc_entry(PROCREG_DIR, 0);
841
842 if (proc_dbg_regs)
843 remove_proc_entry(PROCREG_DBG_REGS, proc_reg_dir);
844}
845