summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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.
Additional required and optional properties can be found in dsa.txt.
Required properties:
-- compatible : Should be one of "marvell,mv88e6085",
+- compatible : Should be one of "marvell,mv88e6085" or
+ "marvell,mv88e6190"
- reg : Address on the MII bus for the switch.
Optional 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,
netdev_err(ds->ports[port].netdev, "failed to configure MAC\n");
}
-static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip)
+static int mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
{
- u16 val;
- int i, err;
-
- for (i = 0; i < 10; i++) {
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_OP, &val);
- if ((val & GLOBAL_STATS_OP_BUSY) == 0)
- return 0;
- }
-
- return -ETIMEDOUT;
-}
-
-static int _mv88e6xxx_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
-{
- int err;
-
- if (mv88e6xxx_6320_family(chip) || mv88e6xxx_6352_family(chip))
- port = (port + 1) << 5;
-
- /* Snapshot the hardware statistics counters for this port. */
- err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_CAPTURE_PORT |
- GLOBAL_STATS_OP_HIST_RX_TX | port);
- if (err)
- return err;
-
- /* Wait for the snapshotting to complete. */
- return _mv88e6xxx_stats_wait(chip);
-}
-
-static void _mv88e6xxx_stats_read(struct mv88e6xxx_chip *chip,
- int stat, u32 *val)
-{
- u32 value;
- u16 reg;
- int err;
-
- *val = 0;
-
- err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
- GLOBAL_STATS_OP_READ_CAPTURED |
- GLOBAL_STATS_OP_HIST_RX_TX | stat);
- if (err)
- return;
-
- err = _mv88e6xxx_stats_wait(chip);
- if (err)
- return;
-
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
- if (err)
- return;
-
- value = reg << 16;
-
- err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
- if (err)
- return;
+ if (!chip->info->ops->stats_snapshot)
+ return -EOPNOTSUPP;
- *val = value | reg;
+ return chip->info->ops->stats_snapshot(chip, port);
}
static struct mv88e6xxx_hw_stat mv88e6xxx_hw_stats[] = {
- { "in_good_octets", 8, 0x00, BANK0, },
- { "in_bad_octets", 4, 0x02, BANK0, },
- { "in_unicast", 4, 0x04, BANK0, },
- { "in_broadcasts", 4, 0x06, BANK0, },
- { "in_multicasts", 4, 0x07, BANK0, },
- { "in_pause", 4, 0x16, BANK0, },
- { "in_undersize", 4, 0x18, BANK0, },
- { "in_fragments", 4, 0x19, BANK0, },
- { "in_oversize", 4, 0x1a, BANK0, },
- { "in_jabber", 4, 0x1b, BANK0, },
- { "in_rx_error", 4, 0x1c, BANK0, },
- { "in_fcs_error", 4, 0x1d, BANK0, },
- { "out_octets", 8, 0x0e, BANK0, },
- { "out_unicast", 4, 0x10, BANK0, },
- { "out_broadcasts", 4, 0x13, BANK0, },
- { "out_multicasts", 4, 0x12, BANK0, },
- { "out_pause", 4, 0x15, BANK0, },
- { "excessive", 4, 0x11, BANK0, },
- { "collisions", 4, 0x1e, BANK0, },
- { "deferred", 4, 0x05, BANK0, },
- { "single", 4, 0x14, BANK0, },
- { "multiple", 4, 0x17, BANK0, },
- { "out_fcs_error", 4, 0x03, BANK0, },
- { "late", 4, 0x1f, BANK0, },
- { "hist_64bytes", 4, 0x08, BANK0, },
- { "hist_65_127bytes", 4, 0x09, BANK0, },
- { "hist_128_255bytes", 4, 0x0a, BANK0, },
- { "hist_256_511bytes", 4, 0x0b, BANK0, },
- { "hist_512_1023bytes", 4, 0x0c, BANK0, },
- { "hist_1024_max_bytes", 4, 0x0d, BANK0, },
- { "sw_in_discards", 4, 0x10, PORT, },
- { "sw_in_filtered", 2, 0x12, PORT, },
- { "sw_out_filtered", 2, 0x13, PORT, },
- { "in_discards", 4, 0x00 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_filtered", 4, 0x01 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_accepted", 4, 0x02 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_accepted", 4, 0x03 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_a", 4, 0x04 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_good_avb_class_b", 4, 0x05 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_a", 4, 0x06 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_bad_avb_class_b", 4, 0x07 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_0", 4, 0x08 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_1", 4, 0x09 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_2", 4, 0x0a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "tcam_counter_3", 4, 0x0b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_da_unknown", 4, 0x0e | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "in_management", 4, 0x0f | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_0", 4, 0x10 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_1", 4, 0x11 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_2", 4, 0x12 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_3", 4, 0x13 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_4", 4, 0x14 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_5", 4, 0x15 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_6", 4, 0x16 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_queue_7", 4, 0x17 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_cut_through", 4, 0x18 | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_a", 4, 0x1a | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_octets_b", 4, 0x1b | GLOBAL_STATS_OP_BANK_1, BANK1, },
- { "out_management", 4, 0x1f | GLOBAL_STATS_OP_BANK_1, BANK1, },
+ { "in_good_octets", 8, 0x00, STATS_TYPE_BANK0, },
+ { "in_bad_octets", 4, 0x02, STATS_TYPE_BANK0, },
+ { "in_unicast", 4, 0x04, STATS_TYPE_BANK0, },
+ { "in_broadcasts", 4, 0x06, STATS_TYPE_BANK0, },
+ { "in_multicasts", 4, 0x07, STATS_TYPE_BANK0, },
+ { "in_pause", 4, 0x16, STATS_TYPE_BANK0, },
+ { "in_undersize", 4, 0x18, STATS_TYPE_BANK0, },
+ { "in_fragments", 4, 0x19, STATS_TYPE_BANK0, },
+ { "in_oversize", 4, 0x1a, STATS_TYPE_BANK0, },
+ { "in_jabber", 4, 0x1b, STATS_TYPE_BANK0, },
+ { "in_rx_error", 4, 0x1c, STATS_TYPE_BANK0, },
+ { "in_fcs_error", 4, 0x1d, STATS_TYPE_BANK0, },
+ { "out_octets", 8, 0x0e, STATS_TYPE_BANK0, },
+ { "out_unicast", 4, 0x10, STATS_TYPE_BANK0, },
+ { "out_broadcasts", 4, 0x13, STATS_TYPE_BANK0, },
+ { "out_multicasts", 4, 0x12, STATS_TYPE_BANK0, },
+ { "out_pause", 4, 0x15, STATS_TYPE_BANK0, },
+ { "excessive", 4, 0x11, STATS_TYPE_BANK0, },
+ { "collisions", 4, 0x1e, STATS_TYPE_BANK0, },
+ { "deferred", 4, 0x05, STATS_TYPE_BANK0, },
+ { "single", 4, 0x14, STATS_TYPE_BANK0, },
+ { "multiple", 4, 0x17, STATS_TYPE_BANK0, },
+ { "out_fcs_error", 4, 0x03, STATS_TYPE_BANK0, },
+ { "late", 4, 0x1f, STATS_TYPE_BANK0, },
+ { "hist_64bytes", 4, 0x08, STATS_TYPE_BANK0, },
+ { "hist_65_127bytes", 4, 0x09, STATS_TYPE_BANK0, },
+ { "hist_128_255bytes", 4, 0x0a, STATS_TYPE_BANK0, },
+ { "hist_256_511bytes", 4, 0x0b, STATS_TYPE_BANK0, },
+ { "hist_512_1023bytes", 4, 0x0c, STATS_TYPE_BANK0, },
+ { "hist_1024_max_bytes", 4, 0x0d, STATS_TYPE_BANK0, },
+ { "sw_in_discards", 4, 0x10, STATS_TYPE_PORT, },
+ { "sw_in_filtered", 2, 0x12, STATS_TYPE_PORT, },
+ { "sw_out_filtered", 2, 0x13, STATS_TYPE_PORT, },
+ { "in_discards", 4, 0x00, STATS_TYPE_BANK1, },
+ { "in_filtered", 4, 0x01, STATS_TYPE_BANK1, },
+ { "in_accepted", 4, 0x02, STATS_TYPE_BANK1, },
+ { "in_bad_accepted", 4, 0x03, STATS_TYPE_BANK1, },
+ { "in_good_avb_class_a", 4, 0x04, STATS_TYPE_BANK1, },
+ { "in_good_avb_class_b", 4, 0x05, STATS_TYPE_BANK1, },
+ { "in_bad_avb_class_a", 4, 0x06, STATS_TYPE_BANK1, },
+ { "in_bad_avb_class_b", 4, 0x07, STATS_TYPE_BANK1, },
+ { "tcam_counter_0", 4, 0x08, STATS_TYPE_BANK1, },
+ { "tcam_counter_1", 4, 0x09, STATS_TYPE_BANK1, },
+ { "tcam_counter_2", 4, 0x0a, STATS_TYPE_BANK1, },
+ { "tcam_counter_3", 4, 0x0b, STATS_TYPE_BANK1, },
+ { "in_da_unknown", 4, 0x0e, STATS_TYPE_BANK1, },
+ { "in_management", 4, 0x0f, STATS_TYPE_BANK1, },
+ { "out_queue_0", 4, 0x10, STATS_TYPE_BANK1, },
+ { "out_queue_1", 4, 0x11, STATS_TYPE_BANK1, },
+ { "out_queue_2", 4, 0x12, STATS_TYPE_BANK1, },
+ { "out_queue_3", 4, 0x13, STATS_TYPE_BANK1, },
+ { "out_queue_4", 4, 0x14, STATS_TYPE_BANK1, },
+ { "out_queue_5", 4, 0x15, STATS_TYPE_BANK1, },
+ { "out_queue_6", 4, 0x16, STATS_TYPE_BANK1, },
+ { "out_queue_7", 4, 0x17, STATS_TYPE_BANK1, },
+ { "out_cut_through", 4, 0x18, STATS_TYPE_BANK1, },
+ { "out_octets_a", 4, 0x1a, STATS_TYPE_BANK1, },
+ { "out_octets_b", 4, 0x1b, STATS_TYPE_BANK1, },
+ { "out_management", 4, 0x1f, STATS_TYPE_BANK1, },
};
-static bool mv88e6xxx_has_stat(struct mv88e6xxx_chip *chip,
- struct mv88e6xxx_hw_stat *stat)
-{
- switch (stat->type) {
- case BANK0:
- return true;
- case BANK1:
- return mv88e6xxx_6320_family(chip);
- case PORT:
- return mv88e6xxx_6095_family(chip) ||
- mv88e6xxx_6185_family(chip) ||
- mv88e6xxx_6097_family(chip) ||
- mv88e6xxx_6165_family(chip) ||
- mv88e6xxx_6351_family(chip) ||
- mv88e6xxx_6352_family(chip);
- }
- return false;
-}
-
static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
struct mv88e6xxx_hw_stat *s,
- int port)
+ int port, u16 bank1_select,
+ u16 histogram)
{
u32 low;
u32 high = 0;
+ u16 reg = 0;
int err;
- u16 reg;
u64 value;
switch (s->type) {
- case PORT:
+ case STATS_TYPE_PORT:
err = mv88e6xxx_port_read(chip, port, s->reg, &reg);
if (err)
return UINT64_MAX;
@@ -949,26 +875,28 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
high = reg;
}
break;
- case BANK0:
- case BANK1:
- _mv88e6xxx_stats_read(chip, s->reg, &low);
+ case STATS_TYPE_BANK1:
+ reg = bank1_select;
+ /* fall through */
+ case STATS_TYPE_BANK0:
+ reg |= s->reg | histogram;
+ mv88e6xxx_g1_stats_read(chip, reg, &low);
if (s->sizeof_stat == 8)
- _mv88e6xxx_stats_read(chip, s->reg + 1, &high);
+ mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
}
value = (((u64)high) << 16) | low;
return value;
}
-static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
- uint8_t *data)
+static void mv88e6xxx_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data, int types)
{
- struct mv88e6xxx_chip *chip = ds->priv;
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat)) {
+ if (stat->type & types) {
memcpy(data + j * ETH_GSTRING_LEN, stat->string,
ETH_GSTRING_LEN);
j++;
@@ -976,46 +904,142 @@ static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
}
}
-static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+static void mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
+{
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT);
+}
+
+static void mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
+ uint8_t *data)
+{
+ mv88e6xxx_stats_get_strings(chip, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1);
+}
+
+static void mv88e6xxx_get_strings(struct dsa_switch *ds, int port,
+ uint8_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (chip->info->ops->stats_get_strings)
+ chip->info->ops->stats_get_strings(chip, data);
+}
+
+static int mv88e6xxx_stats_get_sset_count(struct mv88e6xxx_chip *chip,
+ int types)
+{
struct mv88e6xxx_hw_stat *stat;
int i, j;
for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat))
+ if (stat->type & types)
j++;
}
return j;
}
+static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+ STATS_TYPE_PORT);
+}
+
+static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
+ STATS_TYPE_BANK1);
+}
+
+static int mv88e6xxx_get_sset_count(struct dsa_switch *ds)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+
+ if (chip->info->ops->stats_get_sset_count)
+ return chip->info->ops->stats_get_sset_count(chip);
+
+ return 0;
+}
+
+static void mv88e6xxx_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data, int types,
+ u16 bank1_select, u16 histogram)
+{
+ struct mv88e6xxx_hw_stat *stat;
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
+ stat = &mv88e6xxx_hw_stats[i];
+ if (stat->type & types) {
+ data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
+ bank1_select,
+ histogram);
+ j++;
+ }
+ }
+}
+
+static void mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_PORT,
+ 0, GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+ GLOBAL_STATS_OP_BANK_1_BIT_9,
+ GLOBAL_STATS_OP_HIST_RX_TX);
+}
+
+static void mv88e6390_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ return mv88e6xxx_stats_get_stats(chip, port, data,
+ STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
+ GLOBAL_STATS_OP_BANK_1_BIT_10, 0);
+}
+
+static void mv88e6xxx_get_stats(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data)
+{
+ if (chip->info->ops->stats_get_stats)
+ chip->info->ops->stats_get_stats(chip, port, data);
+}
+
static void mv88e6xxx_get_ethtool_stats(struct dsa_switch *ds, int port,
uint64_t *data)
{
struct mv88e6xxx_chip *chip = ds->priv;
- struct mv88e6xxx_hw_stat *stat;
int ret;
- int i, j;
mutex_lock(&chip->reg_lock);
- ret = _mv88e6xxx_stats_snapshot(chip, port);
+ ret = mv88e6xxx_stats_snapshot(chip, port);
if (ret < 0) {
mutex_unlock(&chip->reg_lock);
return;
}
- for (i = 0, j = 0; i < ARRAY_SIZE(mv88e6xxx_hw_stats); i++) {
- stat = &mv88e6xxx_hw_stats[i];
- if (mv88e6xxx_has_stat(chip, stat)) {
- data[j] = _mv88e6xxx_get_ethtool_stat(chip, stat, port);
- j++;
- }
- }
+
+ mv88e6xxx_get_stats(chip, port, data);
mutex_unlock(&chip->reg_lock);
}
+static int mv88e6xxx_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+ if (chip->info->ops->stats_set_histogram)
+ return chip->info->ops->stats_set_histogram(chip);
+
+ return 0;
+}
+
static int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port)
{
return 32 * sizeof(u16);
@@ -2804,6 +2828,11 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
if (err)
return err;
+ /* Initialize the statistics unit */
+ err = mv88e6xxx_stats_set_histogram(chip);
+ if (err)
+ return err;
+
/* Clear the statistics counters for all ports */
err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
GLOBAL_STATS_OP_FLUSH_ALL);
@@ -2811,7 +2840,7 @@ static int mv88e6xxx_g1_setup(struct mv88e6xxx_chip *chip)
return err;
/* Wait for the flush to complete. */
- err = _mv88e6xxx_stats_wait(chip);
+ err = mv88e6xxx_g1_stats_wait(chip);
if (err)
return err;
@@ -3153,60 +3182,91 @@ static int mv88e6xxx_set_eeprom(struct dsa_switch *ds,
}
static const struct mv88e6xxx_ops mv88e6085_ops = {
+ /* MV88E6XXX_FAMILY_6097 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6095_ops = {
+ /* MV88E6XXX_FAMILY_6095 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6123_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6131_ops = {
+ /* MV88E6XXX_FAMILY_6185 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6161_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6165_ops = {
+ /* MV88E6XXX_FAMILY_6165 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_read,
.phy_write = mv88e6xxx_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6171_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3214,9 +3274,14 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6172_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3226,9 +3291,14 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6352_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6175_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3236,9 +3306,14 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6176_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3248,18 +3323,76 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6352_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6185_ops = {
+ /* MV88E6XXX_FAMILY_6185 */
.set_switch_mac = mv88e6xxx_g1_set_switch_mac,
.phy_read = mv88e6xxx_phy_ppu_read,
.phy_write = mv88e6xxx_phy_ppu_write,
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6xxx_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6190_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6190x_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390x_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6191_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6240_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3269,9 +3402,30 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6352_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6290_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6320_ops = {
+ /* MV88E6XXX_FAMILY_6320 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3280,9 +3434,14 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6320_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6321_ops = {
+ /* MV88E6XXX_FAMILY_6321 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3291,9 +3450,14 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
.port_set_link = mv88e6xxx_port_set_link,
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6320_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6350_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3301,9 +3465,14 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6351_ops = {
+ /* MV88E6XXX_FAMILY_6351 */
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
.phy_read = mv88e6xxx_g2_smi_phy_read,
.phy_write = mv88e6xxx_g2_smi_phy_write,
@@ -3311,9 +3480,14 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6185_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
};
static const struct mv88e6xxx_ops mv88e6352_ops = {
+ /* MV88E6XXX_FAMILY_6352 */
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.set_switch_mac = mv88e6xxx_g2_set_switch_mac,
@@ -3323,6 +3497,58 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.port_set_duplex = mv88e6xxx_port_set_duplex,
.port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6352_port_set_speed,
+ .stats_snapshot = mv88e6320_g1_stats_snapshot,
+ .stats_get_sset_count = mv88e6095_stats_get_sset_count,
+ .stats_get_strings = mv88e6095_stats_get_strings,
+ .stats_get_stats = mv88e6095_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6390_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6390x_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390x_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
+};
+
+static const struct mv88e6xxx_ops mv88e6391_ops = {
+ /* MV88E6XXX_FAMILY_6390 */
+ .set_switch_mac = mv88e6xxx_g2_set_switch_mac,
+ .phy_read = mv88e6xxx_g2_smi_phy_read,
+ .phy_write = mv88e6xxx_g2_smi_phy_write,
+ .port_set_link = mv88e6xxx_port_set_link,
+ .port_set_duplex = mv88e6xxx_port_set_duplex,
+ .port_set_rgmii_delay = mv88e6390_port_set_rgmii_delay,
+ .port_set_speed = mv88e6390_port_set_speed,
+ .stats_snapshot = mv88e6390_g1_stats_snapshot,
+ .stats_set_histogram = mv88e6390_g1_stats_set_histogram,
+ .stats_get_sset_count = mv88e6320_stats_get_sset_count,
+ .stats_get_strings = mv88e6320_stats_get_strings,
+ .stats_get_stats = mv88e6390_stats_get_stats,
};
static const struct mv88e6xxx_info mv88e6xxx_table[] = {
@@ -3480,6 +3706,47 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6185_ops,
},
+ [MV88E6190] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6190,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6190",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6190_ops,
+ },
+
+ [MV88E6190X] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6190X,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6190X",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6190x_ops,
+ },
+
+ [MV88E6191] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6191,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6191",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6391_ops,
+ },
+
[MV88E6240] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6240,
.family = MV88E6XXX_FAMILY_6352,
@@ -3494,6 +3761,20 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6240_ops,
},
+ [MV88E6290] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6290,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6290",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6290_ops,
+ },
+
[MV88E6320] = {
.prod_num = PORT_SWITCH_ID_PROD_NUM_6320,
.family = MV88E6XXX_FAMILY_6320,
@@ -3563,6 +3844,32 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.flags = MV88E6XXX_FLAGS_FAMILY_6352,
.ops = &mv88e6352_ops,
},
+ [MV88E6390] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6390,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6390",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6390_ops,
+ },
+ [MV88E6390X] = {
+ .prod_num = PORT_SWITCH_ID_PROD_NUM_6390X,
+ .family = MV88E6XXX_FAMILY_6390,
+ .name = "Marvell 88E6390X",
+ .num_databases = 4096,
+ .num_ports = 11, /* 10 + Z80 */
+ .port_base_addr = 0x0,
+ .global1_addr = 0x1b,
+ .age_time_coeff = 15000,
+ .g1_irqs = 9,
+ .flags = MV88E6XXX_FLAGS_FAMILY_6390,
+ .ops = &mv88e6390x_ops,
+ },
};
static const struct mv88e6xxx_info *mv88e6xxx_lookup_info(unsigned int prod_num)
@@ -3855,16 +4162,16 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)
if (err)
return err;
+ chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(chip->reset))
+ return PTR_ERR(chip->reset);
+
err = mv88e6xxx_detect(chip);
if (err)
return err;
mv88e6xxx_phy_init(chip);
- chip->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_ASIS);
- if (IS_ERR(chip->reset))
- return PTR_ERR(chip->reset);
-
if (chip->info->ops->get_eeprom &&
!of_property_read_u32(np, "eeprom-length", &eeprom_len))
chip->eeprom_len = eeprom_len;
@@ -3946,6 +4253,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
.compatible = "marvell,mv88e6085",
.data = &mv88e6xxx_table[MV88E6085],
},
+ {
+ .compatible = "marvell,mv88e6190",
+ .data = &mv88e6xxx_table[MV88E6190],
+ },
{ /* sentinel */ },
};
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)
{
return mv88e6xxx_wait(chip, chip->info->global1_addr, reg, mask);
}
+
+/* Offset 0x1c: Global Control 2 */
+
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip)
+{
+ u16 val;
+ int err;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_CONTROL_2, &val);
+ if (err)
+ return err;
+
+ val |= GLOBAL_CONTROL_2_HIST_RX_TX;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_CONTROL_2, val);
+
+ return err;
+}
+
+/* Offset 0x1d: Statistics Operation 2 */
+
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip)
+{
+ return mv88e6xxx_g1_wait(chip, GLOBAL_STATS_OP, GLOBAL_STATS_OP_BUSY);
+}
+
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ /* Snapshot the hardware statistics counters for this port. */
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_CAPTURE_PORT |
+ GLOBAL_STATS_OP_HIST_RX_TX | port);
+ if (err)
+ return err;
+
+ /* Wait for the snapshotting to complete. */
+ return mv88e6xxx_g1_stats_wait(chip);
+}
+
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ port = (port + 1) << 5;
+
+ return mv88e6xxx_g1_stats_snapshot(chip, port);
+}
+
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port)
+{
+ int err;
+
+ port = (port + 1) << 5;
+
+ /* Snapshot the hardware statistics counters for this port. */
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_CAPTURE_PORT | port);
+ if (err)
+ return err;
+
+ /* Wait for the snapshotting to complete. */
+ return mv88e6xxx_g1_stats_wait(chip);
+}
+
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val)
+{
+ u32 value;
+ u16 reg;
+ int err;
+
+ *val = 0;
+
+ err = mv88e6xxx_g1_write(chip, GLOBAL_STATS_OP,
+ GLOBAL_STATS_OP_READ_CAPTURED | stat);
+ if (err)
+ return;
+
+ err = mv88e6xxx_g1_stats_wait(chip);
+ if (err)
+ return;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_32, &reg);
+ if (err)
+ return;
+
+ value = reg << 16;
+
+ err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, &reg);
+ if (err)
+ return;
+
+ *val = value | reg;
+}
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 @@
int mv88e6xxx_g1_read(struct mv88e6xxx_chip *chip, int reg, u16 *val);
int mv88e6xxx_g1_write(struct mv88e6xxx_chip *chip, int reg, u16 val);
int mv88e6xxx_g1_wait(struct mv88e6xxx_chip *chip, int reg, u16 mask);
+int mv88e6xxx_g1_stats_wait(struct mv88e6xxx_chip *chip);
+int mv88e6xxx_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6320_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_snapshot(struct mv88e6xxx_chip *chip, int port);
+int mv88e6390_g1_stats_set_histogram(struct mv88e6xxx_chip *chip);
+void mv88e6xxx_g1_stats_read(struct mv88e6xxx_chip *chip, int stat, u32 *val);
#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 @@
#define PORT_SWITCH_ID_PROD_NUM_6175 0x175
#define PORT_SWITCH_ID_PROD_NUM_6176 0x176
#define PORT_SWITCH_ID_PROD_NUM_6185 0x1a7
+#define PORT_SWITCH_ID_PROD_NUM_6190 0x190
+#define PORT_SWITCH_ID_PROD_NUM_6190X 0x0a0
+#define PORT_SWITCH_ID_PROD_NUM_6191 0x191
#define PORT_SWITCH_ID_PROD_NUM_6240 0x240
+#define PORT_SWITCH_ID_PROD_NUM_6290 0x290
#define PORT_SWITCH_ID_PROD_NUM_6321 0x310
#define PORT_SWITCH_ID_PROD_NUM_6352 0x352
#define PORT_SWITCH_ID_PROD_NUM_6350 0x371
#define PORT_SWITCH_ID_PROD_NUM_6351 0x375
+#define PORT_SWITCH_ID_PROD_NUM_6390 0x390
+#define PORT_SWITCH_ID_PROD_NUM_6390X 0x0a1
#define PORT_CONTROL 0x04
#define PORT_CONTROL_USE_CORE_TAG BIT(15)
#define PORT_CONTROL_DROP_ON_LOCK BIT(14)
@@ -277,7 +283,9 @@
#define GLOBAL_CONTROL_2 0x1c
#define GLOBAL_CONTROL_2_NO_CASCADE 0xe000
#define GLOBAL_CONTROL_2_MULTIPLE_CASCADE 0xf000
-
+#define GLOBAL_CONTROL_2_HIST_RX (0x1 << 6)
+#define GLOBAL_CONTROL_2_HIST_TX (0x2 << 6)
+#define GLOBAL_CONTROL_2_HIST_RX_TX (0x3 << 6)
#define GLOBAL_STATS_OP 0x1d
#define GLOBAL_STATS_OP_BUSY BIT(15)
#define GLOBAL_STATS_OP_NOP (0 << 12)
@@ -288,7 +296,8 @@
#define GLOBAL_STATS_OP_HIST_RX ((1 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_TX ((2 << 10) | GLOBAL_STATS_OP_BUSY)
#define GLOBAL_STATS_OP_HIST_RX_TX ((3 << 10) | GLOBAL_STATS_OP_BUSY)
-#define GLOBAL_STATS_OP_BANK_1 BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_9 BIT(9)
+#define GLOBAL_STATS_OP_BANK_1_BIT_10 BIT(10)
#define GLOBAL_STATS_COUNTER_32 0x1e
#define GLOBAL_STATS_COUNTER_01 0x1f
@@ -378,12 +387,18 @@ enum mv88e6xxx_model {
MV88E6175,
MV88E6176,
MV88E6185,
+ MV88E6190,
+ MV88E6190X,
+ MV88E6191,
MV88E6240,
+ MV88E6290,
MV88E6320,
MV88E6321,
MV88E6350,
MV88E6351,
MV88E6352,
+ MV88E6390,
+ MV88E6390X,
};
enum mv88e6xxx_family {
@@ -396,6 +411,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
MV88E6XXX_FAMILY_6352, /* 6172 6176 6240 6352 */
+ MV88E6XXX_FAMILY_6390, /* 6190 6190X 6191 6290 6390 6390X */
};
enum mv88e6xxx_cap {
@@ -615,6 +631,18 @@ enum mv88e6xxx_cap {
struct mv88e6xxx_ops;
+#define MV88E6XXX_FLAGS_FAMILY_6390 \
+ (MV88E6XXX_FLAG_EEE | \
+ MV88E6XXX_FLAG_GLOBAL2 | \
+ MV88E6XXX_FLAG_PPU_ACTIVE | \
+ MV88E6XXX_FLAG_STU | \
+ MV88E6XXX_FLAG_TEMP | \
+ MV88E6XXX_FLAG_TEMP_LIMIT | \
+ MV88E6XXX_FLAG_VTU | \
+ MV88E6XXX_FLAGS_IRL | \
+ MV88E6XXX_FLAGS_MULTI_CHIP | \
+ MV88E6XXX_FLAGS_PVT)
+
struct mv88e6xxx_info {
enum mv88e6xxx_family family;
u16 prod_num;
@@ -769,19 +797,33 @@ struct mv88e6xxx_ops {
* Use SPEED_UNFORCED for normal detection, SPEED_MAX for max value.
*/
int (*port_set_speed)(struct mv88e6xxx_chip *chip, int port, int speed);
-};
-enum stat_type {
- BANK0,
- BANK1,
- PORT,
+ /* Snapshot the statistics for a port. The statistics can then
+ * be read back a leisure but still with a consistent view.
+ */
+ int (*stats_snapshot)(struct mv88e6xxx_chip *chip, int port);
+
+ /* Set the histogram mode for statistics, when the control registers
+ * are separated out of the STATS_OP register.
+ */
+ int (*stats_set_histogram)(struct mv88e6xxx_chip *chip);
+
+ /* Return the number of strings describing statistics */
+ int (*stats_get_sset_count)(struct mv88e6xxx_chip *chip);
+ void (*stats_get_strings)(struct mv88e6xxx_chip *chip, uint8_t *data);
+ void (*stats_get_stats)(struct mv88e6xxx_chip *chip, int port,
+ uint64_t *data);
};
+#define STATS_TYPE_PORT BIT(0)
+#define STATS_TYPE_BANK0 BIT(1)
+#define STATS_TYPE_BANK1 BIT(2)
+
struct mv88e6xxx_hw_stat {
char string[ETH_GSTRING_LEN];
int sizeof_stat;
int reg;
- enum stat_type type;
+ int type;
};
static inline bool mv88e6xxx_has(struct mv88e6xxx_chip *chip,