static int my3126_interrupt_handler(struct cphy *cphy) { u32 val; u16 val16; u16 status; u32 act_count; adapter_t *adapter; adapter = cphy->adapter; if (cphy->count == 50) { cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; status = cphy->bmsr ^ val16; if (status & MDIO_STAT1_LSTATUS) t1_link_changed(adapter, 0); cphy->bmsr = val16; /* We have only enabled link change interrupts so it must be that */ cphy->count = 0; } t1_tpi_write(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_CONTROL), SUNI1x10GEXP_BITMSK_MSTAT_SNAP); t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_1_LOW), &act_count); t1_tpi_read(adapter, OFFSET(SUNI1x10GEXP_REG_MSTAT_COUNTER_33_LOW), &val); act_count += val; /* Populate elmer_gpo with the register value */ t1_tpi_read(adapter, A_ELMER0_GPO, &val); cphy->elmer_gpo = val; if ( (val & (1 << 8)) || (val & (1 << 19)) || (cphy->act_count == act_count) || cphy->act_on ) { if (is_T2(adapter)) val |= (1 << 9); else if (t1_is_T1B(adapter)) val |= (1 << 20); cphy->act_on = 0; } else { if (is_T2(adapter)) val &= ~(1 << 9); else if (t1_is_T1B(adapter)) val &= ~(1 << 20); cphy->act_on = 1; } t1_tpi_write(adapter, A_ELMER0_GPO, val); cphy->elmer_gpo = val; cphy->act_count = act_count; cphy->count++; return cphy_cause_link_change; }
static struct cphy *mv88x201x_phy_create(struct net_device *dev, int phy_addr, const struct mdio_ops *mdio_ops) { u32 val; struct cphy *cphy = kzalloc(sizeof(*cphy), GFP_KERNEL); if (!cphy) return NULL; cphy_init(cphy, dev, phy_addr, &mv88x201x_ops, mdio_ops); /* Commands the PHY to enable XFP's clock. */ cphy_mdio_read(cphy, MDIO_MMD_PCS, 0x8300, &val); cphy_mdio_write(cphy, MDIO_MMD_PCS, 0x8300, val | 1); /* Clear link status. Required because of a bug in the PHY. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT2, &val); cphy_mdio_read(cphy, MDIO_MMD_PCS, MDIO_STAT2, &val); /* Allows for Link,Ack LED turn on/off */ led_init(cphy); return cphy; }
static int led_link(struct cphy *cphy, u32 do_enable) { u32 led = 0; #define LINK_ENABLE_BIT 0x1 cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, &led); if (do_enable & LINK_ENABLE_BIT) { led |= LINK_ENABLE_BIT; cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } else { led &= ~LINK_ENABLE_BIT; cphy_mdio_write(cphy, MDIO_MMD_PMAPMD, MDIO_CTRL2, led); } return 0; }
/* To check the activity LED */ static int my3126_get_link_status(struct cphy *cphy, int *link_ok, int *speed, int *duplex, int *fc) { u32 val; u16 val16; adapter_t *adapter; adapter = cphy->adapter; cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val16 = (u16) val; /* Populate elmer_gpo with the register value */ t1_tpi_read(adapter, A_ELMER0_GPO, &val); cphy->elmer_gpo = val; *link_ok = (val16 & MDIO_STAT1_LSTATUS); if (*link_ok) { /* Turn on the LED. */ if (is_T2(adapter)) val &= ~(1 << 8); else if (t1_is_T1B(adapter)) val &= ~(1 << 19); } else { /* Turn off the LED. */ if (is_T2(adapter)) val |= (1 << 8); else if (t1_is_T1B(adapter)) val |= (1 << 19); } t1_tpi_write(adapter, A_ELMER0_GPO, val); cphy->elmer_gpo = val; *speed = SPEED_10000; *duplex = DUPLEX_FULL; /* need to add flow control */ if (fc) *fc = PAUSE_RX | PAUSE_TX; return 0; }
static int mv88x201x_get_link_status(struct cphy *cphy, int *link_ok, int *speed, int *duplex, int *fc) { u32 val = 0; if (link_ok) { /* Read link status. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); val &= MDIO_STAT1_LSTATUS; *link_ok = (val == MDIO_STAT1_LSTATUS); /* Turn on/off Link LED */ led_link(cphy, *link_ok); } if (speed) *speed = SPEED_10000; if (duplex) *duplex = DUPLEX_FULL; if (fc) *fc = PAUSE_RX | PAUSE_TX; return 0; }
static int mv88x201x_interrupt_clear(struct cphy *cphy) { u32 elmer; u32 val; #ifdef MV88x2010_LINK_STATUS_BUGS /* Required to read twice before clear takes affect. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); /* Read this register after the others above it else * the register doesn't clear correctly. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); #endif /* Clear link status. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_STAT1, &val); /* Clear PHY LASI interrupts. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_STAT, &val); #ifdef MV88x2010_LINK_STATUS_BUGS /* Do it again. */ cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_RXSTAT, &val); cphy_mdio_read(cphy, MDIO_MMD_PMAPMD, MDIO_PMA_LASI_TXSTAT, &val); #endif /* Clear Marvell interrupts through Elmer0. */ if (t1_is_asic(cphy->adapter)) { t1_tpi_read(cphy->adapter, A_ELMER0_INT_CAUSE, &elmer); elmer |= ELMER0_GP_BIT6; t1_tpi_write(cphy->adapter, A_ELMER0_INT_CAUSE, elmer); } return 0; }