diff options
Diffstat (limited to 'drivers/char/scx200_gpio.c')
-rw-r--r-- | drivers/char/scx200_gpio.c | 72 |
1 files changed, 29 insertions, 43 deletions
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c index 45083e5dd23..b956c7babd1 100644 --- a/drivers/char/scx200_gpio.c +++ b/drivers/char/scx200_gpio.c @@ -5,7 +5,6 @@ Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */ -#include <linux/config.h> #include <linux/device.h> #include <linux/fs.h> #include <linux/module.h> @@ -22,37 +21,37 @@ #include <linux/scx200_gpio.h> #include <linux/nsc_gpio.h> -#define NAME "scx200_gpio" -#define DEVNAME NAME +#define DRVNAME "scx200_gpio" static struct platform_device *pdev; MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); -MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver"); +MODULE_DESCRIPTION("NatSemi/AMD SCx200 GPIO Pin Driver"); MODULE_LICENSE("GPL"); static int major = 0; /* default to dynamic major */ module_param(major, int, 0); MODULE_PARM_DESC(major, "Major device number"); -struct nsc_gpio_ops scx200_access = { +#define MAX_PINS 32 /* 64 later, when known ok */ + +struct nsc_gpio_ops scx200_gpio_ops = { .owner = THIS_MODULE, .gpio_config = scx200_gpio_configure, .gpio_dump = nsc_gpio_dump, .gpio_get = scx200_gpio_get, .gpio_set = scx200_gpio_set, - .gpio_set_high = scx200_gpio_set_high, - .gpio_set_low = scx200_gpio_set_low, .gpio_change = scx200_gpio_change, .gpio_current = scx200_gpio_current }; +EXPORT_SYMBOL(scx200_gpio_ops); static int scx200_gpio_open(struct inode *inode, struct file *file) { unsigned m = iminor(inode); - file->private_data = &scx200_access; + file->private_data = &scx200_gpio_ops; - if (m > 63) + if (m >= MAX_PINS) return -EINVAL; return nonseekable_open(inode, file); } @@ -62,8 +61,7 @@ static int scx200_gpio_release(struct inode *inode, struct file *file) return 0; } - -static struct file_operations scx200_gpio_fops = { +static const struct file_operations scx200_gpio_fileops = { .owner = THIS_MODULE, .write = nsc_gpio_write, .read = nsc_gpio_read, @@ -71,21 +69,20 @@ static struct file_operations scx200_gpio_fops = { .release = scx200_gpio_release, }; -struct cdev *scx200_devices; -static int num_pins = 32; +struct cdev scx200_gpio_cdev; /* use 1 cdev for all pins */ static int __init scx200_gpio_init(void) { - int rc, i; - dev_t dev = MKDEV(major, 0); + int rc; + dev_t devid; if (!scx200_gpio_present()) { - printk(KERN_ERR NAME ": no SCx200 gpio present\n"); + printk(KERN_ERR DRVNAME ": no SCx200 gpio present\n"); return -ENODEV; } /* support dev_dbg() with pdev->dev */ - pdev = platform_device_alloc(DEVNAME, 0); + pdev = platform_device_alloc(DRVNAME, 0); if (!pdev) return -ENOMEM; @@ -94,37 +91,25 @@ static int __init scx200_gpio_init(void) goto undo_malloc; /* nsc_gpio uses dev_dbg(), so needs this */ - scx200_access.dev = &pdev->dev; - - if (major) - rc = register_chrdev_region(dev, num_pins, "scx200_gpio"); - else { - rc = alloc_chrdev_region(&dev, 0, num_pins, "scx200_gpio"); - major = MAJOR(dev); + scx200_gpio_ops.dev = &pdev->dev; + + if (major) { + devid = MKDEV(major, 0); + rc = register_chrdev_region(devid, MAX_PINS, "scx200_gpio"); + } else { + rc = alloc_chrdev_region(&devid, 0, MAX_PINS, "scx200_gpio"); + major = MAJOR(devid); } if (rc < 0) { dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc); goto undo_platform_device_add; } - scx200_devices = kzalloc(num_pins * sizeof(struct cdev), GFP_KERNEL); - if (!scx200_devices) { - rc = -ENOMEM; - goto undo_chrdev_region; - } - for (i = 0; i < num_pins; i++) { - struct cdev *cdev = &scx200_devices[i]; - cdev_init(cdev, &scx200_gpio_fops); - cdev->owner = THIS_MODULE; - rc = cdev_add(cdev, MKDEV(major, i), 1); - /* tolerate 'minor' errors */ - if (rc) - dev_err(&pdev->dev, "Error %d on minor %d", rc, i); - } + + cdev_init(&scx200_gpio_cdev, &scx200_gpio_fileops); + cdev_add(&scx200_gpio_cdev, devid, MAX_PINS); return 0; /* succeed */ -undo_chrdev_region: - unregister_chrdev_region(dev, num_pins); undo_platform_device_add: platform_device_del(pdev); undo_malloc: @@ -135,10 +120,11 @@ undo_malloc: static void __exit scx200_gpio_cleanup(void) { - kfree(scx200_devices); - unregister_chrdev_region(MKDEV(major, 0), num_pins); + cdev_del(&scx200_gpio_cdev); + /* cdev_put(&scx200_gpio_cdev); */ + + unregister_chrdev_region(MKDEV(major, 0), MAX_PINS); platform_device_unregister(pdev); - /* kfree(pdev); */ } module_init(scx200_gpio_init); |