LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc_phy_smsc87x0.c
Go to the documentation of this file.
1 /*
2  * @brief SMSC 87x0 simple PHY driver
3  *
4  * @note
5  * Copyright(C) NXP Semiconductors, 2012
6  * All rights reserved.
7  *
8  * @par
9  * Software that is described herein is for illustrative purposes only
10  * which provides customers with programming information regarding the
11  * LPC products. This software is supplied "AS IS" without any warranties of
12  * any kind, and NXP Semiconductors and its licensor disclaim any and
13  * all warranties, express or implied, including all implied warranties of
14  * merchantability, fitness for a particular purpose and non-infringement of
15  * intellectual property rights. NXP Semiconductors assumes no responsibility
16  * or liability for the use of the software, conveys no license or rights under any
17  * patent, copyright, mask work right, or any other intellectual property rights in
18  * or to any products. NXP Semiconductors reserves the right to make changes
19  * in the software without notification. NXP Semiconductors also makes no
20  * representation or warranty that such application will be suitable for the
21  * specified use without further testing or modification.
22  *
23  * @par
24  * Permission to use, copy, modify, and distribute this software and its
25  * documentation is hereby granted, under NXP Semiconductors' and its
26  * licensor's relevant copyrights in the software, without fee, provided that it
27  * is used in conjunction with NXP Semiconductors microcontrollers. This
28  * copyright, permission, and disclaimer notice must appear in all copies of
29  * this code.
30  */
31 
32 #include "chip.h"
33 #include "lpc_phy.h"
34 
42 /* LAN8720 PHY register offsets */
43 #define LAN8_BCR_REG 0x0
44 #define LAN8_BSR_REG 0x1
45 #define LAN8_PHYID1_REG 0x2
46 #define LAN8_PHYID2_REG 0x3
47 #define LAN8_PHYSPLCTL_REG 0x1F
49 /* LAN8720 BCR register definitions */
50 #define LAN8_RESET (1 << 15)
51 #define LAN8_LOOPBACK (1 << 14)
52 #define LAN8_SPEED_SELECT (1 << 13)
53 #define LAN8_AUTONEG (1 << 12)
54 #define LAN8_POWER_DOWN (1 << 11)
55 #define LAN8_ISOLATE (1 << 10)
56 #define LAN8_RESTART_AUTONEG (1 << 9)
57 #define LAN8_DUPLEX_MODE (1 << 8)
59 /* LAN8720 BSR register definitions */
60 #define LAN8_100BASE_T4 (1 << 15)
61 #define LAN8_100BASE_TX_FD (1 << 14)
62 #define LAN8_100BASE_TX_HD (1 << 13)
63 #define LAN8_10BASE_T_FD (1 << 12)
64 #define LAN8_10BASE_T_HD (1 << 11)
65 #define LAN8_AUTONEG_COMP (1 << 5)
66 #define LAN8_RMT_FAULT (1 << 4)
67 #define LAN8_AUTONEG_ABILITY (1 << 3)
68 #define LAN8_LINK_STATUS (1 << 2)
69 #define LAN8_JABBER_DETECT (1 << 1)
70 #define LAN8_EXTEND_CAPAB (1 << 0)
72 /* LAN8720 PHYSPLCTL status definitions */
73 #define LAN8_SPEEDMASK (7 << 2)
74 #define LAN8_SPEED100F (6 << 2)
75 #define LAN8_SPEED10F (5 << 2)
76 #define LAN8_SPEED100H (2 << 2)
77 #define LAN8_SPEED10H (1 << 2)
79 /* LAN8720 PHY ID 1/2 register definitions */
80 #define LAN8_PHYID1_OUI 0x0007
81 #define LAN8_PHYID2_OUI 0xC0F0
83 /* DP83848 PHY update flags */
85 
86 /* PHY update counter for state machine */
87 static int32_t phyustate;
88 
89 /* Pointer to delay function used for this driver */
91 
92 /* Write to the PHY. Will block for delays based on the pDelayMs function. Returns
93  true on success, or false on failure */
94 static Status lpc_mii_write(uint8_t reg, uint16_t data)
95 {
96  Status sts = ERROR;
97  int32_t mst = 250;
98 
99  /* Write value for register */
100  Chip_ENET_Start_MII_Write(reg, data);
101 
102  /* Wait for unbusy status */
103  while (mst > 0) {
104  if (Chip_ENET_Is_MII_Busy()) {
105  mst--;
106  pDelayMs(1);
107  }
108  else {
109  mst = 0;
110  sts = SUCCESS;
111  }
112  }
113 
114  return sts;
115 }
116 
117 /* Read from the PHY. Will block for delays based on the pDelayMs function. Returns
118  true on success, or false on failure */
119 static Status lpc_mii_read(uint8_t reg, uint16_t *data)
120 {
121  Status sts = ERROR;
122  int32_t mst = 250;
123 
124  /* Start register read */
126 
127  /* Wait for unbusy status */
128  while (mst > 0) {
129  if (!Chip_ENET_Is_MII_Busy()) {
130  mst = 0;
131  *data = Chip_ENET_Read_MII_Data();
132  sts = SUCCESS;
133  }
134  else {
135  mst--;
136  pDelayMs(1);
137  }
138  }
139 
140  return sts;
141 }
142 
143 /* Update PHY status from passed value */
144 static void smsc_update_phy_sts(uint16_t linksts, uint16_t sdsts)
145 {
146  /* Update link active status */
147  if (linksts & LAN8_LINK_STATUS) {
149  }
150  else {
152  }
153 
154  switch (sdsts & LAN8_SPEEDMASK) {
155  case LAN8_SPEED100F:
156  default:
159  break;
160 
161  case LAN8_SPEED10F:
164  break;
165 
166  case LAN8_SPEED100H:
169  break;
170 
171  case LAN8_SPEED10H:
174  break;
175  }
176 
177  /* If the status has changed, indicate via change flag */
180  olddphysts = physts;
182  }
183 }
184 
185 /* Initialize the SMSC 87x0 PHY */
186 uint32_t lpc_phy_init(bool rmii, p_msDelay_func_t pDelayMsFunc)
187 {
188  uint16_t tmp;
189  int32_t i;
190 
191  pDelayMs = pDelayMsFunc;
192 
193  /* Initial states for PHY status and state machine */
194  olddphysts = physts = phyustate = 0;
195 
196  /* Only first read and write are checked for failure */
197  /* Put the DP83848C in reset mode and wait for completion */
199  return ERROR;
200  }
201  i = 400;
202  while (i > 0) {
203  pDelayMs(1);
204  if (lpc_mii_read(LAN8_BCR_REG, &tmp) != SUCCESS) {
205  return ERROR;
206  }
207 
208  if (!(tmp & (LAN8_RESET | LAN8_POWER_DOWN))) {
209  i = -1;
210  }
211  else {
212  i--;
213  }
214  }
215  /* Timeout? */
216  if (i == 0) {
217  return ERROR;
218  }
219 
220  /* Setup link */
222 
223  /* The link is not set active at this point, but will be detected
224  later */
225 
226  return SUCCESS;
227 }
228 
229 /* Phy status update state machine */
231 {
232  static uint16_t sts;
233 
234  switch (phyustate) {
235  default:
236  case 0:
237  /* Read BMSR to clear faults */
241  phyustate = 1;
242  break;
243 
244  case 1:
245  /* Wait for read status state */
246  if (!Chip_ENET_Is_MII_Busy()) {
247  /* Get PHY status with link state */
248  sts = Chip_ENET_Read_MII_Data();
250  phyustate = 2;
251  }
252  break;
253 
254  case 2:
255  /* Wait for read status state */
256  if (!Chip_ENET_Is_MII_Busy()) {
257  /* Update PHY status */
258  physts &= ~PHY_LINK_BUSY;
260  phyustate = 0;
261  }
262  break;
263  }
264 
265  return physts;
266 }
267