Adapted to Lora Semtech + Nucleo

Dependencies:   DebugLib

Dependents:   LoRaWAN-lmic-app LoRaWAN-lmic-app LoRaWAN-test-10secs LoRaPersonalizedDeviceForEverynet ... more

Fork of lwip_ppp_ethernet by Donatien Garnier

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 /**********************************************************************
00002 * $Id$        lpc_phy_dp83848.c            2011-11-20
00003 *//**
00004 * @file        lpc_phy_dp83848.c
00005 * @brief    DP83848C PHY status and control.
00006 * @version    1.0
00007 * @date        20 Nov. 2011
00008 * @author    NXP MCU SW Application Team
00009 *
00010 * Copyright(C) 2011, NXP Semiconductor
00011 * All rights reserved.
00012 *
00013 ***********************************************************************
00014 * Software that is described herein is for illustrative purposes only
00015 * which provides customers with programming information regarding the
00016 * products. This software is supplied "AS IS" without any warranties.
00017 * NXP Semiconductors assumes no responsibility or liability for the
00018 * use of the software, conveys no license or title under any patent,
00019 * copyright, or mask work right to the product. NXP Semiconductors
00020 * reserves the right to make changes in the software without
00021 * notification. NXP Semiconductors also make no representation or
00022 * warranty that such application will be suitable for the specified
00023 * use without further testing or modification.
00024 **********************************************************************/
00025 
00026 #include "lwip/opt.h"
00027 
00028 #if NET_ETHERNET
00029 
00030 #include "lwip/err.h"
00031 #include "lwip/snmp.h"
00032 #include "lpc_emac_config.h"
00033 #include "lpc_phy.h"
00034 #include "sys_arch.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_ANADV_REG       0x4  /**< Auto_Neg Advt Reg  */
00051 #define DP8_ANLPA_REG       0x5  /**< Auto_neg Link Partner Ability Reg */
00052 #define DP8_ANEEXP_REG      0x6  /**< Auto-neg Expansion Reg  */
00053 #define DP8_PHY_STAT_REG    0x10 /**< PHY Status Register  */
00054 #define DP8_PHY_INT_CTL_REG 0x11 /**< PHY Interrupt Control Register */
00055 #define DP8_PHY_STS_REG     0x19 /**< PHY Status Register  */
00056 
00057 /** \brief DP83848 Control register definitions */
00058 #define DP8_RESET          (1 << 15)  /**< 1= S/W Reset */
00059 #define DP8_LOOPBACK       (1 << 14)  /**< 1=loopback Enabled */
00060 #define DP8_SPEED_SELECT   (1 << 13)  /**< 1=Select 100MBps */
00061 #define DP8_AUTONEG        (1 << 12)  /**< 1=Enable auto-negotiation */
00062 #define DP8_POWER_DOWN     (1 << 11)  /**< 1=Power down PHY */
00063 #define DP8_ISOLATE        (1 << 10)  /**< 1=Isolate PHY */
00064 #define DP8_RESTART_AUTONEG (1 << 9)  /**< 1=Restart auto-negoatiation */
00065 #define DP8_DUPLEX_MODE    (1 << 8)   /**< 1=Full duplex mode */
00066 #define DP8_COLLISION_TEST (1 << 7)   /**< 1=Perform collsion test */
00067 
00068 /** \brief DP83848 Status register definitions */
00069 #define DP8_100BASE_T4     (1 << 15)  /**< T4 mode */
00070 #define DP8_100BASE_TX_FD  (1 << 14)  /**< 100MBps full duplex */
00071 #define DP8_100BASE_TX_HD  (1 << 13)  /**< 100MBps half duplex */
00072 #define DP8_10BASE_T_FD    (1 << 12)  /**< 100Bps full duplex */
00073 #define DP8_10BASE_T_HD    (1 << 11)  /**< 10MBps half duplex */
00074 #define DP8_MF_PREAMB_SUPPR (1 << 6)  /**< Preamble suppress */
00075 #define DP8_AUTONEG_COMP   (1 << 5)   /**< Auto-negotation complete */
00076 #define DP8_RMT_FAULT      (1 << 4)   /**< Fault */
00077 #define DP8_AUTONEG_ABILITY (1 << 3)  /**< Auto-negotation supported */
00078 #define DP8_LINK_STATUS    (1 << 2)   /**< 1=Link active */
00079 #define DP8_JABBER_DETECT  (1 << 1)   /**< Jabber detect */
00080 #define DP8_EXTEND_CAPAB   (1 << 0)   /**< Supports extended capabilities */
00081 
00082 /** \brief DP83848 PHY status definitions */
00083 #define DP8_REMOTEFAULT    (1 << 6)   /**< Remote fault */
00084 #define DP8_FULLDUPLEX     (1 << 2)   /**< 1=full duplex */
00085 #define DP8_SPEED10MBPS    (1 << 1)   /**< 1=10MBps speed */
00086 #define DP8_VALID_LINK     (1 << 0)   /**< 1=Link active */
00087 
00088 /** \brief DP83848 PHY ID register definitions */
00089 #define DP8_PHYID1_OUI     0x2000     /**< Expected PHY ID1 */
00090 #define DP8_PHYID2_OUI     0x5c90     /**< Expected PHY ID2 */
00091 
00092 /** \brief PHY status structure used to indicate current status of PHY.
00093  */
00094 typedef struct {
00095     u32_t     phy_speed_100mbs:1; /**< 10/100 MBS connection speed flag. */
00096     u32_t     phy_full_duplex:1;  /**< Half/full duplex connection speed flag. */
00097     u32_t     phy_link_active:1;  /**< Phy link active flag. */
00098 } PHY_STATUS_TYPE;
00099 
00100 /** \brief  PHY update flags */
00101 static PHY_STATUS_TYPE physts;
00102 
00103 /** \brief  Last PHY update flags, used for determing if something has changed */
00104 static PHY_STATUS_TYPE olddphysts;
00105 
00106 /** \brief  PHY update counter for state machine */
00107 static s32_t phyustate;
00108 
00109 /** \brief  Update PHY status from passed value
00110  *
00111  *  This function updates the current PHY status based on the
00112  *  passed PHY status word. The PHY status indicate if the link
00113  *  is active, the connection speed, and duplex.
00114  *
00115  *  \param[in]    netif   NETIF structure
00116  *  \param[in]    linksts Status word from PHY
00117  *  \return        1 if the status has changed, otherwise 0
00118  */
00119 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts)
00120 {
00121     s32_t changed = 0;
00122 
00123     /* Update link active status */
00124     if (linksts & DP8_VALID_LINK)
00125         physts.phy_link_active = 1;
00126     else
00127         physts.phy_link_active = 0;
00128 
00129     /* Full or half duplex */
00130     if (linksts & DP8_FULLDUPLEX)
00131         physts.phy_full_duplex = 1;
00132     else
00133         physts.phy_full_duplex = 0;
00134 
00135     /* Configure 100MBit/10MBit mode. */
00136     if (linksts & DP8_SPEED10MBPS)
00137         physts.phy_speed_100mbs = 0;
00138     else
00139         physts.phy_speed_100mbs = 1;
00140 
00141     if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) {
00142         changed = 1;
00143         if (physts.phy_speed_100mbs) {
00144             /* 100MBit mode. */
00145             lpc_emac_set_speed(1);
00146 
00147             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000);
00148         }
00149         else {
00150             /* 10MBit mode. */
00151             lpc_emac_set_speed(0);
00152 
00153             NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000);
00154         }
00155 
00156         olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs;
00157     }
00158 
00159     if (physts.phy_full_duplex != olddphysts.phy_full_duplex) {
00160         changed = 1;
00161         if (physts.phy_full_duplex)
00162             lpc_emac_set_duplex(1);
00163         else
00164             lpc_emac_set_duplex(0);
00165 
00166         olddphysts.phy_full_duplex = physts.phy_full_duplex;
00167     }
00168 
00169     if (physts.phy_link_active != olddphysts.phy_link_active) {
00170         changed = 1;
00171         if (physts.phy_link_active)
00172             netif_set_link_up(netif);
00173         else
00174             netif_set_link_down(netif);
00175 
00176         olddphysts.phy_link_active = physts.phy_link_active;
00177     }
00178 
00179     return changed;
00180 }
00181 
00182 /** \brief  Initialize the DP83848 PHY.
00183  *
00184  *  This function initializes the DP83848 PHY. It will block until
00185  *  complete. This function is called as part of the EMAC driver
00186  *  initialization. Configuration of the PHY at startup is
00187  *  controlled by setting up configuration defines in lpc_phy.h.
00188  *
00189  *  \param[in]     netif   NETIF structure
00190  *  \return         ERR_OK if the setup was successful, otherwise ERR_TIMEOUT
00191  */
00192 err_t lpc_phy_init(struct netif *netif)
00193 {
00194     u32_t tmp;
00195     s32_t i;
00196 
00197     physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2;
00198     physts.phy_full_duplex = olddphysts.phy_full_duplex = 2;
00199     physts.phy_link_active = olddphysts.phy_link_active = 2;
00200     phyustate = 0;
00201 
00202     /* Only first read and write are checked for failure */
00203     /* Put the DP83848C in reset mode and wait for completion */
00204     if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != 0)
00205         return ERR_TIMEOUT;
00206     i = 400;
00207     while (i > 0) {
00208         osDelay(1);   /* 1 ms */
00209         if (lpc_mii_read(DP8_BMCR_REG, &tmp) != 0)
00210             return ERR_TIMEOUT;
00211 
00212         if (!(tmp & (DP8_RESET | DP8_POWER_DOWN)))
00213             i = -1;
00214         else
00215             i--;
00216     }
00217     /* Timeout? */
00218     if (i == 0)
00219         return ERR_TIMEOUT;
00220 
00221     /* Setup link based on configuration options */
00222 #if PHY_USE_AUTONEG==1
00223     tmp = DP8_AUTONEG;
00224 #else
00225     tmp = 0;
00226 #endif
00227 #if PHY_USE_100MBS==1
00228     tmp |= DP8_SPEED_SELECT;
00229 #endif
00230 #if PHY_USE_FULL_DUPLEX==1
00231     tmp |= DP8_DUPLEX_MODE;
00232 #endif
00233     lpc_mii_write(DP8_BMCR_REG, tmp);
00234 
00235     /* The link is not set active at this point, but will be detected
00236        later */
00237 
00238     return ERR_OK;
00239 }
00240 
00241 /* Phy status update state machine */
00242 s32_t lpc_phy_sts_sm(struct netif *netif)
00243 {
00244     s32_t changed = 0;
00245 
00246     switch (phyustate) {
00247         default:
00248         case 0:
00249             /* Read BMSR to clear faults */
00250             lpc_mii_read_noblock(DP8_PHY_STAT_REG);
00251             phyustate = 1;
00252             break;
00253 
00254         case 1:
00255             /* Wait for read status state */
00256             if (!lpc_mii_is_busy()) {
00257                 /* Update PHY status */
00258                 changed = lpc_update_phy_sts(netif, lpc_mii_read_data());
00259                 phyustate = 0;
00260             }
00261             break;
00262     }
00263 
00264     return changed;
00265 }
00266 
00267 #endif
00268 
00269 /**
00270  * @}
00271  */
00272 
00273 /* --------------------------------- End Of File ------------------------------ */