diff options
Diffstat (limited to 'drivers/net/dsa/mv88e6xxx/chip.c')
| -rw-r--r-- | drivers/net/dsa/mv88e6xxx/chip.c | 417 | 
1 files changed, 218 insertions, 199 deletions
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 0a5d6c7bb128..08a46ffd53af 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, @@ -3354,9 +3354,14 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port)  	 * If this is the upstream port for this switch, enable  	 * forwarding of unknown unicasts and multicasts.  	 */ -	reg = MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP | -		MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP | +	reg = MV88E6185_PORT_CTL0_USE_TAG | MV88E6185_PORT_CTL0_USE_IP |  		MV88E6XXX_PORT_CTL0_STATE_FORWARDING; +	/* Forward any IPv4 IGMP or IPv6 MLD frames received +	 * by a USER port to the CPU port to allow snooping. +	 */ +	if (dsa_is_user_port(ds, port)) +		reg |= MV88E6XXX_PORT_CTL0_IGMP_MLD_SNOOP; +  	err = mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_CTL0, reg);  	if (err)  		return err; @@ -3549,7 +3554,7 @@ static int mv88e6xxx_get_max_mtu(struct dsa_switch *ds, int port)  		return 10240 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN;  	else if (chip->info->ops->set_max_frame_size)  		return 1632 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; -	return 1522 - VLAN_ETH_HLEN - EDSA_HLEN - ETH_FCS_LEN; +	return ETH_DATA_LEN;  }  static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu) @@ -3557,6 +3562,17 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)  	struct mv88e6xxx_chip *chip = ds->priv;  	int ret = 0; +	/* For families where we don't know how to alter the MTU, +	 * just accept any value up to ETH_DATA_LEN +	 */ +	if (!chip->info->ops->port_set_jumbo_size && +	    !chip->info->ops->set_max_frame_size) { +		if (new_mtu > ETH_DATA_LEN) +			return -EINVAL; + +		return 0; +	} +  	if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))  		new_mtu += EDSA_HLEN; @@ -3565,9 +3581,6 @@ static int mv88e6xxx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)  		ret = chip->info->ops->port_set_jumbo_size(chip, port, new_mtu);  	else if (chip->info->ops->set_max_frame_size)  		ret = chip->info->ops->set_max_frame_size(chip, new_mtu); -	else -		if (new_mtu > 1522) -			ret = -EINVAL;  	mv88e6xxx_reg_unlock(chip);  	return ret; @@ -3672,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, @@ -3976,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); @@ -4019,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; @@ -4054,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; @@ -5169,6 +5194,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {  	.set_cpu_port = mv88e6095_g1_set_cpu_port,  	.set_egress_port = mv88e6095_g1_set_egress_port,  	.watchdog_ops = &mv88e6390_watchdog_ops, +	.mgmt_rsvd2cpu = mv88e6352_g2_mgmt_rsvd2cpu,  	.reset = mv88e6352_g1_reset,  	.vtu_getnext = mv88e6185_g1_vtu_getnext,  	.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge, @@ -5588,7 +5614,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {  	 * .port_set_upstream_port method.  	 */  	.set_egress_port = mv88e6393x_set_egress_port, -	.watchdog_ops = &mv88e6390_watchdog_ops, +	.watchdog_ops = &mv88e6393x_watchdog_ops,  	.mgmt_rsvd2cpu = mv88e6393x_port_mgmt_rsvd2cpu,  	.pot_clear = mv88e6xxx_g2_pot_clear,  	.reset = mv88e6352_g1_reset, @@ -7144,7 +7170,7 @@ static int mv88e6xxx_probe(struct mdio_device *mdiodev)  		goto out;  	}  	if (chip->reset) -		usleep_range(1000, 2000); +		usleep_range(10000, 20000);  	/* Detect if the device is configured in single chip addressing mode,  	 * otherwise continue with address specific smi init/detection. @@ -7220,18 +7246,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: @@ -7268,7 +7288,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);  |