eb7d63d024ba0d96fe686f4db0449d5edfba5f3b
[openwrt/staging/mkresin.git] / openwrt / target / linux / linux-2.4 / patches / ar7 / 002-led_driver.patch
1 diff -urN linux.old/drivers/char/avalanche_led/ledmod.c linux.dev/drivers/char/avalanche_led/ledmod.c
2 --- linux.old/drivers/char/avalanche_led/ledmod.c 1970-01-01 01:00:00.000000000 +0100
3 +++ linux.dev/drivers/char/avalanche_led/ledmod.c 2005-07-11 03:16:48.247012224 +0200
4 @@ -0,0 +1,719 @@
5 +#include <linux/config.h>
6 +#include <linux/init.h>
7 +#include <linux/kernel.h>
8 +#include <linux/proc_fs.h>
9 +#include <asm/uaccess.h>
10 +#include <linux/fs.h>
11 +#include <linux/timer.h>
12 +#include <linux/delay.h>
13 +#include <linux/spinlock.h>
14 +#include <asm/ar7/avalanche_regs.h>
15 +#include <asm/ar7/ledapp.h>
16 +#include <linux/module.h>
17 +
18 +#define LED_ON 1
19 +#define LED_OFF 2
20 +#define LED_BLINK 3
21 +#define LED_FLASH 4
22 +
23 +#define LED_BLINK_UP 5
24 +#define LED_BLINK_DOWN 6
25 +
26 +typedef struct state_entry {
27 + unsigned char mode;
28 + unsigned char led;
29 + void (*handler) (struct state_entry * pState);
30 + unsigned long param;
31 +} state_entry_t;
32 +
33 +typedef struct mod_entry {
34 + state_entry_t *states[MAX_STATE_ID];
35 +} mod_entry_t;
36 +
37 +static mod_entry_t *modArr[MAX_MOD_ID];
38 +static struct proc_dir_entry *led_proc_dir, *led_file;
39 +
40 +/* index of the array is the led number HARDWARE SPECIFIC*/
41 +typedef struct led_data {
42 + led_reg_t *led;
43 + int state;
44 + struct timer_list *pTimer;
45 + unsigned char timer_running;
46 + unsigned long param;
47 +} led_data_t;
48 +
49 +led_data_t led_arr[MAX_LED_ID + 1];
50 +/*!!! The last device is actually being used for ar7 reset to factory default */
51 +#if 1
52 +/* Ron add for adsl LED blink */
53 +#define GPIO_ADSL_ACT (1<<6)
54 +#define GPIO_ADSL_DOWN (1<<8)
55 +#define BLINK_FAST 5*HZ/100
56 +#define BLINK_SLOW 15*HZ/100
57 +static struct timer_list my_led_timer;
58 +static int my_blink_count = 0;
59 +static int my_mode = 1;
60 +void led_operation(int mod, int state);
61 +
62 +static void my_led_on(unsigned long gpio, int logic)
63 +{
64 + if (logic > 0)
65 + GPIO_DATA_OUTPUT |= gpio;
66 + else
67 + GPIO_DATA_OUTPUT &= ~gpio;
68 +
69 +}
70 +static void my_led_off(unsigned long gpio, int logic)
71 +{
72 + if (logic > 0)
73 + GPIO_DATA_OUTPUT &= ~gpio;
74 + else
75 + GPIO_DATA_OUTPUT |= gpio;
76 +
77 +}
78 +
79 +static void my_led_init(unsigned long gpio, int init, int logic)
80 +{
81 + GPIO_DATA_ENABLE |= gpio;
82 + GPIO_DATA_DIR &= ~gpio;
83 + if (init)
84 + my_led_on(gpio, logic);
85 + else
86 + my_led_off(gpio, logic);
87 +}
88 +
89 +static void my_led_blink_timer(unsigned long data)
90 +{
91 + unsigned long gpio = GPIO_ADSL_ACT;
92 + unsigned int speed = BLINK_FAST;
93 + if (my_mode == 2) {
94 + gpio = GPIO_ADSL_DOWN;
95 + speed = BLINK_SLOW;
96 + }
97 + if (my_blink_count) {
98 + if (GPIO_DATA_OUTPUT & gpio) {
99 + GPIO_DATA_OUTPUT &= ~gpio;
100 + if (my_mode != 2)
101 + my_blink_count = 0;
102 + } else {
103 + GPIO_DATA_OUTPUT |= gpio;
104 + }
105 + }
106 + my_led_timer.expires = jiffies + speed;
107 + add_timer(&my_led_timer);
108 +}
109 +
110 +/* Ron add for ADSL led blink */
111 +#endif
112 +static spinlock_t config_lock;
113 +
114 +static void board_led_link_up(state_entry_t * pState);
115 +static void board_led_link_down(state_entry_t * pState);
116 +static void board_led_activity_on(state_entry_t * pState);
117 +static void board_led_activity_off(state_entry_t * pState);
118 +static void led_timer_func(unsigned long data);
119 +
120 +static ssize_t proc_read_led_fops(struct file *filp, char *buf, size_t count, loff_t * offp);
121 +static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp);
122 +static int config_led(unsigned long y);
123 +
124 +struct file_operations led_fops = {
125 + read:proc_read_led_fops,
126 + write:proc_write_led_fops,
127 +};
128 +
129 +static int led_atoi(char *name)
130 +{
131 + int val = 0;
132 + for (;; name++) {
133 + switch (*name) {
134 + case '0'...'9':
135 + val = val * 10 + (*name - '0');
136 + break;
137 + default:
138 + return val;
139 + }
140 + }
141 +}
142 +
143 +static int free_memory(void)
144 +{
145 + int i, j;
146 +
147 + for (i = 0; i < MAX_MOD_ID; i++) {
148 + if (modArr[i] != NULL) {
149 + for (j = 0; j < MAX_STATE_ID; j++) {
150 + if (modArr[i]->states[j] != NULL)
151 + kfree(modArr[i]->states[j]);
152 + }
153 + kfree(modArr[i]);
154 + modArr[i] = NULL;
155 + }
156 + }
157 + return 0;
158 +}
159 +
160 +static int led_on(state_entry_t * pState)
161 +{
162 + if (led_arr[pState->led].led == NULL)
163 + return -1;
164 + led_arr[pState->led].led->onfunc(led_arr[pState->led].led->param);
165 + return 0;
166 +}
167 +
168 +static int led_off(state_entry_t * pState)
169 +{
170 + if (led_arr[pState->led].led == NULL)
171 + return -1;
172 + led_arr[pState->led].led->offfunc(led_arr[pState->led].led->param);
173 + return 0;
174 +}
175 +
176 +static void board_led_link_up(state_entry_t * pState)
177 +{
178 + led_arr[pState->led].state = LED_ON;
179 + if (led_arr[pState->led].timer_running == 0)
180 + led_on(pState);
181 + return;
182 +}
183 +
184 +static void board_led_link_down(state_entry_t * pState)
185 +{
186 + led_arr[pState->led].state = LED_OFF;
187 + if (led_arr[pState->led].timer_running == 0)
188 + led_off(pState);
189 + return;
190 +}
191 +
192 +static void add_led_timer(state_entry_t * pState)
193 +{
194 + led_arr[pState->led].pTimer->expires =
195 + jiffies + HZ * (pState->param) / 1000;
196 + led_arr[pState->led].param = pState->param;
197 + led_arr[pState->led].pTimer->data = pState;
198 + add_timer(led_arr[pState->led].pTimer);
199 +}
200 +
201 +static void board_led_activity_on(state_entry_t * pState)
202 +{
203 + if (led_arr[pState->led].timer_running == 0) {
204 + led_on(pState);
205 + add_led_timer(pState);
206 + led_arr[pState->led].timer_running = 1;
207 + led_arr[pState->led].state = LED_BLINK_UP;
208 + } else if (led_arr[pState->led].timer_running > 0xF0) {
209 + led_arr[pState->led].state = LED_BLINK_UP;
210 + led_arr[pState->led].pTimer->expires =
211 + jiffies + HZ * (pState->param) / 1000;
212 + led_arr[pState->led].param = pState->param;
213 + led_arr[pState->led].pTimer->data = pState;
214 + }
215 + return;
216 +}
217 +
218 +static void board_led_activity_off(state_entry_t * pState)
219 +{
220 + if (led_arr[pState->led].timer_running == 0) {
221 + led_off(pState);
222 + add_led_timer(pState);
223 + led_arr[pState->led].timer_running = 1;
224 + led_arr[pState->led].state = LED_BLINK_UP;
225 + } else if (led_arr[pState->led].timer_running > 0xF0) {
226 + led_arr[pState->led].state = LED_BLINK_UP;
227 + led_arr[pState->led].pTimer->expires =
228 + jiffies + HZ * (pState->param) / 1000;
229 + led_arr[pState->led].param = pState->param;
230 + led_arr[pState->led].pTimer->data = pState;
231 + }
232 + return;
233 +}
234 +
235 +static void board_led_link_flash(state_entry_t * pState)
236 +{
237 + if (led_on(pState))
238 + return;
239 + if (led_arr[pState->led].timer_running == 0)
240 + add_led_timer(pState);
241 + else
242 + led_arr[pState->led].param = pState->param;
243 + led_arr[pState->led].timer_running = 0xFF;
244 + led_arr[pState->led].state = LED_FLASH;
245 + return;
246 +}
247 +
248 +static void led_timer_func(unsigned long data)
249 +{
250 + state_entry_t *pState = NULL;
251 + mod_entry_t *pMod = NULL;
252 + unsigned int flags;
253 +
254 + spin_lock_irqsave(&config_lock, flags);
255 +
256 + pState = (state_entry_t *) data;
257 +
258 + if (led_arr[pState->led].state == LED_BLINK_DOWN) {
259 + led_arr[pState->led].timer_running = 0;
260 + if (pState->mode == 2)
261 + led_arr[pState->led].state = LED_OFF;
262 + else
263 + led_arr[pState->led].state = LED_ON;
264 + } else if (led_arr[pState->led].state == LED_BLINK_UP) {
265 + led_arr[pState->led].pTimer->expires =
266 + jiffies + HZ * (led_arr[pState->led].param) / 1000;
267 + led_arr[pState->led].pTimer->data = pState;
268 + add_timer(led_arr[pState->led].pTimer);
269 + if (pState->mode == 2) {
270 + led_off(pState);
271 + led_arr[pState->led].state = LED_BLINK_DOWN;
272 + } else {
273 + led_on(pState);
274 + led_arr[pState->led].state = LED_BLINK_DOWN;
275 + }
276 + led_arr[pState->led].timer_running = 1;
277 + } else if (led_arr[pState->led].state == LED_FLASH) {
278 + led_arr[pState->led].pTimer->expires =
279 + jiffies + HZ * (led_arr[pState->led].param) / 1000;
280 + led_arr[pState->led].pTimer->data = pState;
281 + add_timer(led_arr[pState->led].pTimer);
282 +
283 + if (led_arr[pState->led].timer_running == 0xFF) {
284 + led_off(pState);
285 + led_arr[pState->led].timer_running--;
286 + } else {
287 + led_on(pState);
288 + led_arr[pState->led].timer_running++;
289 + }
290 + spin_unlock_irqrestore(&config_lock, flags);
291 + return;
292 + } else if (led_arr[pState->led].state == LED_OFF) {
293 + led_off(pState);
294 + led_arr[pState->led].timer_running = 0;
295 + } else if (led_arr[pState->led].state == LED_ON) {
296 + led_on(pState);
297 + led_arr[pState->led].timer_running = 0;
298 + }
299 + spin_unlock_irqrestore(&config_lock, flags);
300 + return;
301 +}
302 +
303 +static ssize_t proc_read_led_fops(struct file *filp,
304 + char *buf, size_t count, loff_t * offp)
305 +{
306 + char *pdata = NULL;
307 + int i = 0, j = 0, len = 0, totallen = 0;
308 + char line[255];
309 +
310 + if (*offp != 0)
311 + return 0;
312 +
313 + pdata = buf;
314 + len += sprintf(line, "LEDS Registered for use are:");
315 + for (i = 0; i < MAX_LED_ID; i++)
316 + if (led_arr[i].led != NULL)
317 + len += sprintf(&line[len], " %d ", i);
318 + line[len++] = '\n';
319 +
320 + copy_to_user(pdata, line, len);
321 + pdata += len;
322 + totallen += len;
323 + len = 0;
324 + len = sprintf(line, "USER MODULE INFORMATION:\n");
325 + copy_to_user(pdata, line, len);
326 + pdata += len;
327 + totallen += len;
328 + len = 0;
329 + for (i = 0; i < MAX_MOD_ID; i++) {
330 + if (modArr[i] != NULL) {
331 + len = sprintf(line, " Module ID = %d \n", i);
332 + copy_to_user(pdata, line, len);
333 + pdata += len;
334 + totallen += len;
335 + len = 0;
336 + for (j = 0; j < MAX_STATE_ID; j++) {
337 + if (modArr[i]->states[j] != NULL) {
338 + len = sprintf(line, " State = %d , Led = %d,", j,
339 + modArr[i]->states[j]->led);
340 + copy_to_user(pdata, line, len);
341 + pdata += len;
342 + totallen += len;
343 +
344 + len = 0;
345 + switch (modArr[i]->states[j]->mode) {
346 + case 1:
347 + len = sprintf(line, " Mode = OFF\n");
348 + break;
349 + case 2:
350 + len = sprintf(line, " Mode = BLINK_ON , On Time(ms) = %d\n",
351 + (unsigned int) modArr[i]->states[j]->
352 + param);
353 + break;
354 + case 3:
355 + len = sprintf(line, " Mode = BLINK_OFF , Off Time(ms) = %d\n",
356 + (unsigned int) modArr[i]->states[j]->
357 + param);
358 + break;
359 + case 4:
360 + len = sprintf(line, " Mode = ON \n");
361 + break;
362 + case 5:
363 + len = sprintf(line, " Mode = FLASH , Time Period(ms) = %d\n",
364 + (unsigned int) modArr[i]->states[j]->
365 + param);
366 + break;
367 + default:
368 + break;
369 +
370 + }
371 + copy_to_user(pdata, line, len);
372 + pdata += len;
373 + totallen += len;
374 +
375 + len = 0;
376 + }
377 + }
378 + }
379 + }
380 + /* Return with configuration information for LEDs */
381 + *offp = totallen;
382 + return totallen;
383 +}
384 +
385 +static ssize_t proc_write_led_fops(struct file *filp, const char *buffer, size_t count, loff_t * offp)
386 +{
387 + char *pdata = NULL, *ptemp = NULL;
388 + char line[10], temp[10];
389 + int i = 0;
390 + int mod = 0xFFFF, state = 0xFFFF;
391 + int flag = 0;
392 +
393 + /* Check if this write is for configuring stuff */
394 + if (*(int *) (buffer) == 0xFFEEDDCC) {
395 + printk("<1>proc write:Calling Configuration\n");
396 + config_led((unsigned long) (buffer + sizeof(int)));
397 + return count;
398 + }
399 +
400 + if (count >= 10) {
401 + printk("<1>proc write:Input too long,max length = %d\n", 10);
402 + return count;
403 + }
404 + memset(temp, 0x00, 10);
405 + memset(line, 0x00, 10);
406 + copy_from_user(line, buffer, count);
407 + line[count] = 0x00;
408 + pdata = line;
409 + ptemp = temp;
410 + while (flag == 0) {
411 + if (i > 10)
412 + break;
413 + if (((*pdata) >= '0') && ((*pdata) <= '9')) {
414 + *ptemp = *pdata;
415 + ptemp++;
416 + } else if ((*pdata) == ',') {
417 + *ptemp = 0x00;
418 + flag = 1;
419 + }
420 + pdata++;
421 + i++;
422 + };
423 + if (flag == 1)
424 + mod = led_atoi(temp);
425 + else
426 + return count;
427 +
428 + ptemp = temp;
429 + *ptemp = 0x00;
430 + flag = 0;
431 + while (flag == 0) {
432 + if (i > 10)
433 + break;
434 + if (((*pdata) >= '0') && ((*pdata) <= '9')) {
435 + *ptemp = *pdata;
436 + ptemp++;
437 + } else if ((*pdata) == 0x00) {
438 + *ptemp = 0x00;
439 + flag = 1;
440 + }
441 + pdata++;
442 + i++;
443 + };
444 + if (flag == 1)
445 + state = led_atoi(temp);
446 + else
447 + return count;
448 + if ((mod == 0xFFFF) || (state == 0xFFFF))
449 + return count;
450 + else
451 + led_operation(mod, state);
452 + return count;
453 +}
454 +
455 +static int config_led(unsigned long y)
456 +{
457 + config_elem_t *pcfg = NULL;
458 + char *pdata = NULL;
459 + int i;
460 + int length = 0, number = 0;
461 + unsigned int flags;
462 +
463 + spin_lock_irqsave(&config_lock, flags);
464 +
465 + /* ioctl to configure */
466 + length = *((int *) y);
467 + pdata = (char *) y + sizeof(int);
468 + number = (length - sizeof(int)) / sizeof(config_elem_t);
469 + pcfg = (config_elem_t *) (pdata);
470 +
471 + /* Check if an earlier configuration exists IF yes free it up */
472 + free_memory();
473 +
474 + for (i = 0; i < number; i++) {
475 + /* If no structure has been allocated for the module do so */
476 + if (modArr[pcfg->name] == NULL) {
477 + printk("<1>module = %d\n", pcfg->name);
478 + if (pcfg->name >= MAX_MOD_ID) {
479 + printk
480 + ("<1>Exiting Configuration: Module ID too large %d\n",
481 + pcfg->name);
482 + free_memory();
483 + spin_unlock_irqrestore(&config_lock, flags);
484 + return -1;
485 + }
486 + modArr[pcfg->name] = kmalloc(sizeof(mod_entry_t), GFP_KERNEL);
487 + if (modArr[pcfg->name] == NULL) {
488 + printk
489 + ("<1>Exiting Configuration: Error in allocating memory\n");
490 + free_memory();
491 + spin_unlock_irqrestore(&config_lock, flags);
492 + return -1;
493 + }
494 + memset(modArr[pcfg->name], 0x00, sizeof(mod_entry_t));
495 + }
496 +
497 + /* if no structure is allocated previously for this state
498 + allocate a structure, if it's already there fill it up */
499 + if (modArr[pcfg->name]->states[pcfg->state] == NULL) {
500 + printk("<1>STATE = %d\n", pcfg->state);
501 + if (pcfg->state >= MAX_STATE_ID) {
502 + printk("<1>Exiting Configuration: State ID too large\n");
503 + free_memory();
504 + spin_unlock_irqrestore(&config_lock, flags);
505 + return -1;
506 + }
507 + modArr[pcfg->name]->states[pcfg->state] =
508 + kmalloc(sizeof(state_entry_t), GFP_KERNEL);
509 + if (modArr[pcfg->name]->states[pcfg->state] == NULL) {
510 + free_memory();
511 + spin_unlock_irqrestore(&config_lock, flags);
512 + return -1;
513 + }
514 + memset(modArr[pcfg->name]->states[pcfg->state], 0x00,
515 + sizeof(state_entry_t));
516 + }
517 + /* Fill up the fields of the state */
518 + if (pcfg->led >= MAX_LED_ID) {
519 + printk("<1>led = %d\n", pcfg->led);
520 + free_memory();
521 + spin_unlock_irqrestore(&config_lock, flags);
522 + return -1;
523 + }
524 + modArr[pcfg->name]->states[pcfg->state]->led = pcfg->led;
525 + modArr[pcfg->name]->states[pcfg->state]->mode = pcfg->mode;
526 + modArr[pcfg->name]->states[pcfg->state]->param = pcfg->param;
527 + switch (pcfg->mode) {
528 + case 1:
529 + modArr[pcfg->name]->states[pcfg->state]->handler =
530 + board_led_link_down;
531 + break;
532 + case 2:
533 + case 3:
534 + case 5:
535 + if (pcfg->mode == 2)
536 + modArr[pcfg->name]->states[pcfg->state]->handler =
537 + board_led_activity_on;
538 + else if (pcfg->mode == 3)
539 + modArr[pcfg->name]->states[pcfg->state]->handler =
540 + board_led_activity_off;
541 + else
542 + modArr[pcfg->name]->states[pcfg->state]->handler =
543 + board_led_link_flash;
544 + break;
545 + case 4:
546 + modArr[pcfg->name]->states[pcfg->state]->handler =
547 + board_led_link_up;
548 + break;
549 + default:
550 + printk("<1>Exiting Configuration: Unknown LED Mode\n");
551 + free_memory();
552 + spin_unlock_irqrestore(&config_lock, flags);
553 + return -1;
554 + }
555 + pcfg++;
556 + }
557 + spin_unlock_irqrestore(&config_lock, flags);
558 + return 0;
559 +}
560 +
561 +
562 +int __init led_init(void)
563 +{
564 +
565 + /* Clear our memory */
566 + memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID);
567 + memset(led_arr, 0x00, sizeof(led_data_t *) * MAX_LED_ID);
568 +
569 + /* Create spin lock for config data structure */
570 + config_lock = SPIN_LOCK_UNLOCKED;
571 +
572 +#if 0
573 + /* Create directory */
574 + led_proc_dir = proc_mkdir("led_mod", NULL);
575 + if (led_proc_dir == NULL)
576 + goto out;
577 +#endif
578 +
579 + /* Create adsl file */
580 + led_file = create_proc_entry("led", 0777, NULL);
581 + if (led_file == NULL)
582 + goto led_file;
583 +
584 + led_file->owner = THIS_MODULE;
585 + led_file->proc_fops = &led_fops;
586 +
587 + memset(modArr, 0x00, sizeof(mod_entry_t *) * MAX_MOD_ID);
588 +
589 + /* Ron add for ADSL LED blink */
590 + my_mode = 1;
591 + my_led_init(GPIO_ADSL_ACT, 0, -1);
592 + my_led_init(GPIO_ADSL_DOWN, 0, -1);
593 + init_timer(&my_led_timer);
594 + my_led_timer.function = my_led_blink_timer;
595 + my_led_timer.data = 0;
596 + my_led_timer.expires = jiffies + BLINK_SLOW;
597 + add_timer(&my_led_timer);
598 + /* Ron add for ADSL LED blink */
599 + return 0;
600 +
601 + led_file:
602 + remove_proc_entry("led", NULL);
603 + out:
604 + return 0;
605 +
606 +}
607 +
608 +void led_exit(void)
609 +{
610 + remove_proc_entry("led", NULL);
611 +}
612 +
613 +void led_operation(int mod, int state)
614 +{
615 +
616 + unsigned int flags;
617 +
618 + spin_lock_irqsave(&config_lock, flags);
619 +#if 1
620 + /* Ron Add for ADSL LED blink */
621 + //printk("mod==%d state==%d\n",mod,state);
622 +
623 + if (mod == 1) {
624 + switch (state) {
625 + /* off */
626 + case 1:
627 + my_mode = 1;
628 + my_blink_count = 0;
629 + my_led_off(GPIO_ADSL_ACT, -1);
630 + my_led_off(GPIO_ADSL_DOWN, -1);
631 + break;
632 + /* sync */
633 + case 2:
634 + if (my_mode == 1) {
635 + my_mode = 2;
636 + my_led_off(GPIO_ADSL_ACT, -1);
637 + my_blink_count++;
638 + }
639 + break;
640 + /* on */
641 + case 3:
642 + my_mode = 3;
643 + my_blink_count = 0;
644 + my_led_off(GPIO_ADSL_DOWN, -1);
645 + my_led_on(GPIO_ADSL_ACT, -1);
646 + break;
647 + /* off */
648 + case 4:
649 + my_mode = 4;
650 + my_led_off(GPIO_ADSL_DOWN, -1);
651 + my_blink_count++;
652 + break;
653 + }
654 + } /* Ron add for ADSL LED Blink */
655 +#endif
656 + if ((mod >= MAX_MOD_ID) || (state >= MAX_STATE_ID)) {
657 + spin_unlock_irqrestore(&config_lock, flags);
658 + return;
659 + }
660 + if (modArr[mod] == NULL) {
661 + spin_unlock_irqrestore(&config_lock, flags);
662 + return;
663 + }
664 + if (modArr[mod]->states[state] == NULL) {
665 + spin_unlock_irqrestore(&config_lock, flags);
666 + return;
667 + }
668 + /* Call the function handler */
669 + modArr[mod]->states[state]->handler(modArr[mod]->states[state]);
670 +
671 + spin_unlock_irqrestore(&config_lock, flags);
672 +}
673 +
674 +void register_led_drv(int device, led_reg_t * pInfo)
675 +{
676 + unsigned int flags;
677 + struct timer_list *pTimer = NULL;
678 +
679 + spin_lock_irqsave(&config_lock, flags);
680 +
681 + led_arr[device].led = pInfo;
682 + if (led_arr[device].led->init != 0x00)
683 + led_arr[device].led->init(led_arr[device].led->param);
684 + if (led_arr[device].led->offfunc != 0x00)
685 + led_arr[device].led->offfunc(led_arr[device].led->param);
686 +
687 + /* Create a timer for blinking */
688 + pTimer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
689 + init_timer(pTimer);
690 + pTimer->function = led_timer_func;
691 + pTimer->data = 0;
692 + led_arr[device].pTimer = pTimer;
693 + led_arr[device].timer_running = 0;
694 +
695 + spin_unlock_irqrestore(&config_lock, flags);
696 +
697 + return;
698 +}
699 +
700 +void deregister_led_drv(int device)
701 +{
702 + unsigned int flags;
703 +
704 + spin_lock_irqsave(&config_lock, flags);
705 + led_arr[device].led = NULL;
706 +
707 + if (led_arr[device].pTimer != NULL) {
708 + del_timer(led_arr[device].pTimer);
709 + kfree(led_arr[device].pTimer);
710 + }
711 + spin_unlock_irqrestore(&config_lock, flags);
712 +
713 + return;
714 +}
715 +
716 +module_init(led_init);
717 +module_exit(led_exit);
718 +
719 +
720 +EXPORT_SYMBOL_NOVERS(led_init);
721 +EXPORT_SYMBOL_NOVERS(led_operation);
722 +EXPORT_SYMBOL_NOVERS(register_led_drv);
723 +EXPORT_SYMBOL_NOVERS(deregister_led_drv);
724 diff -urN linux.old/drivers/char/avalanche_led/Makefile linux.dev/drivers/char/avalanche_led/Makefile
725 --- linux.old/drivers/char/avalanche_led/Makefile 1970-01-01 01:00:00.000000000 +0100
726 +++ linux.dev/drivers/char/avalanche_led/Makefile 2005-07-11 02:42:24.191796312 +0200
727 @@ -0,0 +1,23 @@
728 +# File: drivers/char/avalanche_led/Makefile
729 +#
730 +# Makefile for the Linux LED device driver.
731 +#
732 +
733 +
734 +O_TARGET := avalanche_led.o
735 +obj-m := avalanche_led.o
736 +list-multi := avalanche_led.o
737 +
738 +EXTRA_CFLAGS := -I$(TOPDIR)/include/asm/ar7
739 +
740 +export-objs := ledmod.o
741 +
742 +avalanche_led-objs := ledmod.o
743 +
744 +include $(TOPDIR)/Rules.make
745 +
746 +avalanche_led.o: $(avalanche_led-objs)
747 + $(LD) -r -o $@ $(avalanche_led-objs)
748 +
749 +clean:
750 + rm -f core *.o *.a *.s
751 diff -urN linux.old/drivers/char/Config.in linux.dev/drivers/char/Config.in
752 --- linux.old/drivers/char/Config.in 2005-07-10 20:53:55.650624032 +0200
753 +++ linux.dev/drivers/char/Config.in 2005-07-10 20:50:43.556826000 +0200
754 @@ -133,6 +133,10 @@
755 fi
756 fi
757 fi
758 +if [ "$CONFIG_AR7" = "y" ]; then
759 + bool 'Enable LED support' CONFIG_MIPS_AVALANCHE_LED
760 +fi
761 +
762 if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_ZORRO" = "y" ]; then
763 tristate 'Commodore A2232 serial support (EXPERIMENTAL)' CONFIG_A2232
764 fi
765 diff -urN linux.old/drivers/char/Makefile linux.dev/drivers/char/Makefile
766 --- linux.old/drivers/char/Makefile 2005-07-10 20:53:55.651623880 +0200
767 +++ linux.dev/drivers/char/Makefile 2005-07-10 20:50:43.556826000 +0200
768 @@ -190,6 +190,19 @@
769 obj-$(CONFIG_PCI) += keyboard.o $(KEYMAP)
770 endif
771
772 +#
773 +# Texas Intruments LED driver
774 +#
775 +ifeq ($(CONFIG_MIPS_AVALANCHE_LED),y)
776 +obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
777 +subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
778 +endif
779 +
780 +ifeq ($(CONFIG_MIPS_AVALANCHE_LED),m)
781 +obj-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led/avalanche_led.o
782 +subdir-$(CONFIG_MIPS_AVALANCHE_LED) += avalanche_led
783 +endif
784 +
785 obj-$(CONFIG_HIL) += hp_keyb.o
786 obj-$(CONFIG_MAGIC_SYSRQ) += sysrq.o
787 obj-$(CONFIG_ATARI_DSP56K) += dsp56k.o
788 diff -urN linux.old/include/asm-mips/ar7/ledapp.h linux.dev/include/asm-mips/ar7/ledapp.h
789 --- linux.old/include/asm-mips/ar7/ledapp.h 1970-01-01 01:00:00.000000000 +0100
790 +++ linux.dev/include/asm-mips/ar7/ledapp.h 2005-07-10 20:50:43.557826000 +0200
791 @@ -0,0 +1,59 @@
792 +#ifndef __LED_APP__
793 +#define __LED_APP__
794 +
795 +#define CONF_FILE "/etc/led.conf"
796 +#define LED_PROC_FILE "/proc/led_mod/led"
797 +
798 +#define CONFIG_LED_MODULE
799 +
800 +#define MAX_MOD_ID 25
801 +#define MAX_STATE_ID 25
802 +#define MAX_LED_ID 25
803 +
804 +#define MOD_ADSL 1
805 +#define DEF_ADSL_IDLE 1
806 +#define DEF_ADSL_TRAINING 2
807 +#define DEF_ADSL_SYNC 3
808 +#define DEF_ADSL_ACTIVITY 4
809 +
810 +#define MOD_WAN 2
811 +#define DEF_WAN_IDLE 1
812 +#define DEF_WAN_NEGOTIATE 2
813 +#define DEF_WAN_SESSION 3
814 +
815 +#define MOD_LAN 3
816 +#define DEF_LAN_IDLE 1
817 +#define DEF_LAN_LINK_UP 2
818 +#define DEF_LAN_ACTIVITY 3
819 +
820 +#define MOD_WLAN 4
821 +#define DEF_WLAN_IDLE 1
822 +#define DEF_WLAN_LINK_UP 2
823 +#define DEF_WLAN_ACTIVITY 3
824 +
825 +#define MOD_USB 5
826 +#define DEF_USB_IDLE 1
827 +#define DEF_USB_LINK_UP 2
828 +#define DEF_USB_ACTIVITY 3
829 +
830 +#define MOD_ETH 6
831 +#define DEF_ETH_IDLE 1
832 +#define DEF_ETH_LINK_UP 2
833 +#define DEF_ETH_ACTIVITY 3
834 +
835 +typedef struct config_elem{
836 + unsigned char name;
837 + unsigned char state;
838 + unsigned char mode;
839 + unsigned char led;
840 + int param;
841 +}config_elem_t;
842 +
843 +typedef struct led_reg{
844 + unsigned int param;
845 + void (*init)(unsigned long param);
846 + void (*onfunc)(unsigned long param);
847 + void (*offfunc)(unsigned long param);
848 +}led_reg_t;
849 +
850 +#endif