blob: 02d5f6f32af8db777951c235912c6d930723c1cc [file] [log] [blame]
Yuri Tikhonovc147d482008-02-04 14:10:42 +01001/*
2 * (C) Copyright 2008 Dmitry Rakhchev, EmCraft Systems, rda@emcraft.com
3 *
4 * Developed for DENX Software Engineering GmbH
5 *
6 * See file CREDITS for list of people who contributed to this
7 * project.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of
12 * the License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 * MA 02111-1307 USA
23 */
24
25#include <post.h>
26#include <common.h>
27
Yuri Tikhonovc147d482008-02-04 14:10:42 +010028/*
29 * SYSMON test
30 *
31 * This test performs the system hardware monitoring.
32 * The test passes when all the following voltages and temperatures
33 * are within allowed ranges:
34 *
Wolfgang Denk7f39a012008-04-26 00:34:42 +020035 * Temperature -40 .. +85 C
36 * +5V +4.75 .. +5.25 V
37 * +5V standby +4.75 .. +5.25 V
Yuri Tikhonovc147d482008-02-04 14:10:42 +010038 *
39 * LCD backlight is not enabled if temperature values are not within
40 * allowed ranges (-30 .. + 80). The brightness of backlite can be
41 * controlled by setting "brightness" enviroment variable. Default value is 50%
42 *
43 * See the list of all parameters in the sysmon_table below
44 */
45
46#include <post.h>
47#include <watchdog.h>
48#include <i2c.h>
49
Yuri Tikhonov7151a342008-03-18 13:27:57 +010050#if defined(CONFIG_VIDEO)
51#include <mb862xx.h>
52#endif
53
Yuri Tikhonovc147d482008-02-04 14:10:42 +010054#if CONFIG_POST & CFG_POST_SYSMON
55
56DECLARE_GLOBAL_DATA_PTR;
57
Yuri Tikhonovc147d482008-02-04 14:10:42 +010058/* from dspic.c */
59extern int dspic_read(ushort reg);
Yuri Tikhonovc147d482008-02-04 14:10:42 +010060
61#define RELOC(x) if (x != NULL) x = (void *) ((ulong) (x) + gd->reloc_off)
62
63typedef struct sysmon_s sysmon_t;
64typedef struct sysmon_table_s sysmon_table_t;
65
66static void sysmon_dspic_init (sysmon_t * this);
67static int sysmon_dspic_read (sysmon_t * this, uint addr);
68static void sysmon_backlight_disable (sysmon_table_t * this);
Yuri Tikhonovc147d482008-02-04 14:10:42 +010069
70struct sysmon_s
71{
72 uchar chip;
73 void (*init)(sysmon_t *);
74 int (*read)(sysmon_t *, uint);
75};
76
77static sysmon_t sysmon_dspic =
78 {CFG_I2C_DSPIC_IO_ADDR, sysmon_dspic_init, sysmon_dspic_read};
79
80static sysmon_t * sysmon_list[] =
81{
82 &sysmon_dspic,
83 NULL
84};
85
86struct sysmon_table_s
87{
88 char * name;
89 char * unit_name;
90 sysmon_t * sysmon;
91 void (*exec_before)(sysmon_table_t *);
92 void (*exec_after)(sysmon_table_t *);
93
94 int unit_precision;
95 int unit_div;
96 int unit_min;
97 int unit_max;
98 uint val_mask;
99 uint val_min;
100 uint val_max;
101 int val_valid;
102 uint val_min_alt;
103 uint val_max_alt;
104 int val_valid_alt;
105 uint addr;
106};
107
108static sysmon_table_t sysmon_table[] =
109{
Wolfgang Denk7f39a012008-04-26 00:34:42 +0200110 {"Temperature", " C", &sysmon_dspic, NULL, sysmon_backlight_disable,
111 1, 1, -32768, 32767, 0xFFFF, 0x8000-40, 0x8000+85, 0,
112 0x8000-30, 0x8000+80, 0, 0x12BC},
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100113
Wolfgang Denk7f39a012008-04-26 00:34:42 +0200114 {"+ 5 V", "V", &sysmon_dspic, NULL, NULL,
115 100, 1000, -0x8000, 0x7FFF, 0xFFFF, 0x8000+4750, 0x8000+5250, 0,
116 0x8000+4750, 0x8000+5250, 0, 0x12CA},
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100117
Wolfgang Denk7f39a012008-04-26 00:34:42 +0200118 {"+ 5 V standby", "V", &sysmon_dspic, NULL, NULL,
119 100, 1000, -0x8000, 0x7FFF, 0xFFFF, 0x8000+4750, 0x8000+5250, 0,
120 0x8000+4750, 0x8000+5250, 0, 0x12C6},
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100121};
122static int sysmon_table_size = sizeof(sysmon_table) / sizeof(sysmon_table[0]);
123
124int sysmon_init_f (void)
125{
126 sysmon_t ** l;
127
128 for (l = sysmon_list; *l; l++)
129 (*l)->init(*l);
130
131 return 0;
132}
133
134void sysmon_reloc (void)
135{
136 sysmon_t ** l;
137 sysmon_table_t * t;
138
139 for (l = sysmon_list; *l; l++) {
140 RELOC(*l);
141 RELOC((*l)->init);
142 RELOC((*l)->read);
143 }
144
145 for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
146 RELOC(t->exec_before);
147 RELOC(t->exec_after);
148 RELOC(t->sysmon);
149 }
150}
151
152static char *sysmon_unit_value (sysmon_table_t *s, uint val)
153{
154 static char buf[32];
155 char *p, sign;
156 int decimal, frac;
157 int unit_val;
158
Wolfgang Denk7f39a012008-04-26 00:34:42 +0200159 unit_val = s->unit_min + (s->unit_max - s->unit_min) * val / s->val_mask;
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100160
161 if (val == -1)
162 return "I/O ERROR";
163
164 if (unit_val < 0) {
165 sign = '-';
166 unit_val = -unit_val;
167 } else
168 sign = '+';
169
170 p = buf + sprintf(buf, "%c%2d", sign, unit_val / s->unit_div);
171
172
173 frac = unit_val % s->unit_div;
174
175 frac /= (s->unit_div / s->unit_precision);
176
177 decimal = s->unit_precision;
178
179 if (decimal != 1)
180 *p++ = '.';
181 for (decimal /= 10; decimal != 0; decimal /= 10)
182 *p++ = '0' + (frac / decimal) % 10;
183 strcpy(p, s->unit_name);
184
185 return buf;
186}
187
188static void sysmon_dspic_init (sysmon_t * this)
189{
190}
191
192static int sysmon_dspic_read (sysmon_t * this, uint addr)
193{
194 int res = dspic_read(addr);
195
196 /* To fit into the table range we should add 0x8000 */
197 return (res == -1) ? -1 : (res + 0x8000);
198}
199
200static void sysmon_backlight_disable (sysmon_table_t * this)
201{
Yuri Tikhonov7151a342008-03-18 13:27:57 +0100202#if defined(CONFIG_VIDEO)
203 board_backlight_switch(this->val_valid_alt);
204#endif
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100205}
206
207int sysmon_post_test (int flags)
208{
209 int res = 0;
210 sysmon_table_t * t;
211 int val;
212
213 for (t = sysmon_table; t < sysmon_table + sysmon_table_size; t ++) {
214 if (t->exec_before)
215 t->exec_before(t);
216
217 val = t->sysmon->read(t->sysmon, t->addr);
218 if (val != -1) {
219 t->val_valid = val >= t->val_min && val <= t->val_max;
220 t->val_valid_alt = val >= t->val_min_alt && val <= t->val_max_alt;
221 } else {
222 t->val_valid = 0;
223 t->val_valid_alt = 0;
224 }
225
226 if (t->exec_after)
227 t->exec_after(t);
228
229 if ((!t->val_valid) || (flags & POST_MANUAL)) {
230 printf("%-17s = %-10s ", t->name, sysmon_unit_value(t, val));
231 printf("allowed range");
232 printf(" %-8s ..", sysmon_unit_value(t, t->val_min));
233 printf(" %-8s", sysmon_unit_value(t, t->val_max));
234 printf(" %s\n", t->val_valid ? "OK" : "FAIL");
235 }
236
237 if (!t->val_valid)
238 res = 1;
239 }
240
241 return res;
242}
Yuri Tikhonovc147d482008-02-04 14:10:42 +0100243#endif /* CONFIG_POST & CFG_POST_SYSMON */