source: src/linux/pb42/linux-2.6.23/arch/mips/ar7100/proc_gpio.c @ 13863

Last change on this file since 13863 was 13863, checked in by BrainSlayer, 3 years ago

fixes for realtek 8366rb driver

File size: 8.3 KB
Line 
1/*
2 * proc_gpio: AR5315 GPIO pins in /proc/gpio/
3 * by olg
4 * modification for AR7100 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/autoconf.h>
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/types.h>
17#include <linux/stddef.h>
18#include <linux/proc_fs.h>
19#include <linux/kernel.h>
20#include <linux/string.h>
21#include <linux/fs.h>
22#include <asm/uaccess.h>        /* for copy_from_user */
23
24#include "ar7100.h"
25
26#define PROCFS_MAX_SIZE 64
27extern const char *get_arch_type(void);
28struct proc_dir_entry *proc_gpio, *gpio_dir;
29
30//Masks for data exchange through "void *data" pointer
31#define GPIO_IN (1<<5)
32#define GPIO_OUT (1<<6)
33#define GPIO_DIR (1<<7)
34#define PIN_MASK 0x1f
35#define GPIO_CR_M(x)                (1 << (x))  /* mask for i/o */
36
37static void cleanup_proc(void);
38void ar7100_set_gpio(int gpio, int val)
39{
40        u32 reg = ar7100_reg_rd(AR7100_GPIO_OE);
41        reg |= 1 << gpio;
42        ar7100_reg_wr(AR7100_GPIO_OE, reg);
43        (void)ar7100_reg_rd(AR7100_GPIO_OE);    /* flush write to hardware */
44        reg = ar7100_reg_rd(AR7100_GPIO_OUT);
45        if (val)
46                reg |= 1 << gpio;
47        else
48                reg &= ~(1 << gpio);
49        ar7100_reg_wr(AR7100_GPIO_OUT, reg);
50}
51
52int ar7100_get_gpio(int gpio)
53{
54        u32 reg = ar7100_reg_rd(AR7100_GPIO_OE);
55        reg &= ~(1 << gpio);
56        ar7100_reg_wr(AR7100_GPIO_OE, reg);
57        reg = ar7100_reg_rd(AR7100_GPIO_IN);
58        if (reg & (1 << gpio))
59                return 1;
60        else
61                return 0;
62}
63
64void
65ar7100_gpio_config_output(int gpio)
66{
67    ar7100_reg_rmw_set(AR7100_GPIO_OE, (1 << gpio));
68    (void)ar7100_reg_rd(AR7100_GPIO_OE);        /* flush write to hardware */
69}
70
71void
72ar7100_gpio_config_input(int gpio)
73{
74    ar7100_reg_rmw_clear(AR7100_GPIO_OE, (1 << gpio));
75    (void)ar7100_reg_rd(AR7100_GPIO_OE);        /* flush write to hardware */
76}
77
78void
79ar7100_gpio_out_val(int gpio, int val)
80{
81    if (val & 0x1) {
82        ar7100_reg_rmw_set(AR7100_GPIO_OUT, (1 << gpio));
83    }
84    else {
85        ar7100_reg_rmw_clear(AR7100_GPIO_OUT, (1 << gpio));
86    }
87    (void)ar7100_reg_rd(AR7100_GPIO_OUT);       /* flush write to hardware */
88}
89
90int
91ar7100_gpio_in_val(int gpio)
92{
93    return((1 << gpio) & (ar7100_reg_rd(AR7100_GPIO_IN)));
94}
95
96
97
98EXPORT_SYMBOL(ar7100_set_gpio);
99EXPORT_SYMBOL(ar7100_get_gpio);
100EXPORT_SYMBOL(ar7100_gpio_config_output);
101EXPORT_SYMBOL(ar7100_gpio_config_input);
102EXPORT_SYMBOL(ar7100_gpio_in_val);
103EXPORT_SYMBOL(ar7100_gpio_out_val);
104
105#define USB_LED_OFF 1
106#define USB_LED_ON 0
107
108void ap_usb_led_on(void)
109{
110#ifdef AP_USB_LED_GPIO
111        ar7100_set_gpio(AP_USB_LED_GPIO, USB_LED_ON);
112#endif
113}
114EXPORT_SYMBOL(ap_usb_led_on);
115
116void ap_usb_led_off(void)
117{
118#ifdef AP_USB_LED_GPIO
119        ar7100_set_gpio(AP_USB_LED_GPIO, USB_LED_OFF);
120#endif
121}
122EXPORT_SYMBOL(ap_usb_led_off);
123
124
125
126
127#define NXP_74HC153_NUM_GPIOS   8
128#define NXP_74HC153_S0_MASK     0x1
129#define NXP_74HC153_S1_MASK     0x2
130#define NXP_74HC153_BANK_MASK   0x4
131
132#define WZRHPG300NH_GPIO_74HC153_S0     9
133#define WZRHPG300NH_GPIO_74HC153_S1     11
134#define WZRHPG300NH_GPIO_74HC153_1Y     12
135#define WZRHPG300NH_GPIO_74HC153_2Y     14
136
137#define WZRHPG300NH_GPIO_EXP_BASE       23
138#define WZRHPG300NH_GPIO_BTN_AOSS       (WZRHPG300NH_GPIO_EXP_BASE + 0)
139#define WZRHPG300NH_GPIO_BTN_RESET      (WZRHPG300NH_GPIO_EXP_BASE + 1)
140#define WZRHPG300NH_GPIO_BTN_ROUTER_ON  (WZRHPG300NH_GPIO_EXP_BASE + 2)
141#define WZRHPG300NH_GPIO_BTN_QOS_ON     (WZRHPG300NH_GPIO_EXP_BASE + 3)
142#define WZRHPG300NH_GPIO_BTN_USB        (WZRHPG300NH_GPIO_EXP_BASE + 5)
143#define WZRHPG300NH_GPIO_BTN_ROUTER_AUTO (WZRHPG300NH_GPIO_EXP_BASE + 6)
144#define WZRHPG300NH_GPIO_BTN_QOS_OFF    (WZRHPG300NH_GPIO_EXP_BASE + 7)
145
146static int nxp_74hc153_get_value(unsigned offset)
147{
148        unsigned s0;
149        unsigned s1;
150        unsigned pin;
151        int ret;
152
153        s0 = !!(offset & NXP_74HC153_S0_MASK);
154        s1 = !!(offset & NXP_74HC153_S1_MASK);
155        pin = (offset & NXP_74HC153_BANK_MASK) ? WZRHPG300NH_GPIO_74HC153_2Y
156            : WZRHPG300NH_GPIO_74HC153_1Y;
157
158        ar7100_set_gpio(WZRHPG300NH_GPIO_74HC153_S0, s0);
159        ar7100_set_gpio(WZRHPG300NH_GPIO_74HC153_S1, s1);
160        ret = ar7100_get_gpio(pin);
161
162        return ret;
163}
164
165//The buffer used to store the data returned by the proc file
166static char procfs_buffer[PROCFS_MAX_SIZE];
167static unsigned long procfs_buffer_size = 0;
168
169static int
170gpio_proc_read(char *buf, char **start, off_t offset,
171               int len, int *eof, void *data)
172{
173        int val;
174        unsigned int pin = (unsigned int)data & PIN_MASK;
175        if (pin >= 23 && pin <= 31) {
176                val = nxp_74hc153_get_value(pin - 23);
177        //      printk(KERN_EMERG "value for pin %d = %d\n", pin, val);
178                if (val)
179                        buf[0] = '1';
180                else
181                        buf[0] = '0';
182                buf[1] = 0;
183                *eof = 1;
184                return (2);
185        }
186        u32 reg = 0;
187        if ((unsigned int)data & GPIO_IN)
188                reg = ar7100_reg_rd(AR7100_GPIO_IN);
189        if ((unsigned int)data & GPIO_OUT)
190                reg = ar7100_reg_rd(AR7100_GPIO_OUT);
191        if ((unsigned int)data & GPIO_DIR)
192                reg = ar7100_reg_rd(AR7100_GPIO_OE);
193
194        if (GPIO_CR_M(((unsigned int)data) & PIN_MASK) & reg)
195                buf[0] = '1';
196        else
197                buf[0] = '0';
198        buf[1] = 0;
199
200        *eof = 1;
201
202        return (2);
203
204}
205
206static int
207gpio_proc_info_read(char *buf, char **start, off_t offset,
208                    int len, int *eof, void *data)
209{
210        *eof = 1;
211        return (sprintf
212                (buf, "GPIO_IN   %#08X \nGPIO_OUT  %#08X \nGPIO_DIR  %#08X \n",
213                 ar7100_reg_rd(AR7100_GPIO_IN), ar7100_reg_rd(AR7100_GPIO_OUT),
214                 ar7100_reg_rd(AR7100_GPIO_OE)));
215}
216
217static int
218gpio_proc_write(struct file *file, const char *buffer, unsigned long count,
219                void *data)
220{
221        u32 reg = 0;
222
223        /* get buffer size */
224        procfs_buffer_size = count;
225        if (procfs_buffer_size > PROCFS_MAX_SIZE) {
226                procfs_buffer_size = PROCFS_MAX_SIZE;
227        }
228        /* write data to the buffer */
229        if (copy_from_user(procfs_buffer, buffer, procfs_buffer_size)) {
230                return -EFAULT;
231        }
232
233        procfs_buffer[procfs_buffer_size] = 0;
234
235        if ((unsigned int)data & GPIO_IN)
236                reg = ar7100_reg_rd(AR7100_GPIO_IN);
237        if ((unsigned int)data & GPIO_OUT)
238                reg = ar7100_reg_rd(AR7100_GPIO_OUT);
239        if ((unsigned int)data & GPIO_DIR)
240                reg = ar7100_reg_rd(AR7100_GPIO_OE);
241
242        if (procfs_buffer[0] == '0' || procfs_buffer[0] == 'i')
243                reg = reg & ~(GPIO_CR_M(((unsigned int)data) & PIN_MASK));
244        if (procfs_buffer[0] == '1' || procfs_buffer[0] == 'o')
245                reg = reg | GPIO_CR_M(((unsigned int)data) & PIN_MASK);
246
247        if ((unsigned int)data & GPIO_IN) {
248                ar7100_reg_wr(AR7100_GPIO_IN, reg);
249        }
250        if ((unsigned int)data & GPIO_OUT) {
251                ar7100_reg_wr(AR7100_GPIO_OUT, reg);
252        }
253        if ((unsigned int)data & GPIO_DIR) {
254                ar7100_reg_wr(AR7100_GPIO_OE, reg);
255        }
256
257        return procfs_buffer_size;
258}
259
260static __init int register_proc(void)
261{
262        unsigned char i, flag = 0;
263        char proc_name[32];
264        int gpiocount = 32;
265
266        /* create directory gpio */
267        gpio_dir = proc_mkdir("gpio", NULL);
268        if (gpio_dir == NULL)
269                goto fault;
270        gpio_dir->owner = THIS_MODULE;
271
272        for (i = 0; i < gpiocount * 3; i++)     //create for every GPIO "x_in"," x_out" and "x_dir"
273        {
274                if (i / gpiocount == 0) {
275                        flag = GPIO_IN;
276                        sprintf(proc_name, "%i_in", i);
277                }
278                if (i / gpiocount == 1) {
279                        flag = GPIO_OUT;
280                        sprintf(proc_name, "%i_out", i % gpiocount);
281                }
282                if (i / gpiocount == 2) {
283                        flag = GPIO_DIR;
284                        sprintf(proc_name, "%i_dir", i % gpiocount);
285                }
286
287                proc_gpio = create_proc_entry(proc_name, S_IRUGO, gpio_dir);
288                if (proc_gpio) {
289                        proc_gpio->read_proc = gpio_proc_read;
290                        proc_gpio->write_proc = gpio_proc_write;
291                        proc_gpio->owner = THIS_MODULE;
292                        proc_gpio->data = ((i % gpiocount) | flag);
293                } else
294                        goto fault;
295
296        }
297
298        proc_gpio = create_proc_entry("info", S_IRUGO, gpio_dir);
299        if (proc_gpio) {
300                proc_gpio->read_proc = gpio_proc_info_read;
301                proc_gpio->owner = THIS_MODULE;
302        } else
303                goto fault;
304
305        printk(KERN_NOTICE
306               "gpio_proc: module loaded and /proc/gpio/ created\n");
307        return 0;
308
309fault:
310        cleanup_proc();
311        return -EFAULT;
312}
313
314static void cleanup_proc(void)
315{
316        unsigned char i;
317        char proc_name[32];
318        int gpiocount = 32;
319
320        for (i = 0; i < gpiocount; i++) {
321                sprintf(proc_name, "%i_in", i);
322                remove_proc_entry(proc_name, gpio_dir);
323                sprintf(proc_name, "%i_out", i);
324                remove_proc_entry(proc_name, gpio_dir);
325                sprintf(proc_name, "%i_dir", i);
326                remove_proc_entry(proc_name, gpio_dir);
327        }
328        remove_proc_entry("info", gpio_dir);
329        remove_proc_entry("gpio", NULL);
330        printk(KERN_INFO "gpio_proc: unloaded and /proc/gpio/ removed\n");
331
332}
333
334module_init(register_proc);
335module_exit(cleanup_proc);
336
337MODULE_AUTHOR("Sebastian Gottschall");
338MODULE_DESCRIPTION("AR7100 GPIO pins in /proc/gpio/");
339MODULE_LICENSE("GPL");
Note: See TracBrowser for help on using the repository browser.