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

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

/* The IFH bit position of the first VSTAX bit. This is because the
 * VSTAX bit positions in Data sheet is starting from zero.
 */
#define VSTAX 73

#define ifh_encode_bitfield(ifh, value, pos, _width)			\
	({								\
		u32 width = (_width);					\
									\
		/* Max width is 5 bytes - 40 bits. In worst case this will
		 * spread over 6 bytes - 48 bits
		 */							\
		compiletime_assert(width <= 40,				\
				   "Unsupported width, must be <= 40");	\
		__ifh_encode_bitfield((ifh), (value), (pos), width);	\
	})

static void __ifh_encode_bitfield(void *ifh, u64 value, u32 pos, u32 width)
{
	u8 *ifh_hdr = ifh;
	/* Calculate the Start IFH byte position of this IFH bit position */
	u32 byte = (35 - (pos / 8));
	/* Calculate the Start bit position in the Start IFH byte */
	u32 bit  = (pos % 8);
	u64 encode = GENMASK_ULL(bit + width - 1, bit) & (value << bit);

	/* The b0-b7 goes into the start IFH byte */
	if (encode & 0xFF)
		ifh_hdr[byte] |= (u8)((encode & 0xFF));
	/* The b8-b15 goes into the next IFH byte */
	if (encode & 0xFF00)
		ifh_hdr[byte - 1] |= (u8)((encode & 0xFF00) >> 8);
	/* The b16-b23 goes into the next IFH byte */
	if (encode & 0xFF0000)
		ifh_hdr[byte - 2] |= (u8)((encode & 0xFF0000) >> 16);
	/* The b24-b31 goes into the next IFH byte */
	if (encode & 0xFF000000)
		ifh_hdr[byte - 3] |= (u8)((encode & 0xFF000000) >> 24);
	/* The b32-b39 goes into the next IFH byte */
	if (encode & 0xFF00000000)
		ifh_hdr[byte - 4] |= (u8)((encode & 0xFF00000000) >> 32);
	/* The b40-b47 goes into the next IFH byte */
	if (encode & 0xFF0000000000)
		ifh_hdr[byte - 5] |= (u8)((encode & 0xFF0000000000) >> 40);
}

static void sparx5_set_port_ifh(void *ifh_hdr, u16 portno)
{
	/* VSTAX.RSV = 1. MSBit must be 1 */
	ifh_encode_bitfield(ifh_hdr, 1, VSTAX + 79,  1);
	/* VSTAX.INGR_DROP_MODE = Enable. Don't make head-of-line blocking */
	ifh_encode_bitfield(ifh_hdr, 1, VSTAX + 55,  1);
	/* MISC.CPU_MASK/DPORT = Destination port */
	ifh_encode_bitfield(ifh_hdr, portno,   29, 8);
	/* MISC.PIPELINE_PT */
	ifh_encode_bitfield(ifh_hdr, 16,       37, 5);
	/* MISC.PIPELINE_ACT */
	ifh_encode_bitfield(ifh_hdr, 1,        42, 3);
	/* FWD.SRC_PORT = CPU */
	ifh_encode_bitfield(ifh_hdr, SPX5_PORT_CPU, 46, 7);
	/* FWD.SFLOW_ID (disable SFlow sampling) */
	ifh_encode_bitfield(ifh_hdr, 124,      57, 7);
	/* FWD.UPDATE_FCS = Enable. Enforce update of FCS. */
	ifh_encode_bitfield(ifh_hdr, 1,        67, 1);
}

static int sparx5_port_open(struct net_device *ndev)
{
	struct sparx5_port *port = netdev_priv(ndev);
	int err = 0;

	sparx5_port_enable(port, true);
	err = phylink_of_phy_connect(port->phylink, port->of_node, 0);
	if (err) {
		netdev_err(ndev, "Could not attach to PHY\n");
		return err;
	}

	phylink_start(port->phylink);

	if (!ndev->phydev) {
		/* power up serdes */
		port->conf.power_down = false;
		if (port->conf.serdes_reset)
			err = sparx5_serdes_set(port->sparx5, port, &port->conf);
		else
			err = phy_power_on(port->serdes);
		if (err)
			netdev_err(ndev, "%s failed\n", __func__);
	}

	return err;
}

static int sparx5_port_stop(struct net_device *ndev)
{
	struct sparx5_port *port = netdev_priv(ndev);
	int err = 0;

	sparx5_port_enable(port, false);
	phylink_stop(port->phylink);
	phylink_disconnect_phy(port->phylink);

	if (!ndev->phydev) {
		/* power down serdes */
		port->conf.power_down = true;
		if (port->conf.serdes_reset)
			err = sparx5_serdes_set(port->sparx5, port, &port->conf);
		else
			err = phy_power_off(port->serdes);
		if (err)
			netdev_err(ndev, "%s failed\n", __func__);
	}
	return 0;
}

