12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */ 24d5f2ba7SVivien Didelot /* 34d5f2ba7SVivien Didelot * Marvell 88E6xxx Ethernet switch single-chip definition 44d5f2ba7SVivien Didelot * 54d5f2ba7SVivien Didelot * Copyright (c) 2008 Marvell Semiconductor 64d5f2ba7SVivien Didelot */ 74d5f2ba7SVivien Didelot 84d5f2ba7SVivien Didelot #ifndef _MV88E6XXX_CHIP_H 94d5f2ba7SVivien Didelot #define _MV88E6XXX_CHIP_H 104d5f2ba7SVivien Didelot 114d5f2ba7SVivien Didelot #include <linux/if_vlan.h> 124d5f2ba7SVivien Didelot #include <linux/irq.h> 134d5f2ba7SVivien Didelot #include <linux/gpio/consumer.h> 14294d711eSAndrew Lunn #include <linux/kthread.h> 154d5f2ba7SVivien Didelot #include <linux/phy.h> 162fa8d3afSBrandon Streiff #include <linux/ptp_clock_kernel.h> 172fa8d3afSBrandon Streiff #include <linux/timecounter.h> 184d5f2ba7SVivien Didelot #include <net/dsa.h> 194d5f2ba7SVivien Didelot 204d5f2ba7SVivien Didelot #define MV88E6XXX_N_FID 4096 214d5f2ba7SVivien Didelot 224d5f2ba7SVivien Didelot /* PVT limits for 4-bit port and 5-bit switch */ 234d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_SWITCHES 32 244d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_PORTS 16 254d5f2ba7SVivien Didelot 26a73ccd61SBrandon Streiff #define MV88E6XXX_MAX_GPIO 16 27a73ccd61SBrandon Streiff 2831bef4e9SVivien Didelot enum mv88e6xxx_egress_mode { 2931bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNMODIFIED, 3031bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNTAGGED, 3131bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_TAGGED, 3231bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_ETHERTYPE, 3331bef4e9SVivien Didelot }; 3431bef4e9SVivien Didelot 354d5f2ba7SVivien Didelot enum mv88e6xxx_frame_mode { 364d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_NORMAL, 374d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_DSA, 384d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_PROVIDER, 394d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_ETHERTYPE, 404d5f2ba7SVivien Didelot }; 414d5f2ba7SVivien Didelot 424d5f2ba7SVivien Didelot /* List of supported models */ 434d5f2ba7SVivien Didelot enum mv88e6xxx_model { 444d5f2ba7SVivien Didelot MV88E6085, 454d5f2ba7SVivien Didelot MV88E6095, 464d5f2ba7SVivien Didelot MV88E6097, 474d5f2ba7SVivien Didelot MV88E6123, 484d5f2ba7SVivien Didelot MV88E6131, 494d5f2ba7SVivien Didelot MV88E6141, 504d5f2ba7SVivien Didelot MV88E6161, 514d5f2ba7SVivien Didelot MV88E6165, 524d5f2ba7SVivien Didelot MV88E6171, 534d5f2ba7SVivien Didelot MV88E6172, 544d5f2ba7SVivien Didelot MV88E6175, 554d5f2ba7SVivien Didelot MV88E6176, 564d5f2ba7SVivien Didelot MV88E6185, 574d5f2ba7SVivien Didelot MV88E6190, 584d5f2ba7SVivien Didelot MV88E6190X, 594d5f2ba7SVivien Didelot MV88E6191, 6049022647SHubert Feurstein MV88E6220, 614d5f2ba7SVivien Didelot MV88E6240, 621f71836fSRasmus Villemoes MV88E6250, 634d5f2ba7SVivien Didelot MV88E6290, 644d5f2ba7SVivien Didelot MV88E6320, 654d5f2ba7SVivien Didelot MV88E6321, 664d5f2ba7SVivien Didelot MV88E6341, 674d5f2ba7SVivien Didelot MV88E6350, 684d5f2ba7SVivien Didelot MV88E6351, 694d5f2ba7SVivien Didelot MV88E6352, 704d5f2ba7SVivien Didelot MV88E6390, 714d5f2ba7SVivien Didelot MV88E6390X, 724d5f2ba7SVivien Didelot }; 734d5f2ba7SVivien Didelot 744d5f2ba7SVivien Didelot enum mv88e6xxx_family { 754d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_NONE, 764d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */ 774d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6095, /* 6092 6095 */ 784d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ 794d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ 804d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ 8149022647SHubert Feurstein MV88E6XXX_FAMILY_6250, /* 6220 6250 */ 824d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6320, /* 6320 6321 */ 834d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6341, /* 6141 6341 */ 844d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ 854d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ 864d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ 874d5f2ba7SVivien Didelot }; 884d5f2ba7SVivien Didelot 894d5f2ba7SVivien Didelot struct mv88e6xxx_ops; 904d5f2ba7SVivien Didelot 914d5f2ba7SVivien Didelot struct mv88e6xxx_info { 924d5f2ba7SVivien Didelot enum mv88e6xxx_family family; 934d5f2ba7SVivien Didelot u16 prod_num; 944d5f2ba7SVivien Didelot const char *name; 954d5f2ba7SVivien Didelot unsigned int num_databases; 964d5f2ba7SVivien Didelot unsigned int num_ports; 97bc393155SAndrew Lunn unsigned int num_internal_phys; 98a73ccd61SBrandon Streiff unsigned int num_gpio; 994d5f2ba7SVivien Didelot unsigned int max_vid; 1004d5f2ba7SVivien Didelot unsigned int port_base_addr; 1019255bacdSAndrew Lunn unsigned int phy_base_addr; 1024d5f2ba7SVivien Didelot unsigned int global1_addr; 1039069c13aSVivien Didelot unsigned int global2_addr; 1044d5f2ba7SVivien Didelot unsigned int age_time_coeff; 1054d5f2ba7SVivien Didelot unsigned int g1_irqs; 106d6c5e6afSVivien Didelot unsigned int g2_irqs; 1074d5f2ba7SVivien Didelot bool pvt; 108b3e05aa1SVivien Didelot 109c857486aSHubert Feurstein /* Mark certain ports as invalid. This is required for example for the 110c857486aSHubert Feurstein * MV88E6220 (which is in general a MV88E6250 with 7 ports) but the 111c857486aSHubert Feurstein * ports 2-4 are not routet to pins. 112c857486aSHubert Feurstein */ 113c857486aSHubert Feurstein unsigned int invalid_port_mask; 114b3e05aa1SVivien Didelot /* Multi-chip Addressing Mode. 115b3e05aa1SVivien Didelot * Some chips respond to only 2 registers of its own SMI device address 116b3e05aa1SVivien Didelot * when it is non-zero, and use indirect access to internal registers. 117b3e05aa1SVivien Didelot */ 118b3e05aa1SVivien Didelot bool multi_chip; 119f30a19b8SRasmus Villemoes /* Dual-chip Addressing Mode 120f30a19b8SRasmus Villemoes * Some chips respond to only half of the 32 SMI addresses, 121f30a19b8SRasmus Villemoes * allowing two to coexist on the same SMI interface. 122f30a19b8SRasmus Villemoes */ 123f30a19b8SRasmus Villemoes bool dual_chip; 124f30a19b8SRasmus Villemoes 1254d5f2ba7SVivien Didelot enum dsa_tag_protocol tag_protocol; 1264d5f2ba7SVivien Didelot 1274d5f2ba7SVivien Didelot /* Mask for FromPort and ToPort value of PortVec used in ATU Move 1284d5f2ba7SVivien Didelot * operation. 0 means that the ATU Move operation is not supported. 1294d5f2ba7SVivien Didelot */ 1304d5f2ba7SVivien Didelot u8 atu_move_port_mask; 1314d5f2ba7SVivien Didelot const struct mv88e6xxx_ops *ops; 1322fa8d3afSBrandon Streiff 1332fa8d3afSBrandon Streiff /* Supports PTP */ 1342fa8d3afSBrandon Streiff bool ptp_support; 1354d5f2ba7SVivien Didelot }; 1364d5f2ba7SVivien Didelot 1374d5f2ba7SVivien Didelot struct mv88e6xxx_atu_entry { 1384d5f2ba7SVivien Didelot u8 state; 1394d5f2ba7SVivien Didelot bool trunk; 1404d5f2ba7SVivien Didelot u16 portvec; 1414d5f2ba7SVivien Didelot u8 mac[ETH_ALEN]; 1424d5f2ba7SVivien Didelot }; 1434d5f2ba7SVivien Didelot 1444d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry { 1454d5f2ba7SVivien Didelot u16 vid; 1464d5f2ba7SVivien Didelot u16 fid; 1474d5f2ba7SVivien Didelot u8 sid; 1484d5f2ba7SVivien Didelot bool valid; 1494d5f2ba7SVivien Didelot u8 member[DSA_MAX_PORTS]; 1504d5f2ba7SVivien Didelot u8 state[DSA_MAX_PORTS]; 1514d5f2ba7SVivien Didelot }; 1524d5f2ba7SVivien Didelot 1534d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops; 1544d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops; 155a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops; 1560d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops; 1576d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops; 1584d5f2ba7SVivien Didelot 1594d5f2ba7SVivien Didelot struct mv88e6xxx_irq { 1604d5f2ba7SVivien Didelot u16 masked; 1614d5f2ba7SVivien Didelot struct irq_chip chip; 1624d5f2ba7SVivien Didelot struct irq_domain *domain; 1634d5f2ba7SVivien Didelot unsigned int nirqs; 1644d5f2ba7SVivien Didelot }; 1654d5f2ba7SVivien Didelot 166c6fe0ad2SBrandon Streiff /* state flags for mv88e6xxx_port_hwtstamp::state */ 167c6fe0ad2SBrandon Streiff enum { 168c6fe0ad2SBrandon Streiff MV88E6XXX_HWTSTAMP_ENABLED, 169c6fe0ad2SBrandon Streiff MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, 170c6fe0ad2SBrandon Streiff }; 171c6fe0ad2SBrandon Streiff 172c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp { 173c6fe0ad2SBrandon Streiff /* Port index */ 174c6fe0ad2SBrandon Streiff int port_id; 175c6fe0ad2SBrandon Streiff 176c6fe0ad2SBrandon Streiff /* Timestamping state */ 177c6fe0ad2SBrandon Streiff unsigned long state; 178c6fe0ad2SBrandon Streiff 179c6fe0ad2SBrandon Streiff /* Resources for receive timestamping */ 180c6fe0ad2SBrandon Streiff struct sk_buff_head rx_queue; 181c6fe0ad2SBrandon Streiff struct sk_buff_head rx_queue2; 182c6fe0ad2SBrandon Streiff 183c6fe0ad2SBrandon Streiff /* Resources for transmit timestamping */ 184c6fe0ad2SBrandon Streiff unsigned long tx_tstamp_start; 185c6fe0ad2SBrandon Streiff struct sk_buff *tx_skb; 186c6fe0ad2SBrandon Streiff u16 tx_seq_id; 187c6fe0ad2SBrandon Streiff 188c6fe0ad2SBrandon Streiff /* Current timestamp configuration */ 189c6fe0ad2SBrandon Streiff struct hwtstamp_config tstamp_config; 190c6fe0ad2SBrandon Streiff }; 191c6fe0ad2SBrandon Streiff 192cda9f4aaSAndrew Lunn struct mv88e6xxx_port { 1937b898469SAndrew Lunn struct mv88e6xxx_chip *chip; 1947b898469SAndrew Lunn int port; 195cda9f4aaSAndrew Lunn u64 serdes_stats[2]; 19665f60e45SAndrew Lunn u64 atu_member_violation; 19765f60e45SAndrew Lunn u64 atu_miss_violation; 19865f60e45SAndrew Lunn u64 atu_full_violation; 19965f60e45SAndrew Lunn u64 vtu_member_violation; 20065f60e45SAndrew Lunn u64 vtu_miss_violation; 2012d2e1dd2SAndrew Lunn u8 cmode; 202f441ed0fSVivien Didelot unsigned int serdes_irq; 203cda9f4aaSAndrew Lunn }; 204cda9f4aaSAndrew Lunn 2054d5f2ba7SVivien Didelot struct mv88e6xxx_chip { 2064d5f2ba7SVivien Didelot const struct mv88e6xxx_info *info; 2074d5f2ba7SVivien Didelot 2084d5f2ba7SVivien Didelot /* The dsa_switch this private structure is related to */ 2094d5f2ba7SVivien Didelot struct dsa_switch *ds; 2104d5f2ba7SVivien Didelot 2114d5f2ba7SVivien Didelot /* The device this structure is associated to */ 2124d5f2ba7SVivien Didelot struct device *dev; 2134d5f2ba7SVivien Didelot 2144d5f2ba7SVivien Didelot /* This mutex protects the access to the switch registers */ 2154d5f2ba7SVivien Didelot struct mutex reg_lock; 2164d5f2ba7SVivien Didelot 2174d5f2ba7SVivien Didelot /* The MII bus and the address on the bus that is used to 2184d5f2ba7SVivien Didelot * communication with the switch 2194d5f2ba7SVivien Didelot */ 2204d5f2ba7SVivien Didelot const struct mv88e6xxx_bus_ops *smi_ops; 2214d5f2ba7SVivien Didelot struct mii_bus *bus; 2224d5f2ba7SVivien Didelot int sw_addr; 2234d5f2ba7SVivien Didelot 2244d5f2ba7SVivien Didelot /* Handles automatic disabling and re-enabling of the PHY 2254d5f2ba7SVivien Didelot * polling unit. 2264d5f2ba7SVivien Didelot */ 2274d5f2ba7SVivien Didelot const struct mv88e6xxx_bus_ops *phy_ops; 2284d5f2ba7SVivien Didelot struct mutex ppu_mutex; 2294d5f2ba7SVivien Didelot int ppu_disabled; 2304d5f2ba7SVivien Didelot struct work_struct ppu_work; 2314d5f2ba7SVivien Didelot struct timer_list ppu_timer; 2324d5f2ba7SVivien Didelot 2334d5f2ba7SVivien Didelot /* This mutex serialises access to the statistics unit. 2344d5f2ba7SVivien Didelot * Hold this mutex over snapshot + dump sequences. 2354d5f2ba7SVivien Didelot */ 2364d5f2ba7SVivien Didelot struct mutex stats_mutex; 2374d5f2ba7SVivien Didelot 2384d5f2ba7SVivien Didelot /* A switch may have a GPIO line tied to its reset pin. Parse 2394d5f2ba7SVivien Didelot * this from the device tree, and use it before performing 2404d5f2ba7SVivien Didelot * switch soft reset. 2414d5f2ba7SVivien Didelot */ 2424d5f2ba7SVivien Didelot struct gpio_desc *reset; 2434d5f2ba7SVivien Didelot 2444d5f2ba7SVivien Didelot /* set to size of eeprom if supported by the switch */ 24500baabe5SAndrew Lunn u32 eeprom_len; 2464d5f2ba7SVivien Didelot 2474d5f2ba7SVivien Didelot /* List of mdio busses */ 2484d5f2ba7SVivien Didelot struct list_head mdios; 2494d5f2ba7SVivien Didelot 2504d5f2ba7SVivien Didelot /* There can be two interrupt controllers, which are chained 2514d5f2ba7SVivien Didelot * off a GPIO as interrupt source 2524d5f2ba7SVivien Didelot */ 2534d5f2ba7SVivien Didelot struct mv88e6xxx_irq g1_irq; 2544d5f2ba7SVivien Didelot struct mv88e6xxx_irq g2_irq; 2554d5f2ba7SVivien Didelot int irq; 2564d5f2ba7SVivien Didelot int device_irq; 2574d5f2ba7SVivien Didelot int watchdog_irq; 258cda9f4aaSAndrew Lunn 2590977644cSAndrew Lunn int atu_prob_irq; 26062eb1162SAndrew Lunn int vtu_prob_irq; 261294d711eSAndrew Lunn struct kthread_worker *kworker; 262294d711eSAndrew Lunn struct kthread_delayed_work irq_poll_work; 2632fa8d3afSBrandon Streiff 264a73ccd61SBrandon Streiff /* GPIO resources */ 265a73ccd61SBrandon Streiff u8 gpio_data[2]; 266a73ccd61SBrandon Streiff 2672fa8d3afSBrandon Streiff /* This cyclecounter abstracts the switch PTP time. 2682fa8d3afSBrandon Streiff * reg_lock must be held for any operation that read()s. 2692fa8d3afSBrandon Streiff */ 2702fa8d3afSBrandon Streiff struct cyclecounter tstamp_cc; 2712fa8d3afSBrandon Streiff struct timecounter tstamp_tc; 2722fa8d3afSBrandon Streiff struct delayed_work overflow_work; 2732fa8d3afSBrandon Streiff 2742fa8d3afSBrandon Streiff struct ptp_clock *ptp_clock; 2752fa8d3afSBrandon Streiff struct ptp_clock_info ptp_clock_info; 2764eb3be29SBrandon Streiff struct delayed_work tai_event_work; 2774eb3be29SBrandon Streiff struct ptp_pin_desc pin_config[MV88E6XXX_MAX_GPIO]; 2784eb3be29SBrandon Streiff u16 trig_config; 2794eb3be29SBrandon Streiff u16 evcap_config; 280e2294a8bSAndrew Lunn u16 enable_count; 281c6fe0ad2SBrandon Streiff 282c6fe0ad2SBrandon Streiff /* Per-port timestamping resources. */ 283c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS]; 284cda9f4aaSAndrew Lunn 285cda9f4aaSAndrew Lunn /* Array of port structures. */ 286cda9f4aaSAndrew Lunn struct mv88e6xxx_port ports[DSA_MAX_PORTS]; 2874d5f2ba7SVivien Didelot }; 2884d5f2ba7SVivien Didelot 2894d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops { 2904d5f2ba7SVivien Didelot int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); 2914d5f2ba7SVivien Didelot int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); 2924d5f2ba7SVivien Didelot }; 2934d5f2ba7SVivien Didelot 2944d5f2ba7SVivien Didelot struct mv88e6xxx_mdio_bus { 2954d5f2ba7SVivien Didelot struct mii_bus *bus; 2964d5f2ba7SVivien Didelot struct mv88e6xxx_chip *chip; 2974d5f2ba7SVivien Didelot struct list_head list; 2984d5f2ba7SVivien Didelot bool external; 2994d5f2ba7SVivien Didelot }; 3004d5f2ba7SVivien Didelot 3014d5f2ba7SVivien Didelot struct mv88e6xxx_ops { 302ea89098eSAndrew Lunn /* Switch Setup Errata, called early in the switch setup to 303ea89098eSAndrew Lunn * allow any errata actions to be performed 304ea89098eSAndrew Lunn */ 305ea89098eSAndrew Lunn int (*setup_errata)(struct mv88e6xxx_chip *chip); 306ea89098eSAndrew Lunn 30793e18d61SVivien Didelot int (*ieee_pri_map)(struct mv88e6xxx_chip *chip); 30893e18d61SVivien Didelot int (*ip_pri_map)(struct mv88e6xxx_chip *chip); 30993e18d61SVivien Didelot 310cd8da8bbSVivien Didelot /* Ingress Rate Limit unit (IRL) operations */ 311cd8da8bbSVivien Didelot int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port); 312cd8da8bbSVivien Didelot 3134d5f2ba7SVivien Didelot int (*get_eeprom)(struct mv88e6xxx_chip *chip, 3144d5f2ba7SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data); 3154d5f2ba7SVivien Didelot int (*set_eeprom)(struct mv88e6xxx_chip *chip, 3164d5f2ba7SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data); 3174d5f2ba7SVivien Didelot 3184d5f2ba7SVivien Didelot int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr); 3194d5f2ba7SVivien Didelot 3204d5f2ba7SVivien Didelot int (*phy_read)(struct mv88e6xxx_chip *chip, 3214d5f2ba7SVivien Didelot struct mii_bus *bus, 3224d5f2ba7SVivien Didelot int addr, int reg, u16 *val); 3234d5f2ba7SVivien Didelot int (*phy_write)(struct mv88e6xxx_chip *chip, 3244d5f2ba7SVivien Didelot struct mii_bus *bus, 3254d5f2ba7SVivien Didelot int addr, int reg, u16 val); 3264d5f2ba7SVivien Didelot 3279e907d73SVivien Didelot /* Priority Override Table operations */ 3289e907d73SVivien Didelot int (*pot_clear)(struct mv88e6xxx_chip *chip); 3299e907d73SVivien Didelot 3304d5f2ba7SVivien Didelot /* PHY Polling Unit (PPU) operations */ 3314d5f2ba7SVivien Didelot int (*ppu_enable)(struct mv88e6xxx_chip *chip); 3324d5f2ba7SVivien Didelot int (*ppu_disable)(struct mv88e6xxx_chip *chip); 3334d5f2ba7SVivien Didelot 3344d5f2ba7SVivien Didelot /* Switch Software Reset */ 3354d5f2ba7SVivien Didelot int (*reset)(struct mv88e6xxx_chip *chip); 3364d5f2ba7SVivien Didelot 3374d5f2ba7SVivien Didelot /* RGMII Receive/Transmit Timing Control 3384d5f2ba7SVivien Didelot * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise. 3394d5f2ba7SVivien Didelot */ 3404d5f2ba7SVivien Didelot int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port, 3414d5f2ba7SVivien Didelot phy_interface_t mode); 3424d5f2ba7SVivien Didelot 3434d5f2ba7SVivien Didelot #define LINK_FORCED_DOWN 0 3444d5f2ba7SVivien Didelot #define LINK_FORCED_UP 1 3454d5f2ba7SVivien Didelot #define LINK_UNFORCED -2 3464d5f2ba7SVivien Didelot 3474d5f2ba7SVivien Didelot /* Port's MAC link state 3484d5f2ba7SVivien Didelot * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down, 3494d5f2ba7SVivien Didelot * or LINK_UNFORCED for normal link detection. 3504d5f2ba7SVivien Didelot */ 3514d5f2ba7SVivien Didelot int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link); 3524d5f2ba7SVivien Didelot 3534d5f2ba7SVivien Didelot #define DUPLEX_UNFORCED -2 3544d5f2ba7SVivien Didelot 3554d5f2ba7SVivien Didelot /* Port's MAC duplex mode 3564d5f2ba7SVivien Didelot * 3574d5f2ba7SVivien Didelot * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex, 3584d5f2ba7SVivien Didelot * or DUPLEX_UNFORCED for normal duplex detection. 3594d5f2ba7SVivien Didelot */ 3604d5f2ba7SVivien Didelot int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup); 3614d5f2ba7SVivien Didelot 36254186b91SAndrew Lunn #define PAUSE_ON 1 36354186b91SAndrew Lunn #define PAUSE_OFF 0 36454186b91SAndrew Lunn 36554186b91SAndrew Lunn /* Enable/disable sending Pause */ 36654186b91SAndrew Lunn int (*port_set_pause)(struct mv88e6xxx_chip *chip, int port, 36754186b91SAndrew Lunn int pause); 36854186b91SAndrew Lunn 3694d5f2ba7SVivien Didelot #define SPEED_MAX INT_MAX 3704d5f2ba7SVivien Didelot #define SPEED_UNFORCED -2 3714d5f2ba7SVivien Didelot 3724d5f2ba7SVivien Didelot /* Port's MAC speed (in Mbps) 3734d5f2ba7SVivien Didelot * 3744d5f2ba7SVivien Didelot * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid. 3754d5f2ba7SVivien Didelot * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value. 3764d5f2ba7SVivien Didelot */ 3774d5f2ba7SVivien Didelot int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); 3784d5f2ba7SVivien Didelot 3797cbbee05SAndrew Lunn /* What interface mode should be used for maximum speed? */ 3807cbbee05SAndrew Lunn phy_interface_t (*port_max_speed_mode)(int port); 3817cbbee05SAndrew Lunn 3824d5f2ba7SVivien Didelot int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); 3834d5f2ba7SVivien Didelot 3844d5f2ba7SVivien Didelot int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, 3854d5f2ba7SVivien Didelot enum mv88e6xxx_frame_mode mode); 3864d5f2ba7SVivien Didelot int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port, 3874d5f2ba7SVivien Didelot bool unicast, bool multicast); 3884d5f2ba7SVivien Didelot int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, 3894d5f2ba7SVivien Didelot u16 etype); 390cd782656SVivien Didelot int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port, 391cd782656SVivien Didelot size_t size); 3924d5f2ba7SVivien Didelot 3934d5f2ba7SVivien Didelot int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port); 3940898432cSVivien Didelot int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in, 3950898432cSVivien Didelot u8 out); 3964d5f2ba7SVivien Didelot int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port); 3974d5f2ba7SVivien Didelot int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port); 398121b8fe2SHubert Feurstein int (*port_setup_message_port)(struct mv88e6xxx_chip *chip, int port); 3994d5f2ba7SVivien Didelot 4004d5f2ba7SVivien Didelot /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc. 4014d5f2ba7SVivien Didelot * Some chips allow this to be configured on specific ports. 4024d5f2ba7SVivien Didelot */ 4034d5f2ba7SVivien Didelot int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port, 4044d5f2ba7SVivien Didelot phy_interface_t mode); 4052d2e1dd2SAndrew Lunn int (*port_get_cmode)(struct mv88e6xxx_chip *chip, int port, u8 *cmode); 4064d5f2ba7SVivien Didelot 4074d5f2ba7SVivien Didelot /* Some devices have a per port register indicating what is 4084d5f2ba7SVivien Didelot * the upstream port this port should forward to. 4094d5f2ba7SVivien Didelot */ 4104d5f2ba7SVivien Didelot int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port, 4114d5f2ba7SVivien Didelot int upstream_port); 4126c422e34SRussell King /* Return the port link state, as required by phylink */ 4136c422e34SRussell King int (*port_link_state)(struct mv88e6xxx_chip *chip, int port, 4146c422e34SRussell King struct phylink_link_state *state); 4154d5f2ba7SVivien Didelot 4164d5f2ba7SVivien Didelot /* Snapshot the statistics for a port. The statistics can then 4174d5f2ba7SVivien Didelot * be read back a leisure but still with a consistent view. 4184d5f2ba7SVivien Didelot */ 4194d5f2ba7SVivien Didelot int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port); 4204d5f2ba7SVivien Didelot 4214d5f2ba7SVivien Didelot /* Set the histogram mode for statistics, when the control registers 4224d5f2ba7SVivien Didelot * are separated out of the STATS_OP register. 4234d5f2ba7SVivien Didelot */ 4244d5f2ba7SVivien Didelot int (*stats_set_histogram)(struct mv88e6xxx_chip *chip); 4254d5f2ba7SVivien Didelot 4264d5f2ba7SVivien Didelot /* Return the number of strings describing statistics */ 4274d5f2ba7SVivien Didelot int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip); 428436fe17dSAndrew Lunn int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data); 429436fe17dSAndrew Lunn int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, 4304d5f2ba7SVivien Didelot uint64_t *data); 431fa8d1179SVivien Didelot int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); 432fa8d1179SVivien Didelot int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port); 43302317e68SVivien Didelot 43402317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_NONE 0xe 43502317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_MULTIPLE 0xf 43602317e68SVivien Didelot 43702317e68SVivien Didelot int (*set_cascade_port)(struct mv88e6xxx_chip *chip, int port); 43802317e68SVivien Didelot 4394d5f2ba7SVivien Didelot const struct mv88e6xxx_irq_ops *watchdog_ops; 4404d5f2ba7SVivien Didelot 4414d5f2ba7SVivien Didelot int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); 4424d5f2ba7SVivien Didelot 4434d5f2ba7SVivien Didelot /* Power on/off a SERDES interface */ 444dc272f60SVivien Didelot int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, u8 lane, 445dc272f60SVivien Didelot bool up); 4464d5f2ba7SVivien Didelot 44717deaf5cSMarek Behún /* SERDES lane mapping */ 4485122d4ecSVivien Didelot u8 (*serdes_get_lane)(struct mv88e6xxx_chip *chip, int port); 44917deaf5cSMarek Behún 450efd1ba6aSAndrew Lunn /* SERDES interrupt handling */ 4514241ef52SVivien Didelot unsigned int (*serdes_irq_mapping)(struct mv88e6xxx_chip *chip, 4524241ef52SVivien Didelot int port); 453efd1ba6aSAndrew Lunn int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port); 454efd1ba6aSAndrew Lunn void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port); 45561a46b41SVivien Didelot int (*serdes_irq_enable)(struct mv88e6xxx_chip *chip, int port, u8 lane, 45661a46b41SVivien Didelot bool enable); 457efd1ba6aSAndrew Lunn 458436fe17dSAndrew Lunn /* Statistics from the SERDES interface */ 459436fe17dSAndrew Lunn int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); 46065f60e45SAndrew Lunn int (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port, 461436fe17dSAndrew Lunn uint8_t *data); 46265f60e45SAndrew Lunn int (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port, 463436fe17dSAndrew Lunn uint64_t *data); 464436fe17dSAndrew Lunn 4654d5f2ba7SVivien Didelot /* VLAN Translation Unit operations */ 4664d5f2ba7SVivien Didelot int (*vtu_getnext)(struct mv88e6xxx_chip *chip, 4674d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry *entry); 4684d5f2ba7SVivien Didelot int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip, 4694d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry *entry); 4700d632c3dSBrandon Streiff 471a73ccd61SBrandon Streiff /* GPIO operations */ 472a73ccd61SBrandon Streiff const struct mv88e6xxx_gpio_ops *gpio_ops; 473a73ccd61SBrandon Streiff 4740d632c3dSBrandon Streiff /* Interface to the AVB/PTP registers */ 4750d632c3dSBrandon Streiff const struct mv88e6xxx_avb_ops *avb_ops; 4769e5baf9bSVivien Didelot 4779e5baf9bSVivien Didelot /* Remote Management Unit operations */ 4789e5baf9bSVivien Didelot int (*rmu_disable)(struct mv88e6xxx_chip *chip); 4796d2ac8eeSAndrew Lunn 4806d2ac8eeSAndrew Lunn /* Precision Time Protocol operations */ 4816d2ac8eeSAndrew Lunn const struct mv88e6xxx_ptp_ops *ptp_ops; 4826c422e34SRussell King 4836c422e34SRussell King /* Phylink */ 4846c422e34SRussell King void (*phylink_validate)(struct mv88e6xxx_chip *chip, int port, 4856c422e34SRussell King unsigned long *mask, 4866c422e34SRussell King struct phylink_link_state *state); 4874d5f2ba7SVivien Didelot }; 4884d5f2ba7SVivien Didelot 4894d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops { 4904d5f2ba7SVivien Didelot /* Action to be performed when the interrupt happens */ 4914d5f2ba7SVivien Didelot int (*irq_action)(struct mv88e6xxx_chip *chip, int irq); 4924d5f2ba7SVivien Didelot /* Setup the hardware to generate the interrupt */ 4934d5f2ba7SVivien Didelot int (*irq_setup)(struct mv88e6xxx_chip *chip); 4944d5f2ba7SVivien Didelot /* Reset the hardware to stop generating the interrupt */ 4954d5f2ba7SVivien Didelot void (*irq_free)(struct mv88e6xxx_chip *chip); 4964d5f2ba7SVivien Didelot }; 4974d5f2ba7SVivien Didelot 498a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops { 499a73ccd61SBrandon Streiff /* Get/set data on GPIO pin */ 500a73ccd61SBrandon Streiff int (*get_data)(struct mv88e6xxx_chip *chip, unsigned int pin); 501a73ccd61SBrandon Streiff int (*set_data)(struct mv88e6xxx_chip *chip, unsigned int pin, 502a73ccd61SBrandon Streiff int value); 503a73ccd61SBrandon Streiff 504a73ccd61SBrandon Streiff /* get/set GPIO direction */ 505a73ccd61SBrandon Streiff int (*get_dir)(struct mv88e6xxx_chip *chip, unsigned int pin); 506a73ccd61SBrandon Streiff int (*set_dir)(struct mv88e6xxx_chip *chip, unsigned int pin, 507a73ccd61SBrandon Streiff bool input); 508a73ccd61SBrandon Streiff 509a73ccd61SBrandon Streiff /* get/set GPIO pin control */ 510a73ccd61SBrandon Streiff int (*get_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin, 511a73ccd61SBrandon Streiff int *func); 512a73ccd61SBrandon Streiff int (*set_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin, 513a73ccd61SBrandon Streiff int func); 514a73ccd61SBrandon Streiff }; 515a73ccd61SBrandon Streiff 5160d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops { 5170d632c3dSBrandon Streiff /* Access port-scoped Precision Time Protocol registers */ 5180d632c3dSBrandon Streiff int (*port_ptp_read)(struct mv88e6xxx_chip *chip, int port, int addr, 5190d632c3dSBrandon Streiff u16 *data, int len); 5200d632c3dSBrandon Streiff int (*port_ptp_write)(struct mv88e6xxx_chip *chip, int port, int addr, 5210d632c3dSBrandon Streiff u16 data); 5220d632c3dSBrandon Streiff 5230d632c3dSBrandon Streiff /* Access global Precision Time Protocol registers */ 5240d632c3dSBrandon Streiff int (*ptp_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data, 5250d632c3dSBrandon Streiff int len); 5260d632c3dSBrandon Streiff int (*ptp_write)(struct mv88e6xxx_chip *chip, int addr, u16 data); 5270d632c3dSBrandon Streiff 5280d632c3dSBrandon Streiff /* Access global Time Application Interface registers */ 5290d632c3dSBrandon Streiff int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data, 5300d632c3dSBrandon Streiff int len); 5310d632c3dSBrandon Streiff int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data); 5320d632c3dSBrandon Streiff }; 5330d632c3dSBrandon Streiff 5346d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops { 5356d2ac8eeSAndrew Lunn u64 (*clock_read)(const struct cyclecounter *cc); 5366d2ac8eeSAndrew Lunn int (*ptp_enable)(struct ptp_clock_info *ptp, 5376d2ac8eeSAndrew Lunn struct ptp_clock_request *rq, int on); 5386d2ac8eeSAndrew Lunn int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin, 5396d2ac8eeSAndrew Lunn enum ptp_pin_function func, unsigned int chan); 5406d2ac8eeSAndrew Lunn void (*event_work)(struct work_struct *ugly); 541ffc705deSAndrew Lunn int (*port_enable)(struct mv88e6xxx_chip *chip, int port); 542ffc705deSAndrew Lunn int (*port_disable)(struct mv88e6xxx_chip *chip, int port); 543e2294a8bSAndrew Lunn int (*global_enable)(struct mv88e6xxx_chip *chip); 544e2294a8bSAndrew Lunn int (*global_disable)(struct mv88e6xxx_chip *chip); 5456d2ac8eeSAndrew Lunn int n_ext_ts; 546ffc705deSAndrew Lunn int arr0_sts_reg; 547ffc705deSAndrew Lunn int arr1_sts_reg; 548ffc705deSAndrew Lunn int dep_sts_reg; 54948cb5e03SAndrew Lunn u32 rx_filters; 55071509614SHubert Feurstein u32 cc_shift; 55171509614SHubert Feurstein u32 cc_mult; 55271509614SHubert Feurstein u32 cc_mult_num; 55371509614SHubert Feurstein u32 cc_mult_dem; 5546d2ac8eeSAndrew Lunn }; 5556d2ac8eeSAndrew Lunn 5564d5f2ba7SVivien Didelot #define STATS_TYPE_PORT BIT(0) 5574d5f2ba7SVivien Didelot #define STATS_TYPE_BANK0 BIT(1) 5584d5f2ba7SVivien Didelot #define STATS_TYPE_BANK1 BIT(2) 5594d5f2ba7SVivien Didelot 5604d5f2ba7SVivien Didelot struct mv88e6xxx_hw_stat { 5614d5f2ba7SVivien Didelot char string[ETH_GSTRING_LEN]; 562cda9f4aaSAndrew Lunn size_t size; 5634d5f2ba7SVivien Didelot int reg; 5644d5f2ba7SVivien Didelot int type; 5654d5f2ba7SVivien Didelot }; 5664d5f2ba7SVivien Didelot 5674d5f2ba7SVivien Didelot static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip) 5684d5f2ba7SVivien Didelot { 5694d5f2ba7SVivien Didelot return chip->info->pvt; 5704d5f2ba7SVivien Didelot } 5714d5f2ba7SVivien Didelot 5724d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip) 5734d5f2ba7SVivien Didelot { 5744d5f2ba7SVivien Didelot return chip->info->num_databases; 5754d5f2ba7SVivien Didelot } 5764d5f2ba7SVivien Didelot 5774d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip) 5784d5f2ba7SVivien Didelot { 5794d5f2ba7SVivien Didelot return chip->info->num_ports; 5804d5f2ba7SVivien Didelot } 5814d5f2ba7SVivien Didelot 5824d5f2ba7SVivien Didelot static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip) 5834d5f2ba7SVivien Didelot { 5844d5f2ba7SVivien Didelot return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); 5854d5f2ba7SVivien Didelot } 5864d5f2ba7SVivien Didelot 587a73ccd61SBrandon Streiff static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip) 588a73ccd61SBrandon Streiff { 589a73ccd61SBrandon Streiff return chip->info->num_gpio; 590a73ccd61SBrandon Streiff } 591a73ccd61SBrandon Streiff 592c857486aSHubert Feurstein static inline bool mv88e6xxx_is_invalid_port(struct mv88e6xxx_chip *chip, int port) 593c857486aSHubert Feurstein { 594c857486aSHubert Feurstein return (chip->info->invalid_port_mask & BIT(port)) != 0; 595c857486aSHubert Feurstein } 596c857486aSHubert Feurstein 5974d5f2ba7SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); 5984d5f2ba7SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); 599683f2244SVivien Didelot int mv88e6xxx_wait_mask(struct mv88e6xxx_chip *chip, int addr, int reg, 600683f2244SVivien Didelot u16 mask, u16 val); 60119fb7f69SVivien Didelot int mv88e6xxx_wait_bit(struct mv88e6xxx_chip *chip, int addr, int reg, 60219fb7f69SVivien Didelot int bit, int val); 60372d8b4fdSHeiner Kallweit int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link, 60472d8b4fdSHeiner Kallweit int speed, int duplex, int pause, 60572d8b4fdSHeiner Kallweit phy_interface_t mode); 6064d5f2ba7SVivien Didelot struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip); 6074d5f2ba7SVivien Didelot 608c9acece0SRasmus Villemoes static inline void mv88e6xxx_reg_lock(struct mv88e6xxx_chip *chip) 609c9acece0SRasmus Villemoes { 610c9acece0SRasmus Villemoes mutex_lock(&chip->reg_lock); 611c9acece0SRasmus Villemoes } 612c9acece0SRasmus Villemoes 613c9acece0SRasmus Villemoes static inline void mv88e6xxx_reg_unlock(struct mv88e6xxx_chip *chip) 614c9acece0SRasmus Villemoes { 615c9acece0SRasmus Villemoes mutex_unlock(&chip->reg_lock); 616c9acece0SRasmus Villemoes } 617c9acece0SRasmus Villemoes 6184d5f2ba7SVivien Didelot #endif /* _MV88E6XXX_CHIP_H */ 619