aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r--drivers/net/dsa/bcm_sf2.c88
-rw-r--r--drivers/net/dsa/bcm_sf2_regs.h4
-rw-r--r--drivers/net/dsa/mv88e6131.c3
-rw-r--r--drivers/net/dsa/mv88e6352.c13
-rw-r--r--drivers/net/dsa/mv88e6xxx.c9
5 files changed, 84 insertions, 33 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index feb29c4526f7..4daffb284931 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -233,6 +233,35 @@ static void bcm_sf2_eee_enable_set(struct dsa_switch *ds, int port, bool enable)
233 core_writel(priv, reg, CORE_EEE_EN_CTRL); 233 core_writel(priv, reg, CORE_EEE_EN_CTRL);
234} 234}
235 235
236static void bcm_sf2_gphy_enable_set(struct dsa_switch *ds, bool enable)
237{
238 struct bcm_sf2_priv *priv = ds_to_priv(ds);
239 u32 reg;
240
241 reg = reg_readl(priv, REG_SPHY_CNTRL);
242 if (enable) {
243 reg |= PHY_RESET;
244 reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS | CK25_DIS);
245 reg_writel(priv, reg, REG_SPHY_CNTRL);
246 udelay(21);
247 reg = reg_readl(priv, REG_SPHY_CNTRL);
248 reg &= ~PHY_RESET;
249 } else {
250 reg |= EXT_PWR_DOWN | IDDQ_BIAS | PHY_RESET;
251 reg_writel(priv, reg, REG_SPHY_CNTRL);
252 mdelay(1);
253 reg |= CK25_DIS;
254 }
255 reg_writel(priv, reg, REG_SPHY_CNTRL);
256
257 /* Use PHY-driven LED signaling */
258 if (!enable) {
259 reg = reg_readl(priv, REG_LED_CNTRL(0));
260 reg |= SPDLNK_SRC_SEL;
261 reg_writel(priv, reg, REG_LED_CNTRL(0));
262 }
263}
264
236static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, 265static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
237 struct phy_device *phy) 266 struct phy_device *phy)
238{ 267{
@@ -248,6 +277,24 @@ static int bcm_sf2_port_setup(struct dsa_switch *ds, int port,
248 /* Clear the Rx and Tx disable bits and set to no spanning tree */ 277 /* Clear the Rx and Tx disable bits and set to no spanning tree */
249 core_writel(priv, 0, CORE_G_PCTL_PORT(port)); 278 core_writel(priv, 0, CORE_G_PCTL_PORT(port));
250 279
280 /* Re-enable the GPHY and re-apply workarounds */
281 if (port == 0 && priv->hw_params.num_gphy == 1) {
282 bcm_sf2_gphy_enable_set(ds, true);
283 if (phy) {
284 /* if phy_stop() has been called before, phy
285 * will be in halted state, and phy_start()
286 * will call resume.
287 *
288 * the resume path does not configure back
289 * autoneg settings, and since we hard reset
290 * the phy manually here, we need to reset the
291 * state machine also.
292 */
293 phy->state = PHY_READY;
294 phy_init_hw(phy);
295 }
296 }
297
251 /* Enable port 7 interrupts to get notified */ 298 /* Enable port 7 interrupts to get notified */
252 if (port == 7) 299 if (port == 7)
253 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF)); 300 intrl2_1_mask_clear(priv, P_IRQ_MASK(P7_IRQ_OFF));
@@ -281,6 +328,9 @@ static void bcm_sf2_port_disable(struct dsa_switch *ds, int port,
281 intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR); 328 intrl2_1_writel(priv, P_IRQ_MASK(P7_IRQ_OFF), INTRL2_CPU_CLEAR);
282 } 329 }
283 330
331 if (port == 0 && priv->hw_params.num_gphy == 1)
332 bcm_sf2_gphy_enable_set(ds, false);
333
284 if (dsa_is_cpu_port(ds, port)) 334 if (dsa_is_cpu_port(ds, port))
285 off = CORE_IMP_CTL; 335 off = CORE_IMP_CTL;
286 else 336 else
@@ -400,6 +450,16 @@ static int bcm_sf2_sw_rst(struct bcm_sf2_priv *priv)
400 return 0; 450 return 0;
401} 451}
402 452
453static void bcm_sf2_intr_disable(struct bcm_sf2_priv *priv)
454{
455 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
456 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
457 intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
458 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
459 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
460 intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
461}
462
403static int bcm_sf2_sw_setup(struct dsa_switch *ds) 463static int bcm_sf2_sw_setup(struct dsa_switch *ds)
404{ 464{
405 const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME; 465 const char *reg_names[BCM_SF2_REGS_NUM] = BCM_SF2_REGS_NAME;
@@ -440,12 +500,7 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds)
440 } 500 }
441 501
442 /* Disable all interrupts and request them */ 502 /* Disable all interrupts and request them */
443 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); 503 bcm_sf2_intr_disable(priv);
444 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
445 intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
446 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
447 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
448 intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
449 504
450 ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0, 505 ret = request_irq(priv->irq0, bcm_sf2_switch_0_isr, 0,
451 "switch_0", priv); 506 "switch_0", priv);
@@ -747,12 +802,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
747 struct bcm_sf2_priv *priv = ds_to_priv(ds); 802 struct bcm_sf2_priv *priv = ds_to_priv(ds);
748 unsigned int port; 803 unsigned int port;
749 804
750 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET); 805 bcm_sf2_intr_disable(priv);
751 intrl2_0_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
752 intrl2_0_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
753 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_MASK_SET);
754 intrl2_1_writel(priv, 0xffffffff, INTRL2_CPU_CLEAR);
755 intrl2_1_writel(priv, 0, INTRL2_CPU_MASK_CLEAR);
756 806
757 /* Disable all ports physically present including the IMP 807 /* Disable all ports physically present including the IMP
758 * port, the other ones have already been disabled during 808 * port, the other ones have already been disabled during
@@ -771,7 +821,6 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
771{ 821{
772 struct bcm_sf2_priv *priv = ds_to_priv(ds); 822 struct bcm_sf2_priv *priv = ds_to_priv(ds);
773 unsigned int port; 823 unsigned int port;
774 u32 reg;
775 int ret; 824 int ret;
776 825
777 ret = bcm_sf2_sw_rst(priv); 826 ret = bcm_sf2_sw_rst(priv);
@@ -780,17 +829,8 @@ static int bcm_sf2_sw_resume(struct dsa_switch *ds)
780 return ret; 829 return ret;
781 } 830 }
782 831
783 /* Reinitialize the single GPHY */ 832 if (priv->hw_params.num_gphy == 1)
784 if (priv->hw_params.num_gphy == 1) { 833 bcm_sf2_gphy_enable_set(ds, true);
785 reg = reg_readl(priv, REG_SPHY_CNTRL);
786 reg |= PHY_RESET;
787 reg &= ~(EXT_PWR_DOWN | IDDQ_BIAS);
788 reg_writel(priv, reg, REG_SPHY_CNTRL);
789 udelay(21);
790 reg = reg_readl(priv, REG_SPHY_CNTRL);
791 reg &= ~PHY_RESET;
792 reg_writel(priv, reg, REG_SPHY_CNTRL);
793 }
794 834
795 for (port = 0; port < DSA_MAX_PORTS; port++) { 835 for (port = 0; port < DSA_MAX_PORTS; port++) {
796 if ((1 << port) & ds->phys_port_mask) 836 if ((1 << port) & ds->phys_port_mask)
diff --git a/drivers/net/dsa/bcm_sf2_regs.h b/drivers/net/dsa/bcm_sf2_regs.h
index 1bb49cb699ab..cabdfa5e217a 100644
--- a/drivers/net/dsa/bcm_sf2_regs.h
+++ b/drivers/net/dsa/bcm_sf2_regs.h
@@ -61,6 +61,10 @@
61#define LPI_COUNT_SHIFT 9 61#define LPI_COUNT_SHIFT 9
62#define LPI_COUNT_MASK 0x3F 62#define LPI_COUNT_MASK 0x3F
63 63
64#define REG_LED_CNTRL_BASE 0x90
65#define REG_LED_CNTRL(x) (REG_LED_CNTRL_BASE + (x) * 4)
66#define SPDLNK_SRC_SEL (1 << 24)
67
64/* Register set relative to 'INTRL2_0' and 'INTRL2_1' */ 68/* Register set relative to 'INTRL2_0' and 'INTRL2_1' */
65#define INTRL2_CPU_STATUS 0x00 69#define INTRL2_CPU_STATUS 0x00
66#define INTRL2_CPU_SET 0x04 70#define INTRL2_CPU_SET 0x04
diff --git a/drivers/net/dsa/mv88e6131.c b/drivers/net/dsa/mv88e6131.c
index 1230f52aa70e..2540ef0142af 100644
--- a/drivers/net/dsa/mv88e6131.c
+++ b/drivers/net/dsa/mv88e6131.c
@@ -139,7 +139,8 @@ static int mv88e6131_setup_global(struct dsa_switch *ds)
139 int nexthop; 139 int nexthop;
140 140
141 nexthop = 0x1f; 141 nexthop = 0x1f;
142 if (i != ds->index && i < ds->dst->pd->nr_chips) 142 if (ds->pd->rtable &&
143 i != ds->index && i < ds->dst->pd->nr_chips)
143 nexthop = ds->pd->rtable[i] & 0x1f; 144 nexthop = ds->pd->rtable[i] & 0x1f;
144 145
145 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop); 146 REG_WRITE(REG_GLOBAL2, 0x06, 0x8000 | (i << 8) | nexthop);
diff --git a/drivers/net/dsa/mv88e6352.c b/drivers/net/dsa/mv88e6352.c
index 258d9ef5ef25..e13adc7b3dda 100644
--- a/drivers/net/dsa/mv88e6352.c
+++ b/drivers/net/dsa/mv88e6352.c
@@ -22,17 +22,14 @@
22#include <net/dsa.h> 22#include <net/dsa.h>
23#include "mv88e6xxx.h" 23#include "mv88e6xxx.h"
24 24
25static int mv88e6352_wait(struct dsa_switch *ds, int reg, u16 mask) 25static int mv88e6352_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
26{ 26{
27 unsigned long timeout = jiffies + HZ / 10; 27 unsigned long timeout = jiffies + HZ / 10;
28 28
29 while (time_before(jiffies, timeout)) { 29 while (time_before(jiffies, timeout)) {
30 int ret; 30 int ret;
31 31
32 ret = REG_READ(REG_GLOBAL2, reg); 32 ret = REG_READ(reg, offset);
33 if (ret < 0)
34 return ret;
35
36 if (!(ret & mask)) 33 if (!(ret & mask))
37 return 0; 34 return 0;
38 35
@@ -43,17 +40,17 @@ static int mv88e6352_wait(struct dsa_switch *ds, int reg, u16 mask)
43 40
44static inline int mv88e6352_phy_wait(struct dsa_switch *ds) 41static inline int mv88e6352_phy_wait(struct dsa_switch *ds)
45{ 42{
46 return mv88e6352_wait(ds, 0x18, 0x8000); 43 return mv88e6352_wait(ds, REG_GLOBAL2, 0x18, 0x8000);
47} 44}
48 45
49static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds) 46static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds)
50{ 47{
51 return mv88e6352_wait(ds, 0x14, 0x0800); 48 return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x0800);
52} 49}
53 50
54static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds) 51static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds)
55{ 52{
56 return mv88e6352_wait(ds, 0x14, 0x8000); 53 return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
57} 54}
58 55
59static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum) 56static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum)
diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c
index cd6807c6b4ed..3e7e31a6abb7 100644
--- a/drivers/net/dsa/mv88e6xxx.c
+++ b/drivers/net/dsa/mv88e6xxx.c
@@ -85,6 +85,12 @@ int mv88e6xxx_reg_read(struct dsa_switch *ds, int addr, int reg)
85 ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg); 85 ret = __mv88e6xxx_reg_read(bus, ds->pd->sw_addr, addr, reg);
86 mutex_unlock(&ps->smi_mutex); 86 mutex_unlock(&ps->smi_mutex);
87 87
88 if (ret < 0)
89 return ret;
90
91 dev_dbg(ds->master_dev, "<- addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
92 addr, reg, ret);
93
88 return ret; 94 return ret;
89} 95}
90 96
@@ -128,6 +134,9 @@ int mv88e6xxx_reg_write(struct dsa_switch *ds, int addr, int reg, u16 val)
128 if (bus == NULL) 134 if (bus == NULL)
129 return -EINVAL; 135 return -EINVAL;
130 136
137 dev_dbg(ds->master_dev, "-> addr: 0x%.2x reg: 0x%.2x val: 0x%.4x\n",
138 addr, reg, val);
139
131 mutex_lock(&ps->smi_mutex); 140 mutex_lock(&ps->smi_mutex);
132 ret = __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val); 141 ret = __mv88e6xxx_reg_write(bus, ds->pd->sw_addr, addr, reg, val);
133 mutex_unlock(&ps->smi_mutex); 142 mutex_unlock(&ps->smi_mutex);