2021-01-25 12:23:53 +00:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0+ */
|
|
|
|
/*
|
2021-09-17 11:27:13 +00:00
|
|
|
* Copyright 2019-2021 NXP
|
2021-01-25 12:23:53 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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
|
|
|
|
*
|
2021-08-24 12:00:41 +00:00
|
|
|
* @port_probe: Initialize a switch port.
|
|
|
|
* @port_enable: Enable I/O for a port.
|
2021-01-25 12:23:53 +00:00
|
|
|
* @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 {
|
2021-08-24 12:00:41 +00:00
|
|
|
int (*port_probe)(struct udevice *dev, int port,
|
|
|
|
struct phy_device *phy);
|
2021-01-25 12:23:53 +00:00
|
|
|
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__ */
|