blob: 7c4c04bb0cb0ccbd91fe82608df2448ef7306388 [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
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200217/* Must be called with phy mutex held */
218static int _mv88e6xxx_phy_read(struct dsa_switch *ds, int addr, int regnum)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000219{
220 if (addr >= 0)
221 return mv88e6xxx_reg_read(ds, addr, regnum);
222 return 0xffff;
223}
224
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200225/* Must be called with phy mutex held */
226static int _mv88e6xxx_phy_write(struct dsa_switch *ds, int addr, int regnum,
227 u16 val)
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000228{
229 if (addr >= 0)
230 return mv88e6xxx_reg_write(ds, addr, regnum, val);
231 return 0;
232}
233
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000234#ifdef CONFIG_NET_DSA_MV88E6XXX_NEED_PPU
235static int mv88e6xxx_ppu_disable(struct dsa_switch *ds)
236{
237 int ret;
Barry Grussling19b2f972013-01-08 16:05:54 +0000238 unsigned long timeout;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000239
240 ret = REG_READ(REG_GLOBAL, 0x04);
241 REG_WRITE(REG_GLOBAL, 0x04, ret & ~0x4000);
242
Barry Grussling19b2f972013-01-08 16:05:54 +0000243 timeout = jiffies + 1 * HZ;
244 while (time_before(jiffies, timeout)) {
Barry Grussling85686582013-01-08 16:05:56 +0000245 ret = REG_READ(REG_GLOBAL, 0x00);
Barry Grussling19b2f972013-01-08 16:05:54 +0000246 usleep_range(1000, 2000);
Barry Grussling85686582013-01-08 16:05:56 +0000247 if ((ret & 0xc000) != 0xc000)
248 return 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000249 }
250
251 return -ETIMEDOUT;
252}
253
254static int mv88e6xxx_ppu_enable(struct dsa_switch *ds)
255{
256 int ret;
Barry Grussling19b2f972013-01-08 16:05:54 +0000257 unsigned long timeout;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000258
259 ret = REG_READ(REG_GLOBAL, 0x04);
260 REG_WRITE(REG_GLOBAL, 0x04, ret | 0x4000);
261
Barry Grussling19b2f972013-01-08 16:05:54 +0000262 timeout = jiffies + 1 * HZ;
263 while (time_before(jiffies, timeout)) {
Barry Grussling85686582013-01-08 16:05:56 +0000264 ret = REG_READ(REG_GLOBAL, 0x00);
Barry Grussling19b2f972013-01-08 16:05:54 +0000265 usleep_range(1000, 2000);
Barry Grussling85686582013-01-08 16:05:56 +0000266 if ((ret & 0xc000) == 0xc000)
267 return 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000268 }
269
270 return -ETIMEDOUT;
271}
272
273static void mv88e6xxx_ppu_reenable_work(struct work_struct *ugly)
274{
275 struct mv88e6xxx_priv_state *ps;
276
277 ps = container_of(ugly, struct mv88e6xxx_priv_state, ppu_work);
278 if (mutex_trylock(&ps->ppu_mutex)) {
Barry Grussling85686582013-01-08 16:05:56 +0000279 struct dsa_switch *ds = ((struct dsa_switch *)ps) - 1;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000280
Barry Grussling85686582013-01-08 16:05:56 +0000281 if (mv88e6xxx_ppu_enable(ds) == 0)
282 ps->ppu_disabled = 0;
283 mutex_unlock(&ps->ppu_mutex);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000284 }
285}
286
287static void mv88e6xxx_ppu_reenable_timer(unsigned long _ps)
288{
289 struct mv88e6xxx_priv_state *ps = (void *)_ps;
290
291 schedule_work(&ps->ppu_work);
292}
293
294static int mv88e6xxx_ppu_access_get(struct dsa_switch *ds)
295{
Florian Fainellia22adce2014-04-28 11:14:28 -0700296 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000297 int ret;
298
299 mutex_lock(&ps->ppu_mutex);
300
Barry Grussling3675c8d2013-01-08 16:05:53 +0000301 /* If the PHY polling unit is enabled, disable it so that
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000302 * we can access the PHY registers. If it was already
303 * disabled, cancel the timer that is going to re-enable
304 * it.
305 */
306 if (!ps->ppu_disabled) {
Barry Grussling85686582013-01-08 16:05:56 +0000307 ret = mv88e6xxx_ppu_disable(ds);
308 if (ret < 0) {
309 mutex_unlock(&ps->ppu_mutex);
310 return ret;
311 }
312 ps->ppu_disabled = 1;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000313 } else {
Barry Grussling85686582013-01-08 16:05:56 +0000314 del_timer(&ps->ppu_timer);
315 ret = 0;
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000316 }
317
318 return ret;
319}
320
321static void mv88e6xxx_ppu_access_put(struct dsa_switch *ds)
322{
Florian Fainellia22adce2014-04-28 11:14:28 -0700323 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000324
Barry Grussling3675c8d2013-01-08 16:05:53 +0000325 /* Schedule a timer to re-enable the PHY polling unit. */
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000326 mod_timer(&ps->ppu_timer, jiffies + msecs_to_jiffies(10));
327 mutex_unlock(&ps->ppu_mutex);
328}
329
330void mv88e6xxx_ppu_state_init(struct dsa_switch *ds)
331{
Florian Fainellia22adce2014-04-28 11:14:28 -0700332 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000333
334 mutex_init(&ps->ppu_mutex);
335 INIT_WORK(&ps->ppu_work, mv88e6xxx_ppu_reenable_work);
336 init_timer(&ps->ppu_timer);
337 ps->ppu_timer.data = (unsigned long)ps;
338 ps->ppu_timer.function = mv88e6xxx_ppu_reenable_timer;
339}
340
341int mv88e6xxx_phy_read_ppu(struct dsa_switch *ds, int addr, int regnum)
342{
343 int ret;
344
345 ret = mv88e6xxx_ppu_access_get(ds);
346 if (ret >= 0) {
Barry Grussling85686582013-01-08 16:05:56 +0000347 ret = mv88e6xxx_reg_read(ds, addr, regnum);
348 mv88e6xxx_ppu_access_put(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000349 }
350
351 return ret;
352}
353
354int mv88e6xxx_phy_write_ppu(struct dsa_switch *ds, int addr,
355 int regnum, u16 val)
356{
357 int ret;
358
359 ret = mv88e6xxx_ppu_access_get(ds);
360 if (ret >= 0) {
Barry Grussling85686582013-01-08 16:05:56 +0000361 ret = mv88e6xxx_reg_write(ds, addr, regnum, val);
362 mv88e6xxx_ppu_access_put(ds);
Lennert Buytenhek2e5f0322008-10-07 13:45:18 +0000363 }
364
365 return ret;
366}
367#endif
368
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000369void mv88e6xxx_poll_link(struct dsa_switch *ds)
370{
371 int i;
372
373 for (i = 0; i < DSA_MAX_PORTS; i++) {
374 struct net_device *dev;
Ingo Molnar2a9e7972008-11-25 16:50:49 -0800375 int uninitialized_var(port_status);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000376 int link;
377 int speed;
378 int duplex;
379 int fc;
380
381 dev = ds->ports[i];
382 if (dev == NULL)
383 continue;
384
385 link = 0;
386 if (dev->flags & IFF_UP) {
387 port_status = mv88e6xxx_reg_read(ds, REG_PORT(i), 0x00);
388 if (port_status < 0)
389 continue;
390
391 link = !!(port_status & 0x0800);
392 }
393
394 if (!link) {
395 if (netif_carrier_ok(dev)) {
Barry Grusslingab381a92013-01-08 16:05:55 +0000396 netdev_info(dev, "link down\n");
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000397 netif_carrier_off(dev);
398 }
399 continue;
400 }
401
402 switch (port_status & 0x0300) {
403 case 0x0000:
404 speed = 10;
405 break;
406 case 0x0100:
407 speed = 100;
408 break;
409 case 0x0200:
410 speed = 1000;
411 break;
412 default:
413 speed = -1;
414 break;
415 }
416 duplex = (port_status & 0x0400) ? 1 : 0;
417 fc = (port_status & 0x8000) ? 1 : 0;
418
419 if (!netif_carrier_ok(dev)) {
Barry Grusslingab381a92013-01-08 16:05:55 +0000420 netdev_info(dev,
421 "link up, %d Mb/s, %s duplex, flow control %sabled\n",
422 speed,
423 duplex ? "full" : "half",
424 fc ? "en" : "dis");
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000425 netif_carrier_on(dev);
426 }
427 }
428}
429
430static int mv88e6xxx_stats_wait(struct dsa_switch *ds)
431{
432 int ret;
433 int i;
434
435 for (i = 0; i < 10; i++) {
Stephane Contri1ded3f52009-07-02 23:26:48 +0000436 ret = REG_READ(REG_GLOBAL, 0x1d);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000437 if ((ret & 0x8000) == 0)
438 return 0;
439 }
440
441 return -ETIMEDOUT;
442}
443
444static int mv88e6xxx_stats_snapshot(struct dsa_switch *ds, int port)
445{
446 int ret;
447
Barry Grussling3675c8d2013-01-08 16:05:53 +0000448 /* Snapshot the hardware statistics counters for this port. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000449 REG_WRITE(REG_GLOBAL, 0x1d, 0xdc00 | port);
450
Barry Grussling3675c8d2013-01-08 16:05:53 +0000451 /* Wait for the snapshotting to complete. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000452 ret = mv88e6xxx_stats_wait(ds);
453 if (ret < 0)
454 return ret;
455
456 return 0;
457}
458
459static void mv88e6xxx_stats_read(struct dsa_switch *ds, int stat, u32 *val)
460{
461 u32 _val;
462 int ret;
463
464 *val = 0;
465
466 ret = mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x1d, 0xcc00 | stat);
467 if (ret < 0)
468 return;
469
470 ret = mv88e6xxx_stats_wait(ds);
471 if (ret < 0)
472 return;
473
474 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1e);
475 if (ret < 0)
476 return;
477
478 _val = ret << 16;
479
480 ret = mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x1f);
481 if (ret < 0)
482 return;
483
484 *val = _val | ret;
485}
486
487void mv88e6xxx_get_strings(struct dsa_switch *ds,
488 int nr_stats, struct mv88e6xxx_hw_stat *stats,
489 int port, uint8_t *data)
490{
491 int i;
492
493 for (i = 0; i < nr_stats; i++) {
494 memcpy(data + i * ETH_GSTRING_LEN,
495 stats[i].string, ETH_GSTRING_LEN);
496 }
497}
498
499void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds,
500 int nr_stats, struct mv88e6xxx_hw_stat *stats,
501 int port, uint64_t *data)
502{
Florian Fainellia22adce2014-04-28 11:14:28 -0700503 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000504 int ret;
505 int i;
506
507 mutex_lock(&ps->stats_mutex);
508
509 ret = mv88e6xxx_stats_snapshot(ds, port);
510 if (ret < 0) {
511 mutex_unlock(&ps->stats_mutex);
512 return;
513 }
514
Barry Grussling3675c8d2013-01-08 16:05:53 +0000515 /* Read each of the counters. */
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000516 for (i = 0; i < nr_stats; i++) {
517 struct mv88e6xxx_hw_stat *s = stats + i;
518 u32 low;
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700519 u32 high = 0;
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000520
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700521 if (s->reg >= 0x100) {
522 int ret;
523
524 ret = mv88e6xxx_reg_read(ds, REG_PORT(port),
525 s->reg - 0x100);
526 if (ret < 0)
527 goto error;
528 low = ret;
529 if (s->sizeof_stat == 4) {
530 ret = mv88e6xxx_reg_read(ds, REG_PORT(port),
531 s->reg - 0x100 + 1);
532 if (ret < 0)
533 goto error;
534 high = ret;
535 }
536 data[i] = (((u64)high) << 16) | low;
537 continue;
538 }
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000539 mv88e6xxx_stats_read(ds, s->reg, &low);
540 if (s->sizeof_stat == 8)
541 mv88e6xxx_stats_read(ds, s->reg + 1, &high);
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000542
543 data[i] = (((u64)high) << 32) | low;
544 }
Guenter Roeck17ee3e02014-10-29 10:45:07 -0700545error:
Lennert Buytenhek91da11f2008-10-07 13:44:02 +0000546 mutex_unlock(&ps->stats_mutex);
547}
Ben Hutchings98e67302011-11-25 14:36:19 +0000548
Guenter Roecka1ab91f2014-10-29 10:45:05 -0700549int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
550{
551 return 32 * sizeof(u16);
552}
553
554void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
555 struct ethtool_regs *regs, void *_p)
556{
557 u16 *p = _p;
558 int i;
559
560 regs->version = 0;
561
562 memset(p, 0xff, 32 * sizeof(u16));
563
564 for (i = 0; i < 32; i++) {
565 int ret;
566
567 ret = mv88e6xxx_reg_read(ds, REG_PORT(port), i);
568 if (ret >= 0)
569 p[i] = ret;
570 }
571}
572
Andrew Lunneaa23762014-11-15 22:24:51 +0100573#ifdef CONFIG_NET_DSA_HWMON
574
575int mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp)
576{
577 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
578 int ret;
579 int val;
580
581 *temp = 0;
582
583 mutex_lock(&ps->phy_mutex);
584
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200585 ret = _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x6);
Andrew Lunneaa23762014-11-15 22:24:51 +0100586 if (ret < 0)
587 goto error;
588
589 /* Enable temperature sensor */
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200590 ret = _mv88e6xxx_phy_read(ds, 0x0, 0x1a);
Andrew Lunneaa23762014-11-15 22:24:51 +0100591 if (ret < 0)
592 goto error;
593
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200594 ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret | (1 << 5));
Andrew Lunneaa23762014-11-15 22:24:51 +0100595 if (ret < 0)
596 goto error;
597
598 /* Wait for temperature to stabilize */
599 usleep_range(10000, 12000);
600
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200601 val = _mv88e6xxx_phy_read(ds, 0x0, 0x1a);
Andrew Lunneaa23762014-11-15 22:24:51 +0100602 if (val < 0) {
603 ret = val;
604 goto error;
605 }
606
607 /* Disable temperature sensor */
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200608 ret = _mv88e6xxx_phy_write(ds, 0x0, 0x1a, ret & ~(1 << 5));
Andrew Lunneaa23762014-11-15 22:24:51 +0100609 if (ret < 0)
610 goto error;
611
612 *temp = ((val & 0x1f) - 5) * 5;
613
614error:
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200615 _mv88e6xxx_phy_write(ds, 0x0, 0x16, 0x0);
Andrew Lunneaa23762014-11-15 22:24:51 +0100616 mutex_unlock(&ps->phy_mutex);
617 return ret;
618}
619#endif /* CONFIG_NET_DSA_HWMON */
620
Andrew Lunnf3044682015-02-14 19:17:50 +0100621static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
622{
623 unsigned long timeout = jiffies + HZ / 10;
624
625 while (time_before(jiffies, timeout)) {
626 int ret;
627
628 ret = REG_READ(reg, offset);
629 if (!(ret & mask))
630 return 0;
631
632 usleep_range(1000, 2000);
633 }
634 return -ETIMEDOUT;
635}
636
637int mv88e6xxx_phy_wait(struct dsa_switch *ds)
638{
639 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x18, 0x8000);
640}
641
642int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
643{
644 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x0800);
645}
646
647int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
648{
649 return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
650}
651
Guenter Roeckfacd95b2015-03-26 18:36:35 -0700652/* Must be called with SMI lock held */
653static int _mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
654{
655 unsigned long timeout = jiffies + HZ / 10;
656
657 while (time_before(jiffies, timeout)) {
658 int ret;
659
660 ret = _mv88e6xxx_reg_read(ds, reg, offset);
661 if (ret < 0)
662 return ret;
663 if (!(ret & mask))
664 return 0;
665
666 usleep_range(1000, 2000);
667 }
668 return -ETIMEDOUT;
669}
670
671/* Must be called with SMI lock held */
672static int _mv88e6xxx_atu_wait(struct dsa_switch *ds)
673{
674 return _mv88e6xxx_wait(ds, REG_GLOBAL, 0x0b, ATU_BUSY);
675}
676
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200677/* Must be called with phy mutex held */
678static int _mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr,
679 int regnum)
Andrew Lunnf3044682015-02-14 19:17:50 +0100680{
681 int ret;
682
683 REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum);
684
685 ret = mv88e6xxx_phy_wait(ds);
686 if (ret < 0)
687 return ret;
688
689 return REG_READ(REG_GLOBAL2, 0x19);
690}
691
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200692/* Must be called with phy mutex held */
693static int _mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr,
694 int regnum, u16 val)
Andrew Lunnf3044682015-02-14 19:17:50 +0100695{
696 REG_WRITE(REG_GLOBAL2, 0x19, val);
697 REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum);
698
699 return mv88e6xxx_phy_wait(ds);
700}
701
Guenter Roeck11b3b452015-03-06 22:23:51 -0800702int mv88e6xxx_get_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
703{
704 int reg;
705
706 reg = mv88e6xxx_phy_read_indirect(ds, port, 16);
707 if (reg < 0)
708 return -EOPNOTSUPP;
709
710 e->eee_enabled = !!(reg & 0x0200);
711 e->tx_lpi_enabled = !!(reg & 0x0100);
712
713 reg = REG_READ(REG_PORT(port), 0);
714 e->eee_active = !!(reg & 0x0040);
715
716 return 0;
717}
718
719static int mv88e6xxx_eee_enable_set(struct dsa_switch *ds, int port,
720 bool eee_enabled, bool tx_lpi_enabled)
721{
722 int reg, nreg;
723
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200724 reg = _mv88e6xxx_phy_read_indirect(ds, port, 16);
Guenter Roeck11b3b452015-03-06 22:23:51 -0800725 if (reg < 0)
726 return reg;
727
728 nreg = reg & ~0x0300;
729 if (eee_enabled)
730 nreg |= 0x0200;
731 if (tx_lpi_enabled)
732 nreg |= 0x0100;
733
734 if (nreg != reg)
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +0200735 return _mv88e6xxx_phy_write_indirect(ds, port, 16, nreg);
Guenter Roeck11b3b452015-03-06 22:23:51 -0800736
737 return 0;
738}
739
740int mv88e6xxx_set_eee(struct dsa_switch *ds, int port,
741 struct phy_device *phydev, struct ethtool_eee *e)
742{
743 int ret;
744
745 ret = mv88e6xxx_eee_enable_set(ds, port, e->eee_enabled,
746 e->tx_lpi_enabled);
747 if (ret)
748 return -EOPNOTSUPP;
749
750 return 0;
751}
752
Guenter Roeckfacd95b2015-03-26 18:36:35 -0700753static int _mv88e6xxx_atu_cmd(struct dsa_switch *ds, int fid, u16 cmd)
754{
755 int ret;
756
757 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x01, fid);
758 if (ret < 0)
759 return ret;
760
761 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0b, cmd);
762 if (ret < 0)
763 return ret;
764
765 return _mv88e6xxx_atu_wait(ds);
766}
767
768static int _mv88e6xxx_flush_fid(struct dsa_switch *ds, int fid)
769{
770 int ret;
771
772 ret = _mv88e6xxx_atu_wait(ds);
773 if (ret < 0)
774 return ret;
775
776 return _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_FLUSH_NONSTATIC_FID);
777}
778
779static int mv88e6xxx_set_port_state(struct dsa_switch *ds, int port, u8 state)
780{
781 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
782 int reg, ret;
783 u8 oldstate;
784
785 mutex_lock(&ps->smi_mutex);
786
787 reg = _mv88e6xxx_reg_read(ds, REG_PORT(port), 0x04);
788 if (reg < 0)
789 goto abort;
790
791 oldstate = reg & PSTATE_MASK;
792 if (oldstate != state) {
793 /* Flush forwarding database if we're moving a port
794 * from Learning or Forwarding state to Disabled or
795 * Blocking or Listening state.
796 */
797 if (oldstate >= PSTATE_LEARNING && state <= PSTATE_BLOCKING) {
798 ret = _mv88e6xxx_flush_fid(ds, ps->fid[port]);
799 if (ret)
800 goto abort;
801 }
802 reg = (reg & ~PSTATE_MASK) | state;
803 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x04, reg);
804 }
805
806abort:
807 mutex_unlock(&ps->smi_mutex);
808 return ret;
809}
810
811/* Must be called with smi lock held */
812static int _mv88e6xxx_update_port_config(struct dsa_switch *ds, int port)
813{
814 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
815 u8 fid = ps->fid[port];
816 u16 reg = fid << 12;
817
818 if (dsa_is_cpu_port(ds, port))
819 reg |= ds->phys_port_mask;
820 else
821 reg |= (ps->bridge_mask[fid] |
822 (1 << dsa_upstream_port(ds))) & ~(1 << port);
823
824 return _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x06, reg);
825}
826
827/* Must be called with smi lock held */
828static int _mv88e6xxx_update_bridge_config(struct dsa_switch *ds, int fid)
829{
830 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
831 int port;
832 u32 mask;
833 int ret;
834
835 mask = ds->phys_port_mask;
836 while (mask) {
837 port = __ffs(mask);
838 mask &= ~(1 << port);
839 if (ps->fid[port] != fid)
840 continue;
841
842 ret = _mv88e6xxx_update_port_config(ds, port);
843 if (ret)
844 return ret;
845 }
846
847 return _mv88e6xxx_flush_fid(ds, fid);
848}
849
850/* Bridge handling functions */
851
852int mv88e6xxx_join_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
853{
854 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
855 int ret = 0;
856 u32 nmask;
857 int fid;
858
859 /* If the bridge group is not empty, join that group.
860 * Otherwise create a new group.
861 */
862 fid = ps->fid[port];
863 nmask = br_port_mask & ~(1 << port);
864 if (nmask)
865 fid = ps->fid[__ffs(nmask)];
866
867 nmask = ps->bridge_mask[fid] | (1 << port);
868 if (nmask != br_port_mask) {
869 netdev_err(ds->ports[port],
870 "join: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
871 fid, br_port_mask, nmask);
872 return -EINVAL;
873 }
874
875 mutex_lock(&ps->smi_mutex);
876
877 ps->bridge_mask[fid] = br_port_mask;
878
879 if (fid != ps->fid[port]) {
880 ps->fid_mask |= 1 << ps->fid[port];
881 ps->fid[port] = fid;
882 ret = _mv88e6xxx_update_bridge_config(ds, fid);
883 }
884
885 mutex_unlock(&ps->smi_mutex);
886
887 return ret;
888}
889
890int mv88e6xxx_leave_bridge(struct dsa_switch *ds, int port, u32 br_port_mask)
891{
892 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
893 u8 fid, newfid;
894 int ret;
895
896 fid = ps->fid[port];
897
898 if (ps->bridge_mask[fid] != br_port_mask) {
899 netdev_err(ds->ports[port],
900 "leave: Bridge port mask mismatch fid=%d mask=0x%x expected 0x%x\n",
901 fid, br_port_mask, ps->bridge_mask[fid]);
902 return -EINVAL;
903 }
904
905 /* If the port was the last port of a bridge, we are done.
906 * Otherwise assign a new fid to the port, and fix up
907 * the bridge configuration.
908 */
909 if (br_port_mask == (1 << port))
910 return 0;
911
912 mutex_lock(&ps->smi_mutex);
913
914 newfid = __ffs(ps->fid_mask);
915 ps->fid[port] = newfid;
916 ps->fid_mask &= (1 << newfid);
917 ps->bridge_mask[fid] &= ~(1 << port);
918 ps->bridge_mask[newfid] = 1 << port;
919
920 ret = _mv88e6xxx_update_bridge_config(ds, fid);
921 if (!ret)
922 ret = _mv88e6xxx_update_bridge_config(ds, newfid);
923
924 mutex_unlock(&ps->smi_mutex);
925
926 return ret;
927}
928
929int mv88e6xxx_port_stp_update(struct dsa_switch *ds, int port, u8 state)
930{
931 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
932 int stp_state;
933
934 switch (state) {
935 case BR_STATE_DISABLED:
936 stp_state = PSTATE_DISABLED;
937 break;
938 case BR_STATE_BLOCKING:
939 case BR_STATE_LISTENING:
940 stp_state = PSTATE_BLOCKING;
941 break;
942 case BR_STATE_LEARNING:
943 stp_state = PSTATE_LEARNING;
944 break;
945 case BR_STATE_FORWARDING:
946 default:
947 stp_state = PSTATE_FORWARDING;
948 break;
949 }
950
951 netdev_dbg(ds->ports[port], "port state %d [%d]\n", state, stp_state);
952
953 /* mv88e6xxx_port_stp_update may be called with softirqs disabled,
954 * so we can not update the port state directly but need to schedule it.
955 */
956 ps->port_state[port] = stp_state;
957 set_bit(port, &ps->port_state_update_mask);
958 schedule_work(&ps->bridge_work);
959
960 return 0;
961}
962
Guenter Roeckdefb05b2015-03-26 18:36:38 -0700963static int __mv88e6xxx_write_addr(struct dsa_switch *ds,
964 const unsigned char *addr)
965{
966 int i, ret;
967
968 for (i = 0; i < 3; i++) {
969 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0d + i,
970 (addr[i * 2] << 8) | addr[i * 2 + 1]);
971 if (ret < 0)
972 return ret;
973 }
974
975 return 0;
976}
977
978static int __mv88e6xxx_read_addr(struct dsa_switch *ds, unsigned char *addr)
979{
980 int i, ret;
981
982 for (i = 0; i < 3; i++) {
983 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0d + i);
984 if (ret < 0)
985 return ret;
986 addr[i * 2] = ret >> 8;
987 addr[i * 2 + 1] = ret & 0xff;
988 }
989
990 return 0;
991}
992
993static int __mv88e6xxx_port_fdb_cmd(struct dsa_switch *ds, int port,
994 const unsigned char *addr, int state)
995{
996 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
997 u8 fid = ps->fid[port];
998 int ret;
999
1000 ret = _mv88e6xxx_atu_wait(ds);
1001 if (ret < 0)
1002 return ret;
1003
1004 ret = __mv88e6xxx_write_addr(ds, addr);
1005 if (ret < 0)
1006 return ret;
1007
1008 ret = _mv88e6xxx_reg_write(ds, REG_GLOBAL, 0x0c,
1009 (0x10 << port) | state);
1010 if (ret)
1011 return ret;
1012
1013 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_LOAD_FID);
1014
1015 return ret;
1016}
1017
1018int mv88e6xxx_port_fdb_add(struct dsa_switch *ds, int port,
1019 const unsigned char *addr, u16 vid)
1020{
1021 int state = is_multicast_ether_addr(addr) ?
1022 FDB_STATE_MC_STATIC : FDB_STATE_STATIC;
1023 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1024 int ret;
1025
1026 mutex_lock(&ps->smi_mutex);
1027 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, state);
1028 mutex_unlock(&ps->smi_mutex);
1029
1030 return ret;
1031}
1032
1033int mv88e6xxx_port_fdb_del(struct dsa_switch *ds, int port,
1034 const unsigned char *addr, u16 vid)
1035{
1036 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1037 int ret;
1038
1039 mutex_lock(&ps->smi_mutex);
1040 ret = __mv88e6xxx_port_fdb_cmd(ds, port, addr, FDB_STATE_UNUSED);
1041 mutex_unlock(&ps->smi_mutex);
1042
1043 return ret;
1044}
1045
1046static int __mv88e6xxx_port_getnext(struct dsa_switch *ds, int port,
1047 unsigned char *addr, bool *is_static)
1048{
1049 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1050 u8 fid = ps->fid[port];
1051 int ret, state;
1052
1053 ret = _mv88e6xxx_atu_wait(ds);
1054 if (ret < 0)
1055 return ret;
1056
1057 ret = __mv88e6xxx_write_addr(ds, addr);
1058 if (ret < 0)
1059 return ret;
1060
1061 do {
1062 ret = _mv88e6xxx_atu_cmd(ds, fid, ATU_CMD_GETNEXT_FID);
1063 if (ret < 0)
1064 return ret;
1065
1066 ret = _mv88e6xxx_reg_read(ds, REG_GLOBAL, 0x0c);
1067 if (ret < 0)
1068 return ret;
1069 state = ret & FDB_STATE_MASK;
1070 if (state == FDB_STATE_UNUSED)
1071 return -ENOENT;
1072 } while (!(((ret >> 4) & 0xff) & (1 << port)));
1073
1074 ret = __mv88e6xxx_read_addr(ds, addr);
1075 if (ret < 0)
1076 return ret;
1077
1078 *is_static = state == (is_multicast_ether_addr(addr) ?
1079 FDB_STATE_MC_STATIC : FDB_STATE_STATIC);
1080
1081 return 0;
1082}
1083
1084/* get next entry for port */
1085int mv88e6xxx_port_fdb_getnext(struct dsa_switch *ds, int port,
1086 unsigned char *addr, bool *is_static)
1087{
1088 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1089 int ret;
1090
1091 mutex_lock(&ps->smi_mutex);
1092 ret = __mv88e6xxx_port_getnext(ds, port, addr, is_static);
1093 mutex_unlock(&ps->smi_mutex);
1094
1095 return ret;
1096}
1097
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001098static void mv88e6xxx_bridge_work(struct work_struct *work)
1099{
1100 struct mv88e6xxx_priv_state *ps;
1101 struct dsa_switch *ds;
1102 int port;
1103
1104 ps = container_of(work, struct mv88e6xxx_priv_state, bridge_work);
1105 ds = ((struct dsa_switch *)ps) - 1;
1106
1107 while (ps->port_state_update_mask) {
1108 port = __ffs(ps->port_state_update_mask);
1109 clear_bit(port, &ps->port_state_update_mask);
1110 mv88e6xxx_set_port_state(ds, port, ps->port_state[port]);
1111 }
1112}
1113
Guenter Roeckd827e882015-03-26 18:36:29 -07001114int mv88e6xxx_setup_port_common(struct dsa_switch *ds, int port)
1115{
1116 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001117 int ret, fid;
Guenter Roeckd827e882015-03-26 18:36:29 -07001118
1119 mutex_lock(&ps->smi_mutex);
1120
Guenter Roeck366f0a02015-03-26 18:36:30 -07001121 /* Port Control 1: disable trunking, disable sending
1122 * learning messages to this port.
Guenter Roeckd827e882015-03-26 18:36:29 -07001123 */
Guenter Roeck366f0a02015-03-26 18:36:30 -07001124 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x05, 0x0000);
Guenter Roeckd827e882015-03-26 18:36:29 -07001125 if (ret)
1126 goto abort;
1127
1128 /* Port based VLAN map: give each port its own address
1129 * database, allow the CPU port to talk to each of the 'real'
1130 * ports, and allow each of the 'real' ports to only talk to
1131 * the upstream port.
1132 */
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001133 fid = __ffs(ps->fid_mask);
1134 ps->fid[port] = fid;
1135 ps->fid_mask &= ~(1 << fid);
Guenter Roeckd827e882015-03-26 18:36:29 -07001136
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001137 if (!dsa_is_cpu_port(ds, port))
1138 ps->bridge_mask[fid] = 1 << port;
1139
1140 ret = _mv88e6xxx_update_port_config(ds, port);
Guenter Roeckd827e882015-03-26 18:36:29 -07001141 if (ret)
1142 goto abort;
1143
1144 /* Default VLAN ID and priority: don't set a default VLAN
1145 * ID, and set the default packet priority to zero.
1146 */
1147 ret = _mv88e6xxx_reg_write(ds, REG_PORT(port), 0x07, 0x0000);
1148abort:
1149 mutex_unlock(&ps->smi_mutex);
1150 return ret;
1151}
1152
Guenter Roeckacdaffc2015-03-26 18:36:28 -07001153int mv88e6xxx_setup_common(struct dsa_switch *ds)
1154{
1155 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1156
1157 mutex_init(&ps->smi_mutex);
1158 mutex_init(&ps->stats_mutex);
1159 mutex_init(&ps->phy_mutex);
1160
Andrew Lunna8f064c2015-03-26 18:36:40 -07001161 ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0;
1162
Guenter Roeckfacd95b2015-03-26 18:36:35 -07001163 ps->fid_mask = (1 << DSA_MAX_PORTS) - 1;
1164
1165 INIT_WORK(&ps->bridge_work, mv88e6xxx_bridge_work);
1166
Guenter Roeckacdaffc2015-03-26 18:36:28 -07001167 return 0;
1168}
1169
Andrew Lunn143a8302015-04-02 04:06:34 +02001170int mv88e6xxx_switch_reset(struct dsa_switch *ds, bool ppu_active)
1171{
1172 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1173 u16 is_reset = (ppu_active ? 0x8800 : 0xc800);
1174 unsigned long timeout;
1175 int ret;
1176 int i;
1177
1178 /* Set all ports to the disabled state. */
1179 for (i = 0; i < ps->num_ports; i++) {
1180 ret = REG_READ(REG_PORT(i), 0x04);
1181 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
1182 }
1183
1184 /* Wait for transmit queues to drain. */
1185 usleep_range(2000, 4000);
1186
1187 /* Reset the switch. Keep the PPU active if requested. The PPU
1188 * needs to be active to support indirect phy register access
1189 * through global registers 0x18 and 0x19.
1190 */
1191 if (ppu_active)
1192 REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
1193 else
1194 REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
1195
1196 /* Wait up to one second for reset to complete. */
1197 timeout = jiffies + 1 * HZ;
1198 while (time_before(jiffies, timeout)) {
1199 ret = REG_READ(REG_GLOBAL, 0x00);
1200 if ((ret & is_reset) == is_reset)
1201 break;
1202 usleep_range(1000, 2000);
1203 }
1204 if (time_after(jiffies, timeout))
1205 return -ETIMEDOUT;
1206
1207 return 0;
1208}
1209
Andrew Lunn491435852015-04-02 04:06:35 +02001210int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg)
1211{
1212 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1213 int ret;
1214
1215 mutex_lock(&ps->phy_mutex);
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001216 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
Andrew Lunn491435852015-04-02 04:06:35 +02001217 if (ret < 0)
1218 goto error;
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001219 ret = _mv88e6xxx_phy_read_indirect(ds, port, reg);
Andrew Lunn491435852015-04-02 04:06:35 +02001220error:
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001221 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
Andrew Lunn491435852015-04-02 04:06:35 +02001222 mutex_unlock(&ps->phy_mutex);
1223 return ret;
1224}
1225
1226int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page,
1227 int reg, int val)
1228{
1229 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1230 int ret;
1231
1232 mutex_lock(&ps->phy_mutex);
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001233 ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
Andrew Lunn491435852015-04-02 04:06:35 +02001234 if (ret < 0)
1235 goto error;
1236
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001237 ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val);
Andrew Lunn491435852015-04-02 04:06:35 +02001238error:
Andrew Lunnfd3a0ee2015-04-02 04:06:36 +02001239 _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
1240 mutex_unlock(&ps->phy_mutex);
1241 return ret;
1242}
1243
1244static int mv88e6xxx_port_to_phy_addr(struct dsa_switch *ds, int port)
1245{
1246 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1247
1248 if (port >= 0 && port < ps->num_ports)
1249 return port;
1250 return -EINVAL;
1251}
1252
1253int
1254mv88e6xxx_phy_read(struct dsa_switch *ds, int port, int regnum)
1255{
1256 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1257 int addr = mv88e6xxx_port_to_phy_addr(ds, port);
1258 int ret;
1259
1260 if (addr < 0)
1261 return addr;
1262
1263 mutex_lock(&ps->phy_mutex);
1264 ret = _mv88e6xxx_phy_read(ds, addr, regnum);
1265 mutex_unlock(&ps->phy_mutex);
1266 return ret;
1267}
1268
1269int
1270mv88e6xxx_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
1271{
1272 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1273 int addr = mv88e6xxx_port_to_phy_addr(ds, port);
1274 int ret;
1275
1276 if (addr < 0)
1277 return addr;
1278
1279 mutex_lock(&ps->phy_mutex);
1280 ret = _mv88e6xxx_phy_write(ds, addr, regnum, val);
1281 mutex_unlock(&ps->phy_mutex);
1282 return ret;
1283}
1284
1285int
1286mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int port, int regnum)
1287{
1288 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1289 int addr = mv88e6xxx_port_to_phy_addr(ds, port);
1290 int ret;
1291
1292 if (addr < 0)
1293 return addr;
1294
1295 mutex_lock(&ps->phy_mutex);
1296 ret = _mv88e6xxx_phy_read_indirect(ds, addr, regnum);
1297 mutex_unlock(&ps->phy_mutex);
1298 return ret;
1299}
1300
1301int
1302mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int port, int regnum,
1303 u16 val)
1304{
1305 struct mv88e6xxx_priv_state *ps = ds_to_priv(ds);
1306 int addr = mv88e6xxx_port_to_phy_addr(ds, port);
1307 int ret;
1308
1309 if (addr < 0)
1310 return addr;
1311
1312 mutex_lock(&ps->phy_mutex);
1313 ret = _mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
Andrew Lunn491435852015-04-02 04:06:35 +02001314 mutex_unlock(&ps->phy_mutex);
1315 return ret;
1316}
1317
Ben Hutchings98e67302011-11-25 14:36:19 +00001318static int __init mv88e6xxx_init(void)
1319{
1320#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
1321 register_switch_driver(&mv88e6131_switch_driver);
1322#endif
1323#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
1324 register_switch_driver(&mv88e6123_61_65_switch_driver);
1325#endif
Guenter Roeck3ad50cc2014-10-29 10:44:56 -07001326#if IS_ENABLED(CONFIG_NET_DSA_MV88E6352)
1327 register_switch_driver(&mv88e6352_switch_driver);
1328#endif
Andrew Lunn42f27252014-09-12 23:58:44 +02001329#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
1330 register_switch_driver(&mv88e6171_switch_driver);
1331#endif
Ben Hutchings98e67302011-11-25 14:36:19 +00001332 return 0;
1333}
1334module_init(mv88e6xxx_init);
1335
1336static void __exit mv88e6xxx_cleanup(void)
1337{
Andrew Lunn42f27252014-09-12 23:58:44 +02001338#if IS_ENABLED(CONFIG_NET_DSA_MV88E6171)
1339 unregister_switch_driver(&mv88e6171_switch_driver);
1340#endif
Ben Hutchings98e67302011-11-25 14:36:19 +00001341#if IS_ENABLED(CONFIG_NET_DSA_MV88E6123_61_65)
1342 unregister_switch_driver(&mv88e6123_61_65_switch_driver);
1343#endif
1344#if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
1345 unregister_switch_driver(&mv88e6131_switch_driver);
1346#endif
1347}
1348module_exit(mv88e6xxx_cleanup);
Ben Hutchings3d825ed2011-11-25 14:37:16 +00001349
1350MODULE_AUTHOR("Lennert Buytenhek <buytenh@wantstofly.org>");
1351MODULE_DESCRIPTION("Driver for Marvell 88E6XXX ethernet switch chips");
1352MODULE_LICENSE("GPL");