1 /*
2  * Copyright (c) 2020 DENX Software Engineering GmbH
3  *               Lukasz Majewski <lukma@denx.de>
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /** @file
8  * @brief DSA definitions and handlers
9  */
10 
11 #ifndef ZEPHYR_INCLUDE_NET_DSA_H_
12 #define ZEPHYR_INCLUDE_NET_DSA_H_
13 
14 #include <zephyr/device.h>
15 #include <zephyr/net/net_if.h>
16 
17 /**
18  * @brief DSA definitions and helpers
19  * @defgroup DSA Distributed Switch Architecture definitions and helpers
20  * @since 2.5
21  * @version 0.8.0
22  * @ingroup networking
23  * @{
24  */
25 
26 /** @cond INTERNAL_HIDDEN */
27 
28 #define NET_DSA_PORT_MAX_COUNT 8
29 #define DSA_STATUS_PERIOD_MS K_MSEC(1000)
30 
31 #ifdef CONFIG_DSA_TAG_SIZE
32 #define DSA_TAG_SIZE CONFIG_DSA_TAG_SIZE
33 #else
34 #define DSA_TAG_SIZE 0
35 #endif
36 
37 /** @endcond */
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @brief DSA generic transmit function
45  *
46  * This is a generic function for passing packets from slave DSA interface to
47  * master.
48  *
49  * @param dev Device
50  * @param pkt Network packet
51  *
52  * Returns:
53  *  - 0 if ok (packet sent via master iface), < 0 if error
54  */
55 int dsa_tx(const struct device *dev, struct net_pkt *pkt);
56 
57 /**
58  * @brief DSA (MGMT) Receive packet callback
59  *
60  * Callback gets called upon receiving packet. It is responsible for
61  * freeing packet or indicating to the stack that it needs to free packet
62  * by returning correct net_verdict.
63  *
64  * Returns:
65  *  - NET_DROP, if packet was invalid, rejected or we want the stack to free it.
66  *    In this case the core stack will free the packet.
67  *  - NET_OK, if the packet was accepted, in this case the ownership of the
68  *    net_pkt goes to callback and core network stack will forget it.
69  */
70 typedef enum net_verdict (*dsa_net_recv_cb_t)(struct net_if *iface,
71 					      struct net_pkt *pkt);
72 
73 /**
74  * @brief Register DSA Rx callback functions
75  *
76  * @param iface Network interface
77  * @param cb Receive callback function
78  *
79  * @return 0 if ok, < 0 if error
80  */
81 int dsa_register_recv_callback(struct net_if *iface, dsa_net_recv_cb_t cb);
82 
83 /**
84  * @brief Set DSA interface to packet
85  *
86  * @param iface Network interface (master)
87  * @param pkt Network packet
88  *
89  * @return Return the slave network interface
90  */
91 struct net_if *dsa_net_recv(struct net_if *iface, struct net_pkt **pkt);
92 
93 /**
94  * @brief Pointer to master interface send function
95  */
96 typedef int (*dsa_send_t)(const struct device *dev, struct net_pkt *pkt);
97 
98 /**
99  * @brief DSA helper function to register transmit function for master
100  *
101  * @param iface Network interface (master)
102  * @param fn Pointer to master interface send method
103  *
104  * Returns:
105  *  - 0 if ok, < 0 if error
106  */
107 int dsa_register_master_tx(struct net_if *iface, dsa_send_t fn);
108 
109 /**
110  * @brief DSA helper function to check if port is master
111  *
112  * @param iface Network interface (master)
113  *
114  * Returns:
115  *  - true if ok, false otherwise
116  */
117 bool dsa_is_port_master(struct net_if *iface);
118 
119 /**
120  * @cond INTERNAL_HIDDEN
121  *
122  * These are for internal use only, so skip these in
123  * public documentation.
124  */
125 
126 /** DSA context data */
127 struct dsa_context {
128 	/** Pointers to all DSA slave network interfaces */
129 	struct net_if *iface_slave[NET_DSA_PORT_MAX_COUNT];
130 
131 	/** Pointer to DSA master network interface */
132 	struct net_if *iface_master;
133 
134 	/** DSA specific API callbacks - filled in the switch IC driver */
135 	struct dsa_api *dapi;
136 
137 	/** DSA related work (e.g. monitor if network interface is up) */
138 	struct k_work_delayable dsa_work;
139 
140 	/** Number of slave ports in the DSA switch */
141 	uint8_t num_slave_ports;
142 
143 	/** Status of each port */
144 	bool link_up[NET_DSA_PORT_MAX_COUNT];
145 
146 	/** Instance specific data */
147 	void *prv_data;
148 };
149 
150 /**
151  * @brief Structure to provide DSA switch api callbacks - it is an augmented
152  * struct ethernet_api.
153  */
154 struct dsa_api {
155 	/** Function to get proper LAN{123} interface */
156 	struct net_if *(*dsa_get_iface)(struct net_if *iface,
157 					struct net_pkt *pkt);
158 	/*
159 	 * Callbacks required for DSA switch initialization and configuration.
160 	 *
161 	 * Each switch instance (e.g. two KSZ8794 ICs) would have its own struct
162 	 * dsa_context.
163 	 */
164 	/** Read value from DSA register */
165 	int (*switch_read)(const struct device *dev, uint16_t reg_addr,
166 				uint8_t *value);
167 	/** Write value to DSA register */
168 	int (*switch_write)(const struct device *dev, uint16_t reg_addr,
169 				uint8_t value);
170 
171 	/** Program (set) mac table entry in the DSA switch */
172 	int (*switch_set_mac_table_entry)(const struct device *dev,
173 						const uint8_t *mac,
174 						uint8_t fw_port,
175 						uint16_t tbl_entry_idx,
176 						uint16_t flags);
177 
178 	/** Read mac table entry from the DSA switch */
179 	int (*switch_get_mac_table_entry)(const struct device *dev,
180 						uint8_t *buf,
181 						uint16_t tbl_entry_idx);
182 
183 	/*
184 	 * DSA helper callbacks
185 	 */
186 	struct net_pkt *(*dsa_xmit_pkt)(struct net_if *iface,
187 					struct net_pkt *pkt);
188 };
189 
190 /**
191  * @endcond
192  */
193 
194 /**
195  * @brief      Get network interface of a slave port
196  *
197  * @param      iface      Master port
198  * @param[in]  slave_num  Slave port number
199  *
200  * @return     network interface of the slave if successful
201  * @return     NULL if slave port does not exist
202  */
203 struct net_if *dsa_get_slave_port(struct net_if *iface, int slave_num);
204 
205 /**
206  * @brief      Read from DSA switch register
207  *
208  * @param      iface     The interface
209  * @param[in]  reg_addr  The register address
210  * @param      value     The value
211  *
212  * @return     0 if successful, negative if error
213  */
214 int dsa_switch_read(struct net_if *iface, uint16_t reg_addr, uint8_t *value);
215 
216 /**
217  * @brief      Write to DSA switch
218  *
219  * @param      iface     The interface
220  * @param[in]  reg_addr  The register address
221  * @param[in]  value     The value
222  *
223  * @return     { description_of_the_return_value }
224  */
225 int dsa_switch_write(struct net_if *iface, uint16_t reg_addr, uint8_t value);
226 
227 /**
228  * @brief      Write static MAC table entry
229  *
230  * @param      iface          Master DSA interface
231  * @param[in]  mac            MAC address
232  * @param[in]  fw_port        The firmware port
233  * @param[in]  tbl_entry_idx  Table entry index
234  * @param[in]  flags          Flags
235  *
236  * @return     0 if successful, negative if error
237  */
238 int dsa_switch_set_mac_table_entry(struct net_if *iface,
239 					const uint8_t *mac,
240 					uint8_t fw_port,
241 					uint16_t tbl_entry_idx,
242 					uint16_t flags);
243 
244 /**
245  * @brief      Read static MAC table entry
246  *
247  * @param      iface          Master DSA interface
248  * @param      buf            Buffer to receive MAC address
249  * @param[in]  tbl_entry_idx  Table entry index
250  *
251  * @return     0 if successful, negative if error
252  */
253 int dsa_switch_get_mac_table_entry(struct net_if *iface,
254 					uint8_t *buf,
255 					uint16_t tbl_entry_idx);
256 
257 /**
258  * @brief Structure to provide mac address for each LAN interface
259  */
260 
261 struct dsa_slave_config {
262 	/** MAC address for each LAN{123.,} ports */
263 	uint8_t mac_addr[6];
264 };
265 
266 #ifdef __cplusplus
267 }
268 #endif
269 
270 /**
271  * @}
272  */
273 #endif /* ZEPHYR_INCLUDE_NET_DSA_H_ */
274