LPCOpen Platform for LPC18XX/43XX microcontrollers
18XX43XX
LPCOpen Platform for the NXP LPC18XX/43XX family of Microcontrollers
Main Page
Modules
Data Structures
Files
File List
Globals
software
lpc_core
lpc_board
board_common
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 */
84
static
uint32_t
physts
,
olddphysts
;
85
86
/* PHY update counter for state machine */
87
static
int32_t
phyustate
;
88
89
/* Pointer to delay function used for this driver */
90
static
p_msDelay_func_t
pDelayMs
;
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_StartMIIWrite
(
LPC_ETHERNET
, reg, data);
101
102
/* Wait for unbusy status */
103
while
(mst > 0) {
104
if
(
Chip_ENET_IsMIIBusy
(
LPC_ETHERNET
)) {
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 */
125
Chip_ENET_StartMIIRead
(
LPC_ETHERNET
, reg);
126
127
/* Wait for unbusy status */
128
while
(mst > 0) {
129
if
(!
Chip_ENET_IsMIIBusy
(
LPC_ETHERNET
)) {
130
mst = 0;
131
*data =
Chip_ENET_ReadMIIData
(
LPC_ETHERNET
);
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
) {
148
physts
|=
PHY_LINK_CONNECTED
;
149
}
150
else
{
151
physts
&= ~
PHY_LINK_CONNECTED
;
152
}
153
154
switch
(sdsts &
LAN8_SPEEDMASK
) {
155
case
LAN8_SPEED100F
:
156
default
:
157
physts
|=
PHY_LINK_SPEED100
;
158
physts
|=
PHY_LINK_FULLDUPLX
;
159
break
;
160
161
case
LAN8_SPEED10F
:
162
physts
&= ~
PHY_LINK_SPEED100
;
163
physts
|=
PHY_LINK_FULLDUPLX
;
164
break
;
165
166
case
LAN8_SPEED100H
:
167
physts
|=
PHY_LINK_SPEED100
;
168
physts
&= ~
PHY_LINK_FULLDUPLX
;
169
break
;
170
171
case
LAN8_SPEED10H
:
172
physts
&= ~
PHY_LINK_SPEED100
;
173
physts
&= ~
PHY_LINK_FULLDUPLX
;
174
break
;
175
}
176
177
/* If the status has changed, indicate via change flag */
178
if
((
physts
& (
PHY_LINK_SPEED100
|
PHY_LINK_FULLDUPLX
|
PHY_LINK_CONNECTED
)) !=
179
(
olddphysts
& (
PHY_LINK_SPEED100
|
PHY_LINK_FULLDUPLX
|
PHY_LINK_CONNECTED
))) {
180
olddphysts
=
physts
;
181
physts
|=
PHY_LINK_CHANGED
;
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 */
198
if
(
lpc_mii_write
(
LAN8_BCR_REG
,
LAN8_RESET
) !=
SUCCESS
) {
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 */
221
lpc_mii_write
(
LAN8_BCR_REG
,
LAN8_AUTONEG
);
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 */
230
uint32_t
lpcPHYStsPoll
(
void
)
231
{
232
static
uint16_t sts;
233
234
switch
(
phyustate
) {
235
default
:
236
case
0:
237
/* Read BMSR to clear faults */
238
Chip_ENET_StartMIIRead
(
LPC_ETHERNET
,
LAN8_BSR_REG
);
239
physts
&= ~
PHY_LINK_CHANGED
;
240
physts
=
physts
|
PHY_LINK_BUSY
;
241
phyustate
= 1;
242
break
;
243
244
case
1:
245
/* Wait for read status state */
246
if
(!
Chip_ENET_IsMIIBusy
(
LPC_ETHERNET
)) {
247
/* Get PHY status with link state */
248
sts =
Chip_ENET_ReadMIIData
(
LPC_ETHERNET
);
249
Chip_ENET_StartMIIRead
(
LPC_ETHERNET
,
LAN8_PHYSPLCTL_REG
);
250
phyustate
= 2;
251
}
252
break
;
253
254
case
2:
255
/* Wait for read status state */
256
if
(!
Chip_ENET_IsMIIBusy
(
LPC_ETHERNET
)) {
257
/* Update PHY status */
258
physts
&= ~
PHY_LINK_BUSY
;
259
smsc_update_phy_sts
(sts,
Chip_ENET_ReadMIIData
(
LPC_ETHERNET
));
260
phyustate
= 0;
261
}
262
break
;
263
}
264
265
return
physts
;
266
}
267
Generated on Fri Feb 20 2015 21:29:41 for LPCOpen Platform for LPC18XX/43XX microcontrollers by
1.8.3.1