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