191da11f8SLennert Buytenhek /* 291da11f8SLennert Buytenhek * include/net/dsa.h - Driver for Distributed Switch Architecture switch chips 3e84665c9SLennert Buytenhek * Copyright (c) 2008-2009 Marvell Semiconductor 491da11f8SLennert Buytenhek * 591da11f8SLennert Buytenhek * This program is free software; you can redistribute it and/or modify 691da11f8SLennert Buytenhek * it under the terms of the GNU General Public License as published by 791da11f8SLennert Buytenhek * the Free Software Foundation; either version 2 of the License, or 891da11f8SLennert Buytenhek * (at your option) any later version. 991da11f8SLennert Buytenhek */ 1091da11f8SLennert Buytenhek 1191da11f8SLennert Buytenhek #ifndef __LINUX_NET_DSA_H 1291da11f8SLennert Buytenhek #define __LINUX_NET_DSA_H 1391da11f8SLennert Buytenhek 14ea1f51beSAxel Lin #include <linux/if_ether.h> 15c8f0b869SBen Hutchings #include <linux/list.h> 16cf50dcc2SBen Hutchings #include <linux/timer.h> 17cf50dcc2SBen Hutchings #include <linux/workqueue.h> 18fa981d9aSFlorian Fainelli #include <linux/of.h> 19cc30c163SAndrew Lunn #include <linux/of_gpio.h> 20ec9436baSFlorian Fainelli #include <linux/phy.h> 21ce31b31cSFlorian Fainelli #include <linux/phy_fixed.h> 22a2820543SFlorian Fainelli #include <linux/ethtool.h> 23cf50dcc2SBen Hutchings 24ac7a04c3SFlorian Fainelli enum dsa_tag_protocol { 25ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_NONE = 0, 26ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_DSA, 27ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_TRAILER, 28ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_EDSA, 29ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_BRCM, 30ac7a04c3SFlorian Fainelli }; 315037d532SFlorian Fainelli 32e84665c9SLennert Buytenhek #define DSA_MAX_SWITCHES 4 3391da11f8SLennert Buytenhek #define DSA_MAX_PORTS 12 3491da11f8SLennert Buytenhek 35e84665c9SLennert Buytenhek struct dsa_chip_data { 36e84665c9SLennert Buytenhek /* 37e84665c9SLennert Buytenhek * How to access the switch configuration registers. 38e84665c9SLennert Buytenhek */ 39b4d2394dSAlexander Duyck struct device *host_dev; 40e84665c9SLennert Buytenhek int sw_addr; 41e84665c9SLennert Buytenhek 426793abb4SGuenter Roeck /* set to size of eeprom if supported by the switch */ 436793abb4SGuenter Roeck int eeprom_len; 446793abb4SGuenter Roeck 45fa981d9aSFlorian Fainelli /* Device tree node pointer for this specific switch chip 46fa981d9aSFlorian Fainelli * used during switch setup in case additional properties 47fa981d9aSFlorian Fainelli * and resources needs to be used 48fa981d9aSFlorian Fainelli */ 49fa981d9aSFlorian Fainelli struct device_node *of_node; 50fa981d9aSFlorian Fainelli 51e84665c9SLennert Buytenhek /* 52e84665c9SLennert Buytenhek * The names of the switch's ports. Use "cpu" to 53e84665c9SLennert Buytenhek * designate the switch port that the cpu is connected to, 54e84665c9SLennert Buytenhek * "dsa" to indicate that this port is a DSA link to 55e84665c9SLennert Buytenhek * another switch, NULL to indicate the port is unused, 56e84665c9SLennert Buytenhek * or any other string to indicate this is a physical port. 57e84665c9SLennert Buytenhek */ 58e84665c9SLennert Buytenhek char *port_names[DSA_MAX_PORTS]; 59bd47497aSFlorian Fainelli struct device_node *port_dn[DSA_MAX_PORTS]; 60e84665c9SLennert Buytenhek 61e84665c9SLennert Buytenhek /* 62e84665c9SLennert Buytenhek * An array (with nr_chips elements) of which element [a] 63e84665c9SLennert Buytenhek * indicates which port on this switch should be used to 64e84665c9SLennert Buytenhek * send packets to that are destined for switch a. Can be 65e84665c9SLennert Buytenhek * NULL if there is only one switch chip. 66e84665c9SLennert Buytenhek */ 67e84665c9SLennert Buytenhek s8 *rtable; 68cc30c163SAndrew Lunn 69cc30c163SAndrew Lunn /* 70cc30c163SAndrew Lunn * A switch may have a GPIO line tied to its reset pin. Parse 71cc30c163SAndrew Lunn * this from the device tree, and use it before performing 72cc30c163SAndrew Lunn * switch soft reset. 73cc30c163SAndrew Lunn */ 74cc30c163SAndrew Lunn struct gpio_desc *reset; 75e84665c9SLennert Buytenhek }; 76e84665c9SLennert Buytenhek 7791da11f8SLennert Buytenhek struct dsa_platform_data { 7891da11f8SLennert Buytenhek /* 7991da11f8SLennert Buytenhek * Reference to a Linux network interface that connects 80e84665c9SLennert Buytenhek * to the root switch chip of the tree. 8191da11f8SLennert Buytenhek */ 8291da11f8SLennert Buytenhek struct device *netdev; 83769a0202SFlorian Fainelli struct net_device *of_netdev; 8491da11f8SLennert Buytenhek 8591da11f8SLennert Buytenhek /* 86e84665c9SLennert Buytenhek * Info structs describing each of the switch chips 87e84665c9SLennert Buytenhek * connected via this network interface. 8891da11f8SLennert Buytenhek */ 89e84665c9SLennert Buytenhek int nr_chips; 90e84665c9SLennert Buytenhek struct dsa_chip_data *chip; 9191da11f8SLennert Buytenhek }; 9291da11f8SLennert Buytenhek 935075314eSAlexander Duyck struct packet_type; 943e8a72d1SFlorian Fainelli 95cf50dcc2SBen Hutchings struct dsa_switch_tree { 96cf50dcc2SBen Hutchings /* 97cf50dcc2SBen Hutchings * Configuration data for the platform device that owns 98cf50dcc2SBen Hutchings * this dsa switch tree instance. 99cf50dcc2SBen Hutchings */ 100cf50dcc2SBen Hutchings struct dsa_platform_data *pd; 101cf85d08fSLennert Buytenhek 102cf50dcc2SBen Hutchings /* 103cf50dcc2SBen Hutchings * Reference to network device to use, and which tagging 104cf50dcc2SBen Hutchings * protocol to use. 105cf50dcc2SBen Hutchings */ 106cf50dcc2SBen Hutchings struct net_device *master_netdev; 1075075314eSAlexander Duyck int (*rcv)(struct sk_buff *skb, 1085075314eSAlexander Duyck struct net_device *dev, 1095075314eSAlexander Duyck struct packet_type *pt, 1105075314eSAlexander Duyck struct net_device *orig_dev); 111ac7a04c3SFlorian Fainelli enum dsa_tag_protocol tag_protocol; 112cf50dcc2SBen Hutchings 113cf50dcc2SBen Hutchings /* 114cf50dcc2SBen Hutchings * The switch and port to which the CPU is attached. 115cf50dcc2SBen Hutchings */ 116cf50dcc2SBen Hutchings s8 cpu_switch; 117cf50dcc2SBen Hutchings s8 cpu_port; 118cf50dcc2SBen Hutchings 119cf50dcc2SBen Hutchings /* 120cf50dcc2SBen Hutchings * Data for the individual switch chips. 121cf50dcc2SBen Hutchings */ 122cf50dcc2SBen Hutchings struct dsa_switch *ds[DSA_MAX_SWITCHES]; 123cf50dcc2SBen Hutchings }; 124cf50dcc2SBen Hutchings 125c8f0b869SBen Hutchings struct dsa_switch { 126c8f0b869SBen Hutchings /* 127c8f0b869SBen Hutchings * Parent switch tree, and switch index. 128c8f0b869SBen Hutchings */ 129c8f0b869SBen Hutchings struct dsa_switch_tree *dst; 130c8f0b869SBen Hutchings int index; 131c8f0b869SBen Hutchings 132c8f0b869SBen Hutchings /* 1337543a6d5SAndrew Lunn * Give the switch driver somewhere to hang its private data 1347543a6d5SAndrew Lunn * structure. 1357543a6d5SAndrew Lunn */ 1367543a6d5SAndrew Lunn void *priv; 1377543a6d5SAndrew Lunn 1387543a6d5SAndrew Lunn /* 13959299031SFlorian Fainelli * Tagging protocol understood by this switch 14059299031SFlorian Fainelli */ 14159299031SFlorian Fainelli enum dsa_tag_protocol tag_protocol; 14259299031SFlorian Fainelli 14359299031SFlorian Fainelli /* 144c8f0b869SBen Hutchings * Configuration data for this switch. 145c8f0b869SBen Hutchings */ 146c8f0b869SBen Hutchings struct dsa_chip_data *pd; 147c8f0b869SBen Hutchings 148c8f0b869SBen Hutchings /* 149c8f0b869SBen Hutchings * The used switch driver. 150c8f0b869SBen Hutchings */ 151c8f0b869SBen Hutchings struct dsa_switch_driver *drv; 152c8f0b869SBen Hutchings 153c8f0b869SBen Hutchings /* 154b4d2394dSAlexander Duyck * Reference to host device to use. 155c8f0b869SBen Hutchings */ 156b4d2394dSAlexander Duyck struct device *master_dev; 157c8f0b869SBen Hutchings 15851579c3fSGuenter Roeck #ifdef CONFIG_NET_DSA_HWMON 15951579c3fSGuenter Roeck /* 16051579c3fSGuenter Roeck * Hardware monitoring information 16151579c3fSGuenter Roeck */ 16251579c3fSGuenter Roeck char hwmon_name[IFNAMSIZ + 8]; 16351579c3fSGuenter Roeck struct device *hwmon_dev; 16451579c3fSGuenter Roeck #endif 16551579c3fSGuenter Roeck 166c8f0b869SBen Hutchings /* 167c8f0b869SBen Hutchings * Slave mii_bus and devices for the individual ports. 168c8f0b869SBen Hutchings */ 169c8f0b869SBen Hutchings u32 dsa_port_mask; 170*74c3e2a5SAndrew Lunn u32 enabled_port_mask; 1710d8bcdd3SFlorian Fainelli u32 phys_mii_mask; 172c8f0b869SBen Hutchings struct mii_bus *slave_mii_bus; 173c8f0b869SBen Hutchings struct net_device *ports[DSA_MAX_PORTS]; 174c8f0b869SBen Hutchings }; 175c8f0b869SBen Hutchings 176c8f0b869SBen Hutchings static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) 177c8f0b869SBen Hutchings { 178c8f0b869SBen Hutchings return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); 179c8f0b869SBen Hutchings } 180c8f0b869SBen Hutchings 18160045cbfSAndrew Lunn static inline bool dsa_is_dsa_port(struct dsa_switch *ds, int p) 18260045cbfSAndrew Lunn { 18360045cbfSAndrew Lunn return !!((ds->dsa_port_mask) & (1 << p)); 18460045cbfSAndrew Lunn } 18560045cbfSAndrew Lunn 186d79d2107SGuenter Roeck static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) 187d79d2107SGuenter Roeck { 188*74c3e2a5SAndrew Lunn return ds->enabled_port_mask & (1 << p) && ds->ports[p]; 189d79d2107SGuenter Roeck } 190d79d2107SGuenter Roeck 191c8f0b869SBen Hutchings static inline u8 dsa_upstream_port(struct dsa_switch *ds) 192c8f0b869SBen Hutchings { 193c8f0b869SBen Hutchings struct dsa_switch_tree *dst = ds->dst; 194c8f0b869SBen Hutchings 195c8f0b869SBen Hutchings /* 196c8f0b869SBen Hutchings * If this is the root switch (i.e. the switch that connects 197c8f0b869SBen Hutchings * to the CPU), return the cpu port number on this switch. 198c8f0b869SBen Hutchings * Else return the (DSA) port number that connects to the 199c8f0b869SBen Hutchings * switch that is one hop closer to the cpu. 200c8f0b869SBen Hutchings */ 201c8f0b869SBen Hutchings if (dst->cpu_switch == ds->index) 202c8f0b869SBen Hutchings return dst->cpu_port; 203c8f0b869SBen Hutchings else 204c8f0b869SBen Hutchings return ds->pd->rtable[dst->cpu_switch]; 205c8f0b869SBen Hutchings } 206c8f0b869SBen Hutchings 207146a3206SVivien Didelot struct switchdev_trans; 208ea70ba98SVivien Didelot struct switchdev_obj; 209146a3206SVivien Didelot struct switchdev_obj_port_fdb; 21076e398a6SVivien Didelot struct switchdev_obj_port_vlan; 211146a3206SVivien Didelot 212c8f0b869SBen Hutchings struct dsa_switch_driver { 213c8f0b869SBen Hutchings struct list_head list; 214c8f0b869SBen Hutchings 215ac7a04c3SFlorian Fainelli enum dsa_tag_protocol tag_protocol; 216c8f0b869SBen Hutchings 217c8f0b869SBen Hutchings /* 218c8f0b869SBen Hutchings * Probing and setup. 219c8f0b869SBen Hutchings */ 220bbb8d793SAndrew Lunn char *(*probe)(struct device *dsa_dev, struct device *host_dev, 2217543a6d5SAndrew Lunn int sw_addr, void **priv); 222c8f0b869SBen Hutchings int (*setup)(struct dsa_switch *ds); 223c8f0b869SBen Hutchings int (*set_addr)(struct dsa_switch *ds, u8 *addr); 2246819563eSFlorian Fainelli u32 (*get_phy_flags)(struct dsa_switch *ds, int port); 225c8f0b869SBen Hutchings 226c8f0b869SBen Hutchings /* 227c8f0b869SBen Hutchings * Access to the switch's PHY registers. 228c8f0b869SBen Hutchings */ 229c8f0b869SBen Hutchings int (*phy_read)(struct dsa_switch *ds, int port, int regnum); 230c8f0b869SBen Hutchings int (*phy_write)(struct dsa_switch *ds, int port, 231c8f0b869SBen Hutchings int regnum, u16 val); 232c8f0b869SBen Hutchings 233c8f0b869SBen Hutchings /* 234ec9436baSFlorian Fainelli * Link state adjustment (called from libphy) 235ec9436baSFlorian Fainelli */ 236ec9436baSFlorian Fainelli void (*adjust_link)(struct dsa_switch *ds, int port, 237ec9436baSFlorian Fainelli struct phy_device *phydev); 238ce31b31cSFlorian Fainelli void (*fixed_link_update)(struct dsa_switch *ds, int port, 239ce31b31cSFlorian Fainelli struct fixed_phy_status *st); 240ec9436baSFlorian Fainelli 241ec9436baSFlorian Fainelli /* 242c8f0b869SBen Hutchings * ethtool hardware statistics. 243c8f0b869SBen Hutchings */ 244c8f0b869SBen Hutchings void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data); 245c8f0b869SBen Hutchings void (*get_ethtool_stats)(struct dsa_switch *ds, 246c8f0b869SBen Hutchings int port, uint64_t *data); 247c8f0b869SBen Hutchings int (*get_sset_count)(struct dsa_switch *ds); 24824462549SFlorian Fainelli 24924462549SFlorian Fainelli /* 25019e57c4eSFlorian Fainelli * ethtool Wake-on-LAN 25119e57c4eSFlorian Fainelli */ 25219e57c4eSFlorian Fainelli void (*get_wol)(struct dsa_switch *ds, int port, 25319e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 25419e57c4eSFlorian Fainelli int (*set_wol)(struct dsa_switch *ds, int port, 25519e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 25619e57c4eSFlorian Fainelli 25719e57c4eSFlorian Fainelli /* 25824462549SFlorian Fainelli * Suspend and resume 25924462549SFlorian Fainelli */ 26024462549SFlorian Fainelli int (*suspend)(struct dsa_switch *ds); 26124462549SFlorian Fainelli int (*resume)(struct dsa_switch *ds); 262b2f2af21SFlorian Fainelli 263b2f2af21SFlorian Fainelli /* 264b2f2af21SFlorian Fainelli * Port enable/disable 265b2f2af21SFlorian Fainelli */ 266b2f2af21SFlorian Fainelli int (*port_enable)(struct dsa_switch *ds, int port, 267b2f2af21SFlorian Fainelli struct phy_device *phy); 268b2f2af21SFlorian Fainelli void (*port_disable)(struct dsa_switch *ds, int port, 269b2f2af21SFlorian Fainelli struct phy_device *phy); 2707905288fSFlorian Fainelli 2717905288fSFlorian Fainelli /* 2727905288fSFlorian Fainelli * EEE setttings 2737905288fSFlorian Fainelli */ 2747905288fSFlorian Fainelli int (*set_eee)(struct dsa_switch *ds, int port, 2757905288fSFlorian Fainelli struct phy_device *phydev, 2767905288fSFlorian Fainelli struct ethtool_eee *e); 2777905288fSFlorian Fainelli int (*get_eee)(struct dsa_switch *ds, int port, 2787905288fSFlorian Fainelli struct ethtool_eee *e); 27951579c3fSGuenter Roeck 28051579c3fSGuenter Roeck #ifdef CONFIG_NET_DSA_HWMON 28151579c3fSGuenter Roeck /* Hardware monitoring */ 28251579c3fSGuenter Roeck int (*get_temp)(struct dsa_switch *ds, int *temp); 28351579c3fSGuenter Roeck int (*get_temp_limit)(struct dsa_switch *ds, int *temp); 28451579c3fSGuenter Roeck int (*set_temp_limit)(struct dsa_switch *ds, int temp); 28551579c3fSGuenter Roeck int (*get_temp_alarm)(struct dsa_switch *ds, bool *alarm); 28651579c3fSGuenter Roeck #endif 2876793abb4SGuenter Roeck 2886793abb4SGuenter Roeck /* EEPROM access */ 2896793abb4SGuenter Roeck int (*get_eeprom_len)(struct dsa_switch *ds); 2906793abb4SGuenter Roeck int (*get_eeprom)(struct dsa_switch *ds, 2916793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 2926793abb4SGuenter Roeck int (*set_eeprom)(struct dsa_switch *ds, 2936793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 2943d762a0fSGuenter Roeck 2953d762a0fSGuenter Roeck /* 2963d762a0fSGuenter Roeck * Register access. 2973d762a0fSGuenter Roeck */ 2983d762a0fSGuenter Roeck int (*get_regs_len)(struct dsa_switch *ds, int port); 2993d762a0fSGuenter Roeck void (*get_regs)(struct dsa_switch *ds, int port, 3003d762a0fSGuenter Roeck struct ethtool_regs *regs, void *p); 301b73adef6SFlorian Fainelli 302b73adef6SFlorian Fainelli /* 303b73adef6SFlorian Fainelli * Bridge integration 304b73adef6SFlorian Fainelli */ 30571327a4eSVivien Didelot int (*port_bridge_join)(struct dsa_switch *ds, int port, 306a6692754SVivien Didelot struct net_device *bridge); 30716bfa702SVivien Didelot void (*port_bridge_leave)(struct dsa_switch *ds, int port); 30843c44a9fSVivien Didelot void (*port_stp_state_set)(struct dsa_switch *ds, int port, 309b73adef6SFlorian Fainelli u8 state); 3102a778e1bSVivien Didelot 3112a778e1bSVivien Didelot /* 31211149536SVivien Didelot * VLAN support 31311149536SVivien Didelot */ 314fb2dabadSVivien Didelot int (*port_vlan_filtering)(struct dsa_switch *ds, int port, 315fb2dabadSVivien Didelot bool vlan_filtering); 31676e398a6SVivien Didelot int (*port_vlan_prepare)(struct dsa_switch *ds, int port, 31776e398a6SVivien Didelot const struct switchdev_obj_port_vlan *vlan, 31876e398a6SVivien Didelot struct switchdev_trans *trans); 3194d5770b3SVivien Didelot void (*port_vlan_add)(struct dsa_switch *ds, int port, 32076e398a6SVivien Didelot const struct switchdev_obj_port_vlan *vlan, 32176e398a6SVivien Didelot struct switchdev_trans *trans); 32276e398a6SVivien Didelot int (*port_vlan_del)(struct dsa_switch *ds, int port, 32376e398a6SVivien Didelot const struct switchdev_obj_port_vlan *vlan); 32465aebfc0SVivien Didelot int (*port_vlan_dump)(struct dsa_switch *ds, int port, 32565aebfc0SVivien Didelot struct switchdev_obj_port_vlan *vlan, 32665aebfc0SVivien Didelot int (*cb)(struct switchdev_obj *obj)); 32711149536SVivien Didelot 32811149536SVivien Didelot /* 3292a778e1bSVivien Didelot * Forwarding database 3302a778e1bSVivien Didelot */ 331146a3206SVivien Didelot int (*port_fdb_prepare)(struct dsa_switch *ds, int port, 332146a3206SVivien Didelot const struct switchdev_obj_port_fdb *fdb, 333146a3206SVivien Didelot struct switchdev_trans *trans); 3348497aa61SVivien Didelot void (*port_fdb_add)(struct dsa_switch *ds, int port, 3351f36faf2SVivien Didelot const struct switchdev_obj_port_fdb *fdb, 3361f36faf2SVivien Didelot struct switchdev_trans *trans); 3372a778e1bSVivien Didelot int (*port_fdb_del)(struct dsa_switch *ds, int port, 3388057b3e7SVivien Didelot const struct switchdev_obj_port_fdb *fdb); 339ea70ba98SVivien Didelot int (*port_fdb_dump)(struct dsa_switch *ds, int port, 340ea70ba98SVivien Didelot struct switchdev_obj_port_fdb *fdb, 341ea70ba98SVivien Didelot int (*cb)(struct switchdev_obj *obj)); 342c8f0b869SBen Hutchings }; 343c8f0b869SBen Hutchings 344c8f0b869SBen Hutchings void register_switch_driver(struct dsa_switch_driver *type); 345c8f0b869SBen Hutchings void unregister_switch_driver(struct dsa_switch_driver *type); 346b4d2394dSAlexander Duyck struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev); 347c8f0b869SBen Hutchings 3487fa857edSFlorian Fainelli static inline void *ds_to_priv(struct dsa_switch *ds) 3497fa857edSFlorian Fainelli { 3507543a6d5SAndrew Lunn return ds->priv; 3517fa857edSFlorian Fainelli } 3527fa857edSFlorian Fainelli 3535aed85ceSFlorian Fainelli static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) 3545aed85ceSFlorian Fainelli { 3555075314eSAlexander Duyck return dst->rcv != NULL; 3565aed85ceSFlorian Fainelli } 35791da11f8SLennert Buytenhek #endif 358