diff options
Diffstat (limited to 'net/dsa/mv88e6131.c')
-rw-r--r-- | net/dsa/mv88e6131.c | 51 |
1 files changed, 41 insertions, 10 deletions
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index bb2b41bc854e..45f7411e90ba 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c | |||
@@ -14,6 +14,13 @@ | |||
14 | #include "dsa_priv.h" | 14 | #include "dsa_priv.h" |
15 | #include "mv88e6xxx.h" | 15 | #include "mv88e6xxx.h" |
16 | 16 | ||
17 | /* | ||
18 | * Switch product IDs | ||
19 | */ | ||
20 | #define ID_6085 0x04a0 | ||
21 | #define ID_6095 0x0950 | ||
22 | #define ID_6131 0x1060 | ||
23 | |||
17 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | 24 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) |
18 | { | 25 | { |
19 | int ret; | 26 | int ret; |
@@ -21,9 +28,11 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | |||
21 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); | 28 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); |
22 | if (ret >= 0) { | 29 | if (ret >= 0) { |
23 | ret &= 0xfff0; | 30 | ret &= 0xfff0; |
24 | if (ret == 0x0950) | 31 | if (ret == ID_6085) |
32 | return "Marvell 88E6085"; | ||
33 | if (ret == ID_6095) | ||
25 | return "Marvell 88E6095/88E6095F"; | 34 | return "Marvell 88E6095/88E6095F"; |
26 | if (ret == 0x1060) | 35 | if (ret == ID_6131) |
27 | return "Marvell 88E6131"; | 36 | return "Marvell 88E6131"; |
28 | } | 37 | } |
29 | 38 | ||
@@ -124,7 +133,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
124 | * Ignore removed tag data on doubly tagged packets, disable | 133 | * Ignore removed tag data on doubly tagged packets, disable |
125 | * flow control messages, force flow control priority to the | 134 | * flow control messages, force flow control priority to the |
126 | * highest, and send all special multicast frames to the CPU | 135 | * highest, and send all special multicast frames to the CPU |
127 | * port at the higest priority. | 136 | * port at the highest priority. |
128 | */ | 137 | */ |
129 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); | 138 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); |
130 | 139 | ||
@@ -164,6 +173,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
164 | 173 | ||
165 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | 174 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) |
166 | { | 175 | { |
176 | struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); | ||
167 | int addr = REG_PORT(p); | 177 | int addr = REG_PORT(p); |
168 | u16 val; | 178 | u16 val; |
169 | 179 | ||
@@ -171,10 +181,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
171 | * MAC Forcing register: don't force link, speed, duplex | 181 | * MAC Forcing register: don't force link, speed, duplex |
172 | * or flow control state to any particular values on physical | 182 | * or flow control state to any particular values on physical |
173 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s | 183 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s |
174 | * full duplex. | 184 | * (100 Mb/s on 6085) full duplex. |
175 | */ | 185 | */ |
176 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) | 186 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) |
177 | REG_WRITE(addr, 0x01, 0x003e); | 187 | if (ps->id == ID_6085) |
188 | REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */ | ||
189 | else | ||
190 | REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */ | ||
178 | else | 191 | else |
179 | REG_WRITE(addr, 0x01, 0x0003); | 192 | REG_WRITE(addr, 0x01, 0x0003); |
180 | 193 | ||
@@ -194,8 +207,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
194 | * mode, but do not enable forwarding of unknown unicasts. | 207 | * mode, but do not enable forwarding of unknown unicasts. |
195 | */ | 208 | */ |
196 | val = 0x0433; | 209 | val = 0x0433; |
197 | if (p == dsa_upstream_port(ds)) | 210 | if (p == dsa_upstream_port(ds)) { |
198 | val |= 0x0104; | 211 | val |= 0x0104; |
212 | /* | ||
213 | * On 6085, unknown multicast forward is controlled | ||
214 | * here rather than in Port Control 2 register. | ||
215 | */ | ||
216 | if (ps->id == ID_6085) | ||
217 | val |= 0x0008; | ||
218 | } | ||
199 | if (ds->dsa_port_mask & (1 << p)) | 219 | if (ds->dsa_port_mask & (1 << p)) |
200 | val |= 0x0100; | 220 | val |= 0x0100; |
201 | REG_WRITE(addr, 0x04, val); | 221 | REG_WRITE(addr, 0x04, val); |
@@ -238,10 +258,19 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
238 | * If this is the upstream port for this switch, enable | 258 | * If this is the upstream port for this switch, enable |
239 | * forwarding of unknown multicast addresses. | 259 | * forwarding of unknown multicast addresses. |
240 | */ | 260 | */ |
241 | val = 0x0080 | dsa_upstream_port(ds); | 261 | if (ps->id == ID_6085) |
242 | if (p == dsa_upstream_port(ds)) | 262 | /* |
243 | val |= 0x0040; | 263 | * on 6085, bits 3:0 are reserved, bit 6 control ARP |
244 | REG_WRITE(addr, 0x08, val); | 264 | * mirroring, and multicast forward is handled in |
265 | * Port Control register. | ||
266 | */ | ||
267 | REG_WRITE(addr, 0x08, 0x0080); | ||
268 | else { | ||
269 | val = 0x0080 | dsa_upstream_port(ds); | ||
270 | if (p == dsa_upstream_port(ds)) | ||
271 | val |= 0x0040; | ||
272 | REG_WRITE(addr, 0x08, val); | ||
273 | } | ||
245 | 274 | ||
246 | /* | 275 | /* |
247 | * Rate Control: disable ingress rate limiting. | 276 | * Rate Control: disable ingress rate limiting. |
@@ -286,6 +315,8 @@ static int mv88e6131_setup(struct dsa_switch *ds) | |||
286 | mv88e6xxx_ppu_state_init(ds); | 315 | mv88e6xxx_ppu_state_init(ds); |
287 | mutex_init(&ps->stats_mutex); | 316 | mutex_init(&ps->stats_mutex); |
288 | 317 | ||
318 | ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0; | ||
319 | |||
289 | ret = mv88e6131_switch_reset(ds); | 320 | ret = mv88e6131_switch_reset(ds); |
290 | if (ret < 0) | 321 | if (ret < 0) |
291 | return ret; | 322 | return ret; |