xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/chip.h (revision 436fe17d)
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;
113a73ccd61SBrandon Streiff 	unsigned int num_gpio;
1144d5f2ba7SVivien Didelot 	unsigned int max_vid;
1154d5f2ba7SVivien Didelot 	unsigned int port_base_addr;
1164d5f2ba7SVivien Didelot 	unsigned int global1_addr;
1179069c13aSVivien Didelot 	unsigned int global2_addr;
1184d5f2ba7SVivien Didelot 	unsigned int age_time_coeff;
1194d5f2ba7SVivien Didelot 	unsigned int g1_irqs;
120d6c5e6afSVivien Didelot 	unsigned int g2_irqs;
1214d5f2ba7SVivien Didelot 	bool pvt;
122b3e05aa1SVivien Didelot 
123b3e05aa1SVivien Didelot 	/* Multi-chip Addressing Mode.
124b3e05aa1SVivien Didelot 	 * Some chips respond to only 2 registers of its own SMI device address
125b3e05aa1SVivien Didelot 	 * when it is non-zero, and use indirect access to internal registers.
126b3e05aa1SVivien Didelot 	 */
127b3e05aa1SVivien Didelot 	bool multi_chip;
1284d5f2ba7SVivien Didelot 	enum dsa_tag_protocol tag_protocol;
1294d5f2ba7SVivien Didelot 
1304d5f2ba7SVivien Didelot 	/* Mask for FromPort and ToPort value of PortVec used in ATU Move
1314d5f2ba7SVivien Didelot 	 * operation. 0 means that the ATU Move operation is not supported.
1324d5f2ba7SVivien Didelot 	 */
1334d5f2ba7SVivien Didelot 	u8 atu_move_port_mask;
1344d5f2ba7SVivien Didelot 	const struct mv88e6xxx_ops *ops;
1352fa8d3afSBrandon Streiff 
1362fa8d3afSBrandon Streiff 	/* Supports PTP */
1372fa8d3afSBrandon Streiff 	bool ptp_support;
1384d5f2ba7SVivien Didelot };
1394d5f2ba7SVivien Didelot 
1404d5f2ba7SVivien Didelot struct mv88e6xxx_atu_entry {
1414d5f2ba7SVivien Didelot 	u8	state;
1424d5f2ba7SVivien Didelot 	bool	trunk;
1434d5f2ba7SVivien Didelot 	u16	portvec;
1444d5f2ba7SVivien Didelot 	u8	mac[ETH_ALEN];
1454d5f2ba7SVivien Didelot };
1464d5f2ba7SVivien Didelot 
1474d5f2ba7SVivien Didelot struct mv88e6xxx_vtu_entry {
1484d5f2ba7SVivien Didelot 	u16	vid;
1494d5f2ba7SVivien Didelot 	u16	fid;
1504d5f2ba7SVivien Didelot 	u8	sid;
1514d5f2ba7SVivien Didelot 	bool	valid;
1524d5f2ba7SVivien Didelot 	u8	member[DSA_MAX_PORTS];
1534d5f2ba7SVivien Didelot 	u8	state[DSA_MAX_PORTS];
1544d5f2ba7SVivien Didelot };
1554d5f2ba7SVivien Didelot 
1564d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops;
1574d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops;
158a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops;
1590d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops;
1604d5f2ba7SVivien Didelot 
1614d5f2ba7SVivien Didelot struct mv88e6xxx_irq {
1624d5f2ba7SVivien Didelot 	u16 masked;
1634d5f2ba7SVivien Didelot 	struct irq_chip chip;
1644d5f2ba7SVivien Didelot 	struct irq_domain *domain;
1654d5f2ba7SVivien Didelot 	unsigned int nirqs;
1664d5f2ba7SVivien Didelot };
1674d5f2ba7SVivien Didelot 
168c6fe0ad2SBrandon Streiff /* state flags for mv88e6xxx_port_hwtstamp::state */
169c6fe0ad2SBrandon Streiff enum {
170c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_ENABLED,
171c6fe0ad2SBrandon Streiff 	MV88E6XXX_HWTSTAMP_TX_IN_PROGRESS,
172c6fe0ad2SBrandon Streiff };
173c6fe0ad2SBrandon Streiff 
174c6fe0ad2SBrandon Streiff struct mv88e6xxx_port_hwtstamp {
175c6fe0ad2SBrandon Streiff 	/* Port index */
176c6fe0ad2SBrandon Streiff 	int port_id;
177c6fe0ad2SBrandon Streiff 
178c6fe0ad2SBrandon Streiff 	/* Timestamping state */
179c6fe0ad2SBrandon Streiff 	unsigned long state;
180c6fe0ad2SBrandon Streiff 
181c6fe0ad2SBrandon Streiff 	/* Resources for receive timestamping */
182c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue;
183c6fe0ad2SBrandon Streiff 	struct sk_buff_head rx_queue2;
184c6fe0ad2SBrandon Streiff 
185c6fe0ad2SBrandon Streiff 	/* Resources for transmit timestamping */
186c6fe0ad2SBrandon Streiff 	unsigned long tx_tstamp_start;
187c6fe0ad2SBrandon Streiff 	struct sk_buff *tx_skb;
188c6fe0ad2SBrandon Streiff 	u16 tx_seq_id;
189c6fe0ad2SBrandon Streiff 
190c6fe0ad2SBrandon Streiff 	/* Current timestamp configuration */
191c6fe0ad2SBrandon Streiff 	struct hwtstamp_config tstamp_config;
192c6fe0ad2SBrandon Streiff };
193c6fe0ad2SBrandon Streiff 
1944d5f2ba7SVivien Didelot struct mv88e6xxx_chip {
1954d5f2ba7SVivien Didelot 	const struct mv88e6xxx_info *info;
1964d5f2ba7SVivien Didelot 
1974d5f2ba7SVivien Didelot 	/* The dsa_switch this private structure is related to */
1984d5f2ba7SVivien Didelot 	struct dsa_switch *ds;
1994d5f2ba7SVivien Didelot 
2004d5f2ba7SVivien Didelot 	/* The device this structure is associated to */
2014d5f2ba7SVivien Didelot 	struct device *dev;
2024d5f2ba7SVivien Didelot 
2034d5f2ba7SVivien Didelot 	/* This mutex protects the access to the switch registers */
2044d5f2ba7SVivien Didelot 	struct mutex reg_lock;
2054d5f2ba7SVivien Didelot 
2064d5f2ba7SVivien Didelot 	/* The MII bus and the address on the bus that is used to
2074d5f2ba7SVivien Didelot 	 * communication with the switch
2084d5f2ba7SVivien Didelot 	 */
2094d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *smi_ops;
2104d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2114d5f2ba7SVivien Didelot 	int sw_addr;
2124d5f2ba7SVivien Didelot 
2134d5f2ba7SVivien Didelot 	/* Handles automatic disabling and re-enabling of the PHY
2144d5f2ba7SVivien Didelot 	 * polling unit.
2154d5f2ba7SVivien Didelot 	 */
2164d5f2ba7SVivien Didelot 	const struct mv88e6xxx_bus_ops *phy_ops;
2174d5f2ba7SVivien Didelot 	struct mutex		ppu_mutex;
2184d5f2ba7SVivien Didelot 	int			ppu_disabled;
2194d5f2ba7SVivien Didelot 	struct work_struct	ppu_work;
2204d5f2ba7SVivien Didelot 	struct timer_list	ppu_timer;
2214d5f2ba7SVivien Didelot 
2224d5f2ba7SVivien Didelot 	/* This mutex serialises access to the statistics unit.
2234d5f2ba7SVivien Didelot 	 * Hold this mutex over snapshot + dump sequences.
2244d5f2ba7SVivien Didelot 	 */
2254d5f2ba7SVivien Didelot 	struct mutex	stats_mutex;
2264d5f2ba7SVivien Didelot 
2274d5f2ba7SVivien Didelot 	/* A switch may have a GPIO line tied to its reset pin. Parse
2284d5f2ba7SVivien Didelot 	 * this from the device tree, and use it before performing
2294d5f2ba7SVivien Didelot 	 * switch soft reset.
2304d5f2ba7SVivien Didelot 	 */
2314d5f2ba7SVivien Didelot 	struct gpio_desc *reset;
2324d5f2ba7SVivien Didelot 
2334d5f2ba7SVivien Didelot 	/* set to size of eeprom if supported by the switch */
2344d5f2ba7SVivien Didelot 	int		eeprom_len;
2354d5f2ba7SVivien Didelot 
2364d5f2ba7SVivien Didelot 	/* List of mdio busses */
2374d5f2ba7SVivien Didelot 	struct list_head mdios;
2384d5f2ba7SVivien Didelot 
2394d5f2ba7SVivien Didelot 	/* There can be two interrupt controllers, which are chained
2404d5f2ba7SVivien Didelot 	 * off a GPIO as interrupt source
2414d5f2ba7SVivien Didelot 	 */
2424d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g1_irq;
2434d5f2ba7SVivien Didelot 	struct mv88e6xxx_irq g2_irq;
2444d5f2ba7SVivien Didelot 	int irq;
2454d5f2ba7SVivien Didelot 	int device_irq;
2464d5f2ba7SVivien Didelot 	int watchdog_irq;
2470977644cSAndrew Lunn 	int atu_prob_irq;
24862eb1162SAndrew Lunn 	int vtu_prob_irq;
249294d711eSAndrew Lunn 	struct kthread_worker *kworker;
250294d711eSAndrew Lunn 	struct kthread_delayed_work irq_poll_work;
2512fa8d3afSBrandon Streiff 
252a73ccd61SBrandon Streiff 	/* GPIO resources */
253a73ccd61SBrandon Streiff 	u8 gpio_data[2];
254a73ccd61SBrandon Streiff 
2552fa8d3afSBrandon Streiff 	/* This cyclecounter abstracts the switch PTP time.
2562fa8d3afSBrandon Streiff 	 * reg_lock must be held for any operation that read()s.
2572fa8d3afSBrandon Streiff 	 */
2582fa8d3afSBrandon Streiff 	struct cyclecounter	tstamp_cc;
2592fa8d3afSBrandon Streiff 	struct timecounter	tstamp_tc;
2602fa8d3afSBrandon Streiff 	struct delayed_work	overflow_work;
2612fa8d3afSBrandon Streiff 
2622fa8d3afSBrandon Streiff 	struct ptp_clock	*ptp_clock;
2632fa8d3afSBrandon Streiff 	struct ptp_clock_info	ptp_clock_info;
2644eb3be29SBrandon Streiff 	struct delayed_work	tai_event_work;
2654eb3be29SBrandon Streiff 	struct ptp_pin_desc	pin_config[MV88E6XXX_MAX_GPIO];
2664eb3be29SBrandon Streiff 	u16 trig_config;
2674eb3be29SBrandon Streiff 	u16 evcap_config;
268c6fe0ad2SBrandon Streiff 
269c6fe0ad2SBrandon Streiff 	/* Per-port timestamping resources. */
270c6fe0ad2SBrandon Streiff 	struct mv88e6xxx_port_hwtstamp port_hwtstamp[DSA_MAX_PORTS];
2714d5f2ba7SVivien Didelot };
2724d5f2ba7SVivien Didelot 
2734d5f2ba7SVivien Didelot struct mv88e6xxx_bus_ops {
2744d5f2ba7SVivien Didelot 	int (*read)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
2754d5f2ba7SVivien Didelot 	int (*write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
2764d5f2ba7SVivien Didelot };
2774d5f2ba7SVivien Didelot 
2784d5f2ba7SVivien Didelot struct mv88e6xxx_mdio_bus {
2794d5f2ba7SVivien Didelot 	struct mii_bus *bus;
2804d5f2ba7SVivien Didelot 	struct mv88e6xxx_chip *chip;
2814d5f2ba7SVivien Didelot 	struct list_head list;
2824d5f2ba7SVivien Didelot 	bool external;
2834d5f2ba7SVivien Didelot };
2844d5f2ba7SVivien Didelot 
2854d5f2ba7SVivien Didelot struct mv88e6xxx_ops {
286cd8da8bbSVivien Didelot 	/* Ingress Rate Limit unit (IRL) operations */
287cd8da8bbSVivien Didelot 	int (*irl_init_all)(struct mv88e6xxx_chip *chip, int port);
288cd8da8bbSVivien Didelot 
2894d5f2ba7SVivien Didelot 	int (*get_eeprom)(struct mv88e6xxx_chip *chip,
2904d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
2914d5f2ba7SVivien Didelot 	int (*set_eeprom)(struct mv88e6xxx_chip *chip,
2924d5f2ba7SVivien Didelot 			  struct ethtool_eeprom *eeprom, u8 *data);
2934d5f2ba7SVivien Didelot 
2944d5f2ba7SVivien Didelot 	int (*set_switch_mac)(struct mv88e6xxx_chip *chip, u8 *addr);
2954d5f2ba7SVivien Didelot 
2964d5f2ba7SVivien Didelot 	int (*phy_read)(struct mv88e6xxx_chip *chip,
2974d5f2ba7SVivien Didelot 			struct mii_bus *bus,
2984d5f2ba7SVivien Didelot 			int addr, int reg, u16 *val);
2994d5f2ba7SVivien Didelot 	int (*phy_write)(struct mv88e6xxx_chip *chip,
3004d5f2ba7SVivien Didelot 			 struct mii_bus *bus,
3014d5f2ba7SVivien Didelot 			 int addr, int reg, u16 val);
3024d5f2ba7SVivien Didelot 
3039e907d73SVivien Didelot 	/* Priority Override Table operations */
3049e907d73SVivien Didelot 	int (*pot_clear)(struct mv88e6xxx_chip *chip);
3059e907d73SVivien Didelot 
3064d5f2ba7SVivien Didelot 	/* PHY Polling Unit (PPU) operations */
3074d5f2ba7SVivien Didelot 	int (*ppu_enable)(struct mv88e6xxx_chip *chip);
3084d5f2ba7SVivien Didelot 	int (*ppu_disable)(struct mv88e6xxx_chip *chip);
3094d5f2ba7SVivien Didelot 
3104d5f2ba7SVivien Didelot 	/* Switch Software Reset */
3114d5f2ba7SVivien Didelot 	int (*reset)(struct mv88e6xxx_chip *chip);
3124d5f2ba7SVivien Didelot 
3134d5f2ba7SVivien Didelot 	/* RGMII Receive/Transmit Timing Control
3144d5f2ba7SVivien Didelot 	 * Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise.
3154d5f2ba7SVivien Didelot 	 */
3164d5f2ba7SVivien Didelot 	int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port,
3174d5f2ba7SVivien Didelot 				    phy_interface_t mode);
3184d5f2ba7SVivien Didelot 
3194d5f2ba7SVivien Didelot #define LINK_FORCED_DOWN	0
3204d5f2ba7SVivien Didelot #define LINK_FORCED_UP		1
3214d5f2ba7SVivien Didelot #define LINK_UNFORCED		-2
3224d5f2ba7SVivien Didelot 
3234d5f2ba7SVivien Didelot 	/* Port's MAC link state
3244d5f2ba7SVivien Didelot 	 * Use LINK_FORCED_UP or LINK_FORCED_DOWN to force link up or down,
3254d5f2ba7SVivien Didelot 	 * or LINK_UNFORCED for normal link detection.
3264d5f2ba7SVivien Didelot 	 */
3274d5f2ba7SVivien Didelot 	int (*port_set_link)(struct mv88e6xxx_chip *chip, int port, int link);
3284d5f2ba7SVivien Didelot 
3294d5f2ba7SVivien Didelot #define DUPLEX_UNFORCED		-2
3304d5f2ba7SVivien Didelot 
3314d5f2ba7SVivien Didelot 	/* Port's MAC duplex mode
3324d5f2ba7SVivien Didelot 	 *
3334d5f2ba7SVivien Didelot 	 * Use DUPLEX_HALF or DUPLEX_FULL to force half or full duplex,
3344d5f2ba7SVivien Didelot 	 * or DUPLEX_UNFORCED for normal duplex detection.
3354d5f2ba7SVivien Didelot 	 */
3364d5f2ba7SVivien Didelot 	int (*port_set_duplex)(struct mv88e6xxx_chip *chip, int port, int dup);
3374d5f2ba7SVivien Didelot 
3384d5f2ba7SVivien Didelot #define SPEED_MAX		INT_MAX
3394d5f2ba7SVivien Didelot #define SPEED_UNFORCED		-2
3404d5f2ba7SVivien Didelot 
3414d5f2ba7SVivien Didelot 	/* Port's MAC speed (in Mbps)
3424d5f2ba7SVivien Didelot 	 *
3434d5f2ba7SVivien Didelot 	 * Depending on the chip, 10, 100, 200, 1000, 2500, 10000 are valid.
3444d5f2ba7SVivien Didelot 	 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
3454d5f2ba7SVivien Didelot 	 */
3464d5f2ba7SVivien Didelot 	int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
3474d5f2ba7SVivien Didelot 
3484d5f2ba7SVivien Didelot 	int (*port_tag_remap)(struct mv88e6xxx_chip *chip, int port);
3494d5f2ba7SVivien Didelot 
3504d5f2ba7SVivien Didelot 	int (*port_set_frame_mode)(struct mv88e6xxx_chip *chip, int port,
3514d5f2ba7SVivien Didelot 				   enum mv88e6xxx_frame_mode mode);
3524d5f2ba7SVivien Didelot 	int (*port_set_egress_floods)(struct mv88e6xxx_chip *chip, int port,
3534d5f2ba7SVivien Didelot 				      bool unicast, bool multicast);
3544d5f2ba7SVivien Didelot 	int (*port_set_ether_type)(struct mv88e6xxx_chip *chip, int port,
3554d5f2ba7SVivien Didelot 				   u16 etype);
356cd782656SVivien Didelot 	int (*port_set_jumbo_size)(struct mv88e6xxx_chip *chip, int port,
357cd782656SVivien Didelot 				   size_t size);
3584d5f2ba7SVivien Didelot 
3594d5f2ba7SVivien Didelot 	int (*port_egress_rate_limiting)(struct mv88e6xxx_chip *chip, int port);
3600898432cSVivien Didelot 	int (*port_pause_limit)(struct mv88e6xxx_chip *chip, int port, u8 in,
3610898432cSVivien Didelot 				u8 out);
3624d5f2ba7SVivien Didelot 	int (*port_disable_learn_limit)(struct mv88e6xxx_chip *chip, int port);
3634d5f2ba7SVivien Didelot 	int (*port_disable_pri_override)(struct mv88e6xxx_chip *chip, int port);
3644d5f2ba7SVivien Didelot 
3654d5f2ba7SVivien Didelot 	/* CMODE control what PHY mode the MAC will use, eg. SGMII, RGMII, etc.
3664d5f2ba7SVivien Didelot 	 * Some chips allow this to be configured on specific ports.
3674d5f2ba7SVivien Didelot 	 */
3684d5f2ba7SVivien Didelot 	int (*port_set_cmode)(struct mv88e6xxx_chip *chip, int port,
3694d5f2ba7SVivien Didelot 			      phy_interface_t mode);
3704d5f2ba7SVivien Didelot 
3714d5f2ba7SVivien Didelot 	/* Some devices have a per port register indicating what is
3724d5f2ba7SVivien Didelot 	 * the upstream port this port should forward to.
3734d5f2ba7SVivien Didelot 	 */
3744d5f2ba7SVivien Didelot 	int (*port_set_upstream_port)(struct mv88e6xxx_chip *chip, int port,
3754d5f2ba7SVivien Didelot 				      int upstream_port);
3764d5f2ba7SVivien Didelot 
3774d5f2ba7SVivien Didelot 	/* Snapshot the statistics for a port. The statistics can then
3784d5f2ba7SVivien Didelot 	 * be read back a leisure but still with a consistent view.
3794d5f2ba7SVivien Didelot 	 */
3804d5f2ba7SVivien Didelot 	int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
3814d5f2ba7SVivien Didelot 
3824d5f2ba7SVivien Didelot 	/* Set the histogram mode for statistics, when the control registers
3834d5f2ba7SVivien Didelot 	 * are separated out of the STATS_OP register.
3844d5f2ba7SVivien Didelot 	 */
3854d5f2ba7SVivien Didelot 	int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
3864d5f2ba7SVivien Didelot 
3874d5f2ba7SVivien Didelot 	/* Return the number of strings describing statistics */
3884d5f2ba7SVivien Didelot 	int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
389436fe17dSAndrew Lunn 	int (*stats_get_strings)(struct mv88e6xxx_chip *chip,  uint8_t *data);
390436fe17dSAndrew Lunn 	int (*stats_get_stats)(struct mv88e6xxx_chip *chip,  int port,
3914d5f2ba7SVivien Didelot 			       uint64_t *data);
392fa8d1179SVivien Didelot 	int (*set_cpu_port)(struct mv88e6xxx_chip *chip, int port);
393fa8d1179SVivien Didelot 	int (*set_egress_port)(struct mv88e6xxx_chip *chip, int port);
3944d5f2ba7SVivien Didelot 	const struct mv88e6xxx_irq_ops *watchdog_ops;
3954d5f2ba7SVivien Didelot 
3964d5f2ba7SVivien Didelot 	int (*mgmt_rsvd2cpu)(struct mv88e6xxx_chip *chip);
3974d5f2ba7SVivien Didelot 
3984d5f2ba7SVivien Didelot 	/* Power on/off a SERDES interface */
3994d5f2ba7SVivien Didelot 	int (*serdes_power)(struct mv88e6xxx_chip *chip, int port, bool on);
4004d5f2ba7SVivien Didelot 
401436fe17dSAndrew Lunn 	/* Statistics from the SERDES interface */
402436fe17dSAndrew Lunn 	int (*serdes_get_sset_count)(struct mv88e6xxx_chip *chip, int port);
403436fe17dSAndrew Lunn 	void (*serdes_get_strings)(struct mv88e6xxx_chip *chip,  int port,
404436fe17dSAndrew Lunn 				   uint8_t *data);
405436fe17dSAndrew Lunn 	void (*serdes_get_stats)(struct mv88e6xxx_chip *chip,  int port,
406436fe17dSAndrew Lunn 				 uint64_t *data);
407436fe17dSAndrew Lunn 
4084d5f2ba7SVivien Didelot 	/* VLAN Translation Unit operations */
4094d5f2ba7SVivien Didelot 	int (*vtu_getnext)(struct mv88e6xxx_chip *chip,
4104d5f2ba7SVivien Didelot 			   struct mv88e6xxx_vtu_entry *entry);
4114d5f2ba7SVivien Didelot 	int (*vtu_loadpurge)(struct mv88e6xxx_chip *chip,
4124d5f2ba7SVivien Didelot 			     struct mv88e6xxx_vtu_entry *entry);
4130d632c3dSBrandon Streiff 
414a73ccd61SBrandon Streiff 	/* GPIO operations */
415a73ccd61SBrandon Streiff 	const struct mv88e6xxx_gpio_ops *gpio_ops;
416a73ccd61SBrandon Streiff 
4170d632c3dSBrandon Streiff 	/* Interface to the AVB/PTP registers */
4180d632c3dSBrandon Streiff 	const struct mv88e6xxx_avb_ops *avb_ops;
4194d5f2ba7SVivien Didelot };
4204d5f2ba7SVivien Didelot 
4214d5f2ba7SVivien Didelot struct mv88e6xxx_irq_ops {
4224d5f2ba7SVivien Didelot 	/* Action to be performed when the interrupt happens */
4234d5f2ba7SVivien Didelot 	int (*irq_action)(struct mv88e6xxx_chip *chip, int irq);
4244d5f2ba7SVivien Didelot 	/* Setup the hardware to generate the interrupt */
4254d5f2ba7SVivien Didelot 	int (*irq_setup)(struct mv88e6xxx_chip *chip);
4264d5f2ba7SVivien Didelot 	/* Reset the hardware to stop generating the interrupt */
4274d5f2ba7SVivien Didelot 	void (*irq_free)(struct mv88e6xxx_chip *chip);
4284d5f2ba7SVivien Didelot };
4294d5f2ba7SVivien Didelot 
430a73ccd61SBrandon Streiff struct mv88e6xxx_gpio_ops {
431a73ccd61SBrandon Streiff 	/* Get/set data on GPIO pin */
432a73ccd61SBrandon Streiff 	int (*get_data)(struct mv88e6xxx_chip *chip, unsigned int pin);
433a73ccd61SBrandon Streiff 	int (*set_data)(struct mv88e6xxx_chip *chip, unsigned int pin,
434a73ccd61SBrandon Streiff 			int value);
435a73ccd61SBrandon Streiff 
436a73ccd61SBrandon Streiff 	/* get/set GPIO direction */
437a73ccd61SBrandon Streiff 	int (*get_dir)(struct mv88e6xxx_chip *chip, unsigned int pin);
438a73ccd61SBrandon Streiff 	int (*set_dir)(struct mv88e6xxx_chip *chip, unsigned int pin,
439a73ccd61SBrandon Streiff 		       bool input);
440a73ccd61SBrandon Streiff 
441a73ccd61SBrandon Streiff 	/* get/set GPIO pin control */
442a73ccd61SBrandon Streiff 	int (*get_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
443a73ccd61SBrandon Streiff 			int *func);
444a73ccd61SBrandon Streiff 	int (*set_pctl)(struct mv88e6xxx_chip *chip, unsigned int pin,
445a73ccd61SBrandon Streiff 			int func);
446a73ccd61SBrandon Streiff };
447a73ccd61SBrandon Streiff 
4480d632c3dSBrandon Streiff struct mv88e6xxx_avb_ops {
4490d632c3dSBrandon Streiff 	/* Access port-scoped Precision Time Protocol registers */
4500d632c3dSBrandon Streiff 	int (*port_ptp_read)(struct mv88e6xxx_chip *chip, int port, int addr,
4510d632c3dSBrandon Streiff 			     u16 *data, int len);
4520d632c3dSBrandon Streiff 	int (*port_ptp_write)(struct mv88e6xxx_chip *chip, int port, int addr,
4530d632c3dSBrandon Streiff 			      u16 data);
4540d632c3dSBrandon Streiff 
4550d632c3dSBrandon Streiff 	/* Access global Precision Time Protocol registers */
4560d632c3dSBrandon Streiff 	int (*ptp_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
4570d632c3dSBrandon Streiff 			int len);
4580d632c3dSBrandon Streiff 	int (*ptp_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
4590d632c3dSBrandon Streiff 
4600d632c3dSBrandon Streiff 	/* Access global Time Application Interface registers */
4610d632c3dSBrandon Streiff 	int (*tai_read)(struct mv88e6xxx_chip *chip, int addr, u16 *data,
4620d632c3dSBrandon Streiff 			int len);
4630d632c3dSBrandon Streiff 	int (*tai_write)(struct mv88e6xxx_chip *chip, int addr, u16 data);
4640d632c3dSBrandon Streiff };
4650d632c3dSBrandon Streiff 
4664d5f2ba7SVivien Didelot #define STATS_TYPE_PORT		BIT(0)
4674d5f2ba7SVivien Didelot #define STATS_TYPE_BANK0	BIT(1)
4684d5f2ba7SVivien Didelot #define STATS_TYPE_BANK1	BIT(2)
4694d5f2ba7SVivien Didelot 
4704d5f2ba7SVivien Didelot struct mv88e6xxx_hw_stat {
4714d5f2ba7SVivien Didelot 	char string[ETH_GSTRING_LEN];
4724d5f2ba7SVivien Didelot 	int sizeof_stat;
4734d5f2ba7SVivien Didelot 	int reg;
4744d5f2ba7SVivien Didelot 	int type;
4754d5f2ba7SVivien Didelot };
4764d5f2ba7SVivien Didelot 
4774d5f2ba7SVivien Didelot static inline bool mv88e6xxx_has_pvt(struct mv88e6xxx_chip *chip)
4784d5f2ba7SVivien Didelot {
4794d5f2ba7SVivien Didelot 	return chip->info->pvt;
4804d5f2ba7SVivien Didelot }
4814d5f2ba7SVivien Didelot 
4824d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_databases(struct mv88e6xxx_chip *chip)
4834d5f2ba7SVivien Didelot {
4844d5f2ba7SVivien Didelot 	return chip->info->num_databases;
4854d5f2ba7SVivien Didelot }
4864d5f2ba7SVivien Didelot 
4874d5f2ba7SVivien Didelot static inline unsigned int mv88e6xxx_num_ports(struct mv88e6xxx_chip *chip)
4884d5f2ba7SVivien Didelot {
4894d5f2ba7SVivien Didelot 	return chip->info->num_ports;
4904d5f2ba7SVivien Didelot }
4914d5f2ba7SVivien Didelot 
4924d5f2ba7SVivien Didelot static inline u16 mv88e6xxx_port_mask(struct mv88e6xxx_chip *chip)
4934d5f2ba7SVivien Didelot {
4944d5f2ba7SVivien Didelot 	return GENMASK(mv88e6xxx_num_ports(chip) - 1, 0);
4954d5f2ba7SVivien Didelot }
4964d5f2ba7SVivien Didelot 
497a73ccd61SBrandon Streiff static inline unsigned int mv88e6xxx_num_gpio(struct mv88e6xxx_chip *chip)
498a73ccd61SBrandon Streiff {
499a73ccd61SBrandon Streiff 	return chip->info->num_gpio;
500a73ccd61SBrandon Streiff }
501a73ccd61SBrandon Streiff 
5024d5f2ba7SVivien Didelot int mv88e6xxx_read(struct mv88e6xxx_chip *chip, int addr, int reg, u16 *val);
5034d5f2ba7SVivien Didelot int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val);
5044d5f2ba7SVivien Didelot int mv88e6xxx_update(struct mv88e6xxx_chip *chip, int addr, int reg,
5054d5f2ba7SVivien Didelot 		     u16 update);
5064d5f2ba7SVivien Didelot int mv88e6xxx_wait(struct mv88e6xxx_chip *chip, int addr, int reg, u16 mask);
5074d5f2ba7SVivien Didelot struct mii_bus *mv88e6xxx_default_mdio_bus(struct mv88e6xxx_chip *chip);
5084d5f2ba7SVivien Didelot 
5094d5f2ba7SVivien Didelot #endif /* _MV88E6XXX_CHIP_H */
510