xref: /kernel/linux/linux-6.6/include/linux/mii.h (revision 62306a36)
162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * linux/mii.h: definitions for MII-compatible transceivers
462306a36Sopenharmony_ci * Originally drivers/net/sunhme.h.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1996, 1999, 2001 David S. Miller (davem@redhat.com)
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#ifndef __LINUX_MII_H__
962306a36Sopenharmony_ci#define __LINUX_MII_H__
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#include <linux/if.h>
1362306a36Sopenharmony_ci#include <linux/linkmode.h>
1462306a36Sopenharmony_ci#include <uapi/linux/mii.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistruct ethtool_cmd;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_cistruct mii_if_info {
1962306a36Sopenharmony_ci	int phy_id;
2062306a36Sopenharmony_ci	int advertising;
2162306a36Sopenharmony_ci	int phy_id_mask;
2262306a36Sopenharmony_ci	int reg_num_mask;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	unsigned int full_duplex : 1;	/* is full duplex? */
2562306a36Sopenharmony_ci	unsigned int force_media : 1;	/* is autoneg. disabled? */
2662306a36Sopenharmony_ci	unsigned int supports_gmii : 1; /* are GMII registers supported? */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci	struct net_device *dev;
2962306a36Sopenharmony_ci	int (*mdio_read) (struct net_device *dev, int phy_id, int location);
3062306a36Sopenharmony_ci	void (*mdio_write) (struct net_device *dev, int phy_id, int location, int val);
3162306a36Sopenharmony_ci};
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ciextern int mii_link_ok (struct mii_if_info *mii);
3462306a36Sopenharmony_ciextern int mii_nway_restart (struct mii_if_info *mii);
3562306a36Sopenharmony_ciextern void mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
3662306a36Sopenharmony_ciextern void mii_ethtool_get_link_ksettings(
3762306a36Sopenharmony_ci	struct mii_if_info *mii, struct ethtool_link_ksettings *cmd);
3862306a36Sopenharmony_ciextern int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd);
3962306a36Sopenharmony_ciextern int mii_ethtool_set_link_ksettings(
4062306a36Sopenharmony_ci	struct mii_if_info *mii, const struct ethtool_link_ksettings *cmd);
4162306a36Sopenharmony_ciextern int mii_check_gmii_support(struct mii_if_info *mii);
4262306a36Sopenharmony_ciextern void mii_check_link (struct mii_if_info *mii);
4362306a36Sopenharmony_ciextern unsigned int mii_check_media (struct mii_if_info *mii,
4462306a36Sopenharmony_ci				     unsigned int ok_to_print,
4562306a36Sopenharmony_ci				     unsigned int init_media);
4662306a36Sopenharmony_ciextern int generic_mii_ioctl(struct mii_if_info *mii_if,
4762306a36Sopenharmony_ci			     struct mii_ioctl_data *mii_data, int cmd,
4862306a36Sopenharmony_ci			     unsigned int *duplex_changed);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic inline struct mii_ioctl_data *if_mii(struct ifreq *rq)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	return (struct mii_ioctl_data *) &rq->ifr_ifru;
5462306a36Sopenharmony_ci}
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/**
5762306a36Sopenharmony_ci * mii_nway_result
5862306a36Sopenharmony_ci * @negotiated: value of MII ANAR and'd with ANLPAR
5962306a36Sopenharmony_ci *
6062306a36Sopenharmony_ci * Given a set of MII abilities, check each bit and returns the
6162306a36Sopenharmony_ci * currently supported media, in the priority order defined by
6262306a36Sopenharmony_ci * IEEE 802.3u.  We use LPA_xxx constants but note this is not the
6362306a36Sopenharmony_ci * value of LPA solely, as described above.
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * The one exception to IEEE 802.3u is that 100baseT4 is placed
6662306a36Sopenharmony_ci * between 100T-full and 100T-half.  If your phy does not support
6762306a36Sopenharmony_ci * 100T4 this is fine.  If your phy places 100T4 elsewhere in the
6862306a36Sopenharmony_ci * priority order, you will need to roll your own function.
6962306a36Sopenharmony_ci */
7062306a36Sopenharmony_cistatic inline unsigned int mii_nway_result (unsigned int negotiated)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	unsigned int ret;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	if (negotiated & LPA_100FULL)
7562306a36Sopenharmony_ci		ret = LPA_100FULL;
7662306a36Sopenharmony_ci	else if (negotiated & LPA_100BASE4)
7762306a36Sopenharmony_ci		ret = LPA_100BASE4;
7862306a36Sopenharmony_ci	else if (negotiated & LPA_100HALF)
7962306a36Sopenharmony_ci		ret = LPA_100HALF;
8062306a36Sopenharmony_ci	else if (negotiated & LPA_10FULL)
8162306a36Sopenharmony_ci		ret = LPA_10FULL;
8262306a36Sopenharmony_ci	else
8362306a36Sopenharmony_ci		ret = LPA_10HALF;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	return ret;
8662306a36Sopenharmony_ci}
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci/**
8962306a36Sopenharmony_ci * mii_duplex
9062306a36Sopenharmony_ci * @duplex_lock: Non-zero if duplex is locked at full
9162306a36Sopenharmony_ci * @negotiated: value of MII ANAR and'd with ANLPAR
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci * A small helper function for a common case.  Returns one
9462306a36Sopenharmony_ci * if the media is operating or locked at full duplex, and
9562306a36Sopenharmony_ci * returns zero otherwise.
9662306a36Sopenharmony_ci */
9762306a36Sopenharmony_cistatic inline unsigned int mii_duplex (unsigned int duplex_lock,
9862306a36Sopenharmony_ci				       unsigned int negotiated)
9962306a36Sopenharmony_ci{
10062306a36Sopenharmony_ci	if (duplex_lock)
10162306a36Sopenharmony_ci		return 1;
10262306a36Sopenharmony_ci	if (mii_nway_result(negotiated) & LPA_DUPLEX)
10362306a36Sopenharmony_ci		return 1;
10462306a36Sopenharmony_ci	return 0;
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci/**
10862306a36Sopenharmony_ci * ethtool_adv_to_mii_adv_t
10962306a36Sopenharmony_ci * @ethadv: the ethtool advertisement settings
11062306a36Sopenharmony_ci *
11162306a36Sopenharmony_ci * A small helper function that translates ethtool advertisement
11262306a36Sopenharmony_ci * settings to phy autonegotiation advertisements for the
11362306a36Sopenharmony_ci * MII_ADVERTISE register.
11462306a36Sopenharmony_ci */
11562306a36Sopenharmony_cistatic inline u32 ethtool_adv_to_mii_adv_t(u32 ethadv)
11662306a36Sopenharmony_ci{
11762306a36Sopenharmony_ci	u32 result = 0;
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci	if (ethadv & ADVERTISED_10baseT_Half)
12062306a36Sopenharmony_ci		result |= ADVERTISE_10HALF;
12162306a36Sopenharmony_ci	if (ethadv & ADVERTISED_10baseT_Full)
12262306a36Sopenharmony_ci		result |= ADVERTISE_10FULL;
12362306a36Sopenharmony_ci	if (ethadv & ADVERTISED_100baseT_Half)
12462306a36Sopenharmony_ci		result |= ADVERTISE_100HALF;
12562306a36Sopenharmony_ci	if (ethadv & ADVERTISED_100baseT_Full)
12662306a36Sopenharmony_ci		result |= ADVERTISE_100FULL;
12762306a36Sopenharmony_ci	if (ethadv & ADVERTISED_Pause)
12862306a36Sopenharmony_ci		result |= ADVERTISE_PAUSE_CAP;
12962306a36Sopenharmony_ci	if (ethadv & ADVERTISED_Asym_Pause)
13062306a36Sopenharmony_ci		result |= ADVERTISE_PAUSE_ASYM;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	return result;
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/**
13662306a36Sopenharmony_ci * linkmode_adv_to_mii_adv_t
13762306a36Sopenharmony_ci * @advertising: the linkmode advertisement settings
13862306a36Sopenharmony_ci *
13962306a36Sopenharmony_ci * A small helper function that translates linkmode advertisement
14062306a36Sopenharmony_ci * settings to phy autonegotiation advertisements for the
14162306a36Sopenharmony_ci * MII_ADVERTISE register.
14262306a36Sopenharmony_ci */
14362306a36Sopenharmony_cistatic inline u32 linkmode_adv_to_mii_adv_t(unsigned long *advertising)
14462306a36Sopenharmony_ci{
14562306a36Sopenharmony_ci	u32 result = 0;
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, advertising))
14862306a36Sopenharmony_ci		result |= ADVERTISE_10HALF;
14962306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, advertising))
15062306a36Sopenharmony_ci		result |= ADVERTISE_10FULL;
15162306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, advertising))
15262306a36Sopenharmony_ci		result |= ADVERTISE_100HALF;
15362306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, advertising))
15462306a36Sopenharmony_ci		result |= ADVERTISE_100FULL;
15562306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising))
15662306a36Sopenharmony_ci		result |= ADVERTISE_PAUSE_CAP;
15762306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, advertising))
15862306a36Sopenharmony_ci		result |= ADVERTISE_PAUSE_ASYM;
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_ci	return result;
16162306a36Sopenharmony_ci}
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci/**
16462306a36Sopenharmony_ci * mii_adv_to_ethtool_adv_t
16562306a36Sopenharmony_ci * @adv: value of the MII_ADVERTISE register
16662306a36Sopenharmony_ci *
16762306a36Sopenharmony_ci * A small helper function that translates MII_ADVERTISE bits
16862306a36Sopenharmony_ci * to ethtool advertisement settings.
16962306a36Sopenharmony_ci */
17062306a36Sopenharmony_cistatic inline u32 mii_adv_to_ethtool_adv_t(u32 adv)
17162306a36Sopenharmony_ci{
17262306a36Sopenharmony_ci	u32 result = 0;
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci	if (adv & ADVERTISE_10HALF)
17562306a36Sopenharmony_ci		result |= ADVERTISED_10baseT_Half;
17662306a36Sopenharmony_ci	if (adv & ADVERTISE_10FULL)
17762306a36Sopenharmony_ci		result |= ADVERTISED_10baseT_Full;
17862306a36Sopenharmony_ci	if (adv & ADVERTISE_100HALF)
17962306a36Sopenharmony_ci		result |= ADVERTISED_100baseT_Half;
18062306a36Sopenharmony_ci	if (adv & ADVERTISE_100FULL)
18162306a36Sopenharmony_ci		result |= ADVERTISED_100baseT_Full;
18262306a36Sopenharmony_ci	if (adv & ADVERTISE_PAUSE_CAP)
18362306a36Sopenharmony_ci		result |= ADVERTISED_Pause;
18462306a36Sopenharmony_ci	if (adv & ADVERTISE_PAUSE_ASYM)
18562306a36Sopenharmony_ci		result |= ADVERTISED_Asym_Pause;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	return result;
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci/**
19162306a36Sopenharmony_ci * ethtool_adv_to_mii_ctrl1000_t
19262306a36Sopenharmony_ci * @ethadv: the ethtool advertisement settings
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * A small helper function that translates ethtool advertisement
19562306a36Sopenharmony_ci * settings to phy autonegotiation advertisements for the
19662306a36Sopenharmony_ci * MII_CTRL1000 register when in 1000T mode.
19762306a36Sopenharmony_ci */
19862306a36Sopenharmony_cistatic inline u32 ethtool_adv_to_mii_ctrl1000_t(u32 ethadv)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	u32 result = 0;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (ethadv & ADVERTISED_1000baseT_Half)
20362306a36Sopenharmony_ci		result |= ADVERTISE_1000HALF;
20462306a36Sopenharmony_ci	if (ethadv & ADVERTISED_1000baseT_Full)
20562306a36Sopenharmony_ci		result |= ADVERTISE_1000FULL;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	return result;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci/**
21162306a36Sopenharmony_ci * linkmode_adv_to_mii_ctrl1000_t
21262306a36Sopenharmony_ci * @advertising: the linkmode advertisement settings
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * A small helper function that translates linkmode advertisement
21562306a36Sopenharmony_ci * settings to phy autonegotiation advertisements for the
21662306a36Sopenharmony_ci * MII_CTRL1000 register when in 1000T mode.
21762306a36Sopenharmony_ci */
21862306a36Sopenharmony_cistatic inline u32 linkmode_adv_to_mii_ctrl1000_t(unsigned long *advertising)
21962306a36Sopenharmony_ci{
22062306a36Sopenharmony_ci	u32 result = 0;
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
22362306a36Sopenharmony_ci			      advertising))
22462306a36Sopenharmony_ci		result |= ADVERTISE_1000HALF;
22562306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
22662306a36Sopenharmony_ci			      advertising))
22762306a36Sopenharmony_ci		result |= ADVERTISE_1000FULL;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	return result;
23062306a36Sopenharmony_ci}
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci/**
23362306a36Sopenharmony_ci * mii_ctrl1000_to_ethtool_adv_t
23462306a36Sopenharmony_ci * @adv: value of the MII_CTRL1000 register
23562306a36Sopenharmony_ci *
23662306a36Sopenharmony_ci * A small helper function that translates MII_CTRL1000
23762306a36Sopenharmony_ci * bits, when in 1000Base-T mode, to ethtool
23862306a36Sopenharmony_ci * advertisement settings.
23962306a36Sopenharmony_ci */
24062306a36Sopenharmony_cistatic inline u32 mii_ctrl1000_to_ethtool_adv_t(u32 adv)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	u32 result = 0;
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (adv & ADVERTISE_1000HALF)
24562306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Half;
24662306a36Sopenharmony_ci	if (adv & ADVERTISE_1000FULL)
24762306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Full;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	return result;
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci/**
25362306a36Sopenharmony_ci * mii_lpa_to_ethtool_lpa_t
25462306a36Sopenharmony_ci * @adv: value of the MII_LPA register
25562306a36Sopenharmony_ci *
25662306a36Sopenharmony_ci * A small helper function that translates MII_LPA
25762306a36Sopenharmony_ci * bits, when in 1000Base-T mode, to ethtool
25862306a36Sopenharmony_ci * LP advertisement settings.
25962306a36Sopenharmony_ci */
26062306a36Sopenharmony_cistatic inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	u32 result = 0;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	if (lpa & LPA_LPACK)
26562306a36Sopenharmony_ci		result |= ADVERTISED_Autoneg;
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	return result | mii_adv_to_ethtool_adv_t(lpa);
26862306a36Sopenharmony_ci}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci/**
27162306a36Sopenharmony_ci * mii_stat1000_to_ethtool_lpa_t
27262306a36Sopenharmony_ci * @adv: value of the MII_STAT1000 register
27362306a36Sopenharmony_ci *
27462306a36Sopenharmony_ci * A small helper function that translates MII_STAT1000
27562306a36Sopenharmony_ci * bits, when in 1000Base-T mode, to ethtool
27662306a36Sopenharmony_ci * advertisement settings.
27762306a36Sopenharmony_ci */
27862306a36Sopenharmony_cistatic inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa)
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	u32 result = 0;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	if (lpa & LPA_1000HALF)
28362306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Half;
28462306a36Sopenharmony_ci	if (lpa & LPA_1000FULL)
28562306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Full;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	return result;
28862306a36Sopenharmony_ci}
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci/**
29162306a36Sopenharmony_ci * mii_stat1000_mod_linkmode_lpa_t
29262306a36Sopenharmony_ci * @advertising: target the linkmode advertisement settings
29362306a36Sopenharmony_ci * @adv: value of the MII_STAT1000 register
29462306a36Sopenharmony_ci *
29562306a36Sopenharmony_ci * A small helper function that translates MII_STAT1000 bits, when in
29662306a36Sopenharmony_ci * 1000Base-T mode, to linkmode advertisement settings. Other bits in
29762306a36Sopenharmony_ci * advertising are not changes.
29862306a36Sopenharmony_ci */
29962306a36Sopenharmony_cistatic inline void mii_stat1000_mod_linkmode_lpa_t(unsigned long *advertising,
30062306a36Sopenharmony_ci						   u32 lpa)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT,
30362306a36Sopenharmony_ci			 advertising, lpa & LPA_1000HALF);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
30662306a36Sopenharmony_ci			 advertising, lpa & LPA_1000FULL);
30762306a36Sopenharmony_ci}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci/**
31062306a36Sopenharmony_ci * ethtool_adv_to_mii_adv_x
31162306a36Sopenharmony_ci * @ethadv: the ethtool advertisement settings
31262306a36Sopenharmony_ci *
31362306a36Sopenharmony_ci * A small helper function that translates ethtool advertisement
31462306a36Sopenharmony_ci * settings to phy autonegotiation advertisements for the
31562306a36Sopenharmony_ci * MII_CTRL1000 register when in 1000Base-X mode.
31662306a36Sopenharmony_ci */
31762306a36Sopenharmony_cistatic inline u32 ethtool_adv_to_mii_adv_x(u32 ethadv)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	u32 result = 0;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	if (ethadv & ADVERTISED_1000baseT_Half)
32262306a36Sopenharmony_ci		result |= ADVERTISE_1000XHALF;
32362306a36Sopenharmony_ci	if (ethadv & ADVERTISED_1000baseT_Full)
32462306a36Sopenharmony_ci		result |= ADVERTISE_1000XFULL;
32562306a36Sopenharmony_ci	if (ethadv & ADVERTISED_Pause)
32662306a36Sopenharmony_ci		result |= ADVERTISE_1000XPAUSE;
32762306a36Sopenharmony_ci	if (ethadv & ADVERTISED_Asym_Pause)
32862306a36Sopenharmony_ci		result |= ADVERTISE_1000XPSE_ASYM;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	return result;
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci/**
33462306a36Sopenharmony_ci * mii_adv_to_ethtool_adv_x
33562306a36Sopenharmony_ci * @adv: value of the MII_CTRL1000 register
33662306a36Sopenharmony_ci *
33762306a36Sopenharmony_ci * A small helper function that translates MII_CTRL1000
33862306a36Sopenharmony_ci * bits, when in 1000Base-X mode, to ethtool
33962306a36Sopenharmony_ci * advertisement settings.
34062306a36Sopenharmony_ci */
34162306a36Sopenharmony_cistatic inline u32 mii_adv_to_ethtool_adv_x(u32 adv)
34262306a36Sopenharmony_ci{
34362306a36Sopenharmony_ci	u32 result = 0;
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci	if (adv & ADVERTISE_1000XHALF)
34662306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Half;
34762306a36Sopenharmony_ci	if (adv & ADVERTISE_1000XFULL)
34862306a36Sopenharmony_ci		result |= ADVERTISED_1000baseT_Full;
34962306a36Sopenharmony_ci	if (adv & ADVERTISE_1000XPAUSE)
35062306a36Sopenharmony_ci		result |= ADVERTISED_Pause;
35162306a36Sopenharmony_ci	if (adv & ADVERTISE_1000XPSE_ASYM)
35262306a36Sopenharmony_ci		result |= ADVERTISED_Asym_Pause;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	return result;
35562306a36Sopenharmony_ci}
35662306a36Sopenharmony_ci
35762306a36Sopenharmony_ci/**
35862306a36Sopenharmony_ci * mii_adv_mod_linkmode_adv_t
35962306a36Sopenharmony_ci * @advertising:pointer to destination link mode.
36062306a36Sopenharmony_ci * @adv: value of the MII_ADVERTISE register
36162306a36Sopenharmony_ci *
36262306a36Sopenharmony_ci * A small helper function that translates MII_ADVERTISE bits to
36362306a36Sopenharmony_ci * linkmode advertisement settings. Leaves other bits unchanged.
36462306a36Sopenharmony_ci */
36562306a36Sopenharmony_cistatic inline void mii_adv_mod_linkmode_adv_t(unsigned long *advertising,
36662306a36Sopenharmony_ci					      u32 adv)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
36962306a36Sopenharmony_ci			 advertising, adv & ADVERTISE_10HALF);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
37262306a36Sopenharmony_ci			 advertising, adv & ADVERTISE_10FULL);
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
37562306a36Sopenharmony_ci			 advertising, adv & ADVERTISE_100HALF);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
37862306a36Sopenharmony_ci			 advertising, adv & ADVERTISE_100FULL);
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, advertising,
38162306a36Sopenharmony_ci			 adv & ADVERTISE_PAUSE_CAP);
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
38462306a36Sopenharmony_ci			 advertising, adv & ADVERTISE_PAUSE_ASYM);
38562306a36Sopenharmony_ci}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci/**
38862306a36Sopenharmony_ci * mii_adv_to_linkmode_adv_t
38962306a36Sopenharmony_ci * @advertising:pointer to destination link mode.
39062306a36Sopenharmony_ci * @adv: value of the MII_ADVERTISE register
39162306a36Sopenharmony_ci *
39262306a36Sopenharmony_ci * A small helper function that translates MII_ADVERTISE bits
39362306a36Sopenharmony_ci * to linkmode advertisement settings. Clears the old value
39462306a36Sopenharmony_ci * of advertising.
39562306a36Sopenharmony_ci */
39662306a36Sopenharmony_cistatic inline void mii_adv_to_linkmode_adv_t(unsigned long *advertising,
39762306a36Sopenharmony_ci					     u32 adv)
39862306a36Sopenharmony_ci{
39962306a36Sopenharmony_ci	linkmode_zero(advertising);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci	mii_adv_mod_linkmode_adv_t(advertising, adv);
40262306a36Sopenharmony_ci}
40362306a36Sopenharmony_ci
40462306a36Sopenharmony_ci/**
40562306a36Sopenharmony_ci * mii_lpa_to_linkmode_lpa_t
40662306a36Sopenharmony_ci * @adv: value of the MII_LPA register
40762306a36Sopenharmony_ci *
40862306a36Sopenharmony_ci * A small helper function that translates MII_LPA bits, when in
40962306a36Sopenharmony_ci * 1000Base-T mode, to linkmode LP advertisement settings. Clears the
41062306a36Sopenharmony_ci * old value of advertising
41162306a36Sopenharmony_ci */
41262306a36Sopenharmony_cistatic inline void mii_lpa_to_linkmode_lpa_t(unsigned long *lp_advertising,
41362306a36Sopenharmony_ci					     u32 lpa)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	mii_adv_to_linkmode_adv_t(lp_advertising, lpa);
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (lpa & LPA_LPACK)
41862306a36Sopenharmony_ci		linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
41962306a36Sopenharmony_ci				 lp_advertising);
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci}
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci/**
42462306a36Sopenharmony_ci * mii_lpa_mod_linkmode_lpa_t
42562306a36Sopenharmony_ci * @adv: value of the MII_LPA register
42662306a36Sopenharmony_ci *
42762306a36Sopenharmony_ci * A small helper function that translates MII_LPA bits, when in
42862306a36Sopenharmony_ci * 1000Base-T mode, to linkmode LP advertisement settings. Leaves
42962306a36Sopenharmony_ci * other bits unchanged.
43062306a36Sopenharmony_ci */
43162306a36Sopenharmony_cistatic inline void mii_lpa_mod_linkmode_lpa_t(unsigned long *lp_advertising,
43262306a36Sopenharmony_ci					      u32 lpa)
43362306a36Sopenharmony_ci{
43462306a36Sopenharmony_ci	mii_adv_mod_linkmode_adv_t(lp_advertising, lpa);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
43762306a36Sopenharmony_ci			 lp_advertising, lpa & LPA_LPACK);
43862306a36Sopenharmony_ci}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistatic inline void mii_ctrl1000_mod_linkmode_adv_t(unsigned long *advertising,
44162306a36Sopenharmony_ci						   u32 ctrl1000)
44262306a36Sopenharmony_ci{
44362306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, advertising,
44462306a36Sopenharmony_ci			 ctrl1000 & ADVERTISE_1000HALF);
44562306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, advertising,
44662306a36Sopenharmony_ci			 ctrl1000 & ADVERTISE_1000FULL);
44762306a36Sopenharmony_ci}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci/**
45062306a36Sopenharmony_ci * linkmode_adv_to_lcl_adv_t
45162306a36Sopenharmony_ci * @advertising:pointer to linkmode advertising
45262306a36Sopenharmony_ci *
45362306a36Sopenharmony_ci * A small helper function that translates linkmode advertising to LVL
45462306a36Sopenharmony_ci * pause capabilities.
45562306a36Sopenharmony_ci */
45662306a36Sopenharmony_cistatic inline u32 linkmode_adv_to_lcl_adv_t(unsigned long *advertising)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	u32 lcl_adv = 0;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT,
46162306a36Sopenharmony_ci			      advertising))
46262306a36Sopenharmony_ci		lcl_adv |= ADVERTISE_PAUSE_CAP;
46362306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
46462306a36Sopenharmony_ci			      advertising))
46562306a36Sopenharmony_ci		lcl_adv |= ADVERTISE_PAUSE_ASYM;
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	return lcl_adv;
46862306a36Sopenharmony_ci}
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci/**
47162306a36Sopenharmony_ci * mii_lpa_mod_linkmode_x - decode the link partner's config_reg to linkmodes
47262306a36Sopenharmony_ci * @linkmodes: link modes array
47362306a36Sopenharmony_ci * @lpa: config_reg word from link partner
47462306a36Sopenharmony_ci * @fd_bit: link mode for 1000XFULL bit
47562306a36Sopenharmony_ci */
47662306a36Sopenharmony_cistatic inline void mii_lpa_mod_linkmode_x(unsigned long *linkmodes, u16 lpa,
47762306a36Sopenharmony_ci					 int fd_bit)
47862306a36Sopenharmony_ci{
47962306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, linkmodes,
48062306a36Sopenharmony_ci			 lpa & LPA_LPACK);
48162306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes,
48262306a36Sopenharmony_ci			 lpa & LPA_1000XPAUSE);
48362306a36Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes,
48462306a36Sopenharmony_ci			 lpa & LPA_1000XPAUSE_ASYM);
48562306a36Sopenharmony_ci	linkmode_mod_bit(fd_bit, linkmodes,
48662306a36Sopenharmony_ci			 lpa & LPA_1000XFULL);
48762306a36Sopenharmony_ci}
48862306a36Sopenharmony_ci
48962306a36Sopenharmony_ci/**
49062306a36Sopenharmony_ci * linkmode_adv_to_mii_adv_x - encode a linkmode to config_reg
49162306a36Sopenharmony_ci * @linkmodes: linkmodes
49262306a36Sopenharmony_ci * @fd_bit: full duplex bit
49362306a36Sopenharmony_ci */
49462306a36Sopenharmony_cistatic inline u16 linkmode_adv_to_mii_adv_x(const unsigned long *linkmodes,
49562306a36Sopenharmony_ci					    int fd_bit)
49662306a36Sopenharmony_ci{
49762306a36Sopenharmony_ci	u16 adv = 0;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	if (linkmode_test_bit(fd_bit, linkmodes))
50062306a36Sopenharmony_ci		adv |= ADVERTISE_1000XFULL;
50162306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes))
50262306a36Sopenharmony_ci		adv |= ADVERTISE_1000XPAUSE;
50362306a36Sopenharmony_ci	if (linkmode_test_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes))
50462306a36Sopenharmony_ci		adv |= ADVERTISE_1000XPSE_ASYM;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	return adv;
50762306a36Sopenharmony_ci}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci/**
51062306a36Sopenharmony_ci * mii_advertise_flowctrl - get flow control advertisement flags
51162306a36Sopenharmony_ci * @cap: Flow control capabilities (FLOW_CTRL_RX, FLOW_CTRL_TX or both)
51262306a36Sopenharmony_ci */
51362306a36Sopenharmony_cistatic inline u16 mii_advertise_flowctrl(int cap)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	u16 adv = 0;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	if (cap & FLOW_CTRL_RX)
51862306a36Sopenharmony_ci		adv = ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
51962306a36Sopenharmony_ci	if (cap & FLOW_CTRL_TX)
52062306a36Sopenharmony_ci		adv ^= ADVERTISE_PAUSE_ASYM;
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	return adv;
52362306a36Sopenharmony_ci}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_ci/**
52662306a36Sopenharmony_ci * mii_resolve_flowctrl_fdx
52762306a36Sopenharmony_ci * @lcladv: value of MII ADVERTISE register
52862306a36Sopenharmony_ci * @rmtadv: value of MII LPA register
52962306a36Sopenharmony_ci *
53062306a36Sopenharmony_ci * Resolve full duplex flow control as per IEEE 802.3-2005 table 28B-3
53162306a36Sopenharmony_ci */
53262306a36Sopenharmony_cistatic inline u8 mii_resolve_flowctrl_fdx(u16 lcladv, u16 rmtadv)
53362306a36Sopenharmony_ci{
53462306a36Sopenharmony_ci	u8 cap = 0;
53562306a36Sopenharmony_ci
53662306a36Sopenharmony_ci	if (lcladv & rmtadv & ADVERTISE_PAUSE_CAP) {
53762306a36Sopenharmony_ci		cap = FLOW_CTRL_TX | FLOW_CTRL_RX;
53862306a36Sopenharmony_ci	} else if (lcladv & rmtadv & ADVERTISE_PAUSE_ASYM) {
53962306a36Sopenharmony_ci		if (lcladv & ADVERTISE_PAUSE_CAP)
54062306a36Sopenharmony_ci			cap = FLOW_CTRL_RX;
54162306a36Sopenharmony_ci		else if (rmtadv & ADVERTISE_PAUSE_CAP)
54262306a36Sopenharmony_ci			cap = FLOW_CTRL_TX;
54362306a36Sopenharmony_ci	}
54462306a36Sopenharmony_ci
54562306a36Sopenharmony_ci	return cap;
54662306a36Sopenharmony_ci}
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci/**
54962306a36Sopenharmony_ci * mii_bmcr_encode_fixed - encode fixed speed/duplex settings to a BMCR value
55062306a36Sopenharmony_ci * @speed: a SPEED_* value
55162306a36Sopenharmony_ci * @duplex: a DUPLEX_* value
55262306a36Sopenharmony_ci *
55362306a36Sopenharmony_ci * Encode the speed and duplex to a BMCR value. 2500, 1000, 100 and 10 Mbps are
55462306a36Sopenharmony_ci * supported. 2500Mbps is encoded to 1000Mbps. Other speeds are encoded as 10
55562306a36Sopenharmony_ci * Mbps. Unknown duplex values are encoded to half-duplex.
55662306a36Sopenharmony_ci */
55762306a36Sopenharmony_cistatic inline u16 mii_bmcr_encode_fixed(int speed, int duplex)
55862306a36Sopenharmony_ci{
55962306a36Sopenharmony_ci	u16 bmcr;
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	switch (speed) {
56262306a36Sopenharmony_ci	case SPEED_2500:
56362306a36Sopenharmony_ci	case SPEED_1000:
56462306a36Sopenharmony_ci		bmcr = BMCR_SPEED1000;
56562306a36Sopenharmony_ci		break;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	case SPEED_100:
56862306a36Sopenharmony_ci		bmcr = BMCR_SPEED100;
56962306a36Sopenharmony_ci		break;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci	case SPEED_10:
57262306a36Sopenharmony_ci	default:
57362306a36Sopenharmony_ci		bmcr = BMCR_SPEED10;
57462306a36Sopenharmony_ci		break;
57562306a36Sopenharmony_ci	}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_ci	if (duplex == DUPLEX_FULL)
57862306a36Sopenharmony_ci		bmcr |= BMCR_FULLDPLX;
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	return bmcr;
58162306a36Sopenharmony_ci}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci#endif /* __LINUX_MII_H__ */
584