| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

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 */
92 static uint32_t physts, olddphysts;
93
94 /* PHY update counter for state machine */
95 static int32_t phyustate;
96
97 /* Pointer to delay function used for this driver */
98 static p_msDelay_func_t pDelayMs;
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_StartMIIWrite(LPC_ETHERNET, reg, data);
109
110 /* Wait for unbusy status */
111 while (mst > 0) {
112 if (Chip_ENET_IsMIIBusy(LPC_ETHERNET)) {
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 */
133 Chip_ENET_StartMIIRead(LPC_ETHERNET, reg);
134
135 /* Wait for unbusy status */
136 while (mst > 0) {
137 if (!Chip_ENET_IsMIIBusy(LPC_ETHERNET)) {
138 mst = 0;
139 *data = Chip_ENET_ReadMIIData(LPC_ETHERNET);
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) {
156 physts |= PHY_LINK_CONNECTED;
157 }
158 else {
159 physts &= ~PHY_LINK_CONNECTED;
160 }
161
162 /* Full or half duplex */
163 if (linksts & DP8_FULLDUPLEX) {
164 physts |= PHY_LINK_FULLDUPLX;
165 }
166 else {
167 physts &= ~PHY_LINK_FULLDUPLX;
168 }
169
170 /* Configure 100MBit/10MBit mode. */
171 if (linksts & DP8_SPEED10MBPS) {
172 physts &= ~PHY_LINK_SPEED100;
173 }
174 else {
175 physts |= PHY_LINK_SPEED100;
176 }
177
178 /* If the status has changed, indicate via change flag */
179 if ((physts & (PHY_LINK_SPEED100 | PHY_LINK_FULLDUPLX | PHY_LINK_CONNECTED)) !=
180 (olddphysts & (PHY_LINK_SPEED100 | PHY_LINK_FULLDUPLX | PHY_LINK_CONNECTED))) {
181 olddphysts = physts;
182 physts |= PHY_LINK_CHANGED;
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 */
199 if (lpc_mii_write(DP8_BMCR_REG, DP8_RESET) != SUCCESS) {
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
239 lpc_mii_write(DP8_BMCR_REG, tmp);
240
241 /* Enable RMII mode for PHY */
242 if (rmii) {
243 lpc_mii_write(DP8_PHY_RBR_REG, DP8_RBR_RMII_MODE);
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 */
253 uint32_t lpcPHYStsPoll(void)
254 {
255 switch (phyustate) {
256 default:
257 case 0:
258 /* Read BMSR to clear faults */
259 Chip_ENET_StartMIIRead(LPC_ETHERNET, DP8_PHY_STAT_REG);
260 physts &= ~PHY_LINK_CHANGED;
261 physts = physts | PHY_LINK_BUSY;
262 phyustate = 1;
263 break;
264
265 case 1:
266 /* Wait for read status state */
267 if (!Chip_ENET_IsMIIBusy(LPC_ETHERNET)) {
268 /* Update PHY status */
269 physts &= ~PHY_LINK_BUSY;
270 lpc_update_phy_sts(Chip_ENET_ReadMIIData(LPC_ETHERNET));
271 phyustate = 0;
272 }
273 break;
274 }
275
276 return physts;
277 }
278