3 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
5 * SPDX-License-Identifier: GPL-2.0+
14 * This test performs the system hardware monitoring.
15 * The test passes when all the following voltages and temperatures
16 * are within allowed ranges:
26 * CCFL is not enabled if temperature values are not within allowed ranges
28 * See the list off all parameters in the sysmon_table below
35 #if CONFIG_POST & CONFIG_SYS_POST_SYSMON
37 DECLARE_GLOBAL_DATA_PTR
;
39 static int sysmon_temp_invalid
= 0;
43 typedef struct sysmon_s sysmon_t
;
44 typedef struct sysmon_table_s sysmon_table_t
;
46 static void sysmon_lm87_init (sysmon_t
* this);
47 static void sysmon_pic_init (sysmon_t
* this);
48 static uint
sysmon_i2c_read (sysmon_t
* this, uint addr
);
49 static uint
sysmon_i2c_read_sgn (sysmon_t
* this, uint addr
);
50 static void sysmon_ccfl_disable (sysmon_table_t
* this);
51 static void sysmon_ccfl_enable (sysmon_table_t
* this);
56 void (*init
)(sysmon_t
*);
57 uint (*read
)(sysmon_t
*, uint
);
60 static sysmon_t sysmon_lm87
=
61 {CONFIG_SYS_I2C_SYSMON_ADDR
, sysmon_lm87_init
, sysmon_i2c_read
};
62 static sysmon_t sysmon_lm87_sgn
=
63 {CONFIG_SYS_I2C_SYSMON_ADDR
, sysmon_lm87_init
, sysmon_i2c_read_sgn
};
64 static sysmon_t sysmon_pic
=
65 {CONFIG_SYS_I2C_PICIO_ADDR
, sysmon_pic_init
, sysmon_i2c_read
};
67 static sysmon_t
* sysmon_list
[] =
80 void (*exec_before
)(sysmon_table_t
*);
81 void (*exec_after
)(sysmon_table_t
*);
97 static sysmon_table_t sysmon_table
[] =
99 {"Board temperature", " C", &sysmon_lm87_sgn
, NULL
, sysmon_ccfl_disable
,
100 1, 1, -128, 127, 0xFF, 0x58, 0xD5, 0, 0x6C, 0xC6, 0, 0x27},
102 {"Front temperature", " C", &sysmon_lm87
, NULL
, sysmon_ccfl_disable
,
103 1, 100, -27316, 8984, 0xFF, 0xA4, 0xFC, 0, 0xB2, 0xF1, 0, 0x29},
105 {"+3.3V CPU logic", "V", &sysmon_lm87
, NULL
, NULL
,
106 100, 1000, 0, 4386, 0xFF, 0xB6, 0xC9, 0, 0xB6, 0xC9, 0, 0x22},
108 {"+ 5 V logic", "V", &sysmon_lm87
, NULL
, NULL
,
109 100, 1000, 0, 6630, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x23},
111 {"+12 V PCMCIA", "V", &sysmon_lm87
, NULL
, NULL
,
112 100, 1000, 0, 15460, 0xFF, 0xBC, 0xD0, 0, 0xBC, 0xD0, 0, 0x21},
114 {"+12 V CCFL", "V", &sysmon_lm87
, NULL
, sysmon_ccfl_enable
,
115 100, 1000, 0, 15900, 0xFF, 0xB6, 0xCA, 0, 0xB6, 0xCA, 0, 0x24},
117 {"+ 5 V standby", "V", &sysmon_pic
, NULL
, NULL
,
118 100, 1000, 0, 6040, 0xFF, 0xC8, 0xDE, 0, 0xC8, 0xDE, 0, 0x7C},
120 static int sysmon_table_size
= ARRAY_SIZE(sysmon_table
);
122 static int conversion_done
= 0;
125 int sysmon_init_f (void)
130 /* Power on CCFL, PCMCIA */
131 reg
= pic_read (0x60);
133 pic_write (0x60, reg
);
135 for (l
= sysmon_list
; *l
; l
++) {
142 void sysmon_reloc (void)
144 /* Do nothing for now, sysmon_reloc() is required by the sysmon post */
147 static char *sysmon_unit_value (sysmon_table_t
*s
, uint val
)
151 s
->unit_min
+ (s
->unit_max
- s
->unit_min
) * val
/ s
->val_mask
;
161 unit_val
= -unit_val
;
166 p
= buf
+ sprintf(buf
, "%c%2d", sign
, unit_val
/ s
->unit_div
);
169 frac
= unit_val
% s
->unit_div
;
171 frac
/= (s
->unit_div
/ s
->unit_precision
);
173 dec
= s
->unit_precision
;
178 for (dec
/= 10; dec
!= 0; dec
/= 10) {
179 *p
++ = '0' + (frac
/ dec
) % 10;
181 strcpy(p
, s
->unit_name
);
186 static void sysmon_lm87_init (sysmon_t
* this)
190 /* Detect LM87 chip */
191 if (i2c_read(this->chip
, 0x40, 1, &val
, 1) || (val
& 0x80) != 0 ||
192 i2c_read(this->chip
, 0x3E, 1, &val
, 1) || val
!= 0x02) {
193 printf("Error: LM87 not found at 0x%02X\n", this->chip
);
197 /* Configure pins 5,6 as AIN */
199 if (i2c_write(this->chip
, 0x16, 1, &val
, 1)) {
200 printf("Error: can't write LM87 config register\n");
204 /* Start monitoring */
206 if (i2c_write(this->chip
, 0x40, 1, &val
, 1)) {
207 printf("Error: can't write LM87 config register\n");
212 static void sysmon_pic_init (sysmon_t
* this)
216 static uint
sysmon_i2c_read (sysmon_t
* this, uint addr
)
219 uint res
= i2c_read(this->chip
, addr
, 1, &val
, 1);
221 return res
== 0 ? val
: -1;
224 static uint
sysmon_i2c_read_sgn (sysmon_t
* this, uint addr
)
227 return i2c_read(this->chip
, addr
, 1, &val
, 1) == 0 ?
228 128 + (signed char)val
: -1;
231 static void sysmon_ccfl_disable (sysmon_table_t
* this)
233 if (!this->val_valid_alt
) {
234 sysmon_temp_invalid
= 1;
238 static void sysmon_ccfl_enable (sysmon_table_t
* this)
242 if (!sysmon_temp_invalid
) {
243 reg
= pic_read (0x60);
245 pic_write (0x60, reg
);
249 int sysmon_post_test (int flags
)
256 * The A/D conversion on the LM87 sensor takes 300 ms.
258 if (! conversion_done
) {
259 while (post_time_ms(gd
->post_init_f_time
) < 300) WATCHDOG_RESET ();
263 for (t
= sysmon_table
; t
< sysmon_table
+ sysmon_table_size
; t
++) {
264 if (t
->exec_before
) {
268 val
= t
->sysmon
->read(t
->sysmon
, t
->addr
);
270 t
->val_valid
= val
>= t
->val_min
&& val
<= t
->val_max
;
271 t
->val_valid_alt
= val
>= t
->val_min_alt
&& val
<= t
->val_max_alt
;
274 t
->val_valid_alt
= 0;
281 if ((!t
->val_valid
) || (flags
& POST_MANUAL
)) {
282 printf("%-17s = %-10s ", t
->name
, sysmon_unit_value(t
, val
));
283 printf("allowed range");
284 printf(" %-8s ..", sysmon_unit_value(t
, t
->val_min
));
285 printf(" %-8s", sysmon_unit_value(t
, t
->val_max
));
286 printf(" %s\n", t
->val_valid
? "OK" : "FAIL");
297 #endif /* CONFIG_POST & CONFIG_SYS_POST_SYSMON */