mediatek: add support for rtl8367c
[openwrt/openwrt.git] / target / linux / mediatek / files-5.4 / drivers / net / phy / rtk / rtl8367c / rtl8367c_asicdrv_phy.c
1 /*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * Unless you and Realtek execute a separate written software license
6 * agreement governing use of this software, this software is licensed
7 * to you under the terms of the GNU General Public License version 2,
8 * available at https://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
9 *
10 * $Revision: 76306 $
11 * $Date: 2017-03-08 15:13:58 +0800 (週三, 08 三月 2017) $
12 *
13 * Purpose : RTL8367C switch high-level API for RTL8367C
14 * Feature : PHY related functions
15 *
16 */
17 #include <rtl8367c_asicdrv_phy.h>
18
19 #if defined(MDC_MDIO_OPERATION)
20 /* Function Name:
21 * rtl8367c_setAsicPHYOCPReg
22 * Description:
23 * Set PHY OCP registers
24 * Input:
25 * phyNo - Physical port number (0~7)
26 * ocpAddr - OCP address
27 * ocpData - Writing data
28 * Output:
29 * None
30 * Return:
31 * RT_ERR_OK - Success
32 * RT_ERR_SMI - SMI access error
33 * RT_ERR_PHY_REG_ID - invalid PHY address
34 * RT_ERR_PHY_ID - invalid PHY no
35 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
36 * Note:
37 * None
38 */
39 ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData )
40 {
41 ret_t retVal;
42 rtk_uint32 regAddr;
43 rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
44
45 /* OCP prefix */
46 ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
47 if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
48 return retVal;
49
50 /*prepare access address*/
51 ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
52 ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
53 regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
54 if((retVal = rtl8367c_setAsicReg(regAddr, ocpData)) != RT_ERR_OK)
55 return retVal;
56
57 return RT_ERR_OK;
58 }
59
60 /* Function Name:
61 * rtl8367c_getAsicPHYOCPReg
62 * Description:
63 * Get PHY OCP registers
64 * Input:
65 * phyNo - Physical port number (0~7)
66 * ocpAddr - PHY address
67 * pRegData - read data
68 * Output:
69 * None
70 * Return:
71 * RT_ERR_OK - Success
72 * RT_ERR_SMI - SMI access error
73 * RT_ERR_PHY_REG_ID - invalid PHY address
74 * RT_ERR_PHY_ID - invalid PHY no
75 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
76 * Note:
77 * None
78 */
79 ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData )
80 {
81 ret_t retVal;
82 rtk_uint32 regAddr;
83 rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
84 /* OCP prefix */
85 ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
86 if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
87 return retVal;
88
89 /*prepare access address*/
90 ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
91 ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
92 regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
93 if((retVal = rtl8367c_getAsicReg(regAddr, pRegData)) != RT_ERR_OK)
94 return retVal;
95
96 return RT_ERR_OK;
97 }
98
99 #else
100
101 /* Function Name:
102 * rtl8367c_setAsicPHYOCPReg
103 * Description:
104 * Set PHY OCP registers
105 * Input:
106 * phyNo - Physical port number (0~7)
107 * ocpAddr - OCP address
108 * ocpData - Writing data
109 * Output:
110 * None
111 * Return:
112 * RT_ERR_OK - Success
113 * RT_ERR_SMI - SMI access error
114 * RT_ERR_PHY_REG_ID - invalid PHY address
115 * RT_ERR_PHY_ID - invalid PHY no
116 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
117 * Note:
118 * None
119 */
120 ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData )
121 {
122 ret_t retVal;
123 rtk_uint32 regData;
124 rtk_uint32 busyFlag, checkCounter;
125 rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
126
127 /*Check internal phy access busy or not*/
128 /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
129 retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
130 if(retVal != RT_ERR_OK)
131 return retVal;
132
133 if(busyFlag)
134 return RT_ERR_BUSYWAIT_TIMEOUT;
135
136 /* OCP prefix */
137 ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
138 if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
139 return retVal;
140
141 /*prepare access data*/
142 retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_WRITE_DATA, ocpData);
143 if(retVal != RT_ERR_OK)
144 return retVal;
145
146 /*prepare access address*/
147 ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
148 ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
149 regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
150 retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
151 if(retVal != RT_ERR_OK)
152 return retVal;
153
154 /*Set WRITE Command*/
155 retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK | RTL8367C_RW_MASK);
156
157 checkCounter = 100;
158 while(checkCounter)
159 {
160 retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
161 if((retVal != RT_ERR_OK) || busyFlag)
162 {
163 checkCounter --;
164 if(0 == checkCounter)
165 return RT_ERR_BUSYWAIT_TIMEOUT;
166 }
167 else
168 {
169 checkCounter = 0;
170 }
171 }
172
173 return retVal;
174 }
175 /* Function Name:
176 * rtl8367c_getAsicPHYOCPReg
177 * Description:
178 * Get PHY OCP registers
179 * Input:
180 * phyNo - Physical port number (0~7)
181 * ocpAddr - PHY address
182 * pRegData - read data
183 * Output:
184 * None
185 * Return:
186 * RT_ERR_OK - Success
187 * RT_ERR_SMI - SMI access error
188 * RT_ERR_PHY_REG_ID - invalid PHY address
189 * RT_ERR_PHY_ID - invalid PHY no
190 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
191 * Note:
192 * None
193 */
194 ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData )
195 {
196 ret_t retVal;
197 rtk_uint32 regData;
198 rtk_uint32 busyFlag,checkCounter;
199 rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
200 /*Check internal phy access busy or not*/
201 /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
202 retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
203 if(retVal != RT_ERR_OK)
204 return retVal;
205
206 if(busyFlag)
207 return RT_ERR_BUSYWAIT_TIMEOUT;
208
209 /* OCP prefix */
210 ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
211 if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
212 return retVal;
213
214 /*prepare access address*/
215 ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
216 ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
217 regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
218 retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
219 if(retVal != RT_ERR_OK)
220 return retVal;
221
222 /*Set READ Command*/
223 retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK );
224 if(retVal != RT_ERR_OK)
225 return retVal;
226
227 checkCounter = 100;
228 while(checkCounter)
229 {
230 retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
231 if((retVal != RT_ERR_OK) || busyFlag)
232 {
233 checkCounter --;
234 if(0 == checkCounter)
235 return RT_ERR_FAILED;
236 }
237 else
238 {
239 checkCounter = 0;
240 }
241 }
242
243 /*get PHY register*/
244 retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_READ_DATA, &regData);
245 if(retVal != RT_ERR_OK)
246 return retVal;
247
248 *pRegData = regData;
249
250 return RT_ERR_OK;
251 }
252
253 #endif
254
255 /* Function Name:
256 * rtl8367c_setAsicPHYReg
257 * Description:
258 * Set PHY registers
259 * Input:
260 * phyNo - Physical port number (0~7)
261 * phyAddr - PHY address (0~31)
262 * phyData - Writing data
263 * Output:
264 * None
265 * Return:
266 * RT_ERR_OK - Success
267 * RT_ERR_SMI - SMI access error
268 * RT_ERR_PHY_REG_ID - invalid PHY address
269 * RT_ERR_PHY_ID - invalid PHY no
270 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
271 * Note:
272 * None
273 */
274 ret_t rtl8367c_setAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 phyData )
275 {
276 rtk_uint32 ocp_addr;
277
278 if(phyAddr > RTL8367C_PHY_REGNOMAX)
279 return RT_ERR_PHY_REG_ID;
280
281 ocp_addr = 0xa400 + phyAddr*2;
282
283 return rtl8367c_setAsicPHYOCPReg(phyNo, ocp_addr, phyData);
284 }
285 /* Function Name:
286 * rtl8367c_getAsicPHYReg
287 * Description:
288 * Get PHY registers
289 * Input:
290 * phyNo - Physical port number (0~7)
291 * phyAddr - PHY address (0~31)
292 * pRegData - Writing data
293 * Output:
294 * None
295 * Return:
296 * RT_ERR_OK - Success
297 * RT_ERR_SMI - SMI access error
298 * RT_ERR_PHY_REG_ID - invalid PHY address
299 * RT_ERR_PHY_ID - invalid PHY no
300 * RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
301 * Note:
302 * None
303 */
304 ret_t rtl8367c_getAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 *pRegData )
305 {
306 rtk_uint32 ocp_addr;
307
308 if(phyAddr > RTL8367C_PHY_REGNOMAX)
309 return RT_ERR_PHY_REG_ID;
310
311 ocp_addr = 0xa400 + phyAddr*2;
312
313 return rtl8367c_getAsicPHYOCPReg(phyNo, ocp_addr, pRegData);
314 }
315
316
317 /* Function Name:
318 * rtl8367c_setAsicSdsReg
319 * Description:
320 * Set Serdes registers
321 * Input:
322 * sdsId - sdsid (0~1)
323 * sdsReg - reg address (0~31)
324 * sdsPage - Writing data
325 * Output:
326 * None
327 * Return:
328 * RT_ERR_OK - Success
329
330 * Note:
331 * None
332 */
333
334 ret_t rtl8367c_setAsicSdsReg(rtk_uint32 sdsId, rtk_uint32 sdsReg, rtk_uint32 sdsPage, rtk_uint32 value)
335 {
336 rtk_uint32 retVal;
337
338 if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_DATA, value)) != RT_ERR_OK)
339 return retVal;
340
341 if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_ADR, (sdsPage<<5) | sdsReg)) != RT_ERR_OK)
342 return retVal;
343
344 if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_CMD, 0x00C0|sdsId)) != RT_ERR_OK)
345 return retVal;
346
347 return RT_ERR_OK;
348
349 }
350
351 /* Function Name:
352 * rtl8367c_getAiscSdsReg
353 * Description:
354 * Get Serdes registers
355 * Input:
356 * sdsId - sdsid (0~1)
357 * sdsReg - reg address (0~31)
358 * sdsPage - Writing data
359 * Output:
360 * None
361 * Return:
362 * RT_ERR_OK - Success
363
364 * Note:
365 * None
366 */
367 ret_t rtl8367c_getAsicSdsReg(rtk_uint32 sdsId, rtk_uint32 sdsReg, rtk_uint32 sdsPage, rtk_uint32 *value)
368 {
369 rtk_uint32 retVal, busy;
370
371 if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_ADR, (sdsPage<<5) | sdsReg)) != RT_ERR_OK)
372 return retVal;
373
374 if( (retVal = rtl8367c_setAsicReg(RTL8367C_REG_SDS_INDACS_CMD, 0x0080|sdsId)) != RT_ERR_OK)
375 return retVal;
376
377 while(1)
378 {
379 if ((retVal = rtl8367c_getAsicReg(RTL8367C_REG_SDS_INDACS_CMD, &busy))!=RT_ERR_OK)
380 return retVal;
381
382 if ((busy & 0x100) == 0)
383 break;
384 }
385
386 if ((retVal = rtl8367c_getAsicReg(RTL8367C_REG_SDS_INDACS_DATA, value))!=RT_ERR_OK)
387 return retVal;
388
389 return RT_ERR_OK;
390 }
391
392
393
394