xref: /openbmc/linux/drivers/net/phy/mxl-gpy.c (revision dff03381)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Copyright (C) 2021 Maxlinear Corporation
3  * Copyright (C) 2020 Intel Corporation
4  *
5  * Drivers for Maxlinear Ethernet GPY
6  *
7  */
8 
9 #include <linux/module.h>
10 #include <linux/bitfield.h>
11 #include <linux/hwmon.h>
12 #include <linux/phy.h>
13 #include <linux/polynomial.h>
14 #include <linux/netdevice.h>
15 
16 /* PHY ID */
17 #define PHY_ID_GPYx15B_MASK	0xFFFFFFFC
18 #define PHY_ID_GPY21xB_MASK	0xFFFFFFF9
19 #define PHY_ID_GPY2xx		0x67C9DC00
20 #define PHY_ID_GPY115B		0x67C9DF00
21 #define PHY_ID_GPY115C		0x67C9DF10
22 #define PHY_ID_GPY211B		0x67C9DE08
23 #define PHY_ID_GPY211C		0x67C9DE10
24 #define PHY_ID_GPY212B		0x67C9DE09
25 #define PHY_ID_GPY212C		0x67C9DE20
26 #define PHY_ID_GPY215B		0x67C9DF04
27 #define PHY_ID_GPY215C		0x67C9DF20
28 #define PHY_ID_GPY241B		0x67C9DE40
29 #define PHY_ID_GPY241BM		0x67C9DE80
30 #define PHY_ID_GPY245B		0x67C9DEC0
31 
32 #define PHY_MIISTAT		0x18	/* MII state */
33 #define PHY_IMASK		0x19	/* interrupt mask */
34 #define PHY_ISTAT		0x1A	/* interrupt status */
35 #define PHY_FWV			0x1E	/* firmware version */
36 
37 #define PHY_MIISTAT_SPD_MASK	GENMASK(2, 0)
38 #define PHY_MIISTAT_DPX		BIT(3)
39 #define PHY_MIISTAT_LS		BIT(10)
40 
41 #define PHY_MIISTAT_SPD_10	0
42 #define PHY_MIISTAT_SPD_100	1
43 #define PHY_MIISTAT_SPD_1000	2
44 #define PHY_MIISTAT_SPD_2500	4
45 
46 #define PHY_IMASK_WOL		BIT(15)	/* Wake-on-LAN */
47 #define PHY_IMASK_ANC		BIT(10)	/* Auto-Neg complete */
48 #define PHY_IMASK_ADSC		BIT(5)	/* Link auto-downspeed detect */
49 #define PHY_IMASK_DXMC		BIT(2)	/* Duplex mode change */
50 #define PHY_IMASK_LSPC		BIT(1)	/* Link speed change */
51 #define PHY_IMASK_LSTC		BIT(0)	/* Link state change */
52 #define PHY_IMASK_MASK		(PHY_IMASK_LSTC | \
53 				 PHY_IMASK_LSPC | \
54 				 PHY_IMASK_DXMC | \
55 				 PHY_IMASK_ADSC | \
56 				 PHY_IMASK_ANC)
57 
58 #define PHY_FWV_REL_MASK	BIT(15)
59 #define PHY_FWV_MAJOR_MASK	GENMASK(11, 8)
60 #define PHY_FWV_MINOR_MASK	GENMASK(7, 0)
61 
62 /* SGMII */
63 #define VSPEC1_SGMII_CTRL	0x08
64 #define VSPEC1_SGMII_CTRL_ANEN	BIT(12)		/* Aneg enable */
65 #define VSPEC1_SGMII_CTRL_ANRS	BIT(9)		/* Restart Aneg */
66 #define VSPEC1_SGMII_ANEN_ANRS	(VSPEC1_SGMII_CTRL_ANEN | \
67 				 VSPEC1_SGMII_CTRL_ANRS)
68 
69 /* Temperature sensor */
70 #define VPSPEC1_TEMP_STA	0x0E
71 #define VPSPEC1_TEMP_STA_DATA	GENMASK(9, 0)
72 
73 /* WoL */
74 #define VPSPEC2_WOL_CTL		0x0E06
75 #define VPSPEC2_WOL_AD01	0x0E08
76 #define VPSPEC2_WOL_AD23	0x0E09
77 #define VPSPEC2_WOL_AD45	0x0E0A
78 #define WOL_EN			BIT(0)
79 
80 struct gpy_priv {
81 	u8 fw_major;
82 	u8 fw_minor;
83 };
84 
85 static const struct {
86 	int major;
87 	int minor;
88 } ver_need_sgmii_reaneg[] = {
89 	{7, 0x6D},
90 	{8, 0x6D},
91 	{9, 0x73},
92 };
93 
94 #if IS_ENABLED(CONFIG_HWMON)
95 /* The original translation formulae of the temperature (in degrees of Celsius)
96  * are as follows:
97  *
98  *   T = -2.5761e-11*(N^4) + 9.7332e-8*(N^3) + -1.9165e-4*(N^2) +
99  *       3.0762e-1*(N^1) + -5.2156e1
100  *
101  * where [-52.156, 137.961]C and N = [0, 1023].
102  *
103  * They must be accordingly altered to be suitable for the integer arithmetics.
104  * The technique is called 'factor redistribution', which just makes sure the
105  * multiplications and divisions are made so to have a result of the operations
106  * within the integer numbers limit. In addition we need to translate the
107  * formulae to accept millidegrees of Celsius. Here what it looks like after
108  * the alterations:
109  *
110  *   T = -25761e-12*(N^4) + 97332e-9*(N^3) + -191650e-6*(N^2) +
111  *       307620e-3*(N^1) + -52156
112  *
113  * where T = [-52156, 137961]mC and N = [0, 1023].
114  */
115 static const struct polynomial poly_N_to_temp = {
116 	.terms = {
117 		{4,  -25761, 1000, 1},
118 		{3,   97332, 1000, 1},
119 		{2, -191650, 1000, 1},
120 		{1,  307620, 1000, 1},
121 		{0,  -52156,    1, 1}
122 	}
123 };
124 
125 static int gpy_hwmon_read(struct device *dev,
126 			  enum hwmon_sensor_types type,
127 			  u32 attr, int channel, long *value)
128 {
129 	struct phy_device *phydev = dev_get_drvdata(dev);
130 	int ret;
131 
132 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VPSPEC1_TEMP_STA);
133 	if (ret < 0)
134 		return ret;
135 	if (!ret)
136 		return -ENODATA;
137 
138 	*value = polynomial_calc(&poly_N_to_temp,
139 				 FIELD_GET(VPSPEC1_TEMP_STA_DATA, ret));
140 
141 	return 0;
142 }
143 
144 static umode_t gpy_hwmon_is_visible(const void *data,
145 				    enum hwmon_sensor_types type,
146 				    u32 attr, int channel)
147 {
148 	return 0444;
149 }
150 
151 static const struct hwmon_channel_info *gpy_hwmon_info[] = {
152 	HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
153 	NULL
154 };
155 
156 static const struct hwmon_ops gpy_hwmon_hwmon_ops = {
157 	.is_visible	= gpy_hwmon_is_visible,
158 	.read		= gpy_hwmon_read,
159 };
160 
161 static const struct hwmon_chip_info gpy_hwmon_chip_info = {
162 	.ops		= &gpy_hwmon_hwmon_ops,
163 	.info		= gpy_hwmon_info,
164 };
165 
166 static int gpy_hwmon_register(struct phy_device *phydev)
167 {
168 	struct device *dev = &phydev->mdio.dev;
169 	struct device *hwmon_dev;
170 	char *hwmon_name;
171 
172 	hwmon_name = devm_hwmon_sanitize_name(dev, dev_name(dev));
173 	if (IS_ERR(hwmon_name))
174 		return PTR_ERR(hwmon_name);
175 
176 	hwmon_dev = devm_hwmon_device_register_with_info(dev, hwmon_name,
177 							 phydev,
178 							 &gpy_hwmon_chip_info,
179 							 NULL);
180 
181 	return PTR_ERR_OR_ZERO(hwmon_dev);
182 }
183 #else
184 static int gpy_hwmon_register(struct phy_device *phydev)
185 {
186 	return 0;
187 }
188 #endif
189 
190 static int gpy_config_init(struct phy_device *phydev)
191 {
192 	int ret;
193 
194 	/* Mask all interrupts */
195 	ret = phy_write(phydev, PHY_IMASK, 0);
196 	if (ret)
197 		return ret;
198 
199 	/* Clear all pending interrupts */
200 	ret = phy_read(phydev, PHY_ISTAT);
201 	return ret < 0 ? ret : 0;
202 }
203 
204 static int gpy_probe(struct phy_device *phydev)
205 {
206 	struct device *dev = &phydev->mdio.dev;
207 	struct gpy_priv *priv;
208 	int fw_version;
209 	int ret;
210 
211 	if (!phydev->is_c45) {
212 		ret = phy_get_c45_ids(phydev);
213 		if (ret < 0)
214 			return ret;
215 	}
216 
217 	priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
218 	if (!priv)
219 		return -ENOMEM;
220 	phydev->priv = priv;
221 
222 	fw_version = phy_read(phydev, PHY_FWV);
223 	if (fw_version < 0)
224 		return fw_version;
225 	priv->fw_major = FIELD_GET(PHY_FWV_MAJOR_MASK, fw_version);
226 	priv->fw_minor = FIELD_GET(PHY_FWV_MINOR_MASK, fw_version);
227 
228 	ret = gpy_hwmon_register(phydev);
229 	if (ret)
230 		return ret;
231 
232 	/* Show GPY PHY FW version in dmesg */
233 	phydev_info(phydev, "Firmware Version: %d.%d (0x%04X%s)\n",
234 		    priv->fw_major, priv->fw_minor, fw_version,
235 		    fw_version & PHY_FWV_REL_MASK ? "" : " test version");
236 
237 	return 0;
238 }
239 
240 static bool gpy_sgmii_need_reaneg(struct phy_device *phydev)
241 {
242 	struct gpy_priv *priv = phydev->priv;
243 	size_t i;
244 
245 	for (i = 0; i < ARRAY_SIZE(ver_need_sgmii_reaneg); i++) {
246 		if (priv->fw_major != ver_need_sgmii_reaneg[i].major)
247 			continue;
248 		if (priv->fw_minor < ver_need_sgmii_reaneg[i].minor)
249 			return true;
250 		break;
251 	}
252 
253 	return false;
254 }
255 
256 static bool gpy_2500basex_chk(struct phy_device *phydev)
257 {
258 	int ret;
259 
260 	ret = phy_read(phydev, PHY_MIISTAT);
261 	if (ret < 0) {
262 		phydev_err(phydev, "Error: MDIO register access failed: %d\n",
263 			   ret);
264 		return false;
265 	}
266 
267 	if (!(ret & PHY_MIISTAT_LS) ||
268 	    FIELD_GET(PHY_MIISTAT_SPD_MASK, ret) != PHY_MIISTAT_SPD_2500)
269 		return false;
270 
271 	phydev->speed = SPEED_2500;
272 	phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
273 	phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
274 		       VSPEC1_SGMII_CTRL_ANEN, 0);
275 	return true;
276 }
277 
278 static bool gpy_sgmii_aneg_en(struct phy_device *phydev)
279 {
280 	int ret;
281 
282 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL);
283 	if (ret < 0) {
284 		phydev_err(phydev, "Error: MMD register access failed: %d\n",
285 			   ret);
286 		return true;
287 	}
288 
289 	return (ret & VSPEC1_SGMII_CTRL_ANEN) ? true : false;
290 }
291 
292 static int gpy_config_aneg(struct phy_device *phydev)
293 {
294 	bool changed = false;
295 	u32 adv;
296 	int ret;
297 
298 	if (phydev->autoneg == AUTONEG_DISABLE) {
299 		/* Configure half duplex with genphy_setup_forced,
300 		 * because genphy_c45_pma_setup_forced does not support.
301 		 */
302 		return phydev->duplex != DUPLEX_FULL
303 			? genphy_setup_forced(phydev)
304 			: genphy_c45_pma_setup_forced(phydev);
305 	}
306 
307 	ret = genphy_c45_an_config_aneg(phydev);
308 	if (ret < 0)
309 		return ret;
310 	if (ret > 0)
311 		changed = true;
312 
313 	adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
314 	ret = phy_modify_changed(phydev, MII_CTRL1000,
315 				 ADVERTISE_1000FULL | ADVERTISE_1000HALF,
316 				 adv);
317 	if (ret < 0)
318 		return ret;
319 	if (ret > 0)
320 		changed = true;
321 
322 	ret = genphy_c45_check_and_restart_aneg(phydev, changed);
323 	if (ret < 0)
324 		return ret;
325 
326 	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII ||
327 	    phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
328 		return 0;
329 
330 	/* No need to trigger re-ANEG if link speed is 2.5G or SGMII ANEG is
331 	 * disabled.
332 	 */
333 	if (!gpy_sgmii_need_reaneg(phydev) || gpy_2500basex_chk(phydev) ||
334 	    !gpy_sgmii_aneg_en(phydev))
335 		return 0;
336 
337 	/* There is a design constraint in GPY2xx device where SGMII AN is
338 	 * only triggered when there is change of speed. If, PHY link
339 	 * partner`s speed is still same even after PHY TPI is down and up
340 	 * again, SGMII AN is not triggered and hence no new in-band message
341 	 * from GPY to MAC side SGMII.
342 	 * This could cause an issue during power up, when PHY is up prior to
343 	 * MAC. At this condition, once MAC side SGMII is up, MAC side SGMII
344 	 * wouldn`t receive new in-band message from GPY with correct link
345 	 * status, speed and duplex info.
346 	 *
347 	 * 1) If PHY is already up and TPI link status is still down (such as
348 	 *    hard reboot), TPI link status is polled for 4 seconds before
349 	 *    retriggerring SGMII AN.
350 	 * 2) If PHY is already up and TPI link status is also up (such as soft
351 	 *    reboot), polling of TPI link status is not needed and SGMII AN is
352 	 *    immediately retriggered.
353 	 * 3) Other conditions such as PHY is down, speed change etc, skip
354 	 *    retriggering SGMII AN. Note: in case of speed change, GPY FW will
355 	 *    initiate SGMII AN.
356 	 */
357 
358 	if (phydev->state != PHY_UP)
359 		return 0;
360 
361 	ret = phy_read_poll_timeout(phydev, MII_BMSR, ret, ret & BMSR_LSTATUS,
362 				    20000, 4000000, false);
363 	if (ret == -ETIMEDOUT)
364 		return 0;
365 	else if (ret < 0)
366 		return ret;
367 
368 	/* Trigger SGMII AN. */
369 	return phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
370 			      VSPEC1_SGMII_CTRL_ANRS, VSPEC1_SGMII_CTRL_ANRS);
371 }
372 
373 static void gpy_update_interface(struct phy_device *phydev)
374 {
375 	int ret;
376 
377 	/* Interface mode is fixed for USXGMII and integrated PHY */
378 	if (phydev->interface == PHY_INTERFACE_MODE_USXGMII ||
379 	    phydev->interface == PHY_INTERFACE_MODE_INTERNAL)
380 		return;
381 
382 	/* Automatically switch SERDES interface between SGMII and 2500-BaseX
383 	 * according to speed. Disable ANEG in 2500-BaseX mode.
384 	 */
385 	switch (phydev->speed) {
386 	case SPEED_2500:
387 		phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
388 		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
389 				     VSPEC1_SGMII_CTRL_ANEN, 0);
390 		if (ret < 0)
391 			phydev_err(phydev,
392 				   "Error: Disable of SGMII ANEG failed: %d\n",
393 				   ret);
394 		break;
395 	case SPEED_1000:
396 	case SPEED_100:
397 	case SPEED_10:
398 		phydev->interface = PHY_INTERFACE_MODE_SGMII;
399 		if (gpy_sgmii_aneg_en(phydev))
400 			break;
401 		/* Enable and restart SGMII ANEG for 10/100/1000Mbps link speed
402 		 * if ANEG is disabled (in 2500-BaseX mode).
403 		 */
404 		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, VSPEC1_SGMII_CTRL,
405 				     VSPEC1_SGMII_ANEN_ANRS,
406 				     VSPEC1_SGMII_ANEN_ANRS);
407 		if (ret < 0)
408 			phydev_err(phydev,
409 				   "Error: Enable of SGMII ANEG failed: %d\n",
410 				   ret);
411 		break;
412 	}
413 
414 	if (phydev->speed == SPEED_2500 || phydev->speed == SPEED_1000)
415 		genphy_read_master_slave(phydev);
416 }
417 
418 static int gpy_read_status(struct phy_device *phydev)
419 {
420 	int ret;
421 
422 	ret = genphy_update_link(phydev);
423 	if (ret)
424 		return ret;
425 
426 	phydev->speed = SPEED_UNKNOWN;
427 	phydev->duplex = DUPLEX_UNKNOWN;
428 	phydev->pause = 0;
429 	phydev->asym_pause = 0;
430 
431 	if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
432 		ret = genphy_c45_read_lpa(phydev);
433 		if (ret < 0)
434 			return ret;
435 
436 		/* Read the link partner's 1G advertisement */
437 		ret = phy_read(phydev, MII_STAT1000);
438 		if (ret < 0)
439 			return ret;
440 		mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
441 	} else if (phydev->autoneg == AUTONEG_DISABLE) {
442 		linkmode_zero(phydev->lp_advertising);
443 	}
444 
445 	ret = phy_read(phydev, PHY_MIISTAT);
446 	if (ret < 0)
447 		return ret;
448 
449 	phydev->link = (ret & PHY_MIISTAT_LS) ? 1 : 0;
450 	phydev->duplex = (ret & PHY_MIISTAT_DPX) ? DUPLEX_FULL : DUPLEX_HALF;
451 	switch (FIELD_GET(PHY_MIISTAT_SPD_MASK, ret)) {
452 	case PHY_MIISTAT_SPD_10:
453 		phydev->speed = SPEED_10;
454 		break;
455 	case PHY_MIISTAT_SPD_100:
456 		phydev->speed = SPEED_100;
457 		break;
458 	case PHY_MIISTAT_SPD_1000:
459 		phydev->speed = SPEED_1000;
460 		break;
461 	case PHY_MIISTAT_SPD_2500:
462 		phydev->speed = SPEED_2500;
463 		break;
464 	}
465 
466 	if (phydev->link)
467 		gpy_update_interface(phydev);
468 
469 	return 0;
470 }
471 
472 static int gpy_config_intr(struct phy_device *phydev)
473 {
474 	u16 mask = 0;
475 
476 	if (phydev->interrupts == PHY_INTERRUPT_ENABLED)
477 		mask = PHY_IMASK_MASK;
478 
479 	return phy_write(phydev, PHY_IMASK, mask);
480 }
481 
482 static irqreturn_t gpy_handle_interrupt(struct phy_device *phydev)
483 {
484 	int reg;
485 
486 	reg = phy_read(phydev, PHY_ISTAT);
487 	if (reg < 0) {
488 		phy_error(phydev);
489 		return IRQ_NONE;
490 	}
491 
492 	if (!(reg & PHY_IMASK_MASK))
493 		return IRQ_NONE;
494 
495 	phy_trigger_machine(phydev);
496 
497 	return IRQ_HANDLED;
498 }
499 
500 static int gpy_set_wol(struct phy_device *phydev,
501 		       struct ethtool_wolinfo *wol)
502 {
503 	struct net_device *attach_dev = phydev->attached_dev;
504 	int ret;
505 
506 	if (wol->wolopts & WAKE_MAGIC) {
507 		/* MAC address - Byte0:Byte1:Byte2:Byte3:Byte4:Byte5
508 		 * VPSPEC2_WOL_AD45 = Byte0:Byte1
509 		 * VPSPEC2_WOL_AD23 = Byte2:Byte3
510 		 * VPSPEC2_WOL_AD01 = Byte4:Byte5
511 		 */
512 		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
513 				       VPSPEC2_WOL_AD45,
514 				       ((attach_dev->dev_addr[0] << 8) |
515 				       attach_dev->dev_addr[1]));
516 		if (ret < 0)
517 			return ret;
518 
519 		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
520 				       VPSPEC2_WOL_AD23,
521 				       ((attach_dev->dev_addr[2] << 8) |
522 				       attach_dev->dev_addr[3]));
523 		if (ret < 0)
524 			return ret;
525 
526 		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
527 				       VPSPEC2_WOL_AD01,
528 				       ((attach_dev->dev_addr[4] << 8) |
529 				       attach_dev->dev_addr[5]));
530 		if (ret < 0)
531 			return ret;
532 
533 		/* Enable the WOL interrupt */
534 		ret = phy_write(phydev, PHY_IMASK, PHY_IMASK_WOL);
535 		if (ret < 0)
536 			return ret;
537 
538 		/* Enable magic packet matching */
539 		ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
540 				       VPSPEC2_WOL_CTL,
541 				       WOL_EN);
542 		if (ret < 0)
543 			return ret;
544 
545 		/* Clear the interrupt status register.
546 		 * Only WoL is enabled so clear all.
547 		 */
548 		ret = phy_read(phydev, PHY_ISTAT);
549 		if (ret < 0)
550 			return ret;
551 	} else {
552 		/* Disable magic packet matching */
553 		ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
554 					 VPSPEC2_WOL_CTL,
555 					 WOL_EN);
556 		if (ret < 0)
557 			return ret;
558 	}
559 
560 	if (wol->wolopts & WAKE_PHY) {
561 		/* Enable the link state change interrupt */
562 		ret = phy_set_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
563 		if (ret < 0)
564 			return ret;
565 
566 		/* Clear the interrupt status register */
567 		ret = phy_read(phydev, PHY_ISTAT);
568 		if (ret < 0)
569 			return ret;
570 
571 		if (ret & (PHY_IMASK_MASK & ~PHY_IMASK_LSTC))
572 			phy_trigger_machine(phydev);
573 
574 		return 0;
575 	}
576 
577 	/* Disable the link state change interrupt */
578 	return phy_clear_bits(phydev, PHY_IMASK, PHY_IMASK_LSTC);
579 }
580 
581 static void gpy_get_wol(struct phy_device *phydev,
582 			struct ethtool_wolinfo *wol)
583 {
584 	int ret;
585 
586 	wol->supported = WAKE_MAGIC | WAKE_PHY;
587 	wol->wolopts = 0;
588 
589 	ret = phy_read_mmd(phydev, MDIO_MMD_VEND2, VPSPEC2_WOL_CTL);
590 	if (ret & WOL_EN)
591 		wol->wolopts |= WAKE_MAGIC;
592 
593 	ret = phy_read(phydev, PHY_IMASK);
594 	if (ret & PHY_IMASK_LSTC)
595 		wol->wolopts |= WAKE_PHY;
596 }
597 
598 static int gpy_loopback(struct phy_device *phydev, bool enable)
599 {
600 	int ret;
601 
602 	ret = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
603 			 enable ? BMCR_LOOPBACK : 0);
604 	if (!ret) {
605 		/* It takes some time for PHY device to switch
606 		 * into/out-of loopback mode.
607 		 */
608 		msleep(100);
609 	}
610 
611 	return ret;
612 }
613 
614 static int gpy115_loopback(struct phy_device *phydev, bool enable)
615 {
616 	struct gpy_priv *priv = phydev->priv;
617 
618 	if (enable)
619 		return gpy_loopback(phydev, enable);
620 
621 	if (priv->fw_minor > 0x76)
622 		return gpy_loopback(phydev, 0);
623 
624 	return genphy_soft_reset(phydev);
625 }
626 
627 static struct phy_driver gpy_drivers[] = {
628 	{
629 		PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx),
630 		.name		= "Maxlinear Ethernet GPY2xx",
631 		.get_features	= genphy_c45_pma_read_abilities,
632 		.config_init	= gpy_config_init,
633 		.probe		= gpy_probe,
634 		.suspend	= genphy_suspend,
635 		.resume		= genphy_resume,
636 		.config_aneg	= gpy_config_aneg,
637 		.aneg_done	= genphy_c45_aneg_done,
638 		.read_status	= gpy_read_status,
639 		.config_intr	= gpy_config_intr,
640 		.handle_interrupt = gpy_handle_interrupt,
641 		.set_wol	= gpy_set_wol,
642 		.get_wol	= gpy_get_wol,
643 		.set_loopback	= gpy_loopback,
644 	},
645 	{
646 		.phy_id		= PHY_ID_GPY115B,
647 		.phy_id_mask	= PHY_ID_GPYx15B_MASK,
648 		.name		= "Maxlinear Ethernet GPY115B",
649 		.get_features	= genphy_c45_pma_read_abilities,
650 		.config_init	= gpy_config_init,
651 		.probe		= gpy_probe,
652 		.suspend	= genphy_suspend,
653 		.resume		= genphy_resume,
654 		.config_aneg	= gpy_config_aneg,
655 		.aneg_done	= genphy_c45_aneg_done,
656 		.read_status	= gpy_read_status,
657 		.config_intr	= gpy_config_intr,
658 		.handle_interrupt = gpy_handle_interrupt,
659 		.set_wol	= gpy_set_wol,
660 		.get_wol	= gpy_get_wol,
661 		.set_loopback	= gpy115_loopback,
662 	},
663 	{
664 		PHY_ID_MATCH_MODEL(PHY_ID_GPY115C),
665 		.name		= "Maxlinear Ethernet GPY115C",
666 		.get_features	= genphy_c45_pma_read_abilities,
667 		.config_init	= gpy_config_init,
668 		.probe		= gpy_probe,
669 		.suspend	= genphy_suspend,
670 		.resume		= genphy_resume,
671 		.config_aneg	= gpy_config_aneg,
672 		.aneg_done	= genphy_c45_aneg_done,
673 		.read_status	= gpy_read_status,
674 		.config_intr	= gpy_config_intr,
675 		.handle_interrupt = gpy_handle_interrupt,
676 		.set_wol	= gpy_set_wol,
677 		.get_wol	= gpy_get_wol,
678 		.set_loopback	= gpy115_loopback,
679 	},
680 	{
681 		.phy_id		= PHY_ID_GPY211B,
682 		.phy_id_mask	= PHY_ID_GPY21xB_MASK,
683 		.name		= "Maxlinear Ethernet GPY211B",
684 		.get_features	= genphy_c45_pma_read_abilities,
685 		.config_init	= gpy_config_init,
686 		.probe		= gpy_probe,
687 		.suspend	= genphy_suspend,
688 		.resume		= genphy_resume,
689 		.config_aneg	= gpy_config_aneg,
690 		.aneg_done	= genphy_c45_aneg_done,
691 		.read_status	= gpy_read_status,
692 		.config_intr	= gpy_config_intr,
693 		.handle_interrupt = gpy_handle_interrupt,
694 		.set_wol	= gpy_set_wol,
695 		.get_wol	= gpy_get_wol,
696 		.set_loopback	= gpy_loopback,
697 	},
698 	{
699 		PHY_ID_MATCH_MODEL(PHY_ID_GPY211C),
700 		.name		= "Maxlinear Ethernet GPY211C",
701 		.get_features	= genphy_c45_pma_read_abilities,
702 		.config_init	= gpy_config_init,
703 		.probe		= gpy_probe,
704 		.suspend	= genphy_suspend,
705 		.resume		= genphy_resume,
706 		.config_aneg	= gpy_config_aneg,
707 		.aneg_done	= genphy_c45_aneg_done,
708 		.read_status	= gpy_read_status,
709 		.config_intr	= gpy_config_intr,
710 		.handle_interrupt = gpy_handle_interrupt,
711 		.set_wol	= gpy_set_wol,
712 		.get_wol	= gpy_get_wol,
713 		.set_loopback	= gpy_loopback,
714 	},
715 	{
716 		.phy_id		= PHY_ID_GPY212B,
717 		.phy_id_mask	= PHY_ID_GPY21xB_MASK,
718 		.name		= "Maxlinear Ethernet GPY212B",
719 		.get_features	= genphy_c45_pma_read_abilities,
720 		.config_init	= gpy_config_init,
721 		.probe		= gpy_probe,
722 		.suspend	= genphy_suspend,
723 		.resume		= genphy_resume,
724 		.config_aneg	= gpy_config_aneg,
725 		.aneg_done	= genphy_c45_aneg_done,
726 		.read_status	= gpy_read_status,
727 		.config_intr	= gpy_config_intr,
728 		.handle_interrupt = gpy_handle_interrupt,
729 		.set_wol	= gpy_set_wol,
730 		.get_wol	= gpy_get_wol,
731 		.set_loopback	= gpy_loopback,
732 	},
733 	{
734 		PHY_ID_MATCH_MODEL(PHY_ID_GPY212C),
735 		.name		= "Maxlinear Ethernet GPY212C",
736 		.get_features	= genphy_c45_pma_read_abilities,
737 		.config_init	= gpy_config_init,
738 		.probe		= gpy_probe,
739 		.suspend	= genphy_suspend,
740 		.resume		= genphy_resume,
741 		.config_aneg	= gpy_config_aneg,
742 		.aneg_done	= genphy_c45_aneg_done,
743 		.read_status	= gpy_read_status,
744 		.config_intr	= gpy_config_intr,
745 		.handle_interrupt = gpy_handle_interrupt,
746 		.set_wol	= gpy_set_wol,
747 		.get_wol	= gpy_get_wol,
748 		.set_loopback	= gpy_loopback,
749 	},
750 	{
751 		.phy_id		= PHY_ID_GPY215B,
752 		.phy_id_mask	= PHY_ID_GPYx15B_MASK,
753 		.name		= "Maxlinear Ethernet GPY215B",
754 		.get_features	= genphy_c45_pma_read_abilities,
755 		.config_init	= gpy_config_init,
756 		.probe		= gpy_probe,
757 		.suspend	= genphy_suspend,
758 		.resume		= genphy_resume,
759 		.config_aneg	= gpy_config_aneg,
760 		.aneg_done	= genphy_c45_aneg_done,
761 		.read_status	= gpy_read_status,
762 		.config_intr	= gpy_config_intr,
763 		.handle_interrupt = gpy_handle_interrupt,
764 		.set_wol	= gpy_set_wol,
765 		.get_wol	= gpy_get_wol,
766 		.set_loopback	= gpy_loopback,
767 	},
768 	{
769 		PHY_ID_MATCH_MODEL(PHY_ID_GPY215C),
770 		.name		= "Maxlinear Ethernet GPY215C",
771 		.get_features	= genphy_c45_pma_read_abilities,
772 		.config_init	= gpy_config_init,
773 		.probe		= gpy_probe,
774 		.suspend	= genphy_suspend,
775 		.resume		= genphy_resume,
776 		.config_aneg	= gpy_config_aneg,
777 		.aneg_done	= genphy_c45_aneg_done,
778 		.read_status	= gpy_read_status,
779 		.config_intr	= gpy_config_intr,
780 		.handle_interrupt = gpy_handle_interrupt,
781 		.set_wol	= gpy_set_wol,
782 		.get_wol	= gpy_get_wol,
783 		.set_loopback	= gpy_loopback,
784 	},
785 	{
786 		PHY_ID_MATCH_MODEL(PHY_ID_GPY241B),
787 		.name		= "Maxlinear Ethernet GPY241B",
788 		.get_features	= genphy_c45_pma_read_abilities,
789 		.config_init	= gpy_config_init,
790 		.probe		= gpy_probe,
791 		.suspend	= genphy_suspend,
792 		.resume		= genphy_resume,
793 		.config_aneg	= gpy_config_aneg,
794 		.aneg_done	= genphy_c45_aneg_done,
795 		.read_status	= gpy_read_status,
796 		.config_intr	= gpy_config_intr,
797 		.handle_interrupt = gpy_handle_interrupt,
798 		.set_wol	= gpy_set_wol,
799 		.get_wol	= gpy_get_wol,
800 		.set_loopback	= gpy_loopback,
801 	},
802 	{
803 		PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM),
804 		.name		= "Maxlinear Ethernet GPY241BM",
805 		.get_features	= genphy_c45_pma_read_abilities,
806 		.config_init	= gpy_config_init,
807 		.probe		= gpy_probe,
808 		.suspend	= genphy_suspend,
809 		.resume		= genphy_resume,
810 		.config_aneg	= gpy_config_aneg,
811 		.aneg_done	= genphy_c45_aneg_done,
812 		.read_status	= gpy_read_status,
813 		.config_intr	= gpy_config_intr,
814 		.handle_interrupt = gpy_handle_interrupt,
815 		.set_wol	= gpy_set_wol,
816 		.get_wol	= gpy_get_wol,
817 		.set_loopback	= gpy_loopback,
818 	},
819 	{
820 		PHY_ID_MATCH_MODEL(PHY_ID_GPY245B),
821 		.name		= "Maxlinear Ethernet GPY245B",
822 		.get_features	= genphy_c45_pma_read_abilities,
823 		.config_init	= gpy_config_init,
824 		.probe		= gpy_probe,
825 		.suspend	= genphy_suspend,
826 		.resume		= genphy_resume,
827 		.config_aneg	= gpy_config_aneg,
828 		.aneg_done	= genphy_c45_aneg_done,
829 		.read_status	= gpy_read_status,
830 		.config_intr	= gpy_config_intr,
831 		.handle_interrupt = gpy_handle_interrupt,
832 		.set_wol	= gpy_set_wol,
833 		.get_wol	= gpy_get_wol,
834 		.set_loopback	= gpy_loopback,
835 	},
836 };
837 module_phy_driver(gpy_drivers);
838 
839 static struct mdio_device_id __maybe_unused gpy_tbl[] = {
840 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx)},
841 	{PHY_ID_GPY115B, PHY_ID_GPYx15B_MASK},
842 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY115C)},
843 	{PHY_ID_GPY211B, PHY_ID_GPY21xB_MASK},
844 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY211C)},
845 	{PHY_ID_GPY212B, PHY_ID_GPY21xB_MASK},
846 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY212C)},
847 	{PHY_ID_GPY215B, PHY_ID_GPYx15B_MASK},
848 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY215C)},
849 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY241B)},
850 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM)},
851 	{PHY_ID_MATCH_MODEL(PHY_ID_GPY245B)},
852 	{ }
853 };
854 MODULE_DEVICE_TABLE(mdio, gpy_tbl);
855 
856 MODULE_DESCRIPTION("Maxlinear Ethernet GPY Driver");
857 MODULE_AUTHOR("Xu Liang");
858 MODULE_LICENSE("GPL");
859