Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lan8742.c
00001 /** 00002 * @file lan8742.c 00003 * @brief LAN8742 Ethernet PHY transceiver 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneTCP Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL NIC_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include "core/net.h" 00034 #include "drivers/lan8742.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief LAN8742 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver lan8742PhyDriver = 00043 { 00044 lan8742Init, 00045 lan8742Tick, 00046 lan8742EnableIrq, 00047 lan8742DisableIrq, 00048 lan8742EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief LAN8742 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t lan8742Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing LAN8742...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver (soft reset) 00068 lan8742WritePhyReg(interface, LAN8742_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(lan8742ReadPhyReg(interface, LAN8742_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Restore default auto-negotiation advertisement parameters 00073 lan8742WritePhyReg(interface, LAN8742_PHY_REG_ANAR, ANAR_100BTX_FD | 00074 ANAR_100BTX | ANAR_10BT_FD | ANAR_10BT | ANAR_SELECTOR0); 00075 00076 //Enable auto-negotiation 00077 lan8742WritePhyReg(interface, LAN8742_PHY_REG_BMCR, BMCR_AN_EN); 00078 00079 //Dump PHY registers for debugging purpose 00080 lan8742DumpPhyReg(interface); 00081 00082 //The PHY will generate interrupts when link status changes are detected 00083 lan8742WritePhyReg(interface, LAN8742_PHY_REG_IMR, 00084 IMR_AN_COMPLETE | IMR_LINK_DOWN); 00085 00086 //Force the TCP/IP stack to poll the link state at startup 00087 interface->phyEvent = TRUE; 00088 //Notify the TCP/IP stack of the event 00089 osSetEvent(&netEvent); 00090 00091 //Successful initialization 00092 return NO_ERROR; 00093 } 00094 00095 00096 /** 00097 * @brief LAN8742 timer handler 00098 * @param[in] interface Underlying network interface 00099 **/ 00100 00101 void lan8742Tick(NetInterface *interface) 00102 { 00103 uint16_t value; 00104 bool_t linkState; 00105 00106 //No external interrupt line driver? 00107 if(interface->extIntDriver == NULL) 00108 { 00109 //Read basic status register 00110 value = lan8742ReadPhyReg(interface, LAN8742_PHY_REG_BMSR); 00111 //Retrieve current link state 00112 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE; 00113 00114 //Link up event? 00115 if(linkState && !interface->linkState) 00116 { 00117 //Set event flag 00118 interface->phyEvent = TRUE; 00119 //Notify the TCP/IP stack of the event 00120 osSetEvent(&netEvent); 00121 } 00122 //Link down event? 00123 else if(!linkState && interface->linkState) 00124 { 00125 //Set event flag 00126 interface->phyEvent = TRUE; 00127 //Notify the TCP/IP stack of the event 00128 osSetEvent(&netEvent); 00129 } 00130 } 00131 } 00132 00133 00134 /** 00135 * @brief Enable interrupts 00136 * @param[in] interface Underlying network interface 00137 **/ 00138 00139 void lan8742EnableIrq(NetInterface *interface) 00140 { 00141 //Enable PHY transceiver interrupts 00142 if(interface->extIntDriver != NULL) 00143 interface->extIntDriver->enableIrq(); 00144 } 00145 00146 00147 /** 00148 * @brief Disable interrupts 00149 * @param[in] interface Underlying network interface 00150 **/ 00151 00152 void lan8742DisableIrq(NetInterface *interface) 00153 { 00154 //Disable PHY transceiver interrupts 00155 if(interface->extIntDriver != NULL) 00156 interface->extIntDriver->disableIrq(); 00157 } 00158 00159 00160 /** 00161 * @brief LAN8742 event handler 00162 * @param[in] interface Underlying network interface 00163 **/ 00164 00165 void lan8742EventHandler(NetInterface *interface) 00166 { 00167 uint16_t value; 00168 00169 //Read status register to acknowledge the interrupt 00170 value = lan8742ReadPhyReg(interface, LAN8742_PHY_REG_ISR); 00171 00172 //Link status change? 00173 if(value & (IMR_AN_COMPLETE | IMR_LINK_DOWN)) 00174 { 00175 //Any link failure condition is latched in the BMSR register... Reading 00176 //the register twice will always return the actual link status 00177 value = lan8742ReadPhyReg(interface, LAN8742_PHY_REG_BMSR); 00178 value = lan8742ReadPhyReg(interface, LAN8742_PHY_REG_BMSR); 00179 00180 //Link is up? 00181 if(value & BMSR_LINK_STATUS) 00182 { 00183 //Read PHY special control/status register 00184 value = lan8742ReadPhyReg(interface, LAN8742_PHY_REG_PSCSR); 00185 00186 //Check current operation mode 00187 switch(value & PSCSR_HCDSPEED_MASK) 00188 { 00189 //10BASE-T 00190 case PSCSR_HCDSPEED_10BT: 00191 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00192 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00193 break; 00194 //10BASE-T full-duplex 00195 case PSCSR_HCDSPEED_10BT_FD: 00196 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00197 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00198 break; 00199 //100BASE-TX 00200 case PSCSR_HCDSPEED_100BTX: 00201 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00202 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00203 break; 00204 //100BASE-TX full-duplex 00205 case PSCSR_HCDSPEED_100BTX_FD: 00206 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00207 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00208 break; 00209 //Unknown operation mode 00210 default: 00211 //Debug message 00212 TRACE_WARNING("Invalid Duplex mode\r\n"); 00213 break; 00214 } 00215 00216 //Update link state 00217 interface->linkState = TRUE; 00218 00219 //Adjust MAC configuration parameters for proper operation 00220 interface->nicDriver->updateMacConfig(interface); 00221 } 00222 else 00223 { 00224 //Update link state 00225 interface->linkState = FALSE; 00226 } 00227 00228 //Process link state change event 00229 nicNotifyLinkChange(interface); 00230 } 00231 } 00232 00233 00234 /** 00235 * @brief Write PHY register 00236 * @param[in] interface Underlying network interface 00237 * @param[in] address PHY register address 00238 * @param[in] data Register value 00239 **/ 00240 00241 void lan8742WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00242 { 00243 uint8_t phyAddr; 00244 00245 //Get the address of the PHY transceiver 00246 if(interface->phyAddr < 32) 00247 phyAddr = interface->phyAddr; 00248 else 00249 phyAddr = LAN8742_PHY_ADDR; 00250 00251 //Write the specified PHY register 00252 interface->nicDriver->writePhyReg(phyAddr, address, data); 00253 } 00254 00255 00256 /** 00257 * @brief Read PHY register 00258 * @param[in] interface Underlying network interface 00259 * @param[in] address PHY register address 00260 * @return Register value 00261 **/ 00262 00263 uint16_t lan8742ReadPhyReg(NetInterface *interface, uint8_t address) 00264 { 00265 uint8_t phyAddr; 00266 00267 //Get the address of the PHY transceiver 00268 if(interface->phyAddr < 32) 00269 phyAddr = interface->phyAddr; 00270 else 00271 phyAddr = LAN8742_PHY_ADDR; 00272 00273 //Read the specified PHY register 00274 return interface->nicDriver->readPhyReg(phyAddr, address); 00275 } 00276 00277 00278 /** 00279 * @brief Dump PHY registers for debugging purpose 00280 * @param[in] interface Underlying network interface 00281 **/ 00282 00283 void lan8742DumpPhyReg(NetInterface *interface) 00284 { 00285 uint8_t i; 00286 00287 //Loop through PHY registers 00288 for(i = 0; i < 32; i++) 00289 { 00290 //Display current PHY register 00291 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, lan8742ReadPhyReg(interface, i)); 00292 } 00293 00294 //Terminate with a line feed 00295 TRACE_DEBUG("\r\n"); 00296 } 00297
Generated on Tue Jul 12 2022 17:10:14 by
