Skip to content

Commit

Permalink
Merge branch 'net-phy-QUSGMII'
Browse files Browse the repository at this point in the history
Maxime Chevallier says:

====================
net: Introduce QUSGMII phy mode

Re-sending, since the previous v4 was sent while net-next was closed.

This is a resend of the V4 of a previous series [1] initially aimed at
introducing inband extensions, with modes like QUSGMII. This mode allows
passing info in the ethernet preamble between the MAC and the PHY, such as
timestamps.

This series has now become a preliminary series, that simply introduces
the new interface mode, without support for inband extensions, that will
come later.

The reasonning is that work will need to be done in the networking
subsystem, but also in the generic phy driver subsystem to allow serdes
configuration for qusgmii.

This series add the mode, the relevant binding changes, adds support for
it in the lan966x driver, and also introduces a small helper to get the
number of links a given phy mode can carry (think 1 for SGMII and 4 for
QSGMII). This allows for better readability and will prove useful
when (if) we support PSGMII (5 links on 1 interface) and OUSGMII (8
links on one interface).

V4 contains no change but the collected Reviewed-by from Andrew.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Aug 22, 2022
2 parents d04807b + ac0167f commit 5b247d9
Show file tree
Hide file tree
Showing 9 changed files with 97 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ properties:
- gmii
- sgmii
- qsgmii
- qusgmii
- tbi
- rev-mii
- rmii
Expand Down
9 changes: 9 additions & 0 deletions Documentation/networking/phy.rst
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,15 @@ Some of the interface modes are described below:
rate of 125Mpbs using a 4B/5B encoding scheme, resulting in an underlying
data rate of 100Mpbs.

``PHY_INTERFACE_MODE_QUSGMII``
This defines the Cisco the Quad USGMII mode, which is the Quad variant of
the USGMII (Universal SGMII) link. It's very similar to QSGMII, but uses
a Packet Control Header (PCH) instead of the 7 bytes preamble to carry not
only the port id, but also so-called "extensions". The only documented
extension so-far in the specification is the inclusion of timestamps, for
PTP-enabled PHYs. This mode isn't compatible with QSGMII, but offers the
same capabilities in terms of link speed and negociation.

