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