MOXA linux-2.6.x / linux-2.6.19-uc1 from UC-7110-LX-BOOTLOADER-1.9_VERSION-4.2.tgz
[linux-2.6.19-moxart.git] / drivers / char / gpio.c
blobbf129c622e4b6c5130d46af7527e1cde41d0309a
1 /*
2 * pio: 104
4 * History:
5 * Date Aurhor Comment
6 * 12-06-2005 Victor Yu. Create it.
7 * 24-05-2006 Jimmy Chen. Fix it.
8 * 02-09-2007 Victor Yu. Porting to kernel verion 2.6.19.
9 */
10 #if 1 // add by Victor Yu. 02-09-2007
11 #include <linux/version.h>
12 #endif
13 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) // add by Victor Yu. 02-09-2007
14 #include <linux/config.h>
15 #endif
16 #include <asm/arch/moxa.h>
17 #include <linux/module.h>
18 #include <linux/kernel.h>
19 #include <linux/types.h>
20 #include <linux/miscdevice.h>
21 #include <linux/fcntl.h>
22 #include <linux/init.h>
23 #include <linux/poll.h>
24 #include <linux/proc_fs.h>
25 #include <linux/spinlock.h>
26 #include <linux/delay.h>
27 #include <linux/rtc.h>
28 #include <linux/timer.h>
29 #include <linux/ioport.h>
31 #include <asm/io.h>
32 #include <asm/uaccess.h>
33 #include <asm/system.h>
34 #include <asm/arch/gpio.h>
36 #define MOXA_PIO_MINOR 104
38 #define GPIO_BASE_SHIFT 10
39 #define GPIO_MASK (0x3ff<<GPIO_BASE_SHIFT)
42 // PIO file operaiton function call
44 #define MAX_PIO 10
45 #define PIO_INPUT 1
46 #define PIO_OUTPUT 0
47 #define PIO_HIGH 1
48 #define PIO_LOW 0
50 #define IOCTL_PIO_GET_MODE 1
51 #define IOCTL_PIO_SET_MODE 2
52 #define IOCTL_PIO_GET_DATA 3
53 #define IOCTL_PIO_SET_DATA 4
54 struct pio_set_struct {
55 int io_number;
56 int mode_data; // 1 for input, 0 for output, 1 for high, 0 for low
59 static int pio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
61 struct pio_set_struct set;
63 switch ( cmd ) {
64 case IOCTL_PIO_SET_MODE :
65 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
66 return -EFAULT;
67 if ( set.io_number < 0 || set.io_number > MAX_PIO )
68 return -EINVAL;
69 if ( set.mode_data == PIO_INPUT )
70 mcpu_gpio_inout(1<<(set.io_number+GPIO_BASE_SHIFT), MCPU_GPIO_INPUT);
71 else if ( set.mode_data == PIO_OUTPUT )
72 mcpu_gpio_inout(1<<(set.io_number+GPIO_BASE_SHIFT), MCPU_GPIO_OUTPUT);
73 else
74 return -EINVAL;
75 break;
76 case IOCTL_PIO_GET_MODE :
77 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
78 return -EFAULT;
79 if ( set.io_number < 0 || set.io_number > MAX_PIO )
80 return -EINVAL;
81 if ( mcpu_gpio_get_inout(1<<(set.io_number+GPIO_BASE_SHIFT)) == MCPU_GPIO_INPUT )
82 set.mode_data = PIO_INPUT;
83 else
84 set.mode_data = PIO_OUTPUT;
85 if ( copy_to_user((struct pio_set_struct *)arg, &set, sizeof(struct pio_set_struct)) )
86 return -EFAULT;
87 break;
88 case IOCTL_PIO_SET_DATA :
89 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
90 return -EFAULT;
91 if ( set.io_number < 0 || set.io_number > MAX_PIO )
92 return -EINVAL;
93 if ( set.mode_data == PIO_HIGH )
94 mcpu_gpio_set(1<<(set.io_number+GPIO_BASE_SHIFT), MCPU_GPIO_HIGH);
95 else if ( set.mode_data == PIO_LOW )
96 mcpu_gpio_set(1<<(set.io_number+GPIO_BASE_SHIFT), MCPU_GPIO_LOW);
97 else
98 return -EINVAL;
99 break;
100 case IOCTL_PIO_GET_DATA :
101 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
102 return -EFAULT;
103 if ( set.io_number < 0 || set.io_number > MAX_PIO )
104 return -EINVAL;
105 if ( mcpu_gpio_get(1<<(set.io_number+GPIO_BASE_SHIFT)) )
106 set.mode_data = PIO_HIGH;
107 else
108 set.mode_data = PIO_LOW;
109 if ( copy_to_user((struct pio_set_struct *)arg, &set, sizeof(struct pio_set_struct)) )
110 return -EFAULT;
111 break;
112 default:
113 return -EINVAL;
115 return 0;
118 static int pio_open(struct inode *inode, struct file *file)
120 if ( MINOR(inode->i_rdev) == MOXA_PIO_MINOR )
121 return 0;
122 return -ENODEV;
125 static int pio_release(struct inode *inode, struct file *file)
127 return 0;
130 static struct file_operations pio_fops = {
131 owner:THIS_MODULE,
132 llseek:NULL,
133 ioctl:pio_ioctl,
134 open:pio_open,
135 release:pio_release,
137 static struct miscdevice pio_dev = {
138 MOXA_PIO_MINOR,
139 "pio",
140 &pio_fops
143 #if 1 // add by Victor Yu. 03-08-2007
144 extern int moxa_gpio_sd_used_flag; // define on arch/arm/kernel/armksyms.c
145 #endif
146 static void __exit pio_exit(void)
148 misc_deregister(&pio_dev);
149 #if 1 // add by Victor Yu. 12-05-2007
151 unsigned long flags;
152 local_irq_save(flags);
153 moxa_gpio_sd_used_flag = 0;
154 local_irq_restore(flags);
156 #endif
159 static int __init pio_init(void)
161 printk("Moxa CPU misc: Register PIO misc ver1.0 ");
162 #if 1 // add by Victor Yu. 03-08-2007
164 unsigned long flags;
165 local_irq_save(flags);
166 if ( moxa_gpio_sd_used_flag ) {
167 printk("The IO has used by other device driver !\n");
168 local_irq_restore(flags);
169 return -ENODEV;
171 moxa_gpio_sd_used_flag = 1;
172 local_irq_restore(flags);
174 #endif
175 if ( misc_register(&pio_dev) ) {
176 printk("fail !\n");
177 return -ENOMEM;
180 // set the CPU for GPIO
181 mcpu_gpio_mp_set(GPIO_MASK);
183 // default set all GPIO for input
184 mcpu_gpio_inout(GPIO_MASK, MCPU_GPIO_OUTPUT);
186 // default set all GPIO data_out high
187 mcpu_gpio_set(GPIO_MASK, MCPU_GPIO_HIGH);
188 printk("OK.\n");
189 return 0;
192 module_init(pio_init);
193 module_exit(pio_exit);
195 MODULE_AUTHOR("Victor Yu");
196 MODULE_LICENSE("GPL");