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> 19ec9436baSFlorian Fainelli #include <linux/phy.h> 20ce31b31cSFlorian Fainelli #include <linux/phy_fixed.h> 21a2820543SFlorian Fainelli #include <linux/ethtool.h> 22cf50dcc2SBen Hutchings 23ac7a04c3SFlorian Fainelli enum dsa_tag_protocol { 24ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_NONE = 0, 25ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_DSA, 26ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_TRAILER, 27ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_EDSA, 28ac7a04c3SFlorian Fainelli DSA_TAG_PROTO_BRCM, 29ac7a04c3SFlorian Fainelli }; 305037d532SFlorian Fainelli 31e84665c9SLennert Buytenhek #define DSA_MAX_SWITCHES 4 3291da11f8SLennert Buytenhek #define DSA_MAX_PORTS 12 3391da11f8SLennert Buytenhek 34e84665c9SLennert Buytenhek struct dsa_chip_data { 35e84665c9SLennert Buytenhek /* 36e84665c9SLennert Buytenhek * How to access the switch configuration registers. 37e84665c9SLennert Buytenhek */ 38b4d2394dSAlexander Duyck struct device *host_dev; 39e84665c9SLennert Buytenhek int sw_addr; 40e84665c9SLennert Buytenhek 416793abb4SGuenter Roeck /* set to size of eeprom if supported by the switch */ 426793abb4SGuenter Roeck int eeprom_len; 436793abb4SGuenter Roeck 44fa981d9aSFlorian Fainelli /* Device tree node pointer for this specific switch chip 45fa981d9aSFlorian Fainelli * used during switch setup in case additional properties 46fa981d9aSFlorian Fainelli * and resources needs to be used 47fa981d9aSFlorian Fainelli */ 48fa981d9aSFlorian Fainelli struct device_node *of_node; 49fa981d9aSFlorian Fainelli 50e84665c9SLennert Buytenhek /* 51e84665c9SLennert Buytenhek * The names of the switch's ports. Use "cpu" to 52e84665c9SLennert Buytenhek * designate the switch port that the cpu is connected to, 53e84665c9SLennert Buytenhek * "dsa" to indicate that this port is a DSA link to 54e84665c9SLennert Buytenhek * another switch, NULL to indicate the port is unused, 55e84665c9SLennert Buytenhek * or any other string to indicate this is a physical port. 56e84665c9SLennert Buytenhek */ 57e84665c9SLennert Buytenhek char *port_names[DSA_MAX_PORTS]; 58bd47497aSFlorian Fainelli struct device_node *port_dn[DSA_MAX_PORTS]; 59e84665c9SLennert Buytenhek 60e84665c9SLennert Buytenhek /* 61e84665c9SLennert Buytenhek * An array (with nr_chips elements) of which element [a] 62e84665c9SLennert Buytenhek * indicates which port on this switch should be used to 63e84665c9SLennert Buytenhek * send packets to that are destined for switch a. Can be 64e84665c9SLennert Buytenhek * NULL if there is only one switch chip. 65e84665c9SLennert Buytenhek */ 66e84665c9SLennert Buytenhek s8 *rtable; 67e84665c9SLennert Buytenhek }; 68e84665c9SLennert Buytenhek 6991da11f8SLennert Buytenhek struct dsa_platform_data { 7091da11f8SLennert Buytenhek /* 7191da11f8SLennert Buytenhek * Reference to a Linux network interface that connects 72e84665c9SLennert Buytenhek * to the root switch chip of the tree. 7391da11f8SLennert Buytenhek */ 7491da11f8SLennert Buytenhek struct device *netdev; 7591da11f8SLennert Buytenhek 7691da11f8SLennert Buytenhek /* 77e84665c9SLennert Buytenhek * Info structs describing each of the switch chips 78e84665c9SLennert Buytenhek * connected via this network interface. 7991da11f8SLennert Buytenhek */ 80e84665c9SLennert Buytenhek int nr_chips; 81e84665c9SLennert Buytenhek struct dsa_chip_data *chip; 8291da11f8SLennert Buytenhek }; 8391da11f8SLennert Buytenhek 845075314eSAlexander Duyck struct packet_type; 853e8a72d1SFlorian Fainelli 86cf50dcc2SBen Hutchings struct dsa_switch_tree { 87cf50dcc2SBen Hutchings /* 88cf50dcc2SBen Hutchings * Configuration data for the platform device that owns 89cf50dcc2SBen Hutchings * this dsa switch tree instance. 90cf50dcc2SBen Hutchings */ 91cf50dcc2SBen Hutchings struct dsa_platform_data *pd; 92cf85d08fSLennert Buytenhek 93cf50dcc2SBen Hutchings /* 94cf50dcc2SBen Hutchings * Reference to network device to use, and which tagging 95cf50dcc2SBen Hutchings * protocol to use. 96cf50dcc2SBen Hutchings */ 97cf50dcc2SBen Hutchings struct net_device *master_netdev; 985075314eSAlexander Duyck int (*rcv)(struct sk_buff *skb, 995075314eSAlexander Duyck struct net_device *dev, 1005075314eSAlexander Duyck struct packet_type *pt, 1015075314eSAlexander Duyck struct net_device *orig_dev); 102ac7a04c3SFlorian Fainelli enum dsa_tag_protocol tag_protocol; 103cf50dcc2SBen Hutchings 104cf50dcc2SBen Hutchings /* 105cf50dcc2SBen Hutchings * The switch and port to which the CPU is attached. 106cf50dcc2SBen Hutchings */ 107cf50dcc2SBen Hutchings s8 cpu_switch; 108cf50dcc2SBen Hutchings s8 cpu_port; 109cf50dcc2SBen Hutchings 110cf50dcc2SBen Hutchings /* 111cf50dcc2SBen Hutchings * Link state polling. 112cf50dcc2SBen Hutchings */ 113cf50dcc2SBen Hutchings int link_poll_needed; 114cf50dcc2SBen Hutchings struct work_struct link_poll_work; 115cf50dcc2SBen Hutchings struct timer_list link_poll_timer; 116cf50dcc2SBen Hutchings 117cf50dcc2SBen Hutchings /* 118cf50dcc2SBen Hutchings * Data for the individual switch chips. 119cf50dcc2SBen Hutchings */ 120cf50dcc2SBen Hutchings struct dsa_switch *ds[DSA_MAX_SWITCHES]; 121cf50dcc2SBen Hutchings }; 122cf50dcc2SBen Hutchings 123c8f0b869SBen Hutchings struct dsa_switch { 124c8f0b869SBen Hutchings /* 125c8f0b869SBen Hutchings * Parent switch tree, and switch index. 126c8f0b869SBen Hutchings */ 127c8f0b869SBen Hutchings struct dsa_switch_tree *dst; 128c8f0b869SBen Hutchings int index; 129c8f0b869SBen Hutchings 130c8f0b869SBen Hutchings /* 131c8f0b869SBen Hutchings * Configuration data for this switch. 132c8f0b869SBen Hutchings */ 133c8f0b869SBen Hutchings struct dsa_chip_data *pd; 134c8f0b869SBen Hutchings 135c8f0b869SBen Hutchings /* 136c8f0b869SBen Hutchings * The used switch driver. 137c8f0b869SBen Hutchings */ 138c8f0b869SBen Hutchings struct dsa_switch_driver *drv; 139c8f0b869SBen Hutchings 140c8f0b869SBen Hutchings /* 141b4d2394dSAlexander Duyck * Reference to host device to use. 142c8f0b869SBen Hutchings */ 143b4d2394dSAlexander Duyck struct device *master_dev; 144c8f0b869SBen Hutchings 14551579c3fSGuenter Roeck #ifdef CONFIG_NET_DSA_HWMON 14651579c3fSGuenter Roeck /* 14751579c3fSGuenter Roeck * Hardware monitoring information 14851579c3fSGuenter Roeck */ 14951579c3fSGuenter Roeck char hwmon_name[IFNAMSIZ + 8]; 15051579c3fSGuenter Roeck struct device *hwmon_dev; 15151579c3fSGuenter Roeck #endif 15251579c3fSGuenter Roeck 153c8f0b869SBen Hutchings /* 154c8f0b869SBen Hutchings * Slave mii_bus and devices for the individual ports. 155c8f0b869SBen Hutchings */ 156c8f0b869SBen Hutchings u32 dsa_port_mask; 157c8f0b869SBen Hutchings u32 phys_port_mask; 1580d8bcdd3SFlorian Fainelli u32 phys_mii_mask; 159c8f0b869SBen Hutchings struct mii_bus *slave_mii_bus; 160c8f0b869SBen Hutchings struct net_device *ports[DSA_MAX_PORTS]; 161c8f0b869SBen Hutchings }; 162c8f0b869SBen Hutchings 163c8f0b869SBen Hutchings static inline bool dsa_is_cpu_port(struct dsa_switch *ds, int p) 164c8f0b869SBen Hutchings { 165c8f0b869SBen Hutchings return !!(ds->index == ds->dst->cpu_switch && p == ds->dst->cpu_port); 166c8f0b869SBen Hutchings } 167c8f0b869SBen Hutchings 168*d79d2107SGuenter Roeck static inline bool dsa_is_port_initialized(struct dsa_switch *ds, int p) 169*d79d2107SGuenter Roeck { 170*d79d2107SGuenter Roeck return ds->phys_port_mask & (1 << p) && ds->ports[p]; 171*d79d2107SGuenter Roeck } 172*d79d2107SGuenter Roeck 173c8f0b869SBen Hutchings static inline u8 dsa_upstream_port(struct dsa_switch *ds) 174c8f0b869SBen Hutchings { 175c8f0b869SBen Hutchings struct dsa_switch_tree *dst = ds->dst; 176c8f0b869SBen Hutchings 177c8f0b869SBen Hutchings /* 178c8f0b869SBen Hutchings * If this is the root switch (i.e. the switch that connects 179c8f0b869SBen Hutchings * to the CPU), return the cpu port number on this switch. 180c8f0b869SBen Hutchings * Else return the (DSA) port number that connects to the 181c8f0b869SBen Hutchings * switch that is one hop closer to the cpu. 182c8f0b869SBen Hutchings */ 183c8f0b869SBen Hutchings if (dst->cpu_switch == ds->index) 184c8f0b869SBen Hutchings return dst->cpu_port; 185c8f0b869SBen Hutchings else 186c8f0b869SBen Hutchings return ds->pd->rtable[dst->cpu_switch]; 187c8f0b869SBen Hutchings } 188c8f0b869SBen Hutchings 189c8f0b869SBen Hutchings struct dsa_switch_driver { 190c8f0b869SBen Hutchings struct list_head list; 191c8f0b869SBen Hutchings 192ac7a04c3SFlorian Fainelli enum dsa_tag_protocol tag_protocol; 193c8f0b869SBen Hutchings int priv_size; 194c8f0b869SBen Hutchings 195c8f0b869SBen Hutchings /* 196c8f0b869SBen Hutchings * Probing and setup. 197c8f0b869SBen Hutchings */ 198b4d2394dSAlexander Duyck char *(*probe)(struct device *host_dev, int sw_addr); 199c8f0b869SBen Hutchings int (*setup)(struct dsa_switch *ds); 200c8f0b869SBen Hutchings int (*set_addr)(struct dsa_switch *ds, u8 *addr); 2016819563eSFlorian Fainelli u32 (*get_phy_flags)(struct dsa_switch *ds, int port); 202c8f0b869SBen Hutchings 203c8f0b869SBen Hutchings /* 204c8f0b869SBen Hutchings * Access to the switch's PHY registers. 205c8f0b869SBen Hutchings */ 206c8f0b869SBen Hutchings int (*phy_read)(struct dsa_switch *ds, int port, int regnum); 207c8f0b869SBen Hutchings int (*phy_write)(struct dsa_switch *ds, int port, 208c8f0b869SBen Hutchings int regnum, u16 val); 209c8f0b869SBen Hutchings 210c8f0b869SBen Hutchings /* 211c8f0b869SBen Hutchings * Link state polling and IRQ handling. 212c8f0b869SBen Hutchings */ 213c8f0b869SBen Hutchings void (*poll_link)(struct dsa_switch *ds); 214c8f0b869SBen Hutchings 215c8f0b869SBen Hutchings /* 216ec9436baSFlorian Fainelli * Link state adjustment (called from libphy) 217ec9436baSFlorian Fainelli */ 218ec9436baSFlorian Fainelli void (*adjust_link)(struct dsa_switch *ds, int port, 219ec9436baSFlorian Fainelli struct phy_device *phydev); 220ce31b31cSFlorian Fainelli void (*fixed_link_update)(struct dsa_switch *ds, int port, 221ce31b31cSFlorian Fainelli struct fixed_phy_status *st); 222ec9436baSFlorian Fainelli 223ec9436baSFlorian Fainelli /* 224c8f0b869SBen Hutchings * ethtool hardware statistics. 225c8f0b869SBen Hutchings */ 226c8f0b869SBen Hutchings void (*get_strings)(struct dsa_switch *ds, int port, uint8_t *data); 227c8f0b869SBen Hutchings void (*get_ethtool_stats)(struct dsa_switch *ds, 228c8f0b869SBen Hutchings int port, uint64_t *data); 229c8f0b869SBen Hutchings int (*get_sset_count)(struct dsa_switch *ds); 23024462549SFlorian Fainelli 23124462549SFlorian Fainelli /* 23219e57c4eSFlorian Fainelli * ethtool Wake-on-LAN 23319e57c4eSFlorian Fainelli */ 23419e57c4eSFlorian Fainelli void (*get_wol)(struct dsa_switch *ds, int port, 23519e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 23619e57c4eSFlorian Fainelli int (*set_wol)(struct dsa_switch *ds, int port, 23719e57c4eSFlorian Fainelli struct ethtool_wolinfo *w); 23819e57c4eSFlorian Fainelli 23919e57c4eSFlorian Fainelli /* 24024462549SFlorian Fainelli * Suspend and resume 24124462549SFlorian Fainelli */ 24224462549SFlorian Fainelli int (*suspend)(struct dsa_switch *ds); 24324462549SFlorian Fainelli int (*resume)(struct dsa_switch *ds); 244b2f2af21SFlorian Fainelli 245b2f2af21SFlorian Fainelli /* 246b2f2af21SFlorian Fainelli * Port enable/disable 247b2f2af21SFlorian Fainelli */ 248b2f2af21SFlorian Fainelli int (*port_enable)(struct dsa_switch *ds, int port, 249b2f2af21SFlorian Fainelli struct phy_device *phy); 250b2f2af21SFlorian Fainelli void (*port_disable)(struct dsa_switch *ds, int port, 251b2f2af21SFlorian Fainelli struct phy_device *phy); 2527905288fSFlorian Fainelli 2537905288fSFlorian Fainelli /* 2547905288fSFlorian Fainelli * EEE setttings 2557905288fSFlorian Fainelli */ 2567905288fSFlorian Fainelli int (*set_eee)(struct dsa_switch *ds, int port, 2577905288fSFlorian Fainelli struct phy_device *phydev, 2587905288fSFlorian Fainelli struct ethtool_eee *e); 2597905288fSFlorian Fainelli int (*get_eee)(struct dsa_switch *ds, int port, 2607905288fSFlorian Fainelli struct ethtool_eee *e); 26151579c3fSGuenter Roeck 26251579c3fSGuenter Roeck #ifdef CONFIG_NET_DSA_HWMON 26351579c3fSGuenter Roeck /* Hardware monitoring */ 26451579c3fSGuenter Roeck int (*get_temp)(struct dsa_switch *ds, int *temp); 26551579c3fSGuenter Roeck int (*get_temp_limit)(struct dsa_switch *ds, int *temp); 26651579c3fSGuenter Roeck int (*set_temp_limit)(struct dsa_switch *ds, int temp); 26751579c3fSGuenter Roeck int (*get_temp_alarm)(struct dsa_switch *ds, bool *alarm); 26851579c3fSGuenter Roeck #endif 2696793abb4SGuenter Roeck 2706793abb4SGuenter Roeck /* EEPROM access */ 2716793abb4SGuenter Roeck int (*get_eeprom_len)(struct dsa_switch *ds); 2726793abb4SGuenter Roeck int (*get_eeprom)(struct dsa_switch *ds, 2736793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 2746793abb4SGuenter Roeck int (*set_eeprom)(struct dsa_switch *ds, 2756793abb4SGuenter Roeck struct ethtool_eeprom *eeprom, u8 *data); 2763d762a0fSGuenter Roeck 2773d762a0fSGuenter Roeck /* 2783d762a0fSGuenter Roeck * Register access. 2793d762a0fSGuenter Roeck */ 2803d762a0fSGuenter Roeck int (*get_regs_len)(struct dsa_switch *ds, int port); 2813d762a0fSGuenter Roeck void (*get_regs)(struct dsa_switch *ds, int port, 2823d762a0fSGuenter Roeck struct ethtool_regs *regs, void *p); 283b73adef6SFlorian Fainelli 284b73adef6SFlorian Fainelli /* 285b73adef6SFlorian Fainelli * Bridge integration 286b73adef6SFlorian Fainelli */ 287b73adef6SFlorian Fainelli int (*port_join_bridge)(struct dsa_switch *ds, int port, 288b73adef6SFlorian Fainelli u32 br_port_mask); 289b73adef6SFlorian Fainelli int (*port_leave_bridge)(struct dsa_switch *ds, int port, 290b73adef6SFlorian Fainelli u32 br_port_mask); 291b73adef6SFlorian Fainelli int (*port_stp_update)(struct dsa_switch *ds, int port, 292b73adef6SFlorian Fainelli u8 state); 293c8f0b869SBen Hutchings }; 294c8f0b869SBen Hutchings 295c8f0b869SBen Hutchings void register_switch_driver(struct dsa_switch_driver *type); 296c8f0b869SBen Hutchings void unregister_switch_driver(struct dsa_switch_driver *type); 297b4d2394dSAlexander Duyck struct mii_bus *dsa_host_dev_to_mii_bus(struct device *dev); 298c8f0b869SBen Hutchings 2997fa857edSFlorian Fainelli static inline void *ds_to_priv(struct dsa_switch *ds) 3007fa857edSFlorian Fainelli { 3017fa857edSFlorian Fainelli return (void *)(ds + 1); 3027fa857edSFlorian Fainelli } 3037fa857edSFlorian Fainelli 3045aed85ceSFlorian Fainelli static inline bool dsa_uses_tagged_protocol(struct dsa_switch_tree *dst) 3055aed85ceSFlorian Fainelli { 3065075314eSAlexander Duyck return dst->rcv != NULL; 3075aed85ceSFlorian Fainelli } 30891da11f8SLennert Buytenhek #endif 309