Skip to content

Commit

Permalink
Merge branch 'bgmac-phy-init'
Browse files Browse the repository at this point in the history
Rafał Miłecki says:

====================
net-next: use one struct bgmac & add PHY support

This patchset adds support for initializing PHY using PHY subsystem.
It's required e.g. for wireless access point devices that use bgmac
supported Ethernet device connected to some external PHY.

Implementing this required accessing phydev in bcma specific code which
wasn't possible with core code allocating struct bgmac on its own. This
is why I needed to modify alloc_etherdev usage first.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jan 31, 2017
2 parents 953046e + 8e6f31b commit 624374a
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 73 deletions.
108 changes: 50 additions & 58 deletions drivers/net/ethernet/broadcom/bgmac-bcma-mdio.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,6 @@
#include <linux/brcmphy.h>
#include "bgmac.h"

struct bcma_mdio {
struct bcma_device *core;
u8 phyaddr;
};

static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask,
u32 value, int timeout)
{
Expand All @@ -37,7 +32,7 @@ static bool bcma_mdio_wait_value(struct bcma_device *core, u16 reg, u32 mask,
* PHY ops
**************************************************/

static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg)
static u16 bcma_mdio_phy_read(struct bgmac *bgmac, u8 phyaddr, u8 reg)
{
struct bcma_device *core;
u16 phy_access_addr;
Expand All @@ -56,12 +51,12 @@ static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg)
BUILD_BUG_ON(BGMAC_PC_MCT_SHIFT != BCMA_GMAC_CMN_PC_MCT_SHIFT);
BUILD_BUG_ON(BGMAC_PC_MTE != BCMA_GMAC_CMN_PC_MTE);

if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
core = bcma_mdio->core->bus->drv_gmac_cmn.core;
if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) {
core = bgmac->bcma.core->bus->drv_gmac_cmn.core;
phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
} else {
core = bcma_mdio->core;
core = bgmac->bcma.core;
phy_access_addr = BGMAC_PHY_ACCESS;
phy_ctl_addr = BGMAC_PHY_CNTL;
}
Expand All @@ -87,20 +82,20 @@ static u16 bcma_mdio_phy_read(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg)
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphywr */
static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg,
static int bcma_mdio_phy_write(struct bgmac *bgmac, u8 phyaddr, u8 reg,
u16 value)
{
struct bcma_device *core;
u16 phy_access_addr;
u16 phy_ctl_addr;
u32 tmp;

if (bcma_mdio->core->id.id == BCMA_CORE_4706_MAC_GBIT) {
core = bcma_mdio->core->bus->drv_gmac_cmn.core;
if (bgmac->bcma.core->id.id == BCMA_CORE_4706_MAC_GBIT) {
core = bgmac->bcma.core->bus->drv_gmac_cmn.core;
phy_access_addr = BCMA_GMAC_CMN_PHY_ACCESS;
phy_ctl_addr = BCMA_GMAC_CMN_PHY_CTL;
} else {
core = bcma_mdio->core;
core = bgmac->bcma.core;
phy_access_addr = BGMAC_PHY_ACCESS;
phy_ctl_addr = BGMAC_PHY_CNTL;
}
Expand All @@ -110,8 +105,8 @@ static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg,
tmp |= phyaddr;
bcma_write32(core, phy_ctl_addr, tmp);

bcma_write32(bcma_mdio->core, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
if (bcma_read32(bcma_mdio->core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
bcma_write32(bgmac->bcma.core, BGMAC_INT_STATUS, BGMAC_IS_MDIO);
if (bcma_read32(bgmac->bcma.core, BGMAC_INT_STATUS) & BGMAC_IS_MDIO)
dev_warn(&core->dev, "Error setting MDIO int\n");

tmp = BGMAC_PA_START;
Expand All @@ -132,57 +127,67 @@ static int bcma_mdio_phy_write(struct bcma_mdio *bcma_mdio, u8 phyaddr, u8 reg,
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */
static void bcma_mdio_phy_init(struct bcma_mdio *bcma_mdio)
static void bcma_mdio_phy_init(struct bgmac *bgmac)
{
struct bcma_chipinfo *ci = &bcma_mdio->core->bus->chipinfo;
struct bcma_chipinfo *ci = &bgmac->bcma.core->bus->chipinfo;
u8 i;

/* For some legacy hardware we do chipset-based PHY initialization here
* without even detecting PHY ID. It's hacky and should be cleaned as
* soon as someone can test it.
*/
if (ci->id == BCMA_CHIP_ID_BCM5356) {
for (i = 0; i < 5; i++) {
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x008b);
bcma_mdio_phy_write(bcma_mdio, i, 0x15, 0x0100);
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bcma_mdio, i, 0x12, 0x2aaa);
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x008b);
bcma_mdio_phy_write(bgmac, i, 0x15, 0x0100);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bgmac, i, 0x12, 0x2aaa);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
}
return;
}
if ((ci->id == BCMA_CHIP_ID_BCM5357 && ci->pkg != 10) ||
(ci->id == BCMA_CHIP_ID_BCM4749 && ci->pkg != 10) ||
(ci->id == BCMA_CHIP_ID_BCM53572 && ci->pkg != 9)) {
struct bcma_drv_cc *cc = &bcma_mdio->core->bus->drv_cc;
struct bcma_drv_cc *cc = &bgmac->bcma.core->bus->drv_cc;

bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0);
bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0);
for (i = 0; i < 5; i++) {
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5284);
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x0010);
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x5296);
bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x1073);
bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9073);
bcma_mdio_phy_write(bcma_mdio, i, 0x16, 0x52b6);
bcma_mdio_phy_write(bcma_mdio, i, 0x17, 0x9273);
bcma_mdio_phy_write(bcma_mdio, i, 0x1f, 0x000b);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bgmac, i, 0x16, 0x5284);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
bcma_mdio_phy_write(bgmac, i, 0x17, 0x0010);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000f);
bcma_mdio_phy_write(bgmac, i, 0x16, 0x5296);
bcma_mdio_phy_write(bgmac, i, 0x17, 0x1073);
bcma_mdio_phy_write(bgmac, i, 0x17, 0x9073);
bcma_mdio_phy_write(bgmac, i, 0x16, 0x52b6);
bcma_mdio_phy_write(bgmac, i, 0x17, 0x9273);
bcma_mdio_phy_write(bgmac, i, 0x1f, 0x000b);
}
return;
}

