lwip 1.4 - DM9161A PHY
Embed:
(wiki syntax)
Show/hide line numbers
lpc_phy_DM9161A.c
Go to the documentation of this file.
00001 /********************************************************************** 00002 * $Id$ lpc_phy_DM9161A.c 2013-01-28 00003 *//** 00004 * @file lpc_phy_DM9161A.c 00005 * @brief DM9161A PHY status and control. 00006 * @version 1.0 00007 * @date 14 Jan. 2013 00008 * @author Frank Vannieuwkerke 00009 * based on NXP MCU SW Application Team lpc_phy_dp83848.c 00010 * Copyright(C) 2011, NXP Semiconductor 00011 * All rights reserved. 00012 * 00013 * 00014 * 00015 * @NOTES: 00016 * 1. How to test : import http://mbed.org/users/mbed_official/code/TCPSocket_HelloWorld/ into the mbed compiler. 00017 * 00018 * 2. Open EthernetInterface\lwip-eth\arch folder 00019 * Delete 'lpc_phy_dp83848.c'. 00020 * Copy 'lpc_phy_DM9161A.c' (this file) into this folder. 00021 * 00022 * 3. When used with the Mini-DK hardware: 00023 * Modify EthernetInterface\lwip-eth\arch\lpc_emac_config.h: 00024 * Change #define LPC_PHYDEF_PHYADDR 1 to #define LPC_PHYDEF_PHYADDR 19 00025 * 00026 * Add following MAC address definition in main.cpp (before 'EthernetInterface eth;'). 00027 * extern "C" void mbed_mac_address(char * mac) 00028 * { 00029 * // define your own MAC Address 00030 * mac[0] = 0x00; 00031 * mac[1] = 0x1F; 00032 * mac[2] = 0x33; 00033 * mac[3] = 0x42; 00034 * mac[4] = 0xFC; 00035 * mac[5] = 0x6F; 00036 * }; 00037 * 00038 * 00039 * 00040 * 00041 *********************************************************************** 00042 * Software that is described herein is for illustrative purposes only 00043 * which provides customers with programming information regarding the 00044 * products. This software is supplied "AS IS" without any warranties. 00045 * NXP Semiconductors assumes no responsibility or liability for the 00046 * use of the software, conveys no license or title under any patent, 00047 * copyright, or mask work right to the product. NXP Semiconductors 00048 * reserves the right to make changes in the software without 00049 * notification. NXP Semiconductors also make no representation or 00050 * warranty that such application will be suitable for the specified 00051 * use without further testing or modification. 00052 **********************************************************************/ 00053 00054 #include "lwip/opt.h" 00055 #include "lwip/err.h" 00056 #include "lwip/tcpip.h" 00057 #include "lwip/snmp.h" 00058 #include "lpc_emac_config.h" 00059 #include "lpc_phy.h" 00060 00061 /** @defgroup DM9161A_phy PHY status and control for the DM9161A. 00062 * @ingroup lwip_phy 00063 * 00064 * Various functions for controlling and monitoring the status of the 00065 * DM9161A PHY. In polled (standalone) systems, the PHY state must be 00066 * monitored as part of the application. In a threaded (RTOS) system, 00067 * the PHY state is monitored by the PHY handler thread. The MAC 00068 * driver will not transmit unless the PHY link is active. 00069 * @{ 00070 */ 00071 00072 /** \brief DM9161A PHY register offsets */ 00073 #define DM9161A_BMCR_REG 0x00 /**< Basic Mode Control Register */ 00074 #define DM9161A_BMSR_REG 0x01 /**< Basic Mode Status Reg */ 00075 #define DM9161A_IDR1_REG 0x02 /**< PHY ID 1 Reg */ 00076 #define DM9161A_IDR2_REG 0x03 /**< PHY ID 2 Reg */ 00077 #define DM9161A_ANAR_REG 0x04 /**< Auto_Neg Advt Reg */ 00078 #define DM9161A_ANLPAR_REG 0x05 /**< Auto_neg Link Partner Ability Reg */ 00079 #define DM9161A_ANER_REG 0x06 /**< Auto-neg Expansion Reg */ 00080 #define DM9161A_DSCR_REG 0x10 /**< Specified Configuration Reg */ 00081 #define DM9161A_DSCSR_REG 0x11 /**< Specified Configuration and Status Reg */ 00082 #define DM9161A_10BTCSR_REG 0x12 /**< 10BASE-T Configuration and Satus Reg */ 00083 #define DM9161A_MDINTR_REG 0x15 /**< Specified Interrupt Reg */ 00084 #define DM9161A_RECR_REG 0x16 /**< Specified Receive Error Counter Reg */ 00085 #define DM9161A_DISCR_REG 0x17 /**< Specified Disconnect Counter Reg */ 00086 #define DM9161A_RLSR_REG 0x18 /**< Hardware Reset Latch State Reg */ 00087 00088 /** \brief DM9161A BMCR register definitions */ 00089 #define DM9161A_RESET (1 << 15) /**< 1= S/W Reset */ 00090 #define DM9161A_LOOPBACK (1 << 14) /**< 1=loopback Enabled */ 00091 #define DM9161A_SPEED_SELECT (1 << 13) /**< 1=Select 100MBps */ 00092 #define DM9161A_AUTONEG (1 << 12) /**< 1=Enable auto-negotiation */ 00093 #define DM9161A_POWER_DOWN (1 << 11) /**< 1=Power down PHY */ 00094 #define DM9161A_ISOLATE (1 << 10) /**< 1=Isolate PHY */ 00095 #define DM9161A_RESTART_AUTONEG (1 << 9 ) /**< 1=Restart auto-negoatiation */ 00096 #define DM9161A_DUPLEX_MODE (1 << 8 ) /**< 1=Full duplex mode */ 00097 #define DM9161A_COLLISION_TEST (1 << 7 ) /**< 1=Perform collsion test */ 00098 00099 /** \brief DM9161A BMSR register definitions */ 00100 #define DM9161A_100BASE_T4 (1 << 15) /**< T4 mode */ 00101 #define DM9161A_100BASE_TX_FD (1 << 14) /**< 100MBps full duplex */ 00102 #define DM9161A_100BASE_TX_HD (1 << 13) /**< 100MBps half duplex */ 00103 #define DM9161A_10BASE_T_FD (1 << 12) /**< 10MBps full duplex */ 00104 #define DM9161A_10BASE_T_HD (1 << 11) /**< 10MBps half duplex */ 00105 #define DM9161A_MF_PREAMB_SUPPR (1 << 6 ) /**< Preamble suppress */ 00106 #define DM9161A_AUTONEG_COMP (1 << 5 ) /**< Auto-negotation complete */ 00107 #define DM9161A_RMT_FAULT (1 << 4 ) /**< Fault */ 00108 #define DM9161A_AUTONEG_ABILITY (1 << 3 ) /**< Auto-negotation supported */ 00109 #define DM9161A_LINK_STATUS (1 << 2 ) /**< 1=Link active */ 00110 #define DM9161A_JABBER_DETECT (1 << 1 ) /**< Jabber detect */ 00111 #define DM9161A_EXTEND_CAPAB (1 << 0 ) /**< Supports extended capabilities */ 00112 00113 /** \brief DM9161A ANAR and ANLPAR register definitions */ 00114 #define DM9161A_NP (1 << 15) /**< No next page - always = 0 */ 00115 #define DM9161A_ACK (1 << 14) /**< 1 = Link partner ability data reception acknowledged */ 00116 #define DM9161A_RF (1 << 13) /**< 1 = Local device senses a fault condition */ 00117 #define DM9161A_FCS (1 << 10) /**< 1 = Controller chip supports flow control ability */ 00118 #define DM9161A_T4 (1 << 9 ) /**< No 100BASE-T4 is supported - always = 0 */ 00119 #define DM9161A_TX_FDX (1 << 8 ) /**< 1 = 100BASE-TX full duplex is supported by the local device */ 00120 #define DM9161A_TX_HDX (1 << 7 ) /**< 1 = 100BASE-TX half duplex is supported by the local device */ 00121 #define DM9161A_10_FDX (1 << 6 ) /**< 1 = 10BASE-T full duplex is supported by the local device */ 00122 #define DM9161A_10_HDX (1 << 5 ) /**< 1 = 10BASE-T half duplex is supported by the local device */ 00123 #define DM9161A_AN_IEEE_802_3 0x0001 /**< this device supports IEEE 802.3 CSMA/CD */ 00124 00125 /** \brief DM9161A ANER register definitions */ 00126 #define DM9161A_PDF (1 << 4 ) /**< 1 = A fault detected via parallel detection function */ 00127 #define DM9161A_LP_NP_ABLE (1 << 3 ) /**< 1 = Link partner, next page available */ 00128 #define DM9161A_NP_ABLE (1 << 2 ) /**< No next page - always = 0 */ 00129 #define DM9161A_PAGE_RX (1 << 1 ) /**< New page received - cleared when reg 6 is read */ 00130 #define DM9161A_LP_AN_ABLE (1 << 0 ) /**< 1 = Link partner supports auto-negotiation */ 00131 00132 /** \brief DM9161A DSCR register definitions */ 00133 #define DM9161A_BP4B5B (1 << 15) /**< 1 = 4B5B encoder and 5B4B decoder function bypassed */ 00134 #define DM9161A_BP_SCR (1 << 14) /**< 1 = Scrambler and descrambler function bypassed */ 00135 #define DM9161A_BP_ALIGN (1 << 13) /**< 1 = Receive and Transmit functions disabled */ 00136 #define DM9161A_BP_ADPOK (1 << 12) /**< 1 = Force signal detector (SD) active - ONLY FOR DEBUG */ 00137 #define DM9161A_REPEATER (1 << 11) /**< 1 = Repeater mode - latched at power up reset */ 00138 #define DM9161A_TX (1 << 10) /**< 1 = 100BASE-TX operation */ 00139 #define DM9161A_RMII_ENABLE (1 << 8 ) /**< 1 = Enable Reduced MII */ 00140 #define DM9161A_F_LINK_100 (1 << 7 ) /**< 1 = Force 100Mbps good link status */ 00141 #define DM9161A_SPLED_CTL (1 << 6 ) /**< 1 = Disable SPEEDLED output and enable SD signal monitor - ONLY FOR DEBUG */ 00142 #define DM9161A_COLLED_CTL (1 << 5 ) /**< 1 = FDX/COLLED output is configured to indicate Fullduplex Collision status */ 00143 #define DM9161A_RPDCTR_EN (1 << 4 ) /**< 1 = Enable automatic reduced power down */ 00144 #define DM9161A_SM_RST (1 << 3 ) /**< 1 = Reset state machine - auto cleared after reset */ 00145 #define DM9161A_MFP_SC (1 << 2 ) /**< 1 = MF preamble suppression bit on */ 00146 #define DM9161A_SLEEP (1 << 1 ) /**< 1 = sleep mode */ 00147 #define DM9161A_RLOUT (1 << 0 ) /**< 1 = 1, loop out the received data to the transmit channel */ 00148 00149 /** \brief DM9161A DSCSR register definitions */ 00150 #define DM9161A_SPEEDMASK (15 << 12) /**< Speed and duplex mask */ 00151 #define DM9161A_100FDX (1 << 15) /**< 1 = 100MB full duplex */ 00152 #define DM9161A_100HDX (1 << 14) /**< 1 = 100MB half duplex */ 00153 #define DM9161A_10FDX (1 << 13) /**< 1 = 10MB full duplex */ 00154 #define DM9161A_10HDX (1 << 12) /**< 1 = 10MB half duplex */ 00155 00156 /** \brief DM9161A 10BTCSR register definitions */ 00157 #define DM9161A_LP_EN (1 << 14) /**< 1 = Transmission of link pulses enabled */ 00158 #define DM9161A_HBE (1 << 13) /**< 1 = Heartbeat function enabled */ 00159 #define DM9161A_SQUELCH (1 << 12) /**< 1 = normal squelch */ 00160 #define DM9161A_JABEN (1 << 11) /**< 1 = Jabber function enabled */ 00161 #define DM9161A_10BT_SER (1 << 10) /**< 1 = 10BASE-T GPSI mode selected */ 00162 #define DM9161A_POLR (1 << 0 ) /**< 1 = 10Mbps cable polarity is reversed */ 00163 00164 /** \brief DM9161A MDINTR register definitions */ 00165 #define DM9161A_INTR_PEND (1 << 15) /**< Interrupt pending */ 00166 #define DM9161A_FDX_MASK (1 << 11) /**< Full-duplex interrupt mask */ 00167 #define DM9161A_SPD_MASK (1 << 10) /**< Speed interrupt mask */ 00168 #define DM9161A_LINK_MASK (1 << 9 ) /**< Link interrupt mask */ 00169 #define DM9161A_INTR_MASK (1 << 8 ) /**< Master interrupt mask */ 00170 #define DM9161A_FDX_CHANGE (1 << 4 ) /**< 1 = indicates a change of duplex since last register read */ 00171 #define DM9161A_SPD_CHANGE (1 << 3 ) /**< 1 = indicates a change of speed since last register read */ 00172 #define DM9161A_LINK_CHANGE (1 << 2 ) /**< 1 = indicates a change of link since last register read */ 00173 #define DM9161A_INTR_STATUS (1 << 0 ) /**< 1 = indicates that the interrupt mask is off */ 00174 00175 /** \brief DM9161A RLSR register definitions */ 00176 #define DM9161A_LH_LEDMODE (1 << 15) /**< LEDMODE pin reset latch value */ 00177 #define DM9161A_LH_MDINTR (1 << 14) /**< MDINTR pin reset latch value */ 00178 #define DM9161A_LH_CSTS (1 << 13) /**< CABLESTS pin reset latch value */ 00179 #define DM9161A_LH_ISO (1 << 12) /**< TXCLK pin reset latch value */ 00180 #define DM9161A_LH_RMII (1 << 11) /**< COL pin reset latch value */ 00181 #define DM9161A_LH_TP10SER (1 << 10) /**< RXCLK pin reset latch value */ 00182 #define DM9161A_LH_REPTR (1 << 9) /**< RXER pin reset latch value */ 00183 #define DM9161A_LH_TSTMOD (1 << 8 ) /**< RXDV pin reset latch value */ 00184 #define DM9161A_LH_OP2 (1 << 7 ) /**< LINKLED pin reset latch value */ 00185 #define DM9161A_LH_OP1 (1 << 6 ) /**< SPOLED pin reset latch value */ 00186 #define DM9161A_LH_OP0 (1 << 5 ) /**< FDXLED pin reset latch value */ 00187 #define DM9161A_LH_PH4 (1 << 4 ) /**< CRS pin reset latch value */ 00188 #define DM9161A_LH_PH3 (1 << 3 ) /**< RXD3 pin reset latch value */ 00189 #define DM9161A_LH_PH2 (1 << 2 ) /**< RXD2 pin reset latch value */ 00190 #define DM9161A_LH_PH1 (1 << 1 ) /**< RXD1 pin reset latch value */ 00191 #define DM9161A_LH_PH0 (1 << 0 ) /**< RXD0 pin reset latch value */ 00192 00193 #define DM9161A_FULLD_100M 0x2100 /**< Full Duplex 100Mbit */ 00194 #define DM9161A_HALFD_100M 0x2000 /**< Half Duplex 100Mbit */ 00195 #define DM9161A_FULLD_10M 0x0100 /**< Full Duplex 10Mbit */ 00196 #define DM9161A_HALFD_10M 0x0000 /**< Half Duplex 10MBit */ 00197 #define DM9161A_AUTO_NEG 0x3000 /**< Select Auto Negotiation */ 00198 #define DM9161A_AUTO_NEG_MASK 0xEFFF /**< Auto Negotiation mask bit */ 00199 00200 /** \brief DM9161A PHY ID register definitions */ 00201 #define DM9161A_PHYID1_OUI 0x0181 /**< Expected PHY ID1 */ 00202 #define DM9161A_PHYID2_OUI 0xB8A0 /**< Expected PHY ID2 */ 00203 00204 #define DM9161A_DEF_ADR 0x1300 /**< Default PHY device address DM9161A */ 00205 00206 /** \brief PHY status structure used to indicate current status of PHY. 00207 */ 00208 typedef struct { 00209 u32_t phy_speed_100mbs:2; /**< 10/100 MBS connection speed flag. */ 00210 u32_t phy_full_duplex:2; /**< Half/full duplex connection speed flag. */ 00211 u32_t phy_link_active:2; /**< Phy link active flag. */ 00212 } PHY_STATUS_TYPE; 00213 00214 /** \brief PHY update flags */ 00215 static PHY_STATUS_TYPE physts; 00216 00217 /** \brief Last PHY update flags, used for determing if something has changed */ 00218 static PHY_STATUS_TYPE olddphysts; 00219 00220 /** \brief PHY update counter for state machine */ 00221 static s32_t phyustate; 00222 00223 /** \brief Update PHY status from passed value 00224 * 00225 * This function updates the current PHY status based on the 00226 * passed PHY status word. The PHY status indicate if the link 00227 * is active, the connection speed, and duplex. 00228 * 00229 * \param[in] netif NETIF structure 00230 * \param[in] linksts Status word with link state 00231 * \param[in] sdsts Status word with speed and duplex states 00232 * \return 1 if the status has changed, otherwise 0 00233 */ 00234 static s32_t lpc_update_phy_sts(struct netif *netif, u32_t linksts, u32_t sdsts) 00235 { 00236 s32_t changed = 0; 00237 00238 // sdsts &= DM9161A_AUTO_NEG_MASK; // mask DM9161A_AUTO_NEG 00239 00240 /* Update link active status */ 00241 if (linksts & DM9161A_LINK_STATUS) 00242 physts.phy_link_active = 1; 00243 else 00244 physts.phy_link_active = 0; 00245 00246 /* Full or half duplex */ 00247 if (sdsts & DM9161A_DUPLEX_MODE) 00248 physts.phy_full_duplex = 1; 00249 else 00250 physts.phy_full_duplex = 0; 00251 00252 /* Configure 100MBit/10MBit mode. */ 00253 if (sdsts & DM9161A_SPEED_SELECT) 00254 physts.phy_speed_100mbs = 1; 00255 else 00256 physts.phy_speed_100mbs = 0; 00257 00258 if (physts.phy_speed_100mbs != olddphysts.phy_speed_100mbs) { 00259 changed = 1; 00260 if (physts.phy_speed_100mbs) { 00261 /* 100MBit mode. */ 00262 lpc_emac_set_speed(1); 00263 00264 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 100000000); 00265 } 00266 else { 00267 /* 10MBit mode. */ 00268 lpc_emac_set_speed(0); 00269 00270 NETIF_INIT_SNMP(netif, snmp_ifType_ethernet_csmacd, 10000000); 00271 } 00272 00273 olddphysts.phy_speed_100mbs = physts.phy_speed_100mbs; 00274 } 00275 00276 if (physts.phy_full_duplex != olddphysts.phy_full_duplex) { 00277 changed = 1; 00278 if (physts.phy_full_duplex) 00279 lpc_emac_set_duplex(1); 00280 else 00281 lpc_emac_set_duplex(0); 00282 00283 olddphysts.phy_full_duplex = physts.phy_full_duplex; 00284 } 00285 00286 if (physts.phy_link_active != olddphysts.phy_link_active) { 00287 changed = 1; 00288 #if NO_SYS == 1 00289 if (physts.phy_link_active) 00290 netif_set_link_up(netif); 00291 else 00292 netif_set_link_down(netif); 00293 #else 00294 if (physts.phy_link_active) 00295 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_up, 00296 (void*) netif, 1); 00297 else 00298 tcpip_callback_with_block((tcpip_callback_fn) netif_set_link_down, 00299 (void*) netif, 1); 00300 #endif 00301 00302 olddphysts.phy_link_active = physts.phy_link_active; 00303 } 00304 00305 return changed; 00306 } 00307 00308 /** \brief Initialize the DM9161A PHY. 00309 * 00310 * This function initializes the DM9161A PHY. It will block until 00311 * complete. This function is called as part of the EMAC driver 00312 * initialization. Configuration of the PHY at startup is 00313 * controlled by setting up configuration defines in lpc_phy.h. 00314 * 00315 * \param[in] netif NETIF structure 00316 * \param[in] rmii If set, configures the PHY for RMII mode 00317 * \return ERR_OK if the setup was successful, otherwise ERR_TIMEOUT 00318 */ 00319 err_t lpc_phy_init(struct netif *netif, int rmii) 00320 { 00321 u32_t tmp; 00322 s32_t i; 00323 00324 physts.phy_speed_100mbs = olddphysts.phy_speed_100mbs = 2; 00325 physts.phy_full_duplex = olddphysts.phy_full_duplex = 2; 00326 physts.phy_link_active = olddphysts.phy_link_active = 2; 00327 phyustate = 0; 00328 00329 /* Only first read and write are checked for failure */ 00330 /* Put the DM9161A in reset mode and wait for completion */ 00331 if (lpc_mii_write(DM9161A_BMCR_REG, DM9161A_RESET) != 0) 00332 return ERR_TIMEOUT; 00333 i = 400; 00334 while (i > 0) { 00335 osDelay(1); // 1 ms 00336 if (lpc_mii_read(DM9161A_BMCR_REG, &tmp) != 0) 00337 return ERR_TIMEOUT; 00338 00339 if (!(tmp & (DM9161A_RESET | DM9161A_POWER_DOWN))) 00340 i = -1; 00341 else 00342 i--; 00343 } 00344 // Timeout? 00345 if (i == 0) 00346 return ERR_TIMEOUT; 00347 00348 /* Setup link based on configuration options */ 00349 #if PHY_USE_AUTONEG==1 00350 tmp = DM9161A_AUTONEG | DM9161A_RESTART_AUTONEG; 00351 #else 00352 tmp = 0; 00353 #endif 00354 #if PHY_USE_100MBS==1 00355 tmp |= DM9161A_SPEED_SELECT; 00356 #endif 00357 #if PHY_USE_FULL_DUPLEX==1 00358 tmp |= DM9161A_DUPLEX_MODE; 00359 #endif 00360 00361 lpc_mii_write(DM9161A_BMCR_REG, tmp); 00362 00363 /* Wait for autonegotiation completion */ 00364 i = 400; 00365 while (i > 0) 00366 { 00367 osDelay(1); // 1 ms 00368 if (lpc_mii_read(DM9161A_BMSR_REG, &tmp) != 0) 00369 { 00370 printf("Timeout\n"); 00371 return ERR_TIMEOUT; 00372 } 00373 if (tmp & (DM9161A_AUTONEG_COMP)) 00374 i = -1; 00375 else 00376 i--; 00377 } 00378 // Timeout? 00379 if (i == 0) 00380 { 00381 printf("Timeout\n"); 00382 return ERR_TIMEOUT; 00383 } 00384 00385 /* Enable RMII mode for PHY - NOT NEEDED FOR MIDI-DK - RMII pin is lathed on reset*/ 00386 /* if (rmii) 00387 lpc_mii_write(DM9161A_DSCR_REG, DM9161A_RMII_ENABLE); 00388 */ 00389 /* The link is not set active at this point, but will be detected 00390 later */ 00391 00392 return ERR_OK; 00393 } 00394 00395 /* Phy status update state machine */ 00396 s32_t lpc_phy_sts_sm(struct netif *netif) 00397 { 00398 static u32_t sts; 00399 s32_t changed = 0; 00400 switch (phyustate) 00401 { 00402 default: 00403 case 0: 00404 // Read BMSR to clear faults 00405 lpc_mii_read_noblock(DM9161A_BMSR_REG); 00406 phyustate = 1; 00407 break; 00408 00409 case 1: 00410 // Wait for read status state 00411 if (!lpc_mii_is_busy()) 00412 { 00413 // Get autonegotiation complete bit 00414 sts = lpc_mii_read_data(); 00415 lpc_mii_read_noblock(DM9161A_BMCR_REG); 00416 phyustate = 2; 00417 } 00418 break; 00419 00420 case 2: 00421 // Wait for read status state 00422 if (!lpc_mii_is_busy()) 00423 { 00424 // Update PHY status (BMCR contains speed and duplex state) 00425 changed = lpc_update_phy_sts(netif, sts, lpc_mii_read_data()); 00426 phyustate = 0; 00427 } 00428 break; 00429 } 00430 return changed; 00431 } 00432 00433 /* //Original state machine code 00434 */ 00435 00436 00437 00438 /** 00439 * @} 00440 */ 00441 00442 /* --------------------------------- End Of File ------------------------------ */
Generated on Tue Jul 12 2022 20:48:42 by 1.7.2