1 /*
2 * Copyright 2020-2021 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_enet_mdio.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /*******************************************************************************
15 * Prototypes
16 ******************************************************************************/
17
18 static void ENET_MDIO_Init(mdio_handle_t *handle);
19 static status_t ENET_MDIO_Write(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t data);
20 static status_t ENET_MDIO_Read(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t *dataPtr);
21 #if defined(FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO
22 static status_t ENET_MDIO_WriteExt(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t data);
23 static status_t ENET_MDIO_ReadExt(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t *dataPtr);
24 #endif
25 static status_t ENET_MDIO_WaitTransferOver(ENET_Type *base);
26
27 /*******************************************************************************
28 * Variables
29 ******************************************************************************/
30
31 const mdio_operations_t enet_ops = {.mdioInit = ENET_MDIO_Init,
32 .mdioWrite = ENET_MDIO_Write,
33 .mdioRead = ENET_MDIO_Read,
34 #if defined(FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO
35 .mdioWriteExt = ENET_MDIO_WriteExt,
36 .mdioReadExt = ENET_MDIO_ReadExt};
37 #else
38 .mdioWriteExt = NULL,
39 .mdioReadExt = NULL};
40 #endif
41
42 /*******************************************************************************
43 * Code
44 ******************************************************************************/
45
ENET_MDIO_Init(mdio_handle_t * handle)46 static void ENET_MDIO_Init(mdio_handle_t *handle)
47 {
48 mdio_resource_t *resource = (mdio_resource_t *)&handle->resource;
49 ENET_Type *base = (ENET_Type *)resource->base;
50
51 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
52 uint32_t instance = ENET_GetInstance(base);
53
54 /* Set SMI first. */
55 (void)CLOCK_EnableClock(s_enetClock[instance]);
56 #if defined(FSL_FEATURE_ENET_HAS_EXTRA_CLOCK_GATE) && FSL_FEATURE_ENET_HAS_EXTRA_CLOCK_GATE
57 (void)CLOCK_EnableClock(s_enetExtraClock[instance]);
58 #endif
59 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
60 ENET_SetSMI(base, resource->csrClock_Hz, false);
61 }
62
ENET_MDIO_Write(mdio_handle_t * handle,uint32_t phyAddr,uint32_t devAddr,uint32_t data)63 static status_t ENET_MDIO_Write(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t data)
64 {
65 mdio_resource_t *resource = (mdio_resource_t *)&handle->resource;
66 ENET_Type *base = (ENET_Type *)resource->base;
67 status_t result = kStatus_Success;
68
69 /* Clear the SMI interrupt event. */
70 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
71
72 /* Starts a SMI write command. */
73 ENET_StartSMIWrite(base, phyAddr, devAddr, kENET_MiiWriteValidFrame, data);
74
75 result = ENET_MDIO_WaitTransferOver(base);
76 if (result != kStatus_Success)
77 {
78 return result;
79 }
80
81 /* Clear SMI interrupt event. */
82 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
83
84 return result;
85 }
86
ENET_MDIO_Read(mdio_handle_t * handle,uint32_t phyAddr,uint32_t devAddr,uint32_t * dataPtr)87 static status_t ENET_MDIO_Read(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t *dataPtr)
88 {
89 assert(dataPtr != NULL);
90
91 mdio_resource_t *resource = (mdio_resource_t *)&handle->resource;
92 ENET_Type *base = (ENET_Type *)resource->base;
93 status_t result = kStatus_Success;
94
95 /* Clear the SMI interrupt event. */
96 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
97
98 /* Starts a SMI read command operation. */
99 ENET_StartSMIRead(base, phyAddr, devAddr, kENET_MiiReadValidFrame);
100
101 result = ENET_MDIO_WaitTransferOver(base);
102 if (result != kStatus_Success)
103 {
104 return result;
105 }
106
107 /* Get data from SMI register. */
108 *dataPtr = ENET_ReadSMIData(base);
109
110 /* Clear SMI interrupt event. */
111 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
112
113 return result;
114 }
115
116 #if defined(FSL_FEATURE_ENET_HAS_EXTEND_MDIO) && FSL_FEATURE_ENET_HAS_EXTEND_MDIO
ENET_MDIO_WriteExt(mdio_handle_t * handle,uint32_t phyAddr,uint32_t devAddr,uint32_t data)117 static status_t ENET_MDIO_WriteExt(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t data)
118 {
119 mdio_resource_t *resource = (mdio_resource_t *)&handle->resource;
120 ENET_Type *base = (ENET_Type *)resource->base;
121 status_t result = kStatus_Success;
122
123 /* Write the register address */
124 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
125 ENET_StartExtC45SMIWriteReg(base, phyAddr, devAddr);
126 result = ENET_MDIO_WaitTransferOver(base);
127 if (result != kStatus_Success)
128 {
129 return result;
130 }
131 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
132
133 /* Write data to the specified register address */
134 ENET_StartExtC45SMIWriteData(base, phyAddr, devAddr, data);
135 result = ENET_MDIO_WaitTransferOver(base);
136 if (result != kStatus_Success)
137 {
138 return result;
139 }
140 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
141
142 return result;
143 }
144
ENET_MDIO_ReadExt(mdio_handle_t * handle,uint32_t phyAddr,uint32_t devAddr,uint32_t * dataPtr)145 static status_t ENET_MDIO_ReadExt(mdio_handle_t *handle, uint32_t phyAddr, uint32_t devAddr, uint32_t *dataPtr)
146 {
147 assert(dataPtr != NULL);
148
149 mdio_resource_t *resource = (mdio_resource_t *)&handle->resource;
150 ENET_Type *base = (ENET_Type *)resource->base;
151 status_t result = kStatus_Success;
152
153 /* Write the register address */
154 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
155 ENET_StartExtC45SMIWriteReg(base, phyAddr, devAddr);
156 result = ENET_MDIO_WaitTransferOver(base);
157 if (result != kStatus_Success)
158 {
159 return result;
160 }
161
162 /* Read data from the specified register address */
163 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
164 ENET_StartExtC45SMIReadData(base, phyAddr, devAddr);
165 result = ENET_MDIO_WaitTransferOver(base);
166 if (result != kStatus_Success)
167 {
168 return result;
169 }
170 ENET_ClearInterruptStatus(base, ENET_EIR_MII_MASK);
171 *dataPtr = ENET_ReadSMIData(base);
172 return result;
173 }
174 #endif
175
ENET_MDIO_WaitTransferOver(ENET_Type * base)176 static status_t ENET_MDIO_WaitTransferOver(ENET_Type *base)
177 {
178 status_t result = kStatus_Success;
179 #ifdef MDIO_TIMEOUT_COUNT
180 uint32_t counter;
181 #endif
182
183 /* Wait for SMI complete. */
184 #ifdef MDIO_TIMEOUT_COUNT
185 for (counter = MDIO_TIMEOUT_COUNT; counter > 0U; counter--)
186 {
187 if (ENET_EIR_MII_MASK == (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK))
188 {
189 break;
190 }
191 }
192 /* Check for timeout. */
193 if (0U == counter)
194 {
195 result = kStatus_PHY_SMIVisitTimeout;
196 }
197 #else
198 while (ENET_EIR_MII_MASK != (ENET_GetInterruptStatus(base) & ENET_EIR_MII_MASK))
199 {
200 }
201 #endif
202 return result;
203 }
204