aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2016-11-22 09:55:32 -0500
committerDavid S. Miller <davem@davemloft.net>2016-11-22 09:55:32 -0500
commit2903372695eb33568bc13a02b3e91da1fe6fe855 (patch)
treeb5733e0d5650b144544f620fd902280ef083fdd9
parente796f49d826aadb856981c751efc086c6ce11a77 (diff)
parent7f9ef3af397b2a10730e11fac8475f6509cbf603 (diff)
Merge branch 'mv88e6390-initial-support'
Andrew Lunn says: ==================== Start adding support for mv88e6390 This is the first patchset implementing support for the mv88e6390 family. This is a new generation of switch devices and has numerous incompatible changes to the registers. These patches allow the switch to the detected during probe, and makes the statistics unit work. These patches are insufficient to make the mv88e6390 functional. More patches will follow. v2: Move stats code into global1 Change DT compatible string to mv88e6190 Fixed mv88e6351 stats which v1 had broken ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/devicetree/bindings/net/dsa/marvell.txt3
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c643
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.c93
-rw-r--r--drivers/net/dsa/mv88e6xxx/global1.h6
-rw-r--r--drivers/net/dsa/mv88e6xxx/mv88e6xxx.h58
5 files changed, 628 insertions, 175 deletions
diff --git a/Documentation/devicetree/bindings/net/dsa/marvell.txt b/Documentation/devicetree/bindings/net/dsa/marvell.txt
index 32025eb4b31b..b3dd6b40e0de 100644
--- a/Documentation/devicetree/bindings/net/dsa/marvell.txt
+++ b/Documentation/devicetree/bindings/net/dsa/marvell.txt
@@ -14,7 +14,8 @@ The properties described here are those specific to Marvell devices.
14Additional required and optional properties can be found in dsa.txt. 14Additional required and optional properties can be found in dsa.txt.
15 15
16Required properties: 16Required properties:
17- compatible : Should be one of "marvell,mv88e6085", 17- compatible : Should be one of "marvell,mv88e6085" or
18 "marvell,mv88e6190"
18- reg : Address on the MII bus for the switch. 19- reg : Address on the MII bus for the switch.
19 20
20Optional properties: 21Optional properties:
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index e30d0eaf2b5f..bada6465af59 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -780,163 +780,89 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port,
780 netdev_err(ds->ports[port].netdev, "failed to configure MAC\n"); 780 netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
781} 781}
782 782
783static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip) 783static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
784{ 784{
785 u16 val; 785 if (!chip->info->ops->stats_snapshot)
786 int i, err; 786 return -EOPNOTSUPP;
787
788 for (i = 0; i < 10; i++) {
789 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_OP, &val);
790 if ((val & GLOBAL_STATS_OP_BUSY) == 0)
791 return 0;
792 }
793
794 return -ETIMEDOUT;
795}
796
797static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
798{
799 int err;
800
801 if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
802 port = (port + 1) << 5;
803
804 /* Snapshot the hardware statistics counters for this port. */
805 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
806 GLOBAL_STATS_OP_CAPTURE_PORT |
807 GLOBAL_STATS_OP_HIST_RX_TX | port);
808 if (err)
809 return err;
810
811 /* Wait for the snapshotting to complete. */
812 return _mv88e6xxx_stats_wait(chip);
813}
814
815static void _mv88e6xxx_stats_read(struct mv88e6xxx_chip *chip,
816 int stat, u32 *val)
817{
818 u32 value;
819 u16 reg;
820 int err;
821
822 *val = 0;
823
824 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
825 GLOBAL_STATS_OP_READ_CAPTURED |
826 GLOBAL_STATS_OP_HIST_RX_TX | stat);
827 if (err)
828 return;
829
830 err = _mv88e6xxx_stats_wait(chip);
831 if (err)
832 return;
833
834 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
835 if (err)
836 return;
837
838 value = reg << 16;
839
840 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
841 if (err)
842 return;
843 787
844 *val = value | reg; 788 return chip->info->ops->stats_snapshot(chip, port);
845} 789}
846 790
847static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = { 791static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
848 { "in_good_octets", 8, 0x00, BANK0, }, 792 { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
849 { "in_bad_octets", 4, 0x02, BANK0, }, 793 { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
850 { "in_unicast", 4, 0x04, BANK0, }, 794 { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
851 { "in_broadcasts", 4, 0x06, BANK0, }, 795 { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
852 { "in_multicasts", 4, 0x07, BANK0, }, 796 { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
853 { "in_pause", 4, 0x16, BANK0, }, 797 { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
854 { "in_undersize", 4, 0x18, BANK0, }, 798 { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
855 { "in_fragments", 4, 0x19, BANK0, }, 799 { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
856 { "in_oversize", 4, 0x1a, BANK0, }, 800 { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
857 { "in_jabber", 4, 0x1b, BANK0, }, 801 { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
858 { "in_rx_error", 4, 0x1c, BANK0, }, 802 { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
859 { "in_fcs_error", 4, 0x1d, BANK0, }, 803 { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
860 { "out_octets", 8, 0x0e, BANK0, }, 804 { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
861 { "out_unicast", 4, 0x10, BANK0, }, 805 { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
862 { "out_broadcasts", 4, 0x13, BANK0, }, 806 { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
863 { "out_multicasts", 4, 0x12, BANK0, }, 807 { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
864 { "out_pause", 4, 0x15, BANK0, }, 808 { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
865 { "excessive", 4, 0x11, BANK0, }, 809 { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
866 { "collisions", 4, 0x1e, BANK0, }, 810 { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
867 { "deferred", 4, 0x05, BANK0, }, 811 { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
868 { "single", 4, 0x14, BANK0, }, 812 { "single", 4, 0x14, STATS_TYPE_BANK0, },
869 { "multiple", 4, 0x17, BANK0, }, 813 { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
870 { "out_fcs_error", 4, 0x03, BANK0, }, 814 { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
871 { "late", 4, 0x1f, BANK0, }, 815 { "late", 4, 0x1f, STATS_TYPE_BANK0, },
872 { "hist_64bytes", 4, 0x08, BANK0, }, 816 { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
873 { "hist_65_127bytes", 4, 0x09, BANK0, }, 817 { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
874 { "hist_128_255bytes", 4, 0x0a, BANK0, }, 818 { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
875 { "hist_256_511bytes", 4, 0x0b, BANK0, }, 819 { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
876 { "hist_512_1023bytes", 4, 0x0c, BANK0, }, 820 { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
877 { "hist_1024_max_bytes", 4, 0x0d, BANK0, }, 821 { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
878 { "sw_in_discards", 4, 0x10, PORT, }, 822 { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
879 { "sw_in_filtered", 2, 0x12, PORT, }, 823 { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
880 { "sw_out_filtered", 2, 0x13, PORT, }, 824 { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
881 { "in_discards", 4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 825 { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
882 { "in_filtered", 4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 826 { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
883 { "in_accepted", 4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 827 { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
884 { "in_bad_accepted", 4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 828 { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
885 { "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 829 { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
886 { "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 830 { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
887 { "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 831 { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
888 { "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 832 { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
889 { "tcam_counter_0", 4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 833 { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
890 { "tcam_counter_1", 4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 834 { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
891 { "tcam_counter_2", 4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, }, 835 { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
892 { "tcam_counter_3", 4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, }, 836 { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
893 { "in_da_unknown", 4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, }, 837 { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
894 { "in_management", 4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, }, 838 { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
895 { "out_queue_0", 4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 839 { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
896 { "out_queue_1", 4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 840 { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
897 { "out_queue_2", 4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 841 { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
898 { "out_queue_3", 4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 842 { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
899 { "out_queue_4", 4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 843 { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
900 { "out_queue_5", 4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 844 { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
901 { "out_queue_6", 4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 845 { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
902 { "out_queue_7", 4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 846 { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
903 { "out_cut_through", 4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, }, 847 { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
904 { "out_octets_a", 4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, }, 848 { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
905 { "out_octets_b", 4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, }, 849 { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
906 { "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, }, 850 { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
907}; 851};
908 852
909static bool mv88e6xxx_has_stat(struct mv88e6xxx_chip *chip,
910 struct mv88e6xxx_hw_stat *stat)
911{
912 switch (stat->type) {
913 case BANK0:
914 return true;
915 case BANK1:
916 return mv88e6xxx_6320_family(chip);
917 case PORT:
918 return mv88e6xxx_6095_family(chip) ||
919 mv88e6xxx_6185_family(chip) ||
920 mv88e6xxx_6097_family(chip) ||
921 mv88e6xxx_6165_family(chip) ||
922 mv88e6xxx_6351_family(chip) ||
923 mv88e6xxx_6352_family(chip);
924 }
925 return false;
926}
927
928static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip, 853static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
929 struct mv88e6xxx_hw_stat *s, 854 struct mv88e6xxx_hw_stat *s,
930 int port) 855 int port, u16 bank1_select,
856 u16 histogram)
931{ 857{
932 u32 low; 858 u32 low;
933 u32 high = 0; 859 u32 high = 0;
860 u16 reg = 0;
934 int err; 861 int err;
935 u16 reg;
936 u64 value; 862 u64 value;
937 863
938 switch (s->type) { 864 switch (s->type) {
939 case PORT: 865 case STATS_TYPE_PORT:
940 err = mv88e6xxx_port_read(chip, port, s->reg, &reg); 866 err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
941 if (err) 867 if (err)
942 return UINT64_MAX; 868 return UINT64_MAX;
@@ -949,26 +875,28 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
949 high = reg; 875 high = reg;
950 } 876 }
951 break; 877 break;
952 case BANK0: 878 case STATS_TYPE_BANK1:
953 case BANK1: 879 reg = bank1_select;
954 _mv88e6xxx_stats_read(chip, s->reg, &low); 880 /* fall through */
881 case STATS_TYPE_BANK0:
882 reg |= s->reg | histogram;
883 mv88e6xxx_g1_stats_read(chip, reg, &low);
955 if (s->sizeof_stat == 8) 884 if (s->sizeof_stat == 8)
956 _mv88e6xxx_stats_read(chip, s->reg + 1, &high); 885 mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
957 } 886 }
958 value = (((u64)high) << 16) | low; 887 value = (((u64)high) << 16) | low;
959 return value; 888 return value;
960} 889}
961 890
962static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port, 891static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
963 uint8_t *data) 892 uint8_t *data, int types)
964{ 893{
965 struct mv88e6xxx_chip *chip = ds->priv;
966 struct mv88e6xxx_hw_stat *stat; 894 struct mv88e6xxx_hw_stat *stat;
967 int i, j; 895 int i, j;
968 896
969 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 897 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
970 stat = &mv88e6xxx_hw_stats[i]; 898 stat = &mv88e6xxx_hw_stats[i];
971 if (mv88e6xxx_has_stat(chip, stat)) { 899 if (stat->type & types) {
972 memcpy(data + j * ETH_GSTRING_LEN, stat->string, 900 memcpy(data + j * ETH_GSTRING_LEN, stat->string,
973 ETH_GSTRING_LEN); 901 ETH_GSTRING_LEN);
974 j++; 902 j++;
@@ -976,46 +904,142 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
976 } 904 }
977} 905}
978 906
979static int mv88e6xxx_get_sset_count(struct dsa_switch *ds) 907static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
908 uint8_t *data)
909{
910 mv88e6xxx_stats_get_strings(chip, data,
911 STATS_TYPE_BANK0 | STATS_TYPE_PORT);
912}
913
914static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
915 uint8_t *data)
916{
917 mv88e6xxx_stats_get_strings(chip, data,
918 STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
919}
920
921static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
922 uint8_t *data)
980{ 923{
981 struct mv88e6xxx_chip *chip = ds->priv; 924 struct mv88e6xxx_chip *chip = ds->priv;
925
926 if (chip->info->ops->stats_get_strings)
927 chip->info->ops->stats_get_strings(chip, data);
928}
929
930static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
931 int types)
932{
982 struct mv88e6xxx_hw_stat *stat; 933 struct mv88e6xxx_hw_stat *stat;
983 int i, j; 934 int i, j;
984 935
985 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 936 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
986 stat = &mv88e6xxx_hw_stats[i]; 937 stat = &mv88e6xxx_hw_stats[i];
987 if (mv88e6xxx_has_stat(chip, stat)) 938 if (stat->type & types)
988 j++; 939 j++;
989 } 940 }
990 return j; 941 return j;
991} 942}
992 943
944static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
945{
946 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
947 STATS_TYPE_PORT);
948}
949
950static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
951{
952 return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
953 STATS_TYPE_BANK1);
954}
955
956static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
957{
958 struct mv88e6xxx_chip *chip = ds->priv;
959
960 if (chip->info->ops->stats_get_sset_count)
961 return chip->info->ops->stats_get_sset_count(chip);
962
963 return 0;
964}
965
966static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
967 uint64_t *data, int types,
968 u16 bank1_select, u16 histogram)
969{
970 struct mv88e6xxx_hw_stat *stat;
971 int i, j;
972
973 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
974 stat = &mv88e6xxx_hw_stats[i];
975 if (stat->type & types) {
976 data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
977 bank1_select,
978 histogram);
979 j++;
980 }
981 }
982}
983
984static void mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
985 uint64_t *data)
986{
987 return mv88e6xxx_stats_get_stats(chip, port, data,
988 STATS_TYPE_BANK0 | STATS_TYPE_PORT,
989 0, GLOBAL_STATS_OP_HIST_RX_TX);
990}
991
992static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
993 uint64_t *data)
994{
995 return mv88e6xxx_stats_get_stats(chip, port, data,
996 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
997 GLOBAL_STATS_OP_BANK_1_BIT_9,
998 GLOBAL_STATS_OP_HIST_RX_TX);
999}
1000
1001static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
1002 uint64_t *data)
1003{
1004 return mv88e6xxx_stats_get_stats(chip, port, data,
1005 STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
1006 GLOBAL_STATS_OP_BANK_1_BIT_10, 0);
1007}
1008
1009static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
1010 uint64_t *data)
1011{
1012 if (chip->info->ops->stats_get_stats)
1013 chip->info->ops->stats_get_stats(chip, port, data);
1014}
1015
993static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port, 1016static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
994 uint64_t *data) 1017 uint64_t *data)
995{ 1018{
996 struct mv88e6xxx_chip *chip = ds->priv; 1019 struct mv88e6xxx_chip *chip = ds->priv;
997 struct mv88e6xxx_hw_stat *stat;
998 int ret; 1020 int ret;
999 int i, j;
1000 1021
1001 mutex_lock(&chip->reg_lock); 1022 mutex_lock(&chip->reg_lock);
1002 1023
1003 ret = _mv88e6xxx_stats_snapshot(chip, port); 1024 ret = mv88e6xxx_stats_snapshot(chip, port);
1004 if (ret < 0) { 1025 if (ret < 0) {
1005 mutex_unlock(&chip->reg_lock); 1026 mutex_unlock(&chip->reg_lock);
1006 return; 1027 return;
1007 } 1028 }
1008 for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) { 1029
1009 stat = &mv88e6xxx_hw_stats[i]; 1030 mv88e6xxx_get_stats(chip, port, data);
1010 if (mv88e6xxx_has_stat(chip, stat)) {
1011 data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port);
1012 j++;
1013 }
1014 }
1015 1031
1016 mutex_unlock(&chip->reg_lock); 1032 mutex_unlock(&chip->reg_lock);
1017} 1033}
1018 1034
1035static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
1036{
1037 if (chip->info->ops->stats_set_histogram)
1038 return chip->info->ops->stats_set_histogram(chip);
1039
1040 return 0;
1041}
1042
1019static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port) 1043static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
1020{ 1044{
1021 return 32 * sizeof(u16); 1045 return 32 * sizeof(u16);
@@ -2804,6 +2828,11 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
2804 if (err) 2828 if (err)
2805 return err; 2829 return err;
2806 2830
2831 /* Initialize the statistics unit */
2832 err = mv88e6xxx_stats_set_histogram(chip);
2833 if (err)
2834 return err;
2835
2807 /* Clear the statistics counters for all ports */ 2836 /* Clear the statistics counters for all ports */
2808 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP, 2837 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
2809 GLOBAL_STATS_OP_FLUSH_ALL); 2838 GLOBAL_STATS_OP_FLUSH_ALL);
@@ -2811,7 +2840,7 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
2811 return err; 2840 return err;
2812 2841
2813 /* Wait for the flush to complete. */ 2842 /* Wait for the flush to complete. */
2814 err = _mv88e6xxx_stats_wait(chip); 2843 err = mv88e6xxx_g1_stats_wait(chip);
2815 if (err) 2844 if (err)
2816 return err; 2845 return err;
2817 2846
@@ -3153,60 +3182,91 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
3153} 3182}
3154 3183
3155static const struct mv88e6xxx_ops mv88e6085_ops = { 3184static const struct mv88e6xxx_ops mv88e6085_ops = {
3185 /* MV88E6XXX_FAMILY_6097 */
3156 .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 3186 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3157 .phy_read = mv88e6xxx_phy_ppu_read, 3187 .phy_read = mv88e6xxx_phy_ppu_read,
3158 .phy_write = mv88e6xxx_phy_ppu_write, 3188 .phy_write = mv88e6xxx_phy_ppu_write,
3159 .port_set_link = mv88e6xxx_port_set_link, 3189 .port_set_link = mv88e6xxx_port_set_link,
3160 .port_set_duplex = mv88e6xxx_port_set_duplex, 3190 .port_set_duplex = mv88e6xxx_port_set_duplex,
3161 .port_set_speed = mv88e6185_port_set_speed, 3191 .port_set_speed = mv88e6185_port_set_speed,
3192 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3193 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3194 .stats_get_strings = mv88e6095_stats_get_strings,
3195 .stats_get_stats = mv88e6095_stats_get_stats,
3162}; 3196};
3163 3197
3164static const struct mv88e6xxx_ops mv88e6095_ops = { 3198static const struct mv88e6xxx_ops mv88e6095_ops = {
3199 /* MV88E6XXX_FAMILY_6095 */
3165 .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 3200 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3166 .phy_read = mv88e6xxx_phy_ppu_read, 3201 .phy_read = mv88e6xxx_phy_ppu_read,
3167 .phy_write = mv88e6xxx_phy_ppu_write, 3202 .phy_write = mv88e6xxx_phy_ppu_write,
3168 .port_set_link = mv88e6xxx_port_set_link, 3203 .port_set_link = mv88e6xxx_port_set_link,
3169 .port_set_duplex = mv88e6xxx_port_set_duplex, 3204 .port_set_duplex = mv88e6xxx_port_set_duplex,
3170 .port_set_speed = mv88e6185_port_set_speed, 3205 .port_set_speed = mv88e6185_port_set_speed,
3206 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3207 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3208 .stats_get_strings = mv88e6095_stats_get_strings,
3209 .stats_get_stats = mv88e6095_stats_get_stats,
3171}; 3210};
3172 3211
3173static const struct mv88e6xxx_ops mv88e6123_ops = { 3212static const struct mv88e6xxx_ops mv88e6123_ops = {
3213 /* MV88E6XXX_FAMILY_6165 */
3174 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3214 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3175 .phy_read = mv88e6xxx_read, 3215 .phy_read = mv88e6xxx_read,
3176 .phy_write = mv88e6xxx_write, 3216 .phy_write = mv88e6xxx_write,
3177 .port_set_link = mv88e6xxx_port_set_link, 3217 .port_set_link = mv88e6xxx_port_set_link,
3178 .port_set_duplex = mv88e6xxx_port_set_duplex, 3218 .port_set_duplex = mv88e6xxx_port_set_duplex,
3179 .port_set_speed = mv88e6185_port_set_speed, 3219 .port_set_speed = mv88e6185_port_set_speed,
3220 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3221 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3222 .stats_get_strings = mv88e6095_stats_get_strings,
3223 .stats_get_stats = mv88e6095_stats_get_stats,
3180}; 3224};
3181 3225
3182static const struct mv88e6xxx_ops mv88e6131_ops = { 3226static const struct mv88e6xxx_ops mv88e6131_ops = {
3227 /* MV88E6XXX_FAMILY_6185 */
3183 .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 3228 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3184 .phy_read = mv88e6xxx_phy_ppu_read, 3229 .phy_read = mv88e6xxx_phy_ppu_read,
3185 .phy_write = mv88e6xxx_phy_ppu_write, 3230 .phy_write = mv88e6xxx_phy_ppu_write,
3186 .port_set_link = mv88e6xxx_port_set_link, 3231 .port_set_link = mv88e6xxx_port_set_link,
3187 .port_set_duplex = mv88e6xxx_port_set_duplex, 3232 .port_set_duplex = mv88e6xxx_port_set_duplex,
3188 .port_set_speed = mv88e6185_port_set_speed, 3233 .port_set_speed = mv88e6185_port_set_speed,
3234 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3235 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3236 .stats_get_strings = mv88e6095_stats_get_strings,
3237 .stats_get_stats = mv88e6095_stats_get_stats,
3189}; 3238};
3190 3239
3191static const struct mv88e6xxx_ops mv88e6161_ops = { 3240static const struct mv88e6xxx_ops mv88e6161_ops = {
3241 /* MV88E6XXX_FAMILY_6165 */
3192 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3242 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3193 .phy_read = mv88e6xxx_read, 3243 .phy_read = mv88e6xxx_read,
3194 .phy_write = mv88e6xxx_write, 3244 .phy_write = mv88e6xxx_write,
3195 .port_set_link = mv88e6xxx_port_set_link, 3245 .port_set_link = mv88e6xxx_port_set_link,
3196 .port_set_duplex = mv88e6xxx_port_set_duplex, 3246 .port_set_duplex = mv88e6xxx_port_set_duplex,
3197 .port_set_speed = mv88e6185_port_set_speed, 3247 .port_set_speed = mv88e6185_port_set_speed,
3248 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3249 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3250 .stats_get_strings = mv88e6095_stats_get_strings,
3251 .stats_get_stats = mv88e6095_stats_get_stats,
3198}; 3252};
3199 3253
3200static const struct mv88e6xxx_ops mv88e6165_ops = { 3254static const struct mv88e6xxx_ops mv88e6165_ops = {
3255 /* MV88E6XXX_FAMILY_6165 */
3201 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3256 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3202 .phy_read = mv88e6xxx_read, 3257 .phy_read = mv88e6xxx_read,
3203 .phy_write = mv88e6xxx_write, 3258 .phy_write = mv88e6xxx_write,
3204 .port_set_link = mv88e6xxx_port_set_link, 3259 .port_set_link = mv88e6xxx_port_set_link,
3205 .port_set_duplex = mv88e6xxx_port_set_duplex, 3260 .port_set_duplex = mv88e6xxx_port_set_duplex,
3206 .port_set_speed = mv88e6185_port_set_speed, 3261 .port_set_speed = mv88e6185_port_set_speed,
3262 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3263 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3264 .stats_get_strings = mv88e6095_stats_get_strings,
3265 .stats_get_stats = mv88e6095_stats_get_stats,
3207}; 3266};
3208 3267
3209static const struct mv88e6xxx_ops mv88e6171_ops = { 3268static const struct mv88e6xxx_ops mv88e6171_ops = {
3269 /* MV88E6XXX_FAMILY_6351 */
3210 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3270 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3211 .phy_read = mv88e6xxx_g2_smi_phy_read, 3271 .phy_read = mv88e6xxx_g2_smi_phy_read,
3212 .phy_write = mv88e6xxx_g2_smi_phy_write, 3272 .phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3214,9 +3274,14 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
3214 .port_set_duplex = mv88e6xxx_port_set_duplex, 3274 .port_set_duplex = mv88e6xxx_port_set_duplex,
3215 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3275 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3216 .port_set_speed = mv88e6185_port_set_speed, 3276 .port_set_speed = mv88e6185_port_set_speed,
3277 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3278 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3279 .stats_get_strings = mv88e6095_stats_get_strings,
3280 .stats_get_stats = mv88e6095_stats_get_stats,
3217}; 3281};
3218 3282
3219static const struct mv88e6xxx_ops mv88e6172_ops = { 3283static const struct mv88e6xxx_ops mv88e6172_ops = {
3284 /* MV88E6XXX_FAMILY_6352 */
3220 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3285 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3221 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3286 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3222 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3287 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3226,9 +3291,14 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
3226 .port_set_duplex = mv88e6xxx_port_set_duplex, 3291 .port_set_duplex = mv88e6xxx_port_set_duplex,
3227 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3292 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3228 .port_set_speed = mv88e6352_port_set_speed, 3293 .port_set_speed = mv88e6352_port_set_speed,
3294 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3295 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3296 .stats_get_strings = mv88e6095_stats_get_strings,
3297 .stats_get_stats = mv88e6095_stats_get_stats,
3229}; 3298};
3230 3299
3231static const struct mv88e6xxx_ops mv88e6175_ops = { 3300static const struct mv88e6xxx_ops mv88e6175_ops = {
3301 /* MV88E6XXX_FAMILY_6351 */
3232 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3302 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3233 .phy_read = mv88e6xxx_g2_smi_phy_read, 3303 .phy_read = mv88e6xxx_g2_smi_phy_read,
3234 .phy_write = mv88e6xxx_g2_smi_phy_write, 3304 .phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3236,9 +3306,14 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
3236 .port_set_duplex = mv88e6xxx_port_set_duplex, 3306 .port_set_duplex = mv88e6xxx_port_set_duplex,
3237 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3307 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3238 .port_set_speed = mv88e6185_port_set_speed, 3308 .port_set_speed = mv88e6185_port_set_speed,
3309 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3310 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3311 .stats_get_strings = mv88e6095_stats_get_strings,
3312 .stats_get_stats = mv88e6095_stats_get_stats,
3239}; 3313};
3240 3314
3241static const struct mv88e6xxx_ops mv88e6176_ops = { 3315static const struct mv88e6xxx_ops mv88e6176_ops = {
3316 /* MV88E6XXX_FAMILY_6352 */
3242 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3317 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3243 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3318 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3244 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3319 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3248,18 +3323,76 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
3248 .port_set_duplex = mv88e6xxx_port_set_duplex, 3323 .port_set_duplex = mv88e6xxx_port_set_duplex,
3249 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3324 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3250 .port_set_speed = mv88e6352_port_set_speed, 3325 .port_set_speed = mv88e6352_port_set_speed,
3326 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3327 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3328 .stats_get_strings = mv88e6095_stats_get_strings,
3329 .stats_get_stats = mv88e6095_stats_get_stats,
3251}; 3330};
3252 3331
3253static const struct mv88e6xxx_ops mv88e6185_ops = { 3332static const struct mv88e6xxx_ops mv88e6185_ops = {
3333 /* MV88E6XXX_FAMILY_6185 */
3254 .set_switch_mac = mv88e6xxx_g1_set_switch_mac, 3334 .set_switch_mac = mv88e6xxx_g1_set_switch_mac,
3255 .phy_read = mv88e6xxx_phy_ppu_read, 3335 .phy_read = mv88e6xxx_phy_ppu_read,
3256 .phy_write = mv88e6xxx_phy_ppu_write, 3336 .phy_write = mv88e6xxx_phy_ppu_write,
3257 .port_set_link = mv88e6xxx_port_set_link, 3337 .port_set_link = mv88e6xxx_port_set_link,
3258 .port_set_duplex = mv88e6xxx_port_set_duplex, 3338 .port_set_duplex = mv88e6xxx_port_set_duplex,
3259 .port_set_speed = mv88e6185_port_set_speed, 3339 .port_set_speed = mv88e6185_port_set_speed,
3340 .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
3341 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3342 .stats_get_strings = mv88e6095_stats_get_strings,
3343 .stats_get_stats = mv88e6095_stats_get_stats,
3344};
3345
3346static const struct mv88e6xxx_ops mv88e6190_ops = {
3347 /* MV88E6XXX_FAMILY_6390 */
3348 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3349 .phy_read = mv88e6xxx_g2_smi_phy_read,
3350 .phy_write = mv88e6xxx_g2_smi_phy_write,
3351 .port_set_link = mv88e6xxx_port_set_link,
3352 .port_set_duplex = mv88e6xxx_port_set_duplex,
3353 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3354 .port_set_speed = mv88e6390_port_set_speed,
3355 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3356 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3357 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3358 .stats_get_strings = mv88e6320_stats_get_strings,
3359 .stats_get_stats = mv88e6390_stats_get_stats,
3360};
3361
3362static const struct mv88e6xxx_ops mv88e6190x_ops = {
3363 /* MV88E6XXX_FAMILY_6390 */
3364 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3365 .phy_read = mv88e6xxx_g2_smi_phy_read,
3366 .phy_write = mv88e6xxx_g2_smi_phy_write,
3367 .port_set_link = mv88e6xxx_port_set_link,
3368 .port_set_duplex = mv88e6xxx_port_set_duplex,
3369 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3370 .port_set_speed = mv88e6390x_port_set_speed,
3371 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3372 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3373 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3374 .stats_get_strings = mv88e6320_stats_get_strings,
3375 .stats_get_stats = mv88e6390_stats_get_stats,
3376};
3377
3378static const struct mv88e6xxx_ops mv88e6191_ops = {
3379 /* MV88E6XXX_FAMILY_6390 */
3380 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3381 .phy_read = mv88e6xxx_g2_smi_phy_read,
3382 .phy_write = mv88e6xxx_g2_smi_phy_write,
3383 .port_set_link = mv88e6xxx_port_set_link,
3384 .port_set_duplex = mv88e6xxx_port_set_duplex,
3385 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3386 .port_set_speed = mv88e6390_port_set_speed,
3387 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3388 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3389 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3390 .stats_get_strings = mv88e6320_stats_get_strings,
3391 .stats_get_stats = mv88e6390_stats_get_stats,
3260}; 3392};
3261 3393
3262static const struct mv88e6xxx_ops mv88e6240_ops = { 3394static const struct mv88e6xxx_ops mv88e6240_ops = {
3395 /* MV88E6XXX_FAMILY_6352 */
3263 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3396 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3264 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3397 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3265 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3398 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3269,9 +3402,30 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
3269 .port_set_duplex = mv88e6xxx_port_set_duplex, 3402 .port_set_duplex = mv88e6xxx_port_set_duplex,
3270 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3403 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3271 .port_set_speed = mv88e6352_port_set_speed, 3404 .port_set_speed = mv88e6352_port_set_speed,
3405 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3406 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3407 .stats_get_strings = mv88e6095_stats_get_strings,
3408 .stats_get_stats = mv88e6095_stats_get_stats,
3409};
3410
3411static const struct mv88e6xxx_ops mv88e6290_ops = {
3412 /* MV88E6XXX_FAMILY_6390 */
3413 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3414 .phy_read = mv88e6xxx_g2_smi_phy_read,
3415 .phy_write = mv88e6xxx_g2_smi_phy_write,
3416 .port_set_link = mv88e6xxx_port_set_link,
3417 .port_set_duplex = mv88e6xxx_port_set_duplex,
3418 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3419 .port_set_speed = mv88e6390_port_set_speed,
3420 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3421 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3422 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3423 .stats_get_strings = mv88e6320_stats_get_strings,
3424 .stats_get_stats = mv88e6390_stats_get_stats,
3272}; 3425};
3273 3426
3274static const struct mv88e6xxx_ops mv88e6320_ops = { 3427static const struct mv88e6xxx_ops mv88e6320_ops = {
3428 /* MV88E6XXX_FAMILY_6320 */
3275 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3429 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3276 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3430 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3277 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3431 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3280,9 +3434,14 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
3280 .port_set_link = mv88e6xxx_port_set_link, 3434 .port_set_link = mv88e6xxx_port_set_link,
3281 .port_set_duplex = mv88e6xxx_port_set_duplex, 3435 .port_set_duplex = mv88e6xxx_port_set_duplex,
3282 .port_set_speed = mv88e6185_port_set_speed, 3436 .port_set_speed = mv88e6185_port_set_speed,
3437 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3438 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3439 .stats_get_strings = mv88e6320_stats_get_strings,
3440 .stats_get_stats = mv88e6320_stats_get_stats,
3283}; 3441};
3284 3442
3285static const struct mv88e6xxx_ops mv88e6321_ops = { 3443static const struct mv88e6xxx_ops mv88e6321_ops = {
3444 /* MV88E6XXX_FAMILY_6321 */
3286 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3445 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3287 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3446 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3288 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3447 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3291,9 +3450,14 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
3291 .port_set_link = mv88e6xxx_port_set_link, 3450 .port_set_link = mv88e6xxx_port_set_link,
3292 .port_set_duplex = mv88e6xxx_port_set_duplex, 3451 .port_set_duplex = mv88e6xxx_port_set_duplex,
3293 .port_set_speed = mv88e6185_port_set_speed, 3452 .port_set_speed = mv88e6185_port_set_speed,
3453 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3454 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3455 .stats_get_strings = mv88e6320_stats_get_strings,
3456 .stats_get_stats = mv88e6320_stats_get_stats,
3294}; 3457};
3295 3458
3296static const struct mv88e6xxx_ops mv88e6350_ops = { 3459static const struct mv88e6xxx_ops mv88e6350_ops = {
3460 /* MV88E6XXX_FAMILY_6351 */
3297 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3461 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3298 .phy_read = mv88e6xxx_g2_smi_phy_read, 3462 .phy_read = mv88e6xxx_g2_smi_phy_read,
3299 .phy_write = mv88e6xxx_g2_smi_phy_write, 3463 .phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3301,9 +3465,14 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
3301 .port_set_duplex = mv88e6xxx_port_set_duplex, 3465 .port_set_duplex = mv88e6xxx_port_set_duplex,
3302 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3466 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3303 .port_set_speed = mv88e6185_port_set_speed, 3467 .port_set_speed = mv88e6185_port_set_speed,
3468 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3469 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3470 .stats_get_strings = mv88e6095_stats_get_strings,
3471 .stats_get_stats = mv88e6095_stats_get_stats,
3304}; 3472};
3305 3473
3306static const struct mv88e6xxx_ops mv88e6351_ops = { 3474static const struct mv88e6xxx_ops mv88e6351_ops = {
3475 /* MV88E6XXX_FAMILY_6351 */
3307 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3476 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3308 .phy_read = mv88e6xxx_g2_smi_phy_read, 3477 .phy_read = mv88e6xxx_g2_smi_phy_read,
3309 .phy_write = mv88e6xxx_g2_smi_phy_write, 3478 .phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3311,9 +3480,14 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
3311 .port_set_duplex = mv88e6xxx_port_set_duplex, 3480 .port_set_duplex = mv88e6xxx_port_set_duplex,
3312 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3481 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3313 .port_set_speed = mv88e6185_port_set_speed, 3482 .port_set_speed = mv88e6185_port_set_speed,
3483 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3484 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3485 .stats_get_strings = mv88e6095_stats_get_strings,
3486 .stats_get_stats = mv88e6095_stats_get_stats,
3314}; 3487};
3315 3488
3316static const struct mv88e6xxx_ops mv88e6352_ops = { 3489static const struct mv88e6xxx_ops mv88e6352_ops = {
3490 /* MV88E6XXX_FAMILY_6352 */
3317 .get_eeprom = mv88e6xxx_g2_get_eeprom16, 3491 .get_eeprom = mv88e6xxx_g2_get_eeprom16,
3318 .set_eeprom = mv88e6xxx_g2_set_eeprom16, 3492 .set_eeprom = mv88e6xxx_g2_set_eeprom16,
3319 .set_switch_mac = mv88e6xxx_g2_set_switch_mac, 3493 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3323,6 +3497,58 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
3323 .port_set_duplex = mv88e6xxx_port_set_duplex, 3497 .port_set_duplex = mv88e6xxx_port_set_duplex,
3324 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, 3498 .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
3325 .port_set_speed = mv88e6352_port_set_speed, 3499 .port_set_speed = mv88e6352_port_set_speed,
3500 .stats_snapshot = mv88e6320_g1_stats_snapshot,
3501 .stats_get_sset_count = mv88e6095_stats_get_sset_count,
3502 .stats_get_strings = mv88e6095_stats_get_strings,
3503 .stats_get_stats = mv88e6095_stats_get_stats,
3504};
3505
3506static const struct mv88e6xxx_ops mv88e6390_ops = {
3507 /* MV88E6XXX_FAMILY_6390 */
3508 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3509 .phy_read = mv88e6xxx_g2_smi_phy_read,
3510 .phy_write = mv88e6xxx_g2_smi_phy_write,
3511 .port_set_link = mv88e6xxx_port_set_link,
3512 .port_set_duplex = mv88e6xxx_port_set_duplex,
3513 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3514 .port_set_speed = mv88e6390_port_set_speed,
3515 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3516 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3517 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3518 .stats_get_strings = mv88e6320_stats_get_strings,
3519 .stats_get_stats = mv88e6390_stats_get_stats,
3520};
3521
3522static const struct mv88e6xxx_ops mv88e6390x_ops = {
3523 /* MV88E6XXX_FAMILY_6390 */
3524 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3525 .phy_read = mv88e6xxx_g2_smi_phy_read,
3526 .phy_write = mv88e6xxx_g2_smi_phy_write,
3527 .port_set_link = mv88e6xxx_port_set_link,
3528 .port_set_duplex = mv88e6xxx_port_set_duplex,
3529 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3530 .port_set_speed = mv88e6390x_port_set_speed,
3531 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3532 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3533 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3534 .stats_get_strings = mv88e6320_stats_get_strings,
3535 .stats_get_stats = mv88e6390_stats_get_stats,
3536};
3537
3538static const struct mv88e6xxx_ops mv88e6391_ops = {
3539 /* MV88E6XXX_FAMILY_6390 */
3540 .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
3541 .phy_read = mv88e6xxx_g2_smi_phy_read,
3542 .phy_write = mv88e6xxx_g2_smi_phy_write,
3543 .port_set_link = mv88e6xxx_port_set_link,
3544 .port_set_duplex = mv88e6xxx_port_set_duplex,
3545 .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
3546 .port_set_speed = mv88e6390_port_set_speed,
3547 .stats_snapshot = mv88e6390_g1_stats_snapshot,
3548 .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
3549 .stats_get_sset_count = mv88e6320_stats_get_sset_count,
3550 .stats_get_strings = mv88e6320_stats_get_strings,
3551 .stats_get_stats = mv88e6390_stats_get_stats,
3326}; 3552};
3327 3553
3328static const struct mv88e6xxx_info mv88e6xxx_table[] = { 3554static const struct mv88e6xxx_info mv88e6xxx_table[] = {
@@ -3480,6 +3706,47 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3480 .ops = &mv88e6185_ops, 3706 .ops = &mv88e6185_ops,
3481 }, 3707 },
3482 3708
3709 [MV88E6190] = {
3710 .prod_num = PORT_SWITCH_ID_PROD_NUM_6190,
3711 .family = MV88E6XXX_FAMILY_6390,
3712 .name = "Marvell 88E6190",
3713 .num_databases = 4096,
3714 .num_ports = 11, /* 10 + Z80 */
3715 .port_base_addr = 0x0,
3716 .global1_addr = 0x1b,
3717 .age_time_coeff = 15000,
3718 .g1_irqs = 9,
3719 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3720 .ops = &mv88e6190_ops,
3721 },
3722
3723 [MV88E6190X] = {
3724 .prod_num = PORT_SWITCH_ID_PROD_NUM_6190X,
3725 .family = MV88E6XXX_FAMILY_6390,
3726 .name = "Marvell 88E6190X",
3727 .num_databases = 4096,
3728 .num_ports = 11, /* 10 + Z80 */
3729 .port_base_addr = 0x0,
3730 .global1_addr = 0x1b,
3731 .age_time_coeff = 15000,
3732 .g1_irqs = 9,
3733 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3734 .ops = &mv88e6190x_ops,
3735 },
3736
3737 [MV88E6191] = {
3738 .prod_num = PORT_SWITCH_ID_PROD_NUM_6191,
3739 .family = MV88E6XXX_FAMILY_6390,
3740 .name = "Marvell 88E6191",
3741 .num_databases = 4096,
3742 .num_ports = 11, /* 10 + Z80 */
3743 .port_base_addr = 0x0,
3744 .global1_addr = 0x1b,
3745 .age_time_coeff = 15000,
3746 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3747 .ops = &mv88e6391_ops,
3748 },
3749
3483 [MV88E6240] = { 3750 [MV88E6240] = {
3484 .prod_num = PORT_SWITCH_ID_PROD_NUM_6240, 3751 .prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
3485 .family = MV88E6XXX_FAMILY_6352, 3752 .family = MV88E6XXX_FAMILY_6352,
@@ -3494,6 +3761,20 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3494 .ops = &mv88e6240_ops, 3761 .ops = &mv88e6240_ops,
3495 }, 3762 },
3496 3763
3764 [MV88E6290] = {
3765 .prod_num = PORT_SWITCH_ID_PROD_NUM_6290,
3766 .family = MV88E6XXX_FAMILY_6390,
3767 .name = "Marvell 88E6290",
3768 .num_databases = 4096,
3769 .num_ports = 11, /* 10 + Z80 */
3770 .port_base_addr = 0x0,
3771 .global1_addr = 0x1b,
3772 .age_time_coeff = 15000,
3773 .g1_irqs = 9,
3774 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3775 .ops = &mv88e6290_ops,
3776 },
3777
3497 [MV88E6320] = { 3778 [MV88E6320] = {
3498 .prod_num = PORT_SWITCH_ID_PROD_NUM_6320, 3779 .prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
3499 .family = MV88E6XXX_FAMILY_6320, 3780 .family = MV88E6XXX_FAMILY_6320,
@@ -3563,6 +3844,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
3563 .flags = MV88E6XXX_FLAGS_FAMILY_6352, 3844 .flags = MV88E6XXX_FLAGS_FAMILY_6352,
3564 .ops = &mv88e6352_ops, 3845 .ops = &mv88e6352_ops,
3565 }, 3846 },
3847 [MV88E6390] = {
3848 .prod_num = PORT_SWITCH_ID_PROD_NUM_6390,
3849 .family = MV88E6XXX_FAMILY_6390,
3850 .name = "Marvell 88E6390",
3851 .num_databases = 4096,
3852 .num_ports = 11, /* 10 + Z80 */
3853 .port_base_addr = 0x0,
3854 .global1_addr = 0x1b,
3855 .age_time_coeff = 15000,
3856 .g1_irqs = 9,
3857 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3858 .ops = &mv88e6390_ops,
3859 },
3860 [MV88E6390X] = {
3861 .prod_num = PORT_SWITCH_ID_PROD_NUM_6390X,
3862 .family = MV88E6XXX_FAMILY_6390,
3863 .name = "Marvell 88E6390X",
3864 .num_databases = 4096,
3865 .num_ports = 11, /* 10 + Z80 */
3866 .port_base_addr = 0x0,
3867 .global1_addr = 0x1b,
3868 .age_time_coeff = 15000,
3869 .g1_irqs = 9,
3870 .flags = MV88E6XXX_FLAGS_FAMILY_6390,
3871 .ops = &mv88e6390x_ops,
3872 },
3566}; 3873};
3567 3874
3568static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num) 3875static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
@@ -3855,16 +4162,16 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
3855 if (err) 4162 if (err)
3856 return err; 4163 return err;
3857 4164
4165 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
4166 if (IS_ERR(chip->reset))
4167 return PTR_ERR(chip->reset);
4168
3858 err = mv88e6xxx_detect(chip); 4169 err = mv88e6xxx_detect(chip);
3859 if (err) 4170 if (err)
3860 return err; 4171 return err;
3861 4172
3862 mv88e6xxx_phy_init(chip); 4173 mv88e6xxx_phy_init(chip);
3863 4174
3864 chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
3865 if (IS_ERR(chip->reset))
3866 return PTR_ERR(chip->reset);
3867
3868 if (chip->info->ops->get_eeprom && 4175 if (chip->info->ops->get_eeprom &&
3869 !of_property_read_u32(np, "eeprom-length", &eeprom_len)) 4176 !of_property_read_u32(np, "eeprom-length", &eeprom_len))
3870 chip->eeprom_len = eeprom_len; 4177 chip->eeprom_len = eeprom_len;
@@ -3946,6 +4253,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
3946 .compatible = "marvell,mv88e6085", 4253 .compatible = "marvell,mv88e6085",
3947 .data = &mv88e6xxx_table[MV88E6085], 4254 .data = &mv88e6xxx_table[MV88E6085],
3948 }, 4255 },
4256 {
4257 .compatible = "marvell,mv88e6190",
4258 .data = &mv88e6xxx_table[MV88E6190],
4259 },
3949 { /* sentinel */ }, 4260 { /* sentinel */ },
3950}; 4261};
3951 4262
diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c
index d358720b6c2d..5fcf23dbf04b 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.c
+++ b/drivers/net/dsa/mv88e6xxx/global1.c
@@ -32,3 +32,96 @@ int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask)
32{ 32{
33 return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask); 33 return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
34} 34}
35
36/* Offset 0x1c: Global Control 2 */
37
38int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
39{
40 u16 val;
41 int err;
42
43 err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
44 if (err)
45 return err;
46
47 val |= GLOBAL_CONTROL_2_HIST_RX_TX;
48
49 err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
50
51 return err;
52}
53
54/* Offset 0x1d: Statistics Operation 2 */
55
56int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
57{
58 return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
59}
60
61int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
62{
63 int err;
64
65 /* Snapshot the hardware statistics counters for this port. */
66 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
67 GLOBAL_STATS_OP_CAPTURE_PORT |
68 GLOBAL_STATS_OP_HIST_RX_TX | port);
69 if (err)
70 return err;
71
72 /* Wait for the snapshotting to complete. */
73 return mv88e6xxx_g1_stats_wait(chip);
74}
75
76int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
77{
78 port = (port + 1) << 5;
79
80 return mv88e6xxx_g1_stats_snapshot(chip, port);
81}
82
83int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
84{
85 int err;
86
87 port = (port + 1) << 5;
88
89 /* Snapshot the hardware statistics counters for this port. */
90 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
91 GLOBAL_STATS_OP_CAPTURE_PORT | port);
92 if (err)
93 return err;
94
95 /* Wait for the snapshotting to complete. */
96 return mv88e6xxx_g1_stats_wait(chip);
97}
98
99void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
100{
101 u32 value;
102 u16 reg;
103 int err;
104
105 *val = 0;
106
107 err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
108 GLOBAL_STATS_OP_READ_CAPTURED | stat);
109 if (err)
110 return;
111
112 err = mv88e6xxx_g1_stats_wait(chip);
113 if (err)
114 return;
115
116 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
117 if (err)
118 return;
119
120 value = reg << 16;
121
122 err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
123 if (err)
124 return;
125
126 *val = value | reg;
127}
diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h
index 62291e6fe3a3..df3794cdbfb9 100644
--- a/drivers/net/dsa/mv88e6xxx/global1.h
+++ b/drivers/net/dsa/mv88e6xxx/global1.h
@@ -19,5 +19,11 @@
19int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val); 19int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
20int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val); 20int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
21int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask); 21int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
22int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip);
23int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
24int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
25int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
26int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip);
27void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val);
22 28
23#endif /* _MV88E6XXX_GLOBAL1_H */ 29#endif /* _MV88E6XXX_GLOBAL1_H */
diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
index a3869504f881..9298faa5878b 100644
--- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
+++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h
@@ -91,11 +91,17 @@
91#define PORT_SWITCH_ID_PROD_NUM_6175 0x175 91#define PORT_SWITCH_ID_PROD_NUM_6175 0x175
92#define PORT_SWITCH_ID_PROD_NUM_6176 0x176 92#define PORT_SWITCH_ID_PROD_NUM_6176 0x176
93#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7 93#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7
94#define PORT_SWITCH_ID_PROD_NUM_6190 0x190
95#define PORT_SWITCH_ID_PROD_NUM_6190X 0x0a0
96#define PORT_SWITCH_ID_PROD_NUM_6191 0x191
94#define PORT_SWITCH_ID_PROD_NUM_6240 0x240 97#define PORT_SWITCH_ID_PROD_NUM_6240 0x240
98#define PORT_SWITCH_ID_PROD_NUM_6290 0x290
95#define PORT_SWITCH_ID_PROD_NUM_6321 0x310 99#define PORT_SWITCH_ID_PROD_NUM_6321 0x310
96#define PORT_SWITCH_ID_PROD_NUM_6352 0x352 100#define PORT_SWITCH_ID_PROD_NUM_6352 0x352
97#define PORT_SWITCH_ID_PROD_NUM_6350 0x371 101#define PORT_SWITCH_ID_PROD_NUM_6350 0x371
98#define PORT_SWITCH_ID_PROD_NUM_6351 0x375 102#define PORT_SWITCH_ID_PROD_NUM_6351 0x375
103#define PORT_SWITCH_ID_PROD_NUM_6390 0x390
104#define PORT_SWITCH_ID_PROD_NUM_6390X 0x0a1
99#define PORT_CONTROL 0x04 105#define PORT_CONTROL 0x04
100#define PORT_CONTROL_USE_CORE_TAG BIT(15) 106#define PORT_CONTROL_USE_CORE_TAG BIT(15)
101#define PORT_CONTROL_DROP_ON_LOCK BIT(14) 107#define PORT_CONTROL_DROP_ON_LOCK BIT(14)
@@ -277,7 +283,9 @@
277#define GLOBAL_CONTROL_2 0x1c 283#define GLOBAL_CONTROL_2 0x1c
278#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000 284#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000
279#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000 285#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000
280 286#define GLOBAL_CONTROL_2_HIST_RX (0x1 << 6)
287#define GLOBAL_CONTROL_2_HIST_TX (0x2 << 6)
288#define GLOBAL_CONTROL_2_HIST_RX_TX (0x3 << 6)
281#define GLOBAL_STATS_OP 0x1d 289#define GLOBAL_STATS_OP 0x1d
282#define GLOBAL_STATS_OP_BUSY BIT(15) 290#define GLOBAL_STATS_OP_BUSY BIT(15)
283#define GLOBAL_STATS_OP_NOP (0 << 12) 291#define GLOBAL_STATS_OP_NOP (0 << 12)
@@ -288,7 +296,8 @@
288#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY) 296#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY)
289#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY) 297#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY)
290#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY) 298#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY)
291#define GLOBAL_STATS_OP_BANK_1 BIT(9) 299#define GLOBAL_STATS_OP_BANK_1_BIT_9 BIT(9)
300#define GLOBAL_STATS_OP_BANK_1_BIT_10 BIT(10)
292#define GLOBAL_STATS_COUNTER_32 0x1e 301#define GLOBAL_STATS_COUNTER_32 0x1e
293#define GLOBAL_STATS_COUNTER_01 0x1f 302#define GLOBAL_STATS_COUNTER_01 0x1f
294 303
@@ -378,12 +387,18 @@ enum mv88e6xxx_model {
378 MV88E6175, 387 MV88E6175,
379 MV88E6176, 388 MV88E6176,
380 MV88E6185, 389 MV88E6185,
390 MV88E6190,
391 MV88E6190X,
392 MV88E6191,
381 MV88E6240, 393 MV88E6240,
394 MV88E6290,
382 MV88E6320, 395 MV88E6320,
383 MV88E6321, 396 MV88E6321,
384 MV88E6350, 397 MV88E6350,
385 MV88E6351, 398 MV88E6351,
386 MV88E6352, 399 MV88E6352,
400 MV88E6390,
401 MV88E6390X,
387}; 402};
388 403
389enum mv88e6xxx_family { 404enum mv88e6xxx_family {
@@ -396,6 +411,7 @@ enum mv88e6xxx_family {
396 MV88E6XXX_FAMILY_6320, /* 6320 6321 */ 411 MV88E6XXX_FAMILY_6320, /* 6320 6321 */
397 MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ 412 MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
398 MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */ 413 MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
414 MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
399}; 415};
400 416
401enum mv88e6xxx_cap { 417enum mv88e6xxx_cap {
@@ -615,6 +631,18 @@ enum mv88e6xxx_cap {
615 631
616struct mv88e6xxx_ops; 632struct mv88e6xxx_ops;
617 633
634#define MV88E6XXX_FLAGS_FAMILY_6390 \
635 (MV88E6XXX_FLAG_EEE | \
636 MV88E6XXX_FLAG_GLOBAL2 | \
637 MV88E6XXX_FLAG_PPU_ACTIVE | \
638 MV88E6XXX_FLAG_STU | \
639 MV88E6XXX_FLAG_TEMP | \
640 MV88E6XXX_FLAG_TEMP_LIMIT | \
641 MV88E6XXX_FLAG_VTU | \
642 MV88E6XXX_FLAGS_IRL | \
643 MV88E6XXX_FLAGS_MULTI_CHIP | \
644 MV88E6XXX_FLAGS_PVT)
645
618struct mv88e6xxx_info { 646struct mv88e6xxx_info {
619 enum mv88e6xxx_family family; 647 enum mv88e6xxx_family family;
620 u16 prod_num; 648 u16 prod_num;
@@ -769,19 +797,33 @@ struct mv88e6xxx_ops {
769 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value. 797 * Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
770 */ 798 */
771 int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed); 799 int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
772};
773 800
774enum stat_type { 801 /* Snapshot the statistics for a port. The statistics can then
775 BANK0, 802 * be read back a leisure but still with a consistent view.
776 BANK1, 803 */
777 PORT, 804 int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
805
806 /* Set the histogram mode for statistics, when the control registers
807 * are separated out of the STATS_OP register.
808 */
809 int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
810
811 /* Return the number of strings describing statistics */
812 int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
813 void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
814 void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
815 uint64_t *data);
778}; 816};
779 817
818#define STATS_TYPE_PORT BIT(0)
819#define STATS_TYPE_BANK0 BIT(1)
820#define STATS_TYPE_BANK1 BIT(2)
821
780struct mv88e6xxx_hw_stat { 822struct mv88e6xxx_hw_stat {
781 char string[ETH_GSTRING_LEN]; 823 char string[ETH_GSTRING_LEN];
782 int sizeof_stat; 824 int sizeof_stat;
783 int reg; 825 int reg;
784 enum stat_type type; 826 int type;
785}; 827};
786 828
787static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip, 829static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip,