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.
ksz9031.c
00001 /** 00002 * @file ksz9031.c 00003 * @brief KSZ9031 Gigabit 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/ksz9031.h" 00035 #include "debug.h" 00036 00037 00038 /** 00039 * @brief KSZ9031 Ethernet PHY driver 00040 **/ 00041 00042 const PhyDriver ksz9031PhyDriver = 00043 { 00044 ksz9031Init, 00045 ksz9031Tick, 00046 ksz9031EnableIrq, 00047 ksz9031DisableIrq, 00048 ksz9031EventHandler, 00049 }; 00050 00051 00052 /** 00053 * @brief KSZ9031 PHY transceiver initialization 00054 * @param[in] interface Underlying network interface 00055 * @return Error code 00056 **/ 00057 00058 error_t ksz9031Init(NetInterface *interface) 00059 { 00060 //Debug message 00061 TRACE_INFO("Initializing KSZ9031...\r\n"); 00062 00063 //Initialize external interrupt line driver 00064 if(interface->extIntDriver != NULL) 00065 interface->extIntDriver->init(); 00066 00067 //Reset PHY transceiver 00068 ksz9031WritePhyReg(interface, KSZ9031_PHY_REG_BMCR, BMCR_RESET); 00069 //Wait for the reset to complete 00070 while(ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMCR) & BMCR_RESET); 00071 00072 //Dump PHY registers for debugging purpose 00073 ksz9031DumpPhyReg(interface); 00074 00075 //The PHY will generate interrupts when link status changes are detected 00076 ksz9031WritePhyReg(interface, KSZ9031_PHY_REG_ICSR, ICSR_LINK_DOWN_IE | ICSR_LINK_UP_IE); 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 KSZ9031 timer handler 00090 * @param[in] interface Underlying network interface 00091 **/ 00092 00093 void ksz9031Tick(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 = ksz9031ReadPhyReg(interface, KSZ9031_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 ksz9031EnableIrq(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 ksz9031DisableIrq(NetInterface *interface) 00145 { 00146 //Disable PHY transceiver interrupts 00147 if(interface->extIntDriver != NULL) 00148 interface->extIntDriver->disableIrq(); 00149 } 00150 00151 00152 /** 00153 * @brief KSZ9031 event handler 00154 * @param[in] interface Underlying network interface 00155 **/ 00156 00157 void ksz9031EventHandler(NetInterface *interface) 00158 { 00159 uint16_t value; 00160 00161 //Read status register to acknowledge the interrupt 00162 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_ICSR); 00163 00164 //Link status change? 00165 if(value & (ICSR_LINK_DOWN_IF | ICSR_LINK_UP_IF)) 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 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMSR); 00170 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_BMSR); 00171 00172 //Link is up? 00173 if(value & BMSR_LINK_STATUS) 00174 { 00175 //Read PHY control register 00176 value = ksz9031ReadPhyReg(interface, KSZ9031_PHY_REG_PHYCON); 00177 00178 //Check current speed 00179 if(value & PHYCON_SPEED_1000BT) 00180 { 00181 //1000BASE-T 00182 interface->linkSpeed = NIC_LINK_SPEED_1GBPS; 00183 } 00184 else if(value & PHYCON_SPEED_100BTX) 00185 { 00186 //100BASE-TX 00187 interface->linkSpeed = NIC_LINK_SPEED_100MBPS; 00188 } 00189 else if(value & PHYCON_SPEED_10BT) 00190 { 00191 //10BASE-T 00192 interface->linkSpeed = NIC_LINK_SPEED_10MBPS; 00193 } 00194 else 00195 { 00196 //Debug message 00197 TRACE_WARNING("Invalid speed!\r\n"); 00198 } 00199 00200 //Check current duplex mode 00201 if(value & PHYCON_DUPLEX_STATUS) 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 ksz9031WritePhyReg(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 = KSZ9031_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 ksz9031ReadPhyReg(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 = KSZ9031_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 ksz9031DumpPhyReg(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, ksz9031ReadPhyReg(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:14 by
1.7.2