dp83tc812_driver.c
Go to the documentation of this file.
1 /**
2  * @file dp83tc812_driver.c
3  * @brief DP83TC812 100Base-T1 Ethernet PHY driver
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneTCP Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL NIC_TRACE_LEVEL
33 
34 //Dependencies
35 #include "core/net.h"
37 #include "debug.h"
38 
39 
40 /**
41  * @brief DP83TC812 Ethernet PHY driver
42  **/
43 
45 {
51 };
52 
53 
54 /**
55  * @brief DP83TC812 PHY transceiver initialization
56  * @param[in] interface Underlying network interface
57  * @return Error code
58  **/
59 
61 {
62  //Debug message
63  TRACE_INFO("Initializing DP83TC812...\r\n");
64 
65  //Undefined PHY address?
66  if(interface->phyAddr >= 32)
67  {
68  //Use the default address
69  interface->phyAddr = DP83TC812_PHY_ADDR;
70  }
71 
72  //Initialize serial management interface
73  if(interface->smiDriver != NULL)
74  {
75  interface->smiDriver->init();
76  }
77 
78  //Initialize external interrupt line driver
79  if(interface->extIntDriver != NULL)
80  {
81  interface->extIntDriver->init();
82  }
83 
84  //Reset PHY transceiver
86 
87  //Wait for the reset to complete
89  {
90  }
91 
92  //Dump PHY registers for debugging purpose
93  dp83tc812DumpPhyReg(interface);
94 
95  //Perform custom configuration
96  dp83tc812InitHook(interface);
97 
98  //Force the TCP/IP stack to poll the link state at startup
99  interface->phyEvent = TRUE;
100  //Notify the TCP/IP stack of the event
102 
103  //Successful initialization
104  return NO_ERROR;
105 }
106 
107 
108 /**
109  * @brief DP83TC812 custom configuration
110  * @param[in] interface Underlying network interface
111  **/
112 
113 __weak_func void dp83tc812InitHook(NetInterface *interface)
114 {
115 }
116 
117 
118 /**
119  * @brief DP83TC812 timer handler
120  * @param[in] interface Underlying network interface
121  **/
122 
123 void dp83tc812Tick(NetInterface *interface)
124 {
125  uint16_t value;
126  bool_t linkState;
127 
128  //No external interrupt line driver?
129  if(interface->extIntDriver == NULL)
130  {
131  //Read status register
133  //Retrieve current link state
134  linkState = (value & DP83TC812_BMSR_LINK_STATUS) ? TRUE : FALSE;
135 
136  //Link up event?
137  if(linkState && !interface->linkState)
138  {
139  //Set event flag
140  interface->phyEvent = TRUE;
141  //Notify the TCP/IP stack of the event
143  }
144  //Link down event?
145  else if(!linkState && interface->linkState)
146  {
147  //Set event flag
148  interface->phyEvent = TRUE;
149  //Notify the TCP/IP stack of the event
151  }
152  }
153 }
154 
155 
156 /**
157  * @brief Enable interrupts
158  * @param[in] interface Underlying network interface
159  **/
160 
162 {
163  //Enable PHY transceiver interrupts
164  if(interface->extIntDriver != NULL)
165  {
166  interface->extIntDriver->enableIrq();
167  }
168 }
169 
170 
171 /**
172  * @brief Disable interrupts
173  * @param[in] interface Underlying network interface
174  **/
175 
177 {
178  //Disable PHY transceiver interrupts
179  if(interface->extIntDriver != NULL)
180  {
181  interface->extIntDriver->disableIrq();
182  }
183 }
184 
185 
186 /**
187  * @brief DP83TC812 event handler
188  * @param[in] interface Underlying network interface
189  **/
190 
192 {
193  uint16_t value;
194 
195  //Read status register
197 
198  //Link is up?
199  if((value & DP83TC812_BMSR_LINK_STATUS) != 0)
200  {
201  //The PHY is only able to operate in 100 Mbps mode
202  interface->linkSpeed = NIC_LINK_SPEED_100MBPS;
203  interface->duplexMode = NIC_FULL_DUPLEX_MODE;
204 
205  //Adjust MAC configuration parameters for proper operation
206  interface->nicDriver->updateMacConfig(interface);
207 
208  //Update link state
209  interface->linkState = TRUE;
210  }
211  else
212  {
213  //Update link state
214  interface->linkState = FALSE;
215  }
216 
217  //Process link state change event
218  nicNotifyLinkChange(interface);
219 }
220 
221 
222 /**
223  * @brief Write PHY register
224  * @param[in] interface Underlying network interface
225  * @param[in] address PHY register address
226  * @param[in] data Register value
227  **/
228 
229 void dp83tc812WritePhyReg(NetInterface *interface, uint8_t address,
230  uint16_t data)
231 {
232  //Write the specified PHY register
233  if(interface->smiDriver != NULL)
234  {
235  interface->smiDriver->writePhyReg(SMI_OPCODE_WRITE,
236  interface->phyAddr, address, data);
237  }
238  else
239  {
240  interface->nicDriver->writePhyReg(SMI_OPCODE_WRITE,
241  interface->phyAddr, address, data);
242  }
243 }
244 
245 
246 /**
247  * @brief Read PHY register
248  * @param[in] interface Underlying network interface
249  * @param[in] address PHY register address
250  * @return Register value
251  **/
252 
253 uint16_t dp83tc812ReadPhyReg(NetInterface *interface, uint8_t address)
254 {
255  uint16_t data;
256 
257  //Read the specified PHY register
258  if(interface->smiDriver != NULL)
259  {
260  data = interface->smiDriver->readPhyReg(SMI_OPCODE_READ,
261  interface->phyAddr, address);
262  }
263  else
264  {
265  data = interface->nicDriver->readPhyReg(SMI_OPCODE_READ,
266  interface->phyAddr, address);
267  }
268 
269  //Return the value of the PHY register
270  return data;
271 }
272 
273 
274 /**
275  * @brief Dump PHY registers for debugging purpose
276  * @param[in] interface Underlying network interface
277  **/
278 
280 {
281  uint8_t i;
282 
283  //Loop through PHY registers
284  for(i = 0; i < 32; i++)
285  {
286  //Display current PHY register
287  TRACE_DEBUG("%02" PRIu8 ": 0x%04" PRIX16 "\r\n", i,
288  dp83tc812ReadPhyReg(interface, i));
289  }
290 
291  //Terminate with a line feed
292  TRACE_DEBUG("\r\n");
293 }
294 
295 
296 /**
297  * @brief Write MMD register
298  * @param[in] interface Underlying network interface
299  * @param[in] devAddr Device address
300  * @param[in] regAddr Register address
301  * @param[in] data MMD register value
302  **/
303 
304 void dp83tc812WriteMmdReg(NetInterface *interface, uint8_t devAddr,
305  uint16_t regAddr, uint16_t data)
306 {
307  //Select register operation
310 
311  //Write MMD register address
313 
314  //Select data operation
317 
318  //Write the content of the MMD register
320 }
321 
322 
323 /**
324  * @brief Read MMD register
325  * @param[in] interface Underlying network interface
326  * @param[in] devAddr Device address
327  * @param[in] regAddr Register address
328  * @return MMD register value
329  **/
330 
331 uint16_t dp83tc812ReadMmdReg(NetInterface *interface, uint8_t devAddr,
332  uint16_t regAddr)
333 {
334  //Select register operation
337 
338  //Write MMD register address
340 
341  //Select data operation
344 
345  //Read the content of the MMD register
346  return dp83tc812ReadPhyReg(interface, DP83TC812_ADDAR);
347 }
void nicNotifyLinkChange(NetInterface *interface)
Process link state change notification.
Definition: nic.c:559
void dp83tc812DisableIrq(NetInterface *interface)
Disable interrupts.
error_t dp83tc812Init(NetInterface *interface)
DP83TC812 PHY transceiver initialization.
void dp83tc812EnableIrq(NetInterface *interface)
Enable interrupts.
int bool_t
Definition: compiler_port.h:53
void dp83tc812DumpPhyReg(NetInterface *interface)
Dump PHY registers for debugging purpose.
#define netEvent
Definition: net_legacy.h:196
#define DP83TC812_BMCR
@ NIC_FULL_DUPLEX_MODE
Definition: nic.h:125
#define TRUE
Definition: os_port.h:50
Ethernet PHY driver.
Definition: nic.h:311
uint8_t data[]
Definition: ethernet.h:222
void dp83tc812EventHandler(NetInterface *interface)
DP83TC812 event handler.
#define DP83TC812_REGCR_DEVAD
#define DP83TC812_ADDAR
#define DP83TC812_REGCR_CMD_DATA_NO_POST_INC
#define DP83TC812_REGCR_CMD_ADDR
#define SMI_OPCODE_WRITE
Definition: nic.h:66
#define FALSE
Definition: os_port.h:46
error_t
Error codes.
Definition: error.h:43
uint16_t dp83tc812ReadMmdReg(NetInterface *interface, uint8_t devAddr, uint16_t regAddr)
Read MMD register.
#define NetInterface
Definition: net.h:36
#define SMI_OPCODE_READ
Definition: nic.h:67
#define TRACE_INFO(...)
Definition: debug.h:95
#define DP83TC812_BMSR_LINK_STATUS
#define TRACE_DEBUG(...)
Definition: debug.h:107
uint16_t regAddr
__weak_func void dp83tc812InitHook(NetInterface *interface)
DP83TC812 custom configuration.
Ipv6Addr address[]
Definition: ipv6.h:325
DP83TC812 100Base-T1 Ethernet PHY driver.
void dp83tc812Tick(NetInterface *interface)
DP83TC812 timer handler.
const PhyDriver dp83tc812PhyDriver
DP83TC812 Ethernet PHY driver.
void dp83tc812WritePhyReg(NetInterface *interface, uint8_t address, uint16_t data)
Write PHY register.
#define DP83TC812_PHY_ADDR
uint8_t value[]
Definition: tcp.h:369
#define DP83TC812_BMCR_RESET
void osSetEvent(OsEvent *event)
Set the specified event object to the signaled state.
#define DP83TC812_REGCR
uint16_t dp83tc812ReadPhyReg(NetInterface *interface, uint8_t address)
Read PHY register.
@ NIC_LINK_SPEED_100MBPS
Definition: nic.h:112
TCP/IP stack core.
#define DP83TC812_BMSR
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
void dp83tc812WriteMmdReg(NetInterface *interface, uint8_t devAddr, uint16_t regAddr, uint16_t data)
Write MMD register.