]>
git.ipfire.org Git - thirdparty/u-boot.git/blob - net/dsa-uclass.c
1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright 2019-2021 NXP
8 #include <dm/device_compat.h>
9 #include <dm/device-internal.h>
10 #include <dm/uclass-internal.h>
11 #include <linux/bitmap.h>
14 #define DSA_PORT_CHILD_DRV_NAME "dsa-port"
16 /* per-device internal state structure */
18 struct phy_device
*cpu_port_fixed_phy
;
19 struct udevice
*master_dev
;
27 int dsa_set_tagging(struct udevice
*dev
, ushort headroom
, ushort tailroom
)
29 struct dsa_priv
*priv
;
34 if (headroom
+ tailroom
> DSA_MAX_OVR
)
37 priv
= dev_get_uclass_priv(dev
);
40 priv
->headroom
= headroom
;
42 priv
->tailroom
= tailroom
;
47 ofnode
dsa_port_get_ofnode(struct udevice
*dev
, int port
)
49 struct dsa_pdata
*pdata
= dev_get_uclass_plat(dev
);
50 struct dsa_port_pdata
*port_pdata
;
53 if (port
== pdata
->cpu_port
)
54 return pdata
->cpu_port_node
;
56 for (device_find_first_child(dev
, &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
);
67 /* returns the DSA master Ethernet device */
68 struct udevice
*dsa_get_master(struct udevice
*dev
)
70 struct dsa_priv
*priv
;
75 priv
= dev_get_uclass_priv(dev
);
77 return priv
->master_dev
;
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
84 static int dsa_port_start(struct udevice
*pdev
)
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
);
92 if (ops
->port_enable
) {
93 struct dsa_port_pdata
*port_pdata
;
95 port_pdata
= dev_get_parent_plat(pdev
);
96 err
= ops
->port_enable(dev
, port_pdata
->index
,
101 err
= ops
->port_enable(dev
, priv
->cpu_port
,
102 priv
->cpu_port_fixed_phy
);
107 return eth_get_ops(master
)->start(master
);
110 /* Stop the desired port, the CPU port and the master Eth interface */
111 static void dsa_port_stop(struct udevice
*pdev
)
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
);
118 if (ops
->port_disable
) {
119 struct dsa_port_pdata
*port_pdata
;
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
);
126 eth_get_ops(master
)->stop(master
);
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.
134 static int dsa_port_send(struct udevice
*pdev
, void *packet
, int length
)
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
;
146 if (length
+ head
+ tail
> PKTSIZE_ALIGN
)
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 /* copy back to preserve original buffer alignment */
154 memcpy(packet
, dsa_packet_tmp
, length
);
156 port_pdata
= dev_get_parent_plat(pdev
);
157 err
= ops
->xmit(dev
, port_pdata
->index
, packet
, length
);
162 return eth_get_ops(master
)->send(master
, packet
, length
);
165 /* Receive a frame from master Ethernet, process it and pass it on */
166 static int dsa_port_recv(struct udevice
*pdev
, int flags
, uchar
**packetp
)
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
;
176 length
= eth_get_ops(master
)->recv(master
, flags
, packetp
);
177 if (length
<= 0 || !ops
->rcv
)
181 * If we receive frames from a different port or frames that DSA driver
182 * doesn't like we discard them here.
183 * In case of discard we return with no frame and expect to be called
184 * again instead of looping here, so upper layer can deal with timeouts.
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
);
195 * We move the pointer over headroom here to avoid a copy. If free_pkt
196 * gets called we move the pointer back before calling master free_pkt.
200 return length
- head
- tail
;
203 static int dsa_port_free_pkt(struct udevice
*pdev
, uchar
*packet
, int length
)
205 struct udevice
*dev
= dev_get_parent(pdev
);
206 struct udevice
*master
= dsa_get_master(dev
);
207 struct dsa_priv
*priv
;
209 priv
= dev_get_uclass_priv(dev
);
210 if (eth_get_ops(master
)->free_pkt
) {
211 /* return the original pointer and length to master Eth */
212 packet
-= priv
->headroom
;
213 length
+= priv
->headroom
- priv
->tailroom
;
215 return eth_get_ops(master
)->free_pkt(master
, packet
, length
);
221 static int dsa_port_of_to_pdata(struct udevice
*pdev
)
223 struct dsa_port_pdata
*port_pdata
;
224 struct eth_pdata
*eth_pdata
;
232 err
= ofnode_read_u32(dev_ofnode(pdev
), "reg", &index
);
236 port_pdata
= dev_get_parent_plat(pdev
);
237 port_pdata
->index
= index
;
239 label
= ofnode_read_string(dev_ofnode(pdev
), "label");
241 strlcpy(port_pdata
->name
, label
, DSA_PORT_NAME_LENGTH
);
243 eth_pdata
= dev_get_plat(pdev
);
244 eth_pdata
->priv_pdata
= port_pdata
;
246 dev_dbg(pdev
, "port %d node %s\n", port_pdata
->index
,
247 ofnode_get_name(dev_ofnode(pdev
)));
252 static 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
,
261 * Inherit port's hwaddr from the DSA master, unless the port already has a
262 * unique MAC address specified in the environment.
264 static void dsa_port_set_hwaddr(struct udevice
*pdev
, struct udevice
*master
)
266 struct eth_pdata
*eth_pdata
, *master_pdata
;
267 unsigned char env_enetaddr
[ARP_HLEN
];
269 eth_env_get_enetaddr_by_index("eth", dev_seq(pdev
), env_enetaddr
);
270 if (!is_zero_ethaddr(env_enetaddr
)) {
271 /* individual port mac addrs require master to be promisc */
272 struct eth_ops
*eth_ops
= eth_get_ops(master
);
274 if (eth_ops
->set_promisc
)
275 eth_ops
->set_promisc(master
, true);
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
);
287 static int dsa_port_probe(struct udevice
*pdev
)
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
;
295 port_pdata
= dev_get_parent_plat(pdev
);
297 port_pdata
->phy
= dm_eth_phy_connect(pdev
);
298 if (!port_pdata
->phy
)
301 master
= dsa_get_master(dev
);
306 * Probe the master device. We depend on the master device for proper
307 * operation and we also need it for MAC inheritance below.
309 * TODO: we assume the master device is always there and doesn't get
310 * removed during runtime.
312 err
= device_probe(master
);
316 dsa_port_set_hwaddr(pdev
, master
);
318 if (ops
->port_probe
) {
319 err
= ops
->port_probe(dev
, port_pdata
->index
,
328 static int dsa_port_remove(struct udevice
*pdev
)
330 struct dsa_port_pdata
*port_pdata
= dev_get_parent_plat(pdev
);
332 port_pdata
->phy
= NULL
;
337 U_BOOT_DRIVER(dsa_port
) = {
338 .name
= DSA_PORT_CHILD_DRV_NAME
,
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
),
347 static int dsa_sanitize_ops(struct udevice
*dev
)
349 struct dsa_ops
*ops
= dsa_get_ops(dev
);
351 if ((!ops
->xmit
|| !ops
->rcv
) &&
352 (!ops
->port_enable
&& !ops
->port_disable
)) {
353 dev_err(dev
, "Packets cannot be steered to ports\n");
361 * This function mostly deals with pulling information out of the device tree
362 * into the pdata structure.
363 * It goes through the list of switch ports, registers an eth device for each
364 * front panel port and identifies the cpu port connected to master eth device.
365 * TODO: support cascaded switches
367 static int dsa_post_bind(struct udevice
*dev
)
369 struct dsa_pdata
*pdata
= dev_get_uclass_plat(dev
);
370 ofnode node
= dev_ofnode(dev
), pnode
;
371 int i
, err
, first_err
= 0;
373 if (!ofnode_valid(node
))
376 err
= dsa_sanitize_ops(dev
);
380 pdata
->master_node
= ofnode_null();
382 node
= ofnode_find_subnode(node
, "ports");
383 if (!ofnode_valid(node
))
384 node
= ofnode_find_subnode(dev_ofnode(dev
), "ethernet-ports");
385 if (!ofnode_valid(node
)) {
386 dev_err(dev
, "ports node is missing under DSA device!\n");
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",
397 /* look for the CPU port */
398 ofnode_for_each_subnode(pnode
, node
) {
401 if (ofnode_read_u32(pnode
, "ethernet", ðernet
))
404 pdata
->master_node
= ofnode_get_by_phandle(ethernet
);
405 pdata
->cpu_port_node
= pnode
;
409 if (!ofnode_valid(pdata
->master_node
)) {
410 dev_err(dev
, "master eth node missing!\n");
414 if (ofnode_read_u32(pnode
, "reg", &pdata
->cpu_port
)) {
415 dev_err(dev
, "CPU port node not valid!\n");
419 dev_dbg(dev
, "master node %s on port %d\n",
420 ofnode_get_name(pdata
->master_node
), pdata
->cpu_port
);
422 for (i
= 0; i
< pdata
->num_ports
; i
++) {
423 char name
[DSA_PORT_NAME_LENGTH
];
424 struct udevice
*pdev
;
427 * If this is the CPU port don't register it as an ETH device,
428 * we skip it on purpose since I/O to/from it from the CPU
431 if (i
== pdata
->cpu_port
)
435 * Set up default port names. If present, DT port labels
436 * will override the default port names.
438 snprintf(name
, DSA_PORT_NAME_LENGTH
, "%s@%d", dev
->name
, i
);
440 ofnode_for_each_subnode(pnode
, node
) {
443 if (ofnode_read_u32(pnode
, "reg", ®
))
451 * skip registration if port id not found or if the port
452 * is explicitly disabled in DT
454 if (!ofnode_valid(pnode
) || !ofnode_is_enabled(pnode
))
457 err
= device_bind_driver_to_node(dev
, DSA_PORT_CHILD_DRV_NAME
,
460 struct dsa_port_pdata
*port_pdata
;
462 port_pdata
= dev_get_parent_plat(pdev
);
463 strlcpy(port_pdata
->name
, name
, DSA_PORT_NAME_LENGTH
);
464 pdev
->name
= port_pdata
->name
;
467 /* try to bind all ports but keep 1st error */
468 if (err
&& !first_err
)
475 dev_dbg(dev
, "DSA ports successfully bound\n");
481 * Initialize the uclass per device internal state structure (priv).
482 * TODO: pick up references to other switch devices here, if we're cascaded.
484 static int dsa_pre_probe(struct udevice
*dev
)
486 struct dsa_pdata
*pdata
= dev_get_uclass_plat(dev
);
487 struct dsa_priv
*priv
= dev_get_uclass_priv(dev
);
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");
498 err
= uclass_get_device_by_ofnode(UCLASS_ETH
, pdata
->master_node
,
506 static int dsa_post_probe(struct udevice
*dev
)
508 struct dsa_priv
*priv
= dev_get_uclass_priv(dev
);
509 struct dsa_ops
*ops
= dsa_get_ops(dev
);
512 /* Simulate a probing event for the CPU port */
513 if (ops
->port_probe
) {
514 err
= ops
->port_probe(dev
, priv
->cpu_port
,
515 priv
->cpu_port_fixed_phy
);
523 UCLASS_DRIVER(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
,