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