3 * PXA25x GPIOs exposed under /proc for reading and writing
4 * They will show up under /proc/gpio/NN
6 * Based on patch 1773/1 in the arm kernel patch repository at arm.linux.co.uk
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/proc_fs.h>
13 #include <linux/string.h>
14 #include <linux/ctype.h>
16 #include <mach/hardware.h>
17 #include <mach/gpio.h>
18 #include <asm/uaccess.h>
20 extern struct proc_dir_entry proc_root
;
22 extern int pxa_last_gpio
;
24 static struct proc_dir_entry
*proc_gpio_parent
;
25 static struct proc_dir_entry
**proc_gpios
;
33 static gpio_summary_type
*gpio_summaries
;
35 static int proc_gpio_write(struct file
*file
, const char __user
*buf
,
36 unsigned long count
, void *data
)
38 char *cur
, lbuf
[count
+ 1];
39 gpio_summary_type
*summary
= data
;
40 u32 altfn
, direction
, setclear
, gafr
;
42 if (!capable(CAP_SYS_ADMIN
))
45 memset(lbuf
, 0, count
+ 1);
47 if (copy_from_user(lbuf
, buf
, count
))
52 // Initialize to current state
53 altfn
= ((GAFR(summary
->gpio
) >> ((summary
->gpio
& 0x0f) << 0x01)) & 0x03);
54 direction
= GPDR(summary
->gpio
) & GPIO_bit(summary
->gpio
);
55 setclear
= GPLR(summary
->gpio
) & GPIO_bit(summary
->gpio
);
58 // We accept options: {GPIO|AF1|AF2|AF3}, {set|clear}, {in|out}
59 // Anything else is an error
60 while(cur
[0] && (isspace(cur
[0]) || ispunct(cur
[0]))) cur
= &(cur
[1]);
62 if('\0' == cur
[0]) break;
64 // Ok, so now we're pointing at the start of something
68 // Check that next is "PIO" -- '\0' will cause safe short-circuit if end of buf
69 if(!(cur
[1] == 'P' && cur
[2] == 'I' && cur
[3] == 'O')) goto parse_error
;
70 // Ok, so set this GPIO to GPIO (non-ALT) function
75 if(!(cur
[1] == 'F' && cur
[2] >= '1' && cur
[2] <= '3')) goto parse_error
;
80 if(!(cur
[1] == 'e' && cur
[2] == 't')) goto parse_error
;
85 if(!(cur
[1] == 'l' && cur
[2] == 'e' && cur
[3] == 'a' && cur
[4] == 'r')) goto parse_error
;
90 if(!(cur
[1] == 'n')) goto parse_error
;
95 if(!(cur
[1] == 'u' && cur
[2] == 't')) goto parse_error
;
99 default: goto parse_error
;
102 // Ok, now set gpio mode and value
104 GPDR(summary
->gpio
) |= GPIO_bit(summary
->gpio
);
106 GPDR(summary
->gpio
) &= ~GPIO_bit(summary
->gpio
);
108 gafr
= GAFR(summary
->gpio
) & ~(0x3 << (((summary
->gpio
) & 0xf)*2));
109 GAFR(summary
->gpio
) = gafr
| (altfn
<< (((summary
->gpio
) & 0xf)*2));
111 if(direction
&& !altfn
)
113 if(setclear
) GPSR(summary
->gpio
) = GPIO_bit(summary
->gpio
);
114 else GPCR(summary
->gpio
) = GPIO_bit(summary
->gpio
);
117 #ifdef CONFIG_PROC_GPIO_DEBUG
118 printk(KERN_INFO
"Set (%s,%s,%s) via /proc/gpio/%s\n",altfn
? (altfn
== 1 ? "AF1" : (altfn
== 2 ? "AF2" : "AF3")) : "GPIO",
119 direction
? "out" : "in",
120 setclear
? "set" : "clear",
127 printk(KERN_CRIT
"Parse error: Expect \"[GPIO|AF1|AF2|AF3]|[set|clear]|[in|out] ...\"\n");
131 static int proc_gpio_read(char *page
, char **start
, off_t off
,
132 int count
, int *eof
, void *data
)
135 gpio_summary_type
*summary
= data
;
139 p
+= sprintf(p
, "%d\t%s\t%s\t%s\n", i
,
140 (af
= ((GAFR(i
) >> ((i
& 0x0f) << 0x01)) & 0x03)) ? (af
== 1 ? "AF1" : (af
== 2 ? "AF2" : "AF3")) : "GPIO",
141 (GPDR(i
) & GPIO_bit(i
)) ? "out" : "in",
142 (GPLR(i
) & GPIO_bit(i
)) ? "set" : "clear");
144 len
= (p
- page
) - off
;
151 *eof
= (len
<= count
) ? 1 : 0;
159 static const char const *GAFR_DESC
[] = { "GAFR0_L", "GAFR0_U", "GAFR1_L", "GAFR1_U", "GAFR2_L", "GAFR2_U" };
160 #elif defined(CONFIG_PXA27x)
161 static const char const *GAFR_DESC
[] = { "GAFR0_L", "GAFR0_U", "GAFR1_L", "GAFR1_U", "GAFR2_L", "GAFR2_U", "GAFR3_L", "GAFR3_U" };
164 static int proc_gafr_read(char *page
, char **start
, off_t off
,
165 int count
, int *eof
, void *data
)
170 for(i
=0; i
<ARRAY_SIZE(GAFR_DESC
); i
++)
172 p
+= sprintf(p
, "%s: %08x\n", GAFR_DESC
[i
], GAFR(i
*16));
175 len
= (p
- page
) - off
;
182 *eof
= (len
<= count
) ? 1 : 0;
188 static int proc_gpdr_read(char *page
, char **start
, off_t off
,
189 int count
, int *eof
, void *data
)
196 p
+= sprintf(p
, "GPDR%d: %08x\n", i
, GPDR(i
* 32));
199 len
= (p
- page
) - off
;
206 *eof
= (len
<= count
) ? 1 : 0;
212 static int proc_gplr_read(char *page
, char **start
, off_t off
,
213 int count
, int *eof
, void *data
)
220 p
+= sprintf(p
, "GPLR%d: %08x\n", i
, GPLR(i
* 32));
223 len
= (p
- page
) - off
;
230 *eof
= (len
<= count
) ? 1 : 0;
236 static int __init
gpio_init(void)
240 proc_gpio_parent
= NULL
;
241 for (proc_gpio_parent
= proc_root
.subdir
; proc_gpio_parent
; proc_gpio_parent
= proc_gpio_parent
->next
) {
242 if (( proc_gpio_parent
->namelen
== 4 ) && ( memcmp(proc_gpio_parent
->name
, "gpio", 4 ) == 0 ))
246 // proc_gpio_parent will be non-NULL if the directory already exists
248 if (!proc_gpio_parent
) {
249 proc_gpio_parent
= create_proc_entry("gpio", S_IFDIR
| S_IRUGO
| S_IXUGO
, NULL
);
252 if(!proc_gpio_parent
) return 0;
254 proc_gpios
= kmalloc(sizeof(struct proc_dir_entry
*) * (pxa_last_gpio
+ 1), GFP_KERNEL
);
258 gpio_summaries
= kmalloc(sizeof(gpio_summary_type
) * (pxa_last_gpio
+ 1), GFP_KERNEL
);
259 if (!gpio_summaries
) {
264 for(i
=0; i
< (pxa_last_gpio
+1); i
++)
266 gpio_summaries
[i
].gpio
= i
;
267 sprintf(gpio_summaries
[i
].name
, "GPIO%d", i
);
268 proc_gpios
[i
] = create_proc_entry(gpio_summaries
[i
].name
, 0644, proc_gpio_parent
);
271 proc_gpios
[i
]->data
= &gpio_summaries
[i
];
272 proc_gpios
[i
]->read_proc
= proc_gpio_read
;
273 proc_gpios
[i
]->write_proc
= proc_gpio_write
;
277 create_proc_read_entry("GAFR", 0444, proc_gpio_parent
, proc_gafr_read
, NULL
);
278 create_proc_read_entry("GPDR", 0444, proc_gpio_parent
, proc_gpdr_read
, NULL
);
279 create_proc_read_entry("GPLR", 0444, proc_gpio_parent
, proc_gplr_read
, NULL
);
284 static void gpio_exit(void)
288 remove_proc_entry("GAFR", proc_gpio_parent
);
289 remove_proc_entry("GPDR", proc_gpio_parent
);
290 remove_proc_entry("GPLR", proc_gpio_parent
);
292 for(i
=0; i
< (pxa_last_gpio
+1); i
++)
294 if(proc_gpios
[i
]) remove_proc_entry(gpio_summaries
[i
].name
, proc_gpio_parent
);
297 kfree(gpio_summaries
);
300 if (proc_gpio_parent
)
302 if (!proc_gpio_parent
->subdir
)
304 // Only remove /proc/gpio if it's empty.
305 remove_proc_entry( "gpio", NULL
);
311 module_init(gpio_init
);
312 module_exit(gpio_exit
);
313 MODULE_LICENSE("GPL");