1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* DSA driver for: |
3 | * Vitesse VSC7385 SparX-G5 5+1-port Integrated Gigabit Ethernet Switch |
4 | * Vitesse VSC7388 SparX-G8 8-port Integrated Gigabit Ethernet Switch |
5 | * Vitesse VSC7395 SparX-G5e 5+1-port Integrated Gigabit Ethernet Switch |
6 | * Vitesse VSC7398 SparX-G8e 8-port Integrated Gigabit Ethernet Switch |
7 | * |
8 | * These switches have a built-in 8051 CPU and can download and execute a |
9 | * firmware in this CPU. They can also be configured to use an external CPU |
10 | * handling the switch in a memory-mapped manner by connecting to that external |
11 | * CPU's memory bus. |
12 | * |
13 | * Copyright (C) 2018 Linus Wallej <linus.walleij@linaro.org> |
14 | * Includes portions of code from the firmware uploader by: |
15 | * Copyright (C) 2009 Gabor Juhos <juhosg@openwrt.org> |
16 | */ |
17 | #include <linux/kernel.h> |
18 | #include <linux/module.h> |
19 | #include <linux/device.h> |
20 | #include <linux/of.h> |
21 | #include <linux/of_mdio.h> |
22 | #include <linux/bitops.h> |
23 | #include <linux/if_bridge.h> |
24 | #include <linux/etherdevice.h> |
25 | #include <linux/gpio/consumer.h> |
26 | #include <linux/gpio/driver.h> |
27 | #include <linux/random.h> |
28 | #include <net/dsa.h> |
29 | |
30 | #include "vitesse-vsc73xx.h" |
31 | |
32 | #define VSC73XX_BLOCK_MAC 0x1 /* Subblocks 0-4, 6 (CPU port) */ |
33 | #define VSC73XX_BLOCK_ANALYZER 0x2 /* Only subblock 0 */ |
34 | #define VSC73XX_BLOCK_MII 0x3 /* Subblocks 0 and 1 */ |
35 | #define VSC73XX_BLOCK_MEMINIT 0x3 /* Only subblock 2 */ |
36 | #define VSC73XX_BLOCK_CAPTURE 0x4 /* Only subblock 2 */ |
37 | #define VSC73XX_BLOCK_ARBITER 0x5 /* Only subblock 0 */ |
38 | #define VSC73XX_BLOCK_SYSTEM 0x7 /* Only subblock 0 */ |
39 | |
40 | #define CPU_PORT 6 /* CPU port */ |
41 | |
42 | /* MAC Block registers */ |
43 | #define VSC73XX_MAC_CFG 0x00 |
44 | #define VSC73XX_MACHDXGAP 0x02 |
45 | #define VSC73XX_FCCONF 0x04 |
46 | #define VSC73XX_FCMACHI 0x08 |
47 | #define VSC73XX_FCMACLO 0x0c |
48 | #define VSC73XX_MAXLEN 0x10 |
49 | #define VSC73XX_ADVPORTM 0x19 |
50 | #define VSC73XX_TXUPDCFG 0x24 |
51 | #define VSC73XX_TXQ_SELECT_CFG 0x28 |
52 | #define VSC73XX_RXOCT 0x50 |
53 | #define VSC73XX_TXOCT 0x51 |
54 | #define VSC73XX_C_RX0 0x52 |
55 | #define VSC73XX_C_RX1 0x53 |
56 | #define VSC73XX_C_RX2 0x54 |
57 | #define VSC73XX_C_TX0 0x55 |
58 | #define VSC73XX_C_TX1 0x56 |
59 | #define VSC73XX_C_TX2 0x57 |
60 | #define VSC73XX_C_CFG 0x58 |
61 | #define VSC73XX_CAT_DROP 0x6e |
62 | #define VSC73XX_CAT_PR_MISC_L2 0x6f |
63 | #define VSC73XX_CAT_PR_USR_PRIO 0x75 |
64 | #define VSC73XX_Q_MISC_CONF 0xdf |
65 | |
66 | /* MAC_CFG register bits */ |
67 | #define VSC73XX_MAC_CFG_WEXC_DIS BIT(31) |
68 | #define VSC73XX_MAC_CFG_PORT_RST BIT(29) |
69 | #define VSC73XX_MAC_CFG_TX_EN BIT(28) |
70 | #define VSC73XX_MAC_CFG_SEED_LOAD BIT(27) |
71 | #define VSC73XX_MAC_CFG_SEED_MASK GENMASK(26, 19) |
72 | #define VSC73XX_MAC_CFG_SEED_OFFSET 19 |
73 | #define VSC73XX_MAC_CFG_FDX BIT(18) |
74 | #define VSC73XX_MAC_CFG_GIGA_MODE BIT(17) |
75 | #define VSC73XX_MAC_CFG_RX_EN BIT(16) |
76 | #define VSC73XX_MAC_CFG_VLAN_DBLAWR BIT(15) |
77 | #define VSC73XX_MAC_CFG_VLAN_AWR BIT(14) |
78 | #define VSC73XX_MAC_CFG_100_BASE_T BIT(13) /* Not in manual */ |
79 | #define VSC73XX_MAC_CFG_TX_IPG_MASK GENMASK(10, 6) |
80 | #define VSC73XX_MAC_CFG_TX_IPG_OFFSET 6 |
81 | #define VSC73XX_MAC_CFG_TX_IPG_1000M (6 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) |
82 | #define VSC73XX_MAC_CFG_TX_IPG_100_10M (17 << VSC73XX_MAC_CFG_TX_IPG_OFFSET) |
83 | #define VSC73XX_MAC_CFG_MAC_RX_RST BIT(5) |
84 | #define VSC73XX_MAC_CFG_MAC_TX_RST BIT(4) |
85 | #define VSC73XX_MAC_CFG_CLK_SEL_MASK GENMASK(2, 0) |
86 | #define VSC73XX_MAC_CFG_CLK_SEL_OFFSET 0 |
87 | #define VSC73XX_MAC_CFG_CLK_SEL_1000M 1 |
88 | #define VSC73XX_MAC_CFG_CLK_SEL_100M 2 |
89 | #define VSC73XX_MAC_CFG_CLK_SEL_10M 3 |
90 | #define VSC73XX_MAC_CFG_CLK_SEL_EXT 4 |
91 | |
92 | #define VSC73XX_MAC_CFG_1000M_F_PHY (VSC73XX_MAC_CFG_FDX | \ |
93 | VSC73XX_MAC_CFG_GIGA_MODE | \ |
94 | VSC73XX_MAC_CFG_TX_IPG_1000M | \ |
95 | VSC73XX_MAC_CFG_CLK_SEL_EXT) |
96 | #define VSC73XX_MAC_CFG_100_10M_F_PHY (VSC73XX_MAC_CFG_FDX | \ |
97 | VSC73XX_MAC_CFG_TX_IPG_100_10M | \ |
98 | VSC73XX_MAC_CFG_CLK_SEL_EXT) |
99 | #define VSC73XX_MAC_CFG_100_10M_H_PHY (VSC73XX_MAC_CFG_TX_IPG_100_10M | \ |
100 | VSC73XX_MAC_CFG_CLK_SEL_EXT) |
101 | #define VSC73XX_MAC_CFG_1000M_F_RGMII (VSC73XX_MAC_CFG_FDX | \ |
102 | VSC73XX_MAC_CFG_GIGA_MODE | \ |
103 | VSC73XX_MAC_CFG_TX_IPG_1000M | \ |
104 | VSC73XX_MAC_CFG_CLK_SEL_1000M) |
105 | #define VSC73XX_MAC_CFG_RESET (VSC73XX_MAC_CFG_PORT_RST | \ |
106 | VSC73XX_MAC_CFG_MAC_RX_RST | \ |
107 | VSC73XX_MAC_CFG_MAC_TX_RST) |
108 | |
109 | /* Flow control register bits */ |
110 | #define VSC73XX_FCCONF_ZERO_PAUSE_EN BIT(17) |
111 | #define VSC73XX_FCCONF_FLOW_CTRL_OBEY BIT(16) |
112 | #define VSC73XX_FCCONF_PAUSE_VAL_MASK GENMASK(15, 0) |
113 | |
114 | /* ADVPORTM advanced port setup register bits */ |
115 | #define VSC73XX_ADVPORTM_IFG_PPM BIT(7) |
116 | #define VSC73XX_ADVPORTM_EXC_COL_CONT BIT(6) |
117 | #define VSC73XX_ADVPORTM_EXT_PORT BIT(5) |
118 | #define VSC73XX_ADVPORTM_INV_GTX BIT(4) |
119 | #define VSC73XX_ADVPORTM_ENA_GTX BIT(3) |
120 | #define VSC73XX_ADVPORTM_DDR_MODE BIT(2) |
121 | #define VSC73XX_ADVPORTM_IO_LOOPBACK BIT(1) |
122 | #define VSC73XX_ADVPORTM_HOST_LOOPBACK BIT(0) |
123 | |
124 | /* CAT_DROP categorizer frame dropping register bits */ |
125 | #define VSC73XX_CAT_DROP_DROP_MC_SMAC_ENA BIT(6) |
126 | #define VSC73XX_CAT_DROP_FWD_CTRL_ENA BIT(4) |
127 | #define VSC73XX_CAT_DROP_FWD_PAUSE_ENA BIT(3) |
128 | #define VSC73XX_CAT_DROP_UNTAGGED_ENA BIT(2) |
129 | #define VSC73XX_CAT_DROP_TAGGED_ENA BIT(1) |
130 | #define VSC73XX_CAT_DROP_NULL_MAC_ENA BIT(0) |
131 | |
132 | #define VSC73XX_Q_MISC_CONF_EXTENT_MEM BIT(31) |
133 | #define VSC73XX_Q_MISC_CONF_EARLY_TX_MASK GENMASK(4, 1) |
134 | #define VSC73XX_Q_MISC_CONF_EARLY_TX_512 (1 << 1) |
135 | #define VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE BIT(0) |
136 | |
137 | /* Frame analyzer block 2 registers */ |
138 | #define VSC73XX_STORMLIMIT 0x02 |
139 | #define VSC73XX_ADVLEARN 0x03 |
140 | #define VSC73XX_IFLODMSK 0x04 |
141 | #define VSC73XX_VLANMASK 0x05 |
142 | #define VSC73XX_MACHDATA 0x06 |
143 | #define VSC73XX_MACLDATA 0x07 |
144 | #define VSC73XX_ANMOVED 0x08 |
145 | #define VSC73XX_ANAGEFIL 0x09 |
146 | #define VSC73XX_ANEVENTS 0x0a |
147 | #define VSC73XX_ANCNTMASK 0x0b |
148 | #define VSC73XX_ANCNTVAL 0x0c |
149 | #define VSC73XX_LEARNMASK 0x0d |
150 | #define VSC73XX_UFLODMASK 0x0e |
151 | #define VSC73XX_MFLODMASK 0x0f |
152 | #define VSC73XX_RECVMASK 0x10 |
153 | #define VSC73XX_AGGRCTRL 0x20 |
154 | #define VSC73XX_AGGRMSKS 0x30 /* Until 0x3f */ |
155 | #define VSC73XX_DSTMASKS 0x40 /* Until 0x7f */ |
156 | #define VSC73XX_SRCMASKS 0x80 /* Until 0x87 */ |
157 | #define VSC73XX_CAPENAB 0xa0 |
158 | #define VSC73XX_MACACCESS 0xb0 |
159 | #define VSC73XX_IPMCACCESS 0xb1 |
160 | #define VSC73XX_MACTINDX 0xc0 |
161 | #define VSC73XX_VLANACCESS 0xd0 |
162 | #define VSC73XX_VLANTIDX 0xe0 |
163 | #define VSC73XX_AGENCTRL 0xf0 |
164 | #define VSC73XX_CAPRST 0xff |
165 | |
166 | #define VSC73XX_MACACCESS_CPU_COPY BIT(14) |
167 | #define VSC73XX_MACACCESS_FWD_KILL BIT(13) |
168 | #define VSC73XX_MACACCESS_IGNORE_VLAN BIT(12) |
169 | #define VSC73XX_MACACCESS_AGED_FLAG BIT(11) |
170 | #define VSC73XX_MACACCESS_VALID BIT(10) |
171 | #define VSC73XX_MACACCESS_LOCKED BIT(9) |
172 | #define VSC73XX_MACACCESS_DEST_IDX_MASK GENMASK(8, 3) |
173 | #define VSC73XX_MACACCESS_CMD_MASK GENMASK(2, 0) |
174 | #define VSC73XX_MACACCESS_CMD_IDLE 0 |
175 | #define VSC73XX_MACACCESS_CMD_LEARN 1 |
176 | #define VSC73XX_MACACCESS_CMD_FORGET 2 |
177 | #define VSC73XX_MACACCESS_CMD_AGE_TABLE 3 |
178 | #define VSC73XX_MACACCESS_CMD_FLUSH_TABLE 4 |
179 | #define VSC73XX_MACACCESS_CMD_CLEAR_TABLE 5 |
180 | #define VSC73XX_MACACCESS_CMD_READ_ENTRY 6 |
181 | #define VSC73XX_MACACCESS_CMD_WRITE_ENTRY 7 |
182 | |
183 | #define VSC73XX_VLANACCESS_LEARN_DISABLED BIT(30) |
184 | #define VSC73XX_VLANACCESS_VLAN_MIRROR BIT(29) |
185 | #define VSC73XX_VLANACCESS_VLAN_SRC_CHECK BIT(28) |
186 | #define VSC73XX_VLANACCESS_VLAN_PORT_MASK GENMASK(9, 2) |
187 | #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_MASK GENMASK(2, 0) |
188 | #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_IDLE 0 |
189 | #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_READ_ENTRY 1 |
190 | #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_WRITE_ENTRY 2 |
191 | #define VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE 3 |
192 | |
193 | /* MII block 3 registers */ |
194 | #define VSC73XX_MII_STAT 0x0 |
195 | #define VSC73XX_MII_CMD 0x1 |
196 | #define VSC73XX_MII_DATA 0x2 |
197 | |
198 | /* Arbiter block 5 registers */ |
199 | #define VSC73XX_ARBEMPTY 0x0c |
200 | #define VSC73XX_ARBDISC 0x0e |
201 | #define VSC73XX_SBACKWDROP 0x12 |
202 | #define VSC73XX_DBACKWDROP 0x13 |
203 | #define VSC73XX_ARBBURSTPROB 0x15 |
204 | |
205 | /* System block 7 registers */ |
206 | #define VSC73XX_ICPU_SIPAD 0x01 |
207 | #define VSC73XX_GMIIDELAY 0x05 |
208 | #define VSC73XX_ICPU_CTRL 0x10 |
209 | #define VSC73XX_ICPU_ADDR 0x11 |
210 | #define VSC73XX_ICPU_SRAM 0x12 |
211 | #define VSC73XX_HWSEM 0x13 |
212 | #define VSC73XX_GLORESET 0x14 |
213 | #define VSC73XX_ICPU_MBOX_VAL 0x15 |
214 | #define VSC73XX_ICPU_MBOX_SET 0x16 |
215 | #define VSC73XX_ICPU_MBOX_CLR 0x17 |
216 | #define VSC73XX_CHIPID 0x18 |
217 | #define VSC73XX_GPIO 0x34 |
218 | |
219 | #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_NONE 0 |
220 | #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_4_NS 1 |
221 | #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_1_7_NS 2 |
222 | #define VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS 3 |
223 | |
224 | #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_NONE (0 << 4) |
225 | #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_4_NS (1 << 4) |
226 | #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_1_7_NS (2 << 4) |
227 | #define VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS (3 << 4) |
228 | |
229 | #define VSC73XX_ICPU_CTRL_WATCHDOG_RST BIT(31) |
230 | #define VSC73XX_ICPU_CTRL_CLK_DIV_MASK GENMASK(12, 8) |
231 | #define VSC73XX_ICPU_CTRL_SRST_HOLD BIT(7) |
232 | #define VSC73XX_ICPU_CTRL_ICPU_PI_EN BIT(6) |
233 | #define VSC73XX_ICPU_CTRL_BOOT_EN BIT(3) |
234 | #define VSC73XX_ICPU_CTRL_EXT_ACC_EN BIT(2) |
235 | #define VSC73XX_ICPU_CTRL_CLK_EN BIT(1) |
236 | #define VSC73XX_ICPU_CTRL_SRST BIT(0) |
237 | |
238 | #define VSC73XX_CHIPID_ID_SHIFT 12 |
239 | #define VSC73XX_CHIPID_ID_MASK 0xffff |
240 | #define VSC73XX_CHIPID_REV_SHIFT 28 |
241 | #define VSC73XX_CHIPID_REV_MASK 0xf |
242 | #define VSC73XX_CHIPID_ID_7385 0x7385 |
243 | #define VSC73XX_CHIPID_ID_7388 0x7388 |
244 | #define VSC73XX_CHIPID_ID_7395 0x7395 |
245 | #define VSC73XX_CHIPID_ID_7398 0x7398 |
246 | |
247 | #define VSC73XX_GLORESET_STROBE BIT(4) |
248 | #define VSC73XX_GLORESET_ICPU_LOCK BIT(3) |
249 | #define VSC73XX_GLORESET_MEM_LOCK BIT(2) |
250 | #define VSC73XX_GLORESET_PHY_RESET BIT(1) |
251 | #define VSC73XX_GLORESET_MASTER_RESET BIT(0) |
252 | |
253 | #define VSC7385_CLOCK_DELAY ((3 << 4) | 3) |
254 | #define VSC7385_CLOCK_DELAY_MASK ((3 << 4) | 3) |
255 | |
256 | #define VSC73XX_ICPU_CTRL_STOP (VSC73XX_ICPU_CTRL_SRST_HOLD | \ |
257 | VSC73XX_ICPU_CTRL_BOOT_EN | \ |
258 | VSC73XX_ICPU_CTRL_EXT_ACC_EN) |
259 | |
260 | #define VSC73XX_ICPU_CTRL_START (VSC73XX_ICPU_CTRL_CLK_DIV | \ |
261 | VSC73XX_ICPU_CTRL_BOOT_EN | \ |
262 | VSC73XX_ICPU_CTRL_CLK_EN | \ |
263 | VSC73XX_ICPU_CTRL_SRST) |
264 | |
265 | #define IS_7385(a) ((a)->chipid == VSC73XX_CHIPID_ID_7385) |
266 | #define IS_7388(a) ((a)->chipid == VSC73XX_CHIPID_ID_7388) |
267 | #define IS_7395(a) ((a)->chipid == VSC73XX_CHIPID_ID_7395) |
268 | #define IS_7398(a) ((a)->chipid == VSC73XX_CHIPID_ID_7398) |
269 | #define IS_739X(a) (IS_7395(a) || IS_7398(a)) |
270 | |
271 | struct vsc73xx_counter { |
272 | u8 counter; |
273 | const char *name; |
274 | }; |
275 | |
276 | /* Counters are named according to the MIB standards where applicable. |
277 | * Some counters are custom, non-standard. The standard counters are |
278 | * named in accordance with RFC2819, RFC2021 and IEEE Std 802.3-2002 Annex |
279 | * 30A Counters. |
280 | */ |
281 | static const struct vsc73xx_counter vsc73xx_rx_counters[] = { |
282 | { 0, "RxEtherStatsPkts" }, |
283 | { 1, "RxBroadcast+MulticastPkts" }, /* non-standard counter */ |
284 | { 2, "RxTotalErrorPackets" }, /* non-standard counter */ |
285 | { 3, "RxEtherStatsBroadcastPkts" }, |
286 | { 4, "RxEtherStatsMulticastPkts" }, |
287 | { 5, "RxEtherStatsPkts64Octets" }, |
288 | { 6, "RxEtherStatsPkts65to127Octets" }, |
289 | { 7, "RxEtherStatsPkts128to255Octets" }, |
290 | { 8, "RxEtherStatsPkts256to511Octets" }, |
291 | { 9, "RxEtherStatsPkts512to1023Octets" }, |
292 | { 10, "RxEtherStatsPkts1024to1518Octets" }, |
293 | { 11, "RxJumboFrames" }, /* non-standard counter */ |
294 | { 12, "RxaPauseMACControlFramesTransmitted" }, |
295 | { 13, "RxFIFODrops" }, /* non-standard counter */ |
296 | { 14, "RxBackwardDrops" }, /* non-standard counter */ |
297 | { 15, "RxClassifierDrops" }, /* non-standard counter */ |
298 | { 16, "RxEtherStatsCRCAlignErrors" }, |
299 | { 17, "RxEtherStatsUndersizePkts" }, |
300 | { 18, "RxEtherStatsOversizePkts" }, |
301 | { 19, "RxEtherStatsFragments" }, |
302 | { 20, "RxEtherStatsJabbers" }, |
303 | { 21, "RxaMACControlFramesReceived" }, |
304 | /* 22-24 are undefined */ |
305 | { 25, "RxaFramesReceivedOK" }, |
306 | { 26, "RxQoSClass0" }, /* non-standard counter */ |
307 | { 27, "RxQoSClass1" }, /* non-standard counter */ |
308 | { 28, "RxQoSClass2" }, /* non-standard counter */ |
309 | { 29, "RxQoSClass3" }, /* non-standard counter */ |
310 | }; |
311 | |
312 | static const struct vsc73xx_counter vsc73xx_tx_counters[] = { |
313 | { 0, "TxEtherStatsPkts" }, |
314 | { 1, "TxBroadcast+MulticastPkts" }, /* non-standard counter */ |
315 | { 2, "TxTotalErrorPackets" }, /* non-standard counter */ |
316 | { 3, "TxEtherStatsBroadcastPkts" }, |
317 | { 4, "TxEtherStatsMulticastPkts" }, |
318 | { 5, "TxEtherStatsPkts64Octets" }, |
319 | { 6, "TxEtherStatsPkts65to127Octets" }, |
320 | { 7, "TxEtherStatsPkts128to255Octets" }, |
321 | { 8, "TxEtherStatsPkts256to511Octets" }, |
322 | { 9, "TxEtherStatsPkts512to1023Octets" }, |
323 | { 10, "TxEtherStatsPkts1024to1518Octets" }, |
324 | { 11, "TxJumboFrames" }, /* non-standard counter */ |
325 | { 12, "TxaPauseMACControlFramesTransmitted" }, |
326 | { 13, "TxFIFODrops" }, /* non-standard counter */ |
327 | { 14, "TxDrops" }, /* non-standard counter */ |
328 | { 15, "TxEtherStatsCollisions" }, |
329 | { 16, "TxEtherStatsCRCAlignErrors" }, |
330 | { 17, "TxEtherStatsUndersizePkts" }, |
331 | { 18, "TxEtherStatsOversizePkts" }, |
332 | { 19, "TxEtherStatsFragments" }, |
333 | { 20, "TxEtherStatsJabbers" }, |
334 | /* 21-24 are undefined */ |
335 | { 25, "TxaFramesReceivedOK" }, |
336 | { 26, "TxQoSClass0" }, /* non-standard counter */ |
337 | { 27, "TxQoSClass1" }, /* non-standard counter */ |
338 | { 28, "TxQoSClass2" }, /* non-standard counter */ |
339 | { 29, "TxQoSClass3" }, /* non-standard counter */ |
340 | }; |
341 | |
342 | int vsc73xx_is_addr_valid(u8 block, u8 subblock) |
343 | { |
344 | switch (block) { |
345 | case VSC73XX_BLOCK_MAC: |
346 | switch (subblock) { |
347 | case 0 ... 4: |
348 | case 6: |
349 | return 1; |
350 | } |
351 | break; |
352 | |
353 | case VSC73XX_BLOCK_ANALYZER: |
354 | case VSC73XX_BLOCK_SYSTEM: |
355 | switch (subblock) { |
356 | case 0: |
357 | return 1; |
358 | } |
359 | break; |
360 | |
361 | case VSC73XX_BLOCK_MII: |
362 | case VSC73XX_BLOCK_CAPTURE: |
363 | case VSC73XX_BLOCK_ARBITER: |
364 | switch (subblock) { |
365 | case 0 ... 1: |
366 | return 1; |
367 | } |
368 | break; |
369 | } |
370 | |
371 | return 0; |
372 | } |
373 | EXPORT_SYMBOL(vsc73xx_is_addr_valid); |
374 | |
375 | static int vsc73xx_read(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, |
376 | u32 *val) |
377 | { |
378 | return vsc->ops->read(vsc, block, subblock, reg, val); |
379 | } |
380 | |
381 | static int vsc73xx_write(struct vsc73xx *vsc, u8 block, u8 subblock, u8 reg, |
382 | u32 val) |
383 | { |
384 | return vsc->ops->write(vsc, block, subblock, reg, val); |
385 | } |
386 | |
387 | static int vsc73xx_update_bits(struct vsc73xx *vsc, u8 block, u8 subblock, |
388 | u8 reg, u32 mask, u32 val) |
389 | { |
390 | u32 tmp, orig; |
391 | int ret; |
392 | |
393 | /* Same read-modify-write algorithm as e.g. regmap */ |
394 | ret = vsc73xx_read(vsc, block, subblock, reg, val: &orig); |
395 | if (ret) |
396 | return ret; |
397 | tmp = orig & ~mask; |
398 | tmp |= val & mask; |
399 | return vsc73xx_write(vsc, block, subblock, reg, val: tmp); |
400 | } |
401 | |
402 | static int vsc73xx_detect(struct vsc73xx *vsc) |
403 | { |
404 | bool icpu_si_boot_en; |
405 | bool icpu_pi_en; |
406 | u32 val; |
407 | u32 rev; |
408 | int ret; |
409 | u32 id; |
410 | |
411 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
412 | VSC73XX_ICPU_MBOX_VAL, val: &val); |
413 | if (ret) { |
414 | dev_err(vsc->dev, "unable to read mailbox (%d)\n" , ret); |
415 | return ret; |
416 | } |
417 | |
418 | if (val == 0xffffffff) { |
419 | dev_info(vsc->dev, "chip seems dead.\n" ); |
420 | return -EAGAIN; |
421 | } |
422 | |
423 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
424 | VSC73XX_CHIPID, val: &val); |
425 | if (ret) { |
426 | dev_err(vsc->dev, "unable to read chip id (%d)\n" , ret); |
427 | return ret; |
428 | } |
429 | |
430 | id = (val >> VSC73XX_CHIPID_ID_SHIFT) & |
431 | VSC73XX_CHIPID_ID_MASK; |
432 | switch (id) { |
433 | case VSC73XX_CHIPID_ID_7385: |
434 | case VSC73XX_CHIPID_ID_7388: |
435 | case VSC73XX_CHIPID_ID_7395: |
436 | case VSC73XX_CHIPID_ID_7398: |
437 | break; |
438 | default: |
439 | dev_err(vsc->dev, "unsupported chip, id=%04x\n" , id); |
440 | return -ENODEV; |
441 | } |
442 | |
443 | vsc->chipid = id; |
444 | rev = (val >> VSC73XX_CHIPID_REV_SHIFT) & |
445 | VSC73XX_CHIPID_REV_MASK; |
446 | dev_info(vsc->dev, "VSC%04X (rev: %d) switch found\n" , id, rev); |
447 | |
448 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
449 | VSC73XX_ICPU_CTRL, val: &val); |
450 | if (ret) { |
451 | dev_err(vsc->dev, "unable to read iCPU control\n" ); |
452 | return ret; |
453 | } |
454 | |
455 | /* The iCPU can always be used but can boot in different ways. |
456 | * If it is initially disabled and has no external memory, |
457 | * we are in control and can do whatever we like, else we |
458 | * are probably in trouble (we need some way to communicate |
459 | * with the running firmware) so we bail out for now. |
460 | */ |
461 | icpu_pi_en = !!(val & VSC73XX_ICPU_CTRL_ICPU_PI_EN); |
462 | icpu_si_boot_en = !!(val & VSC73XX_ICPU_CTRL_BOOT_EN); |
463 | if (icpu_si_boot_en && icpu_pi_en) { |
464 | dev_err(vsc->dev, |
465 | "iCPU enabled boots from SI, has external memory\n" ); |
466 | dev_err(vsc->dev, "no idea how to deal with this\n" ); |
467 | return -ENODEV; |
468 | } |
469 | if (icpu_si_boot_en && !icpu_pi_en) { |
470 | dev_err(vsc->dev, |
471 | "iCPU enabled boots from PI/SI, no external memory\n" ); |
472 | return -EAGAIN; |
473 | } |
474 | if (!icpu_si_boot_en && icpu_pi_en) { |
475 | dev_err(vsc->dev, |
476 | "iCPU enabled, boots from PI external memory\n" ); |
477 | dev_err(vsc->dev, "no idea how to deal with this\n" ); |
478 | return -ENODEV; |
479 | } |
480 | /* !icpu_si_boot_en && !cpu_pi_en */ |
481 | dev_info(vsc->dev, "iCPU disabled, no external memory\n" ); |
482 | |
483 | return 0; |
484 | } |
485 | |
486 | static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum) |
487 | { |
488 | struct vsc73xx *vsc = ds->priv; |
489 | u32 cmd; |
490 | u32 val; |
491 | int ret; |
492 | |
493 | /* Setting bit 26 means "read" */ |
494 | cmd = BIT(26) | (phy << 21) | (regnum << 16); |
495 | ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, subblock: 0, reg: 1, val: cmd); |
496 | if (ret) |
497 | return ret; |
498 | msleep(msecs: 2); |
499 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MII, subblock: 0, reg: 2, val: &val); |
500 | if (ret) |
501 | return ret; |
502 | if (val & BIT(16)) { |
503 | dev_err(vsc->dev, "reading reg %02x from phy%d failed\n" , |
504 | regnum, phy); |
505 | return -EIO; |
506 | } |
507 | val &= 0xFFFFU; |
508 | |
509 | dev_dbg(vsc->dev, "read reg %02x from phy%d = %04x\n" , |
510 | regnum, phy, val); |
511 | |
512 | return val; |
513 | } |
514 | |
515 | static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum, |
516 | u16 val) |
517 | { |
518 | struct vsc73xx *vsc = ds->priv; |
519 | u32 cmd; |
520 | int ret; |
521 | |
522 | /* It was found through tedious experiments that this router |
523 | * chip really hates to have it's PHYs reset. They |
524 | * never recover if that happens: autonegotiation stops |
525 | * working after a reset. Just filter out this command. |
526 | * (Resetting the whole chip is OK.) |
527 | */ |
528 | if (regnum == 0 && (val & BIT(15))) { |
529 | dev_info(vsc->dev, "reset PHY - disallowed\n" ); |
530 | return 0; |
531 | } |
532 | |
533 | cmd = (phy << 21) | (regnum << 16); |
534 | ret = vsc73xx_write(vsc, VSC73XX_BLOCK_MII, subblock: 0, reg: 1, val: cmd); |
535 | if (ret) |
536 | return ret; |
537 | |
538 | dev_dbg(vsc->dev, "write %04x to reg %02x in phy%d\n" , |
539 | val, regnum, phy); |
540 | return 0; |
541 | } |
542 | |
543 | static enum dsa_tag_protocol vsc73xx_get_tag_protocol(struct dsa_switch *ds, |
544 | int port, |
545 | enum dsa_tag_protocol mp) |
546 | { |
547 | /* The switch internally uses a 8 byte header with length, |
548 | * source port, tag, LPA and priority. This is supposedly |
549 | * only accessible when operating the switch using the internal |
550 | * CPU or with an external CPU mapping the device in, but not |
551 | * when operating the switch over SPI and putting frames in/out |
552 | * on port 6 (the CPU port). So far we must assume that we |
553 | * cannot access the tag. (See "Internal frame header" section |
554 | * 3.9.1 in the manual.) |
555 | */ |
556 | return DSA_TAG_PROTO_NONE; |
557 | } |
558 | |
559 | static int vsc73xx_setup(struct dsa_switch *ds) |
560 | { |
561 | struct vsc73xx *vsc = ds->priv; |
562 | int i; |
563 | |
564 | dev_info(vsc->dev, "set up the switch\n" ); |
565 | |
566 | /* Issue RESET */ |
567 | vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, VSC73XX_GLORESET, |
568 | VSC73XX_GLORESET_MASTER_RESET); |
569 | usleep_range(min: 125, max: 200); |
570 | |
571 | /* Initialize memory, initialize RAM bank 0..15 except 6 and 7 |
572 | * This sequence appears in the |
573 | * VSC7385 SparX-G5 datasheet section 6.6.1 |
574 | * VSC7395 SparX-G5e datasheet section 6.6.1 |
575 | * "initialization sequence". |
576 | * No explanation is given to the 0x1010400 magic number. |
577 | */ |
578 | for (i = 0; i <= 15; i++) { |
579 | if (i != 6 && i != 7) { |
580 | vsc73xx_write(vsc, VSC73XX_BLOCK_MEMINIT, |
581 | subblock: 2, |
582 | reg: 0, val: 0x1010400 + i); |
583 | mdelay(1); |
584 | } |
585 | } |
586 | mdelay(30); |
587 | |
588 | /* Clear MAC table */ |
589 | vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, |
590 | VSC73XX_MACACCESS, |
591 | VSC73XX_MACACCESS_CMD_CLEAR_TABLE); |
592 | |
593 | /* Clear VLAN table */ |
594 | vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, |
595 | VSC73XX_VLANACCESS, |
596 | VSC73XX_VLANACCESS_VLAN_TBL_CMD_CLEAR_TABLE); |
597 | |
598 | msleep(msecs: 40); |
599 | |
600 | /* Use 20KiB buffers on all ports on VSC7395 |
601 | * The VSC7385 has 16KiB buffers and that is the |
602 | * default if we don't set this up explicitly. |
603 | * Port "31" is "all ports". |
604 | */ |
605 | if (IS_739X(vsc)) |
606 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: 0x1f, |
607 | VSC73XX_Q_MISC_CONF, |
608 | VSC73XX_Q_MISC_CONF_EXTENT_MEM); |
609 | |
610 | /* Put all ports into reset until enabled */ |
611 | for (i = 0; i < 7; i++) { |
612 | if (i == 5) |
613 | continue; |
614 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: 4, |
615 | VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); |
616 | } |
617 | |
618 | /* MII delay, set both GTX and RX delay to 2 ns */ |
619 | vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, VSC73XX_GMIIDELAY, |
620 | VSC73XX_GMIIDELAY_GMII0_GTXDELAY_2_0_NS | |
621 | VSC73XX_GMIIDELAY_GMII0_RXDELAY_2_0_NS); |
622 | /* Enable reception of frames on all ports */ |
623 | vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, VSC73XX_RECVMASK, |
624 | val: 0x5f); |
625 | /* IP multicast flood mask (table 144) */ |
626 | vsc73xx_write(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, VSC73XX_IFLODMSK, |
627 | val: 0xff); |
628 | |
629 | mdelay(50); |
630 | |
631 | /* Release reset from the internal PHYs */ |
632 | vsc73xx_write(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, VSC73XX_GLORESET, |
633 | VSC73XX_GLORESET_PHY_RESET); |
634 | |
635 | udelay(4); |
636 | |
637 | return 0; |
638 | } |
639 | |
640 | static void vsc73xx_init_port(struct vsc73xx *vsc, int port) |
641 | { |
642 | u32 val; |
643 | |
644 | /* MAC configure, first reset the port and then write defaults */ |
645 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
646 | subblock: port, |
647 | VSC73XX_MAC_CFG, |
648 | VSC73XX_MAC_CFG_RESET); |
649 | |
650 | /* Take up the port in 1Gbit mode by default, this will be |
651 | * augmented after auto-negotiation on the PHY-facing |
652 | * ports. |
653 | */ |
654 | if (port == CPU_PORT) |
655 | val = VSC73XX_MAC_CFG_1000M_F_RGMII; |
656 | else |
657 | val = VSC73XX_MAC_CFG_1000M_F_PHY; |
658 | |
659 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
660 | subblock: port, |
661 | VSC73XX_MAC_CFG, |
662 | val: val | |
663 | VSC73XX_MAC_CFG_TX_EN | |
664 | VSC73XX_MAC_CFG_RX_EN); |
665 | |
666 | /* Flow control for the CPU port: |
667 | * Use a zero delay pause frame when pause condition is left |
668 | * Obey pause control frames |
669 | */ |
670 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
671 | subblock: port, |
672 | VSC73XX_FCCONF, |
673 | VSC73XX_FCCONF_ZERO_PAUSE_EN | |
674 | VSC73XX_FCCONF_FLOW_CTRL_OBEY); |
675 | |
676 | /* Issue pause control frames on PHY facing ports. |
677 | * Allow early initiation of MAC transmission if the amount |
678 | * of egress data is below 512 bytes on CPU port. |
679 | * FIXME: enable 20KiB buffers? |
680 | */ |
681 | if (port == CPU_PORT) |
682 | val = VSC73XX_Q_MISC_CONF_EARLY_TX_512; |
683 | else |
684 | val = VSC73XX_Q_MISC_CONF_MAC_PAUSE_MODE; |
685 | val |= VSC73XX_Q_MISC_CONF_EXTENT_MEM; |
686 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
687 | subblock: port, |
688 | VSC73XX_Q_MISC_CONF, |
689 | val); |
690 | |
691 | /* Flow control MAC: a MAC address used in flow control frames */ |
692 | val = (vsc->addr[5] << 16) | (vsc->addr[4] << 8) | (vsc->addr[3]); |
693 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
694 | subblock: port, |
695 | VSC73XX_FCMACHI, |
696 | val); |
697 | val = (vsc->addr[2] << 16) | (vsc->addr[1] << 8) | (vsc->addr[0]); |
698 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
699 | subblock: port, |
700 | VSC73XX_FCMACLO, |
701 | val); |
702 | |
703 | /* Tell the categorizer to forward pause frames, not control |
704 | * frame. Do not drop anything. |
705 | */ |
706 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
707 | subblock: port, |
708 | VSC73XX_CAT_DROP, |
709 | VSC73XX_CAT_DROP_FWD_PAUSE_ENA); |
710 | |
711 | /* Clear all counters */ |
712 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
713 | subblock: port, VSC73XX_C_RX0, val: 0); |
714 | } |
715 | |
716 | static void vsc73xx_adjust_enable_port(struct vsc73xx *vsc, |
717 | int port, struct phy_device *phydev, |
718 | u32 initval) |
719 | { |
720 | u32 val = initval; |
721 | u8 seed; |
722 | |
723 | /* Reset this port FIXME: break out subroutine */ |
724 | val |= VSC73XX_MAC_CFG_RESET; |
725 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, VSC73XX_MAC_CFG, val); |
726 | |
727 | /* Seed the port randomness with randomness */ |
728 | get_random_bytes(buf: &seed, len: 1); |
729 | val |= seed << VSC73XX_MAC_CFG_SEED_OFFSET; |
730 | val |= VSC73XX_MAC_CFG_SEED_LOAD; |
731 | val |= VSC73XX_MAC_CFG_WEXC_DIS; |
732 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, VSC73XX_MAC_CFG, val); |
733 | |
734 | /* Flow control for the PHY facing ports: |
735 | * Use a zero delay pause frame when pause condition is left |
736 | * Obey pause control frames |
737 | * When generating pause frames, use 0xff as pause value |
738 | */ |
739 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, VSC73XX_FCCONF, |
740 | VSC73XX_FCCONF_ZERO_PAUSE_EN | |
741 | VSC73XX_FCCONF_FLOW_CTRL_OBEY | |
742 | 0xff); |
743 | |
744 | /* Disallow backward dropping of frames from this port */ |
745 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
746 | VSC73XX_SBACKWDROP, BIT(port), val: 0); |
747 | |
748 | /* Enable TX, RX, deassert reset, stop loading seed */ |
749 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
750 | VSC73XX_MAC_CFG, |
751 | VSC73XX_MAC_CFG_RESET | VSC73XX_MAC_CFG_SEED_LOAD | |
752 | VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN, |
753 | VSC73XX_MAC_CFG_TX_EN | VSC73XX_MAC_CFG_RX_EN); |
754 | } |
755 | |
756 | static void vsc73xx_adjust_link(struct dsa_switch *ds, int port, |
757 | struct phy_device *phydev) |
758 | { |
759 | struct vsc73xx *vsc = ds->priv; |
760 | u32 val; |
761 | |
762 | /* Special handling of the CPU-facing port */ |
763 | if (port == CPU_PORT) { |
764 | /* Other ports are already initialized but not this one */ |
765 | vsc73xx_init_port(vsc, CPU_PORT); |
766 | /* Select the external port for this interface (EXT_PORT) |
767 | * Enable the GMII GTX external clock |
768 | * Use double data rate (DDR mode) |
769 | */ |
770 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, |
771 | CPU_PORT, |
772 | VSC73XX_ADVPORTM, |
773 | VSC73XX_ADVPORTM_EXT_PORT | |
774 | VSC73XX_ADVPORTM_ENA_GTX | |
775 | VSC73XX_ADVPORTM_DDR_MODE); |
776 | } |
777 | |
778 | /* This is the MAC confiuration that always need to happen |
779 | * after a PHY or the CPU port comes up or down. |
780 | */ |
781 | if (!phydev->link) { |
782 | int maxloop = 10; |
783 | |
784 | dev_dbg(vsc->dev, "port %d: went down\n" , |
785 | port); |
786 | |
787 | /* Disable RX on this port */ |
788 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
789 | VSC73XX_MAC_CFG, |
790 | VSC73XX_MAC_CFG_RX_EN, val: 0); |
791 | |
792 | /* Discard packets */ |
793 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
794 | VSC73XX_ARBDISC, BIT(port), BIT(port)); |
795 | |
796 | /* Wait until queue is empty */ |
797 | vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
798 | VSC73XX_ARBEMPTY, val: &val); |
799 | while (!(val & BIT(port))) { |
800 | msleep(msecs: 1); |
801 | vsc73xx_read(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
802 | VSC73XX_ARBEMPTY, val: &val); |
803 | if (--maxloop == 0) { |
804 | dev_err(vsc->dev, |
805 | "timeout waiting for block arbiter\n" ); |
806 | /* Continue anyway */ |
807 | break; |
808 | } |
809 | } |
810 | |
811 | /* Put this port into reset */ |
812 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, VSC73XX_MAC_CFG, |
813 | VSC73XX_MAC_CFG_RESET); |
814 | |
815 | /* Accept packets again */ |
816 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
817 | VSC73XX_ARBDISC, BIT(port), val: 0); |
818 | |
819 | /* Allow backward dropping of frames from this port */ |
820 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ARBITER, subblock: 0, |
821 | VSC73XX_SBACKWDROP, BIT(port), BIT(port)); |
822 | |
823 | /* Receive mask (disable forwarding) */ |
824 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, |
825 | VSC73XX_RECVMASK, BIT(port), val: 0); |
826 | |
827 | return; |
828 | } |
829 | |
830 | /* Figure out what speed was negotiated */ |
831 | if (phydev->speed == SPEED_1000) { |
832 | dev_dbg(vsc->dev, "port %d: 1000 Mbit mode full duplex\n" , |
833 | port); |
834 | |
835 | /* Set up default for internal port or external RGMII */ |
836 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII) |
837 | val = VSC73XX_MAC_CFG_1000M_F_RGMII; |
838 | else |
839 | val = VSC73XX_MAC_CFG_1000M_F_PHY; |
840 | vsc73xx_adjust_enable_port(vsc, port, phydev, initval: val); |
841 | } else if (phydev->speed == SPEED_100) { |
842 | if (phydev->duplex == DUPLEX_FULL) { |
843 | val = VSC73XX_MAC_CFG_100_10M_F_PHY; |
844 | dev_dbg(vsc->dev, |
845 | "port %d: 100 Mbit full duplex mode\n" , |
846 | port); |
847 | } else { |
848 | val = VSC73XX_MAC_CFG_100_10M_H_PHY; |
849 | dev_dbg(vsc->dev, |
850 | "port %d: 100 Mbit half duplex mode\n" , |
851 | port); |
852 | } |
853 | vsc73xx_adjust_enable_port(vsc, port, phydev, initval: val); |
854 | } else if (phydev->speed == SPEED_10) { |
855 | if (phydev->duplex == DUPLEX_FULL) { |
856 | val = VSC73XX_MAC_CFG_100_10M_F_PHY; |
857 | dev_dbg(vsc->dev, |
858 | "port %d: 10 Mbit full duplex mode\n" , |
859 | port); |
860 | } else { |
861 | val = VSC73XX_MAC_CFG_100_10M_H_PHY; |
862 | dev_dbg(vsc->dev, |
863 | "port %d: 10 Mbit half duplex mode\n" , |
864 | port); |
865 | } |
866 | vsc73xx_adjust_enable_port(vsc, port, phydev, initval: val); |
867 | } else { |
868 | dev_err(vsc->dev, |
869 | "could not adjust link: unknown speed\n" ); |
870 | } |
871 | |
872 | /* Enable port (forwarding) in the receieve mask */ |
873 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_ANALYZER, subblock: 0, |
874 | VSC73XX_RECVMASK, BIT(port), BIT(port)); |
875 | } |
876 | |
877 | static int vsc73xx_port_enable(struct dsa_switch *ds, int port, |
878 | struct phy_device *phy) |
879 | { |
880 | struct vsc73xx *vsc = ds->priv; |
881 | |
882 | dev_info(vsc->dev, "enable port %d\n" , port); |
883 | vsc73xx_init_port(vsc, port); |
884 | |
885 | return 0; |
886 | } |
887 | |
888 | static void vsc73xx_port_disable(struct dsa_switch *ds, int port) |
889 | { |
890 | struct vsc73xx *vsc = ds->priv; |
891 | |
892 | /* Just put the port into reset */ |
893 | vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
894 | VSC73XX_MAC_CFG, VSC73XX_MAC_CFG_RESET); |
895 | } |
896 | |
897 | static const struct vsc73xx_counter * |
898 | vsc73xx_find_counter(struct vsc73xx *vsc, |
899 | u8 counter, |
900 | bool tx) |
901 | { |
902 | const struct vsc73xx_counter *cnts; |
903 | int num_cnts; |
904 | int i; |
905 | |
906 | if (tx) { |
907 | cnts = vsc73xx_tx_counters; |
908 | num_cnts = ARRAY_SIZE(vsc73xx_tx_counters); |
909 | } else { |
910 | cnts = vsc73xx_rx_counters; |
911 | num_cnts = ARRAY_SIZE(vsc73xx_rx_counters); |
912 | } |
913 | |
914 | for (i = 0; i < num_cnts; i++) { |
915 | const struct vsc73xx_counter *cnt; |
916 | |
917 | cnt = &cnts[i]; |
918 | if (cnt->counter == counter) |
919 | return cnt; |
920 | } |
921 | |
922 | return NULL; |
923 | } |
924 | |
925 | static void vsc73xx_get_strings(struct dsa_switch *ds, int port, u32 stringset, |
926 | uint8_t *data) |
927 | { |
928 | const struct vsc73xx_counter *cnt; |
929 | struct vsc73xx *vsc = ds->priv; |
930 | u8 indices[6]; |
931 | u8 *buf = data; |
932 | int i; |
933 | u32 val; |
934 | int ret; |
935 | |
936 | if (stringset != ETH_SS_STATS) |
937 | return; |
938 | |
939 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
940 | VSC73XX_C_CFG, val: &val); |
941 | if (ret) |
942 | return; |
943 | |
944 | indices[0] = (val & 0x1f); /* RX counter 0 */ |
945 | indices[1] = ((val >> 5) & 0x1f); /* RX counter 1 */ |
946 | indices[2] = ((val >> 10) & 0x1f); /* RX counter 2 */ |
947 | indices[3] = ((val >> 16) & 0x1f); /* TX counter 0 */ |
948 | indices[4] = ((val >> 21) & 0x1f); /* TX counter 1 */ |
949 | indices[5] = ((val >> 26) & 0x1f); /* TX counter 2 */ |
950 | |
951 | /* The first counters is the RX octets */ |
952 | ethtool_puts(data: &buf, str: "RxEtherStatsOctets" ); |
953 | |
954 | /* Each port supports recording 3 RX counters and 3 TX counters, |
955 | * figure out what counters we use in this set-up and return the |
956 | * names of them. The hardware default counters will be number of |
957 | * packets on RX/TX, combined broadcast+multicast packets RX/TX and |
958 | * total error packets RX/TX. |
959 | */ |
960 | for (i = 0; i < 3; i++) { |
961 | cnt = vsc73xx_find_counter(vsc, counter: indices[i], tx: false); |
962 | ethtool_puts(data: &buf, str: cnt ? cnt->name : "" ); |
963 | } |
964 | |
965 | /* TX stats begins with the number of TX octets */ |
966 | ethtool_puts(data: &buf, str: "TxEtherStatsOctets" ); |
967 | |
968 | for (i = 3; i < 6; i++) { |
969 | cnt = vsc73xx_find_counter(vsc, counter: indices[i], tx: true); |
970 | ethtool_puts(data: &buf, str: cnt ? cnt->name : "" ); |
971 | |
972 | } |
973 | } |
974 | |
975 | static int vsc73xx_get_sset_count(struct dsa_switch *ds, int port, int sset) |
976 | { |
977 | /* We only support SS_STATS */ |
978 | if (sset != ETH_SS_STATS) |
979 | return 0; |
980 | /* RX and TX packets, then 3 RX counters, 3 TX counters */ |
981 | return 8; |
982 | } |
983 | |
984 | static void vsc73xx_get_ethtool_stats(struct dsa_switch *ds, int port, |
985 | uint64_t *data) |
986 | { |
987 | struct vsc73xx *vsc = ds->priv; |
988 | u8 regs[] = { |
989 | VSC73XX_RXOCT, |
990 | VSC73XX_C_RX0, |
991 | VSC73XX_C_RX1, |
992 | VSC73XX_C_RX2, |
993 | VSC73XX_TXOCT, |
994 | VSC73XX_C_TX0, |
995 | VSC73XX_C_TX1, |
996 | VSC73XX_C_TX2, |
997 | }; |
998 | u32 val; |
999 | int ret; |
1000 | int i; |
1001 | |
1002 | for (i = 0; i < ARRAY_SIZE(regs); i++) { |
1003 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
1004 | reg: regs[i], val: &val); |
1005 | if (ret) { |
1006 | dev_err(vsc->dev, "error reading counter %d\n" , i); |
1007 | return; |
1008 | } |
1009 | data[i] = val; |
1010 | } |
1011 | } |
1012 | |
1013 | static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) |
1014 | { |
1015 | struct vsc73xx *vsc = ds->priv; |
1016 | |
1017 | return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, subblock: port, |
1018 | VSC73XX_MAXLEN, val: new_mtu + ETH_HLEN + ETH_FCS_LEN); |
1019 | } |
1020 | |
1021 | /* According to application not "VSC7398 Jumbo Frames" setting |
1022 | * up the frame size to 9.6 KB does not affect the performance on standard |
1023 | * frames. It is clear from the application note that |
1024 | * "9.6 kilobytes" == 9600 bytes. |
1025 | */ |
1026 | static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port) |
1027 | { |
1028 | return 9600 - ETH_HLEN - ETH_FCS_LEN; |
1029 | } |
1030 | |
1031 | static void vsc73xx_phylink_get_caps(struct dsa_switch *dsa, int port, |
1032 | struct phylink_config *config) |
1033 | { |
1034 | unsigned long *interfaces = config->supported_interfaces; |
1035 | |
1036 | if (port == 5) |
1037 | return; |
1038 | |
1039 | if (port == CPU_PORT) { |
1040 | __set_bit(PHY_INTERFACE_MODE_MII, interfaces); |
1041 | __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); |
1042 | __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); |
1043 | __set_bit(PHY_INTERFACE_MODE_RGMII, interfaces); |
1044 | } |
1045 | |
1046 | if (port <= 4) { |
1047 | /* Internal PHYs */ |
1048 | __set_bit(PHY_INTERFACE_MODE_INTERNAL, interfaces); |
1049 | /* phylib default */ |
1050 | __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); |
1051 | } |
1052 | |
1053 | config->mac_capabilities = MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000; |
1054 | } |
1055 | |
1056 | static const struct dsa_switch_ops vsc73xx_ds_ops = { |
1057 | .get_tag_protocol = vsc73xx_get_tag_protocol, |
1058 | .setup = vsc73xx_setup, |
1059 | .phy_read = vsc73xx_phy_read, |
1060 | .phy_write = vsc73xx_phy_write, |
1061 | .adjust_link = vsc73xx_adjust_link, |
1062 | .get_strings = vsc73xx_get_strings, |
1063 | .get_ethtool_stats = vsc73xx_get_ethtool_stats, |
1064 | .get_sset_count = vsc73xx_get_sset_count, |
1065 | .port_enable = vsc73xx_port_enable, |
1066 | .port_disable = vsc73xx_port_disable, |
1067 | .port_change_mtu = vsc73xx_change_mtu, |
1068 | .port_max_mtu = vsc73xx_get_max_mtu, |
1069 | .phylink_get_caps = vsc73xx_phylink_get_caps, |
1070 | }; |
1071 | |
1072 | static int vsc73xx_gpio_get(struct gpio_chip *chip, unsigned int offset) |
1073 | { |
1074 | struct vsc73xx *vsc = gpiochip_get_data(gc: chip); |
1075 | u32 val; |
1076 | int ret; |
1077 | |
1078 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
1079 | VSC73XX_GPIO, val: &val); |
1080 | if (ret) |
1081 | return ret; |
1082 | |
1083 | return !!(val & BIT(offset)); |
1084 | } |
1085 | |
1086 | static void vsc73xx_gpio_set(struct gpio_chip *chip, unsigned int offset, |
1087 | int val) |
1088 | { |
1089 | struct vsc73xx *vsc = gpiochip_get_data(gc: chip); |
1090 | u32 tmp = val ? BIT(offset) : 0; |
1091 | |
1092 | vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
1093 | VSC73XX_GPIO, BIT(offset), val: tmp); |
1094 | } |
1095 | |
1096 | static int vsc73xx_gpio_direction_output(struct gpio_chip *chip, |
1097 | unsigned int offset, int val) |
1098 | { |
1099 | struct vsc73xx *vsc = gpiochip_get_data(gc: chip); |
1100 | u32 tmp = val ? BIT(offset) : 0; |
1101 | |
1102 | return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
1103 | VSC73XX_GPIO, BIT(offset + 4) | BIT(offset), |
1104 | BIT(offset + 4) | tmp); |
1105 | } |
1106 | |
1107 | static int vsc73xx_gpio_direction_input(struct gpio_chip *chip, |
1108 | unsigned int offset) |
1109 | { |
1110 | struct vsc73xx *vsc = gpiochip_get_data(gc: chip); |
1111 | |
1112 | return vsc73xx_update_bits(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
1113 | VSC73XX_GPIO, BIT(offset + 4), |
1114 | val: 0); |
1115 | } |
1116 | |
1117 | static int vsc73xx_gpio_get_direction(struct gpio_chip *chip, |
1118 | unsigned int offset) |
1119 | { |
1120 | struct vsc73xx *vsc = gpiochip_get_data(gc: chip); |
1121 | u32 val; |
1122 | int ret; |
1123 | |
1124 | ret = vsc73xx_read(vsc, VSC73XX_BLOCK_SYSTEM, subblock: 0, |
1125 | VSC73XX_GPIO, val: &val); |
1126 | if (ret) |
1127 | return ret; |
1128 | |
1129 | return !(val & BIT(offset + 4)); |
1130 | } |
1131 | |
1132 | static int vsc73xx_gpio_probe(struct vsc73xx *vsc) |
1133 | { |
1134 | int ret; |
1135 | |
1136 | vsc->gc.label = devm_kasprintf(dev: vsc->dev, GFP_KERNEL, fmt: "VSC%04x" , |
1137 | vsc->chipid); |
1138 | if (!vsc->gc.label) |
1139 | return -ENOMEM; |
1140 | vsc->gc.ngpio = 4; |
1141 | vsc->gc.owner = THIS_MODULE; |
1142 | vsc->gc.parent = vsc->dev; |
1143 | vsc->gc.base = -1; |
1144 | vsc->gc.get = vsc73xx_gpio_get; |
1145 | vsc->gc.set = vsc73xx_gpio_set; |
1146 | vsc->gc.direction_input = vsc73xx_gpio_direction_input; |
1147 | vsc->gc.direction_output = vsc73xx_gpio_direction_output; |
1148 | vsc->gc.get_direction = vsc73xx_gpio_get_direction; |
1149 | vsc->gc.can_sleep = true; |
1150 | ret = devm_gpiochip_add_data(vsc->dev, &vsc->gc, vsc); |
1151 | if (ret) { |
1152 | dev_err(vsc->dev, "unable to register GPIO chip\n" ); |
1153 | return ret; |
1154 | } |
1155 | return 0; |
1156 | } |
1157 | |
1158 | int vsc73xx_probe(struct vsc73xx *vsc) |
1159 | { |
1160 | struct device *dev = vsc->dev; |
1161 | int ret; |
1162 | |
1163 | /* Release reset, if any */ |
1164 | vsc->reset = devm_gpiod_get_optional(dev, con_id: "reset" , flags: GPIOD_OUT_LOW); |
1165 | if (IS_ERR(ptr: vsc->reset)) { |
1166 | dev_err(dev, "failed to get RESET GPIO\n" ); |
1167 | return PTR_ERR(ptr: vsc->reset); |
1168 | } |
1169 | if (vsc->reset) |
1170 | /* Wait 20ms according to datasheet table 245 */ |
1171 | msleep(msecs: 20); |
1172 | |
1173 | ret = vsc73xx_detect(vsc); |
1174 | if (ret == -EAGAIN) { |
1175 | dev_err(vsc->dev, |
1176 | "Chip seems to be out of control. Assert reset and try again.\n" ); |
1177 | gpiod_set_value_cansleep(desc: vsc->reset, value: 1); |
1178 | /* Reset pulse should be 20ns minimum, according to datasheet |
1179 | * table 245, so 10us should be fine |
1180 | */ |
1181 | usleep_range(min: 10, max: 100); |
1182 | gpiod_set_value_cansleep(desc: vsc->reset, value: 0); |
1183 | /* Wait 20ms according to datasheet table 245 */ |
1184 | msleep(msecs: 20); |
1185 | ret = vsc73xx_detect(vsc); |
1186 | } |
1187 | if (ret) { |
1188 | dev_err(dev, "no chip found (%d)\n" , ret); |
1189 | return -ENODEV; |
1190 | } |
1191 | |
1192 | eth_random_addr(addr: vsc->addr); |
1193 | dev_info(vsc->dev, |
1194 | "MAC for control frames: %02X:%02X:%02X:%02X:%02X:%02X\n" , |
1195 | vsc->addr[0], vsc->addr[1], vsc->addr[2], |
1196 | vsc->addr[3], vsc->addr[4], vsc->addr[5]); |
1197 | |
1198 | /* The VSC7395 switch chips have 5+1 ports which means 5 |
1199 | * ordinary ports and a sixth CPU port facing the processor |
1200 | * with an RGMII interface. These ports are numbered 0..4 |
1201 | * and 6, so they leave a "hole" in the port map for port 5, |
1202 | * which is invalid. |
1203 | * |
1204 | * The VSC7398 has 8 ports, port 7 is again the CPU port. |
1205 | * |
1206 | * We allocate 8 ports and avoid access to the nonexistant |
1207 | * ports. |
1208 | */ |
1209 | vsc->ds = devm_kzalloc(dev, size: sizeof(*vsc->ds), GFP_KERNEL); |
1210 | if (!vsc->ds) |
1211 | return -ENOMEM; |
1212 | |
1213 | vsc->ds->dev = dev; |
1214 | vsc->ds->num_ports = 8; |
1215 | vsc->ds->priv = vsc; |
1216 | |
1217 | vsc->ds->ops = &vsc73xx_ds_ops; |
1218 | ret = dsa_register_switch(ds: vsc->ds); |
1219 | if (ret) { |
1220 | dev_err(dev, "unable to register switch (%d)\n" , ret); |
1221 | return ret; |
1222 | } |
1223 | |
1224 | ret = vsc73xx_gpio_probe(vsc); |
1225 | if (ret) { |
1226 | dsa_unregister_switch(ds: vsc->ds); |
1227 | return ret; |
1228 | } |
1229 | |
1230 | return 0; |
1231 | } |
1232 | EXPORT_SYMBOL(vsc73xx_probe); |
1233 | |
1234 | void vsc73xx_remove(struct vsc73xx *vsc) |
1235 | { |
1236 | dsa_unregister_switch(ds: vsc->ds); |
1237 | gpiod_set_value(desc: vsc->reset, value: 1); |
1238 | } |
1239 | EXPORT_SYMBOL(vsc73xx_remove); |
1240 | |
1241 | void vsc73xx_shutdown(struct vsc73xx *vsc) |
1242 | { |
1243 | dsa_switch_shutdown(ds: vsc->ds); |
1244 | } |
1245 | EXPORT_SYMBOL(vsc73xx_shutdown); |
1246 | |
1247 | MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>" ); |
1248 | MODULE_DESCRIPTION("Vitesse VSC7385/7388/7395/7398 driver" ); |
1249 | MODULE_LICENSE("GPL v2" ); |
1250 | |