1/* 2 * Copyright (c) 2012, 2015, The Linux Foundation. All rights reserved. 3 * Permission to use, copy, modify, and/or distribute this software for 4 * any purpose with or without fee is hereby granted, provided that the 5 * above copyright notice and this permission notice appear in all copies. 6 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 7 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 8 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 9 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 10 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 11 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 12 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 13 */ 14 15 16 17#include "sw.h" 18#include "fal_port_ctrl.h" 19#include "hsl_api.h" 20#include "hsl.h" 21#include "f1_phy.h" 22#include "aos_timer.h" 23#include "hsl_phy.h" 24#include <linux/kconfig.h> 25#include <linux/kernel.h> 26#include <linux/module.h> 27#include <linux/phy.h> 28 29static a_uint16_t 30_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_addr, a_uint32_t reg) 31{ 32 sw_error_t rv; 33 a_uint16_t val; 34 35 HSL_PHY_GET(rv, dev_id, phy_addr, reg, &val); 36 if (SW_OK != rv) 37 return 0xFFFF; 38 39 return val; 40} 41 42static void 43_phy_reg_write(a_uint32_t dev_id, a_uint32_t phy_addr, a_uint32_t reg, 44 a_uint16_t val) 45{ 46 sw_error_t rv; 47 48 HSL_PHY_SET(rv, dev_id, phy_addr, reg, val); 49} 50 51/* #define f1_phy_reg_read _phy_reg_read */ 52/* #define f1_phy_reg_write _phy_reg_write */ 53 54/****************************************************************************** 55* 56* f1_phy_mii_read - mii register read 57* 58* mil register read 59*/ 60a_uint16_t 61f1_phy_reg_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg_id) 62{ 63 return _phy_reg_read(dev_id, phy_id, reg_id); 64 65} 66 67/****************************************************************************** 68* 69* f1_phy_reg_write - mii register write 70* 71* mii register write 72*/ 73sw_error_t 74f1_phy_reg_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t reg_id, 75 a_uint16_t reg_val) 76{ 77 78 _phy_reg_write(dev_id,phy_id, reg_id, reg_val); 79 80 return SW_OK; 81} 82 83 84/****************************************************************************** 85* 86* f1_phy_debug_write - debug port write 87* 88* debug port write 89*/ 90sw_error_t 91f1_phy_debug_write(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_id, 92 a_uint16_t reg_val) 93{ 94 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, reg_id); 95 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_DATA, reg_val); 96 97 return SW_OK; 98} 99 100/****************************************************************************** 101* 102* f1_phy_debug_read - debug port read 103* 104* debug port read 105*/ 106a_uint16_t 107f1_phy_debug_read(a_uint32_t dev_id, a_uint32_t phy_id, a_uint16_t reg_id) 108{ 109 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, reg_id); 110 return f1_phy_reg_read(dev_id, phy_id, F1_DEBUG_PORT_DATA); 111} 112 113/****************************************************************************** 114* 115* f1_phy_mmd_write - PHY MMD register write 116* 117* PHY MMD register write 118*/ 119sw_error_t 120f1_phy_mmd_write(a_uint32_t dev_id, a_uint32_t phy_id, 121 a_uint16_t mmd_num, 122 a_uint16_t reg_id, 123 a_uint16_t reg_val) 124{ 125 f1_phy_reg_write(dev_id, phy_id, F1_MMD_CTRL_REG, mmd_num); 126 f1_phy_reg_write(dev_id, phy_id, F1_MMD_DATA_REG, reg_id); 127 f1_phy_reg_write(dev_id, phy_id, F1_MMD_CTRL_REG, 0x4000|mmd_num); 128 f1_phy_reg_write(dev_id, phy_id, F1_MMD_DATA_REG, reg_val); 129 130 return SW_OK; 131} 132 133/****************************************************************************** 134* 135* f1_phy_mmd_read - PHY MMD register read 136* 137* PHY MMD register read 138*/ 139a_uint16_t 140f1_phy_mmd_read(a_uint32_t dev_id, a_uint32_t phy_id, 141 a_uint16_t mmd_num, 142 a_uint16_t reg_id) 143{ 144 f1_phy_reg_write(dev_id, phy_id, F1_MMD_CTRL_REG, mmd_num); 145 f1_phy_reg_write(dev_id, phy_id, F1_MMD_DATA_REG, reg_id); 146 f1_phy_reg_write(dev_id, phy_id, F1_MMD_CTRL_REG, 0x4000|mmd_num); 147 148 return f1_phy_reg_read(dev_id, phy_id, F1_MMD_DATA_REG); 149} 150 151 152/****************************************************************************** 153* 154* f1_phy_set_powersave - set power saving status 155* 156* set power saving status 157*/ 158sw_error_t 159f1_phy_set_powersave(a_uint32_t dev_id, a_uint32_t phy_id, a_bool_t enable) 160{ 161 a_uint16_t phy_data; 162 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, 0x29); 163 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_DEBUG_PORT_DATA); 164 165 if(enable == A_TRUE) 166 { 167 phy_data |= 0x8000; 168 } 169 else 170 { 171 phy_data &= ~0x8000; 172 } 173 174 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_DATA, phy_data); 175 176 return SW_OK; 177} 178 179/****************************************************************************** 180* 181* f1_phy_get_powersave - get power saving status 182* 183* set power saving status 184*/ 185sw_error_t 186f1_phy_get_powersave(a_uint32_t dev_id, a_uint32_t phy_id, a_bool_t *enable) 187{ 188 a_uint16_t phy_data; 189 *enable = A_FALSE; 190 191 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, 0x29); 192 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_DEBUG_PORT_DATA); 193 194 if(phy_data & 0x8000) 195 *enable = A_TRUE; 196 197 return SW_OK; 198} 199 200/****************************************************************************** 201* 202* f1_phy_set_hibernate - set hibernate status 203* 204* set hibernate status 205*/ 206sw_error_t 207f1_phy_set_hibernate(a_uint32_t dev_id, a_uint32_t phy_id, a_bool_t enable) 208{ 209 a_uint16_t phy_data; 210 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, 0xb); 211 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_DEBUG_PORT_DATA); 212 213 if(enable == A_TRUE) 214 { 215 phy_data |= 0x8000; 216 } 217 else 218 { 219 phy_data &= ~0x8000; 220 } 221 222 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_DATA, phy_data); 223 224 return SW_OK; 225} 226 227/****************************************************************************** 228* 229* f1_phy_get_hibernate - get hibernate status 230* 231* get hibernate status 232*/ 233sw_error_t 234f1_phy_get_hibernate(a_uint32_t dev_id, a_uint32_t phy_id, a_bool_t *enable) 235{ 236 a_uint16_t phy_data; 237 *enable = A_FALSE; 238 239 f1_phy_reg_write(dev_id, phy_id, F1_DEBUG_PORT_ADDRESS, 0xb); 240 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_DEBUG_PORT_DATA); 241 242 if(phy_data & 0x8000) 243 *enable = A_TRUE; 244 245 return SW_OK; 246} 247 248/****************************************************************************** 249* 250* f1_phy_cdt - cable diagnostic test 251* 252* cable diagnostic test 253*/ 254#ifdef ISISC 255#define RUN_CDT 0x8000 256#define CABLE_LENGTH_UNIT 0x0400 257sw_error_t f1_phy_reset(a_uint32_t dev_id, a_uint32_t phy_id); 258a_bool_t f1_phy_reset_done(a_uint32_t dev_id, a_uint32_t phy_id); 259a_bool_t f1_phy_get_link_status(a_uint32_t dev_id, a_uint32_t phy_id); 260 261static inline fal_cable_status_t 262_fal_cdt_status_mapping(a_uint16_t status) 263{ 264 fal_cable_status_t status_mapping = FAL_CABLE_STATUS_INVALID; 265 266 if (0 == status) 267 status_mapping = FAL_CABLE_STATUS_INVALID; 268 else if (1 == status) 269 status_mapping = FAL_CABLE_STATUS_NORMAL; 270 else if (2 == status) 271 status_mapping = FAL_CABLE_STATUS_OPENED; 272 else if (3 == status) 273 status_mapping = FAL_CABLE_STATUS_SHORT; 274 275 return status_mapping; 276} 277 278static sw_error_t 279f1_phy_cdt_start(a_uint32_t dev_id, a_uint32_t phy_id) 280{ 281 a_uint16_t status = 0; 282 a_uint16_t ii = 100; 283 284 /* RUN CDT */ 285 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CDT_CONTROL, RUN_CDT|CABLE_LENGTH_UNIT); 286 do 287 { 288 aos_mdelay(30); 289 status = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CDT_CONTROL); 290 } 291 while ((status & RUN_CDT) && (--ii)); 292 293 return SW_OK; 294} 295 296sw_error_t 297f1_phy_cdt_get(a_uint32_t dev_id, a_uint32_t phy_id, fal_port_cdt_t *port_cdt) 298{ 299 a_uint16_t status = 0; 300 a_uint16_t cable_delta_time = 0; 301 a_uint16_t org_debug_value = 0; 302 int ii = 100; 303 a_bool_t link_st = A_FALSE; 304 a_uint16_t reg806e = 0; 305 int i; 306 307 if((!port_cdt) || (phy_id > 4)) 308 { 309 return SW_FAIL; 310 } 311 312 /*disable clock gating*/ 313 org_debug_value = f1_phy_debug_read(dev_id, phy_id, 0x3f); 314 f1_phy_debug_write(dev_id, phy_id, 0x3f, 0); 315 316 f1_phy_cdt_start(dev_id, phy_id); 317 318 /* Get cable status */ 319 status = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8064); 320 321 /* Workaround for cable lenth less than 20M */ 322 port_cdt->pair_c_status = (status >> 4) & 0x3; 323 /* Get Cable Length value */ 324 cable_delta_time = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8067); 325 /* the actual cable length equals to CableDeltaTime * 0.824*/ 326 port_cdt->pair_c_len = (cable_delta_time * 824) /1000; 327 if ((1 == port_cdt->pair_c_status) && 328 (port_cdt->pair_c_len > 0) && (port_cdt->pair_c_len <= 20)) 329 { 330 reg806e = f1_phy_mmd_read(dev_id, phy_id, 3, 0x806e); 331 f1_phy_mmd_write(dev_id, phy_id, 3, 0x806e, reg806e & (~0x8000)); 332 333 f1_phy_reset(dev_id, phy_id); 334 f1_phy_reset_done(dev_id, phy_id); 335 do 336 { 337 link_st = f1_phy_get_link_status(dev_id, phy_id); 338 aos_mdelay(100); 339 } while ((A_FALSE == link_st) && (--ii)); 340 341 f1_phy_cdt_start(dev_id, phy_id); 342 /* Get cable status */ 343 status = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8064); 344 } 345 346 for (i=0;i<4;i++) 347 { 348 switch(i) 349 { 350 case 0: 351 port_cdt->pair_a_status = (status >> 12) & 0x3; 352 /* Get Cable Length value */ 353 cable_delta_time = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8065); 354 /* the actual cable length equals to CableDeltaTime * 0.824*/ 355 port_cdt->pair_a_len = (cable_delta_time * 824) /1000; 356 357 break; 358 case 1: 359 port_cdt->pair_b_status = (status >> 8) & 0x3; 360 /* Get Cable Length value */ 361 cable_delta_time = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8066); 362 /* the actual cable length equals to CableDeltaTime * 0.824*/ 363 port_cdt->pair_b_len = (cable_delta_time * 824) /1000; 364 break; 365 case 2: 366 port_cdt->pair_c_status = (status >> 4) & 0x3; 367 /* Get Cable Length value */ 368 cable_delta_time = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8067); 369 /* the actual cable length equals to CableDeltaTime * 0.824*/ 370 port_cdt->pair_c_len = (cable_delta_time * 824) /1000; 371 break; 372 case 3: 373 port_cdt->pair_d_status = status & 0x3; 374 /* Get Cable Length value */ 375 cable_delta_time = f1_phy_mmd_read(dev_id, phy_id, 3, 0x8068); 376 /* the actual cable length equals to CableDeltaTime * 0.824*/ 377 port_cdt->pair_d_len = (cable_delta_time * 824) /1000; 378 break; 379 default: 380 break; 381 } 382 } 383 384 /*restore debug port value*/ 385 f1_phy_debug_write(dev_id, phy_id, 0x3f, org_debug_value); 386 387 return SW_OK; 388} 389 390sw_error_t 391f1_phy_cdt(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t mdi_pair, 392 fal_cable_status_t *cable_status, a_uint32_t *cable_len) 393{ 394 fal_port_cdt_t f1_port_cdt; 395 396 if((mdi_pair >= 4) || (phy_id > 4)) 397 { 398 //There are only 4 mdi pairs in 1000BASE-T 399 return SW_BAD_PARAM; 400 } 401 402 f1_phy_cdt_get(dev_id, phy_id, &f1_port_cdt); 403 404 switch(mdi_pair) 405 { 406 case 0: 407 *cable_status = _fal_cdt_status_mapping(f1_port_cdt.pair_a_status); 408 /* Get Cable Length value */ 409 *cable_len = f1_port_cdt.pair_a_len; 410 break; 411 case 1: 412 *cable_status = _fal_cdt_status_mapping(f1_port_cdt.pair_b_status); 413 /* Get Cable Length value */ 414 *cable_len = f1_port_cdt.pair_b_len; 415 break; 416 case 2: 417 *cable_status = _fal_cdt_status_mapping(f1_port_cdt.pair_c_status); 418 /* Get Cable Length value */ 419 *cable_len = f1_port_cdt.pair_c_len; 420 break; 421 case 3: 422 *cable_status = _fal_cdt_status_mapping(f1_port_cdt.pair_d_status); 423 /* Get Cable Length value */ 424 *cable_len = f1_port_cdt.pair_d_len; 425 break; 426 default: 427 break; 428 } 429 430 return SW_OK; 431} 432#else 433sw_error_t 434f1_phy_cdt(a_uint32_t dev_id, a_uint32_t phy_id, a_uint32_t mdi_pair, 435 fal_cable_status_t *cable_status, a_uint32_t *cable_len) 436{ 437 a_uint16_t status = 0; 438 a_uint16_t ii = 100; 439 440 if(!cable_status || !cable_len) 441 { 442 return SW_FAIL; 443 } 444 445 if(mdi_pair >= 4) 446 { 447 //There are only 4 mdi pairs in 1000BASE-T 448 return SW_BAD_PARAM; 449 } 450 451 a_uint16_t org_debug_value = f1_phy_debug_read(dev_id, phy_id, 0x3f); 452 453 /*disable clock gating*/ 454 f1_phy_debug_write(dev_id, phy_id, 0x3f, 0); 455 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CDT_CONTROL, (mdi_pair << 8) | 0x0001); 456 457 do 458 { 459 aos_mdelay(30); 460 status = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CDT_CONTROL); 461 } 462 while ((status & 0x0001) && (--ii)); 463 464 status = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CDT_STATUS); 465 466 *cable_status = (status&0x300) >> 8; 467 if ( (*cable_status == 1) || (*cable_status == 2)) 468 { 469 if ( mdi_pair == 1 || mdi_pair == 3 ) 470 { 471 /*Reverse the mdi status for channel 1 and channel 3*/ 472 *cable_status = (~(*cable_status)) & 0x3; 473 } 474 } 475 476 /* the actual cable length equals to CableDeltaTime * 0.824*/ 477 a_uint16_t cable_delta_time = status & 0xff; 478 *cable_len = (cable_delta_time * 824) /1000; 479 480 /*restore debug port value*/ 481 f1_phy_debug_write(dev_id, phy_id, 0x3f, org_debug_value); 482 //f1_phy_reg_write(dev_id, phy_id, 0x00, 0x9000);//Reset the PHY if necessary 483 484 return SW_OK; 485} 486#endif 487 488/****************************************************************************** 489* 490* f1_phy_reset_done - reset the phy 491* 492* reset the phy 493*/ 494a_bool_t 495f1_phy_reset_done(a_uint32_t dev_id, a_uint32_t phy_id) 496{ 497 a_uint16_t phy_data; 498 a_uint16_t ii = 200; 499 500 do 501 { 502 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 503 aos_mdelay(10); 504 } 505 while ((!F1_RESET_DONE(phy_data)) && --ii); 506 507 if (ii == 0) 508 return A_FALSE; 509 510 return A_TRUE; 511} 512 513/****************************************************************************** 514* 515* f1_autoneg_done 516* 517* f1_autoneg_done 518*/ 519a_bool_t 520f1_autoneg_done(a_uint32_t dev_id, a_uint32_t phy_id) 521{ 522 a_uint16_t phy_data; 523 a_uint16_t ii = 200; 524 525 do 526 { 527 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_STATUS); 528 aos_mdelay(10); 529 } 530 while ((!F1_AUTONEG_DONE(phy_data)) && --ii); 531 532 if (ii == 0) 533 return A_FALSE; 534 535 return A_TRUE; 536} 537 538/****************************************************************************** 539* 540* f1_phy_Speed_Duplex_Resolved 541 - reset the phy 542* 543* reset the phy 544*/ 545a_bool_t 546f1_phy_speed_duplex_resolved(a_uint32_t dev_id, a_uint32_t phy_id) 547{ 548 a_uint16_t phy_data; 549 a_uint16_t ii = 200; 550 551 do 552 { 553 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_SPEC_STATUS); 554 aos_mdelay(10); 555 } 556 while ((!F1_SPEED_DUPLEX_RESOVLED(phy_data)) && --ii); 557 558 if (ii == 0) 559 return A_FALSE; 560 561 return A_TRUE; 562} 563 564/****************************************************************************** 565* 566* f1_phy_reset - reset the phy 567* 568* reset the phy 569*/ 570sw_error_t 571f1_phy_reset(a_uint32_t dev_id, a_uint32_t phy_id) 572{ 573 a_uint16_t phy_data; 574 575 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 576 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, 577 phy_data | F1_CTRL_SOFTWARE_RESET); 578 579 return SW_OK; 580} 581 582/****************************************************************************** 583* 584* f1_phy_off - power off the phy to change its speed 585* 586* Power off the phy 587*/ 588sw_error_t 589f1_phy_poweroff(a_uint32_t dev_id, a_uint32_t phy_id) 590{ 591 a_uint16_t phy_data; 592 593 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 594 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, 595 phy_data | F1_CTRL_POWER_DOWN); 596 597 return SW_OK; 598} 599 600/****************************************************************************** 601* 602* f1_phy_on - power on the phy after speed changed 603* 604* Power on the phy 605*/ 606sw_error_t 607f1_phy_poweron(a_uint32_t dev_id, a_uint32_t phy_id) 608{ 609 a_uint16_t phy_data; 610 611 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 612 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, 613 phy_data & ~F1_CTRL_POWER_DOWN); 614 615 aos_mdelay(200); 616 617 return SW_OK; 618} 619 620/****************************************************************************** 621* 622* f1_phy_get_ability - get the phy ability 623* 624* 625*/ 626sw_error_t 627f1_phy_get_ability(a_uint32_t dev_id, a_uint32_t phy_id, 628 a_uint32_t * ability) 629{ 630 a_uint16_t phy_data; 631 632 *ability = 0; 633 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_STATUS); 634 635 if (phy_data & F1_STATUS_AUTONEG_CAPS) 636 *ability |= FAL_PHY_AUTONEG_CAPS; 637 638 if (phy_data & F1_STATUS_100T2_HD_CAPS) 639 *ability |= FAL_PHY_100T2_HD_CAPS; 640 641 if (phy_data & F1_STATUS_100T2_FD_CAPS) 642 *ability |= FAL_PHY_100T2_FD_CAPS; 643 644 if (phy_data & F1_STATUS_10T_HD_CAPS) 645 *ability |= FAL_PHY_10T_HD_CAPS; 646 647 if (phy_data & F1_STATUS_10T_FD_CAPS) 648 *ability |= FAL_PHY_10T_FD_CAPS; 649 650 if (phy_data & F1_STATUS_100X_HD_CAPS) 651 *ability |= FAL_PHY_100X_HD_CAPS; 652 653 if (phy_data & F1_STATUS_100X_FD_CAPS) 654 *ability |= FAL_PHY_100X_FD_CAPS; 655 656 if (phy_data & F1_STATUS_100T4_CAPS) 657 *ability |= FAL_PHY_100T4_CAPS; 658 659 if (phy_data & F1_STATUS_EXTENDED_STATUS) 660 { 661 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_EXTENDED_STATUS); 662 663 if (phy_data & F1_STATUS_1000T_FD_CAPS) 664 { 665 *ability |= FAL_PHY_1000T_FD_CAPS; 666 } 667 668 if (phy_data & F1_STATUS_1000X_FD_CAPS) 669 { 670 *ability |= FAL_PHY_1000X_FD_CAPS; 671 } 672 } 673 674 return SW_OK; 675} 676 677/****************************************************************************** 678* 679* f1_phy_get_ability - get the phy ability 680* 681* 682*/ 683sw_error_t 684f1_phy_get_partner_ability(a_uint32_t dev_id, a_uint32_t phy_id, 685 a_uint32_t * ability) 686{ 687 a_uint16_t phy_data; 688 689 *ability = 0; 690 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_LINK_PARTNER_ABILITY); 691 692 if (phy_data & F1_LINK_10BASETX_HALF_DUPLEX) 693 *ability |= FAL_PHY_PART_10T_HD; 694 695 if (phy_data & F1_LINK_10BASETX_FULL_DUPLEX) 696 *ability |= FAL_PHY_PART_10T_FD; 697 698 if (phy_data & F1_LINK_100BASETX_HALF_DUPLEX) 699 *ability |= FAL_PHY_PART_100TX_HD; 700 701 if (phy_data & F1_LINK_100BASETX_FULL_DUPLEX) 702 *ability |= FAL_PHY_PART_100TX_FD; 703 704 if (phy_data & F1_LINK_NPAGE) 705 { 706 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_1000BASET_STATUS); 707 708 if (phy_data & F1_LINK_1000BASETX_FULL_DUPLEX) 709 *ability |= FAL_PHY_PART_1000T_FD; 710 } 711 712 return SW_OK; 713} 714 715/****************************************************************************** 716* 717* f1_phy_status - test to see if the specified phy link is alive 718* 719* RETURNS: 720* A_TRUE --> link is alive 721* A_FALSE --> link is down 722*/ 723a_bool_t 724f1_phy_get_link_status(a_uint32_t dev_id, a_uint32_t phy_id) 725{ 726 a_uint16_t phy_data; 727 728 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_SPEC_STATUS); 729 730 if (phy_data & F1_STATUS_LINK_PASS) 731 return A_TRUE; 732 733 return A_FALSE; 734} 735 736/****************************************************************************** 737* 738* f1_set_autoneg_adv - set the phy autoneg Advertisement 739* 740*/ 741sw_error_t 742f1_phy_set_autoneg_adv(a_uint32_t dev_id, a_uint32_t phy_id, 743 a_uint32_t autoneg) 744{ 745 a_uint16_t phy_data = 0; 746 747 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_AUTONEG_ADVERT); 748 phy_data &= ~F1_ADVERTISE_MEGA_ALL; 749 phy_data &= ~(F1_ADVERTISE_PAUSE | F1_ADVERTISE_ASYM_PAUSE); 750 751 if (autoneg & FAL_PHY_ADV_100TX_FD) 752 phy_data |= F1_ADVERTISE_100FULL; 753 754 if (autoneg & FAL_PHY_ADV_100TX_HD) 755 phy_data |= F1_ADVERTISE_100HALF; 756 757 if (autoneg & FAL_PHY_ADV_10T_FD) 758 phy_data |= F1_ADVERTISE_10FULL; 759 760 if (autoneg & FAL_PHY_ADV_10T_HD) 761 phy_data |= F1_ADVERTISE_10HALF; 762 763 if (autoneg & FAL_PHY_ADV_PAUSE) 764 phy_data |= F1_ADVERTISE_PAUSE; 765 766 if (autoneg & FAL_PHY_ADV_ASY_PAUSE) 767 phy_data |= F1_ADVERTISE_ASYM_PAUSE; 768 769 f1_phy_reg_write(dev_id, phy_id, F1_AUTONEG_ADVERT, phy_data); 770 771 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_1000BASET_CONTROL); 772 phy_data &= ~F1_ADVERTISE_1000FULL; 773 phy_data &= ~F1_ADVERTISE_1000HALF; 774 775 if (autoneg & FAL_PHY_ADV_1000T_FD) 776 phy_data |= F1_ADVERTISE_1000FULL; 777 778 f1_phy_reg_write(dev_id, phy_id, F1_1000BASET_CONTROL, phy_data); 779 780 return SW_OK; 781} 782 783/****************************************************************************** 784* 785* f1_get_autoneg_adv - get the phy autoneg Advertisement 786* 787*/ 788sw_error_t 789f1_phy_get_autoneg_adv(a_uint32_t dev_id, a_uint32_t phy_id, 790 a_uint32_t * autoneg) 791{ 792 a_uint16_t phy_data = 0; 793 794 *autoneg = 0; 795 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_AUTONEG_ADVERT); 796 797 if (phy_data & F1_ADVERTISE_100FULL) 798 *autoneg |= FAL_PHY_ADV_100TX_FD; 799 800 if (phy_data & F1_ADVERTISE_100HALF) 801 *autoneg |= FAL_PHY_ADV_100TX_HD; 802 803 if (phy_data & F1_ADVERTISE_10FULL) 804 *autoneg |= FAL_PHY_ADV_10T_FD; 805 806 if (phy_data & F1_ADVERTISE_10HALF) 807 *autoneg |= FAL_PHY_ADV_10T_HD; 808 809 if (phy_data & F1_ADVERTISE_PAUSE) 810 *autoneg |= FAL_PHY_ADV_PAUSE; 811 812 if (phy_data & F1_ADVERTISE_ASYM_PAUSE) 813 *autoneg |= FAL_PHY_ADV_ASY_PAUSE; 814 815 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_1000BASET_CONTROL); 816 817 if (phy_data & F1_ADVERTISE_1000FULL) 818 *autoneg |= FAL_PHY_ADV_1000T_FD; 819 820 return SW_OK; 821} 822 823/****************************************************************************** 824* 825* f1_phy_enable_autonego - power off the phy to change its speed 826* 827* Power off the phy 828*/ 829a_bool_t 830f1_phy_autoneg_status(a_uint32_t dev_id, a_uint32_t phy_id) 831{ 832 a_uint16_t phy_data; 833 834 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 835 836 if (phy_data & F1_CTRL_AUTONEGOTIATION_ENABLE) 837 return A_TRUE; 838 839 return A_FALSE; 840} 841 842/****************************************************************************** 843* 844* f1_restart_autoneg - restart the phy autoneg 845* 846*/ 847sw_error_t 848f1_phy_restart_autoneg(a_uint32_t dev_id, a_uint32_t phy_id) 849{ 850 a_uint16_t phy_data = 0; 851 852 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 853 854 phy_data |= F1_CTRL_AUTONEGOTIATION_ENABLE; 855 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, 856 phy_data | F1_CTRL_RESTART_AUTONEGOTIATION); 857 858 return SW_OK; 859} 860 861/****************************************************************************** 862* 863* f1_phy_enable_autonego - power off the phy to change its speed 864* 865* Power off the phy 866*/ 867sw_error_t 868f1_phy_enable_autoneg(a_uint32_t dev_id, a_uint32_t phy_id) 869{ 870 a_uint16_t phy_data = 0; 871 872 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_CONTROL); 873 874 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, 875 phy_data | F1_CTRL_AUTONEGOTIATION_ENABLE); 876 877 return SW_OK; 878} 879 880 881/****************************************************************************** 882* 883* f1_phy_get_speed - Determines the speed of phy ports associated with the 884* specified device. 885*/ 886 887sw_error_t 888f1_phy_get_speed(a_uint32_t dev_id, a_uint32_t phy_id, 889 fal_port_speed_t * speed) 890{ 891 a_uint16_t phy_data; 892 893 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_SPEC_STATUS); 894 895 switch (phy_data & F1_STATUS_SPEED_MASK) 896 { 897 case F1_STATUS_SPEED_1000MBS: 898 *speed = FAL_SPEED_1000; 899 break; 900 case F1_STATUS_SPEED_100MBS: 901 *speed = FAL_SPEED_100; 902 break; 903 case F1_STATUS_SPEED_10MBS: 904 *speed = FAL_SPEED_10; 905 break; 906 default: 907 return SW_READ_ERROR; 908 } 909 910 return SW_OK; 911} 912 913/****************************************************************************** 914* 915* f1_phy_set_speed - Determines the speed of phy ports associated with the 916* specified device. 917*/ 918sw_error_t 919f1_phy_set_speed(a_uint32_t dev_id, a_uint32_t phy_id, 920 fal_port_speed_t speed) 921{ 922 a_uint16_t phy_data = 0; 923 a_uint16_t phy_status = 0; 924 925 a_uint32_t autoneg, oldneg; 926 fal_port_duplex_t old_duplex; 927 928 if (FAL_SPEED_1000 == speed) 929 { 930 phy_data |= F1_CTRL_SPEED_1000; 931 } 932 else if (FAL_SPEED_100 == speed) 933 { 934 phy_data |= F1_CTRL_SPEED_100; 935 } 936 else if (FAL_SPEED_10 == speed) 937 { 938 phy_data |= F1_CTRL_SPEED_10; 939 } 940 else 941 { 942 return SW_BAD_PARAM; 943 } 944 945 phy_data &= ~F1_CTRL_AUTONEGOTIATION_ENABLE; 946 947 (void)f1_phy_get_autoneg_adv(dev_id, phy_id, &autoneg); 948 oldneg = autoneg; 949 autoneg &= ~FAL_PHY_ADV_GE_SPEED_ALL; 950 951 (void)f1_phy_get_duplex(dev_id, phy_id, &old_duplex); 952 953 if (old_duplex == FAL_FULL_DUPLEX) 954 { 955 phy_data |= F1_CTRL_FULL_DUPLEX; 956 957 if (FAL_SPEED_1000 == speed) 958 { 959 autoneg |= FAL_PHY_ADV_1000T_FD; 960 } 961 else if (FAL_SPEED_100 == speed) 962 { 963 autoneg |= FAL_PHY_ADV_100TX_FD; 964 } 965 else 966 { 967 autoneg |= FAL_PHY_ADV_10T_FD; 968 } 969 } 970 else if (old_duplex == FAL_HALF_DUPLEX) 971 { 972 phy_data &= ~F1_CTRL_FULL_DUPLEX; 973 974 if (FAL_SPEED_100 == speed) 975 { 976 autoneg |= FAL_PHY_ADV_100TX_HD; 977 } 978 else 979 { 980 autoneg |= FAL_PHY_ADV_10T_HD; 981 } 982 } 983 else 984 { 985 return SW_FAIL; 986 } 987 988 (void)f1_phy_set_autoneg_adv(dev_id, phy_id, autoneg); 989 (void)f1_phy_restart_autoneg(dev_id, phy_id); 990 if(f1_phy_get_link_status(dev_id, phy_id)) 991 { 992 do 993 { 994 phy_status = f1_phy_reg_read(dev_id, phy_id, F1_PHY_STATUS); 995 } 996 while(!F1_AUTONEG_DONE(phy_status)); 997 } 998 999 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, phy_data); 1000 (void)f1_phy_set_autoneg_adv(dev_id, phy_id, oldneg); 1001 1002 return SW_OK; 1003 1004} 1005 1006/****************************************************************************** 1007* 1008* f1_phy_get_duplex - Determines the speed of phy ports associated with the 1009* specified device. 1010*/ 1011sw_error_t 1012f1_phy_get_duplex(a_uint32_t dev_id, a_uint32_t phy_id, 1013 fal_port_duplex_t * duplex) 1014{ 1015 a_uint16_t phy_data; 1016 1017 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_SPEC_STATUS); 1018 1019 //read duplex 1020 if (phy_data & F1_STATUS_FULL_DUPLEX) 1021 *duplex = FAL_FULL_DUPLEX; 1022 else 1023 *duplex = FAL_HALF_DUPLEX; 1024 1025 return SW_OK; 1026} 1027 1028/****************************************************************************** 1029* 1030* f1_phy_set_duplex - Determines the speed of phy ports associated with the 1031* specified device. 1032*/ 1033sw_error_t 1034f1_phy_set_duplex(a_uint32_t dev_id, a_uint32_t phy_id, 1035 fal_port_duplex_t duplex) 1036{ 1037 a_uint16_t phy_data = 0; 1038 a_uint16_t phy_status = 0; 1039 1040 fal_port_speed_t old_speed; 1041 a_uint32_t oldneg, autoneg; 1042 1043 if (A_TRUE == f1_phy_autoneg_status(dev_id, phy_id)) 1044 phy_data &= ~F1_CTRL_AUTONEGOTIATION_ENABLE; 1045 1046 (void)f1_phy_get_autoneg_adv(dev_id, phy_id, &autoneg); 1047 oldneg = autoneg; 1048 autoneg &= ~FAL_PHY_ADV_GE_SPEED_ALL; 1049 (void)f1_phy_get_speed(dev_id, phy_id, &old_speed); 1050 1051 if (FAL_SPEED_1000 == old_speed) 1052 { 1053 phy_data |= F1_CTRL_SPEED_1000; 1054 } 1055 else if (FAL_SPEED_100 == old_speed) 1056 { 1057 phy_data |= F1_CTRL_SPEED_100; 1058 } 1059 else if (FAL_SPEED_10 == old_speed) 1060 { 1061 phy_data |= F1_CTRL_SPEED_10; 1062 } 1063 else 1064 { 1065 return SW_FAIL; 1066 } 1067 1068 if (duplex == FAL_FULL_DUPLEX) 1069 { 1070 phy_data |= F1_CTRL_FULL_DUPLEX; 1071 1072 if (FAL_SPEED_1000 == old_speed) 1073 { 1074 autoneg = FAL_PHY_ADV_1000T_FD; 1075 } 1076 else if (FAL_SPEED_100 == old_speed) 1077 { 1078 autoneg = FAL_PHY_ADV_100TX_FD; 1079 } 1080 else 1081 { 1082 autoneg = FAL_PHY_ADV_10T_FD; 1083 } 1084 } 1085 else if (duplex == FAL_HALF_DUPLEX) 1086 { 1087 phy_data &= ~F1_CTRL_FULL_DUPLEX; 1088 1089 if (FAL_SPEED_100 == old_speed) 1090 { 1091 autoneg = FAL_PHY_ADV_100TX_HD; 1092 } 1093 else 1094 { 1095 autoneg = FAL_PHY_ADV_10T_HD; 1096 } 1097 } 1098 else 1099 { 1100 return SW_BAD_PARAM; 1101 } 1102 1103 (void)f1_phy_set_autoneg_adv(dev_id, phy_id, autoneg); 1104 (void)f1_phy_restart_autoneg(dev_id, phy_id); 1105 if(f1_phy_get_link_status(dev_id, phy_id)) 1106 { 1107 do 1108 { 1109 phy_status = f1_phy_reg_read(dev_id, phy_id, F1_PHY_STATUS); 1110 } 1111 while(!F1_AUTONEG_DONE(phy_status)); 1112 } 1113 1114 f1_phy_reg_write(dev_id, phy_id, F1_PHY_CONTROL, phy_data); 1115 (void)f1_phy_set_autoneg_adv(dev_id, phy_id, oldneg); 1116 1117 return SW_OK; 1118} 1119 1120/****************************************************************************** 1121* 1122* f1_phy_get_phy_id - get the phy id 1123* 1124*/ 1125static sw_error_t 1126f1_phy_get_phy_id(a_uint32_t dev_id, a_uint32_t phy_id, 1127 a_uint16_t * org_id, a_uint16_t * rev_id) 1128{ 1129 *org_id = f1_phy_reg_read(dev_id, phy_id, F1_PHY_ID1); 1130 *rev_id = f1_phy_reg_read(dev_id, phy_id, F1_PHY_ID2); 1131 1132 return SW_OK; 1133} 1134 1135/****************************************************************************** 1136* 1137* f1_phy_intr_mask_set - Set interrupt mask with the 1138* specified device. 1139*/ 1140sw_error_t 1141f1_phy_intr_mask_set(a_uint32_t dev_id, a_uint32_t phy_id, 1142 a_uint32_t intr_mask_flag) 1143{ 1144 a_uint16_t phy_data = 0; 1145 1146 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_INTR_MASK); 1147 1148 if (FAL_PHY_INTR_STATUS_UP_CHANGE & intr_mask_flag) 1149 { 1150 phy_data |= F1_INTR_STATUS_UP_CHANGE; 1151 } 1152 else 1153 { 1154 phy_data &= (~F1_INTR_STATUS_UP_CHANGE); 1155 } 1156 1157 if (FAL_PHY_INTR_STATUS_DOWN_CHANGE & intr_mask_flag) 1158 { 1159 phy_data |= F1_INTR_STATUS_DOWN_CHANGE; 1160 } 1161 else 1162 { 1163 phy_data &= (~F1_INTR_STATUS_DOWN_CHANGE); 1164 } 1165 1166 if (FAL_PHY_INTR_SPEED_CHANGE & intr_mask_flag) 1167 { 1168 phy_data |= F1_INTR_SPEED_CHANGE; 1169 } 1170 else 1171 { 1172 phy_data &= (~F1_INTR_SPEED_CHANGE); 1173 } 1174 1175 if (FAL_PHY_INTR_DUPLEX_CHANGE & intr_mask_flag) 1176 { 1177 phy_data |= F1_INTR_DUPLEX_CHANGE; 1178 } 1179 else 1180 { 1181 phy_data &= (~F1_INTR_DUPLEX_CHANGE); 1182 } 1183 1184 f1_phy_reg_write(dev_id, phy_id, F1_PHY_INTR_MASK, phy_data); 1185 return SW_OK; 1186} 1187 1188/****************************************************************************** 1189* 1190* f1_phy_intr_mask_get - Get interrupt mask with the 1191* specified device. 1192*/ 1193sw_error_t 1194f1_phy_intr_mask_get(a_uint32_t dev_id, a_uint32_t phy_id, 1195 a_uint32_t * intr_mask_flag) 1196{ 1197 a_uint16_t phy_data = 0; 1198 1199 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_INTR_MASK); 1200 1201 *intr_mask_flag = 0; 1202 if (F1_INTR_STATUS_UP_CHANGE & phy_data) 1203 { 1204 *intr_mask_flag |= FAL_PHY_INTR_STATUS_UP_CHANGE; 1205 } 1206 1207 if (F1_INTR_STATUS_DOWN_CHANGE & phy_data) 1208 { 1209 *intr_mask_flag |= FAL_PHY_INTR_STATUS_DOWN_CHANGE; 1210 } 1211 1212 if (F1_INTR_SPEED_CHANGE & phy_data) 1213 { 1214 *intr_mask_flag |= FAL_PHY_INTR_SPEED_CHANGE; 1215 } 1216 1217 if (F1_INTR_DUPLEX_CHANGE & phy_data) 1218 { 1219 *intr_mask_flag |= FAL_PHY_INTR_DUPLEX_CHANGE; 1220 } 1221 1222 return SW_OK; 1223} 1224 1225/****************************************************************************** 1226* 1227* f1_phy_intr_status_get - Get interrupt status with the 1228* specified device. 1229*/ 1230sw_error_t 1231f1_phy_intr_status_get(a_uint32_t dev_id, a_uint32_t phy_id, 1232 a_uint32_t * intr_status_flag) 1233{ 1234 a_uint16_t phy_data = 0; 1235 1236 phy_data = f1_phy_reg_read(dev_id, phy_id, F1_PHY_INTR_STATUS); 1237 1238 *intr_status_flag = 0; 1239 if (F1_INTR_STATUS_UP_CHANGE & phy_data) 1240 { 1241 *intr_status_flag |= FAL_PHY_INTR_STATUS_UP_CHANGE; 1242 } 1243 1244 if (F1_INTR_STATUS_DOWN_CHANGE & phy_data) 1245 { 1246 *intr_status_flag |= FAL_PHY_INTR_STATUS_DOWN_CHANGE; 1247 } 1248 1249 if (F1_INTR_SPEED_CHANGE & phy_data) 1250 { 1251 *intr_status_flag |= FAL_PHY_INTR_SPEED_CHANGE; 1252 } 1253 1254 if (F1_INTR_DUPLEX_CHANGE & phy_data) 1255 { 1256 *intr_status_flag |= FAL_PHY_INTR_DUPLEX_CHANGE; 1257 } 1258 1259 return SW_OK; 1260} 1261 1262 1263#if 0 1264/****************************************************************************** 1265* 1266* f1_phy_init - 1267* 1268*/ 1269a_bool_t 1270f1_phy_init(a_uint32_t dev_id, a_uint32_t phy_id, 1271 a_uint16_t org_id, a_uint16_t rev_id) 1272{ 1273 a_uint16_t org_tmp, rev_tmp; 1274 1275 (void)f1_phy_get_phy_id(dev_id, phy_id, &org_tmp, &rev_tmp); 1276 if ((org_id == org_tmp) && (rev_id == rev_tmp)) 1277 return A_TRUE; 1278 else 1279 return A_FALSE; 1280} 1281 1282#endif 1283 1284static int f1_phy_probe(struct phy_device *pdev) 1285{ 1286 int ret; 1287 hsl_phy_ops_t f1_phy_api_ops = { 0 }; 1288 1289 f1_phy_api_ops.phy_hibernation_set = f1_phy_set_hibernate; 1290 f1_phy_api_ops.phy_hibernation_get = f1_phy_get_hibernate; 1291 f1_phy_api_ops.phy_speed_get = f1_phy_get_speed; 1292 f1_phy_api_ops.phy_speed_set = f1_phy_set_speed; 1293 f1_phy_api_ops.phy_duplex_get = f1_phy_get_duplex; 1294 f1_phy_api_ops.phy_duplex_set = f1_phy_set_duplex; 1295 f1_phy_api_ops.phy_autoneg_enable_set = f1_phy_enable_autoneg; 1296 f1_phy_api_ops.phy_restart_autoneg = f1_phy_restart_autoneg; 1297 f1_phy_api_ops.phy_autoneg_status_get = f1_phy_autoneg_status; 1298 f1_phy_api_ops.phy_autoneg_adv_set = f1_phy_set_autoneg_adv; 1299 f1_phy_api_ops.phy_autoneg_adv_get = f1_phy_get_autoneg_adv; 1300 f1_phy_api_ops.phy_powersave_set = f1_phy_set_powersave; 1301 f1_phy_api_ops.phy_powersave_get = f1_phy_get_powersave; 1302 f1_phy_api_ops.phy_cdt = f1_phy_cdt; 1303 f1_phy_api_ops.phy_link_status_get = f1_phy_get_link_status; 1304 f1_phy_api_ops.phy_reset = f1_phy_reset; 1305 f1_phy_api_ops.phy_power_off = f1_phy_poweroff; 1306 f1_phy_api_ops.phy_power_on = f1_phy_poweron; 1307 f1_phy_api_ops.phy_id_get = f1_phy_get_phy_id; 1308 f1_phy_api_ops.phy_reg_write = f1_phy_reg_write; 1309 f1_phy_api_ops.phy_reg_read = f1_phy_reg_read; 1310 f1_phy_api_ops.phy_debug_write = f1_phy_debug_write; 1311 f1_phy_api_ops.phy_debug_read = f1_phy_debug_read; 1312 f1_phy_api_ops.phy_mmd_write = f1_phy_mmd_write; 1313 f1_phy_api_ops.phy_mmd_read = f1_phy_mmd_read; 1314 f1_phy_api_ops.phy_intr_mask_set = f1_phy_intr_mask_set; 1315 f1_phy_api_ops.phy_intr_mask_get = f1_phy_intr_mask_get; 1316 f1_phy_api_ops.phy_intr_status_get = f1_phy_intr_status_get; 1317 ret = hsl_phy_api_ops_register(&f1_phy_api_ops); 1318 1319 if (ret == 0) 1320 printk("qca probe f1 phy driver succeeded!\n"); 1321 else 1322 printk("qca probe f1 phy driver failed! (code: %d)\n", ret); 1323 return ret; 1324} 1325 1326int f1_phy_init(void) 1327{ 1328 phy_api_ops_init(0); 1329 return f1_phy_probe((struct phy_device *)NULL); 1330} 1331 1332