63a806cd716b9c78a8438e839968055779791973
[oweals/openwrt.git] / obsolete-buildroot / sources / openwrt / kernel / diag.c
1 // replacement diag module
2 // (c) 2004 openwrt 
3 // mbm at alt dot org
4 //
5 // initial release 2004/03/28
6
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/kernel.h>
10 #include <linux/sysctl.h>
11 #include <asm/io.h>
12 #include <typedefs.h>
13 #include <bcm4710.h>
14 #include <sbutils.h>
15
16 static void *sbh;
17
18 // v2.x - - - - -
19 #define DIAG_GPIO (1<<1)
20 #define DMZ_GPIO  (1<<7)
21
22 static void set_gpio(uint32 mask, uint32 value) {
23         sb_gpiocontrol(sbh,mask,0);
24         sb_gpioouten(sbh,mask,mask);
25         sb_gpioout(sbh,mask,value);
26 }
27
28 static void v2_set_diag(u8 state) {
29         set_gpio(DIAG_GPIO,state);
30 }
31 static void v2_set_dmz(u8 state) {
32         set_gpio(DMZ_GPIO,state);
33 }
34
35 // v1.x - - - - -
36 #define LED_DIAG   0x13
37 #define LED_DMZ    0x12
38
39 static void v1_set_diag(u8 state) {
40         if (!state) {
41                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG)=0xFF;
42         } else {
43                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DIAG);
44         }
45 }
46 static void v1_set_dmz(u8 state) {
47         if (!state) {
48                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ)=0xFF;
49         } else {
50                 *(volatile u8*)(KSEG1ADDR(BCM4710_EUART)+LED_DMZ);
51         }
52 }
53
54 // - - - - -
55 static void ignore(u8 ignored) {};
56
57 // - - - - -
58 #define BIT_DMZ         0x01
59 #define BIT_DIAG        0x04
60
61 void (*set_diag)(u8 state);
62 void (*set_dmz)(u8 state);
63
64 static unsigned int diag = 0;
65
66 static void diag_change()
67 {
68         printk(KERN_INFO "led -> %02x\n",diag);
69
70         set_diag(0xFF); // off
71         set_dmz(0xFF); // off
72
73         if(diag & BIT_DIAG)
74                 set_diag(0x00); // on
75         if(diag & BIT_DMZ)
76                 set_dmz(0x00); // on
77 }
78
79 static int proc_diag(ctl_table *table, int write, struct file *filp,
80                 void *buffer, size_t *lenp)
81 {
82         int r;
83         r = proc_dointvec(table, write, filp, buffer, lenp);
84         if (write && !r) {
85                 diag_change();
86         }
87         return r;
88 }
89
90 // - - - - -
91 static unsigned char reset_gpio = 0;
92 static unsigned char reset_polarity = 0;
93 static unsigned int reset = 0;
94
95 static int proc_reset(ctl_table *table, int write, struct file *filp,
96                 void *buffer, size_t *lenp)
97 {
98
99         if (reset_gpio) {
100                 sb_gpiocontrol(sbh,reset_gpio,reset_gpio);
101                 sb_gpioouten(sbh,reset_gpio,0);
102                 reset=!(sb_gpioin(sbh)&reset_gpio);
103
104                 if (reset_polarity) reset=!reset;
105         } else {
106                 reset=0;
107         }
108
109         return proc_dointvec(table, write, filp, buffer, lenp);
110 }
111
112 // - - - - -
113 static struct ctl_table_header *diag_sysctl_header;
114
115 static ctl_table sys_diag[] = {
116          { 
117            ctl_name: 2000,
118            procname: "diag", 
119            data: &diag,
120            maxlen: sizeof(diag), 
121            mode: 0644,
122            proc_handler: proc_diag
123          },
124          {
125            ctl_name: 2001,
126            procname: "reset",
127            data: &reset,
128            maxlen: sizeof(reset),
129            mode: 0444,
130            proc_handler: proc_reset 
131          },
132          { 0 }
133 };
134
135 static int __init diag_init()
136 {
137         char *buf;
138         u32 board_type;
139         sbh = sb_kattach();
140         sb_gpiosetcore(sbh);
141
142         board_type = sb_boardtype(sbh);
143         printk(KERN_INFO "diag boardtype: %08x\n",board_type);
144
145         set_diag=ignore;
146         set_dmz=ignore;
147         
148         if (board_type & 0x400) {
149                 board_type=1;
150                 set_diag=v1_set_diag;
151                 set_dmz=v1_set_dmz;
152
153                 buf=nvram_get("boardtype")?:"";
154
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 (!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                         // buffalo
171                         set_diag=ignore;
172                         set_dmz=v2_set_dmz;
173                         reset_gpio=(1<<4);
174                         reset_polarity=1;
175                 }
176         } else {
177                 board_type=2;
178                 set_diag=v2_set_diag;
179                 set_dmz=v2_set_dmz;
180                 reset_gpio=(1<<6);
181                 reset_polarity=0;
182         }
183         printk(KERN_INFO "using v%d hardware\n",board_type);
184
185         diag_sysctl_header = register_sysctl_table(sys_diag, 0);
186         diag_change();
187
188         return 0;
189 }
190
191 static void __exit diag_exit()
192 {
193         unregister_sysctl_table(diag_sysctl_header);
194 }
195
196 module_init(diag_init);
197 module_exit(diag_exit);