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