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