diff options
author | Florian Fainelli <f.fainelli@gmail.com> | 2014-09-24 20:05:20 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-28 17:14:09 -0400 |
commit | b6d045db59210476323caef042c5b50884e4675f (patch) | |
tree | 81f8ea611a082f4a671382eed7b795c646e483e1 /drivers | |
parent | 7de1557ce7521e756974d5c28794c2375d28e3cc (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')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 60 |
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 | ||
138 | static void bcm_sf2_imp_setup(struct dsa_switch *ds, int port) | 138 | static 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 | |||
158 | static 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 | ||
217 | static void bcm_sf2_port_setup(struct dsa_switch *ds, int port) | 223 | static 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 | ||
241 | static void bcm_sf2_port_disable(struct dsa_switch *ds, int port) | 253 | static 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 | ||
777 | static int __init bcm_sf2_init(void) | 797 | static int __init bcm_sf2_init(void) |