// 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 = devm_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)) {
		spi_unregister_master(master);
		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;

	spi_unregister_master(spi->master);
	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);
	ndev->spi = NULL;
}


