|
|
|
@ -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;
|
|
|
|
|
if (!chip->info->ops->stats_snapshot)
|
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
|
|
|
|
|
|
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, ®);
|
|
|
|
|
if (err)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
value = reg << 16;
|
|
|
|
|
|
|
|
|
|
err = mv88e6xxx_g1_read(chip, GLOBAL_STATS_COUNTER_01, ®);
|
|
|
|
|
if (err)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
*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, ®);
|
|
|
|
|
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 */ },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|