KEIS

Dependents:   EthernetInterface_t

Fork of lwip-eth by mbed official

Revision:
5:698d868a5285
Parent:
4:d827a085afd9
Child:
7:8938486fccab
--- a/arch/lpc_phy_dp83848.c	Fri Mar 01 15:30:33 2013 +0000
+++ b/arch/lpc_phy_dp83848.c	Thu May 30 17:15:45 2013 +0100
@@ -1,11 +1,11 @@
 /**********************************************************************
-* $Id$        lpc_phy_dp83848.c            2011-11-20
+* $Id$		lpc_phy_dp83848.c			2011-11-20
 *//**
-* @file        lpc_phy_dp83848.c
-* @brief    DP83848C PHY status and control.
-* @version    1.0
-* @date        20 Nov. 2011
-* @author    NXP MCU SW Application Team
+* @file		lpc_phy_dp83848.c
+* @brief	DP83848C PHY status and control.
+* @version	1.0
+* @date		20 Nov. 2011
+* @author	NXP MCU SW Application Team
 *
 * Copyright(C) 2011, NXP Semiconductor
 * All rights reserved.
@@ -30,7 +30,7 @@
 #include "lpc_emac_config.h"
 #include "lpc_phy.h"
 
-/** @defgroup dp83848_phy    PHY status and control for the DP83848.
+/** @defgroup dp83848_phy	PHY status and control for the DP83848.
  * @ingroup lwip_phy
  *
  * Various functions for controlling and monitoring the status of the
@@ -44,6 +44,8 @@
 /** \brief  DP83848 PHY register offsets */
 #define DP8_BMCR_REG        0x0  /**< Basic Mode Control Register */
 #define DP8_BMSR_REG        0x1  /**< Basic Mode Status Reg */
+#define DP8_IDR1_REG        0x2  /**< Basic Mode Status Reg */
+#define DP8_IDR2_REG        0x3  /**< Basic Mode Status Reg */
 #define DP8_ANADV_REG       0x4  /**< Auto_Neg Advt Reg  */
 #define DP8_ANLPA_REG       0x5  /**< Auto_neg Link Partner Ability Reg */
 #define DP8_ANEEXP_REG      0x6  /**< Auto-neg Expansion Reg  */
@@ -52,6 +54,8 @@
 #define DP8_PHY_RBR_REG     0x17 /**< PHY RMII and Bypass Register  */
 #define DP8_PHY_STS_REG     0x19 /**< PHY Status Register  */
 
+#define DP8_PHY_SCSR_REG    0x1f /**< PHY Special Control/Status Register (LAN8720)  */
+
 /** \brief DP83848 Control register definitions */
 #define DP8_RESET          (1 << 15)  /**< 1= S/W Reset */
 #define DP8_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
@@ -90,12 +94,25 @@
 #define DP8_PHYID1_OUI     0x2000     /**< Expected PHY ID1 */
 #define DP8_PHYID2_OUI     0x5c90     /**< 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 DP83848C_ID         0x20005C90  /**< PHY Identifier - DP83848C */
+#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. */
+	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 */
@@ -107,6 +124,12 @@
 /** \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;
+
 /** \brief  Update PHY status from passed value
  *
  *  This function updates the current PHY status based on the
@@ -119,61 +142,61 @@
  */
 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
 {
-    s32_t changed = 0;
+	s32_t changed = 0;
 
-    /* Update link active status */
-    if (linksts & DP8_VALID_LINK)
-        physts.phy_link_active = 1;
-    else
-        physts.phy_link_active = 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 & DP8_FULLDUPLEX)
-        physts.phy_full_duplex = 1;
-    else
-        physts.phy_full_duplex = 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 & DP8_SPEED10MBPS)
-        physts.phy_speed_100mbs = 0;
-    else
-        physts.phy_speed_100mbs = 1;
+	/* 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);
+	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, 100000000);
+		}
+		else {
+			/* 10MBit mode. */
+			lpc_emac_set_speed(0);
 
-            NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
-        }
+			NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
+		}
 
-        olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
-    }
+		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);
+	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;
-    }
+		olddphysts.phy_full_duplex = physts.phy_full_duplex;
+	}
 
-    if (physts.phy_link_active != olddphysts.phy_link_active) {
-        changed = 1;
+	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);
+		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,
@@ -183,10 +206,10 @@
                 (void*) netif, 1);
 #endif
 
-        olddphysts.phy_link_active = physts.phy_link_active;
-    }
+		olddphysts.phy_link_active = physts.phy_link_active;
+	}
 
