1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * SCR24x PCMCIA Smart Card Reader Driver
4 *
5 * Copyright (C) 2005-2006 TL Sudheendran
6 * Copyright (C) 2016 Lubomir Rintel
7 *
8 * Derived from "scr24x_v4.2.6_Release.tar.gz" driver by TL Sudheendran.
9 */
10
11#include <linux/device.h>
12#include <linux/module.h>
13#include <linux/delay.h>
14#include <linux/cdev.h>
15#include <linux/slab.h>
16#include <linux/fs.h>
17#include <linux/io.h>
18#include <linux/uaccess.h>
19
20#include <pcmcia/cistpl.h>
21#include <pcmcia/ds.h>
22
23#define CCID_HEADER_SIZE	10
24#define CCID_LENGTH_OFFSET	1
25#define CCID_MAX_LEN		271
26
27#define SCR24X_DATA(n)		(1 + n)
28#define SCR24X_CMD_STATUS	7
29#define CMD_START		0x40
30#define CMD_WRITE_BYTE		0x41
31#define CMD_READ_BYTE		0x42
32#define STATUS_BUSY		0x80
33
34struct scr24x_dev {
35	struct device *dev;
36	struct cdev c_dev;
37	unsigned char buf[CCID_MAX_LEN];
38	int devno;
39	struct mutex lock;
40	struct kref refcnt;
41	u8 __iomem *regs;
42};
43
44#define SCR24X_DEVS 8
45static DECLARE_BITMAP(scr24x_minors, SCR24X_DEVS);
46
47static struct class *scr24x_class;
48static dev_t scr24x_devt;
49
50static void scr24x_delete(struct kref *kref)
51{
52	struct scr24x_dev *dev = container_of(kref, struct scr24x_dev,
53								refcnt);
54
55	kfree(dev);
56}
57
58static int scr24x_wait_ready(struct scr24x_dev *dev)
59{
60	u_char status;
61	int timeout = 100;
62
63	do {
64		status = ioread8(dev->regs + SCR24X_CMD_STATUS);
65		if (!(status & STATUS_BUSY))
66			return 0;
67
68		msleep(20);
69	} while (--timeout);
70
71	return -EIO;
72}
73
74static int scr24x_open(struct inode *inode, struct file *filp)
75{
76	struct scr24x_dev *dev = container_of(inode->i_cdev,
77				struct scr24x_dev, c_dev);
78
79	kref_get(&dev->refcnt);
80	filp->private_data = dev;
81
82	return stream_open(inode, filp);
83}
84
85static int scr24x_release(struct inode *inode, struct file *filp)
86{
87	struct scr24x_dev *dev = filp->private_data;
88
89	/* We must not take the dev->lock here as scr24x_delete()
90	 * might be called to remove the dev structure altogether.
91	 * We don't need the lock anyway, since after the reference
92	 * acquired in probe() is released in remove() the chrdev
93	 * is already unregistered and noone can possibly acquire
94	 * a reference via open() anymore. */
95	kref_put(&dev->refcnt, scr24x_delete);
96	return 0;
97}
98
99static int read_chunk(struct scr24x_dev *dev, size_t offset, size_t limit)
100{
101	size_t i, y;
102	int ret;
103
104	for (i = offset; i < limit; i += 5) {
105		iowrite8(CMD_READ_BYTE, dev->regs + SCR24X_CMD_STATUS);
106		ret = scr24x_wait_ready(dev);
107		if (ret < 0)
108			return ret;
109
110		for (y = 0; y < 5 && i + y < limit; y++)
111			dev->buf[i + y] = ioread8(dev->regs + SCR24X_DATA(y));
112	}
113
114	return 0;
115}
116
117static ssize_t scr24x_read(struct file *filp, char __user *buf, size_t count,
118								loff_t *ppos)
119{
120	struct scr24x_dev *dev = filp->private_data;
121	int ret;
122	int len;
123
124	if (count < CCID_HEADER_SIZE)
125		return -EINVAL;
126
127	if (mutex_lock_interruptible(&dev->lock))
128		return -ERESTARTSYS;
129
130	if (!dev->dev) {
131		ret = -ENODEV;
132		goto out;
133	}
134
135	ret = scr24x_wait_ready(dev);
136	if (ret < 0)
137		goto out;
138	len = CCID_HEADER_SIZE;
139	ret = read_chunk(dev, 0, len);
140	if (ret < 0)
141		goto out;
142
143	len += le32_to_cpu(*(__le32 *)(&dev->buf[CCID_LENGTH_OFFSET]));
144	if (len > sizeof(dev->buf)) {
145		ret = -EIO;
146		goto out;
147	}
148	ret = read_chunk(dev, CCID_HEADER_SIZE, len);
149	if (ret < 0)
150		goto out;
151
152	if (len < count)
153		count = len;
154
155	if (copy_to_user(buf, dev->buf, count)) {
156		ret = -EFAULT;
157		goto out;
158	}
159
160	ret = count;
161out:
162	mutex_unlock(&dev->lock);
163	return ret;
164}
165
166static ssize_t scr24x_write(struct file *filp, const char __user *buf,
167					size_t count, loff_t *ppos)
168{
169	struct scr24x_dev *dev = filp->private_data;
170	size_t i, y;
171	int ret;
172
173	if (mutex_lock_interruptible(&dev->lock))
174		return -ERESTARTSYS;
175
176	if (!dev->dev) {
177		ret = -ENODEV;
178		goto out;
179	}
180
181	if (count > sizeof(dev->buf)) {
182		ret = -EINVAL;
183		goto out;
184	}
185
186	if (copy_from_user(dev->buf, buf, count)) {
187		ret = -EFAULT;
188		goto out;
189	}
190
191	ret = scr24x_wait_ready(dev);
192	if (ret < 0)
193		goto out;
194
195	iowrite8(CMD_START, dev->regs + SCR24X_CMD_STATUS);
196	ret = scr24x_wait_ready(dev);
197	if (ret < 0)
198		goto out;
199
200	for (i = 0; i < count; i += 5) {
201		for (y = 0; y < 5 && i + y < count; y++)
202			iowrite8(dev->buf[i + y], dev->regs + SCR24X_DATA(y));
203
204		iowrite8(CMD_WRITE_BYTE, dev->regs + SCR24X_CMD_STATUS);
205		ret = scr24x_wait_ready(dev);
206		if (ret < 0)
207			goto out;
208	}
209
210	ret = count;
211out:
212	mutex_unlock(&dev->lock);
213	return ret;
214}
215
216static const struct file_operations scr24x_fops = {
217	.owner		= THIS_MODULE,
218	.read		= scr24x_read,
219	.write		= scr24x_write,
220	.open		= scr24x_open,
221	.release	= scr24x_release,
222	.llseek		= no_llseek,
223};
224
225static int scr24x_config_check(struct pcmcia_device *link, void *priv_data)
226{
227	if (resource_size(link->resource[PCMCIA_IOPORT_0]) != 0x11)
228		return -ENODEV;
229	return pcmcia_request_io(link);
230}
231
232static int scr24x_probe(struct pcmcia_device *link)
233{
234	struct scr24x_dev *dev;
235	int ret;
236
237	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
238	if (!dev)
239		return -ENOMEM;
240
241	dev->devno = find_first_zero_bit(scr24x_minors, SCR24X_DEVS);
242	if (dev->devno >= SCR24X_DEVS) {
243		ret = -EBUSY;
244		goto err;
245	}
246
247	mutex_init(&dev->lock);
248	kref_init(&dev->refcnt);
249
250	link->priv = dev;
251	link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
252
253	ret = pcmcia_loop_config(link, scr24x_config_check, NULL);
254	if (ret < 0)
255		goto err;
256
257	dev->dev = &link->dev;
258	dev->regs = devm_ioport_map(&link->dev,
259				link->resource[PCMCIA_IOPORT_0]->start,
260				resource_size(link->resource[PCMCIA_IOPORT_0]));
261	if (!dev->regs) {
262		ret = -EIO;
263		goto err;
264	}
265
266	cdev_init(&dev->c_dev, &scr24x_fops);
267	dev->c_dev.owner = THIS_MODULE;
268	dev->c_dev.ops = &scr24x_fops;
269	ret = cdev_add(&dev->c_dev, MKDEV(MAJOR(scr24x_devt), dev->devno), 1);
270	if (ret < 0)
271		goto err;
272
273	ret = pcmcia_enable_device(link);
274	if (ret < 0) {
275		pcmcia_disable_device(link);
276		goto err;
277	}
278
279	device_create(scr24x_class, NULL, MKDEV(MAJOR(scr24x_devt), dev->devno),
280		      NULL, "scr24x%d", dev->devno);
281
282	dev_info(&link->dev, "SCR24x Chip Card Interface\n");
283	return 0;
284
285err:
286	if (dev->devno < SCR24X_DEVS)
287		clear_bit(dev->devno, scr24x_minors);
288	kfree (dev);
289	return ret;
290}
291
292static void scr24x_remove(struct pcmcia_device *link)
293{
294	struct scr24x_dev *dev = (struct scr24x_dev *)link->priv;
295
296	device_destroy(scr24x_class, MKDEV(MAJOR(scr24x_devt), dev->devno));
297	mutex_lock(&dev->lock);
298	pcmcia_disable_device(link);
299	cdev_del(&dev->c_dev);
300	clear_bit(dev->devno, scr24x_minors);
301	dev->dev = NULL;
302	mutex_unlock(&dev->lock);
303
304	kref_put(&dev->refcnt, scr24x_delete);
305}
306
307static const struct pcmcia_device_id scr24x_ids[] = {
308	PCMCIA_DEVICE_PROD_ID12("HP", "PC Card Smart Card Reader",
309					0x53cb94f9, 0xbfdf89a5),
310	PCMCIA_DEVICE_PROD_ID1("SCR241 PCMCIA", 0x6271efa3),
311	PCMCIA_DEVICE_PROD_ID1("SCR243 PCMCIA", 0x2054e8de),
312	PCMCIA_DEVICE_PROD_ID1("SCR24x PCMCIA", 0x54a33665),
313	PCMCIA_DEVICE_NULL
314};
315MODULE_DEVICE_TABLE(pcmcia, scr24x_ids);
316
317static struct pcmcia_driver scr24x_driver = {
318	.owner		= THIS_MODULE,
319	.name		= "scr24x_cs",
320	.probe		= scr24x_probe,
321	.remove		= scr24x_remove,
322	.id_table	= scr24x_ids,
323};
324
325static int __init scr24x_init(void)
326{
327	int ret;
328
329	scr24x_class = class_create(THIS_MODULE, "scr24x");
330	if (IS_ERR(scr24x_class))
331		return PTR_ERR(scr24x_class);
332
333	ret = alloc_chrdev_region(&scr24x_devt, 0, SCR24X_DEVS, "scr24x");
334	if (ret < 0)  {
335		class_destroy(scr24x_class);
336		return ret;
337	}
338
339	ret = pcmcia_register_driver(&scr24x_driver);
340	if (ret < 0) {
341		unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
342		class_destroy(scr24x_class);
343	}
344
345	return ret;
346}
347
348static void __exit scr24x_exit(void)
349{
350	pcmcia_unregister_driver(&scr24x_driver);
351	unregister_chrdev_region(scr24x_devt, SCR24X_DEVS);
352	class_destroy(scr24x_class);
353}
354
355module_init(scr24x_init);
356module_exit(scr24x_exit);
357
358MODULE_AUTHOR("Lubomir Rintel");
359MODULE_DESCRIPTION("SCR24x PCMCIA Smart Card Reader Driver");
360MODULE_LICENSE("GPL");
361