diff options
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 88 | ||||
-rw-r--r-- | drivers/net/dsa/bcm_sf2_regs.h | 4 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6131.c | 3 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6352.c | 13 | ||||
-rw-r--r-- | drivers/net/dsa/mv88e6xxx.c | 9 |
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 | ||
236 | static 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 | |||
236 | static int bcm_sf2_port_setup(struct dsa_switch *ds, int port, | 265 | static 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 | ||
453 | static 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 | |||
403 | static int bcm_sf2_sw_setup(struct dsa_switch *ds) | 463 | static 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 | ||
25 | static int mv88e6352_wait(struct dsa_switch *ds, int reg, u16 mask) | 25 | static 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 | ||
44 | static inline int mv88e6352_phy_wait(struct dsa_switch *ds) | 41 | static 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 | ||
49 | static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds) | 46 | static 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 | ||
54 | static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds) | 51 | static 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 | ||
59 | static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum) | 56 | static 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); |