A web server for monitoring and controlling a MakerBot Replicator over the USB host and ethernet.

Dependencies:   IAP NTPClient RTC mbed-rtos mbed Socket lwip-sys lwip BurstSPI

Fork of LPC1768_Mini-DK by Frank Vannieuwkerke

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers lpc_phy_dp83848.c Source File

lpc_phy_dp83848.c

Go to the documentation of this file.
00001 #include "Target.h"
00002 
00003 #ifdef TARGET_MBED
00004 /**********************************************************************
00005 * $Id$      lpc_phy_dp83848.c           2011-11-20
00006 *//**
00007 * @file     lpc_phy_dp83848.c
00008 * @brief    DP83848C PHY status and control.
00009 * @version  1.0
00010 * @date     20 Nov. 2011
00011 * @author   NXP MCU SW Application Team
00012 *
00013 * Copyright(C) 2011, NXP Semiconductor
00014 * All rights reserved.
00015 *
00016 ***********************************************************************
00017 * Software that is described herein is for illustrative purposes only
00018 * which provides customers with programming information regarding the
00019 * products. This software is supplied "AS IS" without any warranties.
00020 * NXP Semiconductors assumes no responsibility or liability for the
00021 * use of the software, conveys no license or title under any patent,
00022 * copyright, or mask work right to the product. NXP Semiconductors
00023 * reserves the right to make changes in the software without
00024 * notification. NXP Semiconductors also make no representation or
00025 * warranty that such application will be suitable for the specified
00026 * use without further testing or modification.
00027 **********************************************************************/
00028 
00029 #include "lwip/opt.h"
00030 #include "lwip/err.h"
00031 #include "lwip/tcpip.h"
00032 #include "lwip/snmp.h"
00033 #include "lpc_emac_config.h"
00034 #include "lpc_phy.h"
00035 
00036 /** @defgroup dp83848_phy   PHY status and control for the DP83848.
00037  * @ingroup lwip_phy
00038  *
00039  * Various functions for controlling and monitoring the status of the
00040  * DP83848 PHY. In polled (standalone) systems, the PHY state must be
00041  * monitored as part of the application. In a threaded (RTOS) system,
00042  * the PHY state is monitored by the PHY handler thread. The MAC
00043  * driver will not transmit unless the PHY link is active.
00044  * @{
00045  */
00046 
00047 /** \brief  DP83848 PHY register offsets */
00048 #define DP8_BMCR_REG        0x0  /**< Basic Mode Control Register */
00049 #define DP8_BMSR_REG        0x1  /**< Basic Mode Status Reg */
00050 #define DP8_IDR1_REG        0x2  /**< Basic Mode Status Reg */
00051 #define DP8_IDR2_REG        0x3  /**< Basic Mode Status Reg */
00052 #define DP8_ANADV_REG       0x4  /**< Auto_Neg Advt Reg  */
00053 #define DP8_ANLPA_REG       0x5  /**< Auto_neg Link Partner Ability Reg */
00054 #define DP8_ANEEXP_REG      0x6  /**< Auto-neg Expansion Reg  */
00055 #define DP8_PHY_STAT_REG    0x10 /**< PHY Status Register  */
00056 #define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
00057 #define DP8_PHY_RBR_REG     0x17 /**< PHY RMII and Bypass Register  */
00058 #define DP8_PHY_STS_REG     0x19 /**< PHY Status Register  */
00059 
00060 #define DP8_PHY_SCSR_REG    0x1f /**< PHY Special Control/Status Register (LAN8720)  */
00061 
00062 /** \brief DP83848 Control register definitions */
00063 #define DP8_RESET          (1 << 15)  /**< 1= S/W Reset */
00064 #define DP8_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
00065 #define DP8_SPEED_SELECT   (1 << 13)  /**< 1=Select 100MBps */
00066 #define DP8_AUTONEG        (1 << 12)  /**< 1=Enable auto-negotiation */
00067 #define DP8_POWER_DOWN     (1 << 11)  /**< 1=Power down PHY */
00068 #define DP8_ISOLATE        (1 << 10)  /**< 1=Isolate PHY */
00069 #define DP8_RESTART_AUTONEG (1 << 9)  /**< 1=Restart auto-negoatiation */
00070 #define DP8_DUPLEX_MODE    (1 << 8)   /**< 1=Full duplex mode */
00071 #define DP8_COLLISION_TEST (1 << 7)   /**< 1=Perform collsion test */
00072 
00073 /** \brief DP83848 Status register definitions */
00074 #define DP8_100BASE_T4     (1 << 15)  /**< T4 mode */
00075 #define DP8_100BASE_TX_FD  (1 << 14)  /**< 100MBps full duplex */
00076 #define DP8_100BASE_TX_HD  (1 << 13)  /**< 100MBps half duplex */
00077 #define DP8_10BASE_T_FD    (1 << 12)  /**< 100Bps full duplex */
00078 #define DP8_10BASE_T_HD    (1 << 11)  /**< 10MBps half duplex */
00079 #define DP8_MF_PREAMB_SUPPR (1 << 6)  /**< Preamble suppress */
00080 #define DP8_AUTONEG_COMP   (1 << 5)   /**< Auto-negotation complete */
00081 #define DP8_RMT_FAULT      (1 << 4)   /**< Fault */
00082 #define DP8_AUTONEG_ABILITY (1 << 3)  /**< Auto-negotation supported */
00083 #define DP8_LINK_STATUS    (1 << 2)   /**< 1=Link active */
00084 #define DP8_JABBER_DETECT  (1 << 1)   /**< Jabber detect */
00085 #define DP8_EXTEND_CAPAB   (1 << 0)   /**< Supports extended capabilities */
00086 
00087 /** \brief DP83848 PHY RBR MII dode definitions */
00088 #define DP8_RBR_RMII_MODE  (1 << 5)   /**< Use RMII mode */
00089 
00090 /** \brief DP83848 PHY status definitions */
00091 #define DP8_REMOTEFAULT    (1 << 6)   /**< Remote fault */
00092 #define DP8_FULLDUPLEX     (1 << 2)   /**< 1=full duplex */
00093 #define DP8_SPEED10MBPS    (1 << 1)   /**< 1=10MBps speed */
00094 #define DP8_VALID_LINK     (1 << 0)   /**< 1=Link active */
00095 
00096 /** \brief DP83848 PHY ID register definitions */
00097 #define DP8_PHYID1_OUI     0x2000     /**< Expected PHY ID1 */
00098 #define DP8_PHYID2_OUI     0x5c90     /**< Expected PHY ID2 */
00099 
00100 /** \brief LAN8720 PHY Special Control/Status Register */
00101 #define PHY_SCSR_100MBIT    0x0008    /**< Speed: 1=100 MBit, 0=10Mbit */
00102 #define PHY_SCSR_DUPLEX     0x0010    /**< PHY Duplex Mask             */
00103 
00104 /** \brief Link status bits */
00105 #define LNK_STAT_VALID       0x01 
00106 #define LNK_STAT_FULLDUPLEX  0x02
00107 #define LNK_STAT_SPEED10MPS  0x04
00108 
00109 /** \brief PHY ID definitions */
00110 #define DP83848C_ID         0x20005C90  /**< PHY Identifier - DP83848C */
00111 #define LAN8720_ID          0x0007C0F0  /**< PHY Identifier - LAN8720  */
00112 
00113 /** \brief PHY status structure used to indicate current status of PHY.
00114  */
00115 typedef struct {
00116     u32_t     phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
00117     u32_t     phy_full_duplex:1;  /**< Half/full duplex connection speed flag. */
00118     u32_t     phy_link_active:1;  /**< Phy link active flag. */
00119 } PHY_STATUS_TYPE;
00120 
00121 /** \brief  PHY update flags */
00122 static PHY_STATUS_TYPE physts;
00123 
00124 /** \brief  Last PHY update flags, used for determing if something has changed */
00125 static PHY_STATUS_TYPE olddphysts;
00126 
00127 /** \brief  PHY update counter for state machine */
00128 static s32_t phyustate;
00129 
00130 /** \brief  Holds the PHY ID */
00131 static u32_t phy_id;
00132 
00133 /** \brief  Temporary holder of link status for LAN7420 */
00134 static u32_t phy_lan7420_sts_tmp;
00135 
00136 /** \brief  Update PHY status from passed value
00137  *
00138  *  This function updates the current PHY status based on the
00139  *  passed PHY status word. The PHY status indicate if the link
00140  *  is active, the connection speed, and duplex.
00141  *
00142  *  \param[in]    netif   NETIF structure
00143  *  \param[in]    linksts Status word from PHY
00144  *  \return        1 if the status has changed, otherwise 0
00145  */
00146 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
00147 {
00148     s32_t changed = 0;
00149 
00150     /* Update link active status */
00151     if (linksts & LNK_STAT_VALID)
00152         physts.phy_link_active = 1;
00153     else
00154         physts.phy_link_active = 0;
00155 
00156     /* Full or half duplex */
00157     if (linksts & LNK_STAT_FULLDUPLEX)
00158         physts.phy_full_duplex = 1;
00159     else
00160         physts.phy_full_duplex = 0;
00161 
00162     /* Configure 100MBit/10MBit mode. */
00163     if (linksts & LNK_STAT_SPEED10MPS)
00164         physts.phy_speed_100mbs = 0;
00165     else
00166         physts.phy_speed_100mbs = 1;
00167 
00168     if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
00169         changed = 1;
00170         if (physts.phy_speed_100mbs) {
00171             /* 100MBit mode. */
00172             lpc_emac_set_speed(1);
00173 
00174             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
00175         }
00176         else {
00177             /* 10MBit mode. */
00178             lpc_emac_set_speed(0);
00179 
00180             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
00181         }
00182 
00183         olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
00184     }
00185 
00186     if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
00187         changed = 1;
00188         if (physts.phy_full_duplex)
00189             lpc_emac_set_duplex(1);
00190         else
00191             lpc_emac_set_duplex(0);
00192 
00193         olddphysts.phy_full_duplex = physts.phy_full_duplex;
00194     }
00195 
00196     if (physts.phy_link_active != olddphysts.phy_link_active) {
00197         changed = 1;
00198 #if NO_SYS == 1
00199         if (physts.phy_link_active)
00200             netif_set_link_up(netif);
00201         else
00202             netif_set_link_down(netif);
00203 #else
00204         if (physts.phy_link_active)
00205             tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
00206                 (void*) netif, 1);
00207          else
00208             tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
00209                 (void*) netif, 1);
00210 #endif
00211 
00212         olddphysts.phy_link_active = physts.phy_link_active;
00213     }
00214 
00215     return changed;
00216 }
00217 
00218 /** \brief  Initialize the DP83848 PHY.
00219  *
00220  *  This function initializes the DP83848 PHY. It will block until
00221  *  complete. This function is called as part of the EMAC driver
00222  *  initialization. Configuration of the PHY at startup is
00223  *  controlled by setting up configuration defines in lpc_phy.h.
00224  *
00225  *  \param[in]     netif   NETIF structure
00226  *  \param[in]     rmii    If set, configures the PHY for RMII mode
00227  *  \return         ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
00228  */
00229 err_t lpc_phy_init(struct netif *netif, int rmii)
00230 {
00231     u32_t tmp;
00232     s32_t i;
00233 
00234     physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
00235     physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
00236     physts.phy_link_active = olddphysts.phy_link_active = 2;
00237     phyustate = 0;
00238 
00239     /* Only first read and write are checked for failure */
00240     /* Put the DP83848C in reset mode and wait for completion */
00241     if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
00242         return ERR_TIMEOUT;
00243     i = 400;
00244     while (i > 0) {
00245         osDelay(1);   /* 1 ms */
00246         if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
00247             return ERR_TIMEOUT;
00248 
00249         if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
00250             i = -1;
00251         else
00252             i--;
00253     }
00254     /* Timeout? */
00255     if (i == 0)
00256         return ERR_TIMEOUT;
00257 
00258     // read PHY ID
00259     lpc_mii_read(DP8_IDR1_REG, &tmp);
00260     phy_id = (tmp << 16);
00261     lpc_mii_read(DP8_IDR2_REG, &tmp);    
00262     phy_id |= (tmp & 0XFFF0);    
00263 
00264     /* Setup link based on configuration options */
00265 #if PHY_USE_AUTONEG==1
00266     tmp = DP8_AUTONEG;
00267 #else
00268     tmp = 0;
00269 #endif
00270 #if PHY_USE_100MBS==1
00271     tmp |= DP8_SPEED_SELECT;
00272 #endif
00273 #if PHY_USE_FULL_DUPLEX==1
00274     tmp |= DP8_DUPLEX_MODE;
00275 #endif
00276     lpc_mii_write(DP8_BMCR_REG, tmp);
00277 
00278     /* Enable RMII mode for PHY */
00279     if (rmii)
00280         lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
00281 
00282     /* The link is not set active at this point, but will be detected
00283        later */
00284 
00285     return ERR_OK;
00286 }
00287 
00288 /* Phy status update state machine */
00289 s32_t lpc_phy_sts_sm(struct netif *netif)
00290 {
00291     s32_t changed = 0;
00292     u32_t data = 0;
00293     u32_t tmp;
00294 
00295     switch (phyustate) {
00296         default:
00297         case 0:
00298             if (phy_id == DP83848C_ID) {    
00299                 lpc_mii_read_noblock(DP8_PHY_STAT_REG);
00300                 phyustate = 2;
00301             }
00302             else if (phy_id == LAN8720_ID) {
00303                 lpc_mii_read_noblock(DP8_PHY_SCSR_REG);
00304                 phyustate = 1;        
00305             }
00306             break;
00307 
00308         case 1:
00309             if (phy_id == LAN8720_ID) {
00310                 tmp = lpc_mii_read_data();
00311                 // we get speed and duplex here. 
00312                 phy_lan7420_sts_tmp =  (tmp & PHY_SCSR_DUPLEX)  ? LNK_STAT_FULLDUPLEX : 0;
00313                 phy_lan7420_sts_tmp |= (tmp & PHY_SCSR_100MBIT) ? 0 : LNK_STAT_SPEED10MPS;
00314 
00315                 //read the status register to get link status 
00316                 lpc_mii_read_noblock(DP8_BMSR_REG);
00317                 phyustate = 2;        
00318             }
00319             break;
00320 
00321         case 2:
00322             /* Wait for read status state */
00323             if (!lpc_mii_is_busy()) {
00324                 /* Update PHY status */
00325                 tmp = lpc_mii_read_data();
00326 
00327                 if (phy_id == DP83848C_ID) {
00328                     // STS register contains all needed status bits
00329                     data  = (tmp & DP8_VALID_LINK) ? LNK_STAT_VALID : 0;
00330                     data |= (tmp & DP8_FULLDUPLEX) ? LNK_STAT_FULLDUPLEX : 0;
00331                     data |= (tmp & DP8_SPEED10MBPS) ? LNK_STAT_SPEED10MPS : 0;
00332                 }
00333                 else if (phy_id == LAN8720_ID) {    
00334                     // we only get the link status here.
00335                     phy_lan7420_sts_tmp |= (tmp & DP8_LINK_STATUS) ? LNK_STAT_VALID : 0;
00336                     data = phy_lan7420_sts_tmp;          
00337                 }
00338 
00339                 changed = lpc_update_phy_sts(netif, data);        
00340                 phyustate = 0;                
00341             }
00342             break;
00343     }
00344 
00345     return changed;
00346 }
00347 
00348 /**
00349  * @}
00350  */
00351 
00352 /* --------------------------------- End Of File ------------------------------ */
00353 #endif