root/src/linux/adm5120/linux-2.6.23/arch/mips/adm5120/proc_gpio.c

Revision 12415, 5.4 kB (checked in by BrainSlayer, 5 months ago)

latest adm5120 update incl. remap patch

Line 
1 //proc_gpio: AR5315 GPIO pins in /proc/gpio/
2 // by olg
3 // GPL'ed
4 // some code stolen from Yoshinori Sato <ysato@users.sourceforge.jp>
5
6 #include <linux/autoconf.h>
7 #include <linux/init.h>
8 #include <linux/module.h>
9 #include <linux/types.h>
10 #include <linux/stddef.h>
11 #include <linux/proc_fs.h>
12 #include <linux/kernel.h>
13 #include <linux/string.h>
14 #include <linux/fs.h>
15 #include <asm/uaccess.h>        /* for copy_from_user */
16 #include <asm/gpio.h>
17 #include <adm5120_defs.h>
18 #include <adm5120_info.h>
19 #include <adm5120_switch.h>
20
21 #define PROCFS_MAX_SIZE 64
22 extern const char *get_arch_type( void );
23 struct proc_dir_entry *proc_gpio, *gpio_dir;
24
25 //Masks for data exchange through "void *data" pointer
26 #define GPIO_IN (1<<5)
27 #define GPIO_OUT (1<<6)
28 #define GPIO_DIR (1<<7)
29 #define PIN_MASK 0x1f
30 #define GPIO_CR_M(x)                (1 << (x))  /* mask for i/o */
31
32
33 #define GPIO_READ(r)            readl((r))
34 #define GPIO_WRITE(v, r)        writel((v), (r))
35 #define GPIO_REG(r)     (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE)+r)
36
37 static void cleanup_proc( void );
38
39 //The buffer used to store the data returned by the proc file
40 static char procfs_buffer[PROCFS_MAX_SIZE];
41 static unsigned long procfs_buffer_size = 0;
42
43
44 #define PIN_IM(p)       ((1 << GPIO_CONF0_IM_SHIFT) << p)
45 #define PIN_IV(p)       ((1 << GPIO_CONF0_IV_SHIFT) << p)
46 #define PIN_OE(p)       ((1 << GPIO_CONF0_OE_SHIFT) << p)
47 #define PIN_OV(p)       ((1 << GPIO_CONF0_OV_SHIFT) << p)
48
49
50 static int
51 gpio_proc_read( char *buf, char **start, off_t offset,
52                 int len, int *eof, void *data )
53 {
54         void __iomem **reg;
55         u32 t;
56         int ret;
57
58         reg = GPIO_REG(SWITCH_REG_GPIO_CONF0);
59        
60         if( ( unsigned int )data & GPIO_IN )
61             {
62             t = GPIO_READ(reg);
63             t &= PIN_IV((( unsigned int )data & PIN_MASK));
64             if (t)
65                 ret=1;
66             else
67                 ret=0;     
68             }
69         if( ( unsigned int )data & GPIO_OUT )
70             {
71             t = GPIO_READ(reg);
72             t &= PIN_OV((( unsigned int )data & PIN_MASK));
73             if (t)
74                 ret=1;
75             else
76                 ret=0;     
77             }
78         if( ( unsigned int )data & GPIO_DIR )
79             {
80             t = GPIO_READ(reg);
81             t &= PIN_OE((( unsigned int )data & PIN_MASK));
82             if (t)
83                 ret=1;
84             else
85                 ret=0;     
86             }
87
88     if( ret )
89         buf[0] = '1';
90     else
91         buf[0] = '0';
92     buf[1] = 0;
93
94     *eof = 1;
95
96     return ( 2 );
97
98 }
99
100 static int
101 gpio_proc_info_read( char *buf, char **start, off_t offset,
102                      int len, int *eof, void *data )
103 {
104     *eof = 1;
105     return 0;
106 }
107
108 static int
109 gpio_proc_write( struct file *file, const char *buffer, unsigned long count,
110                  void *data )
111 {
112     u32 reg = 0;
113
114     /* get buffer size */
115     procfs_buffer_size = count;
116     if( procfs_buffer_size > PROCFS_MAX_SIZE )
117     {
118         procfs_buffer_size = PROCFS_MAX_SIZE;
119     }
120     /* write data to the buffer */
121     if( copy_from_user( procfs_buffer, buffer, procfs_buffer_size ) )
122     {
123         return -EFAULT;
124     }
125
126     procfs_buffer[procfs_buffer_size] = 0;
127
128         if( procfs_buffer[0] == '0' || procfs_buffer[0] == 'i' )
129             reg = 0;
130         if( procfs_buffer[0] == '1' || procfs_buffer[0] == 'o' )
131             reg = 1;
132         if( ( unsigned int )data & GPIO_IN )
133         {
134             adm5120_gpio_set_value(( unsigned int )data & PIN_MASK,reg);
135         }
136         if( ( unsigned int )data & GPIO_OUT )
137         {
138             adm5120_gpio_direction_output(( unsigned int )data & PIN_MASK,reg);
139         }
140         if( ( unsigned int )data & GPIO_DIR )
141         {
142             if (!reg)
143             adm5120_gpio_direction_input(( unsigned int )data & PIN_MASK);
144                 else
145             adm5120_gpio_direction_output(( unsigned int )data & PIN_MASK,0);
146         }
147     return procfs_buffer_size;
148 }
149
150 static __init int register_proc( void )
151 {
152     unsigned char i, flag = 0;
153     char proc_name[16];
154     int gpiocount;
155
156     gpiocount = 22;
157
158     /* create directory gpio */
159     gpio_dir = proc_mkdir( "gpio", NULL );
160     if( gpio_dir == NULL )
161         goto fault;
162     gpio_dir->owner = THIS_MODULE;
163
164     for( i = 0; i < gpiocount * 3; i++ )        //create for every GPIO "x_in"," x_out" and "x_dir"
165     {
166         if( i / gpiocount == 0 )
167         {
168             flag = GPIO_IN;
169             sprintf( proc_name, "%i_in", i );
170         }
171         if( i / gpiocount == 1 )
172         {
173             flag = GPIO_OUT;
174             sprintf( proc_name, "%i_out", i % gpiocount );
175         }
176         if( i / gpiocount == 2 )
177         {
178             flag = GPIO_DIR;
179             sprintf( proc_name, "%i_dir", i % gpiocount );
180         }
181
182         proc_gpio = create_proc_entry( proc_name, S_IRUGO, gpio_dir );
183         if( proc_gpio )
184         {
185             proc_gpio->read_proc = gpio_proc_read;
186             proc_gpio->write_proc = gpio_proc_write;
187             proc_gpio->owner = THIS_MODULE;
188             proc_gpio->data = ( ( i % gpiocount ) | flag );
189         }
190         else
191             goto fault;
192
193     }
194
195     proc_gpio = create_proc_entry( "info", S_IRUGO, gpio_dir );
196     if( proc_gpio )
197     {
198         proc_gpio->read_proc = gpio_proc_info_read;
199         proc_gpio->owner = THIS_MODULE;
200     }
201     else
202         goto fault;
203
204     printk( KERN_NOTICE
205             "gpio_proc: module loaded and /proc/gpio/ created\n" );
206     return 0;
207
208   fault:
209     cleanup_proc(  );
210     return -EFAULT;
211 }
212
213 static void cleanup_proc( void )
214 {
215     unsigned char i;
216     char proc_name[16];
217     int gpiocount;
218
219     gpiocount = 8;
220
221     for( i = 0; i < gpiocount; i++ )
222     {
223         sprintf( proc_name, "%i_in", i );
224         remove_proc_entry( proc_name, gpio_dir );
225         sprintf( proc_name, "%i_out", i );
226         remove_proc_entry( proc_name, gpio_dir );
227         sprintf( proc_name, "%i_dir", i );
228         remove_proc_entry( proc_name, gpio_dir );
229     }
230     remove_proc_entry( "info", gpio_dir );
231     remove_proc_entry( "gpio", NULL );
232     printk( KERN_INFO "gpio_proc: unloaded and /proc/gpio/ removed\n" );
233
234 }
235
236 module_init( register_proc );
237 module_exit( cleanup_proc );
238
239 MODULE_AUTHOR( "olg" );
240 MODULE_DESCRIPTION( "ADM5120 GPIO pins in /proc/gpio/" );
241 MODULE_LICENSE( "GPL" );
Note: See TracBrowser for help on using the browser.