diff options
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/chip.c')
-rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 387 |
1 files changed, 196 insertions, 191 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7108f745fbf0..dc263cea205f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -611,10 +611,10 @@ static void mv88e6185_phylink_get_caps(struct mv88e6xxx_chip *chip, int port, } static const u8 mv88e6xxx_phy_interface_modes[] = { - [MV88E6XXX_PORT_STS_CMODE_MII_PHY] = PHY_INTERFACE_MODE_MII, + [MV88E6XXX_PORT_STS_CMODE_MII_PHY] = PHY_INTERFACE_MODE_REVMII, [MV88E6XXX_PORT_STS_CMODE_MII] = PHY_INTERFACE_MODE_MII, [MV88E6XXX_PORT_STS_CMODE_GMII] = PHY_INTERFACE_MODE_GMII, - [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_RMII, + [MV88E6XXX_PORT_STS_CMODE_RMII_PHY] = PHY_INTERFACE_MODE_REVRMII, [MV88E6XXX_PORT_STS_CMODE_RMII] = PHY_INTERFACE_MODE_RMII, [MV88E6XXX_PORT_STS_CMODE_100BASEX] = PHY_INTERFACE_MODE_100BASEX, [MV88E6XXX_PORT_STS_CMODE_1000BASEX] = PHY_INTERFACE_MODE_1000BASEX, @@ -3685,185 +3685,6 @@ static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip) return mv88e6xxx_software_reset(chip); } -static void mv88e6xxx_teardown(struct dsa_switch *ds) -{ - mv88e6xxx_teardown_devlink_params(ds); - dsa_devlink_resources_unregister(ds); - mv88e6xxx_teardown_devlink_regions_global(ds); -} - -static int mv88e6xxx_setup(struct dsa_switch *ds) -{ - struct mv88e6xxx_chip *chip = ds->priv; - u8 cmode; - int err; - int i; - - chip->ds = ds; - ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); - - /* Since virtual bridges are mapped in the PVT, the number we support - * depends on the physical switch topology. We need to let DSA figure - * that out and therefore we cannot set this at dsa_register_switch() - * time. - */ - if (mv88e6xxx_has_pvt(chip)) - ds->max_num_bridges = MV88E6XXX_MAX_PVT_SWITCHES - - ds->dst->last_switch - 1; - - mv88e6xxx_reg_lock(chip); - - if (chip->info->ops->setup_errata) { - err = chip->info->ops->setup_errata(chip); - if (err) - goto unlock; - } - - /* Cache the cmode of each port. */ - for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { - if (chip->info->ops->port_get_cmode) { - err = chip->info->ops->port_get_cmode(chip, i, &cmode); - if (err) - goto unlock; - - chip->ports[i].cmode = cmode; - } - } - - err = mv88e6xxx_vtu_setup(chip); - if (err) - goto unlock; - - /* Must be called after mv88e6xxx_vtu_setup (which flushes the - * VTU, thereby also flushing the STU). - */ - err = mv88e6xxx_stu_setup(chip); - if (err) - goto unlock; - - /* Setup Switch Port Registers */ - for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { - if (dsa_is_unused_port(ds, i)) - continue; - - /* Prevent the use of an invalid port. */ - if (mv88e6xxx_is_invalid_port(chip, i)) { - dev_err(chip->dev, "port %d is invalid\n", i); - err = -EINVAL; - goto unlock; - } - - err = mv88e6xxx_setup_port(chip, i); - if (err) - goto unlock; - } - - err = mv88e6xxx_irl_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_mac_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_phy_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_pvt_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_atu_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_broadcast_setup(chip, 0); - if (err) - goto unlock; - - err = mv88e6xxx_pot_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_rmu_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_rsvd2cpu_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_trunk_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_devmap_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_pri_setup(chip); - if (err) - goto unlock; - - /* Setup PTP Hardware Clock and timestamping */ - if (chip->info->ptp_support) { - err = mv88e6xxx_ptp_setup(chip); - if (err) - goto unlock; - - err = mv88e6xxx_hwtstamp_setup(chip); - if (err) - goto unlock; - } - - err = mv88e6xxx_stats_setup(chip); - if (err) - goto unlock; - -unlock: - mv88e6xxx_reg_unlock(chip); - - if (err) - return err; - - /* Have to be called without holding the register lock, since - * they take the devlink lock, and we later take the locks in - * the reverse order when getting/setting parameters or - * resource occupancy. - */ - err = mv88e6xxx_setup_devlink_resources(ds); - if (err) - return err; - - err = mv88e6xxx_setup_devlink_params(ds); - if (err) - goto out_resources; - - err = mv88e6xxx_setup_devlink_regions_global(ds); - if (err) - goto out_params; - - return 0; - -out_params: - mv88e6xxx_teardown_devlink_params(ds); -out_resources: - dsa_devlink_resources_unregister(ds); - - return err; -} - -static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) -{ - return mv88e6xxx_setup_devlink_regions_port(ds, port); -} - -static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) -{ - mv88e6xxx_teardown_devlink_regions_port(ds, port); -} - /* prod_id for switch families which do not have a PHY model number */ static const u16 family_prod_id_table[] = { [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, @@ -3989,6 +3810,9 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip, bus->read_c45 = mv88e6xxx_mdio_read_c45; bus->write_c45 = mv88e6xxx_mdio_write_c45; bus->parent = chip->dev; + bus->phy_mask = ~GENMASK(chip->info->phy_base_addr + + mv88e6xxx_num_ports(chip) - 1, + chip->info->phy_base_addr); if (!external) { err = mv88e6xxx_g2_irq_mdio_setup(chip, bus); @@ -4032,9 +3856,9 @@ static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip) } } -static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, - struct device_node *np) +static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip) { + struct device_node *np = chip->dev->of_node; struct device_node *child; int err; @@ -4067,6 +3891,194 @@ static int mv88e6xxx_mdios_register(struct mv88e6xxx_chip *chip, return 0; } +static void mv88e6xxx_teardown(struct dsa_switch *ds) +{ + struct mv88e6xxx_chip *chip = ds->priv; + + mv88e6xxx_teardown_devlink_params(ds); + dsa_devlink_resources_unregister(ds); + mv88e6xxx_teardown_devlink_regions_global(ds); + mv88e6xxx_mdios_unregister(chip); +} + +static int mv88e6xxx_setup(struct dsa_switch *ds) +{ + struct mv88e6xxx_chip *chip = ds->priv; + u8 cmode; + int err; + int i; + + err = mv88e6xxx_mdios_register(chip); + if (err) + return err; + + chip->ds = ds; + ds->slave_mii_bus = mv88e6xxx_default_mdio_bus(chip); + + /* Since virtual bridges are mapped in the PVT, the number we support + * depends on the physical switch topology. We need to let DSA figure + * that out and therefore we cannot set this at dsa_register_switch() + * time. + */ + if (mv88e6xxx_has_pvt(chip)) + ds->max_num_bridges = MV88E6XXX_MAX_PVT_SWITCHES - + ds->dst->last_switch - 1; + + mv88e6xxx_reg_lock(chip); + + if (chip->info->ops->setup_errata) { + err = chip->info->ops->setup_errata(chip); + if (err) + goto unlock; + } + + /* Cache the cmode of each port. */ + for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { + if (chip->info->ops->port_get_cmode) { + err = chip->info->ops->port_get_cmode(chip, i, &cmode); + if (err) + goto unlock; + + chip->ports[i].cmode = cmode; + } + } + + err = mv88e6xxx_vtu_setup(chip); + if (err) + goto unlock; + + /* Must be called after mv88e6xxx_vtu_setup (which flushes the + * VTU, thereby also flushing the STU). + */ + err = mv88e6xxx_stu_setup(chip); + if (err) + goto unlock; + + /* Setup Switch Port Registers */ + for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { + if (dsa_is_unused_port(ds, i)) + continue; + + /* Prevent the use of an invalid port. */ + if (mv88e6xxx_is_invalid_port(chip, i)) { + dev_err(chip->dev, "port %d is invalid\n", i); + err = -EINVAL; + goto unlock; + } + + err = mv88e6xxx_setup_port(chip, i); + if (err) + goto unlock; + } + + err = mv88e6xxx_irl_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_mac_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_phy_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_pvt_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_atu_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_broadcast_setup(chip, 0); + if (err) + goto unlock; + + err = mv88e6xxx_pot_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_rmu_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_rsvd2cpu_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_trunk_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_devmap_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_pri_setup(chip); + if (err) + goto unlock; + + /* Setup PTP Hardware Clock and timestamping */ + if (chip->info->ptp_support) { + err = mv88e6xxx_ptp_setup(chip); + if (err) + goto unlock; + + err = mv88e6xxx_hwtstamp_setup(chip); + if (err) + goto unlock; + } + + err = mv88e6xxx_stats_setup(chip); + if (err) + goto unlock; + +unlock: + mv88e6xxx_reg_unlock(chip); + + if (err) + goto out_mdios; + + /* Have to be called without holding the register lock, since + * they take the devlink lock, and we later take the locks in + * the reverse order when getting/setting parameters or + * resource occupancy. + */ + err = mv88e6xxx_setup_devlink_resources(ds); + if (err) + goto out_mdios; + + err = mv88e6xxx_setup_devlink_params(ds); + if (err) + goto out_resources; + + err = mv88e6xxx_setup_devlink_regions_global(ds); + if (err) + goto out_params; + + return 0; + +out_params: + mv88e6xxx_teardown_devlink_params(ds); +out_resources: + dsa_devlink_resources_unregister(ds); +out_mdios: + mv88e6xxx_mdios_unregister(chip); + + return err; +} + +static int mv88e6xxx_port_setup(struct dsa_switch *ds, int port) +{ + return mv88e6xxx_setup_devlink_regions_port(ds, port); +} + +static void mv88e6xxx_port_teardown(struct dsa_switch *ds, int port) +{ + mv88e6xxx_teardown_devlink_regions_port(ds, port); +} + static int mv88e6xxx_get_eeprom_len(struct dsa_switch *ds) { struct mv88e6xxx_chip *chip = ds->priv; @@ -7233,18 +7245,12 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev) if (err) goto out_g1_atu_prob_irq; - err = mv88e6xxx_mdios_register(chip, np); - if (err) - goto out_g1_vtu_prob_irq; - err = mv88e6xxx_register_switch(chip); if (err) - goto out_mdio; + goto out_g1_vtu_prob_irq; return 0; -out_mdio: - mv88e6xxx_mdios_unregister(chip); out_g1_vtu_prob_irq: mv88e6xxx_g1_vtu_prob_irq_free(chip); out_g1_atu_prob_irq: @@ -7281,7 +7287,6 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) mv88e6xxx_phy_destroy(chip); mv88e6xxx_unregister_switch(chip); - mv88e6xxx_mdios_unregister(chip); mv88e6xxx_g1_vtu_prob_irq_free(chip); mv88e6xxx_g1_atu_prob_irq_free(chip); |