blob: 0174e39916e73e3b5d35ccebdf489627ccfe8b76 [file] [log] [blame]
wdenke3093092002-10-01 01:07:28 +00001/*
2 * (C) Copyright 2000
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 * PCBoot, 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
40typedef struct {
41 ulong mask;
42 int state;
43 int period;
44 int cnt;
45} led_dev_t;
46
47led_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};
68
69#define MAX_LED_DEV (sizeof(led_dev)/sizeof(led_dev_t))
70
71static int status_led_init_done = 0;
72
73static void status_led_init (void)
74{
75 volatile immap_t *immr = (immap_t *)CFG_IMMR;
76 int i;
77
78 for (i=0; i<MAX_LED_DEV; ++i) {
79 led_dev_t *ld = &led_dev[i];
80
81 immr->STATUS_LED_PAR &= ~(ld->mask);
82#ifdef STATUS_LED_ODR
83 immr->STATUS_LED_ODR &= ~(ld->mask);
84#endif
85#if (STATUS_LED_ACTIVE == 0)
86 if (ld->state == STATUS_LED_ON)
87 immr->STATUS_LED_DAT &= ~(ld->mask);
88 else
89 immr->STATUS_LED_DAT |= ld->mask ;
90#else
91 if (ld->state == STATUS_LED_ON)
92 immr->STATUS_LED_DAT |= ld->mask ;
93 else
94 immr->STATUS_LED_DAT &= ~(ld->mask);
95#endif
96 immr->STATUS_LED_DIR |= ld->mask ;
97 }
98
99 status_led_init_done = 1;
100}
101
102void status_led_tick (ulong timestamp)
103{
104 volatile immap_t *immr = (immap_t *)CFG_IMMR;
105 int i;
106
107 if (!status_led_init_done)
108 status_led_init();
109
110 for (i=0; i<MAX_LED_DEV; ++i) {
111 led_dev_t *ld = &led_dev[i];
112
113 if (ld->state != STATUS_LED_BLINKING)
114 continue;
115
116 if (++(ld->cnt) >= ld->period) {
117 immr->STATUS_LED_DAT ^= ld->mask;
118 ld->cnt -= ld->period;
119 }
120 }
121}
122
123void status_led_set (int led, int state)
124{
125 volatile immap_t *immr = (immap_t *)CFG_IMMR;
126 led_dev_t *ld;
127
128 if (led < 0 || led >= MAX_LED_DEV)
129 return;
130
131 if (!status_led_init_done)
132 status_led_init();
133
134 ld = &led_dev[led];
135
136 switch (state) {
137 default:
138 return;
139 case STATUS_LED_BLINKING:
140 ld->cnt = 0; /* always start with full period */
141 /* fall through */ /* always start with LED _ON_ */
142 case STATUS_LED_ON:
143#if (STATUS_LED_ACTIVE == 0)
144 immr->STATUS_LED_DAT &= ~(ld->mask);
145#else
146 immr->STATUS_LED_DAT |= ld->mask ;
147#endif
148 break;
149 case STATUS_LED_OFF:
150#if (STATUS_LED_ACTIVE == 0)
151 immr->STATUS_LED_DAT |= ld->mask ;
152#else
153 immr->STATUS_LED_DAT &= ~(ld->mask);
154#endif
155 break;
156 }
157 ld->state = state;
158}
159
160#endif /* CONFIG_STATUS_LED */