brcm47xx: b44: detect external phy by bit set in DevControl register

Without this patch we treated only phy addr 30 as an external phy, but
there is a register to check that. Now we do not have to try to reset
the switch to check for an external switch.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>

SVN-Revision: 38502
This commit is contained in:
Hauke Mehrtens 2013-10-22 21:01:35 +00:00
parent 5d4cc68b66
commit 6d2136c3f2
8 changed files with 147 additions and 73 deletions

View file

@ -0,0 +1,97 @@
From 3fc36ba561bd9a9bdc097d6ace32f1303364268c Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Tue, 22 Oct 2013 21:05:25 +0200
Subject: [PATCH 2/9] b44: use B44_FLAG_EXTERNAL_PHY
---
drivers/net/ethernet/broadcom/b44.c | 18 +++++++++---------
drivers/net/ethernet/broadcom/b44.h | 2 +-
2 files changed, 10 insertions(+), 10 deletions(-)
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -284,7 +284,7 @@ static int __b44_writephy(struct b44 *bp
static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
{
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0;
return __b44_readphy(bp, bp->phy_addr, reg, val);
@@ -292,7 +292,7 @@ static inline int b44_readphy(struct b44
static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
{
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0;
return __b44_writephy(bp, bp->phy_addr, reg, val);
@@ -321,7 +321,7 @@ static int b44_phy_reset(struct b44 *bp)
u32 val;
int err;
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0;
err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
if (err)
@@ -423,7 +423,7 @@ static int b44_setup_phy(struct b44 *bp)
b44_wap54g10_workaround(bp);
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0;
if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
goto out;
@@ -521,7 +521,7 @@ static void b44_check_phy(struct b44 *bp
{
u32 bmsr, aux;
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
+ if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
bp->flags |= B44_FLAG_100_BASE_T;
bp->flags |= B44_FLAG_FULL_DUPLEX;
if (!netif_carrier_ok(bp->dev)) {
@@ -1315,7 +1315,7 @@ static void b44_chip_reset(struct b44 *b
if (!(br32(bp, B44_DEVCTRL) & DEVCTRL_IPP)) {
bw32(bp, B44_ENET_CTRL, ENET_CTRL_EPSEL);
br32(bp, B44_ENET_CTRL);
- bp->flags &= ~B44_FLAG_INTERNAL_PHY;
+ bp->flags |= B44_FLAG_EXTERNAL_PHY;
} else {
u32 val = br32(bp, B44_DEVCTRL);
@@ -1324,7 +1324,7 @@ static void b44_chip_reset(struct b44 *b
br32(bp, B44_DEVCTRL);
udelay(100);
}
- bp->flags |= B44_FLAG_INTERNAL_PHY;
+ bp->flags &= ~B44_FLAG_EXTERNAL_PHY;
}
}
@@ -1828,8 +1828,8 @@ static int b44_get_settings(struct net_d
DUPLEX_FULL : DUPLEX_HALF;
cmd->port = 0;
cmd->phy_address = bp->phy_addr;
- cmd->transceiver = (bp->flags & B44_FLAG_INTERNAL_PHY) ?
- XCVR_INTERNAL : XCVR_EXTERNAL;
+ cmd->transceiver = (bp->flags & B44_FLAG_EXTERNAL_PHY) ?
+ XCVR_EXTERNAL : XCVR_INTERNAL;
cmd->autoneg = (bp->flags & B44_FLAG_FORCE_LINK) ?
AUTONEG_DISABLE : AUTONEG_ENABLE;
if (cmd->autoneg == AUTONEG_ENABLE)
--- a/drivers/net/ethernet/broadcom/b44.h
+++ b/drivers/net/ethernet/broadcom/b44.h
@@ -376,7 +376,7 @@ struct b44 {
#define B44_FLAG_ADV_10FULL 0x02000000
#define B44_FLAG_ADV_100HALF 0x04000000
#define B44_FLAG_ADV_100FULL 0x08000000
-#define B44_FLAG_INTERNAL_PHY 0x10000000
+#define B44_FLAG_EXTERNAL_PHY 0x10000000
#define B44_FLAG_RX_RING_HACK 0x20000000
#define B44_FLAG_TX_RING_HACK 0x40000000
#define B44_FLAG_WOL_ENABLE 0x80000000

View file

@ -1,7 +1,7 @@
From 991b6722fb727b6e2a98e7e8b57176ac68626110 Mon Sep 17 00:00:00 2001 From 888594b4a1f70d02b7f6b05e868b00514b5cf559 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 3 Oct 2013 20:41:29 +0200 Date: Thu, 3 Oct 2013 20:41:29 +0200
Subject: [PATCH 2/5] b44: rename B44_PHY_ADDR_NO_PHY to Subject: [PATCH 3/9] b44: rename B44_PHY_ADDR_NO_PHY to
B44_PHY_ADDR_NO_LOCAL_PHY B44_PHY_ADDR_NO_LOCAL_PHY
The PHY address 30 means there is no local PHY, but there could be an The PHY address 30 means there is no local PHY, but there could be an
@ -10,57 +10,12 @@ embedded home routers where this driver is used.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/net/ethernet/broadcom/b44.c | 12 ++++++------ drivers/net/ethernet/broadcom/b44.c | 2 +-
drivers/net/ethernet/broadcom/b44.h | 6 +++--- drivers/net/ethernet/broadcom/b44.h | 6 +++---
2 files changed, 9 insertions(+), 9 deletions(-) 2 files changed, 4 insertions(+), 4 deletions(-)
--- a/drivers/net/ethernet/broadcom/b44.c --- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c
@@ -284,7 +284,7 @@ static int __b44_writephy(struct b44 *bp
static inline int b44_readphy(struct b44 *bp, int reg, u32 *val)
{
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY)
return 0;
return __b44_readphy(bp, bp->phy_addr, reg, val);
@@ -292,7 +292,7 @@ static inline int b44_readphy(struct b44
static inline int b44_writephy(struct b44 *bp, int reg, u32 val)
{
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY)
return 0;
return __b44_writephy(bp, bp->phy_addr, reg, val);
@@ -321,7 +321,7 @@ static int b44_phy_reset(struct b44 *bp)
u32 val;
int err;
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY)
return 0;
err = b44_writephy(bp, MII_BMCR, BMCR_RESET);
if (err)
@@ -423,7 +423,7 @@ static int b44_setup_phy(struct b44 *bp)
b44_wap54g10_workaround(bp);
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY)
+ if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY)
return 0;
if ((err = b44_readphy(bp, B44_MII_ALEDCTRL, &val)) != 0)
goto out;
@@ -521,7 +521,7 @@ static void b44_check_phy(struct b44 *bp
{
u32 bmsr, aux;
- if (bp->phy_addr == B44_PHY_ADDR_NO_PHY) {
+ if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY) {
bp->flags |= B44_FLAG_100_BASE_T;
bp->flags |= B44_FLAG_FULL_DUPLEX;
if (!netif_carrier_ok(bp->dev)) {
@@ -2238,7 +2238,7 @@ static int b44_init_one(struct ssb_devic @@ -2238,7 +2238,7 @@ static int b44_init_one(struct ssb_devic
/* do a phy reset to test if there is an active phy */ /* do a phy reset to test if there is an active phy */

View file

@ -1,7 +1,7 @@
From 1bfdc259652abe22a587fd6d856c1b71168cccb2 Mon Sep 17 00:00:00 2001 From d6668993d793d39e2c9d7699e8079462cae67f7e Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 3 Oct 2013 20:49:10 +0200 Date: Thu, 3 Oct 2013 20:49:10 +0200
Subject: [PATCH 3/5] b44: abort when no PHY is available at all Subject: [PATCH 4/9] b44: abort when no PHY is available at all
When the phy address is 31, this means that there is no PHY connected When the phy address is 31, this means that there is no PHY connected
to this MAC at all, no internal and no external PHY. Reading these PHY to this MAC at all, no internal and no external PHY. Reading these PHY

View file

@ -1,7 +1,7 @@
From 6dcaccfc1e0046632dd54d91b6f679fee7f841bc Mon Sep 17 00:00:00 2001 From 16b8dde613e5b59bee13537469f3562081da1a2c Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 6 Oct 2013 15:31:04 +0200 Date: Sun, 6 Oct 2013 15:31:04 +0200
Subject: [PATCH 4/5] b44: rename b44_mii_{read,write} to Subject: [PATCH 5/9] b44: rename b44_mii_{read,write} to
b44_mdio_{read,write}_mii b44_mdio_{read,write}_mii
The next patch will add these functions for phylib, and we should The next patch will add these functions for phylib, and we should

View file

@ -1,7 +1,7 @@
From 46e5460f446109565b3f4a0cb728171d74bce33b Mon Sep 17 00:00:00 2001 From 31963d998d2984079dc4f4b36b7df170d85f6d66 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Thu, 3 Oct 2013 22:07:11 +0200 Date: Thu, 3 Oct 2013 22:07:11 +0200
Subject: [PATCH 5/6] b44: add phylib support Subject: [PATCH 6/9] b44: add phylib support
Most of the older home routers based on the Broadcom BCM47XX SoC series Most of the older home routers based on the Broadcom BCM47XX SoC series
are using a MAC that is supported by b44. On most of these routers not are using a MAC that is supported by b44. On most of these routers not
@ -21,9 +21,9 @@ This was tested with a BCM4704, BCM4712 and BCM5354.
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de> Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
--- ---
drivers/net/ethernet/broadcom/Kconfig | 1 + drivers/net/ethernet/broadcom/Kconfig | 1 +
drivers/net/ethernet/broadcom/b44.c | 183 ++++++++++++++++++++++++++++++++- drivers/net/ethernet/broadcom/b44.c | 181 ++++++++++++++++++++++++++++++++-
drivers/net/ethernet/broadcom/b44.h | 5 + drivers/net/ethernet/broadcom/b44.h | 4 +
3 files changed, 186 insertions(+), 3 deletions(-) 3 files changed, 183 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/broadcom/Kconfig --- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig +++ b/drivers/net/ethernet/broadcom/Kconfig
@ -81,7 +81,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
{ {
struct b44 *bp = netdev_priv(dev); struct b44 *bp = netdev_priv(dev);
+ if (bp->has_phy) { + if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+ BUG_ON(!bp->phydev); + BUG_ON(!bp->phydev);
+ return phy_ethtool_gset(bp->phydev, cmd); + return phy_ethtool_gset(bp->phydev, cmd);
+ } + }
@ -97,7 +97,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+ u32 speed; + u32 speed;
+ int ret; + int ret;
+ +
+ if (bp->has_phy) { + if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+ BUG_ON(!bp->phydev); + BUG_ON(!bp->phydev);
+ spin_lock_irq(&bp->lock); + spin_lock_irq(&bp->lock);
+ if (netif_running(dev)) + if (netif_running(dev))
@ -127,7 +127,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
spin_lock_irq(&bp->lock); spin_lock_irq(&bp->lock);
- err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL); - err = generic_mii_ioctl(&bp->mii_if, data, cmd, NULL);
+ if (bp->has_phy) { + if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+ BUG_ON(bp->phydev); + BUG_ON(bp->phydev);
+ err = phy_mii_ioctl(bp->phydev, ifr, cmd); + err = phy_mii_ioctl(bp->phydev, ifr, cmd);
+ } else { + } else {
@ -261,13 +261,11 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
static int b44_init_one(struct ssb_device *sdev, static int b44_init_one(struct ssb_device *sdev,
const struct ssb_device_id *ent) const struct ssb_device_id *ent)
{ {
@@ -2246,10 +2408,22 @@ static int b44_init_one(struct ssb_devic @@ -2246,10 +2408,20 @@ static int b44_init_one(struct ssb_devic
if (b44_phy_reset(bp) < 0) if (b44_phy_reset(bp) < 0)
bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY; bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY;
+ bp->has_phy = bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY; + if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
+
+ if (bp->has_phy) {
+ err = b44_register_phy_one(bp); + err = b44_register_phy_one(bp);
+ if (err) { + if (err) {
+ dev_err(sdev->dev, "Cannot register PHY, aborting\n"); + dev_err(sdev->dev, "Cannot register PHY, aborting\n");
@ -284,25 +282,24 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
err_out_powerdown: err_out_powerdown:
ssb_bus_may_powerdown(sdev->bus); ssb_bus_may_powerdown(sdev->bus);
@@ -2263,8 +2437,11 @@ out: @@ -2263,8 +2435,11 @@ out:
static void b44_remove_one(struct ssb_device *sdev) static void b44_remove_one(struct ssb_device *sdev)
{ {
struct net_device *dev = ssb_get_drvdata(sdev); struct net_device *dev = ssb_get_drvdata(sdev);
+ struct b44 *bp = netdev_priv(dev); + struct b44 *bp = netdev_priv(dev);
unregister_netdev(dev); unregister_netdev(dev);
+ if (bp->has_phy) + if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+ b44_unregister_phy_one(bp); + b44_unregister_phy_one(bp);
ssb_device_disable(sdev, 0); ssb_device_disable(sdev, 0);
ssb_bus_may_powerdown(sdev->bus); ssb_bus_may_powerdown(sdev->bus);
free_netdev(dev); free_netdev(dev);
--- a/drivers/net/ethernet/broadcom/b44.h --- a/drivers/net/ethernet/broadcom/b44.h
+++ b/drivers/net/ethernet/broadcom/b44.h +++ b/drivers/net/ethernet/broadcom/b44.h
@@ -397,6 +397,11 @@ struct b44 { @@ -397,6 +397,10 @@ struct b44 {
u32 tx_pending; u32 tx_pending;
u8 phy_addr; u8 phy_addr;
u8 force_copybreak; u8 force_copybreak;
+ bool has_phy;
+ struct phy_device *phydev; + struct phy_device *phydev;
+ struct mii_bus *mii_bus; + struct mii_bus *mii_bus;
+ int old_link; + int old_link;

View file

@ -1,7 +1,7 @@
From 444044a410d4cf3b6dd462f2c9352d56039d9e07 Mon Sep 17 00:00:00 2001 From f6a8d917c3efcfb974097ef4b345e8cda5283bab Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de> From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Sun, 6 Oct 2013 17:58:24 +0200 Date: Sun, 6 Oct 2013 17:58:24 +0200
Subject: [PATCH 6/6] b44: activate PHY when MAC is off Subject: [PATCH 7/9] b44: activate PHY when MAC is off
Without this patch we can not access the PHY when the MAC is switched Without this patch we can not access the PHY when the MAC is switched
off. This PHY access is needed to configure the switch, which is done off. This PHY access is needed to configure the switch, which is done
@ -19,7 +19,7 @@ Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
/* now reset the chip, but without enabling the MAC&PHY /* now reset the chip, but without enabling the MAC&PHY
* part of it. This has to be done _after_ we shut down the PHY */ * part of it. This has to be done _after_ we shut down the PHY */
- b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL); - b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);
+ if (bp->has_phy) + if (bp->flags & B44_FLAG_EXTERNAL_PHY)
+ b44_chip_reset(bp, B44_CHIP_RESET_FULL); + b44_chip_reset(bp, B44_CHIP_RESET_FULL);
+ else + else
+ b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL); + b44_chip_reset(bp, B44_CHIP_RESET_PARTIAL);

View file

@ -0,0 +1,25 @@
From c2ecc401a08f0bda3b2483b93989d9792cadf6b2 Mon Sep 17 00:00:00 2001
From: Hauke Mehrtens <hauke@hauke-m.de>
Date: Mon, 21 Oct 2013 20:30:04 +0200
Subject: [PATCH 8/9] b44: do not set phy addr to 30 for every ext phy
---
drivers/net/ethernet/broadcom/b44.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -2408,8 +2408,11 @@ static int b44_init_one(struct ssb_devic
b44_chip_reset(bp, B44_CHIP_RESET_FULL);
/* do a phy reset to test if there is an active phy */
- if (b44_phy_reset(bp) < 0)
- bp->phy_addr = B44_PHY_ADDR_NO_LOACL_PHY;
+ err = b44_phy_reset(bp);
+ if (err < 0) {
+ dev_err(sdev->dev, "phy reset failed\n");
+ goto err_out_unregister_netdev;
+ }
if (bp->flags & B44_FLAG_EXTERNAL_PHY) {
err = b44_register_phy_one(bp);

View file

@ -41,7 +41,7 @@
b44_wap54g10_workaround(bp); b44_wap54g10_workaround(bp);
+ b44_bcm47xx_workarounds(bp); + b44_bcm47xx_workarounds(bp);
if (bp->phy_addr == B44_PHY_ADDR_NO_LOACL_PHY) if (bp->flags & B44_FLAG_EXTERNAL_PHY)
return 0; return 0;
@@ -2158,6 +2183,8 @@ static int b44_get_invariants(struct b44 @@ -2158,6 +2183,8 @@ static int b44_get_invariants(struct b44
* valid PHY address. */ * valid PHY address. */