// SPDX-License-Identifier: GPL-2.0+
/*
 *  comedi/drivers/mf6x4.c
 *  Driver for Humusoft MF634 and MF624 Data acquisition cards
 *
 *  COMEDI - Linux Control and Measurement Device Interface
 *  Copyright (C) 2000 David A. Schleef <ds@schleef.org>
 */
/*
 * Driver: mf6x4
 * Description: Humusoft MF634 and MF624 Data acquisition card driver
 * Devices: [Humusoft] MF634 (mf634), MF624 (mf624)
 * Author: Rostislav Lisovy <lisovy@gmail.com>
 * Status: works
 * Updated:
 * Configuration Options: none
 */

#include <linux/module.h>
#include <linux/delay.h>

#include "../comedi_pci.h"

/* Registers present in BAR0 memory region */
#define MF624_GPIOC_REG		0x54

#define MF6X4_GPIOC_EOLC	BIT(17)	/* End Of Last Conversion */
#define MF6X4_GPIOC_LDAC	BIT(23)	/* Load DACs */
#define MF6X4_GPIOC_DACEN	BIT(26)

/* BAR1 registers */
#define MF6X4_ADDATA_REG	0x00
#define MF6X4_ADCTRL_REG	0x00
#define MF6X4_ADCTRL_CHAN(x)	BIT(chan)
#define MF6X4_DIN_REG		0x10
#define MF6X4_DIN_MASK		0xff
#define MF6X4_DOUT_REG		0x10
#define MF6X4_ADSTART_REG	0x20
#define MF6X4_DAC_REG(x)	(0x20 + ((x) * 2))

/* BAR2 registers */
#define MF634_GPIOC_REG		0x68

enum mf6x4_boardid {
	BOARD_MF634,
	BOARD_MF624,
};

struct mf6x4_board {
	const char *name;
	/* We need to keep track of the order of BARs used by the cards */
	unsigned int bar_nums[3];
};

static const struct mf6x4_board mf6x4_boards[] = {
	[BOARD_MF634] = {
		.name           = "mf634",
		.bar_nums	= {0, 2, 3},
	},
	[BOARD_MF624] = {
		.name           = "mf624",
		.bar_nums	= {0, 2, 4},
	},
};

struct mf6x4_private {
	/*
	 * Documentation for both MF634 and MF624 describes registers
	 * present in BAR0, 1 and 2 regions.
	 * The real (i.e. in HW) BAR numbers are different for MF624
	 * and MF634 yet we will call them 0, 1, 2
	 */
	void __iomem *bar0_mem;
	void __iomem *bar2_mem;

	/*
	 * This configuration register has the same function and fields
	 * for both cards however it lies in different BARs on different
	 * offsets -- this variable makes the access easier
	 */
	void __iomem *gpioc_reg;
};

static int mf6x4_di_insn_bits(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn,
			      unsigned int *data)
{
	data[1] = ioread16(dev->mmio + MF6X4_DIN_REG) & MF6X4_DIN_MASK;

	return insn->n;
}

static int mf6x4_do_insn_bits(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn,
			      unsigned int *data)
{
	if (comedi_dio_update_state(s, data))
		iowrite16(s->state, dev->mmio + MF6X4_DOUT_REG);

	data[1] = s->state;

	return insn->n;
}

static int mf6x4_ai_eoc(struct comedi_device *dev,
			struct comedi_subdevice *s,
			struct comedi_insn *insn,
			unsigned long context)
{
	struct mf6x4_private *devpriv = dev->private;
	unsigned int status;

	status = ioread32(devpriv->gpioc_reg);
	if (status & MF6X4_GPIOC_EOLC)
		return 0;
	return -EBUSY;
}

static int mf6x4_ai_insn_read(struct comedi_device *dev,
			      struct comedi_subdevice *s,
			      struct comedi_insn *insn,
			      unsigned int *data)
{
	unsigned int chan = CR_CHAN(insn->chanspec);
	unsigned int d;
	int ret;
	int i;

	/* Set the ADC channel number in the scan list */
	iowrite16(MF6X4_ADCTRL_CHAN(chan), dev->mmio + MF6X4_ADCTRL_REG);

	for (i = 0; i < insn->n; i++) {
		/* Trigger ADC conversion by reading ADSTART */
		ioread16(dev->mmio + MF6X4_ADSTART_REG);

		ret = comedi_timeout(dev, s, insn, mf6x4_ai_eoc, 0);
		if (ret)
			return ret;

		/* Read the actual value */
		d = ioread16(dev->mmio + MF6X4_ADDATA_REG);
		d &= s->maxdata;
		/* munge the 2's complement data to offset binary */
		data[i] = comedi_offset_munge(s, d);
	}

	iowrite16(0x0, dev->mmio + MF6X4_ADCTRL_REG);

	return insn->n;
}