/* For all other hw do initialization using PHY subsystem. */
if (bgmac->net_dev && bgmac->net_dev->phydev)
phy_init_hw(bgmac->net_dev->phydev);
}

/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */
static int bcma_mdio_phy_reset(struct mii_bus *bus)
{
struct bcma_mdio *bcma_mdio = bus->priv;
u8 phyaddr = bcma_mdio->phyaddr;
struct bgmac *bgmac = bus->priv;
u8 phyaddr = bgmac->phyaddr;

if (bcma_mdio->phyaddr == BGMAC_PHY_NOREGS)
if (phyaddr == BGMAC_PHY_NOREGS)
return 0;

bcma_mdio_phy_write(bcma_mdio, phyaddr, MII_BMCR, BMCR_RESET);
bcma_mdio_phy_write(bgmac, phyaddr, MII_BMCR, BMCR_RESET);
udelay(100);
if (bcma_mdio_phy_read(bcma_mdio, phyaddr, MII_BMCR) & BMCR_RESET)
dev_err(&bcma_mdio->core->dev, "PHY reset failed\n");
bcma_mdio_phy_init(bcma_mdio);
if (bcma_mdio_phy_read(bgmac, phyaddr, MII_BMCR) & BMCR_RESET)
dev_err(bgmac->dev, "PHY reset failed\n");
bcma_mdio_phy_init(bgmac);

return 0;
}
Expand All @@ -202,16 +207,12 @@ static int bcma_mdio_mii_write(struct mii_bus *bus, int mii_id, int regnum,
return bcma_mdio_phy_write(bus->priv, mii_id, regnum, value);
}

struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr)
struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac)
{
struct bcma_mdio *bcma_mdio;
struct bcma_device *core = bgmac->bcma.core;
struct mii_bus *mii_bus;
int err;

bcma_mdio = kzalloc(sizeof(*bcma_mdio), GFP_KERNEL);
if (!bcma_mdio)
return ERR_PTR(-ENOMEM);

mii_bus = mdiobus_alloc();
if (!mii_bus) {
err = -ENOMEM;
Expand All @@ -221,15 +222,12 @@ struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr)
mii_bus->name = "bcma_mdio mii bus";
sprintf(mii_bus->id, "%s-%d-%d", "bcma_mdio", core->bus->num,
core->core_unit);
mii_bus->priv = bcma_mdio;
mii_bus->priv = bgmac;
mii_bus->read = bcma_mdio_mii_read;
mii_bus->write = bcma_mdio_mii_write;
mii_bus->reset = bcma_mdio_phy_reset;
mii_bus->parent = &core->dev;
mii_bus->phy_mask = ~(1 << phyaddr);

bcma_mdio->core = core;
bcma_mdio->phyaddr = phyaddr;
mii_bus->phy_mask = ~(1 << bgmac->phyaddr);

err = mdiobus_register(mii_bus);
if (err) {
Expand All @@ -242,23 +240,17 @@ struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr)
err_free_bus:
mdiobus_free(mii_bus);
err:
kfree(bcma_mdio);
return ERR_PTR(err);
}
EXPORT_SYMBOL_GPL(bcma_mdio_mii_register);

void bcma_mdio_mii_unregister(struct mii_bus *mii_bus)
{
struct bcma_mdio *bcma_mdio;

if (!mii_bus)
return;

bcma_mdio = mii_bus->priv;

mdiobus_unregister(mii_bus);
mdiobus_free(mii_bus);
kfree(bcma_mdio);
}
EXPORT_SYMBOL_GPL(bcma_mdio_mii_unregister);

