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