1 /*
2 * Copyright (c) 2004, 2005 Zultys Technologies
3 * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
4 */
5 #include <stdio.h>
6 #include <stdint.h>
7 #include <stddef.h>
8
9 #include "internal.h"
10
11 /* Ethtool get_regs complex data.
12 * we want to get not just EMAC registers, but also MAL, ZMII, RGMII, TAH
13 * when available.
14 *
15 * Returned BLOB consists of the ibm_emac_ethtool_regs_hdr,
16 * MAL registers, EMAC registers and optional ZMII, RGMII, TAH registers.
17 * Each register component is preceded with emac_ethtool_regs_subhdr.
18 * Order of the optional headers follows their relative bit posititions
19 * in emac_ethtool_regs_hdr.components
20 */
21 #define EMAC_ETHTOOL_REGS_ZMII 0x00000001
22 #define EMAC_ETHTOOL_REGS_RGMII 0x00000002
23 #define EMAC_ETHTOOL_REGS_TAH 0x00000004
24
25 #define EMAC_VERSION 3
26 #define EMAC4_VERSION 4
27 #define EMAC4SYNC_VERSION 5
28
29 struct emac_ethtool_regs_hdr {
30 u32 components;
31 };
32
33 struct emac_ethtool_regs_subhdr {
34 u32 version;
35 u32 index;
36 };
37
38 struct emac_regs {
39 /* Common registers across all EMAC implementations. */
40 u32 mr0; /* Special */
41 u32 mr1; /* Reset */
42 u32 tmr0; /* Special */
43 u32 tmr1; /* Special */
44 u32 rmr; /* Reset */
45 u32 isr; /* Always */
46 u32 iser; /* Reset */
47 u32 iahr; /* Reset, R, T */
48 u32 ialr; /* Reset, R, T */
49 u32 vtpid; /* Reset, R, T */
50 u32 vtci; /* Reset, R, T */
51 u32 ptr; /* Reset, T */
52 union {
53 /* Registers unique to EMAC4 implementations */
54 struct {
55 u32 iaht1; /* Reset, R */
56 u32 iaht2; /* Reset, R */
57 u32 iaht3; /* Reset, R */
58 u32 iaht4; /* Reset, R */
59 u32 gaht1; /* Reset, R */
60 u32 gaht2; /* Reset, R */
61 u32 gaht3; /* Reset, R */
62 u32 gaht4; /* Reset, R */
63 } emac4;
64 /* Registers unique to EMAC4SYNC implementations */
65 struct {
66 u32 mahr; /* Reset, R, T */
67 u32 malr; /* Reset, R, T */
68 u32 mmahr; /* Reset, R, T */
69 u32 mmalr; /* Reset, R, T */
70 u32 rsvd0[4];
71 } emac4sync;
72 } u0;
73 /* Common registers across all EMAC implementations. */
74 u32 lsah;
75 u32 lsal;
76 u32 ipgvr; /* Reset, T */
77 u32 stacr; /* Special */
78 u32 trtr; /* Special */
79 u32 rwmr; /* Reset */
80 u32 octx;
81 u32 ocrx;
82 union {
83 /* Registers unique to EMAC4 implementations */
84 struct {
85 u32 ipcr;
86 } emac4;
87 /* Registers unique to EMAC4SYNC implementations */
88 struct {
89 u32 rsvd1;
90 u32 revid;
91 u32 rsvd2[2];
92 u32 iaht1; /* Reset, R */
93 u32 iaht2; /* Reset, R */
94 u32 iaht3; /* Reset, R */
95 u32 iaht4; /* Reset, R */
96 u32 iaht5; /* Reset, R */
97 u32 iaht6; /* Reset, R */
98 u32 iaht7; /* Reset, R */
99 u32 iaht8; /* Reset, R */
100 u32 gaht1; /* Reset, R */
101 u32 gaht2; /* Reset, R */
102 u32 gaht3; /* Reset, R */
103 u32 gaht4; /* Reset, R */
104 u32 gaht5; /* Reset, R */
105 u32 gaht6; /* Reset, R */
106 u32 gaht7; /* Reset, R */
107 u32 gaht8; /* Reset, R */
108 u32 tpc; /* Reset, T */
109 } emac4sync;
110 } u1;
111 };
112
113 struct mal_regs {
114 u32 tx_count;
115 u32 rx_count;
116
117 u32 cfg;
118 u32 esr;
119 u32 ier;
120 u32 tx_casr;
121 u32 tx_carr;
122 u32 tx_eobisr;
123 u32 tx_deir;
124 u32 rx_casr;
125 u32 rx_carr;
126 u32 rx_eobisr;
127 u32 rx_deir;
128 u32 tx_ctpr[32];
129 u32 rx_ctpr[32];
130 u32 rcbs[32];
131 };
132
133 struct zmii_regs {
134 u32 fer;
135 u32 ssr;
136 u32 smiisr;
137 };
138
139 struct rgmii_regs {
140 u32 fer;
141 u32 ssr;
142 };
143
144 struct tah_regs {
145 u32 revid;
146 u32 pad[3];
147 u32 mr;
148 u32 ssr0;
149 u32 ssr1;
150 u32 ssr2;
151 u32 ssr3;
152 u32 ssr4;
153 u32 ssr5;
154 u32 tsr;
155 };
156
print_emac_regs(void * buf)157 static void *print_emac_regs(void *buf)
158 {
159 struct emac_ethtool_regs_subhdr *hdr = buf;
160 struct emac_regs *p = (struct emac_regs *)(hdr + 1);
161 void *res = p + 1;
162
163 if (!((hdr->version == EMAC_VERSION) ||
164 (hdr->version == EMAC4_VERSION) ||
165 (hdr->version == EMAC4SYNC_VERSION)))
166 {
167 printf("This driver version doesn't support information\n"
168 " output for EMAC area, please update it or use older\n"
169 " ethtool version\n");
170 return res;
171 }
172
173 printf("EMAC%d Registers\n", hdr->index);
174 printf("-----------------\n");
175 printf("MR0 = 0x%08x MR1 = 0x%08x RMR = 0x%08x\n"
176 "ISR = 0x%08x ISER = 0x%08x\n"
177 "TMR0 = 0x%08x TMR1 = 0x%08x\n"
178 "TRTR = 0x%08x RWMR = 0x%08x\n"
179 "IAR = %04x%08x\n"
180 "LSA = %04x%08x\n"
181 "VTPID = 0x%04x VTCI = 0x%04x\n"
182 "IPGVR = 0x%04x STACR = 0x%08x\n"
183 "OCTX = 0x%08x OCRX = 0x%08x\n",
184 p->mr0, p->mr1, p->rmr,
185 p->isr, p->iser,
186 p->tmr0, p->tmr1,
187 p->trtr, p->rwmr,
188 p->iahr, p->ialr,
189 p->lsah, p->lsal,
190 p->vtpid, p->vtci,
191 p->ipgvr, p->stacr, p->octx, p->ocrx);
192
193 if (hdr->version == EMAC4SYNC_VERSION) {
194 printf("MAHR = 0x%08x MALR = 0x%08x MMAHR = 0x%08x\n"
195 "MMALR = 0x%08x REVID = 0x%08x\n",
196 p->u0.emac4sync.mahr, p->u0.emac4sync.malr,
197 p->u0.emac4sync.mmahr, p->u0.emac4sync.mmalr,
198 p->u1.emac4sync.revid);
199
200 printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
201 p->u1.emac4sync.iaht1, p->u1.emac4sync.iaht2,
202 p->u1.emac4sync.iaht3, p->u1.emac4sync.iaht4);
203 printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n",
204 p->u1.emac4sync.iaht5, p->u1.emac4sync.iaht6,
205 p->u1.emac4sync.iaht7, p->u1.emac4sync.iaht8);
206
207
208 printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
209 p->u1.emac4sync.gaht1, p->u1.emac4sync.gaht2,
210 p->u1.emac4sync.gaht3, p->u1.emac4sync.gaht4);
211 printf(" 0x%04x 0x%04x 0x%04x 0x%04x\n\n",
212 p->u1.emac4sync.gaht5, p->u1.emac4sync.gaht6,
213 p->u1.emac4sync.gaht7, p->u1.emac4sync.gaht8);
214
215 } else if (hdr->version == EMAC4_VERSION) {
216 printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
217 p->u0.emac4.iaht1, p->u0.emac4.iaht2,
218 p->u0.emac4.iaht3, p->u0.emac4.iaht4);
219
220 printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
221 p->u0.emac4.gaht1, p->u0.emac4.gaht2,
222 p->u0.emac4.gaht3, p->u0.emac4.gaht4);
223
224 printf(" IPCR = 0x%08x\n\n", p->u1.emac4.ipcr);
225 } else if (hdr->version == EMAC_VERSION) {
226 printf("IAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
227 p->u0.emac4.iaht1, p->u0.emac4.iaht2,
228 p->u0.emac4.iaht3, p->u0.emac4.iaht4);
229
230 printf("GAHT = 0x%04x 0x%04x 0x%04x 0x%04x\n",
231 p->u0.emac4.gaht1, p->u0.emac4.gaht2,
232 p->u0.emac4.gaht3, p->u0.emac4.gaht4);
233 }
234 return res;
235 }
236
print_mal_regs(void * buf)237 static void *print_mal_regs(void *buf)
238 {
239 struct emac_ethtool_regs_subhdr *hdr = buf;
240 struct mal_regs *p = (struct mal_regs *)(hdr + 1);
241 int i;
242
243 printf("MAL%d Registers\n", hdr->index);
244 printf("-----------------\n");
245 printf("CFG = 0x%08x ESR = 0x%08x IER = 0x%08x\n"
246 "TX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n"
247 "RX|CASR = 0x%08x CARR = 0x%08x EOBISR = 0x%08x DEIR = 0x%08x\n",
248 p->cfg, p->esr, p->ier,
249 p->tx_casr, p->tx_carr, p->tx_eobisr, p->tx_deir,
250 p->rx_casr, p->rx_carr, p->rx_eobisr, p->rx_deir);
251
252 printf("TX|");
253 for (i = 0; i < p->tx_count; ++i) {
254 if (i && !(i % 4))
255 printf("\n ");
256 printf("CTP%d = 0x%08x ", i, p->tx_ctpr[i]);
257 }
258 printf("\nRX|");
259 for (i = 0; i < p->rx_count; ++i) {
260 if (i && !(i % 4))
261 printf("\n ");
262 printf("CTP%d = 0x%08x ", i, p->rx_ctpr[i]);
263 }
264 printf("\n ");
265 for (i = 0; i < p->rx_count; ++i) {
266 u32 r = p->rcbs[i];
267 if (i && !(i % 3))
268 printf("\n ");
269 printf("RCBS%d = 0x%08x (%d) ", i, r, r * 16);
270 }
271 printf("\n\n");
272 return p + 1;
273 }
274
print_zmii_regs(void * buf)275 static void *print_zmii_regs(void *buf)
276 {
277 struct emac_ethtool_regs_subhdr *hdr = buf;
278 struct zmii_regs *p = (struct zmii_regs *)(hdr + 1);
279
280 printf("ZMII%d Registers\n", hdr->index);
281 printf("-----------------\n");
282 printf("FER = %08x SSR = %08x\n"
283 "SMIISR = %08x\n\n", p->fer, p->ssr, p->smiisr);
284
285 return p + 1;
286 }
287
print_rgmii_regs(void * buf)288 static void *print_rgmii_regs(void *buf)
289 {
290 struct emac_ethtool_regs_subhdr *hdr = buf;
291 struct rgmii_regs *p = (struct rgmii_regs *)(hdr + 1);
292
293 printf("RGMII%d Registers\n", hdr->index);
294 printf("-----------------\n");
295 printf("FER = %08x SSR = %08x\n\n", p->fer, p->ssr);
296
297 return p + 1;
298 }
299
print_tah_regs(void * buf)300 static void *print_tah_regs(void *buf)
301 {
302 struct emac_ethtool_regs_subhdr *hdr = buf;
303 struct tah_regs *p = (struct tah_regs *)(hdr + 1);
304
305 printf("TAH%d Registers\n", hdr->index);
306 printf("-----------------\n");
307
308 printf("REVID = %08x MR = %08x TSR = %08x\n"
309 "SSR0 = %08x SSR1 = %08x SSR2 = %08x\n"
310 "SSR3 = %08x SSR4 = %08x SSR5 = %08x\n\n",
311 p->revid, p->mr, p->tsr,
312 p->ssr0, p->ssr1, p->ssr2, p->ssr3, p->ssr4, p->ssr5);
313
314 return p + 1;
315 }
316
ibm_emac_dump_regs(struct ethtool_drvinfo * info maybe_unused,struct ethtool_regs * regs)317 int ibm_emac_dump_regs(struct ethtool_drvinfo *info maybe_unused,
318 struct ethtool_regs *regs)
319 {
320 struct emac_ethtool_regs_hdr *hdr =
321 (struct emac_ethtool_regs_hdr *)regs->data;
322 void *buf = hdr + 1;
323
324 buf = print_mal_regs(buf);
325 buf = print_emac_regs(buf);
326 if (hdr->components & EMAC_ETHTOOL_REGS_ZMII)
327 buf = print_zmii_regs(buf);
328 if (hdr->components & EMAC_ETHTOOL_REGS_RGMII)
329 buf = print_rgmii_regs(buf);
330 if (hdr->components & EMAC_ETHTOOL_REGS_TAH)
331 print_tah_regs(buf);
332
333 return 0;
334 }
335