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.
10 #if 1 // add by Victor Yu. 02-09-2007
11 #include <linux/version.h>
13 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12) // add by Victor Yu. 02-09-2007
14 #include <linux/config.h>
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>
32 #include <asm/uaccess.h>
33 #include <asm/system.h>
35 #define MOXA_PIO_MINOR 104
37 static spinlock_t pio_lock=SPIN_LOCK_UNLOCKED;
39 // GPIO register offset on Moxa CPU
40 #define GPIO_DATA_OUT 0
41 #define GPIO_DATA_IN 4
42 #define GPIO_PIN_DIR 8
43 #define GPIO_DATA_SET 0x10
44 #define GPIO_DATA_CLEAR 0x14
45 #define GPIO_PIN_PULL_ENABLE 0x18
46 #define GPIO_PIN_PULL_TYPE 0x1C
47 #define GPIO_INT_ENABLE 0x20
48 #define GPIO_INT_RAW_STATE 0x24
49 #define GPIO_INT_MASKED_STATE 0x28
50 #define GPIO_INT_MASK 0x2C
51 #define GPIO_INT_CLEAR 0x30
52 #define GPIO_INT_TRIGGER 0x34
53 #define GPIO_INT_BOTH 0x38
54 #define GPIO_INT_RISE_NEG 0x3C
55 #define GPIO_BOUNCE_ENABLE 0x40
56 #define GPIO_BOUNCE_PRE_SCALE 0x44
58 #define GPIO_BASE_SHIFT 10
59 //#define GPIO_MASK (0xffff<<GPIO_BASE_SHIFT)
60 #define GPIO_MASK (0x3ff<<GPIO_BASE_SHIFT)
62 typedef struct _gpio_reg_struct {
63 unsigned int data_out;
66 unsigned int reserved;
67 unsigned int data_set;
68 unsigned int data_clear;
69 unsigned int pin_pull_enable;
70 unsigned int pin_pull_type;
71 unsigned int int_enable;
72 unsigned int int_raw_state;
73 unsigned int int_masked_state;
74 unsigned int int_mask;
75 unsigned int int_clear;
76 unsigned int int_trigger;
77 unsigned int int_both;
78 unsigned int int_rise_neg;
79 unsigned int bounce_enable;
80 unsigned int bounce_pre_scale;
82 static gpio_reg_struct *gpio_reg=(gpio_reg_struct *)CPE_GPIO_BASE;
85 // PIO file operaiton function call
93 #define IOCTL_PIO_GET_MODE 1
94 #define IOCTL_PIO_SET_MODE 2
95 #define IOCTL_PIO_GET_DATA 3
96 #define IOCTL_PIO_SET_DATA 4
97 struct pio_set_struct {
99 int mode_data; // 1 for input, 0 for output, 1 for high, 0 for low
102 static int pio_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
104 struct pio_set_struct set;
107 case IOCTL_PIO_SET_MODE :
108 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
110 if ( set.io_number < 0 || set.io_number > MAX_PIO )
112 if ( set.mode_data == PIO_INPUT )
113 writel(readl(&gpio_reg->pin_dir)&~(1<<(set.io_number+GPIO_BASE_SHIFT)), &gpio_reg->pin_dir);
114 else if ( set.mode_data == PIO_OUTPUT )
115 writel(readl(&gpio_reg->pin_dir)|(1<<(set.io_number+GPIO_BASE_SHIFT)), &gpio_reg->pin_dir);
119 case IOCTL_PIO_GET_MODE :
120 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
122 if ( set.io_number < 0 || set.io_number > MAX_PIO )
124 if ( readl(&gpio_reg->pin_dir) & (1<<(set.io_number+GPIO_BASE_SHIFT)) )
128 if ( copy_to_user((struct pio_set_struct *)arg, &set, sizeof(struct pio_set_struct)) )
131 case IOCTL_PIO_SET_DATA :
132 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
134 if ( set.io_number < 0 || set.io_number > MAX_PIO )
136 if ( set.mode_data == PIO_HIGH )
137 writel(readl(&gpio_reg->data_out)|(1<<(set.io_number+GPIO_BASE_SHIFT)), &gpio_reg->data_out);
138 else if ( set.mode_data == PIO_LOW )
139 writel(readl(&gpio_reg->data_out)&~(1<<(set.io_number+GPIO_BASE_SHIFT)), &gpio_reg->data_out);
143 case IOCTL_PIO_GET_DATA :
144 if ( copy_from_user(&set, (struct pio_set_struct *)arg, sizeof(struct pio_set_struct)) )
146 if ( set.io_number < 0 || set.io_number > MAX_PIO )
148 if ( readl(&gpio_reg->data_in) & (1<<(set.io_number+GPIO_BASE_SHIFT)) )
152 if ( copy_to_user((struct pio_set_struct *)arg, &set, sizeof(struct pio_set_struct)) )
161 static int pio_open(struct inode *inode, struct file *file)
163 if ( MINOR(inode->i_rdev) == MOXA_PIO_MINOR )
168 static int pio_release(struct inode *inode, struct file *file)
173 static struct file_operations pio_fops = {
180 static struct miscdevice pio_dev = {
186 static void __exit pio_exit(void)
188 spin_lock(&pio_lock);
189 misc_deregister(&pio_dev);
190 spin_unlock(&pio_lock);
193 #if 1 // add by Victor Yu. 03-08-2007
194 extern int moxa_gpio_sd_used_flag; // define on arch/arm/kernel/armksyms.c
196 static int __init pio_init(void)
198 printk("Moxa CPU misc: Register PIO misc ver1.0 ");
199 #if 1 // add by Victor Yu. 03-08-2007
202 local_irq_save(flags);
203 if ( moxa_gpio_sd_used_flag ) {
204 printk("The IO has used by other device driver !\n");
205 local_irq_restore(flags);
208 moxa_gpio_sd_used_flag = 1;
209 local_irq_restore(flags);
212 if ( misc_register(&pio_dev) ) {
217 // set the CPU for GPIO
218 *(volatile unsigned int *)(CPE_PMU_BASE+0x100) |= GPIO_MASK;
220 // default set all GPIO for input
221 writel(readl(&gpio_reg->pin_dir)&~GPIO_MASK, &gpio_reg->pin_dir);
223 // default set all GPIO interrupt disable
224 //writel(readl(&gpio_reg->int_enable)&~GPIO_MASK, &gpio_reg->int_enable);
226 // default set all GPIO pin pull disable
227 writel(readl(&gpio_reg->pin_pull_enable)|GPIO_MASK, &gpio_reg->pin_pull_enable);
229 // default set all GPIO data_out high
230 writel(readl(&gpio_reg->data_out)|GPIO_MASK, &gpio_reg->data_out);
235 module_init(pio_init);
236 module_exit(pio_exit);
238 MODULE_AUTHOR("Victor Yu");
239 MODULE_LICENSE("GPL");