Ignore:
Timestamp:
2010-06-13T15:27:06+02:00 (6 years ago)
Author:
claudio
Message:

[kernel] Extend the gpio device driver (#5671)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/target/linux/generic-2.6/files/drivers/char/gpio_dev.c

    r18927 r21787  
    1818 * Feedback, Bugs...  blogic@openwrt.org 
    1919 * 
     20 * dpg 20100106 
    2021 */ 
    2122 
     
    3738 
    3839static int dev_major; 
    39 static unsigned int gpio_access_mask; 
    4040static struct class *gpiodev_class; 
    4141 
    42 /* Counter is 1, if the device is not opened and zero (or less) if opened. */ 
    43 static atomic_t gpio_open_cnt = ATOMIC_INIT(1); 
    4442 
     43/* third argument of user space ioctl ('arg' here) contains the <pin> */ 
    4544static int 
    46 gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) 
     45gpio_ioctl(struct inode * inode, struct file * file, unsigned int cmd, 
     46           unsigned long arg) 
    4747{ 
    4848        int retval = 0; 
    49  
    50         if (((1 << arg) & gpio_access_mask) != (1 << arg)) 
    51         { 
    52                 retval = -EINVAL; 
    53                 goto out; 
    54         } 
    5549 
    5650        switch (cmd) 
     
    5953                retval = gpio_get_value(arg); 
    6054                break; 
    61  
    6255        case GPIO_SET: 
    6356                gpio_set_value(arg, 1); 
    6457                break; 
    65  
    6658        case GPIO_CLEAR: 
    6759                gpio_set_value(arg, 0); 
    6860                break; 
    69  
    7061        case GPIO_DIR_IN: 
    71                 gpio_direction_input(arg); 
     62                retval = gpio_direction_input(arg); 
    7263                break; 
    73  
    7464        case GPIO_DIR_OUT: 
    75                 gpio_direction_output(arg, 0); 
     65                retval = gpio_direction_output(arg, 0); 
    7666                break; 
    77  
     67        case GPIO_DIR_HIGH: 
     68                retval = gpio_direction_output(arg, 1); 
     69                break; 
     70        case GPIO_REQUEST: 
     71                /* should be first ioctl operation on <pin> */ 
     72                retval = gpio_request(arg, DRVNAME); 
     73                break; 
     74        case GPIO_FREE: 
     75                /* should be last ioctl operation on <pin> */ 
     76                /* may be needed first if previous user missed this ioctl */ 
     77                gpio_free(arg); 
     78                break; 
     79        case GPIO_CAN_SLEEP: 
     80                retval = gpio_cansleep(arg); 
     81                break; 
    7882        default: 
    7983                retval = -EINVAL; 
     84                /* = -ENOTTY; // correct return but ... */ 
    8085                break; 
    8186        } 
    82  
    83 out: 
    8487        return retval; 
    8588} 
    8689 
     90/* Allow co-incident opens */ 
    8791static int 
    8892gpio_open(struct inode *inode, struct file *file) 
     
    97101                goto out; 
    98102        } 
    99  
    100         /* FIXME: We should really allow multiple applications to open the device 
    101          *        at the same time, as long as the apps access different IO pins. 
    102          *        The generic gpio-registration functions can be used for that. 
    103          *        Two new IOCTLs have to be introduced for that. Need to check userspace 
    104          *        compatibility first. --mb */ 
    105         if (!atomic_dec_and_test(&gpio_open_cnt)) { 
    106                 atomic_inc(&gpio_open_cnt); 
    107                 printk(KERN_ERR DRVNAME ": Device with minor ID %d already in use\n", dev_minor); 
    108                 result = -EBUSY; 
    109                 goto out; 
    110         } 
    111  
    112103out: 
    113104        return result; 
     
    117108gpio_close(struct inode * inode, struct file * file) 
    118109{ 
    119         smp_mb__before_atomic_inc(); 
    120         atomic_inc(&gpio_open_cnt); 
    121  
     110        /* could track all <pin>s requested by this fd and gpio_free() 
     111         * them here 
     112         */ 
    122113        return 0; 
    123114} 
     
    141132                goto out; 
    142133        } 
    143  
    144134        gpiodev_class = class_create(THIS_MODULE, DRVNAME); 
    145135        device_create(gpiodev_class, NULL, MKDEV(dev_major, 0), dev, DEVNAME); 
    146  
    147136        printk(KERN_INFO DRVNAME ": gpio device registered with major %d\n", dev_major); 
    148  
    149         if (dev->num_resources != 1) 
    150         { 
    151                 printk(KERN_ERR DRVNAME ": device may only have 1 resource\n"); 
    152                 result = -ENODEV; 
    153                 goto out; 
    154         } 
    155  
    156         gpio_access_mask = dev->resource[0].start; 
    157  
    158         printk(KERN_INFO DRVNAME ": gpio platform device registered with access mask %08X\n", gpio_access_mask); 
    159137out: 
    160138        return result; 
     
    183161        int ret = platform_driver_register(&gpio_driver); 
    184162        if (ret) 
    185                 printk(KERN_INFO DRVNAME ": Error registering platfom driver!"); 
     163                printk(KERN_INFO DRVNAME ": Error registering platfom driver!\n"); 
    186164 
    187165        return ret; 
     
    198176 
    199177MODULE_LICENSE("GPL"); 
    200 MODULE_AUTHOR("John Crispin / OpenWrt"); 
     178MODULE_AUTHOR("John Crispin / OpenWrt +"); 
    201179MODULE_DESCRIPTION("Character device for for generic gpio api"); 
Note: See TracChangeset for help on using the changeset viewer.