diff options
Diffstat (limited to 'drivers/net/dsa/ocelot/felix.c')
| -rw-r--r-- | drivers/net/dsa/ocelot/felix.c | 114 | 
1 files changed, 93 insertions, 21 deletions
| diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 61e95487732d..e554699f06d4 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -1050,24 +1050,32 @@ static void felix_phylink_get_caps(struct dsa_switch *ds, int port,  		  config->supported_interfaces);  } -static void felix_phylink_mac_config(struct dsa_switch *ds, int port, +static void felix_phylink_mac_config(struct phylink_config *config,  				     unsigned int mode,  				     const struct phylink_link_state *state)  { -	struct ocelot *ocelot = ds->priv; -	struct felix *felix = ocelot_to_felix(ocelot); +	struct dsa_port *dp = dsa_phylink_to_port(config); +	struct ocelot *ocelot = dp->ds->priv; +	int port = dp->index; +	struct felix *felix; + +	felix = ocelot_to_felix(ocelot);  	if (felix->info->phylink_mac_config)  		felix->info->phylink_mac_config(ocelot, port, mode, state);  } -static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds, -							int port, -							phy_interface_t iface) +static struct phylink_pcs * +felix_phylink_mac_select_pcs(struct phylink_config *config, +			     phy_interface_t iface)  { -	struct ocelot *ocelot = ds->priv; -	struct felix *felix = ocelot_to_felix(ocelot); +	struct dsa_port *dp = dsa_phylink_to_port(config); +	struct ocelot *ocelot = dp->ds->priv;  	struct phylink_pcs *pcs = NULL; +	int port = dp->index; +	struct felix *felix; + +	felix = ocelot_to_felix(ocelot);  	if (felix->pcs && felix->pcs[port])  		pcs = felix->pcs[port]; @@ -1075,11 +1083,13 @@ static struct phylink_pcs *felix_phylink_mac_select_pcs(struct dsa_switch *ds,  	return pcs;  } -static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port, +static void felix_phylink_mac_link_down(struct phylink_config *config,  					unsigned int link_an_mode,  					phy_interface_t interface)  { -	struct ocelot *ocelot = ds->priv; +	struct dsa_port *dp = dsa_phylink_to_port(config); +	struct ocelot *ocelot = dp->ds->priv; +	int port = dp->index;  	struct felix *felix;  	felix = ocelot_to_felix(ocelot); @@ -1088,15 +1098,19 @@ static void felix_phylink_mac_link_down(struct dsa_switch *ds, int port,  				     felix->info->quirks);  } -static void felix_phylink_mac_link_up(struct dsa_switch *ds, int port, +static void felix_phylink_mac_link_up(struct phylink_config *config, +				      struct phy_device *phydev,  				      unsigned int link_an_mode,  				      phy_interface_t interface, -				      struct phy_device *phydev,  				      int speed, int duplex,  				      bool tx_pause, bool rx_pause)  { -	struct ocelot *ocelot = ds->priv; -	struct felix *felix = ocelot_to_felix(ocelot); +	struct dsa_port *dp = dsa_phylink_to_port(config); +	struct ocelot *ocelot = dp->ds->priv; +	int port = dp->index; +	struct felix *felix; + +	felix = ocelot_to_felix(ocelot);  	ocelot_phylink_mac_link_up(ocelot, port, phydev, link_an_mode,  				   interface, speed, duplex, tx_pause, rx_pause, @@ -1220,7 +1234,7 @@ static int felix_get_sset_count(struct dsa_switch *ds, int port, int sset)  }  static int felix_get_ts_info(struct dsa_switch *ds, int port, -			     struct ethtool_ts_info *info) +			     struct kernel_ethtool_ts_info *info)  {  	struct ocelot *ocelot = ds->priv; @@ -1583,6 +1597,15 @@ static int felix_setup(struct dsa_switch *ds)  		felix_port_qos_map_init(ocelot, dp->index);  	} +	if (felix->info->request_irq) { +		err = felix->info->request_irq(ocelot); +		if (err) { +			dev_err(ocelot->dev, "Failed to request IRQ: %pe\n", +				ERR_PTR(err)); +			goto out_deinit_ports; +		} +	} +  	err = ocelot_devlink_sb_register(ocelot);  	if (err)  		goto out_deinit_ports; @@ -2083,7 +2106,14 @@ static void felix_get_mm_stats(struct dsa_switch *ds, int port,  	ocelot_port_get_mm_stats(ocelot, port, stats);  } -const struct dsa_switch_ops felix_switch_ops = { +static const struct phylink_mac_ops felix_phylink_mac_ops = { +	.mac_select_pcs		= felix_phylink_mac_select_pcs, +	.mac_config		= felix_phylink_mac_config, +	.mac_link_down		= felix_phylink_mac_link_down, +	.mac_link_up		= felix_phylink_mac_link_up, +}; + +static const struct dsa_switch_ops felix_switch_ops = {  	.get_tag_protocol		= felix_get_tag_protocol,  	.change_tag_protocol		= felix_change_tag_protocol,  	.connect_tag_protocol		= felix_connect_tag_protocol, @@ -2104,10 +2134,6 @@ const struct dsa_switch_ops felix_switch_ops = {  	.get_sset_count			= felix_get_sset_count,  	.get_ts_info			= felix_get_ts_info,  	.phylink_get_caps		= felix_phylink_get_caps, -	.phylink_mac_config		= felix_phylink_mac_config, -	.phylink_mac_select_pcs		= felix_phylink_mac_select_pcs, -	.phylink_mac_link_down		= felix_phylink_mac_link_down, -	.phylink_mac_link_up		= felix_phylink_mac_link_up,  	.port_enable			= felix_port_enable,  	.port_fast_age			= felix_port_fast_age,  	.port_fdb_dump			= felix_fdb_dump, @@ -2166,7 +2192,53 @@ const struct dsa_switch_ops felix_switch_ops = {  	.port_set_host_flood		= felix_port_set_host_flood,  	.port_change_conduit		= felix_port_change_conduit,  }; -EXPORT_SYMBOL_GPL(felix_switch_ops); + +int felix_register_switch(struct device *dev, resource_size_t switch_base, +			  int num_flooding_pgids, bool ptp, +			  bool mm_supported, +			  enum dsa_tag_protocol init_tag_proto, +			  const struct felix_info *info) +{ +	struct dsa_switch *ds; +	struct ocelot *ocelot; +	struct felix *felix; +	int err; + +	felix = devm_kzalloc(dev, sizeof(*felix), GFP_KERNEL); +	if (!felix) +		return -ENOMEM; + +	ds = devm_kzalloc(dev, sizeof(*ds), GFP_KERNEL); +	if (!ds) +		return -ENOMEM; + +	dev_set_drvdata(dev, felix); + +	ocelot = &felix->ocelot; +	ocelot->dev = dev; +	ocelot->num_flooding_pgids = num_flooding_pgids; +	ocelot->ptp = ptp; +	ocelot->mm_supported = mm_supported; + +	felix->info = info; +	felix->switch_base = switch_base; +	felix->ds = ds; +	felix->tag_proto = init_tag_proto; + +	ds->dev = dev; +	ds->num_ports = info->num_ports; +	ds->num_tx_queues = OCELOT_NUM_TC; +	ds->ops = &felix_switch_ops; +	ds->phylink_mac_ops = &felix_phylink_mac_ops; +	ds->priv = ocelot; + +	err = dsa_register_switch(ds); +	if (err) +		dev_err_probe(dev, err, "Failed to register DSA switch\n"); + +	return err; +} +EXPORT_SYMBOL_GPL(felix_register_switch);  struct net_device *felix_port_to_netdev(struct ocelot *ocelot, int port)  { |