1
2
3
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
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
27int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom)
28{
29 struct dsa_priv *priv;
30
31 if (!dev)
32 return -EINVAL;
33
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
47ofnode 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
67
68struct udevice *dsa_get_master(struct udevice *dev)
69{
70 struct dsa_priv *priv;
71
72 if (!dev)
73 return NULL;
74
75 priv = dev_get_uclass_priv(dev);
76
77 return priv->master_dev;
78}
79
80
81
82
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
92 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
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
118 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);
123 ops->port_disable(dev, priv->cpu_port, priv->cpu_port_fixed_phy);
124 }
125
126 eth_get_ops(master)->stop(master);
127}
128
129
130
131
132
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
145 if (ops->xmit) {
146 if (length + head + tail > PKTSIZE_ALIGN)
147 return -EINVAL;
148
149 memset(dsa_packet_tmp, 0, head);
150 memset(dsa_packet_tmp + head + length, 0, tail);
151 memcpy(dsa_packet_tmp + head, packet, length);
152 length += head + tail;
153
154 memcpy(packet, dsa_packet_tmp, length);
155
156 port_pdata = dev_get_parent_plat(pdev);
157 err = ops->xmit(dev, port_pdata->index, packet, length);
158 if (err)
159 return err;
160 }
161
162 return eth_get_ops(master)->send(master, packet, length);
163}
164
165
166static int dsa_port_recv(struct udevice *pdev, int flags, uchar **packetp)
167{
168 struct udevice *dev = dev_get_parent(pdev);
169 struct dsa_priv *priv = dev_get_uclass_priv(dev);
170 int head = priv->headroom, tail = priv->tailroom;
171 struct udevice *master = dsa_get_master(dev);
172 struct dsa_ops *ops = dsa_get_ops(dev);
173 struct dsa_port_pdata *port_pdata;
174 int length, port_index, err;
175
176 length = eth_get_ops(master)->recv(master, flags, packetp);
177 if (length <= 0 || !ops->rcv)
178 return length;
179
180
181
182
183
184
185
186 port_pdata = dev_get_parent_plat(pdev);
187 err = ops->rcv(dev, &port_index, *packetp, length);
188 if (err || port_index != port_pdata->index || (length <= head + tail)) {
189 if (eth_get_ops(master)->free_pkt)
190 eth_get_ops(master)->free_pkt(master, *packetp, length);
191 return -EAGAIN;
192 }
193
194
195
196
197
198 *packetp += head;
199
200 return length - head - tail;
201}
202
203static int dsa_port_free_pkt(struct udevice *pdev, uchar *packet, int length)
204{
205 struct udevice *dev = dev_get_parent(pdev);
206 struct udevice *master = dsa_get_master(dev);
207 struct dsa_priv *priv;
208
209 priv = dev_get_uclass_priv(dev);
210 if (eth_get_ops(master)->free_pkt) {
211
212 packet -= priv->headroom;
213 length += priv->headroom - priv->tailroom;
214
215 return eth_get_ops(master)->free_pkt(master, packet, length);
216 }
217
218 return 0;
219}
220
221static int dsa_port_of_to_pdata(struct udevice *pdev)
222{
223 struct dsa_port_pdata *port_pdata;
224 struct eth_pdata *eth_pdata;
225 const char *label;
226 u32 index;
227 int err;
228
229 if (!pdev)
230 return -ENODEV;
231
232 err = ofnode_read_u32(dev_ofnode(pdev), "reg", &index);
233 if (err)
234 return err;
235
236 port_pdata = dev_get_parent_plat(pdev);
237 port_pdata->index = index;
238
239 label = ofnode_read_string(dev_ofnode(pdev), "label");
240 if (label)
241 strlcpy(port_pdata->name, label, DSA_PORT_NAME_LENGTH);
242
243 eth_pdata = dev_get_plat(pdev);
244 eth_pdata->priv_pdata = port_pdata;
245
246 dev_dbg(pdev, "port %d node %s\n", port_pdata->index,
247 ofnode_get_name(dev_ofnode(pdev)));
248
249 return 0;
250}
251
252static const struct eth_ops dsa_port_ops = {
253 .start = dsa_port_start,
254 .send = dsa_port_send,
255 .recv = dsa_port_recv,
256 .stop = dsa_port_stop,
257 .free_pkt = dsa_port_free_pkt,
258};
259
260
261
262
263
264static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master)
265{
266 struct eth_pdata *eth_pdata, *master_pdata;
267 unsigned char env_enetaddr[ARP_HLEN];
268
269 eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
270 if (!is_zero_ethaddr(env_enetaddr)) {
271
272 struct eth_ops *eth_ops = eth_get_ops(master);
273
274 if (eth_ops->set_promisc)
275 eth_ops->set_promisc(master, true);
276
277 return;
278 }
279
280 master_pdata = dev_get_plat(master);
281 eth_pdata = dev_get_plat(pdev);
282 memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN);
283 eth_env_set_enetaddr_by_index("eth", dev_seq(pdev),
284 master_pdata->enetaddr);
285}
286
287static int dsa_port_probe(struct udevice *pdev)
288{
289 struct udevice *dev = dev_get_parent(pdev);
290 struct dsa_ops *ops = dsa_get_ops(dev);
291 struct dsa_port_pdata *port_pdata;
292 struct udevice *master;
293 int err;
294
295 port_pdata = dev_get_parent_plat(pdev);
296
297 port_pdata->phy = dm_eth_phy_connect(pdev);
298 if (!port_pdata->phy)
299 return -ENODEV;
300
301 master = dsa_get_master(dev);
302 if (!master)
303 return -ENODEV;
304
305
306
307
308
309
310
311
312 err = device_probe(master);
313 if (err)
314 return err;
315
316 dsa_port_set_hwaddr(pdev, master);
317
318 if (ops->port_probe) {
319 err = ops->port_probe(dev, port_pdata->index,
320 port_pdata->phy);
321 if (err)
322 return err;
323 }
324
325 return 0;
326}
327
328static int dsa_port_remove(struct udevice *pdev)
329{
330 struct dsa_port_pdata *port_pdata = dev_get_parent_plat(pdev);
331
332 port_pdata->phy = NULL;
333
334 return 0;
335}
336
337U_BOOT_DRIVER(dsa_port) = {
338 .name = DSA_PORT_CHILD_DRV_NAME,
339 .id = UCLASS_ETH,
340 .ops = &dsa_port_ops,
341 .probe = dsa_port_probe,
342 .remove = dsa_port_remove,
343 .of_to_plat = dsa_port_of_to_pdata,
344 .plat_auto = sizeof(struct eth_pdata),
345};
346
347static int dsa_sanitize_ops(struct udevice *dev)
348{
349 struct dsa_ops *ops = dsa_get_ops(dev);
350
351 if ((!ops->xmit || !ops->rcv) &&
352 (!ops->port_enable && !ops->port_disable)) {
353 dev_err(dev, "Packets cannot be steered to ports\n");
354 return -EINVAL;
355 }
356
357 return 0;
358}
359
360
361
362
363
364
365
366
367static int dsa_post_bind(struct udevice *dev)
368{
369 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
370 ofnode node = dev_ofnode(dev), pnode;
371 int i, err, first_err = 0;
372
373 if (!ofnode_valid(node))
374 return -ENODEV;
375
376 err = dsa_sanitize_ops(dev);
377 if (err)
378 return err;
379
380 pdata->master_node = ofnode_null();
381
382 node = ofnode_find_subnode(node, "ports");
383 if (!ofnode_valid(node))
384 node = ofnode_find_subnode(node, "ethernet-ports");
385 if (!ofnode_valid(node)) {
386 dev_err(dev, "ports node is missing under DSA device!\n");
387 return -EINVAL;
388 }
389
390 pdata->num_ports = ofnode_get_child_count(node);
391 if (pdata->num_ports <= 0 || pdata->num_ports > DSA_MAX_PORTS) {
392 dev_err(dev, "invalid number of ports (%d)\n",
393 pdata->num_ports);
394 return -EINVAL;
395 }
396
397
398 ofnode_for_each_subnode(pnode, node) {
399 u32 ethernet;
400
401 if (ofnode_read_u32(pnode, "ethernet", ðernet))
402 continue;
403
404 pdata->master_node = ofnode_get_by_phandle(ethernet);
405 pdata->cpu_port_node = pnode;
406 break;
407 }
408
409 if (!ofnode_valid(pdata->master_node)) {
410 dev_err(dev, "master eth node missing!\n");
411 return -EINVAL;
412 }
413
414 if (ofnode_read_u32(pnode, "reg", &pdata->cpu_port)) {
415 dev_err(dev, "CPU port node not valid!\n");
416 return -EINVAL;
417 }
418
419 dev_dbg(dev, "master node %s on port %d\n",
420 ofnode_get_name(pdata->master_node), pdata->cpu_port);
421
422 for (i = 0; i < pdata->num_ports; i++) {
423 char name[DSA_PORT_NAME_LENGTH];
424 struct udevice *pdev;
425
426
427
428
429
430
431 if (i == pdata->cpu_port)
432 continue;
433
434
435
436
437
438 snprintf(name, DSA_PORT_NAME_LENGTH, "%s@%d", dev->name, i);
439
440 ofnode_for_each_subnode(pnode, node) {
441 u32 reg;
442
443 if (ofnode_read_u32(pnode, "reg", ®))
444 continue;
445
446 if (reg == i)
447 break;
448 }
449
450
451
452
453
454 if (!ofnode_valid(pnode) || !ofnode_is_enabled(pnode))
455 continue;
456
457 err = device_bind_driver_to_node(dev, DSA_PORT_CHILD_DRV_NAME,
458 name, pnode, &pdev);
459 if (pdev) {
460 struct dsa_port_pdata *port_pdata;
461
462 port_pdata = dev_get_parent_plat(pdev);
463 strlcpy(port_pdata->name, name, DSA_PORT_NAME_LENGTH);
464 pdev->name = port_pdata->name;
465 }
466
467
468 if (err && !first_err)
469 first_err = err;
470 }
471
472 if (first_err)
473 return first_err;
474
475 dev_dbg(dev, "DSA ports successfully bound\n");
476
477 return 0;
478}
479
480
481
482
483
484static int dsa_pre_probe(struct udevice *dev)
485{
486 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
487 struct dsa_priv *priv = dev_get_uclass_priv(dev);
488 int err;
489
490 priv->num_ports = pdata->num_ports;
491 priv->cpu_port = pdata->cpu_port;
492 priv->cpu_port_fixed_phy = fixed_phy_create(pdata->cpu_port_node);
493 if (!priv->cpu_port_fixed_phy) {
494 dev_err(dev, "Failed to register fixed-link for CPU port\n");
495 return -ENODEV;
496 }
497
498 err = uclass_get_device_by_ofnode(UCLASS_ETH, pdata->master_node,
499 &priv->master_dev);
500 if (err)
501 return err;
502
503 return 0;
504}
505
506static int dsa_post_probe(struct udevice *dev)
507{
508 struct dsa_priv *priv = dev_get_uclass_priv(dev);
509 struct dsa_ops *ops = dsa_get_ops(dev);
510 int err;
511
512
513 if (ops->port_probe) {
514 err = ops->port_probe(dev, priv->cpu_port,
515 priv->cpu_port_fixed_phy);
516 if (err)
517 return err;
518 }
519
520 return 0;
521}
522
523UCLASS_DRIVER(dsa) = {
524 .id = UCLASS_DSA,
525 .name = "dsa",
526 .post_bind = dsa_post_bind,
527 .pre_probe = dsa_pre_probe,
528 .post_probe = dsa_post_probe,
529 .per_device_auto = sizeof(struct dsa_priv),
530 .per_device_plat_auto = sizeof(struct dsa_pdata),
531 .per_child_plat_auto = sizeof(struct dsa_port_pdata),
532 .flags = DM_UC_FLAG_SEQ_ALIAS,
533};
534