OSDN Git Service

net: mscc: ocelot: separate the implementation of switch reset
authorVladimir Oltean <vladimir.oltean@nxp.com>
Thu, 14 Nov 2019 15:03:26 +0000 (17:03 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Nov 2019 20:32:16 +0000 (12:32 -0800)
The Felix switch has a different reset procedure, so a function pointer
needs to be created and added to the ocelot_ops structure.

The reset procedure has been moved into ocelot_init.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mscc/ocelot.c
drivers/net/ethernet/mscc/ocelot.h
drivers/net/ethernet/mscc/ocelot_board.c

index 42da193..961f9a7 100644 (file)
@@ -2269,6 +2269,14 @@ int ocelot_init(struct ocelot *ocelot)
        int i, ret;
        u32 port;
 
+       if (ocelot->ops->reset) {
+               ret = ocelot->ops->reset(ocelot);
+               if (ret) {
+                       dev_err(ocelot->dev, "Switch reset failed\n");
+                       return ret;
+               }
+       }
+
        ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
                                    sizeof(u32), GFP_KERNEL);
        if (!ocelot->lags)
index bdc9b1d..199ca2d 100644 (file)
@@ -446,6 +446,7 @@ struct ocelot_stat_layout {
 
 struct ocelot_ops {
        void (*pcs_init)(struct ocelot *ocelot, int port);
+       int (*reset)(struct ocelot *ocelot);
 };
 
 struct ocelot {
index 32aafd9..5581b3b 100644 (file)
@@ -277,8 +277,32 @@ static void ocelot_port_pcs_init(struct ocelot *ocelot, int port)
        ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
 }
 
+static int ocelot_reset(struct ocelot *ocelot)
+{
+       int retries = 100;
+       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;
+
+       regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
+       regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
+
+       return 0;
+}
+
 static const struct ocelot_ops ocelot_ops = {
        .pcs_init               = ocelot_port_pcs_init,
+       .reset                  = ocelot_reset,
 };
 
 static int mscc_ocelot_probe(struct platform_device *pdev)
@@ -289,7 +313,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
        struct ocelot *ocelot;
        struct regmap *hsio;
        unsigned int i;
-       u32 val;
 
        struct {
                enum ocelot_target id;
@@ -369,18 +392,6 @@ static int mscc_ocelot_probe(struct platform_device *pdev)
                ocelot->ptp = 1;
        }
 
-       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);
-
-       regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
-       regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
-
        ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */
 
        ports = of_get_child_by_name(np, "ethernet-ports");