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