xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/chip.h (revision ffc705de)
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 #define SMI_CMD			0x00
254d5f2ba7SVivien Didelot #define SMI_CMD_BUSY		BIT(15)
264d5f2ba7SVivien Didelot #define SMI_CMD_CLAUSE_22	BIT(12)
274d5f2ba7SVivien Didelot #define SMI_CMD_OP_22_WRITE	((1 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22)
284d5f2ba7SVivien Didelot #define SMI_CMD_OP_22_READ	((2 << 10) | SMI_CMD_BUSY | SMI_CMD_CLAUSE_22)
294d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_WRITE_ADDR	((0 << 10) | SMI_CMD_BUSY)
304d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_WRITE_DATA	((1 << 10) | SMI_CMD_BUSY)
314d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_READ_DATA		((2 << 10) | SMI_CMD_BUSY)
324d5f2ba7SVivien Didelot #define SMI_CMD_OP_45_READ_DATA_INC	((3 << 10) | SMI_CMD_BUSY)
334d5f2ba7SVivien Didelot #define SMI_DATA		0x01
344d5f2ba7SVivien Didelot 
354d5f2ba7SVivien Didelot #define MV88E6XXX_N_FID		4096
364d5f2ba7SVivien Didelot 
374d5f2ba7SVivien Didelot /* PVT limits for 4-bit port and 5-bit switch */
384d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_SWITCHES	32
394d5f2ba7SVivien Didelot #define MV88E6XXX_MAX_PVT_PORTS		16
404d5f2ba7SVivien Didelot 
41a73ccd61SBrandon Streiff #define MV88E6XXX_MAX_GPIO	16
42a73ccd61SBrandon Streiff 
4331bef4e9SVivien Didelot enum mv88e6xxx_egress_mode {
4431bef4e9SVivien Didelot 	MV88E6XXX_EGRESS_MODE_UNMODIFIED,
4531bef4e9SVivien Didelot 	MV88E6XXX_EGRESS_MODE_UNTAGGED,
4631bef4e9SVivien Didelot 	MV88E6XXX_EGRESS_MODE_TAGGED,
4731bef4e9SVivien Didelot 	MV88E6XXX_EGRESS_MODE_ETHERTYPE,
4831bef4e9SVivien Didelot };
4931bef4e9SVivien Didelot 
504d5f2ba7SVivien Didelot enum mv88e6xxx_frame_mode {
514d5f2ba7SVivien Didelot 	MV88E6XXX_FRAME_MODE_NORMAL,
524d5f2ba7SVivien Didelot 	MV88E6XXX_FRAME_MODE_DSA,
534d5f2ba7SVivien Didelot 	MV88E6XXX_FRAME_MODE_PROVIDER,
544d5f2ba7SVivien Didelot 	MV88E6XXX_FRAME_MODE_ETHERTYPE,
554d5f2ba7SVivien Didelot };
564d5f2ba7SVivien Didelot 
574d5f2ba7SVivien Didelot /* List of supported models */
584d5f2ba7SVivien Didelot enum mv88e6xxx_model {
594d5f2ba7SVivien Didelot 	MV88E6085,
604d5f2ba7SVivien Didelot 	MV88E6095,
614d5f2ba7SVivien Didelot 	MV88E6097,
624d5f2ba7SVivien Didelot 	MV88E6123,
634d5f2ba7SVivien Didelot 	MV88E6131,
644d5f2ba7SVivien Didelot 	MV88E6141,
654d5f2ba7SVivien Didelot 	MV88E6161,
664d5f2ba7SVivien Didelot 	MV88E6165,
674d5f2ba7SVivien Didelot 	MV88E6171,
684d5f2ba7SVivien Didelot 	MV88E6172,
694d5f2ba7SVivien Didelot 	MV88E6175,
704d5f2ba7SVivien Didelot 	MV88E6176,
714d5f2ba7SVivien Didelot 	MV88E6185,
724d5f2ba7SVivien Didelot 	MV88E6190,
734d5f2ba7SVivien Didelot 	MV88E6190X,
744d5f2ba7SVivien Didelot 	MV88E6191,
754d5f2ba7SVivien Didelot 	MV88E6240,
764d5f2ba7SVivien Didelot 	MV88E6290,
774d5f2ba7SVivien Didelot 	MV88E6320,
784d5f2ba7SVivien Didelot 	MV88E6321,
794d5f2ba7SVivien Didelot 	MV88E6341,
804d5f2ba7SVivien Didelot 	MV88E6350,
814d5f2ba7SVivien Didelot 	MV88E6351,
824d5f2ba7SVivien Didelot 	MV88E6352,
834d5f2ba7SVivien Didelot 	MV88E6390,
844d5f2ba7SVivien Didelot 	MV88E6390X,
854d5f2ba7SVivien Didelot };
864d5f2ba7SVivien Didelot 
874d5f2ba7SVivien Didelot enum mv88e6xxx_family {
884d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_NONE,
894d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6065,	/* 6031 6035 6061 6065 */
904d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6095,	/* 6092 6095 */
914d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6097,	/* 6046 6085 6096 6097 */
924d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6165,	/* 6123 6161 6165 */
934d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6185,	/* 6108 6121 6122 6131 6152 6155 6182 6185 */
944d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6320,	/* 6320 6321 */
954d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6341,	/* 6141 6341 */
964d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6351,	/* 6171 6175 6350 6351 */
974d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6352,	/* 6172 6176 6240 6352 */
984d5f2ba7SVivien Didelot 	MV88E6XXX_FAMILY_6390,  /* 6190 6190X 6191 6290 6390 6390X */
994d5f2ba7SVivien Didelot };
1004d5f2ba7SVivien Didelot 
1014d5f2ba7SVivien Didelot struct mv88e6xxx_ops;
1024d5f2ba7SVivien Didelot 
1034d5f2ba7SVivien Didelot struct mv88e6xxx_info {
1044d5f2ba7SVivien Didelot 	enum mv88e6xxx_family family;
1054d5f2ba7SVivien Didelot 	u16 prod_num;
1064d5f2ba7SVivien Didelot 	const char *name;
1074d5f2ba7SVivien Didelot 	unsigned int num_databases;
1084d5f2ba7SVivien Didelot 	unsigned int num_ports;
109bc393155SAndrew Lunn 	unsigned int num_internal_phys;
110a73ccd61SBrandon Streiff 	unsigned int num_gpio;
1114d5f2ba7SVivien Didelot 	unsigned int max_vid;
1124d5f2ba7SVivien Didelot 	unsigned int port_base_addr;
1139255bacdSAndrew Lunn 	unsigned int phy_base_addr;
1144d5f2ba7SVivien Didelot 	unsigned int global1_addr;
1159069c13aSVivien Didelot 	unsigned int global2_addr;
1164d5f2ba7SVivien Didelot 	unsigned int age_time_coeff;
1174d5f2ba7SVivien Didelot 	unsigned int g1_irqs;
118d6c5e6afSVivien Didelot 	unsigned int g2_irqs;
1194d5f2ba7SVivien Didelot 	bool pvt;
120b3e05aa1SVivien Didelot 
121b3e05aa1SVivien Didelot 	/* Multi-chip Addressing Mode.
122b3e05aa1SVivien Didelot 	 * Some chips respond to only 2 registers of its own SMI device address
123b3e05aa1SVivien Didelot 	 * when it is non-zero, and use indirect access to internal registers.
124b3e05aa1SVivien Didelot 	 */
125b3e05aa1SVivien Didelot 	bool multi_chip;
1264d5f2ba7SVivien Didelot 	enum dsa_tag_protocol tag_protocol;
1274d5f2ba7SVivien Didelot 
1284d5f2ba7SVivien Didelot 	/* Mask for FromPort and ToPort value of PortVec used in ATU Move
1294d5f2ba7SVivien Didelot 	 * operation. 0 means that the ATU Move operation is not supported.
1304d5f2ba7SVivien Didelot 	 */
1314d5f2ba7SVivien Didelot 	u8 atu_move_port_mask;
1324d5f2ba7SVivien Didelot 	const struct mv88e6xxx_ops *ops;
1332fa8d3afSBrandon Streiff 
1342fa8d3afSBrandon Streiff 	/* Supports PTP */
1352fa8d3afSBrandon Streiff 	bool ptp_support;
1364d5f2ba7SVivien Didelot };
1374d5f2ba7SVivien Didelot 
1384d5f2ba7SVivien Didelot struct mv88e6xxx_atu_entry {
1394d5f2ba7SVivien Didelot 	u8	state;
1404d5f2ba7SVivien Didelot 	bool	trunk;
1414d5f2ba7SVivien Didelot 	u16	portvec;
1424d5f2ba7SVivien Didelot 	u8	mac[ETH_ALEN];
1434d5f2ba7SVivien Didelot };
1444d5f2ba7SVivien Didelot 
1454d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry {
1464d5f2ba7SVivien Didelot 	u16	vid;
1474d5f2ba7SVivien Didelot 	u16	fid;
1484d5f2ba7SVivien Didelot 	u8	sid;
1494d5f2ba7SVivien Didelot 	bool	valid;
1504d5f2ba7SVivien Didelot 	u8	member[DSA_MAX_PORTS];
1514d5f2ba7SVivien Didelot 	u8	state[DSA_MAX_PORTS];
1524d5f2ba7SVivien Didelot };
1534d5f2ba7SVivien Didelot 
1544d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops;
1554d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops;
156a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops;
1570d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops;
1586d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops;
1594d5f2ba7SVivien Didelot 
1604d5f2ba7SVivien Didelot struct mv88e6xxx_irq {
1614d5f2ba7SVivien Didelot 	u16 masked;
1624d5f2ba7SVivien Didelot 	struct irq_chip chip;
1634d5f2ba7SVivien Didelot 	struct irq_domain *domain;
1644d5f2ba7SVivien Didelot 	unsigned int nirqs;
1654d5f2ba7SVivien Didelot };
1664d5f2ba7SVivien Didelot 
167c6fe0ad2SBrandon Streiff /* state flags for mv88e6xxx_port_hwtstamp::state */
168c6fe0ad2SBrandon Streiff enum {
169c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_ENABLED,
170c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
171c6fe0ad2SBrandon Streiff };
172c6fe0ad2SBrandon Streiff 
173c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp {
174c6fe0ad2SBrandon Streiff 	/* Port index */
175c6fe0ad2SBrandon Streiff 	int port_id;
176c6fe0ad2SBrandon Streiff 
177c6fe0ad2SBrandon Streiff 	/* Timestamping state */
178c6fe0ad2SBrandon Streiff 	unsigned long state;
179c6fe0ad2SBrandon Streiff 
180c6fe0ad2SBrandon Streiff 	/* Resources for receive timestamping */
181c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue;
182c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue2;
183c6fe0ad2SBrandon Streiff 
184c6fe0ad2SBrandon Streiff 	/* Resources for transmit timestamping */
185c6fe0ad2SBrandon Streiff 	unsigned long tx_tstamp_start;
186c6fe0ad2SBrandon Streiff 	struct sk_buff *tx_skb;
187c6fe0ad2SBrandon Streiff 	u16 tx_seq_id;
188c6fe0ad2SBrandon Streiff 
189c6fe0ad2SBrandon Streiff 	/* Current timestamp configuration */
190c6fe0ad2SBrandon Streiff 	struct hwtstamp_config tstamp_config;
191c6fe0ad2SBrandon Streiff };
192c6fe0ad2SBrandon Streiff 
193cda9f4aaSAndrew Lunn struct mv88e6xxx_port {
194cda9f4aaSAndrew Lunn 	u64 serdes_stats[2];
19565f60e45SAndrew Lunn 	u64 atu_member_violation;
19665f60e45SAndrew Lunn 	u64 atu_miss_violation;
19765f60e45SAndrew Lunn 	u64 atu_full_violation;
19865f60e45SAndrew Lunn 	u64 vtu_member_violation;
19965f60e45SAndrew Lunn 	u64 vtu_miss_violation;
200cda9f4aaSAndrew Lunn };
201cda9f4aaSAndrew Lunn 
2024d5f2ba7SVivien Didelot struct mv88e6xxx_chip {
2034d5f2ba7SVivien Didelot 	const struct mv88e6xxx_info *info;
2044d5f2ba7SVivien Didelot 
2054d5f2ba7SVivien Didelot 	/* The dsa_switch this private structure is related to */
2064d5f2ba7SVivien Didelot 	struct dsa_switch *ds;
2074d5f2ba7SVivien Didelot 
2084d5f2ba7SVivien Didelot 	/* The device this structure is associated to */
2094d5f2ba7SVivien Didelot 	struct device *dev;
2104d5f2ba7SVivien Didelot 
2114d5f2ba7SVivien Didelot 	/* This mutex protects the access to the switch registers */
2124d5f2ba7SVivien Didelot 	struct mutex reg_lock;
2134d5f2ba7SVivien Didelot 
2144d5f2ba7SVivien Didelot 	/* The MII bus and the address on the bus that is used to
2154d5f2ba7SVivien Didelot 	 * communication with the switch
2164d5f2ba7SVivien Didelot 	 */
2174d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *smi_ops;
2184d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2194d5f2ba7SVivien Didelot 	int sw_addr;
2204d5f2ba7SVivien Didelot 
2214d5f2ba7SVivien Didelot 	/* Handles automatic disabling and re-enabling of the PHY
2224d5f2ba7SVivien Didelot 	 * polling unit.
2234d5f2ba7SVivien Didelot 	 */
2244d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *phy_ops;
2254d5f2ba7SVivien Didelot 	struct mutex		ppu_mutex;
2264d5f2ba7SVivien Didelot 	int			ppu_disabled;
2274d5f2ba7SVivien Didelot 	struct work_struct	ppu_work;
2284d5f2ba7SVivien Didelot 	struct timer_list	ppu_timer;
2294d5f2ba7SVivien Didelot 
2304d5f2ba7SVivien Didelot 	/* This mutex serialises access to the statistics unit.
2314d5f2ba7SVivien Didelot 	 * Hold this mutex over snapshot + dump sequences.
2324d5f2ba7SVivien Didelot 	 */
2334d5f2ba7SVivien Didelot 	struct mutex	stats_mutex;
2344d5f2ba7SVivien Didelot 
2354d5f2ba7SVivien Didelot 	/* A switch may have a GPIO line tied to its reset pin. Parse
2364d5f2ba7SVivien Didelot 	 * this from the device tree, and use it before performing
2374d5f2ba7SVivien Didelot 	 * switch soft reset.
2384d5f2ba7SVivien Didelot 	 */
2394d5f2ba7SVivien Didelot 	struct gpio_desc *reset;
2404d5f2ba7SVivien Didelot 
2414d5f2ba7SVivien Didelot 	/* set to size of eeprom if supported by the switch */
24200baabe5SAndrew Lunn 	u32 eeprom_len;
2434d5f2ba7SVivien Didelot 
2444d5f2ba7SVivien Didelot 	/* List of mdio busses */
2454d5f2ba7SVivien Didelot 	struct list_head mdios;
2464d5f2ba7SVivien Didelot 
2474d5f2ba7SVivien Didelot 	/* There can be two interrupt controllers, which are chained
2484d5f2ba7SVivien Didelot 	 * off a GPIO as interrupt source
2494d5f2ba7SVivien Didelot 	 */
2504d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g1_irq;
2514d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g2_irq;
2524d5f2ba7SVivien Didelot 	int irq;
2534d5f2ba7SVivien Didelot 	int device_irq;
2544d5f2ba7SVivien Didelot 	int watchdog_irq;
255cda9f4aaSAndrew Lunn 
2560977644cSAndrew Lunn 	int atu_prob_irq;
25762eb1162SAndrew Lunn 	int vtu_prob_irq;
258294d711eSAndrew Lunn 	struct kthread_worker *kworker;
259294d711eSAndrew Lunn 	struct kthread_delayed_work irq_poll_work;
2602fa8d3afSBrandon Streiff 
261a73ccd61SBrandon Streiff 	/* GPIO resources */
262a73ccd61SBrandon Streiff 	u8 gpio_data[2];
263a73ccd61SBrandon Streiff 
2642fa8d3afSBrandon Streiff 	/* This cyclecounter abstracts the switch PTP time.
2652fa8d3afSBrandon Streiff 	 * reg_lock must be held for any operation that read()s.
2662fa8d3afSBrandon Streiff 	 */
2672fa8d3afSBrandon Streiff 	struct cyclecounter	tstamp_cc;
2682fa8d3afSBrandon Streiff 	struct timecounter	tstamp_tc;
2692fa8d3afSBrandon Streiff 	struct delayed_work	overflow_work;
2702fa8d3afSBrandon Streiff 
2712fa8d3afSBrandon Streiff 	struct ptp_clock	*ptp_clock;
2722fa8d3afSBrandon Streiff 	struct ptp_clock_info	ptp_clock_info;
2734eb3be29SBrandon Streiff 	struct delayed_work	tai_event_work;
2744eb3be29SBrandon Streiff 	struct ptp_pin_desc	pin_config[MV88E6XXX_MAX_GPIO];
2754eb3be29SBrandon Streiff 	u16 trig_config;
2764eb3be29SBrandon Streiff 	u16 evcap_config;
277c6fe0ad2SBrandon Streiff 
278c6fe0ad2SBrandon Streiff 	/* Per-port timestamping resources. */
279c6fe0ad2SBrandon Streiff 	struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
280cda9f4aaSAndrew Lunn 
281cda9f4aaSAndrew Lunn 	/* Array of port structures. */
282cda9f4aaSAndrew Lunn 	struct mv88e6xxx_port ports[DSA_MAX_PORTS];
2834d5f2ba7SVivien Didelot };
2844d5f2ba7SVivien Didelot 
2854d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops {
2864d5f2ba7SVivien Didelot 	int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
2874d5f2ba7SVivien Didelot 	int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
2884d5f2ba7SVivien Didelot };
2894d5f2ba7SVivien Didelot 
2904d5f2ba7SVivien Didelot struct mv88e6xxx_mdio_bus {
2914d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2924d5f2ba7SVivien Didelot 	struct mv88e6xxx_chip *chip;
2934d5f2ba7SVivien Didelot 	struct list_head list;
2944d5f2ba7SVivien Didelot 	bool external;
2954d5f2ba7SVivien Didelot };
2964d5f2ba7SVivien Didelot 
2974d5f2ba7SVivien Didelot struct mv88e6xxx_ops {
29893e18d61SVivien Didelot 	int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
29993e18d61SVivien Didelot 	int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
30093e18d61SVivien Didelot 
301cd8da8bbSVivien Didelot 	/* Ingress Rate Limit unit (IRL) operations */
302cd8da8bbSVivien Didelot 	int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
303cd8da8bbSVivien Didelot 
3044d5f2ba7SVivien Didelot 	int (*get_eeprom)(struct mv88e6xxx_chip *chip,
3054d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
3064d5f2ba7SVivien Didelot 	int (*set_eeprom)(struct mv88e6xxx_chip *chip,
3074d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
3084d5f2ba7SVivien Didelot 
3094d5f2ba7SVivien Didelot 	int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr);
3104d5f2ba7SVivien Didelot 
3114d5f2ba7SVivien Didelot 	int (*phy_read)(struct mv88e6xxx_chip *chip,
3124d5f2ba7SVivien Didelot 			struct mii_bus *bus,
3134d5f2ba7SVivien Didelot 			int addr, int reg, u16 *val);
3144d5f2ba7SVivien Didelot 	int (*phy_write)(struct mv88e6xxx_chip *chip,
3154d5f2ba7SVivien Didelot 			 struct mii_bus *bus,
3164d5f2ba7SVivien Didelot 			 int addr, int reg, u16 val);
3174d5f2ba7SVivien Didelot 
3189e907d73SVivien Didelot 	/* Priority Override Table operations */
3199e907d73SVivien Didelot 	int (*pot_clear)(struct mv88e6xxx_chip *chip);
3209e907d73SVivien Didelot 
3214d5f2ba7SVivien Didelot 	/* PHY Polling Unit (PPU) operations */
3224d5f2ba7SVivien Didelot 	int (*ppu_enable)(struct mv88e6xxx_chip *chip);
3234d5f2ba7SVivien Didelot 	int (*ppu_disable)(struct mv88e6xxx_chip *chip);
3244d5f2ba7SVivien Didelot 
3254d5f2ba7SVivien Didelot 	/* Switch Software Reset */
3264d5f2ba7SVivien Didelot 	int (*reset)(struct mv88e6xxx_chip *chip);
3274d5f2ba7SVivien Didelot 
3284d5f2ba7SVivien Didelot 	/* RGMII Receive/Transmit Timing Control
3294d5f2ba7SVivien Didelot 	 * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise.
3304d5f2ba7SVivien Didelot 	 */
3314d5f2ba7SVivien Didelot 	int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port,
3324d5f2ba7SVivien Didelot 				    phy_interface_t mode);
3334d5f2ba7SVivien Didelot 
3344d5f2ba7SVivien Didelot #define LINK_FORCED_DOWN	0
3354d5f2ba7SVivien Didelot #define LINK_FORCED_UP		1
3364d5f2ba7SVivien Didelot #define LINK_UNFORCED		-2
3374d5f2ba7SVivien Didelot 
3384d5f2ba7SVivien Didelot 	/* Port's MAC link state
3394d5f2ba7SVivien Didelot 	 * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down,
3404d5f2ba7SVivien Didelot 	 * or LINK_UNFORCED for normal link detection.
3414d5f2ba7SVivien Didelot 	 */
3424d5f2ba7SVivien Didelot 	int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
3434d5f2ba7SVivien Didelot 
3444d5f2ba7SVivien Didelot #define DUPLEX_UNFORCED		-2
3454d5f2ba7SVivien Didelot 
3464d5f2ba7SVivien Didelot 	/* Port's MAC duplex mode
3474d5f2ba7SVivien Didelot 	 *
3484d5f2ba7SVivien Didelot 	 * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
3494d5f2ba7SVivien Didelot 	 * or DUPLEX_UNFORCED for normal duplex detection.
3504d5f2ba7SVivien Didelot 	 */
3514d5f2ba7SVivien Didelot 	int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
3524d5f2ba7SVivien Didelot 
3534d5f2ba7SVivien Didelot #define SPEED_MAX		INT_MAX
3544d5f2ba7SVivien Didelot #define SPEED_UNFORCED		-2
3554d5f2ba7SVivien Didelot 
3564d5f2ba7SVivien Didelot 	/* Port's MAC speed (in Mbps)
3574d5f2ba7SVivien Didelot 	 *
3584d5f2ba7SVivien Didelot 	 * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
3594d5f2ba7SVivien Didelot 	 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
3604d5f2ba7SVivien Didelot 	 */
3614d5f2ba7SVivien Didelot 	int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
3624d5f2ba7SVivien Didelot 
3634d5f2ba7SVivien Didelot 	int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
3644d5f2ba7SVivien Didelot 
3654d5f2ba7SVivien Didelot 	int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
3664d5f2ba7SVivien Didelot 				   enum mv88e6xxx_frame_mode mode);
3674d5f2ba7SVivien Didelot 	int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port,
3684d5f2ba7SVivien Didelot 				      bool unicast, bool multicast);
3694d5f2ba7SVivien Didelot 	int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
3704d5f2ba7SVivien Didelot 				   u16 etype);
371cd782656SVivien Didelot 	int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port,
372cd782656SVivien Didelot 				   size_t size);
3734d5f2ba7SVivien Didelot 
3744d5f2ba7SVivien Didelot 	int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
3750898432cSVivien Didelot 	int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in,
3760898432cSVivien Didelot 				u8 out);
3774d5f2ba7SVivien Didelot 	int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
3784d5f2ba7SVivien Didelot 	int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
3794d5f2ba7SVivien Didelot 
3804d5f2ba7SVivien Didelot 	/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
3814d5f2ba7SVivien Didelot 	 * Some chips allow this to be configured on specific ports.
3824d5f2ba7SVivien Didelot 	 */
3834d5f2ba7SVivien Didelot 	int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port,
3844d5f2ba7SVivien Didelot 			      phy_interface_t mode);
3854d5f2ba7SVivien Didelot 
3864d5f2ba7SVivien Didelot 	/* Some devices have a per port register indicating what is
3874d5f2ba7SVivien Didelot 	 * the upstream port this port should forward to.
3884d5f2ba7SVivien Didelot 	 */
3894d5f2ba7SVivien Didelot 	int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port,
3904d5f2ba7SVivien Didelot 				      int upstream_port);
3914d5f2ba7SVivien Didelot 
3924d5f2ba7SVivien Didelot 	/* Snapshot the statistics for a port. The statistics can then
3934d5f2ba7SVivien Didelot 	 * be read back a leisure but still with a consistent view.
3944d5f2ba7SVivien Didelot 	 */
3954d5f2ba7SVivien Didelot 	int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
3964d5f2ba7SVivien Didelot 
3974d5f2ba7SVivien Didelot 	/* Set the histogram mode for statistics, when the control registers
3984d5f2ba7SVivien Didelot 	 * are separated out of the STATS_OP register.
3994d5f2ba7SVivien Didelot 	 */
4004d5f2ba7SVivien Didelot 	int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
4014d5f2ba7SVivien Didelot 
4024d5f2ba7SVivien Didelot 	/* Return the number of strings describing statistics */
4034d5f2ba7SVivien Didelot 	int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
404436fe17dSAndrew Lunn 	int (*stats_get_strings)(struct mv88e6xxx_chip *chip,  uint8_t *data);
405436fe17dSAndrew Lunn 	int (*stats_get_stats)(struct mv88e6xxx_chip *chip,  int port,
4064d5f2ba7SVivien Didelot 			       uint64_t *data);
407fa8d1179SVivien Didelot 	int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
408fa8d1179SVivien Didelot 	int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
40902317e68SVivien Didelot 
41002317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_NONE		0xe
41102317e68SVivien Didelot #define MV88E6XXX_CASCADE_PORT_MULTIPLE		0xf
41202317e68SVivien Didelot 
41302317e68SVivien Didelot 	int (*set_cascade_port)(struct mv88e6xxx_chip *chip, int port);
41402317e68SVivien Didelot 
4154d5f2ba7SVivien Didelot 	const struct mv88e6xxx_irq_ops *watchdog_ops;
4164d5f2ba7SVivien Didelot 
4174d5f2ba7SVivien Didelot 	int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
4184d5f2ba7SVivien Didelot 
4194d5f2ba7SVivien Didelot 	/* Power on/off a SERDES interface */
4204d5f2ba7SVivien Didelot 	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
4214d5f2ba7SVivien Didelot 
422436fe17dSAndrew Lunn 	/* Statistics from the SERDES interface */
423436fe17dSAndrew Lunn 	int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
42465f60e45SAndrew Lunn 	int (*serdes_get_strings)(struct mv88e6xxx_chip *chip,  int port,
425436fe17dSAndrew Lunn 				  uint8_t *data);
42665f60e45SAndrew Lunn 	int (*serdes_get_stats)(struct mv88e6xxx_chip *chip,  int port,
427436fe17dSAndrew Lunn 				uint64_t *data);
428436fe17dSAndrew Lunn 
4294d5f2ba7SVivien Didelot 	/* VLAN Translation Unit operations */
4304d5f2ba7SVivien Didelot 	int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
4314d5f2ba7SVivien Didelot 			   struct mv88e6xxx_vtu_entry *entry);
4324d5f2ba7SVivien Didelot 	int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip,
4334d5f2ba7SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry);
4340d632c3dSBrandon Streiff 
435a73ccd61SBrandon Streiff 	/* GPIO operations */
436a73ccd61SBrandon Streiff 	const struct mv88e6xxx_gpio_ops *gpio_ops;
437a73ccd61SBrandon Streiff 
4380d632c3dSBrandon Streiff 	/* Interface to the AVB/PTP registers */
4390d632c3dSBrandon Streiff 	const struct mv88e6xxx_avb_ops *avb_ops;
4409e5baf9bSVivien Didelot 
4419e5baf9bSVivien Didelot 	/* Remote Management Unit operations */
4429e5baf9bSVivien Didelot 	int (*rmu_disable)(struct mv88e6xxx_chip *chip);
4436d2ac8eeSAndrew Lunn 
4446d2ac8eeSAndrew Lunn 	/* Precision Time Protocol operations */
4456d2ac8eeSAndrew Lunn 	const struct mv88e6xxx_ptp_ops *ptp_ops;
4464d5f2ba7SVivien Didelot };
4474d5f2ba7SVivien Didelot 
4484d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops {
4494d5f2ba7SVivien Didelot 	/* Action to be performed when the interrupt happens */
4504d5f2ba7SVivien Didelot 	int (*irq_action)(struct mv88e6xxx_chip *chip, int irq);
4514d5f2ba7SVivien Didelot 	/* Setup the hardware to generate the interrupt */
4524d5f2ba7SVivien Didelot 	int (*irq_setup)(struct mv88e6xxx_chip *chip);
4534d5f2ba7SVivien Didelot 	/* Reset the hardware to stop generating the interrupt */
4544d5f2ba7SVivien Didelot 	void (*irq_free)(struct mv88e6xxx_chip *chip);
4554d5f2ba7SVivien Didelot };
4564d5f2ba7SVivien Didelot 
457a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops {
458a73ccd61SBrandon Streiff 	/* Get/set data on GPIO pin */
459a73ccd61SBrandon Streiff 	int (*get_data)(struct mv88e6xxx_chip *chip, unsigned int pin);
460a73ccd61SBrandon Streiff 	int (*set_data)(struct mv88e6xxx_chip *chip, unsigned int pin,
461a73ccd61SBrandon Streiff 			int value);
462a73ccd61SBrandon Streiff 
463a73ccd61SBrandon Streiff 	/* get/set GPIO direction */
464a73ccd61SBrandon Streiff 	int (*get_dir)(struct mv88e6xxx_chip *chip, unsigned int pin);
465a73ccd61SBrandon Streiff 	int (*set_dir)(struct mv88e6xxx_chip *chip, unsigned int pin,
466a73ccd61SBrandon Streiff 		       bool input);
467a73ccd61SBrandon Streiff 
468a73ccd61SBrandon Streiff 	/* get/set GPIO pin control */
469a73ccd61SBrandon Streiff 	int (*get_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
470a73ccd61SBrandon Streiff 			int *func);
471a73ccd61SBrandon Streiff 	int (*set_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
472a73ccd61SBrandon Streiff 			int func);
473a73ccd61SBrandon Streiff };
474a73ccd61SBrandon Streiff 
4750d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops {
4760d632c3dSBrandon Streiff 	/* Access port-scoped Precision Time Protocol registers */
4770d632c3dSBrandon Streiff 	int (*port_ptp_read)(struct mv88e6xxx_chip *chip, int port, int addr,
4780d632c3dSBrandon Streiff 			     u16 *data, int len);
4790d632c3dSBrandon Streiff 	int (*port_ptp_write)(struct mv88e6xxx_chip *chip, int port, int addr,
4800d632c3dSBrandon Streiff 			      u16 data);
4810d632c3dSBrandon Streiff 
4820d632c3dSBrandon Streiff 	/* Access global Precision Time Protocol registers */
4830d632c3dSBrandon Streiff 	int (*ptp_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
4840d632c3dSBrandon Streiff 			int len);
4850d632c3dSBrandon Streiff 	int (*ptp_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
4860d632c3dSBrandon Streiff 
4870d632c3dSBrandon Streiff 	/* Access global Time Application Interface registers */
4880d632c3dSBrandon Streiff 	int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
4890d632c3dSBrandon Streiff 			int len);
4900d632c3dSBrandon Streiff 	int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
4910d632c3dSBrandon Streiff };
4920d632c3dSBrandon Streiff 
4936d2ac8eeSAndrew Lunn struct mv88e6xxx_ptp_ops {
4946d2ac8eeSAndrew Lunn 	u64 (*clock_read)(const struct cyclecounter *cc);
4956d2ac8eeSAndrew Lunn 	int (*ptp_enable)(struct ptp_clock_info *ptp,
4966d2ac8eeSAndrew Lunn 			  struct ptp_clock_request *rq, int on);
4976d2ac8eeSAndrew Lunn 	int (*ptp_verify)(struct ptp_clock_info *ptp, unsigned int pin,
4986d2ac8eeSAndrew Lunn 			  enum ptp_pin_function func, unsigned int chan);
4996d2ac8eeSAndrew Lunn 	void (*event_work)(struct work_struct *ugly);
500ffc705deSAndrew Lunn 	int (*port_enable)(struct mv88e6xxx_chip *chip, int port);
501ffc705deSAndrew Lunn 	int (*port_disable)(struct mv88e6xxx_chip *chip, int port);
5026d2ac8eeSAndrew Lunn 	int n_ext_ts;
503ffc705deSAndrew Lunn 	int arr0_sts_reg;
504ffc705deSAndrew Lunn 	int arr1_sts_reg;
505ffc705deSAndrew Lunn 	int dep_sts_reg;
5066d2ac8eeSAndrew Lunn };
5076d2ac8eeSAndrew Lunn 
5084d5f2ba7SVivien Didelot #define STATS_TYPE_PORT		BIT(0)
5094d5f2ba7SVivien Didelot #define STATS_TYPE_BANK0	BIT(1)
5104d5f2ba7SVivien Didelot #define STATS_TYPE_BANK1	BIT(2)
5114d5f2ba7SVivien Didelot 
5124d5f2ba7SVivien Didelot struct mv88e6xxx_hw_stat {
5134d5f2ba7SVivien Didelot 	char string[ETH_GSTRING_LEN];
514cda9f4aaSAndrew Lunn 	size_t size;
5154d5f2ba7SVivien Didelot 	int reg;
5164d5f2ba7SVivien Didelot 	int type;
5174d5f2ba7SVivien Didelot };
5184d5f2ba7SVivien Didelot 
5194d5f2ba7SVivien Didelot static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip)
5204d5f2ba7SVivien Didelot {
5214d5f2ba7SVivien Didelot 	return chip->info->pvt;
5224d5f2ba7SVivien Didelot }
5234d5f2ba7SVivien Didelot 
5244d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip)
5254d5f2ba7SVivien Didelot {
5264d5f2ba7SVivien Didelot 	return chip->info->num_databases;
5274d5f2ba7SVivien Didelot }
5284d5f2ba7SVivien Didelot 
5294d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
5304d5f2ba7SVivien Didelot {
5314d5f2ba7SVivien Didelot 	return chip->info->num_ports;
5324d5f2ba7SVivien Didelot }
5334d5f2ba7SVivien Didelot 
5344d5f2ba7SVivien Didelot static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip)
5354d5f2ba7SVivien Didelot {
5364d5f2ba7SVivien Didelot 	return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
5374d5f2ba7SVivien Didelot }
5384d5f2ba7SVivien Didelot 
539a73ccd61SBrandon Streiff static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip)
540a73ccd61SBrandon Streiff {
541a73ccd61SBrandon Streiff 	return chip->info->num_gpio;
542a73ccd61SBrandon Streiff }
543a73ccd61SBrandon Streiff 
5444d5f2ba7SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
5454d5f2ba7SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
5464d5f2ba7SVivien Didelot int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
5474d5f2ba7SVivien Didelot 		     u16 update);
5484d5f2ba7SVivien Didelot int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
5494d5f2ba7SVivien Didelot struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip);
5504d5f2ba7SVivien Didelot 
5514d5f2ba7SVivien Didelot #endif /* _MV88E6XXX_CHIP_H */
552