1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright 2019-2021 NXP Semiconductors
4  */
5 
6 #ifndef __DSA_H__
7 #define __DSA_H__
8 
9 #include <phy.h>
10 #include <net.h>
11 
12 /**
13  * DSA stands for Distributed Switch Architecture and it is infrastructure
14  * intended to support drivers for Switches that rely on an intermediary
15  * Ethernet device for I/O.  These switches may support cascading allowing
16  * them to be arranged as a tree.
17  * DSA is documented in detail in the Linux kernel documentation under
18  * Documentation/networking/dsa/dsa.txt
19  * The network layout of such a switch is shown below:
20  *
21  *                      |------|
22  *                      | eth0 | <--- master eth device (regular eth driver)
23  *                      |------|
24  *                        ^  |
25  * tag added by switch -->|  |
26  *                        |  |
27  *                        |  |<-- tag added by DSA driver
28  *                        |  v
29  *      |--------------------------------------|
30  *      |             | CPU port |             | <-- DSA (switch) device
31  *      |             ------------             |     (DSA driver)
32  *      | _________  _________       _________ |
33  *      | | port0 |  | port1 |  ...  | portn | | <-- ports as eth devices
34  *      |-+-------+--+-------+-------+-------+-|     ('dsa-port' eth driver)
35  *
36  * In U-Boot the intent is to allow access to front panel ports (shown at the
37  * bottom of the picture) through the master Ethernet dev (eth0 in the picture).
38  * Front panel ports are presented as regular Ethernet devices in U-Boot and
39  * they are expected to support the typical networking commands.
40  * In general DSA switches require the use of tags, extra headers added both by
41  * software on Tx and by the switch on Rx.  These tags carry at a minimum port
42  * information and switch information for cascaded set-ups.
43  * In U-Boot these tags are inserted and parsed by the DSA switch driver, the
44  * class code helps with headroom/tailroom for the extra headers.
45  *
46  * TODO:
47  * - handle switch cascading, for now U-Boot only supports stand-alone switches.
48  * - Add support to probe DSA switches connected to a MDIO bus, this is needed
49  * to convert switch drivers that are now under drivers/net/phy.
50  */
51 
52 #define DSA_PORT_NAME_LENGTH	16
53 
54 /* Maximum number of ports each DSA device can have */
55 #define DSA_MAX_PORTS		12
56 
57 /**
58  * struct dsa_ops - DSA operations
59  *
60  * @port_enable:  Initialize a switch port for I/O.
61  * @port_disable: Disable I/O for a port.
62  * @xmit:         Insert the DSA tag for transmission.
63  *                DSA drivers receive a copy of the packet with headroom and
64  *                tailroom reserved and set to 0. 'packet' points to headroom
65  *                and 'length' is updated to include both head and tailroom.
66  * @rcv:          Process the DSA tag on reception and return the port index
67  *                from the h/w provided tag. Return the index via 'portp'.
68  *                'packet' and 'length' describe the frame as received from
69  *                master including any additional headers.
70  */
71 struct dsa_ops {
72 	int (*port_enable)(struct udevice *dev, int port,
73 			   struct phy_device *phy);
74 	void (*port_disable)(struct udevice *dev, int port,
75 			     struct phy_device *phy);
76 	int (*xmit)(struct udevice *dev, int port, void *packet, int length);
77 	int (*rcv)(struct udevice *dev, int *portp, void *packet, int length);
78 };
79 
80 #define dsa_get_ops(dev) ((struct dsa_ops *)(dev)->driver->ops)
81 
82 /**
83  * struct dsa_port_pdata - DSA port platform data
84  *
85  * @phy:   PHY device associated with this port.
86  *         The uclass code attempts to set this field for all ports except CPU
87  *         port, based on DT information.  It may be NULL.
88  * @index: Port index in the DSA switch, set by the uclass code.
89  * @name:  Name of the port Eth device.  If a label property is present in the
90  *         port DT node, it is used as name.
91  */
92 struct dsa_port_pdata {
93 	struct phy_device *phy;
94 	u32 index;
95 	char name[DSA_PORT_NAME_LENGTH];
96 };
97 
98 /**
99  * struct dsa_pdata - Per-device platform data for DSA DM
100  *
101  * @num_ports:   Number of ports the device has, must be <= DSA_MAX_PORTS.
102  *		 This number is extracted from the DT 'ports' node of this
103  *		 DSA device, and it counts the CPU port and all the other
104  *		 port subnodes including the disabled ones.
105  * @cpu_port:    Index of the switch port linked to the master Ethernet.
106  *		 The uclass code sets this based on DT information.
107  * @master_node: OF node of the host Ethernet controller.
108  * @cpu_port_node: DT node of the switch's CPU port.
109  */
110 struct dsa_pdata {
111 	int num_ports;
112 	u32 cpu_port;
113 	ofnode master_node;
114 	ofnode cpu_port_node;
115 };
116 
117 /**
118  * dsa_set_tagging() - Configure the headroom and/or tailroom sizes
119  *
120  * The DSA class code allocates headroom and tailroom on Tx before
121  * calling the DSA driver's xmit function.
122  * All drivers must call this at probe time.
123  *
124  * @dev:	DSA device pointer
125  * @headroom:	Size, in bytes, of headroom needed for the DSA tag.
126  * @tailroom:	Size, in bytes, of tailroom needed for the DSA tag.
127  *		Total headroom and tailroom size should not exceed
128  *		DSA_MAX_OVR.
129  * @return 0 if OK, -ve on error
130  */
131 int dsa_set_tagging(struct udevice *dev, ushort headroom, ushort tailroom);
132 
133 /* DSA helpers */
134 
135 /**
136  * dsa_get_master() - Return a reference to the master Ethernet device
137  *
138  * Can be called at driver probe time or later.
139  *
140  * @dev:	DSA device pointer
141  * @return Master Eth 'udevice' pointer if OK, NULL on error
142  */
143 struct udevice *dsa_get_master(struct udevice *dev);
144 
145 /**
146  * dsa_port_get_pdata() - Helper that returns the platdata of an active
147  *			(non-CPU) DSA port device.
148  *
149  * Can be called at driver probe time or later.
150  *
151  * @pdev:	DSA port device pointer
152  * @return 'dsa_port_pdata' pointer if OK, NULL on error
153  */
154 static inline struct dsa_port_pdata *
dsa_port_get_pdata(struct udevice * pdev)155 	dsa_port_get_pdata(struct udevice *pdev)
156 {
157 	struct eth_pdata *eth = dev_get_plat(pdev);
158 
159 	if (!eth)
160 		return NULL;
161 
162 	return eth->priv_pdata;
163 }
164 
165 #endif /* __DSA_H__ */
166