hc
2024-01-31 f9004dbfff8a3fbbd7e2a88c8a4327c7f2f8e5b2
kernel/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
....@@ -3,6 +3,7 @@
33
44 #include <linux/pci.h>
55 #include <linux/delay.h>
6
+#include <linux/iopoll.h>
67 #include <linux/sched.h>
78
89 #include "ixgbe.h"
....@@ -658,6 +659,307 @@
658659 return status;
659660 }
660661
662
+#define IXGBE_HW_READ_REG(addr) IXGBE_READ_REG(hw, addr)
663
+
664
+/**
665
+ * ixgbe_msca_cmd - Write the command register and poll for completion/timeout
666
+ * @hw: pointer to hardware structure
667
+ * @cmd: command register value to write
668
+ **/
669
+static s32 ixgbe_msca_cmd(struct ixgbe_hw *hw, u32 cmd)
670
+{
671
+ IXGBE_WRITE_REG(hw, IXGBE_MSCA, cmd);
672
+
673
+ return readx_poll_timeout(IXGBE_HW_READ_REG, IXGBE_MSCA, cmd,
674
+ !(cmd & IXGBE_MSCA_MDI_COMMAND), 10,
675
+ 10 * IXGBE_MDIO_COMMAND_TIMEOUT);
676
+}
677
+
678
+/**
679
+ * ixgbe_mii_bus_read_generic - Read a clause 22/45 register with gssr flags
680
+ * @hw: pointer to hardware structure
681
+ * @addr: address
682
+ * @regnum: register number
683
+ * @gssr: semaphore flags to acquire
684
+ **/
685
+static s32 ixgbe_mii_bus_read_generic(struct ixgbe_hw *hw, int addr,
686
+ int regnum, u32 gssr)
687
+{
688
+ u32 hwaddr, cmd;
689
+ s32 data;
690
+
691
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
692
+ return -EBUSY;
693
+
694
+ hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
695
+ if (regnum & MII_ADDR_C45) {
696
+ hwaddr |= regnum & GENMASK(21, 0);
697
+ cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
698
+ } else {
699
+ hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
700
+ cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL |
701
+ IXGBE_MSCA_READ_AUTOINC | IXGBE_MSCA_MDI_COMMAND;
702
+ }
703
+
704
+ data = ixgbe_msca_cmd(hw, cmd);
705
+ if (data < 0)
706
+ goto mii_bus_read_done;
707
+
708
+ /* For a clause 45 access the address cycle just completed, we still
709
+ * need to do the read command, otherwise just get the data
710
+ */
711
+ if (!(regnum & MII_ADDR_C45))
712
+ goto do_mii_bus_read;
713
+
714
+ cmd = hwaddr | IXGBE_MSCA_READ | IXGBE_MSCA_MDI_COMMAND;
715
+ data = ixgbe_msca_cmd(hw, cmd);
716
+ if (data < 0)
717
+ goto mii_bus_read_done;
718
+
719
+do_mii_bus_read:
720
+ data = IXGBE_READ_REG(hw, IXGBE_MSRWD);
721
+ data = (data >> IXGBE_MSRWD_READ_DATA_SHIFT) & GENMASK(16, 0);
722
+
723
+mii_bus_read_done:
724
+ hw->mac.ops.release_swfw_sync(hw, gssr);
725
+ return data;
726
+}
727
+
728
+/**
729
+ * ixgbe_mii_bus_write_generic - Write a clause 22/45 register with gssr flags
730
+ * @hw: pointer to hardware structure
731
+ * @addr: address
732
+ * @regnum: register number
733
+ * @val: value to write
734
+ * @gssr: semaphore flags to acquire
735
+ **/
736
+static s32 ixgbe_mii_bus_write_generic(struct ixgbe_hw *hw, int addr,
737
+ int regnum, u16 val, u32 gssr)
738
+{
739
+ u32 hwaddr, cmd;
740
+ s32 err;
741
+
742
+ if (hw->mac.ops.acquire_swfw_sync(hw, gssr))
743
+ return -EBUSY;
744
+
745
+ IXGBE_WRITE_REG(hw, IXGBE_MSRWD, (u32)val);
746
+
747
+ hwaddr = addr << IXGBE_MSCA_PHY_ADDR_SHIFT;
748
+ if (regnum & MII_ADDR_C45) {
749
+ hwaddr |= regnum & GENMASK(21, 0);
750
+ cmd = hwaddr | IXGBE_MSCA_ADDR_CYCLE | IXGBE_MSCA_MDI_COMMAND;
751
+ } else {
752
+ hwaddr |= (regnum & GENMASK(5, 0)) << IXGBE_MSCA_DEV_TYPE_SHIFT;
753
+ cmd = hwaddr | IXGBE_MSCA_OLD_PROTOCOL | IXGBE_MSCA_WRITE |
754
+ IXGBE_MSCA_MDI_COMMAND;
755
+ }
756
+
757
+ /* For clause 45 this is an address cycle, for clause 22 this is the
758
+ * entire transaction
759
+ */
760
+ err = ixgbe_msca_cmd(hw, cmd);
761
+ if (err < 0 || !(regnum & MII_ADDR_C45))
762
+ goto mii_bus_write_done;
763
+
764
+ cmd = hwaddr | IXGBE_MSCA_WRITE | IXGBE_MSCA_MDI_COMMAND;
765
+ err = ixgbe_msca_cmd(hw, cmd);
766
+
767
+mii_bus_write_done:
768
+ hw->mac.ops.release_swfw_sync(hw, gssr);
769
+ return err;
770
+}
771
+
772
+/**
773
+ * ixgbe_mii_bus_read - Read a clause 22/45 register
774
+ * @bus: pointer to mii_bus structure which points to our driver private
775
+ * @addr: address
776
+ * @regnum: register number
777
+ **/
778
+static s32 ixgbe_mii_bus_read(struct mii_bus *bus, int addr, int regnum)
779
+{
780
+ struct ixgbe_adapter *adapter = bus->priv;
781
+ struct ixgbe_hw *hw = &adapter->hw;
782
+ u32 gssr = hw->phy.phy_semaphore_mask;
783
+
784
+ return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
785
+}
786
+
787
+/**
788
+ * ixgbe_mii_bus_write - Write a clause 22/45 register
789
+ * @bus: pointer to mii_bus structure which points to our driver private
790
+ * @addr: address
791
+ * @regnum: register number
792
+ * @val: value to write
793
+ **/
794
+static s32 ixgbe_mii_bus_write(struct mii_bus *bus, int addr, int regnum,
795
+ u16 val)
796
+{
797
+ struct ixgbe_adapter *adapter = bus->priv;
798
+ struct ixgbe_hw *hw = &adapter->hw;
799
+ u32 gssr = hw->phy.phy_semaphore_mask;
800
+
801
+ return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
802
+}
803
+
804
+/**
805
+ * ixgbe_x550em_a_mii_bus_read - Read a clause 22/45 register on x550em_a
806
+ * @bus: pointer to mii_bus structure which points to our driver private
807
+ * @addr: address
808
+ * @regnum: register number
809
+ **/
810
+static s32 ixgbe_x550em_a_mii_bus_read(struct mii_bus *bus, int addr,
811
+ int regnum)
812
+{
813
+ struct ixgbe_adapter *adapter = bus->priv;
814
+ struct ixgbe_hw *hw = &adapter->hw;
815
+ u32 gssr = hw->phy.phy_semaphore_mask;
816
+
817
+ gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
818
+ return ixgbe_mii_bus_read_generic(hw, addr, regnum, gssr);
819
+}
820
+
821
+/**
822
+ * ixgbe_x550em_a_mii_bus_write - Write a clause 22/45 register on x550em_a
823
+ * @bus: pointer to mii_bus structure which points to our driver private
824
+ * @addr: address
825
+ * @regnum: register number
826
+ * @val: value to write
827
+ **/
828
+static s32 ixgbe_x550em_a_mii_bus_write(struct mii_bus *bus, int addr,
829
+ int regnum, u16 val)
830
+{
831
+ struct ixgbe_adapter *adapter = bus->priv;
832
+ struct ixgbe_hw *hw = &adapter->hw;
833
+ u32 gssr = hw->phy.phy_semaphore_mask;
834
+
835
+ gssr |= IXGBE_GSSR_TOKEN_SM | IXGBE_GSSR_PHY0_SM;
836
+ return ixgbe_mii_bus_write_generic(hw, addr, regnum, val, gssr);
837
+}
838
+
839
+/**
840
+ * ixgbe_get_first_secondary_devfn - get first device downstream of root port
841
+ * @devfn: PCI_DEVFN of root port on domain 0, bus 0
842
+ *
843
+ * Returns pci_dev pointer to PCI_DEVFN(0, 0) on subordinate side of root
844
+ * on domain 0, bus 0, devfn = 'devfn'
845
+ **/
846
+static struct pci_dev *ixgbe_get_first_secondary_devfn(unsigned int devfn)
847
+{
848
+ struct pci_dev *rp_pdev;
849
+ int bus;
850
+
851
+ rp_pdev = pci_get_domain_bus_and_slot(0, 0, devfn);
852
+ if (rp_pdev && rp_pdev->subordinate) {
853
+ bus = rp_pdev->subordinate->number;
854
+ pci_dev_put(rp_pdev);
855
+ return pci_get_domain_bus_and_slot(0, bus, 0);
856
+ }
857
+
858
+ pci_dev_put(rp_pdev);
859
+ return NULL;
860
+}
861
+
862
+/**
863
+ * ixgbe_x550em_a_has_mii - is this the first ixgbe x550em_a PCI function?
864
+ * @hw: pointer to hardware structure
865
+ *
866
+ * Returns true if hw points to lowest numbered PCI B:D.F x550_em_a device in
867
+ * the SoC. There are up to 4 MACs sharing a single MDIO bus on the x550em_a,
868
+ * but we only want to register one MDIO bus.
869
+ **/
870
+static bool ixgbe_x550em_a_has_mii(struct ixgbe_hw *hw)
871
+{
872
+ struct ixgbe_adapter *adapter = hw->back;
873
+ struct pci_dev *pdev = adapter->pdev;
874
+ struct pci_dev *func0_pdev;
875
+ bool has_mii = false;
876
+
877
+ /* For the C3000 family of SoCs (x550em_a) the internal ixgbe devices
878
+ * are always downstream of root ports @ 0000:00:16.0 & 0000:00:17.0
879
+ * It's not valid for function 0 to be disabled and function 1 is up,
880
+ * so the lowest numbered ixgbe dev will be device 0 function 0 on one
881
+ * of those two root ports
882
+ */
883
+ func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x16, 0));
884
+ if (func0_pdev) {
885
+ if (func0_pdev == pdev)
886
+ has_mii = true;
887
+ goto out;
888
+ }
889
+ func0_pdev = ixgbe_get_first_secondary_devfn(PCI_DEVFN(0x17, 0));
890
+ if (func0_pdev == pdev)
891
+ has_mii = true;
892
+
893
+out:
894
+ pci_dev_put(func0_pdev);
895
+ return has_mii;
896
+}
897
+
898
+/**
899
+ * ixgbe_mii_bus_init - mii_bus structure setup
900
+ * @hw: pointer to hardware structure
901
+ *
902
+ * Returns 0 on success, negative on failure
903
+ *
904
+ * ixgbe_mii_bus_init initializes a mii_bus structure in adapter
905
+ **/
906
+s32 ixgbe_mii_bus_init(struct ixgbe_hw *hw)
907
+{
908
+ s32 (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
909
+ s32 (*read)(struct mii_bus *bus, int addr, int regnum);
910
+ struct ixgbe_adapter *adapter = hw->back;
911
+ struct pci_dev *pdev = adapter->pdev;
912
+ struct device *dev = &adapter->netdev->dev;
913
+ struct mii_bus *bus;
914
+
915
+ switch (hw->device_id) {
916
+ /* C3000 SoCs */
917
+ case IXGBE_DEV_ID_X550EM_A_KR:
918
+ case IXGBE_DEV_ID_X550EM_A_KR_L:
919
+ case IXGBE_DEV_ID_X550EM_A_SFP_N:
920
+ case IXGBE_DEV_ID_X550EM_A_SGMII:
921
+ case IXGBE_DEV_ID_X550EM_A_SGMII_L:
922
+ case IXGBE_DEV_ID_X550EM_A_10G_T:
923
+ case IXGBE_DEV_ID_X550EM_A_SFP:
924
+ case IXGBE_DEV_ID_X550EM_A_1G_T:
925
+ case IXGBE_DEV_ID_X550EM_A_1G_T_L:
926
+ if (!ixgbe_x550em_a_has_mii(hw))
927
+ return 0;
928
+ read = &ixgbe_x550em_a_mii_bus_read;
929
+ write = &ixgbe_x550em_a_mii_bus_write;
930
+ break;
931
+ default:
932
+ read = &ixgbe_mii_bus_read;
933
+ write = &ixgbe_mii_bus_write;
934
+ break;
935
+ }
936
+
937
+ bus = devm_mdiobus_alloc(dev);
938
+ if (!bus)
939
+ return -ENOMEM;
940
+
941
+ bus->read = read;
942
+ bus->write = write;
943
+
944
+ /* Use the position of the device in the PCI hierarchy as the id */
945
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mdio-%s", ixgbe_driver_name,
946
+ pci_name(pdev));
947
+
948
+ bus->name = "ixgbe-mdio";
949
+ bus->priv = adapter;
950
+ bus->parent = dev;
951
+ bus->phy_mask = GENMASK(31, 0);
952
+
953
+ /* Support clause 22/45 natively. ixgbe_probe() sets MDIO_EMULATE_C22
954
+ * unfortunately that causes some clause 22 frames to be sent with
955
+ * clause 45 addressing. We don't want that.
956
+ */
957
+ hw->phy.mdio.mode_support = MDIO_SUPPORTS_C45 | MDIO_SUPPORTS_C22;
958
+
959
+ adapter->mii_bus = bus;
960
+ return mdiobus_register(bus);
961
+}
962
+
661963 /**
662964 * ixgbe_setup_phy_link_generic - Set and restart autoneg
663965 * @hw: pointer to hardware structure