// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * SCR24x PCMCIA Smart Card Reader Driver
 *
 * Copyright (C) 2005-2006 TL Sudheendran
 * Copyright (C) 2016 Lubomir Rintel
 *
 * Derived from "scr24x_v4.2.6_Release.tar.gz" driver by TL Sudheendran.
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/io.h>
#include <linux/uaccess.h>

#include <pcmcia/cistpl.h>
#include <pcmcia/ds.h>

#define CCID_HEADER_SIZE	10
#define CCID_LENGTH_OFFSET	1
#define CCID_MAX_LEN		271

#define SCR24X_DATA(n)		(1 + n)
#define SCR24X_CMD_STATUS	7
#define CMD_START		0x40
#define CMD_WRITE_BYTE		0x41
#define CMD_READ_BYTE		0x42
#define STATUS_BUSY		0x80

struct scr24x_dev {
	struct device *dev;
	struct cdev c_dev;
	unsigned char buf[CCID_MAX_LEN];
	int devno;
	struct mutex lock;
	struct kref refcnt;
	u8 __iomem *regs;
};

#define SCR24X_DEVS 8
static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);

static struct class *scr24x_class;
static dev_t scr24x_devt;

static void scr24x_delete(struct kref *kref)
{
	struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
								refcnt);

	kfree(dev);
}

static int scr24x_wait_ready(struct scr24x_dev *dev)
{
	u_char status;
	int timeout = 100;

	do {
		status = ioread8(dev->regs + SCR24X_CMD_STATUS);
		if (!(status & STATUS_BUSY))
			return 0;

		msleep(20);
	} while (--timeout);

	return -EIO;
}

static int scr24x_open(struct inode *inode, struct file *filp)
{
	struct scr24x_dev *dev = container_of(inode->i_cdev,
				struct scr24x_dev, c_dev);

	kref_get(&dev->refcnt);
	filp->private_data = dev;

	return stream_open(inode, filp);
}

static int scr24x_release(struct inode *inode, struct file *filp)
{
	struct scr24x_dev *dev = filp->private_data;

	/* We must not take the dev->lock here as scr24x_delete()
	 * might be called to remove the dev structure altogether.
	 * We don't need the lock anyway, since after the reference
	 * acquired in probe() is released in remove() the chrdev
	 * is already unregistered and noone can possibly acquire
	 * a reference via open() anymore. */
	kref_put(&dev->refcnt, scr24x_delete);
	return 0;
}

static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
{
	size_t i, y;
	int ret;

	for (i = offset; i < limit; i += 5) {
		iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
		ret = scr24x_wait_ready(dev);
		if (ret < 0)
			return ret;

		for (y = 0; y < 5 && i + y < limit; y++)
			dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
	}

	return 0;
}

static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
								loff_t *ppos)
{
	struct scr24x_dev *dev = filp->private_data;
	int ret;
	int len;

	if (count < CCID_HEADER_SIZE)
		return -EINVAL;

	if (mutex_lock_interruptible(&dev->lock))
		return -ERESTARTSYS;

	if (!dev->dev) {
		ret = -ENODEV;
		goto out;
	}

	ret = scr24x_wait_ready(dev);
	if (ret < 0)
		goto out;
	len = CCID_HEADER_SIZE;
	ret = read_chunk(dev, 0, len);
	if (ret < 0)
		goto out;

	len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
	if (len > sizeof(dev->buf)) {
		ret = -EIO;
		goto out;
	}
	ret = read_chunk(dev, CCID_HEADER_SIZE, len);
	if (ret < 0)
		goto out;

	if (len < count)
		count = len;

	if (copy_to_user(buf, dev->buf, count)) {
		ret = -EFAULT;
		goto out;
	}

	ret = count;
out:
	mutex_unlock(&dev->lock);
	return ret;
}

