xref: /openbmc/linux/drivers/net/dsa/mv88e6xxx/serdes.h (revision 05407b0e)
12874c5fdSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
26d91782fSAndrew Lunn /*
36d91782fSAndrew Lunn  * Marvell 88E6xxx SERDES manipulation, via SMI bus
46d91782fSAndrew Lunn  *
56d91782fSAndrew Lunn  * Copyright (c) 2008 Marvell Semiconductor
66d91782fSAndrew Lunn  *
76d91782fSAndrew Lunn  * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
86d91782fSAndrew Lunn  */
96d91782fSAndrew Lunn 
106d91782fSAndrew Lunn #ifndef _MV88E6XXX_SERDES_H
116d91782fSAndrew Lunn #define _MV88E6XXX_SERDES_H
126d91782fSAndrew Lunn 
134d5f2ba7SVivien Didelot #include "chip.h"
146d91782fSAndrew Lunn 
15*05407b0eSRussell King (Oracle) struct phylink_link_state;
16*05407b0eSRussell King (Oracle) 
176d91782fSAndrew Lunn #define MV88E6352_ADDR_SERDES		0x0f
186d91782fSAndrew Lunn #define MV88E6352_SERDES_PAGE_FIBER	0x01
194382172fSAndrew Lunn #define MV88E6352_SERDES_IRQ		0x0b
204382172fSAndrew Lunn #define MV88E6352_SERDES_INT_ENABLE	0x12
214382172fSAndrew Lunn #define MV88E6352_SERDES_INT_SPEED_CHANGE	BIT(14)
224382172fSAndrew Lunn #define MV88E6352_SERDES_INT_DUPLEX_CHANGE	BIT(13)
234382172fSAndrew Lunn #define MV88E6352_SERDES_INT_PAGE_RX		BIT(12)
244382172fSAndrew Lunn #define MV88E6352_SERDES_INT_AN_COMPLETE	BIT(11)
254382172fSAndrew Lunn #define MV88E6352_SERDES_INT_LINK_CHANGE	BIT(10)
264382172fSAndrew Lunn #define MV88E6352_SERDES_INT_SYMBOL_ERROR	BIT(9)
274382172fSAndrew Lunn #define MV88E6352_SERDES_INT_FALSE_CARRIER	BIT(8)
284382172fSAndrew Lunn #define MV88E6352_SERDES_INT_FIFO_OVER_UNDER	BIT(7)
294382172fSAndrew Lunn #define MV88E6352_SERDES_INT_FIBRE_ENERGY	BIT(4)
304382172fSAndrew Lunn #define MV88E6352_SERDES_INT_STATUS	0x13
314382172fSAndrew Lunn 
32926eae60SHolger Brunck #define MV88E6352_SERDES_SPEC_CTRL2	0x1a
33926eae60SHolger Brunck #define MV88E6352_SERDES_OUT_AMP_MASK		0x0007
346d91782fSAndrew Lunn 
35d3cf7d8fSMarek Behún #define MV88E6341_PORT5_LANE		0x15
365bafeb6eSMarek Behún 
376335e9f2SAndrew Lunn #define MV88E6390_PORT9_LANE0		0x09
386335e9f2SAndrew Lunn #define MV88E6390_PORT9_LANE1		0x12
396335e9f2SAndrew Lunn #define MV88E6390_PORT9_LANE2		0x13
406335e9f2SAndrew Lunn #define MV88E6390_PORT9_LANE3		0x14
416335e9f2SAndrew Lunn #define MV88E6390_PORT10_LANE0		0x0a
426335e9f2SAndrew Lunn #define MV88E6390_PORT10_LANE1		0x15
436335e9f2SAndrew Lunn #define MV88E6390_PORT10_LANE2		0x16
446335e9f2SAndrew Lunn #define MV88E6390_PORT10_LANE3		0x17
456335e9f2SAndrew Lunn 
466335e9f2SAndrew Lunn /* 10GBASE-R and 10GBASE-X4/X2 */
47bf604bc9SRussell King #define MV88E6390_10G_CTRL1		(0x1000 + MDIO_CTRL1)
487019bba4SRussell King #define MV88E6390_10G_STAT1		(0x1000 + MDIO_STAT1)
49de776d0dSPavana Sharma #define MV88E6393X_10G_INT_ENABLE	0x9000
50de776d0dSPavana Sharma #define MV88E6393X_10G_INT_LINK_CHANGE	BIT(2)
51de776d0dSPavana Sharma #define MV88E6393X_10G_INT_STATUS	0x9001
526335e9f2SAndrew Lunn 
534a562127SMichal Smulski /* USXGMII */
544a562127SMichal Smulski #define MV88E6390_USXGMII_LP_STATUS       0xf0a2
554a562127SMichal Smulski #define MV88E6390_USXGMII_PHY_STATUS      0xf0a6
564a562127SMichal Smulski 
576335e9f2SAndrew Lunn /* 1000BASE-X and SGMII */
584c8b7350SRussell King #define MV88E6390_SGMII_BMCR		(0x2000 + MII_BMCR)
597e0e6243SRussell King #define MV88E6390_SGMII_BMSR		(0x2000 + MII_BMSR)
60a5a6858bSRussell King #define MV88E6390_SGMII_ADVERTISE	(0x2000 + MII_ADVERTISE)
61a5a6858bSRussell King #define MV88E6390_SGMII_LPA		(0x2000 + MII_LPA)
62efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_ENABLE	0xa001
63efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_SPEED_CHANGE	BIT(14)
64efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_DUPLEX_CHANGE	BIT(13)
65efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_PAGE_RX		BIT(12)
66efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_AN_COMPLETE		BIT(11)
67efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_LINK_DOWN		BIT(10)
68efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_LINK_UP		BIT(9)
69efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_SYMBOL_ERROR	BIT(8)
70efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_FALSE_CARRIER	BIT(7)
71efd1ba6aSAndrew Lunn #define MV88E6390_SGMII_INT_STATUS	0xa002
7272d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS	0xa003
7372d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK	GENMASK(15, 14)
7472d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_SPEED_1000	0x8000
7572d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_SPEED_100	0x4000
7672d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_SPEED_10	0x0000
7772d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL	BIT(13)
7872d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
7972d8b4fdSHeiner Kallweit #define MV88E6390_SGMII_PHY_STATUS_LINK		BIT(10)
80a5a6858bSRussell King #define MV88E6390_SGMII_PHY_STATUS_TX_PAUSE	BIT(3)
81a5a6858bSRussell King #define MV88E6390_SGMII_PHY_STATUS_RX_PAUSE	BIT(2)
826335e9f2SAndrew Lunn 
830df95287SNikita Yushchenko /* Packet generator pad packet checker */
840df95287SNikita Yushchenko #define MV88E6390_PG_CONTROL		0xf010
850df95287SNikita Yushchenko #define MV88E6390_PG_CONTROL_ENABLE_PC		BIT(0)
860df95287SNikita Yushchenko 
87de776d0dSPavana Sharma #define MV88E6393X_PORT0_LANE			0x00
88de776d0dSPavana Sharma #define MV88E6393X_PORT9_LANE			0x09
89de776d0dSPavana Sharma #define MV88E6393X_PORT10_LANE			0x0a
90de776d0dSPavana Sharma 
91de776d0dSPavana Sharma /* Port Operational Configuration */
92de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC			0xf002
93de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_1000BASEX	0x0000
94de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_2500BASEX	0x0001
95de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_SGMII_PHY	0x0002
96de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_SGMII_MAC	0x0003
97de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_5GBASER	0x0004
98de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_10GBASER	0x0005
99de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_USXGMII_PHY	0x0006
100de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_USXGMII_MAC	0x0007
101de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PCS_MASK		0x0007
102de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_RESET		BIT(15)
103de776d0dSPavana Sharma #define MV88E6393X_SERDES_POC_PDOWN		BIT(5)
104163000dbSMarek Behún #define MV88E6393X_SERDES_POC_AN		BIT(3)
1057527d662SMarek Behún #define MV88E6393X_SERDES_CTRL1			0xf003
1067527d662SMarek Behún #define MV88E6393X_SERDES_CTRL1_TX_PDOWN	BIT(9)
1077527d662SMarek Behún #define MV88E6393X_SERDES_CTRL1_RX_PDOWN	BIT(8)
108de776d0dSPavana Sharma 
109de776d0dSPavana Sharma #define MV88E6393X_ERRATA_4_8_REG		0xF074
110de776d0dSPavana Sharma #define MV88E6393X_ERRATA_4_8_BIT		BIT(14)
111de776d0dSPavana Sharma 
112*05407b0eSRussell King (Oracle) int mv88e6xxx_pcs_decode_state(struct device *dev, u16 bmsr, u16 lpa,
113*05407b0eSRussell King (Oracle) 			       u16 status, struct phylink_link_state *state);
114*05407b0eSRussell King (Oracle) 
115193c5b26SPavana Sharma int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
116193c5b26SPavana Sharma int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
117193c5b26SPavana Sharma int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
118193c5b26SPavana Sharma int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
119193c5b26SPavana Sharma int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
120de776d0dSPavana Sharma int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
121a5a6858bSRussell King int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
122193c5b26SPavana Sharma 				int lane, unsigned int mode,
123a5a6858bSRussell King 				phy_interface_t interface,
124a5a6858bSRussell King 				const unsigned long *advertise);
125a5a6858bSRussell King int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
126193c5b26SPavana Sharma 				int lane, unsigned int mode,
127a5a6858bSRussell King 				phy_interface_t interface,
128a5a6858bSRussell King 				const unsigned long *advertise);
129f5be107cSChris Packham int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
130193c5b26SPavana Sharma 				   int lane, struct phylink_link_state *state);
131a5a6858bSRussell King int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
132193c5b26SPavana Sharma 				   int lane, struct phylink_link_state *state);
133a5a6858bSRussell King int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
134193c5b26SPavana Sharma 				   int lane, struct phylink_link_state *state);
135de776d0dSPavana Sharma int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
136de776d0dSPavana Sharma 				    int lane, struct phylink_link_state *state);
137a5a6858bSRussell King int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
138193c5b26SPavana Sharma 				    int lane);
139a5a6858bSRussell King int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
140193c5b26SPavana Sharma 				    int lane);
141a5a6858bSRussell King int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
142193c5b26SPavana Sharma 				 int lane, int speed, int duplex);
143a5a6858bSRussell King int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
144193c5b26SPavana Sharma 				 int lane, int speed, int duplex);
1454241ef52SVivien Didelot unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
1464241ef52SVivien Didelot 					  int port);
1474241ef52SVivien Didelot unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
1484241ef52SVivien Didelot 					  int port);
149193c5b26SPavana Sharma int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
150f5be107cSChris Packham 			   bool up);
151193c5b26SPavana Sharma int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
152dc272f60SVivien Didelot 			   bool on);
153193c5b26SPavana Sharma int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
154dc272f60SVivien Didelot 			   bool on);
155de776d0dSPavana Sharma int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
156de776d0dSPavana Sharma 			    bool on);
157de776d0dSPavana Sharma int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip);
158193c5b26SPavana Sharma int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
1595c19bc8bSChris Packham 				bool enable);
160193c5b26SPavana Sharma int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
16161a46b41SVivien Didelot 				bool enable);
162193c5b26SPavana Sharma int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
16361a46b41SVivien Didelot 				bool enable);
164de776d0dSPavana Sharma int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
165de776d0dSPavana Sharma 				 int lane, bool enable);
1665c19bc8bSChris Packham irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
167193c5b26SPavana Sharma 					int lane);
168907b9b9fSVivien Didelot irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
169193c5b26SPavana Sharma 					int lane);
170907b9b9fSVivien Didelot irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
171193c5b26SPavana Sharma 					int lane);
172de776d0dSPavana Sharma irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
173de776d0dSPavana Sharma 					 int lane);
174cda9f4aaSAndrew Lunn int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
17565f60e45SAndrew Lunn int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
176cda9f4aaSAndrew Lunn 				 int port, uint8_t *data);
17765f60e45SAndrew Lunn int mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
178cda9f4aaSAndrew Lunn 			       uint64_t *data);
1790df95287SNikita Yushchenko int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
1800df95287SNikita Yushchenko int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
1810df95287SNikita Yushchenko 				 int port, uint8_t *data);
1820df95287SNikita Yushchenko int mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
1830df95287SNikita Yushchenko 			       uint64_t *data);
1844382172fSAndrew Lunn 
185d3f88a24SAndrew Lunn int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
186d3f88a24SAndrew Lunn void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
187bf3504ceSAndrew Lunn int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
188bf3504ceSAndrew Lunn void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
189d3f88a24SAndrew Lunn 
190926eae60SHolger Brunck int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
191926eae60SHolger Brunck 				      int val);
192926eae60SHolger Brunck 
193193c5b26SPavana Sharma /* Return the (first) SERDES lane address a port is using, -errno otherwise. */
194193c5b26SPavana Sharma static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
1955122d4ecSVivien Didelot 					    int port)
1965122d4ecSVivien Didelot {
1975122d4ecSVivien Didelot 	if (!chip->info->ops->serdes_get_lane)
198193c5b26SPavana Sharma 		return -EOPNOTSUPP;
1995122d4ecSVivien Didelot 
2005122d4ecSVivien Didelot 	return chip->info->ops->serdes_get_lane(chip, port);
2015122d4ecSVivien Didelot }
2025122d4ecSVivien Didelot 
203dc272f60SVivien Didelot static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip,
204193c5b26SPavana Sharma 					    int port, int lane)
205dc272f60SVivien Didelot {
206dc272f60SVivien Didelot 	if (!chip->info->ops->serdes_power)
207dc272f60SVivien Didelot 		return -EOPNOTSUPP;
208dc272f60SVivien Didelot 
209dc272f60SVivien Didelot 	return chip->info->ops->serdes_power(chip, port, lane, true);
210dc272f60SVivien Didelot }
211dc272f60SVivien Didelot 
212dc272f60SVivien Didelot static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip,
213193c5b26SPavana Sharma 					      int port, int lane)
214dc272f60SVivien Didelot {
215dc272f60SVivien Didelot 	if (!chip->info->ops->serdes_power)
216dc272f60SVivien Didelot 		return -EOPNOTSUPP;
217dc272f60SVivien Didelot 
218dc272f60SVivien Didelot 	return chip->info->ops->serdes_power(chip, port, lane, false);
219dc272f60SVivien Didelot }
220dc272f60SVivien Didelot 
2214241ef52SVivien Didelot static inline unsigned int
2224241ef52SVivien Didelot mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
2234241ef52SVivien Didelot {
2244241ef52SVivien Didelot 	if (!chip->info->ops->serdes_irq_mapping)
2254241ef52SVivien Didelot 		return 0;
2264241ef52SVivien Didelot 
2274241ef52SVivien Didelot 	return chip->info->ops->serdes_irq_mapping(chip, port);
2284241ef52SVivien Didelot }
229734447d4SAndrew Lunn 
23061a46b41SVivien Didelot static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip,
231193c5b26SPavana Sharma 					      int port, int lane)
23261a46b41SVivien Didelot {
23361a46b41SVivien Didelot 	if (!chip->info->ops->serdes_irq_enable)
23461a46b41SVivien Didelot 		return -EOPNOTSUPP;
23561a46b41SVivien Didelot 
23661a46b41SVivien Didelot 	return chip->info->ops->serdes_irq_enable(chip, port, lane, true);
23761a46b41SVivien Didelot }
23861a46b41SVivien Didelot 
23961a46b41SVivien Didelot static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip,
240193c5b26SPavana Sharma 					       int port, int lane)
24161a46b41SVivien Didelot {
24261a46b41SVivien Didelot 	if (!chip->info->ops->serdes_irq_enable)
24361a46b41SVivien Didelot 		return -EOPNOTSUPP;
24461a46b41SVivien Didelot 
24561a46b41SVivien Didelot 	return chip->info->ops->serdes_irq_enable(chip, port, lane, false);
24661a46b41SVivien Didelot }
24761a46b41SVivien Didelot 
248907b9b9fSVivien Didelot static inline irqreturn_t
249193c5b26SPavana Sharma mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane)
250907b9b9fSVivien Didelot {
251907b9b9fSVivien Didelot 	if (!chip->info->ops->serdes_irq_status)
252907b9b9fSVivien Didelot 		return IRQ_NONE;
253907b9b9fSVivien Didelot 
254907b9b9fSVivien Didelot 	return chip->info->ops->serdes_irq_status(chip, port, lane);
255907b9b9fSVivien Didelot }
256907b9b9fSVivien Didelot 
2576d91782fSAndrew Lunn #endif
258