// SPDX-License-Identifier: GPL-2.0+
/* Microchip Sparx5 Switch driver
 *
 * Copyright (c) 2021 Microchip Technology Inc. and its subsidiaries.
 */

#include <linux/module.h>
#include <linux/phylink.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/sfp.h>

#include "sparx5_main_regs.h"
#include "sparx5_main.h"
#include "sparx5_port.h"

static bool port_conf_has_changed(struct sparx5_port_config *a, struct sparx5_port_config *b)
{
	if (a->speed != b->speed ||
	    a->portmode != b->portmode ||
	    a->autoneg != b->autoneg ||
	    a->pause_adv != b->pause_adv ||
	    a->power_down != b->power_down ||
	    a->media != b->media)
		return true;
	return false;
}

static void sparx5_phylink_validate(struct phylink_config *config,
				    unsigned long *supported,
				    struct phylink_link_state *state)
{
	struct sparx5_port *port = netdev_priv(to_net_dev(config->dev));
	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };

	phylink_set(mask, Autoneg);
	phylink_set_port_modes(mask);
	phylink_set(mask, Pause);
	phylink_set(mask, Asym_Pause);

	switch (state->interface) {
	case PHY_INTERFACE_MODE_5GBASER:
	case PHY_INTERFACE_MODE_10GBASER:
	case PHY_INTERFACE_MODE_25GBASER:
	case PHY_INTERFACE_MODE_NA:
		if (port->conf.bandwidth == SPEED_5000)
			phylink_set(mask, 5000baseT_Full);
		if (port->conf.bandwidth == SPEED_10000) {
			phylink_set(mask, 5000baseT_Full);
			phylink_set(mask, 10000baseT_Full);
			phylink_set(mask, 10000baseCR_Full);
			phylink_set(mask, 10000baseSR_Full);
			phylink_set(mask, 10000baseLR_Full);
			phylink_set(mask, 10000baseLRM_Full);
			phylink_set(mask, 10000baseER_Full);
		}
		if (port->conf.bandwidth == SPEED_25000) {
			phylink_set(mask, 5000baseT_Full);
			phylink_set(mask, 10000baseT_Full);
			phylink_set(mask, 10000baseCR_Full);
			phylink_set(mask, 10000baseSR_Full);
			phylink_set(mask, 10000baseLR_Full);
			phylink_set(mask, 10000baseLRM_Full);
			phylink_set(mask, 10000baseER_Full);
			phylink_set(mask, 25000baseCR_Full);
			phylink_set(mask, 25000baseSR_Full);
		}
		if (state->interface != PHY_INTERFACE_MODE_NA)
			break;
		fallthrough;
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_QSGMII:
		phylink_set(mask, 10baseT_Half);
		phylink_set(mask, 10baseT_Full);
		phylink_set(mask, 100baseT_Half);
		phylink_set(mask, 100baseT_Full);
		phylink_set(mask, 1000baseT_Full);
		phylink_set(mask, 1000baseX_Full);
		if (state->interface != PHY_INTERFACE_MODE_NA)
			break;
		fallthrough;
	case PHY_INTERFACE_MODE_1000BASEX:
	case PHY_INTERFACE_MODE_2500BASEX:
		if (state->interface != PHY_INTERFACE_MODE_2500BASEX) {
			phylink_set(mask, 1000baseT_Full);
			phylink_set(mask, 1000baseX_Full);
		}
		if (state->interface == PHY_INTERFACE_MODE_2500BASEX ||
		    state->interface == PHY_INTERFACE_MODE_NA) {
			phylink_set(mask, 2500baseT_Full);
			phylink_set(mask, 2500baseX_Full);
		}
		break;
	default:
		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
		return;
	}
	bitmap_and(supported, supported, mask, __ETHTOOL_LINK_MODE_MASK_NBITS);
	bitmap_and(state->advertising, state->advertising, mask,
		   __ETHTOOL_LINK_MODE_MASK_NBITS);
}

