2 * drivers/cbus/tahvo-user.c
4 * Tahvo 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>
34 #include <linux/sched.h>
35 #include <linux/mutex.h>
37 #include <asm/uaccess.h>
41 #include "user_retu_tahvo.h"
43 /* Maximum size of IRQ node buffer/pool */
44 #define TAHVO_MAX_IRQ_BUF_LEN 16
46 #define PFX "tahvo-user: "
48 /* Bitmap for marking the interrupt sources as having the handlers */
49 static u32 tahvo_irq_bits
;
51 /* For allowing only one user process to subscribe to the tahvo interrupts */
52 static struct file
*tahvo_irq_subscr
= NULL
;
54 /* For poll and IRQ passing */
57 struct list_head node
;
60 static spinlock_t tahvo_irqs_lock
;
61 static struct tahvo_irq
*tahvo_irq_block
;
62 static LIST_HEAD(tahvo_irqs
);
63 static LIST_HEAD(tahvo_irqs_reserve
);
65 /* Wait queue - used when user wants to read the device */
66 DECLARE_WAIT_QUEUE_HEAD(tahvo_user_waitqueue
);
68 /* Semaphore to protect irq subscription sequence */
69 static struct mutex tahvo_mutex
;
71 /* This array specifies TAHVO register types (read/write/toggle) */
72 static const u8 tahvo_access_bits
[] = {
90 * The handler for all TAHVO interrupts.
92 * arg is the interrupt source in TAHVO.
94 static void tahvo_user_irq_handler(unsigned long arg
)
96 struct tahvo_irq
*irq
;
98 /* user has to re-enable the interrupt once ready
99 * for receiving them again */
100 tahvo_disable_irq(arg
);
103 spin_lock(&tahvo_irqs_lock
);
104 if (list_empty(&tahvo_irqs_reserve
)) {
105 spin_unlock(&tahvo_irqs_lock
);
108 irq
= list_entry((&tahvo_irqs_reserve
)->next
, struct tahvo_irq
, node
);
110 list_move_tail(&irq
->node
, &tahvo_irqs
);
111 spin_unlock(&tahvo_irqs_lock
);
113 /* wake up waiting thread */
114 wake_up(&tahvo_user_waitqueue
);
118 * This routine sets up the interrupt handler and marks an interrupt source
119 * in TAHVO as a candidate for signal delivery to the user process.
121 static int tahvo_user_subscribe_to_irq(int id
, struct file
*filp
)
125 mutex_lock(&tahvo_mutex
);
126 if ((tahvo_irq_subscr
!= NULL
) && (tahvo_irq_subscr
!= filp
)) {
127 mutex_unlock(&tahvo_mutex
);
130 /* Store the file pointer of the first user process registering IRQs */
131 tahvo_irq_subscr
= filp
;
132 mutex_unlock(&tahvo_mutex
);
134 if (tahvo_irq_bits
& (1 << id
))
137 ret
= tahvo_request_irq(id
, tahvo_user_irq_handler
, id
, "");
141 /* Mark that this interrupt has a handler */
142 tahvo_irq_bits
|= 1 << id
;
148 * Unregister all TAHVO interrupt handlers
150 static void tahvo_unreg_irq_handlers(void)
157 for (id
= 0; id
< MAX_TAHVO_IRQ_HANDLERS
; id
++)
158 if (tahvo_irq_bits
& (1 << id
))
165 * Write to TAHVO register.
166 * Returns 0 upon success, a negative error value otherwise.
168 static int tahvo_user_write_with_mask(u32 field
, u16 value
)
178 /* Detect bad mask and reg */
179 if (mask
== 0 || reg
> TAHVO_REG_MAX
||
180 tahvo_access_bits
[reg
] == READ_ONLY
) {
181 printk(KERN_ERR PFX
"invalid arguments (reg=%#x, mask=%#x)\n",
186 /* Justify value according to mask */
187 while (!(mask
& 1)) {
192 spin_lock_irqsave(&tahvo_lock
, flags
);
193 if (tahvo_access_bits
[reg
] == TOGGLE
) {
194 /* No need to detect previous content of register */
197 /* Read current value of register */
198 tmp
= tahvo_read_reg(reg
);
200 /* Generate a new value */
201 tmp
= (tmp
& ~MASK(field
)) | (value
& MASK(field
));
202 /* Write data to TAHVO */
203 tahvo_write_reg(reg
, tmp
);
204 spin_unlock_irqrestore(&tahvo_lock
, flags
);
210 * Read TAHVO register.
212 static u32
tahvo_user_read_with_mask(u32 field
)
220 /* Detect bad mask and reg */
221 if (mask
== 0 || reg
> TAHVO_REG_MAX
) {
222 printk(KERN_ERR PFX
"invalid arguments (reg=%#x, mask=%#x)\n",
227 /* Read the register */
228 value
= tahvo_read_reg(reg
) & mask
;
230 /* Right justify value */
231 while (!(mask
& 1)) {
242 static int tahvo_close(struct inode
*inode
, struct file
*filp
)
244 /* Unregister all interrupts that have been registered */
245 if (tahvo_irq_subscr
== filp
) {
246 tahvo_unreg_irq_handlers();
247 tahvo_irq_subscr
= NULL
;
254 * Device control (ioctl)
256 static int tahvo_ioctl(struct inode
*inode
, struct file
*filp
,
257 unsigned int cmd
, unsigned long arg
)
259 struct retu_tahvo_write_parms par
;
263 case URT_IOCT_IRQ_SUBSCR
:
264 return tahvo_user_subscribe_to_irq(arg
, filp
);
265 case TAHVO_IOCH_READ
:
266 return tahvo_user_read_with_mask(arg
);
267 case TAHVO_IOCX_WRITE
:
268 ret
= copy_from_user(&par
, (void __user
*) arg
, sizeof(par
));
270 printk(KERN_ERR
"copy_from_user failed: %d\n", ret
);
271 par
.result
= tahvo_user_write_with_mask(par
.field
, par
.value
);
272 ret
= copy_to_user((void __user
*) arg
, &par
, sizeof(par
));
274 printk(KERN_ERR
"copy_to_user failed: %d\n", ret
);
285 static ssize_t
tahvo_read(struct file
*filp
, char *buf
, size_t count
,
288 struct tahvo_irq
*irq
;
292 /* read not permitted if neither filp nor anyone has registered IRQs */
293 if (tahvo_irq_subscr
!= filp
)
296 if ((count
< sizeof(u32
)) || ((count
% sizeof(u32
)) != 0))
299 nr
= count
/ sizeof(u32
);
301 for (i
= 0; i
< nr
; i
++) {
306 ret
= wait_event_interruptible(tahvo_user_waitqueue
,
307 !list_empty(&tahvo_irqs
));
311 spin_lock_irqsave(&tahvo_irqs_lock
, flags
);
312 irq
= list_entry((&tahvo_irqs
)->next
, struct tahvo_irq
, node
);
314 list_move(&irq
->node
, &tahvo_irqs_reserve
);
315 spin_unlock_irqrestore(&tahvo_irqs_lock
, flags
);
317 ret
= copy_to_user(buf
+ i
* sizeof(irq_id
), &irq_id
,
320 printk(KERN_ERR
"copy_to_user failed: %d\n", ret
);
329 static unsigned tahvo_poll(struct file
*filp
, struct poll_table_struct
*pt
)
331 if (!list_empty(&tahvo_irqs
))
334 poll_wait(filp
, &tahvo_user_waitqueue
, pt
);
336 if (!list_empty(&tahvo_irqs
))
342 static struct file_operations tahvo_user_fileops
= {
343 .owner
= THIS_MODULE
,
344 .ioctl
= tahvo_ioctl
,
346 .release
= tahvo_close
,
350 static struct miscdevice tahvo_device
= {
351 .minor
= MISC_DYNAMIC_MINOR
,
353 .fops
= &tahvo_user_fileops
359 * @return 0 if successful, error value otherwise.
361 int tahvo_user_init(void)
363 struct tahvo_irq
*irq
;
366 irq
= kmalloc(sizeof(*irq
) * TAHVO_MAX_IRQ_BUF_LEN
, GFP_KERNEL
);
368 printk(KERN_ERR PFX
"kmalloc failed\n");
371 memset(irq
, 0, sizeof(*irq
) * TAHVO_MAX_IRQ_BUF_LEN
);
372 for (i
= 0; i
< TAHVO_MAX_IRQ_BUF_LEN
; i
++)
373 list_add(&irq
[i
].node
, &tahvo_irqs_reserve
);
375 tahvo_irq_block
= irq
;
377 spin_lock_init(&tahvo_irqs_lock
);
378 mutex_init(&tahvo_mutex
);
380 /* Request a misc device */
381 res
= misc_register(&tahvo_device
);
383 printk(KERN_ERR PFX
"unable to register misc device for %s\n",
395 void tahvo_user_cleanup(void)
397 /* Unregister our misc device */
398 misc_deregister(&tahvo_device
);
399 /* Unregister and disable all TAHVO interrupts */
400 tahvo_unreg_irq_handlers();
401 kfree(tahvo_irq_block
);
404 MODULE_DESCRIPTION("Tahvo ASIC user space functions");
405 MODULE_LICENSE("GPL");
406 MODULE_AUTHOR("Mikko Ylinen");