// SPDX-License-Identifier: GPL-2.0+
/*
* Core PHY library, taken from phy.c
*/
#include <linux/export.h>
#include <linux/phy.h>
#include <linux/of.h>
/**
* phy_speed_to_str - Return a string representing the PHY link speed
*
* @speed: Speed of the link
*/
const char *phy_speed_to_str(int speed)
{
BUILD_BUG_ON_MSG(__ETHTOOL_LINK_MODE_MASK_NBITS != 103,
"Enum ethtool_link_mode_bit_indices and phylib are out of sync. "
"If a speed or mode has been added please update phy_speed_to_str "
"and the PHY settings array.\n");
switch (speed) {
case SPEED_10:
return "10Mbps";
case SPEED_100:
return "100Mbps";
case SPEED_1000:
return "1Gbps";
case SPEED_2500:
return "2.5Gbps";
case SPEED_5000:
return "5Gbps";
case SPEED_10000:
return "10Gbps";
case SPEED_14000:
return "14Gbps";
case SPEED_20000:
return "20Gbps";
case SPEED_25000:
return "25Gbps";
case SPEED_40000:
return "40Gbps";
case SPEED_50000:
return "50Gbps";
case SPEED_56000:
return "56Gbps";
case SPEED_100000:
return "100Gbps";
case SPEED_200000:
return "200Gbps";
case SPEED_400000:
return "400Gbps";
case SPEED_800000:
return "800Gbps";
case SPEED_UNKNOWN:
return "Unknown";
default:
return "Unsupported (update phy-core.c)";
}
}
EXPORT_SYMBOL_GPL(phy_speed_to_str);
/**
* phy_duplex_to_str - Return string describing the duplex
*
* @duplex: Duplex setting to describe
*/
const char *phy_duplex_to_str(unsigned int duplex)
{
if (duplex == DUPLEX_HALF)
return "Half";
if (duplex == DUPLEX_FULL)
return "Full";
if (duplex == DUPLEX_UNKNOWN)
return "Unknown";
return "Unsupported (update phy-core.c)";
}
EXPORT_SYMBOL_GPL(phy_duplex_to_str);
/**
* phy_rate_matching_to_str - Return a string describing the rate matching
*
* @rate_matching: Type of rate matching to describe
*/
const char *phy_rate_matching_to_str(int rate_matching)
{
switch (rate_matching) {
case RATE_MATCH_NONE:
return "none";
case RATE_MATCH_PAUSE:
return "pause";
case RATE_MATCH_CRS:
return "crs";
case RATE_MATCH_OPEN_LOOP:
return "open-loop";
}
return "Unsupported (update phy-core.c)";
}
EXPORT_SYMBOL_GPL(phy_rate_matching_to_str);
/**
* phy_interface_num_ports - Return the number of links that can be carried by
* a given MAC-PHY physical link. Returns 0 if this is
* unknown, the number of links else.
*
* @interface: The interface mode we want to get the number of ports
*/
int phy_interface_num_ports(phy_interface_t interface)
{
switch (interface) {
case PHY_INTERFACE_MODE_NA:
return 0;
case PHY_INTERFACE_MODE_INTERNAL:
case PHY_INTERFACE_MODE_MII:
case PHY_INTERFACE_MODE_GMII:
case PHY_INTERFACE_MODE_TBI:
case PHY_INTERFACE_MODE_REVMII:
case PHY_INTERFACE_MODE_RMII:
case PHY_INTERFACE_MODE_REVRMII:
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII_RXID:
case PHY_INTERFACE_MODE_RGMII_TXID:
case PHY_INTERFACE_MODE_RTBI:
case PHY_INTERFACE_MODE_XGMII:
case PHY_INTERFACE_MODE_XLGMII:
case PHY_INTERFACE_MODE_MOCA:
case PHY_INTERFACE_MODE_TRGMII:
case PHY_INTERFACE_MODE_USXGMII:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_SMII:
case PHY_INTERFACE_MODE_1000BASEX:
case PHY_INTERFACE_MODE_2500BASEX:
case PHY_INTERFACE_MODE_5GBASER:
case PHY_INTERFACE_MODE_10GBASER:
case PHY_INTERFACE_MODE_25GBASER:
case PHY_INTERFACE_MODE_10GKR:
case PHY_INTERFACE_MODE_100BASEX:
case PHY_INTERFACE_MODE_RXAUI:
case PHY_INTERFACE_MODE_XAUI:
case PHY_INTERFACE_MODE_1000BASEKX:
return 1;
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_10G_QXGMII:
return 4;
case PHY_INTERFACE_MODE_PSGMII:
return 5;
case PHY_INTERFACE_MODE_MAX:
WARN_ONCE(1, "PHY_INTERFACE_MODE_MAX isn't a valid interface mode");
return 0;
}
return 0;
}
EXPORT_SYMBOL_GPL(phy_interface_num_ports);
/* A mapping of all SUPPORTED settings to speed/duplex. This table
* must be grouped by speed and sorted in descending match priority
* - iow, descending speed.
*/
#define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \
.bit = ETHTOOL_LINK_MODE_ ## b ## _BIT}
static const struct phy_setting settings[] = {
/* 800G */
PHY_SETTING( 800000, FULL, 800000baseCR8_Full ),
PHY_SETTING( 800000, FULL, 800000baseKR8_Full ),
PHY_SETTING( 800000, FULL, 800000baseDR8_Full ),
PHY_SETTING( 800000, FULL, 800000baseDR8_2_Full ),
PHY_SETTING( 800000, FULL, 800000baseSR8_Full ),
PHY_SETTING( 800000, FULL, 800000baseVR8_Full ),
/* 400G */
PHY_SETTING( 400000, FULL, 400000baseCR8_Full ),
PHY_SETTING( 400000, FULL, 400000baseKR8_Full ),
PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full ),
PHY_SETTING( 400000, FULL, 400000baseDR8_Full ),
PHY_SETTING( 400000, FULL, 400000baseSR8_Full ),
PHY_SETTING( 400000, FULL, 400000baseCR4_Full ),
PHY_SETTING(