port the changes from [3155] to Kamikaze
[openwrt/svn-archive/archive.git] / openwrt / target / linux / 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 // - - - - -
84 static void ignore(u8 ignored) {};
85
86 // - - - - -
87 #define BIT_DMZ 0x01
88 #define BIT_DIAG 0x04
89
90 void (*set_diag)(u8 state);
91 void (*set_dmz)(u8 state);
92
93 static unsigned int diag = 0;
94
95 static void diag_change()
96 {
97 set_diag(0xFF); // off
98 set_dmz(0xFF); // off
99
100 if(diag & BIT_DIAG)
101 set_diag(0x00); // on
102 if(diag & BIT_DMZ)
103 set_dmz(0x00); // on
104 }
105
106 static int proc_diag(ctl_table *table, int write, struct file *filp,
107 void *buffer, size_t *lenp)
108 {
109 int r;
110 r = proc_dointvec(table, write, filp, buffer, lenp);
111 if (write && !r) {
112 diag_change();
113 }
114 return r;
115 }
116
117 // - - - - -
118 static unsigned char reset_gpio = 0;
119 static unsigned char reset_polarity = 0;
120 static unsigned int reset = 0;
121
122 static int proc_reset(ctl_table *table, int write, struct file *filp,
123 void *buffer, size_t *lenp)
124 {
125
126 if (reset_gpio) {
127 sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
128 sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
129 reset=!(sb_gpioin(sbh)&reset_gpio);
130
131 if (reset_polarity) reset=!reset;
132 } else {
133 reset=0;
134 }
135
136 return proc_dointvec(table, write, filp, buffer, lenp);
137 }
138
139 // - - - - -
140 static struct ctl_table_header *diag_sysctl_header;
141
142 static ctl_table sys_diag[] = {
143 {
144 ctl_name: 2000,
145 procname: "diag",
146 data: &diag,
147 maxlen: sizeof(diag),
148 mode: 0644,
149 proc_handler: proc_diag
150 },
151 {
152 ctl_name: 2001,
153 procname: "reset",
154 data: &reset,
155 maxlen: sizeof(reset),
156 mode: 0444,
157 proc_handler: proc_reset
158 },
159 { 0 }
160 };
161
162 static int __init diag_init()
163 {
164 char *buf;
165 u32 board_type;
166 sbh = sb_kattach();
167 sb_gpiosetcore(sbh);
168
169 board_type = sb_boardtype(sbh);
170 printk(KERN_INFO "diag boardtype: %08x\n",board_type);
171
172 set_diag=ignore;
173 set_dmz=ignore;
174
175 buf=nvram_get("pmon_ver") ?: "";
176 if (((board_type & 0xf00) == 0x400) && (strncmp(buf, "CFE", 3) != 0)) {
177 buf=nvram_get("boardtype")?:"";
178 if (!strcmp(buf,"bcm94710dev")) {
179 buf=nvram_get("boardnum")?:"";
180 if (!strcmp(buf,"42")) {
181 // wrt54g v1.x
182 set_diag=v1_set_diag;
183 set_dmz=v1_set_dmz;
184 reset_gpio=(1<<6);
185 }
186 if (!strcmp(buf,"asusX")) {
187 //asus wl-500g
188 reset_gpio=(1<<6);
189 }
190 if (!strcmp(buf,"2")) {
191 //wa840g v1 / we800g v1
192 reset_gpio=(1<<0);
193 }
194 }
195 if (!strcmp(buf,"bcm94710ap")) {
196 buf=nvram_get("boardnum")?:"";
197 if (!strcmp(buf,"42")) {
198 // buffalo
199 set_dmz=v2_set_dmz;
200 reset_gpio=(1<<4);
201 }
202 if (!strcmp(buf,"44")) {
203 //dell truemobile
204 set_dmz=v2_set_dmz;
205 reset_gpio=(1<<0);
206 }
207 }
208 } else {
209 buf=nvram_get("boardnum")?:"";
210 if (!strcmp(buf,"42")) {
211 //linksys
212 set_diag=v2_set_diag;
213 set_dmz=v2_set_dmz;
214 reset_gpio=(1<<6);
215 }
216 if (!strcmp(buf,"44")) {
217 //motorola
218 reset_gpio=(1<<5);
219 }
220 if (!strcmp(buf,"00")) {
221 //buffalo
222 reset_gpio=(1<<7);
223 }
224 if (!strcmp(buf,"45")) {
225 //wl-500g deluxe
226 reset_gpio=(1<<6);
227 }
228 }
229
230
231 sb_gpiocontrol(sbh,reset_gpio,reset_gpio,GPIO_DRV_PRIORITY);
232 sb_gpioouten(sbh,reset_gpio,0,GPIO_DRV_PRIORITY);
233 reset_polarity=!(sb_gpioin(sbh)&reset_gpio);
234
235 diag_sysctl_header = register_sysctl_table(sys_diag, 0);
236 diag_change();
237
238 return 0;
239 }
240
241 static void __exit diag_exit()
242 {
243 unregister_sysctl_table(diag_sysctl_header);
244 }
245
246 EXPORT_NO_SYMBOLS;
247 MODULE_AUTHOR("openwrt.org");
248 MODULE_LICENSE("GPL");
249
250 module_init(diag_init);
251 module_exit(diag_exit);