2 * This is Moxa CPU device driver.
3 * This device driver will control the READY LED & RESET button.
4 * Also this device driver will control debug LED.
5 * It is from misc interface. So the device node major number is 10.
6 * The device node minor number is following:
11 * 02-22-2006 Victor Yu. Create it.
13 #include <linux/config.h>
14 #include <linux/module.h>
15 #include <linux/kernel.h>
16 #include <linux/types.h>
17 #include <linux/miscdevice.h>
18 #include <linux/fcntl.h>
19 #include <linux/init.h>
20 #include <linux/poll.h>
21 #include <linux/proc_fs.h>
22 #include <linux/spinlock.h>
23 #include <linux/delay.h>
24 #include <linux/rtc.h>
25 #include <linux/timer.h>
26 #include <linux/ioport.h>
27 #include <linux/kmod.h>
30 #include <asm/uaccess.h>
31 #include <asm/system.h>
32 #include <asm/arch/cpe/cpe.h>
33 #include <asm/arch/gpio.h>
35 #define MOXA_MISC_MINOR 105
37 #if (defined CONFIG_ARCH_IA241_32128)||(defined CONFIG_ARCH_IA241_16128)// add by Victor Yu. 05-22-2007
38 #define CONFIG_ARCH_IA241
41 #if (defined CONFIG_ARCH_UC_7112_LX_PLUS_LITON)
42 #define CONFIG_ARCH_UC_7112_LX_PLUS
45 #if defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_IA241) || defined(CONFIG_ARCH_W341) || defined(CONFIG_ARCH_W345) || defined(CONFIG_ARCH_W345_IMP1) || defined(CONFIG_ARCH_UC_7112_LX_PLUS) || defined(CONFIG_ARCH_W321)|| defined(CONFIG_ARCH_W311) || defined(CONFIG_ARCH_W325) || defined(CONFIG_ARCH_W315)
46 #define SW_READY_GPIO (1<<27)
47 #define SW_RESET_GPIO (1<<25)
49 #define SW_READY_GPIO (1<<4)
50 #define SW_RESET_GPIO (1<<23)
53 #if defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_IA241) // mask by Victor Yu. 04-20-2007
54 #define DEBUG_LED_0 (1<<0)
55 #define DEBUG_LED_1 (1<<1)
56 #define DEBUG_LED_2 (1<<2)
57 #define DEBUG_LED_3 (1<<3)
58 #define DEBUG_LED (DEBUG_LED_0|DEBUG_LED_1|DEBUG_LED_2|DEBUG_LED_3)
61 #define RESET_POLL_TIME (HZ/5)
62 #define RESET_TIMEOUT (HZ * 5)
65 // file operaiton function call
67 #define IOCTL_SW_READY_ON 1
68 #define IOCTL_SW_READY_OFF 2
70 #if defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_IA241)//0 // mask by Victor Yu. 04-20---2007
71 #define IOCTL_DEBUG_LED_OUT 0x100
74 static struct timer_list resettimer
;
75 static spinlock_t resetlock
=SPIN_LOCK_UNLOCKED
;
76 static unsigned long endresettime
, intervaltime
;
77 static int ledonoffflag
;
78 static struct work_struct resetqueue
;
80 static void settodefault(void *unused
)
82 char *argv
[2], *envp
[5];
86 if ( !current
->fs
->root
)
88 argv
[0] = "/bin/setdef";
91 envp
[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
93 call_usermodehelper(argv
[0], argv
, envp
, 0);
96 static void reset_poll(unsigned long ingore
)
98 spin_lock(&resetlock
);
99 del_timer(&resettimer
);
100 if ( !mcpu_gpio_get(SW_RESET_GPIO
) ) {
101 if ( endresettime
== 0 ) {
102 endresettime
= jiffies
+ RESET_TIMEOUT
;
103 intervaltime
= jiffies
+ HZ
;
104 } else if ( time_after(jiffies
, endresettime
) ){
105 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_HIGH
);
106 schedule_work(&resetqueue
);
108 } else if ( time_after(jiffies
, intervaltime
) ) {
109 if ( ledonoffflag
) {
111 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_HIGH
);
114 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_LOW
);
116 intervaltime
= jiffies
+ HZ
;
118 } else if ( endresettime
) {
121 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_LOW
);
123 resettimer
.function
= reset_poll
;
124 resettimer
.expires
= jiffies
+ RESET_POLL_TIME
;
125 add_timer(&resettimer
);
127 spin_unlock(&resetlock
);
130 static int mxmisc_ioctl(struct inode
*inode
, struct file
*file
, unsigned int cmd
, unsigned long arg
)
133 case IOCTL_SW_READY_ON
:
134 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_LOW
);
136 case IOCTL_SW_READY_OFF
:
137 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_HIGH
);
139 #if defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_IA241)//0 // mask by Victor Yu. 04-20-2007
140 case IOCTL_DEBUG_LED_OUT
:
143 if ( copy_from_user(&val
, (unsigned int *)arg
, sizeof(unsigned int)) )
146 mcpu_gpio_set(DEBUG_LED_0
, MCPU_GPIO_LOW
);
148 mcpu_gpio_set(DEBUG_LED_0
, MCPU_GPIO_HIGH
);
150 mcpu_gpio_set(DEBUG_LED_1
, MCPU_GPIO_LOW
);
152 mcpu_gpio_set(DEBUG_LED_1
, MCPU_GPIO_HIGH
);
154 mcpu_gpio_set(DEBUG_LED_2
, MCPU_GPIO_LOW
);
156 mcpu_gpio_set(DEBUG_LED_2
, MCPU_GPIO_HIGH
);
158 mcpu_gpio_set(DEBUG_LED_3
, MCPU_GPIO_LOW
);
160 mcpu_gpio_set(DEBUG_LED_3
, MCPU_GPIO_HIGH
);
170 static int mxmisc_open(struct inode
*inode
, struct file
*file
)
172 if ( MINOR(inode
->i_rdev
) == MOXA_MISC_MINOR
)
177 static int mxmisc_release(struct inode
*inode
, struct file
*file
)
182 static struct file_operations mxmisc_fops
= {
187 release
:mxmisc_release
,
189 static struct miscdevice mxmisc_dev
= {
195 static void __exit
mxmisc_exit(void)
197 spin_lock(&resetlock
);
198 del_timer(&resettimer
);
199 spin_unlock(&resetlock
);
200 misc_deregister(&mxmisc_dev
);
203 static int __init
mxmisc_init(void)
205 printk("Register Moxa misc ver1.0 ");
206 if ( misc_register(&mxmisc_dev
) ) {
211 // set the CPU for GPIO
212 mcpu_gpio_mp_set(SW_READY_GPIO
|SW_RESET_GPIO
);
213 // default set all GPIO for input/ouput
214 mcpu_gpio_inout(SW_READY_GPIO
, MCPU_GPIO_OUTPUT
);
215 mcpu_gpio_inout(SW_RESET_GPIO
, MCPU_GPIO_INPUT
);
216 mcpu_gpio_set(SW_READY_GPIO
, MCPU_GPIO_HIGH
);
218 #if defined(CONFIG_ARCH_IA240) || defined(CONFIG_ARCH_IA241)//0 // mask by Victor Yu. 04-20-2007
219 // set the debug led output
220 mcpu_gpio_inout(DEBUG_LED
, MCPU_GPIO_OUTPUT
);
223 // initialize the reset polling
224 INIT_WORK(&resetqueue
, settodefault
, NULL
);
225 spin_lock(&resetlock
);
228 init_timer(&resettimer
);
229 resettimer
.function
= reset_poll
;
230 resettimer
.expires
= jiffies
+ RESET_POLL_TIME
;
231 add_timer(&resettimer
);
232 spin_unlock(&resetlock
);
238 module_init(mxmisc_init
);
239 module_exit(mxmisc_exit
);
241 MODULE_AUTHOR("Victor Yu");
242 MODULE_LICENSE("GPL");