1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Marvell 10G 88x3310 PHY driver
4 *
5 * Based upon the ID registers, this PHY appears to be a mixture of IPs
6 * from two different companies.
7 *
8 * There appears to be several different data paths through the PHY which
9 * are automatically managed by the PHY.  The following has been determined
10 * via observation and experimentation for a setup using single-lane Serdes:
11 *
12 *       SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
13 *  10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
14 *  10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
15 *
16 * With XAUI, observation shows:
17 *
18 *        XAUI PHYXS -- <appropriate PCS as above>
19 *
20 * and no switching of the host interface mode occurs.
21 *
22 * If both the fiber and copper ports are connected, the first to gain
23 * link takes priority and the other port is completely locked out.
24 */
25#include <common.h>
26#include <console.h>
27#include <dm/device_compat.h>
28#include <dm/devres.h>
29#include <errno.h>
30#include <linux/bitfield.h>
31#include <linux/bitops.h>
32#include <linux/compat.h>
33#include <linux/delay.h>
34#include <linux/iopoll.h>
35#include <marvell_phy.h>
36#include <phy.h>
37
38#define MV_PHY_ALASKA_NBT_QUIRK_MASK	0xfffffffe
39#define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
40
41#define MV_VERSION(a, b, c, d) ((a) << 24 | (b) << 16 | (c) << 8 | (d))
42
43enum {
44	MV_PMA_FW_VER0		= 0xc011,
45	MV_PMA_FW_VER1		= 0xc012,
46	MV_PMA_21X0_PORT_CTRL	= 0xc04a,
47	MV_PMA_21X0_PORT_CTRL_SWRST				= BIT(15),
48	MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
49	MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII			= 0x0,
50	MV_PMA_2180_PORT_CTRL_MACTYPE_DXGMII			= 0x1,
51	MV_PMA_2180_PORT_CTRL_MACTYPE_QXGMII			= 0x2,
52	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER			= 0x4,
53	MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER_NO_SGMII_AN	= 0x5,
54	MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
55	MV_PMA_BOOT		= 0xc050,
56	MV_PMA_BOOT_FATAL	= BIT(0),
57
58	MV_PCS_BASE_T		= 0x0000,
59	MV_PCS_BASE_R		= 0x1000,
60	MV_PCS_1000BASEX	= 0x2000,
61
62	MV_PCS_CSCR1		= 0x8000,
63	MV_PCS_CSCR1_ED_MASK	= 0x0300,
64	MV_PCS_CSCR1_ED_OFF	= 0x0000,
65	MV_PCS_CSCR1_ED_RX	= 0x0200,
66	MV_PCS_CSCR1_ED_NLP	= 0x0300,
67	MV_PCS_CSCR1_MDIX_MASK	= 0x0060,
68	MV_PCS_CSCR1_MDIX_MDI	= 0x0000,
69	MV_PCS_CSCR1_MDIX_MDIX	= 0x0020,
70	MV_PCS_CSCR1_MDIX_AUTO	= 0x0060,
71
72	MV_PCS_DSC1		= 0x8003,
73	MV_PCS_DSC1_ENABLE	= BIT(9),
74	MV_PCS_DSC1_10GBT	= 0x01c0,
75	MV_PCS_DSC1_1GBR	= 0x0038,
76	MV_PCS_DSC1_100BTX	= 0x0007,
77	MV_PCS_DSC2		= 0x8004,
78	MV_PCS_DSC2_2P5G	= 0xf000,
79	MV_PCS_DSC2_5G		= 0x0f00,
80
81	MV_PCS_CSSR1		= 0x8008,
82	MV_PCS_CSSR1_SPD1_MASK	= 0xc000,
83	MV_PCS_CSSR1_SPD1_SPD2	= 0xc000,
84	MV_PCS_CSSR1_SPD1_1000	= 0x8000,
85	MV_PCS_CSSR1_SPD1_100	= 0x4000,
86	MV_PCS_CSSR1_SPD1_10	= 0x0000,
87	MV_PCS_CSSR1_DUPLEX_FULL = BIT(13),
88	MV_PCS_CSSR1_RESOLVED	= BIT(11),
89	MV_PCS_CSSR1_MDIX	= BIT(6),
90	MV_PCS_CSSR1_SPD2_MASK	= 0x000c,
91	MV_PCS_CSSR1_SPD2_5000	= 0x0008,
92	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
93	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
94
95	/* Temperature read register (88E2110 only) */
96	MV_PCS_TEMP		= 0x8042,
97
98	/* Number of ports on the device */
99	MV_PCS_PORT_INFO	= 0xd00d,
100	MV_PCS_PORT_INFO_NPORTS_MASK	= 0x0380,
101	MV_PCS_PORT_INFO_NPORTS_SHIFT	= 7,
102
103	/* SerDes reinitialization 88E21X0 */
104	MV_AN_21X0_SERDES_CTRL2	= 0x800f,
105	MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS	= BIT(13),
106	MV_AN_21X0_SERDES_CTRL2_RUN_INIT	= BIT(15),
107
108	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
109	 * registers appear to set themselves to the 0x800X when AN is
110	 * restarted, but status registers appear readable from either.
111	 */
112	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
113	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
114
115	/* Vendor2 MMD registers */
116	MV_V2_PORT_CTRL		= 0xf001,
117	MV_V2_PORT_CTRL_PWRDOWN					= BIT(11),
118	MV_V2_33X0_PORT_CTRL_SWRST				= BIT(15),
119	MV_V2_33X0_PORT_CTRL_MACTYPE_MASK			= 0x7,
120	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI			= 0x0,
121	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH		= 0x1,
122	MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN		= 0x1,
123	MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH		= 0x2,
124	MV_V2_3310_PORT_CTRL_MACTYPE_XAUI			= 0x3,
125	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER			= 0x4,
126	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_NO_SGMII_AN	= 0x5,
127	MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH	= 0x6,
128	MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII			= 0x7,
129	MV_V2_PORT_INTR_STS		= 0xf040,
130	MV_V2_PORT_INTR_MASK		= 0xf043,
131	MV_V2_PORT_INTR_STS_WOL_EN	= BIT(8),
132	MV_V2_MAGIC_PKT_WORD0		= 0xf06b,
133	MV_V2_MAGIC_PKT_WORD1		= 0xf06c,
134	MV_V2_MAGIC_PKT_WORD2		= 0xf06d,
135	/* Wake on LAN registers */
136	MV_V2_WOL_CTRL			= 0xf06e,
137	MV_V2_WOL_CTRL_CLEAR_STS	= BIT(15),
138	MV_V2_WOL_CTRL_MAGIC_PKT_EN	= BIT(0),
139	/* Temperature control/read registers (88X3310 only) */
140	MV_V2_TEMP_CTRL		= 0xf08a,
141	MV_V2_TEMP_CTRL_MASK	= 0xc000,
142	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
143	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
144	MV_V2_TEMP		= 0xf08c,
145	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
146};
147
148struct mv3310_chip {
149	bool (*has_downshift)(struct phy_device *phydev);
150	int (*test_supported_interfaces)(struct phy_device *phydev);
151	int (*get_mactype)(struct phy_device *phydev);
152	int (*set_mactype)(struct phy_device *phydev, int mactype);
153	int (*select_mactype)(struct phy_device *phydev);
154	int (*init_interface)(struct phy_device *phydev, int mactype);
155};
156
157struct mv3310_priv {
158	DECLARE_BITMAP(supported_interfaces, PHY_INTERFACE_MODE_MAX);
159
160	u32 firmware_ver;
161	bool has_downshift;
162	bool rate_match;
163};
164
165static const struct mv3310_chip *to_mv3310_chip(struct phy_device *phydev)
166{
167	return (const struct mv3310_chip *)phydev->drv->data;
168}
169
170static int mv3310_power_down(struct phy_device *phydev)
171{
172	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
173				MV_V2_PORT_CTRL_PWRDOWN);
174}
175
176static int mv3310_power_up(struct phy_device *phydev)
177{
178	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
179	int ret;
180
181	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
182				 MV_V2_PORT_CTRL_PWRDOWN);
183
184	if (phydev->drv->uid != MARVELL_PHY_ID_88X3310 ||
185	    priv->firmware_ver < 0x00030000)
186		return ret;
187
188	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
189				MV_V2_33X0_PORT_CTRL_SWRST);
190}
191
192static int mv3310_reset(struct phy_device *phydev, u32 unit)
193{
194	int val, err;
195
196	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
197			     MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
198	if (err < 0)
199		return err;
200
201	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
202					 unit + MDIO_CTRL1, val,
203					 !(val & MDIO_CTRL1_RESET),
204					 5000, 100000, true);
205}
206
207static int mv3310_set_downshift(struct phy_device *phydev)
208{
209	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
210	const u8 ds = 1;
211	u16 val;
212	int err;
213
214	if (!priv->has_downshift)
215		return -EOPNOTSUPP;
216
217	val = FIELD_PREP(MV_PCS_DSC2_2P5G, ds);
218	val |= FIELD_PREP(MV_PCS_DSC2_5G, ds);
219	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC2,
220			     MV_PCS_DSC2_2P5G | MV_PCS_DSC2_5G, val);
221	if (err < 0)
222		return err;
223
224	val = MV_PCS_DSC1_ENABLE;
225	val |= FIELD_PREP(MV_PCS_DSC1_10GBT, ds);
226	val |= FIELD_PREP(MV_PCS_DSC1_1GBR, ds);
227	val |= FIELD_PREP(MV_PCS_DSC1_100BTX, ds);
228
229	return phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_PCS_DSC1,
230			      MV_PCS_DSC1_ENABLE | MV_PCS_DSC1_10GBT |
231			      MV_PCS_DSC1_1GBR | MV_PCS_DSC1_100BTX, val);
232}
233
234static int mv3310_set_edpd(struct phy_device *phydev)
235{
236	int err;
237
238	err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
239				     MV_PCS_CSCR1_ED_MASK,
240				     MV_PCS_CSCR1_ED_NLP);
241	if (err > 0)
242		err = mv3310_reset(phydev, MV_PCS_BASE_T);
243
244	return err;
245}
246
247static int mv3310_probe(struct phy_device *phydev)
248{
249	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
250	struct mv3310_priv *priv;
251	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
252	int ret;
253
254	if (!phydev->is_c45 ||
255	    (phydev->mmds & mmd_mask) != mmd_mask)
256		return -ENODEV;
257
258	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
259	if (ret < 0)
260		return ret;
261
262	if (ret & MV_PMA_BOOT_FATAL) {
263		dev_warn(phydev->dev,
264			 "PHY failed to boot firmware, status=%04x\n", ret);
265		return -ENODEV;
266	}
267
268	priv = devm_kzalloc(phydev->dev, sizeof(*priv), GFP_KERNEL);
269	if (!priv)
270		return -ENOMEM;
271
272	phydev->priv = priv;
273
274	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
275	if (ret < 0)
276		return ret;
277
278	priv->firmware_ver = ret << 16;
279
280	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
281	if (ret < 0)
282		return ret;
283
284	priv->firmware_ver |= ret;
285
286	dev_info(phydev->dev, "Firmware version %u.%u.%u.%u\n",
287		 priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
288		 (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
289
290	if (chip->has_downshift)
291		priv->has_downshift = chip->has_downshift(phydev);
292
293	/* Powering down the port when not in use saves about 600mW */
294	ret = mv3310_power_down(phydev);
295	if (ret)
296		return ret;
297
298	return 0;
299}
300
301static int mv2110_get_mactype(struct phy_device *phydev)
302{
303	int mactype;
304
305	mactype = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL);
306	if (mactype < 0)
307		return mactype;
308
309	return mactype & MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
310}
311
312static int mv2110_set_mactype(struct phy_device *phydev, int mactype)
313{
314	int err, val;
315
316	mactype &= MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK;
317	err = phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_21X0_PORT_CTRL,
318			     MV_PMA_21X0_PORT_CTRL_SWRST |
319			     MV_PMA_21X0_PORT_CTRL_MACTYPE_MASK,
320			     MV_PMA_21X0_PORT_CTRL_SWRST | mactype);
321	if (err)
322		return err;
323
324	err = phy_set_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
325			       MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS |
326			       MV_AN_21X0_SERDES_CTRL2_RUN_INIT);
327	if (err)
328		return err;
329
330	err = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_AN,
331					MV_AN_21X0_SERDES_CTRL2, val,
332					!(val &
333					  MV_AN_21X0_SERDES_CTRL2_RUN_INIT),
334					5000, 100000, true);
335	if (err)
336		return err;
337
338	return phy_clear_bits_mmd(phydev, MDIO_MMD_AN, MV_AN_21X0_SERDES_CTRL2,
339				  MV_AN_21X0_SERDES_CTRL2_AUTO_INIT_DIS);
340}
341
342static int mv2110_select_mactype(struct phy_device *phydev)
343{
344	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
345		return MV_PMA_21X0_PORT_CTRL_MACTYPE_USXGMII;
346	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
347		 !(phydev->interface == PHY_INTERFACE_MODE_10GBASER))
348		return MV_PMA_21X0_PORT_CTRL_MACTYPE_5GBASER;
349	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
350		return MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
351	else
352		return -1;
353}
354
355static int mv3310_get_mactype(struct phy_device *phydev)
356{
357	int mactype;
358
359	mactype = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
360	if (mactype < 0)
361		return mactype;
362
363	return mactype & MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
364}
365
366static int mv3310_set_mactype(struct phy_device *phydev, int mactype)
367{
368	int ret;
369
370	mactype &= MV_V2_33X0_PORT_CTRL_MACTYPE_MASK;
371	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
372				     MV_V2_33X0_PORT_CTRL_MACTYPE_MASK,
373				     mactype);
374	if (ret <= 0)
375		return ret;
376
377	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
378				MV_V2_33X0_PORT_CTRL_SWRST);
379}
380
381static int mv3310_select_mactype(struct phy_device *phydev)
382{
383	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII)
384		return MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII;
385	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
386		 phydev->interface == PHY_INTERFACE_MODE_10GBASER)
387		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
388	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
389		 phydev->interface == PHY_INTERFACE_MODE_RXAUI)
390		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI;
391	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII &&
392		 phydev->interface == PHY_INTERFACE_MODE_XAUI)
393		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI;
394	else if (phydev->interface == PHY_INTERFACE_MODE_10GBASER)
395		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH;
396	else if (phydev->interface == PHY_INTERFACE_MODE_RXAUI)
397		return MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH;
398	else if (phydev->interface == PHY_INTERFACE_MODE_XAUI)
399		return MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH;
400	else if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
401		return MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER;
402	else
403		return -1;
404}
405
406static int mv2110_init_interface(struct phy_device *phydev, int mactype)
407{
408	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
409
410	priv->rate_match = false;
411
412	if (mactype == MV_PMA_21X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH)
413		priv->rate_match = true;
414
415	return 0;
416}
417
418static int mv3310_init_interface(struct phy_device *phydev, int mactype)
419{
420	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
421
422	priv->rate_match = false;
423
424	if (mactype != MV_V2_3340_PORT_CTRL_MACTYPE_RXAUI_NO_SGMII_AN)
425		return 0;
426
427	if (mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH ||
428	    mactype == MV_V2_33X0_PORT_CTRL_MACTYPE_RXAUI_RATE_MATCH ||
429	    mactype == MV_V2_3310_PORT_CTRL_MACTYPE_XAUI_RATE_MATCH)
430		priv->rate_match = true;
431
432	return 0;
433}
434
435static int mv3310_config_init(struct phy_device *phydev)
436{
437	const struct mv3310_chip *chip = to_mv3310_chip(phydev);
438	int err, mactype;
439
440	/* Check that the PHY interface type is compatible */
441	err = chip->test_supported_interfaces(phydev);
442	if (err)
443		return err;
444
445	/* Power up so reset works */
446	err = mv3310_power_up(phydev);
447	if (err)
448		return err;
449
450	/* If host provided host supported interface modes, try to select the
451	 * best one
452	 */
453	mactype = chip->select_mactype(phydev);
454	if (mactype >= 0) {
455		dev_info(phydev->dev, "Changing MACTYPE to %i\n",
456			 mactype);
457		err = chip->set_mactype(phydev, mactype);
458		if (err)
459			return err;
460	}
461
462	mactype = chip->get_mactype(phydev);
463	if (mactype < 0)
464		return mactype;
465
466	err = chip->init_interface(phydev, mactype);
467	if (err) {
468		dev_err(phydev->dev, "MACTYPE configuration invalid\n");
469		return err;
470	}
471
472	/* Enable EDPD mode - saving 600mW */
473	err = mv3310_set_edpd(phydev);
474	if (err)
475		return err;
476
477	/* Allow downshift */
478	err = mv3310_set_downshift(phydev);
479	if (err && err != -EOPNOTSUPP)
480		return err;
481
482	return 0;
483}
484
485static int mv3310_config(struct phy_device *phydev)
486{
487	int err;
488
489	err = mv3310_probe(phydev);
490	if (!err)
491		err = mv3310_config_init(phydev);
492
493	return err;
494}
495
496static int mv3310_get_number_of_ports(struct phy_device *phydev)
497{
498	int ret;
499
500	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PORT_INFO);
501	if (ret < 0)
502		return ret;
503
504	ret &= MV_PCS_PORT_INFO_NPORTS_MASK;
505	ret >>= MV_PCS_PORT_INFO_NPORTS_SHIFT;
506
507	return ret + 1;
508}
509
510static int mv3310_match_phy_device(struct phy_device *phydev)
511{
512	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88X3310)
513		return 0;
514
515	return mv3310_get_number_of_ports(phydev) == 1;
516}
517
518static int mv211x_match_phy_device(struct phy_device *phydev, bool has_5g)
519{
520	int val;
521
522	if ((phydev->phy_id & MARVELL_PHY_ID_MASK) != MARVELL_PHY_ID_88E2110)
523		return 0;
524
525	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_SPEED);
526	if (val < 0)
527		return val;
528
529	return !!(val & MDIO_PCS_SPEED_5G) == has_5g;
530}
531
532static int mv2110_match_phy_device(struct phy_device *phydev)
533{
534	return mv211x_match_phy_device(phydev, true);
535}
536
537static bool mv3310_has_downshift(struct phy_device *phydev)
538{
539	struct mv3310_priv *priv = (struct mv3310_priv *)phydev->priv;
540
541	/* Fails to downshift with firmware older than v0.3.5.0 */
542	return priv->firmware_ver >= MV_VERSION(0, 3, 5, 0);
543}
544
545#define mv_test_bit(iface, phydev)	\
546	({ if ((phydev)->interface & (iface)) return 0; })
547
548static int mv3310_mv3340_test_supported_interfaces(struct phy_device *phydev)
549{
550	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
551	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
552	mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
553	if (mv3310_match_phy_device(phydev))
554		mv_test_bit(PHY_INTERFACE_MODE_XAUI, phydev);
555	mv_test_bit(PHY_INTERFACE_MODE_RXAUI, phydev);
556	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
557	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
558	return -ENODEV;
559}
560
561static int mv2110_mv2111_test_supported_interfaces(struct phy_device *phydev)
562{
563	mv_test_bit(PHY_INTERFACE_MODE_SGMII, phydev);
564	mv_test_bit(PHY_INTERFACE_MODE_2500BASEX, phydev);
565	if (mv2110_match_phy_device(phydev))
566		mv_test_bit(PHY_INTERFACE_MODE_5GBASER, phydev);
567	mv_test_bit(PHY_INTERFACE_MODE_10GBASER, phydev);
568	mv_test_bit(PHY_INTERFACE_MODE_USXGMII, phydev);
569	return -ENODEV;
570}
571
572static const struct mv3310_chip mv3310_mv3340_type = {
573	.has_downshift = mv3310_has_downshift,
574	.test_supported_interfaces = mv3310_mv3340_test_supported_interfaces,
575	.get_mactype = mv3310_get_mactype,
576	.set_mactype = mv3310_set_mactype,
577	.select_mactype = mv3310_select_mactype,
578	.init_interface = mv3310_init_interface,
579};
580
581static const struct mv3310_chip mv2110_mv2111_type = {
582	.test_supported_interfaces = mv2110_mv2111_test_supported_interfaces,
583	.get_mactype = mv2110_get_mactype,
584	.set_mactype = mv2110_set_mactype,
585	.select_mactype = mv2110_select_mactype,
586	.init_interface = mv2110_init_interface,
587};
588
589U_BOOT_PHY_DRIVER(mv88e3310_mv88e3340) = {
590	.name		= "mv88x3310",
591	.uid		= MARVELL_PHY_ID_88X3310,
592	.mask		= MARVELL_PHY_ID_MASK,
593	.features	= PHY_10G_FEATURES,
594	.data		= (ulong)&mv3310_mv3340_type,
595	.config		= mv3310_config,
596};
597
598U_BOOT_PHY_DRIVER(mv88e2110_mv88e2111) = {
599	.name		= "mv88e2110",
600	.uid		= MARVELL_PHY_ID_88E2110,
601	.mask		= MARVELL_PHY_ID_MASK,
602	.features	= PHY_10G_FEATURES,
603	.data		= (ulong)&mv2110_mv2111_type,
604	.config		= mv3310_config,
605};
606