11 #include <linux/list.h>
12 #include <linux/module.h>
13 #include <linux/netdevice.h>
18 static char *mv88e6123_61_65_probe(
struct mii_bus *
bus,
int sw_addr)
25 return "Marvell 88E6123 (A1)";
27 return "Marvell 88E6123 (A2)";
28 if ((ret & 0xfff0) == 0x1210)
29 return "Marvell 88E6123";
32 return "Marvell 88E6161 (A1)";
34 return "Marvell 88E6161 (A2)";
35 if ((ret & 0xfff0) == 0x1610)
36 return "Marvell 88E6161";
39 return "Marvell 88E6165 (A1)";
41 return "Marvell 88e6165 (A2)";
42 if ((ret & 0xfff0) == 0x1650)
43 return "Marvell 88E6165";
49 static int mv88e6123_61_65_switch_reset(
struct dsa_switch *
ds)
57 for (i = 0; i < 8; i++) {
75 for (i = 0; i < 1000; i++) {
77 if ((ret & 0xc800) == 0xc800)
88 static int mv88e6123_61_65_setup_global(
struct dsa_switch *ds)
152 for (i = 0; i < 32; i++) {
156 if (i != ds->
index && i < ds->
dst->pd->nr_chips)
157 nexthop = ds->
pd->rtable[
i] & 0x1f;
165 for (i = 0; i < 8; i++)
171 for (i = 0; i < 16; i++)
178 for (i = 0; i < 6; i++)
189 for (i = 0; i < 16; i++)
197 static int mv88e6123_61_65_setup_port(
struct dsa_switch *ds,
int p)
236 if (dsa_is_cpu_port(ds, p)) {
244 if (p == dsa_upstream_port(ds))
252 REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
260 val = (p & 0xf) << 12;
261 if (dsa_is_cpu_port(ds, p))
264 val |= 1 << dsa_upstream_port(ds);
333 static int mv88e6123_61_65_setup(
struct dsa_switch *ds)
342 ret = mv88e6123_61_65_switch_reset(ds);
348 ret = mv88e6123_61_65_setup_global(ds);
352 for (i = 0; i < 6; i++) {
353 ret = mv88e6123_61_65_setup_port(ds, i);
361 static int mv88e6123_61_65_port_to_phy_addr(
int port)
363 if (port >= 0 && port <= 4)
369 mv88e6123_61_65_phy_read(
struct dsa_switch *ds,
int port,
int regnum)
371 int addr = mv88e6123_61_65_port_to_phy_addr(port);
376 mv88e6123_61_65_phy_write(
struct dsa_switch *ds,
377 int port,
int regnum,
u16 val)
379 int addr = mv88e6123_61_65_port_to_phy_addr(port);
384 {
"in_good_octets", 8, 0x00, },
385 {
"in_bad_octets", 4, 0x02, },
386 {
"in_unicast", 4, 0x04, },
387 {
"in_broadcasts", 4, 0x06, },
388 {
"in_multicasts", 4, 0x07, },
389 {
"in_pause", 4, 0x16, },
390 {
"in_undersize", 4, 0x18, },
391 {
"in_fragments", 4, 0x19, },
392 {
"in_oversize", 4, 0x1a, },
393 {
"in_jabber", 4, 0x1b, },
394 {
"in_rx_error", 4, 0x1c, },
395 {
"in_fcs_error", 4, 0x1d, },
396 {
"out_octets", 8, 0x0e, },
397 {
"out_unicast", 4, 0x10, },
398 {
"out_broadcasts", 4, 0x13, },
399 {
"out_multicasts", 4, 0x12, },
400 {
"out_pause", 4, 0x15, },
401 {
"excessive", 4, 0x11, },
402 {
"collisions", 4, 0x1e, },
403 {
"deferred", 4, 0x05, },
404 {
"single", 4, 0x14, },
405 {
"multiple", 4, 0x17, },
406 {
"out_fcs_error", 4, 0x03, },
407 {
"late", 4, 0x1f, },
408 {
"hist_64bytes", 4, 0x08, },
409 {
"hist_65_127bytes", 4, 0x09, },
410 {
"hist_128_255bytes", 4, 0x0a, },
411 {
"hist_256_511bytes", 4, 0x0b, },
412 {
"hist_512_1023bytes", 4, 0x0c, },
413 {
"hist_1024_max_bytes", 4, 0x0d, },
420 mv88e6123_61_65_hw_stats, port, data);
424 mv88e6123_61_65_get_ethtool_stats(
struct dsa_switch *ds,
428 mv88e6123_61_65_hw_stats, port, data);
431 static int mv88e6123_61_65_get_sset_count(
struct dsa_switch *ds)
439 .probe = mv88e6123_61_65_probe,
440 .setup = mv88e6123_61_65_setup,
442 .phy_read = mv88e6123_61_65_phy_read,
443 .phy_write = mv88e6123_61_65_phy_write,
445 .get_strings = mv88e6123_61_65_get_strings,
446 .get_ethtool_stats = mv88e6123_61_65_get_ethtool_stats,
447 .get_sset_count = mv88e6123_61_65_get_sset_count,