net: mscc: ocelot: utilize readx_poll_timeout() for chip reset
authorColin Foster <colin.foster@in-advantage.com>
Sat, 17 Sep 2022 17:51:26 +0000 (10:51 -0700)
committerJakub Kicinski <kuba@kernel.org>
Thu, 22 Sep 2022 01:29:34 +0000 (18:29 -0700)
Clean up the reset code by utilizing readx_poll_timeout instead of a custom
loop.

Signed-off-by: Colin Foster <colin.foster@in-advantage.com>
Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mscc/ocelot_vsc7514.c

index ae42bbba57470c9e097db5c15f7ba11930f11f13..3fb9183c1159c85fc003f85bf4a9aaf040cfefa4 100644 (file)
@@ -6,6 +6,7 @@
  */
 #include <linux/dsa/ocelot.h>
 #include <linux/interrupt.h>
+#include <linux/iopoll.h>
 #include <linux/module.h>
 #include <linux/of_net.h>
 #include <linux/netdevice.h>
@@ -25,6 +26,9 @@
 #define VSC7514_VCAP_POLICER_BASE                      128
 #define VSC7514_VCAP_POLICER_MAX                       191
 
+#define MEM_INIT_SLEEP_US                              1000
+#define MEM_INIT_TIMEOUT_US                            100000
+
 static const u32 *ocelot_regmap[TARGET_MAX] = {
        [ANA] = vsc7514_ana_regmap,
        [QS] = vsc7514_qs_regmap,
@@ -191,22 +195,32 @@ static const struct of_device_id mscc_ocelot_match[] = {
 };
 MODULE_DEVICE_TABLE(of, mscc_ocelot_match);
 
+static int ocelot_mem_init_status(struct ocelot *ocelot)
+{
+       unsigned int val;
+       int err;
+
+       err = regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
+                               &val);
+
+       return err ?: val;
+}
+
 static int ocelot_reset(struct ocelot *ocelot)
 {
-       int retries = 100;
+       int err;
        u32 val;
 
        regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
        regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
 
-       do {
-               msleep(1);
-               regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
-                                 &val);
-       } while (val && --retries);
-
-       if (!retries)
-               return -ETIMEDOUT;
+       /* MEM_INIT is a self-clearing bit. Wait for it to be cleared (should be
+        * 100us) before enabling the switch core.
+        */
+       err = readx_poll_timeout(ocelot_mem_init_status, ocelot, val, !val,
+                                MEM_INIT_SLEEP_US, MEM_INIT_TIMEOUT_US);
+       if (err)
+               return err;
 
        regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
        regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);