xref: /linux/drivers/net/ethernet/mscc/ocelot_vsc7514.c (revision 8a922b7728a93d837954315c98b84f6b78de0c4f)
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.h>
20 #include <soc/mscc/ocelot_vcap.h>
21 #include <soc/mscc/ocelot_hsio.h>
22 #include <soc/mscc/vsc7514_regs.h>
23 #include "ocelot_fdma.h"
24 #include "ocelot.h"
25 
26 #define VSC7514_VCAP_POLICER_BASE			128
27 #define VSC7514_VCAP_POLICER_MAX			191
28 
29 static void ocelot_pll5_init(struct ocelot *ocelot)
30 {
31 	/* Configure PLL5. This will need a proper CCF driver
32 	 * The values are coming from the VTSS API for Ocelot
33 	 */
34 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG4,
35 		     HSIO_PLL5G_CFG4_IB_CTRL(0x7600) |
36 		     HSIO_PLL5G_CFG4_IB_BIAS_CTRL(0x8));
37 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG0,
38 		     HSIO_PLL5G_CFG0_CORE_CLK_DIV(0x11) |
39 		     HSIO_PLL5G_CFG0_CPU_CLK_DIV(2) |
40 		     HSIO_PLL5G_CFG0_ENA_BIAS |
41 		     HSIO_PLL5G_CFG0_ENA_VCO_BUF |
42 		     HSIO_PLL5G_CFG0_ENA_CP1 |
43 		     HSIO_PLL5G_CFG0_SELCPI(2) |
44 		     HSIO_PLL5G_CFG0_LOOP_BW_RES(0xe) |
45 		     HSIO_PLL5G_CFG0_SELBGV820(4) |
46 		     HSIO_PLL5G_CFG0_DIV4 |
47 		     HSIO_PLL5G_CFG0_ENA_CLKTREE |
48 		     HSIO_PLL5G_CFG0_ENA_LANE);
49 	regmap_write(ocelot->targets[HSIO], HSIO_PLL5G_CFG2,
50 		     HSIO_PLL5G_CFG2_EN_RESET_FRQ_DET |
51 		     HSIO_PLL5G_CFG2_EN_RESET_OVERRUN |
52 		     HSIO_PLL5G_CFG2_GAIN_TEST(0x8) |
53 		     HSIO_PLL5G_CFG2_ENA_AMPCTRL |
54 		     HSIO_PLL5G_CFG2_PWD_AMPCTRL_N |
55 		     HSIO_PLL5G_CFG2_AMPC_SEL(0x10));
56 }
57 
58 static int ocelot_chip_init(struct ocelot *ocelot, const struct ocelot_ops *ops)
59 {
60 	int ret;
61 
62 	ocelot->map = vsc7514_regmap;
63 	ocelot->num_mact_rows = 1024;
64 	ocelot->ops = ops;
65 
66 	ret = ocelot_regfields_init(ocelot, vsc7514_regfields);
67 	if (ret)
68 		return ret;
69 
70 	ocelot_pll5_init(ocelot);
71 
72 	eth_random_addr(ocelot->base_mac);
73 	ocelot->base_mac[5] &= 0xf0;
74 
75 	return 0;
76 }
77 
78 static irqreturn_t ocelot_xtr_irq_handler(int irq, void *arg)
79 {
80 	struct ocelot *ocelot = arg;
81 	int grp = 0, err;
82 
83 	while (ocelot_read(ocelot, QS_XTR_DATA_PRESENT) & BIT(grp)) {
84 		struct sk_buff *skb;
85 
86 		err = ocelot_xtr_poll_frame(ocelot, grp, &skb);
87 		if (err)
88 			goto out;
89 
90 		skb->dev->stats.rx_bytes += skb->len;
91 		skb->dev->stats.rx_packets++;
92 
93 		if (!skb_defer_rx_timestamp(skb))
94 			netif_rx(skb);
95 	}
96 
97 out:
98 	if (err < 0)
99 		ocelot_drain_cpu_queue(ocelot, 0);
100 
101 	return IRQ_HANDLED;
102 }
103 
104 static irqreturn_t ocelot_ptp_rdy_irq_handler(int irq, void *arg)
105 {
106 	struct ocelot *ocelot = arg;
107 
108 	ocelot_get_txtstamp(ocelot);
109 
110 	return IRQ_HANDLED;
111 }
112 
113 static const struct of_device_id mscc_ocelot_match[] = {
114 	{ .compatible = "mscc,vsc7514-switch" },
115 	{ }
116 };
117 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
118 
119 static const struct ocelot_ops ocelot_ops = {
120 	.reset			= ocelot_reset,
121 	.wm_enc			= ocelot_wm_enc,
122 	.wm_dec			= ocelot_wm_dec,
123 	.wm_stat		= ocelot_wm_stat,
124 	.port_to_netdev		= ocelot_port_to_netdev,
125 	.netdev_to_port		= ocelot_netdev_to_port,
126 };
127 
128 static struct ptp_clock_info ocelot_ptp_clock_info = {
129 	.owner		= THIS_MODULE,
130 	.name		= "ocelot ptp",
131 	.max_adj	= 0x7fffffff,
132 	.n_alarm	= 0,
133 	.n_ext_ts	= 0,
134 	.n_per_out	= OCELOT_PTP_PINS_NUM,
135 	.n_pins		= OCELOT_PTP_PINS_NUM,
136 	.pps		= 0,
137 	.gettime64	= ocelot_ptp_gettime64,
138 	.settime64	= ocelot_ptp_settime64,
139 	.adjtime	= ocelot_ptp_adjtime,
140 	.adjfine	= ocelot_ptp_adjfine,
141 	.verify		= ocelot_ptp_verify,
142 	.enable		= ocelot_ptp_enable,
143 };
144 
145 static void mscc_ocelot_teardown_devlink_ports(struct ocelot *ocelot)
146 {
147 	int port;
148 
149 	for (port = 0; port < ocelot->num_phys_ports; port++)
150 		ocelot_port_devlink_teardown(ocelot, port);
151 }
152 
153 static void mscc_ocelot_release_ports(struct ocelot *ocelot)
154 {
155 	int port;
156 
157 	for (port = 0; port < ocelot->num_phys_ports; port++) {
158 		struct ocelot_port *ocelot_port;
159 
160 		ocelot_port = ocelot->ports[port];
161 		if (!ocelot_port)
162 			continue;
163 
164 		ocelot_deinit_port(ocelot, port);
165 		ocelot_release_port(ocelot_port);
166 	}
167 }
168 
169 static int mscc_ocelot_init_ports(struct platform_device *pdev,
170 				  struct device_node *ports)
171 {
172 	struct ocelot *ocelot = platform_get_drvdata(pdev);
173 	u32 devlink_ports_registered = 0;
174 	struct device_node *portnp;
175 	int port, err;
176 	u32 reg;
177 
178 	ocelot->ports = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
179 				     sizeof(struct ocelot_port *), GFP_KERNEL);
180 	if (!ocelot->ports)
181 		return -ENOMEM;
182 
183 	ocelot->devlink_ports = devm_kcalloc(ocelot->dev,
184 					     ocelot->num_phys_ports,
185 					     sizeof(*ocelot->devlink_ports),
186 					     GFP_KERNEL);
187 	if (!ocelot->devlink_ports)
188 		return -ENOMEM;
189 
190 	for_each_available_child_of_node(ports, portnp) {
191 		struct regmap *target;
192 		struct resource *res;
193 		char res_name[8];
194 
195 		if (of_property_read_u32(portnp, "reg", &reg))
196 			continue;
197 
198 		port = reg;
199 		if (port < 0 || port >= ocelot->num_phys_ports) {
200 			dev_err(ocelot->dev,
201 				"invalid port number: %d >= %d\n", port,
202 				ocelot->num_phys_ports);
203 			continue;
204 		}
205 
206 		snprintf(res_name, sizeof(res_name), "port%d", port);
207 
208 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
209 						   res_name);
210 		target = ocelot_regmap_init(ocelot, res);
211 		if (IS_ERR(target)) {
212 			err = PTR_ERR(target);
213 			of_node_put(portnp);
214 			goto out_teardown;
215 		}
216 
217 		err = ocelot_port_devlink_init(ocelot, port,
218 					       DEVLINK_PORT_FLAVOUR_PHYSICAL);
219 		if (err) {
220 			of_node_put(portnp);
221 			goto out_teardown;
222 		}
223 
224 		err = ocelot_probe_port(ocelot, port, target, portnp);
225 		if (err) {
226 			ocelot_port_devlink_teardown(ocelot, port);
227 			continue;
228 		}
229 
230 		devlink_ports_registered |= BIT(port);
231 	}
232 
233 	/* Initialize unused devlink ports at the end */
234 	for (port = 0; port < ocelot->num_phys_ports; port++) {
235 		if (devlink_ports_registered & BIT(port))
236 			continue;
237 
238 		err = ocelot_port_devlink_init(ocelot, port,
239 					       DEVLINK_PORT_FLAVOUR_UNUSED);
240 		if (err)
241 			goto out_teardown;
242 
243 		devlink_ports_registered |= BIT(port);
244 	}
245 
246 	return 0;
247 
248 out_teardown:
249 	/* Unregister the network interfaces */
250 	mscc_ocelot_release_ports(ocelot);
251 	/* Tear down devlink ports for the registered network interfaces */
252 	for (port = 0; port < ocelot->num_phys_ports; port++) {
253 		if (devlink_ports_registered & BIT(port))
254 			ocelot_port_devlink_teardown(ocelot, port);
255 	}
256 	return err;
257 }
258 
259 static int mscc_ocelot_probe(struct platform_device *pdev)
260 {
261 	struct device_node *np = pdev->dev.of_node;
262 	int err, irq_xtr, irq_ptp_rdy;
263 	struct device_node *ports;
264 	struct devlink *devlink;
265 	struct ocelot *ocelot;
266 	struct regmap *hsio;
267 	unsigned int i;
268 
269 	struct {
270 		enum ocelot_target id;
271 		char *name;
272 		u8 optional:1;
273 	} io_target[] = {
274 		{ SYS, "sys" },
275 		{ REW, "rew" },
276 		{ QSYS, "qsys" },
277 		{ ANA, "ana" },
278 		{ QS, "qs" },
279 		{ S0, "s0" },
280 		{ S1, "s1" },
281 		{ S2, "s2" },
282 		{ PTP, "ptp", 1 },
283 		{ FDMA, "fdma", 1 },
284 	};
285 
286 	if (!np && !pdev->dev.platform_data)
287 		return -ENODEV;
288 
289 	devlink =
290 		devlink_alloc(&ocelot_devlink_ops, sizeof(*ocelot), &pdev->dev);
291 	if (!devlink)
292 		return -ENOMEM;
293 
294 	ocelot = devlink_priv(devlink);
295 	ocelot->devlink = priv_to_devlink(ocelot);
296 	platform_set_drvdata(pdev, ocelot);
297 	ocelot->dev = &pdev->dev;
298 
299 	for (i = 0; i < ARRAY_SIZE(io_target); i++) {
300 		struct regmap *target;
301 		struct resource *res;
302 
303 		res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
304 						   io_target[i].name);
305 
306 		target = ocelot_regmap_init(ocelot, res);
307 		if (IS_ERR(target)) {
308 			if (io_target[i].optional) {
309 				ocelot->targets[io_target[i].id] = NULL;
310 				continue;
311 			}
312 			err = PTR_ERR(target);
313 			goto out_free_devlink;
314 		}
315 
316 		ocelot->targets[io_target[i].id] = target;
317 	}
318 
319 	if (ocelot->targets[FDMA])
320 		ocelot_fdma_init(pdev, ocelot);
321 
322 	hsio = syscon_regmap_lookup_by_compatible("mscc,ocelot-hsio");
323 	if (IS_ERR(hsio)) {
324 		dev_err(&pdev->dev, "missing hsio syscon\n");
325 		err = PTR_ERR(hsio);
326 		goto out_free_devlink;
327 	}
328 
329 	ocelot->targets[HSIO] = hsio;
330 
331 	err = ocelot_chip_init(ocelot, &ocelot_ops);
332 	if (err)
333 		goto out_free_devlink;
334 
335 	irq_xtr = platform_get_irq_byname(pdev, "xtr");
336 	if (irq_xtr < 0) {
337 		err = irq_xtr;
338 		goto out_free_devlink;
339 	}
340 
341 	err = devm_request_threaded_irq(&pdev->dev, irq_xtr, NULL,
342 					ocelot_xtr_irq_handler, IRQF_ONESHOT,
343 					"frame extraction", ocelot);
344 	if (err)
345 		goto out_free_devlink;
346 
347 	irq_ptp_rdy = platform_get_irq_byname(pdev, "ptp_rdy");
348 	if (irq_ptp_rdy > 0 && ocelot->targets[PTP]) {
349 		err = devm_request_threaded_irq(&pdev->dev, irq_ptp_rdy, NULL,
350 						ocelot_ptp_rdy_irq_handler,
351 						IRQF_ONESHOT, "ptp ready",
352 						ocelot);
353 		if (err)
354 			goto out_free_devlink;
355 
356 		/* Both the PTP interrupt and the PTP bank are available */
357 		ocelot->ptp = 1;
358 	}
359 
360 	ports = of_get_child_by_name(np, "ethernet-ports");
361 	if (!ports) {
362 		dev_err(ocelot->dev, "no ethernet-ports child node found\n");
363 		err = -ENODEV;
364 		goto out_free_devlink;
365 	}
366 
367 	ocelot->num_phys_ports = of_get_child_count(ports);
368 	ocelot->num_flooding_pgids = 1;
369 
370 	ocelot->vcap = vsc7514_vcap_props;
371 
372 	ocelot->vcap_pol.base = VSC7514_VCAP_POLICER_BASE;
373 	ocelot->vcap_pol.max = VSC7514_VCAP_POLICER_MAX;
374 
375 	ocelot->npi = -1;
376 
377 	err = ocelot_init(ocelot);
378 	if (err)
379 		goto out_put_ports;
380 
381 	err = mscc_ocelot_init_ports(pdev, ports);
382 	if (err)
383 		goto out_ocelot_devlink_unregister;
384 
385 	if (ocelot->fdma)
386 		ocelot_fdma_start(ocelot);
387 
388 	err = ocelot_devlink_sb_register(ocelot);
389 	if (err)
390 		goto out_ocelot_release_ports;
391 
392 	if (ocelot->ptp) {
393 		err = ocelot_init_timestamp(ocelot, &ocelot_ptp_clock_info);
394 		if (err) {
395 			dev_err(ocelot->dev,
396 				"Timestamp initialization failed\n");
397 			ocelot->ptp = 0;
398 		}
399 	}
400 
401 	register_netdevice_notifier(&ocelot_netdevice_nb);
402 	register_switchdev_notifier(&ocelot_switchdev_nb);
403 	register_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
404 
405 	of_node_put(ports);
406 	devlink_register(devlink);
407 
408 	dev_info(&pdev->dev, "Ocelot switch probed\n");
409 
410 	return 0;
411 
412 out_ocelot_release_ports:
413 	mscc_ocelot_release_ports(ocelot);
414 	mscc_ocelot_teardown_devlink_ports(ocelot);
415 out_ocelot_devlink_unregister:
416 	ocelot_deinit(ocelot);
417 out_put_ports:
418 	of_node_put(ports);
419 out_free_devlink:
420 	devlink_free(devlink);
421 	return err;
422 }
423 
424 static int mscc_ocelot_remove(struct platform_device *pdev)
425 {
426 	struct ocelot *ocelot = platform_get_drvdata(pdev);
427 
428 	if (ocelot->fdma)
429 		ocelot_fdma_deinit(ocelot);
430 	devlink_unregister(ocelot->devlink);
431 	ocelot_deinit_timestamp(ocelot);
432 	ocelot_devlink_sb_unregister(ocelot);
433 	mscc_ocelot_release_ports(ocelot);
434 	mscc_ocelot_teardown_devlink_ports(ocelot);
435 	ocelot_deinit(ocelot);
436 	unregister_switchdev_blocking_notifier(&ocelot_switchdev_blocking_nb);
437 	unregister_switchdev_notifier(&ocelot_switchdev_nb);
438 	unregister_netdevice_notifier(&ocelot_netdevice_nb);
439 	devlink_free(ocelot->devlink);
440 
441 	return 0;
442 }
443 
444 static struct platform_driver mscc_ocelot_driver = {
445 	.probe = mscc_ocelot_probe,
446 	.remove = mscc_ocelot_remove,
447 	.driver = {
448 		.name = "ocelot-switch",
449 		.of_match_table = mscc_ocelot_match,
450 	},
451 };
452 
453 module_platform_driver(mscc_ocelot_driver);
454 
455 MODULE_DESCRIPTION("Microsemi Ocelot switch driver");
456 MODULE_AUTHOR("Alexandre Belloni <alexandre.belloni@bootlin.com>");
457 MODULE_LICENSE("Dual MIT/GPL");
458