|
7 | 7 |
|
8 | 8 | #include <dt-bindings/phy/phy.h> |
9 | 9 | #include <linux/clk.h> |
| 10 | +#include <linux/debugfs.h> |
10 | 11 | #include <linux/delay.h> |
11 | 12 | #include <linux/iopoll.h> |
12 | 13 | #include <linux/mfd/syscon.h> |
|
264 | 265 |
|
265 | 266 | #define TPHY_CLKS_CNT 2 |
266 | 267 |
|
| 268 | +#define USER_BUF_LEN(count) min_t(size_t, 8, (count)) |
| 269 | + |
267 | 270 | enum mtk_phy_version { |
268 | 271 | MTK_PHY_V1 = 1, |
269 | 272 | MTK_PHY_V2, |
@@ -336,6 +339,358 @@ struct mtk_tphy { |
336 | 339 | int src_coef; /* coefficient for slew rate calibrate */ |
337 | 340 | }; |
338 | 341 |
|
| 342 | +#if IS_ENABLED(CONFIG_DEBUG_FS) |
| 343 | + |
| 344 | +enum u2_phy_params { |
| 345 | + U2P_EYE_VRT = 0, |
| 346 | + U2P_EYE_TERM, |
| 347 | + U2P_EFUSE_EN, |
| 348 | + U2P_EFUSE_INTR, |
| 349 | + U2P_DISCTH, |
| 350 | + U2P_PRE_EMPHASIS, |
| 351 | +}; |
| 352 | + |
| 353 | +enum u3_phy_params { |
| 354 | + U3P_EFUSE_EN = 0, |
| 355 | + U3P_EFUSE_INTR, |
| 356 | + U3P_EFUSE_TX_IMP, |
| 357 | + U3P_EFUSE_RX_IMP, |
| 358 | +}; |
| 359 | + |
| 360 | +static const char *const u2_phy_files[] = { |
| 361 | + [U2P_EYE_VRT] = "vrt", |
| 362 | + [U2P_EYE_TERM] = "term", |
| 363 | + [U2P_EFUSE_EN] = "efuse", |
| 364 | + [U2P_EFUSE_INTR] = "intr", |
| 365 | + [U2P_DISCTH] = "discth", |
| 366 | + [U2P_PRE_EMPHASIS] = "preemph", |
| 367 | +}; |
| 368 | + |
| 369 | +static const char *const u3_phy_files[] = { |
| 370 | + [U3P_EFUSE_EN] = "efuse", |
| 371 | + [U3P_EFUSE_INTR] = "intr", |
| 372 | + [U3P_EFUSE_TX_IMP] = "tx-imp", |
| 373 | + [U3P_EFUSE_RX_IMP] = "rx-imp", |
| 374 | +}; |
| 375 | + |
| 376 | +static int u2_phy_params_show(struct seq_file *sf, void *unused) |
| 377 | +{ |
| 378 | + struct mtk_phy_instance *inst = sf->private; |
| 379 | + const char *fname = file_dentry(sf->file)->d_iname; |
| 380 | + struct u2phy_banks *u2_banks = &inst->u2_banks; |
| 381 | + void __iomem *com = u2_banks->com; |
| 382 | + u32 max = 0; |
| 383 | + u32 tmp = 0; |
| 384 | + u32 val = 0; |
| 385 | + int ret; |
| 386 | + |
| 387 | + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); |
| 388 | + if (ret < 0) |
| 389 | + return ret; |
| 390 | + |
| 391 | + switch (ret) { |
| 392 | + case U2P_EYE_VRT: |
| 393 | + tmp = readl(com + U3P_USBPHYACR1); |
| 394 | + val = FIELD_GET(PA1_RG_VRT_SEL, tmp); |
| 395 | + max = FIELD_MAX(PA1_RG_VRT_SEL); |
| 396 | + break; |
| 397 | + |
| 398 | + case U2P_EYE_TERM: |
| 399 | + tmp = readl(com + U3P_USBPHYACR1); |
| 400 | + val = FIELD_GET(PA1_RG_TERM_SEL, tmp); |
| 401 | + max = FIELD_MAX(PA1_RG_TERM_SEL); |
| 402 | + break; |
| 403 | + |
| 404 | + case U2P_EFUSE_EN: |
| 405 | + if (u2_banks->misc) { |
| 406 | + tmp = readl(u2_banks->misc + U3P_MISC_REG1); |
| 407 | + max = 1; |
| 408 | + } |
| 409 | + |
| 410 | + val = !!(tmp & MR1_EFUSE_AUTO_LOAD_DIS); |
| 411 | + break; |
| 412 | + |
| 413 | + case U2P_EFUSE_INTR: |
| 414 | + tmp = readl(com + U3P_USBPHYACR1); |
| 415 | + val = FIELD_GET(PA1_RG_INTR_CAL, tmp); |
| 416 | + max = FIELD_MAX(PA1_RG_INTR_CAL); |
| 417 | + break; |
| 418 | + |
| 419 | + case U2P_DISCTH: |
| 420 | + tmp = readl(com + U3P_USBPHYACR6); |
| 421 | + val = FIELD_GET(PA6_RG_U2_DISCTH, tmp); |
| 422 | + max = FIELD_MAX(PA6_RG_U2_DISCTH); |
| 423 | + break; |
| 424 | + |
| 425 | + case U2P_PRE_EMPHASIS: |
| 426 | + tmp = readl(com + U3P_USBPHYACR6); |
| 427 | + val = FIELD_GET(PA6_RG_U2_PRE_EMP, tmp); |
| 428 | + max = FIELD_MAX(PA6_RG_U2_PRE_EMP); |
| 429 | + break; |
| 430 | + |
| 431 | + default: |
| 432 | + seq_printf(sf, "invalid, %d\n", ret); |
| 433 | + break; |
| 434 | + } |
| 435 | + |
| 436 | + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); |
| 437 | + |
| 438 | + return 0; |
| 439 | +} |
| 440 | + |
| 441 | +static int u2_phy_params_open(struct inode *inode, struct file *file) |
| 442 | +{ |
| 443 | + return single_open(file, u2_phy_params_show, inode->i_private); |
| 444 | +} |
| 445 | + |
| 446 | +static ssize_t u2_phy_params_write(struct file *file, const char __user *ubuf, |
| 447 | + size_t count, loff_t *ppos) |
| 448 | +{ |
| 449 | + const char *fname = file_dentry(file)->d_iname; |
| 450 | + struct seq_file *sf = file->private_data; |
| 451 | + struct mtk_phy_instance *inst = sf->private; |
| 452 | + struct u2phy_banks *u2_banks = &inst->u2_banks; |
| 453 | + void __iomem *com = u2_banks->com; |
| 454 | + ssize_t rc; |
| 455 | + u32 val; |
| 456 | + int ret; |
| 457 | + |
| 458 | + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); |
| 459 | + if (rc) |
| 460 | + return rc; |
| 461 | + |
| 462 | + ret = match_string(u2_phy_files, ARRAY_SIZE(u2_phy_files), fname); |
| 463 | + if (ret < 0) |
| 464 | + return (ssize_t)ret; |
| 465 | + |
| 466 | + switch (ret) { |
| 467 | + case U2P_EYE_VRT: |
| 468 | + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_VRT_SEL, val); |
| 469 | + break; |
| 470 | + |
| 471 | + case U2P_EYE_TERM: |
| 472 | + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_TERM_SEL, val); |
| 473 | + break; |
| 474 | + |
| 475 | + case U2P_EFUSE_EN: |
| 476 | + if (u2_banks->misc) |
| 477 | + mtk_phy_update_field(u2_banks->misc + U3P_MISC_REG1, |
| 478 | + MR1_EFUSE_AUTO_LOAD_DIS, !!val); |
| 479 | + break; |
| 480 | + |
| 481 | + case U2P_EFUSE_INTR: |
| 482 | + mtk_phy_update_field(com + U3P_USBPHYACR1, PA1_RG_INTR_CAL, val); |
| 483 | + break; |
| 484 | + |
| 485 | + case U2P_DISCTH: |
| 486 | + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_DISCTH, val); |
| 487 | + break; |
| 488 | + |
| 489 | + case U2P_PRE_EMPHASIS: |
| 490 | + mtk_phy_update_field(com + U3P_USBPHYACR6, PA6_RG_U2_PRE_EMP, val); |
| 491 | + break; |
| 492 | + |
| 493 | + default: |
| 494 | + break; |
| 495 | + } |
| 496 | + |
| 497 | + return count; |
| 498 | +} |
| 499 | + |
| 500 | +static const struct file_operations u2_phy_fops = { |
| 501 | + .open = u2_phy_params_open, |
| 502 | + .write = u2_phy_params_write, |
| 503 | + .read = seq_read, |
| 504 | + .llseek = seq_lseek, |
| 505 | + .release = single_release, |
| 506 | +}; |
| 507 | + |
| 508 | +static void u2_phy_dbgfs_files_create(struct mtk_phy_instance *inst) |
| 509 | +{ |
| 510 | + u32 count = ARRAY_SIZE(u2_phy_files); |
| 511 | + int i; |
| 512 | + |
| 513 | + for (i = 0; i < count; i++) |
| 514 | + debugfs_create_file(u2_phy_files[i], 0644, inst->phy->debugfs, |
| 515 | + inst, &u2_phy_fops); |
| 516 | +} |
| 517 | + |
| 518 | +static int u3_phy_params_show(struct seq_file *sf, void *unused) |
| 519 | +{ |
| 520 | + struct mtk_phy_instance *inst = sf->private; |
| 521 | + const char *fname = file_dentry(sf->file)->d_iname; |
| 522 | + struct u3phy_banks *u3_banks = &inst->u3_banks; |
| 523 | + u32 val = 0; |
| 524 | + u32 max = 0; |
| 525 | + u32 tmp; |
| 526 | + int ret; |
| 527 | + |
| 528 | + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); |
| 529 | + if (ret < 0) |
| 530 | + return ret; |
| 531 | + |
| 532 | + switch (ret) { |
| 533 | + case U3P_EFUSE_EN: |
| 534 | + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_RSV); |
| 535 | + val = !!(tmp & P3D_RG_EFUSE_AUTO_LOAD_DIS); |
| 536 | + max = 1; |
| 537 | + break; |
| 538 | + |
| 539 | + case U3P_EFUSE_INTR: |
| 540 | + tmp = readl(u3_banks->phya + U3P_U3_PHYA_REG0); |
| 541 | + val = FIELD_GET(P3A_RG_IEXT_INTR, tmp); |
| 542 | + max = FIELD_MAX(P3A_RG_IEXT_INTR); |
| 543 | + break; |
| 544 | + |
| 545 | + case U3P_EFUSE_TX_IMP: |
| 546 | + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL0); |
| 547 | + val = FIELD_GET(P3D_RG_TX_IMPEL, tmp); |
| 548 | + max = FIELD_MAX(P3D_RG_TX_IMPEL); |
| 549 | + break; |
| 550 | + |
| 551 | + case U3P_EFUSE_RX_IMP: |
| 552 | + tmp = readl(u3_banks->phyd + U3P_U3_PHYD_IMPCAL1); |
| 553 | + val = FIELD_GET(P3D_RG_RX_IMPEL, tmp); |
| 554 | + max = FIELD_MAX(P3D_RG_RX_IMPEL); |
| 555 | + break; |
| 556 | + |
| 557 | + default: |
| 558 | + seq_printf(sf, "invalid, %d\n", ret); |
| 559 | + break; |
| 560 | + } |
| 561 | + |
| 562 | + seq_printf(sf, "%s : %d [0, %d]\n", fname, val, max); |
| 563 | + |
| 564 | + return 0; |
| 565 | +} |
| 566 | + |
| 567 | +static int u3_phy_params_open(struct inode *inode, struct file *file) |
| 568 | +{ |
| 569 | + return single_open(file, u3_phy_params_show, inode->i_private); |
| 570 | +} |
| 571 | + |
| 572 | +static ssize_t u3_phy_params_write(struct file *file, const char __user *ubuf, |
| 573 | + size_t count, loff_t *ppos) |
| 574 | +{ |
| 575 | + const char *fname = file_dentry(file)->d_iname; |
| 576 | + struct seq_file *sf = file->private_data; |
| 577 | + struct mtk_phy_instance *inst = sf->private; |
| 578 | + struct u3phy_banks *u3_banks = &inst->u3_banks; |
| 579 | + void __iomem *phyd = u3_banks->phyd; |
| 580 | + ssize_t rc; |
| 581 | + u32 val; |
| 582 | + int ret; |
| 583 | + |
| 584 | + rc = kstrtouint_from_user(ubuf, USER_BUF_LEN(count), 0, &val); |
| 585 | + if (rc) |
| 586 | + return rc; |
| 587 | + |
| 588 | + ret = match_string(u3_phy_files, ARRAY_SIZE(u3_phy_files), fname); |
| 589 | + if (ret < 0) |
| 590 | + return (ssize_t)ret; |
| 591 | + |
| 592 | + switch (ret) { |
| 593 | + case U3P_EFUSE_EN: |
| 594 | + mtk_phy_update_field(phyd + U3P_U3_PHYD_RSV, |
| 595 | + P3D_RG_EFUSE_AUTO_LOAD_DIS, !!val); |
| 596 | + break; |
| 597 | + |
| 598 | + case U3P_EFUSE_INTR: |
| 599 | + mtk_phy_update_field(u3_banks->phya + U3P_U3_PHYA_REG0, |
| 600 | + P3A_RG_IEXT_INTR, val); |
| 601 | + break; |
| 602 | + |
| 603 | + case U3P_EFUSE_TX_IMP: |
| 604 | + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_TX_IMPEL, val); |
| 605 | + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL0, P3D_RG_FORCE_TX_IMPEL); |
| 606 | + break; |
| 607 | + |
| 608 | + case U3P_EFUSE_RX_IMP: |
| 609 | + mtk_phy_update_field(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_RX_IMPEL, val); |
| 610 | + mtk_phy_set_bits(phyd + U3P_U3_PHYD_IMPCAL1, P3D_RG_FORCE_RX_IMPEL); |
| 611 | + break; |
| 612 | + |
| 613 | + default: |
| 614 | + break; |
| 615 | + } |
| 616 | + |
| 617 | + return count; |
| 618 | +} |
| 619 | + |
| 620 | +static const struct file_operations u3_phy_fops = { |
| 621 | + .open = u3_phy_params_open, |
| 622 | + .write = u3_phy_params_write, |
| 623 | + .read = seq_read, |
| 624 | + .llseek = seq_lseek, |
| 625 | + .release = single_release, |
| 626 | +}; |
| 627 | + |
| 628 | +static void u3_phy_dbgfs_files_create(struct mtk_phy_instance *inst) |
| 629 | +{ |
| 630 | + u32 count = ARRAY_SIZE(u3_phy_files); |
| 631 | + int i; |
| 632 | + |
| 633 | + for (i = 0; i < count; i++) |
| 634 | + debugfs_create_file(u3_phy_files[i], 0644, inst->phy->debugfs, |
| 635 | + inst, &u3_phy_fops); |
| 636 | +} |
| 637 | + |
| 638 | +static int phy_type_show(struct seq_file *sf, void *unused) |
| 639 | +{ |
| 640 | + struct mtk_phy_instance *inst = sf->private; |
| 641 | + const char *type; |
| 642 | + |
| 643 | + switch (inst->type) { |
| 644 | + case PHY_TYPE_USB2: |
| 645 | + type = "USB2"; |
| 646 | + break; |
| 647 | + case PHY_TYPE_USB3: |
| 648 | + type = "USB3"; |
| 649 | + break; |
| 650 | + case PHY_TYPE_PCIE: |
| 651 | + type = "PCIe"; |
| 652 | + break; |
| 653 | + case PHY_TYPE_SGMII: |
| 654 | + type = "SGMII"; |
| 655 | + break; |
| 656 | + case PHY_TYPE_SATA: |
| 657 | + type = "SATA"; |
| 658 | + break; |
| 659 | + default: |
| 660 | + type = ""; |
| 661 | + } |
| 662 | + |
| 663 | + seq_printf(sf, "%s\n", type); |
| 664 | + |
| 665 | + return 0; |
| 666 | +} |
| 667 | +DEFINE_SHOW_ATTRIBUTE(phy_type); |
| 668 | + |
| 669 | +/* these files will be removed when phy is released by phy core */ |
| 670 | +static void phy_debugfs_init(struct mtk_phy_instance *inst) |
| 671 | +{ |
| 672 | + debugfs_create_file("type", 0444, inst->phy->debugfs, inst, &phy_type_fops); |
| 673 | + |
| 674 | + switch (inst->type) { |
| 675 | + case PHY_TYPE_USB2: |
| 676 | + u2_phy_dbgfs_files_create(inst); |
| 677 | + break; |
| 678 | + case PHY_TYPE_USB3: |
| 679 | + case PHY_TYPE_PCIE: |
| 680 | + u3_phy_dbgfs_files_create(inst); |
| 681 | + break; |
| 682 | + default: |
| 683 | + break; |
| 684 | + } |
| 685 | +} |
| 686 | + |
| 687 | +#else |
| 688 | + |
| 689 | +static void phy_debugfs_init(struct mtk_phy_instance *inst) |
| 690 | +{} |
| 691 | + |
| 692 | +#endif |
| 693 | + |
339 | 694 | static void hs_slew_rate_calibrate(struct mtk_tphy *tphy, |
340 | 695 | struct mtk_phy_instance *instance) |
341 | 696 | { |
@@ -1140,6 +1495,7 @@ static struct phy *mtk_phy_xlate(struct device *dev, |
1140 | 1495 |
|
1141 | 1496 | phy_parse_property(tphy, instance); |
1142 | 1497 | phy_type_set(instance); |
| 1498 | + phy_debugfs_init(instance); |
1143 | 1499 |
|
1144 | 1500 | return instance->phy; |
1145 | 1501 | } |
|
0 commit comments