// SPDX-License-Identifier: GPL-2.0
/*
 * This file is based on code from OCTEON SDK by Cavium Networks.
 *
 * Copyright (c) 2003-2007 Cavium Networks
 */

#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/interrupt.h>
#include <linux/phy.h>
#include <linux/ratelimit.h>
#include <net/dst.h>

#include <asm/octeon/octeon.h>

#include "ethernet-defines.h"
#include "octeon-ethernet.h"
#include "ethernet-util.h"
#include "ethernet-mdio.h"

#include <asm/octeon/cvmx-helper.h>

#include <asm/octeon/cvmx-ipd-defs.h>
#include <asm/octeon/cvmx-npi-defs.h>
#include <asm/octeon/cvmx-gmxx-defs.h>

static DEFINE_SPINLOCK(global_register_lock);

static void cvm_oct_set_hw_preamble(struct octeon_ethernet *priv, bool enable)
{
	union cvmx_gmxx_rxx_frm_ctl gmxx_rxx_frm_ctl;
	union cvmx_ipd_sub_port_fcs ipd_sub_port_fcs;
	union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;
	int interface = INTERFACE(priv->port);
	int index = INDEX(priv->port);

	/* Set preamble checking. */
	gmxx_rxx_frm_ctl.u64 = cvmx_read_csr(CVMX_GMXX_RXX_FRM_CTL(index,
								   interface));
	gmxx_rxx_frm_ctl.s.pre_chk = enable;
	cvmx_write_csr(CVMX_GMXX_RXX_FRM_CTL(index, interface),
		       gmxx_rxx_frm_ctl.u64);

	/* Set FCS stripping. */
	ipd_sub_port_fcs.u64 = cvmx_read_csr(CVMX_IPD_SUB_PORT_FCS);
	if (enable)
		ipd_sub_port_fcs.s.port_bit |= 1ull << priv->port;
	else
		ipd_sub_port_fcs.s.port_bit &=
					0xffffffffull ^ (1ull << priv->port);
	cvmx_write_csr(CVMX_IPD_SUB_PORT_FCS, ipd_sub_port_fcs.u64);

	/* Clear any error bits. */
	gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG(index,
								   interface));
	cvmx_write_csr(CVMX_GMXX_RXX_INT_REG(index, interface),
		       gmxx_rxx_int_reg.u64);
}

static void cvm_oct_check_preamble_errors(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	cvmx_helper_link_info_t link_info;
	unsigned long flags;

	link_info.u64 = priv->link_info;

	/*
	 * Take the global register lock since we are going to
	 * touch registers that affect more than one port.
	 */
	spin_lock_irqsave(&global_register_lock, flags);

	if (link_info.s.speed == 10 && priv->last_speed == 10) {
		/*
		 * Read the GMXX_RXX_INT_REG[PCTERR] bit and see if we are
		 * getting preamble errors.
		 */
		int interface = INTERFACE(priv->port);
		int index = INDEX(priv->port);
		union cvmx_gmxx_rxx_int_reg gmxx_rxx_int_reg;

		gmxx_rxx_int_reg.u64 = cvmx_read_csr(CVMX_GMXX_RXX_INT_REG
							(index, interface));
		if (gmxx_rxx_int_reg.s.pcterr) {
			/*
			 * We are getting preamble errors at 10Mbps. Most
			 * likely the PHY is giving us packets with misaligned
			 * preambles. In order to get these packets we need to
			 * disable preamble checking and do it in software.
			 */
			cvm_oct_set_hw_preamble(priv, false);
			printk_ratelimited("%s: Using 10Mbps with software preamble removal\n",
					   dev->name);
		}
	} else {
		/*
		 * Since the 10Mbps preamble workaround is allowed we need to
		 * enable preamble checking, FCS stripping, and clear error
		 * bits on every speed change. If errors occur during 10Mbps
		 * operation the above code will change this stuff
		 */
		if (priv->last_speed != link_info.s.speed)
			cvm_oct_set_hw_preamble(priv, true);
		priv->last_speed = link_info.s.speed;
	}
	spin_unlock_irqrestore(&global_register_lock, flags);
}

static void cvm_oct_rgmii_poll(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	cvmx_helper_link_info_t link_info;
	bool status_change;

	link_info = cvmx_helper_link_get(priv->port);
	if (priv->link_info != link_info.u64 &&
	    cvmx_helper_link_set(priv->port, link_info))
		link_info.u64 = priv->link_info;
	status_change = priv->link_info != link_info.u64;
	priv->link_info = link_info.u64;

	cvm_oct_check_preamble_errors(dev);

	if (likely(!status_change))
		return;

	/* Tell core. */
	if (link_info.s.link_up) {
		if (!netif_carrier_ok(dev))
			netif_carrier_on(dev);
	} else if (netif_carrier_ok(dev)) {
		netif_carrier_off(dev);
	}
	cvm_oct_note_carrier(priv, link_info);
}

int cvm_oct_rgmii_open(struct net_device *dev)
{
	struct octeon_ethernet *priv = netdev_priv(dev);
	int ret;

	ret = cvm_oct_common_open(dev, cvm_oct_rgmii_poll);
	if (ret)
		return ret;

	if (dev->phydev) {
		/*
		 * In phydev mode, we need still periodic polling for the
		 * preamble error checking, and we also need to call this
		 * function on every link state change.
		 *
		 * Only true RGMII ports need to be polled. In GMII mode, port
		 * 0 is really a RGMII port.
		 */
		if ((priv->imode == CVMX_HELPER_INTERFACE_MODE_GMII &&
		     priv->port  == 0) ||
		    (priv->imode == CVMX_HELPER_INTERFACE_MODE_RGMII)) {
			priv->poll = cvm_oct_check_preamble_errors;
			cvm_oct_check_preamble_errors(dev);
		}
	}

	return 0;
}
