// 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"

static int sparx5_vlant_set_mask(struct sparx5 *sparx5, u16 vid)
{
	u32 mask[3];

	/* Divide up mask in 32 bit words */
	bitmap_to_arr32(mask, sparx5->vlan_mask[vid], SPX5_PORTS);

	/* Output mask to respective registers */
	spx5_wr(mask[0], sparx5, ANA_L3_VLAN_MASK_CFG(vid));
	spx5_wr(mask[1], sparx5, ANA_L3_VLAN_MASK_CFG1(vid));
	spx5_wr(mask[2], sparx5, ANA_L3_VLAN_MASK_CFG2(vid));

	return 0;
}

void sparx5_vlan_init(struct sparx5 *sparx5)
{
	u16 vid;

	spx5_rmw(ANA_L3_VLAN_CTRL_VLAN_ENA_SET(1),
		 ANA_L3_VLAN_CTRL_VLAN_ENA,
		 sparx5,
		 ANA_L3_VLAN_CTRL);

	/* Map VLAN = FID */
	for (vid = NULL_VID; vid < VLAN_N_VID; vid++)
		spx5_rmw(ANA_L3_VLAN_CFG_VLAN_FID_SET(vid),
			 ANA_L3_VLAN_CFG_VLAN_FID,
			 sparx5,
			 ANA_L3_VLAN_CFG(vid));
}

void sparx5_vlan_port_setup(struct sparx5 *sparx5, int portno)
{
	struct sparx5_port *port = sparx5->ports[portno];

	/* Configure PVID */
	spx5_rmw(ANA_CL_VLAN_CTRL_VLAN_AWARE_ENA_SET(0) |
		 ANA_CL_VLAN_CTRL_PORT_VID_SET(port->pvid),
		 ANA_CL_VLAN_CTRL_VLAN_AWARE_ENA |
		 ANA_CL_VLAN_CTRL_PORT_VID,
		 sparx5,
		 ANA_CL_VLAN_CTRL(port->portno));
}

int sparx5_vlan_vid_add(struct sparx5_port *port, u16 vid, bool pvid,
			bool untagged)
{
	struct sparx5 *sparx5 = port->sparx5;
	int ret;

	/* Make the port a member of the VLAN */
	set_bit(port->portno, sparx5->vlan_mask[vid]);
	ret = sparx5_vlant_set_mask(sparx5, vid);
	if (ret)
		return ret;

	/* Default ingress vlan classification */
	if (pvid)
		port->pvid = vid;

	/* Untagged egress vlan classification */
	if (untagged && port->vid != vid) {
		if (port->vid) {
			netdev_err(port->ndev,
				   "Port already has a native VLAN: %d\n",
				   port->vid);
			return -EBUSY;
		}
		port->vid = vid;
	}

	sparx5_vlan_port_apply(sparx5, port);

	return 0;
}

int sparx5_vlan_vid_del(struct sparx5_port *port, u16 vid)
{
	struct sparx5 *sparx5 = port->sparx5;
	int ret;

	/* 8021q removes VID 0 on module unload for all interfaces
	 * with VLAN filtering feature. We need to keep it to receive
	 * untagged traffic.
	 */
	if (vid == 0)
		return 0;

	/* Stop the port from being a member of the vlan */
	clear_bit(port->portno, sparx5->vlan_mask[vid]);
	ret = sparx5_vlant_set_mask(sparx5, vid);
	if (ret)
		return ret;

	/* Ingress */
	if (port->pvid == vid)
		port->pvid = 0;

	/* Egress */
	if (port->vid == vid)
		port->vid = 0;

	sparx5_vlan_port_apply(sparx5, port);

	return 0;
}

void sparx5_pgid_update_mask(struct sparx5_port *port, int pgid, bool enable)
{
	struct sparx5 *sparx5 = port->sparx5;
	u32 val, mask;

	/* mask is spread across 3 registers x 32 bit */
	if (port->portno < 32) {
		mask = BIT(port->portno);
		val = enable ? mask : 0;
		spx5_rmw(val, mask, sparx5, ANA_AC_PGID_CFG(pgid));
	} else if (port->portno < 64) {
		mask = BIT(port->portno - 32);
		val = enable ? mask : 0;
		spx5_rmw(val, mask, sparx5, ANA_AC_PGID_CFG1(pgid));
	} else if (port->portno < SPX5_PORTS) {
		mask = BIT(port->portno - 64);
		val = enable ? mask : 0;
		spx5_rmw(val, mask, sparx5, ANA_AC_PGID_CFG2(pgid));
	} else {
		netdev_err(port->ndev, "Invalid port no: %d\n", port->portno);
	}
}

