xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/chip.h (revision 49022647)
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 
109b3e05aa1SVivien Didelot 	/* Multi-chip Addressing Mode.
110b3e05aa1SVivien Didelot 	 * Some chips respond to only 2 registers of its own SMI device address
111b3e05aa1SVivien Didelot 	 * when it is non-zero, and use indirect access to internal registers.
112b3e05aa1SVivien Didelot 	 */
113b3e05aa1SVivien Didelot 	bool multi_chip;
114f30a19b8SRasmus Villemoes 	/* Dual-chip Addressing Mode
115f30a19b8SRasmus Villemoes 	 * Some chips respond to only half of the 32 SMI addresses,
116f30a19b8SRasmus Villemoes 	 * allowing two to coexist on the same SMI interface.
117f30a19b8SRasmus Villemoes 	 */
118f30a19b8SRasmus Villemoes 	bool dual_chip;
119f30a19b8SRasmus Villemoes 
1204d5f2ba7SVivien Didelot 	enum dsa_tag_protocol tag_protocol;
1214d5f2ba7SVivien Didelot 
1224d5f2ba7SVivien Didelot 	/* Mask for FromPort and ToPort value of PortVec used in ATU Move
1234d5f2ba7SVivien Didelot 	 * operation. 0 means that the ATU Move operation is not supported.
1244d5f2ba7SVivien Didelot 	 */
1254d5f2ba7SVivien Didelot 	u8 atu_move_port_mask;
1264d5f2ba7SVivien Didelot 	const struct mv88e6xxx_ops *ops;
1272fa8d3afSBrandon Streiff 
1282fa8d3afSBrandon Streiff 	/* Supports PTP */
1292fa8d3afSBrandon Streiff 	bool ptp_support;
1304d5f2ba7SVivien Didelot };
1314d5f2ba7SVivien Didelot 
1324d5f2ba7SVivien Didelot struct mv88e6xxx_atu_entry {
1334d5f2ba7SVivien Didelot 	u8	state;
1344d5f2ba7SVivien Didelot 	bool	trunk;
1354d5f2ba7SVivien Didelot 	u16	portvec;
1364d5f2ba7SVivien Didelot 	u8	mac[ETH_ALEN];
1374d5f2ba7SVivien Didelot };
1384d5f2ba7SVivien Didelot 
1394d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry {
1404d5f2ba7SVivien Didelot 	u16	vid;
1414d5f2ba7SVivien Didelot 	u16	fid;
1424d5f2ba7SVivien Didelot 	u8	sid;
1434d5f2ba7SVivien Didelot 	bool	valid;
1444d5f2ba7SVivien Didelot 	u8	member[DSA_MAX_PORTS];
1454d5f2ba7SVivien Didelot 	u8	state[DSA_MAX_PORTS];
1464d5f2ba7SVivien Didelot };
1474d5f2ba7SVivien Didelot 
1484d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops;
1494d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops;
150a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops;
1510d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops;
1526d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops;
1534d5f2ba7SVivien Didelot 
1544d5f2ba7SVivien Didelot struct mv88e6xxx_irq {
1554d5f2ba7SVivien Didelot 	u16 masked;
1564d5f2ba7SVivien Didelot 	struct irq_chip chip;
1574d5f2ba7SVivien Didelot 	struct irq_domain *domain;
1584d5f2ba7SVivien Didelot 	unsigned int nirqs;
1594d5f2ba7SVivien Didelot };
1604d5f2ba7SVivien Didelot 
161c6fe0ad2SBrandon Streiff /* state flags for mv88e6xxx_port_hwtstamp::state */
162c6fe0ad2SBrandon Streiff enum {
163c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_ENABLED,
164c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
165c6fe0ad2SBrandon Streiff };
166c6fe0ad2SBrandon Streiff 
167c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp {
168c6fe0ad2SBrandon Streiff 	/* Port index */
169c6fe0ad2SBrandon Streiff 	int port_id;
170c6fe0ad2SBrandon Streiff 
171c6fe0ad2SBrandon Streiff 	/* Timestamping state */
172c6fe0ad2SBrandon Streiff 	unsigned long state;
173c6fe0ad2SBrandon Streiff 
174c6fe0ad2SBrandon Streiff 	/* Resources for receive timestamping */
175c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue;
176c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue2;
177c6fe0ad2SBrandon Streiff 
178c6fe0ad2SBrandon Streiff 	/* Resources for transmit timestamping */
179c6fe0ad2SBrandon Streiff 	unsigned long tx_tstamp_start;
180c6fe0ad2SBrandon Streiff 	struct sk_buff *tx_skb;
181c6fe0ad2SBrandon Streiff 	u16 tx_seq_id;
182c6fe0ad2SBrandon Streiff 
183c6fe0ad2SBrandon Streiff 	/* Current timestamp configuration */
184c6fe0ad2SBrandon Streiff 	struct hwtstamp_config tstamp_config;
185c6fe0ad2SBrandon Streiff };
186c6fe0ad2SBrandon Streiff 
187cda9f4aaSAndrew Lunn struct mv88e6xxx_port {
1887b898469SAndrew Lunn 	struct mv88e6xxx_chip *chip;
1897b898469SAndrew Lunn 	int port;
190cda9f4aaSAndrew Lunn 	u64 serdes_stats[2];
19165f60e45SAndrew Lunn 	u64 atu_member_violation;
19265f60e45SAndrew Lunn 	u64 atu_miss_violation;
19365f60e45SAndrew Lunn 	u64 atu_full_violation;
19465f60e45SAndrew Lunn 	u64 vtu_member_violation;
19565f60e45SAndrew Lunn 	u64 vtu_miss_violation;
1962d2e1dd2SAndrew Lunn 	u8 cmode;
197efd1ba6aSAndrew Lunn 	int serdes_irq;
198cda9f4aaSAndrew Lunn };
199cda9f4aaSAndrew Lunn 
2004d5f2ba7SVivien Didelot struct mv88e6xxx_chip {
2014d5f2ba7SVivien Didelot 	const struct mv88e6xxx_info *info;
2024d5f2ba7SVivien Didelot 
2034d5f2ba7SVivien Didelot 	/* The dsa_switch this private structure is related to */
2044d5f2ba7SVivien Didelot 	struct dsa_switch *ds;
2054d5f2ba7SVivien Didelot 
2064d5f2ba7SVivien Didelot 	/* The device this structure is associated to */
2074d5f2ba7SVivien Didelot 	struct device *dev;
2084d5f2ba7SVivien Didelot 
2094d5f2ba7SVivien Didelot 	/* This mutex protects the access to the switch registers */
2104d5f2ba7SVivien Didelot 	struct mutex reg_lock;
2114d5f2ba7SVivien Didelot 
2124d5f2ba7SVivien Didelot 	/* The MII bus and the address on the bus that is used to
2134d5f2ba7SVivien Didelot 	 * communication with the switch
2144d5f2ba7SVivien Didelot 	 */
2154d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *smi_ops;
2164d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2174d5f2ba7SVivien Didelot 	int sw_addr;
2184d5f2ba7SVivien Didelot 
2194d5f2ba7SVivien Didelot 	/* Handles automatic disabling and re-enabling of the PHY
2204d5f2ba7SVivien Didelot 	 * polling unit.
2214d5f2ba7SVivien Didelot 	 */
2224d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *phy_ops;
2234d5f2ba7SVivien Didelot 	struct mutex		ppu_mutex;
2244d5f2ba7SVivien Didelot 	int			ppu_disabled;
2254d5f2ba7SVivien Didelot 	struct work_struct	ppu_work;
2264d5f2ba7SVivien Didelot 	struct timer_list	ppu_timer;
2274d5f2ba7SVivien Didelot 
2284d5f2ba7SVivien Didelot 	/* This mutex serialises access to the statistics unit.
2294d5f2ba7SVivien Didelot 	 * Hold this mutex over snapshot + dump sequences.
2304d5f2ba7SVivien Didelot 	 */
2314d5f2ba7SVivien Didelot 	struct mutex	stats_mutex;
2324d5f2ba7SVivien Didelot 
2334d5f2ba7SVivien Didelot 	/* A switch may have a GPIO line tied to its reset pin. Parse
2344d5f2ba7SVivien Didelot 	 * this from the device tree, and use it before performing
2354d5f2ba7SVivien Didelot 	 * switch soft reset.
2364d5f2ba7SVivien Didelot 	 */
2374d5f2ba7SVivien Didelot 	struct gpio_desc *reset;
2384d5f2ba7SVivien Didelot 
2394d5f2ba7SVivien Didelot 	/* set to size of eeprom if supported by the switch */
24000baabe5SAndrew Lunn 	u32 eeprom_len;
2414d5f2ba7SVivien Didelot 
2424d5f2ba7SVivien Didelot 	/* List of mdio busses */
2434d5f2ba7SVivien Didelot 	struct list_head mdios;
2444d5f2ba7SVivien Didelot 
2454d5f2ba7SVivien Didelot 	/* There can be two interrupt controllers, which are chained
2464d5f2ba7SVivien Didelot 	 * off a GPIO as interrupt source
2474d5f2ba7SVivien Didelot 	 */
2484d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g1_irq;
2494d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g2_irq;
2504d5f2ba7SVivien Didelot 	int irq;
2514d5f2ba7SVivien Didelot 	int device_irq;
2524d5f2ba7SVivien Didelot 	int watchdog_irq;
253cda9f4aaSAndrew Lunn 
2540977644cSAndrew Lunn 	int atu_prob_irq;
25562eb1162SAndrew Lunn 	int vtu_prob_irq;
256294d711eSAndrew Lunn 	struct kthread_worker *kworker;
257294d711eSAndrew Lunn 	struct kthread_delayed_work irq_poll_work;
2582fa8d3afSBrandon Streiff 
259a73ccd61SBrandon Streiff 	/* GPIO resources */
260a73ccd61SBrandon Streiff 	u8 gpio_data[2];
261a73ccd61SBrandon Streiff 
2622fa8d3afSBrandon Streiff 	/* This cyclecounter abstracts the switch PTP time.
2632fa8d3afSBrandon Streiff 	 * reg_lock must be held for any operation that read()s.
2642fa8d3afSBrandon Streiff 	 */
2652fa8d3afSBrandon Streiff 	struct cyclecounter	tstamp_cc;
2662fa8d3afSBrandon Streiff 	struct timecounter	tstamp_tc;
2672fa8d3afSBrandon Streiff 	struct delayed_work	overflow_work;
2682fa8d3afSBrandon Streiff 
2692fa8d3afSBrandon Streiff 	struct ptp_clock	*ptp_clock;
2702fa8d3afSBrandon Streiff 	struct ptp_clock_info	ptp_clock_info;
2714eb3be29SBrandon Streiff 	struct delayed_work	tai_event_work;
2724eb3be29SBrandon Streiff 	struct ptp_pin_desc	pin_config[MV88E6XXX_MAX_GPIO];
2734eb3be29SBrandon Streiff 	u16 trig_config;
2744eb3be29SBrandon Streiff 	u16 evcap_config;
275e2294a8bSAndrew Lunn 	u16 enable_count;
276c6fe0ad2SBrandon Streiff 
277c6fe0ad2SBrandon Streiff 	/* Per-port timestamping resources. */
278c6fe0ad2SBrandon Streiff 	struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
279cda9f4aaSAndrew Lunn 
280cda9f4aaSAndrew Lunn 	/* Array of port structures. */
281cda9f4aaSAndrew Lunn 	struct mv88e6xxx_port ports[DSA_MAX_PORTS];
2824d5f2ba7SVivien Didelot };
2834d5f2ba7SVivien Didelot 
2844d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops {
2854d5f2ba7SVivien Didelot 	int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
2864d5f2ba7SVivien Didelot 	int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
2874d5f2ba7SVivien Didelot };
2884d5f2ba7SVivien Didelot 
2894d5f2ba7SVivien Didelot struct mv88e6xxx_mdio_bus {
2904d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2914d5f2ba7SVivien Didelot 	struct mv88e6xxx_chip *chip;
2924d5f2ba7SVivien Didelot 	struct list_head list;
2934d5f2ba7SVivien Didelot 	bool external;
2944d5f2ba7SVivien Didelot };
2954d5f2ba7SVivien Didelot 
2964d5f2ba7SVivien Didelot struct mv88e6xxx_ops {
297ea89098eSAndrew Lunn 	/* Switch Setup Errata, called early in the switch setup to
298ea89098eSAndrew Lunn 	 * allow any errata actions to be performed
299ea89098eSAndrew Lunn 	 */
300ea89098eSAndrew Lunn 	int (*setup_errata)(struct mv88e6xxx_chip *chip);
301ea89098eSAndrew Lunn 
30293e18d61SVivien Didelot 	int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
30393e18d61SVivien Didelot 	int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
30493e18d61SVivien Didelot 
305cd8da8bbSVivien Didelot 	/* Ingress Rate Limit unit (IRL) operations */
306cd8da8bbSVivien Didelot 	int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
307cd8da8bbSVivien Didelot 
3084d5f2ba7SVivien Didelot 	int (*get_eeprom)(struct mv88e6xxx_chip *chip,
3094d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
3104d5f2ba7SVivien Didelot 	int (*set_eeprom)(struct mv88e6xxx_chip *chip,
3114d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
3124d5f2ba7SVivien Didelot 
3134d5f2ba7SVivien Didelot 	int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr);
3144d5f2ba7SVivien Didelot 
3154d5f2ba7SVivien Didelot 	int (*phy_read)(struct mv88e6xxx_chip *chip,
3164d5f2ba7SVivien Didelot 			struct mii_bus *bus,
3174d5f2ba7SVivien Didelot 			int addr, int reg, u16 *val);
3184d5f2ba7SVivien Didelot 	int (*phy_write)(struct mv88e6xxx_chip *chip,
3194d5f2ba7SVivien Didelot 			 struct mii_bus *bus,
3204d5f2ba7SVivien Didelot 			 int addr, int reg, u16 val);
3214d5f2ba7SVivien Didelot 
3229e907d73SVivien Didelot 	/* Priority Override Table operations */
3239e907d73SVivien Didelot 	int (*pot_clear)(struct mv88e6xxx_chip *chip);
3249e907d73SVivien Didelot 
3254d5f2ba7SVivien Didelot 	/* PHY Polling Unit (PPU) operations */
3264d5f2ba7SVivien Didelot 	int (*ppu_enable)(struct mv88e6xxx_chip *chip);
3274d5f2ba7SVivien Didelot 	int (*ppu_disable)(struct mv88e6xxx_chip *chip);
3284d5f2ba7SVivien Didelot 
3294d5f2ba7SVivien Didelot 	/* Switch Software Reset */
3304d5f2ba7SVivien Didelot 	int (*reset)(struct mv88e6xxx_chip *chip);
3314d5f2ba7SVivien Didelot 
3324d5f2ba7SVivien Didelot 	/* RGMII Receive/Transmit Timing Control
3334d5f2ba7SVivien Didelot 	 * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise.
3344d5f2ba7SVivien Didelot 	 */
3354d5f2ba7SVivien Didelot 	int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port,
3364d5f2ba7SVivien Didelot 				    phy_interface_t mode);
3374d5f2ba7SVivien Didelot 
3384d5f2ba7SVivien Didelot #define LINK_FORCED_DOWN	0
3394d5f2ba7SVivien Didelot #define LINK_FORCED_UP		1
3404d5f2ba7SVivien Didelot #define LINK_UNFORCED		-2
3414d5f2ba7SVivien Didelot 
3424d5f2ba7SVivien Didelot 	/* Port's MAC link state
3434d5f2ba7SVivien Didelot 	 * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down,
3444d5f2ba7SVivien Didelot 	 * or LINK_UNFORCED for normal link detection.
3454d5f2ba7SVivien Didelot 	 */
3464d5f2ba7SVivien Didelot 	int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
3474d5f2ba7SVivien Didelot 
3484d5f2ba7SVivien Didelot #define DUPLEX_UNFORCED		-2
3494d5f2ba7SVivien Didelot 
3504d5f2ba7SVivien Didelot 	/* Port's MAC duplex mode
3514d5f2ba7SVivien Didelot 	 *
3524d5f2ba7SVivien Didelot 	 * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
3534d5f2ba7SVivien Didelot 	 * or DUPLEX_UNFORCED for normal duplex detection.
3544d5f2ba7SVivien Didelot 	 */
3554d5f2ba7SVivien Didelot 	int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
3564d5f2ba7SVivien Didelot 
35754186b91SAndrew Lunn #define PAUSE_ON		1
35854186b91SAndrew Lunn #define PAUSE_OFF		0
35954186b91SAndrew Lunn 
36054186b91SAndrew Lunn 	/* Enable/disable sending Pause */
36154186b91SAndrew Lunn 	int (*port_set_pause)(struct mv88e6xxx_chip *chip, int port,
36254186b91SAndrew Lunn 			      int pause);
36354186b91SAndrew Lunn 
3644d5f2ba7SVivien Didelot #define SPEED_MAX		INT_MAX
3654d5f2ba7SVivien Didelot #define SPEED_UNFORCED		-2
3664d5f2ba7SVivien Didelot 
3674d5f2ba7SVivien Didelot 	/* Port's MAC speed (in Mbps)
3684d5f2ba7SVivien Didelot 	 *
3694d5f2ba7SVivien Didelot 	 * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
3704d5f2ba7SVivien Didelot 	 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
3714d5f2ba7SVivien Didelot 	 */
3724d5f2ba7SVivien Didelot 	int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
3734d5f2ba7SVivien Didelot 
3747cbbee05SAndrew Lunn 	/* What interface mode should be used for maximum speed? */
3757cbbee05SAndrew Lunn 	phy_interface_t (*port_max_speed_mode)(int port);
3767cbbee05SAndrew Lunn 
3774d5f2ba7SVivien Didelot 	int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
3784d5f2ba7SVivien Didelot 
3794d5f2ba7SVivien Didelot 	int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
3804d5f2ba7SVivien Didelot 				   enum mv88e6xxx_frame_mode mode);
3814d5f2ba7SVivien Didelot 	int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port,
3824d5f2ba7SVivien Didelot 				      bool unicast, bool multicast);
3834d5f2ba7SVivien Didelot 	int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
3844d5f2ba7SVivien Didelot 				   u16 etype);
385cd782656SVivien Didelot 	int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port,
386cd782656SVivien Didelot 				   size_t size);
3874d5f2ba7SVivien Didelot 
3884d5f2ba7SVivien Didelot 	int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
3890898432cSVivien Didelot 	int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in,
3900898432cSVivien Didelot 				u8 out);
3914d5f2ba7SVivien Didelot 	int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
3924d5f2ba7SVivien Didelot 	int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
3934d5f2ba7SVivien Didelot 
3944d5f2ba7SVivien Didelot 	/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
3954d5f2ba7SVivien Didelot 	 * Some chips allow this to be configured on specific ports.
3964d5f2ba7SVivien Didelot 	 */
3974d5f2ba7SVivien Didelot 	int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port,
3984d5f2ba7SVivien Didelot 			      phy_interface_t mode);
3992d2e1dd2SAndrew Lunn 	int (*port_get_cmode)(struct mv88e6xxx_chip *chip, int port, u8 *cmode);
4004d5f2ba7SVivien Didelot 
4014d5f2ba7SVivien Didelot 	/* Some devices have a per port register indicating what is
4024d5f2ba7SVivien Didelot 	 * the upstream port this port should forward to.
4034d5f2ba7SVivien Didelot 	 */
4044d5f2ba7SVivien Didelot 	int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port,
4054d5f2ba7SVivien Didelot 				      int upstream_port);
4066c422e34SRussell King 	/* Return the port link state, as required by phylink */
4076c422e34SRussell King 	int (*port_link_state)(struct mv88e6xxx_chip *chip, int port,
4086c422e34SRussell King 			       struct phylink_link_state *state);
4094d5f2ba7SVivien Didelot 
4104d5f2ba7SVivien Didelot 	/* Snapshot the statistics for a port. The statistics can then
4114d5f2ba7SVivien Didelot 	 * be read back a leisure but still with a consistent view.
4124d5f2ba7SVivien Didelot 	 */
4134d5f2ba7SVivien Didelot 	int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
4144d5f2ba7SVivien Didelot 
4154d5f2ba7SVivien Didelot 	/* Set the histogram mode for statistics, when the control registers
4164d5f2ba7SVivien Didelot 	 * are separated out of the STATS_OP register.
4174d5f2ba7SVivien Didelot 	 */
4184d5f2ba7SVivien Didelot 	int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
4194d5f2ba7SVivien Didelot 
4204d5f2ba7SVivien Didelot 	/* Return the number of strings describing statistics */
4214d5f2ba7SVivien Didelot 	int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
422436fe17dSAndrew Lunn 	int (*stats_get_strings)(struct mv88e6xxx_chip *chip,  uint8_t *data);
423436fe17dSAndrew Lunn 	int (*stats_get_stats)(struct mv88e6xxx_chip *chip,  int port,
4244d5f2ba7SVivien Didelot 			       uint64_t *data);
425fa8d1179SVivien Didelot 	int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
426fa8d1179SVivien Didelot 	int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
42702317e68SVivien Didelot 
42802317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_NONE		0xe
42902317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_MULTIPLE		0xf
43002317e68SVivien Didelot 
43102317e68SVivien Didelot 	int (*set_cascade_port)(struct mv88e6xxx_chip *chip, int port);
43202317e68SVivien Didelot 
4334d5f2ba7SVivien Didelot 	const struct mv88e6xxx_irq_ops *watchdog_ops;
4344d5f2ba7SVivien Didelot 
4354d5f2ba7SVivien Didelot 	int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
4364d5f2ba7SVivien Didelot 
4374d5f2ba7SVivien Didelot 	/* Power on/off a SERDES interface */
4384d5f2ba7SVivien Didelot 	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
4394d5f2ba7SVivien Didelot 
440efd1ba6aSAndrew Lunn 	/* SERDES interrupt handling */
441efd1ba6aSAndrew Lunn 	int (*serdes_irq_setup)(struct mv88e6xxx_chip *chip, int port);
442efd1ba6aSAndrew Lunn 	void (*serdes_irq_free)(struct mv88e6xxx_chip *chip, int port);
443efd1ba6aSAndrew Lunn 
444436fe17dSAndrew Lunn 	/* Statistics from the SERDES interface */
445436fe17dSAndrew Lunn 	int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
44665f60e45SAndrew Lunn 	int (*serdes_get_strings)(struct mv88e6xxx_chip *chip,  int port,
447436fe17dSAndrew Lunn 				  uint8_t *data);
44865f60e45SAndrew Lunn 	int (*serdes_get_stats)(struct mv88e6xxx_chip *chip,  int port,
449436fe17dSAndrew Lunn 				uint64_t *data);
450436fe17dSAndrew Lunn 
4514d5f2ba7SVivien Didelot 	/* VLAN Translation Unit operations */
4524d5f2ba7SVivien Didelot 	int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
4534d5f2ba7SVivien Didelot 			   struct mv88e6xxx_vtu_entry *entry);
4544d5f2ba7SVivien Didelot 	int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip,
4554d5f2ba7SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry);
4560d632c3dSBrandon Streiff 
457a73ccd61SBrandon Streiff 	/* GPIO operations */
458a73ccd61SBrandon Streiff 	const struct mv88e6xxx_gpio_ops *gpio_ops;
459a73ccd61SBrandon Streiff 
4600d632c3dSBrandon Streiff 	/* Interface to the AVB/PTP registers */
4610d632c3dSBrandon Streiff 	const struct mv88e6xxx_avb_ops *avb_ops;
4629e5baf9bSVivien Didelot 
4639e5baf9bSVivien Didelot 	/* Remote Management Unit operations */
4649e5baf9bSVivien Didelot 	int (*rmu_disable)(struct mv88e6xxx_chip *chip);
4656d2ac8eeSAndrew Lunn 
4666d2ac8eeSAndrew Lunn 	/* Precision Time Protocol operations */
4676d2ac8eeSAndrew Lunn 	const struct mv88e6xxx_ptp_ops *ptp_ops;
4686c422e34SRussell King 
4696c422e34SRussell King 	/* Phylink */
4706c422e34SRussell King 	void (*phylink_validate)(struct mv88e6xxx_chip *chip, int port,
4716c422e34SRussell King 				 unsigned long *mask,
4726c422e34SRussell King 				 struct phylink_link_state *state);
4734d5f2ba7SVivien Didelot };
4744d5f2ba7SVivien Didelot 
4754d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops {
4764d5f2ba7SVivien Didelot 	/* Action to be performed when the interrupt happens */
4774d5f2ba7SVivien Didelot 	int (*irq_action)(struct mv88e6xxx_chip *chip, int irq);
4784d5f2ba7SVivien Didelot 	/* Setup the hardware to generate the interrupt */
4794d5f2ba7SVivien Didelot 	int (*irq_setup)(struct mv88e6xxx_chip *chip);
4804d5f2ba7SVivien Didelot 	/* Reset the hardware to stop generating the interrupt */
4814d5f2ba7SVivien Didelot 	void (*irq_free)(struct mv88e6xxx_chip *chip);
4824d5f2ba7SVivien Didelot };
4834d5f2ba7SVivien Didelot 
484a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops {
485a73ccd61SBrandon Streiff 	/* Get/set data on GPIO pin */
486a73ccd61SBrandon Streiff 	int (*get_data)(struct mv88e6xxx_chip *chip, unsigned int pin);
487a73ccd61SBrandon Streiff 	int (*set_data)(struct mv88e6xxx_chip *chip, unsigned int pin,
488a73ccd61SBrandon Streiff 			int value);
489a73ccd61SBrandon Streiff 
490a73ccd61SBrandon Streiff 	/* get/set GPIO direction */
491a73ccd61SBrandon Streiff 	int (*get_dir)(struct mv88e6xxx_chip *chip, unsigned int pin);
492a73ccd61SBrandon Streiff 	int (*set_dir)(struct mv88e6xxx_chip *chip, unsigned int pin,
493a73ccd61SBrandon Streiff 		       bool input);
494a73ccd61SBrandon Streiff 
495a73ccd61SBrandon Streiff 	/* get/set GPIO pin control */
496a73ccd61SBrandon Streiff 	int (*get_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
497a73ccd61SBrandon Streiff 			int *func);
498a73ccd61SBrandon Streiff 	int (*set_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
499a73ccd61SBrandon Streiff 			int func);
500a73ccd61SBrandon Streiff };
501a73ccd61SBrandon Streiff 
5020d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops {
5030d632c3dSBrandon Streiff 	/* Access port-scoped Precision Time Protocol registers */
5040d632c3dSBrandon Streiff 	int (*port_ptp_read)(struct mv88e6xxx_chip *chip, int port, int addr,
5050d632c3dSBrandon Streiff 			     u16 *data, int len);
5060d632c3dSBrandon Streiff 	int (*port_ptp_write)(struct mv88e6xxx_chip *chip, int port, int addr,
5070d632c3dSBrandon Streiff 			      u16 data);
5080d632c3dSBrandon Streiff 
5090d632c3dSBrandon Streiff 	/* Access global Precision Time Protocol registers */
5100d632c3dSBrandon Streiff 	int (*ptp_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
5110d632c3dSBrandon Streiff 			int len);
5120d632c3dSBrandon Streiff 	int (*ptp_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
5130d632c3dSBrandon Streiff 
5140d632c3dSBrandon Streiff 	/* Access global Time Application Interface registers */
5150d632c3dSBrandon Streiff 	int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
5160d632c3dSBrandon Streiff 			int len);
5170d632c3dSBrandon Streiff 	int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
5180d632c3dSBrandon Streiff };
5190d632c3dSBrandon Streiff 
5206d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops {
5216d2ac8eeSAndrew Lunn 	u64 (*clock_read)(const struct cyclecounter *cc);
5226d2ac8eeSAndrew Lunn 	int (*ptp_enable)(struct ptp_clock_info *ptp,
5236d2ac8eeSAndrew Lunn 			  struct ptp_clock_request *rq, int on);
5246d2ac8eeSAndrew Lunn 	int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin,
5256d2ac8eeSAndrew Lunn 			  enum ptp_pin_function func, unsigned int chan);
5266d2ac8eeSAndrew Lunn 	void (*event_work)(struct work_struct *ugly);
527ffc705deSAndrew Lunn 	int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
528ffc705deSAndrew Lunn 	int (*port_disable)(struct mv88e6xxx_chip *chip, int port);
529e2294a8bSAndrew Lunn 	int (*global_enable)(struct mv88e6xxx_chip *chip);
530e2294a8bSAndrew Lunn 	int (*global_disable)(struct mv88e6xxx_chip *chip);
5316d2ac8eeSAndrew Lunn 	int n_ext_ts;
532ffc705deSAndrew Lunn 	int arr0_sts_reg;
533ffc705deSAndrew Lunn 	int arr1_sts_reg;
534ffc705deSAndrew Lunn 	int dep_sts_reg;
53548cb5e03SAndrew Lunn 	u32 rx_filters;
5366d2ac8eeSAndrew Lunn };
5376d2ac8eeSAndrew Lunn 
5384d5f2ba7SVivien Didelot #define STATS_TYPE_PORT		BIT(0)
5394d5f2ba7SVivien Didelot #define STATS_TYPE_BANK0	BIT(1)
5404d5f2ba7SVivien Didelot #define STATS_TYPE_BANK1	BIT(2)
5414d5f2ba7SVivien Didelot 
5424d5f2ba7SVivien Didelot struct mv88e6xxx_hw_stat {
5434d5f2ba7SVivien Didelot 	char string[ETH_GSTRING_LEN];
544cda9f4aaSAndrew Lunn 	size_t size;
5454d5f2ba7SVivien Didelot 	int reg;
5464d5f2ba7SVivien Didelot 	int type;
5474d5f2ba7SVivien Didelot };
5484d5f2ba7SVivien Didelot 
5494d5f2ba7SVivien Didelot static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip)
5504d5f2ba7SVivien Didelot {
5514d5f2ba7SVivien Didelot 	return chip->info->pvt;
5524d5f2ba7SVivien Didelot }
5534d5f2ba7SVivien Didelot 
5544d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip)
5554d5f2ba7SVivien Didelot {
5564d5f2ba7SVivien Didelot 	return chip->info->num_databases;
5574d5f2ba7SVivien Didelot }
5584d5f2ba7SVivien Didelot 
5594d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
5604d5f2ba7SVivien Didelot {
5614d5f2ba7SVivien Didelot 	return chip->info->num_ports;
5624d5f2ba7SVivien Didelot }
5634d5f2ba7SVivien Didelot 
5644d5f2ba7SVivien Didelot static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip)
5654d5f2ba7SVivien Didelot {
5664d5f2ba7SVivien Didelot 	return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
5674d5f2ba7SVivien Didelot }
5684d5f2ba7SVivien Didelot 
569a73ccd61SBrandon Streiff static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip)
570a73ccd61SBrandon Streiff {
571a73ccd61SBrandon Streiff 	return chip->info->num_gpio;
572a73ccd61SBrandon Streiff }
573a73ccd61SBrandon Streiff 
5744d5f2ba7SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
5754d5f2ba7SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
5764d5f2ba7SVivien Didelot int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
5774d5f2ba7SVivien Didelot 		     u16 update);
5784d5f2ba7SVivien Didelot int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
57972d8b4fdSHeiner Kallweit int mv88e6xxx_port_setup_mac(struct mv88e6xxx_chip *chip, int port, int link,
58072d8b4fdSHeiner Kallweit 			     int speed, int duplex, int pause,
58172d8b4fdSHeiner Kallweit 			     phy_interface_t mode);
5824d5f2ba7SVivien Didelot struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip);
5834d5f2ba7SVivien Didelot 
584c9acece0SRasmus Villemoes static inline void mv88e6xxx_reg_lock(struct mv88e6xxx_chip *chip)
585c9acece0SRasmus Villemoes {
586c9acece0SRasmus Villemoes 	mutex_lock(&chip->reg_lock);
587c9acece0SRasmus Villemoes }
588c9acece0SRasmus Villemoes 
589c9acece0SRasmus Villemoes static inline void mv88e6xxx_reg_unlock(struct mv88e6xxx_chip *chip)
590c9acece0SRasmus Villemoes {
591c9acece0SRasmus Villemoes 	mutex_unlock(&chip->reg_lock);
592c9acece0SRasmus Villemoes }
593c9acece0SRasmus Villemoes 
5944d5f2ba7SVivien Didelot #endif /* _MV88E6XXX_CHIP_H */
595