• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/char/rtl8365mb/
1/*
2 * Copyright (C) 2013 Realtek Semiconductor Corp.
3 * All Rights Reserved.
4 *
5 * This program is the proprietary software of Realtek Semiconductor
6 * Corporation and/or its licensors, and only be used, duplicated,
7 * modified or distributed under the authorized license from Realtek.
8 *
9 * ANY USE OF THE SOFTWARE OTHER THAN AS AUTHORIZED UNDER
10 * THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.
11 *
12 * $Revision: 48276 $
13 * $Date: 2014-06-05 15:21:01 +0800 (������, 05 ������ 2014) $
14 *
15 * Purpose : RTL8367C switch high-level API for RTL8367C
16 * Feature : PHY related functions
17 *
18 */
19#include <rtl8367c_asicdrv_phy.h>
20
21#if defined(MDC_MDIO_OPERATION)
22/* Function Name:
23 *      rtl8367c_setAsicPHYReg
24 * Description:
25 *      Set PHY registers
26 * Input:
27 *      phyNo 	- Physical port number (0~4)
28 *      phyAddr - PHY address (0~31)
29 *      phyData - Writing data
30 * Output:
31 *      None
32 * Return:
33 *      RT_ERR_OK 				- Success
34 *      RT_ERR_SMI  			- SMI access error
35 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
36 *      RT_ERR_PHY_ID  			- invalid PHY no
37 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
38 * Note:
39 *      None
40 */
41ret_t rtl8367c_setAsicPHYReg( rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 value)
42{
43    ret_t retVal;
44    rtk_uint32 regAddr;
45
46#ifdef RTK_X86_CLE
47
48#else
49    if(phyNo > RTL8367C_PHY_INTERNALNOMAX)
50        return RT_ERR_PORT_ID;
51#endif
52
53    if(phyAddr > RTL8367C_PHY_REGNOMAX)
54        return RT_ERR_PHY_REG_ID;
55
56    /* Default OCP Address */
57    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, 0x29)) != RT_ERR_OK)
58        return retVal;
59
60    regAddr = 0x2000 + (phyNo << 5) + phyAddr;
61
62    return rtl8367c_setAsicReg(regAddr, value);
63}
64
65/* Function Name:
66 *      rtl8367c_getAsicPHYReg
67 * Description:
68 *      Get PHY registers
69 * Input:
70 *      phyNo 	- Physical port number (0~4)
71 *      phyAddr - PHY address (0~31)
72 *      pRegData - Writing data
73 * Output:
74 *      None
75 * Return:
76 *      RT_ERR_OK 				- Success
77 *      RT_ERR_SMI  			- SMI access error
78 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
79 *      RT_ERR_PHY_ID  			- invalid PHY no
80 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
81 * Note:
82 *      None
83 */
84ret_t rtl8367c_getAsicPHYReg( rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 *value)
85{
86    ret_t retVal;
87    rtk_uint32 regAddr;
88
89#ifdef RTK_X86_CLE
90
91#else
92    if(phyNo > RTL8367C_PHY_INTERNALNOMAX)
93        return RT_ERR_PORT_ID;
94#endif
95
96    if(phyAddr > RTL8367C_PHY_REGNOMAX)
97        return RT_ERR_PHY_REG_ID;
98
99    /* Default OCP Address */
100    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, 0x29)) != RT_ERR_OK)
101        return retVal;
102
103    regAddr = 0x2000 + (phyNo << 5) + phyAddr;
104
105    return rtl8367c_getAsicReg(regAddr, value);
106}
107
108/* Function Name:
109 *      rtl8367c_setAsicPHYOCPReg
110 * Description:
111 *      Set PHY OCP registers
112 * Input:
113 *      phyNo 	- Physical port number (0~7)
114 *      ocpAddr - OCP address
115 *      ocpData - Writing data
116 * Output:
117 *      None
118 * Return:
119 *      RT_ERR_OK 				- Success
120 *      RT_ERR_SMI  			- SMI access error
121 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
122 *      RT_ERR_PHY_ID  			- invalid PHY no
123 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
124 * Note:
125 *      None
126 */
127ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData )
128{
129    ret_t retVal;
130	rtk_uint32 regAddr;
131    rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
132
133    /* OCP prefix */
134    ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
135    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
136        return retVal;
137
138    /*prepare access address*/
139    ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
140    ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
141    regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
142    if((retVal = rtl8367c_setAsicReg(regAddr, ocpData)) != RT_ERR_OK)
143        return retVal;
144
145    return RT_ERR_OK;
146}
147
148/* Function Name:
149 *      rtl8367c_getAsicPHYOCPReg
150 * Description:
151 *      Get PHY OCP registers
152 * Input:
153 *      phyNo 	- Physical port number (0~7)
154 *      ocpAddr - PHY address
155 *      pRegData - read data
156 * Output:
157 *      None
158 * Return:
159 *      RT_ERR_OK 				- Success
160 *      RT_ERR_SMI  			- SMI access error
161 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
162 *      RT_ERR_PHY_ID  			- invalid PHY no
163 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
164 * Note:
165 *      None
166 */
167ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData )
168{
169    ret_t retVal;
170	rtk_uint32 regAddr;
171    rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
172
173    /* OCP prefix */
174    ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
175    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
176        return retVal;
177
178    /*prepare access address*/
179    ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
180    ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
181    regAddr = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
182    if((retVal = rtl8367c_getAsicReg(regAddr, pRegData)) != RT_ERR_OK)
183        return retVal;
184
185    return RT_ERR_OK;
186}
187
188#else
189
190/* Function Name:
191 *      rtl8367c_setAsicPHYReg
192 * Description:
193 *      Set PHY registers
194 * Input:
195 *      phyNo 	- Physical port number (0~7)
196 *      phyAddr - PHY address (0~31)
197 *      phyData - Writing data
198 * Output:
199 *      None
200 * Return:
201 *      RT_ERR_OK 				- Success
202 *      RT_ERR_SMI  			- SMI access error
203 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
204 *      RT_ERR_PHY_ID  			- invalid PHY no
205 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
206 * Note:
207 *      None
208 */
209ret_t rtl8367c_setAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 phyData )
210{
211	ret_t retVal;
212	rtk_uint32 regData;
213    rtk_uint32 busyFlag, checkCounter;
214
215#ifdef RTK_X86_CLE
216
217#else
218	if(phyNo > RTL8367C_PHY_INTERNALNOMAX)
219		return RT_ERR_PHY_ID;
220#endif
221
222	if(phyAddr > RTL8367C_PHY_REGNOMAX)
223		return RT_ERR_PHY_REG_ID;
224
225    /*Check internal phy access busy or not*/
226    /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
227    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
228	if(retVal != RT_ERR_OK)
229		return retVal;
230
231    if(busyFlag)
232        return RT_ERR_BUSYWAIT_TIMEOUT;
233
234    /* Default OCP Address */
235    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, 0x29)) != RT_ERR_OK)
236        return retVal;
237
238    /*prepare access data*/
239    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_WRITE_DATA, phyData);
240	if(retVal != RT_ERR_OK)
241		return retVal;
242
243    /*prepare access address*/
244    regData = RTL8367C_PHY_BASE | (phyNo << RTL8367C_PHY_OFFSET) | phyAddr;
245
246    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
247	if(retVal != RT_ERR_OK)
248		return retVal;
249
250    /*Set WRITE Command*/
251    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK | RTL8367C_RW_MASK);
252
253    checkCounter = 100;
254	while(checkCounter)
255	{
256    	retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
257		if((retVal != RT_ERR_OK) || busyFlag)
258		{
259			checkCounter --;
260			if(0 == checkCounter)
261                return RT_ERR_BUSYWAIT_TIMEOUT;
262		}
263		else
264		{
265			checkCounter = 0;
266		}
267	}
268
269    return retVal;
270}
271/* Function Name:
272 *      rtl8367c_getAsicPHYReg
273 * Description:
274 *      Get PHY registers
275 * Input:
276 *      phyNo 	- Physical port number (0~7)
277 *      phyAddr - PHY address (0~31)
278 *      pRegData - Writing data
279 * Output:
280 *      None
281 * Return:
282 *      RT_ERR_OK 				- Success
283 *      RT_ERR_SMI  			- SMI access error
284 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
285 *      RT_ERR_PHY_ID  			- invalid PHY no
286 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
287 * Note:
288 *      None
289 */
290ret_t rtl8367c_getAsicPHYReg(rtk_uint32 phyNo, rtk_uint32 phyAddr, rtk_uint32 *pRegData )
291{
292	ret_t retVal;
293	rtk_uint32 regData;
294    rtk_uint32 busyFlag,checkCounter;
295
296#ifdef RTK_X86_CLE
297
298#else
299	if(phyNo > RTL8367C_PHY_INTERNALNOMAX)
300		return RT_ERR_PHY_ID;
301#endif
302	if(phyAddr > RTL8367C_PHY_REGNOMAX)
303		return RT_ERR_PHY_REG_ID;
304
305    /*Check internal phy access busy or not*/
306    /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
307    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
308	if(retVal != RT_ERR_OK)
309		return retVal;
310
311    if(busyFlag)
312        return RT_ERR_BUSYWAIT_TIMEOUT;
313
314    /* Default OCP Address */
315    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, 0x29)) != RT_ERR_OK)
316        return retVal;
317
318    /*prepare access address*/
319    regData = RTL8367C_PHY_BASE | (phyNo << RTL8367C_PHY_OFFSET) | phyAddr;
320
321    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
322	if(retVal != RT_ERR_OK)
323		return retVal;
324
325    /*Set READ Command*/
326    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK );
327	if(retVal != RT_ERR_OK)
328		return retVal;
329
330	checkCounter = 100;
331	while(checkCounter)
332	{
333    	retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
334		if((retVal != RT_ERR_OK) || busyFlag)
335		{
336			checkCounter --;
337			if(0 == checkCounter)
338                return RT_ERR_FAILED;
339		}
340		else
341		{
342			checkCounter = 0;
343		}
344	}
345
346    /*get PHY register*/
347    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_READ_DATA, &regData);
348	if(retVal != RT_ERR_OK)
349		return retVal;
350
351    *pRegData = regData;
352
353    return RT_ERR_OK;
354}
355
356/* Function Name:
357 *      rtl8367c_setAsicPHYOCPReg
358 * Description:
359 *      Set PHY OCP registers
360 * Input:
361 *      phyNo 	- Physical port number (0~7)
362 *      ocpAddr - OCP address
363 *      ocpData - Writing data
364 * Output:
365 *      None
366 * Return:
367 *      RT_ERR_OK 				- Success
368 *      RT_ERR_SMI  			- SMI access error
369 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
370 *      RT_ERR_PHY_ID  			- invalid PHY no
371 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
372 * Note:
373 *      None
374 */
375ret_t rtl8367c_setAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 ocpData )
376{
377	ret_t retVal;
378	rtk_uint32 regData;
379    rtk_uint32 busyFlag, checkCounter;
380    rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
381
382    /*Check internal phy access busy or not*/
383    /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
384    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
385	if(retVal != RT_ERR_OK)
386		return retVal;
387
388    if(busyFlag)
389        return RT_ERR_BUSYWAIT_TIMEOUT;
390
391    /* OCP prefix */
392    ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
393    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
394        return retVal;
395
396    /*prepare access data*/
397    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_WRITE_DATA, ocpData);
398	if(retVal != RT_ERR_OK)
399		return retVal;
400
401    /*prepare access address*/
402    ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
403    ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
404    regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
405    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
406	if(retVal != RT_ERR_OK)
407		return retVal;
408
409    /*Set WRITE Command*/
410    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK | RTL8367C_RW_MASK);
411
412    checkCounter = 100;
413	while(checkCounter)
414	{
415    	retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
416		if((retVal != RT_ERR_OK) || busyFlag)
417		{
418			checkCounter --;
419			if(0 == checkCounter)
420                return RT_ERR_BUSYWAIT_TIMEOUT;
421		}
422		else
423		{
424			checkCounter = 0;
425		}
426	}
427
428    return retVal;
429}
430/* Function Name:
431 *      rtl8367c_getAsicPHYOCPReg
432 * Description:
433 *      Get PHY OCP registers
434 * Input:
435 *      phyNo 	- Physical port number (0~7)
436 *      ocpAddr - PHY address
437 *      pRegData - read data
438 * Output:
439 *      None
440 * Return:
441 *      RT_ERR_OK 				- Success
442 *      RT_ERR_SMI  			- SMI access error
443 *      RT_ERR_PHY_REG_ID  		- invalid PHY address
444 *      RT_ERR_PHY_ID  			- invalid PHY no
445 *      RT_ERR_BUSYWAIT_TIMEOUT - PHY access busy
446 * Note:
447 *      None
448 */
449ret_t rtl8367c_getAsicPHYOCPReg(rtk_uint32 phyNo, rtk_uint32 ocpAddr, rtk_uint32 *pRegData )
450{
451	ret_t retVal;
452	rtk_uint32 regData;
453    rtk_uint32 busyFlag,checkCounter;
454    rtk_uint32 ocpAddrPrefix, ocpAddr9_6, ocpAddr5_1;
455
456    /*Check internal phy access busy or not*/
457    /*retVal = rtl8367c_getAsicRegBit(RTL8367C_REG_INDRECT_ACCESS_STATUS, RTL8367C_INDRECT_ACCESS_STATUS_OFFSET,&busyFlag);*/
458    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
459	if(retVal != RT_ERR_OK)
460		return retVal;
461
462    if(busyFlag)
463        return RT_ERR_BUSYWAIT_TIMEOUT;
464
465    /* OCP prefix */
466    ocpAddrPrefix = ((ocpAddr & 0xFC00) >> 10);
467    if((retVal = rtl8367c_setAsicRegBits(RTL8367C_REG_GPHY_OCP_MSB_0, RTL8367C_CFG_CPU_OCPADR_MSB_MASK, ocpAddrPrefix)) != RT_ERR_OK)
468        return retVal;
469
470    /*prepare access address*/
471    ocpAddr9_6 = ((ocpAddr >> 6) & 0x000F);
472    ocpAddr5_1 = ((ocpAddr >> 1) & 0x001F);
473    regData = RTL8367C_PHY_BASE | (ocpAddr9_6 << 8) | (phyNo << RTL8367C_PHY_OFFSET) | ocpAddr5_1;
474    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_ADDRESS, regData);
475	if(retVal != RT_ERR_OK)
476		return retVal;
477
478    /*Set READ Command*/
479    retVal = rtl8367c_setAsicReg(RTL8367C_REG_INDRECT_ACCESS_CTRL, RTL8367C_CMD_MASK );
480	if(retVal != RT_ERR_OK)
481		return retVal;
482
483	checkCounter = 100;
484	while(checkCounter)
485	{
486    	retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_STATUS,&busyFlag);
487		if((retVal != RT_ERR_OK) || busyFlag)
488		{
489			checkCounter --;
490			if(0 == checkCounter)
491                return RT_ERR_FAILED;
492		}
493		else
494		{
495			checkCounter = 0;
496		}
497	}
498
499    /*get PHY register*/
500    retVal = rtl8367c_getAsicReg(RTL8367C_REG_INDRECT_ACCESS_READ_DATA, &regData);
501	if(retVal != RT_ERR_OK)
502		return retVal;
503
504    *pRegData = regData;
505
506    return RT_ERR_OK;
507}
508#endif
509