diff options
author | Claudiu Manoil <claudiu.manoil@nxp.com> | 2021-01-25 14:23:53 +0200 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2021-02-16 11:48:20 -0500 |
commit | fc054d563bfb676f808f26204dfe17c690eed1ba (patch) | |
tree | 8ce6b59c99c0821434c7eda2d4add41f1d46493a /include | |
parent | d0781c95bc448a211546404c779e78b29ada1214 (diff) | |
download | u-boot-fc054d563bfb676f808f26204dfe17c690eed1ba.zip u-boot-fc054d563bfb676f808f26204dfe17c690eed1ba.tar.gz u-boot-fc054d563bfb676f808f26204dfe17c690eed1ba.tar.bz2 |
net: Introduce DSA class for Ethernet switches
DSA stands for Distributed Switch Architecture and it covers switches that
are connected to the CPU through an Ethernet link and generally use frame
tags to pass information about the source/destination ports to/from CPU.
Front panel ports are presented as regular ethernet devices in U-Boot and
they are expected to support the typical networking commands.
DSA switches may be cascaded, DSA class code does not currently support
this.
Signed-off-by: Alex Marginean <alexandru.marginean@nxp.com>
Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/dm/uclass-id.h | 1 | ||||
-rw-r--r-- | include/net.h | 6 | ||||
-rw-r--r-- | include/net/dsa.h | 165 |
3 files changed, 172 insertions, 0 deletions
diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index ae4425d..d75de36 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -46,6 +46,7 @@ enum uclass_id { UCLASS_DISPLAY, /* Display (e.g. DisplayPort, HDMI) */ UCLASS_DSI_HOST, /* Display Serial Interface host */ UCLASS_DMA, /* Direct Memory Access */ + UCLASS_DSA, /* Distributed (Ethernet) Switch Architecture */ UCLASS_EFI, /* EFI managed devices */ UCLASS_ETH, /* Ethernet device */ UCLASS_ETH_PHY, /* Ethernet PHY device */ diff --git a/include/net.h b/include/net.h index 13da69b..b95d6a6 100644 --- a/include/net.h +++ b/include/net.h @@ -499,7 +499,13 @@ struct icmp_hdr { * maximum packet size and multiple of 32 bytes = 1536 */ #define PKTSIZE 1522 +#ifndef CONFIG_DM_DSA #define PKTSIZE_ALIGN 1536 +#else +/* Maximum DSA tagging overhead (headroom and/or tailroom) */ +#define DSA_MAX_OVR 256 +#define PKTSIZE_ALIGN (1536 + DSA_MAX_OVR) +#endif /* * Maximum receive ring size; that is, the number of packets diff --git a/include/net/dsa.h b/include/net/dsa.h new file mode 100644 index 0000000..0f31a90 --- /dev/null +++ b/include/net/dsa.h @@ -0,0 +1,165 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2019-2021 NXP Semiconductors + */ + +#ifndef __DSA_H__ +#define __DSA_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_enable: Initialize a switch port for I/O. + * @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_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_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__ */ |