summaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/mv88e6xxx/serdes.h
blob: 67369054951fb854d9c5369eaf8e1bcc1655dbbc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
/* SPDX-License-Identifier: GPL-2.0-or-later */
/*
 * Marvell 88E6xxx SERDES manipulation, via SMI bus
 *
 * Copyright (c) 2008 Marvell Semiconductor
 *
 * Copyright (c) 2016 Andrew Lunn <andrew@lunn.ch>
 */

#ifndef _MV88E6XXX_SERDES_H
#define _MV88E6XXX_SERDES_H

#include "chip.h"

#define MV88E6352_ADDR_SERDES		0x0f
#define MV88E6352_SERDES_PAGE_FIBER	0x01
#define MV88E6352_SERDES_IRQ		0x0b
#define MV88E6352_SERDES_INT_ENABLE	0x12
#define MV88E6352_SERDES_INT_SPEED_CHANGE	BIT(14)
#define MV88E6352_SERDES_INT_DUPLEX_CHANGE	BIT(13)
#define MV88E6352_SERDES_INT_PAGE_RX		BIT(12)
#define MV88E6352_SERDES_INT_AN_COMPLETE	BIT(11)
#define MV88E6352_SERDES_INT_LINK_CHANGE	BIT(10)
#define MV88E6352_SERDES_INT_SYMBOL_ERROR	BIT(9)
#define MV88E6352_SERDES_INT_FALSE_CARRIER	BIT(8)
#define MV88E6352_SERDES_INT_FIFO_OVER_UNDER	BIT(7)
#define MV88E6352_SERDES_INT_FIBRE_ENERGY	BIT(4)
#define MV88E6352_SERDES_INT_STATUS	0x13

#define MV88E6352_SERDES_SPEC_CTRL2	0x1a
#define MV88E6352_SERDES_OUT_AMP_MASK		0x0007

#define MV88E6341_PORT5_LANE		0x15

#define MV88E6390_PORT9_LANE0		0x09
#define MV88E6390_PORT9_LANE1		0x12
#define MV88E6390_PORT9_LANE2		0x13
#define MV88E6390_PORT9_LANE3		0x14
#define MV88E6390_PORT10_LANE0		0x0a
#define MV88E6390_PORT10_LANE1		0x15
#define MV88E6390_PORT10_LANE2		0x16
#define MV88E6390_PORT10_LANE3		0x17

/* 10GBASE-R and 10GBASE-X4/X2 */
#define MV88E6390_10G_CTRL1		(0x1000 + MDIO_CTRL1)
#define MV88E6390_10G_STAT1		(0x1000 + MDIO_STAT1)
#define MV88E6393X_10G_INT_ENABLE	0x9000
#define MV88E6393X_10G_INT_LINK_CHANGE	BIT(2)
#define MV88E6393X_10G_INT_STATUS	0x9001

/* 1000BASE-X and SGMII */
#define MV88E6390_SGMII_BMCR		(0x2000 + MII_BMCR)
#define MV88E6390_SGMII_BMSR		(0x2000 + MII_BMSR)
#define MV88E6390_SGMII_ADVERTISE	(0x2000 + MII_ADVERTISE)
#define MV88E6390_SGMII_LPA		(0x2000 + MII_LPA)
#define MV88E6390_SGMII_INT_ENABLE	0xa001
#define MV88E6390_SGMII_INT_SPEED_CHANGE	BIT(14)
#define MV88E6390_SGMII_INT_DUPLEX_CHANGE	BIT(13)
#define MV88E6390_SGMII_INT_PAGE_RX		BIT(12)
#define MV88E6390_SGMII_INT_AN_COMPLETE		BIT(11)
#define MV88E6390_SGMII_INT_LINK_DOWN		BIT(10)
#define MV88E6390_SGMII_INT_LINK_UP		BIT(9)
#define MV88E6390_SGMII_INT_SYMBOL_ERROR	BIT(8)
#define MV88E6390_SGMII_INT_FALSE_CARRIER	BIT(7)
#define MV88E6390_SGMII_INT_STATUS	0xa002
#define MV88E6390_SGMII_PHY_STATUS	0xa003
#define MV88E6390_SGMII_PHY_STATUS_SPEED_MASK	GENMASK(15, 14)
#define MV88E6390_SGMII_PHY_STATUS_SPEED_1000	0x8000
#define MV88E6390_SGMII_PHY_STATUS_SPEED_100	0x4000
#define MV88E6390_SGMII_PHY_STATUS_SPEED_10	0x0000
#define MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL	BIT(13)
#define MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID BIT(11)
#define MV88E6390_SGMII_PHY_STATUS_LINK		BIT(10)
#define MV88E6390_SGMII_PHY_STATUS_TX_PAUSE	BIT(3)
#define MV88E6390_SGMII_PHY_STATUS_RX_PAUSE	BIT(2)

