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, ®Data); 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, ®Data); 501 if(retVal != RT_ERR_OK) 502 return retVal; 503 504 *pRegData = regData; 505 506 return RT_ERR_OK; 507} 508#endif 509