update brcm-2.4 to 2.4.35.4, integrate new broadcom system code, update broadcom...
[openwrt/svn-archive/archive.git] / target / linux / brcm-2.4 / files / arch / mips / bcm947xx / gpio.c
1 /*
2 * GPIO char driver
3 *
4 * Copyright 2005, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id$
13 */
14
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/fs.h>
18 #include <linux/miscdevice.h>
19 #include <asm/uaccess.h>
20
21 #include <typedefs.h>
22 #include <osl.h>
23 #include <sbutils.h>
24 #include <bcmdevs.h>
25
26 static sb_t *gpio_sbh;
27 static int gpio_major;
28 static devfs_handle_t gpio_dir;
29 static struct {
30 char *name;
31 devfs_handle_t handle;
32 } gpio_file[] = {
33 { "in", NULL },
34 { "out", NULL },
35 { "outen", NULL },
36 { "control", NULL }
37 };
38
39 static int
40 gpio_open(struct inode *inode, struct file * file)
41 {
42 if (MINOR(inode->i_rdev) > ARRAYSIZE(gpio_file))
43 return -ENODEV;
44
45 MOD_INC_USE_COUNT;
46 return 0;
47 }
48
49 static int
50 gpio_release(struct inode *inode, struct file * file)
51 {
52 MOD_DEC_USE_COUNT;
53 return 0;
54 }
55
56 static ssize_t
57 gpio_read(struct file *file, char *buf, size_t count, loff_t *ppos)
58 {
59 u32 val;
60
61 switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
62 case 0:
63 val = sb_gpioin(gpio_sbh);
64 break;
65 case 1:
66 val = sb_gpioout(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
67 break;
68 case 2:
69 val = sb_gpioouten(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
70 break;
71 case 3:
72 val = sb_gpiocontrol(gpio_sbh, 0, 0, GPIO_DRV_PRIORITY);
73 break;
74 default:
75 return -ENODEV;
76 }
77
78 if (put_user(val, (u32 *) buf))
79 return -EFAULT;
80
81 return sizeof(val);
82 }
83
84 static ssize_t
85 gpio_write(struct file *file, const char *buf, size_t count, loff_t *ppos)
86 {
87 u32 val;
88
89 if (get_user(val, (u32 *) buf))
90 return -EFAULT;
91
92 switch (MINOR(file->f_dentry->d_inode->i_rdev)) {
93 case 0:
94 return -EACCES;
95 case 1:
96 sb_gpioout(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
97 break;
98 case 2:
99 sb_gpioouten(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
100 break;
101 case 3:
102 sb_gpiocontrol(gpio_sbh, ~0, val, GPIO_DRV_PRIORITY);
103 break;
104 default:
105 return -ENODEV;
106 }
107
108 return sizeof(val);
109 }
110
111 static struct file_operations gpio_fops = {
112 owner: THIS_MODULE,
113 open: gpio_open,
114 release: gpio_release,
115 read: gpio_read,
116 write: gpio_write,
117 };
118
119 static int __init
120 gpio_init(void)
121 {
122 int i;
123
124 if (!(gpio_sbh = sb_kattach(SB_OSH)))
125 return -ENODEV;
126
127 sb_gpiosetcore(gpio_sbh);
128
129 if ((gpio_major = devfs_register_chrdev(0, "gpio", &gpio_fops)) < 0)
130 return gpio_major;
131
132 gpio_dir = devfs_mk_dir(NULL, "gpio", NULL);
133
134 for (i = 0; i < ARRAYSIZE(gpio_file); i++) {
135 gpio_file[i].handle = devfs_register(gpio_dir,
136 gpio_file[i].name,
137 DEVFS_FL_DEFAULT, gpio_major, i,
138 S_IFCHR | S_IRUGO | S_IWUGO,
139 &gpio_fops, NULL);
140 }
141
142 return 0;
143 }
144
145 static void __exit
146 gpio_exit(void)
147 {
148 int i;
149
150 for (i = 0; i < ARRAYSIZE(gpio_file); i++)
151 devfs_unregister(gpio_file[i].handle);
152 devfs_unregister(gpio_dir);
153 devfs_unregister_chrdev(gpio_major, "gpio");
154 sb_detach(gpio_sbh);
155 }
156
157 module_init(gpio_init);
158 module_exit(gpio_exit);