code style scripts/checkpatch.pl (linux-3.9-rc1) formatting
[linux-2.6.32.60-moxart.git] / arch / arm / mach-moxart / gpio.c
blob3227311cd3e39990ceb48c537ef318f27d7c9869
1 /* MOXART GPIO (LEDs and RESET pin) driver (based on MOXA sources)
2 * Copyright (C) 2013 Jonas Jensen <jonas.jensen@gmail.com>
3 * This program is free software; you can redistribute it and/or modify it
4 * under the terms of the GNU General Public License as published by the
5 * Free Software Foundation; either version 2 of the License,
6 * or (at your option) any later version. */
8 #include <linux/kernel.h>
9 #include <linux/init.h>
10 #include <linux/io.h>
11 #include <linux/irq.h>
12 #include <linux/gpio.h>
13 #include <linux/delay.h>
14 #include <linux/module.h>
15 #include <linux/types.h>
16 #include <linux/miscdevice.h>
17 #include <linux/fcntl.h>
18 #include <linux/poll.h>
19 #include <linux/proc_fs.h>
20 #include <linux/spinlock.h>
21 #include <linux/rtc.h>
22 #include <linux/timer.h>
23 #include <linux/ioport.h>
24 #include <linux/kmod.h>
26 #include <asm/io.h>
27 #include <asm/uaccess.h>
28 #include <asm/system.h>
30 #include <mach/hardware.h>
31 #include <mach/irqs.h>
32 #include <mach/gpio.h>
34 #define MOXA_MISC_MINOR 105
35 #define RESET_POLL_TIME (HZ/5)
36 #define RESET_TIMEOUT (HZ * 5)
37 #define IOCTL_SW_READY_ON 1
38 #define IOCTL_SW_READY_OFF 2
40 static struct timer_list reset_timer;
42 static DEFINE_SPINLOCK(reset_lock);
43 static DEFINE_SPINLOCK(gpio_lock);
45 static unsigned long reset_time_end, reset_time_interval;
46 static int led_on_off_flag;
47 static struct work_struct reset_pin_detected_queue;
49 void moxart_gpio_mp_set(u32 gpio)
51 unsigned long flags;
53 spin_lock_irqsave(&gpio_lock, flags);
54 writel(readl(IO_ADDRESS(MOXART_PMU_BASE)+0x100) |
55 gpio, IO_ADDRESS(MOXART_PMU_BASE)+0x100);
56 spin_unlock_irqrestore(&gpio_lock, flags);
59 void moxart_gpio_mp_clear(u32 gpio)
61 unsigned long flags;
63 spin_lock_irqsave(&gpio_lock, flags);
64 writel(readl(IO_ADDRESS(MOXART_PMU_BASE)+0x100) &
65 ~gpio, IO_ADDRESS(MOXART_PMU_BASE)+0x100);
66 spin_unlock_irqrestore(&gpio_lock, flags);
69 void moxart_gpio_inout(u32 gpio, bool inout)
71 unsigned long flags;
72 void __iomem *ioaddr = (void __force __iomem *)
73 GPIO_PIN_DIRECTION(IO_ADDRESS(MOXART_GPIO_BASE));
75 spin_lock_irqsave(&gpio_lock, flags);
76 (inout) ? writel(readl(ioaddr) | gpio, ioaddr) :
77 writel(readl(ioaddr) & ~gpio, ioaddr);
78 spin_unlock_irqrestore(&gpio_lock, flags);
81 void moxart_gpio_set(u32 gpio, bool highlow)
83 unsigned long flags;
84 void __iomem *ioaddr = (void __force __iomem *)
85 GPIO_DATA_OUT(IO_ADDRESS(MOXART_GPIO_BASE));
87 spin_lock_irqsave(&gpio_lock, flags);
88 (highlow) ? writel(readl(ioaddr) | gpio, ioaddr) :
89 writel(readl(ioaddr) & ~gpio, ioaddr);
90 spin_unlock_irqrestore(&gpio_lock, flags);
93 u32 moxart_gpio_get(u32 gpio)
95 unsigned long flags;
96 u32 ret;
98 spin_lock_irqsave(&gpio_lock, flags);
99 ret = readl(GPIO_PIN_DIRECTION(IO_ADDRESS(MOXART_GPIO_BASE)));
100 if (ret & gpio) {
101 /* printk(KERN_INFO "MOXART GPIO: moxart_gpio_get: readl(%x)"
102 "=%x\n", GPIO_DATA_OUT(IO_ADDRESS(MOXART_GPIO_BASE)),
103 readl(GPIO_DATA_OUT(IO_ADDRESS(MOXART_GPIO_BASE))));*/
104 ret = readl(GPIO_DATA_OUT(IO_ADDRESS(MOXART_GPIO_BASE))) & gpio;
105 } else {
106 ret = readl(GPIO_DATA_IN(IO_ADDRESS(MOXART_GPIO_BASE))) & gpio;
108 spin_unlock_irqrestore(&gpio_lock, flags);
109 return ret;
112 void moxart_gpio_write_byte(u8 data)
114 int i;
115 for (i = 0; i < 8; i++, data >>= 1) {
116 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_LOW);
117 moxart_gpio_set(GPIO_RTC_DATA, ((data & 1) == 1));
118 udelay(GPIO_RTC_DELAY_TIME);
119 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_HIGH);
120 udelay(GPIO_RTC_DELAY_TIME);
124 u8 moxart_gpio_read_byte(void)
126 int i;
127 u8 data = 0;
128 for (i = 0; i < 8; i++) {
129 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_LOW);
130 udelay(GPIO_RTC_DELAY_TIME);
131 moxart_gpio_set(GPIO_RTC_SCLK, GPIO_EM1240_HIGH);
132 if (moxart_gpio_get(GPIO_RTC_DATA))
133 data |= (1 << i);
134 udelay(GPIO_RTC_DELAY_TIME);
136 return data;
139 void reset_pin_detected(struct work_struct *work)
141 /* char *argv[2], *envp[5]; */
143 if (in_interrupt())
144 return;
145 pr_info("MOXART GPIO: reset_pin_detected\n");
147 /* commenting below, not everyone is going to
148 * have /bin/setdef binary.. */
150 /*if (!current->fs->root) return;
151 argv[0] = "/bin/setdef";
152 argv[1] = 0;
153 envp[0] = "HOME=/";
154 envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
155 envp[2] = 0;
156 call_usermodehelper(argv[0], argv, envp, 0);
160 void reset_poll(unsigned long ingore)
162 unsigned long flags;
164 spin_lock_irqsave(&reset_lock, flags);
165 del_timer(&reset_timer);
167 /* printk(KERN_INFO "MOXART GPIO: reset_poll: moxart_gpio_get"
168 * "(SW_READY_GPIO) = %x\n", moxart_gpio_get(SW_READY_GPIO)); */
169 moxart_gpio_get(SW_READY_GPIO);
170 if (!moxart_gpio_get(SW_RESET_GPIO)) {
171 if (reset_time_end == 0) {
172 reset_time_end = jiffies + RESET_TIMEOUT;
173 reset_time_interval = jiffies + HZ;
174 } else if (time_after(jiffies, reset_time_end)) {
175 moxart_gpio_set(SW_READY_GPIO, GPIO_EM1240_HIGH);
176 schedule_work(&reset_pin_detected_queue);
177 goto poll_exit;
178 } else if (time_after(jiffies, reset_time_interval)) {
179 if (led_on_off_flag) {
180 led_on_off_flag = 0;
181 moxart_gpio_set(SW_READY_GPIO,
182 GPIO_EM1240_HIGH);
183 } else {
184 led_on_off_flag = 1;
185 moxart_gpio_set(SW_READY_GPIO,
186 GPIO_EM1240_LOW);
188 reset_time_interval = jiffies + HZ;
190 } else if (reset_time_end) {
191 reset_time_end = 0;
192 led_on_off_flag = 1;
193 moxart_gpio_set(SW_READY_GPIO, GPIO_EM1240_LOW);
195 reset_timer.function = reset_poll;
196 reset_timer.expires = jiffies + RESET_POLL_TIME;
197 add_timer(&reset_timer);
199 poll_exit:
200 spin_unlock_irqrestore(&reset_lock, flags);
203 static int gpio_ioctl(struct inode *inode, struct file *file,
204 unsigned int cmd, unsigned long arg)
206 switch (cmd) {
207 case IOCTL_SW_READY_ON:
208 moxart_gpio_set(SW_READY_GPIO, GPIO_EM1240_LOW);
209 break;
210 case IOCTL_SW_READY_OFF:
211 moxart_gpio_set(SW_READY_GPIO, GPIO_EM1240_HIGH);
212 break;
213 default:
214 return -EINVAL;
216 return 0;
219 static int gpio_open(struct inode *inode, struct file *file)
221 if (MINOR(inode->i_rdev) == MOXA_MISC_MINOR)
222 return 0;
223 return -ENODEV;
226 static int gpio_release(struct inode *inode, struct file *file)
228 return 0;
231 static const struct file_operations gpio_fops = {
232 .owner = THIS_MODULE,
233 .llseek = no_llseek,
234 .ioctl = gpio_ioctl,
235 .open = gpio_open,
236 .release = gpio_release,
239 static struct miscdevice gpio_dev = {
240 MOXA_MISC_MINOR,
241 "moxart_gpio",
242 &gpio_fops
245 static void __exit gpio_exit(void)
247 unsigned long flags;
249 spin_lock_irqsave(&reset_lock, flags);
250 del_timer(&reset_timer);
251 spin_unlock_irqrestore(&reset_lock, flags);
252 misc_deregister(&gpio_dev);
255 static int __init gpio_init(void)
257 unsigned long flags;
259 pr_info("MOXART GPIO (LEDs and RESET pin) driver\n");
260 if (misc_register(&gpio_dev)) {
261 pr_info(": misc_register failed!\n");
262 return -ENOMEM;
265 moxart_gpio_mp_set(SW_READY_GPIO|SW_RESET_GPIO);
266 moxart_gpio_inout(SW_READY_GPIO, GPIO_EM1240_OUTPUT);
267 moxart_gpio_inout(SW_RESET_GPIO, GPIO_EM1240_INPUT);
268 moxart_gpio_set(SW_READY_GPIO, GPIO_EM1240_HIGH);
270 INIT_WORK(&reset_pin_detected_queue, reset_pin_detected);
271 spin_lock_init(&reset_lock);
272 spin_lock_init(&gpio_lock);
273 spin_lock_irqsave(&reset_lock, flags);
274 reset_time_end = 0;
275 led_on_off_flag = 1;
276 init_timer(&reset_timer);
277 reset_timer.function = reset_poll;
278 reset_timer.expires = jiffies + RESET_POLL_TIME;
279 add_timer(&reset_timer);
280 spin_unlock_irqrestore(&reset_lock, flags);
282 return 0;
285 module_init(gpio_init);
286 module_exit(gpio_exit);
288 MODULE_DESCRIPTION("MOXART GPIO (LEDs and RESET pin) driver");
289 MODULE_LICENSE("GPL");