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