blob: ca4415c0b9234716c8e1d5238cc4bfee2e48fd7c [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.ukac678042009-11-17 18:30:34 +090028#include <asm/arch/s3c24x0_cpu.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 */
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200112int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
113int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
114int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
115int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
116int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char * const 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);
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200121int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char * const 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
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200165int do_burn_in (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk4f7cb082003-09-11 23:06:34 +0000166{
wdenka0ff7f22003-10-09 13:16:55 +0000167 int i;
168 int cycle_status;
wdenk4f7cb082003-09-11 23:06:34 +0000169
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200170 if (argc > 1)
171 return cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000172
wdenka0ff7f22003-10-09 13:16:55 +0000173 led_init ();
174 global_vars_init ();
175 test_function_table_init ();
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400176 tsc2000_spi_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000177
wdenka0ff7f22003-10-09 13:16:55 +0000178 if (global_vars_write_to_eeprom () != 0) {
179 printf ("%s: error writing global_vars to eeprom\n",
180 __FUNCTION__);
181 return (1);
182 }
wdenk4f7cb082003-09-11 23:06:34 +0000183
wdenka0ff7f22003-10-09 13:16:55 +0000184 if (read_max_cycles () != 0) {
185 printf ("%s: error reading max_cycles from eeprom\n",
186 __FUNCTION__);
187 return (1);
188 }
wdenk4f7cb082003-09-11 23:06:34 +0000189
wdenka0ff7f22003-10-09 13:16:55 +0000190 if (max_cycles == 0) {
191 printf ("%s: error, burn in max_cycles = 0\n", __FUNCTION__);
192 return (1);
193 }
wdenk4f7cb082003-09-11 23:06:34 +0000194
wdenka0ff7f22003-10-09 13:16:55 +0000195 status = 0;
196 for (act_cycle = 1; act_cycle <= max_cycles; act_cycle++) {
wdenk4f7cb082003-09-11 23:06:34 +0000197
wdenka0ff7f22003-10-09 13:16:55 +0000198 cycle_status = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000199
wdenka0ff7f22003-10-09 13:16:55 +0000200 /*
201 * avoid timestamp overflow problem after about 68 minutes of
202 * udelay() time.
203 */
204 reset_timer_masked ();
205 for (i = 0; i < BIF_MAX; i++) {
wdenk4f7cb082003-09-11 23:06:34 +0000206
wdenka0ff7f22003-10-09 13:16:55 +0000207 /* call test function */
208 if ((*test_function[i].pf)() != 0) {
209 printf ("error in %s test\n",
210 test_function[i].name);
wdenk4f7cb082003-09-11 23:06:34 +0000211
wdenka0ff7f22003-10-09 13:16:55 +0000212 /* is it the first error? */
213 if (status == 0) {
214 status = 1;
215 first_error_cycle = act_cycle;
wdenk4f7cb082003-09-11 23:06:34 +0000216
wdenka0ff7f22003-10-09 13:16:55 +0000217 /* do not use error_num 0 */
218 first_error_num = i+1;
219 strncpy (first_error_name,
220 test_function[i].name,
221 sizeof (first_error_name));
222 led_set (0);
223 }
224 cycle_status = 1;
225 }
226 }
227 /* were all tests of actual cycle OK? */
228 if (cycle_status == 0)
229 pass_cycles++;
wdenk4f7cb082003-09-11 23:06:34 +0000230
wdenka0ff7f22003-10-09 13:16:55 +0000231 /* set status LED if no error is occoured since yet */
232 if (status == 0)
233 led_set (1);
wdenk4f7cb082003-09-11 23:06:34 +0000234
wdenka0ff7f22003-10-09 13:16:55 +0000235 printf ("%s: cycle %d finished\n", __FUNCTION__, act_cycle);
wdenk4f7cb082003-09-11 23:06:34 +0000236
wdenka0ff7f22003-10-09 13:16:55 +0000237 /* pause between cycles */
238 sdelay (BURN_IN_CYCLE_DELAY);
239 }
wdenk4f7cb082003-09-11 23:06:34 +0000240
wdenka0ff7f22003-10-09 13:16:55 +0000241 if (global_vars_write_to_eeprom () != 0) {
242 led_set (0);
243 printf ("%s: error writing global_vars to eeprom\n",
244 __FUNCTION__);
245 status = 1;
246 }
247
248 if (status == 0) {
249 led_blink (); /* endless loop!! */
250 return (0);
251 } else {
252 led_set (0);
253 return (1);
254 }
wdenk4f7cb082003-09-11 23:06:34 +0000255}
256
257U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000258 burn_in, 1, 1, do_burn_in,
Peter Tyser2fb26042009-01-27 18:03:12 -0600259 "start burn-in test application on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000260 "\n"
261 " - start burn-in test application\n"
262 " The burn-in test could took a while to finish!\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200263 " The content of the onboard EEPROM is modified!"
wdenk4f7cb082003-09-11 23:06:34 +0000264);
265
266
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200267int do_dip (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk4f7cb082003-09-11 23:06:34 +0000268{
wdenka0ff7f22003-10-09 13:16:55 +0000269 int i, dip;
wdenk4f7cb082003-09-11 23:06:34 +0000270
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200271 if (argc > 1)
272 return cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000273
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200274 if ((dip = read_dip ()) == -1)
wdenka0ff7f22003-10-09 13:16:55 +0000275 return 1;
wdenk4f7cb082003-09-11 23:06:34 +0000276
wdenka0ff7f22003-10-09 13:16:55 +0000277 for (i = 0; i < 4; i++) {
278 if ((dip & (1 << i)) == 0)
279 printf("0");
280 else
281 printf("1");
282 }
283 printf("\n");
wdenk4f7cb082003-09-11 23:06:34 +0000284
285 return 0;
286}
287
288U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000289 dip, 1, 1, do_dip,
Peter Tyser2fb26042009-01-27 18:03:12 -0600290 "read dip switch on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000291 "\n"
292 " - read state of dip switch (S1) on TRAB board\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200293 " read sequence: 1-2-3-4; ON=1; OFF=0; e.g.: \"0100\""
wdenk4f7cb082003-09-11 23:06:34 +0000294);
295
296
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200297int do_vcc5v (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk4f7cb082003-09-11 23:06:34 +0000298{
wdenka0ff7f22003-10-09 13:16:55 +0000299 int vcc5v;
wdenk4f7cb082003-09-11 23:06:34 +0000300
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200301 if (argc > 1)
302 return cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000303
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200304 if ((vcc5v = read_vcc5v ()) == -1)
wdenka0ff7f22003-10-09 13:16:55 +0000305 return (1);
wdenk4f7cb082003-09-11 23:06:34 +0000306
wdenka0ff7f22003-10-09 13:16:55 +0000307 printf ("%d", (vcc5v / 1000));
308 printf (".%d", (vcc5v % 1000) / 100);
309 printf ("%d V\n", (vcc5v % 100) / 10) ;
wdenk4f7cb082003-09-11 23:06:34 +0000310
311 return 0;
312}
313
314U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000315 vcc5v, 1, 1, do_vcc5v,
Peter Tyser2fb26042009-01-27 18:03:12 -0600316 "read VCC5V on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000317 "\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200318 " - read actual value of voltage VCC5V"
wdenk4f7cb082003-09-11 23:06:34 +0000319);
320
321
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200322int do_contact_temp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk4f7cb082003-09-11 23:06:34 +0000323{
wdenka0ff7f22003-10-09 13:16:55 +0000324 int contact_temp;
wdenk4f7cb082003-09-11 23:06:34 +0000325
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200326 if (argc > 1)
327 return cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000328
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400329 tsc2000_spi_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000330
wdenka0ff7f22003-10-09 13:16:55 +0000331 contact_temp = tsc2000_contact_temp();
332 printf ("%d degree C * 100\n", contact_temp) ;
wdenk4f7cb082003-09-11 23:06:34 +0000333
334 return 0;
335}
336
337U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000338 c_temp, 1, 1, do_contact_temp,
Peter Tyser2fb26042009-01-27 18:03:12 -0600339 "read contact temperature on TRAB",
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200340 ""
wdenka0ff7f22003-10-09 13:16:55 +0000341 " - reads the onboard temperature (=contact temperature)\n"
wdenk4f7cb082003-09-11 23:06:34 +0000342);
343
344
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200345int do_burn_in_status (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk4f7cb082003-09-11 23:06:34 +0000346{
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200347 if (argc > 1)
348 return cmd_usage(cmdtp);
wdenk4f7cb082003-09-11 23:06:34 +0000349
wdenka0ff7f22003-10-09 13:16:55 +0000350 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1,
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200351 (unsigned char*) &status, 1))
wdenka0ff7f22003-10-09 13:16:55 +0000352 return (1);
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200353
wdenka0ff7f22003-10-09 13:16:55 +0000354 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1,
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200355 (unsigned char*) &pass_cycles, 2))
wdenka0ff7f22003-10-09 13:16:55 +0000356 return (1);
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200357
wdenka0ff7f22003-10-09 13:16:55 +0000358 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE,
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200359 1, (unsigned char*) &first_error_cycle, 2))
wdenka0ff7f22003-10-09 13:16:55 +0000360 return (1);
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200361
wdenka0ff7f22003-10-09 13:16:55 +0000362 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM,
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200363 1, (unsigned char*) &first_error_num, 1))
wdenka0ff7f22003-10-09 13:16:55 +0000364 return (1);
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200365
wdenka0ff7f22003-10-09 13:16:55 +0000366 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200367 1, (unsigned char*)first_error_name,
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200368 sizeof (first_error_name)))
wdenka0ff7f22003-10-09 13:16:55 +0000369 return (1);
wdenk4f7cb082003-09-11 23:06:34 +0000370
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200371 if (read_max_cycles () != 0)
wdenka0ff7f22003-10-09 13:16:55 +0000372 return (1);
wdenk4f7cb082003-09-11 23:06:34 +0000373
wdenka0ff7f22003-10-09 13:16:55 +0000374 printf ("max_cycles = %d\n", max_cycles);
375 printf ("status = %d\n", status);
376 printf ("pass_cycles = %d\n", pass_cycles);
377 printf ("first_error_cycle = %d\n", first_error_cycle);
378 printf ("first_error_num = %d\n", first_error_num);
379 printf ("first_error_name = %.*s\n",(int) sizeof(first_error_name),
380 first_error_name);
wdenk4f7cb082003-09-11 23:06:34 +0000381
382 return 0;
383}
384
385U_BOOT_CMD(
wdenka0ff7f22003-10-09 13:16:55 +0000386 bis, 1, 1, do_burn_in_status,
Peter Tyser2fb26042009-01-27 18:03:12 -0600387 "print burn in status on TRAB",
wdenka0ff7f22003-10-09 13:16:55 +0000388 "\n"
389 " - prints the status variables of the last burn in test\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200390 " stored in the onboard EEPROM on TRAB board"
wdenk4f7cb082003-09-11 23:06:34 +0000391);
392
393static int read_dip (void)
394{
wdenka0ff7f22003-10-09 13:16:55 +0000395 unsigned int result = 0;
396 int adc_val;
397 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000398
399 /***********************************************************
400 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
401 SW1 - AIN4
402 SW2 - AIN5
403 SW3 - AIN6
404 SW4 - AIN7
405
406 "On" DIP switch position short-circuits the voltage from
407 the input channel (i.e. '0' conversion result means "on").
408 *************************************************************/
409
410 for (i = 7; i > 3; i--) {
411
wdenka0ff7f22003-10-09 13:16:55 +0000412 if ((adc_val = adc_read (i)) == -1) {
413 printf ("%s: Channel %d could not be read\n",
414 __FUNCTION__, i);
415 return (-1);
416 }
wdenk4f7cb082003-09-11 23:06:34 +0000417
418 /*
419 * Input voltage (switch open) is 1.8 V.
420 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
421 * Set trigger at halve that value.
422 */
423 if (adc_val < 368)
wdenka0ff7f22003-10-09 13:16:55 +0000424 result |= (1 << (i-4));
425 }
426 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000427}
428
429
430static int read_vcc5v (void)
431{
wdenka0ff7f22003-10-09 13:16:55 +0000432 s32 result;
wdenk4f7cb082003-09-11 23:06:34 +0000433
wdenka0ff7f22003-10-09 13:16:55 +0000434 /* VCC5V is connected to channel 2 */
wdenk4f7cb082003-09-11 23:06:34 +0000435
wdenka0ff7f22003-10-09 13:16:55 +0000436 if ((result = adc_read (2)) == -1) {
437 printf ("%s: VCC5V could not be read\n", __FUNCTION__);
438 return (-1);
439 }
440 /*
441 * Calculate voltage value. Split in two parts because there is no
442 * floating point support. VCC5V is connected over an resistor divider:
443 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
444 */
445 result = result * 10 * 1000 / 1023; /* result in mV */
wdenk4f7cb082003-09-11 23:06:34 +0000446
wdenka0ff7f22003-10-09 13:16:55 +0000447 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000448}
449
450
451static int test_dip (void)
452{
wdenka0ff7f22003-10-09 13:16:55 +0000453 static int first_run = 1;
454 static int first_dip;
wdenk4f7cb082003-09-11 23:06:34 +0000455
wdenka0ff7f22003-10-09 13:16:55 +0000456 if (first_run) {
457 if ((first_dip = read_dip ()) == -1) {
458 return (1);
459 }
460 first_run = 0;
461 debug ("%s: first_dip=%d\n", __FUNCTION__, first_dip);
462 }
463 if (first_dip != read_dip ()) {
464 return (1);
465 } else {
466 return (0);
467 }
wdenk4f7cb082003-09-11 23:06:34 +0000468}
469
470
471static int test_vcc5v (void)
472{
wdenka0ff7f22003-10-09 13:16:55 +0000473 int vcc5v;
wdenk4f7cb082003-09-11 23:06:34 +0000474
wdenka0ff7f22003-10-09 13:16:55 +0000475 if ((vcc5v = read_vcc5v ()) == -1) {
476 return (1);
477 }
wdenk4f7cb082003-09-11 23:06:34 +0000478
wdenka0ff7f22003-10-09 13:16:55 +0000479 if ((vcc5v > VCC5V_MAX) || (vcc5v < VCC5V_MIN)) {
480 printf ("%s: vcc5v[V/100]=%d\n", __FUNCTION__, vcc5v);
481 return (1);
482 } else {
483 return (0);
484 }
wdenk4f7cb082003-09-11 23:06:34 +0000485}
486
487
488static int test_rotary_switch (void)
489{
wdenka0ff7f22003-10-09 13:16:55 +0000490 static int first_run = 1;
491 static int first_rs;
wdenk4f7cb082003-09-11 23:06:34 +0000492
wdenka0ff7f22003-10-09 13:16:55 +0000493 if (first_run) {
494 /*
495 * clear bits in CPLD, because they have random values after
496 * power-up or reset.
497 */
498 *CPLD_ROTARY_SWITCH |= (1 << 16) | (1 << 17);
wdenk4f7cb082003-09-11 23:06:34 +0000499
wdenka0ff7f22003-10-09 13:16:55 +0000500 first_rs = ((*CPLD_ROTARY_SWITCH >> 16) & 0x7);
501 first_run = 0;
502 debug ("%s: first_rs=%d\n", __FUNCTION__, first_rs);
503 }
wdenk4f7cb082003-09-11 23:06:34 +0000504
wdenka0ff7f22003-10-09 13:16:55 +0000505 if (first_rs != ((*CPLD_ROTARY_SWITCH >> 16) & 0x7)) {
506 return (1);
507 } else {
508 return (0);
509 }
wdenk4f7cb082003-09-11 23:06:34 +0000510}
511
512
513static int test_sram (void)
514{
wdenka0ff7f22003-10-09 13:16:55 +0000515 return (memory_post_tests (SRAM_ADDR, SRAM_SIZE));
wdenk4f7cb082003-09-11 23:06:34 +0000516}
517
518
519static int test_eeprom (void)
520{
wdenka0ff7f22003-10-09 13:16:55 +0000521 unsigned char temp[sizeof (EEPROM_TEST_STRING_1)];
522 int result = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000523
wdenka0ff7f22003-10-09 13:16:55 +0000524 /* write test string 1, read back and verify */
525 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200526 (unsigned char*)EEPROM_TEST_STRING_1,
wdenka0ff7f22003-10-09 13:16:55 +0000527 sizeof (EEPROM_TEST_STRING_1))) {
528 return (1);
529 }
wdenk4f7cb082003-09-11 23:06:34 +0000530
wdenka0ff7f22003-10-09 13:16:55 +0000531 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
532 temp, sizeof (EEPROM_TEST_STRING_1))) {
533 return (1);
534 }
wdenk4f7cb082003-09-11 23:06:34 +0000535
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200536 if (strcmp ((char *)temp, EEPROM_TEST_STRING_1) != 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000537 result = 1;
538 printf ("%s: error; read_str = \"%s\"\n", __FUNCTION__, temp);
539 }
wdenk4f7cb082003-09-11 23:06:34 +0000540
wdenka0ff7f22003-10-09 13:16:55 +0000541 /* write test string 2, read back and verify */
542 if (result == 0) {
543 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200544 (unsigned char*)EEPROM_TEST_STRING_2,
wdenka0ff7f22003-10-09 13:16:55 +0000545 sizeof (EEPROM_TEST_STRING_2))) {
546 return (1);
547 }
wdenk4f7cb082003-09-11 23:06:34 +0000548
wdenka0ff7f22003-10-09 13:16:55 +0000549 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_TEST, 1,
550 temp, sizeof (EEPROM_TEST_STRING_2))) {
551 return (1);
552 }
wdenk4f7cb082003-09-11 23:06:34 +0000553
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200554 if (strcmp ((char *)temp, EEPROM_TEST_STRING_2) != 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000555 result = 1;
556 printf ("%s: error; read str = \"%s\"\n",
557 __FUNCTION__, temp);
558 }
559 }
560 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000561}
562
563
564static int test_contact_temp (void)
565{
wdenka0ff7f22003-10-09 13:16:55 +0000566 int contact_temp;
wdenk4f7cb082003-09-11 23:06:34 +0000567
wdenka0ff7f22003-10-09 13:16:55 +0000568 contact_temp = tsc2000_contact_temp ();
wdenk4f7cb082003-09-11 23:06:34 +0000569
wdenka0ff7f22003-10-09 13:16:55 +0000570 if ((contact_temp < MIN_CONTACT_TEMP)
571 || (contact_temp > MAX_CONTACT_TEMP))
572 return (1);
573 else
574 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000575}
576
577
wdenkf54ebdf2003-09-17 15:10:32 +0000578int i2c_write_multiple (uchar chip, uint addr, int alen,
579 uchar *buffer, int len)
wdenk4f7cb082003-09-11 23:06:34 +0000580{
wdenka0ff7f22003-10-09 13:16:55 +0000581 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000582
wdenka0ff7f22003-10-09 13:16:55 +0000583 if (alen != 1) {
584 printf ("%s: addr len other than 1 not supported\n",
585 __FUNCTION__);
586 return (1);
587 }
wdenk4f7cb082003-09-11 23:06:34 +0000588
wdenka0ff7f22003-10-09 13:16:55 +0000589 for (i = 0; i < len; i++) {
590 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
591 printf ("%s: could not write to i2c device %d"
592 ", addr %d\n", __FUNCTION__, chip, addr);
593 return (1);
594 }
wdenk4f7cb082003-09-11 23:06:34 +0000595#if 0
wdenka0ff7f22003-10-09 13:16:55 +0000596 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
597 "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
598 alen, buffer, i, buffer+i, buffer+i);
wdenk4f7cb082003-09-11 23:06:34 +0000599#endif
600
wdenka0ff7f22003-10-09 13:16:55 +0000601 udelay (30000);
602 }
603 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000604}
605
606
wdenkf54ebdf2003-09-17 15:10:32 +0000607int i2c_read_multiple ( uchar chip, uint addr, int alen,
608 uchar *buffer, int len)
wdenk4f7cb082003-09-11 23:06:34 +0000609{
wdenka0ff7f22003-10-09 13:16:55 +0000610 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000611
wdenka0ff7f22003-10-09 13:16:55 +0000612 if (alen != 1) {
613 printf ("%s: addr len other than 1 not supported\n",
614 __FUNCTION__);
615 return (1);
616 }
wdenk4f7cb082003-09-11 23:06:34 +0000617
wdenka0ff7f22003-10-09 13:16:55 +0000618 for (i = 0; i < len; i++) {
619 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
620 printf ("%s: could not read from i2c device %#x"
621 ", addr %d\n", __FUNCTION__, chip, addr);
622 return (1);
623 }
624 }
625 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000626}
627
628
629static int adc_read (unsigned int channel)
630{
wdenka0ff7f22003-10-09 13:16:55 +0000631 int j = 1000; /* timeout value for wait loop in us */
632 int result;
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900633 struct s3c2400_adc *padc;
wdenk4f7cb082003-09-11 23:06:34 +0000634
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900635 padc = s3c2400_get_base_adc();
wdenka0ff7f22003-10-09 13:16:55 +0000636 channel &= 0x7;
wdenk4f7cb082003-09-11 23:06:34 +0000637
wdenka0ff7f22003-10-09 13:16:55 +0000638 adc_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000639
wdenka0ff7f22003-10-09 13:16:55 +0000640 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
wdenk4f7cb082003-09-11 23:06:34 +0000641 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
wdenka0ff7f22003-10-09 13:16:55 +0000642 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
wdenk4f7cb082003-09-11 23:06:34 +0000643
wdenka0ff7f22003-10-09 13:16:55 +0000644 while (j--) {
645 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
646 break;
647 udelay (1);
648 }
wdenk4f7cb082003-09-11 23:06:34 +0000649
wdenka0ff7f22003-10-09 13:16:55 +0000650 if (j == 0) {
651 printf("%s: ADC timeout\n", __FUNCTION__);
652 padc->ADCCON |= ADC_STDBM; /* select standby mode */
653 return -1;
654 }
wdenk4f7cb082003-09-11 23:06:34 +0000655
wdenka0ff7f22003-10-09 13:16:55 +0000656 result = padc->ADCDAT & 0x3FF;
wdenk4f7cb082003-09-11 23:06:34 +0000657
wdenka0ff7f22003-10-09 13:16:55 +0000658 padc->ADCCON |= ADC_STDBM; /* select standby mode */
wdenk4f7cb082003-09-11 23:06:34 +0000659
wdenka0ff7f22003-10-09 13:16:55 +0000660 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
661 (padc->ADCCON >> 3) & 0x7, result);
wdenk4f7cb082003-09-11 23:06:34 +0000662
wdenka0ff7f22003-10-09 13:16:55 +0000663 /*
664 * Wait for ADC to be ready for next conversion. This delay value was
665 * estimated, because the datasheet does not specify a value.
666 */
667 udelay (1000);
668
669 return (result);
wdenk4f7cb082003-09-11 23:06:34 +0000670}
671
672
673static void adc_init (void)
674{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900675 struct s3c2400_adc *padc;
wdenk4f7cb082003-09-11 23:06:34 +0000676
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900677 padc = s3c2400_get_base_adc();
wdenk4f7cb082003-09-11 23:06:34 +0000678
679 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
680 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
681
wdenka0ff7f22003-10-09 13:16:55 +0000682 /*
683 * Wait some time to avoid problem with very first call of
684 * adc_read(). Without this delay, sometimes the first read
685 * adc value is 0. Perhaps because the adjustment of prescaler
686 * takes some clock cycles?
687 */
688 udelay (1000);
689
690 return;
wdenk4f7cb082003-09-11 23:06:34 +0000691}
692
693
694static void led_set (unsigned int state)
695{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900696 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenk4f7cb082003-09-11 23:06:34 +0000697
wdenka0ff7f22003-10-09 13:16:55 +0000698 led_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000699
wdenka0ff7f22003-10-09 13:16:55 +0000700 switch (state) {
701 case 0: /* turn LED off */
702 gpio->PADAT |= (1 << 12);
703 break;
704 case 1: /* turn LED on */
705 gpio->PADAT &= ~(1 << 12);
706 break;
707 default:
wdenke86e5a02004-10-17 21:12:06 +0000708 break;
wdenka0ff7f22003-10-09 13:16:55 +0000709 }
wdenk4f7cb082003-09-11 23:06:34 +0000710}
711
712static void led_blink (void)
713{
wdenka0ff7f22003-10-09 13:16:55 +0000714 led_init ();
wdenk4f7cb082003-09-11 23:06:34 +0000715
wdenka0ff7f22003-10-09 13:16:55 +0000716 /* blink LED. This function does not return! */
717 while (1) {
Wolfgang Denkb9fff8e2006-06-16 15:52:58 +0200718 reset_timer_masked ();
wdenka0ff7f22003-10-09 13:16:55 +0000719 led_set (1);
720 udelay (1000000 / LED_BLINK_FREQ / 2);
721 led_set (0);
722 udelay (1000000 / LED_BLINK_FREQ / 2);
723 }
wdenk4f7cb082003-09-11 23:06:34 +0000724}
725
726
727static void led_init (void)
728{
kevin.morfitt@fearnside-systems.co.ukeb0ae7f2009-10-10 13:33:11 +0900729 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
wdenk4f7cb082003-09-11 23:06:34 +0000730
wdenka0ff7f22003-10-09 13:16:55 +0000731 /* configure GPA12 as output and set to High -> LED off */
732 gpio->PACON &= ~(1 << 12);
733 gpio->PADAT |= (1 << 12);
wdenk4f7cb082003-09-11 23:06:34 +0000734}
735
736
737static void sdelay (unsigned long seconds)
738{
wdenka0ff7f22003-10-09 13:16:55 +0000739 unsigned long i;
wdenk4f7cb082003-09-11 23:06:34 +0000740
wdenka0ff7f22003-10-09 13:16:55 +0000741 for (i = 0; i < seconds; i++) {
742 udelay (1000000);
743 }
wdenk4f7cb082003-09-11 23:06:34 +0000744}
745
746
747static int global_vars_write_to_eeprom (void)
748{
wdenka0ff7f22003-10-09 13:16:55 +0000749 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_STATUS, 1,
750 (unsigned char*) &status, 1)) {
751 return (1);
752 }
753 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_PASS_CYCLES, 1,
754 (unsigned char*) &pass_cycles, 2)) {
755 return (1);
756 }
757 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_CYCLE,
758 1, (unsigned char*) &first_error_cycle, 2)) {
759 return (1);
760 }
761 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NUM,
762 1, (unsigned char*) &first_error_num, 1)) {
763 return (1);
764 }
765 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_FIRST_ERROR_NAME,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200766 1, (unsigned char*) first_error_name,
wdenka0ff7f22003-10-09 13:16:55 +0000767 sizeof(first_error_name))) {
768 return (1);
769 }
770 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000771}
772
773static void global_vars_init (void)
774{
wdenka0ff7f22003-10-09 13:16:55 +0000775 status = 1; /* error */
776 pass_cycles = 0;
777 first_error_cycle = 0;
778 first_error_num = 0;
779 first_error_name[0] = '\0';
780 act_cycle = 0;
781 max_cycles = 0;
wdenk4f7cb082003-09-11 23:06:34 +0000782}
783
784
785static void test_function_table_init (void)
786{
wdenka0ff7f22003-10-09 13:16:55 +0000787 int i;
wdenk4f7cb082003-09-11 23:06:34 +0000788
wdenka0ff7f22003-10-09 13:16:55 +0000789 for (i = 0; i < BIF_MAX; i++)
wdenk4f7cb082003-09-11 23:06:34 +0000790 test_function[i].pf = dummy;
791
wdenka0ff7f22003-10-09 13:16:55 +0000792 /*
793 * the length of "name" must not exceed 16, including the '\0'
794 * termination. See also the EEPROM address map.
795 */
796 test_function[0].pf = test_dip;
797 test_function[0].name = "dip";
wdenk4f7cb082003-09-11 23:06:34 +0000798
wdenka0ff7f22003-10-09 13:16:55 +0000799 test_function[1].pf = test_vcc5v;
800 test_function[1].name = "vcc5v";
wdenk4f7cb082003-09-11 23:06:34 +0000801
wdenka0ff7f22003-10-09 13:16:55 +0000802 test_function[2].pf = test_rotary_switch;
803 test_function[2].name = "rotary_switch";
wdenk4f7cb082003-09-11 23:06:34 +0000804
wdenka0ff7f22003-10-09 13:16:55 +0000805 test_function[3].pf = test_sram;
806 test_function[3].name = "sram";
wdenk4f7cb082003-09-11 23:06:34 +0000807
wdenka0ff7f22003-10-09 13:16:55 +0000808 test_function[4].pf = test_eeprom;
809 test_function[4].name = "eeprom";
wdenk4f7cb082003-09-11 23:06:34 +0000810
wdenka0ff7f22003-10-09 13:16:55 +0000811 test_function[5].pf = test_contact_temp;
812 test_function[5].name = "contact_temp";
wdenk4f7cb082003-09-11 23:06:34 +0000813}
814
815
816static int read_max_cycles (void)
817{
wdenka0ff7f22003-10-09 13:16:55 +0000818 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, EE_ADDR_MAX_CYCLES, 1,
819 (unsigned char *) &max_cycles, 2) != 0) {
820 return (1);
821 }
wdenk4f7cb082003-09-11 23:06:34 +0000822
wdenka0ff7f22003-10-09 13:16:55 +0000823 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000824}
825
826static int dummy(void)
827{
wdenka0ff7f22003-10-09 13:16:55 +0000828 return (0);
wdenk4f7cb082003-09-11 23:06:34 +0000829}
830
Wolfgang Denk54841ab2010-06-28 22:00:46 +0200831int do_temp_log (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
wdenk151ab832005-02-24 22:44:16 +0000832{
833 int contact_temp;
834 int delay = 0;
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500835#if defined(CONFIG_CMD_DATE)
wdenk151ab832005-02-24 22:44:16 +0000836 struct rtc_time tm;
837#endif
838
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200839 if (argc > 2)
840 return cmd_usage(cmdtp);
wdenk151ab832005-02-24 22:44:16 +0000841
Wolfgang Denk47e26b12010-07-17 01:06:04 +0200842 if (argc > 1)
wdenk151ab832005-02-24 22:44:16 +0000843 delay = simple_strtoul(argv[1], NULL, 10);
wdenk151ab832005-02-24 22:44:16 +0000844
Mike Frysingerf6e3a1f2009-08-13 00:32:14 -0400845 tsc2000_spi_init ();
wdenk151ab832005-02-24 22:44:16 +0000846 while (1) {
847
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500848#if defined(CONFIG_CMD_DATE)
wdenk151ab832005-02-24 22:44:16 +0000849 rtc_get (&tm);
850 printf ("%4d-%02d-%02d %2d:%02d:%02d - ",
851 tm.tm_year, tm.tm_mon, tm.tm_mday,
852 tm.tm_hour, tm.tm_min, tm.tm_sec);
853#endif
854
855 contact_temp = tsc2000_contact_temp();
856 printf ("%d\n", contact_temp) ;
857
858 if (delay != 0)
859 /*
860 * reset timer to avoid timestamp overflow problem
861 * after about 68 minutes of udelay() time.
862 */
863 reset_timer_masked ();
864 sdelay (delay);
865 }
866
867 return 0;
868}
869
870U_BOOT_CMD(
871 tlog, 2, 1, do_temp_log,
Peter Tyser2fb26042009-01-27 18:03:12 -0600872 "log contact temperature [1/100 C] to console (endlessly)",
wdenk151ab832005-02-24 22:44:16 +0000873 "delay\n"
874 " - contact temperature [1/100 C] is printed endlessly to console\n"
875 " <delay> specifies the seconds to wait between two measurements\n"
Wolfgang Denka89c33d2009-05-24 17:06:54 +0200876 " For each measurment a timestamp is printeted"
wdenk151ab832005-02-24 22:44:16 +0000877);
878
Jon Loeligerd39b5742007-07-10 10:48:22 -0500879#endif