From alan@linux.intel.com Mon Oct 26 15:01:00 2009 From: Alan Cox Date: Tue, 06 Oct 2009 15:51:10 +0100 Subject: Staging: et131x: phy clean up To: greg@kroah.com Message-ID: <20091006145109.8604.97309.stgit@localhost.localdomain> Clean up the phy code a bit so we can see what needs doing. This involves moving blocks around and making stuff static Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/staging/et131x/et1310_phy.c | 1158 ++++++++++++++++++------------------ drivers/staging/et131x/et1310_phy.h | 30 2 files changed, 582 insertions(+), 606 deletions(-) --- a/drivers/staging/et131x/et1310_phy.c +++ b/drivers/staging/et131x/et1310_phy.c @@ -109,12 +109,12 @@ static int et131x_xcvr_init(struct et131 * * Returns 0 on success, errno on failure (as defined in errno.h) */ -int PhyMiRead(struct et131x_adapter *adapter, uint8_t xcvrAddr, - uint8_t xcvrReg, uint16_t *value) +int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr, + u8 xcvrReg, u16 *value) { struct _MAC_t __iomem *mac = &adapter->regs->mac; int status = 0; - uint32_t delay; + u32 delay; u32 miiAddr; u32 miiCmd; u32 miiIndicator; @@ -174,14 +174,16 @@ int PhyMiRead(struct et131x_adapter *ada * @xcvrReg: the register to read * @value: 16-bit value to write * + * FIXME: one caller in netdev still + * * Return 0 on success, errno on failure (as defined in errno.h) */ -int MiWrite(struct et131x_adapter *adapter, uint8_t xcvrReg, uint16_t value) +int MiWrite(struct et131x_adapter *adapter, u8 xcvrReg, u16 value) { struct _MAC_t __iomem *mac = &adapter->regs->mac; int status = 0; - uint8_t xcvrAddr = adapter->Stats.xcvr_addr; - uint32_t delay; + u8 xcvrAddr = adapter->Stats.xcvr_addr; + u32 delay; u32 miiAddr; u32 miiCmd; u32 miiIndicator; @@ -210,7 +212,7 @@ int MiWrite(struct et131x_adapter *adapt /* If we hit the max delay, we could not write the register */ if (delay == 100) { - uint16_t TempValue; + u16 TempValue; dev_warn(&adapter->pdev->dev, "xcvrReg 0x%08x could not be written", xcvrReg); @@ -244,22 +246,22 @@ int MiWrite(struct et131x_adapter *adapt int et131x_xcvr_find(struct et131x_adapter *adapter) { int status = -ENODEV; - uint8_t xcvr_addr; + u8 xcvr_addr; MI_IDR1_t idr1; MI_IDR2_t idr2; - uint32_t xcvr_id; + u32 xcvr_id; /* We need to get xcvr id and address we just get the first one */ for (xcvr_addr = 0; xcvr_addr < 32; xcvr_addr++) { /* Read the ID from the PHY */ PhyMiRead(adapter, xcvr_addr, - (uint8_t) offsetof(MI_REGS_t, idr1), + (u8) offsetof(MI_REGS_t, idr1), &idr1.value); PhyMiRead(adapter, xcvr_addr, - (uint8_t) offsetof(MI_REGS_t, idr2), + (u8) offsetof(MI_REGS_t, idr2), &idr2.value); - xcvr_id = (uint32_t) ((idr1.value << 16) | idr2.value); + xcvr_id = (u32) ((idr1.value << 16) | idr2.value); if ((idr1.value != 0) && (idr1.value != 0xffff)) { adapter->Stats.xcvr_id = xcvr_id; @@ -290,279 +292,317 @@ int et131x_setphy_normal(struct et131x_a return status; } -/** - * et131x_xcvr_init - Init the phy if we are setting it into force mode - * @adapter: pointer to our private adapter structure - * - * Returns 0 on success, errno on failure (as defined in errno.h) - */ -static int et131x_xcvr_init(struct et131x_adapter *adapter) +void ET1310_PhyReset(struct et131x_adapter *etdev) { - int status = 0; - MI_IMR_t imr; - MI_ISR_t isr; - MI_LCR2_t lcr2; - - /* Zero out the adapter structure variable representing BMSR */ - adapter->Bmsr.value = 0; - - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, isr), &isr.value); - - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, imr), &imr.value); + MiWrite(etdev, PHY_CONTROL, 0x8000); +} - /* Set the link status interrupt only. Bad behavior when link status - * and auto neg are set, we run into a nested interrupt problem - */ - imr.bits.int_en = 0x1; - imr.bits.link_status = 0x1; - imr.bits.autoneg_status = 0x1; +void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down) +{ + u16 data; - MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, imr), imr.value); + MiRead(etdev, PHY_CONTROL, &data); - /* Set the LED behavior such that LED 1 indicates speed (off = - * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates - * link and activity (on for link, blink off for activity). - * - * NOTE: Some customizations have been added here for specific - * vendors; The LED behavior is now determined by vendor data in the - * EEPROM. However, the above description is the default. - */ - if ((adapter->eepromData[1] & 0x4) == 0) { - MiRead(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2), - &lcr2.value); - if ((adapter->eepromData[1] & 0x8) == 0) - lcr2.bits.led_tx_rx = 0x3; - else - lcr2.bits.led_tx_rx = 0x4; - lcr2.bits.led_link = 0xa; - MiWrite(adapter, (uint8_t) offsetof(MI_REGS_t, lcr2), - lcr2.value); + if (down == false) { + /* Power UP */ + data &= ~0x0800; + MiWrite(etdev, PHY_CONTROL, data); + } else { + /* Power DOWN */ + data |= 0x0800; + MiWrite(etdev, PHY_CONTROL, data); } +} - /* Determine if we need to go into a force mode and set it */ - if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) { - if ((adapter->RegistryFlowControl == TxOnly) || - (adapter->RegistryFlowControl == Both)) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 11, NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 11, NULL); - } - - if (adapter->RegistryFlowControl == Both) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 10, NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 10, NULL); - } +static void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable) +{ + u16 data; - /* Set the phy to autonegotiation */ - ET1310_PhyAutoNeg(adapter, true); + MiRead(etdev, PHY_CONTROL, &data); - /* NOTE - Do we need this? */ - ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL); - return status; + if (enable == true) { + /* Autonegotiation ON */ + data |= 0x1000; + MiWrite(etdev, PHY_CONTROL, data); } else { - ET1310_PhyAutoNeg(adapter, false); - - /* Set to the correct force mode. */ - if (adapter->AiForceDpx != 1) { - if ((adapter->RegistryFlowControl == TxOnly) || - (adapter->RegistryFlowControl == Both)) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 11, - NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 11, - NULL); - } + /* Autonegotiation OFF */ + data &= ~0x1000; + MiWrite(etdev, PHY_CONTROL, data); + } +} - if (adapter->RegistryFlowControl == Both) { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_SET, 4, 10, - NULL); - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 10, - NULL); - } - } else { - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 10, NULL); - ET1310_PhyAccessMiBit(adapter, - TRUEPHY_BIT_CLEAR, 4, 11, NULL); - } +static void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, u16 duplex) +{ + u16 data; - switch (adapter->AiForceSpeed) { - case 10: - if (adapter->AiForceDpx == 1) - TPAL_SetPhy10HalfDuplex(adapter); - else if (adapter->AiForceDpx == 2) - TPAL_SetPhy10FullDuplex(adapter); - else - TPAL_SetPhy10Force(adapter); - break; - case 100: - if (adapter->AiForceDpx == 1) - TPAL_SetPhy100HalfDuplex(adapter); - else if (adapter->AiForceDpx == 2) - TPAL_SetPhy100FullDuplex(adapter); - else - TPAL_SetPhy100Force(adapter); - break; - case 1000: - TPAL_SetPhy1000FullDuplex(adapter); - break; - } + MiRead(etdev, PHY_CONTROL, &data); - return status; + if (duplex == TRUEPHY_DUPLEX_FULL) { + /* Set Full Duplex */ + data |= 0x100; + MiWrite(etdev, PHY_CONTROL, data); + } else { + /* Set Half Duplex */ + data &= ~0x100; + MiWrite(etdev, PHY_CONTROL, data); } } -void et131x_Mii_check(struct et131x_adapter *etdev, - MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints) +static void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, u16 speed) { - uint8_t link_status; - uint32_t autoneg_status; - uint32_t speed; - uint32_t duplex; - uint32_t mdi_mdix; - uint32_t masterslave; - uint32_t polarity; - unsigned long flags; + u16 data; - if (bmsr_ints.bits.link_status) { - if (bmsr.bits.link_status) { - etdev->PoMgmt.TransPhyComaModeOnBoot = 20; - - /* Update our state variables and indicate the - * connected state - */ - spin_lock_irqsave(&etdev->Lock, flags); - - etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT; - etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION; + /* Read the PHY control register */ + MiRead(etdev, PHY_CONTROL, &data); - spin_unlock_irqrestore(&etdev->Lock, flags); + /* Clear all Speed settings (Bits 6, 13) */ + data &= ~0x2040; - netif_carrier_on(etdev->netdev); - } else { - dev_warn(&etdev->pdev->dev, - "Link down - cable problem ?\n"); + /* Reset the speed bits based on user selection */ + switch (speed) { + case TRUEPHY_SPEED_10MBPS: + /* Bits already cleared above, do nothing */ + break; - if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { - /* NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) { - */ - uint16_t Register18; + case TRUEPHY_SPEED_100MBPS: + /* 100M == Set bit 13 */ + data |= 0x2000; + break; - MiRead(etdev, 0x12, &Register18); - MiWrite(etdev, 0x12, Register18 | 0x4); - MiWrite(etdev, 0x10, Register18 | 0x8402); - MiWrite(etdev, 0x11, Register18 | 511); - MiWrite(etdev, 0x12, Register18); - } + case TRUEPHY_SPEED_1000MBPS: + default: + data |= 0x0040; + break; + } - /* For the first N seconds of life, we are in "link - * detection" When we are in this state, we should - * only report "connected". When the LinkDetection - * Timer expires, we can report disconnected (handled - * in the LinkDetectionDPC). - */ - if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) || - (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) { - spin_lock_irqsave(&etdev->Lock, flags); - etdev->MediaState = - NETIF_STATUS_MEDIA_DISCONNECT; - spin_unlock_irqrestore(&etdev->Lock, - flags); + /* Write back the new speed */ + MiWrite(etdev, PHY_CONTROL, data); +} - netif_carrier_off(etdev->netdev); - } +static void ET1310_PhyLinkStatus(struct et131x_adapter *etdev, + u8 *link_status, + u32 *autoneg, + u32 *linkspeed, + u32 *duplex_mode, + u32 *mdi_mdix, + u32 *masterslave, u32 *polarity) +{ + u16 mistatus = 0; + u16 is1000BaseT = 0; + u16 vmi_phystatus = 0; + u16 control = 0; - etdev->linkspeed = 0; - etdev->duplex_mode = 0; + MiRead(etdev, PHY_STATUS, &mistatus); + MiRead(etdev, PHY_1000_STATUS, &is1000BaseT); + MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus); + MiRead(etdev, PHY_CONTROL, &control); - /* Free the packets being actively sent & stopped */ - et131x_free_busy_send_packets(etdev); + if (link_status) { + *link_status = + (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0); + } - /* Re-initialize the send structures */ - et131x_init_send(etdev); + if (autoneg) { + *autoneg = + (control & 0x1000) ? ((vmi_phystatus & 0x0020) ? + TRUEPHY_ANEG_COMPLETE : + TRUEPHY_ANEG_NOT_COMPLETE) : + TRUEPHY_ANEG_DISABLED; + } - /* Reset the RFD list and re-start RU */ - et131x_reset_recv(etdev); + if (linkspeed) + *linkspeed = (vmi_phystatus & 0x0300) >> 8; - /* - * Bring the device back to the state it was during - * init prior to autonegotiation being complete. This - * way, when we get the auto-neg complete interrupt, - * we can complete init by calling ConfigMacREGS2. - */ - et131x_soft_reset(etdev); + if (duplex_mode) + *duplex_mode = (vmi_phystatus & 0x0080) >> 7; - /* Setup ET1310 as per the documentation */ - et131x_adapter_setup(etdev); + if (mdi_mdix) + /* NOTE: Need to complete this */ + *mdi_mdix = 0; - /* Setup the PHY into coma mode until the cable is - * plugged back in - */ - if (etdev->RegistryPhyComa == 1) - EnablePhyComa(etdev); - } + if (masterslave) { + *masterslave = + (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER : + TRUEPHY_CFG_SLAVE; } - if (bmsr_ints.bits.auto_neg_complete || - (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) { - if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) { - ET1310_PhyLinkStatus(etdev, - &link_status, &autoneg_status, - &speed, &duplex, &mdi_mdix, - &masterslave, &polarity); + if (polarity) { + *polarity = + (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED : + TRUEPHY_POLARITY_NORMAL; + } +} - etdev->linkspeed = speed; - etdev->duplex_mode = duplex; +static void ET1310_PhyAndOrReg(struct et131x_adapter *etdev, + u16 regnum, u16 andMask, u16 orMask) +{ + u16 reg; - etdev->PoMgmt.TransPhyComaModeOnBoot = 20; + /* Read the requested register */ + MiRead(etdev, regnum, ®); - if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { - /* - * NOTE - Is there a way to query this without - * TruePHY? - * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) { - */ - uint16_t Register18; + /* Apply the AND mask */ + reg &= andMask; - MiRead(etdev, 0x12, &Register18); - MiWrite(etdev, 0x12, Register18 | 0x4); - MiWrite(etdev, 0x10, Register18 | 0x8402); - MiWrite(etdev, 0x11, Register18 | 511); - MiWrite(etdev, 0x12, Register18); - } + /* Apply the OR mask */ + reg |= orMask; - ConfigFlowControl(etdev); + /* Write the value back to the register */ + MiWrite(etdev, regnum, reg); +} - if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS && - etdev->RegistryJumboPacket > 2048) - ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff, - 0x2000); +/* Still used from _mac */ +void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, u16 action, + u16 regnum, u16 bitnum, u8 *value) +{ + u16 reg; + u16 mask = 0; - SetRxDmaTimer(etdev); - ConfigMACRegs2(etdev); - } + /* Create a mask to isolate the requested bit */ + mask = 0x0001 << bitnum; + + /* Read the requested register */ + MiRead(etdev, regnum, ®); + + switch (action) { + case TRUEPHY_BIT_READ: + if (value != NULL) + *value = (reg & mask) >> bitnum; + break; + + case TRUEPHY_BIT_SET: + reg |= mask; + MiWrite(etdev, regnum, reg); + break; + + case TRUEPHY_BIT_CLEAR: + reg &= ~mask; + MiWrite(etdev, regnum, reg); + break; + + default: + break; + } +} + +void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the PHY 1000 Base-T Control Register */ + MiRead(etdev, PHY_1000_CONTROL, &data); + + /* Clear Bits 8,9 */ + data &= ~0x0300; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 9 */ + data |= 0x0200; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 8 */ + data |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + data |= 0x0300; + break; + } + + /* Write back advertisement */ + MiWrite(etdev, PHY_1000_CONTROL, data); +} + +static void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the Autonegotiation Register (10/100) */ + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); + + /* Clear bits 7,8 */ + data &= ~0x0180; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 8 */ + data |= 0x0100; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 7 */ + data |= 0x0080; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + /* Set Bits 7,8 */ + data |= 0x0180; + break; + } + + /* Write back advertisement */ + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); +} + +static void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev, + u16 duplex) +{ + u16 data; + + /* Read the Autonegotiation Register (10/100) */ + MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); + + /* Clear bits 5,6 */ + data &= ~0x0060; + + switch (duplex) { + case TRUEPHY_ADV_DUPLEX_NONE: + /* Duplex already cleared, do nothing */ + break; + + case TRUEPHY_ADV_DUPLEX_FULL: + /* Set Bit 6 */ + data |= 0x0040; + break; + + case TRUEPHY_ADV_DUPLEX_HALF: + /* Set Bit 5 */ + data |= 0x0020; + break; + + case TRUEPHY_ADV_DUPLEX_BOTH: + default: + /* Set Bits 5,6 */ + data |= 0x0060; + break; } + + /* Write back advertisement */ + MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); } + /** * TPAL_SetPhy10HalfDuplex - Force the phy into 10 Base T Half Duplex mode. * @etdev: pointer to the adapter structure * * Also sets the MAC so it is syncd up properly */ -void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev) +static void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -585,7 +625,7 @@ void TPAL_SetPhy10HalfDuplex(struct et13 * * Also sets the MAC so it is syncd up properly */ -void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev) +static void TPAL_SetPhy10FullDuplex(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -606,7 +646,7 @@ void TPAL_SetPhy10FullDuplex(struct et13 * TPAL_SetPhy10Force - Force Base-T FD mode WITHOUT using autonegotiation * @etdev: pointer to the adapter structure */ -void TPAL_SetPhy10Force(struct et131x_adapter *etdev) +static void TPAL_SetPhy10Force(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -635,7 +675,7 @@ void TPAL_SetPhy10Force(struct et131x_ad * * Also sets the MAC so it is syncd up properly. */ -void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev) +static void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -661,7 +701,7 @@ void TPAL_SetPhy100HalfDuplex(struct et1 * * Also sets the MAC so it is syncd up properly */ -void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev) +static void TPAL_SetPhy100FullDuplex(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -682,7 +722,7 @@ void TPAL_SetPhy100FullDuplex(struct et1 * TPAL_SetPhy100Force - Force 100 BaseT FD mode WITHOUT using autonegotiation * @etdev: pointer to the adapter structure */ -void TPAL_SetPhy100Force(struct et131x_adapter *etdev) +static void TPAL_SetPhy100Force(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -711,7 +751,7 @@ void TPAL_SetPhy100Force(struct et131x_a * * Also sets the MAC so it is syncd up properly. */ -void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev) +static void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -732,7 +772,7 @@ void TPAL_SetPhy1000FullDuplex(struct et * TPAL_SetPhyAutoNeg - Set phy to autonegotiation mode. * @etdev: pointer to the adapter structure */ -void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev) +static void TPAL_SetPhyAutoNeg(struct et131x_adapter *etdev) { /* Power down PHY */ ET1310_PhyPowerDown(etdev, 1); @@ -755,56 +795,319 @@ void TPAL_SetPhyAutoNeg(struct et131x_ad } -/* - * The routines which follow provide low-level access to the PHY, and are used - * primarily by the routines above (although there are a few places elsewhere - * in the driver where this level of access is required). + +/** + * et131x_xcvr_init - Init the phy if we are setting it into force mode + * @adapter: pointer to our private adapter structure + * + * Returns 0 on success, errno on failure (as defined in errno.h) */ +static int et131x_xcvr_init(struct et131x_adapter *adapter) +{ + int status = 0; + MI_IMR_t imr; + MI_ISR_t isr; + MI_LCR2_t lcr2; -static const uint16_t ConfigPhy[25][2] = { - /* Reg Value Register */ - /* Addr */ - {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */ - {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */ - {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */ + /* Zero out the adapter structure variable representing BMSR */ + adapter->Bmsr.value = 0; - {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */ - {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */ - {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */ + MiRead(adapter, (u8) offsetof(MI_REGS_t, isr), &isr.value); - {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */ - {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */ - {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */ + MiRead(adapter, (u8) offsetof(MI_REGS_t, imr), &imr.value); - {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */ - {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */ - {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */ + /* Set the link status interrupt only. Bad behavior when link status + * and auto neg are set, we run into a nested interrupt problem + */ + imr.bits.int_en = 0x1; + imr.bits.link_status = 0x1; + imr.bits.autoneg_status = 0x1; - {0x300D, 1}, /* DisableNorm */ + MiWrite(adapter, (u8) offsetof(MI_REGS_t, imr), imr.value); - {0x280C, 0x0180}, /* LinkHoldEnd */ + /* Set the LED behavior such that LED 1 indicates speed (off = + * 10Mbits, blink = 100Mbits, on = 1000Mbits) and LED 2 indicates + * link and activity (on for link, blink off for activity). + * + * NOTE: Some customizations have been added here for specific + * vendors; The LED behavior is now determined by vendor data in the + * EEPROM. However, the above description is the default. + */ + if ((adapter->eepromData[1] & 0x4) == 0) { + MiRead(adapter, (u8) offsetof(MI_REGS_t, lcr2), + &lcr2.value); + if ((adapter->eepromData[1] & 0x8) == 0) + lcr2.bits.led_tx_rx = 0x3; + else + lcr2.bits.led_tx_rx = 0x4; + lcr2.bits.led_link = 0xa; + MiWrite(adapter, (u8) offsetof(MI_REGS_t, lcr2), + lcr2.value); + } - {0x1C21, 0x0002}, /* AlphaM */ + /* Determine if we need to go into a force mode and set it */ + if (adapter->AiForceSpeed == 0 && adapter->AiForceDpx == 0) { + if (adapter->RegistryFlowControl == TxOnly || + adapter->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_SET, 4, 11, NULL); + else + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 11, NULL); - {0x3821, 6}, /* FfeLkgTx0 */ - {0x381D, 1}, /* FfeLkg1g4 */ - {0x381E, 1}, /* FfeLkg1g5 */ - {0x381F, 1}, /* FfeLkg1g6 */ - {0x3820, 1}, /* FfeLkg1g7 */ + if (adapter->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_SET, 4, 10, NULL); + else + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 10, NULL); - {0x8402, 0x01F0}, /* Btinact */ - {0x800E, 20}, /* LftrainTime */ - {0x800F, 24}, /* DvguardTime */ - {0x8010, 46}, /* IdlguardTime */ + /* Set the phy to autonegotiation */ + ET1310_PhyAutoNeg(adapter, true); - {0, 0} + /* NOTE - Do we need this? */ + ET1310_PhyAccessMiBit(adapter, TRUEPHY_BIT_SET, 0, 9, NULL); + return status; + } else { + ET1310_PhyAutoNeg(adapter, false); + + /* Set to the correct force mode. */ + if (adapter->AiForceDpx != 1) { + if (adapter->RegistryFlowControl == TxOnly || + adapter->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_SET, 4, 11, + NULL); + else + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 11, + NULL); + + if (adapter->RegistryFlowControl == Both) + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_SET, 4, 10, + NULL); + else + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 10, + NULL); + } else { + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 10, NULL); + ET1310_PhyAccessMiBit(adapter, + TRUEPHY_BIT_CLEAR, 4, 11, NULL); + } + + switch (adapter->AiForceSpeed) { + case 10: + if (adapter->AiForceDpx == 1) + TPAL_SetPhy10HalfDuplex(adapter); + else if (adapter->AiForceDpx == 2) + TPAL_SetPhy10FullDuplex(adapter); + else + TPAL_SetPhy10Force(adapter); + break; + case 100: + if (adapter->AiForceDpx == 1) + TPAL_SetPhy100HalfDuplex(adapter); + else if (adapter->AiForceDpx == 2) + TPAL_SetPhy100FullDuplex(adapter); + else + TPAL_SetPhy100Force(adapter); + break; + case 1000: + TPAL_SetPhy1000FullDuplex(adapter); + break; + } + + return status; + } +} + +void et131x_Mii_check(struct et131x_adapter *etdev, + MI_BMSR_t bmsr, MI_BMSR_t bmsr_ints) +{ + u8 link_status; + u32 autoneg_status; + u32 speed; + u32 duplex; + u32 mdi_mdix; + u32 masterslave; + u32 polarity; + unsigned long flags; + + if (bmsr_ints.bits.link_status) { + if (bmsr.bits.link_status) { + etdev->PoMgmt.TransPhyComaModeOnBoot = 20; + + /* Update our state variables and indicate the + * connected state + */ + spin_lock_irqsave(&etdev->Lock, flags); + + etdev->MediaState = NETIF_STATUS_MEDIA_CONNECT; + etdev->Flags &= ~fMP_ADAPTER_LINK_DETECTION; + + spin_unlock_irqrestore(&etdev->Lock, flags); + + netif_carrier_on(etdev->netdev); + } else { + dev_warn(&etdev->pdev->dev, + "Link down - cable problem ?\n"); + + if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { + /* NOTE - Is there a way to query this without + * TruePHY? + * && TRU_QueryCoreType(etdev->hTruePhy, 0) == EMI_TRUEPHY_A13O) { + */ + u16 Register18; + + MiRead(etdev, 0x12, &Register18); + MiWrite(etdev, 0x12, Register18 | 0x4); + MiWrite(etdev, 0x10, Register18 | 0x8402); + MiWrite(etdev, 0x11, Register18 | 511); + MiWrite(etdev, 0x12, Register18); + } + + /* For the first N seconds of life, we are in "link + * detection" When we are in this state, we should + * only report "connected". When the LinkDetection + * Timer expires, we can report disconnected (handled + * in the LinkDetectionDPC). + */ + if (!(etdev->Flags & fMP_ADAPTER_LINK_DETECTION) || + (etdev->MediaState == NETIF_STATUS_MEDIA_DISCONNECT)) { + spin_lock_irqsave(&etdev->Lock, flags); + etdev->MediaState = + NETIF_STATUS_MEDIA_DISCONNECT; + spin_unlock_irqrestore(&etdev->Lock, + flags); + + netif_carrier_off(etdev->netdev); + } + + etdev->linkspeed = 0; + etdev->duplex_mode = 0; + + /* Free the packets being actively sent & stopped */ + et131x_free_busy_send_packets(etdev); + + /* Re-initialize the send structures */ + et131x_init_send(etdev); + + /* Reset the RFD list and re-start RU */ + et131x_reset_recv(etdev); + + /* + * Bring the device back to the state it was during + * init prior to autonegotiation being complete. This + * way, when we get the auto-neg complete interrupt, + * we can complete init by calling ConfigMacREGS2. + */ + et131x_soft_reset(etdev); + + /* Setup ET1310 as per the documentation */ + et131x_adapter_setup(etdev); + + /* Setup the PHY into coma mode until the cable is + * plugged back in + */ + if (etdev->RegistryPhyComa == 1) + EnablePhyComa(etdev); + } + } + + if (bmsr_ints.bits.auto_neg_complete || + (etdev->AiForceDpx == 3 && bmsr_ints.bits.link_status)) { + if (bmsr.bits.auto_neg_complete || etdev->AiForceDpx == 3) { + ET1310_PhyLinkStatus(etdev, + &link_status, &autoneg_status, + &speed, &duplex, &mdi_mdix, + &masterslave, &polarity); + + etdev->linkspeed = speed; + etdev->duplex_mode = duplex; + + etdev->PoMgmt.TransPhyComaModeOnBoot = 20; + + if (etdev->linkspeed == TRUEPHY_SPEED_10MBPS) { + /* + * NOTE - Is there a way to query this without + * TruePHY? + * && TRU_QueryCoreType(etdev->hTruePhy, 0)== EMI_TRUEPHY_A13O) { + */ + u16 Register18; + + MiRead(etdev, 0x12, &Register18); + MiWrite(etdev, 0x12, Register18 | 0x4); + MiWrite(etdev, 0x10, Register18 | 0x8402); + MiWrite(etdev, 0x11, Register18 | 511); + MiWrite(etdev, 0x12, Register18); + } + + ConfigFlowControl(etdev); + + if (etdev->linkspeed == TRUEPHY_SPEED_1000MBPS && + etdev->RegistryJumboPacket > 2048) + ET1310_PhyAndOrReg(etdev, 0x16, 0xcfff, + 0x2000); + + SetRxDmaTimer(etdev); + ConfigMACRegs2(etdev); + } + } +} + +/* + * The routines which follow provide low-level access to the PHY, and are used + * primarily by the routines above (although there are a few places elsewhere + * in the driver where this level of access is required). + */ + +static const u16 ConfigPhy[25][2] = { + /* Reg Value Register */ + /* Addr */ + {0x880B, 0x0926}, /* AfeIfCreg4B1000Msbs */ + {0x880C, 0x0926}, /* AfeIfCreg4B100Msbs */ + {0x880D, 0x0926}, /* AfeIfCreg4B10Msbs */ + + {0x880E, 0xB4D3}, /* AfeIfCreg4B1000Lsbs */ + {0x880F, 0xB4D3}, /* AfeIfCreg4B100Lsbs */ + {0x8810, 0xB4D3}, /* AfeIfCreg4B10Lsbs */ + + {0x8805, 0xB03E}, /* AfeIfCreg3B1000Msbs */ + {0x8806, 0xB03E}, /* AfeIfCreg3B100Msbs */ + {0x8807, 0xFF00}, /* AfeIfCreg3B10Msbs */ + + {0x8808, 0xE090}, /* AfeIfCreg3B1000Lsbs */ + {0x8809, 0xE110}, /* AfeIfCreg3B100Lsbs */ + {0x880A, 0x0000}, /* AfeIfCreg3B10Lsbs */ + + {0x300D, 1}, /* DisableNorm */ + + {0x280C, 0x0180}, /* LinkHoldEnd */ + + {0x1C21, 0x0002}, /* AlphaM */ + + {0x3821, 6}, /* FfeLkgTx0 */ + {0x381D, 1}, /* FfeLkg1g4 */ + {0x381E, 1}, /* FfeLkg1g5 */ + {0x381F, 1}, /* FfeLkg1g6 */ + {0x3820, 1}, /* FfeLkg1g7 */ + + {0x8402, 0x01F0}, /* Btinact */ + {0x800E, 20}, /* LftrainTime */ + {0x800F, 24}, /* DvguardTime */ + {0x8010, 46}, /* IdlguardTime */ + + {0, 0} }; /* condensed version of the phy initialization routine */ void ET1310_PhyInit(struct et131x_adapter *etdev) { - uint16_t data, index; + u16 data, index; if (etdev == NULL) return; @@ -869,304 +1172,3 @@ void ET1310_PhyInit(struct et131x_adapte MiWrite(etdev, PHY_MPHY_CONTROL_REG, 0x0002); } -void ET1310_PhyReset(struct et131x_adapter *etdev) -{ - MiWrite(etdev, PHY_CONTROL, 0x8000); -} - -void ET1310_PhyPowerDown(struct et131x_adapter *etdev, bool down) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (down == false) { - /* Power UP */ - data &= ~0x0800; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Power DOWN */ - data |= 0x0800; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhyAutoNeg(struct et131x_adapter *etdev, bool enable) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (enable == true) { - /* Autonegotiation ON */ - data |= 0x1000; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Autonegotiation OFF */ - data &= ~0x1000; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhyDuplexMode(struct et131x_adapter *etdev, uint16_t duplex) -{ - uint16_t data; - - MiRead(etdev, PHY_CONTROL, &data); - - if (duplex == TRUEPHY_DUPLEX_FULL) { - /* Set Full Duplex */ - data |= 0x100; - MiWrite(etdev, PHY_CONTROL, data); - } else { - /* Set Half Duplex */ - data &= ~0x100; - MiWrite(etdev, PHY_CONTROL, data); - } -} - -void ET1310_PhySpeedSelect(struct et131x_adapter *etdev, uint16_t speed) -{ - uint16_t data; - - /* Read the PHY control register */ - MiRead(etdev, PHY_CONTROL, &data); - - /* Clear all Speed settings (Bits 6, 13) */ - data &= ~0x2040; - - /* Reset the speed bits based on user selection */ - switch (speed) { - case TRUEPHY_SPEED_10MBPS: - /* Bits already cleared above, do nothing */ - break; - - case TRUEPHY_SPEED_100MBPS: - /* 100M == Set bit 13 */ - data |= 0x2000; - break; - - case TRUEPHY_SPEED_1000MBPS: - default: - data |= 0x0040; - break; - } - - /* Write back the new speed */ - MiWrite(etdev, PHY_CONTROL, data); -} - -void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the PHY 1000 Base-T Control Register */ - MiRead(etdev, PHY_1000_CONTROL, &data); - - /* Clear Bits 8,9 */ - data &= ~0x0300; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 9 */ - data |= 0x0200; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 8 */ - data |= 0x0100; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - data |= 0x0300; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_1000_CONTROL, data); -} - -void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the Autonegotiation Register (10/100) */ - MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); - - /* Clear bits 7,8 */ - data &= ~0x0180; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 8 */ - data |= 0x0100; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 7 */ - data |= 0x0080; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - /* Set Bits 7,8 */ - data |= 0x0180; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); -} - -void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *etdev, - uint16_t duplex) -{ - uint16_t data; - - /* Read the Autonegotiation Register (10/100) */ - MiRead(etdev, PHY_AUTO_ADVERTISEMENT, &data); - - /* Clear bits 5,6 */ - data &= ~0x0060; - - switch (duplex) { - case TRUEPHY_ADV_DUPLEX_NONE: - /* Duplex already cleared, do nothing */ - break; - - case TRUEPHY_ADV_DUPLEX_FULL: - /* Set Bit 6 */ - data |= 0x0040; - break; - - case TRUEPHY_ADV_DUPLEX_HALF: - /* Set Bit 5 */ - data |= 0x0020; - break; - - case TRUEPHY_ADV_DUPLEX_BOTH: - default: - /* Set Bits 5,6 */ - data |= 0x0060; - break; - } - - /* Write back advertisement */ - MiWrite(etdev, PHY_AUTO_ADVERTISEMENT, data); -} - -void ET1310_PhyLinkStatus(struct et131x_adapter *etdev, - uint8_t *link_status, - uint32_t *autoneg, - uint32_t *linkspeed, - uint32_t *duplex_mode, - uint32_t *mdi_mdix, - uint32_t *masterslave, uint32_t *polarity) -{ - uint16_t mistatus = 0; - uint16_t is1000BaseT = 0; - uint16_t vmi_phystatus = 0; - uint16_t control = 0; - - MiRead(etdev, PHY_STATUS, &mistatus); - MiRead(etdev, PHY_1000_STATUS, &is1000BaseT); - MiRead(etdev, PHY_PHY_STATUS, &vmi_phystatus); - MiRead(etdev, PHY_CONTROL, &control); - - if (link_status) { - *link_status = - (unsigned char)((vmi_phystatus & 0x0040) ? 1 : 0); - } - - if (autoneg) { - *autoneg = - (control & 0x1000) ? ((vmi_phystatus & 0x0020) ? - TRUEPHY_ANEG_COMPLETE : - TRUEPHY_ANEG_NOT_COMPLETE) : - TRUEPHY_ANEG_DISABLED; - } - - if (linkspeed) - *linkspeed = (vmi_phystatus & 0x0300) >> 8; - - if (duplex_mode) - *duplex_mode = (vmi_phystatus & 0x0080) >> 7; - - if (mdi_mdix) - /* NOTE: Need to complete this */ - *mdi_mdix = 0; - - if (masterslave) { - *masterslave = - (is1000BaseT & 0x4000) ? TRUEPHY_CFG_MASTER : - TRUEPHY_CFG_SLAVE; - } - - if (polarity) { - *polarity = - (vmi_phystatus & 0x0400) ? TRUEPHY_POLARITY_INVERTED : - TRUEPHY_POLARITY_NORMAL; - } -} - -void ET1310_PhyAndOrReg(struct et131x_adapter *etdev, - uint16_t regnum, uint16_t andMask, uint16_t orMask) -{ - uint16_t reg; - - /* Read the requested register */ - MiRead(etdev, regnum, ®); - - /* Apply the AND mask */ - reg &= andMask; - - /* Apply the OR mask */ - reg |= orMask; - - /* Write the value back to the register */ - MiWrite(etdev, regnum, reg); -} - -void ET1310_PhyAccessMiBit(struct et131x_adapter *etdev, uint16_t action, - uint16_t regnum, uint16_t bitnum, uint8_t *value) -{ - uint16_t reg; - uint16_t mask = 0; - - /* Create a mask to isolate the requested bit */ - mask = 0x0001 << bitnum; - - /* Read the requested register */ - MiRead(etdev, regnum, ®); - - switch (action) { - case TRUEPHY_BIT_READ: - if (value != NULL) - *value = (reg & mask) >> bitnum; - break; - - case TRUEPHY_BIT_SET: - reg |= mask; - MiWrite(etdev, regnum, reg); - break; - - case TRUEPHY_BIT_CLEAR: - reg &= ~mask; - MiWrite(etdev, regnum, reg); - break; - - default: - break; - } -} --- a/drivers/staging/et131x/et1310_phy.h +++ b/drivers/staging/et131x/et1310_phy.h @@ -739,25 +739,15 @@ typedef union _MI_LCR2_t { /* Forward declaration of the private adapter structure */ struct et131x_adapter; -/* OS Specific Functions*/ -void TPAL_SetPhy10HalfDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy10FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy10Force(struct et131x_adapter *pAdapter); -void TPAL_SetPhy100HalfDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy100FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhy100Force(struct et131x_adapter *pAdapter); -void TPAL_SetPhy1000FullDuplex(struct et131x_adapter *adapter); -void TPAL_SetPhyAutoNeg(struct et131x_adapter *adapter); - /* Prototypes for ET1310_phy.c */ int et131x_xcvr_find(struct et131x_adapter *adapter); int et131x_setphy_normal(struct et131x_adapter *adapter); -int32_t PhyMiRead(struct et131x_adapter *adapter, - u8 xcvrAddr, u8 xcvrReg, u16 *value); /* static inline function does not work because et131x_adapter is not always * defined */ +int PhyMiRead(struct et131x_adapter *adapter, u8 xcvrAddr, + u8 xcvrReg, u16 *value); #define MiRead(adapter, xcvrReg, value) \ PhyMiRead((adapter), (adapter)->Stats.xcvr_addr, (xcvrReg), (value)) @@ -857,24 +847,8 @@ void SetPhy_10BaseTHalfDuplex(struct et1 void ET1310_PhyInit(struct et131x_adapter *adapter); void ET1310_PhyReset(struct et131x_adapter *adapter); void ET1310_PhyPowerDown(struct et131x_adapter *adapter, bool down); -void ET1310_PhyAutoNeg(struct et131x_adapter *adapter, bool enable); -void ET1310_PhyDuplexMode(struct et131x_adapter *adapter, u16 duplex); -void ET1310_PhySpeedSelect(struct et131x_adapter *adapter, u16 speed); void ET1310_PhyAdvertise1000BaseT(struct et131x_adapter *adapter, u16 duplex); -void ET1310_PhyAdvertise100BaseT(struct et131x_adapter *adapter, - u16 duplex); -void ET1310_PhyAdvertise10BaseT(struct et131x_adapter *adapter, - u16 duplex); -void ET1310_PhyLinkStatus(struct et131x_adapter *adapter, - u8 *Link_status, - u32 *autoneg, - u32 *linkspeed, - u32 *duplex_mode, - u32 *mdi_mdix, - u32 *masterslave, u32 *polarity); -void ET1310_PhyAndOrReg(struct et131x_adapter *adapter, - u16 regnum, u16 andMask, u16 orMask); void ET1310_PhyAccessMiBit(struct et131x_adapter *adapter, u16 action, u16 regnum, u16 bitnum, u8 *value);