blob: c7e3dd1d87b0e8ead4f6e96912e38ece6edd153b [file] [log] [blame]
Vivien Didelotcb8e9802018-12-18 14:06:35 -05001#include <stdio.h>
2#include <string.h>
3
4#include "internal.h"
5
Vivien Didelotff99e462018-12-18 14:06:36 -05006/* Macros and dump functions for the 16-bit mv88e6xxx per-port registers */
7
8#define REG(_reg, _name, _val) \
9 printf("%.02u: %-38.38s 0x%.4x\n", _reg, _name, _val)
10
11#define FIELD(_name, _fmt, ...) \
12 printf(" %-36.36s " _fmt "\n", _name, ##__VA_ARGS__)
13
14#define FIELD_BITMAP(_name, _val) \
15 FIELD(_name, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", \
16 ((_val) & 0x0001) ? "0 " : "", \
17 ((_val) & 0x0002) ? "1 " : "", \
18 ((_val) & 0x0004) ? "2 " : "", \
19 ((_val) & 0x0008) ? "3 " : "", \
20 ((_val) & 0x0010) ? "4 " : "", \
21 ((_val) & 0x0020) ? "5 " : "", \
22 ((_val) & 0x0040) ? "6 " : "", \
23 ((_val) & 0x0080) ? "7 " : "", \
24 ((_val) & 0x0100) ? "8 " : "", \
25 ((_val) & 0x0200) ? "9 " : "", \
26 ((_val) & 0x0400) ? "10 " : "", \
27 ((_val) & 0x0800) ? "11 " : "", \
28 ((_val) & 0x1000) ? "12 " : "", \
29 ((_val) & 0x2000) ? "13 " : "", \
30 ((_val) & 0x4000) ? "14 " : "", \
31 ((_val) & 0x8000) ? "15 " : "")
32
Vivien Didelot4e980292018-12-18 14:06:37 -050033static void dsa_mv88e6185(int reg, u16 val)
34{
35 switch (reg) {
36 case 0:
37 REG(reg, "Port Status", val);
38 break;
39 case 1:
40 REG(reg, "PCS Control", val);
41 break;
42 case 3:
43 REG(reg, "Switch Identifier", val);
44 break;
45 case 4:
46 REG(reg, "Port Control", val);
47 break;
48 case 5:
49 REG(reg, "Port Control 1", val);
50 break;
51 case 6:
52 REG(reg, "Port Base VLAN Map (Header)", val);
53 break;
54 case 7:
55 REG(reg, "Default VLAN ID & Priority", val);
56 break;
57 case 8:
58 REG(reg, "Port Control 2", val);
59 break;
60 case 9:
61 REG(reg, "Rate Control", val);
62 break;
63 case 10:
64 REG(reg, "Rate Control 2", val);
65 break;
66 case 11:
67 REG(reg, "Port Association Vector", val);
68 break;
69 case 16:
70 REG(reg, "InDiscardsLo Frame Counter", val);
71 break;
72 case 17:
73 REG(reg, "InDiscardsHi Frame Counter", val);
74 break;
75 case 18:
76 REG(reg, "InFiltered Frame Counter", val);
77 break;
78 case 19:
79 REG(reg, "OutFiltered Frame Counter", val);
80 break;
81 case 24:
82 REG(reg, "Tag Remap 0-3", val);
83 break;
84 case 25:
85 REG(reg, "Tag Remap 4-7", val);
86 break;
87 default:
88 REG(reg, "Reserved", val);
89 break;
90 }
91};
92
Vivien Didelotff99e462018-12-18 14:06:36 -050093struct dsa_mv88e6xxx_switch {
94 void (*dump)(int reg, u16 val);
95 const char *name;
96 u16 id;
97};
98
99static const struct dsa_mv88e6xxx_switch dsa_mv88e6xxx_switches[] = {
Vivien Didelot4e980292018-12-18 14:06:37 -0500100 { .id = 0x1a70, .name = "88E6185 ", .dump = dsa_mv88e6185 },
Vivien Didelotff99e462018-12-18 14:06:36 -0500101};
102
103static int dsa_mv88e6xxx_dump_regs(struct ethtool_regs *regs)
104{
105 const struct dsa_mv88e6xxx_switch *sw = NULL;
106 const u16 *data = (u16 *)regs->data;
107 u16 id;
108 int i;
109
110 /* Marvell chips have 32 per-port 16-bit registers */
111 if (regs->len < 32 * 2)
112 return 1;
113
114 id = regs->version & 0xfff0;
115
116 for (i = 0; i < ARRAY_SIZE(dsa_mv88e6xxx_switches); i++) {
117 if (id == dsa_mv88e6xxx_switches[i].id) {
118 sw = &dsa_mv88e6xxx_switches[i];
119 break;
120 }
121 }
122
123 if (!sw)
124 return 1;
125
126 printf("%s Switch Port Registers\n", sw->name);
127 printf("------------------------------\n");
128
129 for (i = 0; i < 32; i++)
130 if (sw->dump)
131 sw->dump(i, data[i]);
132 else
133 REG(i, "", data[i]);
134
135 return 0;
136}
137
138#undef FIELD_BITMAP
139#undef FIELD
140#undef REG
141
Vivien Didelotcb8e9802018-12-18 14:06:35 -0500142int dsa_dump_regs(struct ethtool_drvinfo *info, struct ethtool_regs *regs)
143{
144 /* DSA per-driver register dump */
Vivien Didelotff99e462018-12-18 14:06:36 -0500145 if (!dsa_mv88e6xxx_dump_regs(regs))
146 return 0;
Vivien Didelotcb8e9802018-12-18 14:06:35 -0500147
148 /* Fallback to hexdump */
149 return 1;
150}