void sparx5_update_fwd(struct sparx5 *sparx5)
{
	DECLARE_BITMAP(workmask, SPX5_PORTS);
	u32 mask[3];
	int port;

	/* Divide up fwd mask in 32 bit words */
	bitmap_to_arr32(mask, sparx5->bridge_fwd_mask, SPX5_PORTS);

	/* Update flood masks */
	for (port = PGID_UC_FLOOD; port <= PGID_BCAST; port++) {
		spx5_wr(mask[0], sparx5, ANA_AC_PGID_CFG(port));
		spx5_wr(mask[1], sparx5, ANA_AC_PGID_CFG1(port));
		spx5_wr(mask[2], sparx5, ANA_AC_PGID_CFG2(port));
	}

	/* Update SRC masks */
	for (port = 0; port < SPX5_PORTS; port++) {
		if (test_bit(port, sparx5->bridge_fwd_mask)) {
			/* Allow to send to all bridged but self */
			bitmap_copy(workmask, sparx5->bridge_fwd_mask, SPX5_PORTS);
			clear_bit(port, workmask);
			bitmap_to_arr32(mask, workmask, SPX5_PORTS);
			spx5_wr(mask[0], sparx5, ANA_AC_SRC_CFG(port));
			spx5_wr(mask[1], sparx5, ANA_AC_SRC_CFG1(port));
			spx5_wr(mask[2], sparx5, ANA_AC_SRC_CFG2(port));
		} else {
			spx5_wr(0, sparx5, ANA_AC_SRC_CFG(port));
			spx5_wr(0, sparx5, ANA_AC_SRC_CFG1(port));
			spx5_wr(0, sparx5, ANA_AC_SRC_CFG2(port));
		}
	}

	/* Learning enabled only for bridged ports */
	bitmap_and(workmask, sparx5->bridge_fwd_mask,
		   sparx5->bridge_lrn_mask, SPX5_PORTS);
	bitmap_to_arr32(mask, workmask, SPX5_PORTS);

	/* Apply learning mask */
	spx5_wr(mask[0], sparx5, ANA_L2_AUTO_LRN_CFG);
	spx5_wr(mask[1], sparx5, ANA_L2_AUTO_LRN_CFG1);
	spx5_wr(mask[2], sparx5, ANA_L2_AUTO_LRN_CFG2);
}

void sparx5_vlan_port_apply(struct sparx5 *sparx5,
			    struct sparx5_port *port)

{
	u32 val;

	/* Configure PVID, vlan aware */
	val = ANA_CL_VLAN_CTRL_VLAN_AWARE_ENA_SET(port->vlan_aware) |
		ANA_CL_VLAN_CTRL_VLAN_POP_CNT_SET(port->vlan_aware) |
		ANA_CL_VLAN_CTRL_PORT_VID_SET(port->pvid);
	spx5_wr(val, sparx5, ANA_CL_VLAN_CTRL(port->portno));

	val = 0;
	if (port->vlan_aware && !port->pvid)
		/* If port is vlan-aware and tagged, drop untagged and
		 * priority tagged frames.
		 */
		val = ANA_CL_VLAN_FILTER_CTRL_TAG_REQUIRED_ENA_SET(1) |
			ANA_CL_VLAN_FILTER_CTRL_PRIO_CTAG_DIS_SET(1) |
			ANA_CL_VLAN_FILTER_CTRL_PRIO_STAG_DIS_SET(1);
	spx5_wr(val, sparx5,
		ANA_CL_VLAN_FILTER_CTRL(port->portno, 0));

	/* Egress configuration (REW_TAG_CFG): VLAN tag type to 8021Q */
	val = REW_TAG_CTRL_TAG_TPID_CFG_SET(0);
	if (port->vlan_aware) {
		if (port->vid)
			/* Tag all frames except when VID == DEFAULT_VLAN */
			val |= REW_TAG_CTRL_TAG_CFG_SET(1);
		else
			val |= REW_TAG_CTRL_TAG_CFG_SET(3);
	}
	spx5_wr(val, sparx5, REW_TAG_CTRL(port->portno));

	/* Egress VID */
	spx5_rmw(REW_PORT_VLAN_CFG_PORT_VID_SET(port->vid),
		 REW_PORT_VLAN_CFG_PORT_VID,
		 sparx5,
		 REW_PORT_VLAN_CFG(port->portno));
}
