net: dsa: qca8k: Allow overwriting CPU port setting
authorMichal Vokáč <vokac.m@gmail.com>
Wed, 23 May 2018 06:20:22 +0000 (08:20 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 3 Aug 2018 05:55:27 +0000 (07:55 +0200)
commit 9bb2289f90e671bdb78e306974187424ac19ff8e upstream.

Implement adjust_link function that allows to overwrite default CPU port
setting using fixed-link device tree subnode.

Signed-off-by: Michal Vokáč <michal.vokac@ysoft.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/dsa/qca8k.c
drivers/net/dsa/qca8k.h

index dbd7022..7f64a76 100644 (file)
@@ -589,6 +589,47 @@ qca8k_setup(struct dsa_switch *ds)
        return 0;
 }
 
+static void
+qca8k_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phy)
+{
+       struct qca8k_priv *priv = ds->priv;
+       u32 reg;
+
+       /* Force fixed-link setting for CPU port, skip others. */
+       if (!phy_is_pseudo_fixed_link(phy))
+               return;
+
+       /* Set port speed */
+       switch (phy->speed) {
+       case 10:
+               reg = QCA8K_PORT_STATUS_SPEED_10;
+               break;
+       case 100:
+               reg = QCA8K_PORT_STATUS_SPEED_100;
+               break;
+       case 1000:
+               reg = QCA8K_PORT_STATUS_SPEED_1000;
+               break;
+       default:
+               dev_dbg(priv->dev, "port%d link speed %dMbps not supported.\n",
+                       port, phy->speed);
+               return;
+       }
+
+       /* Set duplex mode */
+       if (phy->duplex == DUPLEX_FULL)
+               reg |= QCA8K_PORT_STATUS_DUPLEX;
+
+       /* Force flow control */
+       if (dsa_is_cpu_port(ds, port))
+               reg |= QCA8K_PORT_STATUS_RXFLOW | QCA8K_PORT_STATUS_TXFLOW;
+
+       /* Force link down before changing MAC options */
+       qca8k_port_set_status(priv, port, 0);
+       qca8k_write(priv, QCA8K_REG_PORT_STATUS(port), reg);
+       qca8k_port_set_status(priv, port, 1);
+}
+
 static int
 qca8k_phy_read(struct dsa_switch *ds, int phy, int regnum)
 {
@@ -918,6 +959,7 @@ qca8k_get_tag_protocol(struct dsa_switch *ds)
 static struct dsa_switch_ops qca8k_switch_ops = {
        .get_tag_protocol       = qca8k_get_tag_protocol,
        .setup                  = qca8k_setup,
+       .adjust_link            = qca8k_adjust_link,
        .get_strings            = qca8k_get_strings,
        .phy_read               = qca8k_phy_read,
        .phy_write              = qca8k_phy_write,
@@ -950,6 +992,7 @@ qca8k_sw_probe(struct mdio_device *mdiodev)
                return -ENOMEM;
 
        priv->bus = mdiodev->bus;
+       priv->dev = &mdiodev->dev;
 
        /* read the switches ID register */
        id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
index 2f85f7a..9c22bc3 100644 (file)
@@ -169,6 +169,7 @@ struct qca8k_priv {
        struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];
        struct dsa_switch *ds;
        struct mutex reg_mutex;
+       struct device *dev;
 };
 
 struct qca8k_mib_desc {