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.
rtl8211.c
00001 /** 00002 * @file rtl8211.c 00003 * @brief RTL8211 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/rtl8211.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief RTL8211 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver rtl8211PhyDriver = 00043 { 00044 rtl8211Init, 00045 rtl8211Tick, 00046 rtl8211EnableIrq, 00047 rtl8211DisableIrq, 00048 rtl8211EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief RTL8211 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t rtl8211Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing RTL8211...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver 00068 rtl8211WritePhyReg(interface, RTL8211_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Dump PHY registers for debugging purpose 00073 rtl8211DumpPhyReg(interface); 00074 00075 //The PHY will generate interrupts when link status changes are detected 00076 rtl8211WritePhyReg(interface, RTL8211_PHY_REG_INER, INER_AN_COMPLETE | INER_LINK_STATUS); 00077 00078 //Force the TCP/IP stack to poll the link state at startup 00079 interface->phyEvent = TRUE; 00080 //Notify the TCP/IP stack of the event 00081 osSetEvent(&netEvent); 00082 00083 //Successful initialization 00084 return NO_ERROR; 00085 } 00086 00087 00088 /** 00089 * @brief RTL8211 timer handler 00090 * @param[in] interface Underlying network interface 00091 **/ 00092 00093 void rtl8211Tick(NetInterface *interface) 00094 { 00095 uint16_t value; 00096 bool_t linkState; 00097 00098 //No external interrupt line driver? 00099 if(interface->extIntDriver == NULL) 00100 { 00101 //Read basic status register 00102 value = rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_BMSR); 00103 //Retrieve current link state 00104 linkState = (value & BMSR_LINK_STATUS) ? TRUE : FALSE; 00105 00106 //Link up event? 00107 if(linkState && !interface->linkState) 00108 { 00109 //Set event flag 00110 interface->phyEvent = TRUE; 00111 //Notify the TCP/IP stack of the event 00112 osSetEvent(&netEvent); 00113 } 00114 //Link down event? 00115 else 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 } 00123 } 00124 00125 00126 /** 00127 * @brief Enable interrupts 00128 * @param[in] interface Underlying network interface 00129 **/ 00130 00131 void rtl8211EnableIrq(NetInterface *interface) 00132 { 00133 //Enable PHY transceiver interrupts 00134 if(interface->extIntDriver != NULL) 00135 interface->extIntDriver->enableIrq(); 00136 } 00137 00138 00139 /** 00140 * @brief Disable interrupts 00141 * @param[in] interface Underlying network interface 00142 **/ 00143 00144 void rtl8211DisableIrq(NetInterface *interface) 00145 { 00146 //Disable PHY transceiver interrupts 00147 if(interface->extIntDriver != NULL) 00148 interface->extIntDriver->disableIrq(); 00149 } 00150 00151 00152 /** 00153 * @brief RTL8211 event handler 00154 * @param[in] interface Underlying network interface 00155 **/ 00156 00157 void rtl8211EventHandler(NetInterface *interface) 00158 { 00159 uint16_t status; 00160 00161 //Read status register to acknowledge the interrupt 00162 status = rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_INSR); 00163 00164 //Link status change? 00165 if(status & (INSR_AN_COMPLETE | INSR_LINK_STATUS)) 00166 { 00167 //Any link failure condition is latched in the BMSR register... Reading 00168 //the register twice will always return the actual link status 00169 status = rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_BMSR); 00170 status = rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_BMSR); 00171 00172 //Link is up? 00173 if(status & BMSR_LINK_STATUS) 00174 { 00175 //Read PHY status register 00176 status = rtl8211ReadPhyReg(interface, RTL8211_PHY_REG_PHYSR); 00177 00178 //Check current speed 00179 switch(status & PHYSR_SPEED_MASK) 00180 { 00181 //10BASE-T 00182 case PHYSR_SPEED_10: 00183 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00184 break; 00185 //100BASE-TX 00186 case PHYSR_SPEED_100: 00187 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00188 break; 00189 //1000BASE-T 00190 case PHYSR_SPEED_1000: 00191 interface->linkSpeed = NIC_LINK_SPEED_1GBPS; 00192 break; 00193 //Unknown speed 00194 default: 00195 //Debug message 00196 TRACE_WARNING("Invalid speed\r\n"); 00197 break; 00198 } 00199 00200 //Check current duplex mode 00201 if(status & PHYSR_DUPLEX) 00202 interface->duplexMode = NIC_FULL_DUPLEX_MODE; 00203 else 00204 interface->duplexMode = NIC_HALF_DUPLEX_MODE; 00205 00206 //Update link state 00207 interface->linkState = TRUE; 00208 00209 //Adjust MAC configuration parameters for proper operation 00210 interface->nicDriver->updateMacConfig(interface); 00211 } 00212 else 00213 { 00214 //Update link state 00215 interface->linkState = FALSE; 00216 } 00217 00218 //Process link state change event 00219 nicNotifyLinkChange(interface); 00220 } 00221 } 00222 00223 00224 /** 00225 * @brief Write PHY register 00226 * @param[in] interface Underlying network interface 00227 * @param[in] address PHY register address 00228 * @param[in] data Register value 00229 **/ 00230 00231 void rtl8211WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data) 00232 { 00233 uint8_t phyAddr; 00234 00235 //Get the address of the PHY transceiver 00236 if(interface->phyAddr < 32) 00237 phyAddr = interface->phyAddr; 00238 else 00239 phyAddr = RTL8211_PHY_ADDR; 00240 00241 //Write the specified PHY register 00242 interface->nicDriver->writePhyReg(phyAddr, address, data); 00243 } 00244 00245 00246 /** 00247 * @brief Read PHY register 00248 * @param[in] interface Underlying network interface 00249 * @param[in] address PHY register address 00250 * @return Register value 00251 **/ 00252 00253 uint16_t rtl8211ReadPhyReg(NetInterface *interface, uint8_t address) 00254 { 00255 uint8_t phyAddr; 00256 00257 //Get the address of the PHY transceiver 00258 if(interface->phyAddr < 32) 00259 phyAddr = interface->phyAddr; 00260 else 00261 phyAddr = RTL8211_PHY_ADDR; 00262 00263 //Read the specified PHY register 00264 return interface->nicDriver->readPhyReg(phyAddr, address); 00265 } 00266 00267 00268 /** 00269 * @brief Dump PHY registers for debugging purpose 00270 * @param[in] interface Underlying network interface 00271 **/ 00272 00273 void rtl8211DumpPhyReg(NetInterface *interface) 00274 { 00275 uint8_t i; 00276 00277 //Loop through PHY registers 00278 for(i = 0; i < 32; i++) 00279 { 00280 //Display current PHY register 00281 TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i, rtl8211ReadPhyReg(interface, i)); 00282 } 00283 00284 //Terminate with a line feed 00285 TRACE_DEBUG("\r\n"); 00286 } 00287
Generated on Tue Jul 12 2022 17:10:15 by
1.7.2