6ad7ff102f03e125ed640c427ced0c5d68b64dd8
[openwrt.git] / package / diag / diag_led.c
1 /*
2  * diag_led.c - replacement diag module
3  *
4  * Copyright (C) 2004 Mike Baker,
5  *                    Imre Kaloz <kaloz@dune.hu>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20  *
21  * $Id$
22  */
23
24 /*
25  * ChangeLog:
26  * 2004/03/28 initial release 
27  * 2004/08/26 asus & buffalo support added
28  * 2005/03/14 asus wl-500g deluxe and buffalo v2 support added
29  * 2005/04/13 added licensing informations
30  * 2005/04/18 base reset polarity off initial readings
31  * 2006/02/07 motorola wa840g/we800g support added
32  */
33
34 #include <linux/module.h>
35 #include <linux/init.h>
36 #include <linux/kernel.h>
37 #include <linux/sysctl.h>
38 #include <asm/io.h>
39 #include <typedefs.h>
40 #include <osl.h>
41 #include <bcmdevs.h>
42 #include <sbutils.h>
43
44 extern char * nvram_get(const char *name);
45 static void *sbh;
46
47 // v2.x - - - - -
48 #define DIAG_GPIO (1<<1)
49 #define DMZ_GPIO  (1<<7)
50
51 static void set_gpio(uint32 mask, uint32 value) {
52         sb_gpiocontrol(sbh,mask, 0, GPIO_DRV_PRIORITY);
53         sb_gpioouten(sbh,mask,mask,GPIO_DRV_PRIORITY);
54         sb_gpioout(sbh,mask,value,GPIO_DRV_PRIORITY);
55 }
56
57 static void v2_set_diag(u8 state) {
58         set_gpio(DIAG_GPIO,state);
59 }
60 static void v2_set_dmz(u8 state) {
61         set_gpio(DMZ_GPIO,state);
62 }
63
64 // v1.x - - - - -
65 #define LED_DIAG   0x13
66 #define LED_DMZ    0x12
67
68 static void v1_set_diag(u8 state) {
69         if (!state) {
70                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
71         } else {
72                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
73         }
74 }
75 static void v1_set_dmz(u8 state) {
76         if (!state) {
77                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
78         } else {
79                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
80         }
81 }
82
83 static void wap1_set_diag(u8 state) {
84        set_gpio(1<<3,state);
85 }
86 static void wap1_set_dmz(u8 state) {
87        set_gpio(1<<4,state);
88 }
89
90 // - - - - -
91 static void ignore(u8 ignored) {};
92
93 // - - - - -
94 #define BIT_DMZ         0x01
95 #define BIT_DIAG        0x04
96
97 void (*set_diag)(u8 state);
98 void (*set_dmz)(u8 state);
99
100 static unsigned int diag = 0;
101
102 static void diag_change()
103 {
104         set_diag(0xFF); // off
105         set_dmz(0xFF); // off
106
107         if(diag & BIT_DIAG)
108                 set_diag(0x00); // on
109         if(diag & BIT_DMZ)
110                 set_dmz(0x00); // on
111 }
112
113 static int proc_diag(ctl_table *table, int write, struct file *filp,
114                 void *buffer, size_t *lenp)
115 {
116         int r;
117         r = proc_dointvec(table, write, filp, buffer, lenp);
118         if (write && !r) {
119                 diag_change();
120         }
121         return r;
122 }
123
124 // - - - - -
125 static unsigned char reset_gpio = 0;
126 static unsigned char reset_polarity = 0;
127 static unsigned int reset = 0;
128
129 static int proc_reset(ctl_table *table, int write, struct file *filp,
130                 void *buffer, size_t *lenp)
131 {
132
133         if (reset_gpio) {
134                 sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
135                 sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
136                 reset=!(sb_gpioin(sbh)&reset_gpio);
137
138                 if (reset_polarity) reset=!reset;
139         } else {
140                 reset=0;
141         }
142
143         return proc_dointvec(table, write, filp, buffer, lenp);
144 }
145
146 // - - - - -
147 static struct ctl_table_header *diag_sysctl_header;
148
149 static ctl_table sys_diag[] = {
150          { 
151            ctl_name: 2000,
152            procname: "diag", 
153            data: &diag,
154            maxlen: sizeof(diag), 
155            mode: 0644,
156            proc_handler: proc_diag
157          },
158          {
159            ctl_name: 2001,
160            procname: "reset",
161            data: &reset,
162            maxlen: sizeof(reset),
163            mode: 0444,
164            proc_handler: proc_reset 
165          },
166          { 0 }
167 };
168
169 static int __init diag_init()
170 {
171         char *buf;
172         u32 board_type;
173         sbh = sb_kattach();
174         sb_gpiosetcore(sbh);
175
176         board_type = sb_boardtype(sbh);
177         printk(KERN_INFO "diag boardtype: %08x\n",board_type);
178
179         set_diag=ignore;
180         set_dmz=ignore;
181         
182         buf=nvram_get("pmon_ver") ?: "";
183         if (((board_type & 0xf00) == 0x400) && (strncmp(buf, "CFE", 3) != 0)) {
184                 buf=nvram_get("boardtype")?:"";
185                 if (!strncmp(buf,"bcm94710dev",11)) {
186                         buf=nvram_get("boardnum")?:"";
187                         if (!strcmp(buf,"42")) {
188                                 // wrt54g v1.x
189                                 set_diag=v1_set_diag;
190                                 set_dmz=v1_set_dmz;
191                                 reset_gpio=(1<<6);
192                         }
193                         if (simple_strtoul(buf, NULL, 0) == 2) {
194                                 // wap54g v1.0
195                                 // do not use strcmp as PMON v5.3.22 has some built-in nvram 
196                                 // defaults with trailing \r
197                                 set_diag=wap1_set_diag;
198                                 // no dmz led on wap54g, used green led 
199                                 // labeled "WLAN Link" instead
200                                 set_dmz=wap1_set_dmz;
201                                 reset_gpio=(1<<0);
202                         }
203                         if (!strcmp(buf,"asusX")) {
204                                 //asus wl-500g
205                                 reset_gpio=(1<<6);
206                         }
207                         if (!strcmp(buf,"2")) {
208                                 //wa840g v1 / we800g v1
209                                 reset_gpio=(1<<0);
210                         }
211                 }
212                 if (!strcmp(buf,"bcm94710ap")) {
213                         buf=nvram_get("boardnum")?:"";
214                         if (!strcmp(buf,"42")) {
215                                 // buffalo
216                                 set_dmz=v2_set_dmz;
217                                 reset_gpio=(1<<4);
218                         }
219                         if (!strcmp(buf,"44")) {
220                                 //dell truemobile
221                                 set_dmz=v2_set_dmz;
222                                 reset_gpio=(1<<0);
223                         }
224                 }
225         } else {
226                 buf=nvram_get("boardnum")?:"";
227                 if (!strcmp(buf,"42")) {
228                         //linksys
229                         set_diag=v2_set_diag;
230                         set_dmz=v2_set_dmz;
231                         reset_gpio=(1<<6);
232                 }
233                 if (!strcmp(buf,"44")) {
234                         //motorola
235                         reset_gpio=(1<<5);
236                 }
237                 if (!strcmp(buf,"00")) {
238                         //buffalo
239                         reset_gpio=(1<<7);
240                 }
241                 if (!strcmp(buf,"45")) {
242                         //wl-500g deluxe
243                         reset_gpio=(1<<6);
244                 }
245         }
246
247         
248         sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
249         sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
250         reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
251
252         diag_sysctl_header = register_sysctl_table(sys_diag, 0);
253         diag_change();
254
255         return 0;
256 }
257
258 static void __exit diag_exit()
259 {
260         unregister_sysctl_table(diag_sysctl_header);
261 }
262
263 EXPORT_NO_SYMBOLS;
264 MODULE_AUTHOR("openwrt.org");
265 MODULE_LICENSE("GPL");
266
267 module_init(diag_init);
268 module_exit(diag_exit);