/*
 * This file is based on code from OCTEON SDK by Cavium Networks.
 *
 * Copyright (c) 2003-2007 Cavium Networks
 *
 * This file is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, Version 2, as
 * published by the Free Software Foundation.
 */

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

#include <asm/octeon/octeon.h>

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

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

#include <asm/octeon/cvmx-npi-defs.h>
#include <asm/octeon/cvmx-spxx-defs.h>
#include <asm/octeon/cvmx-stxx-defs.h>

static int number_spi_ports;
static int need_retrain[2] = { 0, 0 };

static void cvm_oct_spxx_int_pr(union cvmx_spxx_int_reg spx_int_reg, int index)
{
	if (spx_int_reg.s.spf)
		pr_err("SPI%d: SRX Spi4 interface down\n", index);
	if (spx_int_reg.s.calerr)
		pr_err("SPI%d: SRX Spi4 Calendar table parity error\n", index);
	if (spx_int_reg.s.syncerr)
		pr_err("SPI%d: SRX Consecutive Spi4 DIP4 errors have exceeded SPX_ERR_CTL[ERRCNT]\n",
		       index);
	if (spx_int_reg.s.diperr)
		pr_err("SPI%d: SRX Spi4 DIP4 error\n", index);
	if (spx_int_reg.s.tpaovr)
		pr_err("SPI%d: SRX Selected port has hit TPA overflow\n",
		       index);
	if (spx_int_reg.s.rsverr)
		pr_err("SPI%d: SRX Spi4 reserved control word detected\n",
		       index);
	if (spx_int_reg.s.drwnng)
		pr_err("SPI%d: SRX Spi4 receive FIFO drowning/overflow\n",
		       index);
	if (spx_int_reg.s.clserr)
		pr_err("SPI%d: SRX Spi4 packet closed on non-16B alignment without EOP\n",
		       index);
	if (spx_int_reg.s.spiovr)
		pr_err("SPI%d: SRX Spi4 async FIFO overflow\n", index);
	if (spx_int_reg.s.abnorm)
		pr_err("SPI%d: SRX Abnormal packet termination (ERR bit)\n",
		       index);
	if (spx_int_reg.s.prtnxa)
		pr_err("SPI%d: SRX Port out of range\n", index);
}

static void cvm_oct_stxx_int_pr(union cvmx_stxx_int_reg stx_int_reg, int index)
{
	if (stx_int_reg.s.syncerr)
		pr_err("SPI%d: STX Interface encountered a fatal error\n",
		       index);
	if (stx_int_reg.s.frmerr)
		pr_err("SPI%d: STX FRMCNT has exceeded STX_DIP_CNT[MAXFRM]\n",
		       index);
	if (stx_int_reg.s.unxfrm)
		pr_err("SPI%d: STX Unexpected framing sequence\n", index);
	if (stx_int_reg.s.nosync)
		pr_err("SPI%d: STX ERRCNT has exceeded STX_DIP_CNT[MAXDIP]\n",
		       index);
	if (stx_int_reg.s.diperr)
		pr_err("SPI%d: STX DIP2 error on the Spi4 Status channel\n",
		       index);
	if (stx_int_reg.s.datovr)
		pr_err("SPI%d: STX Spi4 FIFO overflow error\n", index);
	if (stx_int_reg.s.ovrbst)
		pr_err("SPI%d: STX Transmit packet burst too big\n", index);
	if (stx_int_reg.s.calpar1)
		pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
		       index, 1);
	if (stx_int_reg.s.calpar0)
		pr_err("SPI%d: STX Calendar Table Parity Error Bank%d\n",
		       index, 0);
}

static irqreturn_t cvm_oct_spi_spx_int(int index)
{
	union cvmx_spxx_int_reg spx_int_reg;
	union cvmx_stxx_int_reg stx_int_reg;

	spx_int_reg.u64 = cvmx_read_csr(CVMX_SPXX_INT_REG(index));
	cvmx_write_csr(CVMX_SPXX_INT_REG(index), spx_int_reg.u64);
	if (!need_retrain[index]) {
		spx_int_reg.u64 &= cvmx_read_csr(CVMX_SPXX_INT_MSK(index));
		cvm_oct_spxx_int_pr(spx_int_reg, index);
	}

	stx_int_reg.u64 = cvmx_read_csr(CVMX_STXX_INT_REG(index));
	cvmx_write_csr(CVMX_STXX_INT_REG(index), stx_int_reg.u64);
	if (!need_retrain[index]) {
		stx_int_reg.u64 &= cvmx_read_csr(CVMX_STXX_INT_MSK(index));
		cvm_oct_stxx_int_pr(stx_int_reg, index);
	}

	cvmx_write_csr(CVMX_SPXX_INT_MSK(index), 0);
	cvmx_write_csr(CVMX_STXX_INT_MSK(index), 0);
	need_retrain[index] = 1;

	return IRQ_HANDLED;
}

