14d5f2ba7SVivien Didelot /* 24d5f2ba7SVivien Didelot * Marvell 88E6xxx Ethernet switch single-chip definition 34d5f2ba7SVivien Didelot * 44d5f2ba7SVivien Didelot * Copyright (c) 2008 Marvell Semiconductor 54d5f2ba7SVivien Didelot * 64d5f2ba7SVivien Didelot * This program is free software; you can redistribute it and/or modify 74d5f2ba7SVivien Didelot * it under the terms of the GNU General Public License as published by 84d5f2ba7SVivien Didelot * the Free Software Foundation; either version 2 of the License, or 94d5f2ba7SVivien Didelot * (at your option) any later version. 104d5f2ba7SVivien Didelot */ 114d5f2ba7SVivien Didelot 124d5f2ba7SVivien Didelot #ifndef _MV88E6XXX_CHIP_H 134d5f2ba7SVivien Didelot #define _MV88E6XXX_CHIP_H 144d5f2ba7SVivien Didelot 154d5f2ba7SVivien Didelot #include <linux/if_vlan.h> 164d5f2ba7SVivien Didelot #include <linux/irq.h> 174d5f2ba7SVivien Didelot #include <linux/gpio/consumer.h> 18294d711eSAndrew Lunn #include <linux/kthread.h> 194d5f2ba7SVivien Didelot #include <linux/phy.h> 202fa8d3afSBrandon Streiff #include <linux/ptp_clock_kernel.h> 212fa8d3afSBrandon Streiff #include <linux/timecounter.h> 224d5f2ba7SVivien Didelot #include <net/dsa.h> 234d5f2ba7SVivien Didelot 244d5f2ba7SVivien Didelot #ifndef UINT64_MAX 254d5f2ba7SVivien Didelot #define UINT64_MAX (u64)(~((u64)0)) 264d5f2ba7SVivien Didelot #endif 274d5f2ba7SVivien Didelot 284d5f2ba7SVivien Didelot #define SMI_CMD 0x00 294d5f2ba7SVivien Didelot #define SMI_CMD_BUSY BIT(15) 304d5f2ba7SVivien Didelot #define SMI_CMD_CLAUSE_22 BIT(12) 314d5f2ba7SVivien Didelot #define SMI_CMD_OP_22_WRITE ((1 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22) 324d5f2ba7SVivien Didelot #define SMI_CMD_OP_22_READ ((2 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22) 334d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_WRITE_ADDR ((0 << 10) | SMI_CMD_BUSY) 344d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_WRITE_DATA ((1 << 10) | SMI_CMD_BUSY) 354d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_READ_DATA ((2 << 10) | SMI_CMD_BUSY) 364d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_READ_DATA_INC ((3 << 10) | SMI_CMD_BUSY) 374d5f2ba7SVivien Didelot #define SMI_DATA 0x01 384d5f2ba7SVivien Didelot 394d5f2ba7SVivien Didelot #define MV88E6XXX_N_FID 4096 404d5f2ba7SVivien Didelot 414d5f2ba7SVivien Didelot /* PVT limits for 4-bit port and 5-bit switch */ 424d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_SWITCHES 32 434d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_PORTS 16 444d5f2ba7SVivien Didelot 45a73ccd61SBrandon Streiff #define MV88E6XXX_MAX_GPIO 16 46a73ccd61SBrandon Streiff 4731bef4e9SVivien Didelot enum mv88e6xxx_egress_mode { 4831bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNMODIFIED, 4931bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_UNTAGGED, 5031bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_TAGGED, 5131bef4e9SVivien Didelot MV88E6XXX_EGRESS_MODE_ETHERTYPE, 5231bef4e9SVivien Didelot }; 5331bef4e9SVivien Didelot 544d5f2ba7SVivien Didelot enum mv88e6xxx_frame_mode { 554d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_NORMAL, 564d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_DSA, 574d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_PROVIDER, 584d5f2ba7SVivien Didelot MV88E6XXX_FRAME_MODE_ETHERTYPE, 594d5f2ba7SVivien Didelot }; 604d5f2ba7SVivien Didelot 614d5f2ba7SVivien Didelot /* List of supported models */ 624d5f2ba7SVivien Didelot enum mv88e6xxx_model { 634d5f2ba7SVivien Didelot MV88E6085, 644d5f2ba7SVivien Didelot MV88E6095, 654d5f2ba7SVivien Didelot MV88E6097, 664d5f2ba7SVivien Didelot MV88E6123, 674d5f2ba7SVivien Didelot MV88E6131, 684d5f2ba7SVivien Didelot MV88E6141, 694d5f2ba7SVivien Didelot MV88E6161, 704d5f2ba7SVivien Didelot MV88E6165, 714d5f2ba7SVivien Didelot MV88E6171, 724d5f2ba7SVivien Didelot MV88E6172, 734d5f2ba7SVivien Didelot MV88E6175, 744d5f2ba7SVivien Didelot MV88E6176, 754d5f2ba7SVivien Didelot MV88E6185, 764d5f2ba7SVivien Didelot MV88E6190, 774d5f2ba7SVivien Didelot MV88E6190X, 784d5f2ba7SVivien Didelot MV88E6191, 794d5f2ba7SVivien Didelot MV88E6240, 804d5f2ba7SVivien Didelot MV88E6290, 814d5f2ba7SVivien Didelot MV88E6320, 824d5f2ba7SVivien Didelot MV88E6321, 834d5f2ba7SVivien Didelot MV88E6341, 844d5f2ba7SVivien Didelot MV88E6350, 854d5f2ba7SVivien Didelot MV88E6351, 864d5f2ba7SVivien Didelot MV88E6352, 874d5f2ba7SVivien Didelot MV88E6390, 884d5f2ba7SVivien Didelot MV88E6390X, 894d5f2ba7SVivien Didelot }; 904d5f2ba7SVivien Didelot 914d5f2ba7SVivien Didelot enum mv88e6xxx_family { 924d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_NONE, 934d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6065, /* 6031 6035 6061 6065 */ 944d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6095, /* 6092 6095 */ 954d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ 964d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ 974d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ 984d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6320, /* 6320 6321 */ 994d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6341, /* 6141 6341 */ 1004d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ 1014d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ 1024d5f2ba7SVivien Didelot MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */ 1034d5f2ba7SVivien Didelot }; 1044d5f2ba7SVivien Didelot 1054d5f2ba7SVivien Didelot struct mv88e6xxx_ops; 1064d5f2ba7SVivien Didelot 1074d5f2ba7SVivien Didelot struct mv88e6xxx_info { 1084d5f2ba7SVivien Didelot enum mv88e6xxx_family family; 1094d5f2ba7SVivien Didelot u16 prod_num; 1104d5f2ba7SVivien Didelot const char *name; 1114d5f2ba7SVivien Didelot unsigned int num_databases; 1124d5f2ba7SVivien Didelot unsigned int num_ports; 113bc393155SAndrew Lunn unsigned int num_internal_phys; 114a73ccd61SBrandon Streiff unsigned int num_gpio; 1154d5f2ba7SVivien Didelot unsigned int max_vid; 1164d5f2ba7SVivien Didelot unsigned int port_base_addr; 1174d5f2ba7SVivien Didelot unsigned int global1_addr; 1189069c13aSVivien Didelot unsigned int global2_addr; 1194d5f2ba7SVivien Didelot unsigned int age_time_coeff; 1204d5f2ba7SVivien Didelot unsigned int g1_irqs; 121d6c5e6afSVivien Didelot unsigned int g2_irqs; 1224d5f2ba7SVivien Didelot bool pvt; 123b3e05aa1SVivien Didelot 124b3e05aa1SVivien Didelot /* Multi-chip Addressing Mode. 125b3e05aa1SVivien Didelot * Some chips respond to only 2 registers of its own SMI device address 126b3e05aa1SVivien Didelot * when it is non-zero, and use indirect access to internal registers. 127b3e05aa1SVivien Didelot */ 128b3e05aa1SVivien Didelot bool multi_chip; 1294d5f2ba7SVivien Didelot enum dsa_tag_protocol tag_protocol; 1304d5f2ba7SVivien Didelot 1314d5f2ba7SVivien Didelot /* Mask for FromPort and ToPort value of PortVec used in ATU Move 1324d5f2ba7SVivien Didelot * operation. 0 means that the ATU Move operation is not supported. 1334d5f2ba7SVivien Didelot */ 1344d5f2ba7SVivien Didelot u8 atu_move_port_mask; 1354d5f2ba7SVivien Didelot const struct mv88e6xxx_ops *ops; 1362fa8d3afSBrandon Streiff 1372fa8d3afSBrandon Streiff /* Supports PTP */ 1382fa8d3afSBrandon Streiff bool ptp_support; 1394d5f2ba7SVivien Didelot }; 1404d5f2ba7SVivien Didelot 1414d5f2ba7SVivien Didelot struct mv88e6xxx_atu_entry { 1424d5f2ba7SVivien Didelot u8 state; 1434d5f2ba7SVivien Didelot bool trunk; 1444d5f2ba7SVivien Didelot u16 portvec; 1454d5f2ba7SVivien Didelot u8 mac[ETH_ALEN]; 1464d5f2ba7SVivien Didelot }; 1474d5f2ba7SVivien Didelot 1484d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry { 1494d5f2ba7SVivien Didelot u16 vid; 1504d5f2ba7SVivien Didelot u16 fid; 1514d5f2ba7SVivien Didelot u8 sid; 1524d5f2ba7SVivien Didelot bool valid; 1534d5f2ba7SVivien Didelot u8 member[DSA_MAX_PORTS]; 1544d5f2ba7SVivien Didelot u8 state[DSA_MAX_PORTS]; 1554d5f2ba7SVivien Didelot }; 1564d5f2ba7SVivien Didelot 1574d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops; 1584d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops; 159a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops; 1600d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops; 1614d5f2ba7SVivien Didelot 1624d5f2ba7SVivien Didelot struct mv88e6xxx_irq { 1634d5f2ba7SVivien Didelot u16 masked; 1644d5f2ba7SVivien Didelot struct irq_chip chip; 1654d5f2ba7SVivien Didelot struct irq_domain *domain; 1664d5f2ba7SVivien Didelot unsigned int nirqs; 1674d5f2ba7SVivien Didelot }; 1684d5f2ba7SVivien Didelot 169c6fe0ad2SBrandon Streiff /* state flags for mv88e6xxx_port_hwtstamp::state */ 170c6fe0ad2SBrandon Streiff enum { 171c6fe0ad2SBrandon Streiff MV88E6XXX_HWTSTAMP_ENABLED, 172c6fe0ad2SBrandon Streiff MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS, 173c6fe0ad2SBrandon Streiff }; 174c6fe0ad2SBrandon Streiff 175c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp { 176c6fe0ad2SBrandon Streiff /* Port index */ 177c6fe0ad2SBrandon Streiff int port_id; 178c6fe0ad2SBrandon Streiff 179c6fe0ad2SBrandon Streiff /* Timestamping state */ 180c6fe0ad2SBrandon Streiff unsigned long state; 181c6fe0ad2SBrandon Streiff 182c6fe0ad2SBrandon Streiff /* Resources for receive timestamping */ 183c6fe0ad2SBrandon Streiff struct sk_buff_head rx_queue; 184c6fe0ad2SBrandon Streiff struct sk_buff_head rx_queue2; 185c6fe0ad2SBrandon Streiff 186c6fe0ad2SBrandon Streiff /* Resources for transmit timestamping */ 187c6fe0ad2SBrandon Streiff unsigned long tx_tstamp_start; 188c6fe0ad2SBrandon Streiff struct sk_buff *tx_skb; 189c6fe0ad2SBrandon Streiff u16 tx_seq_id; 190c6fe0ad2SBrandon Streiff 191c6fe0ad2SBrandon Streiff /* Current timestamp configuration */ 192c6fe0ad2SBrandon Streiff struct hwtstamp_config tstamp_config; 193c6fe0ad2SBrandon Streiff }; 194c6fe0ad2SBrandon Streiff 195cda9f4aaSAndrew Lunn struct mv88e6xxx_port { 196cda9f4aaSAndrew Lunn u64 serdes_stats[2]; 197cda9f4aaSAndrew Lunn }; 198cda9f4aaSAndrew Lunn 1994d5f2ba7SVivien Didelot struct mv88e6xxx_chip { 2004d5f2ba7SVivien Didelot const struct mv88e6xxx_info *info; 2014d5f2ba7SVivien Didelot 2024d5f2ba7SVivien Didelot /* The dsa_switch this private structure is related to */ 2034d5f2ba7SVivien Didelot struct dsa_switch *ds; 2044d5f2ba7SVivien Didelot 2054d5f2ba7SVivien Didelot /* The device this structure is associated to */ 2064d5f2ba7SVivien Didelot struct device *dev; 2074d5f2ba7SVivien Didelot 2084d5f2ba7SVivien Didelot /* This mutex protects the access to the switch registers */ 2094d5f2ba7SVivien Didelot struct mutex reg_lock; 2104d5f2ba7SVivien Didelot 2114d5f2ba7SVivien Didelot /* The MII bus and the address on the bus that is used to 2124d5f2ba7SVivien Didelot * communication with the switch 2134d5f2ba7SVivien Didelot */ 2144d5f2ba7SVivien Didelot const struct mv88e6xxx_bus_ops *smi_ops; 2154d5f2ba7SVivien Didelot struct mii_bus *bus; 2164d5f2ba7SVivien Didelot int sw_addr; 2174d5f2ba7SVivien Didelot 2184d5f2ba7SVivien Didelot /* Handles automatic disabling and re-enabling of the PHY 2194d5f2ba7SVivien Didelot * polling unit. 2204d5f2ba7SVivien Didelot */ 2214d5f2ba7SVivien Didelot const struct mv88e6xxx_bus_ops *phy_ops; 2224d5f2ba7SVivien Didelot struct mutex ppu_mutex; 2234d5f2ba7SVivien Didelot int ppu_disabled; 2244d5f2ba7SVivien Didelot struct work_struct ppu_work; 2254d5f2ba7SVivien Didelot struct timer_list ppu_timer; 2264d5f2ba7SVivien Didelot 2274d5f2ba7SVivien Didelot /* This mutex serialises access to the statistics unit. 2284d5f2ba7SVivien Didelot * Hold this mutex over snapshot + dump sequences. 2294d5f2ba7SVivien Didelot */ 2304d5f2ba7SVivien Didelot struct mutex stats_mutex; 2314d5f2ba7SVivien Didelot 2324d5f2ba7SVivien Didelot /* A switch may have a GPIO line tied to its reset pin. Parse 2334d5f2ba7SVivien Didelot * this from the device tree, and use it before performing 2344d5f2ba7SVivien Didelot * switch soft reset. 2354d5f2ba7SVivien Didelot */ 2364d5f2ba7SVivien Didelot struct gpio_desc *reset; 2374d5f2ba7SVivien Didelot 2384d5f2ba7SVivien Didelot /* set to size of eeprom if supported by the switch */ 2394d5f2ba7SVivien Didelot int eeprom_len; 2404d5f2ba7SVivien Didelot 2414d5f2ba7SVivien Didelot /* List of mdio busses */ 2424d5f2ba7SVivien Didelot struct list_head mdios; 2434d5f2ba7SVivien Didelot 2444d5f2ba7SVivien Didelot /* There can be two interrupt controllers, which are chained 2454d5f2ba7SVivien Didelot * off a GPIO as interrupt source 2464d5f2ba7SVivien Didelot */ 2474d5f2ba7SVivien Didelot struct mv88e6xxx_irq g1_irq; 2484d5f2ba7SVivien Didelot struct mv88e6xxx_irq g2_irq; 2494d5f2ba7SVivien Didelot int irq; 2504d5f2ba7SVivien Didelot int device_irq; 2514d5f2ba7SVivien Didelot int watchdog_irq; 252cda9f4aaSAndrew Lunn 2530977644cSAndrew Lunn int atu_prob_irq; 25462eb1162SAndrew Lunn int vtu_prob_irq; 255294d711eSAndrew Lunn struct kthread_worker *kworker; 256294d711eSAndrew Lunn struct kthread_delayed_work irq_poll_work; 2572fa8d3afSBrandon Streiff 258a73ccd61SBrandon Streiff /* GPIO resources */ 259a73ccd61SBrandon Streiff u8 gpio_data[2]; 260a73ccd61SBrandon Streiff 2612fa8d3afSBrandon Streiff /* This cyclecounter abstracts the switch PTP time. 2622fa8d3afSBrandon Streiff * reg_lock must be held for any operation that read()s. 2632fa8d3afSBrandon Streiff */ 2642fa8d3afSBrandon Streiff struct cyclecounter tstamp_cc; 2652fa8d3afSBrandon Streiff struct timecounter tstamp_tc; 2662fa8d3afSBrandon Streiff struct delayed_work overflow_work; 2672fa8d3afSBrandon Streiff 2682fa8d3afSBrandon Streiff struct ptp_clock *ptp_clock; 2692fa8d3afSBrandon Streiff struct ptp_clock_info ptp_clock_info; 2704eb3be29SBrandon Streiff struct delayed_work tai_event_work; 2714eb3be29SBrandon Streiff struct ptp_pin_desc pin_config[MV88E6XXX_MAX_GPIO]; 2724eb3be29SBrandon Streiff u16 trig_config; 2734eb3be29SBrandon Streiff u16 evcap_config; 274c6fe0ad2SBrandon Streiff 275c6fe0ad2SBrandon Streiff /* Per-port timestamping resources. */ 276c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS]; 277cda9f4aaSAndrew Lunn 278cda9f4aaSAndrew Lunn /* Array of port structures. */ 279cda9f4aaSAndrew Lunn struct mv88e6xxx_port ports[DSA_MAX_PORTS]; 2804d5f2ba7SVivien Didelot }; 2814d5f2ba7SVivien Didelot 2824d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops { 2834d5f2ba7SVivien Didelot int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); 2844d5f2ba7SVivien Didelot int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); 2854d5f2ba7SVivien Didelot }; 2864d5f2ba7SVivien Didelot 2874d5f2ba7SVivien Didelot struct mv88e6xxx_mdio_bus { 2884d5f2ba7SVivien Didelot struct mii_bus *bus; 2894d5f2ba7SVivien Didelot struct mv88e6xxx_chip *chip; 2904d5f2ba7SVivien Didelot struct list_head list; 2914d5f2ba7SVivien Didelot bool external; 2924d5f2ba7SVivien Didelot }; 2934d5f2ba7SVivien Didelot 2944d5f2ba7SVivien Didelot struct mv88e6xxx_ops { 295cd8da8bbSVivien Didelot /* Ingress Rate Limit unit (IRL) operations */ 296cd8da8bbSVivien Didelot int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port); 297cd8da8bbSVivien Didelot 2984d5f2ba7SVivien Didelot int (*get_eeprom)(struct mv88e6xxx_chip *chip, 2994d5f2ba7SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data); 3004d5f2ba7SVivien Didelot int (*set_eeprom)(struct mv88e6xxx_chip *chip, 3014d5f2ba7SVivien Didelot struct ethtool_eeprom *eeprom, u8 *data); 3024d5f2ba7SVivien Didelot 3034d5f2ba7SVivien Didelot int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr); 3044d5f2ba7SVivien Didelot 3054d5f2ba7SVivien Didelot int (*phy_read)(struct mv88e6xxx_chip *chip, 3064d5f2ba7SVivien Didelot struct mii_bus *bus, 3074d5f2ba7SVivien Didelot int addr, int reg, u16 *val); 3084d5f2ba7SVivien Didelot int (*phy_write)(struct mv88e6xxx_chip *chip, 3094d5f2ba7SVivien Didelot struct mii_bus *bus, 3104d5f2ba7SVivien Didelot int addr, int reg, u16 val); 3114d5f2ba7SVivien Didelot 3129e907d73SVivien Didelot /* Priority Override Table operations */ 3139e907d73SVivien Didelot int (*pot_clear)(struct mv88e6xxx_chip *chip); 3149e907d73SVivien Didelot 3154d5f2ba7SVivien Didelot /* PHY Polling Unit (PPU) operations */ 3164d5f2ba7SVivien Didelot int (*ppu_enable)(struct mv88e6xxx_chip *chip); 3174d5f2ba7SVivien Didelot int (*ppu_disable)(struct mv88e6xxx_chip *chip); 3184d5f2ba7SVivien Didelot 3194d5f2ba7SVivien Didelot /* Switch Software Reset */ 3204d5f2ba7SVivien Didelot int (*reset)(struct mv88e6xxx_chip *chip); 3214d5f2ba7SVivien Didelot 3224d5f2ba7SVivien Didelot /* RGMII Receive/Transmit Timing Control 3234d5f2ba7SVivien Didelot * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise. 3244d5f2ba7SVivien Didelot */ 3254d5f2ba7SVivien Didelot int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port, 3264d5f2ba7SVivien Didelot phy_interface_t mode); 3274d5f2ba7SVivien Didelot 3284d5f2ba7SVivien Didelot #define LINK_FORCED_DOWN 0 3294d5f2ba7SVivien Didelot #define LINK_FORCED_UP 1 3304d5f2ba7SVivien Didelot #define LINK_UNFORCED -2 3314d5f2ba7SVivien Didelot 3324d5f2ba7SVivien Didelot /* Port's MAC link state 3334d5f2ba7SVivien Didelot * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down, 3344d5f2ba7SVivien Didelot * or LINK_UNFORCED for normal link detection. 3354d5f2ba7SVivien Didelot */ 3364d5f2ba7SVivien Didelot int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link); 3374d5f2ba7SVivien Didelot 3384d5f2ba7SVivien Didelot #define DUPLEX_UNFORCED -2 3394d5f2ba7SVivien Didelot 3404d5f2ba7SVivien Didelot /* Port's MAC duplex mode 3414d5f2ba7SVivien Didelot * 3424d5f2ba7SVivien Didelot * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex, 3434d5f2ba7SVivien Didelot * or DUPLEX_UNFORCED for normal duplex detection. 3444d5f2ba7SVivien Didelot */ 3454d5f2ba7SVivien Didelot int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup); 3464d5f2ba7SVivien Didelot 3474d5f2ba7SVivien Didelot #define SPEED_MAX INT_MAX 3484d5f2ba7SVivien Didelot #define SPEED_UNFORCED -2 3494d5f2ba7SVivien Didelot 3504d5f2ba7SVivien Didelot /* Port's MAC speed (in Mbps) 3514d5f2ba7SVivien Didelot * 3524d5f2ba7SVivien Didelot * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid. 3534d5f2ba7SVivien Didelot * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value. 3544d5f2ba7SVivien Didelot */ 3554d5f2ba7SVivien Didelot int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); 3564d5f2ba7SVivien Didelot 3574d5f2ba7SVivien Didelot int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port); 3584d5f2ba7SVivien Didelot 3594d5f2ba7SVivien Didelot int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port, 3604d5f2ba7SVivien Didelot enum mv88e6xxx_frame_mode mode); 3614d5f2ba7SVivien Didelot int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port, 3624d5f2ba7SVivien Didelot bool unicast, bool multicast); 3634d5f2ba7SVivien Didelot int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port, 3644d5f2ba7SVivien Didelot u16 etype); 365cd782656SVivien Didelot int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port, 366cd782656SVivien Didelot size_t size); 3674d5f2ba7SVivien Didelot 3684d5f2ba7SVivien Didelot int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port); 3690898432cSVivien Didelot int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in, 3700898432cSVivien Didelot u8 out); 3714d5f2ba7SVivien Didelot int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port); 3724d5f2ba7SVivien Didelot int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port); 3734d5f2ba7SVivien Didelot 3744d5f2ba7SVivien Didelot /* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc. 3754d5f2ba7SVivien Didelot * Some chips allow this to be configured on specific ports. 3764d5f2ba7SVivien Didelot */ 3774d5f2ba7SVivien Didelot int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port, 3784d5f2ba7SVivien Didelot phy_interface_t mode); 3794d5f2ba7SVivien Didelot 3804d5f2ba7SVivien Didelot /* Some devices have a per port register indicating what is 3814d5f2ba7SVivien Didelot * the upstream port this port should forward to. 3824d5f2ba7SVivien Didelot */ 3834d5f2ba7SVivien Didelot int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port, 3844d5f2ba7SVivien Didelot int upstream_port); 3854d5f2ba7SVivien Didelot 3864d5f2ba7SVivien Didelot /* Snapshot the statistics for a port. The statistics can then 3874d5f2ba7SVivien Didelot * be read back a leisure but still with a consistent view. 3884d5f2ba7SVivien Didelot */ 3894d5f2ba7SVivien Didelot int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port); 3904d5f2ba7SVivien Didelot 3914d5f2ba7SVivien Didelot /* Set the histogram mode for statistics, when the control registers 3924d5f2ba7SVivien Didelot * are separated out of the STATS_OP register. 3934d5f2ba7SVivien Didelot */ 3944d5f2ba7SVivien Didelot int (*stats_set_histogram)(struct mv88e6xxx_chip *chip); 3954d5f2ba7SVivien Didelot 3964d5f2ba7SVivien Didelot /* Return the number of strings describing statistics */ 3974d5f2ba7SVivien Didelot int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip); 398436fe17dSAndrew Lunn int (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data); 399436fe17dSAndrew Lunn int (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port, 4004d5f2ba7SVivien Didelot uint64_t *data); 401fa8d1179SVivien Didelot int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port); 402fa8d1179SVivien Didelot int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port); 4034d5f2ba7SVivien Didelot const struct mv88e6xxx_irq_ops *watchdog_ops; 4044d5f2ba7SVivien Didelot 4054d5f2ba7SVivien Didelot int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip); 4064d5f2ba7SVivien Didelot 4074d5f2ba7SVivien Didelot /* Power on/off a SERDES interface */ 4084d5f2ba7SVivien Didelot int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on); 4094d5f2ba7SVivien Didelot 410436fe17dSAndrew Lunn /* Statistics from the SERDES interface */ 411436fe17dSAndrew Lunn int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port); 412436fe17dSAndrew Lunn void (*serdes_get_strings)(struct mv88e6xxx_chip *chip, int port, 413436fe17dSAndrew Lunn uint8_t *data); 414436fe17dSAndrew Lunn void (*serdes_get_stats)(struct mv88e6xxx_chip *chip, int port, 415436fe17dSAndrew Lunn uint64_t *data); 416436fe17dSAndrew Lunn 4174d5f2ba7SVivien Didelot /* VLAN Translation Unit operations */ 4184d5f2ba7SVivien Didelot int (*vtu_getnext)(struct mv88e6xxx_chip *chip, 4194d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry *entry); 4204d5f2ba7SVivien Didelot int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip, 4214d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry *entry); 4220d632c3dSBrandon Streiff 423a73ccd61SBrandon Streiff /* GPIO operations */ 424a73ccd61SBrandon Streiff const struct mv88e6xxx_gpio_ops *gpio_ops; 425a73ccd61SBrandon Streiff 4260d632c3dSBrandon Streiff /* Interface to the AVB/PTP registers */ 4270d632c3dSBrandon Streiff const struct mv88e6xxx_avb_ops *avb_ops; 4284d5f2ba7SVivien Didelot }; 4294d5f2ba7SVivien Didelot 4304d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops { 4314d5f2ba7SVivien Didelot /* Action to be performed when the interrupt happens */ 4324d5f2ba7SVivien Didelot int (*irq_action)(struct mv88e6xxx_chip *chip, int irq); 4334d5f2ba7SVivien Didelot /* Setup the hardware to generate the interrupt */ 4344d5f2ba7SVivien Didelot int (*irq_setup)(struct mv88e6xxx_chip *chip); 4354d5f2ba7SVivien Didelot /* Reset the hardware to stop generating the interrupt */ 4364d5f2ba7SVivien Didelot void (*irq_free)(struct mv88e6xxx_chip *chip); 4374d5f2ba7SVivien Didelot }; 4384d5f2ba7SVivien Didelot 439a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops { 440a73ccd61SBrandon Streiff /* Get/set data on GPIO pin */ 441a73ccd61SBrandon Streiff int (*get_data)(struct mv88e6xxx_chip *chip, unsigned int pin); 442a73ccd61SBrandon Streiff int (*set_data)(struct mv88e6xxx_chip *chip, unsigned int pin, 443a73ccd61SBrandon Streiff int value); 444a73ccd61SBrandon Streiff 445a73ccd61SBrandon Streiff /* get/set GPIO direction */ 446a73ccd61SBrandon Streiff int (*get_dir)(struct mv88e6xxx_chip *chip, unsigned int pin); 447a73ccd61SBrandon Streiff int (*set_dir)(struct mv88e6xxx_chip *chip, unsigned int pin, 448a73ccd61SBrandon Streiff bool input); 449a73ccd61SBrandon Streiff 450a73ccd61SBrandon Streiff /* get/set GPIO pin control */ 451a73ccd61SBrandon Streiff int (*get_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin, 452a73ccd61SBrandon Streiff int *func); 453a73ccd61SBrandon Streiff int (*set_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin, 454a73ccd61SBrandon Streiff int func); 455a73ccd61SBrandon Streiff }; 456a73ccd61SBrandon Streiff 4570d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops { 4580d632c3dSBrandon Streiff /* Access port-scoped Precision Time Protocol registers */ 4590d632c3dSBrandon Streiff int (*port_ptp_read)(struct mv88e6xxx_chip *chip, int port, int addr, 4600d632c3dSBrandon Streiff u16 *data, int len); 4610d632c3dSBrandon Streiff int (*port_ptp_write)(struct mv88e6xxx_chip *chip, int port, int addr, 4620d632c3dSBrandon Streiff u16 data); 4630d632c3dSBrandon Streiff 4640d632c3dSBrandon Streiff /* Access global Precision Time Protocol registers */ 4650d632c3dSBrandon Streiff int (*ptp_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data, 4660d632c3dSBrandon Streiff int len); 4670d632c3dSBrandon Streiff int (*ptp_write)(struct mv88e6xxx_chip *chip, int addr, u16 data); 4680d632c3dSBrandon Streiff 4690d632c3dSBrandon Streiff /* Access global Time Application Interface registers */ 4700d632c3dSBrandon Streiff int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data, 4710d632c3dSBrandon Streiff int len); 4720d632c3dSBrandon Streiff int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data); 4730d632c3dSBrandon Streiff }; 4740d632c3dSBrandon Streiff 4754d5f2ba7SVivien Didelot #define STATS_TYPE_PORT BIT(0) 4764d5f2ba7SVivien Didelot #define STATS_TYPE_BANK0 BIT(1) 4774d5f2ba7SVivien Didelot #define STATS_TYPE_BANK1 BIT(2) 4784d5f2ba7SVivien Didelot 4794d5f2ba7SVivien Didelot struct mv88e6xxx_hw_stat { 4804d5f2ba7SVivien Didelot char string[ETH_GSTRING_LEN]; 481cda9f4aaSAndrew Lunn size_t size; 4824d5f2ba7SVivien Didelot int reg; 4834d5f2ba7SVivien Didelot int type; 4844d5f2ba7SVivien Didelot }; 4854d5f2ba7SVivien Didelot 4864d5f2ba7SVivien Didelot static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip) 4874d5f2ba7SVivien Didelot { 4884d5f2ba7SVivien Didelot return chip->info->pvt; 4894d5f2ba7SVivien Didelot } 4904d5f2ba7SVivien Didelot 4914d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip) 4924d5f2ba7SVivien Didelot { 4934d5f2ba7SVivien Didelot return chip->info->num_databases; 4944d5f2ba7SVivien Didelot } 4954d5f2ba7SVivien Didelot 4964d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip) 4974d5f2ba7SVivien Didelot { 4984d5f2ba7SVivien Didelot return chip->info->num_ports; 4994d5f2ba7SVivien Didelot } 5004d5f2ba7SVivien Didelot 5014d5f2ba7SVivien Didelot static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip) 5024d5f2ba7SVivien Didelot { 5034d5f2ba7SVivien Didelot return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); 5044d5f2ba7SVivien Didelot } 5054d5f2ba7SVivien Didelot 506a73ccd61SBrandon Streiff static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip) 507a73ccd61SBrandon Streiff { 508a73ccd61SBrandon Streiff return chip->info->num_gpio; 509a73ccd61SBrandon Streiff } 510a73ccd61SBrandon Streiff 5114d5f2ba7SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val); 5124d5f2ba7SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); 5134d5f2ba7SVivien Didelot int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg, 5144d5f2ba7SVivien Didelot u16 update); 5154d5f2ba7SVivien Didelot int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask); 5164d5f2ba7SVivien Didelot struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip); 5174d5f2ba7SVivien Didelot 5184d5f2ba7SVivien Didelot #endif /* _MV88E6XXX_CHIP_H */ 519