-    return changed;
+	return changed;
 }
 
 /** \brief  Initialize the DP83848 PHY.
@@ -202,81 +225,121 @@
  */
 err_t lpc_phy_init(struct netif *netif, int rmii)
 {
-    u32_t tmp;
-    s32_t i;
+	u32_t tmp;
+	s32_t i;
+
+	physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
+	physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
+	physts.phy_link_active = olddphysts.phy_link_active = 2;
+	phyustate = 0;
 
-    physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
-    physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
-    physts.phy_link_active = olddphysts.phy_link_active = 2;
-    phyustate = 0;
+	/* Only first read and write are checked for failure */
+	/* Put the DP83848C in reset mode and wait for completion */
+	if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
+		return ERR_TIMEOUT;
+	i = 400;
+	while (i > 0) {
+	    osDelay(1);   /* 1 ms */
+		if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
+			return ERR_TIMEOUT;
 
-    /* Only first read and write are checked for failure */
-    /* Put the DP83848C in reset mode and wait for completion */
-    if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
-        return ERR_TIMEOUT;
-    i = 400;
-    while (i > 0) {
-        osDelay(1);   /* 1 ms */
-        if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
-            return ERR_TIMEOUT;
+		if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
+			i = -1;
+		else
+			i--;
+	}
+	/* Timeout? */
+	if (i == 0)
+		return ERR_TIMEOUT;
 
-        if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
-            i = -1;
-        else
-            i--;
-    }
-    /* Timeout? */
-    if (i == 0)
-        return ERR_TIMEOUT;
+	// read PHY ID
+	lpc_mii_read(DP8_IDR1_REG, &tmp);
+	phy_id = (tmp << 16);
+	lpc_mii_read(DP8_IDR2_REG, &tmp);    
+	phy_id |= (tmp & 0XFFF0);    
 
-    /* Setup link based on configuration options */
+	/* Setup link based on configuration options */
 #if PHY_USE_AUTONEG==1
-    tmp = DP8_AUTONEG;
+	tmp = DP8_AUTONEG;
 #else
-    tmp = 0;
+	tmp = 0;
 #endif
 #if PHY_USE_100MBS==1
-    tmp |= DP8_SPEED_SELECT;
+	tmp |= DP8_SPEED_SELECT;
 #endif
 #if PHY_USE_FULL_DUPLEX==1
-    tmp |= DP8_DUPLEX_MODE;
+	tmp |= DP8_DUPLEX_MODE;
 #endif
-    lpc_mii_write(DP8_BMCR_REG, tmp);
+	lpc_mii_write(DP8_BMCR_REG, tmp);
 
     /* Enable RMII mode for PHY */
     if (rmii)
         lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
 
-    /* The link is not set active at this point, but will be detected
+	/* The link is not set active at this point, but will be detected
        later */
 
-    return ERR_OK;
+	return ERR_OK;
 }
 
 /* Phy status update state machine */
 s32_t lpc_phy_sts_sm(struct netif *netif)
 {
-    s32_t changed = 0;
+	s32_t changed = 0;
+	u32_t data = 0;
+	u32_t tmp;
 
-    switch (phyustate) {
-        default:
-        case 0:
-            /* Read BMSR to clear faults */
-            lpc_mii_read_noblock(DP8_PHY_STAT_REG);
-            phyustate = 1;
-            break;
+	switch (phyustate) {
+		default:
+		case 0:
+			if (phy_id == DP83848C_ID) {    
+				lpc_mii_read_noblock(DP8_PHY_STAT_REG);
+				phyustate = 2;
+			}
+			else if (phy_id == LAN8720_ID) {
+				lpc_mii_read_noblock(DP8_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;
 
-        case 1:
-            /* Wait for read status state */
-            if (!lpc_mii_is_busy()) {
-                /* Update PHY status */
-                changed = lpc_update_phy_sts(netif, lpc_mii_read_data());
-                phyustate = 0;
-            }
-            break;
-    }
+				//read the status register to get link status 
+				lpc_mii_read_noblock(DP8_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();
 
-    return changed;
+				if (phy_id == DP83848C_ID) {
+					// STS register contains all needed status bits
+					data  = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0;
+					data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
+					data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
+				}
+				else if (phy_id == LAN8720_ID) {    
+					// we only get the link status here.
+					phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0;
+					data = phy_lan7420_sts_tmp;          
+				}
+
+				changed = lpc_update_phy_sts(netif, data);        
+				phyustate = 0;                
+			}
+			break;
+	}
+
+	return changed;
 }
 
 /**