static ssize_t scr24x_write(struct file *filp, const char __user *buf,
					size_t count, loff_t *ppos)
{
	struct scr24x_dev *dev = filp->private_data;
	size_t i, y;
	int ret;

	if (mutex_lock_interruptible(&dev->lock))
		return -ERESTARTSYS;

	if (!dev->dev) {
		ret = -ENODEV;
		goto out;
	}

	if (count > sizeof(dev->buf)) {
		ret = -EINVAL;
		goto out;
	}

	if (copy_from_user(dev->buf, buf, count)) {
		ret = -EFAULT;
		goto out;
	}

	ret = scr24x_wait_ready(dev);
	if (ret < 0)
		goto out;

	iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
	ret = scr24x_wait_ready(dev);
	if (ret < 0)
		goto out;

	for (i = 0; i < count; i += 5) {
		for (y = 0; y < 5 && i + y < count; y++)
			iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));

		iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
		ret = scr24x_wait_ready(dev);
		if (ret < 0)
			goto out;
	}

	ret = count;
out:
	mutex_unlock(&dev->lock);
	return ret;
}

static const struct file_operations scr24x_fops = {
	.owner		= THIS_MODULE,
	.read		= scr24x_read,
	.write		= scr24x_write,
	.open		= scr24x_open,
	.release	= scr24x_release,
	.llseek		= no_llseek,
};

static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
{
	if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
		return -ENODEV;
	return pcmcia_request_io(link);
}

static int scr24x_probe(struct pcmcia_device *link)
{
	struct scr24x_dev *dev;
	int ret;

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (!dev)
		return -ENOMEM;

	dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
	if (dev->devno >= SCR24X_DEVS) {
		ret = -EBUSY;
		goto err;
	}

	mutex_init(&dev->lock);
	kref_init(&dev->refcnt);

	link->priv = dev;
	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;

	ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
	if (ret < 0)
		goto err;

	dev->dev = &link->dev;
	dev->regs = devm_ioport_map(&link->dev,
				link->resource[PCMCIA_IOPORT_0]->start,
				resource_size(link->resource[PCMCIA_IOPORT_0]));
	if (!dev->regs) {
		ret = -EIO;
		goto err;
	}

	cdev_init(&dev->c_dev, &scr24x_fops);
	dev->c_dev.owner = THIS_MODULE;
	dev->c_dev.ops = &scr24x_fops;
	ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
	if (ret < 0)
		goto err;

	ret = pcmcia_enable_device(link);
	if (ret < 0) {
		pcmcia_disable_device(link);
		goto err;
	}

	device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
		      NULL, "scr24x%d", dev->devno);

	dev_info(&link->dev, "SCR24x Chip Card Interface\n");
	return 0;

err:
	if (dev->devno < SCR24X_DEVS)
		clear_bit(dev->devno, scr24x_minors);
	kfree (dev);
	return ret;
}

static void scr24x_remove(struct pcmcia_device *link)
{
	struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;

	device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
	mutex_lock(&dev->lock);
	pcmcia_disable_device(link);
	cdev_del(&dev->c_dev);
	clear_bit(dev->devno, scr24x_minors);
	dev->dev = NULL;
	mutex_unlock(&dev->lock);

	kref_put(&dev->refcnt, scr24x_delete);
}

static const struct pcmcia_device_id scr24x_ids[] = {
	PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
					0x53cb94f9, 0xbfdf89a5),
	PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
	PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
	PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
	PCMCIA_DEVICE_NULL
};
MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);

static struct pcmcia_driver scr24x_driver = {
	.owner		= THIS_MODULE,
	.name		= "scr24x_cs",
	.probe		= scr24x_probe,
	.remove		= scr24x_remove,
	.id_table	= scr24x_ids,
};

static int __init scr24x_init(void)
{
	int ret;

	scr24x_class = class_create(THIS_MODULE, "scr24x");
	if (IS_ERR(scr24x_class))
		return PTR_ERR(scr24x_class);

	ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
	if (ret < 0)  {
		class_destroy(scr24x_class);
		return ret;
	}

	ret = pcmcia_register_driver(&scr24x_driver);
	if (ret < 0) {
		unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
		class_destroy(scr24x_class);
	}

	return ret;
}

static void __exit scr24x_exit(void)
{
	pcmcia_unregister_driver(&scr24x_driver);
	unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
	class_destroy(scr24x_class);
}

module_init(scr24x_init);
module_exit(scr24x_exit);

MODULE_AUTHOR("Lubomir Rintel");
MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
MODULE_LICENSE("GPL");
