diff options
Diffstat (limited to 'drivers/net/phy/bcm87xx.c')
| -rw-r--r-- | drivers/net/phy/bcm87xx.c | 115 |
1 files changed, 58 insertions, 57 deletions
diff --git a/drivers/net/phy/bcm87xx.c b/drivers/net/phy/bcm87xx.c index f0c0eefe2202..299f9a8f30f4 100644 --- a/drivers/net/phy/bcm87xx.c +++ b/drivers/net/phy/bcm87xx.c @@ -10,12 +10,12 @@ #define PHY_ID_BCM8706 0x0143bdc1 #define PHY_ID_BCM8727 0x0143bff0 -#define BCM87XX_PMD_RX_SIGNAL_DETECT (MII_ADDR_C45 | 0x1000a) -#define BCM87XX_10GBASER_PCS_STATUS (MII_ADDR_C45 | 0x30020) -#define BCM87XX_XGXS_LANE_STATUS (MII_ADDR_C45 | 0x40018) +#define BCM87XX_PMD_RX_SIGNAL_DETECT 0x000a +#define BCM87XX_10GBASER_PCS_STATUS 0x0020 +#define BCM87XX_XGXS_LANE_STATUS 0x0018 -#define BCM87XX_LASI_CONTROL (MII_ADDR_C45 | 0x39002) -#define BCM87XX_LASI_STATUS (MII_ADDR_C45 | 0x39005) +#define BCM87XX_LASI_CONTROL 0x9002 +#define BCM87XX_LASI_STATUS 0x9005 #if IS_ENABLED(CONFIG_OF_MDIO) /* Set and/or override some configuration registers based on the @@ -54,11 +54,10 @@ static int bcm87xx_of_reg_init(struct phy_device *phydev) u16 reg = be32_to_cpup(paddr++); u16 mask = be32_to_cpup(paddr++); u16 val_bits = be32_to_cpup(paddr++); - int val; - u32 regnum = MII_ADDR_C45 | (devid << 16) | reg; - val = 0; + int val = 0; + if (mask) { - val = phy_read(phydev, regnum); + val = phy_read_mmd(phydev, devid, reg); if (val < 0) { ret = val; goto err; @@ -67,7 +66,7 @@ static int bcm87xx_of_reg_init(struct phy_device *phydev) } val |= val_bits; - ret = phy_write(phydev, regnum, val); + ret = phy_write_mmd(phydev, devid, reg, val); if (ret < 0) goto err; } @@ -81,22 +80,18 @@ static int bcm87xx_of_reg_init(struct phy_device *phydev) } #endif /* CONFIG_OF_MDIO */ -static int bcm87xx_config_init(struct phy_device *phydev) +static int bcm87xx_get_features(struct phy_device *phydev) { - linkmode_zero(phydev->supported); linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, phydev->supported); - linkmode_zero(phydev->advertising); - linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, - phydev->advertising); - phydev->state = PHY_NOLINK; - phydev->autoneg = AUTONEG_DISABLE; - - bcm87xx_of_reg_init(phydev); - return 0; } +static int bcm87xx_config_init(struct phy_device *phydev) +{ + return bcm87xx_of_reg_init(phydev); +} + static int bcm87xx_config_aneg(struct phy_device *phydev) { return -EINVAL; @@ -108,21 +103,24 @@ static int bcm87xx_read_status(struct phy_device *phydev) int pcs_status; int xgxs_lane_status; - rx_signal_detect = phy_read(phydev, BCM87XX_PMD_RX_SIGNAL_DETECT); + rx_signal_detect = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, + BCM87XX_PMD_RX_SIGNAL_DETECT); if (rx_signal_detect < 0) return rx_signal_detect; if ((rx_signal_detect & 1) == 0) goto no_link; - pcs_status = phy_read(phydev, BCM87XX_10GBASER_PCS_STATUS); + pcs_status = phy_read_mmd(phydev, MDIO_MMD_PCS, + BCM87XX_10GBASER_PCS_STATUS); if (pcs_status < 0) return pcs_status; if ((pcs_status & 1) == 0) goto no_link; - xgxs_lane_status = phy_read(phydev, BCM87XX_XGXS_LANE_STATUS); + xgxs_lane_status = phy_read_mmd(phydev, MDIO_MMD_PHYXS, + BCM87XX_XGXS_LANE_STATUS); if (xgxs_lane_status < 0) return xgxs_lane_status; @@ -143,50 +141,54 @@ static int bcm87xx_config_intr(struct phy_device *phydev) { int reg, err; - reg = phy_read(phydev, BCM87XX_LASI_CONTROL); + reg = phy_read_mmd(phydev, MDIO_MMD_PCS, BCM87XX_LASI_CONTROL); if (reg < 0) return reg; - if (phydev->interrupts == PHY_INTERRUPT_ENABLED) + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { + err = phy_read_mmd(phydev, MDIO_MMD_PCS, BCM87XX_LASI_STATUS); + if (err) + return err; + reg |= 1; - else + err = phy_write_mmd(phydev, MDIO_MMD_PCS, + BCM87XX_LASI_CONTROL, reg); + } else { reg &= ~1; + err = phy_write_mmd(phydev, MDIO_MMD_PCS, + BCM87XX_LASI_CONTROL, reg); + if (err) + return err; + + err = phy_read_mmd(phydev, MDIO_MMD_PCS, BCM87XX_LASI_STATUS); + } - err = phy_write(phydev, BCM87XX_LASI_CONTROL, reg); return err; } -static int bcm87xx_did_interrupt(struct phy_device *phydev) +static irqreturn_t bcm87xx_handle_interrupt(struct phy_device *phydev) { - int reg; - - reg = phy_read(phydev, BCM87XX_LASI_STATUS); + int irq_status; - if (reg < 0) { - phydev_err(phydev, - "Error: Read of BCM87XX_LASI_STATUS failed: %d\n", - reg); - return 0; + irq_status = phy_read(phydev, BCM87XX_LASI_STATUS); + if (irq_status < 0) { + phy_error(phydev); + return IRQ_NONE; } - return (reg & 1) != 0; -} -static int bcm87xx_ack_interrupt(struct phy_device *phydev) -{ - /* Reading the LASI status clears it. */ - bcm87xx_did_interrupt(phydev); - return 0; -} + if (irq_status == 0) + return IRQ_NONE; -static int bcm8706_match_phy_device(struct phy_device *phydev) -{ - return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8706; + phy_trigger_machine(phydev); + + return IRQ_HANDLED; } -static int bcm8727_match_phy_device(struct phy_device *phydev) +static int bcm87xx_match_phy_device(struct phy_device *phydev, + const struct phy_driver *phydrv) { - return phydev->c45_ids.device_ids[4] == PHY_ID_BCM8727; + return phydev->c45_ids.device_ids[4] == phydrv->phy_id; } static struct phy_driver bcm87xx_driver[] = { @@ -194,28 +196,27 @@ static struct phy_driver bcm87xx_driver[] = { .phy_id = PHY_ID_BCM8706, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8706", - .features = PHY_10GBIT_FEC_FEATURES, + .get_features = bcm87xx_get_features, .config_init = bcm87xx_config_init, .config_aneg = bcm87xx_config_aneg, .read_status = bcm87xx_read_status, - .ack_interrupt = bcm87xx_ack_interrupt, .config_intr = bcm87xx_config_intr, - .did_interrupt = bcm87xx_did_interrupt, - .match_phy_device = bcm8706_match_phy_device, + .handle_interrupt = bcm87xx_handle_interrupt, + .match_phy_device = bcm87xx_match_phy_device, }, { .phy_id = PHY_ID_BCM8727, .phy_id_mask = 0xffffffff, .name = "Broadcom BCM8727", - .features = PHY_10GBIT_FEC_FEATURES, + .get_features = bcm87xx_get_features, .config_init = bcm87xx_config_init, .config_aneg = bcm87xx_config_aneg, .read_status = bcm87xx_read_status, - .ack_interrupt = bcm87xx_ack_interrupt, .config_intr = bcm87xx_config_intr, - .did_interrupt = bcm87xx_did_interrupt, - .match_phy_device = bcm8727_match_phy_device, + .handle_interrupt = bcm87xx_handle_interrupt, + .match_phy_device = bcm87xx_match_phy_device, } }; module_phy_driver(bcm87xx_driver); MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Broadcom BCM87xx PHY driver"); |
