]>
Commit | Line | Data |
---|---|---|
4f7cb08e WD |
1 | /* |
2 | * (C) Copyright 2003 | |
3 | * Martin Krause, TQ-Systems GmbH, [email protected]. | |
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 | ||
a0ff7f2e WD |
24 | #undef DEBUG |
25 | ||
4f7cb08e WD |
26 | #include <common.h> |
27 | #include <command.h> | |
28 | #include <s3c2400.h> | |
151ab83a | 29 | #include <rtc.h> |
4f7cb08e WD |
30 | |
31 | /* | |
32 | * TRAB board specific commands. Especially commands for burn-in and function | |
33 | * test. | |
34 | */ | |
35 | #if (CONFIG_COMMANDS & CFG_CMD_BSP) | |
36 | ||
37 | /* limits for valid range of VCC5V in mV */ | |
38 | #define VCC5V_MIN 4500 | |
39 | #define VCC5V_MAX 5500 | |
40 | ||
41 | /* | |
42 | * Test strings for EEPROM test. Length of string 2 must not exceed length of | |
43 | * string 1. Otherwise a buffer overrun could occur! | |
44 | */ | |
45 | #define EEPROM_TEST_STRING_1 "0987654321 :tset a si siht" | |
46 | #define EEPROM_TEST_STRING_2 "this is a test: 1234567890" | |
47 | ||
48 | /* | |
49 | * min/max limits for valid contact temperature during burn in test (in | |
50 | * degree Centigrade * 100) | |
51 | */ | |
52 | #define MIN_CONTACT_TEMP -1000 | |
53 | #define MAX_CONTACT_TEMP +9000 | |
54 | ||
55 | /* blinking frequency of status LED */ | |
56 | #define LED_BLINK_FREQ 5 | |
57 | ||
58 | /* delay time between burn in cycles in seconds */ | |
59 | #ifndef BURN_IN_CYCLE_DELAY /* if not defined in include/configs/trab.h */ | |
60 | #define BURN_IN_CYCLE_DELAY 5 | |
61 | #endif | |
62 | ||
63 | /* physical SRAM parameters */ | |
64 | #define SRAM_ADDR 0x02000000 /* GCS1 */ | |
65 | #define SRAM_SIZE 0x40000 /* 256 kByte */ | |
66 | ||
67 | /* CPLD-Register for controlling TRAB hardware functions */ | |
68 | #define CPLD_BUTTONS ((volatile unsigned long *)0x04020000) | |
69 | #define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000) | |
70 | #define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000) | |
71 | #define CPLD_RS485_RE ((volatile unsigned long *)0x04028000) | |
72 | ||
73 | /* I2C EEPROM device address */ | |
74 | #define I2C_EEPROM_DEV_ADDR 0x54 | |
75 | ||
76 | /* EEPROM address map */ | |
a0ff7f2e | 77 | #define EE_ADDR_TEST 192 |
4f7cb08e WD |
78 | #define EE_ADDR_MAX_CYCLES 256 |
79 | #define EE_ADDR_STATUS 258 | |
80 | #define EE_ADDR_PASS_CYCLES 259 | |
81 | #define EE_ADDR_FIRST_ERROR_CYCLE 261 | |
82 | #define EE_ADDR_FIRST_ERROR_NUM 263 | |
83 | #define EE_ADDR_FIRST_ERROR_NAME 264 | |
84 | #define EE_ADDR_ACT_CYCLE 280 | |
85 | ||
86 | /* Bit definitions for ADCCON */ | |
87 | #define ADC_ENABLE_START 0x1 | |
88 | #define ADC_READ_START 0x2 | |
89 | #define ADC_STDBM 0x4 | |
90 | #define ADC_INP_AIN0 (0x0 << 3) | |
91 | #define ADC_INP_AIN1 (0x1 << 3) | |
92 | #define ADC_INP_AIN2 (0x2 << 3) | |
93 | #define ADC_INP_AIN3 (0x3 << 3) | |
94 | #define ADC_INP_AIN4 (0x4 << 3) | |
95 | #define ADC_INP_AIN5 (0x5 << 3) | |
96 | #define ADC_INP_AIN6 (0x6 << 3) | |
97 | #define ADC_INP_AIN7 (0x7 << 3) | |
98 | #define ADC_PRSCEN 0x4000 | |
99 | #define ADC_ECFLG 0x800 | |
100 | ||
101 | /* misc */ | |
102 | ||
103 | /* externals */ | |
104 | extern int memory_post_tests (unsigned long start, unsigned long size); | |
105 | extern int i2c_write (uchar, uint, int , uchar* , int); | |
106 | extern int i2c_read (uchar, uint, int , uchar* , int); | |
107 | extern void tsc2000_reg_init (void); | |
108 | extern s32 tsc2000_contact_temp (void); | |
109 | extern void spi_init(void); | |
110 | ||
111 | /* function declarations */ | |
112 | int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
113 | int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
114 | int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
115 | int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
116 | int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); | |
f54ebdfa WD |
117 | int i2c_write_multiple (uchar chip, uint addr, int alen, |
118 | uchar *buffer, int len); | |
119 | int i2c_read_multiple (uchar chip, uint addr, int alen, | |
120 | uchar *buffer, int len); | |
151ab83a | 121 | int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); |
4f7cb08e WD |
122 | |
123 | /* helper functions */ | |
124 | static void adc_init (void); | |
125 | static int adc_read (unsigned int channel); | |
126 | static int read_dip (void); | |
127 | static int read_vcc5v (void); | |
128 | static int test_dip (void); | |
129 | static int test_vcc5v (void); | |
130 | static int test_rotary_switch (void); | |
131 | static int test_sram (void); | |
132 | static int test_eeprom (void); | |
133 | static int test_contact_temp (void); | |
4f7cb08e WD |
134 | static void led_set (unsigned int); |
135 | static void led_blink (void); | |
136 | static void led_init (void); | |
137 | static void sdelay (unsigned long seconds); /* delay in seconds */ | |
138 | static int dummy (void); | |
139 | static int read_max_cycles(void); | |
140 | static void test_function_table_init (void); | |
141 | static void global_vars_init (void); | |
142 | static int global_vars_write_to_eeprom (void); | |
143 | ||
144 | /* globals */ | |
145 | u16 max_cycles; | |
146 | u8 status; | |
147 | u16 pass_cycles; | |
148 | u16 first_error_cycle; | |
149 | u8 first_error_num; | |
150 | unsigned char first_error_name[16]; | |
151 | u16 act_cycle; | |
152 | ||
153 | typedef struct test_function_s { | |
154 | unsigned char *name; | |
a0ff7f2e | 155 | int (*pf)(void); |
4f7cb08e WD |
156 | } test_function_t; |
157 | ||
158 | /* max number of Burn In Functions */ | |
159 | #define BIF_MAX 6 | |
160 | ||
161 | /* table with burn in functions */ | |
162 | test_function_t test_function[BIF_MAX]; | |
163 | ||
164 | ||
165 | int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
166 | { | |
a0ff7f2e WD |
167 | int i; |
168 | int cycle_status; | |
4f7cb08e | 169 | |
a0ff7f2e | 170 | if (argc > 1) { |
4f7cb08e WD |
171 | printf ("Usage:\n%s\n", cmdtp->usage); |
172 | return 1; | |
173 | } | |
174 | ||
a0ff7f2e WD |
175 | led_init (); |
176 | global_vars_init (); | |
177 | test_function_table_init (); | |
151ab83a | 178 | spi_init (); |
a0ff7f2e WD |
179 | |
180 | if (global_vars_write_to_eeprom () != 0) { | |
181 | printf ("%s: error writing global_vars to eeprom\n", | |
182 | __FUNCTION__); | |
183 | return (1); | |
184 | } | |
185 | ||
186 | if (read_max_cycles () != 0) { | |
187 | printf ("%s: error reading max_cycles from eeprom\n", | |
188 | __FUNCTION__); | |
189 | return (1); | |
190 | } | |
191 | ||
192 | if (max_cycles == 0) { | |
193 | printf ("%s: error, burn in max_cycles = 0\n", __FUNCTION__); | |
194 | return (1); | |
195 | } | |
196 | ||
197 | status = 0; | |
198 | for (act_cycle = 1; act_cycle <= max_cycles; act_cycle++) { | |
199 | ||
200 | cycle_status = 0; | |
201 | ||
202 | /* | |
203 | * avoid timestamp overflow problem after about 68 minutes of | |
204 | * udelay() time. | |
205 | */ | |
206 | reset_timer_masked (); | |
207 | for (i = 0; i < BIF_MAX; i++) { | |
208 | ||
209 | /* call test function */ | |
210 | if ((*test_function[i].pf)() != 0) { | |
211 | printf ("error in %s test\n", | |
212 | test_function[i].name); | |
213 | ||
214 | /* is it the first error? */ | |
215 | if (status == 0) { | |
216 | status = 1; | |
217 | first_error_cycle = act_cycle; | |
218 | ||
219 | /* do not use error_num 0 */ | |
220 | first_error_num = i+1; | |
221 | strncpy (first_error_name, | |
222 | test_function[i].name, | |
223 | sizeof (first_error_name)); | |
224 | led_set (0); | |
225 | } | |
226 | cycle_status = 1; | |
227 | } | |
228 | } | |
229 | /* were all tests of actual cycle OK? */ | |
230 | if (cycle_status == 0) | |
231 | pass_cycles++; | |
232 | ||
233 | /* set status LED if no error is occoured since yet */ | |
234 | if (status == 0) | |
235 | led_set (1); | |
236 | ||
237 | printf ("%s: cycle %d finished\n", __FUNCTION__, act_cycle); | |
238 | ||
239 | /* pause between cycles */ | |
240 | sdelay (BURN_IN_CYCLE_DELAY); | |
241 | } | |
242 | ||
243 | if (global_vars_write_to_eeprom () != 0) { | |
244 | led_set (0); | |
245 | printf ("%s: error writing global_vars to eeprom\n", | |
246 | __FUNCTION__); | |
247 | status = 1; | |
248 | } | |
249 | ||
250 | if (status == 0) { | |
251 | led_blink (); /* endless loop!! */ | |
252 | return (0); | |
253 | } else { | |
254 | led_set (0); | |
255 | return (1); | |
256 | } | |
4f7cb08e WD |
257 | } |
258 | ||
259 | U_BOOT_CMD( | |
a0ff7f2e WD |
260 | burn_in, 1, 1, do_burn_in, |
261 | "burn_in - start burn-in test application on TRAB\n", | |
262 | "\n" | |
263 | " - start burn-in test application\n" | |
264 | " The burn-in test could took a while to finish!\n" | |
265 | " The content of the onboard EEPROM is modified!\n" | |
4f7cb08e WD |
266 | ); |
267 | ||
268 | ||
269 | int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
270 | { | |
a0ff7f2e | 271 | int i, dip; |
4f7cb08e | 272 | |
a0ff7f2e | 273 | if (argc > 1) { |
4f7cb08e WD |
274 | printf ("Usage:\n%s\n", cmdtp->usage); |
275 | return 1; | |
276 | } | |
277 | ||
a0ff7f2e WD |
278 | if ((dip = read_dip ()) == -1) { |
279 | return 1; | |
280 | } | |
4f7cb08e | 281 | |
a0ff7f2e WD |
282 | for (i = 0; i < 4; i++) { |
283 | if ((dip & (1 << i)) == 0) | |
284 | printf("0"); | |
285 | else | |
286 | printf("1"); | |
287 | } | |
288 | printf("\n"); | |
4f7cb08e WD |
289 | |
290 | return 0; | |
291 | } | |
292 | ||
293 | U_BOOT_CMD( | |
a0ff7f2e WD |
294 | dip, 1, 1, do_dip, |
295 | "dip - read dip switch on TRAB\n", | |
296 | "\n" | |
297 | " - read state of dip switch (S1) on TRAB board\n" | |
298 | " read sequence: 1-2-3-4; ON=1; OFF=0; e.g.: \"0100\"\n" | |
4f7cb08e WD |
299 | ); |
300 | ||
301 | ||
302 | int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
303 | { | |
a0ff7f2e | 304 | int vcc5v; |
4f7cb08e | 305 | |
a0ff7f2e | 306 | if (argc > 1) { |
4f7cb08e WD |
307 | printf ("Usage:\n%s\n", cmdtp->usage); |
308 | return 1; | |
309 | } | |
310 | ||
a0ff7f2e WD |
311 | if ((vcc5v = read_vcc5v ()) == -1) { |
312 | return (1); | |
313 | } | |
4f7cb08e | 314 | |
a0ff7f2e WD |
315 | printf ("%d", (vcc5v / 1000)); |
316 | printf (".%d", (vcc5v % 1000) / 100); | |
317 | printf ("%d V\n", (vcc5v % 100) / 10) ; | |
4f7cb08e WD |
318 | |
319 | return 0; | |
320 | } | |
321 | ||
322 | U_BOOT_CMD( | |
a0ff7f2e WD |
323 | vcc5v, 1, 1, do_vcc5v, |
324 | "vcc5v - read VCC5V on TRAB\n", | |
325 | "\n" | |
326 | " - read actual value of voltage VCC5V\n" | |
4f7cb08e WD |
327 | ); |
328 | ||
329 | ||
330 | int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
331 | { | |
a0ff7f2e | 332 | int contact_temp; |
4f7cb08e | 333 | |
a0ff7f2e | 334 | if (argc > 1) { |
4f7cb08e WD |
335 | printf ("Usage:\n%s\n", cmdtp->usage); |
336 | return 1; | |
337 | } | |
338 | ||
a0ff7f2e | 339 | spi_init (); |
4f7cb08e | 340 | |
a0ff7f2e WD |
341 | contact_temp = tsc2000_contact_temp(); |
342 | printf ("%d degree C * 100\n", contact_temp) ; | |
4f7cb08e WD |
343 | |
344 | return 0; | |
345 | } | |
346 | ||
347 | U_BOOT_CMD( | |
a0ff7f2e WD |
348 | c_temp, 1, 1, do_contact_temp, |
349 | "c_temp - read contact temperature on TRAB\n", | |
350 | "\n" | |
351 | " - reads the onboard temperature (=contact temperature)\n" | |
4f7cb08e WD |
352 | ); |
353 | ||
354 | ||
355 | int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) | |
356 | { | |
a0ff7f2e | 357 | if (argc > 1) { |
4f7cb08e WD |
358 | printf ("Usage:\n%s\n", cmdtp->usage); |
359 | return 1; | |
360 | } | |
361 | ||
a0ff7f2e WD |
362 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1, |
363 | (unsigned char*) &status, 1)) { | |
364 | return (1); | |
365 | } | |
366 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1, | |
367 | (unsigned char*) &pass_cycles, 2)) { | |
368 | return (1); | |
369 | } | |
370 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE, | |
371 | 1, (unsigned char*) &first_error_cycle, 2)) { | |
372 | return (1); | |
373 | } | |
374 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM, | |
375 | 1, (unsigned char*) &first_error_num, 1)) { | |
376 | return (1); | |
377 | } | |
378 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME, | |
379 | 1, first_error_name, | |
380 | sizeof (first_error_name))) { | |
381 | return (1); | |
382 | } | |
383 | ||
384 | if (read_max_cycles () != 0) { | |
385 | return (1); | |
386 | } | |
387 | ||
388 | printf ("max_cycles = %d\n", max_cycles); | |
389 | printf ("status = %d\n", status); | |
390 | printf ("pass_cycles = %d\n", pass_cycles); | |
391 | printf ("first_error_cycle = %d\n", first_error_cycle); | |
392 | printf ("first_error_num = %d\n", first_error_num); | |
393 | printf ("first_error_name = %.*s\n",(int) sizeof(first_error_name), | |
394 | first_error_name); | |
4f7cb08e WD |
395 | |
396 | return 0; | |
397 | } | |
398 | ||
399 | U_BOOT_CMD( | |
a0ff7f2e WD |
400 | bis, 1, 1, do_burn_in_status, |
401 | "bis - print burn in status on TRAB\n", | |
402 | "\n" | |
403 | " - prints the status variables of the last burn in test\n" | |
404 | " stored in the onboard EEPROM on TRAB board\n" | |
4f7cb08e WD |
405 | ); |
406 | ||
407 | static int read_dip (void) | |
408 | { | |
a0ff7f2e WD |
409 | unsigned int result = 0; |
410 | int adc_val; | |
411 | int i; | |
4f7cb08e WD |
412 | |
413 | /*********************************************************** | |
414 | DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3): | |
415 | SW1 - AIN4 | |
416 | SW2 - AIN5 | |
417 | SW3 - AIN6 | |
418 | SW4 - AIN7 | |
419 | ||
420 | "On" DIP switch position short-circuits the voltage from | |
421 | the input channel (i.e. '0' conversion result means "on"). | |
422 | *************************************************************/ | |
423 | ||
424 | for (i = 7; i > 3; i--) { | |
425 | ||
a0ff7f2e WD |
426 | if ((adc_val = adc_read (i)) == -1) { |
427 | printf ("%s: Channel %d could not be read\n", | |
428 | __FUNCTION__, i); | |
429 | return (-1); | |
430 | } | |
4f7cb08e WD |
431 | |
432 | /* | |
433 | * Input voltage (switch open) is 1.8 V. | |
434 | * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736 | |
435 | * Set trigger at halve that value. | |
436 | */ | |
437 | if (adc_val < 368) | |
a0ff7f2e WD |
438 | result |= (1 << (i-4)); |
439 | } | |
440 | return (result); | |
4f7cb08e WD |
441 | } |
442 | ||
443 | ||
444 | static int read_vcc5v (void) | |
445 | { | |
a0ff7f2e WD |
446 | s32 result; |
447 | ||
448 | /* VCC5V is connected to channel 2 */ | |
449 | ||
450 | if ((result = adc_read (2)) == -1) { | |
451 | printf ("%s: VCC5V could not be read\n", __FUNCTION__); | |
452 | return (-1); | |
453 | } | |
454 | /* | |
455 | * Calculate voltage value. Split in two parts because there is no | |
456 | * floating point support. VCC5V is connected over an resistor divider: | |
457 | * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K. | |
458 | */ | |
459 | result = result * 10 * 1000 / 1023; /* result in mV */ | |
460 | ||
461 | return (result); | |
4f7cb08e WD |
462 | } |
463 | ||
464 | ||
465 | static int test_dip (void) | |
466 | { | |
a0ff7f2e WD |
467 | static int first_run = 1; |
468 | static int first_dip; | |
469 | ||
470 | if (first_run) { | |
471 | if ((first_dip = read_dip ()) == -1) { | |
472 | return (1); | |
473 | } | |
474 | first_run = 0; | |
475 | debug ("%s: first_dip=%d\n", __FUNCTION__, first_dip); | |
476 | } | |
477 | if (first_dip != read_dip ()) { | |
478 | return (1); | |
479 | } else { | |
480 | return (0); | |
481 | } | |
4f7cb08e WD |
482 | } |
483 | ||
484 | ||
485 | static int test_vcc5v (void) | |
486 | { | |
a0ff7f2e | 487 | int vcc5v; |
4f7cb08e | 488 | |
a0ff7f2e WD |
489 | if ((vcc5v = read_vcc5v ()) == -1) { |
490 | return (1); | |
491 | } | |
4f7cb08e | 492 | |
a0ff7f2e WD |
493 | if ((vcc5v > VCC5V_MAX) || (vcc5v < VCC5V_MIN)) { |
494 | printf ("%s: vcc5v[V/100]=%d\n", __FUNCTION__, vcc5v); | |
495 | return (1); | |
496 | } else { | |
497 | return (0); | |
498 | } | |
4f7cb08e WD |
499 | } |
500 | ||
501 | ||
502 | static int test_rotary_switch (void) | |
503 | { | |
a0ff7f2e WD |
504 | static int first_run = 1; |
505 | static int first_rs; | |
506 | ||
507 | if (first_run) { | |
508 | /* | |
509 | * clear bits in CPLD, because they have random values after | |
510 | * power-up or reset. | |
511 | */ | |
512 | *CPLD_ROTARY_SWITCH |= (1 << 16) | (1 << 17); | |
513 | ||
514 | first_rs = ((*CPLD_ROTARY_SWITCH >> 16) & 0x7); | |
515 | first_run = 0; | |
516 | debug ("%s: first_rs=%d\n", __FUNCTION__, first_rs); | |
517 | } | |
518 | ||
519 | if (first_rs != ((*CPLD_ROTARY_SWITCH >> 16) & 0x7)) { | |
520 | return (1); | |
521 | } else { | |
522 | return (0); | |
523 | } | |
4f7cb08e WD |
524 | } |
525 | ||
526 | ||
527 | static int test_sram (void) | |
528 | { | |
a0ff7f2e | 529 | return (memory_post_tests (SRAM_ADDR, SRAM_SIZE)); |
4f7cb08e WD |
530 | } |
531 | ||
532 | ||
533 | static int test_eeprom (void) | |
534 | { | |
a0ff7f2e WD |
535 | unsigned char temp[sizeof (EEPROM_TEST_STRING_1)]; |
536 | int result = 0; | |
537 | ||
538 | /* write test string 1, read back and verify */ | |
539 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1, | |
540 | EEPROM_TEST_STRING_1, | |
541 | sizeof (EEPROM_TEST_STRING_1))) { | |
542 | return (1); | |
543 | } | |
544 | ||
545 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1, | |
546 | temp, sizeof (EEPROM_TEST_STRING_1))) { | |
547 | return (1); | |
548 | } | |
549 | ||
550 | if (strcmp (temp, EEPROM_TEST_STRING_1) != 0) { | |
551 | result = 1; | |
552 | printf ("%s: error; read_str = \"%s\"\n", __FUNCTION__, temp); | |
553 | } | |
554 | ||
555 | /* write test string 2, read back and verify */ | |
556 | if (result == 0) { | |
557 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1, | |
558 | EEPROM_TEST_STRING_2, | |
559 | sizeof (EEPROM_TEST_STRING_2))) { | |
560 | return (1); | |
561 | } | |
562 | ||
563 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1, | |
564 | temp, sizeof (EEPROM_TEST_STRING_2))) { | |
565 | return (1); | |
566 | } | |
567 | ||
568 | if (strcmp (temp, EEPROM_TEST_STRING_2) != 0) { | |
569 | result = 1; | |
570 | printf ("%s: error; read str = \"%s\"\n", | |
571 | __FUNCTION__, temp); | |
572 | } | |
573 | } | |
574 | return (result); | |
4f7cb08e WD |
575 | } |
576 | ||
577 | ||
578 | static int test_contact_temp (void) | |
579 | { | |
a0ff7f2e | 580 | int contact_temp; |
4f7cb08e | 581 | |
a0ff7f2e | 582 | contact_temp = tsc2000_contact_temp (); |
4f7cb08e | 583 | |
a0ff7f2e WD |
584 | if ((contact_temp < MIN_CONTACT_TEMP) |
585 | || (contact_temp > MAX_CONTACT_TEMP)) | |
586 | return (1); | |
587 | else | |
588 | return (0); | |
4f7cb08e WD |
589 | } |
590 | ||
591 | ||
f54ebdfa WD |
592 | int i2c_write_multiple (uchar chip, uint addr, int alen, |
593 | uchar *buffer, int len) | |
4f7cb08e | 594 | { |
a0ff7f2e WD |
595 | int i; |
596 | ||
597 | if (alen != 1) { | |
598 | printf ("%s: addr len other than 1 not supported\n", | |
599 | __FUNCTION__); | |
600 | return (1); | |
601 | } | |
602 | ||
603 | for (i = 0; i < len; i++) { | |
604 | if (i2c_write (chip, addr+i, alen, buffer+i, 1)) { | |
605 | printf ("%s: could not write to i2c device %d" | |
606 | ", addr %d\n", __FUNCTION__, chip, addr); | |
607 | return (1); | |
608 | } | |
4f7cb08e | 609 | #if 0 |
a0ff7f2e WD |
610 | printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i=" |
611 | "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i, | |
612 | alen, buffer, i, buffer+i, buffer+i); | |
4f7cb08e WD |
613 | #endif |
614 | ||
a0ff7f2e WD |
615 | udelay (30000); |
616 | } | |
617 | return (0); | |
4f7cb08e WD |
618 | } |
619 | ||
620 | ||
f54ebdfa WD |
621 | int i2c_read_multiple ( uchar chip, uint addr, int alen, |
622 | uchar *buffer, int len) | |
4f7cb08e | 623 | { |
a0ff7f2e WD |
624 | int i; |
625 | ||
626 | if (alen != 1) { | |
627 | printf ("%s: addr len other than 1 not supported\n", | |
628 | __FUNCTION__); | |
629 | return (1); | |
630 | } | |
631 | ||
632 | for (i = 0; i < len; i++) { | |
633 | if (i2c_read (chip, addr+i, alen, buffer+i, 1)) { | |
634 | printf ("%s: could not read from i2c device %#x" | |
635 | ", addr %d\n", __FUNCTION__, chip, addr); | |
636 | return (1); | |
637 | } | |
638 | } | |
639 | return (0); | |
4f7cb08e WD |
640 | } |
641 | ||
642 | ||
643 | static int adc_read (unsigned int channel) | |
644 | { | |
a0ff7f2e WD |
645 | int j = 1000; /* timeout value for wait loop in us */ |
646 | int result; | |
647 | S3C2400_ADC *padc; | |
4f7cb08e | 648 | |
a0ff7f2e WD |
649 | padc = S3C2400_GetBase_ADC(); |
650 | channel &= 0x7; | |
4f7cb08e | 651 | |
a0ff7f2e | 652 | adc_init (); |
4f7cb08e | 653 | |
a0ff7f2e | 654 | padc->ADCCON &= ~ADC_STDBM; /* select normal mode */ |
4f7cb08e | 655 | padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */ |
a0ff7f2e | 656 | padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START); |
4f7cb08e | 657 | |
a0ff7f2e WD |
658 | while (j--) { |
659 | if ((padc->ADCCON & ADC_ENABLE_START) == 0) | |
660 | break; | |
661 | udelay (1); | |
662 | } | |
663 | ||
664 | if (j == 0) { | |
665 | printf("%s: ADC timeout\n", __FUNCTION__); | |
666 | padc->ADCCON |= ADC_STDBM; /* select standby mode */ | |
667 | return -1; | |
668 | } | |
4f7cb08e | 669 | |
a0ff7f2e | 670 | result = padc->ADCDAT & 0x3FF; |
4f7cb08e | 671 | |
a0ff7f2e | 672 | padc->ADCCON |= ADC_STDBM; /* select standby mode */ |
4f7cb08e | 673 | |
a0ff7f2e WD |
674 | debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__, |
675 | (padc->ADCCON >> 3) & 0x7, result); | |
4f7cb08e | 676 | |
a0ff7f2e WD |
677 | /* |
678 | * Wait for ADC to be ready for next conversion. This delay value was | |
679 | * estimated, because the datasheet does not specify a value. | |
680 | */ | |
681 | udelay (1000); | |
4f7cb08e | 682 | |
a0ff7f2e | 683 | return (result); |
4f7cb08e WD |
684 | } |
685 | ||
686 | ||
687 | static void adc_init (void) | |
688 | { | |
a0ff7f2e | 689 | S3C2400_ADC *padc; |
4f7cb08e | 690 | |
a0ff7f2e | 691 | padc = S3C2400_GetBase_ADC(); |
4f7cb08e WD |
692 | |
693 | padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */ | |
694 | padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */ | |
695 | ||
a0ff7f2e WD |
696 | /* |
697 | * Wait some time to avoid problem with very first call of | |
698 | * adc_read(). Without this delay, sometimes the first read | |
699 | * adc value is 0. Perhaps because the adjustment of prescaler | |
700 | * takes some clock cycles? | |
701 | */ | |
702 | udelay (1000); | |
703 | ||
704 | return; | |
4f7cb08e WD |
705 | } |
706 | ||
707 | ||
708 | static void led_set (unsigned int state) | |
709 | { | |
a0ff7f2e WD |
710 | S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); |
711 | ||
712 | led_init (); | |
713 | ||
714 | switch (state) { | |
715 | case 0: /* turn LED off */ | |
716 | gpio->PADAT |= (1 << 12); | |
717 | break; | |
718 | case 1: /* turn LED on */ | |
719 | gpio->PADAT &= ~(1 << 12); | |
720 | break; | |
721 | default: | |
e86e5a07 | 722 | break; |
a0ff7f2e | 723 | } |
4f7cb08e WD |
724 | } |
725 | ||
726 | static void led_blink (void) | |
727 | { | |
a0ff7f2e WD |
728 | led_init (); |
729 | ||
730 | /* blink LED. This function does not return! */ | |
731 | while (1) { | |
732 | led_set (1); | |
733 | udelay (1000000 / LED_BLINK_FREQ / 2); | |
734 | led_set (0); | |
735 | udelay (1000000 / LED_BLINK_FREQ / 2); | |
736 | } | |
4f7cb08e WD |
737 | } |
738 | ||
739 | ||
740 | static void led_init (void) | |
741 | { | |
a0ff7f2e | 742 | S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO(); |
4f7cb08e | 743 | |
a0ff7f2e WD |
744 | /* configure GPA12 as output and set to High -> LED off */ |
745 | gpio->PACON &= ~(1 << 12); | |
746 | gpio->PADAT |= (1 << 12); | |
4f7cb08e WD |
747 | } |
748 | ||
749 | ||
750 | static void sdelay (unsigned long seconds) | |
751 | { | |
a0ff7f2e | 752 | unsigned long i; |
4f7cb08e | 753 | |
a0ff7f2e WD |
754 | for (i = 0; i < seconds; i++) { |
755 | udelay (1000000); | |
756 | } | |
4f7cb08e WD |
757 | } |
758 | ||
759 | ||
760 | static int global_vars_write_to_eeprom (void) | |
761 | { | |
a0ff7f2e WD |
762 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1, |
763 | (unsigned char*) &status, 1)) { | |
764 | return (1); | |
765 | } | |
766 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1, | |
767 | (unsigned char*) &pass_cycles, 2)) { | |
768 | return (1); | |
769 | } | |
770 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE, | |
771 | 1, (unsigned char*) &first_error_cycle, 2)) { | |
772 | return (1); | |
773 | } | |
774 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM, | |
775 | 1, (unsigned char*) &first_error_num, 1)) { | |
776 | return (1); | |
777 | } | |
778 | if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME, | |
779 | 1, first_error_name, | |
780 | sizeof(first_error_name))) { | |
781 | return (1); | |
782 | } | |
783 | return (0); | |
4f7cb08e WD |
784 | } |
785 | ||
786 | static void global_vars_init (void) | |
787 | { | |
a0ff7f2e WD |
788 | status = 1; /* error */ |
789 | pass_cycles = 0; | |
790 | first_error_cycle = 0; | |
791 | first_error_num = 0; | |
792 | first_error_name[0] = '\0'; | |
793 | act_cycle = 0; | |
794 | max_cycles = 0; | |
4f7cb08e WD |
795 | } |
796 | ||
797 | ||
798 | static void test_function_table_init (void) | |
799 | { | |
a0ff7f2e | 800 | int i; |
4f7cb08e | 801 | |
a0ff7f2e | 802 | for (i = 0; i < BIF_MAX; i++) |
4f7cb08e WD |
803 | test_function[i].pf = dummy; |
804 | ||
a0ff7f2e WD |
805 | /* |
806 | * the length of "name" must not exceed 16, including the '\0' | |
807 | * termination. See also the EEPROM address map. | |
808 | */ | |
809 | test_function[0].pf = test_dip; | |
810 | test_function[0].name = "dip"; | |
4f7cb08e | 811 | |
a0ff7f2e WD |
812 | test_function[1].pf = test_vcc5v; |
813 | test_function[1].name = "vcc5v"; | |
4f7cb08e | 814 | |
a0ff7f2e WD |
815 | test_function[2].pf = test_rotary_switch; |
816 | test_function[2].name = "rotary_switch"; | |
4f7cb08e | 817 | |
a0ff7f2e WD |
818 | test_function[3].pf = test_sram; |
819 | test_function[3].name = "sram"; | |
4f7cb08e | 820 | |
a0ff7f2e WD |
821 | test_function[4].pf = test_eeprom; |
822 | test_function[4].name = "eeprom"; | |
4f7cb08e | 823 | |
a0ff7f2e WD |
824 | test_function[5].pf = test_contact_temp; |
825 | test_function[5].name = "contact_temp"; | |
4f7cb08e WD |
826 | } |
827 | ||
828 | ||
829 | static int read_max_cycles (void) | |
830 | { | |
a0ff7f2e WD |
831 | if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_MAX_CYCLES, 1, |
832 | (unsigned char *) &max_cycles, 2) != 0) { | |
833 | return (1); | |
834 | } | |
4f7cb08e | 835 | |
a0ff7f2e | 836 | return (0); |
4f7cb08e WD |
837 | } |
838 | ||
839 | static int dummy(void) | |
840 | { | |
a0ff7f2e | 841 | return (0); |
4f7cb08e WD |
842 | } |
843 | ||
151ab83a WD |
844 | int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) |
845 | { | |
846 | int contact_temp; | |
847 | int delay = 0; | |
848 | #if (CONFIG_COMMANDS & CFG_CMD_DATE) | |
849 | struct rtc_time tm; | |
850 | #endif | |
851 | ||
852 | if (argc > 2) { | |
853 | printf ("Usage:\n%s\n", cmdtp->usage); | |
854 | return 1; | |
855 | } | |
856 | ||
857 | if (argc > 1) { | |
858 | delay = simple_strtoul(argv[1], NULL, 10); | |
859 | } | |
860 | ||
861 | spi_init (); | |
862 | while (1) { | |
863 | ||
864 | #if (CONFIG_COMMANDS & CFG_CMD_DATE) | |
865 | rtc_get (&tm); | |
866 | printf ("%4d-%02d-%02d %2d:%02d:%02d - ", | |
867 | tm.tm_year, tm.tm_mon, tm.tm_mday, | |
868 | tm.tm_hour, tm.tm_min, tm.tm_sec); | |
869 | #endif | |
870 | ||
871 | contact_temp = tsc2000_contact_temp(); | |
872 | printf ("%d\n", contact_temp) ; | |
873 | ||
874 | if (delay != 0) | |
875 | /* | |
876 | * reset timer to avoid timestamp overflow problem | |
877 | * after about 68 minutes of udelay() time. | |
878 | */ | |
879 | reset_timer_masked (); | |
880 | sdelay (delay); | |
881 | } | |
882 | ||
883 | return 0; | |
884 | } | |
885 | ||
886 | U_BOOT_CMD( | |
887 | tlog, 2, 1, do_temp_log, | |
888 | "tlog - log contact temperature [1/100 C] to console (endlessly)\n", | |
889 | "delay\n" | |
890 | " - contact temperature [1/100 C] is printed endlessly to console\n" | |
891 | " <delay> specifies the seconds to wait between two measurements\n" | |
892 | " For each measurment a timestamp is printeted\n" | |
893 | ); | |
894 | ||
4f7cb08e | 895 | #endif /* CFG_CMD_BSP */ |