Updated PHY KSZ8031

Dependents:   EthernetInterface

Files at this revision

API Documentation at this revision

Comitter:
brdarji
Date:
Wed Feb 28 07:22:25 2018 +0000
Parent:
33:44b00841690b
Commit message:
STM32f4 ethernet add ; LPC1768 ethernet kSZ8081 added

Changed in this revision

arch/TARGET_NXP/lpc_phy_ksz8031.c Show diff for this revision Revisions of this file
arch/TARGET_NXP/lpc_phy_ksz8081.c Show annotated file Show diff for this revision Revisions of this file
arch/TARGET_STM/stm32f4_emac.c Show annotated file Show diff for this revision Revisions of this file
diff -r 44b00841690b -r aadfa95d41d2 arch/TARGET_NXP/lpc_phy_ksz8031.c
--- a/arch/TARGET_NXP/lpc_phy_ksz8031.c	Fri Jul 08 11:08:53 2016 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,453 +0,0 @@
-/**********************************************************************
-* $Id$      lpc_phy_ksz8031.c           2016-1-22
-*//**
-* @file     lpc_phy_ksz8031.c
-* @brief    KSZ8031 PHY status and control.
-* @version  1.0
-* @date     22 Jan. 2016
-* @author   Edutech IoT Team
-*
-**********************************************************************/
-
-#include "lwip/opt.h"
-#include "lwip/err.h"
-#include "lwip/tcpip.h"
-#include "lwip/snmp.h"
-#include "lpc_emac_config.h"
-#include "lpc_phy.h"
-#include "lpc17xx_emac.h"
-
-/** @defgroup ksz8031_phy   PHY status and control for the KSZ8031.
- * @ingroup lwip_phy
- *
- * Various functions for controlling and monitoring the status of the
- * KSZ8031 PHY. In polled (standalone) systems, the PHY state must be
- * monitored as part of the application. In a threaded (RTOS) system,
- * the PHY state is monitored by the PHY handler thread. The MAC
- * driver will not transmit unless the PHY link is active.
- * @{
- */
-
-/** \brief  KSZ8031 PHY register offsets */
-#define KSZ_BMCR_REG        0x0  /**< Basic Mode Control Register */
-#define KSZ_BMSR_REG        0x1  /**< Basic Mode Status Reg */
-#define KSZ_IDR1_REG        0x2  /**< Basic Mode Status Reg */
-#define KSZ_IDR2_REG        0x3  /**< Basic Mode Status Reg */
-#define KSZ_ANADV_REG       0x4  /**< Auto_Neg Advt Reg  */
-#define KSZ_ANLPA_REG       0x5  /**< Auto_neg Link Partner Ability Reg */
-#define KSZ_ANEEXP_REG      0x6  /**< Auto-neg Expansion Reg  */
-#define KSZ_PHY_STAT_REG    0x10 /**< PHY Status Register  */
-#define KSZ_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
-#define KSZ_PHY_RBR_REG     0x17 /**< PHY RMII and Bypass Register  */
-#define KSZ_PHY_STS_REG     0x19 /**< PHY Status Register  */
-
-#define KSZ_PHY_SCSR_REG    0x1f /**< PHY Special Control/Status Register (LAN8720)  */
-
-/** \brief KSZ8031 Control register definitions */
-#define KSZ_RESET          (1 << 15)  /**< 1= S/W Reset */
-#define KSZ_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
-#define KSZ_SPEED_SELECT   (1 << 13)  /**< 1=Select 100MBps */
-#define KSZ_AUTONEG        (3 << 12)  /**< 1=Enable auto-negotiation */
-#define KSZ_POWER_DOWN     (1 << 11)  /**< 1=Power down PHY */
-#define KSZ_ISOLATE        (1 << 10)  /**< 1=Isolate PHY */
-#define KSZ_RESTART_AUTONEG (1 << 9)  /**< 1=Restart auto-negoatiation */
-#define KSZ_DUPLEX_MODE    (1 << 8)   /**< 1=Full duplex mode */
-#define KSZ_COLLISION_TEST (1 << 7)   /**< 1=Perform collsion test */
-
-/** \brief KSZ3848 Status register definitions */
-#define KSZ_100BASE_T4     (1 << 15)  /**< T4 mode */
-#define KSZ_100BASE_TX_FD  (1 << 14)  /**< 100MBps full duplex */
-#define KSZ_100BASE_TX_HD  (1 << 13)  /**< 100MBps half duplex */
-#define KSZ_10BASE_T_FD    (1 << 12)  /**< 100Bps full duplex */
-#define KSZ_10BASE_T_HD    (1 << 11)  /**< 10MBps half duplex */
-#define KSZ_MF_PREAMB_SUPPR (1 << 6)  /**< Preamble suppress */
-#define KSZ_AUTONEG_COMP   (1 << 5)   /**< Auto-negotation complete */
-#define KSZ_RMT_FAULT      (1 << 4)   /**< Fault */
-#define KSZ_AUTONEG_ABILITY (1 << 3)  /**< Auto-negotation supported */
-#define KSZ_LINK_STATUS    (1 << 2)   /**< 1=Link active */
-#define KSZ_JABBER_DETECT  (1 << 1)   /**< Jabber detect */
-#define KSZ_EXTEND_CAPAB   (1 << 0)   /**< Supports extended capabilities */
-
-/** \brief KSZ8031 PHY RBR MII dode definitions */
-#define KSZ_RBR_RMII_MODE  (1 << 5)   /**< Use RMII mode */
-
-/** \brief KSZ8031 PHY status definitions */
-#define KSZ_REMOTEFAULT    (1 << 6)   /**< Remote fault */
-#define KSZ_FULLDUPLEX     (1 << 2)   /**< 1=full duplex */
-#define KSZ_SPEED10MBPS    (1 << 1)   /**< 1=10MBps speed */
-#define KSZ_VALID_LINK     (1 << 0)   /**< 1=Link active */
-
-#define KSZ_PHYID1_OUI     0x0022    /**< Expected PHY ID1 */
-#define KSZ_PHYID2_OUI     0x1560     /**< Expected PHY ID2 */
-
-/** \brief LAN8720 PHY Special Control/Status Register */
-#define PHY_SCSR_100MBIT    0x0008    /**< Speed: 1=100 MBit, 0=10Mbit */
-#define PHY_SCSR_DUPLEX     0x0010    /**< PHY Duplex Mask             */
-
-/** \brief Link status bits */
-#define LNK_STAT_VALID       0x01
-#define LNK_STAT_FULLDUPLEX  0x02
-#define LNK_STAT_SPEED10MPS  0x04
-
-/** \brief PHY ID definitions */
-#define KSZ8031_ID         0x00221560  /**< PHY Identifier - KSZ8031 */
-#define LAN8720_ID         0x0007C0F0  /**< PHY Identifier - LAN8720  */
-
-/** \brief PHY status structure used to indicate current status of PHY.
- */
-typedef struct {
-    u32_t     phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
-    u32_t     phy_full_duplex:1;  /**< Half/full duplex connection speed flag. */
-    u32_t     phy_link_active:1;  /**< Phy link active flag. */
-} PHY_STATUS_TYPE;
-
-/** \brief  PHY update flags */
-static PHY_STATUS_TYPE physts;
-
-/** \brief  Last PHY update flags, used for determing if something has changed */
-static PHY_STATUS_TYPE olddphysts;
-
-/** \brief  PHY update counter for state machine */
-static s32_t phyustate;
-
-/** \brief  Holds the PHY ID */
-static u32_t phy_id;
-
-/** \brief  Temporary holder of link status for LAN7420 */
-static u32_t phy_lan7420_sts_tmp;
-
-/* Write a value via the MII link (non-blocking) */
-void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
-{
-    /* Write value at PHY address and register */
-    LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
-    LPC_EMAC->MWTD = Value;
-}
-
-/* Write a value via the MII link (blocking) */
-err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
-{
-    u32_t mst = 250;
-    err_t sts = ERR_OK;
-
-    /* Write value at PHY address and register */
-    lpc_mii_write_noblock(PhyReg, Value);
-
-    /* Wait for unbusy status */
-    while (mst > 0) {
-        sts = LPC_EMAC->MIND;
-        if ((sts & EMAC_MIND_BUSY) == 0)
-            mst = 0;
-        else {
-            mst--;
-            osDelay(1);
-        }
-    }
-
-    if (sts != 0)
-        sts = ERR_TIMEOUT;
-
-    return sts;
-}
-
-/* Reads current MII link busy status */
-u32_t lpc_mii_is_busy(void)
-{
-    return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
-}
-
-/* Starts a read operation via the MII link (non-blocking) */
-u32_t lpc_mii_read_data(void)
-{
-    u32_t data = LPC_EMAC->MRDD;
-    LPC_EMAC->MCMD = 0;
-
-    return data;
-}
-
-/* Starts a read operation via the MII link (non-blocking) */
-void lpc_mii_read_noblock(u32_t PhyReg)
-{
-    /* Read value at PHY address and register */
-    LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
-    LPC_EMAC->MCMD = EMAC_MCMD_READ;
-}
-
-/* Read a value via the MII link (blocking) */
-err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
-{
-    u32_t mst = 250;
-    err_t sts = ERR_OK;
-
-    /* Read value at PHY address and register */
-    lpc_mii_read_noblock(PhyReg);
-
-    /* Wait for unbusy status */
-    while (mst > 0) {
-        sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
-        if ((sts & EMAC_MIND_BUSY) == 0) {
-            mst = 0;
-            *data = LPC_EMAC->MRDD;
-        } else {
-            mst--;
-            osDelay(1);
-        }
-    }
-
-    LPC_EMAC->MCMD = 0;
-
-    if (sts != 0)
-        sts = ERR_TIMEOUT;
-
-    return sts;
-}
-
-
-/** \brief  Update PHY status from passed value
- *
- *  This function updates the current PHY status based on the
- *  passed PHY status word. The PHY status indicate if the link
- *  is active, the connection speed, and duplex.
- *
- *  \param[in]    netif   NETIF structure
- *  \param[in]    linksts Status word from PHY
- *  \return        1 if the status has changed, otherwise 0
- */
-static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
-{
-    s32_t changed = 0;
-
-    /* Update link active status */
-    if (linksts & LNK_STAT_VALID)
-        physts.phy_link_active = 1;
-    else
-        physts.phy_link_active = 0;
-
-    /* Full or half duplex */
-    if (linksts & LNK_STAT_FULLDUPLEX)
-        physts.phy_full_duplex = 1;
-    else
-        physts.phy_full_duplex = 0;
-
-    /* Configure 100MBit/10MBit mode. */
-    if (linksts & LNK_STAT_SPEED10MPS)
-        physts.phy_speed_100mbs = 0;
-    else
-        physts.phy_speed_100mbs = 1;
-
-    if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
-        changed = 1;
-        if (physts.phy_speed_100mbs) {
-            /* 100MBit mode. */
-            lpc_emac_set_speed(1);
-
-            NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
-        }
-        else {
-            /* 10MBit mode. */
-            lpc_emac_set_speed(0);
-
-            NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
-        }
-
-        olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
-    }
-
-    if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
-        changed = 1;
-        if (physts.phy_full_duplex)
-            lpc_emac_set_duplex(1);
-        else
-            lpc_emac_set_duplex(0);
-
-        olddphysts.phy_full_duplex = physts.phy_full_duplex;
-    }
-
-    if (physts.phy_link_active != olddphysts.phy_link_active) {
-        changed = 1;
-#if NO_SYS == 1
-        if (physts.phy_link_active)
-            netif_set_link_up(netif);
-        else
-            netif_set_link_down(netif);
-#else
-        if (physts.phy_link_active)
-            tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
-                (void*) netif, 1);
-         else
-            tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
-                (void*) netif, 1);
-#endif
-
-        olddphysts.phy_link_active = physts.phy_link_active;
-    }
-
-    return changed;
-}
-
-/** \brief  Initialize the KSZ8031 PHY.
- *
- *  This function initializes the KSZ8031 PHY. It will block until
- *  complete. This function is called as part of the EMAC driver
- *  initialization. Configuration of the PHY at startup is
- *  controlled by setting up configuration defines in lpc_phy.h.
- *
- *  \param[in]     netif   NETIF structure
- *  \param[in]     rmii    If set, configures the PHY for RMII mode
- *  \return         ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
- */
-err_t lpc_phy_init(struct netif *netif, int rmii)
-{
-    u32_t tmp;
-    s32_t i;
-
-    physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
-    physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
-    physts.phy_link_active = olddphysts.phy_link_active = 0;
-    phyustate = 0;
-
-    /* Only first read and write are checked for failure */
-    /* Put the KSZ8031 in reset mode and wait for completion */
-    if (lpc_mii_write(KSZ_BMCR_REG, KSZ_RESET) != 0)
-        return ERR_TIMEOUT;
-    i = 400;
-    while (i > 0) {
-        osDelay(1);   /* 1 ms */
-        if (lpc_mii_read(KSZ_BMCR_REG, &tmp) != 0)
-            return ERR_TIMEOUT;
-
-        if (!(tmp & (KSZ_RESET | KSZ_POWER_DOWN)))
-            i = -1;
-        else
-            i--;
-    }
-    /* Timeout? */
-    if (i == 0)
-        return ERR_TIMEOUT;
-
-    // read PHY ID
-    lpc_mii_read(KSZ_IDR1_REG, &tmp);
-    phy_id = (tmp << 16);
-    lpc_mii_read(KSZ_IDR2_REG, &tmp);
-    phy_id |= (tmp & 0XFFF0);
-
-    /* Setup link based on configuration options */
-#if PHY_USE_AUTONEG==1
-    tmp = KSZ_AUTONEG;
-#else
-    tmp = 0;
-#endif
-#if PHY_USE_100MBS==1
-    tmp |= KSZ_SPEED_SELECT;
-#endif
-#if PHY_USE_FULL_DUPLEX==1
-    tmp |= KSZ_DUPLEX_MODE;
-#endif
-    lpc_mii_write(KSZ_BMCR_REG, tmp);
-
-    /* Wait for autonegotiation completion */
-    int j = 1000;
-    while (j > 0)
-    {
-        osDelay(1);   // 1 ms
-        if (lpc_mii_read(KSZ_BMSR_REG, &tmp) != 0)
-        {
-            return ERR_TIMEOUT;
-        }
-        if (tmp & (KSZ_AUTONEG_COMP))
-            j = -1;
-        else
-            j--;
-    }
-    // Timeout?
-    if (j == 0)
-    {
-        printf("Timeout\n");
-        return ERR_TIMEOUT;
-    }
-
-    /* The link is not set active at this point, but will be detected
-       later */
-
-    return ERR_OK;
-}
-
-/* Phy status update state machine */
-s32_t lpc_phy_sts_sm(struct netif *netif)
-{
-    s32_t changed = 0;
-    u32_t data = 0;
-    u32_t tmp,tmp1;
-
-    switch (phyustate) {
-        default:
-        case 0:
-            if (phy_id == KSZ8031_ID) {
-                lpc_mii_read(KSZ_BMSR_REG, &tmp);
-                /* To Debug Link Status */
-//              if (tmp & LNK_STAT_VALID)
-//              {
-//                  /* Link is on. */
-//                  printf("Link is UP\n\r");
-//              }
-                phyustate = 2;
-            }
-            else if (phy_id == LAN8720_ID) {
-                lpc_mii_read_noblock(KSZ_PHY_SCSR_REG);
-                phyustate = 1;
-            }
-            break;
-
-        case 1:
-            if (phy_id == LAN8720_ID) {
-                tmp = lpc_mii_read_data();
-                // we get speed and duplex here
-                phy_lan7420_sts_tmp =  (tmp & PHY_SCSR_DUPLEX)  ? LNK_STAT_FULLDUPLEX : 0;
-                phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
-
-                //read the status register to get link status
-                lpc_mii_read_noblock(KSZ_BMSR_REG);
-                phyustate = 2;
-            }
-            break;
-
-        case 2:
-            /* Wait for read status state */
-            if (!lpc_mii_is_busy()) {
-                /* Update PHY status */
-                tmp = lpc_mii_read_data();
-
-                if (phy_id == KSZ8031_ID) {
-                    // Get autonegotiation complete bit
-                    lpc_mii_read(KSZ_BMSR_REG,&tmp1);
-                    /* To Debug Auto-negotiation */
-//                  if (tmp1 & KSZ_AUTONEG_COMP)
-//                  {
-//                      /* Auto-negotiation Complete. */
-//                      printf("Auto-negotiation has completed\n\r");
-//                  }
-                    // STS register contains all needed status bits
-                    data  = (tmp & KSZ_VALID_LINK) ? LNK_STAT_VALID : 0;
-                    data |= (tmp & KSZ_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
-                    data |= (tmp & KSZ_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
-                }
-                else if (phy_id == LAN8720_ID) {
-                    // we only get the link status here.
-                    phy_lan7420_sts_tmp |= (tmp & KSZ_LINK_STATUS) ? LNK_STAT_VALID : 0;
-                    data = phy_lan7420_sts_tmp;
-                }
-
-                changed = lpc_update_phy_sts(netif, data);
-                phyustate = 0;
-            }
-            break;
-    }
-
-    return changed;
-}
-
-/**
- * @}
- */
-
-/* --------------------------------- End Of File ------------------------------ */
diff -r 44b00841690b -r aadfa95d41d2 arch/TARGET_NXP/lpc_phy_ksz8081.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arch/TARGET_NXP/lpc_phy_ksz8081.c	Wed Feb 28 07:22:25 2018 +0000
@@ -0,0 +1,461 @@
+/**********************************************************************
+* $Id$      lpc_phy_ksz8031.c           2016-1-22
+*//**
+* @file     lpc_phy_ksz8031.c
+* @brief    KSZ8031 PHY status and control.
+* @version  1.0
+* @date     22 Jan. 2016
+* @author   Edutech IoT Team
+*
+**********************************************************************/
+
+#include "lwip/opt.h"
+#include "lwip/err.h"
+#include "lwip/tcpip.h"
+#include "lwip/snmp.h"
+#include "lpc_emac_config.h"
+#include "lpc_phy.h"
+#include "lpc17xx_emac.h"
+
+/** @defgroup ksz8031_phy   PHY status and control for the KSZ8031.
+ * @ingroup lwip_phy
+ *
+ * Various functions for controlling and monitoring the status of the
+ * KSZ8031 PHY. In polled (standalone) systems, the PHY state must be
+ * monitored as part of the application. In a threaded (RTOS) system,
+ * the PHY state is monitored by the PHY handler thread. The MAC
+ * driver will not transmit unless the PHY link is active.
+ * @{
+ */
+
+/** \brief  KSZ8031 PHY register offsets */
+#define KSZ_BMCR_REG        0x0  /**< Basic Mode Control Register */
+#define KSZ_BMSR_REG        0x1  /**< Basic Mode Status Reg */
+#define KSZ_IDR1_REG        0x2  /**< Basic Mode Status Reg */
+#define KSZ_IDR2_REG        0x3  /**< Basic Mode Status Reg */
+#define KSZ_ANADV_REG       0x4  /**< Auto_Neg Advt Reg  */
+#define KSZ_ANLPA_REG       0x5  /**< Auto_neg Link Partner Ability Reg */
+#define KSZ_ANEEXP_REG      0x6  /**< Auto-neg Expansion Reg  */
+#define KSZ_PHY_STAT_REG    0x10 /**< PHY Status Register  */
+#define KSZ_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
+#define KSZ_PHY_RBR_REG     0x17 /**< PHY RMII and Bypass Register  */
+#define KSZ_PHY_STS_REG     0x19 /**< PHY Status Register  */
+
+#define KSZ_PHY_SCSR_REG    0x1f /**< PHY Special Control/Status Register (LAN8720)  */
+
+/** \brief KSZ8031 Control register definitions */
+#define KSZ_RESET          (1 << 15)  /**< 1= S/W Reset */
+#define KSZ_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
+#define KSZ_SPEED_SELECT   (1 << 13)  /**< 1=Select 100MBps */
+#define KSZ_AUTONEG        (3 << 12)  /**< 1=Enable auto-negotiation */
+#define KSZ_POWER_DOWN     (1 << 11)  /**< 1=Power down PHY */
+#define KSZ_ISOLATE        (1 << 10)  /**< 1=Isolate PHY */
+#define KSZ_RESTART_AUTONEG (1 << 9)  /**< 1=Restart auto-negoatiation */
+#define KSZ_DUPLEX_MODE    (1 << 8)   /**< 1=Full duplex mode */
+#define KSZ_COLLISION_TEST (1 << 7)   /**< 1=Perform collsion test */
+
+/** \brief KSZ3848 Status register definitions */
+#define KSZ_100BASE_T4     (1 << 15)  /**< T4 mode */
+#define KSZ_100BASE_TX_FD  (1 << 14)  /**< 100MBps full duplex */
+#define KSZ_100BASE_TX_HD  (1 << 13)  /**< 100MBps half duplex */
+#define KSZ_10BASE_T_FD    (1 << 12)  /**< 100Bps full duplex */
+#define KSZ_10BASE_T_HD    (1 << 11)  /**< 10MBps half duplex */
+#define KSZ_MF_PREAMB_SUPPR (1 << 6)  /**< Preamble suppress */
+#define KSZ_AUTONEG_COMP   (1 << 5)   /**< Auto-negotation complete */
+#define KSZ_RMT_FAULT      (1 << 4)   /**< Fault */
+#define KSZ_AUTONEG_ABILITY (1 << 3)  /**< Auto-negotation supported */
+#define KSZ_LINK_STATUS    (1 << 2)   /**< 1=Link active */
+#define KSZ_JABBER_DETECT  (1 << 1)   /**< Jabber detect */
+#define KSZ_EXTEND_CAPAB   (1 << 0)   /**< Supports extended capabilities */
+
+/** \brief KSZ8031 PHY RBR MII dode definitions */
+#define KSZ_RBR_RMII_MODE  (1 << 5)   /**< Use RMII mode */
+
+/** \brief KSZ8031 PHY status definitions */
+#define KSZ_REMOTEFAULT    (1 << 6)   /**< Remote fault */
+#define KSZ_FULLDUPLEX     (1 << 2)   /**< 1=full duplex */
+#define KSZ_SPEED10MBPS    (1 << 1)   /**< 1=10MBps speed */
+#define KSZ_VALID_LINK     (1 << 0)   /**< 1=Link active */
+
+//KSZ8081
+#define KSZ_PHYID1_OUI     0x0022    /**< Expected PHY ID1 */
+#define KSZ_PHYID2_OUI     0x1560     /**< Expected PHY ID2 */
+
+
+//KSZ8031
+//#define KSZ_PHYID1_OUI     0x0022    /**< Expected PHY ID1 */
+//#define KSZ_PHYID2_OUI     0x1550     /**< Expected PHY ID2 */
+
+
+/** \brief LAN8720 PHY Special Control/Status Register */
+#define PHY_SCSR_100MBIT    0x0008    /**< Speed: 1=100 MBit, 0=10Mbit */
+#define PHY_SCSR_DUPLEX     0x0010    /**< PHY Duplex Mask             */
+
+/** \brief Link status bits */
+#define LNK_STAT_VALID       0x01
+#define LNK_STAT_FULLDUPLEX  0x02
+#define LNK_STAT_SPEED10MPS  0x04
+
+/** \brief PHY ID definitions */
+//#define KSZ8031_ID         0x00221550  /**< PHY Identifier - KSZ8031 */
+#define KSZ8081_ID         0x00221560  /**< PHY Identifier - KSZ8081 */
+#define LAN8720_ID         0x0007C0F0  /**< PHY Identifier - LAN8720  */
+
+/** \brief PHY status structure used to indicate current status of PHY.
+ */
+typedef struct {
+    u32_t     phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
+    u32_t     phy_full_duplex:1;  /**< Half/full duplex connection speed flag. */
+    u32_t     phy_link_active:1;  /**< Phy link active flag. */
+} PHY_STATUS_TYPE;
+
+/** \brief  PHY update flags */
+static PHY_STATUS_TYPE physts;
+
+/** \brief  Last PHY update flags, used for determing if something has changed */
+static PHY_STATUS_TYPE olddphysts;
+
+/** \brief  PHY update counter for state machine */
+static s32_t phyustate;
+
+/** \brief  Holds the PHY ID */
+static u32_t phy_id;
+
+/** \brief  Temporary holder of link status for LAN7420 */
+static u32_t phy_lan7420_sts_tmp;
+
+/* Write a value via the MII link (non-blocking) */
+void lpc_mii_write_noblock(u32_t PhyReg, u32_t Value)
+{
+    /* Write value at PHY address and register */
+    LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
+    LPC_EMAC->MWTD = Value;
+}
+
+/* Write a value via the MII link (blocking) */
+err_t lpc_mii_write(u32_t PhyReg, u32_t Value)
+{
+    u32_t mst = 250;
+    err_t sts = ERR_OK;
+
+    /* Write value at PHY address and register */
+    lpc_mii_write_noblock(PhyReg, Value);
+
+    /* Wait for unbusy status */
+    while (mst > 0) {
+        sts = LPC_EMAC->MIND;
+        if ((sts & EMAC_MIND_BUSY) == 0)
+            mst = 0;
+        else {
+            mst--;
+            osDelay(1);
+        }
+    }
+
+    if (sts != 0)
+        sts = ERR_TIMEOUT;
+
+    return sts;
+}
+
+/* Reads current MII link busy status */
+u32_t lpc_mii_is_busy(void)
+{
+    return (u32_t) (LPC_EMAC->MIND & EMAC_MIND_BUSY);
+}
+
+/* Starts a read operation via the MII link (non-blocking) */
+u32_t lpc_mii_read_data(void)
+{
+    u32_t data = LPC_EMAC->MRDD;
+    LPC_EMAC->MCMD = 0;
+
+    return data;
+}
+
+/* Starts a read operation via the MII link (non-blocking) */
+void lpc_mii_read_noblock(u32_t PhyReg)
+{
+    /* Read value at PHY address and register */
+    LPC_EMAC->MADR = (LPC_PHYDEF_PHYADDR << 8) | PhyReg;
+    LPC_EMAC->MCMD = EMAC_MCMD_READ;
+}
+
+/* Read a value via the MII link (blocking) */
+err_t lpc_mii_read(u32_t PhyReg, u32_t *data)
+{
+    u32_t mst = 250;
+    err_t sts = ERR_OK;
+
+    /* Read value at PHY address and register */
+    lpc_mii_read_noblock(PhyReg);
+
+    /* Wait for unbusy status */
+    while (mst > 0) {
+        sts = LPC_EMAC->MIND & ~EMAC_MIND_MII_LINK_FAIL;
+        if ((sts & EMAC_MIND_BUSY) == 0) {
+            mst = 0;
+            *data = LPC_EMAC->MRDD;
+        } else {
+            mst--;
+            osDelay(1);
+        }
+    }
+
+    LPC_EMAC->MCMD = 0;
+
+    if (sts != 0)
+        sts = ERR_TIMEOUT;
+
+    return sts;
+}
+
+
+/** \brief  Update PHY status from passed value
+ *
+ *  This function updates the current PHY status based on the
+ *  passed PHY status word. The PHY status indicate if the link
+ *  is active, the connection speed, and duplex.
+ *
+ *  \param[in]    netif   NETIF structure
+ *  \param[in]    linksts Status word from PHY
+ *  \return        1 if the status has changed, otherwise 0
+ */
+static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
+{
+    s32_t changed = 0;
+
+    /* Update link active status */
+    if (linksts & LNK_STAT_VALID)
+        physts.phy_link_active = 1;
+    else
+        physts.phy_link_active = 0;
+
+    /* Full or half duplex */
+    if (linksts & LNK_STAT_FULLDUPLEX)
+        physts.phy_full_duplex = 1;
+    else
+        physts.phy_full_duplex = 0;
+
+    /* Configure 100MBit/10MBit mode. */
+    if (linksts & LNK_STAT_SPEED10MPS)
+        physts.phy_speed_100mbs = 0;
+    else
+        physts.phy_speed_100mbs = 1;
+
+    if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
+        changed = 1;
+        if (physts.phy_speed_100mbs) {
+            /* 100MBit mode. */
+            lpc_emac_set_speed(1);
+
+            NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
+        }
+        else {
+            /* 10MBit mode. */
+            lpc_emac_set_speed(0);
+
+            NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
+        }
+
+        olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
+    }
+
+    if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
+        changed = 1;
+        if (physts.phy_full_duplex)
+            lpc_emac_set_duplex(1);
+        else
+            lpc_emac_set_duplex(0);
+
+        olddphysts.phy_full_duplex = physts.phy_full_duplex;
+    }
+
+    if (physts.phy_link_active != olddphysts.phy_link_active) {
+        changed = 1;
+#if NO_SYS == 1
+        if (physts.phy_link_active)
+            netif_set_link_up(netif);
+        else
+            netif_set_link_down(netif);
+#else
+        if (physts.phy_link_active)
+            tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
+                (void*) netif, 1);
+         else
+            tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
+                (void*) netif, 1);
+#endif
+
+        olddphysts.phy_link_active = physts.phy_link_active;
+    }
+
+    return changed;
+}
+
+/** \brief  Initialize the KSZ8031 PHY.
+ *
+ *  This function initializes the KSZ8031 PHY. It will block until
+ *  complete. This function is called as part of the EMAC driver
+ *  initialization. Configuration of the PHY at startup is
+ *  controlled by setting up configuration defines in lpc_phy.h.
+ *
+ *  \param[in]     netif   NETIF structure
+ *  \param[in]     rmii    If set, configures the PHY for RMII mode
+ *  \return         ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
+ */
+err_t lpc_phy_init(struct netif *netif, int rmii)
+{
+    u32_t tmp;
+    s32_t i;
+
+    physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 0;
+    physts.phy_full_duplex = olddphysts.phy_full_duplex = 0;
+    physts.phy_link_active = olddphysts.phy_link_active = 0;
+    phyustate = 0;
+
+    /* Only first read and write are checked for failure */
+    /* Put the KSZ8031 in reset mode and wait for completion */
+    if (lpc_mii_write(KSZ_BMCR_REG, KSZ_RESET) != 0)
+        return ERR_TIMEOUT;
+    i = 400;
+    while (i > 0) {
+        osDelay(1);   /* 1 ms */
+        if (lpc_mii_read(KSZ_BMCR_REG, &tmp) != 0)
+            return ERR_TIMEOUT;
+
+        if (!(tmp & (KSZ_RESET | KSZ_POWER_DOWN)))
+            i = -1;
+        else
+            i--;
+    }
+    /* Timeout? */
+    if (i == 0)
+        return ERR_TIMEOUT;
+
+    // read PHY ID
+    lpc_mii_read(KSZ_IDR1_REG, &tmp);
+    phy_id = (tmp << 16);
+    lpc_mii_read(KSZ_IDR2_REG, &tmp);
+    phy_id |= (tmp & 0XFFF0);
+
+    /* Setup link based on configuration options */
+#if PHY_USE_AUTONEG==1
+    tmp = KSZ_AUTONEG;
+#else
+    tmp = 0;
+#endif
+#if PHY_USE_100MBS==1
+    tmp |= KSZ_SPEED_SELECT;
+#endif
+#if PHY_USE_FULL_DUPLEX==1
+    tmp |= KSZ_DUPLEX_MODE;
+#endif
+    lpc_mii_write(KSZ_BMCR_REG, tmp);
+
+    /* Wait for autonegotiation completion */
+    int j = 1000;
+    while (j > 0)
+    {
+        osDelay(1);   // 1 ms
+        if (lpc_mii_read(KSZ_BMSR_REG, &tmp) != 0)
+        {
+            return ERR_TIMEOUT;
+        }
+        if (tmp & (KSZ_AUTONEG_COMP))
+            j = -1;
+        else
+            j--;
+    }
+    // Timeout?
+    if (j == 0)
+    {
+        printf("Timeout\n");
+        return ERR_TIMEOUT;
+    }
+
+    /* The link is not set active at this point, but will be detected
+       later */
+
+    return ERR_OK;
+}
+
+/* Phy status update state machine */
+s32_t lpc_phy_sts_sm(struct netif *netif)
+{
+    s32_t changed = 0;
+    u32_t data = 0;
+    u32_t tmp,tmp1;
+
+    switch (phyustate) {
+        default:
+        case 0:
+            if (phy_id == KSZ8081_ID) {
+                lpc_mii_read(KSZ_BMSR_REG, &tmp);
+                /* To Debug Link Status */
+//              if (tmp & LNK_STAT_VALID)
+//              {
+//                  /* Link is on. */
+//                  printf("Link is UP\n\r");
+//              }
+                phyustate = 2;
+            }
+            else if (phy_id == LAN8720_ID) {
+                lpc_mii_read_noblock(KSZ_PHY_SCSR_REG);
+                phyustate = 1;
+            }
+            break;
+
+        case 1:
+            if (phy_id == LAN8720_ID) {
+                tmp = lpc_mii_read_data();
+                // we get speed and duplex here
+                phy_lan7420_sts_tmp =  (tmp & PHY_SCSR_DUPLEX)  ? LNK_STAT_FULLDUPLEX : 0;
+                phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
+
+                //read the status register to get link status
+                lpc_mii_read_noblock(KSZ_BMSR_REG);
+                phyustate = 2;
+            }
+            break;
+
+        case 2:
+            /* Wait for read status state */
+            if (!lpc_mii_is_busy()) {
+                /* Update PHY status */
+                tmp = lpc_mii_read_data();
+
+                if (phy_id == KSZ8081_ID) {
+                    // Get autonegotiation complete bit
+                    lpc_mii_read(KSZ_BMSR_REG,&tmp1);
+                    /* To Debug Auto-negotiation */
+//                  if (tmp1 & KSZ_AUTONEG_COMP)
+//                  {
+//                      /* Auto-negotiation Complete. */
+//                      printf("Auto-negotiation has completed\n\r");
+//                  }
+                    // STS register contains all needed status bits
+                    data  = (tmp & KSZ_VALID_LINK) ? LNK_STAT_VALID : 0;
+                    data |= (tmp & KSZ_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
+                    data |= (tmp & KSZ_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
+                }
+                else if (phy_id == LAN8720_ID) {
+                    // we only get the link status here.
+                    phy_lan7420_sts_tmp |= (tmp & KSZ_LINK_STATUS) ? LNK_STAT_VALID : 0;
+                    data = phy_lan7420_sts_tmp;
+                }
+
+                changed = lpc_update_phy_sts(netif, data);
+                phyustate = 0;
+            }
+            break;
+    }
+
+    return changed;
+}
+
+/**
+ * @}
+ */
+
+/* --------------------------------- End Of File ------------------------------ */
diff -r 44b00841690b -r aadfa95d41d2 arch/TARGET_STM/stm32f4_emac.c
--- a/arch/TARGET_STM/stm32f4_emac.c	Fri Jul 08 11:08:53 2016 +0000
+++ b/arch/TARGET_STM/stm32f4_emac.c	Wed Feb 28 07:22:25 2018 +0000
@@ -57,11 +57,14 @@
  */
 void HAL_ETH_MspInit(ETH_HandleTypeDef* heth)
 {
+    uint8_t i=0;
+    
     GPIO_InitTypeDef GPIO_InitStruct;
     if (heth->Instance == ETH) {
         /* Peripheral clock enable */
         __ETH_CLK_ENABLE();
 
+		__GPIOE_CLK_ENABLE();
         __GPIOA_CLK_ENABLE();
         __GPIOB_CLK_ENABLE();
         __GPIOC_CLK_ENABLE();
@@ -76,6 +79,7 @@
            PB11     ------> ETH_TX_EN
            PB12     ------> ETH_TXD0
            PB13     ------> ETH_TXD1
+           PE2		------> ETH_RST
          */
         GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
@@ -98,6 +102,18 @@
         GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
 
+	    /*Configure GPIO pin : PE2 */
+	    GPIO_InitStruct.Pin = GPIO_PIN_2;
+	    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
+	    GPIO_InitStruct.Pull = GPIO_PULLUP;
+	    GPIO_InitStruct.Speed = GPIO_SPEED_FAST;
+	    HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
+    
+		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_RESET);
+		for (i = 0; i < 100; i++);
+		HAL_GPIO_WritePin(GPIOE, GPIO_PIN_2, GPIO_PIN_SET);
+		for (i = 0; i < 100; i++);
+
         /* Peripheral interrupt init*/
         /* Sets the priority grouping field */
         HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
@@ -181,7 +197,7 @@
     heth.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
     heth.Init.Speed = ETH_SPEED_10M;
     heth.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
-    heth.Init.PhyAddress = 1;
+    heth.Init.PhyAddress = 0;
 #if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
     MACAddr[0] = MBED_MAC_ADDR_0;
     MACAddr[1] = MBED_MAC_ADDR_1;