Pause frames / flow control
===========================

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/microchip/lan966x/lan966x_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,6 +778,8 @@ static int lan966x_probe_port(struct lan966x *lan966x, u32 p,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_QSGMII,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_QUSGMII,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_1000BASEX,
port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_2500BASEX,
Expand Down
3 changes: 2 additions & 1 deletion drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ static int lan966x_phylink_mac_prepare(struct phylink_config *config,
phy_interface_t iface)
{
struct lan966x_port *port = netdev_priv(to_net_dev(config->dev));
phy_interface_t serdes_mode = iface;
int err;

if (port->serdes) {
err = phy_set_mode_ext(port->serdes, PHY_MODE_ETHERNET,
iface);
serdes_mode);
if (err) {
netdev_err(to_net_dev(config->dev),
"Could not set mode of SerDes\n");
Expand Down
22 changes: 16 additions & 6 deletions drivers/net/ethernet/microchip/lan966x/lan966x_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ static void lan966x_port_link_up(struct lan966x_port *port)
/* Also the GIGA_MODE_ENA(1) needs to be set regardless of the
* port speed for QSGMII ports.
*/
if (config->portmode == PHY_INTERFACE_MODE_QSGMII)
if (phy_interface_num_ports(config->portmode) == 4)
mode = DEV_MAC_MODE_CFG_GIGA_MODE_ENA_SET(1);

lan_wr(config->duplex | mode,
Expand Down Expand Up @@ -331,10 +331,14 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
struct lan966x *lan966x = port->lan966x;
bool inband_aneg = false;
bool outband;
bool full_preamble = false;

if (config->portmode == PHY_INTERFACE_MODE_QUSGMII)
full_preamble = true;

if (config->inband) {
if (config->portmode == PHY_INTERFACE_MODE_SGMII ||
config->portmode == PHY_INTERFACE_MODE_QSGMII)
phy_interface_num_ports(config->portmode) == 4)
inband_aneg = true; /* Cisco-SGMII in-band-aneg */
else if (config->portmode == PHY_INTERFACE_MODE_1000BASEX &&
config->autoneg)
Expand All @@ -345,9 +349,15 @@ int lan966x_port_pcs_set(struct lan966x_port *port,
outband = true;
}

/* Disable or enable inband */
lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband),
DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA,
/* Disable or enable inband.
* For QUSGMII, we rely on the preamble to transmit data such as
* timestamps, therefore force full preamble transmission, and prevent
* premable shortening
*/
lan_rmw(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_SET(outband) |
DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(full_preamble),
DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA |
DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA,
lan966x, DEV_PCS1G_MODE_CFG(port->chip_port));

/* Enable PCS */
Expand Down Expand Up @@ -396,7 +406,7 @@ void lan966x_port_init(struct lan966x_port *port)
if (lan966x->fdma)
lan966x_fdma_netdev_init(lan966x, port->dev);

if (config->portmode != PHY_INTERFACE_MODE_QSGMII)
if (phy_interface_num_ports(config->portmode) != 4)
return;

lan_rmw(DEV_CLOCK_CFG_PCS_RX_RST_SET(0) |
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/ethernet/microchip/lan966x/lan966x_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,12 @@ enum lan966x_target {
#define DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA_GET(x)\
FIELD_GET(DEV_PCS1G_MODE_CFG_SGMII_MODE_ENA, x)

#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA BIT(1)
#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_SET(x)\
FIELD_PREP(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)
#define DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA_GET(x)\
FIELD_GET(DEV_PCS1G_MODE_CFG_SAVE_PREAMBLE_ENA, x)

/* DEV:PCS1G_CFG_STATUS:PCS1G_SD_CFG */
#define DEV_PCS1G_SD_CFG(t) __REG(TARGET_DEV, t, 8, 72, 0, 1, 68, 8, 0, 1, 4)

Expand Down
52 changes: 52 additions & 0 deletions drivers/net/phy/phy-core.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,58 @@ const char *phy_duplex_to_str(unsigned int duplex)
}
EXPORT_SYMBOL_GPL(phy_duplex_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:
return 1;
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
return 4;
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.
Expand Down
3 changes: 3 additions & 0 deletions drivers/net/phy/phylink.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface,
case PHY_INTERFACE_MODE_RGMII_ID:
case PHY_INTERFACE_MODE_RGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_GMII:
caps |= MAC_1000HD | MAC_1000FD;
Expand Down Expand Up @@ -632,6 +633,7 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode)
switch (pl->link_config.interface) {
case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
phylink_set(pl->supported, 10baseT_Half);
phylink_set(pl->supported, 10baseT_Full);
phylink_set(pl->supported, 100baseT_Half);
Expand Down Expand Up @@ -2929,6 +2931,7 @@ void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,

case PHY_INTERFACE_MODE_SGMII:
case PHY_INTERFACE_MODE_QSGMII:
case PHY_INTERFACE_MODE_QUSGMII:
phylink_decode_sgmii_word(state, lpa);
break;

Expand Down
6 changes: 6 additions & 0 deletions include/linux/phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ extern const int phy_10gbit_features_array[1];
* @PHY_INTERFACE_MODE_25GBASER: 25G BaseR
* @PHY_INTERFACE_MODE_USXGMII: Universal Serial 10GE MII
* @PHY_INTERFACE_MODE_10GKR: 10GBASE-KR - with Clause 73 AN
* @PHY_INTERFACE_MODE_QUSGMII: Quad Universal SGMII
* @PHY_INTERFACE_MODE_MAX: Book keeping
*
* Describes the interface between the MAC and PHY.
Expand Down Expand Up @@ -152,6 +153,7 @@ typedef enum {
PHY_INTERFACE_MODE_USXGMII,
/* 10GBASE-KR - with Clause 73 AN */
PHY_INTERFACE_MODE_10GKR,
PHY_INTERFACE_MODE_QUSGMII,
PHY_INTERFACE_MODE_MAX,
} phy_interface_t;

Expand Down Expand Up @@ -267,6 +269,8 @@ static inline const char *phy_modes(phy_interface_t interface)
return "10gbase-kr";
case PHY_INTERFACE_MODE_100BASEX:
return "100base-x";
case PHY_INTERFACE_MODE_QUSGMII:
return "qusgmii";
default:
return "unknown";
}
Expand Down Expand Up @@ -964,6 +968,8 @@ struct phy_fixup {
const char *phy_speed_to_str(int speed);
const char *phy_duplex_to_str(unsigned int duplex);

int phy_interface_num_ports(phy_interface_t interface);

/* A structure for mapping a particular speed and duplex
* combination to a particular SUPPORTED and ADVERTISED value
*/
Expand Down

0 comments on commit 5b247d9

Please sign in to comment.