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