aboutsummaryrefslogtreecommitdiffstats
path: root/net/dsa/mv88e6131.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/dsa/mv88e6131.c')
-rw-r--r--net/dsa/mv88e6131.c98
1 files changed, 63 insertions, 35 deletions
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c
index 374d46a01265..bb2b41bc854e 100644
--- a/net/dsa/mv88e6131.c
+++ b/net/dsa/mv88e6131.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * net/dsa/mv88e6131.c - Marvell 88e6131 switch chip support 2 * net/dsa/mv88e6131.c - Marvell 88e6095/6095f/6131 switch chip support
3 * Copyright (c) 2008 Marvell Semiconductor 3 * Copyright (c) 2008-2009 Marvell Semiconductor
4 * 4 *
5 * This program is free software; you can redistribute it and/or modify 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 6 * it under the terms of the GNU General Public License as published by
@@ -21,6 +21,8 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr)
21 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); 21 ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03);
22 if (ret >= 0) { 22 if (ret >= 0) {
23 ret &= 0xfff0; 23 ret &= 0xfff0;
24 if (ret == 0x0950)
25 return "Marvell 88E6095/88E6095F";
24 if (ret == 0x1060) 26 if (ret == 0x1060)
25 return "Marvell 88E6131"; 27 return "Marvell 88E6131";
26 } 28 }
@@ -36,7 +38,7 @@ static int mv88e6131_switch_reset(struct dsa_switch *ds)
36 /* 38 /*
37 * Set all ports to the disabled state. 39 * Set all ports to the disabled state.
38 */ 40 */
39 for (i = 0; i < 8; i++) { 41 for (i = 0; i < 11; i++) {
40 ret = REG_READ(REG_PORT(i), 0x04); 42 ret = REG_READ(REG_PORT(i), 0x04);
41 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc); 43 REG_WRITE(REG_PORT(i), 0x04, ret & 0xfffc);
42 } 44 }
@@ -100,17 +102,17 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
100 REG_WRITE(REG_GLOBAL, 0x19, 0x8100); 102 REG_WRITE(REG_GLOBAL, 0x19, 0x8100);
101 103
102 /* 104 /*
103 * Disable ARP mirroring, and configure the cpu port as the 105 * Disable ARP mirroring, and configure the upstream port as
104 * port to which ingress and egress monitor frames are to be 106 * the port to which ingress and egress monitor frames are to
105 * sent. 107 * be sent.
106 */ 108 */
107 REG_WRITE(REG_GLOBAL, 0x1a, (ds->cpu_port * 0x1100) | 0x00f0); 109 REG_WRITE(REG_GLOBAL, 0x1a, (dsa_upstream_port(ds) * 0x1100) | 0x00f0);
108 110
109 /* 111 /*
110 * Disable cascade port functionality, and set the switch's 112 * Disable cascade port functionality, and set the switch's
111 * DSA device number to zero. 113 * DSA device number.
112 */ 114 */
113 REG_WRITE(REG_GLOBAL, 0x1c, 0xe000); 115 REG_WRITE(REG_GLOBAL, 0x1c, 0xe000 | (ds->index & 0x1f));
114 116
115 /* 117 /*
116 * Send all frames with destination addresses matching 118 * Send all frames with destination addresses matching
@@ -127,16 +129,23 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
127 REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); 129 REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff);
128 130
129 /* 131 /*
130 * Map all DSA device IDs to the CPU port. 132 * Program the DSA routing table.
131 */ 133 */
132 for (i = 0; i < 32; i++) 134 for (i = 0; i < 32; i++) {
133 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | ds->cpu_port); 135 int nexthop;
136
137 nexthop = 0x1f;
138 if (i != ds->index && i < ds->dst->pd->nr_chips)
139 nexthop = ds->pd->rtable[i] & 0x1f;
140
141 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
142 }
134 143
135 /* 144 /*
136 * Clear all trunk masks. 145 * Clear all trunk masks.
137 */ 146 */
138 for (i = 0; i < 8; i++) 147 for (i = 0; i < 8; i++)
139 REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0xff); 148 REG_WRITE(REG_GLOBAL2, 0x07, 0x8000 | (i << 12) | 0x7ff);
140 149
141 /* 150 /*
142 * Clear all trunk mappings. 151 * Clear all trunk mappings.
@@ -156,12 +165,18 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
156static int mv88e6131_setup_port(struct dsa_switch *ds, int p) 165static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
157{ 166{
158 int addr = REG_PORT(p); 167 int addr = REG_PORT(p);
168 u16 val;
159 169
160 /* 170 /*
161 * MAC Forcing register: don't force link, speed, duplex 171 * MAC Forcing register: don't force link, speed, duplex
162 * or flow control state to any particular values. 172 * 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
174 * full duplex.
163 */ 175 */
164 REG_WRITE(addr, 0x01, 0x0003); 176 if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p))
177 REG_WRITE(addr, 0x01, 0x003e);
178 else
179 REG_WRITE(addr, 0x01, 0x0003);
165 180
166 /* 181 /*
167 * Port Control: disable Core Tag, disable Drop-on-Lock, 182 * Port Control: disable Core Tag, disable Drop-on-Lock,
@@ -169,29 +184,40 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
169 * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN 184 * enable IGMP/MLD snoop, disable DoubleTag, disable VLAN
170 * tunneling, determine priority by looking at 802.1p and 185 * tunneling, determine priority by looking at 802.1p and
171 * IP priority fields (IP prio has precedence), and set STP 186 * IP priority fields (IP prio has precedence), and set STP
172 * state to Forwarding. Finally, if this is the CPU port, 187 * state to Forwarding.
173 * additionally enable DSA tagging and forwarding of unknown 188 *
174 * unicast addresses. 189 * If this is the upstream port for this switch, enable
190 * forwarding of unknown unicasts, and enable DSA tagging
191 * mode.
192 *
193 * If this is the link to another switch, use DSA tagging
194 * mode, but do not enable forwarding of unknown unicasts.
175 */ 195 */
176 REG_WRITE(addr, 0x04, (p == ds->cpu_port) ? 0x0537 : 0x0433); 196 val = 0x0433;
197 if (p == dsa_upstream_port(ds))
198 val |= 0x0104;
199 if (ds->dsa_port_mask & (1 << p))
200 val |= 0x0100;
201 REG_WRITE(addr, 0x04, val);
177 202
178 /* 203 /*
179 * Port Control 1: disable trunking. Also, if this is the 204 * Port Control 1: disable trunking. Also, if this is the
180 * CPU port, enable learn messages to be sent to this port. 205 * CPU port, enable learn messages to be sent to this port.
181 */ 206 */
182 REG_WRITE(addr, 0x05, (p == ds->cpu_port) ? 0x8000 : 0x0000); 207 REG_WRITE(addr, 0x05, dsa_is_cpu_port(ds, p) ? 0x8000 : 0x0000);
183 208
184 /* 209 /*
185 * Port based VLAN map: give each port its own address 210 * Port based VLAN map: give each port its own address
186 * database, allow the CPU port to talk to each of the 'real' 211 * database, allow the CPU port to talk to each of the 'real'
187 * ports, and allow each of the 'real' ports to only talk to 212 * ports, and allow each of the 'real' ports to only talk to
188 * the CPU port. 213 * the upstream port.
189 */ 214 */
190 REG_WRITE(addr, 0x06, 215 val = (p & 0xf) << 12;
191 ((p & 0xf) << 12) | 216 if (dsa_is_cpu_port(ds, p))
192 ((p == ds->cpu_port) ? 217 val |= ds->phys_port_mask;
193 ds->valid_port_mask : 218 else
194 (1 << ds->cpu_port))); 219 val |= 1 << dsa_upstream_port(ds);
220 REG_WRITE(addr, 0x06, val);
195 221
196 /* 222 /*
197 * Default VLAN ID and priority: don't set a default VLAN 223 * Default VLAN ID and priority: don't set a default VLAN
@@ -207,13 +233,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p)
207 * untagged frames on this port, do a destination address 233 * untagged frames on this port, do a destination address
208 * lookup on received packets as usual, don't send a copy 234 * lookup on received packets as usual, don't send a copy
209 * of all transmitted/received frames on this port to the 235 * of all transmitted/received frames on this port to the
210 * CPU, and configure the CPU port number. Also, if this 236 * CPU, and configure the upstream port number.
211 * is the CPU port, enable forwarding of unknown multicast 237 *
212 * addresses. 238 * If this is the upstream port for this switch, enable
239 * forwarding of unknown multicast addresses.
213 */ 240 */
214 REG_WRITE(addr, 0x08, 241 val = 0x0080 | dsa_upstream_port(ds);
215 ((p == ds->cpu_port) ? 0x00c0 : 0x0080) | 242 if (p == dsa_upstream_port(ds))
216 ds->cpu_port); 243 val |= 0x0040;
244 REG_WRITE(addr, 0x08, val);
217 245
218 /* 246 /*
219 * Rate Control: disable ingress rate limiting. 247 * Rate Control: disable ingress rate limiting.
@@ -268,7 +296,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
268 if (ret < 0) 296 if (ret < 0)
269 return ret; 297 return ret;
270 298
271 for (i = 0; i < 6; i++) { 299 for (i = 0; i < 11; i++) {
272 ret = mv88e6131_setup_port(ds, i); 300 ret = mv88e6131_setup_port(ds, i);
273 if (ret < 0) 301 if (ret < 0)
274 return ret; 302 return ret;
@@ -279,7 +307,7 @@ static int mv88e6131_setup(struct dsa_switch *ds)
279 307
280static int mv88e6131_port_to_phy_addr(int port) 308static int mv88e6131_port_to_phy_addr(int port)
281{ 309{
282 if (port >= 0 && port != 3 && port <= 7) 310 if (port >= 0 && port <= 11)
283 return port; 311 return port;
284 return -1; 312 return -1;
285} 313}
@@ -353,7 +381,7 @@ static int mv88e6131_get_sset_count(struct dsa_switch *ds)
353} 381}
354 382
355static struct dsa_switch_driver mv88e6131_switch_driver = { 383static struct dsa_switch_driver mv88e6131_switch_driver = {
356 .tag_protocol = __constant_htons(ETH_P_DSA), 384 .tag_protocol = cpu_to_be16(ETH_P_DSA),
357 .priv_size = sizeof(struct mv88e6xxx_priv_state), 385 .priv_size = sizeof(struct mv88e6xxx_priv_state),
358 .probe = mv88e6131_probe, 386 .probe = mv88e6131_probe,
359 .setup = mv88e6131_setup, 387 .setup = mv88e6131_setup,