source: src/linux/universal/linux-3.2/arch/mips/ar7240/proc_gpio.c @ 18404

Last change on this file since 18404 was 18404, checked in by BrainSlayer, 16 months ago

WNR2000 uboot detection and platform mac

File size: 7.9 KB
Line 
1/*
2 * proc_gpio: AR5315 GPIO pins in /proc/gpio/
3 * by olg
4 * modification for AR7240 support by Sebastian Gottschall <s.gottschall@newmedia-net.de>
5 * GPL'ed
6 * some code stolen from Yoshinori Sato <ysato@users.sourceforge.jp>
7 *
8 *  This program is free software; you can redistribute it and/or modify it
9 *  under the terms of the GNU General Public License version 2 as published
10 *  by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/types.h>
16#include <linux/stddef.h>
17#include <linux/proc_fs.h>
18#include <linux/kernel.h>
19#include <linux/string.h>
20#include <linux/fs.h>
21#include <asm/uaccess.h>        /* for copy_from_user */
22
23#include "ar7240.h"
24
25#define PROCFS_MAX_SIZE 64
26extern const char *get_arch_type (void);
27struct proc_dir_entry *proc_gpio, *gpio_dir;
28
29//Masks for data exchange through "void *data" pointer
30#define GPIO_IN (1<<5)
31#define GPIO_OUT (1<<6)
32#define GPIO_DIR (1<<7)
33#define PIN_MASK 0x1f
34#define GPIO_CR_M(x)                (1 << (x))  /* mask for i/o */
35
36
37static void cleanup_proc (void);
38
39//The buffer used to store the data returned by the proc file
40static char procfs_buffer[PROCFS_MAX_SIZE];
41static unsigned long procfs_buffer_size = 0;
42
43
44static int
45gpio_proc_read (char *buf, char **start, off_t offset,
46                int len, int *eof, void *data)
47{
48  u32 reg = 0;
49      if ((unsigned int) data & GPIO_IN)
50        reg = ar7240_reg_rd(AR7240_GPIO_IN);
51      if ((unsigned int) data & GPIO_OUT)
52        reg = ar7240_reg_rd(AR7240_GPIO_OUT);
53      if ((unsigned int) data & GPIO_DIR)
54        reg = ar7240_reg_rd(AR7240_GPIO_OE);
55
56  if (GPIO_CR_M (((unsigned int) data) & PIN_MASK) & reg)
57    buf[0] = '1';
58  else
59    buf[0] = '0';
60  buf[1] = 0;
61
62  *eof = 1;
63
64  return (2);
65
66}
67
68static int
69gpio_proc_info_read (char *buf, char **start, off_t offset,
70                     int len, int *eof, void *data)
71{
72  *eof = 1;
73      return (sprintf
74              (buf, "GPIO_IN   %#08X \nGPIO_OUT  %#08X \nGPIO_DIR  %#08X \n",
75               ar7240_reg_rd(AR7240_GPIO_IN), ar7240_reg_rd(AR7240_GPIO_OUT),
76               ar7240_reg_rd(AR7240_GPIO_OE)));
77}
78
79static int
80gpio_proc_write (struct file *file, const char *buffer, unsigned long count,
81                 void *data)
82{
83  u32 reg = 0;
84
85  /* get buffer size */
86  procfs_buffer_size = count;
87  if (procfs_buffer_size > PROCFS_MAX_SIZE)
88    {
89      procfs_buffer_size = PROCFS_MAX_SIZE;
90    }
91  /* write data to the buffer */
92  if (copy_from_user (procfs_buffer, buffer, procfs_buffer_size))
93    {
94      return -EFAULT;
95    }
96
97  procfs_buffer[procfs_buffer_size] = 0;
98
99      if ((unsigned int) data & GPIO_IN)
100        reg = ar7240_reg_rd(AR7240_GPIO_IN);
101      if ((unsigned int) data & GPIO_OUT)
102        reg = ar7240_reg_rd(AR7240_GPIO_OUT);
103      if ((unsigned int) data & GPIO_DIR)
104        reg = ar7240_reg_rd(AR7240_GPIO_OE);
105
106  if (procfs_buffer[0] == '0' || procfs_buffer[0] == 'i')
107    reg = reg & ~(GPIO_CR_M (((unsigned int) data) & PIN_MASK));
108  if (procfs_buffer[0] == '1' || procfs_buffer[0] == 'o')
109    reg = reg | GPIO_CR_M (((unsigned int) data) & PIN_MASK);
110
111
112      if ((unsigned int) data & GPIO_IN)
113        {
114          ar7240_reg_wr(AR7240_GPIO_IN, reg);
115        }
116      if ((unsigned int) data & GPIO_OUT)
117        {
118          ar7240_reg_wr(AR7240_GPIO_OUT, reg);
119        }
120      if ((unsigned int) data & GPIO_DIR)
121        {
122          ar7240_reg_wr(AR7240_GPIO_OE, reg);
123        }
124
125  return procfs_buffer_size;
126}
127
128void ar7100_set_gpio(int gpio, int val)
129{
130u32 reg = ar7240_reg_rd(AR7240_GPIO_OE);
131reg |= 1<<gpio;
132ar7240_reg_wr(AR7240_GPIO_OE, reg);
133(void)ar7240_reg_rd(AR7240_GPIO_OE); /* flush write to hardware */
134reg = ar7240_reg_rd(AR7240_GPIO_OUT);
135if (val)
136    reg|=1<<gpio;
137else
138    reg&=~(1<<gpio);
139ar7240_reg_wr(AR7240_GPIO_OUT, reg);
140}
141
142int ar7100_get_gpio(int gpio)
143{
144u32 reg = ar7240_reg_rd(AR7240_GPIO_OE);
145reg&=~(1<<gpio);
146ar7240_reg_wr(AR7240_GPIO_OE, reg);
147reg = ar7240_reg_rd(AR7240_GPIO_IN);
148if (reg&(1<<gpio))
149    return 1;
150else
151    return 0;
152}
153EXPORT_SYMBOL(ar7100_set_gpio);
154EXPORT_SYMBOL(ar7100_get_gpio);
155
156
157
158typedef u32                                     gpio_words;
159
160#define GPIO_WL0_ADDR           KSEG1ADDR(AR7240_PCI_MEM_BASE + 0x4048)                         //AR9220 GPIO IN/OUT REGISTER   --> PCI MAP 0xB0000000 + OFFSET [0x4048]
161#define GPIOOUT_WL0_ADDR                KSEG1ADDR(AR7240_PCI_MEM_BASE + 0x404c)                         //AR9223 GPIO IN/OUT REGISTER   --> PCI MAP 0xB0010000 + OFFSET [0x4048]
162
163#define AR_GPIO_OE_OUT                           0x404c // GPIO output register
164#define AR_GPIO_OE_OUT_DRV                       0x3    // 2 bit field mask, shifted by 2*bitpos
165#define AR_GPIO_OE_OUT_DRV_NO                    0x0    // tristate
166#define AR_GPIO_OE_OUT_DRV_LOW                   0x1    // drive if low
167#define AR_GPIO_OE_OUT_DRV_HI                    0x2    // drive if high
168#define AR_GPIO_OE_OUT_DRV_ALL                   0x3    // drive always
169
170int is_ar9300=0;
171
172void set_wl0_gpio(int gpio,int val)
173{
174        register        gpio_words      wl0;
175        int shift;
176        int addr;
177
178        unsigned int output = GPIOOUT_WL0_ADDR;
179        if (is_ar9300)
180            output = KSEG1ADDR(AR7240_PCI_MEM_BASE + 0x4050);
181           
182
183        wl0 = (gpio_words)ar7240_reg_rd(output);
184        shift = gpio*2;
185        wl0 |=  AR_GPIO_OE_OUT_DRV << shift;
186        ar7240_reg_wr(output, wl0);     //ar9283 register [0x4048]
187        ar7240_reg_rd(output);  //ar9283 register [0x4048]
188       
189        wl0 = (gpio_words)ar7240_reg_rd(GPIO_WL0_ADDR); //ar9280 register [0x4048]
190        if (val)
191            wl0|=1<<gpio;
192        else
193            wl0&=(~(1<<gpio));
194
195        ar7240_reg_wr(GPIO_WL0_ADDR, wl0);      //ar9283 register [0x4048]
196        ar7240_reg_rd(GPIO_WL0_ADDR);   //ar9283 register [0x4048]
197}
198
199int get_wl0_gpio(int gpio)
200{
201        register        gpio_words      wl0     = (gpio_words)ar7240_reg_rd(GPIO_WL0_ADDR);     //ar9280 register [0x4048]
202        if (wl0&(1<<gpio));
203            return 1;
204        return 0;
205}
206
207#define USB_LED_OFF 1
208#define USB_LED_ON 0
209
210
211void ap_usb_led_on(void)
212{
213printk(KERN_EMERG "switch USB LED On\n");
214#ifdef CONFIG_WZRG300NH2
215set_wl0_gpio(4,0);
216#else
217#ifdef AP_USB_LED_GPIO
218        ar7100_set_gpio(AP_USB_LED_GPIO, USB_LED_ON);
219#endif
220#endif
221}
222EXPORT_SYMBOL(ap_usb_led_on);
223
224void ap_usb_led_off(void)
225{
226printk(KERN_EMERG "switch USB LED Off\n");
227#ifdef CONFIG_WZRG300NH2
228set_wl0_gpio(4,1);
229#else
230#ifdef AP_USB_LED_GPIO
231        ar7100_set_gpio(AP_USB_LED_GPIO, USB_LED_OFF);
232#endif
233#endif
234}
235EXPORT_SYMBOL(ap_usb_led_off);
236
237void __init ar71xx_gpio_init(void);
238
239static __init int
240register_proc (void)
241{
242  unsigned char i, flag = 0;
243
244
245  char proc_name[64];
246  int gpiocount = 32;
247 
248  /* create directory gpio */
249  gpio_dir = proc_mkdir ("gpio", NULL);
250  if (gpio_dir == NULL)
251    goto fault;
252
253  for (i = 0; i < gpiocount * 3; i++)   //create for every GPIO "x_in"," x_out" and "x_dir"
254    {
255      if (i / gpiocount == 0)
256        {
257          flag = GPIO_IN;
258          sprintf (proc_name, "%i_in", i);
259        }
260      if (i / gpiocount == 1)
261        {
262          flag = GPIO_OUT;
263          sprintf (proc_name, "%i_out", i % gpiocount);
264        }
265      if (i / gpiocount == 2)
266        {
267          flag = GPIO_DIR;
268          sprintf (proc_name, "%i_dir", i % gpiocount);
269        }
270
271      proc_gpio = create_proc_entry (proc_name, S_IRUGO, gpio_dir);
272      if (proc_gpio)
273        {
274          proc_gpio->read_proc = gpio_proc_read;
275          proc_gpio->write_proc = gpio_proc_write;
276          proc_gpio->data = ((i % gpiocount) | flag);
277        }
278      else
279        goto fault;
280
281    }
282
283  proc_gpio = create_proc_entry ("info", S_IRUGO, gpio_dir);
284  if (proc_gpio)
285    {
286      proc_gpio->read_proc = gpio_proc_info_read;
287    }
288  else
289    goto fault;
290
291  printk (KERN_NOTICE "gpio_proc: module loaded and /proc/gpio/ created\n");
292  ar71xx_gpio_init();
293  return 0;
294
295fault:
296  cleanup_proc ();
297  return -EFAULT;
298}
299
300static void
301cleanup_proc (void)
302{
303  unsigned char i;
304  char proc_name[64];
305  int gpiocount=32;
306
307  for (i = 0; i < gpiocount; i++)
308    {
309      sprintf (proc_name, "%i_in", i);
310      remove_proc_entry (proc_name, gpio_dir);
311      sprintf (proc_name, "%i_out", i);
312      remove_proc_entry (proc_name, gpio_dir);
313      sprintf (proc_name, "%i_dir", i);
314      remove_proc_entry (proc_name, gpio_dir);
315    }
316  remove_proc_entry ("info", gpio_dir);
317  remove_proc_entry ("gpio", NULL);
318  printk (KERN_INFO "gpio_proc: unloaded and /proc/gpio/ removed\n");
319
320}
321
322
323module_init (register_proc);
324module_exit (cleanup_proc);
325
326MODULE_AUTHOR ("Sebastian Gottschall");
327MODULE_DESCRIPTION ("AR7240 GPIO pins in /proc/gpio/");
328MODULE_LICENSE ("GPL");
Note: See TracBrowser for help on using the repository browser.