aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Lunn <andrew@lunn.ch>2015-04-01 22:06:34 -0400
committerDavid S. Miller <davem@davemloft.net>2015-04-01 22:55:40 -0400
commit143a83073aaea145aa050cd0ebb80454c9362608 (patch)
tree291485b615cb19d4b8f93831da0ba0e2ba53e0cb
parent44e50ddbc74a4bd6a862be9e6de22bce8c0b4150 (diff)
net: dsa: Centralize Marvell switch reset
Marvell switches are all reset in nearly the same way. The only difference is if the PPU should be enabled or not. Move this code into the shared mv88x6xxx.c. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Tested-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/dsa/mv88e6123_61_65.c36
-rw-r--r--drivers/net/dsa/mv88e6131.c36
-rw-r--r--drivers/net/dsa/mv88e6171.c48
-rw-r--r--drivers/net/dsa/mv88e6352.c38
-rw-r--r--drivers/net/dsa/mv88e6xxx.c40
-rw-r--r--drivers/net/dsa/mv88e6xxx.h1
6 files changed, 45 insertions, 154 deletions
diff --git a/drivers/net/dsa/mv88e6123_61_65.c b/drivers/net/dsa/mv88e6123_61_65.c
index 6480f77829ef..10228ad48151 100644
--- a/drivers/net/dsa/mv88e6123_61_65.c
+++ b/drivers/net/dsa/mv88e6123_61_65.c
@@ -52,40 +52,6 @@ static char *mv88e6123_61_65_probe(struct device *host_dev, int sw_addr)
52 return NULL; 52 return NULL;
53} 53}
54 54
55static int mv88e6123_61_65_switch_reset(struct dsa_switch *ds)
56{
57 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
58 int i;
59 int ret;
60 unsigned long timeout;
61
62 /* Set all ports to the disabled state. */
63 for (i = 0; i < ps->num_ports; i++) {
64 ret = REG_READ(REG_PORT(i), 0x04);
65 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
66 }
67
68 /* Wait for transmit queues to drain. */
69 usleep_range(2000, 4000);
70
71 /* Reset the switch. */
72 REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
73
74 /* Wait up to one second for reset to complete. */
75 timeout = jiffies + 1 * HZ;
76 while (time_before(jiffies, timeout)) {
77 ret = REG_READ(REG_GLOBAL, 0x00);
78 if ((ret & 0xc800) == 0xc800)
79 break;
80
81 usleep_range(1000, 2000);
82 }
83 if (time_after(jiffies, timeout))
84 return -ETIMEDOUT;
85
86 return 0;
87}
88
89static int mv88e6123_61_65_setup_global(struct dsa_switch *ds) 55static int mv88e6123_61_65_setup_global(struct dsa_switch *ds)
90{ 56{
91 int ret; 57 int ret;
@@ -292,7 +258,7 @@ static int mv88e6123_61_65_setup(struct dsa_switch *ds)
292 return -ENODEV; 258 return -ENODEV;
293 } 259 }
294 260
295 ret = mv88e6123_61_65_switch_reset(ds); 261 ret = mv88e6xxx_switch_reset(ds, false);
296 if (ret < 0) 262 if (ret < 0)
297 return ret; 263 return ret;
298 264
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 6b818fde2216..534a8f0b1c28 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -42,40 +42,6 @@ static char *mv88e6131_probe(struct device *host_dev, int sw_addr)
42 return NULL; 42 return NULL;
43} 43}
44 44
45static int mv88e6131_switch_reset(struct dsa_switch *ds)
46{
47 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
48 int i;
49 int ret;
50 unsigned long timeout;
51
52 /* Set all ports to the disabled state. */
53 for (i = 0; i < ps->num_ports; i++) {
54 ret = REG_READ(REG_PORT(i), 0x04);
55 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
56 }
57
58 /* Wait for transmit queues to drain. */
59 usleep_range(2000, 4000);
60
61 /* Reset the switch. */
62 REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
63
64 /* Wait up to one second for reset to complete. */
65 timeout = jiffies + 1 * HZ;
66 while (time_before(jiffies, timeout)) {
67 ret = REG_READ(REG_GLOBAL, 0x00);
68 if ((ret & 0xc800) == 0xc800)
69 break;
70
71 usleep_range(1000, 2000);
72 }
73 if (time_after(jiffies, timeout))
74 return -ETIMEDOUT;
75
76 return 0;
77}
78
79static int mv88e6131_setup_global(struct dsa_switch *ds) 45static int mv88e6131_setup_global(struct dsa_switch *ds)
80{ 46{
81 int ret; 47 int ret;
@@ -281,7 +247,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
281 return -ENODEV; 247 return -ENODEV;
282 } 248 }
283 249
284 ret = mv88e6131_switch_reset(ds); 250 ret = mv88e6xxx_switch_reset(ds, false);
285 if (ret < 0) 251 if (ret < 0)
286 return ret; 252 return ret;
287 253
diff --git a/drivers/net/dsa/mv88e6171.c b/drivers/net/dsa/mv88e6171.c
index 5a295533ff20..69b35d124de5 100644
--- a/drivers/net/dsa/mv88e6171.c
+++ b/drivers/net/dsa/mv88e6171.c
@@ -36,52 +36,6 @@ static char *mv88e6171_probe(struct device *host_dev, int sw_addr)
36 return NULL; 36 return NULL;
37} 37}
38 38
39static int mv88e6171_switch_reset(struct dsa_switch *ds)
40{
41 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
42 int i;
43 int ret;
44 unsigned long timeout;
45
46 /* Set all ports to the disabled state. */
47 for (i = 0; i < ps->num_ports; i++) {
48 ret = REG_READ(REG_PORT(i), 0x04);
49 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
50 }
51
52 /* Wait for transmit queues to drain. */
53 usleep_range(2000, 4000);
54
55 /* Reset the switch. Keep PPU active. The PPU needs to be
56 * active to support indirect phy register accesses through
57 * global registers 0x18 and 0x19.
58 */
59 REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
60
61 /* Wait up to one second for reset to complete. */
62 timeout = jiffies + 1 * HZ;
63 while (time_before(jiffies, timeout)) {
64 ret = REG_READ(REG_GLOBAL, 0x00);
65 if ((ret & 0xc800) == 0xc800)
66 break;
67
68 usleep_range(1000, 2000);
69 }
70 if (time_after(jiffies, timeout))
71 return -ETIMEDOUT;
72
73 /* Enable ports not under DSA, e.g. WAN port */
74 for (i = 0; i < ps->num_ports; i++) {
75 if (dsa_is_cpu_port(ds, i) || ds->phys_port_mask & (1 << i))
76 continue;
77
78 ret = REG_READ(REG_PORT(i), 0x04);
79 REG_WRITE(REG_PORT(i), 0x04, ret | 0x03);
80 }
81
82 return 0;
83}
84
85static int mv88e6171_setup_global(struct dsa_switch *ds) 39static int mv88e6171_setup_global(struct dsa_switch *ds)
86{ 40{
87 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 41 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -282,7 +236,7 @@ static int mv88e6171_setup(struct dsa_switch *ds)
282 236
283 ps->num_ports = 7; 237 ps->num_ports = 7;
284 238
285 ret = mv88e6171_switch_reset(ds); 239 ret = mv88e6xxx_switch_reset(ds, true);
286 if (ret < 0) 240 if (ret < 0)
287 return ret; 241 return ret;
288 242
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 040027fcd013..214bdbc8a5b1 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -45,42 +45,6 @@ static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
45 return NULL; 45 return NULL;
46} 46}
47 47
48static int mv88e6352_switch_reset(struct dsa_switch *ds)
49{
50 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
51 unsigned long timeout;
52 int ret;
53 int i;
54
55 /* Set all ports to the disabled state. */
56 for (i = 0; i < ps->num_ports; i++) {
57 ret = REG_READ(REG_PORT(i), 0x04);
58 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
59 }
60
61 /* Wait for transmit queues to drain. */
62 usleep_range(2000, 4000);
63
64 /* Reset the switch. Keep PPU active (bit 14, undocumented).
65 * The PPU needs to be active to support indirect phy register
66 * accesses through global registers 0x18 and 0x19.
67 */
68 REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
69
70 /* Wait up to one second for reset to complete. */
71 timeout = jiffies + 1 * HZ;
72 while (time_before(jiffies, timeout)) {
73 ret = REG_READ(REG_GLOBAL, 0x00);
74 if ((ret & 0x8800) == 0x8800)
75 break;
76 usleep_range(1000, 2000);
77 }
78 if (time_after(jiffies, timeout))
79 return -ETIMEDOUT;
80
81 return 0;
82}
83
84static int mv88e6352_setup_global(struct dsa_switch *ds) 48static int mv88e6352_setup_global(struct dsa_switch *ds)
85{ 49{
86 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); 50 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
@@ -373,7 +337,7 @@ static int mv88e6352_setup(struct dsa_switch *ds)
373 337
374 mutex_init(&ps->eeprom_mutex); 338 mutex_init(&ps->eeprom_mutex);
375 339
376 ret = mv88e6352_switch_reset(ds); 340 ret = mv88e6xxx_switch_reset(ds, true);
377 if (ret < 0) 341 if (ret < 0)
378 return ret; 342 return ret;
379 343
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index 13572cc24c6d..9db5b40d78ea 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -1161,6 +1161,46 @@ int mv88e6xxx_setup_common(struct dsa_switch *ds)
1161 return 0; 1161 return 0;
1162} 1162}
1163 1163
1164int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
1165{
1166 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1167 u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
1168 unsigned long timeout;
1169 int ret;
1170 int i;
1171
1172 /* Set all ports to the disabled state. */
1173 for (i = 0; i < ps->num_ports; i++) {
1174 ret = REG_READ(REG_PORT(i), 0x04);
1175 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
1176 }
1177
1178 /* Wait for transmit queues to drain. */
1179 usleep_range(2000, 4000);
1180
1181 /* Reset the switch. Keep the PPU active if requested. The PPU
1182 * needs to be active to support indirect phy register access
1183 * through global registers 0x18 and 0x19.
1184 */
1185 if (ppu_active)
1186 REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
1187 else
1188 REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
1189
1190 /* Wait up to one second for reset to complete. */
1191 timeout = jiffies + 1 * HZ;
1192 while (time_before(jiffies, timeout)) {
1193 ret = REG_READ(REG_GLOBAL, 0x00);
1194 if ((ret & is_reset) == is_reset)
1195 break;
1196 usleep_range(1000, 2000);
1197 }
1198 if (time_after(jiffies, timeout))
1199 return -ETIMEDOUT;
1200
1201 return 0;
1202}
1203
1164static int __init mv88e6xxx_init(void) 1204static int __init mv88e6xxx_init(void)
1165{ 1205{
1166#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131) 1206#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h
index ef058444bdb7..f84d3d5178b9 100644
--- a/drivers/net/dsa/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx.h
@@ -129,6 +129,7 @@ struct mv88e6xxx_hw_stat {
129 int reg; 129 int reg;
130}; 130};
131 131
132int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active);
132int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port); 133int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port);
133int mv88e6xxx_setup_common(struct dsa_switch *ds); 134int mv88e6xxx_setup_common(struct dsa_switch *ds);
134int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg); 135int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg);