4 * @brief Driver for VMOD12E16 ADC mezzanine on VMOD/MOD-PCI MODULBUS
7 * Copyright (c) 2009 CERN
8 * @author Juan David Gonzalez Cobas <dcobas@cern.ch>
10 * @section license_sec License
11 * Released under the GPL v2. (and only v2, not any later version)
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/init.h>
18 #include <linux/cdev.h>
19 #include <linux/delay.h>
21 #include <linux/uaccess.h>
22 #include <linux/semaphore.h>
23 #include "modulbus_register.h"
25 #include "vmod12e16.h"
27 #define DRIVER_NAME "vmod12e16"
28 #define PFX DRIVER_NAME ": "
29 #define VMOD12E16_MAX_MODULES VMOD_MAX_BOARDS
31 /* The One And Only Device (OAOD) */
33 static struct cdev cdev
;
35 /** configuration parameters from module params */
36 static struct vmod_devices config
;
37 static struct vmod12e16_dev device_list
[VMOD12E16_MAX_MODULES
];
39 static int vmod12e16_open(struct inode
*ino
, struct file
*filp
)
41 unsigned int lun
= iminor(ino
);
42 unsigned int idx
= lun_to_index(&config
, lun
);
45 printk(KERN_ERR PFX
"could not open, bad lun %d\n", lun
);
48 filp
->private_data
= &device_list
[idx
];
52 static int vmod12e16_release(struct inode
*ino
, struct file
*filp
)
57 static int do_conversion(struct file
*filp
,
58 struct vmod12e16_conversion
*conversion
)
60 struct vmod12e16_dev
*dev
= filp
->private_data
;
61 struct vmod12e16_registers __iomem
*regs
=
62 (struct vmod12e16_registers __iomem
*)dev
->config
->address
;
64 int channel
= conversion
->channel
;
65 int ampli
= conversion
->amplification
;
68 if (down_interruptible(&dev
->sem
))
71 /* explicitly disable interrupt mode for safely polling */
72 iowrite16be(VMOD_12E16_ADC_INTERRUPT_MASK
, ®s
->interrupt
);
74 /* specify channel and amplification */
75 if ((ampli
& ~((1<<2)-1)) || channel
& ~((1<<4)-1)) {
79 iowrite16be((ampli
<<4) | channel
, ®s
->control
);
81 /* wait at most the manufacturer-supplied max time */
83 while (us_elapsed
< VMOD_12E16_MAX_CONVERSION_TIME
) {
84 udelay(VMOD_12E16_CONVERSION_TIME
);
85 if ((ioread16be(®s
->ready
) & VMOD_12E16_RDY_BIT
) == 0) {
86 conversion
->data
= ioread16be(®s
->data
) & VMOD_12E16_ADC_DATA_MASK
;
87 udelay(VMOD_12E16_CONVERSION_TIME
);
91 us_elapsed
+= VMOD_12E16_CONVERSION_TIME
;
99 static int vmod12e16_ioctl(struct inode
*ino
,
104 struct vmod12e16_conversion cnv
, *cnvp
= &cnv
;
109 case VMOD12E16_IOCCONVERT
:
110 if (copy_from_user(cnvp
, (const void __user
*)arg
, sizeof(cnv
)))
112 if ((err
= do_conversion(filp
, cnvp
)) != 0)
114 if (copy_to_user((void __user
*)arg
, cnvp
, sizeof(cnv
)))
127 static struct file_operations fops
= {
128 .owner
= THIS_MODULE
,
129 .ioctl
= vmod12e16_ioctl
,
130 .open
= vmod12e16_open
,
131 .release
= vmod12e16_release
,
134 /* module initialization and cleanup */
135 static int __init
init(void)
139 printk(KERN_INFO PFX
"reading parameters\n");
140 err
= read_params(DRIVER_NAME
, &config
);
144 "initializing driver for %d (max %d) cards\n",
145 config
.num_modules
, VMOD_MAX_BOARDS
);
147 /* fill in config data and semaphore */
148 for (i
= 0; i
< config
.num_modules
; i
++) {
149 device_list
[i
].config
= &config
.module
[i
];
150 init_MUTEX(&device_list
[i
].sem
);
153 err
= alloc_chrdev_region(&devno
, 0, VMOD12E16_MAX_MODULES
, DRIVER_NAME
);
156 printk(KERN_INFO PFX
"allocated device %d\n", MAJOR(devno
));
158 cdev_init(&cdev
, &fops
);
159 cdev
.owner
= THIS_MODULE
;
160 if (cdev_add(&cdev
, devno
, VMOD12E16_MAX_MODULES
) != 0) {
162 "failed to create chardev %d with err %d\n",
169 unregister_chrdev_region(devno
, VMOD12E16_MAX_MODULES
);
174 static void __exit
exit(void)
177 unregister_chrdev_region(devno
, VMOD12E16_MAX_MODULES
);
184 MODULE_LICENSE("GPL");
185 MODULE_AUTHOR("Juan David Gonzalez Cobas <dcobas@cern.ch>");