Commit 1f71836f authored by Rasmus Villemoes's avatar Rasmus Villemoes Committed by David S. Miller

net: dsa: mv88e6xxx: add support for mv88e6250

This adds support for the Marvell 88E6250. I've checked that each
member in the ops-structure makes sense, and basic switchdev
functionality works fine.

It uses the new dual_chip option, and since its port registers start
at SMI address 0x08 or 0x18 (i.e., always sw_addr + 0x08), we need to
introduce a new compatible string in order for the auto-identification
in mv88e6xxx_detect() to work.

The chip has four per port 16-bits statistics registers, two of which
correspond to the existing "sw_in_filtered" and "sw_out_filtered" (but
at offsets 0x13 and 0x10 rather than 0x12 and 0x13, because why should
this be easy...). Wiring up those four statistics seems to require
introducing a STATS_TYPE_PORT_6250 bit or similar, which seems a tad
ugly, so for now this just allows access to the STATS_TYPE_BANK0 ones.

The chip does have ptp support, and the existing
mv88e6352_{gpio,avb,ptp}_ops at first glance seem like they would work
out-of-the-box, but for simplicity (and lack of testing) I'm eliding
this.
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarRasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ce91c453
...@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip, ...@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
STATS_TYPE_BANK0 | STATS_TYPE_PORT); STATS_TYPE_BANK0 | STATS_TYPE_PORT);
} }
static int mv88e6250_stats_get_strings(struct mv88e6xxx_chip *chip,
uint8_t *data)
{
return mv88e6xxx_stats_get_strings(chip, data, STATS_TYPE_BANK0);
}
static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip, static int mv88e6320_stats_get_strings(struct mv88e6xxx_chip *chip,
uint8_t *data) uint8_t *data)
{ {
...@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip) ...@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
STATS_TYPE_PORT); STATS_TYPE_PORT);
} }
static int mv88e6250_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{
return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0);
}
static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip) static int mv88e6320_stats_get_sset_count(struct mv88e6xxx_chip *chip)
{ {
return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 | return mv88e6xxx_stats_get_sset_count(chip, STATS_TYPE_BANK0 |
...@@ -966,6 +977,13 @@ static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port, ...@@ -966,6 +977,13 @@ static int mv88e6095_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX); 0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
} }
static int mv88e6250_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data)
{
return mv88e6xxx_stats_get_stats(chip, port, data, STATS_TYPE_BANK0,
0, MV88E6XXX_G1_STATS_OP_HIST_RX_TX);
}
static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port, static int mv88e6320_stats_get_stats(struct mv88e6xxx_chip *chip, int port,
uint64_t *data) uint64_t *data)
{ {
...@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { ...@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.phylink_validate = mv88e6352_phylink_validate, .phylink_validate = mv88e6352_phylink_validate,
}; };
static const struct mv88e6xxx_ops mv88e6250_ops = {
/* MV88E6XXX_FAMILY_6250 */
.ieee_pri_map = mv88e6250_g1_ieee_pri_map,
.ip_pri_map = mv88e6085_g1_ip_pri_map,
.irl_init_all = mv88e6352_g2_irl_init_all,
.get_eeprom = mv88e6xxx_g2_get_eeprom16,
.set_eeprom = mv88e6xxx_g2_set_eeprom16,
.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 = mv88e6352_port_set_rgmii_delay,
.port_set_speed = mv88e6250_port_set_speed,
.port_tag_remap = mv88e6095_port_tag_remap,
.port_set_frame_mode = mv88e6351_port_set_frame_mode,
.port_set_egress_floods = mv88e6352_port_set_egress_floods,
.port_set_ether_type = mv88e6351_port_set_ether_type,
.port_egress_rate_limiting = mv88e6097_port_egress_rate_limiting,
.port_pause_limit = mv88e6097_port_pause_limit,
.port_disable_pri_override = mv88e6xxx_port_disable_pri_override,
.port_link_state = mv88e6250_port_link_state,
.stats_snapshot = mv88e6320_g1_stats_snapshot,
.stats_set_histogram = mv88e6095_g1_stats_set_histogram,
.stats_get_sset_count = mv88e6250_stats_get_sset_count,
.stats_get_strings = mv88e6250_stats_get_strings,
.stats_get_stats = mv88e6250_stats_get_stats,
.set_cpu_port = mv88e6095_g1_set_cpu_port,
.set_egress_port = mv88e6095_g1_set_egress_port,
.watchdog_ops = &mv88e6250_watchdog_ops,
.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,
.pot_clear = mv88e6xxx_g2_pot_clear,
.reset = mv88e6250_g1_reset,
.vtu_getnext = mv88e6250_g1_vtu_getnext,
.vtu_loadpurge = mv88e6250_g1_vtu_loadpurge,
.phylink_validate = mv88e6065_phylink_validate,
};
static const struct mv88e6xxx_ops mv88e6290_ops = { static const struct mv88e6xxx_ops mv88e6290_ops = {
/* MV88E6XXX_FAMILY_6390 */ /* MV88E6XXX_FAMILY_6390 */
.setup_errata = mv88e6390_setup_errata, .setup_errata = mv88e6390_setup_errata,
...@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = { ...@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.ops = &mv88e6240_ops, .ops = &mv88e6240_ops,
}, },
[MV88E6250] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6250,
.family = MV88E6XXX_FAMILY_6250,
.name = "Marvell 88E6250",
.num_databases = 64,
.num_ports = 7,
.num_internal_phys = 5,
.max_vid = 4095,
.port_base_addr = 0x08,
.phy_base_addr = 0x00,
.global1_addr = 0x0f,
.global2_addr = 0x07,
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.tag_protocol = DSA_TAG_PROTO_DSA,
.ops = &mv88e6250_ops,
},
[MV88E6290] = { [MV88E6290] = {
.prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290, .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
.family = MV88E6XXX_FAMILY_6390, .family = MV88E6XXX_FAMILY_6390,
...@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = { ...@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
.compatible = "marvell,mv88e6190", .compatible = "marvell,mv88e6190",
.data = &mv88e6xxx_table[MV88E6190], .data = &mv88e6xxx_table[MV88E6190],
}, },
{
.compatible = "marvell,mv88e6250",
.data = &mv88e6xxx_table[MV88E6250],
},
{ /* sentinel */ }, { /* sentinel */ },
}; };
......
...@@ -62,6 +62,7 @@ enum mv88e6xxx_model { ...@@ -62,6 +62,7 @@ enum mv88e6xxx_model {
MV88E6190X, MV88E6190X,
MV88E6191, MV88E6191,
MV88E6240, MV88E6240,
MV88E6250,
MV88E6290, MV88E6290,
MV88E6320, MV88E6320,
MV88E6321, MV88E6321,
...@@ -80,6 +81,7 @@ enum mv88e6xxx_family { ...@@ -80,6 +81,7 @@ enum mv88e6xxx_family {
MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */ MV88E6XXX_FAMILY_6097, /* 6046 6085 6096 6097 */
MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */ MV88E6XXX_FAMILY_6165, /* 6123 6161 6165 */
MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */ MV88E6XXX_FAMILY_6185, /* 6108 6121 6122 6131 6152 6155 6182 6185 */
MV88E6XXX_FAMILY_6250, /* 6250 */
MV88E6XXX_FAMILY_6320, /* 6320 6321 */ MV88E6XXX_FAMILY_6320, /* 6320 6321 */
MV88E6XXX_FAMILY_6341, /* 6141 6341 */ MV88E6XXX_FAMILY_6341, /* 6141 6341 */
MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */ MV88E6XXX_FAMILY_6351, /* 6171 6175 6350 6351 */
......
...@@ -182,6 +182,25 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip) ...@@ -182,6 +182,25 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip)
return mv88e6185_g1_wait_ppu_polling(chip); return mv88e6185_g1_wait_ppu_polling(chip);
} }
int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip)
{
u16 val;
int err;
/* Set the SWReset bit 15 */
err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &val);
if (err)
return err;
val |= MV88E6XXX_G1_CTL1_SW_RESET;
err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_CTL1, val);
if (err)
return err;
return mv88e6xxx_g1_wait_init_ready(chip);
}
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip) int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip)
{ {
u16 val; u16 val;
......
...@@ -259,6 +259,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); ...@@ -259,6 +259,7 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr);
int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip);
int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip);
......
...@@ -122,6 +122,7 @@ ...@@ -122,6 +122,7 @@
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6191 0x1910
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6185 0x1a70
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6240 0x2400
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6250 0x2500
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6290 0x2900
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6321 0x3100
#define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141 0x3400
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment