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 <linux/ctype.h>
26#include <linux/delay.h>
27#include <linux/hwmon.h>
28#include <linux/marvell_phy.h>
29#include <linux/phy.h>
30#include <linux/sfp.h>
31
32#define MV_PHY_ALASKA_NBT_QUIRK_MASK	0xfffffffe
33#define MV_PHY_ALASKA_NBT_QUIRK_REV	(MARVELL_PHY_ID_88X3310 | 0xa)
34
35enum {
36	MV_PMA_FW_VER0		= 0xc011,
37	MV_PMA_FW_VER1		= 0xc012,
38	MV_PMA_BOOT		= 0xc050,
39	MV_PMA_BOOT_FATAL	= BIT(0),
40
41	MV_PCS_BASE_T		= 0x0000,
42	MV_PCS_BASE_R		= 0x1000,
43	MV_PCS_1000BASEX	= 0x2000,
44
45	MV_PCS_CSCR1		= 0x8000,
46	MV_PCS_CSCR1_ED_MASK	= 0x0300,
47	MV_PCS_CSCR1_ED_OFF	= 0x0000,
48	MV_PCS_CSCR1_ED_RX	= 0x0200,
49	MV_PCS_CSCR1_ED_NLP	= 0x0300,
50	MV_PCS_CSCR1_MDIX_MASK	= 0x0060,
51	MV_PCS_CSCR1_MDIX_MDI	= 0x0000,
52	MV_PCS_CSCR1_MDIX_MDIX	= 0x0020,
53	MV_PCS_CSCR1_MDIX_AUTO	= 0x0060,
54
55	MV_PCS_CSSR1		= 0x8008,
56	MV_PCS_CSSR1_SPD1_MASK	= 0xc000,
57	MV_PCS_CSSR1_SPD1_SPD2	= 0xc000,
58	MV_PCS_CSSR1_SPD1_1000	= 0x8000,
59	MV_PCS_CSSR1_SPD1_100	= 0x4000,
60	MV_PCS_CSSR1_SPD1_10	= 0x0000,
61	MV_PCS_CSSR1_DUPLEX_FULL= BIT(13),
62	MV_PCS_CSSR1_RESOLVED	= BIT(11),
63	MV_PCS_CSSR1_MDIX	= BIT(6),
64	MV_PCS_CSSR1_SPD2_MASK	= 0x000c,
65	MV_PCS_CSSR1_SPD2_5000	= 0x0008,
66	MV_PCS_CSSR1_SPD2_2500	= 0x0004,
67	MV_PCS_CSSR1_SPD2_10000	= 0x0000,
68
69	/* Temperature read register (88E2110 only) */
70	MV_PCS_TEMP		= 0x8042,
71
72	/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
73	 * registers appear to set themselves to the 0x800X when AN is
74	 * restarted, but status registers appear readable from either.
75	 */
76	MV_AN_CTRL1000		= 0x8000, /* 1000base-T control register */
77	MV_AN_STAT1000		= 0x8001, /* 1000base-T status register */
78
79	/* Vendor2 MMD registers */
80	MV_V2_PORT_CTRL		= 0xf001,
81	MV_V2_PORT_CTRL_SWRST	= BIT(15),
82	MV_V2_PORT_CTRL_PWRDOWN = BIT(11),
83	MV_V2_PORT_MAC_TYPE_MASK = 0x7,
84	MV_V2_PORT_MAC_TYPE_RATE_MATCH = 0x6,
85	/* Temperature control/read registers (88X3310 only) */
86	MV_V2_TEMP_CTRL		= 0xf08a,
87	MV_V2_TEMP_CTRL_MASK	= 0xc000,
88	MV_V2_TEMP_CTRL_SAMPLE	= 0x0000,
89	MV_V2_TEMP_CTRL_DISABLE	= 0xc000,
90	MV_V2_TEMP		= 0xf08c,
91	MV_V2_TEMP_UNKNOWN	= 0x9600, /* unknown function */
92};
93
94struct mv3310_priv {
95	u32 firmware_ver;
96	bool rate_match;
97
98	struct device *hwmon_dev;
99	char *hwmon_name;
100};
101
102#ifdef CONFIG_HWMON
103static umode_t mv3310_hwmon_is_visible(const void *data,
104				       enum hwmon_sensor_types type,
105				       u32 attr, int channel)
106{
107	if (type == hwmon_chip && attr == hwmon_chip_update_interval)
108		return 0444;
109	if (type == hwmon_temp && attr == hwmon_temp_input)
110		return 0444;
111	return 0;
112}
113
114static int mv3310_hwmon_read_temp_reg(struct phy_device *phydev)
115{
116	return phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP);
117}
118
119static int mv2110_hwmon_read_temp_reg(struct phy_device *phydev)
120{
121	return phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_TEMP);
122}
123
124static int mv10g_hwmon_read_temp_reg(struct phy_device *phydev)
125{
126	if (phydev->drv->phy_id == MARVELL_PHY_ID_88X3310)
127		return mv3310_hwmon_read_temp_reg(phydev);
128	else /* MARVELL_PHY_ID_88E2110 */
129		return mv2110_hwmon_read_temp_reg(phydev);
130}
131
132static int mv3310_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
133			     u32 attr, int channel, long *value)
134{
135	struct phy_device *phydev = dev_get_drvdata(dev);
136	int temp;
137
138	if (type == hwmon_chip && attr == hwmon_chip_update_interval) {
139		*value = MSEC_PER_SEC;
140		return 0;
141	}
142
143	if (type == hwmon_temp && attr == hwmon_temp_input) {
144		temp = mv10g_hwmon_read_temp_reg(phydev);
145		if (temp < 0)
146			return temp;
147
148		*value = ((temp & 0xff) - 75) * 1000;
149
150		return 0;
151	}
152
153	return -EOPNOTSUPP;
154}
155
156static const struct hwmon_ops mv3310_hwmon_ops = {
157	.is_visible = mv3310_hwmon_is_visible,
158	.read = mv3310_hwmon_read,
159};
160
161static u32 mv3310_hwmon_chip_config[] = {
162	HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL,
163	0,
164};
165
166static const struct hwmon_channel_info mv3310_hwmon_chip = {
167	.type = hwmon_chip,
168	.config = mv3310_hwmon_chip_config,
169};
170
171static u32 mv3310_hwmon_temp_config[] = {
172	HWMON_T_INPUT,
173	0,
174};
175
176static const struct hwmon_channel_info mv3310_hwmon_temp = {
177	.type = hwmon_temp,
178	.config = mv3310_hwmon_temp_config,
179};
180
181static const struct hwmon_channel_info *mv3310_hwmon_info[] = {
182	&mv3310_hwmon_chip,
183	&mv3310_hwmon_temp,
184	NULL,
185};
186
187static const struct hwmon_chip_info mv3310_hwmon_chip_info = {
188	.ops = &mv3310_hwmon_ops,
189	.info = mv3310_hwmon_info,
190};
191
192static int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
193{
194	u16 val;
195	int ret;
196
197	if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310)
198		return 0;
199
200	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP,
201			    MV_V2_TEMP_UNKNOWN);
202	if (ret < 0)
203		return ret;
204
205	val = enable ? MV_V2_TEMP_CTRL_SAMPLE : MV_V2_TEMP_CTRL_DISABLE;
206
207	return phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_TEMP_CTRL,
208			      MV_V2_TEMP_CTRL_MASK, val);
209}
210
211static int mv3310_hwmon_probe(struct phy_device *phydev)
212{
213	struct device *dev = &phydev->mdio.dev;
214	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
215	int i, j, ret;
216
217	priv->hwmon_name = devm_kstrdup(dev, dev_name(dev), GFP_KERNEL);
218	if (!priv->hwmon_name)
219		return -ENODEV;
220
221	for (i = j = 0; priv->hwmon_name[i]; i++) {
222		if (isalnum(priv->hwmon_name[i])) {
223			if (i != j)
224				priv->hwmon_name[j] = priv->hwmon_name[i];
225			j++;
226		}
227	}
228	priv->hwmon_name[j] = '\0';
229
230	ret = mv3310_hwmon_config(phydev, true);
231	if (ret)
232		return ret;
233
234	priv->hwmon_dev = devm_hwmon_device_register_with_info(dev,
235				priv->hwmon_name, phydev,
236				&mv3310_hwmon_chip_info, NULL);
237
238	return PTR_ERR_OR_ZERO(priv->hwmon_dev);
239}
240#else
241static inline int mv3310_hwmon_config(struct phy_device *phydev, bool enable)
242{
243	return 0;
244}
245
246static int mv3310_hwmon_probe(struct phy_device *phydev)
247{
248	return 0;
249}
250#endif
251
252static int mv3310_power_down(struct phy_device *phydev)
253{
254	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
255				MV_V2_PORT_CTRL_PWRDOWN);
256}
257
258static int mv3310_power_up(struct phy_device *phydev)
259{
260	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
261	int ret;
262
263	ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
264				 MV_V2_PORT_CTRL_PWRDOWN);
265
266	/* Sometimes, the power down bit doesn't clear immediately, and
267	 * a read of this register causes the bit not to clear. Delay
268	 * 100us to allow the PHY to come out of power down mode before
269	 * the next access.
270	 */
271	udelay(100);
272
273	if (phydev->drv->phy_id != MARVELL_PHY_ID_88X3310 ||
274	    priv->firmware_ver < 0x00030000)
275		return ret;
276
277	return phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL,
278				MV_V2_PORT_CTRL_SWRST);
279}
280
281static int mv3310_reset(struct phy_device *phydev, u32 unit)
282{
283	int val, err;
284
285	err = phy_modify_mmd(phydev, MDIO_MMD_PCS, unit + MDIO_CTRL1,
286			     MDIO_CTRL1_RESET, MDIO_CTRL1_RESET);
287	if (err < 0)
288		return err;
289
290	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PCS,
291					 unit + MDIO_CTRL1, val,
292					 !(val & MDIO_CTRL1_RESET),
293					 5000, 100000, true);
294}
295
296static int mv3310_get_edpd(struct phy_device *phydev, u16 *edpd)
297{
298	int val;
299
300	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1);
301	if (val < 0)
302		return val;
303
304	switch (val & MV_PCS_CSCR1_ED_MASK) {
305	case MV_PCS_CSCR1_ED_NLP:
306		*edpd = 1000;
307		break;
308	case MV_PCS_CSCR1_ED_RX:
309		*edpd = ETHTOOL_PHY_EDPD_NO_TX;
310		break;
311	default:
312		*edpd = ETHTOOL_PHY_EDPD_DISABLE;
313		break;
314	}
315	return 0;
316}
317
318static int mv3310_set_edpd(struct phy_device *phydev, u16 edpd)
319{
320	u16 val;
321	int err;
322
323	switch (edpd) {
324	case 1000:
325	case ETHTOOL_PHY_EDPD_DFLT_TX_MSECS:
326		val = MV_PCS_CSCR1_ED_NLP;
327		break;
328
329	case ETHTOOL_PHY_EDPD_NO_TX:
330		val = MV_PCS_CSCR1_ED_RX;
331		break;
332
333	case ETHTOOL_PHY_EDPD_DISABLE:
334		val = MV_PCS_CSCR1_ED_OFF;
335		break;
336
337	default:
338		return -EINVAL;
339	}
340
341	err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
342				     MV_PCS_CSCR1_ED_MASK, val);
343	if (err > 0)
344		err = mv3310_reset(phydev, MV_PCS_BASE_T);
345
346	return err;
347}
348
349static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
350{
351	struct phy_device *phydev = upstream;
352	__ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, };
353	phy_interface_t iface;
354
355	sfp_parse_support(phydev->sfp_bus, id, support);
356	iface = sfp_select_interface(phydev->sfp_bus, support);
357
358	if (iface != PHY_INTERFACE_MODE_10GBASER) {
359		dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n");
360		return -EINVAL;
361	}
362	return 0;
363}
364
365static const struct sfp_upstream_ops mv3310_sfp_ops = {
366	.attach = phy_sfp_attach,
367	.detach = phy_sfp_detach,
368	.module_insert = mv3310_sfp_insert,
369};
370
371static int mv3310_probe(struct phy_device *phydev)
372{
373	struct mv3310_priv *priv;
374	u32 mmd_mask = MDIO_DEVS_PMAPMD | MDIO_DEVS_AN;
375	int ret;
376
377	if (!phydev->is_c45 ||
378	    (phydev->c45_ids.devices_in_package & mmd_mask) != mmd_mask)
379		return -ENODEV;
380
381	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_BOOT);
382	if (ret < 0)
383		return ret;
384
385	if (ret & MV_PMA_BOOT_FATAL) {
386		dev_warn(&phydev->mdio.dev,
387			 "PHY failed to boot firmware, status=%04x\n", ret);
388		return -ENODEV;
389	}
390
391	priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
392	if (!priv)
393		return -ENOMEM;
394
395	dev_set_drvdata(&phydev->mdio.dev, priv);
396
397	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER0);
398	if (ret < 0)
399		return ret;
400
401	priv->firmware_ver = ret << 16;
402
403	ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_PMA_FW_VER1);
404	if (ret < 0)
405		return ret;
406
407	priv->firmware_ver |= ret;
408
409	phydev_info(phydev, "Firmware version %u.%u.%u.%u\n",
410		    priv->firmware_ver >> 24, (priv->firmware_ver >> 16) & 255,
411		    (priv->firmware_ver >> 8) & 255, priv->firmware_ver & 255);
412
413	/* Powering down the port when not in use saves about 600mW */
414	ret = mv3310_power_down(phydev);
415	if (ret)
416		return ret;
417
418	ret = mv3310_hwmon_probe(phydev);
419	if (ret)
420		return ret;
421
422	return phy_sfp_probe(phydev, &mv3310_sfp_ops);
423}
424
425static void mv3310_remove(struct phy_device *phydev)
426{
427	mv3310_hwmon_config(phydev, false);
428}
429
430static int mv3310_suspend(struct phy_device *phydev)
431{
432	return mv3310_power_down(phydev);
433}
434
435static int mv3310_resume(struct phy_device *phydev)
436{
437	int ret;
438
439	ret = mv3310_power_up(phydev);
440	if (ret)
441		return ret;
442
443	return mv3310_hwmon_config(phydev, true);
444}
445
446/* Some PHYs in the Alaska family such as the 88X3310 and the 88E2010
447 * don't set bit 14 in PMA Extended Abilities (1.11), although they do
448 * support 2.5GBASET and 5GBASET. For these models, we can still read their
449 * 2.5G/5G extended abilities register (1.21). We detect these models based on
450 * the PMA device identifier, with a mask matching models known to have this
451 * issue
452 */
453static bool mv3310_has_pma_ngbaset_quirk(struct phy_device *phydev)
454{
455	if (!(phydev->c45_ids.devices_in_package & MDIO_DEVS_PMAPMD))
456		return false;
457
458	/* Only some revisions of the 88X3310 family PMA seem to be impacted */
459	return (phydev->c45_ids.device_ids[MDIO_MMD_PMAPMD] &
460		MV_PHY_ALASKA_NBT_QUIRK_MASK) == MV_PHY_ALASKA_NBT_QUIRK_REV;
461}
462
463static int mv3310_config_init(struct phy_device *phydev)
464{
465	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
466	int err;
467	int val;
468
469	/* Check that the PHY interface type is compatible */
470	if (phydev->interface != PHY_INTERFACE_MODE_SGMII &&
471	    phydev->interface != PHY_INTERFACE_MODE_2500BASEX &&
472	    phydev->interface != PHY_INTERFACE_MODE_XAUI &&
473	    phydev->interface != PHY_INTERFACE_MODE_RXAUI &&
474	    phydev->interface != PHY_INTERFACE_MODE_10GBASER)
475		return -ENODEV;
476
477	phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
478
479	/* Power up so reset works */
480	err = mv3310_power_up(phydev);
481	if (err)
482		return err;
483
484	val = phy_read_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL);
485	if (val < 0)
486		return val;
487	priv->rate_match = ((val & MV_V2_PORT_MAC_TYPE_MASK) ==
488			MV_V2_PORT_MAC_TYPE_RATE_MATCH);
489
490	/* Enable EDPD mode - saving 600mW */
491	return mv3310_set_edpd(phydev, ETHTOOL_PHY_EDPD_DFLT_TX_MSECS);
492}
493
494static int mv3310_get_features(struct phy_device *phydev)
495{
496	int ret, val;
497
498	ret = genphy_c45_pma_read_abilities(phydev);
499	if (ret)
500		return ret;
501
502	if (mv3310_has_pma_ngbaset_quirk(phydev)) {
503		val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
504				   MDIO_PMA_NG_EXTABLE);
505		if (val < 0)
506			return val;
507
508		linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
509				 phydev->supported,
510				 val & MDIO_PMA_NG_EXTABLE_2_5GBT);
511
512		linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
513				 phydev->supported,
514				 val & MDIO_PMA_NG_EXTABLE_5GBT);
515	}
516
517	return 0;
518}
519
520static int mv3310_config_mdix(struct phy_device *phydev)
521{
522	u16 val;
523	int err;
524
525	switch (phydev->mdix_ctrl) {
526	case ETH_TP_MDI_AUTO:
527		val = MV_PCS_CSCR1_MDIX_AUTO;
528		break;
529	case ETH_TP_MDI_X:
530		val = MV_PCS_CSCR1_MDIX_MDIX;
531		break;
532	case ETH_TP_MDI:
533		val = MV_PCS_CSCR1_MDIX_MDI;
534		break;
535	default:
536		return -EINVAL;
537	}
538
539	err = phy_modify_mmd_changed(phydev, MDIO_MMD_PCS, MV_PCS_CSCR1,
540				     MV_PCS_CSCR1_MDIX_MASK, val);
541	if (err > 0)
542		err = mv3310_reset(phydev, MV_PCS_BASE_T);
543
544	return err;
545}
546
547static int mv3310_config_aneg(struct phy_device *phydev)
548{
549	bool changed = false;
550	u16 reg;
551	int ret;
552
553	ret = mv3310_config_mdix(phydev);
554	if (ret < 0)
555		return ret;
556
557	if (phydev->autoneg == AUTONEG_DISABLE)
558		return genphy_c45_pma_setup_forced(phydev);
559
560	ret = genphy_c45_an_config_aneg(phydev);
561	if (ret < 0)
562		return ret;
563	if (ret > 0)
564		changed = true;
565
566	/* Clause 45 has no standardized support for 1000BaseT, therefore
567	 * use vendor registers for this mode.
568	 */
569	reg = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
570	ret = phy_modify_mmd_changed(phydev, MDIO_MMD_AN, MV_AN_CTRL1000,
571			     ADVERTISE_1000FULL | ADVERTISE_1000HALF, reg);
572	if (ret < 0)
573		return ret;
574	if (ret > 0)
575		changed = true;
576
577	return genphy_c45_check_and_restart_aneg(phydev, changed);
578}
579
580static int mv3310_aneg_done(struct phy_device *phydev)
581{
582	int val;
583
584	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
585	if (val < 0)
586		return val;
587
588	if (val & MDIO_STAT1_LSTATUS)
589		return 1;
590
591	return genphy_c45_aneg_done(phydev);
592}
593
594static void mv3310_update_interface(struct phy_device *phydev)
595{
596	struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev);
597
598	/* In "XFI with Rate Matching" mode the PHY interface is fixed at
599	 * 10Gb. The PHY adapts the rate to actual wire speed with help of
600	 * internal 16KB buffer.
601	 */
602	if (priv->rate_match) {
603		phydev->interface = PHY_INTERFACE_MODE_10GBASER;
604		return;
605	}
606
607	if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
608	     phydev->interface == PHY_INTERFACE_MODE_2500BASEX ||
609	     phydev->interface == PHY_INTERFACE_MODE_10GBASER) &&
610	    phydev->link) {
611		/* The PHY automatically switches its serdes interface (and
612		 * active PHYXS instance) between Cisco SGMII, 10GBase-R and
613		 * 2500BaseX modes according to the speed.  Florian suggests
614		 * setting phydev->interface to communicate this to the MAC.
615		 * Only do this if we are already in one of the above modes.
616		 */
617		switch (phydev->speed) {
618		case SPEED_10000:
619			phydev->interface = PHY_INTERFACE_MODE_10GBASER;
620			break;
621		case SPEED_2500:
622			phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
623			break;
624		case SPEED_1000:
625		case SPEED_100:
626		case SPEED_10:
627			phydev->interface = PHY_INTERFACE_MODE_SGMII;
628			break;
629		default:
630			break;
631		}
632	}
633}
634
635/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
636static int mv3310_read_status_10gbaser(struct phy_device *phydev)
637{
638	phydev->link = 1;
639	phydev->speed = SPEED_10000;
640	phydev->duplex = DUPLEX_FULL;
641	phydev->port = PORT_FIBRE;
642
643	return 0;
644}
645
646static int mv3310_read_status_copper(struct phy_device *phydev)
647{
648	int cssr1, speed, val;
649
650	val = genphy_c45_read_link(phydev);
651	if (val < 0)
652		return val;
653
654	val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_STAT1);
655	if (val < 0)
656		return val;
657
658	cssr1 = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_CSSR1);
659	if (cssr1 < 0)
660		return cssr1;
661
662	/* If the link settings are not resolved, mark the link down */
663	if (!(cssr1 & MV_PCS_CSSR1_RESOLVED)) {
664		phydev->link = 0;
665		return 0;
666	}
667
668	/* Read the copper link settings */
669	speed = cssr1 & MV_PCS_CSSR1_SPD1_MASK;
670	if (speed == MV_PCS_CSSR1_SPD1_SPD2)
671		speed |= cssr1 & MV_PCS_CSSR1_SPD2_MASK;
672
673	switch (speed) {
674	case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_10000:
675		phydev->speed = SPEED_10000;
676		break;
677
678	case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_5000:
679		phydev->speed = SPEED_5000;
680		break;
681
682	case MV_PCS_CSSR1_SPD1_SPD2 | MV_PCS_CSSR1_SPD2_2500:
683		phydev->speed = SPEED_2500;
684		break;
685
686	case MV_PCS_CSSR1_SPD1_1000:
687		phydev->speed = SPEED_1000;
688		break;
689
690	case MV_PCS_CSSR1_SPD1_100:
691		phydev->speed = SPEED_100;
692		break;
693
694	case MV_PCS_CSSR1_SPD1_10:
695		phydev->speed = SPEED_10;
696		break;
697	}
698
699	phydev->duplex = cssr1 & MV_PCS_CSSR1_DUPLEX_FULL ?
700			 DUPLEX_FULL : DUPLEX_HALF;
701	phydev->port = PORT_TP;
702	phydev->mdix = cssr1 & MV_PCS_CSSR1_MDIX ?
703		       ETH_TP_MDI_X : ETH_TP_MDI;
704
705	if (val & MDIO_AN_STAT1_COMPLETE) {
706		val = genphy_c45_read_lpa(phydev);
707		if (val < 0)
708			return val;
709
710		/* Read the link partner's 1G advertisement */
711		val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_STAT1000);
712		if (val < 0)
713			return val;
714
715		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, val);
716
717		/* Update the pause status */
718		phy_resolve_aneg_pause(phydev);
719	}
720
721	return 0;
722}
723
724static int mv3310_read_status(struct phy_device *phydev)
725{
726	int err, val;
727
728	phydev->speed = SPEED_UNKNOWN;
729	phydev->duplex = DUPLEX_UNKNOWN;
730	linkmode_zero(phydev->lp_advertising);
731	phydev->link = 0;
732	phydev->pause = 0;
733	phydev->asym_pause = 0;
734	phydev->mdix = ETH_TP_MDI_INVALID;
735
736	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
737	if (val < 0)
738		return val;
739
740	if (val & MDIO_STAT1_LSTATUS)
741		err = mv3310_read_status_10gbaser(phydev);
742	else
743		err = mv3310_read_status_copper(phydev);
744	if (err < 0)
745		return err;
746
747	if (phydev->link)
748		mv3310_update_interface(phydev);
749
750	return 0;
751}
752
753static int mv3310_get_tunable(struct phy_device *phydev,
754			      struct ethtool_tunable *tuna, void *data)
755{
756	switch (tuna->id) {
757	case ETHTOOL_PHY_EDPD:
758		return mv3310_get_edpd(phydev, data);
759	default:
760		return -EOPNOTSUPP;
761	}
762}
763
764static int mv3310_set_tunable(struct phy_device *phydev,
765			      struct ethtool_tunable *tuna, const void *data)
766{
767	switch (tuna->id) {
768	case ETHTOOL_PHY_EDPD:
769		return mv3310_set_edpd(phydev, *(u16 *)data);
770	default:
771		return -EOPNOTSUPP;
772	}
773}
774
775static struct phy_driver mv3310_drivers[] = {
776	{
777		.phy_id		= MARVELL_PHY_ID_88X3310,
778		.phy_id_mask	= MARVELL_PHY_ID_MASK,
779		.name		= "mv88x3310",
780		.get_features	= mv3310_get_features,
781		.config_init	= mv3310_config_init,
782		.probe		= mv3310_probe,
783		.suspend	= mv3310_suspend,
784		.resume		= mv3310_resume,
785		.config_aneg	= mv3310_config_aneg,
786		.aneg_done	= mv3310_aneg_done,
787		.read_status	= mv3310_read_status,
788		.get_tunable	= mv3310_get_tunable,
789		.set_tunable	= mv3310_set_tunable,
790		.remove		= mv3310_remove,
791	},
792	{
793		.phy_id		= MARVELL_PHY_ID_88E2110,
794		.phy_id_mask	= MARVELL_PHY_ID_MASK,
795		.name		= "mv88x2110",
796		.probe		= mv3310_probe,
797		.suspend	= mv3310_suspend,
798		.resume		= mv3310_resume,
799		.config_init	= mv3310_config_init,
800		.config_aneg	= mv3310_config_aneg,
801		.aneg_done	= mv3310_aneg_done,
802		.read_status	= mv3310_read_status,
803		.get_tunable	= mv3310_get_tunable,
804		.set_tunable	= mv3310_set_tunable,
805		.remove		= mv3310_remove,
806	},
807};
808
809module_phy_driver(mv3310_drivers);
810
811static struct mdio_device_id __maybe_unused mv3310_tbl[] = {
812	{ MARVELL_PHY_ID_88X3310, MARVELL_PHY_ID_MASK },
813	{ MARVELL_PHY_ID_88E2110, MARVELL_PHY_ID_MASK },
814	{ },
815};
816MODULE_DEVICE_TABLE(mdio, mv3310_tbl);
817MODULE_DESCRIPTION("Marvell Alaska X 10Gigabit Ethernet PHY driver (MV88X3310)");
818MODULE_LICENSE("GPL");
819