/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyreset */ static void bgmac_phy_reset(struct bgmac *bgmac) { if (bgmac->phyaddr == BGMAC_PHY_NOREGS) return; bgmac_phy_write(bgmac, bgmac->phyaddr, MII_BMCR, BMCR_RESET); udelay(100); if (bgmac_phy_read(bgmac, bgmac->phyaddr, MII_BMCR) & BMCR_RESET) bgmac_err(bgmac, "PHY reset failed\n"); bgmac_phy_init(bgmac); }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyadvertise */ static void bgmac_phy_advertise(struct bgmac *bgmac) { u16 adv; if (bgmac->phyaddr == BGMAC_PHY_NOREGS) return; if (!bgmac->autoneg) return; /* Adv selected 10/100 speeds */ adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV); adv &= ~(BGMAC_PHY_ADV_10HALF | BGMAC_PHY_ADV_10FULL | BGMAC_PHY_ADV_100HALF | BGMAC_PHY_ADV_100FULL); if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10) adv |= BGMAC_PHY_ADV_10HALF; if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100) adv |= BGMAC_PHY_ADV_100HALF; if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_10) adv |= BGMAC_PHY_ADV_10FULL; if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_100) adv |= BGMAC_PHY_ADV_100FULL; bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV, adv); /* Adv selected 1000 speeds */ adv = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2); adv &= ~(BGMAC_PHY_ADV2_1000HALF | BGMAC_PHY_ADV2_1000FULL); if (!bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000) adv |= BGMAC_PHY_ADV2_1000HALF; if (bgmac->full_duplex && bgmac->speed & BGMAC_SPEED_1000) adv |= BGMAC_PHY_ADV2_1000FULL; bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_ADV2, adv); /* Restart */ bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL) | BGMAC_PHY_CTL_RESTART); }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyforce */ static void bgmac_phy_force(struct bgmac *bgmac) { u16 ctl; u16 mask = ~(BGMAC_PHY_CTL_SPEED | BGMAC_PHY_CTL_SPEED_MSB | BGMAC_PHY_CTL_ANENAB | BGMAC_PHY_CTL_DUPLEX); if (bgmac->phyaddr == BGMAC_PHY_NOREGS) return; if (bgmac->autoneg) return; ctl = bgmac_phy_read(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL); ctl &= mask; if (bgmac->full_duplex) ctl |= BGMAC_PHY_CTL_DUPLEX; if (bgmac->speed == BGMAC_SPEED_100) ctl |= BGMAC_PHY_CTL_SPEED_100; else if (bgmac->speed == BGMAC_SPEED_1000) ctl |= BGMAC_PHY_CTL_SPEED_1000; bgmac_phy_write(bgmac, bgmac->phyaddr, BGMAC_PHY_CTL, ctl); }
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipphyinit */ static void bgmac_phy_init(struct bgmac *bgmac) { struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo; struct bcma_drv_cc *cc = &bgmac->core->bus->drv_cc; u8 i; if (ci->id == BCMA_CHIP_ID_BCM5356) { for (i = 0; i < 5; i++) { bgmac_phy_write(bgmac, i, 0x1f, 0x008b); bgmac_phy_write(bgmac, i, 0x15, 0x0100); bgmac_phy_write(bgmac, i, 0x1f, 0x000f); bgmac_phy_write(bgmac, i, 0x12, 0x2aaa); bgmac_phy_write(bgmac, i, 0x1f, 0x000b); } } 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)) { bcma_chipco_chipctl_maskset(cc, 2, ~0xc0000000, 0); bcma_chipco_chipctl_maskset(cc, 4, ~0x80000000, 0); for (i = 0; i < 5; i++) { bgmac_phy_write(bgmac, i, 0x1f, 0x000f); bgmac_phy_write(bgmac, i, 0x16, 0x5284); bgmac_phy_write(bgmac, i, 0x1f, 0x000b); bgmac_phy_write(bgmac, i, 0x17, 0x0010); bgmac_phy_write(bgmac, i, 0x1f, 0x000f); bgmac_phy_write(bgmac, i, 0x16, 0x5296); bgmac_phy_write(bgmac, i, 0x17, 0x1073); bgmac_phy_write(bgmac, i, 0x17, 0x9073); bgmac_phy_write(bgmac, i, 0x16, 0x52b6); bgmac_phy_write(bgmac, i, 0x17, 0x9273); bgmac_phy_write(bgmac, i, 0x1f, 0x000b); } } }
static int bgmac_mii_write(struct mii_bus *bus, int mii_id, int regnum, u16 value) { return bgmac_phy_write(bus->priv, mii_id, regnum, value); }