net: dsa: mv88e6xxx: add support for mv88e6250
authorRasmus Villemoes <rasmus.villemoes@prevas.dk>
Tue, 4 Jun 2019 07:34:32 +0000 (07:34 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 5 Jun 2019 03:07:57 +0000 (20:07 -0700)
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: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/dsa/mv88e6xxx/chip.h
drivers/net/dsa/mv88e6xxx/global1.c
drivers/net/dsa/mv88e6xxx/global1.h
drivers/net/dsa/mv88e6xxx/port.h

index 12f165a71a6c7b6c91c60e64e51799cdbcc90345..df9c51da77330b12c05f3bdb7ab0586cf3778c63 100644 (file)
@@ -829,6 +829,12 @@ static int mv88e6095_stats_get_strings(struct mv88e6xxx_chip *chip,
                                           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,
                                       uint8_t *data)
 {
@@ -899,6 +905,11 @@ static int mv88e6095_stats_get_sset_count(struct mv88e6xxx_chip *chip)
                                              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)
 {
        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,
                                         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,
                                     uint64_t *data)
 {
@@ -3448,6 +3466,44 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
        .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 = {
        /* MV88E6XXX_FAMILY_6390 */
        .setup_errata = mv88e6390_setup_errata,
@@ -4233,6 +4289,27 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
                .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] = {
                .prod_num = MV88E6XXX_PORT_SWITCH_ID_PROD_6290,
                .family = MV88E6XXX_FAMILY_6390,
@@ -4841,6 +4918,10 @@ static const struct of_device_id mv88e6xxx_of_match[] = {
                .compatible = "marvell,mv88e6190",
                .data = &mv88e6xxx_table[MV88E6190],
        },
+       {
+               .compatible = "marvell,mv88e6250",
+               .data = &mv88e6xxx_table[MV88E6250],
+       },
        { /* sentinel */ },
 };
 
index 74777c3bc3135f298d33f4764db6dc58f306945e..2fbe72b7587b94eddaada99ddb8222e359ea25e9 100644 (file)
@@ -62,6 +62,7 @@ enum mv88e6xxx_model {
        MV88E6190X,
        MV88E6191,
        MV88E6240,
+       MV88E6250,
        MV88E6290,
        MV88E6320,
        MV88E6321,
@@ -80,6 +81,7 @@ enum mv88e6xxx_family {
        MV88E6XXX_FAMILY_6097,  /* 6046 6085 6096 6097 */
        MV88E6XXX_FAMILY_6165,  /* 6123 6161 6165 */
        MV88E6XXX_FAMILY_6185,  /* 6108 6121 6122 6131 6152 6155 6182 6185 */
+       MV88E6XXX_FAMILY_6250,  /* 6250 */
        MV88E6XXX_FAMILY_6320,  /* 6320 6321 */
        MV88E6XXX_FAMILY_6341,  /* 6141 6341 */
        MV88E6XXX_FAMILY_6351,  /* 6171 6175 6350 6351 */
index c851b7b532a4e778e6c215a2c91dcb47f5b64945..fc10b6e495f55109980ac6aba156ff74a1006ac5 100644 (file)
@@ -182,6 +182,25 @@ int mv88e6185_g1_reset(struct mv88e6xxx_chip *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)
 {
        u16 val;
index ba8b4b4c685b64b9cbf8a7a9d167701b1c647cab..9681ce25598ac301105ccb6b607dc63793fd00b0 100644 (file)
@@ -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 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_disable(struct mv88e6xxx_chip *chip);
index 3a89c2868cec58e40a3ab2d69aa977821cb85d18..b3b57ea6ef0753610a72d389473a9b7baf877ee1 100644 (file)
 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6191     0x1910
 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6185     0x1a70
 #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_6321     0x3100
 #define MV88E6XXX_PORT_SWITCH_ID_PROD_6141     0x3400