/* Packet generator pad packet checker */
#define MV88E6390_PG_CONTROL		0xf010
#define MV88E6390_PG_CONTROL_ENABLE_PC		BIT(0)

#define MV88E6393X_PORT0_LANE			0x00
#define MV88E6393X_PORT9_LANE			0x09
#define MV88E6393X_PORT10_LANE			0x0a

/* Port Operational Configuration */
#define MV88E6393X_SERDES_POC			0xf002
#define MV88E6393X_SERDES_POC_PCS_1000BASEX	0x0000
#define MV88E6393X_SERDES_POC_PCS_2500BASEX	0x0001
#define MV88E6393X_SERDES_POC_PCS_SGMII_PHY	0x0002
#define MV88E6393X_SERDES_POC_PCS_SGMII_MAC	0x0003
#define MV88E6393X_SERDES_POC_PCS_5GBASER	0x0004
#define MV88E6393X_SERDES_POC_PCS_10GBASER	0x0005
#define MV88E6393X_SERDES_POC_PCS_USXGMII_PHY	0x0006
#define MV88E6393X_SERDES_POC_PCS_USXGMII_MAC	0x0007
#define MV88E6393X_SERDES_POC_PCS_MASK		0x0007
#define MV88E6393X_SERDES_POC_RESET		BIT(15)
#define MV88E6393X_SERDES_POC_PDOWN		BIT(5)
#define MV88E6393X_SERDES_POC_AN		BIT(3)
#define MV88E6393X_SERDES_CTRL1			0xf003
#define MV88E6393X_SERDES_CTRL1_TX_PDOWN	BIT(9)
#define MV88E6393X_SERDES_CTRL1_RX_PDOWN	BIT(8)

#define MV88E6393X_ERRATA_4_8_REG		0xF074
#define MV88E6393X_ERRATA_4_8_BIT		BIT(14)

int mv88e6185_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6341_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6390x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6393x_serdes_get_lane(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
				int lane, unsigned int mode,
				phy_interface_t interface,
				const unsigned long *advertise);
int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
				int lane, unsigned int mode,
				phy_interface_t interface,
				const unsigned long *advertise);
int mv88e6185_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
				   int lane, struct phylink_link_state *state);
int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
				   int lane, struct phylink_link_state *state);
int mv88e6390_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
				   int lane, struct phylink_link_state *state);
int mv88e6393x_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
				    int lane, struct phylink_link_state *state);
int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
				    int lane);
int mv88e6390_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
				    int lane);
int mv88e6352_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
				 int lane, int speed, int duplex);
int mv88e6390_serdes_pcs_link_up(struct mv88e6xxx_chip *chip, int port,
				 int lane, int speed, int duplex);
unsigned int mv88e6352_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
					  int port);
unsigned int mv88e6390_serdes_irq_mapping(struct mv88e6xxx_chip *chip,
					  int port);
int mv88e6185_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
			   bool up);
