]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: lan966x: Add QUSGMII support for lan966x
authorMaxime Chevallier <maxime.chevallier@bootlin.com>
Wed, 17 Aug 2022 12:32:55 +0000 (14:32 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 22 Aug 2022 12:46:26 +0000 (13:46 +0100)
The Lan996x controller supports the QUSGMII mode, which is very similar
to QSGMII in the way it's configured and the autonegociation
capababilities it provides.

This commit adds support for that mode, treating it most of the time
like QSGMII, making sure that we do configure the PCS how we should.

Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/microchip/lan966x/lan966x_main.c
drivers/net/ethernet/microchip/lan966x/lan966x_phylink.c
drivers/net/ethernet/microchip/lan966x/lan966x_port.c
drivers/net/ethernet/microchip/lan966x/lan966x_regs.h

index d928b75f37803992b87298753d894e546dd4d65f..2ad078608c450439dee25f99383a2b4dad84c86f 100644 (file)
@@ -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,
index 38a7e95d69b473a1c91e1f331f1931fdcb3e50f1..87f3d3a57aed8072c1acc755dbf3d21e95c166e2 100644 (file)
@@ -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");
index f141644e4372ff7bad8450e4260a5844f659dad4..bbf42fc8c8d5ae71ce7d74bda56074a12bca4939 100644 (file)
@@ -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,
@@ -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)
@@ -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 */
@@ -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) |
index 8265ad89f0bcb82ec7f2f2484b021915d7433022..c53bae5d8dbd45ddb2c01b0ebcf01d64d6cf91dc 100644 (file)
@@ -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)