blob: 9db5b40d78ea047716876465a26920e321ab2ff6 [file] [log] [blame]
Lennert Buytenhek91da11f2008-10-07 13:44:02 +00001/*
2 * net/dsa/mv88e6xxx.c - Marvell 88e6xxx switch chip support
3 * Copyright (c) 2008 Marvell Semiconductor
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 */
10
Barry Grussling19b2f972013-01-08 16:05:54 +000011#include <linux/delay.h>
Guenter Roeckdefb05b2015-03-26 18:36:38 -070012#include <linux/etherdevice.h>
Guenter Roeckfacd95b2015-03-26 18:36:35 -070013#include <linux/if_bridge.h>
Barry Grussling19b2f972013-01-08 16:05:54 +000014#include <linux/jiffies.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000015#include <linux/list.h>
Paul Gortmaker2bbba272012-01-24 10:41:40 +000016#include <linux/module.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000017#include <linux/netdevice.h>
18#include <linux/phy.h>
Ben Hutchingsc8f0b862011-11-27 17:06:08 +000019#include <net/dsa.h>
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000020#include "mv88e6xxx.h"
21
Barry Grussling3675c8d2013-01-08 16:05:53 +000022/* If the switch's ADDR[4:0] strap pins are strapped to zero, it will
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000023 * use all 32 SMI bus addresses on its SMI bus, and all switch registers
24 * will be directly accessible on some {device address,register address}
25 * pair. If the ADDR[4:0] pins are not strapped to zero, the switch
26 * will only respond to SMI transactions to that specific address, and
27 * an indirect addressing mechanism needs to be used to access its
28 * registers.
29 */
30static int mv88e6xxx_reg_wait_ready(struct mii_bus *bus, int sw_addr)
31{
32 int ret;
33 int i;
34
35 for (i = 0; i < 16; i++) {
36 ret = mdiobus_read(bus, sw_addr, 0);
37 if (ret < 0)
38 return ret;
39
40 if ((ret & 0x8000) == 0)
41 return 0;
42 }
43
44 return -ETIMEDOUT;
45}
46
47int __mv88e6xxx_reg_read(struct mii_bus *bus, int sw_addr, int addr, int reg)
48{
49 int ret;
50
51 if (sw_addr == 0)
52 return mdiobus_read(bus, addr, reg);
53
Barry Grussling3675c8d2013-01-08 16:05:53 +000054 /* Wait for the bus to become free. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000055 ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
56 if (ret < 0)
57 return ret;
58
Barry Grussling3675c8d2013-01-08 16:05:53 +000059 /* Transmit the read command. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000060 ret = mdiobus_write(bus, sw_addr, 0, 0x9800 | (addr << 5) | reg);
61 if (ret < 0)
62 return ret;
63
Barry Grussling3675c8d2013-01-08 16:05:53 +000064 /* Wait for the read command to complete. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000065 ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
66 if (ret < 0)
67 return ret;
68
Barry Grussling3675c8d2013-01-08 16:05:53 +000069 /* Read the data. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000070 ret = mdiobus_read(bus, sw_addr, 1);
71 if (ret < 0)
72 return ret;
73
74 return ret & 0xffff;
75}
76
Guenter Roeck8d6d09e2015-03-26 18:36:31 -070077/* Must be called with SMI mutex held */
78static int _mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000079{
Guenter Roeckb184e492014-10-17 12:30:58 -070080 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000081 int ret;
82
Guenter Roeckb184e492014-10-17 12:30:58 -070083 if (bus == NULL)
84 return -EINVAL;
85
Guenter Roeckb184e492014-10-17 12:30:58 -070086 ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
Vivien Didelotbb92ea52015-01-23 16:10:36 -050087 if (ret < 0)
88 return ret;
89
90 dev_dbg(ds->master_dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
91 addr, reg, ret);
92
Lennert Buytenhek91da11f2008-10-07 13:44:02 +000093 return ret;
94}
95
Guenter Roeck8d6d09e2015-03-26 18:36:31 -070096int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
97{
98 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
99 int ret;
100
101 mutex_lock(&ps->smi_mutex);
102 ret = _mv88e6xxx_reg_read(ds, addr, reg);
103 mutex_unlock(&ps->smi_mutex);
104
105 return ret;
106}
107
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000108int __mv88e6xxx_reg_write(struct mii_bus *bus, int sw_addr, int addr,
109 int reg, u16 val)
110{
111 int ret;
112
113 if (sw_addr == 0)
114 return mdiobus_write(bus, addr, reg, val);
115
Barry Grussling3675c8d2013-01-08 16:05:53 +0000116 /* Wait for the bus to become free. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000117 ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
118 if (ret < 0)
119 return ret;
120
Barry Grussling3675c8d2013-01-08 16:05:53 +0000121 /* Transmit the data to write. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000122 ret = mdiobus_write(bus, sw_addr, 1, val);
123 if (ret < 0)
124 return ret;
125
Barry Grussling3675c8d2013-01-08 16:05:53 +0000126 /* Transmit the write command. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000127 ret = mdiobus_write(bus, sw_addr, 0, 0x9400 | (addr << 5) | reg);
128 if (ret < 0)
129 return ret;
130
Barry Grussling3675c8d2013-01-08 16:05:53 +0000131 /* Wait for the write command to complete. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000132 ret = mv88e6xxx_reg_wait_ready(bus, sw_addr);
133 if (ret < 0)
134 return ret;
135
136 return 0;
137}
138
Guenter Roeck8d6d09e2015-03-26 18:36:31 -0700139/* Must be called with SMI mutex held */
140static int _mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg,
141 u16 val)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000142{
Guenter Roeckb184e492014-10-17 12:30:58 -0700143 struct mii_bus *bus = dsa_host_dev_to_mii_bus(ds->master_dev);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000144
Guenter Roeckb184e492014-10-17 12:30:58 -0700145 if (bus == NULL)
146 return -EINVAL;
147
Vivien Didelotbb92ea52015-01-23 16:10:36 -0500148 dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
149 addr, reg, val);
150
Guenter Roeck8d6d09e2015-03-26 18:36:31 -0700151 return __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
152}
153
154int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
155{
156 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
157 int ret;
158
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000159 mutex_lock(&ps->smi_mutex);
Guenter Roeck8d6d09e2015-03-26 18:36:31 -0700160 ret = _mv88e6xxx_reg_write(ds, addr, reg, val);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000161 mutex_unlock(&ps->smi_mutex);
162
163 return ret;
164}
165
166int mv88e6xxx_config_prio(struct dsa_switch *ds)
167{
Barry Grussling3675c8d2013-01-08 16:05:53 +0000168 /* Configure the IP ToS mapping registers. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000169 REG_WRITE(REG_GLOBAL, 0x10, 0x0000);
170 REG_WRITE(REG_GLOBAL, 0x11, 0x0000);
171 REG_WRITE(REG_GLOBAL, 0x12, 0x5555);
172 REG_WRITE(REG_GLOBAL, 0x13, 0x5555);
173 REG_WRITE(REG_GLOBAL, 0x14, 0xaaaa);
174 REG_WRITE(REG_GLOBAL, 0x15, 0xaaaa);
175 REG_WRITE(REG_GLOBAL, 0x16, 0xffff);
176 REG_WRITE(REG_GLOBAL, 0x17, 0xffff);
177
Barry Grussling3675c8d2013-01-08 16:05:53 +0000178 /* Configure the IEEE 802.1p priority mapping register. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000179 REG_WRITE(REG_GLOBAL, 0x18, 0xfa41);
180
181 return 0;
182}
183
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000184int mv88e6xxx_set_addr_direct(struct dsa_switch *ds, u8 *addr)
185{
186 REG_WRITE(REG_GLOBAL, 0x01, (addr[0] << 8) | addr[1]);
187 REG_WRITE(REG_GLOBAL, 0x02, (addr[2] << 8) | addr[3]);
188 REG_WRITE(REG_GLOBAL, 0x03, (addr[4] << 8) | addr[5]);
189
190 return 0;
191}
192
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000193int mv88e6xxx_set_addr_indirect(struct dsa_switch *ds, u8 *addr)
194{
195 int i;
196 int ret;
197
198 for (i = 0; i < 6; i++) {
199 int j;
200
Barry Grussling3675c8d2013-01-08 16:05:53 +0000201 /* Write the MAC address byte. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000202 REG_WRITE(REG_GLOBAL2, 0x0d, 0x8000 | (i << 8) | addr[i]);
203
Barry Grussling3675c8d2013-01-08 16:05:53 +0000204 /* Wait for the write to complete. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000205 for (j = 0; j < 16; j++) {
206 ret = REG_READ(REG_GLOBAL2, 0x0d);
207 if ((ret & 0x8000) == 0)
208 break;
209 }
210 if (j == 16)
211 return -ETIMEDOUT;
212 }
213
214 return 0;
215}
216
217int mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
218{
219 if (addr >= 0)
220 return mv88e6xxx_reg_read(ds, addr, regnum);
221 return 0xffff;
222}
223
224int mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum, u16 val)
225{
226 if (addr >= 0)
227 return mv88e6xxx_reg_write(ds, addr, regnum, val);
228 return 0;
229}
230
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000231#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
232static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
233{
234 int ret;
Barry Grussling19b2f972013-01-08 16:05:54 +0000235 unsigned long timeout;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000236
237 ret = REG_READ(REG_GLOBAL, 0x04);
238 REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
239
Barry Grussling19b2f972013-01-08 16:05:54 +0000240 timeout = jiffies + 1 * HZ;
241 while (time_before(jiffies, timeout)) {
Barry Grussling85686582013-01-08 16:05:56 +0000242 ret = REG_READ(REG_GLOBAL, 0x00);
Barry Grussling19b2f972013-01-08 16:05:54 +0000243 usleep_range(1000, 2000);
Barry Grussling85686582013-01-08 16:05:56 +0000244 if ((ret & 0xc000) != 0xc000)
245 return 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000246 }
247
248 return -ETIMEDOUT;
249}
250
251static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
252{
253 int ret;
Barry Grussling19b2f972013-01-08 16:05:54 +0000254 unsigned long timeout;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000255
256 ret = REG_READ(REG_GLOBAL, 0x04);
257 REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
258
Barry Grussling19b2f972013-01-08 16:05:54 +0000259 timeout = jiffies + 1 * HZ;
260 while (time_before(jiffies, timeout)) {
Barry Grussling85686582013-01-08 16:05:56 +0000261 ret = REG_READ(REG_GLOBAL, 0x00);
Barry Grussling19b2f972013-01-08 16:05:54 +0000262 usleep_range(1000, 2000);
Barry Grussling85686582013-01-08 16:05:56 +0000263 if ((ret & 0xc000) == 0xc000)
264 return 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000265 }
266
267 return -ETIMEDOUT;
268}
269
270static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
271{
272 struct mv88e6xxx_priv_state *ps;
273
274 ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
275 if (mutex_trylock(&ps->ppu_mutex)) {
Barry Grussling85686582013-01-08 16:05:56 +0000276 struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000277
Barry Grussling85686582013-01-08 16:05:56 +0000278 if (mv88e6xxx_ppu_enable(ds) == 0)
279 ps->ppu_disabled = 0;
280 mutex_unlock(&ps->ppu_mutex);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000281 }
282}
283
284static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
285{
286 struct mv88e6xxx_priv_state *ps = (void *)_ps;
287
288 schedule_work(&ps->ppu_work);
289}
290
291static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
292{
Florian Fainellia22adce2014-04-28 11:14:28 -0700293 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000294 int ret;
295
296 mutex_lock(&ps->ppu_mutex);
297
Barry Grussling3675c8d2013-01-08 16:05:53 +0000298 /* If the PHY polling unit is enabled, disable it so that
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000299 * we can access the PHY registers. If it was already
300 * disabled, cancel the timer that is going to re-enable
301 * it.
302 */
303 if (!ps->ppu_disabled) {
Barry Grussling85686582013-01-08 16:05:56 +0000304 ret = mv88e6xxx_ppu_disable(ds);
305 if (ret < 0) {
306 mutex_unlock(&ps->ppu_mutex);
307 return ret;
308 }
309 ps->ppu_disabled = 1;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000310 } else {
Barry Grussling85686582013-01-08 16:05:56 +0000311 del_timer(&ps->ppu_timer);
312 ret = 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000313 }
314
315 return ret;
316}
317
318static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
319{
Florian Fainellia22adce2014-04-28 11:14:28 -0700320 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000321
Barry Grussling3675c8d2013-01-08 16:05:53 +0000322 /* Schedule a timer to re-enable the PHY polling unit. */
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000323 mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
324 mutex_unlock(&ps->ppu_mutex);
325}
326
327void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
328{
Florian Fainellia22adce2014-04-28 11:14:28 -0700329 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000330
331 mutex_init(&ps->ppu_mutex);
332 INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
333 init_timer(&ps->ppu_timer);
334 ps->ppu_timer.data = (unsigned long)ps;
335 ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
336}
337
338int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
339{
340 int ret;
341
342 ret = mv88e6xxx_ppu_access_get(ds);
343 if (ret >= 0) {
Barry Grussling85686582013-01-08 16:05:56 +0000344 ret = mv88e6xxx_reg_read(ds, addr, regnum);
345 mv88e6xxx_ppu_access_put(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000346 }
347
348 return ret;
349}
350
351int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
352 int regnum, u16 val)
353{
354 int ret;
355
356 ret = mv88e6xxx_ppu_access_get(ds);
357 if (ret >= 0) {
Barry Grussling85686582013-01-08 16:05:56 +0000358 ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
359 mv88e6xxx_ppu_access_put(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000360 }
361
362 return ret;
363}
364#endif
365
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000366void mv88e6xxx_poll_link(struct dsa_switch *ds)
367{
368 int i;
369
370 for (i = 0; i < DSA_MAX_PORTS; i++) {
371 struct net_device *dev;
Ingo Molnar2a9e7972008-11-25 16:50:49 -0800372 int uninitialized_var(port_status);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000373 int link;
374 int speed;
375 int duplex;
376 int fc;
377
378 dev = ds->ports[i];
379 if (dev == NULL)
380 continue;
381
382 link = 0;
383 if (dev->flags & IFF_UP) {
384 port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
385 if (port_status < 0)
386 continue;
387
388 link = !!(port_status & 0x0800);
389 }
390
391 if (!link) {
392 if (netif_carrier_ok(dev)) {
Barry Grusslingab381a92013-01-08 16:05:55 +0000393 netdev_info(dev, "link down\n");
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000394 netif_carrier_off(dev);
395 }
396 continue;
397 }
398
399 switch (port_status & 0x0300) {
400 case 0x0000:
401 speed = 10;
402 break;
403 case 0x0100:
404 speed = 100;
405 break;
406 case 0x0200:
407 speed = 1000;
408 break;
409 default:
410 speed = -1;
411 break;
412 }
413 duplex = (port_status & 0x0400) ? 1 : 0;
414 fc = (port_status & 0x8000) ? 1 : 0;
415
416 if (!netif_carrier_ok(dev)) {
Barry Grusslingab381a92013-01-08 16:05:55 +0000417 netdev_info(dev,
418 "link up, %d Mb/s, %s duplex, flow control %sabled\n",
419 speed,
420 duplex ? "full" : "half",
421 fc ? "en" : "dis");
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000422 netif_carrier_on(dev);
423 }
424 }
425}
426
427static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
428{
429 int ret;
430 int i;
431
432 for (i = 0; i < 10; i++) {
Stephane Contri1ded3f52009-07-02 23:26:48 +0000433 ret = REG_READ(REG_GLOBAL, 0x1d);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000434 if ((ret & 0x8000) == 0)
435 return 0;
436 }
437
438 return -ETIMEDOUT;
439}
440
441static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
442{
443 int ret;
444
Barry Grussling3675c8d2013-01-08 16:05:53 +0000445 /* Snapshot the hardware statistics counters for this port. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000446 REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
447
Barry Grussling3675c8d2013-01-08 16:05:53 +0000448 /* Wait for the snapshotting to complete. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000449 ret = mv88e6xxx_stats_wait(ds);
450 if (ret < 0)
451 return ret;
452
453 return 0;
454}
455
456static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
457{
458 u32 _val;
459 int ret;
460
461 *val = 0;
462
463 ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
464 if (ret < 0)
465 return;
466
467 ret = mv88e6xxx_stats_wait(ds);
468 if (ret < 0)
469 return;
470
471 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
472 if (ret < 0)
473 return;
474
475 _val = ret << 16;
476
477 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
478 if (ret < 0)
479 return;
480
481 *val = _val | ret;
482}
483
484void mv88e6xxx_get_strings(struct dsa_switch *ds,
485 int nr_stats, struct mv88e6xxx_hw_stat *stats,
486 int port, uint8_t *data)
487{
488 int i;
489
490 for (i = 0; i < nr_stats; i++) {
491 memcpy(data + i * ETH_GSTRING_LEN,
492 stats[i].string, ETH_GSTRING_LEN);
493 }
494}
495
496void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
497 int nr_stats, struct mv88e6xxx_hw_stat *stats,
498 int port, uint64_t *data)
499{
Florian Fainellia22adce2014-04-28 11:14:28 -0700500 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000501 int ret;
502 int i;
503
504 mutex_lock(&ps->stats_mutex);
505
506 ret = mv88e6xxx_stats_snapshot(ds, port);
507 if (ret < 0) {
508 mutex_unlock(&ps->stats_mutex);
509 return;
510 }
511
Barry Grussling3675c8d2013-01-08 16:05:53 +0000512 /* Read each of the counters. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000513 for (i = 0; i < nr_stats; i++) {
514 struct mv88e6xxx_hw_stat *s = stats + i;
515 u32 low;
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700516 u32 high = 0;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000517
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700518 if (s->reg >= 0x100) {
519 int ret;
520
521 ret = mv88e6xxx_reg_read(ds, REG_PORT(port),
522 s->reg - 0x100);
523 if (ret < 0)
524 goto error;
525 low = ret;
526 if (s->sizeof_stat == 4) {
527 ret = mv88e6xxx_reg_read(ds, REG_PORT(port),
528 s->reg - 0x100 + 1);
529 if (ret < 0)
530 goto error;
531 high = ret;
532 }
533 data[i] = (((u64)high) << 16) | low;
534 continue;
535 }
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000536 mv88e6xxx_stats_read(ds, s->reg, &low);
537 if (s->sizeof_stat == 8)
538 mv88e6xxx_stats_read(ds, s->reg + 1, &high);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000539
540 data[i] = (((u64)high) << 32) | low;
541 }
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700542error:
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000543 mutex_unlock(&ps->stats_mutex);
544}
Ben Hutchings98e67302011-11-25 14:36:19 +0000545
Guenter Roecka1ab91f2014-10-29 10:45:05 -0700546int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
547{
548 return 32 * sizeof(u16);
549}
550
551void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
552 struct ethtool_regs *regs, void *_p)
553{
554 u16 *p = _p;
555 int i;
556
557 regs->version = 0;
558
559 memset(p, 0xff, 32 * sizeof(u16));
560
561 for (i = 0; i < 32; i++) {
562 int ret;
563
564 ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i);
565 if (ret >= 0)
566 p[i] = ret;
567 }
568}
569
Andrew Lunneaa23762014-11-15 22:24:51 +0100570#ifdef CONFIG_NET_DSA_HWMON
571
572int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
573{
574 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
575 int ret;
576 int val;
577
578 *temp = 0;
579
580 mutex_lock(&ps->phy_mutex);
581
582 ret = mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6);
583 if (ret < 0)
584 goto error;
585
586 /* Enable temperature sensor */
587 ret = mv88e6xxx_phy_read(ds, 0x0, 0x1a);
588 if (ret < 0)
589 goto error;
590
591 ret = mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5));
592 if (ret < 0)
593 goto error;
594
595 /* Wait for temperature to stabilize */
596 usleep_range(10000, 12000);
597
598 val = mv88e6xxx_phy_read(ds, 0x0, 0x1a);
599 if (val < 0) {
600 ret = val;
601 goto error;
602 }
603
604 /* Disable temperature sensor */
605 ret = mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5));
606 if (ret < 0)
607 goto error;
608
609 *temp = ((val & 0x1f) - 5) * 5;
610
611error:
612 mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0);
613 mutex_unlock(&ps->phy_mutex);
614 return ret;
615}
616#endif /* CONFIG_NET_DSA_HWMON */
617
Andrew Lunnf3044682015-02-14 19:17:50 +0100618static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
619{
620 unsigned long timeout = jiffies + HZ / 10;
621
622 while (time_before(jiffies, timeout)) {
623 int ret;
624
625 ret = REG_READ(reg, offset);
626 if (!(ret & mask))
627 return 0;
628
629 usleep_range(1000, 2000);
630 }
631 return -ETIMEDOUT;
632}
633
634int mv88e6xxx_phy_wait(struct dsa_switch *ds)
635{
636 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x18, 0x8000);
637}
638
639int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
640{
641 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x0800);
642}
643
644int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
645{
646 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
647}
648
Guenter Roeckfacd95b2015-03-26 18:36:35 -0700649/* Must be called with SMI lock held */
650static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
651{
652 unsigned long timeout = jiffies + HZ / 10;
653
654 while (time_before(jiffies, timeout)) {
655 int ret;
656
657 ret = _mv88e6xxx_reg_read(ds, reg, offset);
658 if (ret < 0)
659 return ret;
660 if (!(ret & mask))
661 return 0;
662
663 usleep_range(1000, 2000);
664 }
665 return -ETIMEDOUT;
666}
667
668/* Must be called with SMI lock held */
669static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
670{
671 return _mv88e6xxx_wait(ds, REG_GLOBAL, 0x0b, ATU_BUSY);
672}
673
Andrew Lunnf3044682015-02-14 19:17:50 +0100674int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum)
675{
676 int ret;
677
678 REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum);
679
680 ret = mv88e6xxx_phy_wait(ds);
681 if (ret < 0)
682 return ret;
683
684 return REG_READ(REG_GLOBAL2, 0x19);
685}
686
687int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
688 u16 val)
689{
690 REG_WRITE(REG_GLOBAL2, 0x19, val);
691 REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum);
692
693 return mv88e6xxx_phy_wait(ds);
694}
695
Guenter Roeck11b3b452015-03-06 22:23:51 -0800696int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
697{
698 int reg;
699
700 reg = mv88e6xxx_phy_read_indirect(ds, port, 16);
701 if (reg < 0)
702 return -EOPNOTSUPP;
703
704 e->eee_enabled = !!(reg & 0x0200);
705 e->tx_lpi_enabled = !!(reg & 0x0100);
706
707 reg = REG_READ(REG_PORT(port), 0);
708 e->eee_active = !!(reg & 0x0040);
709
710 return 0;
711}
712
713static int mv88e6xxx_eee_enable_set(struct dsa_switch *ds, int port,
714 bool eee_enabled, bool tx_lpi_enabled)
715{
716 int reg, nreg;
717
718 reg = mv88e6xxx_phy_read_indirect(ds, port, 16);
719 if (reg < 0)
720 return reg;
721
722 nreg = reg & ~0x0300;
723 if (eee_enabled)
724 nreg |= 0x0200;
725 if (tx_lpi_enabled)
726 nreg |= 0x0100;
727
728 if (nreg != reg)
729 return mv88e6xxx_phy_write_indirect(ds, port, 16, nreg);
730
731 return 0;
732}
733
734int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
735 struct phy_device *phydev, struct ethtool_eee *e)
736{
737 int ret;
738
739 ret = mv88e6xxx_eee_enable_set(ds, port, e->eee_enabled,
740 e->tx_lpi_enabled);
741 if (ret)
742 return -EOPNOTSUPP;
743
744 return 0;
745}
746
Guenter Roeckfacd95b2015-03-26 18:36:35 -0700747static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
748{
749 int ret;
750
751 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid);
752 if (ret < 0)
753 return ret;
754
755 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0b, cmd);
756 if (ret < 0)
757 return ret;
758
759 return _mv88e6xxx_atu_wait(ds);
760}
761
762static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
763{
764 int ret;
765
766 ret = _mv88e6xxx_atu_wait(ds);
767 if (ret < 0)
768 return ret;
769
770 return _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_FLUSH_NONSTATIC_FID);
771}
772
773static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
774{
775 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
776 int reg, ret;
777 u8 oldstate;
778
779 mutex_lock(&ps->smi_mutex);
780
781 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), 0x04);
782 if (reg < 0)
783 goto abort;
784
785 oldstate = reg & PSTATE_MASK;
786 if (oldstate != state) {
787 /* Flush forwarding database if we're moving a port
788 * from Learning or Forwarding state to Disabled or
789 * Blocking or Listening state.
790 */
791 if (oldstate >= PSTATE_LEARNING && state <= PSTATE_BLOCKING) {
792 ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]);
793 if (ret)
794 goto abort;
795 }
796 reg = (reg & ~PSTATE_MASK) | state;
797 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x04, reg);
798 }
799
800abort:
801 mutex_unlock(&ps->smi_mutex);
802 return ret;
803}
804
805/* Must be called with smi lock held */
806static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
807{
808 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
809 u8 fid = ps->fid[port];
810 u16 reg = fid << 12;
811
812 if (dsa_is_cpu_port(ds, port))
813 reg |= ds->phys_port_mask;
814 else
815 reg |= (ps->bridge_mask[fid] |
816 (1 << dsa_upstream_port(ds))) & ~(1 << port);
817
818 return _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
819}
820
821/* Must be called with smi lock held */
822static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
823{
824 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
825 int port;
826 u32 mask;
827 int ret;
828
829 mask = ds->phys_port_mask;
830 while (mask) {
831 port = __ffs(mask);
832 mask &= ~(1 << port);
833 if (ps->fid[port] != fid)
834 continue;
835
836 ret = _mv88e6xxx_update_port_config(ds, port);
837 if (ret)
838 return ret;
839 }
840
841 return _mv88e6xxx_flush_fid(ds, fid);
842}
843
844/* Bridge handling functions */
845
846int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
847{
848 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
849 int ret = 0;
850 u32 nmask;
851 int fid;
852
853 /* If the bridge group is not empty, join that group.
854 * Otherwise create a new group.
855 */
856 fid = ps->fid[port];
857 nmask = br_port_mask & ~(1 << port);
858 if (nmask)
859 fid = ps->fid[__ffs(nmask)];
860
861 nmask = ps->bridge_mask[fid] | (1 << port);
862 if (nmask != br_port_mask) {
863 netdev_err(ds->ports[port],
864 "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
865 fid, br_port_mask, nmask);
866 return -EINVAL;
867 }
868
869 mutex_lock(&ps->smi_mutex);
870
871 ps->bridge_mask[fid] = br_port_mask;
872
873 if (fid != ps->fid[port]) {
874 ps->fid_mask |= 1 << ps->fid[port];
875 ps->fid[port] = fid;
876 ret = _mv88e6xxx_update_bridge_config(ds, fid);
877 }
878
879 mutex_unlock(&ps->smi_mutex);
880
881 return ret;
882}
883
884int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
885{
886 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
887 u8 fid, newfid;
888 int ret;
889
890 fid = ps->fid[port];
891
892 if (ps->bridge_mask[fid] != br_port_mask) {
893 netdev_err(ds->ports[port],
894 "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
895 fid, br_port_mask, ps->bridge_mask[fid]);
896 return -EINVAL;
897 }
898
899 /* If the port was the last port of a bridge, we are done.
900 * Otherwise assign a new fid to the port, and fix up
901 * the bridge configuration.
902 */
903 if (br_port_mask == (1 << port))
904 return 0;
905
906 mutex_lock(&ps->smi_mutex);
907
908 newfid = __ffs(ps->fid_mask);
909 ps->fid[port] = newfid;
910 ps->fid_mask &= (1 << newfid);
911 ps->bridge_mask[fid] &= ~(1 << port);
912 ps->bridge_mask[newfid] = 1 << port;
913
914 ret = _mv88e6xxx_update_bridge_config(ds, fid);
915 if (!ret)
916 ret = _mv88e6xxx_update_bridge_config(ds, newfid);
917
918 mutex_unlock(&ps->smi_mutex);
919
920 return ret;
921}
922
923int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
924{
925 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
926 int stp_state;
927
928 switch (state) {
929 case BR_STATE_DISABLED:
930 stp_state = PSTATE_DISABLED;
931 break;
932 case BR_STATE_BLOCKING:
933 case BR_STATE_LISTENING:
934 stp_state = PSTATE_BLOCKING;
935 break;
936 case BR_STATE_LEARNING:
937 stp_state = PSTATE_LEARNING;
938 break;
939 case BR_STATE_FORWARDING:
940 default:
941 stp_state = PSTATE_FORWARDING;
942 break;
943 }
944
945 netdev_dbg(ds->ports[port], "port state %d [%d]\n", state, stp_state);
946
947 /* mv88e6xxx_port_stp_update may be called with softirqs disabled,
948 * so we can not update the port state directly but need to schedule it.
949 */
950 ps->port_state[port] = stp_state;
951 set_bit(port, &ps->port_state_update_mask);
952 schedule_work(&ps->bridge_work);
953
954 return 0;
955}
956
Guenter Roeckdefb05b2015-03-26 18:36:38 -0700957static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
958 const unsigned char *addr)
959{
960 int i, ret;
961
962 for (i = 0; i < 3; i++) {
963 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0d + i,
964 (addr[i * 2] << 8) | addr[i * 2 + 1]);
965 if (ret < 0)
966 return ret;
967 }
968
969 return 0;
970}
971
972static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
973{
974 int i, ret;
975
976 for (i = 0; i < 3; i++) {
977 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0d + i);
978 if (ret < 0)
979 return ret;
980 addr[i * 2] = ret >> 8;
981 addr[i * 2 + 1] = ret & 0xff;
982 }
983
984 return 0;
985}
986
987static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
988 const unsigned char *addr, int state)
989{
990 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
991 u8 fid = ps->fid[port];
992 int ret;
993
994 ret = _mv88e6xxx_atu_wait(ds);
995 if (ret < 0)
996 return ret;
997
998 ret = __mv88e6xxx_write_addr(ds, addr);
999 if (ret < 0)
1000 return ret;
1001
1002 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0c,
1003 (0x10 << port) | state);
1004 if (ret)
1005 return ret;
1006
1007 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_LOAD_FID);
1008
1009 return ret;
1010}
1011
1012int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
1013 const unsigned char *addr, u16 vid)
1014{
1015 int state = is_multicast_ether_addr(addr) ?
1016 FDB_STATE_MC_STATIC : FDB_STATE_STATIC;
1017 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1018 int ret;
1019
1020 mutex_lock(&ps->smi_mutex);
1021 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
1022 mutex_unlock(&ps->smi_mutex);
1023
1024 return ret;
1025}
1026
1027int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1028 const unsigned char *addr, u16 vid)
1029{
1030 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1031 int ret;
1032
1033 mutex_lock(&ps->smi_mutex);
1034 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, FDB_STATE_UNUSED);
1035 mutex_unlock(&ps->smi_mutex);
1036
1037 return ret;
1038}
1039
1040static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
1041 unsigned char *addr, bool *is_static)
1042{
1043 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1044 u8 fid = ps->fid[port];
1045 int ret, state;
1046
1047 ret = _mv88e6xxx_atu_wait(ds);
1048 if (ret < 0)
1049 return ret;
1050
1051 ret = __mv88e6xxx_write_addr(ds, addr);
1052 if (ret < 0)
1053 return ret;
1054
1055 do {
1056 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_GETNEXT_FID);
1057 if (ret < 0)
1058 return ret;
1059
1060 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0c);
1061 if (ret < 0)
1062 return ret;
1063 state = ret & FDB_STATE_MASK;
1064 if (state == FDB_STATE_UNUSED)
1065 return -ENOENT;
1066 } while (!(((ret >> 4) & 0xff) & (1 << port)));
1067
1068 ret = __mv88e6xxx_read_addr(ds, addr);
1069 if (ret < 0)
1070 return ret;
1071
1072 *is_static = state == (is_multicast_ether_addr(addr) ?
1073 FDB_STATE_MC_STATIC : FDB_STATE_STATIC);
1074
1075 return 0;
1076}
1077
1078/* get next entry for port */
1079int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
1080 unsigned char *addr, bool *is_static)
1081{
1082 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1083 int ret;
1084
1085 mutex_lock(&ps->smi_mutex);
1086 ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);
1087 mutex_unlock(&ps->smi_mutex);
1088
1089 return ret;
1090}
1091
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001092static void mv88e6xxx_bridge_work(struct work_struct *work)
1093{
1094 struct mv88e6xxx_priv_state *ps;
1095 struct dsa_switch *ds;
1096 int port;
1097
1098 ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
1099 ds = ((struct dsa_switch *)ps) - 1;
1100
1101 while (ps->port_state_update_mask) {
1102 port = __ffs(ps->port_state_update_mask);
1103 clear_bit(port, &ps->port_state_update_mask);
1104 mv88e6xxx_set_port_state(ds, port, ps->port_state[port]);
1105 }
1106}
1107
Guenter Roeckd827e882015-03-26 18:36:29 -07001108int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
1109{
1110 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001111 int ret, fid;
Guenter Roeckd827e882015-03-26 18:36:29 -07001112
1113 mutex_lock(&ps->smi_mutex);
1114
Guenter Roeck366f0a02015-03-26 18:36:30 -07001115 /* Port Control 1: disable trunking, disable sending
1116 * learning messages to this port.
Guenter Roeckd827e882015-03-26 18:36:29 -07001117 */
Guenter Roeck366f0a02015-03-26 18:36:30 -07001118 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05, 0x0000);
Guenter Roeckd827e882015-03-26 18:36:29 -07001119 if (ret)
1120 goto abort;
1121
1122 /* Port based VLAN map: give each port its own address
1123 * database, allow the CPU port to talk to each of the 'real'
1124 * ports, and allow each of the 'real' ports to only talk to
1125 * the upstream port.
1126 */
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001127 fid = __ffs(ps->fid_mask);
1128 ps->fid[port] = fid;
1129 ps->fid_mask &= ~(1 << fid);
Guenter Roeckd827e882015-03-26 18:36:29 -07001130
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001131 if (!dsa_is_cpu_port(ds, port))
1132 ps->bridge_mask[fid] = 1 << port;
1133
1134 ret = _mv88e6xxx_update_port_config(ds, port);
Guenter Roeckd827e882015-03-26 18:36:29 -07001135 if (ret)
1136 goto abort;
1137
1138 /* Default VLAN ID and priority: don't set a default VLAN
1139 * ID, and set the default packet priority to zero.
1140 */
1141 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x07, 0x0000);
1142abort:
1143 mutex_unlock(&ps->smi_mutex);
1144 return ret;
1145}
1146
Guenter Roeckacdaffc2015-03-26 18:36:28 -07001147int mv88e6xxx_setup_common(struct dsa_switch *ds)
1148{
1149 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1150
1151 mutex_init(&ps->smi_mutex);
1152 mutex_init(&ps->stats_mutex);
1153 mutex_init(&ps->phy_mutex);
1154
Andrew Lunna8f064c2015-03-26 18:36:40 -07001155 ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
1156
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001157 ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
1158
1159 INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
1160
Guenter Roeckacdaffc2015-03-26 18:36:28 -07001161 return 0;
1162}
1163
Andrew Lunn143a8302015-04-02 04:06:34 +02001164int 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
Ben Hutchings98e67302011-11-25 14:36:19 +00001204static int __init mv88e6xxx_init(void)
1205{
1206#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
1207 register_switch_driver(&mv88e6131_switch_driver);
1208#endif
1209#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
1210 register_switch_driver(&mv88e6123_61_65_switch_driver);
1211#endif
Guenter Roeck3ad50cc2014-10-29 10:44:56 -07001212#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
1213 register_switch_driver(&mv88e6352_switch_driver);
1214#endif
Andrew Lunn42f27252014-09-12 23:58:44 +02001215#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
1216 register_switch_driver(&mv88e6171_switch_driver);
1217#endif
Ben Hutchings98e67302011-11-25 14:36:19 +00001218 return 0;
1219}
1220module_init(mv88e6xxx_init);
1221
1222static void __exit mv88e6xxx_cleanup(void)
1223{
Andrew Lunn42f27252014-09-12 23:58:44 +02001224#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
1225 unregister_switch_driver(&mv88e6171_switch_driver);
1226#endif
Ben Hutchings98e67302011-11-25 14:36:19 +00001227#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
1228 unregister_switch_driver(&mv88e6123_61_65_switch_driver);
1229#endif
1230#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
1231 unregister_switch_driver(&mv88e6131_switch_driver);
1232#endif
1233}
1234module_exit(mv88e6xxx_cleanup);
Ben Hutchings3d825ed2011-11-25 14:37:16 +00001235
1236MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
1237MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
1238MODULE_LICENSE("GPL");