2 * drivers/cbus/retu-user.c
4 * Retu user space interface functions
6 * Copyright (C) 2004, 2005 Nokia Corporation
8 * Written by Mikko Ylinen <mikko.k.ylinen@nokia.com>
10 * This file is subject to the terms and conditions of the GNU General
11 * Public License. See the file "COPYING" in the main directory of this
12 * archive for more details.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <linux/types.h>
25 #include <linux/kernel.h>
26 #include <linux/interrupt.h>
27 #include <linux/module.h>
28 #include <linux/init.h>
30 #include <linux/miscdevice.h>
31 #include <linux/poll.h>
32 #include <linux/list.h>
33 #include <linux/spinlock.h>
35 #include <asm/uaccess.h>
39 #include "user_retu_tahvo.h"
41 /* Maximum size of IRQ node buffer/pool */
42 #define RETU_MAX_IRQ_BUF_LEN 16
44 #define PFX "retu-user: "
46 /* Bitmap for marking the interrupt sources as having the handlers */
47 static u32 retu_irq_bits;
49 /* For allowing only one user process to subscribe to the retu interrupts */
50 static struct file *retu_irq_subscr = NULL;
52 /* For poll and IRQ passing */
55 struct list_head node;
58 static spinlock_t retu_irqs_lock;
59 static struct retu_irq *retu_irq_block;
60 static LIST_HEAD(retu_irqs);
61 static LIST_HEAD(retu_irqs_reserve);
63 /* Wait queue - used when user wants to read the device */
64 DECLARE_WAIT_QUEUE_HEAD(retu_user_waitqueue);
66 /* Semaphore to protect irq subscription sequence */
67 static struct semaphore retu_sem;
69 /* This array specifies RETU register types (read/write/toggle) */
70 static const u8 retu_access_bits[] = {
106 * The handler for all RETU interrupts.
108 * arg is the interrupt source in RETU.
110 static void retu_user_irq_handler(unsigned long arg)
112 struct retu_irq *irq;
116 spin_lock(&retu_irqs_lock);
117 if (list_empty(&retu_irqs_reserve)) {
118 spin_unlock(&retu_irqs_lock);
121 irq = list_entry((&retu_irqs_reserve)->next, struct retu_irq, node);
123 list_move_tail(&irq->node, &retu_irqs);
124 spin_unlock(&retu_irqs_lock);
126 /* wake up waiting thread */
127 wake_up(&retu_user_waitqueue);
131 * This routine sets up the interrupt handler and marks an interrupt source
132 * in RETU as a candidate for signal delivery to the user process.
134 static int retu_user_subscribe_to_irq(int id, struct file *filp)
139 if ((retu_irq_subscr != NULL) && (retu_irq_subscr != filp)) {
143 /* Store the file pointer of the first user process registering IRQs */
144 retu_irq_subscr = filp;
147 if (retu_irq_bits & (1 << id))
150 ret = retu_request_irq(id, retu_user_irq_handler, id, "");
154 /* Mark that this interrupt has a handler */
155 retu_irq_bits |= 1 << id;
161 * Unregisters all RETU interrupt handlers.
163 static void retu_unreg_irq_handlers(void)
170 for (id = 0; id < MAX_RETU_IRQ_HANDLERS; id++)
171 if (retu_irq_bits & (1 << id))
178 * Write to RETU register.
179 * Returns 0 upon success, a negative error value otherwise.
181 static int retu_user_write_with_mask(u32 field, u16 value)
191 /* Detect bad mask and reg */
192 if (mask == 0 || reg > RETU_REG_MAX ||
193 retu_access_bits[reg] == READ_ONLY) {
194 printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n",
199 /* Justify value according to mask */
200 while (!(mask & 1)) {
205 spin_lock_irqsave(&retu_lock, flags);
206 if (retu_access_bits[reg] == TOGGLE) {
207 /* No need to detect previous content of register */
210 /* Read current value of register */
211 tmp = retu_read_reg(reg);
214 /* Generate new value */
215 tmp = (tmp & ~MASK(field)) | (value & MASK(field));
216 /* Write data to RETU */
217 retu_write_reg(reg, tmp);
218 spin_unlock_irqrestore(&retu_lock, flags);
224 * Read RETU register.
226 static u32 retu_user_read_with_mask(u32 field)
234 /* Detect bad mask and reg */
235 if (mask == 0 || reg > RETU_REG_MAX) {
236 printk(KERN_ERR PFX "invalid arguments (reg=%#x, mask=%#x)\n",
241 /* Read the register */
242 value = retu_read_reg(reg) & mask;
244 /* Right justify value */
245 while (!(mask & 1)) {
256 static int retu_close(struct inode *inode, struct file *filp)
258 /* Unregister all interrupts that have been registered */
259 if (retu_irq_subscr == filp) {
260 retu_unreg_irq_handlers();
261 retu_irq_subscr = NULL;
268 * Device control (ioctl)
270 static int retu_ioctl(struct inode *inode, struct file *filp,
271 unsigned int cmd, unsigned long arg)
273 struct retu_tahvo_write_parms par;
276 case URT_IOCT_IRQ_SUBSCR:
277 return retu_user_subscribe_to_irq(arg, filp);
279 return retu_user_read_with_mask(arg);
280 case RETU_IOCX_WRITE:
281 copy_from_user(&par, (void __user *) arg, sizeof(par));
282 par.result = retu_user_write_with_mask(par.field, par.value);
283 copy_to_user((void __user *) arg, &par, sizeof(par));
285 case RETU_IOCH_ADC_READ:
286 return retu_read_adc(arg);
296 static ssize_t retu_read(struct file *filp, char *buf, size_t count,
299 struct retu_irq *irq;
303 /* read not permitted if neither filp nor anyone has registered IRQs */
304 if (retu_irq_subscr != filp)
307 if ((count < sizeof(u32)) || ((count % sizeof(u32)) != 0))
310 nr = count / sizeof(u32);
312 for (i = 0; i < nr; i++) {
317 ret = wait_event_interruptible(retu_user_waitqueue,
318 !list_empty(&retu_irqs));
322 spin_lock_irqsave(&retu_irqs_lock, flags);
323 irq = list_entry((&retu_irqs)->next, struct retu_irq, node);
325 list_move(&irq->node, &retu_irqs_reserve);
326 spin_unlock_irqrestore(&retu_irqs_lock, flags);
328 copy_to_user(buf + i * sizeof(irq_id), &irq_id, sizeof(irq_id));
338 static unsigned retu_poll(struct file *filp, struct poll_table_struct *pt)
340 if (!list_empty(&retu_irqs))
343 poll_wait(filp, &retu_user_waitqueue, pt);
345 if (!list_empty(&retu_irqs))
351 static struct file_operations retu_user_fileops = {
352 .owner = THIS_MODULE,
355 .release = retu_close,
359 static struct miscdevice retu_device = {
360 .minor = MISC_DYNAMIC_MINOR,
362 .fops = &retu_user_fileops
368 * @return 0 if successful, error value otherwise.
370 int retu_user_init(void)
372 struct retu_irq *irq;
375 irq = kmalloc(sizeof(*irq) * RETU_MAX_IRQ_BUF_LEN, GFP_KERNEL);
377 printk(KERN_ERR PFX "kmalloc failed\n");
380 memset(irq, 0, sizeof(*irq) * RETU_MAX_IRQ_BUF_LEN);
381 for (i = 0; i < RETU_MAX_IRQ_BUF_LEN; i++)
382 list_add(&irq[i].node, &retu_irqs_reserve);
384 retu_irq_block = irq;
386 spin_lock_init(&retu_irqs_lock);
387 sema_init(&retu_sem, 1);
389 /* Request a misc device */
390 res = misc_register(&retu_device);
392 printk(KERN_ERR PFX "unable to register misc device for %s\n",
404 void retu_user_cleanup(void)
406 /* Unregister our misc device */
407 misc_deregister(&retu_device);
408 /* Unregister and disable all RETU interrupts used by this module */
409 retu_unreg_irq_handlers();
410 kfree(retu_irq_block);
413 MODULE_DESCRIPTION("Retu ASIC user space functions");
414 MODULE_LICENSE("GPL");
415 MODULE_AUTHOR("Mikko Ylinen");