aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-09-24 20:05:20 -0400
committerDavid S. Miller <davem@davemloft.net>2014-09-28 17:14:09 -0400
commitb6d045db59210476323caef042c5b50884e4675f (patch)
tree81f8ea611a082f4a671382eed7b795c646e483e1 /drivers/net/dsa
parent7de1557ce7521e756974d5c28794c2375d28e3cc (diff)
net: dsa: bcm_sf2: add port_enable/disable callbacks
The SF2 switch driver is already architected around per-port enable/disable callbacks, so we just need a slight update to our existing bcm_sf2_port_setup() resp. bcm_sf2_port_disable() functions to be suitable as callbacks for port_enable/port_disable. We need to shuffle a little the code that does the per-port VLAN configuration/isolation since ports can now be brought up/down separately, so we need to make sure that IMP (CPU, management) port is always included in that specific port setup. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r--drivers/net/dsa/bcm_sf2.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 58b8fef25b96..634e44ee8d0d 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -135,10 +135,29 @@ static char *bcm_sf2_sw_probe(struct device *host_dev, int sw_addr)
135 return "Broadcom Starfighter 2"; 135 return "Broadcom Starfighter 2";
136} 136}
137 137
138static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) 138static void bcm_sf2_imp_vlan_setup(struct dsa_switch *ds, int cpu_port)
139{ 139{
140 struct bcm_sf2_priv *priv = ds_to_priv(ds); 140 struct bcm_sf2_priv *priv = ds_to_priv(ds);
141 unsigned int i; 141 unsigned int i;
142 u32 reg;
143
144 /* Enable the IMP Port to be in the same VLAN as the other ports
145 * on a per-port basis such that we only have Port i and IMP in
146 * the same VLAN.
147 */
148 for (i = 0; i < priv->hw_params.num_ports; i++) {
149 if (!((1 << i) & ds->phys_port_mask))
150 continue;
151
152 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
153 reg |= (1 << cpu_port);
154 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(i));
155 }
156}
157
158static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
159{
160 struct bcm_sf2_priv *priv = ds_to_priv(ds);
142 u32 reg, val; 161 u32 reg, val;
143 162
144 /* Enable the port memories */ 163 /* Enable the port memories */
@@ -199,24 +218,13 @@ static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port)
199 reg = core_readl(priv, CORE_STS_OVERRIDE_IMP); 218 reg = core_readl(priv, CORE_STS_OVERRIDE_IMP);
200 reg |= (MII_SW_OR | LINK_STS); 219 reg |= (MII_SW_OR | LINK_STS);
201 core_writel(priv, reg, CORE_STS_OVERRIDE_IMP); 220 core_writel(priv, reg, CORE_STS_OVERRIDE_IMP);
202
203 /* Enable the IMP Port to be in the same VLAN as the other ports
204 * on a per-port basis such that we only have Port i and IMP in
205 * the same VLAN.
206 */
207 for (i = 0; i < priv->hw_params.num_ports; i++) {
208 if (!((1 << i) & ds->phys_port_mask))
209 continue;
210
211 reg = core_readl(priv, CORE_PORT_VLAN_CTL_PORT(i));
212 reg |= (1 << port);
213 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(i));
214 }
215} 221}
216 222
217static void bcm_sf2_port_setup(struct dsa_switch *ds, int port) 223static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
224 struct phy_device *phy)
218{ 225{
219 struct bcm_sf2_priv *priv = ds_to_priv(ds); 226 struct bcm_sf2_priv *priv = ds_to_priv(ds);
227 s8 cpu_port = ds->dst[ds->index].cpu_port;
220 u32 reg; 228 u32 reg;
221 229
222 /* Clear the memory power down */ 230 /* Clear the memory power down */
@@ -236,9 +244,14 @@ static void bcm_sf2_port_setup(struct dsa_switch *ds, int port)
236 reg &= ~PORT_VLAN_CTRL_MASK; 244 reg &= ~PORT_VLAN_CTRL_MASK;
237 reg |= (1 << port); 245 reg |= (1 << port);
238 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(port)); 246 core_writel(priv, reg, CORE_PORT_VLAN_CTL_PORT(port));
247
248 bcm_sf2_imp_vlan_setup(ds, cpu_port);
249
250 return 0;
239} 251}
240 252
241static void bcm_sf2_port_disable(struct dsa_switch *ds, int port) 253static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
254 struct phy_device *phy)
242{ 255{
243 struct bcm_sf2_priv *priv = ds_to_priv(ds); 256 struct bcm_sf2_priv *priv = ds_to_priv(ds);
244 u32 off, reg; 257 u32 off, reg;
@@ -246,6 +259,11 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port)
246 if (priv->wol_ports_mask & (1 << port)) 259 if (priv->wol_ports_mask & (1 << port))
247 return; 260 return;
248 261
262 if (port == 7) {
263 intrl2_1_mask_set(priv, P_IRQ_MASK(P7_IRQ_OFF));
264 intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR);
265 }
266
249 if (dsa_is_cpu_port(ds, port)) 267 if (dsa_is_cpu_port(ds, port))
250 off = CORE_IMP_CTL; 268 off = CORE_IMP_CTL;
251 else 269 else
@@ -363,11 +381,11 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
363 for (port = 0; port < priv->hw_params.num_ports; port++) { 381 for (port = 0; port < priv->hw_params.num_ports; port++) {
364 /* IMP port receives special treatment */ 382 /* IMP port receives special treatment */
365 if ((1 << port) & ds->phys_port_mask) 383 if ((1 << port) & ds->phys_port_mask)
366 bcm_sf2_port_setup(ds, port); 384 bcm_sf2_port_setup(ds, port, NULL);
367 else if (dsa_is_cpu_port(ds, port)) 385 else if (dsa_is_cpu_port(ds, port))
368 bcm_sf2_imp_setup(ds, port); 386 bcm_sf2_imp_setup(ds, port);
369 else 387 else
370 bcm_sf2_port_disable(ds, port); 388 bcm_sf2_port_disable(ds, port, NULL);
371 } 389 }
372 390
373 /* Include the pseudo-PHY address and the broadcast PHY address to 391 /* Include the pseudo-PHY address and the broadcast PHY address to
@@ -638,7 +656,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
638 for (port = 0; port < DSA_MAX_PORTS; port++) { 656 for (port = 0; port < DSA_MAX_PORTS; port++) {
639 if ((1 << port) & ds->phys_port_mask || 657 if ((1 << port) & ds->phys_port_mask ||
640 dsa_is_cpu_port(ds, port)) 658 dsa_is_cpu_port(ds, port))
641 bcm_sf2_port_disable(ds, port); 659 bcm_sf2_port_disable(ds, port, NULL);
642 } 660 }
643 661
644 return 0; 662 return 0;
@@ -694,7 +712,7 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
694 712
695 for (port = 0; port < DSA_MAX_PORTS; port++) { 713 for (port = 0; port < DSA_MAX_PORTS; port++) {
696 if ((1 << port) & ds->phys_port_mask) 714 if ((1 << port) & ds->phys_port_mask)
697 bcm_sf2_port_setup(ds, port); 715 bcm_sf2_port_setup(ds, port, NULL);
698 else if (dsa_is_cpu_port(ds, port)) 716 else if (dsa_is_cpu_port(ds, port))
699 bcm_sf2_imp_setup(ds, port); 717 bcm_sf2_imp_setup(ds, port);
700 } 718 }
@@ -772,6 +790,8 @@ static struct dsa_switch_driver bcm_sf2_switch_driver = {
772 .resume = bcm_sf2_sw_resume, 790 .resume = bcm_sf2_sw_resume,
773 .get_wol = bcm_sf2_sw_get_wol, 791 .get_wol = bcm_sf2_sw_get_wol,
774 .set_wol = bcm_sf2_sw_set_wol, 792 .set_wol = bcm_sf2_sw_set_wol,
793 .port_enable = bcm_sf2_port_setup,
794 .port_disable = bcm_sf2_port_disable,
775}; 795};
776 796
777static int __init bcm_sf2_init(void) 797static int __init bcm_sf2_init(void)