/*
 * Copyright (C) 2013 Google Inc.
 *
 * This program 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.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#ifndef __BBSI_H
#define __BBSI_H

#include <linux/netdevice.h>
#include <linux/spi/spi.h>
#include <linux/vmalloc.h>

#ifndef KSEG1
#define KSEG1 0  // just to appease non-MIPS CPUs. Not really used.
#endif

#define BP_MOCA_MAX_NUM 1

/*
 * The exact values here don't matter, as they're translated into "real"
 * values before talking to mocad.  This is just for the device registration
 * tables.
 */
enum {
	BP_MOCA_TYPE_WAN,
	BP_MOCA_TYPE_LAN,
};

enum {
	BP_MOCA_RF_BAND_D_LOW,
	BP_MOCA_RF_BAND_D_HIGH,
	BP_MOCA_RF_BAND_EXT_D,
	BP_MOCA_RF_BAND_E,
	BP_MOCA_RF_BAND_F,
};

typedef struct BpMocaInfo {
	int type;
	int rfBand;
} BP_MOCA_INFO;

static void BpGetMocaInfo(BP_MOCA_INFO *chips, int *nchips) {
	if (*nchips >= 1) {
		*nchips = 1;
		chips[0].type = BP_MOCA_TYPE_LAN;
		chips[0].rfBand = BP_MOCA_RF_BAND_E;
	}
}

static uint32_t _spi_read32(struct spi_device *spi, uint32_t addr);


// TODO(apenwarr): don't make this global.
//   Or fix the driver to just only enable/disable interrupts at the right
//   times.
static int irq_disabled = 0;

static void kerSysMocaHostIntrEnable(struct spi_device *spi) {
	if (irq_disabled == 1) {
		irq_disabled = 0;
		enable_irq(spi->irq);
	}
}

static void kerSysMocaHostIntrDisable(struct spi_device *spi) {
	if (irq_disabled == 0) {
		disable_irq_nosync(spi->irq);
		irq_disabled = 1;
	}
}

static uint8_t __pollstatus(struct spi_device *spi) {
	uint8_t wclear[] = { 0x80, 0x06 };
	uint8_t rdata[1] = { 0 };
	struct spi_transfer t[2] = {
		{ .tx_buf = wclear, .len = sizeof(wclear) },
		{ .rx_buf = rdata, .len = sizeof(rdata) },
	};
	struct spi_message m;
	int i;

	spi_message_init(&m);
	spi_message_add_tail(&t[0], &m);
	spi_message_add_tail(&t[1], &m);

	for (i = 0; i < 10; i++) {
		if (spi_sync_locked(spi, &m) < 0) {
			pr_warn("spi _pollstatus: SPI error\n");
			return 0x01; // error code
		}
		if (rdata[0] & 0x01) {
			pr_warn("spi _pollstatus: rbus error: %02X\n", rdata[0]);
			return 0x01; // error result; stop polling now
		}
		if (!(rdata[0] & 0x10)) return 0;   // transaction finished
	}
	// if we get here, the transaction still isn't finished: weird
	pr_warn("spi _pollstatus: still busy: %02X\n", rdata[0]);
	return rdata[0];
}

static uint32_t __spi_read32a(struct spi_device *spi, uint32_t addr,
				int speculative) {
	uint8_t waddr[] = {
		0x81, 0x07,
		0x01 | (speculative ? 0x02 : 0),
		0, 0, 0, 0 };
	struct spi_transfer addrt[1] = {
		{ .tx_buf = waddr, .len = sizeof(waddr) },
	};
	struct spi_message addrm;
	int j, st;

	spi_message_init(&addrm);
	spi_message_add_tail(&addrt[0], &addrm);

	__pollstatus(spi);
	for (j = 0; j < 10; j++) {
		// write address reg, which triggers the read
		writel(cpu_to_be32(addr), waddr + sizeof(waddr) - 4);
		if (spi_sync_locked(spi, &addrm) < 0) {
			pr_warn("spi_read_addr: error\n");
		}
		st = __pollstatus(spi);
		if (!st) break;
	}
	return st;
}

static uint32_t __spi_read32d_noswap(struct spi_device *spi) {
	uint8_t wdata[] = { 0x80, 0x0c };
	uint8_t rdata[4];
	struct spi_transfer datat[2] = {
		{ .tx_buf = wdata, .len = sizeof(wdata) },
		{ .rx_buf = rdata, .len = sizeof(rdata) },
	};
	struct spi_message datam;

	spi_message_init(&datam);
	spi_message_add_tail(&datat[0], &datam);
	spi_message_add_tail(&datat[1], &datam);

	// retrieve actual data bits
	if (spi_sync_locked(spi, &datam) < 0) {
		pr_warn("spi_read_data: error\n");
	}
	return readl(rdata);
}

