b44: use fixed PHY device if we do not find any
authorHauke Mehrtens <hauke@hauke-m.de>
Fri, 20 Dec 2013 01:16:13 +0000 (02:16 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 21 Dec 2013 01:48:49 +0000 (20:48 -0500)
The ADM6996L switch and some Broadcom switches with two MII interfaces
like the BCM5325F connected to two MACs on the SoC, used on some
routers do not return a valid value when reading the PHY id register
and Linux thinks there is no PHY at all, but that is wrong.
This patch registers a fixed phy in the arch code and then searches it
when there is no other phy in the Ethernet driver code.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/mips/bcm47xx/setup.c
drivers/net/ethernet/broadcom/b44.c
drivers/net/ethernet/broadcom/b44.h

index 1f30571968e78194ad6338b4f0ac3cb3b64332bc..9057728ac56b4cfa2130b122f2130df966ca7275 100644 (file)
@@ -28,6 +28,9 @@
 
 #include <linux/export.h>
 #include <linux/types.h>
+#include <linux/ethtool.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
 #include <linux/ssb/ssb.h>
 #include <linux/ssb/ssb_embedded.h>
 #include <linux/bcma/bcma_soc.h>
@@ -225,6 +228,12 @@ void __init plat_mem_setup(void)
        bcm47xx_board_detect();
 }
 
+static struct fixed_phy_status bcm47xx_fixed_phy_status __initdata = {
+       .link   = 1,
+       .speed  = SPEED_100,
+       .duplex = DUPLEX_FULL,
+};
+
 static int __init bcm47xx_register_bus_complete(void)
 {
        switch (bcm47xx_bus_type) {
@@ -239,6 +248,7 @@ static int __init bcm47xx_register_bus_complete(void)
                break;
 #endif
        }
+       fixed_phy_add(PHY_POLL, 0, &bcm47xx_fixed_phy_status);
        return 0;
 }
 device_initcall(bcm47xx_register_bus_complete);
index 839dd9092b17068931a0a5f0495b831c28e36b4f..1f7b5aa114fae3ee3adf589af58e5def31fc84d7 100644 (file)
@@ -2233,6 +2233,7 @@ static int b44_register_phy_one(struct b44 *bp)
        struct ssb_device *sdev = bp->sdev;
        struct phy_device *phydev;
        char bus_id[MII_BUS_ID_SIZE + 3];
+       struct ssb_sprom *sprom = &sdev->bus->sprom;
        int err;
 
        mii_bus = mdiobus_alloc();
@@ -2266,7 +2267,20 @@ static int b44_register_phy_one(struct b44 *bp)
                goto err_out_mdiobus_irq;
        }
 
-       snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id, bp->phy_addr);
+       if (!bp->mii_bus->phy_map[bp->phy_addr] &&
+           (sprom->boardflags_lo & (B44_BOARDFLAG_ROBO | B44_BOARDFLAG_ADM))) {
+
+               dev_info(sdev->dev,
+                        "could not find PHY at %i, use fixed one\n",
+                        bp->phy_addr);
+
+               bp->phy_addr = 0;
+               snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, "fixed-0",
+                        bp->phy_addr);
+       } else {
+               snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
+                        bp->phy_addr);
+       }
 
        phydev = phy_connect(bp->dev, bus_id, &b44_adjust_link,
                             PHY_INTERFACE_MODE_MII);
index de81639d9236b774d619fa5b725f2c1cce257aef..3e9c3fc7591b2f05b71e5943e56a089ed7ce4e62 100644 (file)
@@ -345,6 +345,9 @@ B44_STAT_REG_DECLARE
        struct u64_stats_sync   syncp;
 };
 
+#define        B44_BOARDFLAG_ROBO              0x0010  /* Board has robo switch */
+#define        B44_BOARDFLAG_ADM               0x0080  /* Board has ADMtek switch */
+
 struct ssb_device;
 
 struct b44 {