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