xref: /linux/drivers/net/ethernet/mscc/ocelot_vsc7514.c (revision dec1c62e91ba268ab2a6e339d4d7a59287d5eba1)
1 // SPDX-License-Identifier: (GPL-2.0 OR MIT)
2 /*
3  * Microsemi Ocelot Switch driver
4  *
5  * Copyright (c) 2017 Microsemi Corporation
6  */
7 #include <linux/dsa/ocelot.h>
8 #include <linux/interrupt.h>
9 #include <linux/module.h>
10 #include <linux/of_net.h>
11 #include <linux/netdevice.h>
12 #include <linux/phylink.h>
13 #include <linux/of_mdio.h>
14 #include <linux/of_platform.h>
15 #include <linux/mfd/syscon.h>
16 #include <linux/skbuff.h>
17 #include <net/switchdev.h>
18 
19 #include <soc/mscc/ocelot_vcap.h>
20 #include <soc/mscc/ocelot_hsio.h>
21 #include <soc/mscc/vsc7514_regs.h>
22 #include "ocelot_fdma.h"
23 #include "ocelot.h"
24 
25 #define VSC7514_VCAP_POLICER_BASE			128
26 #define VSC7514_VCAP_POLICER_MAX			191
27 
28 static const u32 *ocelot_regmap[TARGET_MAX] = {
29 	[ANA] = vsc7514_ana_regmap,
30 	[QS] = vsc7514_qs_regmap,
31 	[QSYS] = vsc7514_qsys_regmap,
32 	[REW] = vsc7514_rew_regmap,
33 	[SYS] = vsc7514_sys_regmap,
34 	[S0] = vsc7514_vcap_regmap,
35 	[S1] = vsc7514_vcap_regmap,
36 	[S2] = vsc7514_vcap_regmap,
37 	[PTP] = vsc7514_ptp_regmap,
38 	[DEV_GMII] = vsc7514_dev_gmii_regmap,
39 };
40 
41 static const struct reg_field ocelot_regfields[REGFIELD_MAX] = {
42 	[ANA_ADVLEARN_VLAN_CHK] = REG_FIELD(ANA_ADVLEARN, 11, 11),
43 	[ANA_ADVLEARN_LEARN_MIRROR] = REG_FIELD(ANA_ADVLEARN, 0, 10),
44 	[ANA_ANEVENTS_MSTI_DROP] = REG_FIELD(ANA_ANEVENTS, 27, 27),
45 	[ANA_ANEVENTS_ACLKILL] = REG_FIELD(ANA_ANEVENTS, 26, 26),
46 	[ANA_ANEVENTS_ACLUSED] = REG_FIELD(ANA_ANEVENTS, 25, 25),
47 	[ANA_ANEVENTS_AUTOAGE] = REG_FIELD(ANA_ANEVENTS, 24, 24),
48 	[ANA_ANEVENTS_VS2TTL1] = REG_FIELD(ANA_ANEVENTS, 23, 23),
49 	[ANA_ANEVENTS_STORM_DROP] = REG_FIELD(ANA_ANEVENTS, 22, 22),
50 	[ANA_ANEVENTS_LEARN_DROP] = REG_FIELD(ANA_ANEVENTS, 21, 21),
51 	[ANA_ANEVENTS_AGED_ENTRY] = REG_FIELD(ANA_ANEVENTS, 20, 20),
52 	[ANA_ANEVENTS_CPU_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 19, 19),
53 	[ANA_ANEVENTS_AUTO_LEARN_FAILED] = REG_FIELD(ANA_ANEVENTS, 18, 18),
54 	[ANA_ANEVENTS_LEARN_REMOVE] = REG_FIELD(ANA_ANEVENTS, 17, 17),
55 	[ANA_ANEVENTS_AUTO_LEARNED] = REG_FIELD(ANA_ANEVENTS, 16, 16),
56 	[ANA_ANEVENTS_AUTO_MOVED] = REG_FIELD(ANA_ANEVENTS, 15, 15),
57 	[ANA_ANEVENTS_DROPPED] = REG_FIELD(ANA_ANEVENTS, 14, 14),
58 	[ANA_ANEVENTS_CLASSIFIED_DROP] = REG_FIELD(ANA_ANEVENTS, 13, 13),
59 	[ANA_ANEVENTS_CLASSIFIED_COPY] = REG_FIELD(ANA_ANEVENTS, 12, 12),
60 	[ANA_ANEVENTS_VLAN_DISCARD] = REG_FIELD(ANA_ANEVENTS, 11, 11),
61 	[ANA_ANEVENTS_FWD_DISCARD] = REG_FIELD(ANA_ANEVENTS, 10, 10),
62 	[ANA_ANEVENTS_MULTICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 9, 9),
63 	[ANA_ANEVENTS_UNICAST_FLOOD] = REG_FIELD(ANA_ANEVENTS, 8, 8),
64 	[ANA_ANEVENTS_DEST_KNOWN] = REG_FIELD(ANA_ANEVENTS, 7, 7),
65 	[ANA_ANEVENTS_BUCKET3_MATCH] = REG_FIELD(ANA_ANEVENTS, 6, 6),
66 	[ANA_ANEVENTS_BUCKET2_MATCH] = REG_FIELD(ANA_ANEVENTS, 5, 5),
67 	[ANA_ANEVENTS_BUCKET1_MATCH] = REG_FIELD(ANA_ANEVENTS, 4, 4),
68 	[ANA_ANEVENTS_BUCKET0_MATCH] = REG_FIELD(ANA_ANEVENTS, 3, 3),
69 	[ANA_ANEVENTS_CPU_OPERATION] = REG_FIELD(ANA_ANEVENTS, 2, 2),
70 	[ANA_ANEVENTS_DMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 1, 1),
71 	[ANA_ANEVENTS_SMAC_LOOKUP] = REG_FIELD(ANA_ANEVENTS, 0, 0),
72 	[ANA_TABLES_MACACCESS_B_DOM] = REG_FIELD(ANA_TABLES_MACACCESS, 18, 18),
73 	[ANA_TABLES_MACTINDX_BUCKET] = REG_FIELD(ANA_TABLES_MACTINDX, 10, 11),
74 	[ANA_TABLES_MACTINDX_M_INDEX] = REG_FIELD(ANA_TABLES_MACTINDX, 0, 9),
75 	[QSYS_TIMED_FRAME_ENTRY_TFRM_VLD] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 20, 20),
76 	[QSYS_TIMED_FRAME_ENTRY_TFRM_FP] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 8, 19),
77 	[QSYS_TIMED_FRAME_ENTRY_TFRM_PORTNO] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 4, 7),
78 	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_SEL] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 1, 3),
79 	[QSYS_TIMED_FRAME_ENTRY_TFRM_TM_T] = REG_FIELD(QSYS_TIMED_FRAME_ENTRY, 0, 0),
80 	[SYS_RESET_CFG_CORE_ENA] = REG_FIELD(SYS_RESET_CFG, 2, 2),
81 	[SYS_RESET_CFG_MEM_ENA] = REG_FIELD(SYS_RESET_CFG, 1, 1),
82 	[SYS_RESET_CFG_MEM_INIT] = REG_FIELD(SYS_RESET_CFG, 0, 0),
83 	/* Replicated per number of ports (12), register size 4 per port */
84 	[QSYS_SWITCH_PORT_MODE_PORT_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 14, 14, 12, 4),
85 	[QSYS_SWITCH_PORT_MODE_SCH_NEXT_CFG] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 11, 13, 12, 4),
86 	[QSYS_SWITCH_PORT_MODE_YEL_RSRVD] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 10, 10, 12, 4),
87 	[QSYS_SWITCH_PORT_MODE_INGRESS_DROP_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 9, 9, 12, 4),
88 	[QSYS_SWITCH_PORT_MODE_TX_PFC_ENA] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 1, 8, 12, 4),
89 	[QSYS_SWITCH_PORT_MODE_TX_PFC_MODE] = REG_FIELD_ID(QSYS_SWITCH_PORT_MODE, 0, 0, 12, 4),
90 	[SYS_PORT_MODE_DATA_WO_TS] = REG_FIELD_ID(SYS_PORT_MODE, 5, 6, 12, 4),
91 	[SYS_PORT_MODE_INCL_INJ_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 3, 4, 12, 4),
92 	[SYS_PORT_MODE_INCL_XTR_HDR] = REG_FIELD_ID(SYS_PORT_MODE, 1, 2, 12, 4),
93 	[SYS_PORT_MODE_INCL_HDR_ERR] = REG_FIELD_ID(SYS_PORT_MODE, 0, 0, 12, 4),
94 	[SYS_PAUSE_CFG_PAUSE_START] = REG_FIELD_ID(SYS_PAUSE_CFG, 10, 18, 12, 4),
95 	[SYS_PAUSE_CFG_PAUSE_STOP] = REG_FIELD_ID(SYS_PAUSE_CFG, 1, 9, 12, 4),
96 	[SYS_PAUSE_CFG_PAUSE_ENA] = REG_FIELD_ID(SYS_PAUSE_CFG, 0, 1, 12, 4),
97 };
98 
99 static const struct ocelot_stat_layout ocelot_stats_layout[] = {
100 	{ .name = "rx_octets", .offset = 0x00, },
101 	{ .name = "rx_unicast", .offset = 0x01, },
102 	{ .name = "rx_multicast", .offset = 0x02, },
103 	{ .name = "rx_broadcast", .offset = 0x03, },
104 	{ .name = "rx_shorts", .offset = 0x04, },
105 	{ .name = "rx_fragments", .offset = 0x05, },
106 	{ .name = "rx_jabbers", .offset = 0x06, },
107 	{ .name = "rx_crc_align_errs", .offset = 0x07, },
108 	{ .name = "rx_sym_errs", .offset = 0x08, },
109 	{ .name = "rx_frames_below_65_octets", .offset = 0x09, },
110 	{ .name = "rx_frames_65_to_127_octets", .offset = 0x0A, },
111 	{ .name = "rx_frames_128_to_255_octets", .offset = 0x0B, },
112 	{ .name = "rx_frames_256_to_511_octets", .offset = 0x0C, },
113 	{ .name = "rx_frames_512_to_1023_octets", .offset = 0x0D, },
114 	{ .name = "rx_frames_1024_to_1526_octets", .offset = 0x0E, },
115 	{ .name = "rx_frames_over_1526_octets", .offset = 0x0F, },
116 	{ .name = "rx_pause", .offset = 0x10, },
117 	{ .name = "rx_control", .offset = 0x11, },
118 	{ .name = "rx_longs", .offset = 0x12, },
119 	{ .name = "rx_classified_drops", .offset = 0x13, },
120 	{ .name = "rx_red_prio_0", .offset = 0x14, },
121 	{ .name = "rx_red_prio_1", .offset = 0x15, },
122 	{ .name = "rx_red_prio_2", .offset = 0x16, },
123 	{ .name = "rx_red_prio_3", .offset = 0x17, },
124 	{ .name = "rx_red_prio_4", .offset = 0x18, },
125 	{ .name = "rx_red_prio_5", .offset = 0x19, },
126 	{ .name = "rx_red_prio_6", .offset = 0x1A, },
127 	{ .name = "rx_red_prio_7", .offset = 0x1B, },
128 	{ .name = "rx_yellow_prio_0", .offset = 0x1C, },
129 	{ .name = "rx_yellow_prio_1", .offset = 0x1D, },
130 	{ .name = "rx_yellow_prio_2", .offset = 0x1E, },
131 	{ .name = "rx_yellow_prio_3", .offset = 0x1F, },
132 	{ .name = "rx_yellow_prio_4", .offset = 0x20, },
133 	{ .name = "rx_yellow_prio_5", .offset = 0x21, },
134 	{ .name = "rx_yellow_prio_6", .offset = 0x22, },
135 	{ .name = "rx_yellow_prio_7", .offset = 0x23, },
136 	{ .name = "rx_green_prio_0", .offset = 0x24, },
137 	{ .name = "rx_green_prio_1", .offset = 0x25, },
138 	{ .name = "rx_green_prio_2", .offset = 0x26, },
139 	{ .name = "rx_green_prio_3", .offset = 0x27, },
140 	{ .name = "rx_green_prio_4", .offset = 0x28, },
141 	{ .name = "rx_green_prio_5", .offset = 0x29, },
142 	{ .name = "rx_green_prio_6", .offset = 0x2A, },
143 	{ .name = "rx_green_prio_7", .offset = 0x2B, },
144 	{ .name = "tx_octets", .offset = 0x40, },
145 	{ .name = "tx_unicast", .offset = 0x41, },
146 	{ .name = "tx_multicast", .offset = 0x42, },
147 	{ .name = "tx_broadcast", .offset = 0x43, },
148 	{ .name = "tx_collision", .offset = 0x44, },
149 	{ .name = "tx_drops", .offset = 0x45, },
150 	{ .name = "tx_pause", .offset = 0x46, },
151 	{ .name = "tx_frames_below_65_octets", .offset = 0x47, },
152 	{ .name = "tx_frames_65_to_127_octets", .offset = 0x48, },
153 	{ .name = "tx_frames_128_255_octets", .offset = 0x49, },
154 	{ .name = "tx_frames_256_511_octets", .offset = 0x4A, },
155 	{ .name = "tx_frames_512_1023_octets", .offset = 0x4B, },
156 	{ .name = "tx_frames_1024_1526_octets", .offset = 0x4C, },
157 	{ .name = "tx_frames_over_1526_octets", .offset = 0x4D, },
158 	{ .name = "tx_yellow_prio_0", .offset = 0x4E, },
159 	{ .name = "tx_yellow_prio_1", .offset = 0x4F, },
160 	{ .name = "tx_yellow_prio_2", .offset = 0x50, },
161 	{ .name = "tx_yellow_prio_3", .offset = 0x51, },
162 	{ .name = "tx_yellow_prio_4", .offset = 0x52, },
163 	{ .name = "tx_yellow_prio_5", .offset = 0x53, },
164 	{ .name = "tx_yellow_prio_6", .offset = 0x54, },
165 	{ .name = "tx_yellow_prio_7", .offset = 0x55, },
166 	{ .name = "tx_green_prio_0", .offset = 0x56, },
167 	{ .name = "tx_green_prio_1", .offset = 0x57, },
168 	{ .name = "tx_green_prio_2", .offset = 0x58, },
169 	{ .name = "tx_green_prio_3", .offset = 0x59, },
170 	{ .name = "tx_green_prio_4", .offset = 0x5A, },
171 	{ .name = "tx_green_prio_5", .offset = 0x5B, },
172 	{ .name = "tx_green_prio_6", .offset = 0x5C, },
173 	{ .name = "tx_green_prio_7", .offset = 0x5D, },
174 	{ .name = "tx_aged", .offset = 0x5E, },
175 	{ .name = "drop_local", .offset = 0x80, },
176 	{ .name = "drop_tail", .offset = 0x81, },
177 	{ .name = "drop_yellow_prio_0", .offset = 0x82, },
178 	{ .name = "drop_yellow_prio_1", .offset = 0x83, },
179 	{ .name = "drop_yellow_prio_2", .offset = 0x84, },
180 	{ .name = "drop_yellow_prio_3", .offset = 0x85, },
181 	{ .name = "drop_yellow_prio_4", .offset = 0x86, },
182 	{ .name = "drop_yellow_prio_5", .offset = 0x87, },
183 	{ .name = "drop_yellow_prio_6", .offset = 0x88, },
184 	{ .name = "drop_yellow_prio_7", .offset = 0x89, },
185 	{ .name = "drop_green_prio_0", .offset = 0x8A, },
186 	{ .name = "drop_green_prio_1", .offset = 0x8B, },
187 	{ .name = "drop_green_prio_2", .offset = 0x8C, },
188 	{ .name = "drop_green_prio_3", .offset = 0x8D, },
189 	{ .name = "drop_green_prio_4", .offset = 0x8E, },
190 	{ .name = "drop_green_prio_5", .offset = 0x8F, },
191 	{ .name = "drop_green_prio_6", .offset = 0x90, },
192 	{ .name = "drop_green_prio_7", .offset = 0x91, },
193 	OCELOT_STAT_END
194 };
195 
196 static void ocelot_pll5_init(struct ocelot *ocelot)
197 {
198 	/* Configure PLL5. This will need a proper CCF driver
199 	 * The values are coming from the VTSS API for Ocelot
200 	 */
201 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
202 		     HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
203 		     HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
204 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
205 		     HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
206 		     HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
207 		     HSIO_PLL5G_CFG0_ENA_BIAS |
208 		     HSIO_PLL5G_CFG0_ENA_VCO_BUF |
209 		     HSIO_PLL5G_CFG0_ENA_CP1 |
210 		     HSIO_PLL5G_CFG0_SELCPI(2) |
211 		     HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) |
212 		     HSIO_PLL5G_CFG0_SELBGV820(4) |
213 		     HSIO_PLL5G_CFG0_DIV4 |
214 		     HSIO_PLL5G_CFG0_ENA_CLKTREE |
215 		     HSIO_PLL5G_CFG0_ENA_LANE);
216 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
217 		     HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
218 		     HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
219 		     HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
220 		     HSIO_PLL5G_CFG2_ENA_AMPCTRL |
221 		     HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
222 		     HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
223 }
224 
225 static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
226 {
227 	int ret;
228 
229 	ocelot->map = ocelot_regmap;
230 	ocelot->stats_layout = ocelot_stats_layout;
231 	ocelot->num_mact_rows = 1024;
232 	ocelot->ops = ops;
233 
234 	ret = ocelot_regfields_init(ocelot, ocelot_regfields);
235 	if (ret)
236 		return ret;
237 
238 	ocelot_pll5_init(ocelot);
239 
240 	eth_random_addr(ocelot->base_mac);
241 	ocelot->base_mac[5] &= 0xf0;
242 
243 	return 0;
244 }
245 
246 static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
247 {
248 	struct ocelot *ocelot = arg;
249 	int grp = 0, err;
250 
251 	while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) {
252 		struct sk_buff *skb;
253 
254 		err = ocelot_xtr_poll_frame(ocelot, grp, &skb);
255 		if (err)
256 			goto out;
257 
258 		skb->dev->stats.rx_bytes += skb->len;
259 		skb->dev->stats.rx_packets++;
260 
261 		if (!skb_defer_rx_timestamp(skb))
262 			netif_rx(skb);
263 	}
264 
265 out:
266 	if (err < 0)
267 		ocelot_drain_cpu_queue(ocelot, 0);
268 
269 	return IRQ_HANDLED;
270 }
271 
272 static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
273 {
274 	struct ocelot *ocelot = arg;
275 
276 	ocelot_get_txtstamp(ocelot);
277 
278 	return IRQ_HANDLED;
279 }
280 
281 static const struct of_device_id mscc_ocelot_match[] = {
282 	{ .compatible = "mscc,vsc7514-switch" },
283 	{ }
284 };
285 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
286 
287 static int ocelot_reset(struct ocelot *ocelot)
288 {
289 	int retries = 100;
290 	u32 val;
291 
292 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
293 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
294 
295 	do {
296 		msleep(1);
297 		regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
298 				  &val);
299 	} while (val && --retries);
300 
301 	if (!retries)
302 		return -ETIMEDOUT;
303 
304 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
305 	regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
306 
307 	return 0;
308 }
309 
310 /* Watermark encode
311  * Bit 8:   Unit; 0:1, 1:16
312  * Bit 7-0: Value to be multiplied with unit
313  */
314 static u16 ocelot_wm_enc(u16 value)
315 {
316 	WARN_ON(value >= 16 * BIT(8));
317 
318 	if (value >= BIT(8))
319 		return BIT(8) | (value / 16);
320 
321 	return value;
322 }
323 
324 static u16 ocelot_wm_dec(u16 wm)
325 {
326 	if (wm & BIT(8))
327 		return (wm & GENMASK(7, 0)) * 16;
328 
329 	return wm;
330 }
331 
332 static void ocelot_wm_stat(u32 val, u32 *inuse, u32 *maxuse)
333 {
334 	*inuse = (val & GENMASK(23, 12)) >> 12;
335 	*maxuse = val & GENMASK(11, 0);
336 }
337 
338 static const struct ocelot_ops ocelot_ops = {
339 	.reset			= ocelot_reset,
340 	.wm_enc			= ocelot_wm_enc,
341 	.wm_dec			= ocelot_wm_dec,
342 	.wm_stat		= ocelot_wm_stat,
343 	.port_to_netdev		= ocelot_port_to_netdev,
344 	.netdev_to_port		= ocelot_netdev_to_port,
345 };
346 
347 static struct vcap_props vsc7514_vcap_props[] = {
348 	[VCAP_ES0] = {
349 		.action_type_width = 0,
350 		.action_table = {
351 			[ES0_ACTION_TYPE_NORMAL] = {
352 				.width = 73, /* HIT_STICKY not included */
353 				.count = 1,
354 			},
355 		},
356 		.target = S0,
357 		.keys = vsc7514_vcap_es0_keys,
358 		.actions = vsc7514_vcap_es0_actions,
359 	},
360 	[VCAP_IS1] = {
361 		.action_type_width = 0,
362 		.action_table = {
363 			[IS1_ACTION_TYPE_NORMAL] = {
364 				.width = 78, /* HIT_STICKY not included */
365 				.count = 4,
366 			},
367 		},
368 		.target = S1,
369 		.keys = vsc7514_vcap_is1_keys,
370 		.actions = vsc7514_vcap_is1_actions,
371 	},
372 	[VCAP_IS2] = {
373 		.action_type_width = 1,
374 		.action_table = {
375 			[IS2_ACTION_TYPE_NORMAL] = {
376 				.width = 49,
377 				.count = 2
378 			},
379 			[IS2_ACTION_TYPE_SMAC_SIP] = {
380 				.width = 6,
381 				.count = 4
382 			},
383 		},
384 		.target = S2,
385 		.keys = vsc7514_vcap_is2_keys,
386 		.actions = vsc7514_vcap_is2_actions,
387 	},
388 };
389 
390 static struct ptp_clock_info ocelot_ptp_clock_info = {
391 	.owner		= THIS_MODULE,
392 	.name		= "ocelot ptp",
393 	.max_adj	= 0x7fffffff,
394 	.n_alarm	= 0,
395 	.n_ext_ts	= 0,
396 	.n_per_out	= OCELOT_PTP_PINS_NUM,
397 	.n_pins		= OCELOT_PTP_PINS_NUM,
398 	.pps		= 0,
399 	.gettime64	= ocelot_ptp_gettime64,
400 	.settime64	= ocelot_ptp_settime64,
401 	.adjtime	= ocelot_ptp_adjtime,
402 	.adjfine	= ocelot_ptp_adjfine,
403 	.verify		= ocelot_ptp_verify,
404 	.enable		= ocelot_ptp_enable,
405 };
406 
407 static void mscc_ocelot_teardown_devlink_ports(struct ocelot *ocelot)
408 {
409 	int port;
410 
411 	for (port = 0; port < ocelot->num_phys_ports; port++)
412 		ocelot_port_devlink_teardown(ocelot, port);
413 }
414 
415 static void mscc_ocelot_release_ports(struct ocelot *ocelot)
416 {
417 	int port;
418 
419 	for (port = 0; port < ocelot->num_phys_ports; port++) {
420 		struct ocelot_port *ocelot_port;
421 
422 		ocelot_port = ocelot->ports[port];
423 		if (!ocelot_port)
424 			continue;
425 
426 		ocelot_deinit_port(ocelot, port);
427 		ocelot_release_port(ocelot_port);
428 	}
429 }
430 
431 static int mscc_ocelot_init_ports(struct platform_device *pdev,
432 				  struct device_node *ports)
433 {
434 	struct ocelot *ocelot = platform_get_drvdata(pdev);
435 	u32 devlink_ports_registered = 0;
436 	struct device_node *portnp;
437 	int port, err;
438 	u32 reg;
439 
440 	ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
441 				     sizeof(struct ocelot_port *), GFP_KERNEL);
442 	if (!ocelot->ports)
443 		return -ENOMEM;
444 
445 	ocelot->devlink_ports = devm_kcalloc(ocelot->dev,
446 					     ocelot->num_phys_ports,
447 					     sizeof(*ocelot->devlink_ports),
448 					     GFP_KERNEL);
449 	if (!ocelot->devlink_ports)
450 		return -ENOMEM;
451 
452 	for_each_available_child_of_node(ports, portnp) {
453 		struct ocelot_port_private *priv;
454 		struct ocelot_port *ocelot_port;
455 		struct devlink_port *dlp;
456 		struct regmap *target;
457 		struct resource *res;
458 		char res_name[8];
459 
460 		if (of_property_read_u32(portnp, "reg", &reg))
461 			continue;
462 
463 		port = reg;
464 		if (port < 0 || port >= ocelot->num_phys_ports) {
465 			dev_err(ocelot->dev,
466 				"invalid port number: %d >= %d\n", port,
467 				ocelot->num_phys_ports);
468 			continue;
469 		}
470 
471 		snprintf(res_name, sizeof(res_name), "port%d", port);
472 
473 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
474 						   res_name);
475 		target = ocelot_regmap_init(ocelot, res);
476 		if (IS_ERR(target)) {
477 			err = PTR_ERR(target);
478 			of_node_put(portnp);
479 			goto out_teardown;
480 		}
481 
482 		err = ocelot_port_devlink_init(ocelot, port,
483 					       DEVLINK_PORT_FLAVOUR_PHYSICAL);
484 		if (err) {
485 			of_node_put(portnp);
486 			goto out_teardown;
487 		}
488 
489 		err = ocelot_probe_port(ocelot, port, target, portnp);
490 		if (err) {
491 			ocelot_port_devlink_teardown(ocelot, port);
492 			continue;
493 		}
494 
495 		devlink_ports_registered |= BIT(port);
496 
497 		ocelot_port = ocelot->ports[port];
498 		priv = container_of(ocelot_port, struct ocelot_port_private,
499 				    port);
500 		dlp = &ocelot->devlink_ports[port];
501 		devlink_port_type_eth_set(dlp, priv->dev);
502 	}
503 
504 	/* Initialize unused devlink ports at the end */
505 	for (port = 0; port < ocelot->num_phys_ports; port++) {
506 		if (devlink_ports_registered & BIT(port))
507 			continue;
508 
509 		err = ocelot_port_devlink_init(ocelot, port,
510 					       DEVLINK_PORT_FLAVOUR_UNUSED);
511 		if (err)
512 			goto out_teardown;
513 
514 		devlink_ports_registered |= BIT(port);
515 	}
516 
517 	return 0;
518 
519 out_teardown:
520 	/* Unregister the network interfaces */
521 	mscc_ocelot_release_ports(ocelot);
522 	/* Tear down devlink ports for the registered network interfaces */
523 	for (port = 0; port < ocelot->num_phys_ports; port++) {
524 		if (devlink_ports_registered & BIT(port))
525 			ocelot_port_devlink_teardown(ocelot, port);
526 	}
527 	return err;
528 }
529 
530 static int mscc_ocelot_probe(struct platform_device *pdev)
531 {
532 	struct device_node *np = pdev->dev.of_node;
533 	int err, irq_xtr, irq_ptp_rdy;
534 	struct device_node *ports;
535 	struct devlink *devlink;
536 	struct ocelot *ocelot;
537 	struct regmap *hsio;
538 	unsigned int i;
539 
540 	struct {
541 		enum ocelot_target id;
542 		char *name;
543 		u8 optional:1;
544 	} io_target[] = {
545 		{ SYS, "sys" },
546 		{ REW, "rew" },
547 		{ QSYS, "qsys" },
548 		{ ANA, "ana" },
549 		{ QS, "qs" },
550 		{ S0, "s0" },
551 		{ S1, "s1" },
552 		{ S2, "s2" },
553 		{ PTP, "ptp", 1 },
554 		{ FDMA, "fdma", 1 },
555 	};
556 
557 	if (!np && !pdev->dev.platform_data)
558 		return -ENODEV;
559 
560 	devlink =
561 		devlink_alloc(&ocelot_devlink_ops, sizeof(*ocelot), &pdev->dev);
562 	if (!devlink)
563 		return -ENOMEM;
564 
565 	ocelot = devlink_priv(devlink);
566 	ocelot->devlink = priv_to_devlink(ocelot);
567 	platform_set_drvdata(pdev, ocelot);
568 	ocelot->dev = &pdev->dev;
569 
570 	for (i = 0; i < ARRAY_SIZE(io_target); i++) {
571 		struct regmap *target;
572 		struct resource *res;
573 
574 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
575 						   io_target[i].name);
576 
577 		target = ocelot_regmap_init(ocelot, res);
578 		if (IS_ERR(target)) {
579 			if (io_target[i].optional) {
580 				ocelot->targets[io_target[i].id] = NULL;
581 				continue;
582 			}
583 			err = PTR_ERR(target);
584 			goto out_free_devlink;
585 		}
586 
587 		ocelot->targets[io_target[i].id] = target;
588 	}
589 
590 	if (ocelot->targets[FDMA])
591 		ocelot_fdma_init(pdev, ocelot);
592 
593 	hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
594 	if (IS_ERR(hsio)) {
595 		dev_err(&pdev->dev, "missing hsio syscon\n");
596 		err = PTR_ERR(hsio);
597 		goto out_free_devlink;
598 	}
599 
600 	ocelot->targets[HSIO] = hsio;
601 
602 	err = ocelot_chip_init(ocelot, &ocelot_ops);
603 	if (err)
604 		goto out_free_devlink;
605 
606 	irq_xtr = platform_get_irq_byname(pdev, "xtr");
607 	if (irq_xtr < 0) {
608 		err = irq_xtr;
609 		goto out_free_devlink;
610 	}
611 
612 	err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
613 					ocelot_xtr_irq_handler, IRQF_ONESHOT,
614 					"frame extraction", ocelot);
615 	if (err)
616 		goto out_free_devlink;
617 
618 	irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
619 	if (irq_ptp_rdy > 0 && ocelot->targets[PTP]) {
620 		err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
621 						ocelot_ptp_rdy_irq_handler,
622 						IRQF_ONESHOT, "ptp ready",
623 						ocelot);
624 		if (err)
625 			goto out_free_devlink;
626 
627 		/* Both the PTP interrupt and the PTP bank are available */
628 		ocelot->ptp = 1;
629 	}
630 
631 	ports = of_get_child_by_name(np, "ethernet-ports");
632 	if (!ports) {
633 		dev_err(ocelot->dev, "no ethernet-ports child node found\n");
634 		err = -ENODEV;
635 		goto out_free_devlink;
636 	}
637 
638 	ocelot->num_phys_ports = of_get_child_count(ports);
639 	ocelot->num_flooding_pgids = 1;
640 
641 	ocelot->vcap = vsc7514_vcap_props;
642 
643 	ocelot->vcap_pol.base = VSC7514_VCAP_POLICER_BASE;
644 	ocelot->vcap_pol.max = VSC7514_VCAP_POLICER_MAX;
645 
646 	ocelot->npi = -1;
647 
648 	err = ocelot_init(ocelot);
649 	if (err)
650 		goto out_put_ports;
651 
652 	err = mscc_ocelot_init_ports(pdev, ports);
653 	if (err)
654 		goto out_ocelot_devlink_unregister;
655 
656 	if (ocelot->fdma)
657 		ocelot_fdma_start(ocelot);
658 
659 	err = ocelot_devlink_sb_register(ocelot);
660 	if (err)
661 		goto out_ocelot_release_ports;
662 
663 	if (ocelot->ptp) {
664 		err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
665 		if (err) {
666 			dev_err(ocelot->dev,
667 				"Timestamp initialization failed\n");
668 			ocelot->ptp = 0;
669 		}
670 	}
671 
672 	register_netdevice_notifier(&ocelot_netdevice_nb);
673 	register_switchdev_notifier(&ocelot_switchdev_nb);
674 	register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
675 
676 	of_node_put(ports);
677 	devlink_register(devlink);
678 
679 	dev_info(&pdev->dev, "Ocelot switch probed\n");
680 
681 	return 0;
682 
683 out_ocelot_release_ports:
684 	mscc_ocelot_release_ports(ocelot);
685 	mscc_ocelot_teardown_devlink_ports(ocelot);
686 out_ocelot_devlink_unregister:
687 	ocelot_deinit(ocelot);
688 out_put_ports:
689 	of_node_put(ports);
690 out_free_devlink:
691 	devlink_free(devlink);
692 	return err;
693 }
694 
695 static int mscc_ocelot_remove(struct platform_device *pdev)
696 {
697 	struct ocelot *ocelot = platform_get_drvdata(pdev);
698 
699 	if (ocelot->fdma)
700 		ocelot_fdma_deinit(ocelot);
701 	devlink_unregister(ocelot->devlink);
702 	ocelot_deinit_timestamp(ocelot);
703 	ocelot_devlink_sb_unregister(ocelot);
704 	mscc_ocelot_release_ports(ocelot);
705 	mscc_ocelot_teardown_devlink_ports(ocelot);
706 	ocelot_deinit(ocelot);
707 	unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
708 	unregister_switchdev_notifier(&ocelot_switchdev_nb);
709 	unregister_netdevice_notifier(&ocelot_netdevice_nb);
710 	devlink_free(ocelot->devlink);
711 
712 	return 0;
713 }
714 
715 static struct platform_driver mscc_ocelot_driver = {
716 	.probe = mscc_ocelot_probe,
717 	.remove = mscc_ocelot_remove,
718 	.driver = {
719 		.name = "ocelot-switch",
720 		.of_match_table = mscc_ocelot_match,
721 	},
722 };
723 
724 module_platform_driver(mscc_ocelot_driver);
725 
726 MODULE_DESCRIPTION("Microsemi Ocelot switch driver");
727 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
728 MODULE_LICENSE("Dual MIT/GPL");
729