|
|
|
@ -25,6 +25,7 @@ |
|
|
|
|
#include <asm/uaccess.h> |
|
|
|
|
#include <asm/io.h> |
|
|
|
|
#include <asm/gpio.h> |
|
|
|
|
#include <asm/atomic.h> |
|
|
|
|
#include <linux/init.h> |
|
|
|
|
#include <linux/genhd.h> |
|
|
|
|
#include <linux/device.h> |
|
|
|
@ -35,10 +36,12 @@ |
|
|
|
|
#define DEVNAME "gpio" |
|
|
|
|
|
|
|
|
|
static int dev_major; |
|
|
|
|
static int gpio_is_open = 0; |
|
|
|
|
unsigned int gpio_access_mask = 0; |
|
|
|
|
static unsigned int gpio_access_mask; |
|
|
|
|
static struct class *gpio_class; |
|
|
|
|
|
|
|
|
|
/* Counter is 1, if the device is not opened and zero (or less) if opened. */ |
|
|
|
|
static atomic_t gpio_open_cnt = ATOMIC_INIT(1); |
|
|
|
|
|
|
|
|
|
static int |
|
|
|
|
gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) |
|
|
|
|
{ |
|
|
|
@ -94,15 +97,18 @@ gpio_open(struct inode *inode, struct file *file) |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (gpio_is_open) |
|
|
|
|
{ |
|
|
|
|
/* FIXME: We should really allow multiple applications to open the device
|
|
|
|
|
* at the same time, as long as the apps access different IO pins. |
|
|
|
|
* The generic gpio-registration functions can be used for that. |
|
|
|
|
* Two new IOCTLs have to be introduced for that. Need to check userspace |
|
|
|
|
* compatibility first. --mb */ |
|
|
|
|
if (!atomic_dec_and_test(&gpio_open_cnt)) { |
|
|
|
|
atomic_inc(&gpio_open_cnt); |
|
|
|
|
printk(KERN_ERR DRVNAME ": Device with minor ID %d already in use\n", dev_minor); |
|
|
|
|
result = -EBUSY; |
|
|
|
|
goto out; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gpio_is_open = 1; |
|
|
|
|
|
|
|
|
|
out: |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
@ -110,7 +116,8 @@ out: |
|
|
|
|
static int |
|
|
|
|
gpio_close(struct inode * inode, struct file * file) |
|
|
|
|
{ |
|
|
|
|
gpio_is_open = 0; |
|
|
|
|
smp_mb__before_atomic_inc(); |
|
|
|
|
atomic_inc(&gpio_open_cnt); |
|
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|