static int mf6x4_ao_insn_write(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{
	struct mf6x4_private *devpriv = dev->private;
	unsigned int chan = CR_CHAN(insn->chanspec);
	unsigned int val = s->readback[chan];
	unsigned int gpioc;
	int i;

	/* Enable instantaneous update of converters outputs + Enable DACs */
	gpioc = ioread32(devpriv->gpioc_reg);
	iowrite32((gpioc & ~MF6X4_GPIOC_LDAC) | MF6X4_GPIOC_DACEN,
		  devpriv->gpioc_reg);

	for (i = 0; i < insn->n; i++) {
		val = data[i];
		iowrite16(val, dev->mmio + MF6X4_DAC_REG(chan));
	}
	s->readback[chan] = val;

	return insn->n;
}

static int mf6x4_auto_attach(struct comedi_device *dev, unsigned long context)
{
	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
	const struct mf6x4_board *board = NULL;
	struct mf6x4_private *devpriv;
	struct comedi_subdevice *s;
	int ret;

	if (context < ARRAY_SIZE(mf6x4_boards))
		board = &mf6x4_boards[context];
	else
		return -ENODEV;

	dev->board_ptr = board;
	dev->board_name = board->name;

	ret = comedi_pci_enable(dev);
	if (ret)
		return ret;

	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
	if (!devpriv)
		return -ENOMEM;

	devpriv->bar0_mem = pci_ioremap_bar(pcidev, board->bar_nums[0]);
	if (!devpriv->bar0_mem)
		return -ENODEV;

	dev->mmio = pci_ioremap_bar(pcidev, board->bar_nums[1]);
	if (!dev->mmio)
		return -ENODEV;

	devpriv->bar2_mem = pci_ioremap_bar(pcidev, board->bar_nums[2]);
	if (!devpriv->bar2_mem)
		return -ENODEV;

	if (board == &mf6x4_boards[BOARD_MF634])
		devpriv->gpioc_reg = devpriv->bar2_mem + MF634_GPIOC_REG;
	else
		devpriv->gpioc_reg = devpriv->bar0_mem + MF624_GPIOC_REG;

	ret = comedi_alloc_subdevices(dev, 4);
	if (ret)
		return ret;

	/* Analog Input subdevice */
	s = &dev->subdevices[0];
	s->type		= COMEDI_SUBD_AI;
	s->subdev_flags	= SDF_READABLE | SDF_GROUND;
	s->n_chan	= 8;
	s->maxdata	= 0x3fff;
	s->range_table	= &range_bipolar10;
	s->insn_read	= mf6x4_ai_insn_read;

	/* Analog Output subdevice */
	s = &dev->subdevices[1];
	s->type		= COMEDI_SUBD_AO;
	s->subdev_flags	= SDF_WRITABLE;
	s->n_chan	= 8;
	s->maxdata	= 0x3fff;
	s->range_table	= &range_bipolar10;
	s->insn_write	= mf6x4_ao_insn_write;

	ret = comedi_alloc_subdev_readback(s);
	if (ret)
		return ret;

	/* Digital Input subdevice */
	s = &dev->subdevices[2];
	s->type		= COMEDI_SUBD_DI;
	s->subdev_flags	= SDF_READABLE;
	s->n_chan	= 8;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= mf6x4_di_insn_bits;

	/* Digital Output subdevice */
	s = &dev->subdevices[3];
	s->type		= COMEDI_SUBD_DO;
	s->subdev_flags	= SDF_WRITABLE;
	s->n_chan	= 8;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= mf6x4_do_insn_bits;

	return 0;
}

static void mf6x4_detach(struct comedi_device *dev)
{
	struct mf6x4_private *devpriv = dev->private;

	if (devpriv) {
		if (devpriv->bar0_mem)
			iounmap(devpriv->bar0_mem);
		if (devpriv->bar2_mem)
			iounmap(devpriv->bar2_mem);
	}
	comedi_pci_detach(dev);
}

static struct comedi_driver mf6x4_driver = {
	.driver_name    = "mf6x4",
	.module         = THIS_MODULE,
	.auto_attach    = mf6x4_auto_attach,
	.detach         = mf6x4_detach,
};

static int mf6x4_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
{
	return comedi_pci_auto_config(dev, &mf6x4_driver, id->driver_data);
}

static const struct pci_device_id mf6x4_pci_table[] = {
	{ PCI_VDEVICE(HUMUSOFT, 0x0634), BOARD_MF634 },
	{ PCI_VDEVICE(HUMUSOFT, 0x0624), BOARD_MF624 },
	{ 0 }
};
MODULE_DEVICE_TABLE(pci, mf6x4_pci_table);

static struct pci_driver mf6x4_pci_driver = {
	.name           = "mf6x4",
	.id_table       = mf6x4_pci_table,
	.probe          = mf6x4_pci_probe,
	.remove         = comedi_pci_auto_unconfig,
};

module_comedi_pci_driver(mf6x4_driver, mf6x4_pci_driver);

MODULE_AUTHOR("Rostislav Lisovy <lisovy@gmail.com>");
MODULE_DESCRIPTION("Comedi MF634 and MF624 DAQ cards driver");
MODULE_LICENSE("GPL");
