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_lan8720.c Source File

lpc_phy_lan8720.c

Go to the documentation of this file.
00001 #include "Target.h"
00002 #ifdef TARGET_MINIDK
00003 
00004 /**********************************************************************
00005 * $Id$        lpc_phy_lan8720.c            2011-11-20
00006 *//**
00007 * @file        lpc_phy_lan8720.c
00008 * @brief    LAN8720 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 lan8720_phy    PHY status and control for the LAN8720.
00037  * @ingroup lwip_phy
00038  *
00039  * Various functions for controlling and monitoring the status of the
00040  * LAN8720 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  LAN8720 PHY register offsets */
00048 #define LAN8_BCR_REG        0x0  /**< Basic Control Register */
00049 #define LAN8_BSR_REG        0x1  /**< Basic Status Reg */
00050 #define LAN8_PHYID1_REG     0x2  /**< PHY ID 1 Reg  */
00051 #define LAN8_PHYID2_REG     0x3  /**< PHY ID 2 Reg */
00052 #define LAN8_PHYSPLCTL_REG  0x1F /**< PHY special control/status Reg */
00053 
00054 /* LAN8720 BCR register definitions */
00055 #define LAN8_RESET          (1 << 15)  /**< 1= S/W Reset */
00056 #define LAN8_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
00057 #define LAN8_SPEED_SELECT   (1 << 13)  /**< 1=Select 100MBps */
00058 #define LAN8_AUTONEG        (1 << 12)  /**< 1=Enable auto-negotiation */
00059 #define LAN8_POWER_DOWN     (1 << 11)  /**< 1=Power down PHY */
00060 #define LAN8_ISOLATE        (1 << 10)  /**< 1=Isolate PHY */
00061 #define LAN8_RESTART_AUTONEG (1 << 9)  /**< 1=Restart auto-negoatiation */
00062 #define LAN8_DUPLEX_MODE    (1 << 8)   /**< 1=Full duplex mode */
00063 
00064 /* LAN8720 BSR register definitions */
00065 #define LAN8_100BASE_T4     (1 << 15)  /**< T4 mode */
00066 #define LAN8_100BASE_TX_FD  (1 << 14)  /**< 100MBps full duplex */
00067 #define LAN8_100BASE_TX_HD  (1 << 13)  /**< 100MBps half duplex */
00068 #define LAN8_10BASE_T_FD    (1 << 12)  /**< 100Bps full duplex */
00069 #define LAN8_10BASE_T_HD    (1 << 11)  /**< 10MBps half duplex */
00070 #define LAN8_AUTONEG_COMP   (1 << 5)   /**< Auto-negotation complete */
00071 #define LAN8_RMT_FAULT      (1 << 4)   /**< Fault */
00072 #define LAN8_AUTONEG_ABILITY (1 << 3)  /**< Auto-negotation supported */
00073 #define LAN8_LINK_STATUS    (1 << 2)   /**< 1=Link active */
00074 #define LAN8_JABBER_DETECT  (1 << 1)   /**< Jabber detect */
00075 #define LAN8_EXTEND_CAPAB   (1 << 0)   /**< Supports extended capabilities */
00076 
00077 /* LAN8720 PHYSPLCTL status definitions */
00078 #define LAN8_SPEEDMASK      (7 << 2)   /**< Speed and duplex mask */
00079 #define LAN8_SPEED100F      (6 << 2)   /**< 100BT full duplex */
00080 #define LAN8_SPEED10F       (5 << 2)   /**< 10BT full duplex */
00081 #define LAN8_SPEED100H      (2 << 2)   /**< 100BT half duplex */
00082 #define LAN8_SPEED10H       (1 << 2)   /**< 10BT half duplex */
00083 
00084 /* LAN8720 PHY ID 1/2 register definitions */
00085 #define LAN8_PHYID1_OUI     0x0007     /**< Expected PHY ID1 */
00086 #define LAN8_PHYID2_OUI     0xC0F0     /**< Expected PHY ID2, except last 4 bits */
00087 
00088 /**
00089  * @brief PHY status structure used to indicate current status of PHY.
00090  */
00091 typedef struct {
00092     u32_t     phy_speed_100mbs:2; /**< 10/100 MBS connection speed flag. */
00093     u32_t     phy_full_duplex:2;  /**< Half/full duplex connection speed flag. */
00094     u32_t     phy_link_active:2;  /**< Phy link active flag. */
00095 } PHY_STATUS_TYPE;
00096 
00097 /** \brief  PHY update flags */
00098 static PHY_STATUS_TYPE physts;
00099 
00100 /** \brief  Last PHY update flags, used for determing if something has changed */
00101 static PHY_STATUS_TYPE olddphysts;
00102 
00103 /** \brief  PHY update counter for state machine */
00104 static s32_t phyustate;
00105 
00106 /** \brief  Update PHY status from passed value
00107  *
00108  *  This function updates the current PHY status based on the
00109  *  passed PHY status word. The PHY status indicate if the link
00110  *  is active, the connection speed, and duplex.
00111  *
00112  *  \param[in]    netif   NETIF structure
00113  *  \param[in]    linksts Status word with link state
00114  *  \param[in]    sdsts   Status word with speed and duplex states
00115  *  \return        1 if the status has changed, otherwise 0
00116  */
00117 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts, u32_t sdsts)
00118 {
00119     s32_t changed = 0;
00120 
00121     /* Update link active status */
00122     if (linksts & LAN8_LINK_STATUS)
00123         physts.phy_link_active = 1;
00124     else
00125         physts.phy_link_active = 0;
00126 
00127     switch (sdsts & LAN8_SPEEDMASK) {
00128         case LAN8_SPEED100F:
00129         default:
00130             physts.phy_speed_100mbs = 1;
00131             physts.phy_full_duplex = 1;
00132             break;
00133 
00134         case LAN8_SPEED10F:
00135             physts.phy_speed_100mbs = 0;
00136             physts.phy_full_duplex = 1;
00137             break;
00138 
00139         case LAN8_SPEED100H:
00140             physts.phy_speed_100mbs = 1;
00141             physts.phy_full_duplex = 0;
00142             break;
00143 
00144         case LAN8_SPEED10H:
00145             physts.phy_speed_100mbs = 0;
00146             physts.phy_full_duplex = 0;
00147             break;
00148     }
00149 
00150     if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
00151         changed = 1;
00152         if (physts.phy_speed_100mbs) {
00153             /* 100MBit mode. */
00154             lpc_emac_set_speed(1);
00155 
00156             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
00157         }
00158         else {
00159             /* 10MBit mode. */
00160             lpc_emac_set_speed(0);
00161 
00162             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
00163         }
00164 
00165         olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
00166     }
00167 
00168     if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
00169         changed = 1;
00170         if (physts.phy_full_duplex)
00171             lpc_emac_set_duplex(1);
00172         else
00173             lpc_emac_set_duplex(0);
00174 
00175         olddphysts.phy_full_duplex = physts.phy_full_duplex;
00176     }
00177 
00178     if (physts.phy_link_active != olddphysts.phy_link_active) {
00179         changed = 1;
00180 #if NO_SYS == 1
00181         if (physts.phy_link_active)
00182             netif_set_link_up(netif);
00183         else
00184             netif_set_link_down(netif);
00185 #else
00186         if (physts.phy_link_active)
00187             tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up,
00188                 (void*) netif, 1);
00189          else
00190             tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down,
00191                 (void*) netif, 1);
00192 #endif
00193 
00194         olddphysts.phy_link_active = physts.phy_link_active;
00195     }
00196 
00197     return changed;
00198 }
00199 
00200 /** \brief  Initialize the LAN8720 PHY.
00201  *
00202  *  This function initializes the LAN8720 PHY. It will block until
00203  *  complete. This function is called as part of the EMAC driver
00204  *  initialization. Configuration of the PHY at startup is
00205  *  controlled by setting up configuration defines in
00206  *  lpc_emac_config.h.
00207  *
00208  *  \param[in]     netif   NETIF structure
00209  *  \param[in]     rmii    If set, configures the PHY for RMII mode
00210  *  \return        ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
00211  */
00212 err_t lpc_phy_init(struct netif *netif, int rmii)
00213 {
00214     u32_t tmp;//, tmp1;
00215     s32_t i;
00216 
00217     physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
00218     physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
00219     physts.phy_link_active = olddphysts.phy_link_active = 2;
00220     phyustate = 0;
00221 
00222     /* Only first read and write are checked for failure */
00223     /* Put the LAN8720 in reset mode and wait for completion */
00224     if (lpc_mii_write(LAN8_BCR_REG, LAN8_RESET) != 0)
00225         return ERR_TIMEOUT;
00226     i = 400;
00227     while (i > 0) {
00228         osDelay(1);   /* 1 ms */
00229         if (lpc_mii_read(LAN8_BCR_REG, &tmp) != 0)
00230             return ERR_TIMEOUT;
00231 
00232         if (!(tmp & (LAN8_RESET | LAN8_POWER_DOWN)))
00233             i = -1;
00234         else
00235             i--;
00236     }
00237     /* Timeout? */
00238     if (i == 0)
00239         return ERR_TIMEOUT;
00240 
00241     /* Setup link based on configuration options */
00242 #if PHY_USE_AUTONEG==1
00243     tmp = LAN8_AUTONEG;
00244 #else
00245     tmp = 0;
00246 #endif
00247 #if PHY_USE_100MBS==1
00248     tmp |= LAN8_SPEED_SELECT;
00249 #endif
00250 #if PHY_USE_FULL_DUPLEX==1
00251     tmp |= LAN8_DUPLEX_MODE;
00252 #endif
00253     lpc_mii_write(LAN8_BCR_REG, tmp);
00254 
00255     /* The link is not set active at this point, but will be detected
00256        later */
00257 
00258     return ERR_OK;
00259 }
00260 
00261 /* Phy status update state machine */
00262 s32_t lpc_phy_sts_sm(struct netif *netif)
00263 {
00264     static u32_t sts;
00265     s32_t changed = 0;
00266 
00267     switch (phyustate) {
00268         default:
00269         case 0:
00270             /* Read BMSR to clear faults */
00271             lpc_mii_read_noblock(LAN8_BSR_REG);
00272             phyustate = 1;
00273             break;
00274 
00275         case 1:
00276             /* Wait for read status state */
00277             if (!lpc_mii_is_busy()) {
00278                 /* Get PHY status with link state */
00279                 sts = lpc_mii_read_data();
00280                 lpc_mii_read_noblock(LAN8_PHYSPLCTL_REG);
00281                 phyustate = 2;
00282             }
00283             break;
00284 
00285         case 2:
00286             /* Wait for read status state */
00287             if (!lpc_mii_is_busy()) {
00288                 /* Update PHY status */
00289                 changed = lpc_update_phy_sts(netif, sts, lpc_mii_read_data());
00290                 phyustate = 0;
00291             }
00292             break;
00293     }
00294 
00295     return changed;
00296 }
00297 
00298 /**
00299  * @}
00300  */
00301 
00302 /* --------------------------------- End Of File ------------------------------ */
00303 #endif