Expand Down
6 changes: 2 additions & 4 deletions drivers/net/ethernet/broadcom/bgmac-bcma.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,11 @@ static int bgmac_probe(struct bcma_device *core)
u8 *mac;
int err;

bgmac = kzalloc(sizeof(*bgmac), GFP_KERNEL);
bgmac = bgmac_alloc(&core->dev);
if (!bgmac)
return -ENOMEM;

bgmac->bcma.core = core;
bgmac->dev = &core->dev;
bgmac->dma_dev = core->dma_dev;
bgmac->irq = core->irq;

Expand Down Expand Up @@ -178,7 +177,7 @@ static int bgmac_probe(struct bcma_device *core)

if (!bgmac_is_bcm4707_family(core) &&
!(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
mii_bus = bcma_mdio_mii_register(core, bgmac->phyaddr);
mii_bus = bcma_mdio_mii_register(bgmac);
if (IS_ERR(mii_bus)) {
err = PTR_ERR(mii_bus);
goto err;
Expand Down Expand Up @@ -307,7 +306,6 @@ static int bgmac_probe(struct bcma_device *core)
err1:
bcma_mdio_mii_unregister(bgmac->mii_bus);
err:
kfree(bgmac);
bcma_set_drvdata(core, NULL);

return err;
Expand Down
2 changes: 1 addition & 1 deletion drivers/net/ethernet/broadcom/bgmac-platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static int bgmac_probe(struct platform_device *pdev)
struct resource *regs;
const u8 *mac_addr;

bgmac = devm_kzalloc(&pdev->dev, sizeof(*bgmac), GFP_KERNEL);
bgmac = bgmac_alloc(&pdev->dev);
if (!bgmac)
return -ENOMEM;

Expand Down
25 changes: 17 additions & 8 deletions drivers/net/ethernet/broadcom/bgmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -1446,22 +1446,32 @@ int bgmac_phy_connect_direct(struct bgmac *bgmac)
}
EXPORT_SYMBOL_GPL(bgmac_phy_connect_direct);

int bgmac_enet_probe(struct bgmac *info)
struct bgmac *bgmac_alloc(struct device *dev)
{
struct net_device *net_dev;
struct bgmac *bgmac;
int err;

/* Allocation and references */
net_dev = alloc_etherdev(sizeof(*bgmac));
net_dev = devm_alloc_etherdev(dev, sizeof(*bgmac));
if (!net_dev)
return -ENOMEM;
return NULL;

net_dev->netdev_ops = &bgmac_netdev_ops;
net_dev->ethtool_ops = &bgmac_ethtool_ops;

bgmac = netdev_priv(net_dev);
memcpy(bgmac, info, sizeof(*bgmac));
bgmac->dev = dev;
bgmac->net_dev = net_dev;

return bgmac;
}
EXPORT_SYMBOL_GPL(bgmac_alloc);

int bgmac_enet_probe(struct bgmac *bgmac)
{
struct net_device *net_dev = bgmac->net_dev;
int err;

net_dev->irq = bgmac->irq;
SET_NETDEV_DEV(net_dev, bgmac->dev);

Expand All @@ -1488,7 +1498,7 @@ int bgmac_enet_probe(struct bgmac *info)
err = bgmac_dma_alloc(bgmac);
if (err) {
dev_err(bgmac->dev, "Unable to alloc memory for DMA\n");
goto err_netdev_free;
goto err_out;
}

bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
Expand Down Expand Up @@ -1521,8 +1531,7 @@ int bgmac_enet_probe(struct bgmac *info)
phy_disconnect(net_dev->phydev);
err_dma_free:
bgmac_dma_free(bgmac);
err_netdev_free:
free_netdev(net_dev);
err_out:

return err;
}
Expand Down
5 changes: 3 additions & 2 deletions drivers/net/ethernet/broadcom/bgmac.h
Original file line number Diff line number Diff line change
Expand Up @@ -517,12 +517,13 @@ struct bgmac {
int (*phy_connect)(struct bgmac *bgmac);
};

int bgmac_enet_probe(struct bgmac *info);
struct bgmac *bgmac_alloc(struct device *dev);
int bgmac_enet_probe(struct bgmac *bgmac);
void bgmac_enet_remove(struct bgmac *bgmac);
void bgmac_adjust_link(struct net_device *net_dev);
int bgmac_phy_connect_direct(struct bgmac *bgmac);

struct mii_bus *bcma_mdio_mii_register(struct bcma_device *core, u8 phyaddr);
struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac);
void bcma_mdio_mii_unregister(struct mii_bus *mii_bus);

static inline u32 bgmac_read(struct bgmac *bgmac, u16 offset)
Expand Down

0 comments on commit 624374a

Please sign in to comment.