static void sparx5_phylink_mac_config(struct phylink_config *config,
				      unsigned int mode,
				      const struct phylink_link_state *state)
{
	/* Currently not used */
}

static void sparx5_phylink_mac_link_up(struct phylink_config *config,
				       struct phy_device *phy,
				       unsigned int mode,
				       phy_interface_t interface,
				       int speed, int duplex,
				       bool tx_pause, bool rx_pause)
{
	struct sparx5_port *port = netdev_priv(to_net_dev(config->dev));
	struct sparx5_port_config conf;
	int err;

	conf = port->conf;
	conf.duplex = duplex;
	conf.pause = 0;
	conf.pause |= tx_pause ? MLO_PAUSE_TX : 0;
	conf.pause |= rx_pause ? MLO_PAUSE_RX : 0;
	conf.speed = speed;
	/* Configure the port to speed/duplex/pause */
	err = sparx5_port_config(port->sparx5, port, &conf);
	if (err)
		netdev_err(port->ndev, "port config failed: %d\n", err);
}

static void sparx5_phylink_mac_link_down(struct phylink_config *config,
					 unsigned int mode,
					 phy_interface_t interface)
{
	/* Currently not used */
}

static struct sparx5_port *sparx5_pcs_to_port(struct phylink_pcs *pcs)
{
	return container_of(pcs, struct sparx5_port, phylink_pcs);
}

static void sparx5_pcs_get_state(struct phylink_pcs *pcs,
				 struct phylink_link_state *state)
{
	struct sparx5_port *port = sparx5_pcs_to_port(pcs);
	struct sparx5_port_status status;

	sparx5_get_port_status(port->sparx5, port, &status);
	state->link = status.link && !status.link_down;
	state->an_complete = status.an_complete;
	state->speed = status.speed;
	state->duplex = status.duplex;
	state->pause = status.pause;
}

static int sparx5_pcs_config(struct phylink_pcs *pcs,
			     unsigned int mode,
			     phy_interface_t interface,
			     const unsigned long *advertising,
			     bool permit_pause_to_mac)
{
	struct sparx5_port *port = sparx5_pcs_to_port(pcs);
	struct sparx5_port_config conf;
	int ret = 0;

	conf = port->conf;
	conf.power_down = false;
	conf.portmode = interface;
	conf.inband = phylink_autoneg_inband(mode);
	conf.autoneg = phylink_test(advertising, Autoneg);
	conf.pause_adv = 0;
	if (phylink_test(advertising, Pause))
		conf.pause_adv |= ADVERTISE_1000XPAUSE;
	if (phylink_test(advertising, Asym_Pause))
		conf.pause_adv |= ADVERTISE_1000XPSE_ASYM;
	if (sparx5_is_baser(interface)) {
		if (phylink_test(advertising, FIBRE))
			conf.media = PHY_MEDIA_SR;
		else
			conf.media = PHY_MEDIA_DAC;
	}
	if (!port_conf_has_changed(&port->conf, &conf))
		return ret;
	/* Enable the PCS matching this interface type */
	ret = sparx5_port_pcs_set(port->sparx5, port, &conf);
	if (ret)
		netdev_err(port->ndev, "port PCS config failed: %d\n", ret);
	return ret;
}

static void sparx5_pcs_aneg_restart(struct phylink_pcs *pcs)
{
	/* Currently not used */
}

const struct phylink_pcs_ops sparx5_phylink_pcs_ops = {
	.pcs_get_state = sparx5_pcs_get_state,
	.pcs_config = sparx5_pcs_config,
	.pcs_an_restart = sparx5_pcs_aneg_restart,
};

const struct phylink_mac_ops sparx5_phylink_mac_ops = {
	.validate = sparx5_phylink_validate,
	.mac_config = sparx5_phylink_mac_config,
	.mac_link_down = sparx5_phylink_mac_link_down,
	.mac_link_up = sparx5_phylink_mac_link_up,
};