static irqreturn_t cvm_oct_spi_rml_interrupt(int cpl, void *dev_id)
{
	irqreturn_t return_status = IRQ_NONE;
	union cvmx_npi_rsl_int_blocks rsl_int_blocks;

	/* Check and see if this interrupt was caused by the GMX block */
	rsl_int_blocks.u64 = cvmx_read_csr(CVMX_NPI_RSL_INT_BLOCKS);
	if (rsl_int_blocks.s.spx1) /* 19 - SPX1_INT_REG & STX1_INT_REG */
		return_status = cvm_oct_spi_spx_int(1);

	if (rsl_int_blocks.s.spx0) /* 18 - SPX0_INT_REG & STX0_INT_REG */
		return_status = cvm_oct_spi_spx_int(0);

	return return_status;
}

static void cvm_oct_spi_enable_error_reporting(int interface)
{
	union cvmx_spxx_int_msk spxx_int_msk;
	union cvmx_stxx_int_msk stxx_int_msk;

	spxx_int_msk.u64 = cvmx_read_csr(CVMX_SPXX_INT_MSK(interface));
	spxx_int_msk.s.calerr = 1;
	spxx_int_msk.s.syncerr = 1;
	spxx_int_msk.s.diperr = 1;
	spxx_int_msk.s.tpaovr = 1;
	spxx_int_msk.s.rsverr = 1;
	spxx_int_msk.s.drwnng = 1;
	spxx_int_msk.s.clserr = 1;
	spxx_int_msk.s.spiovr = 1;
	spxx_int_msk.s.abnorm = 1;
	spxx_int_msk.s.prtnxa = 1;
	cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), spxx_int_msk.u64);

	stxx_int_msk.u64 = cvmx_read_csr(CVMX_STXX_INT_MSK(interface));
	stxx_int_msk.s.frmerr = 1;
	stxx_int_msk.s.unxfrm = 1;
	stxx_int_msk.s.nosync = 1;
	stxx_int_msk.s.diperr = 1;
	stxx_int_msk.s.datovr = 1;
	stxx_int_msk.s.ovrbst = 1;
	stxx_int_msk.s.calpar1 = 1;
	stxx_int_msk.s.calpar0 = 1;
	cvmx_write_csr(CVMX_STXX_INT_MSK(interface), stxx_int_msk.u64);
}

static void cvm_oct_spi_poll(struct net_device *dev)
{
	static int spi4000_port;
	struct octeon_ethernet *priv = netdev_priv(dev);
	int interface;

	for (interface = 0; interface < 2; interface++) {

		if ((priv->port == interface * 16) && need_retrain[interface]) {

			if (cvmx_spi_restart_interface
			    (interface, CVMX_SPI_MODE_DUPLEX, 10) == 0) {
				need_retrain[interface] = 0;
				cvm_oct_spi_enable_error_reporting(interface);
			}
		}

		/*
		 * The SPI4000 TWSI interface is very slow. In order
		 * not to bring the system to a crawl, we only poll a
		 * single port every second. This means negotiation
		 * speed changes take up to 10 seconds, but at least
		 * we don't waste absurd amounts of time waiting for
		 * TWSI.
		 */
		if (priv->port == spi4000_port) {
			/*
			 * This function does nothing if it is called on an
			 * interface without a SPI4000.
			 */
			cvmx_spi4000_check_speed(interface, priv->port);
			/*
			 * Normal ordering increments. By decrementing
			 * we only match once per iteration.
			 */
			spi4000_port--;
			if (spi4000_port < 0)
				spi4000_port = 10;
		}
	}
}

int cvm_oct_spi_init(struct net_device *dev)
{
	int r;
	struct octeon_ethernet *priv = netdev_priv(dev);

	if (number_spi_ports == 0) {
		r = request_irq(OCTEON_IRQ_RML, cvm_oct_spi_rml_interrupt,
				IRQF_SHARED, "SPI", &number_spi_ports);
		if (r)
			return r;
	}
	number_spi_ports++;

	if ((priv->port == 0) || (priv->port == 16)) {
		cvm_oct_spi_enable_error_reporting(INTERFACE(priv->port));
		priv->poll = cvm_oct_spi_poll;
	}
	cvm_oct_common_init(dev);
	return 0;
}

void cvm_oct_spi_uninit(struct net_device *dev)
{
	int interface;

	cvm_oct_common_uninit(dev);
	number_spi_ports--;
	if (number_spi_ports == 0) {
		for (interface = 0; interface < 2; interface++) {
			cvmx_write_csr(CVMX_SPXX_INT_MSK(interface), 0);
			cvmx_write_csr(CVMX_STXX_INT_MSK(interface), 0);
		}
		free_irq(OCTEON_IRQ_RML, &number_spi_ports);
	}
}