int mv88e6352_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
			   bool on);
int mv88e6390_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
			   bool on);
int mv88e6393x_serdes_power(struct mv88e6xxx_chip *chip, int port, int lane,
			    bool on);
int mv88e6393x_serdes_setup_errata(struct mv88e6xxx_chip *chip);
int mv88e6097_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
				bool enable);
int mv88e6352_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
				bool enable);
int mv88e6390_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port, int lane,
				bool enable);
int mv88e6393x_serdes_irq_enable(struct mv88e6xxx_chip *chip, int port,
				 int lane, bool enable);
irqreturn_t mv88e6097_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
					int lane);
irqreturn_t mv88e6352_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
					int lane);
irqreturn_t mv88e6390_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
					int lane);
irqreturn_t mv88e6393x_serdes_irq_status(struct mv88e6xxx_chip *chip, int port,
					 int lane);
int mv88e6352_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6352_serdes_get_strings(struct mv88e6xxx_chip *chip,
				 int port, uint8_t *data);
size_t mv88e6352_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
				  uint64_t *data);
int mv88e6390_serdes_get_sset_count(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_serdes_get_strings(struct mv88e6xxx_chip *chip,
				 int port, uint8_t *data);
size_t mv88e6390_serdes_get_stats(struct mv88e6xxx_chip *chip, int port,
				  uint64_t *data);

int mv88e6352_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6352_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);
int mv88e6390_serdes_get_regs_len(struct mv88e6xxx_chip *chip, int port);
void mv88e6390_serdes_get_regs(struct mv88e6xxx_chip *chip, int port, void *_p);

int mv88e6352_serdes_set_tx_amplitude(struct mv88e6xxx_chip *chip, int port,
				      int val);

/* Return the (first) SERDES lane address a port is using, -errno otherwise. */
static inline int mv88e6xxx_serdes_get_lane(struct mv88e6xxx_chip *chip,
					    int port)
{
	if (!chip->info->ops->serdes_get_lane)
		return -EOPNOTSUPP;

	return chip->info->ops->serdes_get_lane(chip, port);
}

static inline int mv88e6xxx_serdes_power_up(struct mv88e6xxx_chip *chip,
					    int port, int lane)
{
	if (!chip->info->ops->serdes_power)
		return -EOPNOTSUPP;

	return chip->info->ops->serdes_power(chip, port, lane, true);
}

static inline int mv88e6xxx_serdes_power_down(struct mv88e6xxx_chip *chip,
					      int port, int lane)
{
	if (!chip->info->ops->serdes_power)
		return -EOPNOTSUPP;

	return chip->info->ops->serdes_power(chip, port, lane, false);
}

static inline unsigned int
mv88e6xxx_serdes_irq_mapping(struct mv88e6xxx_chip *chip, int port)
{
	if (!chip->info->ops->serdes_irq_mapping)
		return 0;

	return chip->info->ops->serdes_irq_mapping(chip, port);
}

static inline int mv88e6xxx_serdes_irq_enable(struct mv88e6xxx_chip *chip,
					      int port, int lane)
{
	if (!chip->info->ops->serdes_irq_enable)
		return -EOPNOTSUPP;

	return chip->info->ops->serdes_irq_enable(chip, port, lane, true);
}

static inline int mv88e6xxx_serdes_irq_disable(struct mv88e6xxx_chip *chip,
					       int port, int lane)
{
	if (!chip->info->ops->serdes_irq_enable)
		return -EOPNOTSUPP;

	return chip->info->ops->serdes_irq_enable(chip, port, lane, false);
}

static inline irqreturn_t
mv88e6xxx_serdes_irq_status(struct mv88e6xxx_chip *chip, int port, int lane)
{
	if (!chip->info->ops->serdes_irq_status)
		return IRQ_NONE;

	return chip->info->ops->serdes_irq_status(chip, port, lane);
}

#endif