aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/scx200_gpio.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/drivers/char/scx200_gpio.c b/drivers/char/scx200_gpio.c
index 507a5bf567cb..e6e52c48697b 100644
--- a/drivers/char/scx200_gpio.c
+++ b/drivers/char/scx200_gpio.c
@@ -6,11 +6,13 @@
6 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */ 6 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */
7 7
8#include <linux/config.h> 8#include <linux/config.h>
9#include <linux/device.h>
9#include <linux/fs.h> 10#include <linux/fs.h>
10#include <linux/module.h> 11#include <linux/module.h>
11#include <linux/errno.h> 12#include <linux/errno.h>
12#include <linux/kernel.h> 13#include <linux/kernel.h>
13#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/platform_device.h>
14#include <asm/uaccess.h> 16#include <asm/uaccess.h>
15#include <asm/io.h> 17#include <asm/io.h>
16 18
@@ -20,6 +22,9 @@
20#include <linux/scx200_gpio.h> 22#include <linux/scx200_gpio.h>
21 23
22#define NAME "scx200_gpio" 24#define NAME "scx200_gpio"
25#define DEVNAME NAME
26
27static struct platform_device *pdev;
23 28
24MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>"); 29MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
25MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver"); 30MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver");
@@ -114,56 +119,70 @@ static struct file_operations scx200_gpio_fops = {
114}; 119};
115 120
116struct cdev *scx200_devices; 121struct cdev *scx200_devices;
117int num_devs = 32; 122static int num_pins = 32;
118 123
119static int __init scx200_gpio_init(void) 124static int __init scx200_gpio_init(void)
120{ 125{
121 int rc, i; 126 int rc, i;
122 dev_t dev = MKDEV(major, 0); 127 dev_t dev = MKDEV(major, 0);
123 128
124 printk(KERN_DEBUG NAME ": NatSemi SCx200 GPIO Driver\n");
125
126 if (!scx200_gpio_present()) { 129 if (!scx200_gpio_present()) {
127 printk(KERN_ERR NAME ": no SCx200 gpio present\n"); 130 printk(KERN_ERR NAME ": no SCx200 gpio present\n");
128 return -ENODEV; 131 return -ENODEV;
129 } 132 }
133
134 /* support dev_dbg() with pdev->dev */
135 pdev = platform_device_alloc(DEVNAME, 0);
136 if (!pdev)
137 return -ENOMEM;
138
139 rc = platform_device_add(pdev);
140 if (rc)
141 goto undo_malloc;
142
130 if (major) 143 if (major)
131 rc = register_chrdev_region(dev, num_devs, "scx200_gpio"); 144 rc = register_chrdev_region(dev, num_pins, "scx200_gpio");
132 else { 145 else {
133 rc = alloc_chrdev_region(&dev, 0, num_devs, "scx200_gpio"); 146 rc = alloc_chrdev_region(&dev, 0, num_pins, "scx200_gpio");
134 major = MAJOR(dev); 147 major = MAJOR(dev);
135 } 148 }
136 if (rc < 0) { 149 if (rc < 0) {
137 printk(KERN_ERR NAME ": SCx200 chrdev_region: %d\n", rc); 150 dev_err(&pdev->dev, "SCx200 chrdev_region err: %d\n", rc);
138 return rc; 151 goto undo_platform_device_add;
139 } 152 }
140 scx200_devices = kzalloc(num_devs * sizeof(struct cdev), GFP_KERNEL); 153 scx200_devices = kzalloc(num_pins * sizeof(struct cdev), GFP_KERNEL);
141 if (!scx200_devices) { 154 if (!scx200_devices) {
142 rc = -ENOMEM; 155 rc = -ENOMEM;
143 goto fail_malloc; 156 goto undo_chrdev_region;
144 } 157 }
145 for (i = 0; i < num_devs; i++) { 158 for (i = 0; i < num_pins; i++) {
146 struct cdev *cdev = &scx200_devices[i]; 159 struct cdev *cdev = &scx200_devices[i];
147 cdev_init(cdev, &scx200_gpio_fops); 160 cdev_init(cdev, &scx200_gpio_fops);
148 cdev->owner = THIS_MODULE; 161 cdev->owner = THIS_MODULE;
149 cdev->ops = &scx200_gpio_fops;
150 rc = cdev_add(cdev, MKDEV(major, i), 1); 162 rc = cdev_add(cdev, MKDEV(major, i), 1);
151 /* Fail gracefully if need be */ 163 /* tolerate 'minor' errors */
152 if (rc) 164 if (rc)
153 printk(KERN_ERR NAME "Error %d on minor %d", rc, i); 165 dev_err(&pdev->dev, "Error %d on minor %d", rc, i);
154 } 166 }
155 167
156 return 0; /* succeed */ 168 return 0; /* succeed */
157 169
158fail_malloc: 170undo_chrdev_region:
159 unregister_chrdev_region(dev, num_devs); 171 unregister_chrdev_region(dev, num_pins);
172undo_platform_device_add:
173 platform_device_put(pdev);
174undo_malloc:
175 kfree(pdev);
160 return rc; 176 return rc;
161} 177}
162 178
163static void __exit scx200_gpio_cleanup(void) 179static void __exit scx200_gpio_cleanup(void)
164{ 180{
165 kfree(scx200_devices); 181 kfree(scx200_devices);
166 unregister_chrdev_region(MKDEV(major, 0), num_devs); 182 unregister_chrdev_region(MKDEV(major, 0), num_pins);
183 platform_device_put(pdev);
184 platform_device_unregister(pdev);
185 /* kfree(pdev); */
167} 186}
168 187
169module_init(scx200_gpio_init); 188module_init(scx200_gpio_init);