aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/dsa/bcm_sf2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/dsa/bcm_sf2.c')
-rw-r--r--drivers/net/dsa/bcm_sf2.c191
1 files changed, 120 insertions, 71 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 97236cfcbae4..ac621f44237a 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -16,6 +16,7 @@
16#include <linux/platform_device.h> 16#include <linux/platform_device.h>
17#include <linux/phy.h> 17#include <linux/phy.h>
18#include <linux/phy_fixed.h> 18#include <linux/phy_fixed.h>
19#include <linux/phylink.h>
19#include <linux/mii.h> 20#include <linux/mii.h>
20#include <linux/of.h> 21#include <linux/of.h>
21#include <linux/of_irq.h> 22#include <linux/of_irq.h>
@@ -306,7 +307,8 @@ static int bcm_sf2_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
306 307
307static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id) 308static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
308{ 309{
309 struct bcm_sf2_priv *priv = dev_id; 310 struct dsa_switch *ds = dev_id;
311 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
310 312
311 priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) & 313 priv->irq0_stat = intrl2_0_readl(priv, INTRL2_CPU_STATUS) &
312 ~priv->irq0_mask; 314 ~priv->irq0_mask;
@@ -317,16 +319,21 @@ static irqreturn_t bcm_sf2_switch_0_isr(int irq, void *dev_id)
317 319
318static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id) 320static irqreturn_t bcm_sf2_switch_1_isr(int irq, void *dev_id)
319{ 321{
320 struct bcm_sf2_priv *priv = dev_id; 322 struct dsa_switch *ds = dev_id;
323 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
321 324
322 priv->irq1_stat = intrl2_1_readl(priv, INTRL2_CPU_STATUS) & 325 priv->irq1_stat = intrl2_1_readl(priv, INTRL2_CPU_STATUS) &
323 ~priv->irq1_mask; 326 ~priv->irq1_mask;
324 intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR); 327 intrl2_1_writel(priv, priv->irq1_stat, INTRL2_CPU_CLEAR);
325 328
326 if (priv->irq1_stat & P_LINK_UP_IRQ(P7_IRQ_OFF)) 329 if (priv->irq1_stat & P_LINK_UP_IRQ(P7_IRQ_OFF)) {
327 priv->port_sts[7].link = 1; 330 priv->port_sts[7].link = true;
328 if (priv->irq1_stat & P_LINK_DOWN_IRQ(P7_IRQ_OFF)) 331 dsa_port_phylink_mac_change(ds, 7, true);
329 priv->port_sts[7].link = 0; 332 }
333 if (priv->irq1_stat & P_LINK_DOWN_IRQ(P7_IRQ_OFF)) {
334 priv->port_sts[7].link = false;
335 dsa_port_phylink_mac_change(ds, 7, false);
336 }
330 337
331 return IRQ_HANDLED; 338 return IRQ_HANDLED;
332} 339}
@@ -473,13 +480,56 @@ static u32 bcm_sf2_sw_get_phy_flags(struct dsa_switch *ds, int port)
473 return priv->hw_params.gphy_rev; 480 return priv->hw_params.gphy_rev;
474} 481}
475 482
476static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port, 483static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port,
477 struct phy_device *phydev) 484 unsigned long *supported,
485 struct phylink_link_state *state)
486{
487 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
488
489 if (!phy_interface_mode_is_rgmii(state->interface) &&
490 state->interface != PHY_INTERFACE_MODE_MII &&
491 state->interface != PHY_INTERFACE_MODE_REVMII &&
492 state->interface != PHY_INTERFACE_MODE_GMII &&
493 state->interface != PHY_INTERFACE_MODE_INTERNAL &&
494 state->interface != PHY_INTERFACE_MODE_MOCA) {
495 bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
496 dev_err(ds->dev,
497 "Unsupported interface: %d\n", state->interface);
498 return;
499 }
500
501 /* Allow all the expected bits */
502 phylink_set(mask, Autoneg);
503 phylink_set_port_modes(mask);
504 phylink_set(mask, Pause);
505 phylink_set(mask, Asym_Pause);
506
507 /* With the exclusion of MII and Reverse MII, we support Gigabit,
508 * including Half duplex
509 */
510 if (state->interface != PHY_INTERFACE_MODE_MII &&
511 state->interface != PHY_INTERFACE_MODE_REVMII) {
512 phylink_set(mask, 1000baseT_Full);
513 phylink_set(mask, 1000baseT_Half);
514 }
515
516 phylink_set(mask, 10baseT_Half);
517 phylink_set(mask, 10baseT_Full);
518 phylink_set(mask, 100baseT_Half);
519 phylink_set(mask, 100baseT_Full);
520
521 bitmap_and(supported, supported, mask,
522 __ETHTOOL_LINK_MODE_MASK_NBITS);
523 bitmap_and(state->advertising, state->advertising, mask,
524 __ETHTOOL_LINK_MODE_MASK_NBITS);
525}
526
527static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port,
528 unsigned int mode,
529 const struct phylink_link_state *state)
478{ 530{
479 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 531 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
480 struct ethtool_eee *p = &priv->dev->ports[port].eee;
481 u32 id_mode_dis = 0, port_mode; 532 u32 id_mode_dis = 0, port_mode;
482 const char *str = NULL;
483 u32 reg, offset; 533 u32 reg, offset;
484 534
485 if (priv->type == BCM7445_DEVICE_ID) 535 if (priv->type == BCM7445_DEVICE_ID)
@@ -487,62 +537,48 @@ static void bcm_sf2_sw_adjust_link(struct dsa_switch *ds, int port,
487 else 537 else
488 offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port); 538 offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port);
489 539
490 switch (phydev->interface) { 540 switch (state->interface) {
491 case PHY_INTERFACE_MODE_RGMII: 541 case PHY_INTERFACE_MODE_RGMII:
492 str = "RGMII (no delay)";
493 id_mode_dis = 1; 542 id_mode_dis = 1;
543 /* fallthrough */
494 case PHY_INTERFACE_MODE_RGMII_TXID: 544 case PHY_INTERFACE_MODE_RGMII_TXID:
495 if (!str)
496 str = "RGMII (TX delay)";
497 port_mode = EXT_GPHY; 545 port_mode = EXT_GPHY;
498 break; 546 break;
499 case PHY_INTERFACE_MODE_MII: 547 case PHY_INTERFACE_MODE_MII:
500 str = "MII";
501 port_mode = EXT_EPHY; 548 port_mode = EXT_EPHY;
502 break; 549 break;
503 case PHY_INTERFACE_MODE_REVMII: 550 case PHY_INTERFACE_MODE_REVMII:
504 str = "Reverse MII";
505 port_mode = EXT_REVMII; 551 port_mode = EXT_REVMII;
506 break; 552 break;
507 default: 553 default:
508 /* All other PHYs: internal and MoCA */ 554 /* all other PHYs: internal and MoCA */
509 goto force_link;
510 }
511
512 /* If the link is down, just disable the interface to conserve power */
513 if (!phydev->link) {
514 reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
515 reg &= ~RGMII_MODE_EN;
516 reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
517 goto force_link; 555 goto force_link;
518 } 556 }
519 557
520 /* Clear id_mode_dis bit, and the existing port mode, but 558 /* Clear id_mode_dis bit, and the existing port mode, let
521 * make sure we enable the RGMII block for data to pass 559 * RGMII_MODE_EN bet set by mac_link_{up,down}
522 */ 560 */
523 reg = reg_readl(priv, REG_RGMII_CNTRL_P(port)); 561 reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
524 reg &= ~ID_MODE_DIS; 562 reg &= ~ID_MODE_DIS;
525 reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT); 563 reg &= ~(PORT_MODE_MASK << PORT_MODE_SHIFT);
526 reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN); 564 reg &= ~(RX_PAUSE_EN | TX_PAUSE_EN);
527 565
528 reg |= port_mode | RGMII_MODE_EN; 566 reg |= port_mode;
529 if (id_mode_dis) 567 if (id_mode_dis)
530 reg |= ID_MODE_DIS; 568 reg |= ID_MODE_DIS;
531 569
532 if (phydev->pause) { 570 if (state->pause & MLO_PAUSE_TXRX_MASK) {
533 if (phydev->asym_pause) 571 if (state->pause & MLO_PAUSE_TX)
534 reg |= TX_PAUSE_EN; 572 reg |= TX_PAUSE_EN;
535 reg |= RX_PAUSE_EN; 573 reg |= RX_PAUSE_EN;
536 } 574 }
537 575
538 reg_writel(priv, reg, REG_RGMII_CNTRL_P(port)); 576 reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
539 577
540 pr_info("Port %d configured for %s\n", port, str);
541
542force_link: 578force_link:
543 /* Force link settings detected from the PHY */ 579 /* Force link settings detected from the PHY */
544 reg = SW_OVERRIDE; 580 reg = SW_OVERRIDE;
545 switch (phydev->speed) { 581 switch (state->speed) {
546 case SPEED_1000: 582 case SPEED_1000:
547 reg |= SPDSTS_1000 << SPEED_SHIFT; 583 reg |= SPDSTS_1000 << SPEED_SHIFT;
548 break; 584 break;
@@ -551,33 +587,61 @@ force_link:
551 break; 587 break;
552 } 588 }
553 589
554 if (phydev->link) 590 if (state->link)
555 reg |= LINK_STS; 591 reg |= LINK_STS;
556 if (phydev->duplex == DUPLEX_FULL) 592 if (state->duplex == DUPLEX_FULL)
557 reg |= DUPLX_MODE; 593 reg |= DUPLX_MODE;
558 594
559 core_writel(priv, reg, offset); 595 core_writel(priv, reg, offset);
560
561 if (!phydev->is_pseudo_fixed_link)
562 p->eee_enabled = b53_eee_init(ds, port, phydev);
563} 596}
564 597
565static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, 598static void bcm_sf2_sw_mac_link_set(struct dsa_switch *ds, int port,
566 struct fixed_phy_status *status) 599 phy_interface_t interface, bool link)
567{ 600{
568 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); 601 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
569 u32 duplex, pause, offset;
570 u32 reg; 602 u32 reg;
571 603
572 if (priv->type == BCM7445_DEVICE_ID) 604 if (!phy_interface_mode_is_rgmii(interface) &&
573 offset = CORE_STS_OVERRIDE_GMIIP_PORT(port); 605 interface != PHY_INTERFACE_MODE_MII &&
606 interface != PHY_INTERFACE_MODE_REVMII)
607 return;
608
609 /* If the link is down, just disable the interface to conserve power */
610 reg = reg_readl(priv, REG_RGMII_CNTRL_P(port));
611 if (link)
612 reg |= RGMII_MODE_EN;
574 else 613 else
575 offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port); 614 reg &= ~RGMII_MODE_EN;
615 reg_writel(priv, reg, REG_RGMII_CNTRL_P(port));
616}
617
618static void bcm_sf2_sw_mac_link_down(struct dsa_switch *ds, int port,
619 unsigned int mode,
620 phy_interface_t interface)
621{
622 bcm_sf2_sw_mac_link_set(ds, port, interface, false);
623}
624
625static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port,
626 unsigned int mode,
627 phy_interface_t interface,
628 struct phy_device *phydev)
629{
630 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
631 struct ethtool_eee *p = &priv->dev->ports[port].eee;
576 632
577 duplex = core_readl(priv, CORE_DUPSTS); 633 bcm_sf2_sw_mac_link_set(ds, port, interface, true);
578 pause = core_readl(priv, CORE_PAUSESTS);
579 634
580 status->link = 0; 635 if (mode == MLO_AN_PHY && phydev)
636 p->eee_enabled = b53_eee_init(ds, port, phydev);
637}
638
639static void bcm_sf2_sw_fixed_state(struct dsa_switch *ds, int port,
640 struct phylink_link_state *status)
641{
642 struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
643
644 status->link = false;
581 645
582 /* MoCA port is special as we do not get link status from CORE_LNKSTS, 646 /* MoCA port is special as we do not get link status from CORE_LNKSTS,
583 * which means that we need to force the link at the port override 647 * which means that we need to force the link at the port override
@@ -596,28 +660,10 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port,
596 */ 660 */
597 if (!status->link) 661 if (!status->link)
598 netif_carrier_off(ds->ports[port].slave); 662 netif_carrier_off(ds->ports[port].slave);
599 status->duplex = 1; 663 status->duplex = DUPLEX_FULL;
600 } else { 664 } else {
601 status->link = 1; 665 status->link = true;
602 status->duplex = !!(duplex & (1 << port));
603 }
604
605 reg = core_readl(priv, offset);
606 reg |= SW_OVERRIDE;
607 if (status->link)
608 reg |= LINK_STS;
609 else
610 reg &= ~LINK_STS;
611 core_writel(priv, reg, offset);
612
613 if ((pause & (1 << port)) &&
614 (pause & (1 << (port + PAUSESTS_TX_PAUSE_SHIFT)))) {
615 status->asym_pause = 1;
616 status->pause = 1;
617 } 666 }
618
619 if (pause & (1 << port))
620 status->pause = 1;
621} 667}
622 668
623static void bcm_sf2_enable_acb(struct dsa_switch *ds) 669static void bcm_sf2_enable_acb(struct dsa_switch *ds)
@@ -861,8 +907,11 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
861 .get_sset_count = b53_get_sset_count, 907 .get_sset_count = b53_get_sset_count,
862 .get_ethtool_phy_stats = b53_get_ethtool_phy_stats, 908 .get_ethtool_phy_stats = b53_get_ethtool_phy_stats,
863 .get_phy_flags = bcm_sf2_sw_get_phy_flags, 909 .get_phy_flags = bcm_sf2_sw_get_phy_flags,
864 .adjust_link = bcm_sf2_sw_adjust_link, 910 .phylink_validate = bcm_sf2_sw_validate,
865 .fixed_link_update = bcm_sf2_sw_fixed_link_update, 911 .phylink_mac_config = bcm_sf2_sw_mac_config,
912 .phylink_mac_link_down = bcm_sf2_sw_mac_link_down,
913 .phylink_mac_link_up = bcm_sf2_sw_mac_link_up,
914 .phylink_fixed_state = bcm_sf2_sw_fixed_state,
866 .suspend = bcm_sf2_sw_suspend, 915 .suspend = bcm_sf2_sw_suspend,
867 .resume = bcm_sf2_sw_resume, 916 .resume = bcm_sf2_sw_resume,
868 .get_wol = bcm_sf2_sw_get_wol, 917 .get_wol = bcm_sf2_sw_get_wol,
@@ -1065,14 +1114,14 @@ static int bcm_sf2_sw_probe(struct platform_device *pdev)
1065 bcm_sf2_intr_disable(priv); 1114 bcm_sf2_intr_disable(priv);
1066 1115
1067 ret = devm_request_irq(&pdev->dev, priv->irq0, bcm_sf2_switch_0_isr, 0, 1116 ret = devm_request_irq(&pdev->dev, priv->irq0, bcm_sf2_switch_0_isr, 0,
1068 "switch_0", priv); 1117 "switch_0", ds);
1069 if (ret < 0) { 1118 if (ret < 0) {
1070 pr_err("failed to request switch_0 IRQ\n"); 1119 pr_err("failed to request switch_0 IRQ\n");
1071 goto out_mdio; 1120 goto out_mdio;
1072 } 1121 }
1073 1122
1074 ret = devm_request_irq(&pdev->dev, priv->irq1, bcm_sf2_switch_1_isr, 0, 1123 ret = devm_request_irq(&pdev->dev, priv->irq1, bcm_sf2_switch_1_isr, 0,
1075 "switch_1", priv); 1124 "switch_1", ds);
1076 if (ret < 0) { 1125 if (ret < 0) {
1077 pr_err("failed to request switch_1 IRQ\n"); 1126 pr_err("failed to request switch_1 IRQ\n");
1078 goto out_mdio; 1127 goto out_mdio;