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