blob: 2ce9ddb90d25f5f4f04461fe2d2fd98ff2dc4b9d [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
31 if (!dev || !dev_get_uclass_priv(dev))
32 return -ENODEV;
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
47/* returns the DSA master Ethernet device */
48struct udevice *dsa_get_master(struct udevice *dev)
49{
50 struct dsa_priv *priv = dev_get_uclass_priv(dev);
51
52 if (!priv)
53 return NULL;
54
55 return priv->master_dev;
56}
57
58/*
59 * Start the desired port, the CPU port and the master Eth interface.
60 * TODO: if cascaded we may need to _start ports in other switches too
61 */
62static int dsa_port_start(struct udevice *pdev)
63{
64 struct udevice *dev = dev_get_parent(pdev);
65 struct dsa_priv *priv = dev_get_uclass_priv(dev);
66 struct udevice *master = dsa_get_master(dev);
67 struct dsa_ops *ops = dsa_get_ops(dev);
68 int err;
69
70 if (!priv)
71 return -ENODEV;
72
73 if (!master) {
74 dev_err(pdev, "DSA master Ethernet device not found!\n");
75 return -EINVAL;
76 }
77
78 if (ops->port_enable) {
79 struct dsa_port_pdata *port_pdata;
80
81 port_pdata = dev_get_parent_plat(pdev);
82 err = ops->port_enable(dev, port_pdata->index,
83 port_pdata->phy);
84 if (err)
85 return err;
86
87 err = ops->port_enable(dev, priv->cpu_port,
88 priv->cpu_port_fixed_phy);
89 if (err)
90 return err;
91 }
92
93 return eth_get_ops(master)->start(master);
94}
95
96/* Stop the desired port, the CPU port and the master Eth interface */
97static void dsa_port_stop(struct udevice *pdev)
98{
99 struct udevice *dev = dev_get_parent(pdev);
100 struct dsa_priv *priv = dev_get_uclass_priv(dev);
101 struct udevice *master = dsa_get_master(dev);
102 struct dsa_ops *ops = dsa_get_ops(dev);
103
104 if (!priv)
105 return;
106
107 if (ops->port_disable) {
108 struct dsa_port_pdata *port_pdata;
109
110 port_pdata = dev_get_parent_plat(pdev);
111 ops->port_disable(dev, port_pdata->index, port_pdata->phy);
112 ops->port_disable(dev, priv->cpu_port, NULL);
113 }
114
115 /*
116 * stop master only if it's active, don't probe it otherwise.
117 * Under normal usage it would be active because we're using it, but
118 * during tear-down it may have been removed ahead of us.
119 */
120 if (master && device_active(master))
121 eth_get_ops(master)->stop(master);
122}
123
124/*
125 * Insert a DSA tag and call master Ethernet send on the resulting packet
126 * We copy the frame to a stack buffer where we have reserved headroom and
127 * tailroom space. Headroom and tailroom are set to 0.
128 */
129static int dsa_port_send(struct udevice *pdev, void *packet, int length)
130{
131 struct udevice *dev = dev_get_parent(pdev);
132 struct dsa_priv *priv = dev_get_uclass_priv(dev);
133 int head = priv->headroom, tail = priv->tailroom;
134 struct udevice *master = dsa_get_master(dev);
135 struct dsa_ops *ops = dsa_get_ops(dev);
136 uchar dsa_packet_tmp[PKTSIZE_ALIGN];
137 struct dsa_port_pdata *port_pdata;
138 int err;
139
140 if (!master)
141 return -EINVAL;
142
143 if (length + head + tail > PKTSIZE_ALIGN)
144 return -EINVAL;
145
146 memset(dsa_packet_tmp, 0, head);
147 memset(dsa_packet_tmp + head + length, 0, tail);
148 memcpy(dsa_packet_tmp + head, packet, length);
149 length += head + tail;
150 /* copy back to preserve original buffer alignment */
151 memcpy(packet, dsa_packet_tmp, length);
152
153 port_pdata = dev_get_parent_plat(pdev);
154 err = ops->xmit(dev, port_pdata->index, packet, length);
155 if (err)
156 return err;
157
158 return eth_get_ops(master)->send(master, packet, length);
159}
160
161/* Receive a frame from master Ethernet, process it and pass it on */
162static int dsa_port_recv(struct udevice *pdev, int flags, uchar **packetp)
163{
164 struct udevice *dev = dev_get_parent(pdev);
165 struct dsa_priv *priv = dev_get_uclass_priv(dev);
166 int head = priv->headroom, tail = priv->tailroom;
167 struct udevice *master = dsa_get_master(dev);
168 struct dsa_ops *ops = dsa_get_ops(dev);
169 struct dsa_port_pdata *port_pdata;
170 int length, port_index, err;
171
172 if (!master)
173 return -EINVAL;
174
175 length = eth_get_ops(master)->recv(master, flags, packetp);
176 if (length <= 0)
177 return length;
178
179 /*
180 * If we receive frames from a different port or frames that DSA driver
181 * doesn't like we discard them here.
182 * In case of discard we return with no frame and expect to be called
183 * again instead of looping here, so upper layer can deal with timeouts.
184 */
185 port_pdata = dev_get_parent_plat(pdev);
186 err = ops->rcv(dev, &port_index, *packetp, length);
187 if (err || port_index != port_pdata->index || (length <= head + tail)) {
188 if (eth_get_ops(master)->free_pkt)
189 eth_get_ops(master)->free_pkt(master, *packetp, length);
190 return -EAGAIN;
191 }
192
193 /*
194 * We move the pointer over headroom here to avoid a copy. If free_pkt
195 * gets called we move the pointer back before calling master free_pkt.
196 */
197 *packetp += head;
198
199 return length - head - tail;
200}
201
202static int dsa_port_free_pkt(struct udevice *pdev, uchar *packet, int length)
203{
204 struct udevice *dev = dev_get_parent(pdev);
205 struct udevice *master = dsa_get_master(dev);
206 struct dsa_priv *priv;
207
208 if (!master)
209 return -EINVAL;
210
211 priv = dev_get_uclass_priv(dev);
212 if (eth_get_ops(master)->free_pkt) {
213 /* return the original pointer and length to master Eth */
214 packet -= priv->headroom;
215 length += priv->headroom - priv->tailroom;
216
217 return eth_get_ops(master)->free_pkt(master, packet, length);
218 }
219
220 return 0;
221}
222
223static int dsa_port_of_to_pdata(struct udevice *pdev)
224{
225 struct dsa_port_pdata *port_pdata;
226 struct dsa_pdata *dsa_pdata;
227 struct eth_pdata *eth_pdata;
228 struct udevice *dev;
229 const char *label;
230 u32 index;
231 int err;
232
233 if (!pdev)
234 return -ENODEV;
235
236 err = ofnode_read_u32(dev_ofnode(pdev), "reg", &index);
237 if (err)
238 return err;
239
240 dev = dev_get_parent(pdev);
241 dsa_pdata = dev_get_uclass_plat(dev);
242
243 port_pdata = dev_get_parent_plat(pdev);
244 port_pdata->index = index;
245
246 label = ofnode_read_string(dev_ofnode(pdev), "label");
247 if (label)
248 strncpy(port_pdata->name, label, DSA_PORT_NAME_LENGTH);
249
250 eth_pdata = dev_get_plat(pdev);
251 eth_pdata->priv_pdata = port_pdata;
252
253 dev_dbg(pdev, "port %d node %s\n", port_pdata->index,
254 ofnode_get_name(dev_ofnode(pdev)));
255
256 return 0;
257}
258
259static const struct eth_ops dsa_port_ops = {
260 .start = dsa_port_start,
261 .send = dsa_port_send,
262 .recv = dsa_port_recv,
263 .stop = dsa_port_stop,
264 .free_pkt = dsa_port_free_pkt,
265};
266
267static int dsa_port_probe(struct udevice *pdev)
268{
269 struct udevice *dev = dev_get_parent(pdev);
270 struct eth_pdata *eth_pdata, *master_pdata;
271 unsigned char env_enetaddr[ARP_HLEN];
272 struct dsa_port_pdata *port_pdata;
273 struct dsa_priv *dsa_priv;
274 struct udevice *master;
275
276 port_pdata = dev_get_parent_plat(pdev);
277 dsa_priv = dev_get_uclass_priv(dev);
278
279 port_pdata->phy = dm_eth_phy_connect(pdev);
280 if (!port_pdata->phy)
281 return -ENODEV;
282
283 /*
284 * Inherit port's hwaddr from the DSA master, unless the port already
285 * has a unique MAC address specified in the environment.
286 */
287 eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
288 if (!is_zero_ethaddr(env_enetaddr))
289 return 0;
290
291 master = dsa_get_master(dev);
292 if (!master)
293 return 0;
294
295 master_pdata = dev_get_plat(master);
296 eth_pdata = dev_get_plat(pdev);
297 memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN);
298 eth_env_set_enetaddr_by_index("eth", dev_seq(pdev),
299 master_pdata->enetaddr);
300
301 return 0;
302}
303
304static int dsa_port_remove(struct udevice *pdev)
305{
306 struct udevice *dev = dev_get_parent(pdev);
307 struct dsa_port_pdata *port_pdata;
308 struct dsa_priv *dsa_priv;
309
310 port_pdata = dev_get_parent_plat(pdev);
311 dsa_priv = dev_get_uclass_priv(dev);
312
313 port_pdata->phy = NULL;
314
315 return 0;
316}
317
318U_BOOT_DRIVER(dsa_port) = {
319 .name = DSA_PORT_CHILD_DRV_NAME,
320 .id = UCLASS_ETH,
321 .ops = &dsa_port_ops,
322 .probe = dsa_port_probe,
323 .remove = dsa_port_remove,
324 .of_to_plat = dsa_port_of_to_pdata,
325 .plat_auto = sizeof(struct eth_pdata),
326};
327
328/*
329 * This function mostly deals with pulling information out of the device tree
330 * into the pdata structure.
331 * It goes through the list of switch ports, registers an eth device for each
332 * front panel port and identifies the cpu port connected to master eth device.
333 * TODO: support cascaded switches
334 */
335static int dsa_post_bind(struct udevice *dev)
336{
337 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
338 ofnode node = dev_ofnode(dev), pnode;
339 int i, err, first_err = 0;
340
341 if (!pdata || !ofnode_valid(node))
342 return -ENODEV;
343
344 pdata->master_node = ofnode_null();
345
346 node = ofnode_find_subnode(node, "ports");
347 if (!ofnode_valid(node))
348 node = ofnode_find_subnode(node, "ethernet-ports");
349 if (!ofnode_valid(node)) {
350 dev_err(dev, "ports node is missing under DSA device!\n");
351 return -EINVAL;
352 }
353
354 pdata->num_ports = ofnode_get_child_count(node);
355 if (pdata->num_ports <= 0 || pdata->num_ports > DSA_MAX_PORTS) {
356 dev_err(dev, "invalid number of ports (%d)\n",
357 pdata->num_ports);
358 return -EINVAL;
359 }
360
361 /* look for the CPU port */
362 ofnode_for_each_subnode(pnode, node) {
363 u32 ethernet;
364
365 if (ofnode_read_u32(pnode, "ethernet", &ethernet))
366 continue;
367
368 pdata->master_node = ofnode_get_by_phandle(ethernet);
369 pdata->cpu_port_node = pnode;
370 break;
371 }
372
373 if (!ofnode_valid(pdata->master_node)) {
374 dev_err(dev, "master eth node missing!\n");
375 return -EINVAL;
376 }
377
378 if (ofnode_read_u32(pnode, "reg", &pdata->cpu_port)) {
379 dev_err(dev, "CPU port node not valid!\n");
380 return -EINVAL;
381 }
382
383 dev_dbg(dev, "master node %s on port %d\n",
384 ofnode_get_name(pdata->master_node), pdata->cpu_port);
385
386 for (i = 0; i < pdata->num_ports; i++) {
387 char name[DSA_PORT_NAME_LENGTH];
388 struct udevice *pdev;
389
390 /*
391 * If this is the CPU port don't register it as an ETH device,
392 * we skip it on purpose since I/O to/from it from the CPU
393 * isn't useful.
394 */
395 if (i == pdata->cpu_port)
396 continue;
397
398 /*
399 * Set up default port names. If present, DT port labels
400 * will override the default port names.
401 */
402 snprintf(name, DSA_PORT_NAME_LENGTH, "%s@%d", dev->name, i);
403
404 ofnode_for_each_subnode(pnode, node) {
405 u32 reg;
406
407 if (ofnode_read_u32(pnode, "reg", &reg))
408 continue;
409
410 if (reg == i)
411 break;
412 }
413
414 /*
415 * skip registration if port id not found or if the port
416 * is explicitly disabled in DT
417 */
418 if (!ofnode_valid(pnode) || !ofnode_is_available(pnode))
419 continue;
420
421 err = device_bind_driver_to_node(dev, DSA_PORT_CHILD_DRV_NAME,
422 name, pnode, &pdev);
423 if (pdev) {
424 struct dsa_port_pdata *port_pdata;
425
426 port_pdata = dev_get_parent_plat(pdev);
427 strncpy(port_pdata->name, name, DSA_PORT_NAME_LENGTH);
428 pdev->name = port_pdata->name;
429 }
430
431 /* try to bind all ports but keep 1st error */
432 if (err && !first_err)
433 first_err = err;
434 }
435
436 if (first_err)
437 return first_err;
438
439 dev_dbg(dev, "DSA ports successfully bound\n");
440
441 return 0;
442}
443
444/**
445 * Initialize the uclass per device internal state structure (priv).
446 * TODO: pick up references to other switch devices here, if we're cascaded.
447 */
448static int dsa_pre_probe(struct udevice *dev)
449{
450 struct dsa_pdata *pdata = dev_get_uclass_plat(dev);
451 struct dsa_priv *priv = dev_get_uclass_priv(dev);
452
453 if (!pdata || !priv)
454 return -ENODEV;
455
456 priv->num_ports = pdata->num_ports;
457 priv->cpu_port = pdata->cpu_port;
458 priv->cpu_port_fixed_phy = fixed_phy_create(pdata->cpu_port_node);
459 if (!priv->cpu_port_fixed_phy) {
460 dev_err(dev, "Failed to register fixed-link for CPU port\n");
461 return -ENODEV;
462 }
463
464 uclass_find_device_by_ofnode(UCLASS_ETH, pdata->master_node,
465 &priv->master_dev);
466 return 0;
467}
468
469UCLASS_DRIVER(dsa) = {
470 .id = UCLASS_DSA,
471 .name = "dsa",
472 .post_bind = dsa_post_bind,
473 .pre_probe = dsa_pre_probe,
474 .per_device_auto = sizeof(struct dsa_priv),
475 .per_device_plat_auto = sizeof(struct dsa_pdata),
476 .per_child_plat_auto = sizeof(struct dsa_port_pdata),
477 .flags = DM_UC_FLAG_SEQ_ALIAS,
478};