xref: /openbmc/linux/drivers/misc/phantom.c (revision 367b8112)
1 /*
2  *  Copyright (C) 2005-2007 Jiri Slaby <jirislaby@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  You need an userspace library to cooperate with this driver. It (and other
10  *  info) may be obtained here:
11  *  http://www.fi.muni.cz/~xslaby/phantom.html
12  *  or alternatively, you might use OpenHaptics provided by Sensable.
13  */
14 
15 #include <linux/compat.h>
16 #include <linux/kernel.h>
17 #include <linux/module.h>
18 #include <linux/device.h>
19 #include <linux/pci.h>
20 #include <linux/fs.h>
21 #include <linux/poll.h>
22 #include <linux/interrupt.h>
23 #include <linux/cdev.h>
24 #include <linux/phantom.h>
25 #include <linux/smp_lock.h>
26 
27 #include <asm/atomic.h>
28 #include <asm/io.h>
29 
30 #define PHANTOM_VERSION		"n0.9.8"
31 
32 #define PHANTOM_MAX_MINORS	8
33 
34 #define PHN_IRQCTL		0x4c    /* irq control in caddr space */
35 
36 #define PHB_RUNNING		1
37 #define PHB_NOT_OH		2
38 
39 static struct class *phantom_class;
40 static int phantom_major;
41 
42 struct phantom_device {
43 	unsigned int opened;
44 	void __iomem *caddr;
45 	u32 __iomem *iaddr;
46 	u32 __iomem *oaddr;
47 	unsigned long status;
48 	atomic_t counter;
49 
50 	wait_queue_head_t wait;
51 	struct cdev cdev;
52 
53 	struct mutex open_lock;
54 	spinlock_t regs_lock;
55 
56 	/* used in NOT_OH mode */
57 	struct phm_regs oregs;
58 	u32 ctl_reg;
59 };
60 
61 static unsigned char phantom_devices[PHANTOM_MAX_MINORS];
62 
63 static int phantom_status(struct phantom_device *dev, unsigned long newstat)
64 {
65 	pr_debug("phantom_status %lx %lx\n", dev->status, newstat);
66 
67 	if (!(dev->status & PHB_RUNNING) && (newstat & PHB_RUNNING)) {
68 		atomic_set(&dev->counter, 0);
69 		iowrite32(PHN_CTL_IRQ, dev->iaddr + PHN_CONTROL);
70 		iowrite32(0x43, dev->caddr + PHN_IRQCTL);
71 		ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
72 	} else if ((dev->status & PHB_RUNNING) && !(newstat & PHB_RUNNING)) {
73 		iowrite32(0, dev->caddr + PHN_IRQCTL);
74 		ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
75 	}
76 
77 	dev->status = newstat;
78 
79 	return 0;
80 }
81 
82 /*
83  * File ops
84  */
85 
86 static long phantom_ioctl(struct file *file, unsigned int cmd,
87 		unsigned long arg)
88 {
89 	struct phantom_device *dev = file->private_data;
90 	struct phm_regs rs;
91 	struct phm_reg r;
92 	void __user *argp = (void __user *)arg;
93 	unsigned long flags;
94 	unsigned int i;
95 
96 	switch (cmd) {
97 	case PHN_SETREG:
98 	case PHN_SET_REG:
99 		if (copy_from_user(&r, argp, sizeof(r)))
100 			return -EFAULT;
101 
102 		if (r.reg > 7)
103 			return -EINVAL;
104 
105 		spin_lock_irqsave(&dev->regs_lock, flags);
106 		if (r.reg == PHN_CONTROL && (r.value & PHN_CTL_IRQ) &&
107 				phantom_status(dev, dev->status | PHB_RUNNING)){
108 			spin_unlock_irqrestore(&dev->regs_lock, flags);
109 			return -ENODEV;
110 		}
111 
112 		pr_debug("phantom: writing %x to %u\n", r.value, r.reg);
113 
114 		/* preserve amp bit (don't allow to change it when in NOT_OH) */
115 		if (r.reg == PHN_CONTROL && (dev->status & PHB_NOT_OH)) {
116 			r.value &= ~PHN_CTL_AMP;
117 			r.value |= dev->ctl_reg & PHN_CTL_AMP;
118 			dev->ctl_reg = r.value;
119 		}
120 
121 		iowrite32(r.value, dev->iaddr + r.reg);
122 		ioread32(dev->iaddr); /* PCI posting */
123 
124 		if (r.reg == PHN_CONTROL && !(r.value & PHN_CTL_IRQ))
125 			phantom_status(dev, dev->status & ~PHB_RUNNING);
126 		spin_unlock_irqrestore(&dev->regs_lock, flags);
127 		break;
128 	case PHN_SETREGS:
129 	case PHN_SET_REGS:
130 		if (copy_from_user(&rs, argp, sizeof(rs)))
131 			return -EFAULT;
132 
133 		pr_debug("phantom: SRS %u regs %x\n", rs.count, rs.mask);
134 		spin_lock_irqsave(&dev->regs_lock, flags);
135 		if (dev->status & PHB_NOT_OH)
136 			memcpy(&dev->oregs, &rs, sizeof(rs));
137 		else {
138 			u32 m = min(rs.count, 8U);
139 			for (i = 0; i < m; i++)
140 				if (rs.mask & BIT(i))
141 					iowrite32(rs.values[i], dev->oaddr + i);
142 			ioread32(dev->iaddr); /* PCI posting */
143 		}
144 		spin_unlock_irqrestore(&dev->regs_lock, flags);
145 		break;
146 	case PHN_GETREG:
147 	case PHN_GET_REG:
148 		if (copy_from_user(&r, argp, sizeof(r)))
149 			return -EFAULT;
150 
151 		if (r.reg > 7)
152 			return -EINVAL;
153 
154 		r.value = ioread32(dev->iaddr + r.reg);
155 
156 		if (copy_to_user(argp, &r, sizeof(r)))
157 			return -EFAULT;
158 		break;
159 	case PHN_GETREGS:
160 	case PHN_GET_REGS: {
161 		u32 m;
162 
163 		if (copy_from_user(&rs, argp, sizeof(rs)))
164 			return -EFAULT;
165 
166 		m = min(rs.count, 8U);
167 
168 		pr_debug("phantom: GRS %u regs %x\n", rs.count, rs.mask);
169 		spin_lock_irqsave(&dev->regs_lock, flags);
170 		for (i = 0; i < m; i++)
171 			if (rs.mask & BIT(i))
172 				rs.values[i] = ioread32(dev->iaddr + i);
173 		atomic_set(&dev->counter, 0);
174 		spin_unlock_irqrestore(&dev->regs_lock, flags);
175 
176 		if (copy_to_user(argp, &rs, sizeof(rs)))
177 			return -EFAULT;
178 		break;
179 	} case PHN_NOT_OH:
180 		spin_lock_irqsave(&dev->regs_lock, flags);
181 		if (dev->status & PHB_RUNNING) {
182 			printk(KERN_ERR "phantom: you need to set NOT_OH "
183 					"before you start the device!\n");
184 			spin_unlock_irqrestore(&dev->regs_lock, flags);
185 			return -EINVAL;
186 		}
187 		dev->status |= PHB_NOT_OH;
188 		spin_unlock_irqrestore(&dev->regs_lock, flags);
189 		break;
190 	default:
191 		return -ENOTTY;
192 	}
193 
194 	return 0;
195 }
196 
197 #ifdef CONFIG_COMPAT
198 static long phantom_compat_ioctl(struct file *filp, unsigned int cmd,
199 		unsigned long arg)
200 {
201 	if (_IOC_NR(cmd) <= 3 && _IOC_SIZE(cmd) == sizeof(compat_uptr_t)) {
202 		cmd &= ~(_IOC_SIZEMASK << _IOC_SIZESHIFT);
203 		cmd |= sizeof(void *) << _IOC_SIZESHIFT;
204 	}
205 	return phantom_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
206 }
207 #else
208 #define phantom_compat_ioctl NULL
209 #endif
210 
211 static int phantom_open(struct inode *inode, struct file *file)
212 {
213 	struct phantom_device *dev = container_of(inode->i_cdev,
214 			struct phantom_device, cdev);
215 
216 	lock_kernel();
217 	nonseekable_open(inode, file);
218 
219 	if (mutex_lock_interruptible(&dev->open_lock)) {
220 		unlock_kernel();
221 		return -ERESTARTSYS;
222 	}
223 
224 	if (dev->opened) {
225 		mutex_unlock(&dev->open_lock);
226 		unlock_kernel();
227 		return -EINVAL;
228 	}
229 
230 	WARN_ON(dev->status & PHB_NOT_OH);
231 
232 	file->private_data = dev;
233 
234 	atomic_set(&dev->counter, 0);
235 	dev->opened++;
236 	mutex_unlock(&dev->open_lock);
237 	unlock_kernel();
238 	return 0;
239 }
240 
241 static int phantom_release(struct inode *inode, struct file *file)
242 {
243 	struct phantom_device *dev = file->private_data;
244 
245 	mutex_lock(&dev->open_lock);
246 
247 	dev->opened = 0;
248 	phantom_status(dev, dev->status & ~PHB_RUNNING);
249 	dev->status &= ~PHB_NOT_OH;
250 
251 	mutex_unlock(&dev->open_lock);
252 
253 	return 0;
254 }
255 
256 static unsigned int phantom_poll(struct file *file, poll_table *wait)
257 {
258 	struct phantom_device *dev = file->private_data;
259 	unsigned int mask = 0;
260 
261 	pr_debug("phantom_poll: %d\n", atomic_read(&dev->counter));
262 	poll_wait(file, &dev->wait, wait);
263 
264 	if (!(dev->status & PHB_RUNNING))
265 		mask = POLLERR;
266 	else if (atomic_read(&dev->counter))
267 		mask = POLLIN | POLLRDNORM;
268 
269 	pr_debug("phantom_poll end: %x/%d\n", mask, atomic_read(&dev->counter));
270 
271 	return mask;
272 }
273 
274 static struct file_operations phantom_file_ops = {
275 	.open = phantom_open,
276 	.release = phantom_release,
277 	.unlocked_ioctl = phantom_ioctl,
278 	.compat_ioctl = phantom_compat_ioctl,
279 	.poll = phantom_poll,
280 };
281 
282 static irqreturn_t phantom_isr(int irq, void *data)
283 {
284 	struct phantom_device *dev = data;
285 	unsigned int i;
286 	u32 ctl;
287 
288 	spin_lock(&dev->regs_lock);
289 	ctl = ioread32(dev->iaddr + PHN_CONTROL);
290 	if (!(ctl & PHN_CTL_IRQ)) {
291 		spin_unlock(&dev->regs_lock);
292 		return IRQ_NONE;
293 	}
294 
295 	iowrite32(0, dev->iaddr);
296 	iowrite32(0xc0, dev->iaddr);
297 
298 	if (dev->status & PHB_NOT_OH) {
299 		struct phm_regs *r = &dev->oregs;
300 		u32 m = min(r->count, 8U);
301 
302 		for (i = 0; i < m; i++)
303 			if (r->mask & BIT(i))
304 				iowrite32(r->values[i], dev->oaddr + i);
305 
306 		dev->ctl_reg ^= PHN_CTL_AMP;
307 		iowrite32(dev->ctl_reg, dev->iaddr + PHN_CONTROL);
308 	}
309 	spin_unlock(&dev->regs_lock);
310 
311 	ioread32(dev->iaddr); /* PCI posting */
312 
313 	atomic_inc(&dev->counter);
314 	wake_up_interruptible(&dev->wait);
315 
316 	return IRQ_HANDLED;
317 }
318 
319 /*
320  * Init and deinit driver
321  */
322 
323 static unsigned int __devinit phantom_get_free(void)
324 {
325 	unsigned int i;
326 
327 	for (i = 0; i < PHANTOM_MAX_MINORS; i++)
328 		if (phantom_devices[i] == 0)
329 			break;
330 
331 	return i;
332 }
333 
334 static int __devinit phantom_probe(struct pci_dev *pdev,
335 	const struct pci_device_id *pci_id)
336 {
337 	struct phantom_device *pht;
338 	unsigned int minor;
339 	int retval;
340 
341 	retval = pci_enable_device(pdev);
342 	if (retval)
343 		goto err;
344 
345 	minor = phantom_get_free();
346 	if (minor == PHANTOM_MAX_MINORS) {
347 		dev_err(&pdev->dev, "too many devices found!\n");
348 		retval = -EIO;
349 		goto err_dis;
350 	}
351 
352 	phantom_devices[minor] = 1;
353 
354 	retval = pci_request_regions(pdev, "phantom");
355 	if (retval)
356 		goto err_null;
357 
358 	retval = -ENOMEM;
359 	pht = kzalloc(sizeof(*pht), GFP_KERNEL);
360 	if (pht == NULL) {
361 		dev_err(&pdev->dev, "unable to allocate device\n");
362 		goto err_reg;
363 	}
364 
365 	pht->caddr = pci_iomap(pdev, 0, 0);
366 	if (pht->caddr == NULL) {
367 		dev_err(&pdev->dev, "can't remap conf space\n");
368 		goto err_fr;
369 	}
370 	pht->iaddr = pci_iomap(pdev, 2, 0);
371 	if (pht->iaddr == NULL) {
372 		dev_err(&pdev->dev, "can't remap input space\n");
373 		goto err_unmc;
374 	}
375 	pht->oaddr = pci_iomap(pdev, 3, 0);
376 	if (pht->oaddr == NULL) {
377 		dev_err(&pdev->dev, "can't remap output space\n");
378 		goto err_unmi;
379 	}
380 
381 	mutex_init(&pht->open_lock);
382 	spin_lock_init(&pht->regs_lock);
383 	init_waitqueue_head(&pht->wait);
384 	cdev_init(&pht->cdev, &phantom_file_ops);
385 	pht->cdev.owner = THIS_MODULE;
386 
387 	iowrite32(0, pht->caddr + PHN_IRQCTL);
388 	ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
389 	retval = request_irq(pdev->irq, phantom_isr,
390 			IRQF_SHARED | IRQF_DISABLED, "phantom", pht);
391 	if (retval) {
392 		dev_err(&pdev->dev, "can't establish ISR\n");
393 		goto err_unmo;
394 	}
395 
396 	retval = cdev_add(&pht->cdev, MKDEV(phantom_major, minor), 1);
397 	if (retval) {
398 		dev_err(&pdev->dev, "chardev registration failed\n");
399 		goto err_irq;
400 	}
401 
402 	if (IS_ERR(device_create(phantom_class, &pdev->dev,
403 				 MKDEV(phantom_major, minor), NULL,
404 				 "phantom%u", minor)))
405 		dev_err(&pdev->dev, "can't create device\n");
406 
407 	pci_set_drvdata(pdev, pht);
408 
409 	return 0;
410 err_irq:
411 	free_irq(pdev->irq, pht);
412 err_unmo:
413 	pci_iounmap(pdev, pht->oaddr);
414 err_unmi:
415 	pci_iounmap(pdev, pht->iaddr);
416 err_unmc:
417 	pci_iounmap(pdev, pht->caddr);
418 err_fr:
419 	kfree(pht);
420 err_reg:
421 	pci_release_regions(pdev);
422 err_null:
423 	phantom_devices[minor] = 0;
424 err_dis:
425 	pci_disable_device(pdev);
426 err:
427 	return retval;
428 }
429 
430 static void __devexit phantom_remove(struct pci_dev *pdev)
431 {
432 	struct phantom_device *pht = pci_get_drvdata(pdev);
433 	unsigned int minor = MINOR(pht->cdev.dev);
434 
435 	device_destroy(phantom_class, MKDEV(phantom_major, minor));
436 
437 	cdev_del(&pht->cdev);
438 
439 	iowrite32(0, pht->caddr + PHN_IRQCTL);
440 	ioread32(pht->caddr + PHN_IRQCTL); /* PCI posting */
441 	free_irq(pdev->irq, pht);
442 
443 	pci_iounmap(pdev, pht->oaddr);
444 	pci_iounmap(pdev, pht->iaddr);
445 	pci_iounmap(pdev, pht->caddr);
446 
447 	kfree(pht);
448 
449 	pci_release_regions(pdev);
450 
451 	phantom_devices[minor] = 0;
452 
453 	pci_disable_device(pdev);
454 }
455 
456 #ifdef CONFIG_PM
457 static int phantom_suspend(struct pci_dev *pdev, pm_message_t state)
458 {
459 	struct phantom_device *dev = pci_get_drvdata(pdev);
460 
461 	iowrite32(0, dev->caddr + PHN_IRQCTL);
462 	ioread32(dev->caddr + PHN_IRQCTL); /* PCI posting */
463 
464 	synchronize_irq(pdev->irq);
465 
466 	return 0;
467 }
468 
469 static int phantom_resume(struct pci_dev *pdev)
470 {
471 	struct phantom_device *dev = pci_get_drvdata(pdev);
472 
473 	iowrite32(0, dev->caddr + PHN_IRQCTL);
474 
475 	return 0;
476 }
477 #else
478 #define phantom_suspend	NULL
479 #define phantom_resume	NULL
480 #endif
481 
482 static struct pci_device_id phantom_pci_tbl[] __devinitdata = {
483 	{ .vendor = PCI_VENDOR_ID_PLX, .device = PCI_DEVICE_ID_PLX_9050,
484 	  .subvendor = PCI_VENDOR_ID_PLX, .subdevice = PCI_DEVICE_ID_PLX_9050,
485 	  .class = PCI_CLASS_BRIDGE_OTHER << 8, .class_mask = 0xffff00 },
486 	{ 0, }
487 };
488 MODULE_DEVICE_TABLE(pci, phantom_pci_tbl);
489 
490 static struct pci_driver phantom_pci_driver = {
491 	.name = "phantom",
492 	.id_table = phantom_pci_tbl,
493 	.probe = phantom_probe,
494 	.remove = __devexit_p(phantom_remove),
495 	.suspend = phantom_suspend,
496 	.resume = phantom_resume
497 };
498 
499 static ssize_t phantom_show_version(struct class *cls, char *buf)
500 {
501 	return sprintf(buf, PHANTOM_VERSION "\n");
502 }
503 
504 static CLASS_ATTR(version, 0444, phantom_show_version, NULL);
505 
506 static int __init phantom_init(void)
507 {
508 	int retval;
509 	dev_t dev;
510 
511 	phantom_class = class_create(THIS_MODULE, "phantom");
512 	if (IS_ERR(phantom_class)) {
513 		retval = PTR_ERR(phantom_class);
514 		printk(KERN_ERR "phantom: can't register phantom class\n");
515 		goto err;
516 	}
517 	retval = class_create_file(phantom_class, &class_attr_version);
518 	if (retval) {
519 		printk(KERN_ERR "phantom: can't create sysfs version file\n");
520 		goto err_class;
521 	}
522 
523 	retval = alloc_chrdev_region(&dev, 0, PHANTOM_MAX_MINORS, "phantom");
524 	if (retval) {
525 		printk(KERN_ERR "phantom: can't register character device\n");
526 		goto err_attr;
527 	}
528 	phantom_major = MAJOR(dev);
529 
530 	retval = pci_register_driver(&phantom_pci_driver);
531 	if (retval) {
532 		printk(KERN_ERR "phantom: can't register pci driver\n");
533 		goto err_unchr;
534 	}
535 
536 	printk(KERN_INFO "Phantom Linux Driver, version " PHANTOM_VERSION ", "
537 			"init OK\n");
538 
539 	return 0;
540 err_unchr:
541 	unregister_chrdev_region(dev, PHANTOM_MAX_MINORS);
542 err_attr:
543 	class_remove_file(phantom_class, &class_attr_version);
544 err_class:
545 	class_destroy(phantom_class);
546 err:
547 	return retval;
548 }
549 
550 static void __exit phantom_exit(void)
551 {
552 	pci_unregister_driver(&phantom_pci_driver);
553 
554 	unregister_chrdev_region(MKDEV(phantom_major, 0), PHANTOM_MAX_MINORS);
555 
556 	class_remove_file(phantom_class, &class_attr_version);
557 	class_destroy(phantom_class);
558 
559 	pr_debug("phantom: module successfully removed\n");
560 }
561 
562 module_init(phantom_init);
563 module_exit(phantom_exit);
564 
565 MODULE_AUTHOR("Jiri Slaby <jirislaby@gmail.com>");
566 MODULE_DESCRIPTION("Sensable Phantom driver (PCI devices)");
567 MODULE_LICENSE("GPL");
568 MODULE_VERSION(PHANTOM_VERSION);
569