kernel: 5.10: backport qca8k stability improvements
[openwrt/openwrt.git] / target / linux / generic / backport-5.10 / 785-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch
diff --git a/target/linux/generic/backport-5.10/785-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch b/target/linux/generic/backport-5.10/785-v5.14-14-net-dsa-qca8k-add-support-for-switch-rev.patch
new file mode 100644 (file)
index 0000000..ed9b818
--- /dev/null
@@ -0,0 +1,114 @@
+From 95ffeaf18b3bb90eeef52cbf7d79ccc9d0345ff5 Mon Sep 17 00:00:00 2001
+From: Ansuel Smith <ansuelsmth@gmail.com>
+Date: Fri, 14 May 2021 23:00:04 +0200
+Subject: [PATCH] net: dsa: qca8k: add support for switch rev
+
+qca8k internal phy driver require some special debug value to be set
+based on the switch revision. Rework the switch id read function to
+also read the chip revision.
+
+Signed-off-by: Ansuel Smith <ansuelsmth@gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/qca8k.c | 53 ++++++++++++++++++++++++++---------------
+ drivers/net/dsa/qca8k.h |  7 ++++--
+ 2 files changed, 39 insertions(+), 21 deletions(-)
+
+--- a/drivers/net/dsa/qca8k.c
++++ b/drivers/net/dsa/qca8k.c
+@@ -1588,12 +1588,40 @@ static const struct dsa_switch_ops qca8k
+       .phylink_mac_link_up    = qca8k_phylink_mac_link_up,
+ };
++static int qca8k_read_switch_id(struct qca8k_priv *priv)
++{
++      const struct qca8k_match_data *data;
++      u32 val;
++      u8 id;
++
++      /* get the switches ID from the compatible */
++      data = of_device_get_match_data(priv->dev);
++      if (!data)
++              return -ENODEV;
++
++      val = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
++      if (val < 0)
++              return -ENODEV;
++
++      id = QCA8K_MASK_CTRL_DEVICE_ID(val & QCA8K_MASK_CTRL_DEVICE_ID_MASK);
++      if (id != data->id) {
++              dev_err(priv->dev, "Switch id detected %x but expected %x", id, data->id);
++              return -ENODEV;
++      }
++
++      priv->switch_id = id;
++
++      /* Save revision to communicate to the internal PHY driver */
++      priv->switch_revision = (val & QCA8K_MASK_CTRL_REV_ID_MASK);
++
++      return 0;
++}
++
+ static int
+ qca8k_sw_probe(struct mdio_device *mdiodev)
+ {
+-      const struct qca8k_match_data *data;
+       struct qca8k_priv *priv;
+-      u32 id;
++      int ret;
+       /* allocate the private data struct so that we can probe the switches
+        * ID register
+@@ -1619,24 +1647,11 @@ qca8k_sw_probe(struct mdio_device *mdiod
+               gpiod_set_value_cansleep(priv->reset_gpio, 0);
+       }
+-      /* get the switches ID from the compatible */
+-      data = of_device_get_match_data(&mdiodev->dev);
+-      if (!data)
+-              return -ENODEV;
++      /* Check the detected switch id */
++      ret = qca8k_read_switch_id(priv);
++      if (ret)
++              return ret;
+-      /* read the switches ID register */
+-      id = qca8k_read(priv, QCA8K_REG_MASK_CTRL);
+-      if (id < 0)
+-              return id;
+-
+-      id >>= QCA8K_MASK_CTRL_ID_S;
+-      id &= QCA8K_MASK_CTRL_ID_M;
+-      if (id != data->id) {
+-              dev_err(&mdiodev->dev, "Switch id detected %x but expected %x", id, data->id);
+-              return -ENODEV;
+-      }
+-
+-      priv->switch_id = id;
+       priv->ds = devm_kzalloc(&mdiodev->dev, sizeof(*priv->ds), GFP_KERNEL);
+       if (!priv->ds)
+               return -ENOMEM;
+--- a/drivers/net/dsa/qca8k.h
++++ b/drivers/net/dsa/qca8k.h
+@@ -30,8 +30,10 @@
+ /* Global control registers */
+ #define QCA8K_REG_MASK_CTRL                           0x000
+-#define   QCA8K_MASK_CTRL_ID_M                                0xff
+-#define   QCA8K_MASK_CTRL_ID_S                                8
++#define   QCA8K_MASK_CTRL_REV_ID_MASK                 GENMASK(7, 0)
++#define   QCA8K_MASK_CTRL_REV_ID(x)                   ((x) >> 0)
++#define   QCA8K_MASK_CTRL_DEVICE_ID_MASK              GENMASK(15, 8)
++#define   QCA8K_MASK_CTRL_DEVICE_ID(x)                        ((x) >> 8)
+ #define QCA8K_REG_PORT0_PAD_CTRL                      0x004
+ #define QCA8K_REG_PORT5_PAD_CTRL                      0x008
+ #define QCA8K_REG_PORT6_PAD_CTRL                      0x00c
+@@ -251,6 +253,7 @@ struct qca8k_match_data {
+ struct qca8k_priv {
+       u8 switch_id;
++      u8 switch_revision;
+       struct regmap *regmap;
+       struct mii_bus *bus;
+       struct ar8xxx_port_status port_sts[QCA8K_NUM_PORTS];