static void sparx5_set_rx_mode(struct net_device *dev)
{
	struct sparx5_port *port = netdev_priv(dev);
	struct sparx5 *sparx5 = port->sparx5;

	if (!test_bit(port->portno, sparx5->bridge_mask))
		__dev_mc_sync(dev, sparx5_mc_sync, sparx5_mc_unsync);
}

static int sparx5_port_get_phys_port_name(struct net_device *dev,
					  char *buf, size_t len)
{
	struct sparx5_port *port = netdev_priv(dev);
	int ret;

	ret = snprintf(buf, len, "p%d", port->portno);
	if (ret >= len)
		return -EINVAL;

	return 0;
}

static int sparx5_set_mac_address(struct net_device *dev, void *p)
{
	struct sparx5_port *port = netdev_priv(dev);
	struct sparx5 *sparx5 = port->sparx5;
	const struct sockaddr *addr = p;

	if (!is_valid_ether_addr(addr->sa_data))
		return -EADDRNOTAVAIL;

	/* Remove current */
	sparx5_mact_forget(sparx5, dev->dev_addr,  port->pvid);

	/* Add new */
	sparx5_mact_learn(sparx5, PGID_CPU, addr->sa_data, port->pvid);

	/* Record the address */
	eth_hw_addr_set(dev, addr->sa_data);

	return 0;
}

static int sparx5_get_port_parent_id(struct net_device *dev,
				     struct netdev_phys_item_id *ppid)
{
	struct sparx5_port *sparx5_port = netdev_priv(dev);
	struct sparx5 *sparx5 = sparx5_port->sparx5;

	ppid->id_len = sizeof(sparx5->base_mac);
	memcpy(&ppid->id, &sparx5->base_mac, ppid->id_len);

	return 0;
}

static const struct net_device_ops sparx5_port_netdev_ops = {
	.ndo_open               = sparx5_port_open,
	.ndo_stop               = sparx5_port_stop,
	.ndo_start_xmit         = sparx5_port_xmit_impl,
	.ndo_set_rx_mode        = sparx5_set_rx_mode,
	.ndo_get_phys_port_name = sparx5_port_get_phys_port_name,
	.ndo_set_mac_address    = sparx5_set_mac_address,
	.ndo_validate_addr      = eth_validate_addr,
	.ndo_get_stats64        = sparx5_get_stats64,
	.ndo_get_port_parent_id = sparx5_get_port_parent_id,
};

bool sparx5_netdevice_check(const struct net_device *dev)
{
	return dev && (dev->netdev_ops == &sparx5_port_netdev_ops);
}

struct net_device *sparx5_create_netdev(struct sparx5 *sparx5, u32 portno)
{
	struct sparx5_port *spx5_port;
	struct net_device *ndev;

	ndev = devm_alloc_etherdev(sparx5->dev, sizeof(struct sparx5_port));
	if (!ndev)
		return ERR_PTR(-ENOMEM);

	SET_NETDEV_DEV(ndev, sparx5->dev);
	spx5_port = netdev_priv(ndev);
	spx5_port->ndev = ndev;
	spx5_port->sparx5 = sparx5;
	spx5_port->portno = portno;
	sparx5_set_port_ifh(spx5_port->ifh, portno);

	ndev->netdev_ops = &sparx5_port_netdev_ops;
	ndev->ethtool_ops = &sparx5_ethtool_ops;

	eth_hw_addr_gen(ndev, sparx5->base_mac, portno + 1);

	return ndev;
}

int sparx5_register_netdevs(struct sparx5 *sparx5)
{
	int portno;
	int err;

	for (portno = 0; portno < SPX5_PORTS; portno++)
		if (sparx5->ports[portno]) {
			err = register_netdev(sparx5->ports[portno]->ndev);
			if (err) {
				dev_err(sparx5->dev,
					"port: %02u: netdev registration failed\n",
					portno);
				return err;
			}
			sparx5_port_inj_timer_setup(sparx5->ports[portno]);
		}
	return 0;
}

void sparx5_destroy_netdevs(struct sparx5 *sparx5)
{
	struct sparx5_port *port;
	int portno;

	for (portno = 0; portno < SPX5_PORTS; portno++) {
		port = sparx5->ports[portno];
		if (port && port->phylink) {
			/* Disconnect the phy */
			rtnl_lock();
			sparx5_port_stop(port->ndev);
			phylink_disconnect_phy(port->phylink);
			rtnl_unlock();
			phylink_destroy(port->phylink);
			port->phylink = NULL;
		}
	}
}

void sparx5_unregister_netdevs(struct sparx5 *sparx5)
{
	int portno;

	for (portno = 0; portno < SPX5_PORTS; portno++)
		if (sparx5->ports[portno])
			unregister_netdev(sparx5->ports[portno]->ndev);
}

