many more code cleanups for checkpatch.pl, most flagged as errors
[openwrt/staging/wigyori.git] / target / linux / ifxmips / files / arch / mips / ifxmips / gpio.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2004 btxu Generate from INCA-IP project
17 * Copyright (C) 2005 Jin-Sze.Sow Comments edited
18 * Copyright (C) 2006 Huang Xiaogang Modification & verification on Danube chip
19 * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
20 */
21
22 #include <linux/module.h>
23 #include <linux/types.h>
24 #include <linux/errno.h>
25 #include <linux/proc_fs.h>
26 #include <linux/init.h>
27 #include <linux/ioctl.h>
28 #include <linux/timer.h>
29 #include <linux/module.h>
30 #include <linux/timer.h>
31 #include <linux/interrupt.h>
32 #include <linux/kobject.h>
33 #include <linux/workqueue.h>
34 #include <linux/skbuff.h>
35 #include <linux/netlink.h>
36 #include <linux/platform_device.h>
37 #include <net/sock.h>
38 #include <linux/uaccess.h>
39 #include <linux/semaphore.h>
40 #include <asm/ifxmips/ifxmips.h>
41
42 #define MAX_PORTS 2
43 #define PINS_PER_PORT 16
44
45 #ifdef CONFIG_IFXMIPS_GPIO_RST_BTN
46
47 unsigned int rst_port = 1;
48 unsigned int rst_pin = 15;
49 static struct timer_list rst_button_timer;
50
51 extern struct sock *uevent_sock;
52 extern u64 uevent_next_seqnum(void);
53 static unsigned long seen;
54 static int pressed;
55
56 struct event_t {
57 struct work_struct wq;
58 int set;
59 unsigned long jiffies;
60 };
61 #endif
62
63 #define IFXMIPS_GPIO_SANITY {if (port > MAX_PORTS || pin > PINS_PER_PORT) return -EINVAL; }
64
65 int ifxmips_port_reserve_pin(unsigned int port, unsigned int pin)
66 {
67 IFXMIPS_GPIO_SANITY;
68 printk(KERN_INFO "%s : call to obseleted function\n", __func__);
69 return 0;
70 }
71 EXPORT_SYMBOL(ifxmips_port_reserve_pin);
72
73 int ifxmips_port_free_pin(unsigned int port, unsigned int pin)
74 {
75 IFXMIPS_GPIO_SANITY;
76 printk(KERN_INFO "%s : call to obseleted function\n", __func__);
77 return 0;
78 }
79 EXPORT_SYMBOL(ifxmips_port_free_pin);
80
81 int ifxmips_port_set_open_drain(unsigned int port, unsigned int pin)
82 {
83 IFXMIPS_GPIO_SANITY;
84 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) | (1 << pin),
85 IFXMIPS_GPIO_P0_OD + (port * 0xC));
86 return 0;
87 }
88 EXPORT_SYMBOL(ifxmips_port_set_open_drain);
89
90 int ifxmips_port_clear_open_drain(unsigned int port, unsigned int pin)
91 {
92 IFXMIPS_GPIO_SANITY;
93 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) & ~(1 << pin),
94 IFXMIPS_GPIO_P0_OD + (port * 0xC));
95 return 0;
96 }
97 EXPORT_SYMBOL(ifxmips_port_clear_open_drain);
98
99 int ifxmips_port_set_pudsel(unsigned int port, unsigned int pin)
100 {
101 IFXMIPS_GPIO_SANITY;
102 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) | (1 << pin),
103 IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC));
104 return 0;
105 }
106 EXPORT_SYMBOL(ifxmips_port_set_pudsel);
107
108 int ifxmips_port_clear_pudsel(unsigned int port, unsigned int pin)
109 {
110 IFXMIPS_GPIO_SANITY;
111 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) & ~(1 << pin),
112 IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC));
113 return 0;
114 }
115 EXPORT_SYMBOL(ifxmips_port_clear_pudsel);
116
117 int ifxmips_port_set_puden(unsigned int port, unsigned int pin)
118 {
119 IFXMIPS_GPIO_SANITY;
120 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) | (1 << pin),
121 IFXMIPS_GPIO_P0_PUDEN + (port * 0xC));
122 return 0;
123 }
124 EXPORT_SYMBOL(ifxmips_port_set_puden);
125
126 int ifxmips_port_clear_puden(unsigned int port, unsigned int pin)
127 {
128 IFXMIPS_GPIO_SANITY;
129 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) & ~(1 << pin),
130 IFXMIPS_GPIO_P0_PUDEN + (port * 0xC));
131 return 0;
132 }
133 EXPORT_SYMBOL(ifxmips_port_clear_puden);
134
135 int ifxmips_port_set_stoff(unsigned int port, unsigned int pin)
136 {
137 IFXMIPS_GPIO_SANITY;
138 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) | (1 << pin),
139 IFXMIPS_GPIO_P0_STOFF + (port * 0xC));
140 return 0;
141 }
142 EXPORT_SYMBOL(ifxmips_port_set_stoff);
143
144 int ifxmips_port_clear_stoff(unsigned int port, unsigned int pin)
145 {
146 IFXMIPS_GPIO_SANITY;
147 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) & ~(1 << pin),
148 IFXMIPS_GPIO_P0_STOFF + (port * 0xC));
149 return 0;
150 }
151 EXPORT_SYMBOL(ifxmips_port_clear_stoff);
152
153 int ifxmips_port_set_dir_out(unsigned int port, unsigned int pin)
154 {
155 IFXMIPS_GPIO_SANITY;
156 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) | (1 << pin),
157 IFXMIPS_GPIO_P0_DIR + (port * 0xC));
158 return 0;
159 }
160 EXPORT_SYMBOL(ifxmips_port_set_dir_out);
161
162 int ifxmips_port_set_dir_in(unsigned int port, unsigned int pin)
163 {
164 IFXMIPS_GPIO_SANITY;
165 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) & ~(1 << pin),
166 IFXMIPS_GPIO_P0_DIR + (port * 0xC));
167 return 0;
168 }
169 EXPORT_SYMBOL(ifxmips_port_set_dir_in);
170
171 int ifxmips_port_set_output(unsigned int port, unsigned int pin)
172 {
173 IFXMIPS_GPIO_SANITY;
174 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) | (1 << pin),
175 IFXMIPS_GPIO_P0_OUT + (port * 0xC));
176 return 0;
177 }
178 EXPORT_SYMBOL(ifxmips_port_set_output);
179
180 int ifxmips_port_clear_output(unsigned int port, unsigned int pin)
181 {
182 IFXMIPS_GPIO_SANITY;
183 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) & ~(1 << pin),
184 IFXMIPS_GPIO_P0_OUT + (port * 0xC));
185 return 0;
186 }
187 EXPORT_SYMBOL(ifxmips_port_clear_output);
188
189 int ifxmips_port_get_input(unsigned int port, unsigned int pin)
190 {
191 IFXMIPS_GPIO_SANITY;
192 if (ifxmips_r32(IFXMIPS_GPIO_P0_IN + (port * 0xC)) & (1 << pin))
193 return 0;
194 else
195 return 1;
196 }
197 EXPORT_SYMBOL(ifxmips_port_get_input);
198
199 int ifxmips_port_set_altsel0(unsigned int port, unsigned int pin)
200 {
201 IFXMIPS_GPIO_SANITY;
202 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) | (1 << pin),
203 IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC));
204 return 0;
205 }
206 EXPORT_SYMBOL(ifxmips_port_set_altsel0);
207
208 int ifxmips_port_clear_altsel0(unsigned int port, unsigned int pin)
209 {
210 IFXMIPS_GPIO_SANITY;
211 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) & ~(1 << pin),
212 IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC));
213 return 0;
214 }
215 EXPORT_SYMBOL(ifxmips_port_clear_altsel0);
216
217 int ifxmips_port_set_altsel1(unsigned int port, unsigned int pin)
218 {
219 IFXMIPS_GPIO_SANITY;
220 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) | (1 << pin),
221 IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC));
222 return 0;
223 }
224 EXPORT_SYMBOL(ifxmips_port_set_altsel1);
225
226 int ifxmips_port_clear_altsel1(unsigned int port, unsigned int pin)
227 {
228 IFXMIPS_GPIO_SANITY;
229 ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) & ~(1 << pin),
230 IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC));
231 return 0;
232 }
233 EXPORT_SYMBOL(ifxmips_port_clear_altsel1);
234
235 #ifdef CONFIG_IFXMIPS_GPIO_RST_BTN
236 static inline void add_msg(struct sk_buff *skb, char *msg)
237 {
238 char *scratch;
239 scratch = skb_put(skb, strlen(msg) + 1);
240 sprintf(scratch, msg);
241 }
242
243 static void hotplug_button(struct work_struct *wq)
244 {
245 struct sk_buff *skb;
246 struct event_t *event;
247 size_t len;
248 char *scratch, *s;
249 char buf[128];
250
251 event = container_of(wq, struct event_t, wq);
252 if (!uevent_sock)
253 goto done;
254
255 s = event->set ? "pressed" : "released";
256 len = strlen(s) + 2;
257 skb = alloc_skb(len + 2048, GFP_KERNEL);
258 if (!skb)
259 goto done;
260
261 scratch = skb_put(skb, len);
262 sprintf(scratch, "%s@", s);
263 add_msg(skb, "HOME=/");
264 add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin");
265 add_msg(skb, "SUBSYSTEM=button");
266 add_msg(skb, "BUTTON=reset");
267 add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released"));
268 sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ);
269 add_msg(skb, buf);
270 snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum());
271 add_msg(skb, buf);
272
273 NETLINK_CB(skb).dst_group = 1;
274 netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL);
275 done:
276 kfree(event);
277 }
278
279 static void reset_button_poll(unsigned long unused)
280 {
281 struct event_t *event;
282
283 rst_button_timer.expires = jiffies + (HZ / 4);
284 add_timer(&rst_button_timer);
285
286 if (pressed != ifxmips_port_get_input(rst_port, rst_pin)) {
287 if (pressed)
288 pressed = 0;
289 else
290 pressed = 1;
291 event = kzalloc(sizeof(struct event_t), GFP_ATOMIC);
292 if (!event) {
293 printk(KERN_INFO "Could not alloc hotplug event\n");
294 return;
295 }
296 event->set = pressed;
297 event->jiffies = jiffies;
298 INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
299 schedule_work(&event->wq);
300 seen = jiffies;
301 }
302 }
303 #endif
304
305 static int ifxmips_gpio_probe(struct platform_device *dev)
306 {
307 int retval = 0;
308
309 #ifdef CONFIG_IFXMIPS_GPIO_RST_BTN
310 rst_port = dev->resource[0].start;
311 rst_pin = dev->resource[0].end;
312 ifxmips_port_set_open_drain(rst_port, rst_pin);
313 ifxmips_port_clear_altsel0(rst_port, rst_pin);
314 ifxmips_port_clear_altsel1(rst_port, rst_pin);
315 ifxmips_port_set_dir_in(rst_port, rst_pin);
316 seen = jiffies;
317 init_timer(&rst_button_timer);
318 rst_button_timer.function = reset_button_poll;
319 rst_button_timer.expires = jiffies + HZ;
320 add_timer(&rst_button_timer);
321 #endif
322 return retval;
323 }
324
325 static int ifxmips_gpio_remove(struct platform_device *pdev)
326 {
327 #ifdef CONFIG_IFXMIPS_GPIO_RST_BTN
328 del_timer_sync(&rst_button_timer);
329 #endif
330 return 0;
331 }
332
333 static struct platform_driver ifxmips_gpio_driver = {
334 .probe = ifxmips_gpio_probe,
335 .remove = ifxmips_gpio_remove,
336 .driver = {
337 .name = "ifxmips_gpio",
338 .owner = THIS_MODULE,
339 },
340 };
341
342 int __init ifxmips_gpio_init(void)
343 {
344 int ret = platform_driver_register(&ifxmips_gpio_driver);
345 if (ret)
346 printk(KERN_INFO "ifxmips_gpio : Error registering platfom driver!");
347 return ret;
348 }
349
350 void __exit ifxmips_gpio_exit(void)
351 {
352 platform_driver_unregister(&ifxmips_gpio_driver);
353 }
354
355 module_init(ifxmips_gpio_init);
356 module_exit(ifxmips_gpio_exit);