Commit | Line | Data |
---|---|---|
1636d883 | 1 | /* net/dsa/mv88e6171.c - Marvell 88e6171 switch chip support |
42f27253 AL |
2 | * Copyright (c) 2008-2009 Marvell Semiconductor |
3 | * Copyright (c) 2014 Claudio Leite <leitec@staticky.com> | |
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 | ||
11 | #include <linux/delay.h> | |
12 | #include <linux/jiffies.h> | |
13 | #include <linux/list.h> | |
14 | #include <linux/module.h> | |
15 | #include <linux/netdevice.h> | |
16 | #include <linux/phy.h> | |
17 | #include <net/dsa.h> | |
18 | #include "mv88e6xxx.h" | |
19 | ||
b4d2394d | 20 | static char *mv88e6171_probe(struct device *host_dev, int sw_addr) |
42f27253 | 21 | { |
b4d2394d | 22 | struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev); |
42f27253 AL |
23 | int ret; |
24 | ||
b4d2394d AD |
25 | if (bus == NULL) |
26 | return NULL; | |
27 | ||
cca8b133 | 28 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), PORT_SWITCH_ID); |
42f27253 | 29 | if (ret >= 0) { |
cca8b133 | 30 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6171) |
42f27253 | 31 | return "Marvell 88E6171"; |
eee7483e AL |
32 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6175) |
33 | return "Marvell 88E6175"; | |
34 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6350) | |
35 | return "Marvell 88E6350"; | |
36 | if ((ret & 0xfff0) == PORT_SWITCH_ID_6351) | |
37 | return "Marvell 88E6351"; | |
42f27253 AL |
38 | } |
39 | ||
40 | return NULL; | |
41 | } | |
42 | ||
42f27253 AL |
43 | static int mv88e6171_setup_global(struct dsa_switch *ds) |
44 | { | |
15966a2a | 45 | u32 upstream_port = dsa_upstream_port(ds); |
42f27253 | 46 | int ret; |
1636d883 | 47 | u32 reg; |
54d792f2 AL |
48 | |
49 | ret = mv88e6xxx_setup_global(ds); | |
50 | if (ret) | |
51 | return ret; | |
42f27253 | 52 | |
4c732668 AL |
53 | /* Discard packets with excessive collisions, mask all |
54 | * interrupt sources, enable PPU. | |
42f27253 | 55 | */ |
15966a2a AL |
56 | REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL, |
57 | GLOBAL_CONTROL_PPU_ENABLE | GLOBAL_CONTROL_DISCARD_EXCESS); | |
42f27253 | 58 | |
42f27253 AL |
59 | /* Configure the upstream port, and configure the upstream |
60 | * port as the port to which ingress and egress monitor frames | |
61 | * are to be sent. | |
62 | */ | |
1636d883 AL |
63 | reg = upstream_port << GLOBAL_MONITOR_CONTROL_INGRESS_SHIFT | |
64 | upstream_port << GLOBAL_MONITOR_CONTROL_EGRESS_SHIFT | | |
65 | upstream_port << GLOBAL_MONITOR_CONTROL_ARP_SHIFT | | |
66 | upstream_port << GLOBAL_MONITOR_CONTROL_MIRROR_SHIFT; | |
67 | REG_WRITE(REG_GLOBAL, GLOBAL_MONITOR_CONTROL, reg); | |
42f27253 AL |
68 | |
69 | /* Disable remote management for now, and set the switch's | |
70 | * DSA device number. | |
71 | */ | |
15966a2a | 72 | REG_WRITE(REG_GLOBAL, GLOBAL_CONTROL_2, ds->index & 0x1f); |
42f27253 | 73 | |
42f27253 AL |
74 | return 0; |
75 | } | |
76 | ||
42f27253 AL |
77 | static int mv88e6171_setup(struct dsa_switch *ds) |
78 | { | |
44e50ddb | 79 | struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); |
42f27253 AL |
80 | int ret; |
81 | ||
acdaffcc GR |
82 | ret = mv88e6xxx_setup_common(ds); |
83 | if (ret < 0) | |
84 | return ret; | |
42f27253 | 85 | |
44e50ddb AL |
86 | ps->num_ports = 7; |
87 | ||
143a8307 | 88 | ret = mv88e6xxx_switch_reset(ds, true); |
42f27253 AL |
89 | if (ret < 0) |
90 | return ret; | |
91 | ||
42f27253 AL |
92 | ret = mv88e6171_setup_global(ds); |
93 | if (ret < 0) | |
94 | return ret; | |
95 | ||
dbde9e66 | 96 | return mv88e6xxx_setup_ports(ds); |
42f27253 AL |
97 | } |
98 | ||
42f27253 | 99 | struct dsa_switch_driver mv88e6171_switch_driver = { |
c146b778 | 100 | .tag_protocol = DSA_TAG_PROTO_EDSA, |
42f27253 AL |
101 | .priv_size = sizeof(struct mv88e6xxx_priv_state), |
102 | .probe = mv88e6171_probe, | |
103 | .setup = mv88e6171_setup, | |
104 | .set_addr = mv88e6xxx_set_addr_indirect, | |
fd3a0ee4 AL |
105 | .phy_read = mv88e6xxx_phy_read_indirect, |
106 | .phy_write = mv88e6xxx_phy_write_indirect, | |
42f27253 | 107 | .poll_link = mv88e6xxx_poll_link, |
e413e7e1 AL |
108 | .get_strings = mv88e6xxx_get_strings, |
109 | .get_ethtool_stats = mv88e6xxx_get_ethtool_stats, | |
110 | .get_sset_count = mv88e6xxx_get_sset_count, | |
4dd38cdb AL |
111 | #ifdef CONFIG_NET_DSA_HWMON |
112 | .get_temp = mv88e6xxx_get_temp, | |
113 | #endif | |
03d6faa9 AL |
114 | .get_regs_len = mv88e6xxx_get_regs_len, |
115 | .get_regs = mv88e6xxx_get_regs, | |
b2a6b93a AL |
116 | .port_join_bridge = mv88e6xxx_join_bridge, |
117 | .port_leave_bridge = mv88e6xxx_leave_bridge, | |
118 | .port_stp_update = mv88e6xxx_port_stp_update, | |
119 | .fdb_add = mv88e6xxx_port_fdb_add, | |
120 | .fdb_del = mv88e6xxx_port_fdb_del, | |
121 | .fdb_getnext = mv88e6xxx_port_fdb_getnext, | |
42f27253 AL |
122 | }; |
123 | ||
124 | MODULE_ALIAS("platform:mv88e6171"); | |
eee7483e AL |
125 | MODULE_ALIAS("platform:mv88e6175"); |
126 | MODULE_ALIAS("platform:mv88e6350"); | |
127 | MODULE_ALIAS("platform:mv88e6351"); |