MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / char / moxa_dio.c
blobb68cd35cd12071373769dc400b87b541c75cac63
1 /*
2 * This is Moxa CPU DIO device driver.
3 * It is from misc interface. So the device node major number is 10.
4 * The device node minor number is following:
5 * dio: 104
7 * History:
8 * Date Aurhor Comment
9 * 12-06-2005 Victor Yu. Create it.
11 #include <linux/config.h>
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/types.h>
15 #include <linux/miscdevice.h>
16 #include <linux/fcntl.h>
17 #include <linux/init.h>
18 #include <linux/poll.h>
19 #include <linux/proc_fs.h>
20 #include <linux/spinlock.h>
21 #include <linux/delay.h>
22 #include <linux/rtc.h>
23 #include <linux/timer.h>
24 #include <linux/ioport.h>
25 #include <linux/proc_fs.h>
27 #include <asm/io.h>
28 #include <asm/uaccess.h>
29 #include <asm/system.h>
30 #include <asm/arch/cpe/cpe.h>
31 #include <asm/arch/gpio.h>
34 #define MOXA_DIO_MINOR 104
36 #if defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
37 #define DO_BASE_SHIFT 22
38 #define DO_MASK (0x01<<DO_BASE_SHIFT)
39 #define GPIO_MASK (DO_MASK)
40 #else
41 #define DI_BASE_SHIFT 4
42 #define DO_BASE_SHIFT 18
43 #define DI_MASK (0x0f<<DI_BASE_SHIFT)
44 #define DO_MASK (0x0f<<DO_BASE_SHIFT)
45 #define GPIO_MASK (DI_MASK|DO_MASK)
46 #endif
49 // DIO file operaiton function call
51 #if defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
52 #define MAX_DIO 1 // just only DO
53 #elif defined(CONFIG_ARCH_W321) || defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_w325) || defined(CONFIG_ARCH_W315) || defined(CONFIG_UC_7112_LX_PLUS)
54 #define MAX_DIO 0
55 #else
56 #define MAX_DIO 4
57 #endif
58 #define DIO_INPUT 1
59 #define DIO_OUTPUT 0
60 #define DIO_HIGH 1
61 #define DIO_LOW 0
62 #define DIO_BASE 3
63 #define IOCTL_DIO_GET_MODE 1
64 #define IOCTL_DIO_SET_MODE 2
65 #define IOCTL_DIO_GET_DATA 3
66 #define IOCTL_DIO_SET_DATA 4
67 #define IOCTL_SET_DOUT 15
68 #define IOCTL_GET_DOUT 16
69 #define IOCTL_GET_DIN 17
70 struct dio_set_struct {
71 int io_number;
72 int mode_data; // 1 for input, 0 for output, 1 for high, 0 for low
76 struct proc_dir_entry* dio_proc;
77 #define dio_proc_name "driver/dio"
78 #define MAX_GPIO 32
79 int dio_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
81 char *out = page;
82 int pin_count, len;
84 for ( pin_count = 0 ; pin_count < MAX_GPIO ; pin_count++ )
85 out += sprintf( out ,"PIN%d:%s:%s\n",pin_count, mcpu_gpio_get_inout(1<<pin_count)?"OUT":"IN", mcpu_gpio_get(1<<pin_count)?"HIGH":"LOW");
87 len = out -page - off;
88 if (len < count) {
89 *eof = 1;
90 if (len <= 0)
91 return 0;
92 } else
93 len = count;
94 *start = page + off;
96 return len;
99 int dio_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data)
101 char kbuffer[64], in_out_mode[2], mode[2], pin[3];
102 int num_count, var_num, byte_count;
104 if ( copy_from_user(kbuffer, (char*)buffer , count) )
105 return -EFAULT;
107 kbuffer[count+1] = '\0';
108 memset(pin,0,3);
109 memset(in_out_mode,0,2);
110 memset(mode,0,2);
111 num_count = var_num = 0 ;
113 for ( byte_count = 0 ; byte_count < count ; byte_count++ ) {
114 if ( kbuffer[byte_count] != ' ' && kbuffer[byte_count] != '\0' && kbuffer[byte_count] != '\n' ) {
115 if ( var_num == 0 ) {
116 num_count++;
117 if ( num_count > 2 ) {
118 printk("The max pin number is %d !!\n",MAX_GPIO);
119 return -EINVAL;
121 pin[num_count-1] = kbuffer[byte_count];
122 pin[num_count] = '\0';
125 if ( var_num == 1 ) {
126 num_count++;
127 if ( num_count > 1 ) {
128 printk("The in mode = 1 out mode = 0 !!\n");
129 return -EINVAL;
131 in_out_mode[num_count-1] = kbuffer[byte_count];
132 in_out_mode[num_count] = '\0';
135 if ( var_num == 2 ) {
136 num_count++;
137 if ( num_count > 1 ) {
138 printk("The in mode = 1 out mode = 0 !!\n");
139 return -EINVAL;
141 mode[num_count-1] = kbuffer[byte_count];
142 mode[num_count] = '\0';
145 } else {
146 if ( pin[0] != 0 && in_out_mode[0] == 0 ) {
147 var_num = 1;
148 num_count = 0;
150 if ( pin[0]!= 0 && in_out_mode[0] != 0 && mode[0] == 0 ) {
151 var_num = 2;
152 num_count = 0;
157 num_count = simple_strtol(pin, NULL, 0); // to keep pin number
158 var_num = simple_strtol(in_out_mode, NULL, 0); // to keep in/out setting
159 byte_count = simple_strtol(mode, NULL, 0); // to keep state setting
161 if ( num_count >= MAX_GPIO ) {
162 //printk("The max pin number is %d !!\n",MAX_GPIO-1);
163 goto error_write_proc;
166 if ( var_num == MCPU_GPIO_OUTPUT ) {
167 mcpu_gpio_inout(1<<num_count, MCPU_GPIO_OUTPUT );
168 if ( byte_count == DIO_HIGH )
169 mcpu_gpio_set(1<<num_count , MCPU_GPIO_HIGH);
170 else if ( byte_count == DIO_LOW )
171 mcpu_gpio_set(1<<num_count, MCPU_GPIO_LOW);
172 else
173 goto error_write_proc;
174 } else if ( var_num == MCPU_GPIO_INPUT ) {
175 mcpu_gpio_inout(1<<num_count , MCPU_GPIO_INPUT );
176 } else {
177 //printk("OUTPUT = 1, INPUT = 0 !!\n");
178 goto error_write_proc;
181 return count;
183 error_write_proc:
184 return -EINVAL;
187 static int dio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
189 struct dio_set_struct set;
191 #if defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
192 switch ( cmd ) {
193 case IOCTL_SET_DOUT :
194 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
195 return -EFAULT;
196 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
197 return -EINVAL;
198 if ( set.mode_data == DIO_HIGH )
199 mcpu_gpio_set(1<<(set.io_number+DO_BASE_SHIFT), MCPU_GPIO_HIGH);
200 else if ( set.mode_data == DIO_LOW )
201 mcpu_gpio_set(1<<(set.io_number+DO_BASE_SHIFT), MCPU_GPIO_LOW);
202 else
203 return -EINVAL;
204 break;
205 case IOCTL_GET_DOUT :
206 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
207 return -EFAULT;
208 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
209 return -EINVAL;
210 if ( mcpu_gpio_get(1<<(set.io_number+DO_BASE_SHIFT)) )
211 set.mode_data = 1;
212 else
213 set.mode_data = 0;
214 if ( copy_to_user((struct dio_set_struct *)arg, &set, sizeof(struct dio_set_struct)) )
215 return -EFAULT;
216 break;
217 default:
218 return -EINVAL;
220 return 0;
221 #elif defined(CONFIG_ARCH_W321) || defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_w325) || defined(CONFIG_ARCH_W315) || defined(CONFIG_UC_7112_LX_PLUS)
222 return -EINVAL;
223 #else
224 switch ( cmd ) {
225 case IOCTL_SET_DOUT :
226 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
227 return -EFAULT;
228 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
229 return -EINVAL;
230 if ( set.mode_data == DIO_HIGH )
231 mcpu_gpio_set(1<<(set.io_number+DO_BASE_SHIFT), MCPU_GPIO_HIGH);
232 else if ( set.mode_data == DIO_LOW )
233 mcpu_gpio_set(1<<(set.io_number+DO_BASE_SHIFT), MCPU_GPIO_LOW);
234 else
235 return -EINVAL;
236 break;
237 case IOCTL_GET_DOUT :
238 case IOCTL_GET_DIN :
239 if ( copy_from_user(&set, (struct dio_set_struct *)arg, sizeof(struct dio_set_struct)) )
240 return -EFAULT;
241 if ( set.io_number < 0 || set.io_number >= MAX_DIO )
242 return -EINVAL;
243 if ( cmd == IOCTL_GET_DOUT ) {
244 if ( mcpu_gpio_get(1<<(set.io_number+DO_BASE_SHIFT)) )
245 set.mode_data = 1;
246 else
247 set.mode_data = 0;
248 } else {
249 if ( mcpu_gpio_get(1<<(set.io_number+DI_BASE_SHIFT)) )
250 set.mode_data = 1;
251 else
252 set.mode_data = 0;
254 if ( copy_to_user((struct dio_set_struct *)arg, &set, sizeof(struct dio_set_struct)) )
255 return -EFAULT;
256 break;
257 default:
258 return -EINVAL;
260 return 0;
261 #endif
264 static int dio_open(struct inode *inode, struct file *file)
266 if ( MINOR(inode->i_rdev) == MOXA_DIO_MINOR )
267 return 0;
269 return -ENODEV;
272 static int dio_release(struct inode *inode, struct file *file)
274 return 0;
277 static struct file_operations dio_fops = {
278 owner:THIS_MODULE,
279 llseek:NULL,
280 ioctl:dio_ioctl,
281 open:dio_open,
282 release:dio_release,
285 static struct miscdevice dio_dev = {
286 MOXA_DIO_MINOR,
287 "dio",
288 &dio_fops
291 static void __exit dio_exit(void)
293 remove_proc_entry(dio_proc_name,0);
294 misc_deregister(&dio_dev);
297 static int __init dio_init(void)
299 printk("Register IO misc ver1.0 ");
300 if ( misc_register(&dio_dev) ) {
301 printk("fail !\n");
302 return -ENOMEM;
305 // set the CPU for GPIO
306 #if defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
307 mcpu_gpio_mp_set(GPIO_MASK);
308 #elif defined(CONFIG_ARCH_W321) || defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_w325) || defined(CONFIG_ARCH_W315) || defined(CONFIG_UC_7112_LX_PLUS)
309 // none DI & DO
310 #else
311 mcpu_gpio_mp_set(GPIO_MASK);
312 #endif
314 // default set all GPIO for input/ouput
315 #if defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1)
316 mcpu_gpio_inout(DO_MASK, MCPU_GPIO_OUTPUT);
317 #elif defined(CONFIG_ARCH_W321) || defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_w325) || defined(CONFIG_ARCH_W315) || defined(CONFIG_UC_7112_LX_PLUS)
318 // none DI & DO
319 #else
320 mcpu_gpio_inout(DI_MASK, MCPU_GPIO_INPUT);
321 mcpu_gpio_inout(DO_MASK, MCPU_GPIO_OUTPUT);
322 #endif
324 dio_proc = create_proc_entry(dio_proc_name, 0, NULL);
325 dio_proc->read_proc = dio_read_proc;
326 dio_proc->write_proc = dio_write_proc;
328 printk("OK.\n");
329 return 0;
332 module_init(dio_init);
333 module_exit(dio_exit);
335 MODULE_AUTHOR("Victor Yu");
336 MODULE_LICENSE("GPL");