1 /**
2 * @file xmc_eth_phy_dp83848.c
3 * @date 2018-08-06
4 *
5 * @cond
6 *********************************************************************************************************************
7 * XMClib v2.1.24 - XMC Peripheral Driver Library
8 *
9 * Copyright (c) 2015-2019, Infineon Technologies AG
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13 * following conditions are met:
14 *
15 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
18 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided with the distribution.
20 *
21 * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22 * products derived from this software without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33 * Infineon Technologies AG dave@infineon.com).
34 *********************************************************************************************************************
35 *
36 * Change History
37 * --------------
38 *
39 * 2015-06-20:
40 * - Initial <br>
41 *
42 * 2015-12-15:
43 * - Added Reset and exit power down
44 * - Reset function called in Init function
45 *
46 * 2018-08-06:
47 * - Fixed XMC_ETH_PHY_Init waiting for PHY MDIO being ready
48 *
49 * @endcond
50 */
51
52 /*******************************************************************************
53 * HEADER FILES
54 *******************************************************************************/
55 #if defined(XMC_ETH_PHY_DP83848C)
56 #include <xmc_eth_phy.h>
57
58 /*******************************************************************************
59 * MACROS
60 *******************************************************************************/
61
62 /* Basic Registers */
63 #define REG_BMCR (0x00U) /* Basic Mode Control Register */
64 #define REG_BMSR (0x01U) /* Basic Mode Status Register */
65 #define REG_PHYIDR1 (0x02U) /* PHY Identifier 1 */
66 #define REG_PHYIDR2 (0x03U) /* PHY Identifier 2 */
67 #define REG_ANAR (0x04U) /* Auto-Negotiation Advertisement */
68 #define REG_ANLPAR (0x05U) /* Auto-Neg. Link Partner Abitily */
69 #define REG_ANER (0x06U) /* Auto-Neg. Expansion Register */
70 #define REG_ANNPTR (0x07U) /* Auto-Neg. Next Page TX */
71 #define REG_RBR (0x17U) /* RMII and Bypass Register */
72
73 /* Extended Registers */
74 #define REG_PHYSTS (0x10U) /* Status Register */
75
76 /* Basic Mode Control Register */
77 #define BMCR_RESET (0x8000U) /* Software Reset */
78 #define BMCR_LOOPBACK (0x4000U) /* Loopback mode */
79 #define BMCR_SPEED_SEL (0x2000U) /* Speed Select (1=100Mb/s) */
80 #define BMCR_ANEG_EN (0x1000U) /* Auto Negotiation Enable */
81 #define BMCR_POWER_DOWN (0x0800U) /* Power Down */
82 #define BMCR_ISOLATE (0x0400U) /* Isolate Media interface */
83 #define BMCR_REST_ANEG (0x0200U) /* Restart Auto Negotiation */
84 #define BMCR_DUPLEX (0x0100U) /* Duplex Mode (1=Full duplex) */
85 #define BMCR_COL_TEST (0x0080U) /* Collision Test */
86
87 /* Basic Mode Status Register */
88 #define BMSR_100B_T4 (0x8000U) /* 100BASE-T4 Capable */
89 #define BMSR_100B_TX_FD (0x4000U) /* 100BASE-TX Full Duplex Capable */
90 #define BMSR_100B_TX_HD (0x2000U) /* 100BASE-TX Half Duplex Capable */
91 #define BMSR_10B_T_FD (0x1000U) /* 10BASE-T Full Duplex Capable */
92 #define BMSR_10B_T_HD (0x0800U) /* 10BASE-T Half Duplex Capable */
93 #define BMSR_MF_PRE_SUP (0x0040U) /* Preamble suppression Capable */
94 #define BMSR_ANEG_COMPL (0x0020U) /* Auto Negotiation Complete */
95 #define BMSR_REM_FAULT (0x0010U) /* Remote Fault */
96 #define BMSR_ANEG_ABIL (0x0008U) /* Auto Negotiation Ability */
97 #define BMSR_LINK_STAT (0x0004U) /* Link Status (1=established) */
98 #define BMSR_JABBER_DET (0x0002U) /* Jaber Detect */
99 #define BMSR_EXT_CAPAB (0x0001U) /* Extended Capability */
100
101 /* RMII and Bypass Register */
102 #define RBR_RMII_MODE (0x0020U) /* Reduced MII Mode */
103
104 /* PHY Identifier Registers */
105 #define PHY_ID1 0x2000 /* DP83848C Device Identifier MSB */
106 #define PHY_ID2 0x5C90 /* DP83848C Device Identifier LSB */
107
108 /* PHY Status Register */
109 #define PHYSTS_MDI_X 0x4000 /* MDI-X mode enabled by Auto-Negot. */
110 #define PHYSTS_REC_ERR 0x2000 /* Receive Error Latch */
111 #define PHYSTS_POL_STAT 0x1000 /* Polarity Status */
112 #define PHYSTS_FC_SENSE 0x0800 /* False Carrier Sense Latch */
113 #define PHYSTS_SIG_DET 0x0400 /* 100Base-TX Signal Detect */
114 #define PHYSTS_DES_LOCK 0x0200 /* 100Base-TX Descrambler Lock */
115 #define PHYSTS_PAGE_REC 0x0100 /* Link Code Word Page Received */
116 #define PHYSTS_MII_INT 0x0080 /* MII Interrupt Pending */
117 #define PHYSTS_REM_FAULT 0x0040 /* Remote Fault */
118 #define PHYSTS_JABBER_DET 0x0020 /* Jabber Detect */
119 #define PHYSTS_ANEG_COMPL 0x0010 /* Auto Negotiation Complete */
120 #define PHYSTS_LOOPBACK 0x0008 /* Loopback Status */
121 #define PHYSTS_DUPLEX 0x0004 /* Duplex Status (1=Full duplex) */
122 #define PHYSTS_SPEED 0x0002 /* Speed10 Status (1=10MBit/s) */
123 #define PHYSTS_LINK_STAT 0x0001 /* Link Status (1=established) */
124
125 /*******************************************************************************
126 * API IMPLEMENTATION
127 *******************************************************************************/
128
129 /* Check if the device identifier is valid */
XMC_ETH_PHY_IsDeviceIdValid(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)130 static int32_t XMC_ETH_PHY_IsDeviceIdValid(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
131 {
132 uint16_t phy_id1;
133 uint16_t phy_id2;
134 XMC_ETH_PHY_STATUS_t status;
135
136 /* Check Device Identification. */
137 if ((XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_PHYIDR1, &phy_id1) == XMC_ETH_MAC_STATUS_OK) &&
138 (XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_PHYIDR2, &phy_id2) == XMC_ETH_MAC_STATUS_OK))
139 {
140 if ((phy_id1 == PHY_ID1) && ((phy_id2 & (uint16_t)0xfff0) == PHY_ID2))
141 {
142 status = XMC_ETH_PHY_STATUS_OK;
143 }
144 else
145 {
146 status = XMC_ETH_PHY_STATUS_ERROR_DEVICE_ID;
147 }
148 }
149 else
150 {
151 status = XMC_ETH_PHY_STATUS_ERROR_TIMEOUT;
152 }
153
154 return (int32_t)status;
155 }
156
157 /* PHY initialize */
XMC_ETH_PHY_Init(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr,const XMC_ETH_PHY_CONFIG_t * const config)158 int32_t XMC_ETH_PHY_Init(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr, const XMC_ETH_PHY_CONFIG_t *const config)
159 {
160 uint32_t retries = 0xffffffffUL;
161 int32_t status;
162 uint16_t reg_val;
163
164 while (((status = XMC_ETH_PHY_IsDeviceIdValid(eth_mac, phy_addr)) != XMC_ETH_PHY_STATUS_OK) && --retries);
165
166 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
167 {
168 status = XMC_ETH_PHY_Reset(eth_mac, phy_addr);
169
170 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
171 {
172 reg_val = 0U;
173 if (config->speed == XMC_ETH_LINK_SPEED_100M)
174 {
175 reg_val |= BMCR_SPEED_SEL;
176 }
177
178 if (config->duplex == XMC_ETH_LINK_DUPLEX_FULL)
179 {
180 reg_val |= BMCR_DUPLEX;
181 }
182
183 if (config->enable_auto_negotiate == true)
184 {
185 reg_val |= BMCR_ANEG_EN;
186 }
187
188 if (config->enable_loop_back == true)
189 {
190 reg_val |= BMCR_LOOPBACK;
191 }
192
193 status = (int32_t)XMC_ETH_MAC_WritePhy(eth_mac, phy_addr, REG_BMCR, reg_val);
194
195 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
196 {
197 /* Configure interface mode */
198 switch (config->interface)
199 {
200 case XMC_ETH_LINK_INTERFACE_MII:
201 reg_val = 0x0001;
202 break;
203 case XMC_ETH_LINK_INTERFACE_RMII:
204 reg_val = RBR_RMII_MODE | 0x0001;
205 break;
206 }
207 status = (int32_t)XMC_ETH_MAC_WritePhy(eth_mac, phy_addr, REG_RBR, reg_val);
208 }
209 }
210 }
211
212 return status;
213 }
214
215 /* Reset */
XMC_ETH_PHY_Reset(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)216 int32_t XMC_ETH_PHY_Reset(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
217 {
218 int32_t status;
219 uint16_t reg_bmcr;
220
221 /* Reset PHY*/
222 status = (int32_t)XMC_ETH_MAC_WritePhy(eth_mac, phy_addr, REG_BMCR, BMCR_RESET);
223 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
224 {
225 /* Wait for the reset to complete */
226 do
227 {
228 status = XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_BMCR, ®_bmcr);
229 } while ((reg_bmcr & BMCR_RESET) != 0);
230 }
231
232 return status;
233 }
234
235 /* Initiate power down */
XMC_ETH_PHY_PowerDown(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)236 int32_t XMC_ETH_PHY_PowerDown(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
237 {
238 int32_t status;
239 uint16_t reg_bmcr;
240
241 status = XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_BMCR, ®_bmcr);
242 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
243 {
244 reg_bmcr |= BMCR_POWER_DOWN;
245 status = (int32_t)XMC_ETH_MAC_WritePhy(eth_mac, phy_addr, REG_BMCR, reg_bmcr);
246 }
247 return status;
248 }
249
250 /* Exit power down */
XMC_ETH_PHY_ExitPowerDown(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)251 int32_t XMC_ETH_PHY_ExitPowerDown(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
252 {
253 int32_t status;
254 uint16_t reg_bmcr;
255
256 status = XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_BMCR, ®_bmcr);
257 if (status == (int32_t)XMC_ETH_PHY_STATUS_OK)
258 {
259 reg_bmcr &= ~BMCR_POWER_DOWN;
260 status = (int32_t)XMC_ETH_MAC_WritePhy(eth_mac, phy_addr, REG_BMCR, reg_bmcr);
261 }
262 return status;
263 }
264
265 /* Get link status */
XMC_ETH_PHY_GetLinkStatus(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)266 XMC_ETH_LINK_STATUS_t XMC_ETH_PHY_GetLinkStatus(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
267 {
268 uint16_t val;
269
270 XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_BMSR, &val);
271
272 return (XMC_ETH_LINK_STATUS_t)((val & BMSR_LINK_STAT) ? XMC_ETH_LINK_STATUS_UP : XMC_ETH_LINK_STATUS_DOWN);
273 }
274
275 /* Get link speed */
XMC_ETH_PHY_GetLinkSpeed(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)276 XMC_ETH_LINK_SPEED_t XMC_ETH_PHY_GetLinkSpeed(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
277 {
278 uint16_t val;
279
280 XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_PHYSTS, &val);
281
282 return (XMC_ETH_LINK_SPEED_t)((val & PHYSTS_SPEED) ? XMC_ETH_LINK_SPEED_10M : XMC_ETH_LINK_SPEED_100M);
283 }
284
285 /* Get link duplex settings */
XMC_ETH_PHY_GetLinkDuplex(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)286 XMC_ETH_LINK_DUPLEX_t XMC_ETH_PHY_GetLinkDuplex(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
287 {
288 uint16_t val;
289
290 XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_PHYSTS, &val);
291
292 return (XMC_ETH_LINK_DUPLEX_t)((val & PHYSTS_DUPLEX) ? XMC_ETH_LINK_DUPLEX_FULL : XMC_ETH_LINK_DUPLEX_HALF);
293 }
294
XMC_ETH_PHY_IsAutonegotiationCompleted(XMC_ETH_MAC_t * const eth_mac,uint8_t phy_addr)295 bool XMC_ETH_PHY_IsAutonegotiationCompleted(XMC_ETH_MAC_t *const eth_mac, uint8_t phy_addr)
296 {
297 uint16_t val;
298
299 XMC_ETH_MAC_ReadPhy(eth_mac, phy_addr, REG_BMSR, &val);
300 return ((val & BMSR_ANEG_COMPL) == BMSR_ANEG_COMPL);
301 }
302
303 #endif // defined(XMC_ETH_PHY_DP83848C)
304