LPCOpen Platform
LPCOpen Platform for NXP LPC Microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lpc_phy_dp83848.c
Go to the documentation of this file.
1 /*
2  * @brief Mational DP83848 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 
43 #define DP8_BMCR_REG 0x0
44 #define DP8_BMSR_REG 0x1
45 #define DP8_ANADV_REG 0x4
46 #define DP8_ANLPA_REG 0x5
47 #define DP8_ANEEXP_REG 0x6
48 #define DP8_PHY_STAT_REG 0x10
49 #define DP8_PHY_INT_CTL_REG 0x11
50 #define DP8_PHY_RBR_REG 0x17
51 #define DP8_PHY_STS_REG 0x19
53 /* DP83848 Control register definitions */
54 #define DP8_RESET (1 << 15)
55 #define DP8_LOOPBACK (1 << 14)
56 #define DP8_SPEED_SELECT (1 << 13)
57 #define DP8_AUTONEG (1 << 12)
58 #define DP8_POWER_DOWN (1 << 11)
59 #define DP8_ISOLATE (1 << 10)
60 #define DP8_RESTART_AUTONEG (1 << 9)
61 #define DP8_DUPLEX_MODE (1 << 8)
62 #define DP8_COLLISION_TEST (1 << 7)
64 /* DP83848 Status register definitions */
65 #define DP8_100BASE_T4 (1 << 15)
66 #define DP8_100BASE_TX_FD (1 << 14)
67 #define DP8_100BASE_TX_HD (1 << 13)
68 #define DP8_10BASE_T_FD (1 << 12)
69 #define DP8_10BASE_T_HD (1 << 11)
70 #define DP8_MF_PREAMB_SUPPR (1 << 6)
71 #define DP8_AUTONEG_COMP (1 << 5)
72 #define DP8_RMT_FAULT (1 << 4)
73 #define DP8_AUTONEG_ABILITY (1 << 3)
74 #define DP8_LINK_STATUS (1 << 2)
75 #define DP8_JABBER_DETECT (1 << 1)
76 #define DP8_EXTEND_CAPAB (1 << 0)
78 /* DP83848 PHY RBR MII dode definitions */
79 #define DP8_RBR_RMII_MODE (1 << 5)
81 /* DP83848 PHY status definitions */
82 #define DP8_REMOTEFAULT (1 << 6)
83 #define DP8_FULLDUPLEX (1 << 2)
84 #define DP8_SPEED10MBPS (1 << 1)
85 #define DP8_VALID_LINK (1 << 0)
87 /* DP83848 PHY ID register definitions */
88 #define DP8_PHYID1_OUI 0x2000
89 #define DP8_PHYID2_OUI 0x5c90
91 /* DP83848 PHY update flags */
93 
94 /* PHY update counter for state machine */
95 static int32_t phyustate;
96 
97 /* Pointer to delay function used for this driver */
99 
100 /* Write to the PHY. Will block for delays based on the pDelayMs function. Returns
101  true on success, or false on failure */
102 static Status lpc_mii_write(uint8_t reg, uint16_t data)
103 {
104  Status sts = ERROR;
105  int32_t mst = 250;
106 
107  /* Write value for register */
108  Chip_ENET_Start_MII_Write(reg, data);
109 
110  /* Wait for unbusy status */
111  while (mst > 0) {
112  if (Chip_ENET_Is_MII_Busy()) {
113  mst--;
114  pDelayMs(1);
115  }
116  else {
117  mst = 0;
118  sts = SUCCESS;
119  }
120  }
121 
122  return sts;
123 }
124 
125 /* Read from the PHY. Will block for delays based on the pDelayMs function. Returns
126  true on success, or false on failure */
127 static Status lpc_mii_read(uint8_t reg, uint16_t *data)
128 {
129  Status sts = ERROR;
130  int32_t mst = 250;
131 
132  /* Start register read */
134 
135  /* Wait for unbusy status */
136  while (mst > 0) {
137  if (!Chip_ENET_Is_MII_Busy()) {
138  mst = 0;
139  *data = Chip_ENET_Read_MII_Data();
140  sts = SUCCESS;
141  }
142  else {
143  mst--;
144  pDelayMs(1);
145  }
146  }
147 
148  return sts;
149 }
150 
151 /* Update PHY status from passed value */
152 static void lpc_update_phy_sts(uint16_t linksts)
153 {
154  /* Update link active status */
155  if (linksts & DP8_VALID_LINK) {
157  }
158  else {
160  }
161 
162  /* Full or half duplex */
163  if (linksts & DP8_FULLDUPLEX) {
165  }
166  else {
168  }
169 
170  /* Configure 100MBit/10MBit mode. */
171  if (linksts & DP8_SPEED10MBPS) {
173  }
174  else {
176  }
177 
178  /* If the status has changed, indicate via change flag */
181  olddphysts = physts;
183  }
184 }
185 
186 /* Initialize the DP83848 PHY */
187 uint32_t lpc_phy_init(bool rmii, p_msDelay_func_t pDelayMsFunc)
188 {
189  uint16_t tmp;
190  int32_t i;
191 
192  pDelayMs = pDelayMsFunc;
193 
194  /* Initial states for PHY status and state machine */
195  olddphysts = physts = phyustate = 0;
196 
197  /* Only first read and write are checked for failure */
198  /* Put the DP83848C in reset mode and wait for completion */
200  return ERROR;
201  }
202  i = 400;
203  while (i > 0) {
204  pDelayMs(1);
205  if (lpc_mii_read(DP8_BMCR_REG, &tmp) != SUCCESS) {
206  return ERROR;
207  }
208 
209  if (!(tmp & (DP8_RESET | DP8_POWER_DOWN))) {
210  i = -1;
211  }
212  else {
213  i--;
214  }
215  }
216  /* Timeout? */
217  if (i == 0) {
218  return ERROR;
219  }
220 
221 #if 0
222  /* Setup link based on configuration options */
223 #if PHY_USE_AUTONEG == 1
224  tmp = DP8_AUTONEG;
225 #else
226  tmp = 0;
227 #endif
228 #if PHY_USE_100MBS == 1
229  tmp |= DP8_SPEED_SELECT;
230 #endif
231 #if PHY_USE_FULL_DUPLEX == 1
232  tmp |= DP8_DUPLEX_MODE;
233 #endif
234 
235 #else
236  tmp = DP8_AUTONEG;
237 #endif
238 
240 
241  /* Enable RMII mode for PHY */
242  if (rmii) {
244  }
245 
246  /* The link is not set active at this point, but will be detected
247  later */
248 
249  return SUCCESS;
250 }
251 
252 /* Phy status update state machine */
254 {
255  switch (phyustate) {
256  default:
257  case 0:
258  /* Read BMSR to clear faults */
262  phyustate = 1;
263  break;
264 
265  case 1:
266  /* Wait for read status state */
267  if (!Chip_ENET_Is_MII_Busy()) {
268  /* Update PHY status */
269  physts &= ~PHY_LINK_BUSY;
271  phyustate = 0;
272  }
273  break;
274  }
275 
276  return physts;
277 }
278