1 /*
2 * Copyright (c) 2013-2016 ARM Limited. All rights reserved.
3 * Copyright (c) 2016, Freescale Semiconductor, Inc. Not a Contribution.
4 * Copyright 2016-2022 NXP. Not a Contribution.
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * Licensed under the Apache License, Version 2.0 (the License); you may
9 * not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
16 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20
21 #include "fsl_enet_phy_cmsis.h"
22 #include "fsl_enet.h"
23
24 #define ARM_ETH_PHY_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(2, 1)
25
26 #ifndef PHY_AUTONEGO_DELAY_COUNT
27 #define PHY_AUTONEGO_DELAY_COUNT (800000U)
28 #endif
29
30 typedef struct _cmsis_enet_phy_state
31 {
32 cmsis_enet_phy_resource_t *resource; /*!< Basic enet resource. */
33 uint32_t cmsis_enet_phy_mode; /*!< ENET MII interface work mode. */
34 } cmsis_enet_phy_state_t;
35
36 static const ARM_DRIVER_VERSION s_phyDriverVersion = {ARM_ETH_PHY_API_VERSION, ARM_ETH_PHY_DRV_VERSION};
37
PHYx_GetVersion(void)38 static ARM_DRIVER_VERSION PHYx_GetVersion(void)
39 {
40 return s_phyDriverVersion;
41 }
42
PHY_SetForcedSpeedDuplexMode(cmsis_enet_phy_state_t * ethPhy,uint32_t mode)43 static int32_t PHY_SetForcedSpeedDuplexMode(cmsis_enet_phy_state_t *ethPhy, uint32_t mode)
44 {
45 int32_t result;
46 uint16_t bsctlReg;
47
48 /* Reset PHY. */
49 result = PHY_Write(&phyHandle, PHY_BASICCONTROL_REG, PHY_BCTL_RESET_MASK);
50 if (result == kStatus_Success)
51 {
52 /* Set with the forced speed and duplex. */
53 result = PHY_Read(&phyHandle, PHY_BASICCONTROL_REG, &bsctlReg);
54 if (result == kStatus_Success)
55 {
56 /* Build the control value. */
57 bsctlReg &= ~(PHY_BCTL_DUPLEX_MASK | PHY_BCTL_SPEED0_MASK | PHY_BCTL_AUTONEG_MASK);
58 if (mode == (uint32_t)ARM_ETH_PHY_DUPLEX_FULL)
59 {
60 bsctlReg |= PHY_BCTL_DUPLEX_MASK;
61 }
62 if (mode == (uint32_t)ARM_ETH_PHY_SPEED_100M)
63 {
64 bsctlReg |= PHY_BCTL_SPEED0_MASK;
65 }
66 result = PHY_Write(&phyHandle, PHY_BASICCONTROL_REG, bsctlReg);
67 }
68 }
69
70 return result;
71 }
72
PHY_SetPowerDown(cmsis_enet_phy_resource_t * enet,bool down)73 static void PHY_SetPowerDown(cmsis_enet_phy_resource_t *enet, bool down)
74 {
75 uint16_t data;
76
77 if (down)
78 {
79 (void)PHY_Read(&phyHandle, PHY_BASICCONTROL_REG, &data);
80 data |= (uint16_t)(1UL << 11);
81 (void)PHY_Write(&phyHandle, PHY_BASICCONTROL_REG, data);
82 }
83 else
84 {
85 (void)PHY_Read(&phyHandle, PHY_BASICCONTROL_REG, &data);
86 data &= ~(uint16_t)(1UL << 11);
87 (void)PHY_Write(&phyHandle, PHY_BASICCONTROL_REG, data);
88 (void)PHY_Read(&phyHandle, PHY_BASICCONTROL_REG, &data);
89 }
90 }
91
92 #if RTE_ENET
93
94 extern cmsis_enet_phy_resource_t ENETPHY0_Resource;
95
96 static cmsis_enet_phy_state_t ENETPHY0_State = {&ENETPHY0_Resource, ARM_ETH_PHY_AUTO_NEGOTIATE};
97
PHY0_Initialize(ARM_ETH_PHY_Read_t fn_read,ARM_ETH_PHY_Write_t fn_write)98 static int32_t PHY0_Initialize(ARM_ETH_PHY_Read_t fn_read, ARM_ETH_PHY_Write_t fn_write)
99 {
100 return ARM_DRIVER_OK;
101 }
102
PHY0_UnInitialize(void)103 static int32_t PHY0_UnInitialize(void)
104 {
105 return ARM_DRIVER_OK;
106 }
107
PHY0_PowerControl(ARM_POWER_STATE state)108 static int32_t PHY0_PowerControl(ARM_POWER_STATE state)
109 {
110 int32_t status;
111 phy_config_t phyConfig = {0};
112 bool autonego = false;
113 uint32_t count;
114
115 switch (state)
116 {
117 case ARM_POWER_FULL:
118 {
119 phyConfig.phyAddr = ENETPHY0_State.resource->phyAddr;
120 phyConfig.ops = ENETPHY0_State.resource->ops;
121 phyConfig.resource = ENETPHY0_State.resource->opsResource;
122 phyConfig.autoNeg = true;
123 status = PHY_Init(&phyHandle, &phyConfig);
124 if (status == kStatus_Success)
125 {
126 count = PHY_AUTONEGO_DELAY_COUNT;
127 do
128 {
129 (void)PHY_GetAutoNegotiationStatus(&phyHandle, &autonego);
130 if (autonego)
131 {
132 break;
133 }
134 } while (--count != 0U);
135 }
136 if (autonego)
137 {
138 status = ARM_DRIVER_OK;
139 }
140 else
141 {
142 status = ARM_DRIVER_ERROR;
143 }
144 }
145 break;
146 case ARM_POWER_OFF:
147 {
148 PHY_SetPowerDown(ENETPHY0_State.resource, true);
149 status = ARM_DRIVER_OK;
150 }
151 break;
152 default:
153 status = ARM_DRIVER_ERROR_UNSUPPORTED;
154 break;
155 }
156 return status;
157 }
158
PHY0_SetInterface(uint32_t interface)159 static int32_t PHY0_SetInterface(uint32_t interface)
160 {
161 int32_t status = ARM_DRIVER_OK;
162 /* The interface for PHY is fixed or controlled by JUMPER setting.
163 * The interface setting for MAC is defined by "RTE_ENET_RMII/RTE_ENET_MII"
164 */
165 if (interface == (uint32_t)ARM_ETH_INTERFACE_SMII)
166 {
167 status = ARM_DRIVER_ERROR_UNSUPPORTED;
168 }
169 return status;
170 }
171
PHY0_SetMode(uint32_t mode)172 static int32_t PHY0_SetMode(uint32_t mode)
173 {
174 int32_t status = ARM_DRIVER_OK;
175 phy_config_t phyConfig = {0};
176 bool autonego = false;
177 uint32_t count;
178
179 /*!< Check input mode. */
180 if ((mode == (uint32_t)ARM_ETH_PHY_SPEED_1G) || (mode == ARM_ETH_PHY_ISOLATE))
181 {
182 return ARM_DRIVER_ERROR_UNSUPPORTED;
183 }
184
185 if (mode == ARM_ETH_PHY_LOOPBACK)
186 {
187 status = PHY_EnableLoopback(&phyHandle, kPHY_RemoteLoop, kPHY_Speed100M, true);
188 }
189 else if (mode == ARM_ETH_PHY_AUTO_NEGOTIATE)
190 {
191 phyConfig.phyAddr = ENETPHY0_State.resource->phyAddr;
192 phyConfig.ops = ENETPHY0_State.resource->ops;
193 phyConfig.resource = &ENETPHY0_State.resource->opsResource;
194 phyConfig.autoNeg = true;
195 status = PHY_Init(&phyHandle, &phyConfig);
196 if (status == kStatus_Success)
197 {
198 count = PHY_AUTONEGO_DELAY_COUNT;
199 do
200 {
201 (void)PHY_GetAutoNegotiationStatus(&phyHandle, &autonego);
202 if (autonego)
203 {
204 break;
205 }
206 } while (--count != 0U);
207 if (!autonego)
208 {
209 status = kStatus_Fail;
210 }
211 }
212 }
213 else
214 {
215 status = PHY_SetForcedSpeedDuplexMode(&ENETPHY0_State, mode);
216 }
217 ENETPHY0_State.cmsis_enet_phy_mode = mode;
218
219 /* Convert to CMSIS status */
220 if (status == kStatus_Success)
221 {
222 status = ARM_DRIVER_OK;
223 }
224 else
225 {
226 status = ARM_DRIVER_ERROR;
227 }
228
229 return status;
230 }
231
PHY0_GetLinkState(void)232 static ARM_ETH_LINK_STATE PHY0_GetLinkState(void)
233 {
234 ARM_ETH_LINK_STATE state;
235 bool linkUp = false;
236 int32_t status;
237
238 status = PHY_GetLinkStatus(&phyHandle, &linkUp);
239 if ((status == kStatus_Success) && linkUp)
240 {
241 state = ARM_ETH_LINK_UP;
242 }
243 else
244 {
245 state = ARM_ETH_LINK_DOWN;
246 }
247 return state;
248 }
249
PHY0_GetLinkInfo(void)250 static ARM_ETH_LINK_INFO PHY0_GetLinkInfo(void)
251 {
252 ARM_ETH_LINK_INFO linkInfo = {0};
253 phy_speed_t speed;
254 phy_duplex_t duplex;
255 int32_t status;
256
257 status = PHY_GetLinkSpeedDuplex(&phyHandle, &speed, &duplex);
258 if (status == kStatus_Success)
259 {
260 if (speed == kPHY_Speed10M)
261 {
262 linkInfo.speed = ARM_ETH_SPEED_10M;
263 }
264 else if (speed == kPHY_Speed100M)
265 {
266 linkInfo.speed = ARM_ETH_SPEED_100M;
267 }
268 else
269 {
270 linkInfo.speed = ARM_ETH_SPEED_1G;
271 }
272
273 if (duplex == kPHY_FullDuplex)
274 {
275 linkInfo.duplex = ARM_ETH_DUPLEX_FULL;
276 }
277 else
278 {
279 linkInfo.duplex = ARM_ETH_DUPLEX_HALF;
280 }
281 }
282 return linkInfo;
283 }
284
285 ARM_DRIVER_ETH_PHY Driver_ETH_PHY0 = {PHYx_GetVersion, PHY0_Initialize, PHY0_UnInitialize, PHY0_PowerControl,
286 PHY0_SetInterface, PHY0_SetMode, PHY0_GetLinkState, PHY0_GetLinkInfo};
287 #endif
288