// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * netup_unidvb_spi.c
 *
 * Internal SPI driver for NetUP Universal Dual DVB-CI
 *
 * Copyright (C) 2014 NetUP Inc.
 * Copyright (C) 2014 Sergey Kozlov <serjk@netup.ru>
 * Copyright (C) 2014 Abylay Ospan <aospan@netup.ru>
 */

#include "netup_unidvb.h"
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <linux/mtd/partitions.h>
#include <mtd/mtd-abi.h>

#define NETUP_SPI_CTRL_IRQ	0x1000
#define NETUP_SPI_CTRL_IMASK	0x2000
#define NETUP_SPI_CTRL_START	0x8000
#define NETUP_SPI_CTRL_LAST_CS	0x4000

#define NETUP_SPI_TIMEOUT	6000

enum netup_spi_state {
	SPI_STATE_START,
	SPI_STATE_DONE,
};

struct netup_spi_regs {
	__u8	data[1024];
	__le16	control_stat;
	__le16	clock_divider;
} __packed __aligned(1);

struct netup_spi {
	struct device			*dev;
	struct spi_master		*master;
	struct netup_spi_regs __iomem	*regs;
	u8 __iomem			*mmio;
	spinlock_t			lock;
	wait_queue_head_t		waitq;
	enum netup_spi_state		state;
};

static char netup_spi_name[64] = "fpga";

static struct mtd_partition netup_spi_flash_partitions = {
	.name = netup_spi_name,
	.size = 0x1000000, /* 16MB */
	.offset = 0,
	.mask_flags = MTD_CAP_ROM
};

static struct flash_platform_data spi_flash_data = {
	.name = "netup0_m25p128",
	.parts = &netup_spi_flash_partitions,
	.nr_parts = 1,
};

static struct spi_board_info netup_spi_board = {
	.modalias = "m25p128",
	.max_speed_hz = 11000000,
	.chip_select = 0,
	.mode = SPI_MODE_0,
	.platform_data = &spi_flash_data,
};

irqreturn_t netup_spi_interrupt(struct netup_spi *spi)
{
	u16 reg;
	unsigned long flags;

	if (!spi)
		return IRQ_NONE;

	spin_lock_irqsave(&spi->lock, flags);
	reg = readw(&spi->regs->control_stat);
	if (!(reg & NETUP_SPI_CTRL_IRQ)) {
		spin_unlock_irqrestore(&spi->lock, flags);
		dev_dbg(&spi->master->dev,
			"%s(): not mine interrupt\n", __func__);
		return IRQ_NONE;
	}
	writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
	reg = readw(&spi->regs->control_stat);
	writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat);
	spi->state = SPI_STATE_DONE;
	wake_up(&spi->waitq);
	spin_unlock_irqrestore(&spi->lock, flags);
	dev_dbg(&spi->master->dev,
		"%s(): SPI interrupt handled\n", __func__);
	return IRQ_HANDLED;
}

static int netup_spi_transfer(struct spi_master *master,
			      struct spi_message *msg)
{
	struct netup_spi *spi = spi_master_get_devdata(master);
	struct spi_transfer *t;
	int result = 0;
	u32 tr_size;