static uint32_t _spi_read32(struct spi_device *spi, uint32_t addr) {
	int st;
	uint32_t retval;

	spi_bus_lock(spi->master);

	st = __spi_read32a(spi, addr, 0);
	if (st) {
		retval = 0x00000000; // error
	} else {
		retval = be32_to_cpu(__spi_read32d_noswap(spi));
	}
	spi_bus_unlock(spi->master);
	return retval;
}

static void __spi_write32a(struct spi_device *spi, uint32_t addr) {
	uint8_t waddr[] = { 0x81, 0x07, 0x00, 0, 0, 0, 0  };
	struct spi_transfer t[1] = {
		{ .tx_buf = waddr, .len = sizeof(waddr) },
	};
	struct spi_message m;

	spi_message_init(&m);
	spi_message_add_tail(&t[0], &m);

	// write address reg
	writel(cpu_to_be32(addr), waddr + sizeof(waddr) - 4);
	if (spi_sync_locked(spi, &m) < 0) {
		pr_warn("spi_write: error\n");
	}
}

static void __spi_write32d_noswap(struct spi_device *spi, uint32_t value) {
	uint8_t wdata[] = { 0x81, 0x0c, 0, 0, 0, 0 };
	struct spi_transfer t[1] = {
		{ .tx_buf = wdata, .len = sizeof(wdata) },
	};
	struct spi_message m;

	spi_message_init(&m);
	spi_message_add_tail(&t[0], &m);

	// write data reg
	writel(value, wdata + sizeof(wdata) - 4);
	if (spi_sync_locked(spi, &m) < 0) {
		pr_warn("spi_write: error\n");
	}
}


static void _spi_write32(struct spi_device *spi, uint32_t addr, uint32_t value) {
	spi_bus_lock(spi->master);
	__pollstatus(spi);
	__spi_write32a(spi, addr);
	__spi_write32d_noswap(spi, cpu_to_be32(value));
	__pollstatus(spi);
	spi_bus_unlock(spi->master);
}

static uint32_t kerSysBcmSpiSlaveReadReg32(struct spi_device *spi, uint32_t addr) {
	return _spi_read32(spi, addr);
}

static void kerSysBcmSpiSlaveWriteReg32(struct spi_device *spi, uint32_t addr, uint32_t value) {
	_spi_write32(spi, addr, value);
}

static void kerSysBcmSpiSlaveReadBuf(struct spi_device *spi, uint32_t addr, void *dst, int len, int wordsize) {
	int i;
	uint32_t *buf = dst;

	spi_bus_lock(spi->master);

	if (wordsize != 4) {
		pr_info("SPI readbuf: only word size == 4 bytes is supported!\n");
		return;
	}
	__spi_read32a(spi, addr, 1);
	for (i = 0; i < len; i += wordsize) {
		buf[i/4] = __spi_read32d_noswap(spi);
		__pollstatus(spi);
	}

	spi_bus_unlock(spi->master);
}

static void kerSysBcmSpiSlaveWriteBuf(struct spi_device *spi, uint32_t addr, const void *src, int len, int wordsize) {
	int i, nelems = len/4;
	const uint32_t *buf = src;
	uint8_t wdata[] = { 0x81, 0x0c };
	struct spi_transfer *t, *tp;
	struct spi_message m;

	if (len > 8192) {
		pr_warn("spi writebuf: buffer size %d is too large\n", len);
		return;
	}
	if (wordsize != 4) {
		pr_err("SPI writebuf: only word size == 4 bytes is supported!\n");
		return;
	}

	t = vmalloc(nelems * sizeof(struct spi_transfer) * 2);
	if (!t) {
		pr_warn("spi writebuf: out of memory\n");
		return;
	}

	memset(t, 0, nelems * sizeof(struct spi_transfer) * 2);
	spi_message_init(&m);

	for (i = 0, tp = t; i < nelems; i++) {
		tp->tx_buf = wdata;
		tp->len = sizeof(wdata);
		spi_message_add_tail(tp, &m);
		tp++;

		tp->tx_buf = &buf[i];
		tp->len = 4;
		tp->cs_change = 1;
		spi_message_add_tail(tp, &m);
		tp++;
	}

	spi_bus_lock(spi->master);

	__pollstatus(spi);
	writel(cpu_to_be32(addr), wdata + 2);
	__spi_write32a(spi, addr);
	spi_sync_locked(spi, &m);
	__pollstatus(spi);

	spi_bus_unlock(spi->master);
	vfree(t);
}

#endif // __BBSI_H
