blob: 211a991cdd0dc3c25b77aae2ba842365b238885f [file] [log] [blame]
Claudiu Manoilfc054d52021-01-25 14:23:53 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2019-2021 NXP
4 */
5
6#include <net/dsa.h>
7#include <dm/lists.h>
8#include <dm/device_compat.h>
9#include <dm/device-internal.h>
10#include <dm/uclass-internal.h>
11#include <linux/bitmap.h>
12#include <miiphy.h>
13
14#define DSA_PORT_CHILD_DRV_NAME "dsa-port"
15
16/* per-device internal state structure */
17struct dsa_priv {
18 struct phy_device *cpu_port_fixed_phy;
19 struct udevice *master_dev;
20 int num_ports;
21 u32 cpu_port;
22 int headroom;
23 int tailroom;
24};
25
26/* external API */
27int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom)
28{
29 struct dsa_priv *priv;
30
Michael Walle108157c2021-02-24 17:40:41 +010031 if (!dev)
32 return -EINVAL;
Claudiu Manoilfc054d52021-01-25 14:23:53 +020033
34 if (headroom + tailroom > DSA_MAX_OVR)
35 return -EINVAL;
36
37 priv = dev_get_uclass_priv(dev);
38
39 if (headroom > 0)
40 priv->headroom = headroom;
41 if (tailroom > 0)
42 priv->tailroom = tailroom;
43
44 return 0;
45}
46
Vladimir Oltean0783b162021-09-29 18:04:38 +030047ofnode dsa_port_get_ofnode(struct udevice *dev, int port)
48{
49 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
50 struct dsa_port_pdata *port_pdata;
51 struct udevice *pdev;
52
53 if (port == pdata->cpu_port)
54 return pdata->cpu_port_node;
55
56 for (device_find_first_child(dev, &pdev);
57 pdev;
58 device_find_next_child(&pdev)) {
59 port_pdata = dev_get_parent_plat(pdev);
60 if (port_pdata->index == port)
61 return dev_ofnode(pdev);
62 }
63
64 return ofnode_null();
65}
66
Claudiu Manoilfc054d52021-01-25 14:23:53 +020067/* returns the DSA master Ethernet device */
68struct udevice *dsa_get_master(struct udevice *dev)
69{
Michael Walle108157c2021-02-24 17:40:41 +010070 struct dsa_priv *priv;
Claudiu Manoilfc054d52021-01-25 14:23:53 +020071
Michael Walle108157c2021-02-24 17:40:41 +010072 if (!dev)
Claudiu Manoilfc054d52021-01-25 14:23:53 +020073 return NULL;
74
Michael Walle108157c2021-02-24 17:40:41 +010075 priv = dev_get_uclass_priv(dev);
76
Claudiu Manoilfc054d52021-01-25 14:23:53 +020077 return priv->master_dev;
78}
79
80/*
81 * Start the desired port, the CPU port and the master Eth interface.
82 * TODO: if cascaded we may need to _start ports in other switches too
83 */
84static int dsa_port_start(struct udevice *pdev)
85{
86 struct udevice *dev = dev_get_parent(pdev);
87 struct dsa_priv *priv = dev_get_uclass_priv(dev);
88 struct udevice *master = dsa_get_master(dev);
89 struct dsa_ops *ops = dsa_get_ops(dev);
90 int err;
91
Claudiu Manoilfc054d52021-01-25 14:23:53 +020092 if (ops->port_enable) {
93 struct dsa_port_pdata *port_pdata;
94
95 port_pdata = dev_get_parent_plat(pdev);
96 err = ops->port_enable(dev, port_pdata->index,
97 port_pdata->phy);
98 if (err)
99 return err;
100
101 err = ops->port_enable(dev, priv->cpu_port,
102 priv->cpu_port_fixed_phy);
103 if (err)
104 return err;
105 }
106
107 return eth_get_ops(master)->start(master);
108}
109
110/* Stop the desired port, the CPU port and the master Eth interface */
111static void dsa_port_stop(struct udevice *pdev)
112{
113 struct udevice *dev = dev_get_parent(pdev);
114 struct dsa_priv *priv = dev_get_uclass_priv(dev);
115 struct udevice *master = dsa_get_master(dev);
116 struct dsa_ops *ops = dsa_get_ops(dev);
117
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200118 if (ops->port_disable) {
119 struct dsa_port_pdata *port_pdata;
120
121 port_pdata = dev_get_parent_plat(pdev);
122 ops->port_disable(dev, port_pdata->index, port_pdata->phy);
Vladimir Oltean5cc283b2021-09-18 14:49:55 +0300123 ops->port_disable(dev, priv->cpu_port, priv->cpu_port_fixed_phy);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200124 }
125
Michael Walle71455532021-02-24 17:40:42 +0100126 eth_get_ops(master)->stop(master);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200127}
128
129/*
130 * Insert a DSA tag and call master Ethernet send on the resulting packet
131 * We copy the frame to a stack buffer where we have reserved headroom and
132 * tailroom space. Headroom and tailroom are set to 0.
133 */
134static int dsa_port_send(struct udevice *pdev, void *packet, int length)
135{
136 struct udevice *dev = dev_get_parent(pdev);
137 struct dsa_priv *priv = dev_get_uclass_priv(dev);
138 int head = priv->headroom, tail = priv->tailroom;
139 struct udevice *master = dsa_get_master(dev);
140 struct dsa_ops *ops = dsa_get_ops(dev);
141 uchar dsa_packet_tmp[PKTSIZE_ALIGN];
142 struct dsa_port_pdata *port_pdata;
143 int err;
144
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200145 if (length + head + tail > PKTSIZE_ALIGN)
146 return -EINVAL;
147
148 memset(dsa_packet_tmp, 0, head);
149 memset(dsa_packet_tmp + head + length, 0, tail);
150 memcpy(dsa_packet_tmp + head, packet, length);
151 length += head + tail;
152 /* copy back to preserve original buffer alignment */
153 memcpy(packet, dsa_packet_tmp, length);
154
155 port_pdata = dev_get_parent_plat(pdev);
156 err = ops->xmit(dev, port_pdata->index, packet, length);
157 if (err)
158 return err;
159
160 return eth_get_ops(master)->send(master, packet, length);
161}
162
163/* Receive a frame from master Ethernet, process it and pass it on */
164static int dsa_port_recv(struct udevice *pdev, int flags, uchar **packetp)
165{
166 struct udevice *dev = dev_get_parent(pdev);
167 struct dsa_priv *priv = dev_get_uclass_priv(dev);
168 int head = priv->headroom, tail = priv->tailroom;
169 struct udevice *master = dsa_get_master(dev);
170 struct dsa_ops *ops = dsa_get_ops(dev);
171 struct dsa_port_pdata *port_pdata;
172 int length, port_index, err;
173
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200174 length = eth_get_ops(master)->recv(master, flags, packetp);
175 if (length <= 0)
176 return length;
177
178 /*
179 * If we receive frames from a different port or frames that DSA driver
180 * doesn't like we discard them here.
181 * In case of discard we return with no frame and expect to be called
182 * again instead of looping here, so upper layer can deal with timeouts.
183 */
184 port_pdata = dev_get_parent_plat(pdev);
185 err = ops->rcv(dev, &port_index, *packetp, length);
186 if (err || port_index != port_pdata->index || (length <= head + tail)) {
187 if (eth_get_ops(master)->free_pkt)
188 eth_get_ops(master)->free_pkt(master, *packetp, length);
189 return -EAGAIN;
190 }
191
192 /*
193 * We move the pointer over headroom here to avoid a copy. If free_pkt
194 * gets called we move the pointer back before calling master free_pkt.
195 */
196 *packetp += head;
197
198 return length - head - tail;
199}
200
201static int dsa_port_free_pkt(struct udevice *pdev, uchar *packet, int length)
202{
203 struct udevice *dev = dev_get_parent(pdev);
204 struct udevice *master = dsa_get_master(dev);
205 struct dsa_priv *priv;
206
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200207 priv = dev_get_uclass_priv(dev);
208 if (eth_get_ops(master)->free_pkt) {
209 /* return the original pointer and length to master Eth */
210 packet -= priv->headroom;
211 length += priv->headroom - priv->tailroom;
212
213 return eth_get_ops(master)->free_pkt(master, packet, length);
214 }
215
216 return 0;
217}
218
219static int dsa_port_of_to_pdata(struct udevice *pdev)
220{
221 struct dsa_port_pdata *port_pdata;
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200222 struct eth_pdata *eth_pdata;
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200223 const char *label;
224 u32 index;
225 int err;
226
227 if (!pdev)
228 return -ENODEV;
229
230 err = ofnode_read_u32(dev_ofnode(pdev), "reg", &index);
231 if (err)
232 return err;
233
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200234 port_pdata = dev_get_parent_plat(pdev);
235 port_pdata->index = index;
236
237 label = ofnode_read_string(dev_ofnode(pdev), "label");
238 if (label)
Vladimir Oltean4fdc7e32021-09-27 14:22:03 +0300239 strlcpy(port_pdata->name, label, DSA_PORT_NAME_LENGTH);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200240
241 eth_pdata = dev_get_plat(pdev);
242 eth_pdata->priv_pdata = port_pdata;
243
244 dev_dbg(pdev, "port %d node %s\n", port_pdata->index,
245 ofnode_get_name(dev_ofnode(pdev)));
246
247 return 0;
248}
249
250static const struct eth_ops dsa_port_ops = {
251 .start = dsa_port_start,
252 .send = dsa_port_send,
253 .recv = dsa_port_recv,
254 .stop = dsa_port_stop,
255 .free_pkt = dsa_port_free_pkt,
256};
257
Vladimir Oltean5eee5ab2021-08-24 15:00:40 +0300258/*
259 * Inherit port's hwaddr from the DSA master, unless the port already has a
260 * unique MAC address specified in the environment.
261 */
262static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master)
263{
264 struct eth_pdata *eth_pdata, *master_pdata;
265 unsigned char env_enetaddr[ARP_HLEN];
266
267 eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
268 if (!is_zero_ethaddr(env_enetaddr)) {
269 /* individual port mac addrs require master to be promisc */
270 struct eth_ops *eth_ops = eth_get_ops(master);
271
272 if (eth_ops->set_promisc)
Bin Mengc7ae46ef2021-11-01 14:15:10 +0800273 eth_ops->set_promisc(master, true);
Vladimir Oltean5eee5ab2021-08-24 15:00:40 +0300274
275 return;
276 }
277
278 master_pdata = dev_get_plat(master);
279 eth_pdata = dev_get_plat(pdev);
280 memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN);
281 eth_env_set_enetaddr_by_index("eth", dev_seq(pdev),
282 master_pdata->enetaddr);
283}
284
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200285static int dsa_port_probe(struct udevice *pdev)
286{
287 struct udevice *dev = dev_get_parent(pdev);
Vladimir Oltean4b46e832021-08-24 15:00:41 +0300288 struct dsa_ops *ops = dsa_get_ops(dev);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200289 struct dsa_port_pdata *port_pdata;
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200290 struct udevice *master;
Vladimir Olteanf4b712b2021-08-24 15:00:39 +0300291 int err;
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200292
293 port_pdata = dev_get_parent_plat(pdev);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200294
295 port_pdata->phy = dm_eth_phy_connect(pdev);
296 if (!port_pdata->phy)
297 return -ENODEV;
298
Michael Wallea02dcbb2021-02-24 17:40:39 +0100299 master = dsa_get_master(dev);
300 if (!master)
301 return -ENODEV;
302
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200303 /*
Michael Wallee5d7d112021-02-24 17:40:40 +0100304 * Probe the master device. We depend on the master device for proper
305 * operation and we also need it for MAC inheritance below.
Michael Walle71455532021-02-24 17:40:42 +0100306 *
307 * TODO: we assume the master device is always there and doesn't get
308 * removed during runtime.
Michael Wallee5d7d112021-02-24 17:40:40 +0100309 */
Vladimir Olteanf4b712b2021-08-24 15:00:39 +0300310 err = device_probe(master);
311 if (err)
312 return err;
Michael Wallee5d7d112021-02-24 17:40:40 +0100313
Vladimir Oltean5eee5ab2021-08-24 15:00:40 +0300314 dsa_port_set_hwaddr(pdev, master);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200315
Vladimir Oltean4b46e832021-08-24 15:00:41 +0300316 if (ops->port_probe) {
317 err = ops->port_probe(dev, port_pdata->index,
318 port_pdata->phy);
319 if (err)
320 return err;
321 }
322
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200323 return 0;
324}
325
326static int dsa_port_remove(struct udevice *pdev)
327{
Vladimir Oltean5ecdf0a2021-09-18 14:49:56 +0300328 struct dsa_port_pdata *port_pdata = dev_get_parent_plat(pdev);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200329
330 port_pdata->phy = NULL;
331
332 return 0;
333}
334
335U_BOOT_DRIVER(dsa_port) = {
336 .name = DSA_PORT_CHILD_DRV_NAME,
337 .id = UCLASS_ETH,
338 .ops = &dsa_port_ops,
339 .probe = dsa_port_probe,
340 .remove = dsa_port_remove,
341 .of_to_plat = dsa_port_of_to_pdata,
342 .plat_auto = sizeof(struct eth_pdata),
343};
344
Tim Harvey43c2a002022-11-30 09:42:46 -0800345static int dsa_sanitize_ops(struct udevice *dev)
346{
347 struct dsa_ops *ops = dsa_get_ops(dev);
348
349 if ((!ops->xmit || !ops->rcv) &&
350 (!ops->port_enable && !ops->port_disable)) {
351 dev_err(dev, "Packets cannot be steered to ports\n");
352 return -EINVAL;
353 }
354
355 return 0;
356}
357
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200358/*
359 * This function mostly deals with pulling information out of the device tree
360 * into the pdata structure.
361 * It goes through the list of switch ports, registers an eth device for each
362 * front panel port and identifies the cpu port connected to master eth device.
363 * TODO: support cascaded switches
364 */
365static int dsa_post_bind(struct udevice *dev)
366{
367 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
368 ofnode node = dev_ofnode(dev), pnode;
369 int i, err, first_err = 0;
370
Michael Walle108157c2021-02-24 17:40:41 +0100371 if (!ofnode_valid(node))
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200372 return -ENODEV;
373
Tim Harvey43c2a002022-11-30 09:42:46 -0800374 err = dsa_sanitize_ops(dev);
375 if (err)
376 return err;
377
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200378 pdata->master_node = ofnode_null();
379
380 node = ofnode_find_subnode(node, "ports");
381 if (!ofnode_valid(node))
382 node = ofnode_find_subnode(node, "ethernet-ports");
383 if (!ofnode_valid(node)) {
384 dev_err(dev, "ports node is missing under DSA device!\n");
385 return -EINVAL;
386 }
387
388 pdata->num_ports = ofnode_get_child_count(node);
389 if (pdata->num_ports <= 0 || pdata->num_ports > DSA_MAX_PORTS) {
390 dev_err(dev, "invalid number of ports (%d)\n",
391 pdata->num_ports);
392 return -EINVAL;
393 }
394
395 /* look for the CPU port */
396 ofnode_for_each_subnode(pnode, node) {
397 u32 ethernet;
398
399 if (ofnode_read_u32(pnode, "ethernet", &ethernet))
400 continue;
401
402 pdata->master_node = ofnode_get_by_phandle(ethernet);
403 pdata->cpu_port_node = pnode;
404 break;
405 }
406
407 if (!ofnode_valid(pdata->master_node)) {
408 dev_err(dev, "master eth node missing!\n");
409 return -EINVAL;
410 }
411
412 if (ofnode_read_u32(pnode, "reg", &pdata->cpu_port)) {
413 dev_err(dev, "CPU port node not valid!\n");
414 return -EINVAL;
415 }
416
417 dev_dbg(dev, "master node %s on port %d\n",
418 ofnode_get_name(pdata->master_node), pdata->cpu_port);
419
420 for (i = 0; i < pdata->num_ports; i++) {
421 char name[DSA_PORT_NAME_LENGTH];
422 struct udevice *pdev;
423
424 /*
425 * If this is the CPU port don't register it as an ETH device,
426 * we skip it on purpose since I/O to/from it from the CPU
427 * isn't useful.
428 */
429 if (i == pdata->cpu_port)
430 continue;
431
432 /*
433 * Set up default port names. If present, DT port labels
434 * will override the default port names.
435 */
436 snprintf(name, DSA_PORT_NAME_LENGTH, "%s@%d", dev->name, i);
437
438 ofnode_for_each_subnode(pnode, node) {
439 u32 reg;
440
441 if (ofnode_read_u32(pnode, "reg", &reg))
442 continue;
443
444 if (reg == i)
445 break;
446 }
447
448 /*
449 * skip registration if port id not found or if the port
450 * is explicitly disabled in DT
451 */
Simon Glass89090662022-09-06 20:27:17 -0600452 if (!ofnode_valid(pnode) || !ofnode_is_enabled(pnode))
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200453 continue;
454
455 err = device_bind_driver_to_node(dev, DSA_PORT_CHILD_DRV_NAME,
456 name, pnode, &pdev);
457 if (pdev) {
458 struct dsa_port_pdata *port_pdata;
459
460 port_pdata = dev_get_parent_plat(pdev);
Vladimir Oltean4fdc7e32021-09-27 14:22:03 +0300461 strlcpy(port_pdata->name, name, DSA_PORT_NAME_LENGTH);
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200462 pdev->name = port_pdata->name;
463 }
464
465 /* try to bind all ports but keep 1st error */
466 if (err && !first_err)
467 first_err = err;
468 }
469
470 if (first_err)
471 return first_err;
472
473 dev_dbg(dev, "DSA ports successfully bound\n");
474
475 return 0;
476}
477
478/**
479 * Initialize the uclass per device internal state structure (priv).
480 * TODO: pick up references to other switch devices here, if we're cascaded.
481 */
482static int dsa_pre_probe(struct udevice *dev)
483{
484 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
485 struct dsa_priv *priv = dev_get_uclass_priv(dev);
Vladimir Oltean0fa44482021-12-05 01:00:34 +0200486 int err;
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200487
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200488 priv->num_ports = pdata->num_ports;
489 priv->cpu_port = pdata->cpu_port;
490 priv->cpu_port_fixed_phy = fixed_phy_create(pdata->cpu_port_node);
491 if (!priv->cpu_port_fixed_phy) {
492 dev_err(dev, "Failed to register fixed-link for CPU port\n");
493 return -ENODEV;
494 }
495
Sean Anderson2a5af402022-05-05 13:11:36 -0400496 err = uclass_get_device_by_ofnode(UCLASS_ETH, pdata->master_node,
497 &priv->master_dev);
498 if (err)
499 return err;
Vladimir Oltean0fa44482021-12-05 01:00:34 +0200500
Tim Harveyc5868fc2022-11-30 09:42:45 -0800501 return 0;
502}
503
504static int dsa_post_probe(struct udevice *dev)
505{
506 struct dsa_priv *priv = dev_get_uclass_priv(dev);
507 struct dsa_ops *ops = dsa_get_ops(dev);
508 int err;
509
Vladimir Oltean0fa44482021-12-05 01:00:34 +0200510 /* Simulate a probing event for the CPU port */
511 if (ops->port_probe) {
512 err = ops->port_probe(dev, priv->cpu_port,
513 priv->cpu_port_fixed_phy);
514 if (err)
515 return err;
516 }
517
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200518 return 0;
519}
520
521UCLASS_DRIVER(dsa) = {
522 .id = UCLASS_DSA,
523 .name = "dsa",
524 .post_bind = dsa_post_bind,
525 .pre_probe = dsa_pre_probe,
Tim Harveyc5868fc2022-11-30 09:42:45 -0800526 .post_probe = dsa_post_probe,
Claudiu Manoilfc054d52021-01-25 14:23:53 +0200527 .per_device_auto = sizeof(struct dsa_priv),
528 .per_device_plat_auto = sizeof(struct dsa_pdata),
529 .per_child_plat_auto = sizeof(struct dsa_port_pdata),
530 .flags = DM_UC_FLAG_SEQ_ALIAS,
531};