diff options
Diffstat (limited to 'drivers/net/dsa/bcm_sf2.c')
-rw-r--r-- | drivers/net/dsa/bcm_sf2.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index cedb572bf25a..079897b3a955 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <net/dsa.h> | 24 | #include <net/dsa.h> |
25 | #include <linux/ethtool.h> | 25 | #include <linux/ethtool.h> |
26 | #include <linux/if_bridge.h> | 26 | #include <linux/if_bridge.h> |
27 | #include <linux/brcmphy.h> | ||
27 | 28 | ||
28 | #include "bcm_sf2.h" | 29 | #include "bcm_sf2.h" |
29 | #include "bcm_sf2_regs.h" | 30 | #include "bcm_sf2_regs.h" |
@@ -695,9 +696,20 @@ static int bcm_sf2_sw_setup(struct dsa_switch *ds) | |||
695 | } | 696 | } |
696 | 697 | ||
697 | /* Include the pseudo-PHY address and the broadcast PHY address to | 698 | /* Include the pseudo-PHY address and the broadcast PHY address to |
698 | * divert reads towards our workaround | 699 | * divert reads towards our workaround. This is only required for |
700 | * 7445D0, since 7445E0 disconnects the internal switch pseudo-PHY such | ||
701 | * that we can use the regular SWITCH_MDIO master controller instead. | ||
702 | * | ||
703 | * By default, DSA initializes ds->phys_mii_mask to ds->phys_port_mask | ||
704 | * to have a 1:1 mapping between Port address and PHY address in order | ||
705 | * to utilize the slave_mii_bus instance to read from Port PHYs. This is | ||
706 | * not what we want here, so we initialize phys_mii_mask 0 to always | ||
707 | * utilize the "master" MDIO bus backed by the "mdio-unimac" driver. | ||
699 | */ | 708 | */ |
700 | ds->phys_mii_mask |= ((1 << 30) | (1 << 0)); | 709 | if (of_machine_is_compatible("brcm,bcm7445d0")) |
710 | ds->phys_mii_mask |= ((1 << BRCM_PSEUDO_PHY_ADDR) | (1 << 0)); | ||
711 | else | ||
712 | ds->phys_mii_mask = 0; | ||
701 | 713 | ||
702 | rev = reg_readl(priv, REG_SWITCH_REVISION); | 714 | rev = reg_readl(priv, REG_SWITCH_REVISION); |
703 | priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & | 715 | priv->hw_params.top_rev = (rev >> SWITCH_TOP_REV_SHIFT) & |
@@ -782,7 +794,7 @@ static int bcm_sf2_sw_phy_read(struct dsa_switch *ds, int addr, int regnum) | |||
782 | */ | 794 | */ |
783 | switch (addr) { | 795 | switch (addr) { |
784 | case 0: | 796 | case 0: |
785 | case 30: | 797 | case BRCM_PSEUDO_PHY_ADDR: |
786 | return bcm_sf2_sw_indir_rw(ds, 1, addr, regnum, 0); | 798 | return bcm_sf2_sw_indir_rw(ds, 1, addr, regnum, 0); |
787 | default: | 799 | default: |
788 | return 0xffff; | 800 | return 0xffff; |
@@ -797,7 +809,7 @@ static int bcm_sf2_sw_phy_write(struct dsa_switch *ds, int addr, int regnum, | |||
797 | */ | 809 | */ |
798 | switch (addr) { | 810 | switch (addr) { |
799 | case 0: | 811 | case 0: |
800 | case 30: | 812 | case BRCM_PSEUDO_PHY_ADDR: |
801 | bcm_sf2_sw_indir_rw(ds, 0, addr, regnum, val); | 813 | bcm_sf2_sw_indir_rw(ds, 0, addr, regnum, val); |
802 | break; | 814 | break; |
803 | } | 815 | } |
@@ -911,6 +923,13 @@ static void bcm_sf2_sw_fixed_link_update(struct dsa_switch *ds, int port, | |||
911 | */ | 923 | */ |
912 | if (port == 7) { | 924 | if (port == 7) { |
913 | status->link = priv->port_sts[port].link; | 925 | status->link = priv->port_sts[port].link; |
926 | /* For MoCA interfaces, also force a link down notification | ||
927 | * since some version of the user-space daemon (mocad) use | ||
928 | * cmd->autoneg to force the link, which messes up the PHY | ||
929 | * state machine and make it go in PHY_FORCING state instead. | ||
930 | */ | ||
931 | if (!status->link) | ||
932 | netif_carrier_off(ds->ports[port]); | ||
914 | status->duplex = 1; | 933 | status->duplex = 1; |
915 | } else { | 934 | } else { |
916 | status->link = 1; | 935 | status->link = 1; |