	/* reset CS */
	writew(NETUP_SPI_CTRL_LAST_CS, &spi->regs->control_stat);
	writew(0, &spi->regs->control_stat);
	list_for_each_entry(t, &msg->transfers, transfer_list) {
		tr_size = t->len;
		while (tr_size) {
			u32 frag_offset = t->len - tr_size;
			u32 frag_size = (tr_size > sizeof(spi->regs->data)) ?
					sizeof(spi->regs->data) : tr_size;
			int frag_last = 0;

			if (list_is_last(&t->transfer_list,
					&msg->transfers) &&
					frag_offset + frag_size == t->len) {
				frag_last = 1;
			}
			if (t->tx_buf) {
				memcpy_toio(spi->regs->data,
					t->tx_buf + frag_offset,
					frag_size);
			} else {
				memset_io(spi->regs->data,
					0, frag_size);
			}
			spi->state = SPI_STATE_START;
			writew((frag_size & 0x3ff) |
				NETUP_SPI_CTRL_IMASK |
				NETUP_SPI_CTRL_START |
				(frag_last ? NETUP_SPI_CTRL_LAST_CS : 0),
				&spi->regs->control_stat);
			dev_dbg(&spi->master->dev,
				"%s(): control_stat 0x%04x\n",
				__func__, readw(&spi->regs->control_stat));
			wait_event_timeout(spi->waitq,
				spi->state != SPI_STATE_START,
				msecs_to_jiffies(NETUP_SPI_TIMEOUT));
			if (spi->state == SPI_STATE_DONE) {
				if (t->rx_buf) {
					memcpy_fromio(t->rx_buf + frag_offset,
						spi->regs->data, frag_size);
				}
			} else {
				if (spi->state == SPI_STATE_START) {
					dev_dbg(&spi->master->dev,
						"%s(): transfer timeout\n",
						__func__);
				} else {
					dev_dbg(&spi->master->dev,
						"%s(): invalid state %d\n",
						__func__, spi->state);
				}
				result = -EIO;
				goto done;
			}
			tr_size -= frag_size;
			msg->actual_length += frag_size;
		}
	}
done:
	msg->status = result;
	spi_finalize_current_message(master);
	return result;
}

static int netup_spi_setup(struct spi_device *spi)
{
	return 0;
}

int netup_spi_init(struct netup_unidvb_dev *ndev)
{
	struct spi_master *master;
	struct netup_spi *nspi;

	master = spi_alloc_master(&ndev->pci_dev->dev,
		sizeof(struct netup_spi));
	if (!master) {
		dev_err(&ndev->pci_dev->dev,
			"%s(): unable to alloc SPI master\n", __func__);
		return -EINVAL;
	}
	nspi = spi_master_get_devdata(master);
	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST;
	master->bus_num = -1;
	master->num_chipselect = 1;
	master->transfer_one_message = netup_spi_transfer;
	master->setup = netup_spi_setup;
	spin_lock_init(&nspi->lock);
	init_waitqueue_head(&nspi->waitq);
	nspi->master = master;
	nspi->regs = (struct netup_spi_regs __iomem *)(ndev->bmmio0 + 0x4000);
	writew(2, &nspi->regs->clock_divider);
	writew(NETUP_UNIDVB_IRQ_SPI, ndev->bmmio0 + REG_IMASK_SET);
	ndev->spi = nspi;
	if (spi_register_master(master)) {
		ndev->spi = NULL;
		dev_err(&ndev->pci_dev->dev,
			"%s(): unable to register SPI bus\n", __func__);
		return -EINVAL;
	}
	snprintf(netup_spi_name,
		sizeof(netup_spi_name),
		"fpga_%02x:%02x.%01x",
		ndev->pci_bus,
		ndev->pci_slot,
		ndev->pci_func);
	if (!spi_new_device(master, &netup_spi_board)) {
		ndev->spi = NULL;
		dev_err(&ndev->pci_dev->dev,
			"%s(): unable to create SPI device\n", __func__);
		return -EINVAL;
	}
	dev_dbg(&ndev->pci_dev->dev, "%s(): SPI init OK\n", __func__);
	return 0;
}

void netup_spi_release(struct netup_unidvb_dev *ndev)
{
	u16 reg;
	unsigned long flags;
	struct netup_spi *spi = ndev->spi;

	if (!spi)
		return;

	spin_lock_irqsave(&spi->lock, flags);
	reg = readw(&spi->regs->control_stat);
	writew(reg | NETUP_SPI_CTRL_IRQ, &spi->regs->control_stat);
	reg = readw(&spi->regs->control_stat);
	writew(reg & ~NETUP_SPI_CTRL_IMASK, &spi->regs->control_stat);
	spin_unlock_irqrestore(&spi->lock, flags);
	spi_unregister_master(spi->master);
	ndev->spi = NULL;
}


