1f7dda9a696c5edc1cf5ddde809d33855f5a2d28
[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/port.h>
33 #include <asm/danube/danube_led.h>
34 #include <asm/danube/danube_gptu.h>
35
36 #define DATA_CLOCKING_EDGE              FALLING_EDGE
37 #define RISING_EDGE                     0
38 #define FALLING_EDGE                    1
39
40 #define port_reserve_pin                danube_port_reserve_pin
41 #define port_free_pin                   danube_port_free_pin
42 #define port_set_altsel0                danube_port_set_altsel0
43 #define port_clear_altsel0              danube_port_clear_altsel0
44 #define port_set_altsel1                danube_port_set_altsel1
45 #define port_clear_altsel1              danube_port_clear_altsel1
46 #define port_set_dir_out                danube_port_set_dir_out
47 #define port_clear_dir_out              danube_port_clear_dir_out
48 #define port_set_open_drain             danube_port_set_open_drain
49 #define port_clear_open_drain           danube_port_clear_open_drain
50
51 #define LED_SH_PORT                     0
52 #define LED_SH_PIN                      4
53 #define LED_SH_DIR                      1
54 #define LED_SH_ALTSEL0                  1
55 #define LED_SH_ALTSEL1                  0
56 #define LED_SH_OPENDRAIN                1
57 #define LED_D_PORT                      0
58 #define LED_D_PIN                       5
59 #define LED_D_DIR                       1
60 #define LED_D_ALTSEL0                   1
61 #define LED_D_ALTSEL1                   0
62 #define LED_D_OPENDRAIN                 1
63 #define LED_ST_PORT                     0
64 #define LED_ST_PIN                      6
65 #define LED_ST_DIR                      1
66 #define LED_ST_ALTSEL0                  1
67 #define LED_ST_ALTSEL1                  0
68 #define LED_ST_OPENDRAIN                1
69
70 #define LED_ADSL0_PORT                  0
71 #define LED_ADSL0_PIN                   4
72 #define LED_ADSL0_DIR                   1
73 #define LED_ADSL0_ALTSEL0               0
74 #define LED_ADSL0_ALTSEL1               1
75 #define LED_ADSL0_OPENDRAIN             1
76 #define LED_ADSL1_PORT                  0
77 #define LED_ADSL1_PIN                   5
78 #define LED_ADSL1_DIR                   1
79 #define LED_ADSL1_ALTSEL0               1
80 #define LED_ADSL1_ALTSEL1               1
81 #define LED_ADSL1_OPENDRAIN             1
82
83 #if (LED_SH_PORT == LED_ADSL0_PORT && LED_SH_PIN == LED_ADSL0_PIN)      \
84     || (LED_D_PORT == LED_ADSL0_PORT && LED_D_PIN == LED_ADSL0_PIN)     \
85     || (LED_ST_PORT == LED_ADSL0_PORT && LED_ST_PIN == LED_ADSL0_PIN)   \
86     || (LED_SH_PORT == LED_ADSL1_PORT && LED_SH_PIN == LED_ADSL1_PIN)   \
87     || (LED_D_PORT == LED_ADSL1_PORT && LED_D_PIN == LED_ADSL1_PIN)     \
88     || (LED_ST_PORT == LED_ADSL1_PORT && LED_ST_PIN == LED_ADSL1_PIN)
89   #define ADSL_LED_IS_EXCLUSIVE         1
90 #else
91   #define ADSL_LED_IS_EXCLUSIVE         0
92 #endif
93
94 #if LED_SH_DIR
95   #define LED_SH_DIR_SETUP              port_set_dir_out
96 #else
97   #define LED_SH_DIR_SETUP              port_clear_dir_out
98 #endif
99 #if LED_SH_ALTSEL0
100   #define LED_SH_ALTSEL0_SETUP          port_set_altsel0
101 #else
102   #define LED_SH_ALTSEL0_SETUP          port_clear_altsel0
103 #endif
104 #if LED_SH_ALTSEL1
105   #define LED_SH_ALTSEL1_SETUP          port_set_altsel1
106 #else
107   #define LED_SH_ALTSEL1_SETUP          port_clear_altsel1
108 #endif
109 #if LED_SH_OPENDRAIN
110   #define LED_SH_OPENDRAIN_SETUP        port_set_open_drain
111 #else
112   #define LED_SH_OPENDRAIN_SETUP        port_clear_open_drain
113 #endif
114
115 #if LED_D_DIR
116   #define LED_D_DIR_SETUP               port_set_dir_out
117 #else
118   #define LED_D_DIR_SETUP               port_clear_dir_out
119 #endif
120 #if LED_D_ALTSEL0
121   #define LED_D_ALTSEL0_SETUP           port_set_altsel0
122 #else
123   #define LED_D_ALTSEL0_SETUP           port_clear_altsel0
124 #endif
125 #if LED_D_ALTSEL1
126   #define LED_D_ALTSEL1_SETUP           port_set_altsel1
127 #else
128   #define LED_D_ALTSEL1_SETUP           port_clear_altsel1
129 #endif
130 #if LED_D_OPENDRAIN
131   #define LED_D_OPENDRAIN_SETUP         port_set_open_drain
132 #else
133   #define LED_D_OPENDRAIN_SETUP         port_clear_open_drain
134 #endif
135
136 #if LED_ST_DIR
137   #define LED_ST_DIR_SETUP              port_set_dir_out
138 #else
139   #define LED_ST_DIR_SETUP              port_clear_dir_out
140 #endif
141 #if LED_ST_ALTSEL0
142   #define LED_ST_ALTSEL0_SETUP          port_set_altsel0
143 #else
144   #define LED_ST_ALTSEL0_SETUP          port_clear_altsel0
145 #endif
146 #if LED_ST_ALTSEL1
147   #define LED_ST_ALTSEL1_SETUP          port_set_altsel1
148 #else
149   #define LED_ST_ALTSEL1_SETUP          port_clear_altsel1
150 #endif
151 #if LED_ST_OPENDRAIN
152   #define LED_ST_OPENDRAIN_SETUP        port_set_open_drain
153 #else
154   #define LED_ST_OPENDRAIN_SETUP        port_clear_open_drain
155 #endif
156
157 #if LED_ADSL0_DIR
158   #define LED_ADSL0_DIR_SETUP           port_set_dir_out
159 #else
160   #define LED_ADSL0_DIR_SETUP           port_clear_dir_out
161 #endif
162 #if LED_ADSL0_ALTSEL0
163   #define LED_ADSL0_ALTSEL0_SETUP       port_set_altsel0
164 #else
165   #define LED_ADSL0_ALTSEL0_SETUP       port_clear_altsel0
166 #endif
167 #if LED_ADSL0_ALTSEL1
168   #define LED_ADSL0_ALTSEL1_SETUP       port_set_altsel1
169 #else
170   #define LED_ADSL0_ALTSEL1_SETUP       port_clear_altsel1
171 #endif
172 #if LED_ADSL0_OPENDRAIN
173   #define LED_ADSL0_OPENDRAIN_SETUP     port_set_open_drain
174 #else
175   #define LED_ADSL0_OPENDRAIN_SETUP     port_clear_open_drain
176 #endif
177
178 #if LED_ADSL1_DIR
179   #define LED_ADSL1_DIR_SETUP           port_set_dir_out
180 #else
181   #define LED_ADSL1_DIR_SETUP           port_clear_dir_out
182 #endif
183 #if LED_ADSL1_ALTSEL0
184   #define LED_ADSL1_ALTSEL0_SETUP       port_set_altsel0
185 #else
186   #define LED_ADSL1_ALTSEL0_SETUP       port_clear_altsel0
187 #endif
188 #if LED_ADSL1_ALTSEL1
189   #define LED_ADSL1_ALTSEL1_SETUP       port_set_altsel1
190 #else
191   #define LED_ADSL1_ALTSEL1_SETUP       port_clear_altsel1
192 #endif
193 #if LED_ADSL1_OPENDRAIN
194   #define LED_ADSL1_OPENDRAIN_SETUP     port_set_open_drain
195 #else
196   #define LED_ADSL1_OPENDRAIN_SETUP     port_clear_open_drain
197 #endif
198
199 #define SET_BITS(x, msb, lsb, value)    (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
200
201 static inline int update_led(void);
202
203 static inline unsigned int set_update_source(unsigned int, unsigned long, unsigned long);
204 static inline unsigned int set_blink_in_batch(unsigned int, unsigned long, unsigned long);
205 static inline unsigned int set_data_clock_edge(unsigned int, unsigned long);
206 static inline unsigned int set_update_clock(unsigned int, unsigned long, unsigned long);
207 static inline unsigned int set_store_mode(unsigned int, unsigned long);
208 static inline unsigned int set_shift_clock(unsigned int, unsigned long);
209 static inline unsigned int set_data_offset(unsigned int, unsigned long);
210 static inline unsigned int set_number_of_enabled_led(unsigned int, unsigned long);
211 static inline unsigned int set_data_in_batch(unsigned int, unsigned long, unsigned long);
212 static inline unsigned int set_access_right(unsigned int, unsigned long, unsigned long);
213
214 static inline void enable_led(void);
215 static inline void disable_led(void);
216
217 static inline int setup_gpio_port(unsigned long);
218 static inline void release_gpio_port(unsigned long);
219
220 static inline int setup_gpt(int, unsigned long);
221 static inline void release_gpt(int);
222
223 static inline int turn_on_led(unsigned long);
224 static inline void turn_off_led(unsigned long);
225
226
227 static struct semaphore led_sem;
228
229 static unsigned long gpt_on = 0;
230 static unsigned long gpt_freq = 0;
231
232 static unsigned long adsl_on = 0;
233 static unsigned long f_led_on = 0;
234
235 static int module_id;
236
237
238 static inline int
239 update_led (void)
240 {
241     int i, j;
242
243     /*
244      *  GPT2 or FPID is the clock to update LEDs automatically.
245      */
246     if (readl(DANUBE_LED_CON1) >> 30)
247         return 0;
248
249     /*
250      *  Check the status to prevent conflict of two consecutive update
251      */
252     for ( i = 100000; i != 0; i -= j / 16 )
253     {
254         down(&led_sem);
255         if (!(readl(DANUBE_LED_CON0) & LED_CON0_SWU))
256         {
257             *DANUBE_LED_CON0 |= 1 << 31;
258             up(&led_sem);
259             return 0;
260         }
261         else
262             up(&led_sem);
263         for ( j = 0; j < 1000 * 16; j++ );
264     }
265
266     return -EBUSY;
267 }
268
269 static inline unsigned int
270 set_update_source (unsigned int reg, unsigned long led, unsigned long source)
271 {
272     return (reg & ~((led & 0x03) << 24)) | ((source & 0x03) << 24);
273 }
274
275 static inline unsigned int
276 set_blink_in_batch (unsigned int reg, unsigned long mask, unsigned long blink)
277 {
278     return (reg & (~(mask & 0x00FFFFFF) & 0x87FFFFFF)) | (blink & 0x00FFFFFF);
279 }
280
281 static inline unsigned int
282 set_data_clock_edge (unsigned int reg, unsigned long f_on_rising_edge)
283 {
284     return f_on_rising_edge ? (reg & ~(1 << 26)) : (reg | (1 << 26));
285 }
286
287 static inline unsigned int
288 set_update_clock (unsigned int reg, unsigned long clock, unsigned long fpid)
289 {
290     switch ( clock )
291     {
292     case 0: reg &= ~0xC0000000; break;
293     case 1: reg = (reg & ~0xC0000000) | 0x40000000; break;
294     case 2: reg = (reg & ~0xCF800000) | 0x80000000 | ((fpid & 0x1F) << 23); break;
295     }
296     return reg;
297 }
298
299 static inline unsigned int
300 set_store_mode (unsigned int reg, unsigned long mode)
301 {
302     return mode ? (reg | (1 << 28)) : (reg & ~(1 << 28));
303 }
304
305 static inline
306 unsigned int set_shift_clock (unsigned int reg, unsigned long fpis)
307 {
308     return SET_BITS(reg, 21, 20, fpis);
309 }
310
311 static inline
312 unsigned int set_data_offset (unsigned int reg, unsigned long offset)
313 {
314     return SET_BITS(reg, 19, 18, offset);
315 }
316
317 static inline
318 unsigned int set_number_of_enabled_led (unsigned int reg, unsigned long number)
319 {
320     unsigned int bit_mask;
321
322     bit_mask = number > 16 ? 0x07 : (number > 8 ? 0x03 : (number ? 0x01 : 0x00));
323     return (reg & ~0x07) | bit_mask;
324 }
325
326 static inline unsigned int
327 set_data_in_batch (unsigned int reg, unsigned long mask, unsigned long data)
328 {
329     return (reg & ~(mask & 0x00FFFFFF)) | (data & 0x00FFFFFF);
330 }
331
332 static inline unsigned int
333 set_access_right (unsigned int reg, unsigned long mask, unsigned long ar)
334 {
335     return (reg & ~(mask & 0x00FFFFFF)) | (~ar & mask);
336 }
337
338 static inline void
339 enable_led (void)
340 {
341     /*  Activate LED module in PMU. */
342     int i = 1000000;
343
344     *(unsigned long *)0xBF10201C &= ~(1 << 11);
345     while ( --i && (*(unsigned long *)0xBF102020 & (1 << 11)) );
346     if ( !i )
347         panic("Activating LED in PMU failed!");
348 }
349
350 static inline void
351 disable_led (void)
352 {
353     *(unsigned long *)0xBF10201C |= 1 << 11;
354 }
355
356 static inline int
357 setup_gpio_port (unsigned long adsl)
358 {
359     int ret = 0;
360
361     /*
362      *  Reserve all pins before config them.
363      */
364     if ( adsl )
365     {
366         ret |= port_reserve_pin(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
367         ret |= port_reserve_pin(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
368     }
369     else
370     {
371         ret |= port_reserve_pin(LED_ST_PORT, LED_ST_PIN, module_id);
372         ret |= port_reserve_pin(LED_D_PORT, LED_D_PIN, module_id);
373         ret |= port_reserve_pin(LED_SH_PORT, LED_SH_PIN, module_id);
374     }
375     if ( ret )
376     {
377         release_gpio_port(adsl);
378         return ret; //  Should be -EBUSY
379     }
380
381     if ( adsl )
382     {
383         LED_ADSL0_ALTSEL0_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
384         LED_ADSL0_ALTSEL1_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
385         LED_ADSL0_DIR_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
386         LED_ADSL0_OPENDRAIN_SETUP(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
387
388         LED_ADSL1_ALTSEL0_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
389         LED_ADSL1_ALTSEL1_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
390         LED_ADSL1_DIR_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
391         LED_ADSL1_OPENDRAIN_SETUP(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
392     }
393     else
394     {
395         /*
396          *  Set LED_ST
397          *    I don't check the return value, because I'm sure the value is valid
398          *    and the pins are reserved already.
399          */
400         LED_ST_ALTSEL0_SETUP(LED_ST_PORT, LED_ST_PIN, module_id);
401         LED_ST_ALTSEL1_SETUP(LED_ST_PORT, LED_ST_PIN, module_id);
402         LED_ST_DIR_SETUP(LED_ST_PORT, LED_ST_PIN, module_id);
403         LED_ST_OPENDRAIN_SETUP(LED_ST_PORT, LED_ST_PIN, module_id);
404
405         /*
406          *  Set LED_D
407          */
408         LED_D_ALTSEL0_SETUP(LED_D_PORT, LED_D_PIN, module_id);
409         LED_D_ALTSEL1_SETUP(LED_D_PORT, LED_D_PIN, module_id);
410         LED_D_DIR_SETUP(LED_D_PORT, LED_D_PIN, module_id);
411         LED_D_OPENDRAIN_SETUP(LED_D_PORT, LED_D_PIN, module_id);
412
413         /*
414          *  Set LED_SH
415          */
416         LED_SH_ALTSEL0_SETUP(LED_SH_PORT, LED_SH_PIN, module_id);
417         LED_SH_ALTSEL1_SETUP(LED_SH_PORT, LED_SH_PIN, module_id);
418         LED_SH_DIR_SETUP(LED_SH_PORT, LED_SH_PIN, module_id);
419         LED_SH_OPENDRAIN_SETUP(LED_SH_PORT, LED_SH_PIN, module_id);
420     }
421
422     return 0;
423 }
424
425 static inline void
426 release_gpio_port (unsigned long adsl)
427 {
428     if ( adsl )
429     {
430         port_free_pin(LED_ADSL0_PORT, LED_ADSL0_PIN, module_id);
431         port_free_pin(LED_ADSL1_PORT, LED_ADSL1_PIN, module_id);
432     }
433     else
434     {
435         port_free_pin(LED_ST_PORT, LED_ST_PIN, module_id);
436         port_free_pin(LED_D_PORT, LED_D_PIN, module_id);
437         port_free_pin(LED_SH_PORT, LED_SH_PIN, module_id);
438     }
439 }
440
441 static inline int
442 setup_gpt (int timer, unsigned long freq)
443 {
444     int ret;
445
446     timer = TIMER(timer, 1);
447
448     ret  = request_timer(timer,
449                            TIMER_FLAG_SYNC
450                          | TIMER_FLAG_16BIT
451                          | TIMER_FLAG_INT_SRC
452                          | TIMER_FLAG_CYCLIC | TIMER_FLAG_COUNTER | TIMER_FLAG_DOWN
453                          | TIMER_FLAG_ANY_EDGE
454                          | TIMER_FLAG_NO_HANDLE,
455                          8000000 / freq,
456                          0,
457                          0);
458
459     if ( !ret )
460     {
461         ret = start_timer(timer, 0);
462         if ( ret )
463             free_timer(timer);
464     }
465
466     return ret;
467 }
468
469 static inline void
470 release_gpt (int timer)
471 {
472     timer = TIMER(timer, 1);
473     stop_timer(timer);
474     free_timer(timer);
475 }
476
477 static inline int
478 turn_on_led (unsigned long adsl)
479 {
480     int ret;
481
482     ret = setup_gpio_port(adsl);
483     if ( ret )
484         return ret;
485
486     enable_led();
487
488     return 0;
489 }
490
491 static inline void
492 turn_off_led (unsigned long adsl)
493 {
494     release_gpio_port(adsl);
495     disable_led();
496 }
497
498
499 int
500 danube_led_set_blink (unsigned int led, unsigned int blink)
501 {
502     unsigned int bit_mask;
503
504     if ( led > 23 )
505         return -EINVAL;
506
507     bit_mask = 1 << led;
508     down(&led_sem);
509     if ( blink )
510         *DANUBE_LED_CON0 |= bit_mask;
511     else
512         *DANUBE_LED_CON0 &= ~bit_mask;
513     up(&led_sem);
514
515     return (led == 0 && (readl(DANUBE_LED_CON0) & LED_CON0_AD0)) || (led == 1 && (readl(DANUBE_LED_CON0) & LED_CON0_AD1)) ? -EINVAL : 0;
516 }
517
518 int
519 danube_led_set_data (unsigned int led, unsigned int data)
520 {
521     unsigned long f_update;
522     unsigned int bit_mask;
523
524     if ( led > 23 )
525         return -EINVAL;
526
527     bit_mask = 1 << led;
528     down(&led_sem);
529     if ( data )
530         *DANUBE_LED_CPU0 |= bit_mask;
531     else
532         *DANUBE_LED_CPU0 &= ~bit_mask;
533     f_update = !(*DANUBE_LED_AR & bit_mask);
534     up(&led_sem);
535
536     return f_update ? update_led() : 0;
537 }
538
539 int
540 danube_led_config (struct led_config_param* param)
541 {
542     int ret;
543     unsigned int reg_con0, reg_con1, reg_cpu0, reg_ar;
544     unsigned int clean_reg_con0, clean_reg_con1, clean_reg_cpu0, clean_reg_ar;
545     unsigned int f_setup_gpt2;
546     unsigned int f_software_update;
547     unsigned int new_led_on, new_adsl_on;
548
549     if ( !param )
550         return -EINVAL;
551
552     down(&led_sem);
553
554     reg_con0 = *DANUBE_LED_CON0;
555     reg_con1 = *DANUBE_LED_CON1;
556     reg_cpu0 = *DANUBE_LED_CPU0;
557     reg_ar   = *DANUBE_LED_AR;
558
559     clean_reg_con0 = 1;
560     clean_reg_con1 = 1;
561     clean_reg_cpu0 = 1;
562     clean_reg_ar   = 1;
563
564     f_setup_gpt2 = 0;
565
566     f_software_update = (readl(DANUBE_LED_CON0) & LED_CON0_SWU) ? 0 : 1;
567
568     new_led_on = f_led_on;
569     new_adsl_on = adsl_on;
570
571     /*  ADSL or LED */
572     if ( (param->operation_mask & CONFIG_OPERATION_UPDATE_SOURCE) )
573     {
574         if ( param->led > 0x03 || param->source > 0x03 )
575             goto INVALID_PARAM;
576         clean_reg_con0 = 0;
577         reg_con0 = set_update_source(reg_con0, param->led, param->source);
578 #if 0   //  ADSL0,1 is source for bit 0, 1 in shift register
579         new_adsl_on = param->source;
580 #endif
581     }
582
583     /*  Blink   */
584     if ( (param->operation_mask & CONFIG_OPERATION_BLINK) )
585     {
586         if ( (param->blink_mask & 0xFF000000) || (param->blink & 0xFF000000) )
587             goto INVALID_PARAM;
588         clean_reg_con0 = 0;
589         reg_con0 = set_blink_in_batch(reg_con0, param->blink_mask, param->blink);
590     }
591
592     /*  Edge    */
593     if ( (param->operation_mask & CONFIG_DATA_CLOCK_EDGE) )
594     {
595         clean_reg_con0 = 0;
596         reg_con0 = set_data_clock_edge(reg_con0, param->f_data_clock_on_rising);
597     }
598
599     /*  Update Clock    */
600     if ( (param->operation_mask & CONFIG_OPERATION_UPDATE_CLOCK) )
601     {
602         if ( param->update_clock > 0x02 || (param->update_clock == 0x02 && param->fpid > 0x3) )
603             goto INVALID_PARAM;
604         clean_reg_con1 = 0;
605         f_software_update = param->update_clock == 0 ? 1 : 0;
606         if ( param->update_clock == 0x01 )
607             f_setup_gpt2 = 1;
608         reg_con1 = set_update_clock(reg_con1, param->update_clock, param->fpid);
609     }
610
611     /*  Store Mode  */
612     if ( (param->operation_mask & CONFIG_OPERATION_STORE_MODE) )
613     {
614         clean_reg_con1 = 0;
615         reg_con1 = set_store_mode(reg_con1, param->store_mode);
616     }
617
618     /*  Shift Clock */
619     if ( (param->operation_mask & CONFIG_OPERATION_SHIFT_CLOCK) )
620     {
621         if ( param->fpis > 0x03 )
622             goto INVALID_PARAM;
623         clean_reg_con1 = 0;
624         reg_con1 = set_shift_clock(reg_con1, param->fpis);
625     }
626
627     /*  Data Offset */
628     if ( (param->operation_mask & CONFIG_OPERATION_DATA_OFFSET) )
629     {
630         if ( param->data_offset > 0x03 )
631             goto INVALID_PARAM;
632         clean_reg_con1 = 0;
633         reg_con1 = set_data_offset(reg_con1, param->data_offset);
634     }
635
636     /*  Number of LED   */
637     if ( (param->operation_mask & CONFIG_OPERATION_NUMBER_OF_LED) )
638     {
639         if ( param->number_of_enabled_led > 0x24 )
640             goto INVALID_PARAM;
641
642         /*
643          *  If there is at lease one LED enabled, the GPIO pin must be setup.
644          */
645         new_led_on = param->number_of_enabled_led ? 1 : 0;
646
647         clean_reg_con1 = 0;
648         reg_con1 = set_number_of_enabled_led(reg_con1, param->number_of_enabled_led);
649     }
650
651     /*  LED Data    */
652     if ( (param->operation_mask & CONFIG_OPERATION_DATA) )
653     {
654         if ( (param->data_mask & 0xFF000000) || (param->data & 0xFF000000) )
655             goto INVALID_PARAM;
656         clean_reg_cpu0 = 0;
657         reg_cpu0 = set_data_in_batch(reg_cpu0, param->data_mask, param->data);
658         if ( f_software_update )
659         {
660             clean_reg_con0 = 0;
661             reg_con0 |= 0x80000000;
662         }
663     }
664
665     /*  Access Right    */
666     if ( (param->operation_mask & CONFIG_OPERATION_MIPS0_ACCESS) )
667     {
668         if ( (param->mips0_access_mask & 0xFF000000) || (param->mips0_access & 0xFF000000) )
669             goto INVALID_PARAM;
670         clean_reg_ar = 0;
671         reg_ar = set_access_right(reg_ar, param->mips0_access_mask, param->mips0_access);
672     }
673
674     /*  Setup GPT   */
675     if ( f_setup_gpt2 && !new_adsl_on )     //  If ADSL led is on, GPT is disabled.
676     {
677         ret = 0;
678
679         if ( gpt_on )
680         {
681             if ( gpt_freq != param->fpid )
682             {
683                 release_gpt(2);
684                 gpt_on = 0;
685                 ret = setup_gpt(2, param->fpid);
686             }
687         }
688         else
689             ret = setup_gpt(2, param->fpid);
690
691         if ( ret )
692         {
693 #if 1
694             printk("Setup GPT error!\n");
695 #endif
696             goto SETUP_GPT_ERROR;
697         }
698         else
699         {
700 #if 0
701             printk("Setup GPT successfully!\n");
702 #endif
703             gpt_on = 1;
704         }
705     }
706     else
707         if ( gpt_on )
708         {
709             release_gpt(2);
710             gpt_on = 0;
711         }
712
713     /*  Turn on LED */
714     if ( new_adsl_on )
715         new_led_on = 1;
716     if ( !new_led_on || adsl_on != new_adsl_on )
717     {
718         turn_off_led(adsl_on);
719         f_led_on = 0;
720         adsl_on = 0;
721     }
722     if ( !f_led_on && new_led_on )
723     {
724         ret = turn_on_led(new_adsl_on);
725         if ( ret )
726         {
727             printk("Setup GPIO error!\n");
728             goto SETUP_GPIO_ERROR;
729         }
730         adsl_on = new_adsl_on;
731         f_led_on = 1;
732     }
733
734     /*  Write Register  */
735     if ( !f_led_on )
736         enable_led();
737     if ( !clean_reg_ar )
738         *DANUBE_LED_AR   = reg_ar;
739     if ( !clean_reg_cpu0 )
740         *DANUBE_LED_CPU0 = reg_cpu0;
741     if ( !clean_reg_con1 )
742         *DANUBE_LED_CON1 = reg_con1;
743     if ( !clean_reg_con0 )
744         *DANUBE_LED_CON0 = reg_con0;
745     if ( !f_led_on )
746         disable_led();
747
748     up(&led_sem);
749     return 0;
750
751 SETUP_GPIO_ERROR:
752     release_gpt(2);
753     gpt_on = 0;
754 SETUP_GPT_ERROR:
755     up(&led_sem);
756     return ret;
757
758 INVALID_PARAM:
759     up(&led_sem);
760     return -EINVAL;
761 }
762
763 static int
764 led_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
765 {
766     int ret = -EINVAL;
767     struct led_config_param param;
768
769     switch ( cmd )
770     {
771     case LED_CONFIG:
772         copy_from_user(&param, (char*)arg, sizeof(param));
773         ret = danube_led_config(&param);
774         break;
775     }
776
777     return ret;
778 }
779
780 static int
781 led_open (struct inode *inode, struct file *file)
782 {
783     return 0;
784 }
785
786 static int
787 led_release (struct inode *inode, struct file *file)
788 {
789     return 0;
790 }
791
792 static struct file_operations led_fops = {
793     owner:      THIS_MODULE,
794     ioctl:      led_ioctl,
795     open:       led_open,
796     release:    led_release
797 };
798
799 static struct miscdevice led_miscdev = {
800     151,
801     "led",
802     &led_fops,
803     NULL,
804     NULL,
805     NULL
806 };
807
808 int __init
809 danube_led_init (void)
810 {
811     int ret;
812     struct led_config_param param = {0};
813
814     enable_led();
815
816     /*
817      *  Set default value to registers to turn off all LED light.
818      */
819     *DANUBE_LED_AR   = 0x0;
820     *DANUBE_LED_CPU0 = 0x0;
821     *DANUBE_LED_CPU1 = 0x0;
822     *DANUBE_LED_CON1 = 0x0;
823     *DANUBE_LED_CON0 = (0x80000000 | (DATA_CLOCKING_EDGE << 26));
824
825     disable_led();
826
827     sema_init(&led_sem, 0);
828
829     ret = misc_register(&led_miscdev);
830     if ( ret == -EBUSY )
831     {
832         led_miscdev.minor = MISC_DYNAMIC_MINOR;
833         ret = misc_register(&led_miscdev);
834     }
835     if ( ret )
836     {
837         printk(KERN_ERR "led: can't misc_register\n");
838         return ret;
839     }
840     else
841         printk(KERN_INFO "led: misc_register on minor = %d\n", led_miscdev.minor);
842
843     module_id = THIS_MODULE ? (int)THIS_MODULE : ((MISC_MAJOR << 8) | led_miscdev.minor);
844
845     up(&led_sem);
846
847     /*  Add to enable hardware relay    */
848         /*  Map for LED on reference board
849               WLAN_READ     LED11   OUT1    15
850               WARNING       LED12   OUT2    14
851               FXS1_LINK     LED13   OUT3    13
852               FXS2_LINK     LED14   OUT4    12
853               FXO_ACT       LED15   OUT5    11
854               USB_LINK      LED16   OUT6    10
855               ADSL2_LINK    LED19   OUT7    9
856               BT_LINK       LED17   OUT8    8
857               SD_LINK       LED20   OUT9    7
858               ADSL2_TRAFFIC LED31   OUT16   0
859             Map for hardware relay on reference board
860               USB Power On          OUT11   5
861               RELAY                 OUT12   4
862         */
863     param.operation_mask = CONFIG_OPERATION_NUMBER_OF_LED;
864     param.number_of_enabled_led = 16;
865     danube_led_config(&param);
866     param.operation_mask = CONFIG_OPERATION_DATA;
867     param.data_mask = 1 << 4;
868     param.data = 1 << 4;
869     danube_led_config(&param);
870
871     //  by default, update by FSC clock (FPID)
872     param.operation_mask = CONFIG_OPERATION_UPDATE_CLOCK;
873     param.update_clock   = 2;   //  FPID
874     param.fpid           = 3;   //  10Hz
875     danube_led_config(&param);
876
877     //  source of LED 0, 1 is ADSL
878     param.operation_mask = CONFIG_OPERATION_UPDATE_SOURCE;
879     param.led            = 3;   //  LED 0, 1
880     param.source         = 3;   //  ADSL
881     danube_led_config(&param);
882
883     //  turn on USB
884     param.operation_mask = CONFIG_OPERATION_DATA;
885     param.data_mask = 1 << 5;
886     param.data = 1 << 5;
887     danube_led_config(&param);
888
889     return 0;
890 }
891
892 void __exit
893 danube_led_exit (void)
894 {
895     int ret;
896
897     ret = misc_deregister(&led_miscdev);
898     if ( ret )
899         printk(KERN_ERR "led: can't misc_deregister, get error number %d\n", -ret);
900     else
901         printk(KERN_INFO "led: misc_deregister successfully\n");
902 }
903
904 EXPORT_SYMBOL(danube_led_set_blink);
905 EXPORT_SYMBOL(danube_led_set_data);
906 EXPORT_SYMBOL(danube_led_config);
907
908 module_init(danube_led_init);
909 module_exit(danube_led_exit);
910