/* SPDX-License-Identifier: GPL-2.0+ */ /* * Copyright 2019-2021 NXP Semiconductors */ #ifndef __DSA_H__ #define __DSA_H__ #include #include /** * 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__ */