1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Marvell 88x2222 dual-port multi-speed ethernet transceiver.
4  *
5  * Supports:
6  *	XAUI on the host side.
7  *	1000Base-X or 10GBase-R on the line side.
8  *	SGMII over 1000Base-X.
9  */
10 #include <linux/module.h>
11 #include <linux/phy.h>
12 #include <linux/gpio.h>
13 #include <linux/delay.h>
14 #include <linux/mdio.h>
15 #include <linux/marvell_phy.h>
16 #include <linux/of.h>
17 #include <linux/of_device.h>
18 #include <linux/of_gpio.h>
19 #include <linux/sfp.h>
20 #include <linux/netdevice.h>
21 
22 /* Port PCS Configuration */
23 #define	MV_PCS_CONFIG		0xF002
24 #define	MV_PCS_HOST_XAUI	0x73
25 #define	MV_PCS_LINE_10GBR	(0x71 << 8)
26 #define	MV_PCS_LINE_1GBX_AN	(0x7B << 8)
27 #define	MV_PCS_LINE_SGMII_AN	(0x7F << 8)
28 
29 /* Port Reset and Power Down */
30 #define	MV_PORT_RST	0xF003
31 #define	MV_LINE_RST_SW	BIT(15)
32 #define	MV_HOST_RST_SW	BIT(7)
33 #define	MV_PORT_RST_SW	(MV_LINE_RST_SW | MV_HOST_RST_SW)
34 
35 /* PMD Receive Signal Detect */
36 #define	MV_RX_SIGNAL_DETECT		0x000A
37 #define	MV_RX_SIGNAL_DETECT_GLOBAL	BIT(0)
38 
39 /* 1000Base-X/SGMII Control Register */
40 #define	MV_1GBX_CTRL		(0x2000 + MII_BMCR)
41 
42 /* 1000BASE-X/SGMII Status Register */
43 #define	MV_1GBX_STAT		(0x2000 + MII_BMSR)
44 
45 /* 1000Base-X Auto-Negotiation Advertisement Register */
46 #define	MV_1GBX_ADVERTISE	(0x2000 + MII_ADVERTISE)
47 
48 /* 1000Base-X PHY Specific Status Register */
49 #define	MV_1GBX_PHY_STAT		0xA003
50 #define	MV_1GBX_PHY_STAT_AN_RESOLVED	BIT(11)
51 #define	MV_1GBX_PHY_STAT_DUPLEX		BIT(13)
52 #define	MV_1GBX_PHY_STAT_SPEED100	BIT(14)
53 #define	MV_1GBX_PHY_STAT_SPEED1000	BIT(15)
54 
55 struct mv2222_data {
56 	phy_interface_t line_interface;
57 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
58 	bool sfp_link;
59 };
60 
61 /* SFI PMA transmit enable */
62 static int mv2222_tx_enable(struct phy_device *phydev)
63 {
64 	return phy_clear_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
65 				  MDIO_PMD_TXDIS_GLOBAL);
66 }
67 
68 /* SFI PMA transmit disable */
69 static int mv2222_tx_disable(struct phy_device *phydev)
70 {
71 	return phy_set_bits_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_TXDIS,
72 				MDIO_PMD_TXDIS_GLOBAL);
73 }
74 
75 static int mv2222_soft_reset(struct phy_device *phydev)
76 {
77 	int val, ret;
78 
79 	ret = phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PORT_RST,
80 			    MV_PORT_RST_SW);
81 	if (ret < 0)
82 		return ret;
83 
84 	return phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_PORT_RST,
85 					 val, !(val & MV_PORT_RST_SW),
86 					 5000, 1000000, true);
87 }
88 
89 static int mv2222_disable_aneg(struct phy_device *phydev)
90 {
91 	int ret = phy_clear_bits_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_CTRL,
92 				     BMCR_ANENABLE | BMCR_ANRESTART);
93 	if (ret < 0)
94 		return ret;
95 
96 	return mv2222_soft_reset(phydev);
97 }
98 
99 static int mv2222_enable_aneg(struct phy_device *phydev)
100 {
101 	int ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_CTRL,
102 				   BMCR_ANENABLE | BMCR_RESET);
103 	if (ret < 0)
104 		return ret;
105 
106 	return mv2222_soft_reset(phydev);
107 }
108 
109 static int mv2222_set_sgmii_speed(struct phy_device *phydev)
110 {
111 	struct mv2222_data *priv = phydev->priv;
112 
113 	switch (phydev->speed) {
114 	default:
115 	case SPEED_1000:
116 		if ((linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
117 				       priv->supported) ||
118 		     linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
119 				       priv->supported)))
120 			return phy_modify_mmd(phydev, MDIO_MMD_PCS,
121 					      MV_1GBX_CTRL,
122 					      BMCR_SPEED1000 | BMCR_SPEED100,
123 					      BMCR_SPEED1000);
124 
125 		fallthrough;
126 	case SPEED_100:
127 		if ((linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
128 				       priv->supported) ||
129 		     linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
130 				       priv->supported)))
131 			return phy_modify_mmd(phydev, MDIO_MMD_PCS,
132 					      MV_1GBX_CTRL,
133 					      BMCR_SPEED1000 | BMCR_SPEED100,
134 					      BMCR_SPEED100);
135 		fallthrough;
136 	case SPEED_10:
137 		if ((linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
138 				       priv->supported) ||
139 		     linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
140 				       priv->supported)))
141 			return phy_modify_mmd(phydev, MDIO_MMD_PCS,
142 					      MV_1GBX_CTRL,
143 					      BMCR_SPEED1000 | BMCR_SPEED100,
144 					      BMCR_SPEED10);
145 
146 		return -EINVAL;
147 	}
148 }
149 
150 static bool mv2222_is_10g_capable(struct phy_device *phydev)
151 {
152 	struct mv2222_data *priv = phydev->priv;
153 
154 	return (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
155 				  priv->supported) ||
156 		linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
157 				  priv->supported) ||
158 		linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
159 				  priv->supported) ||
160 		linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
161 				  priv->supported) ||
162 		linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT,
163 				  priv->supported) ||
164 		linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
165 				  priv->supported));
166 }
167 
168 static bool mv2222_is_1gbx_capable(struct phy_device *phydev)
169 {
170 	struct mv2222_data *priv = phydev->priv;
171 
172 	return linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT,
173 				 priv->supported);
174 }
175 
176 static int mv2222_config_line(struct phy_device *phydev)
177 {
178 	struct mv2222_data *priv = phydev->priv;
179 
180 	switch (priv->line_interface) {
181 	case PHY_INTERFACE_MODE_10GBASER:
182 		return phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG,
183 				     MV_PCS_HOST_XAUI | MV_PCS_LINE_10GBR);
184 	case PHY_INTERFACE_MODE_1000BASEX:
185 		return phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG,
186 				     MV_PCS_HOST_XAUI | MV_PCS_LINE_1GBX_AN);
187 	case PHY_INTERFACE_MODE_SGMII:
188 		return phy_write_mmd(phydev, MDIO_MMD_VEND2, MV_PCS_CONFIG,
189 				     MV_PCS_HOST_XAUI | MV_PCS_LINE_SGMII_AN);
190 	default:
191 		return -EINVAL;
192 	}
193 }
194 
195 static int mv2222_setup_forced(struct phy_device *phydev)
196 {
197 	struct mv2222_data *priv = phydev->priv;
198 	bool changed = false;
199 	int ret;
200 
201 	switch (priv->line_interface) {
202 	case PHY_INTERFACE_MODE_10GBASER:
203 		if (phydev->speed == SPEED_1000 &&
204 		    mv2222_is_1gbx_capable(phydev)) {
205 			priv->line_interface = PHY_INTERFACE_MODE_1000BASEX;
206 			changed = true;
207 		}
208 
209 		break;
210 	case PHY_INTERFACE_MODE_1000BASEX:
211 		if (phydev->speed == SPEED_10000 &&
212 		    mv2222_is_10g_capable(phydev)) {
213 			priv->line_interface = PHY_INTERFACE_MODE_10GBASER;
214 			changed = true;
215 		}
216 
217 		break;
218 	case PHY_INTERFACE_MODE_SGMII:
219 		ret = mv2222_set_sgmii_speed(phydev);
220 		if (ret < 0)
221 			return ret;
222 
223 		break;
224 	default:
225 		return -EINVAL;
226 	}
227 
228 	if (changed) {
229 		ret = mv2222_config_line(phydev);
230 		if (ret < 0)
231 			return ret;
232 	}
233 
234 	return mv2222_disable_aneg(phydev);
235 }
236 
237 static int mv2222_config_aneg(struct phy_device *phydev)
238 {
239 	struct mv2222_data *priv = phydev->priv;
240 	int ret, adv;
241 
242 	/* SFP is not present, do nothing */
243 	if (priv->line_interface == PHY_INTERFACE_MODE_NA)
244 		return 0;
245 
246 	if (phydev->autoneg == AUTONEG_DISABLE ||
247 	    phydev->speed == SPEED_10000)
248 		return mv2222_setup_forced(phydev);
249 
250 	if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER &&
251 	    mv2222_is_1gbx_capable(phydev)) {
252 		priv->line_interface = PHY_INTERFACE_MODE_1000BASEX;
253 		ret = mv2222_config_line(phydev);
254 		if (ret < 0)
255 			return ret;
256 	}
257 
258 	adv = linkmode_adv_to_mii_adv_x(priv->supported,
259 					ETHTOOL_LINK_MODE_1000baseX_Full_BIT);
260 
261 	ret = phy_modify_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_ADVERTISE,
262 			     ADVERTISE_1000XFULL |
263 			     ADVERTISE_1000XPAUSE | ADVERTISE_1000XPSE_ASYM,
264 			     adv);
265 	if (ret < 0)
266 		return ret;
267 
268 	return mv2222_enable_aneg(phydev);
269 }
270 
271 static int mv2222_aneg_done(struct phy_device *phydev)
272 {
273 	int ret;
274 
275 	if (mv2222_is_10g_capable(phydev)) {
276 		ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1);
277 		if (ret < 0)
278 			return ret;
279 
280 		if (ret & MDIO_STAT1_LSTATUS)
281 			return 1;
282 	}
283 
284 	ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT);
285 	if (ret < 0)
286 		return ret;
287 
288 	return (ret & BMSR_ANEGCOMPLETE);
289 }
290 
291 /* Returns negative on error, 0 if link is down, 1 if link is up */
292 static int mv2222_read_status_10g(struct phy_device *phydev)
293 {
294 	int val, link = 0;
295 
296 	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1);
297 	if (val < 0)
298 		return val;
299 
300 	if (val & MDIO_STAT1_LSTATUS) {
301 		link = 1;
302 
303 		/* 10GBASE-R do not support auto-negotiation */
304 		phydev->autoneg = AUTONEG_DISABLE;
305 		phydev->speed = SPEED_10000;
306 		phydev->duplex = DUPLEX_FULL;
307 	}
308 
309 	return link;
310 }
311 
312 /* Returns negative on error, 0 if link is down, 1 if link is up */
313 static int mv2222_read_status_1g(struct phy_device *phydev)
314 {
315 	int val, link = 0;
316 
317 	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT);
318 	if (val < 0)
319 		return val;
320 
321 	if (!(val & BMSR_LSTATUS) ||
322 	    (phydev->autoneg == AUTONEG_ENABLE &&
323 	     !(val & BMSR_ANEGCOMPLETE)))
324 		return 0;
325 
326 	link = 1;
327 
328 	val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_PHY_STAT);
329 	if (val < 0)
330 		return val;
331 
332 	if (val & MV_1GBX_PHY_STAT_AN_RESOLVED) {
333 		if (val & MV_1GBX_PHY_STAT_DUPLEX)
334 			phydev->duplex = DUPLEX_FULL;
335 		else
336 			phydev->duplex = DUPLEX_HALF;
337 
338 		if (val & MV_1GBX_PHY_STAT_SPEED1000)
339 			phydev->speed = SPEED_1000;
340 		else if (val & MV_1GBX_PHY_STAT_SPEED100)
341 			phydev->speed = SPEED_100;
342 		else
343 			phydev->speed = SPEED_10;
344 	}
345 
346 	return link;
347 }
348 
349 static bool mv2222_link_is_operational(struct phy_device *phydev)
350 {
351 	struct mv2222_data *priv = phydev->priv;
352 	int val;
353 
354 	val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MV_RX_SIGNAL_DETECT);
355 	if (val < 0 || !(val & MV_RX_SIGNAL_DETECT_GLOBAL))
356 		return false;
357 
358 	if (phydev->sfp_bus && !priv->sfp_link)
359 		return false;
360 
361 	return true;
362 }
363 
364 static int mv2222_read_status(struct phy_device *phydev)
365 {
366 	struct mv2222_data *priv = phydev->priv;
367 	int link;
368 
369 	phydev->link = 0;
370 	phydev->speed = SPEED_UNKNOWN;
371 	phydev->duplex = DUPLEX_UNKNOWN;
372 
373 	if (!mv2222_link_is_operational(phydev))
374 		return 0;
375 
376 	if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER)
377 		link = mv2222_read_status_10g(phydev);
378 	else
379 		link = mv2222_read_status_1g(phydev);
380 
381 	if (link < 0)
382 		return link;
383 
384 	phydev->link = link;
385 
386 	return 0;
387 }
388 
389 static int mv2222_resume(struct phy_device *phydev)
390 {
391 	return mv2222_tx_enable(phydev);
392 }
393 
394 static int mv2222_suspend(struct phy_device *phydev)
395 {
396 	return mv2222_tx_disable(phydev);
397 }
398 
399 static int mv2222_get_features(struct phy_device *phydev)
400 {
401 	/* All supported linkmodes are set at probe */
402 
403 	return 0;
404 }
405 
406 static int mv2222_config_init(struct phy_device *phydev)
407 {
408 	if (phydev->interface != PHY_INTERFACE_MODE_XAUI)
409 		return -EINVAL;
410 
411 	phydev->autoneg = AUTONEG_DISABLE;
412 
413 	return 0;
414 }
415 
416 static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id)
417 {
418 	struct phy_device *phydev = upstream;
419 	phy_interface_t sfp_interface;
420 	struct mv2222_data *priv;
421 	struct device *dev;
422 	int ret;
423 
424 	__ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_supported) = { 0, };
425 
426 	priv = (struct mv2222_data *)phydev->priv;
427 	dev = &phydev->mdio.dev;
428 
429 	sfp_parse_support(phydev->sfp_bus, id, sfp_supported);
430 	sfp_interface = sfp_select_interface(phydev->sfp_bus, sfp_supported);
431 
432 	dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface));
433 
434 	if (sfp_interface != PHY_INTERFACE_MODE_10GBASER &&
435 	    sfp_interface != PHY_INTERFACE_MODE_1000BASEX &&
436 	    sfp_interface != PHY_INTERFACE_MODE_SGMII) {
437 		dev_err(dev, "Incompatible SFP module inserted\n");
438 
439 		return -EINVAL;
440 	}
441 
442 	priv->line_interface = sfp_interface;
443 	linkmode_and(priv->supported, phydev->supported, sfp_supported);
444 
445 	ret = mv2222_config_line(phydev);
446 	if (ret < 0)
447 		return ret;
448 
449 	if (mutex_trylock(&phydev->lock)) {
450 		if (priv->line_interface == PHY_INTERFACE_MODE_10GBASER)
451 			ret = mv2222_setup_forced(phydev);
452 		else
453 			ret = mv2222_config_aneg(phydev);
454 
455 		mutex_unlock(&phydev->lock);
456 	}
457 
458 	return ret;
459 }
460 
461 static void mv2222_sfp_remove(void *upstream)
462 {
463 	struct phy_device *phydev = upstream;
464 	struct mv2222_data *priv;
465 
466 	priv = (struct mv2222_data *)phydev->priv;
467 
468 	priv->line_interface = PHY_INTERFACE_MODE_NA;
469 	linkmode_zero(priv->supported);
470 }
471 
472 static void mv2222_sfp_link_up(void *upstream)
473 {
474 	struct phy_device *phydev = upstream;
475 	struct mv2222_data *priv;
476 
477 	priv = phydev->priv;
478 	priv->sfp_link = true;
479 }
480 
481 static void mv2222_sfp_link_down(void *upstream)
482 {
483 	struct phy_device *phydev = upstream;
484 	struct mv2222_data *priv;
485 
486 	priv = phydev->priv;
487 	priv->sfp_link = false;
488 }
489 
490 static const struct sfp_upstream_ops sfp_phy_ops = {
491 	.module_insert = mv2222_sfp_insert,
492 	.module_remove = mv2222_sfp_remove,
493 	.link_up = mv2222_sfp_link_up,
494 	.link_down = mv2222_sfp_link_down,
495 	.attach = phy_sfp_attach,
496 	.detach = phy_sfp_detach,
497 };
498 
499 static int mv2222_probe(struct phy_device *phydev)
500 {
501 	struct device *dev = &phydev->mdio.dev;
502 	struct mv2222_data *priv = NULL;
503 
504 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0, };
505 
506 	linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, supported);
507 	linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, supported);
508 	linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, supported);
509 	linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, supported);
510 	linkmode_set_bit(ETHTOOL_LINK_MODE_TP_BIT, supported);
511 	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported);
512 	linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported);
513 	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, supported);
514 	linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, supported);
515 	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, supported);
516 	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, supported);
517 	linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, supported);
518 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, supported);
519 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, supported);
520 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, supported);
521 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, supported);
522 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, supported);
523 	linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, supported);
524 
525 	linkmode_copy(phydev->supported, supported);
526 
527 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
528 	if (!priv)
529 		return -ENOMEM;
530 
531 	priv->line_interface = PHY_INTERFACE_MODE_NA;
532 	phydev->priv = priv;
533 
534 	return phy_sfp_probe(phydev, &sfp_phy_ops);
535 }
536 
537 static struct phy_driver mv2222_drivers[] = {
538 	{
539 		.phy_id = MARVELL_PHY_ID_88X2222,
540 		.phy_id_mask = MARVELL_PHY_ID_MASK,
541 		.name = "Marvell 88X2222",
542 		.get_features = mv2222_get_features,
543 		.soft_reset = mv2222_soft_reset,
544 		.config_init = mv2222_config_init,
545 		.config_aneg = mv2222_config_aneg,
546 		.aneg_done = mv2222_aneg_done,
547 		.probe = mv2222_probe,
548 		.suspend = mv2222_suspend,
549 		.resume = mv2222_resume,
550 		.read_status = mv2222_read_status,
551 	},
552 };
553 module_phy_driver(mv2222_drivers);
554 
555 static struct mdio_device_id __maybe_unused mv2222_tbl[] = {
556 	{ MARVELL_PHY_ID_88X2222, MARVELL_PHY_ID_MASK },
557 	{ }
558 };
559 MODULE_DEVICE_TABLE(mdio, mv2222_tbl);
560 
561 MODULE_DESCRIPTION("Marvell 88x2222 ethernet transceiver driver");
562 MODULE_LICENSE("GPL");
563