danube_led cleanup
[openwrt.git] / target / linux / danube / files / drivers / char / danube_led.c
1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
15 *
16 * Copyright (C) 2006 infineon
17 * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
18 *
19 */
20
21 #include <linux/kernel.h>
22 #include <linux/module.h>
23 #include <linux/version.h>
24 #include <linux/types.h>
25 #include <linux/fs.h>
26 #include <linux/miscdevice.h>
27 #include <linux/init.h>
28 #include <asm/uaccess.h>
29 #include <asm/unistd.h>
30 #include <linux/errno.h>
31 #include <asm/danube/danube.h>
32 #include <asm/danube/danube_gpio.h>
33
34 #define LED_CONFIG 0x01
35
36 #define CONFIG_OPERATION_UPDATE_SOURCE 0x0001
37 #define CONFIG_OPERATION_BLINK 0x0002
38 #define CONFIG_OPERATION_UPDATE_CLOCK 0x0004
39 #define CONFIG_OPERATION_STORE_MODE 0x0008
40 #define CONFIG_OPERATION_SHIFT_CLOCK 0x0010
41 #define CONFIG_OPERATION_DATA_OFFSET 0x0020
42 #define CONFIG_OPERATION_NUMBER_OF_LED 0x0040
43 #define CONFIG_OPERATION_DATA 0x0080
44 #define CONFIG_OPERATION_MIPS0_ACCESS 0x0100
45 #define CONFIG_DATA_CLOCK_EDGE 0x0200
46
47 #define DANUBE_LED_CLK_EDGE DANUBE_LED_FALLING
48 //#define DANUBE_LED_CLK_EDGE DANUBE_LED_RISING
49
50 #define LED_SH_PORT 0
51 #define LED_SH_PIN 4
52 #define LED_SH_DIR 1
53 #define LED_SH_ALTSEL0 1
54 #define LED_SH_ALTSEL1 0
55 #define LED_SH_OPENDRAIN 1
56 #define LED_D_PORT 0
57 #define LED_D_PIN 5
58 #define LED_D_DIR 1
59 #define LED_D_ALTSEL0 1
60 #define LED_D_ALTSEL1 0
61 #define LED_D_OPENDRAIN 1
62 #define LED_ST_PORT 0
63 #define LED_ST_PIN 6
64 #define LED_ST_DIR 1
65 #define LED_ST_ALTSEL0 1
66 #define LED_ST_ALTSEL1 0
67 #define LED_ST_OPENDRAIN 1
68
69 #define LED_ADSL0_PORT 0
70 #define LED_ADSL0_PIN 4
71 #define LED_ADSL0_DIR 1
72 #define LED_ADSL0_ALTSEL0 0
73 #define LED_ADSL0_ALTSEL1 1
74 #define LED_ADSL0_OPENDRAIN 1
75 #define LED_ADSL1_PORT 0
76 #define LED_ADSL1_PIN 5
77 #define LED_ADSL1_DIR 1
78 #define LED_ADSL1_ALTSEL0 1
79 #define LED_ADSL1_ALTSEL1 1
80 #define LED_ADSL1_OPENDRAIN 1
81
82 #if (LED_SH_PORT == LED_ADSL0_PORT && LED_SH_PIN == LED_ADSL0_PIN) \
83 || (LED_D_PORT == LED_ADSL0_PORT && LED_D_PIN == LED_ADSL0_PIN) \
84 || (LED_ST_PORT == LED_ADSL0_PORT && LED_ST_PIN == LED_ADSL0_PIN) \
85 || (LED_SH_PORT == LED_ADSL1_PORT && LED_SH_PIN == LED_ADSL1_PIN) \
86 || (LED_D_PORT == LED_ADSL1_PORT && LED_D_PIN == LED_ADSL1_PIN) \
87 || (LED_ST_PORT == LED_ADSL1_PORT && LED_ST_PIN == LED_ADSL1_PIN)
88 #define ADSL_LED_IS_EXCLUSIVE 1
89 #else
90 #define ADSL_LED_IS_EXCLUSIVE 0
91 #endif
92
93 #if LED_SH_DIR
94 #define LED_SH_DIR_SETUP danube_port_set_dir_out
95 #else
96 #define LED_SH_DIR_SETUP danube_port_clear_dir_out
97 #endif
98 #if LED_SH_ALTSEL0
99 #define LED_SH_ALTSEL0_SETUP danube_port_set_altsel0
100 #else
101 #define LED_SH_ALTSEL0_SETUP danube_port_clear_altsel0
102 #endif
103 #if LED_SH_ALTSEL1
104 #define LED_SH_ALTSEL1_SETUP danube_port_set_altsel1
105 #else
106 #define LED_SH_ALTSEL1_SETUP danube_port_clear_altsel1
107 #endif
108 #if LED_SH_OPENDRAIN
109 #define LED_SH_OPENDRAIN_SETUP danube_port_set_open_drain
110 #else
111 #define LED_SH_OPENDRAIN_SETUP danube_port_clear_open_drain
112 #endif
113
114 #if LED_D_DIR
115 #define LED_D_DIR_SETUP danube_port_set_dir_out
116 #else
117 #define LED_D_DIR_SETUP danube_port_clear_dir_out
118 #endif
119 #if LED_D_ALTSEL0
120 #define LED_D_ALTSEL0_SETUP danube_port_set_altsel0
121 #else
122 #define LED_D_ALTSEL0_SETUP danube_port_clear_altsel0
123 #endif
124 #if LED_D_ALTSEL1
125 #define LED_D_ALTSEL1_SETUP danube_port_set_altsel1
126 #else
127 #define LED_D_ALTSEL1_SETUP danube_port_clear_altsel1
128 #endif
129 #if LED_D_OPENDRAIN
130 #define LED_D_OPENDRAIN_SETUP danube_port_set_open_drain
131 #else
132 #define LED_D_OPENDRAIN_SETUP danube_port_clear_open_drain
133 #endif
134
135 #if LED_ST_DIR
136 #define LED_ST_DIR_SETUP danube_port_set_dir_out
137 #else
138 #define LED_ST_DIR_SETUP danube_port_clear_dir_out
139 #endif
140 #if LED_ST_ALTSEL0
141 #define LED_ST_ALTSEL0_SETUP danube_port_set_altsel0
142 #else
143 #define LED_ST_ALTSEL0_SETUP danube_port_clear_altsel0
144 #endif
145 #if LED_ST_ALTSEL1
146 #define LED_ST_ALTSEL1_SETUP danube_port_set_altsel1
147 #else
148 #define LED_ST_ALTSEL1_SETUP danube_port_clear_altsel1
149 #endif
150 #if LED_ST_OPENDRAIN
151 #define LED_ST_OPENDRAIN_SETUP danube_port_set_open_drain
152 #else
153 #define LED_ST_OPENDRAIN_SETUP danube_port_clear_open_drain
154 #endif
155
156 #if LED_ADSL0_DIR
157 #define LED_ADSL0_DIR_SETUP danube_port_set_dir_out
158 #else
159 #define LED_ADSL0_DIR_SETUP danube_port_clear_dir_out
160 #endif
161 #if LED_ADSL0_ALTSEL0
162 #define LED_ADSL0_ALTSEL0_SETUP danube_port_set_altsel0
163 #else
164 #define LED_ADSL0_ALTSEL0_SETUP danube_port_clear_altsel0
165 #endif
166 #if LED_ADSL0_ALTSEL1
167 #define LED_ADSL0_ALTSEL1_SETUP danube_port_set_altsel1
168 #else
169 #define LED_ADSL0_ALTSEL1_SETUP danube_port_clear_altsel1
170 #endif
171 #if LED_ADSL0_OPENDRAIN
172 #define LED_ADSL0_OPENDRAIN_SETUP danube_port_set_open_drain
173 #else
174 #define LED_ADSL0_OPENDRAIN_SETUP danube_port_clear_open_drain
175 #endif
176
177 #if LED_ADSL1_DIR
178 #define LED_ADSL1_DIR_SETUP danube_port_set_dir_out
179 #else
180 #define LED_ADSL1_DIR_SETUP danube_port_clear_dir_out
181 #endif
182 #if LED_ADSL1_ALTSEL0
183 #define LED_ADSL1_ALTSEL0_SETUP danube_port_set_altsel0
184 #else
185 #define LED_ADSL1_ALTSEL0_SETUP danube_port_clear_altsel0
186 #endif
187 #if LED_ADSL1_ALTSEL1
188 #define LED_ADSL1_ALTSEL1_SETUP danube_port_set_altsel1
189 #else
190 #define LED_ADSL1_ALTSEL1_SETUP danube_port_clear_altsel1
191 #endif
192 #if LED_ADSL1_OPENDRAIN
193 #define LED_ADSL1_OPENDRAIN_SETUP danube_port_set_open_drain
194 #else
195 #define LED_ADSL1_OPENDRAIN_SETUP danube_port_clear_open_drain
196 #endif
197
198 #define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
199
200 static int danube_led_major;
201
202 static int
203 danube_led_setup_gpio (void)
204 {
205 /*
206 * Set LED_ST
207 * I don't check the return value, because I'm sure the value is valid
208 * and the pins are reserved already.
209 */
210 LED_ST_ALTSEL0_SETUP(LED_ST_PORT, LED_ST_PIN);
211 LED_ST_ALTSEL1_SETUP(LED_ST_PORT, LED_ST_PIN);
212 LED_ST_DIR_SETUP(LED_ST_PORT, LED_ST_PIN);
213 LED_ST_OPENDRAIN_SETUP(LED_ST_PORT, LED_ST_PIN);
214
215 /*
216 * Set LED_D
217 */
218 LED_D_ALTSEL0_SETUP(LED_D_PORT, LED_D_PIN);
219 LED_D_ALTSEL1_SETUP(LED_D_PORT, LED_D_PIN);
220 LED_D_DIR_SETUP(LED_D_PORT, LED_D_PIN);
221 LED_D_OPENDRAIN_SETUP(LED_D_PORT, LED_D_PIN);
222
223 /*
224 * Set LED_SH
225 */
226 LED_SH_ALTSEL0_SETUP(LED_SH_PORT, LED_SH_PIN);
227 LED_SH_ALTSEL1_SETUP(LED_SH_PORT, LED_SH_PIN);
228 LED_SH_DIR_SETUP(LED_SH_PORT, LED_SH_PIN);
229 LED_SH_OPENDRAIN_SETUP(LED_SH_PORT, LED_SH_PIN);
230
231 return 0;
232 }
233
234 static void
235 danube_led_enable (void)
236 {
237 int err = 1000000;
238
239 writel(readl(DANUBE_PMU_PWDCR) & ~DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR);
240 while (--err && (readl(DANUBE_PMU_PWDSR) & DANUBE_PMU_PWDCR_LED)) {}
241
242 if (!err)
243 panic("Activating LED in PMU failed!");
244 }
245
246 static inline void
247 danube_led_disable (void)
248 {
249 writel(readl(DANUBE_PMU_PWDCR) | DANUBE_PMU_PWDCR_LED, DANUBE_PMU_PWDCR);
250 }
251
252 static int
253 led_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
254 {
255 int ret = -EINVAL;
256
257 switch ( cmd )
258 {
259 case LED_CONFIG:
260 break;
261 }
262
263 return ret;
264 }
265
266 static int
267 led_open (struct inode *inode, struct file *file)
268 {
269 return 0;
270 }
271
272 static int
273 led_release (struct inode *inode, struct file *file)
274 {
275 return 0;
276 }
277
278 static struct file_operations danube_led_fops = {
279 .owner = THIS_MODULE,
280 .ioctl = led_ioctl,
281 .open = led_open,
282 .release = led_release
283 };
284
285
286 /*
287 Map for LED on reference board
288 WLAN_READ LED11 OUT1 15
289 WARNING LED12 OUT2 14
290 FXS1_LINK LED13 OUT3 13
291 FXS2_LINK LED14 OUT4 12
292 FXO_ACT LED15 OUT5 11
293 USB_LINK LED16 OUT6 10
294 ADSL2_LINK LED19 OUT7 9
295 BT_LINK LED17 OUT8 8
296 SD_LINK LED20 OUT9 7
297 ADSL2_TRAFFIC LED31 OUT16 0
298 Map for hardware relay on reference board
299 USB Power On OUT11 5
300 RELAY OUT12 4
301 */
302
303
304 int __init
305 danube_led_init (void)
306 {
307 int ret = 0;
308
309 danube_led_setup_gpio();
310
311 writel(0, DANUBE_LED_AR);
312 writel(0xff00, DANUBE_LED_CPU0);
313 writel(0, DANUBE_LED_CPU1);
314 writel(0x8000ffff, DANUBE_LED_CON0);
315
316 /* setup the clock edge that the shift register is triggered on */
317 writel(readl(DANUBE_LED_CON0) & ~DANUBE_LED_EDGE_MASK, DANUBE_LED_CON0);
318 writel(readl(DANUBE_LED_CON0) | DANUBE_LED_CLK_EDGE, DANUBE_LED_CON0);
319
320 /* per default leds 15-0 are set */
321 writel(DANUBE_LED_GROUP1 | DANUBE_LED_GROUP0, DANUBE_LED_CON1);
322
323 /* leds are update periodically by the FPID */
324 writel(readl(DANUBE_LED_CON1) & ~DANUBE_LED_UPD_MASK, DANUBE_LED_CON1);
325 writel(readl(DANUBE_LED_CON1) | DANUBE_LED_UPD_SRC_FPI, DANUBE_LED_CON1);
326
327 /* set led update speed */
328 writel(readl(DANUBE_LED_CON1) & ~DANUBE_LED_MASK, DANUBE_LED_CON1);
329 writel(readl(DANUBE_LED_CON1) | DANUBE_LED_8HZ, DANUBE_LED_CON1);
330
331 /* adsl 0 and 1 leds are updated by the arc */
332 writel(readl(DANUBE_LED_CON0) | DANUBE_LED_ADSL_SRC, DANUBE_LED_CON0);
333
334 /* per default, the leds are turned on */
335 danube_led_enable();
336
337 danube_led_major = register_chrdev(0, "danube_led", &danube_led_fops);
338
339 if (!danube_led_major)
340 {
341 printk("danube_led: Error! Could not register device. %d\n", danube_led_major);
342 ret = -EINVAL;
343
344 goto out;
345 }
346
347 printk(KERN_INFO "danube_led : device registered on major %d\n", danube_led_major);
348
349 out:
350 return ret;
351 }
352
353 void __exit
354 danube_led_exit (void)
355 {
356 unregister_chrdev(danube_led_major, "danube_led");
357 }
358
359 module_init(danube_led_init);
360 module_exit(danube_led_exit);
This page took 0.069959 seconds and 5 git commands to generate.