linux/drivers/char/scx200_gpio.c
<<
>>
Prefs
   1/* linux/drivers/char/scx200_gpio.c
   2
   3   National Semiconductor SCx200 GPIO driver.  Allows a user space
   4   process to play with the GPIO pins.
   5
   6   Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */
   7
   8#include <linux/device.h>
   9#include <linux/fs.h>
  10#include <linux/module.h>
  11#include <linux/errno.h>
  12#include <linux/kernel.h>
  13#include <linux/init.h>
  14#include <linux/platform_device.h>
  15#include <asm/uaccess.h>
  16#include <asm/io.h>
  17
  18#include <linux/types.h>
  19#include <linux/cdev.h>
  20
  21#include <linux/scx200_gpio.h>
  22#include <linux/nsc_gpio.h>
  23
  24#define DRVNAME "scx200_gpio"
  25
  26static struct platform_device *pdev;
  27
  28MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
  29MODULE_DESCRIPTION("NatSemi/AMD SCx200 GPIO Pin Driver");
  30MODULE_LICENSE("GPL");
  31
  32static int major = 0;           /* default to dynamic major */
  33module_param(major, int, 0);
  34MODULE_PARM_DESC(major, "Major device number");
  35
  36#define MAX_PINS 32             /* 64 later, when known ok */
  37
  38struct nsc_gpio_ops scx200_gpio_ops = {
  39        .owner          = THIS_MODULE,
  40        .gpio_config    = scx200_gpio_configure,
  41        .gpio_dump      = nsc_gpio_dump,
  42        .gpio_get       = scx200_gpio_get,
  43        .gpio_set       = scx200_gpio_set,
  44        .gpio_change    = scx200_gpio_change,
  45        .gpio_current   = scx200_gpio_current
  46};
  47EXPORT_SYMBOL_GPL(scx200_gpio_ops);
  48
  49static int scx200_gpio_open(struct inode *inode, struct file *file)
  50{
  51        unsigned m = iminor(inode);
  52        file->private_data = &scx200_gpio_ops;
  53
  54        if (m >= MAX_PINS)
  55                return -EINVAL;
  56        return nonseekable_open(inode, file);
  57}
  58
  59static int scx200_gpio_release(struct inode *inode, struct file *file)
  60{
  61        return 0;
  62}
  63
  64static const struct file_operations scx200_gpio_fileops = {
  65        .owner   = THIS_MODULE,
  66        .write   = nsc_gpio_write,
  67        .read    = nsc_gpio_read,
  68        .open    = scx200_gpio_open,
  69        .release = scx200_gpio_release,
  70};
  71
  72static struct cdev scx200_gpio_cdev;  /* use 1 cdev for all pins */
  73
  74static int __init scx200_gpio_init(void)
  75{
  76        int rc;
  77        dev_t devid;
  78
  79        if (!scx200_gpio_present()) {
  80                printk(KERN_ERR DRVNAME ": no SCx200 gpio present\n");
  81                return -ENODEV;
  82        }
  83
  84        /* support dev_dbg() with pdev->dev */
  85        pdev = platform_device_alloc(DRVNAME, 0);
  86        if (!pdev)
  87                return -ENOMEM;
  88
  89        rc = platform_device_add(pdev);
  90        if (rc)
  91                goto undo_malloc;
  92
  93        /* nsc_gpio uses dev_dbg(), so needs this */
  94        scx200_gpio_ops.dev = &pdev->dev;
  95
  96        if (major) {
  97                devid = MKDEV(major, 0);
  98                rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio");
  99        } else {
 100                rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio");
 101                major = MAJOR(devid);
 102        }
 103        if (rc < 0) {
 104                dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
 105                goto undo_platform_device_add;
 106        }
 107
 108        cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops);
 109        cdev_add(&scx200_gpio_cdev, devid, MAX_PINS);
 110
 111        return 0; /* succeed */
 112
 113undo_platform_device_add:
 114        platform_device_del(pdev);
 115undo_malloc:
 116        platform_device_put(pdev);
 117
 118        return rc;
 119}
 120
 121static void __exit scx200_gpio_cleanup(void)
 122{
 123        cdev_del(&scx200_gpio_cdev);
 124        /* cdev_put(&scx200_gpio_cdev); */
 125
 126        unregister_chrdev_region(MKDEV(major, 0), MAX_PINS);
 127        platform_device_unregister(pdev);
 128}
 129
 130module_init(scx200_gpio_init);
 131module_exit(scx200_gpio_cleanup);
 132
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.