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