blob: d8aaeec55d5b399f527ad7e4b2855e3f9205d00a [file] [log] [blame]
wdenk6a30c4c2002-08-21 21:22:07 +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 <mpc8xx.h>
26#include <status_led.h>
27
28/*
29 * The purpose of this code is to signal the operational status of a
30 * target which usually boots over the network; while running in
31 * PCBoot, a status LED is blinking. As soon as a valid BOOTP reply
32 * message has been received, the LED is turned off. The Linux
33 * kernel, once it is running, will start blinking the LED again,
34 * with another frequency.
35 */
36
37/* ------------------------------------------------------------------------- */
38
39#ifdef CONFIG_STATUS_LED
40
41typedef struct {
42 ulong mask;
43 int state;
44 int period;
45 int cnt;
46} led_dev_t;
47
48led_dev_t led_dev[] = {
49 { STATUS_LED_BIT,
50 STATUS_LED_STATE,
51 STATUS_LED_PERIOD,
52 0,
53 },
54#if defined(STATUS_LED_BIT1)
55 { STATUS_LED_BIT1,
56 STATUS_LED_STATE1,
57 STATUS_LED_PERIOD1,
58 0,
59 },
60#endif
61#if defined(STATUS_LED_BIT2)
62 { STATUS_LED_BIT2,
63 STATUS_LED_STATE2,
64 STATUS_LED_PERIOD2,
65 0,
66 },
67#endif
68#if defined(STATUS_LED_BIT3)
69 { STATUS_LED_BIT3,
70 STATUS_LED_STATE3,
71 STATUS_LED_PERIOD3,
72 0,
73 },
74#endif
75};
76
77#define MAX_LED_DEV (sizeof(led_dev)/sizeof(led_dev_t))
78
79static int status_led_init_done = 0;
80
81static void status_led_init (void)
82{
83 volatile immap_t *immr = (immap_t *)CFG_IMMR;
84 int i;
85
86 for (i=0; i<MAX_LED_DEV; ++i) {
87 led_dev_t *ld = &led_dev[i];
88
89 immr->STATUS_LED_PAR &= ~(ld->mask);
90#ifdef STATUS_LED_ODR
91 immr->STATUS_LED_ODR &= ~(ld->mask);
92#endif
93#if (STATUS_LED_ACTIVE == 0)
94 if (ld->state == STATUS_LED_ON)
95 immr->STATUS_LED_DAT &= ~(ld->mask);
96 else
97 immr->STATUS_LED_DAT |= ld->mask ;
98#else
99 if (ld->state == STATUS_LED_ON)
100 immr->STATUS_LED_DAT |= ld->mask ;
101 else
102 immr->STATUS_LED_DAT &= ~(ld->mask);
103#endif
104 immr->STATUS_LED_DIR |= ld->mask ;
105 }
106
107 status_led_init_done = 1;
108}
109
110void status_led_tick (ulong timestamp)
111{
112 volatile immap_t *immr = (immap_t *)CFG_IMMR;
113 int i;
114
115 if (!status_led_init_done)
116 status_led_init();
117
118 for (i=0; i<MAX_LED_DEV; ++i) {
119 led_dev_t *ld = &led_dev[i];
120
121 if (ld->state != STATUS_LED_BLINKING)
122 continue;
123
124 if (++(ld->cnt) >= ld->period) {
125 immr->STATUS_LED_DAT ^= ld->mask;
126 ld->cnt -= ld->period;
127 }
128 }
129}
130
131void status_led_set (int led, int state)
132{
133 volatile immap_t *immr = (immap_t *)CFG_IMMR;
134 led_dev_t *ld;
135
136 if (led < 0 || led >= MAX_LED_DEV)
137 return;
138
139 if (!status_led_init_done)
140 status_led_init();
141
142 ld = &led_dev[led];
143
144 switch (state) {
145 default:
146 return;
147 case STATUS_LED_BLINKING:
148 ld->cnt = 0; /* always start with full period */
149 /* fall through */ /* always start with LED _ON_ */
150 case STATUS_LED_ON:
151#if (STATUS_LED_ACTIVE == 0)
152 immr->STATUS_LED_DAT &= ~(ld->mask);
153#else
154 immr->STATUS_LED_DAT |= ld->mask ;
155#endif
156 break;
157 case STATUS_LED_OFF:
158#if (STATUS_LED_ACTIVE == 0)
159 immr->STATUS_LED_DAT |= ld->mask ;
160#else
161 immr->STATUS_LED_DAT &= ~(ld->mask);
162#endif
163 break;
164 }
165 ld->state = state;
166}
167
168#endif /* CONFIG_STATUS_LED */