6f1ba97324ec214a5fc376fccd121df620e989d9
[openwrt.git] / package / linux / kernel-source / drivers / net / diag / diag_led.c
1 // replacement diag module
2 // (c) 2004 openwrt 
3 // mbm at alt dot org
4 //
5 // initial release 2004/03/28
6 //
7 // 2004/08/26 asus & buffalo support added
8 // 2005/03/14 asus wl-500g deluxe and buffalo v2 support added
9
10 #include <linux/module.h>
11 #include <linux/init.h>
12 #include <linux/kernel.h>
13 #include <linux/sysctl.h>
14 #include <asm/io.h>
15 #include <typedefs.h>
16 #include <bcm4710.h>
17 #include <sbutils.h>
18
19 extern char * nvram_get(const char *name);
20 static void *sbh;
21
22 // v2.x - - - - -
23 #define DIAG_GPIO (1<<1)
24 #define DMZ_GPIO  (1<<7)
25
26 static void set_gpio(uint32 mask, uint32 value) {
27         sb_gpiocontrol(sbh,mask,0);
28         sb_gpioouten(sbh,mask,mask);
29         sb_gpioout(sbh,mask,value);
30 }
31
32 static void v2_set_diag(u8 state) {
33         set_gpio(DIAG_GPIO,state);
34 }
35 static void v2_set_dmz(u8 state) {
36         set_gpio(DMZ_GPIO,state);
37 }
38
39 // v1.x - - - - -
40 #define LED_DIAG   0x13
41 #define LED_DMZ    0x12
42
43 static void v1_set_diag(u8 state) {
44         if (!state) {
45                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
46         } else {
47                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
48         }
49 }
50 static void v1_set_dmz(u8 state) {
51         if (!state) {
52                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
53         } else {
54                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
55         }
56 }
57
58 // - - - - -
59 static void ignore(u8 ignored) {};
60
61 // - - - - -
62 #define BIT_DMZ         0x01
63 #define BIT_DIAG        0x04
64
65 void (*set_diag)(u8 state);
66 void (*set_dmz)(u8 state);
67
68 static unsigned int diag = 0;
69
70 static void diag_change()
71 {
72         //printk(KERN_INFO "led -> %02x\n",diag);
73
74         set_diag(0xFF); // off
75         set_dmz(0xFF); // off
76
77         if(diag & BIT_DIAG)
78                 set_diag(0x00); // on
79         if(diag & BIT_DMZ)
80                 set_dmz(0x00); // on
81 }
82
83 static int proc_diag(ctl_table *table, int write, struct file *filp,
84                 void *buffer, size_t *lenp)
85 {
86         int r;
87         r = proc_dointvec(table, write, filp, buffer, lenp);
88         if (write && !r) {
89                 diag_change();
90         }
91         return r;
92 }
93
94 // - - - - -
95 static unsigned char reset_gpio = 0;
96 static unsigned char reset_polarity = 0;
97 static unsigned int reset = 0;
98
99 static int proc_reset(ctl_table *table, int write, struct file *filp,
100                 void *buffer, size_t *lenp)
101 {
102
103         if (reset_gpio) {
104                 sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
105                 sb_gpioouten(sbh,reset_gpio,0);
106                 reset=!(sb_gpioin(sbh)&reset_gpio);
107
108                 if (reset_polarity) reset=!reset;
109         } else {
110                 reset=0;
111         }
112
113         return proc_dointvec(table, write, filp, buffer, lenp);
114 }
115
116 // - - - - -
117 static struct ctl_table_header *diag_sysctl_header;
118
119 static ctl_table sys_diag[] = {
120          { 
121            ctl_name: 2000,
122            procname: "diag", 
123            data: &diag,
124            maxlen: sizeof(diag), 
125            mode: 0644,
126            proc_handler: proc_diag
127          },
128          {
129            ctl_name: 2001,
130            procname: "reset",
131            data: &reset,
132            maxlen: sizeof(reset),
133            mode: 0444,
134            proc_handler: proc_reset 
135          },
136          { 0 }
137 };
138
139 static int __init diag_init()
140 {
141         char *buf;
142         u32 board_type;
143         sbh = sb_kattach();
144         sb_gpiosetcore(sbh);
145
146         board_type = sb_boardtype(sbh);
147         printk(KERN_INFO "diag boardtype: %08x\n",board_type);
148
149         set_diag=ignore;
150         set_dmz=ignore;
151         
152         if ((board_type & 0xf00) == 0x400) {
153                 board_type=1;
154                 buf=nvram_get("boardtype")?:"";
155                 if (!strcmp(buf,"bcm94710dev")) {
156                         buf=nvram_get("boardnum")?:"";
157                         if (!strcmp(buf,"42")) {
158                                 // wrt54g v1.x
159                                 set_diag=v1_set_diag;
160                                 set_dmz=v1_set_dmz;
161                                 reset_gpio=(1<<6);
162                                 reset_polarity=0;
163                         } else if (!strcmp(buf,"asusX")) {
164                                 //asus wl-500g
165                                 //no leds
166                                 reset_gpio=(1<<6);
167                                 reset_polarity=1;
168                         }
169                 } else if (!strcmp(buf,"bcm94710ap")) {
170                         buf=nvram_get("boardnum")?:"";
171                         if (!strcmp(buf,"42")) {
172                                 // buffalo
173                                 set_dmz=v2_set_dmz;
174                                 reset_gpio=(1<<4);
175                                 reset_polarity=1;
176                         } else if (!strcmp(buf,"44")) {
177                                 //dell truemobile
178                                 set_dmz=v2_set_dmz;
179                                 reset_gpio=(1<<0);
180                                 reset_polarity=0;
181                         }
182                 }
183         } else {
184                 board_type=2;
185                 set_diag=v2_set_diag;
186                 set_dmz=v2_set_dmz;
187                 reset_gpio=(1<<6);
188                 reset_polarity=0;
189                 buf=nvram_get("boardnum")?:"";
190                 if (!strcmp(buf,"44")) {
191                         //motorola
192                         set_diag=ignore;
193                         set_dmz=ignore;
194                         reset_gpio=(1<<5);
195                         reset_polarity=0;
196                 }
197                 if (!strcmp(buf,"00")) {
198                         //buffalo
199                         set_diag=ignore;
200                         set_dmz=ignore;
201                         reset_gpio=(1<<7);
202                         reset_polarity=1;
203                 }
204                 if (!strcmp(buf,"45")) {
205                         //wl-500g deluxe
206                         set_diag=ignore;
207                         set_dmz=ignore;
208                         reset_gpio=(1<<6);
209                         reset_polarity=1;
210                 }
211         }
212         printk(KERN_INFO "using v%d hardware\n",board_type);
213
214         diag_sysctl_header = register_sysctl_table(sys_diag, 0);
215         diag_change();
216
217         return 0;
218 }
219
220 static void __exit diag_exit()
221 {
222         unregister_sysctl_table(diag_sysctl_header);
223 }
224
225 module_init(diag_init);
226 module_exit(diag_exit);