50a37e550066e842e0ba1853a4a32f3c86da828c
[openwrt/staging/stintel.git] /
1 From c96a1cff5d03a56f380ce761aec9d11fcf61c7f1 Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Thu, 14 Nov 2019 17:03:26 +0200
4 Subject: [PATCH] net: mscc: ocelot: separate the implementation of switch
5 reset
6
7 The Felix switch has a different reset procedure, so a function pointer
8 needs to be created and added to the ocelot_ops structure.
9
10 The reset procedure has been moved into ocelot_init.
11
12 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
13 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
14 Signed-off-by: David S. Miller <davem@davemloft.net>
15 ---
16 drivers/net/ethernet/mscc/ocelot.c | 8 +++++++
17 drivers/net/ethernet/mscc/ocelot.h | 1 +
18 drivers/net/ethernet/mscc/ocelot_board.c | 37 +++++++++++++++++++++-----------
19 3 files changed, 33 insertions(+), 13 deletions(-)
20
21 --- a/drivers/net/ethernet/mscc/ocelot.c
22 +++ b/drivers/net/ethernet/mscc/ocelot.c
23 @@ -2271,6 +2271,14 @@ int ocelot_init(struct ocelot *ocelot)
24 int i, ret;
25 u32 port;
26
27 + if (ocelot->ops->reset) {
28 + ret = ocelot->ops->reset(ocelot);
29 + if (ret) {
30 + dev_err(ocelot->dev, "Switch reset failed\n");
31 + return ret;
32 + }
33 + }
34 +
35 ocelot->lags = devm_kcalloc(ocelot->dev, ocelot->num_phys_ports,
36 sizeof(u32), GFP_KERNEL);
37 if (!ocelot->lags)
38 --- a/drivers/net/ethernet/mscc/ocelot.h
39 +++ b/drivers/net/ethernet/mscc/ocelot.h
40 @@ -446,6 +446,7 @@ struct ocelot_stat_layout {
41
42 struct ocelot_ops {
43 void (*pcs_init)(struct ocelot *ocelot, int port);
44 + int (*reset)(struct ocelot *ocelot);
45 };
46
47 struct ocelot {
48 --- a/drivers/net/ethernet/mscc/ocelot_board.c
49 +++ b/drivers/net/ethernet/mscc/ocelot_board.c
50 @@ -285,8 +285,32 @@ static void ocelot_port_pcs_init(struct
51 ocelot_port_writel(ocelot_port, 0, PCS1G_LB_CFG);
52 }
53
54 +static int ocelot_reset(struct ocelot *ocelot)
55 +{
56 + int retries = 100;
57 + u32 val;
58 +
59 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
60 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
61 +
62 + do {
63 + msleep(1);
64 + regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
65 + &val);
66 + } while (val && --retries);
67 +
68 + if (!retries)
69 + return -ETIMEDOUT;
70 +
71 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
72 + regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
73 +
74 + return 0;
75 +}
76 +
77 static const struct ocelot_ops ocelot_ops = {
78 .pcs_init = ocelot_port_pcs_init,
79 + .reset = ocelot_reset,
80 };
81
82 static int mscc_ocelot_probe(struct platform_device *pdev)
83 @@ -297,7 +321,6 @@ static int mscc_ocelot_probe(struct plat
84 struct ocelot *ocelot;
85 struct regmap *hsio;
86 unsigned int i;
87 - u32 val;
88
89 struct {
90 enum ocelot_target id;
91 @@ -377,18 +400,6 @@ static int mscc_ocelot_probe(struct plat
92 ocelot->ptp = 1;
93 }
94
95 - regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_INIT], 1);
96 - regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
97 -
98 - do {
99 - msleep(1);
100 - regmap_field_read(ocelot->regfields[SYS_RESET_CFG_MEM_INIT],
101 - &val);
102 - } while (val);
103 -
104 - regmap_field_write(ocelot->regfields[SYS_RESET_CFG_MEM_ENA], 1);
105 - regmap_field_write(ocelot->regfields[SYS_RESET_CFG_CORE_ENA], 1);
106 -
107 ocelot->num_cpu_ports = 1; /* 1 port on the switch, two groups */
108
109 ports = of_get_child_by_name(np, "ethernet-ports");