e7ed233a18aca7238c375b3a0a2e7f5f67c94c34
[openwrt/svn-archive/archive.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 // 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);