blob: a01ffcc02a6ea3d72894d4bb0d97d2d498f7cb6a [file] [log] [blame]
wdenk4f7cb082003-09-11 23:06:34 +00001/*
2 * (C) Copyright 2003
3 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.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
wdenka0ff7f22003-10-09 13:16:55 +000024#undef DEBUG
25
wdenk4f7cb082003-09-11 23:06:34 +000026#include <common.h>
27#include <command.h>
kevin.morfitt@fearnside-systems.co.uk492fb1f2009-11-03 18:08:41 +090028#include <asm/arch/s3c2400.h>
wdenk151ab832005-02-24 22:44:16 +000029#include <rtc.h>
wdenk4f7cb082003-09-11 23:06:34 +000030
31/*
32 * TRAB board specific commands. Especially commands for burn-in and function
33 * test.
34 */
Jon Loeligerab3abcb2007-07-09 18:45:16 -050035#if defined(CONFIG_CMD_BSP)
wdenk4f7cb082003-09-11 23:06:34 +000036
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 */
wdenka0ff7f22003-10-09 13:16:55 +000077#define EE_ADDR_TEST 192
wdenk4f7cb082003-09-11 23:06:34 +000078#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 */
104extern int memory_post_tests (unsigned long start, unsigned long size);
105extern int i2c_write (uchar, uint, int , uchar* , int);
106extern int i2c_read (uchar, uint, int , uchar* , int);
107extern void tsc2000_reg_init (void);
108extern s32 tsc2000_contact_temp (void);
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400109extern void tsc2000_spi_init(void);
wdenk4f7cb082003-09-11 23:06:34 +0000110
111/* function declarations */
112int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
113int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
114int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
115int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
116int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
wdenkf54ebdf2003-09-17 15:10:32 +0000117int i2c_write_multiple (uchar chip, uint addr, int alen,
118 uchar *buffer, int len);
119int i2c_read_multiple (uchar chip, uint addr, int alen,
120 uchar *buffer, int len);
wdenk151ab832005-02-24 22:44:16 +0000121int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
wdenk4f7cb082003-09-11 23:06:34 +0000122
123/* helper functions */
124static void adc_init (void);
125static int adc_read (unsigned int channel);
126static int read_dip (void);
127static int read_vcc5v (void);
128static int test_dip (void);
129static int test_vcc5v (void);
130static int test_rotary_switch (void);
131static int test_sram (void);
132static int test_eeprom (void);
133static int test_contact_temp (void);
wdenk4f7cb082003-09-11 23:06:34 +0000134static void led_set (unsigned int);
135static void led_blink (void);
136static void led_init (void);
137static void sdelay (unsigned long seconds); /* delay in seconds */
138static int dummy (void);
139static int read_max_cycles(void);
140static void test_function_table_init (void);
141static void global_vars_init (void);
142static int global_vars_write_to_eeprom (void);
143
144/* globals */
145u16 max_cycles;
146u8 status;
147u16 pass_cycles;
148u16 first_error_cycle;
149u8 first_error_num;
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200150char first_error_name[16];
wdenk4f7cb082003-09-11 23:06:34 +0000151u16 act_cycle;
152
153typedef struct test_function_s {
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200154 char *name;
wdenka0ff7f22003-10-09 13:16:55 +0000155 int (*pf)(void);
wdenk4f7cb082003-09-11 23:06:34 +0000156} test_function_t;
157
158/* max number of Burn In Functions */
159#define BIF_MAX 6
160
161/* table with burn in functions */
162test_function_t test_function[BIF_MAX];
163
164
165int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
166{
wdenka0ff7f22003-10-09 13:16:55 +0000167 int i;
168 int cycle_status;
wdenk4f7cb082003-09-11 23:06:34 +0000169
wdenka0ff7f22003-10-09 13:16:55 +0000170 if (argc > 1) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600171 cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000172 return 1;
173 }
174
wdenka0ff7f22003-10-09 13:16:55 +0000175 led_init ();
176 global_vars_init ();
177 test_function_table_init ();
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400178 tsc2000_spi_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000179
wdenka0ff7f22003-10-09 13:16:55 +0000180 if (global_vars_write_to_eeprom () != 0) {
181 printf ("%s: error writing global_vars to eeprom\n",
182 __FUNCTION__);
183 return (1);
184 }
wdenk4f7cb082003-09-11 23:06:34 +0000185
wdenka0ff7f22003-10-09 13:16:55 +0000186 if (read_max_cycles () != 0) {
187 printf ("%s: error reading max_cycles from eeprom\n",
188 __FUNCTION__);
189 return (1);
190 }
wdenk4f7cb082003-09-11 23:06:34 +0000191
wdenka0ff7f22003-10-09 13:16:55 +0000192 if (max_cycles == 0) {
193 printf ("%s: error, burn in max_cycles = 0\n", __FUNCTION__);
194 return (1);
195 }
wdenk4f7cb082003-09-11 23:06:34 +0000196
wdenka0ff7f22003-10-09 13:16:55 +0000197 status = 0;
198 for (act_cycle = 1; act_cycle <= max_cycles; act_cycle++) {
wdenk4f7cb082003-09-11 23:06:34 +0000199
wdenka0ff7f22003-10-09 13:16:55 +0000200 cycle_status = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000201
wdenka0ff7f22003-10-09 13:16:55 +0000202 /*
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++) {
wdenk4f7cb082003-09-11 23:06:34 +0000208
wdenka0ff7f22003-10-09 13:16:55 +0000209 /* call test function */
210 if ((*test_function[i].pf)() != 0) {
211 printf ("error in %s test\n",
212 test_function[i].name);
wdenk4f7cb082003-09-11 23:06:34 +0000213
wdenka0ff7f22003-10-09 13:16:55 +0000214 /* is it the first error? */
215 if (status == 0) {
216 status = 1;
217 first_error_cycle = act_cycle;
wdenk4f7cb082003-09-11 23:06:34 +0000218
wdenka0ff7f22003-10-09 13:16:55 +0000219 /* 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++;
wdenk4f7cb082003-09-11 23:06:34 +0000232
wdenka0ff7f22003-10-09 13:16:55 +0000233 /* set status LED if no error is occoured since yet */
234 if (status == 0)
235 led_set (1);
wdenk4f7cb082003-09-11 23:06:34 +0000236
wdenka0ff7f22003-10-09 13:16:55 +0000237 printf ("%s: cycle %d finished\n", __FUNCTION__, act_cycle);
wdenk4f7cb082003-09-11 23:06:34 +0000238
wdenka0ff7f22003-10-09 13:16:55 +0000239 /* pause between cycles */
240 sdelay (BURN_IN_CYCLE_DELAY);
241 }
wdenk4f7cb082003-09-11 23:06:34 +0000242
wdenka0ff7f22003-10-09 13:16:55 +0000243 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 }
wdenk4f7cb082003-09-11 23:06:34 +0000257}
258
259U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000260 burn_in, 1, 1, do_burn_in,
Peter Tyser2fb26042009-01-27 18:03:12 -0600261 "start burn-in test application on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000262 "\n"
263 " - start burn-in test application\n"
264 " The burn-in test could took a while to finish!\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200265 " The content of the onboard EEPROM is modified!"
wdenk4f7cb082003-09-11 23:06:34 +0000266);
267
268
269int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
270{
wdenka0ff7f22003-10-09 13:16:55 +0000271 int i, dip;
wdenk4f7cb082003-09-11 23:06:34 +0000272
wdenka0ff7f22003-10-09 13:16:55 +0000273 if (argc > 1) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600274 cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000275 return 1;
276 }
277
wdenka0ff7f22003-10-09 13:16:55 +0000278 if ((dip = read_dip ()) == -1) {
279 return 1;
280 }
wdenk4f7cb082003-09-11 23:06:34 +0000281
wdenka0ff7f22003-10-09 13:16:55 +0000282 for (i = 0; i < 4; i++) {
283 if ((dip & (1 << i)) == 0)
284 printf("0");
285 else
286 printf("1");
287 }
288 printf("\n");
wdenk4f7cb082003-09-11 23:06:34 +0000289
290 return 0;
291}
292
293U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000294 dip, 1, 1, do_dip,
Peter Tyser2fb26042009-01-27 18:03:12 -0600295 "read dip switch on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000296 "\n"
297 " - read state of dip switch (S1) on TRAB board\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200298 " read sequence: 1-2-3-4; ON=1; OFF=0; e.g.: \"0100\""
wdenk4f7cb082003-09-11 23:06:34 +0000299);
300
301
302int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
303{
wdenka0ff7f22003-10-09 13:16:55 +0000304 int vcc5v;
wdenk4f7cb082003-09-11 23:06:34 +0000305
wdenka0ff7f22003-10-09 13:16:55 +0000306 if (argc > 1) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600307 cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000308 return 1;
309 }
310
wdenka0ff7f22003-10-09 13:16:55 +0000311 if ((vcc5v = read_vcc5v ()) == -1) {
312 return (1);
313 }
wdenk4f7cb082003-09-11 23:06:34 +0000314
wdenka0ff7f22003-10-09 13:16:55 +0000315 printf ("%d", (vcc5v / 1000));
316 printf (".%d", (vcc5v % 1000) / 100);
317 printf ("%d V\n", (vcc5v % 100) / 10) ;
wdenk4f7cb082003-09-11 23:06:34 +0000318
319 return 0;
320}
321
322U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000323 vcc5v, 1, 1, do_vcc5v,
Peter Tyser2fb26042009-01-27 18:03:12 -0600324 "read VCC5V on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000325 "\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200326 " - read actual value of voltage VCC5V"
wdenk4f7cb082003-09-11 23:06:34 +0000327);
328
329
330int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
331{
wdenka0ff7f22003-10-09 13:16:55 +0000332 int contact_temp;
wdenk4f7cb082003-09-11 23:06:34 +0000333
wdenka0ff7f22003-10-09 13:16:55 +0000334 if (argc > 1) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600335 cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000336 return 1;
337 }
338
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400339 tsc2000_spi_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000340
wdenka0ff7f22003-10-09 13:16:55 +0000341 contact_temp = tsc2000_contact_temp();
342 printf ("%d degree C * 100\n", contact_temp) ;
wdenk4f7cb082003-09-11 23:06:34 +0000343
344 return 0;
345}
346
347U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000348 c_temp, 1, 1, do_contact_temp,
Peter Tyser2fb26042009-01-27 18:03:12 -0600349 "read contact temperature on TRAB",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200350 ""
wdenka0ff7f22003-10-09 13:16:55 +0000351 " - reads the onboard temperature (=contact temperature)\n"
wdenk4f7cb082003-09-11 23:06:34 +0000352);
353
354
355int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
356{
wdenka0ff7f22003-10-09 13:16:55 +0000357 if (argc > 1) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600358 cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000359 return 1;
360 }
361
wdenka0ff7f22003-10-09 13:16:55 +0000362 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,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200379 1, (unsigned char*)first_error_name,
wdenka0ff7f22003-10-09 13:16:55 +0000380 sizeof (first_error_name))) {
381 return (1);
382 }
wdenk4f7cb082003-09-11 23:06:34 +0000383
wdenka0ff7f22003-10-09 13:16:55 +0000384 if (read_max_cycles () != 0) {
385 return (1);
386 }
wdenk4f7cb082003-09-11 23:06:34 +0000387
wdenka0ff7f22003-10-09 13:16:55 +0000388 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);
wdenk4f7cb082003-09-11 23:06:34 +0000395
396 return 0;
397}
398
399U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000400 bis, 1, 1, do_burn_in_status,
Peter Tyser2fb26042009-01-27 18:03:12 -0600401 "print burn in status on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000402 "\n"
403 " - prints the status variables of the last burn in test\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200404 " stored in the onboard EEPROM on TRAB board"
wdenk4f7cb082003-09-11 23:06:34 +0000405);
406
407static int read_dip (void)
408{
wdenka0ff7f22003-10-09 13:16:55 +0000409 unsigned int result = 0;
410 int adc_val;
411 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000412
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
wdenka0ff7f22003-10-09 13:16:55 +0000426 if ((adc_val = adc_read (i)) == -1) {
427 printf ("%s: Channel %d could not be read\n",
428 __FUNCTION__, i);
429 return (-1);
430 }
wdenk4f7cb082003-09-11 23:06:34 +0000431
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)
wdenka0ff7f22003-10-09 13:16:55 +0000438 result |= (1 << (i-4));
439 }
440 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000441}
442
443
444static int read_vcc5v (void)
445{
wdenka0ff7f22003-10-09 13:16:55 +0000446 s32 result;
wdenk4f7cb082003-09-11 23:06:34 +0000447
wdenka0ff7f22003-10-09 13:16:55 +0000448 /* VCC5V is connected to channel 2 */
wdenk4f7cb082003-09-11 23:06:34 +0000449
wdenka0ff7f22003-10-09 13:16:55 +0000450 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 */
wdenk4f7cb082003-09-11 23:06:34 +0000460
wdenka0ff7f22003-10-09 13:16:55 +0000461 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000462}
463
464
465static int test_dip (void)
466{
wdenka0ff7f22003-10-09 13:16:55 +0000467 static int first_run = 1;
468 static int first_dip;
wdenk4f7cb082003-09-11 23:06:34 +0000469
wdenka0ff7f22003-10-09 13:16:55 +0000470 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 }
wdenk4f7cb082003-09-11 23:06:34 +0000482}
483
484
485static int test_vcc5v (void)
486{
wdenka0ff7f22003-10-09 13:16:55 +0000487 int vcc5v;
wdenk4f7cb082003-09-11 23:06:34 +0000488
wdenka0ff7f22003-10-09 13:16:55 +0000489 if ((vcc5v = read_vcc5v ()) == -1) {
490 return (1);
491 }
wdenk4f7cb082003-09-11 23:06:34 +0000492
wdenka0ff7f22003-10-09 13:16:55 +0000493 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 }
wdenk4f7cb082003-09-11 23:06:34 +0000499}
500
501
502static int test_rotary_switch (void)
503{
wdenka0ff7f22003-10-09 13:16:55 +0000504 static int first_run = 1;
505 static int first_rs;
wdenk4f7cb082003-09-11 23:06:34 +0000506
wdenka0ff7f22003-10-09 13:16:55 +0000507 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);
wdenk4f7cb082003-09-11 23:06:34 +0000513
wdenka0ff7f22003-10-09 13:16:55 +0000514 first_rs = ((*CPLD_ROTARY_SWITCH >> 16) & 0x7);
515 first_run = 0;
516 debug ("%s: first_rs=%d\n", __FUNCTION__, first_rs);
517 }
wdenk4f7cb082003-09-11 23:06:34 +0000518
wdenka0ff7f22003-10-09 13:16:55 +0000519 if (first_rs != ((*CPLD_ROTARY_SWITCH >> 16) & 0x7)) {
520 return (1);
521 } else {
522 return (0);
523 }
wdenk4f7cb082003-09-11 23:06:34 +0000524}
525
526
527static int test_sram (void)
528{
wdenka0ff7f22003-10-09 13:16:55 +0000529 return (memory_post_tests (SRAM_ADDR, SRAM_SIZE));
wdenk4f7cb082003-09-11 23:06:34 +0000530}
531
532
533static int test_eeprom (void)
534{
wdenka0ff7f22003-10-09 13:16:55 +0000535 unsigned char temp[sizeof (EEPROM_TEST_STRING_1)];
536 int result = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000537
wdenka0ff7f22003-10-09 13:16:55 +0000538 /* write test string 1, read back and verify */
539 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200540 (unsigned char*)EEPROM_TEST_STRING_1,
wdenka0ff7f22003-10-09 13:16:55 +0000541 sizeof (EEPROM_TEST_STRING_1))) {
542 return (1);
543 }
wdenk4f7cb082003-09-11 23:06:34 +0000544
wdenka0ff7f22003-10-09 13:16:55 +0000545 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
546 temp, sizeof (EEPROM_TEST_STRING_1))) {
547 return (1);
548 }
wdenk4f7cb082003-09-11 23:06:34 +0000549
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200550 if (strcmp ((char *)temp, EEPROM_TEST_STRING_1) != 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000551 result = 1;
552 printf ("%s: error; read_str = \"%s\"\n", __FUNCTION__, temp);
553 }
wdenk4f7cb082003-09-11 23:06:34 +0000554
wdenka0ff7f22003-10-09 13:16:55 +0000555 /* 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,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200558 (unsigned char*)EEPROM_TEST_STRING_2,
wdenka0ff7f22003-10-09 13:16:55 +0000559 sizeof (EEPROM_TEST_STRING_2))) {
560 return (1);
561 }
wdenk4f7cb082003-09-11 23:06:34 +0000562
wdenka0ff7f22003-10-09 13:16:55 +0000563 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
564 temp, sizeof (EEPROM_TEST_STRING_2))) {
565 return (1);
566 }
wdenk4f7cb082003-09-11 23:06:34 +0000567
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200568 if (strcmp ((char *)temp, EEPROM_TEST_STRING_2) != 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000569 result = 1;
570 printf ("%s: error; read str = \"%s\"\n",
571 __FUNCTION__, temp);
572 }
573 }
574 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000575}
576
577
578static int test_contact_temp (void)
579{
wdenka0ff7f22003-10-09 13:16:55 +0000580 int contact_temp;
wdenk4f7cb082003-09-11 23:06:34 +0000581
wdenka0ff7f22003-10-09 13:16:55 +0000582 contact_temp = tsc2000_contact_temp ();
wdenk4f7cb082003-09-11 23:06:34 +0000583
wdenka0ff7f22003-10-09 13:16:55 +0000584 if ((contact_temp < MIN_CONTACT_TEMP)
585 || (contact_temp > MAX_CONTACT_TEMP))
586 return (1);
587 else
588 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000589}
590
591
wdenkf54ebdf2003-09-17 15:10:32 +0000592int i2c_write_multiple (uchar chip, uint addr, int alen,
593 uchar *buffer, int len)
wdenk4f7cb082003-09-11 23:06:34 +0000594{
wdenka0ff7f22003-10-09 13:16:55 +0000595 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000596
wdenka0ff7f22003-10-09 13:16:55 +0000597 if (alen != 1) {
598 printf ("%s: addr len other than 1 not supported\n",
599 __FUNCTION__);
600 return (1);
601 }
wdenk4f7cb082003-09-11 23:06:34 +0000602
wdenka0ff7f22003-10-09 13:16:55 +0000603 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 }
wdenk4f7cb082003-09-11 23:06:34 +0000609#if 0
wdenka0ff7f22003-10-09 13:16:55 +0000610 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);
wdenk4f7cb082003-09-11 23:06:34 +0000613#endif
614
wdenka0ff7f22003-10-09 13:16:55 +0000615 udelay (30000);
616 }
617 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000618}
619
620
wdenkf54ebdf2003-09-17 15:10:32 +0000621int i2c_read_multiple ( uchar chip, uint addr, int alen,
622 uchar *buffer, int len)
wdenk4f7cb082003-09-11 23:06:34 +0000623{
wdenka0ff7f22003-10-09 13:16:55 +0000624 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000625
wdenka0ff7f22003-10-09 13:16:55 +0000626 if (alen != 1) {
627 printf ("%s: addr len other than 1 not supported\n",
628 __FUNCTION__);
629 return (1);
630 }
wdenk4f7cb082003-09-11 23:06:34 +0000631
wdenka0ff7f22003-10-09 13:16:55 +0000632 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);
wdenk4f7cb082003-09-11 23:06:34 +0000640}
641
642
643static int adc_read (unsigned int channel)
644{
wdenka0ff7f22003-10-09 13:16:55 +0000645 int j = 1000; /* timeout value for wait loop in us */
646 int result;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900647 struct s3c2400_adc *padc;
wdenk4f7cb082003-09-11 23:06:34 +0000648
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900649 padc = s3c2400_get_base_adc();
wdenka0ff7f22003-10-09 13:16:55 +0000650 channel &= 0x7;
wdenk4f7cb082003-09-11 23:06:34 +0000651
wdenka0ff7f22003-10-09 13:16:55 +0000652 adc_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000653
wdenka0ff7f22003-10-09 13:16:55 +0000654 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
wdenk4f7cb082003-09-11 23:06:34 +0000655 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
wdenka0ff7f22003-10-09 13:16:55 +0000656 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
wdenk4f7cb082003-09-11 23:06:34 +0000657
wdenka0ff7f22003-10-09 13:16:55 +0000658 while (j--) {
659 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
660 break;
661 udelay (1);
662 }
wdenk4f7cb082003-09-11 23:06:34 +0000663
wdenka0ff7f22003-10-09 13:16:55 +0000664 if (j == 0) {
665 printf("%s: ADC timeout\n", __FUNCTION__);
666 padc->ADCCON |= ADC_STDBM; /* select standby mode */
667 return -1;
668 }
wdenk4f7cb082003-09-11 23:06:34 +0000669
wdenka0ff7f22003-10-09 13:16:55 +0000670 result = padc->ADCDAT & 0x3FF;
wdenk4f7cb082003-09-11 23:06:34 +0000671
wdenka0ff7f22003-10-09 13:16:55 +0000672 padc->ADCCON |= ADC_STDBM; /* select standby mode */
wdenk4f7cb082003-09-11 23:06:34 +0000673
wdenka0ff7f22003-10-09 13:16:55 +0000674 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
675 (padc->ADCCON >> 3) & 0x7, result);
wdenk4f7cb082003-09-11 23:06:34 +0000676
wdenka0ff7f22003-10-09 13:16:55 +0000677 /*
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);
682
683 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000684}
685
686
687static void adc_init (void)
688{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900689 struct s3c2400_adc *padc;
wdenk4f7cb082003-09-11 23:06:34 +0000690
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900691 padc = s3c2400_get_base_adc();
wdenk4f7cb082003-09-11 23:06:34 +0000692
693 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
694 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
695
wdenka0ff7f22003-10-09 13:16:55 +0000696 /*
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;
wdenk4f7cb082003-09-11 23:06:34 +0000705}
706
707
708static void led_set (unsigned int state)
709{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900710 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenk4f7cb082003-09-11 23:06:34 +0000711
wdenka0ff7f22003-10-09 13:16:55 +0000712 led_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000713
wdenka0ff7f22003-10-09 13:16:55 +0000714 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:
wdenke86e5a02004-10-17 21:12:06 +0000722 break;
wdenka0ff7f22003-10-09 13:16:55 +0000723 }
wdenk4f7cb082003-09-11 23:06:34 +0000724}
725
726static void led_blink (void)
727{
wdenka0ff7f22003-10-09 13:16:55 +0000728 led_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000729
wdenka0ff7f22003-10-09 13:16:55 +0000730 /* blink LED. This function does not return! */
731 while (1) {
Wolfgang Denkb9fff8e2006-06-16 15:52:58 +0200732 reset_timer_masked ();
wdenka0ff7f22003-10-09 13:16:55 +0000733 led_set (1);
734 udelay (1000000 / LED_BLINK_FREQ / 2);
735 led_set (0);
736 udelay (1000000 / LED_BLINK_FREQ / 2);
737 }
wdenk4f7cb082003-09-11 23:06:34 +0000738}
739
740
741static void led_init (void)
742{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900743 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenk4f7cb082003-09-11 23:06:34 +0000744
wdenka0ff7f22003-10-09 13:16:55 +0000745 /* configure GPA12 as output and set to High -> LED off */
746 gpio->PACON &= ~(1 << 12);
747 gpio->PADAT |= (1 << 12);
wdenk4f7cb082003-09-11 23:06:34 +0000748}
749
750
751static void sdelay (unsigned long seconds)
752{
wdenka0ff7f22003-10-09 13:16:55 +0000753 unsigned long i;
wdenk4f7cb082003-09-11 23:06:34 +0000754
wdenka0ff7f22003-10-09 13:16:55 +0000755 for (i = 0; i < seconds; i++) {
756 udelay (1000000);
757 }
wdenk4f7cb082003-09-11 23:06:34 +0000758}
759
760
761static int global_vars_write_to_eeprom (void)
762{
wdenka0ff7f22003-10-09 13:16:55 +0000763 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1,
764 (unsigned char*) &status, 1)) {
765 return (1);
766 }
767 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1,
768 (unsigned char*) &pass_cycles, 2)) {
769 return (1);
770 }
771 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE,
772 1, (unsigned char*) &first_error_cycle, 2)) {
773 return (1);
774 }
775 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM,
776 1, (unsigned char*) &first_error_num, 1)) {
777 return (1);
778 }
779 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200780 1, (unsigned char*) first_error_name,
wdenka0ff7f22003-10-09 13:16:55 +0000781 sizeof(first_error_name))) {
782 return (1);
783 }
784 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000785}
786
787static void global_vars_init (void)
788{
wdenka0ff7f22003-10-09 13:16:55 +0000789 status = 1; /* error */
790 pass_cycles = 0;
791 first_error_cycle = 0;
792 first_error_num = 0;
793 first_error_name[0] = '\0';
794 act_cycle = 0;
795 max_cycles = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000796}
797
798
799static void test_function_table_init (void)
800{
wdenka0ff7f22003-10-09 13:16:55 +0000801 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000802
wdenka0ff7f22003-10-09 13:16:55 +0000803 for (i = 0; i < BIF_MAX; i++)
wdenk4f7cb082003-09-11 23:06:34 +0000804 test_function[i].pf = dummy;
805
wdenka0ff7f22003-10-09 13:16:55 +0000806 /*
807 * the length of "name" must not exceed 16, including the '\0'
808 * termination. See also the EEPROM address map.
809 */
810 test_function[0].pf = test_dip;
811 test_function[0].name = "dip";
wdenk4f7cb082003-09-11 23:06:34 +0000812
wdenka0ff7f22003-10-09 13:16:55 +0000813 test_function[1].pf = test_vcc5v;
814 test_function[1].name = "vcc5v";
wdenk4f7cb082003-09-11 23:06:34 +0000815
wdenka0ff7f22003-10-09 13:16:55 +0000816 test_function[2].pf = test_rotary_switch;
817 test_function[2].name = "rotary_switch";
wdenk4f7cb082003-09-11 23:06:34 +0000818
wdenka0ff7f22003-10-09 13:16:55 +0000819 test_function[3].pf = test_sram;
820 test_function[3].name = "sram";
wdenk4f7cb082003-09-11 23:06:34 +0000821
wdenka0ff7f22003-10-09 13:16:55 +0000822 test_function[4].pf = test_eeprom;
823 test_function[4].name = "eeprom";
wdenk4f7cb082003-09-11 23:06:34 +0000824
wdenka0ff7f22003-10-09 13:16:55 +0000825 test_function[5].pf = test_contact_temp;
826 test_function[5].name = "contact_temp";
wdenk4f7cb082003-09-11 23:06:34 +0000827}
828
829
830static int read_max_cycles (void)
831{
wdenka0ff7f22003-10-09 13:16:55 +0000832 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_MAX_CYCLES, 1,
833 (unsigned char *) &max_cycles, 2) != 0) {
834 return (1);
835 }
wdenk4f7cb082003-09-11 23:06:34 +0000836
wdenka0ff7f22003-10-09 13:16:55 +0000837 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000838}
839
840static int dummy(void)
841{
wdenka0ff7f22003-10-09 13:16:55 +0000842 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000843}
844
wdenk151ab832005-02-24 22:44:16 +0000845int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
846{
847 int contact_temp;
848 int delay = 0;
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500849#if defined(CONFIG_CMD_DATE)
wdenk151ab832005-02-24 22:44:16 +0000850 struct rtc_time tm;
851#endif
852
853 if (argc > 2) {
Peter Tyser62c3ae72009-01-27 18:03:10 -0600854 cmd_usage(cmdtp);
wdenk151ab832005-02-24 22:44:16 +0000855 return 1;
856 }
857
858 if (argc > 1) {
859 delay = simple_strtoul(argv[1], NULL, 10);
860 }
861
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400862 tsc2000_spi_init ();
wdenk151ab832005-02-24 22:44:16 +0000863 while (1) {
864
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500865#if defined(CONFIG_CMD_DATE)
wdenk151ab832005-02-24 22:44:16 +0000866 rtc_get (&tm);
867 printf ("%4d-%02d-%02d %2d:%02d:%02d - ",
868 tm.tm_year, tm.tm_mon, tm.tm_mday,
869 tm.tm_hour, tm.tm_min, tm.tm_sec);
870#endif
871
872 contact_temp = tsc2000_contact_temp();
873 printf ("%d\n", contact_temp) ;
874
875 if (delay != 0)
876 /*
877 * reset timer to avoid timestamp overflow problem
878 * after about 68 minutes of udelay() time.
879 */
880 reset_timer_masked ();
881 sdelay (delay);
882 }
883
884 return 0;
885}
886
887U_BOOT_CMD(
888 tlog, 2, 1, do_temp_log,
Peter Tyser2fb26042009-01-27 18:03:12 -0600889 "log contact temperature [1/100 C] to console (endlessly)",
wdenk151ab832005-02-24 22:44:16 +0000890 "delay\n"
891 " - contact temperature [1/100 C] is printed endlessly to console\n"
892 " <delay> specifies the seconds to wait between two measurements\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200893 " For each measurment a timestamp is printeted"
wdenk151ab832005-02-24 22:44:16 +0000894);
895
Jon Loeligerd39b5742007-07-10 10:48:22 -0500896#endif