brintos

brintos / linux-shallow public Read only

0
0
Text · 32.5 KiB · 1f98b6a Raw
1152 lines · c
1// SPDX-License-Identifier: GPL-2.0+2/*3 * Core PHY library, taken from phy.c4 */5#include <linux/export.h>6#include <linux/phy.h>7#include <linux/of.h>8 9/**10 * phy_speed_to_str - Return a string representing the PHY link speed11 *12 * @speed: Speed of the link13 */14const char *phy_speed_to_str(int speed)15{16	BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 103,17		"Enum ethtool_link_mode_bit_indices and phylib are out of sync. "18		"If a speed or mode has been added please update phy_speed_to_str "19		"and the PHY settings array.\n");20 21	switch (speed) {22	case SPEED_10:23		return "10Mbps";24	case SPEED_100:25		return "100Mbps";26	case SPEED_1000:27		return "1Gbps";28	case SPEED_2500:29		return "2.5Gbps";30	case SPEED_5000:31		return "5Gbps";32	case SPEED_10000:33		return "10Gbps";34	case SPEED_14000:35		return "14Gbps";36	case SPEED_20000:37		return "20Gbps";38	case SPEED_25000:39		return "25Gbps";40	case SPEED_40000:41		return "40Gbps";42	case SPEED_50000:43		return "50Gbps";44	case SPEED_56000:45		return "56Gbps";46	case SPEED_100000:47		return "100Gbps";48	case SPEED_200000:49		return "200Gbps";50	case SPEED_400000:51		return "400Gbps";52	case SPEED_800000:53		return "800Gbps";54	case SPEED_UNKNOWN:55		return "Unknown";56	default:57		return "Unsupported (update phy-core.c)";58	}59}60EXPORT_SYMBOL_GPL(phy_speed_to_str);61 62/**63 * phy_duplex_to_str - Return string describing the duplex64 *65 * @duplex: Duplex setting to describe66 */67const char *phy_duplex_to_str(unsigned int duplex)68{69	if (duplex == DUPLEX_HALF)70		return "Half";71	if (duplex == DUPLEX_FULL)72		return "Full";73	if (duplex == DUPLEX_UNKNOWN)74		return "Unknown";75	return "Unsupported (update phy-core.c)";76}77EXPORT_SYMBOL_GPL(phy_duplex_to_str);78 79/**80 * phy_rate_matching_to_str - Return a string describing the rate matching81 *82 * @rate_matching: Type of rate matching to describe83 */84const char *phy_rate_matching_to_str(int rate_matching)85{86	switch (rate_matching) {87	case RATE_MATCH_NONE:88		return "none";89	case RATE_MATCH_PAUSE:90		return "pause";91	case RATE_MATCH_CRS:92		return "crs";93	case RATE_MATCH_OPEN_LOOP:94		return "open-loop";95	}96	return "Unsupported (update phy-core.c)";97}98EXPORT_SYMBOL_GPL(phy_rate_matching_to_str);99 100/**101 * phy_interface_num_ports - Return the number of links that can be carried by102 *			     a given MAC-PHY physical link. Returns 0 if this is103 *			     unknown, the number of links else.104 *105 * @interface: The interface mode we want to get the number of ports106 */107int phy_interface_num_ports(phy_interface_t interface)108{109	switch (interface) {110	case PHY_INTERFACE_MODE_NA:111		return 0;112	case PHY_INTERFACE_MODE_INTERNAL:113	case PHY_INTERFACE_MODE_MII:114	case PHY_INTERFACE_MODE_GMII:115	case PHY_INTERFACE_MODE_TBI:116	case PHY_INTERFACE_MODE_REVMII:117	case PHY_INTERFACE_MODE_RMII:118	case PHY_INTERFACE_MODE_REVRMII:119	case PHY_INTERFACE_MODE_RGMII:120	case PHY_INTERFACE_MODE_RGMII_ID:121	case PHY_INTERFACE_MODE_RGMII_RXID:122	case PHY_INTERFACE_MODE_RGMII_TXID:123	case PHY_INTERFACE_MODE_RTBI:124	case PHY_INTERFACE_MODE_XGMII:125	case PHY_INTERFACE_MODE_XLGMII:126	case PHY_INTERFACE_MODE_MOCA:127	case PHY_INTERFACE_MODE_TRGMII:128	case PHY_INTERFACE_MODE_USXGMII:129	case PHY_INTERFACE_MODE_SGMII:130	case PHY_INTERFACE_MODE_SMII:131	case PHY_INTERFACE_MODE_1000BASEX:132	case PHY_INTERFACE_MODE_2500BASEX:133	case PHY_INTERFACE_MODE_5GBASER:134	case PHY_INTERFACE_MODE_10GBASER:135	case PHY_INTERFACE_MODE_25GBASER:136	case PHY_INTERFACE_MODE_10GKR:137	case PHY_INTERFACE_MODE_100BASEX:138	case PHY_INTERFACE_MODE_RXAUI:139	case PHY_INTERFACE_MODE_XAUI:140	case PHY_INTERFACE_MODE_1000BASEKX:141		return 1;142	case PHY_INTERFACE_MODE_QSGMII:143	case PHY_INTERFACE_MODE_QUSGMII:144	case PHY_INTERFACE_MODE_10G_QXGMII:145		return 4;146	case PHY_INTERFACE_MODE_PSGMII:147		return 5;148	case PHY_INTERFACE_MODE_MAX:149		WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");150		return 0;151	}152	return 0;153}154EXPORT_SYMBOL_GPL(phy_interface_num_ports);155 156/* A mapping of all SUPPORTED settings to speed/duplex.  This table157 * must be grouped by speed and sorted in descending match priority158 * - iow, descending speed.159 */160 161#define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \162			       .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}163 164static const struct phy_setting settings[] = {165	/* 800G */166	PHY_SETTING( 800000, FULL, 800000baseCR8_Full		),167	PHY_SETTING( 800000, FULL, 800000baseKR8_Full		),168	PHY_SETTING( 800000, FULL, 800000baseDR8_Full		),169	PHY_SETTING( 800000, FULL, 800000baseDR8_2_Full		),170	PHY_SETTING( 800000, FULL, 800000baseSR8_Full		),171	PHY_SETTING( 800000, FULL, 800000baseVR8_Full		),172	/* 400G */173	PHY_SETTING( 400000, FULL, 400000baseCR8_Full		),174	PHY_SETTING( 400000, FULL, 400000baseKR8_Full		),175	PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full	),176	PHY_SETTING( 400000, FULL, 400000baseDR8_Full		),177	PHY_SETTING( 400000, FULL, 400000baseSR8_Full		),178	PHY_SETTING( 400000, FULL, 400000baseCR4_Full		),179	PHY_SETTING( 400000, FULL, 400000baseKR4_Full		),180	PHY_SETTING( 400000, FULL, 400000baseLR4_ER4_FR4_Full	),181	PHY_SETTING( 400000, FULL, 400000baseDR4_Full		),182	PHY_SETTING( 400000, FULL, 400000baseSR4_Full		),183	/* 200G */184	PHY_SETTING( 200000, FULL, 200000baseCR4_Full		),185	PHY_SETTING( 200000, FULL, 200000baseKR4_Full		),186	PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full	),187	PHY_SETTING( 200000, FULL, 200000baseDR4_Full		),188	PHY_SETTING( 200000, FULL, 200000baseSR4_Full		),189	PHY_SETTING( 200000, FULL, 200000baseCR2_Full		),190	PHY_SETTING( 200000, FULL, 200000baseKR2_Full		),191	PHY_SETTING( 200000, FULL, 200000baseLR2_ER2_FR2_Full	),192	PHY_SETTING( 200000, FULL, 200000baseDR2_Full		),193	PHY_SETTING( 200000, FULL, 200000baseSR2_Full		),194	/* 100G */195	PHY_SETTING( 100000, FULL, 100000baseCR4_Full		),196	PHY_SETTING( 100000, FULL, 100000baseKR4_Full		),197	PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full	),198	PHY_SETTING( 100000, FULL, 100000baseSR4_Full		),199	PHY_SETTING( 100000, FULL, 100000baseCR2_Full		),200	PHY_SETTING( 100000, FULL, 100000baseKR2_Full		),201	PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full	),202	PHY_SETTING( 100000, FULL, 100000baseDR2_Full		),203	PHY_SETTING( 100000, FULL, 100000baseSR2_Full		),204	PHY_SETTING( 100000, FULL, 100000baseCR_Full		),205	PHY_SETTING( 100000, FULL, 100000baseKR_Full		),206	PHY_SETTING( 100000, FULL, 100000baseLR_ER_FR_Full	),207	PHY_SETTING( 100000, FULL, 100000baseDR_Full		),208	PHY_SETTING( 100000, FULL, 100000baseSR_Full		),209	/* 56G */210	PHY_SETTING(  56000, FULL,  56000baseCR4_Full	  	),211	PHY_SETTING(  56000, FULL,  56000baseKR4_Full	  	),212	PHY_SETTING(  56000, FULL,  56000baseLR4_Full	  	),213	PHY_SETTING(  56000, FULL,  56000baseSR4_Full	  	),214	/* 50G */215	PHY_SETTING(  50000, FULL,  50000baseCR2_Full		),216	PHY_SETTING(  50000, FULL,  50000baseKR2_Full		),217	PHY_SETTING(  50000, FULL,  50000baseSR2_Full		),218	PHY_SETTING(  50000, FULL,  50000baseCR_Full		),219	PHY_SETTING(  50000, FULL,  50000baseKR_Full		),220	PHY_SETTING(  50000, FULL,  50000baseLR_ER_FR_Full	),221	PHY_SETTING(  50000, FULL,  50000baseDR_Full		),222	PHY_SETTING(  50000, FULL,  50000baseSR_Full		),223	/* 40G */224	PHY_SETTING(  40000, FULL,  40000baseCR4_Full		),225	PHY_SETTING(  40000, FULL,  40000baseKR4_Full		),226	PHY_SETTING(  40000, FULL,  40000baseLR4_Full		),227	PHY_SETTING(  40000, FULL,  40000baseSR4_Full		),228	/* 25G */229	PHY_SETTING(  25000, FULL,  25000baseCR_Full		),230	PHY_SETTING(  25000, FULL,  25000baseKR_Full		),231	PHY_SETTING(  25000, FULL,  25000baseSR_Full		),232	/* 20G */233	PHY_SETTING(  20000, FULL,  20000baseKR2_Full		),234	PHY_SETTING(  20000, FULL,  20000baseMLD2_Full		),235	/* 10G */236	PHY_SETTING(  10000, FULL,  10000baseCR_Full		),237	PHY_SETTING(  10000, FULL,  10000baseER_Full		),238	PHY_SETTING(  10000, FULL,  10000baseKR_Full		),239	PHY_SETTING(  10000, FULL,  10000baseKX4_Full		),240	PHY_SETTING(  10000, FULL,  10000baseLR_Full		),241	PHY_SETTING(  10000, FULL,  10000baseLRM_Full		),242	PHY_SETTING(  10000, FULL,  10000baseR_FEC		),243	PHY_SETTING(  10000, FULL,  10000baseSR_Full		),244	PHY_SETTING(  10000, FULL,  10000baseT_Full		),245	/* 5G */246	PHY_SETTING(   5000, FULL,   5000baseT_Full		),247	/* 2.5G */248	PHY_SETTING(   2500, FULL,   2500baseT_Full		),249	PHY_SETTING(   2500, FULL,   2500baseX_Full		),250	/* 1G */251	PHY_SETTING(   1000, FULL,   1000baseT_Full		),252	PHY_SETTING(   1000, HALF,   1000baseT_Half		),253	PHY_SETTING(   1000, FULL,   1000baseT1_Full		),254	PHY_SETTING(   1000, FULL,   1000baseX_Full		),255	PHY_SETTING(   1000, FULL,   1000baseKX_Full		),256	/* 100M */257	PHY_SETTING(    100, FULL,    100baseT_Full		),258	PHY_SETTING(    100, FULL,    100baseT1_Full		),259	PHY_SETTING(    100, HALF,    100baseT_Half		),260	PHY_SETTING(    100, HALF,    100baseFX_Half		),261	PHY_SETTING(    100, FULL,    100baseFX_Full		),262	/* 10M */263	PHY_SETTING(     10, FULL,     10baseT_Full		),264	PHY_SETTING(     10, HALF,     10baseT_Half		),265	PHY_SETTING(     10, FULL,     10baseT1L_Full		),266	PHY_SETTING(     10, FULL,     10baseT1S_Full		),267	PHY_SETTING(     10, HALF,     10baseT1S_Half		),268	PHY_SETTING(     10, HALF,     10baseT1S_P2MP_Half	),269	PHY_SETTING(     10, FULL,     10baseT1BRR_Full		),270};271#undef PHY_SETTING272 273/**274 * phy_lookup_setting - lookup a PHY setting275 * @speed: speed to match276 * @duplex: duplex to match277 * @mask: allowed link modes278 * @exact: an exact match is required279 *280 * Search the settings array for a setting that matches the speed and281 * duplex, and which is supported.282 *283 * If @exact is unset, either an exact match or %NULL for no match will284 * be returned.285 *286 * If @exact is set, an exact match, the fastest supported setting at287 * or below the specified speed, the slowest supported setting, or if288 * they all fail, %NULL will be returned.289 */290const struct phy_setting *291phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact)292{293	const struct phy_setting *p, *match = NULL, *last = NULL;294	int i;295 296	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {297		if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&298		    test_bit(p->bit, mask)) {299			last = p;300			if (p->speed == speed && p->duplex == duplex) {301				/* Exact match for speed and duplex */302				match = p;303				break;304			} else if (!exact) {305				if (!match && p->speed <= speed)306					/* Candidate */307					match = p;308 309				if (p->speed < speed)310					break;311			}312		}313	}314 315	if (!match && !exact)316		match = last;317 318	return match;319}320EXPORT_SYMBOL_GPL(phy_lookup_setting);321 322size_t phy_speeds(unsigned int *speeds, size_t size,323		  unsigned long *mask)324{325	size_t count;326	int i;327 328	for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++)329		if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS &&330		    test_bit(settings[i].bit, mask) &&331		    (count == 0 || speeds[count - 1] != settings[i].speed))332			speeds[count++] = settings[i].speed;333 334	return count;335}336 337static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr)338{339	const struct phy_setting *p;340	int i;341 342	for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) {343		if (p->speed > max_speed)344			linkmode_clear_bit(p->bit, addr);345		else346			break;347	}348}349 350static void __set_phy_supported(struct phy_device *phydev, u32 max_speed)351{352	__set_linkmode_max_speed(max_speed, phydev->supported);353}354 355/**356 * phy_set_max_speed - Set the maximum speed the PHY should support357 *358 * @phydev: The phy_device struct359 * @max_speed: Maximum speed360 *361 * The PHY might be more capable than the MAC. For example a Fast Ethernet362 * is connected to a 1G PHY. This function allows the MAC to indicate its363 * maximum speed, and so limit what the PHY will advertise.364 */365void phy_set_max_speed(struct phy_device *phydev, u32 max_speed)366{367	__set_phy_supported(phydev, max_speed);368 369	phy_advertise_supported(phydev);370}371EXPORT_SYMBOL(phy_set_max_speed);372 373void of_set_phy_supported(struct phy_device *phydev)374{375	struct device_node *node = phydev->mdio.dev.of_node;376	u32 max_speed;377 378	if (!IS_ENABLED(CONFIG_OF_MDIO))379		return;380 381	if (!node)382		return;383 384	if (!of_property_read_u32(node, "max-speed", &max_speed))385		__set_phy_supported(phydev, max_speed);386}387 388void of_set_phy_eee_broken(struct phy_device *phydev)389{390	struct device_node *node = phydev->mdio.dev.of_node;391	u32 broken = 0;392 393	if (!IS_ENABLED(CONFIG_OF_MDIO))394		return;395 396	if (!node)397		return;398 399	if (of_property_read_bool(node, "eee-broken-100tx"))400		broken |= MDIO_EEE_100TX;401	if (of_property_read_bool(node, "eee-broken-1000t"))402		broken |= MDIO_EEE_1000T;403	if (of_property_read_bool(node, "eee-broken-10gt"))404		broken |= MDIO_EEE_10GT;405	if (of_property_read_bool(node, "eee-broken-1000kx"))406		broken |= MDIO_EEE_1000KX;407	if (of_property_read_bool(node, "eee-broken-10gkx4"))408		broken |= MDIO_EEE_10GKX4;409	if (of_property_read_bool(node, "eee-broken-10gkr"))410		broken |= MDIO_EEE_10GKR;411 412	phydev->eee_broken_modes = broken;413}414 415/**416 * phy_resolve_aneg_pause - Determine pause autoneg results417 *418 * @phydev: The phy_device struct419 *420 * Once autoneg has completed the local pause settings can be421 * resolved.  Determine if pause and asymmetric pause should be used422 * by the MAC.423 */424 425void phy_resolve_aneg_pause(struct phy_device *phydev)426{427	if (phydev->duplex == DUPLEX_FULL) {428		phydev->pause = linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,429						  phydev->lp_advertising);430		phydev->asym_pause = linkmode_test_bit(431			ETHTOOL_LINK_MODE_Asym_Pause_BIT,432			phydev->lp_advertising);433	}434}435EXPORT_SYMBOL_GPL(phy_resolve_aneg_pause);436 437/**438 * phy_resolve_aneg_linkmode - resolve the advertisements into PHY settings439 * @phydev: The phy_device struct440 *441 * Resolve our and the link partner advertisements into their corresponding442 * speed and duplex. If full duplex was negotiated, extract the pause mode443 * from the link partner mask.444 */445void phy_resolve_aneg_linkmode(struct phy_device *phydev)446{447	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);448	int i;449 450	linkmode_and(common, phydev->lp_advertising, phydev->advertising);451 452	for (i = 0; i < ARRAY_SIZE(settings); i++)453		if (test_bit(settings[i].bit, common)) {454			phydev->speed = settings[i].speed;455			phydev->duplex = settings[i].duplex;456			break;457		}458 459	phy_resolve_aneg_pause(phydev);460}461EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);462 463/**464 * phy_check_downshift - check whether downshift occurred465 * @phydev: The phy_device struct466 *467 * Check whether a downshift to a lower speed occurred. If this should be the468 * case warn the user.469 * Prerequisite for detecting downshift is that PHY driver implements the470 * read_status callback and sets phydev->speed to the actual link speed.471 */472void phy_check_downshift(struct phy_device *phydev)473{474	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);475	int i, speed = SPEED_UNKNOWN;476 477	phydev->downshifted_rate = 0;478 479	if (phydev->autoneg == AUTONEG_DISABLE ||480	    phydev->speed == SPEED_UNKNOWN)481		return;482 483	linkmode_and(common, phydev->lp_advertising, phydev->advertising);484 485	for (i = 0; i < ARRAY_SIZE(settings); i++)486		if (test_bit(settings[i].bit, common)) {487			speed = settings[i].speed;488			break;489		}490 491	if (speed == SPEED_UNKNOWN || phydev->speed >= speed)492		return;493 494	phydev_warn(phydev, "Downshift occurred from negotiated speed %s to actual speed %s, check cabling!\n",495		    phy_speed_to_str(speed), phy_speed_to_str(phydev->speed));496 497	phydev->downshifted_rate = 1;498}499EXPORT_SYMBOL_GPL(phy_check_downshift);500 501static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only)502{503	__ETHTOOL_DECLARE_LINK_MODE_MASK(common);504	int i = ARRAY_SIZE(settings);505 506	linkmode_and(common, phydev->lp_advertising, phydev->advertising);507 508	while (--i >= 0) {509		if (test_bit(settings[i].bit, common)) {510			if (fdx_only && settings[i].duplex != DUPLEX_FULL)511				continue;512			return settings[i].speed;513		}514	}515 516	return SPEED_UNKNOWN;517}518 519int phy_speed_down_core(struct phy_device *phydev)520{521	int min_common_speed = phy_resolve_min_speed(phydev, true);522 523	if (min_common_speed == SPEED_UNKNOWN)524		return -EINVAL;525 526	__set_linkmode_max_speed(min_common_speed, phydev->advertising);527 528	return 0;529}530 531static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,532			     u16 regnum)533{534	/* Write the desired MMD Devad */535	__mdiobus_write(bus, phy_addr, MII_MMD_CTRL, devad);536 537	/* Write the desired MMD register address */538	__mdiobus_write(bus, phy_addr, MII_MMD_DATA, regnum);539 540	/* Select the Function : DATA with no post increment */541	__mdiobus_write(bus, phy_addr, MII_MMD_CTRL,542			devad | MII_MMD_CTRL_NOINCR);543}544 545static int mmd_phy_read(struct mii_bus *bus, int phy_addr, bool is_c45,546			int devad, u32 regnum)547{548	if (is_c45)549		return __mdiobus_c45_read(bus, phy_addr, devad, regnum);550 551	mmd_phy_indirect(bus, phy_addr, devad, regnum);552	/* Read the content of the MMD's selected register */553	return __mdiobus_read(bus, phy_addr, MII_MMD_DATA);554}555 556static int mmd_phy_write(struct mii_bus *bus, int phy_addr, bool is_c45,557			 int devad, u32 regnum, u16 val)558{559	if (is_c45)560		return __mdiobus_c45_write(bus, phy_addr, devad, regnum, val);561 562	mmd_phy_indirect(bus, phy_addr, devad, regnum);563	/* Write the data into MMD's selected register */564	return __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);565}566 567/**568 * __phy_read_mmd - Convenience function for reading a register569 * from an MMD on a given PHY.570 * @phydev: The phy_device struct571 * @devad: The MMD to read from (0..31)572 * @regnum: The register on the MMD to read (0..65535)573 *574 * Same rules as for __phy_read();575 */576int __phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)577{578	if (regnum > (u16)~0 || devad > 32)579		return -EINVAL;580 581	if (phydev->drv && phydev->drv->read_mmd)582		return phydev->drv->read_mmd(phydev, devad, regnum);583 584	return mmd_phy_read(phydev->mdio.bus, phydev->mdio.addr,585			    phydev->is_c45, devad, regnum);586}587EXPORT_SYMBOL(__phy_read_mmd);588 589/**590 * phy_read_mmd - Convenience function for reading a register591 * from an MMD on a given PHY.592 * @phydev: The phy_device struct593 * @devad: The MMD to read from594 * @regnum: The register on the MMD to read595 *596 * Same rules as for phy_read();597 */598int phy_read_mmd(struct phy_device *phydev, int devad, u32 regnum)599{600	int ret;601 602	phy_lock_mdio_bus(phydev);603	ret = __phy_read_mmd(phydev, devad, regnum);604	phy_unlock_mdio_bus(phydev);605 606	return ret;607}608EXPORT_SYMBOL(phy_read_mmd);609 610/**611 * __phy_write_mmd - Convenience function for writing a register612 * on an MMD on a given PHY.613 * @phydev: The phy_device struct614 * @devad: The MMD to read from615 * @regnum: The register on the MMD to read616 * @val: value to write to @regnum617 *618 * Same rules as for __phy_write();619 */620int __phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)621{622	if (regnum > (u16)~0 || devad > 32)623		return -EINVAL;624 625	if (phydev->drv && phydev->drv->write_mmd)626		return phydev->drv->write_mmd(phydev, devad, regnum, val);627 628	return mmd_phy_write(phydev->mdio.bus, phydev->mdio.addr,629			     phydev->is_c45, devad, regnum, val);630}631EXPORT_SYMBOL(__phy_write_mmd);632 633/**634 * phy_write_mmd - Convenience function for writing a register635 * on an MMD on a given PHY.636 * @phydev: The phy_device struct637 * @devad: The MMD to read from638 * @regnum: The register on the MMD to read639 * @val: value to write to @regnum640 *641 * Same rules as for phy_write();642 */643int phy_write_mmd(struct phy_device *phydev, int devad, u32 regnum, u16 val)644{645	int ret;646 647	phy_lock_mdio_bus(phydev);648	ret = __phy_write_mmd(phydev, devad, regnum, val);649	phy_unlock_mdio_bus(phydev);650 651	return ret;652}653EXPORT_SYMBOL(phy_write_mmd);654 655/**656 * __phy_package_read_mmd - read MMD reg relative to PHY package base addr657 * @phydev: The phy_device struct658 * @addr_offset: The offset to be added to PHY package base_addr659 * @devad: The MMD to read from660 * @regnum: The register on the MMD to read661 *662 * Convenience helper for reading a register of an MMD on a given PHY663 * using the PHY package base address. The base address is added to664 * the addr_offset value.665 *666 * Same calling rules as for __phy_read();667 *668 * NOTE: It's assumed that the entire PHY package is either C22 or C45.669 */670int __phy_package_read_mmd(struct phy_device *phydev,671			   unsigned int addr_offset, int devad,672			   u32 regnum)673{674	int addr = phy_package_address(phydev, addr_offset);675 676	if (addr < 0)677		return addr;678 679	if (regnum > (u16)~0 || devad > 32)680		return -EINVAL;681 682	return mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,683			    regnum);684}685EXPORT_SYMBOL(__phy_package_read_mmd);686 687/**688 * phy_package_read_mmd - read MMD reg relative to PHY package base addr689 * @phydev: The phy_device struct690 * @addr_offset: The offset to be added to PHY package base_addr691 * @devad: The MMD to read from692 * @regnum: The register on the MMD to read693 *694 * Convenience helper for reading a register of an MMD on a given PHY695 * using the PHY package base address. The base address is added to696 * the addr_offset value.697 *698 * Same calling rules as for phy_read();699 *700 * NOTE: It's assumed that the entire PHY package is either C22 or C45.701 */702int phy_package_read_mmd(struct phy_device *phydev,703			 unsigned int addr_offset, int devad,704			 u32 regnum)705{706	int addr = phy_package_address(phydev, addr_offset);707	int val;708 709	if (addr < 0)710		return addr;711 712	if (regnum > (u16)~0 || devad > 32)713		return -EINVAL;714 715	phy_lock_mdio_bus(phydev);716	val = mmd_phy_read(phydev->mdio.bus, addr, phydev->is_c45, devad,717			   regnum);718	phy_unlock_mdio_bus(phydev);719 720	return val;721}722EXPORT_SYMBOL(phy_package_read_mmd);723 724/**725 * __phy_package_write_mmd - write MMD reg relative to PHY package base addr726 * @phydev: The phy_device struct727 * @addr_offset: The offset to be added to PHY package base_addr728 * @devad: The MMD to write to729 * @regnum: The register on the MMD to write730 * @val: value to write to @regnum731 *732 * Convenience helper for writing a register of an MMD on a given PHY733 * using the PHY package base address. The base address is added to734 * the addr_offset value.735 *736 * Same calling rules as for __phy_write();737 *738 * NOTE: It's assumed that the entire PHY package is either C22 or C45.739 */740int __phy_package_write_mmd(struct phy_device *phydev,741			    unsigned int addr_offset, int devad,742			    u32 regnum, u16 val)743{744	int addr = phy_package_address(phydev, addr_offset);745 746	if (addr < 0)747		return addr;748 749	if (regnum > (u16)~0 || devad > 32)750		return -EINVAL;751 752	return mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,753			     regnum, val);754}755EXPORT_SYMBOL(__phy_package_write_mmd);756 757/**758 * phy_package_write_mmd - write MMD reg relative to PHY package base addr759 * @phydev: The phy_device struct760 * @addr_offset: The offset to be added to PHY package base_addr761 * @devad: The MMD to write to762 * @regnum: The register on the MMD to write763 * @val: value to write to @regnum764 *765 * Convenience helper for writing a register of an MMD on a given PHY766 * using the PHY package base address. The base address is added to767 * the addr_offset value.768 *769 * Same calling rules as for phy_write();770 *771 * NOTE: It's assumed that the entire PHY package is either C22 or C45.772 */773int phy_package_write_mmd(struct phy_device *phydev,774			  unsigned int addr_offset, int devad,775			  u32 regnum, u16 val)776{777	int addr = phy_package_address(phydev, addr_offset);778	int ret;779 780	if (addr < 0)781		return addr;782 783	if (regnum > (u16)~0 || devad > 32)784		return -EINVAL;785 786	phy_lock_mdio_bus(phydev);787	ret = mmd_phy_write(phydev->mdio.bus, addr, phydev->is_c45, devad,788			    regnum, val);789	phy_unlock_mdio_bus(phydev);790 791	return ret;792}793EXPORT_SYMBOL(phy_package_write_mmd);794 795/**796 * phy_modify_changed - Function for modifying a PHY register797 * @phydev: the phy_device struct798 * @regnum: register number to modify799 * @mask: bit mask of bits to clear800 * @set: new value of bits set in mask to write to @regnum801 *802 * NOTE: MUST NOT be called from interrupt context,803 * because the bus read/write functions may wait for an interrupt804 * to conclude the operation.805 *806 * Returns negative errno, 0 if there was no change, and 1 in case of change807 */808int phy_modify_changed(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)809{810	int ret;811 812	phy_lock_mdio_bus(phydev);813	ret = __phy_modify_changed(phydev, regnum, mask, set);814	phy_unlock_mdio_bus(phydev);815 816	return ret;817}818EXPORT_SYMBOL_GPL(phy_modify_changed);819 820/**821 * __phy_modify - Convenience function for modifying a PHY register822 * @phydev: the phy_device struct823 * @regnum: register number to modify824 * @mask: bit mask of bits to clear825 * @set: new value of bits set in mask to write to @regnum826 *827 * NOTE: MUST NOT be called from interrupt context,828 * because the bus read/write functions may wait for an interrupt829 * to conclude the operation.830 */831int __phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)832{833	int ret;834 835	ret = __phy_modify_changed(phydev, regnum, mask, set);836 837	return ret < 0 ? ret : 0;838}839EXPORT_SYMBOL_GPL(__phy_modify);840 841/**842 * phy_modify - Convenience function for modifying a given PHY register843 * @phydev: the phy_device struct844 * @regnum: register number to write845 * @mask: bit mask of bits to clear846 * @set: new value of bits set in mask to write to @regnum847 *848 * NOTE: MUST NOT be called from interrupt context,849 * because the bus read/write functions may wait for an interrupt850 * to conclude the operation.851 */852int phy_modify(struct phy_device *phydev, u32 regnum, u16 mask, u16 set)853{854	int ret;855 856	phy_lock_mdio_bus(phydev);857	ret = __phy_modify(phydev, regnum, mask, set);858	phy_unlock_mdio_bus(phydev);859 860	return ret;861}862EXPORT_SYMBOL_GPL(phy_modify);863 864/**865 * __phy_modify_mmd_changed - Function for modifying a register on MMD866 * @phydev: the phy_device struct867 * @devad: the MMD containing register to modify868 * @regnum: register number to modify869 * @mask: bit mask of bits to clear870 * @set: new value of bits set in mask to write to @regnum871 *872 * Unlocked helper function which allows a MMD register to be modified as873 * new register value = (old register value & ~mask) | set874 *875 * Returns negative errno, 0 if there was no change, and 1 in case of change876 */877int __phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,878			     u16 mask, u16 set)879{880	int new, ret;881 882	ret = __phy_read_mmd(phydev, devad, regnum);883	if (ret < 0)884		return ret;885 886	new = (ret & ~mask) | set;887	if (new == ret)888		return 0;889 890	ret = __phy_write_mmd(phydev, devad, regnum, new);891 892	return ret < 0 ? ret : 1;893}894EXPORT_SYMBOL_GPL(__phy_modify_mmd_changed);895 896/**897 * phy_modify_mmd_changed - Function for modifying a register on MMD898 * @phydev: the phy_device struct899 * @devad: the MMD containing register to modify900 * @regnum: register number to modify901 * @mask: bit mask of bits to clear902 * @set: new value of bits set in mask to write to @regnum903 *904 * NOTE: MUST NOT be called from interrupt context,905 * because the bus read/write functions may wait for an interrupt906 * to conclude the operation.907 *908 * Returns negative errno, 0 if there was no change, and 1 in case of change909 */910int phy_modify_mmd_changed(struct phy_device *phydev, int devad, u32 regnum,911			   u16 mask, u16 set)912{913	int ret;914 915	phy_lock_mdio_bus(phydev);916	ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);917	phy_unlock_mdio_bus(phydev);918 919	return ret;920}921EXPORT_SYMBOL_GPL(phy_modify_mmd_changed);922 923/**924 * __phy_modify_mmd - Convenience function for modifying a register on MMD925 * @phydev: the phy_device struct926 * @devad: the MMD containing register to modify927 * @regnum: register number to modify928 * @mask: bit mask of bits to clear929 * @set: new value of bits set in mask to write to @regnum930 *931 * NOTE: MUST NOT be called from interrupt context,932 * because the bus read/write functions may wait for an interrupt933 * to conclude the operation.934 */935int __phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,936		     u16 mask, u16 set)937{938	int ret;939 940	ret = __phy_modify_mmd_changed(phydev, devad, regnum, mask, set);941 942	return ret < 0 ? ret : 0;943}944EXPORT_SYMBOL_GPL(__phy_modify_mmd);945 946/**947 * phy_modify_mmd - Convenience function for modifying a register on MMD948 * @phydev: the phy_device struct949 * @devad: the MMD containing register to modify950 * @regnum: register number to modify951 * @mask: bit mask of bits to clear952 * @set: new value of bits set in mask to write to @regnum953 *954 * NOTE: MUST NOT be called from interrupt context,955 * because the bus read/write functions may wait for an interrupt956 * to conclude the operation.957 */958int phy_modify_mmd(struct phy_device *phydev, int devad, u32 regnum,959		   u16 mask, u16 set)960{961	int ret;962 963	phy_lock_mdio_bus(phydev);964	ret = __phy_modify_mmd(phydev, devad, regnum, mask, set);965	phy_unlock_mdio_bus(phydev);966 967	return ret;968}969EXPORT_SYMBOL_GPL(phy_modify_mmd);970 971static int __phy_read_page(struct phy_device *phydev)972{973	if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n"))974		return -EOPNOTSUPP;975 976	return phydev->drv->read_page(phydev);977}978 979static int __phy_write_page(struct phy_device *phydev, int page)980{981	if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n"))982		return -EOPNOTSUPP;983 984	return phydev->drv->write_page(phydev, page);985}986 987/**988 * phy_save_page() - take the bus lock and save the current page989 * @phydev: a pointer to a &struct phy_device990 *991 * Take the MDIO bus lock, and return the current page number. On error,992 * returns a negative errno. phy_restore_page() must always be called993 * after this, irrespective of success or failure of this call.994 */995int phy_save_page(struct phy_device *phydev)996{997	phy_lock_mdio_bus(phydev);998	return __phy_read_page(phydev);999}1000EXPORT_SYMBOL_GPL(phy_save_page);1001 1002/**1003 * phy_select_page() - take the bus lock, save the current page, and set a page1004 * @phydev: a pointer to a &struct phy_device1005 * @page: desired page1006 *1007 * Take the MDIO bus lock to protect against concurrent access, save the1008 * current PHY page, and set the current page.  On error, returns a1009 * negative errno, otherwise returns the previous page number.1010 * phy_restore_page() must always be called after this, irrespective1011 * of success or failure of this call.1012 */1013int phy_select_page(struct phy_device *phydev, int page)1014{1015	int ret, oldpage;1016 1017	oldpage = ret = phy_save_page(phydev);1018	if (ret < 0)1019		return ret;1020 1021	if (oldpage != page) {1022		ret = __phy_write_page(phydev, page);1023		if (ret < 0)1024			return ret;1025	}1026 1027	return oldpage;1028}1029EXPORT_SYMBOL_GPL(phy_select_page);1030 1031/**1032 * phy_restore_page() - restore the page register and release the bus lock1033 * @phydev: a pointer to a &struct phy_device1034 * @oldpage: the old page, return value from phy_save_page() or phy_select_page()1035 * @ret: operation's return code1036 *1037 * Release the MDIO bus lock, restoring @oldpage if it is a valid page.1038 * This function propagates the earliest error code from the group of1039 * operations.1040 *1041 * Returns:1042 *   @oldpage if it was a negative value, otherwise1043 *   @ret if it was a negative errno value, otherwise1044 *   phy_write_page()'s negative value if it were in error, otherwise1045 *   @ret.1046 */1047int phy_restore_page(struct phy_device *phydev, int oldpage, int ret)1048{1049	int r;1050 1051	if (oldpage >= 0) {1052		r = __phy_write_page(phydev, oldpage);1053 1054		/* Propagate the operation return code if the page write1055		 * was successful.1056		 */1057		if (ret >= 0 && r < 0)1058			ret = r;1059	} else {1060		/* Propagate the phy page selection error code */1061		ret = oldpage;1062	}1063 1064	phy_unlock_mdio_bus(phydev);1065 1066	return ret;1067}1068EXPORT_SYMBOL_GPL(phy_restore_page);1069 1070/**1071 * phy_read_paged() - Convenience function for reading a paged register1072 * @phydev: a pointer to a &struct phy_device1073 * @page: the page for the phy1074 * @regnum: register number1075 *1076 * Same rules as for phy_read().1077 */1078int phy_read_paged(struct phy_device *phydev, int page, u32 regnum)1079{1080	int ret = 0, oldpage;1081 1082	oldpage = phy_select_page(phydev, page);1083	if (oldpage >= 0)1084		ret = __phy_read(phydev, regnum);1085 1086	return phy_restore_page(phydev, oldpage, ret);1087}1088EXPORT_SYMBOL(phy_read_paged);1089 1090/**1091 * phy_write_paged() - Convenience function for writing a paged register1092 * @phydev: a pointer to a &struct phy_device1093 * @page: the page for the phy1094 * @regnum: register number1095 * @val: value to write1096 *1097 * Same rules as for phy_write().1098 */1099int phy_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val)1100{1101	int ret = 0, oldpage;1102 1103	oldpage = phy_select_page(phydev, page);1104	if (oldpage >= 0)1105		ret = __phy_write(phydev, regnum, val);1106 1107	return phy_restore_page(phydev, oldpage, ret);1108}1109EXPORT_SYMBOL(phy_write_paged);1110 1111/**1112 * phy_modify_paged_changed() - Function for modifying a paged register1113 * @phydev: a pointer to a &struct phy_device1114 * @page: the page for the phy1115 * @regnum: register number1116 * @mask: bit mask of bits to clear1117 * @set: bit mask of bits to set1118 *1119 * Returns negative errno, 0 if there was no change, and 1 in case of change1120 */1121int phy_modify_paged_changed(struct phy_device *phydev, int page, u32 regnum,1122			     u16 mask, u16 set)1123{1124	int ret = 0, oldpage;1125 1126	oldpage = phy_select_page(phydev, page);1127	if (oldpage >= 0)1128		ret = __phy_modify_changed(phydev, regnum, mask, set);1129 1130	return phy_restore_page(phydev, oldpage, ret);1131}1132EXPORT_SYMBOL(phy_modify_paged_changed);1133 1134/**1135 * phy_modify_paged() - Convenience function for modifying a paged register1136 * @phydev: a pointer to a &struct phy_device1137 * @page: the page for the phy1138 * @regnum: register number1139 * @mask: bit mask of bits to clear1140 * @set: bit mask of bits to set1141 *1142 * Same rules as for phy_read() and phy_write().1143 */1144int phy_modify_paged(struct phy_device *phydev, int page, u32 regnum,1145		     u16 mask, u16 set)1146{1147	int ret = phy_modify_paged_changed(phydev, page, regnum, mask, set);1148 1149	return ret < 0 ? ret : 0;1150}1151EXPORT_SYMBOL(phy_modify_paged);1152