Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: realtek: Add support for RTL9000AA/AN

RTL9000AA/AN as 100BASE-T1 is following:
- 100 Mbps
- Full duplex
- Link Status Change Interrupt
- Master/Slave configuration

Signed-off-by: Yuusuke Ashizuka <ashiduka@fujitsu.com>
Signed-off-by: Torii Kenichi <torii.ken1@fujitsu.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://lore.kernel.org/r/20210121080254.21286-1-ashiduka@fujitsu.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Yuusuke Ashizuka and committed by
Jakub Kicinski
2d8983f9 ca649cca

+132
+132
drivers/net/phy/realtek.c
··· 60 60 #define RTL_LPADV_5000FULL BIT(6) 61 61 #define RTL_LPADV_2500FULL BIT(5) 62 62 63 + #define RTL9000A_GINMR 0x14 64 + #define RTL9000A_GINMR_LINK_STATUS BIT(4) 65 + 63 66 #define RTLGEN_SPEED_MASK 0x0630 64 67 65 68 #define RTL_GENERIC_PHYID 0x001cc800 ··· 658 655 return ret; 659 656 } 660 657 658 + static int rtl9000a_config_init(struct phy_device *phydev) 659 + { 660 + phydev->autoneg = AUTONEG_DISABLE; 661 + phydev->speed = SPEED_100; 662 + phydev->duplex = DUPLEX_FULL; 663 + 664 + return 0; 665 + } 666 + 667 + static int rtl9000a_config_aneg(struct phy_device *phydev) 668 + { 669 + int ret; 670 + u16 ctl = 0; 671 + 672 + switch (phydev->master_slave_set) { 673 + case MASTER_SLAVE_CFG_MASTER_FORCE: 674 + ctl |= CTL1000_AS_MASTER; 675 + break; 676 + case MASTER_SLAVE_CFG_SLAVE_FORCE: 677 + break; 678 + case MASTER_SLAVE_CFG_UNKNOWN: 679 + case MASTER_SLAVE_CFG_UNSUPPORTED: 680 + return 0; 681 + default: 682 + phydev_warn(phydev, "Unsupported Master/Slave mode\n"); 683 + return -EOPNOTSUPP; 684 + } 685 + 686 + ret = phy_modify_changed(phydev, MII_CTRL1000, CTL1000_AS_MASTER, ctl); 687 + if (ret == 1) 688 + ret = genphy_soft_reset(phydev); 689 + 690 + return ret; 691 + } 692 + 693 + static int rtl9000a_read_status(struct phy_device *phydev) 694 + { 695 + int ret; 696 + 697 + phydev->master_slave_get = MASTER_SLAVE_CFG_UNKNOWN; 698 + phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN; 699 + 700 + ret = genphy_update_link(phydev); 701 + if (ret) 702 + return ret; 703 + 704 + ret = phy_read(phydev, MII_CTRL1000); 705 + if (ret < 0) 706 + return ret; 707 + if (ret & CTL1000_AS_MASTER) 708 + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE; 709 + else 710 + phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE; 711 + 712 + ret = phy_read(phydev, MII_STAT1000); 713 + if (ret < 0) 714 + return ret; 715 + if (ret & LPA_1000MSRES) 716 + phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; 717 + else 718 + phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; 719 + 720 + return 0; 721 + } 722 + 723 + static int rtl9000a_ack_interrupt(struct phy_device *phydev) 724 + { 725 + int err; 726 + 727 + err = phy_read(phydev, RTL8211F_INSR); 728 + 729 + return (err < 0) ? err : 0; 730 + } 731 + 732 + static int rtl9000a_config_intr(struct phy_device *phydev) 733 + { 734 + u16 val; 735 + int err; 736 + 737 + if (phydev->interrupts == PHY_INTERRUPT_ENABLED) { 738 + err = rtl9000a_ack_interrupt(phydev); 739 + if (err) 740 + return err; 741 + 742 + val = (u16)~RTL9000A_GINMR_LINK_STATUS; 743 + err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); 744 + } else { 745 + val = ~0; 746 + err = phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); 747 + if (err) 748 + return err; 749 + 750 + err = rtl9000a_ack_interrupt(phydev); 751 + } 752 + 753 + return phy_write_paged(phydev, 0xa42, RTL9000A_GINMR, val); 754 + } 755 + 756 + static irqreturn_t rtl9000a_handle_interrupt(struct phy_device *phydev) 757 + { 758 + int irq_status; 759 + 760 + irq_status = phy_read(phydev, RTL8211F_INSR); 761 + if (irq_status < 0) { 762 + phy_error(phydev); 763 + return IRQ_NONE; 764 + } 765 + 766 + if (!(irq_status & RTL8211F_INER_LINK_STATUS)) 767 + return IRQ_NONE; 768 + 769 + phy_trigger_machine(phydev); 770 + 771 + return IRQ_HANDLED; 772 + } 773 + 661 774 static struct phy_driver realtek_drvs[] = { 662 775 { 663 776 PHY_ID_MATCH_EXACT(0x00008201), ··· 942 823 .handle_interrupt = genphy_handle_interrupt_no_ack, 943 824 .suspend = genphy_suspend, 944 825 .resume = genphy_resume, 826 + }, { 827 + PHY_ID_MATCH_EXACT(0x001ccb00), 828 + .name = "RTL9000AA_RTL9000AN Ethernet", 829 + .features = PHY_BASIC_T1_FEATURES, 830 + .config_init = rtl9000a_config_init, 831 + .config_aneg = rtl9000a_config_aneg, 832 + .read_status = rtl9000a_read_status, 833 + .config_intr = rtl9000a_config_intr, 834 + .handle_interrupt = rtl9000a_handle_interrupt, 835 + .suspend = genphy_suspend, 836 + .resume = genphy_resume, 837 + .read_page = rtl821x_read_page, 838 + .write_page = rtl821x_write_page, 945 839 }, 946 840 }; 947 841