Merge with /home/git/u-boot
[platform/kernel/u-boot.git] / drivers / status_led.c
1 /*
2  * (C) Copyright 2000-2003
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23
24 #include <common.h>
25 #include <status_led.h>
26
27 /*
28  * The purpose of this code is to signal the operational status of a
29  * target which usually boots over the network; while running in
30  * U-Boot, a status LED is blinking. As soon as a valid BOOTP reply
31  * message has been received, the LED is turned off. The Linux
32  * kernel, once it is running, will start blinking the LED again,
33  * with another frequency.
34  */
35
36 /* ------------------------------------------------------------------------- */
37
38 #ifdef CONFIG_STATUS_LED
39
40 typedef struct {
41         led_id_t mask;
42         int state;
43         int period;
44         int cnt;
45 } led_dev_t;
46
47 led_dev_t led_dev[] = {
48     {   STATUS_LED_BIT,
49         STATUS_LED_STATE,
50         STATUS_LED_PERIOD,
51         0,
52     },
53 #if defined(STATUS_LED_BIT1)
54     {   STATUS_LED_BIT1,
55         STATUS_LED_STATE1,
56         STATUS_LED_PERIOD1,
57         0,
58     },
59 #endif
60 #if defined(STATUS_LED_BIT2)
61     {   STATUS_LED_BIT2,
62         STATUS_LED_STATE2,
63         STATUS_LED_PERIOD2,
64         0,
65     },
66 #endif
67 #if defined(STATUS_LED_BIT3)
68     {   STATUS_LED_BIT3,
69         STATUS_LED_STATE3,
70         STATUS_LED_PERIOD3,
71         0,
72     },
73 #endif
74 };
75
76 #define MAX_LED_DEV     (sizeof(led_dev)/sizeof(led_dev_t))
77
78 static int status_led_init_done = 0;
79
80 static void status_led_init (void)
81 {
82         led_dev_t *ld;
83         int i;
84
85         for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++)
86                 __led_init (ld->mask, ld->state);
87         status_led_init_done = 1;
88 }
89
90 void status_led_tick (ulong timestamp)
91 {
92         led_dev_t *ld;
93         int i;
94
95         if (!status_led_init_done)
96                 status_led_init ();
97
98         for (i = 0, ld = led_dev; i < MAX_LED_DEV; i++, ld++) {
99
100                 if (ld->state != STATUS_LED_BLINKING)
101                         continue;
102
103                 if (++ld->cnt >= ld->period) {
104                         __led_toggle (ld->mask);
105                         ld->cnt -= ld->period;
106                 }
107
108         }
109 }
110
111 void status_led_set (int led, int state)
112 {
113         led_dev_t *ld;
114
115         if (led < 0 || led >= MAX_LED_DEV)
116                 return;
117
118         if (!status_led_init_done)
119                 status_led_init ();
120
121         ld = &led_dev[led];
122
123         ld->state = state;
124         if (state == STATUS_LED_BLINKING) {
125                 ld->cnt = 0;            /* always start with full period    */
126                 state = STATUS_LED_ON;  /* always start with LED _ON_       */
127         }
128         __led_set (ld->mask, state);
129 }
130
131 #endif  /* CONFIG_STATUS_LED */