1 /* Code to dump registers for the Freescale/NXP ENETC controller.
2 *
3 * Copyright 2022 NXP
4 */
5 #include <stdio.h>
6 #include "internal.h"
7
8 #define BIT(x) (1U << (x))
9
10 enum enetc_bdr_type {TX, RX};
11 #define ENETC_SIMR 0
12 #define ENETC_SIPMAR0 0x80
13 #define ENETC_SIPMAR1 0x84
14 #define ENETC_SICBDRMR 0x800
15 #define ENETC_SICBDRSR 0x804
16 #define ENETC_SICBDRBAR0 0x810
17 #define ENETC_SICBDRBAR1 0x814
18 #define ENETC_SICBDRPIR 0x818
19 #define ENETC_SICBDRCIR 0x81c
20 #define ENETC_SICBDRLENR 0x820
21 #define ENETC_SICAPR0 0x900
22 #define ENETC_SICAPR1 0x904
23 #define ENETC_SIUEFDCR 0xe28
24
25 #define ENETC_BDR_OFF(i) ((i) * 0x200)
26 #define ENETC_BDR(t, i, r) (0x8000 + (t) * 0x100 + ENETC_BDR_OFF(i) + (r))
27
28 /* RX BDR reg offsets */
29 #define ENETC_RBMR 0
30 #define ENETC_RBSR 0x4
31 #define ENETC_RBBSR 0x8
32 #define ENETC_RBCIR 0xc
33 #define ENETC_RBBAR0 0x10
34 #define ENETC_RBBAR1 0x14
35 #define ENETC_RBPIR 0x18
36 #define ENETC_RBLENR 0x20
37 #define ENETC_RBIER 0xa0
38 #define ENETC_RBICR0 0xa8
39 #define ENETC_RBICR1 0xac
40
41 /* TX BDR reg offsets */
42 #define ENETC_TBMR 0
43 #define ENETC_TBSR 0x4
44 #define ENETC_TBBAR0 0x10
45 #define ENETC_TBBAR1 0x14
46 #define ENETC_TBPIR 0x18
47 #define ENETC_TBCIR 0x1c
48 #define ENETC_TBLENR 0x20
49 #define ENETC_TBIER 0xa0
50 #define ENETC_TBIDR 0xa4
51 #define ENETC_TBICR0 0xa8
52 #define ENETC_TBICR1 0xac
53
54 /* Port registers */
55 #define ENETC_PORT_BASE 0x10000
56 #define ENETC_PMR ENETC_PORT_BASE + 0x0000
57 #define ENETC_PSR ENETC_PORT_BASE + 0x0004
58 #define ENETC_PSIPMR ENETC_PORT_BASE + 0x0018
59 #define ENETC_PSIPMAR0(n) ENETC_PORT_BASE + (0x0100 + (n) * 0x8) /* n = SI index */
60 #define ENETC_PSIPMAR1(n) ENETC_PORT_BASE + (0x0104 + (n) * 0x8)
61 #define ENETC_PTXMBAR ENETC_PORT_BASE + 0x0608
62 #define ENETC_PCAPR0 ENETC_PORT_BASE + 0x0900
63 #define ENETC_PCAPR1 ENETC_PORT_BASE + 0x0904
64 #define ENETC_PSICFGR0(n) ENETC_PORT_BASE + (0x0940 + (n) * 0xc) /* n = SI index */
65
66 #define ENETC_PRFSCAPR ENETC_PORT_BASE + 0x1804
67 #define ENETC_PTCMSDUR(n) ENETC_PORT_BASE + (0x2020 + (n) * 4) /* n = TC index [0..7] */
68
69 #define ENETC_PM0_CMD_CFG ENETC_PORT_BASE + 0x8008
70 #define ENETC_PM0_CMD_TX_EN BIT(0)
71 #define ENETC_PM0_CMD_RX_EN BIT(1)
72 #define ENETC_PM0_CMD_WAN BIT(3)
73 #define ENETC_PM0_CMD_PROMISC BIT(4)
74 #define ENETC_PM0_CMD_PAD BIT(5)
75 #define ENETC_PM0_CMD_CRC BIT(6)
76 #define ENETC_PM0_CMD_PAUSE_FWD BIT(7)
77 #define ENETC_PM0_CMD_PAUSE_IGN BIT(8)
78 #define ENETC_PM0_CMD_TX_ADDR_INS BIT(9)
79 #define ENETC_PM0_CMD_XGLP BIT(10)
80 #define ENETC_PM0_CMD_TXP BIT(11)
81 #define ENETC_PM0_CMD_SWR BIT(12)
82 #define ENETC_PM0_CMD_CNT_FRM_EN BIT(13)
83 #define ENETC_PM0_CMD_SEND_IDLE BIT(16)
84 #define ENETC_PM0_CMD_NO_LEN_CHK BIT(17)
85 #define ENETC_PM0_CMD_SFD BIT(21)
86 #define ENETC_PM0_CMD_TX_LOWP_ENA BIT(23)
87 #define ENETC_PM0_CMD_REG_LOWP_RXETY BIT(24)
88 #define ENETC_PM0_CMD_RXSTP BIT(29)
89 #define ENETC_PM0_CMD_MG BIT(31)
90
91 #define ENETC_PM0_MAXFRM ENETC_PORT_BASE + 0x8014
92 #define ENETC_PM0_IF_MODE ENETC_PORT_BASE + 0x8300
93
94 struct enetc_register {
95 u32 addr;
96 const char *name;
97 void (*decode)(u32 val, char *buf);
98 };
99
100 #define REG(_reg, _name) { .addr = (_reg), .name = (_name) }
101
102 #define REG_DEC(_reg, _name, _decode) \
103 { .addr = (_reg), .name = (_name), .decode = (_decode) }
104
decode_cmd_cfg(u32 val,char * buf)105 static void decode_cmd_cfg(u32 val, char *buf)
106 {
107 sprintf(buf, "\tMG %d\n\tRXSTP %d\n\tREG_LOWP_RXETY %d\n"
108 "\tTX_LOWP_ENA %d\n\tSFD %d\n\tNO_LEN_CHK %d\n\tSEND_IDLE %d\n"
109 "\tCNT_FRM_EN %d\n\tSWR %d\n\tTXP %d\n\tXGLP %d\n"
110 "\tTX_ADDR_INS %d\n\tPAUSE_IGN %d\n\tPAUSE_FWD %d\n\tCRC %d\n"
111 "\tPAD %d\n\tPROMIS %d\n\tWAN %d\n\tRX_EN %d\n\tTX_EN %d\n",
112 !!(val & ENETC_PM0_CMD_MG),
113 !!(val & ENETC_PM0_CMD_RXSTP),
114 !!(val & ENETC_PM0_CMD_REG_LOWP_RXETY),
115 !!(val & ENETC_PM0_CMD_TX_LOWP_ENA),
116 !!(val & ENETC_PM0_CMD_SFD),
117 !!(val & ENETC_PM0_CMD_NO_LEN_CHK),
118 !!(val & ENETC_PM0_CMD_SEND_IDLE),
119 !!(val & ENETC_PM0_CMD_CNT_FRM_EN),
120 !!(val & ENETC_PM0_CMD_SWR),
121 !!(val & ENETC_PM0_CMD_TXP),
122 !!(val & ENETC_PM0_CMD_XGLP),
123 !!(val & ENETC_PM0_CMD_TX_ADDR_INS),
124 !!(val & ENETC_PM0_CMD_PAUSE_IGN),
125 !!(val & ENETC_PM0_CMD_PAUSE_FWD),
126 !!(val & ENETC_PM0_CMD_CRC),
127 !!(val & ENETC_PM0_CMD_PAD),
128 !!(val & ENETC_PM0_CMD_PROMISC),
129 !!(val & ENETC_PM0_CMD_WAN),
130 !!(val & ENETC_PM0_CMD_RX_EN),
131 !!(val & ENETC_PM0_CMD_TX_EN));
132 }
133
134 #define RXBDR_REGS(_i) \
135 REG(ENETC_BDR(RX, (_i), ENETC_RBMR), "RX BDR " #_i " mode register"), \
136 REG(ENETC_BDR(RX, (_i), ENETC_RBSR), "RX BDR " #_i " status register"), \
137 REG(ENETC_BDR(RX, (_i), ENETC_RBBSR), "RX BDR " #_i " buffer size register"), \
138 REG(ENETC_BDR(RX, (_i), ENETC_RBPIR), "RX BDR " #_i " producer index register"), \
139 REG(ENETC_BDR(RX, (_i), ENETC_RBCIR), "RX BDR " #_i " consumer index register"), \
140 REG(ENETC_BDR(RX, (_i), ENETC_RBBAR0), "RX BDR " #_i " base address register 0"), \
141 REG(ENETC_BDR(RX, (_i), ENETC_RBBAR1), "RX BDR " #_i " base address register 1"), \
142 REG(ENETC_BDR(RX, (_i), ENETC_RBLENR), "RX BDR " #_i " length register"), \
143 REG(ENETC_BDR(RX, (_i), ENETC_RBIER), "RX BDR " #_i " interrupt enable register"), \
144 REG(ENETC_BDR(RX, (_i), ENETC_RBICR0), "RX BDR " #_i " interrupt coalescing register 0"), \
145 REG(ENETC_BDR(RX, (_i), ENETC_RBICR1), "RX BDR " #_i " interrupt coalescing register 1")
146
147 #define TXBDR_REGS(_i) \
148 REG(ENETC_BDR(TX, (_i), ENETC_TBMR), "TX BDR " #_i " mode register"), \
149 REG(ENETC_BDR(TX, (_i), ENETC_TBSR), "TX BDR " #_i " status register"), \
150 REG(ENETC_BDR(TX, (_i), ENETC_TBBAR0), "TX BDR " #_i " base address register 0"), \
151 REG(ENETC_BDR(TX, (_i), ENETC_TBBAR1), "TX BDR " #_i " base address register 1"), \
152 REG(ENETC_BDR(TX, (_i), ENETC_TBPIR), "TX BDR " #_i " producer index register"), \
153 REG(ENETC_BDR(TX, (_i), ENETC_TBCIR), "TX BDR " #_i " consumer index register"), \
154 REG(ENETC_BDR(TX, (_i), ENETC_TBLENR), "TX BDR " #_i " length register"), \
155 REG(ENETC_BDR(TX, (_i), ENETC_TBIER), "TX BDR " #_i " interrupt enable register"), \
156 REG(ENETC_BDR(TX, (_i), ENETC_TBICR0), "TX BDR " #_i " interrupt coalescing register 0"), \
157 REG(ENETC_BDR(TX, (_i), ENETC_TBICR1), "TX BDR " #_i " interrupt coalescing register 1")
158
159 static const struct enetc_register known_enetc_regs[] = {
160 REG(ENETC_SIMR, "SI mode register"),
161 REG(ENETC_SIPMAR0, "SI primary MAC address register 0"),
162 REG(ENETC_SIPMAR1, "SI primary MAC address register 1"),
163 REG(ENETC_SICBDRMR, "SI control BDR mode register"),
164 REG(ENETC_SICBDRSR, "SI control BDR status register"),
165 REG(ENETC_SICBDRBAR0, "SI control BDR base address register 0"),
166 REG(ENETC_SICBDRBAR1, "SI control BDR base address register 1"),
167 REG(ENETC_SICBDRPIR, "SI control BDR producer index register"),
168 REG(ENETC_SICBDRCIR, "SI control BDR consumer index register"),
169 REG(ENETC_SICBDRLENR, "SI control BDR length register"),
170 REG(ENETC_SICAPR0, "SI capability register 0"),
171 REG(ENETC_SICAPR1, "SI capability register 1"),
172 REG(ENETC_SIUEFDCR, "SI uncorrectable error frame drop count register"),
173
174 TXBDR_REGS(0), TXBDR_REGS(1), TXBDR_REGS(2), TXBDR_REGS(3),
175 TXBDR_REGS(4), TXBDR_REGS(5), TXBDR_REGS(6), TXBDR_REGS(7),
176 TXBDR_REGS(8), TXBDR_REGS(9), TXBDR_REGS(10), TXBDR_REGS(11),
177 TXBDR_REGS(12), TXBDR_REGS(13), TXBDR_REGS(14), TXBDR_REGS(15),
178
179 RXBDR_REGS(0), RXBDR_REGS(1), RXBDR_REGS(2), RXBDR_REGS(3),
180 RXBDR_REGS(4), RXBDR_REGS(5), RXBDR_REGS(6), RXBDR_REGS(7),
181 RXBDR_REGS(8), RXBDR_REGS(9), RXBDR_REGS(10), RXBDR_REGS(11),
182 RXBDR_REGS(12), RXBDR_REGS(13), RXBDR_REGS(14), RXBDR_REGS(15),
183
184 REG(ENETC_PMR, "Port mode register"),
185 REG(ENETC_PSR, "Port status register"),
186 REG(ENETC_PSIPMR, "Port SI promiscuous mode register"),
187 REG(ENETC_PSIPMAR0(0), "Port SI0 primary MAC address register 0"),
188 REG(ENETC_PSIPMAR1(0), "Port SI0 primary MAC address register 1"),
189 REG(ENETC_PTXMBAR, "Port HTA transmit memory buffer allocation register"),
190 REG(ENETC_PCAPR0, "Port capability register 0"),
191 REG(ENETC_PCAPR1, "Port capability register 1"),
192 REG(ENETC_PSICFGR0(0), "Port SI0 configuration register 0"),
193 REG(ENETC_PRFSCAPR, "Port RFS capability register"),
194 REG(ENETC_PTCMSDUR(0), "Port traffic class 0 maximum SDU register"),
195 REG_DEC(ENETC_PM0_CMD_CFG, "Port eMAC Command and Configuration Register",
196 decode_cmd_cfg),
197 REG(ENETC_PM0_MAXFRM, "Port eMAC Maximum Frame Length Register"),
198 REG(ENETC_PM0_IF_MODE, "Port eMAC Interface Mode Control Register"),
199 };
200
decode_known_reg(const struct enetc_register * reg,u32 val)201 static void decode_known_reg(const struct enetc_register *reg, u32 val)
202 {
203 char buf[512];
204
205 reg->decode(val, buf);
206 fprintf(stdout, "%s: 0x%x\n%s", reg->name, val, buf);
207 }
208
dump_known_reg(const struct enetc_register * reg,u32 val)209 static void dump_known_reg(const struct enetc_register *reg, u32 val)
210 {
211 fprintf(stdout, "%s: 0x%x\n", reg->name, val);
212 }
213
dump_unknown_reg(u32 addr,u32 val)214 static void dump_unknown_reg(u32 addr, u32 val)
215 {
216 fprintf(stdout, "Reg 0x%x: 0x%x\n", addr, val);
217 }
218
dump_reg(u32 addr,u32 val)219 static void dump_reg(u32 addr, u32 val)
220 {
221 const struct enetc_register *reg;
222 u32 i;
223
224 for (i = 0; i < ARRAY_SIZE(known_enetc_regs); i++) {
225 reg = &known_enetc_regs[i];
226 if (reg->addr == addr) {
227 if (reg->decode)
228 decode_known_reg(reg, val);
229 else
230 dump_known_reg(reg, val);
231 return;
232 }
233 }
234
235 dump_unknown_reg(addr, val);
236 }
237
238 /* Registers are structured in an array of key/value u32 pairs.
239 * Compare each key to our list of known registers, or print it
240 * as a raw address otherwise.
241 */
fsl_enetc_dump_regs(struct ethtool_drvinfo * info __maybe_unused,struct ethtool_regs * regs)242 int fsl_enetc_dump_regs(struct ethtool_drvinfo *info __maybe_unused,
243 struct ethtool_regs *regs)
244 {
245 u32 *data = (u32 *)regs->data;
246 u32 len = regs->len;
247
248 if (len % 8) {
249 fprintf(stdout, "Expected length to be multiple of 8 bytes\n");
250 return -1;
251 }
252
253 while (len) {
254 dump_reg(data[0], data[1]);
255 data += 2; len -= 8;
256 }
257
258 return 0;
259 }
260