1 /* linux/drivers/char/scx200_gpio.c
3 National Semiconductor SCx200 GPIO driver. Allows a user space
4 process to play with the GPIO pins.
6 Copyright (c) 2001,2002 Christer Weinigel <wingel@nano-system.com> */
8 #include <linux/config.h>
9 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/errno.h>
13 #include <linux/kernel.h>
14 #include <linux/init.h>
15 #include <linux/platform_device.h>
16 #include <asm/uaccess.h>
19 #include <linux/types.h>
20 #include <linux/cdev.h>
22 #include <linux/scx200_gpio.h>
24 #define NAME "scx200_gpio"
27 static struct platform_device
*pdev
;
29 MODULE_AUTHOR("Christer Weinigel <wingel@nano-system.com>");
30 MODULE_DESCRIPTION("NatSemi SCx200 GPIO Pin Driver");
31 MODULE_LICENSE("GPL");
33 static int major
= 0; /* default to dynamic major */
34 module_param(major
, int, 0);
35 MODULE_PARM_DESC(major
, "Major device number");
37 extern void scx200_gpio_dump(unsigned index
);
39 static ssize_t
scx200_gpio_write(struct file
*file
, const char __user
*data
,
40 size_t len
, loff_t
*ppos
)
42 unsigned m
= iminor(file
->f_dentry
->d_inode
);
46 for (i
= 0; i
< len
; ++i
) {
48 if (get_user(c
, data
+ i
))
52 scx200_gpio_set(m
, 0);
55 scx200_gpio_set(m
, 1);
58 printk(KERN_INFO NAME
": GPIO%d output enabled\n", m
);
59 scx200_gpio_configure(m
, ~1, 1);
62 printk(KERN_INFO NAME
": GPIO%d output disabled\n", m
);
63 scx200_gpio_configure(m
, ~1, 0);
66 printk(KERN_INFO NAME
": GPIO%d output is push pull\n", m
);
67 scx200_gpio_configure(m
, ~2, 2);
70 printk(KERN_INFO NAME
": GPIO%d output is open drain\n", m
);
71 scx200_gpio_configure(m
, ~2, 0);
74 printk(KERN_INFO NAME
": GPIO%d pull up enabled\n", m
);
75 scx200_gpio_configure(m
, ~4, 4);
78 printk(KERN_INFO NAME
": GPIO%d pull up disabled\n", m
);
79 scx200_gpio_configure(m
, ~4, 0);
83 /* View Current pin settings */
87 /* end of settings string, do nothing */
91 ": GPIO-%2d bad setting: chr<0x%2x>\n", m
,
97 return -EINVAL
; /* full string handled, report error */
102 static ssize_t
scx200_gpio_read(struct file
*file
, char __user
*buf
,
103 size_t len
, loff_t
*ppos
)
105 unsigned m
= iminor(file
->f_dentry
->d_inode
);
108 value
= scx200_gpio_get(m
);
109 if (put_user(value
? '1' : '0', buf
))
115 static int scx200_gpio_open(struct inode
*inode
, struct file
*file
)
117 unsigned m
= iminor(inode
);
120 return nonseekable_open(inode
, file
);
123 static int scx200_gpio_release(struct inode
*inode
, struct file
*file
)
129 static struct file_operations scx200_gpio_fops
= {
130 .owner
= THIS_MODULE
,
131 .write
= scx200_gpio_write
,
132 .read
= scx200_gpio_read
,
133 .open
= scx200_gpio_open
,
134 .release
= scx200_gpio_release
,
137 struct cdev
*scx200_devices
;
138 static int num_pins
= 32;
140 static int __init
scx200_gpio_init(void)
143 dev_t dev
= MKDEV(major
, 0);
145 if (!scx200_gpio_present()) {
146 printk(KERN_ERR NAME
": no SCx200 gpio present\n");
150 /* support dev_dbg() with pdev->dev */
151 pdev
= platform_device_alloc(DEVNAME
, 0);
155 rc
= platform_device_add(pdev
);
160 rc
= register_chrdev_region(dev
, num_pins
, "scx200_gpio");
162 rc
= alloc_chrdev_region(&dev
, 0, num_pins
, "scx200_gpio");
166 dev_err(&pdev
->dev
, "SCx200 chrdev_region err: %d\n", rc
);
167 goto undo_platform_device_add
;
169 scx200_devices
= kzalloc(num_pins
* sizeof(struct cdev
), GFP_KERNEL
);
170 if (!scx200_devices
) {
172 goto undo_chrdev_region
;
174 for (i
= 0; i
< num_pins
; i
++) {
175 struct cdev
*cdev
= &scx200_devices
[i
];
176 cdev_init(cdev
, &scx200_gpio_fops
);
177 cdev
->owner
= THIS_MODULE
;
178 rc
= cdev_add(cdev
, MKDEV(major
, i
), 1);
179 /* tolerate 'minor' errors */
181 dev_err(&pdev
->dev
, "Error %d on minor %d", rc
, i
);
184 return 0; /* succeed */
187 unregister_chrdev_region(dev
, num_pins
);
188 undo_platform_device_add
:
189 platform_device_put(pdev
);
195 static void __exit
scx200_gpio_cleanup(void)
197 kfree(scx200_devices
);
198 unregister_chrdev_region(MKDEV(major
, 0), num_pins
);
199 platform_device_put(pdev
);
200 platform_device_unregister(pdev
);
204 module_init(scx200_gpio_init
);
205 module_exit(scx200_gpio_cleanup
);