blob: 56a80ff4cdd8a83254ecbb8f77f5f67e1ab86151 [file] [log] [blame]
wdenkf5300ab2003-09-12 15:35:15 +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
24#define DEBUG
25
26#include <common.h>
27#include <exports.h>
28#include <s3c2400.h>
29#include "tsc2000.h"
30#include "rs485.h"
31
wdenka0ff7f22003-10-09 13:16:55 +000032/*
33 * define, to wait for the touch to be pressed, before reading coordinates in
34 * command do_touch. If not defined, an error message is printed, when the
35 * command do_touch is invoked and the touch is not pressed within an specific
36 * interval.
37 */
wdenke86e5a02004-10-17 21:12:06 +000038#undef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +000039
40/* max time to wait for touch is pressed */
41#ifndef CONFIG_TOUCH_WAIT_PRESSED
42#define TOUCH_TIMEOUT 5
43#endif /* !CONFIG_TOUCH_WAIT_PRESSED */
44
wdenkf5300ab2003-09-12 15:35:15 +000045/* assignment of CPU internal ADC channels with TRAB hardware */
46#define VCC5V 2
47#define VCC12V 3
48
49/* CPLD-Register for controlling TRAB hardware functions */
50#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
51#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
52#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
53#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
54
55/* timer configuration bits for buzzer and PWM */
56#define START2 (1 << 12)
57#define UPDATE2 (1 << 13)
58#define INVERT2 (1 << 14)
59#define RELOAD2 (1 << 15)
60#define START3 (1 << 16)
61#define UPDATE3 (1 << 17)
62#define INVERT3 (1 << 18)
63#define RELOAD3 (1 << 19)
64
65#define PCLK 66000000
66#define BUZZER_FREQ 1000 /* frequency in Hz */
wdenkf5300ab2003-09-12 15:35:15 +000067#define PWM_FREQ 500
68
69
70/* definitions of I2C EEPROM device address */
71#define I2C_EEPROM_DEV_ADDR 0x54
72
73/* definition for touch panel calibration points */
74#define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
75#define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
76
wdenka0ff7f22003-10-09 13:16:55 +000077/* EEPROM address map */
wdenkf5300ab2003-09-12 15:35:15 +000078#define SERIAL_NUMBER 8
79#define TOUCH_X0 52
80#define TOUCH_Y0 54
81#define TOUCH_X1 56
82#define TOUCH_Y1 58
83#define CRC16 60
84
85/* EEPROM stuff */
86#define EEPROM_MAX_CRC_BUF 64
87
88/* RS485 stuff */
89#define RS485_MAX_RECEIVE_BUF_LEN 100
90
91/* Bit definitions for ADCCON */
92#define ADC_ENABLE_START 0x1
93#define ADC_READ_START 0x2
94#define ADC_STDBM 0x4
95#define ADC_INP_AIN0 (0x0 << 3)
96#define ADC_INP_AIN1 (0x1 << 3)
97#define ADC_INP_AIN2 (0x2 << 3)
98#define ADC_INP_AIN3 (0x3 << 3)
99#define ADC_INP_AIN4 (0x4 << 3)
100#define ADC_INP_AIN5 (0x5 << 3)
101#define ADC_INP_AIN6 (0x6 << 3)
102#define ADC_INP_AIN7 (0x7 << 3)
103#define ADC_PRSCEN 0x4000
104#define ADC_ECFLG 0x8000
105
106/* function test functions */
107int do_dip (void);
108int do_info (void);
109int do_vcc5v (void);
110int do_vcc12v (void);
111int do_buttons (void);
112int do_fill_level (void);
113int do_rotary_switch (void);
114int do_pressure (void);
115int do_v_bat (void);
116int do_vfd_id (void);
wdenka0ff7f22003-10-09 13:16:55 +0000117int do_buzzer (char **);
wdenkf5300ab2003-09-12 15:35:15 +0000118int do_led (char **);
119int do_full_bridge (char **);
120int do_dac (char **);
121int do_motor_contact (void);
122int do_motor (char **);
123int do_pwm (char **);
124int do_thermo (char **);
125int do_touch (char **);
126int do_rs485 (char **);
127int do_serial_number (char **);
128int do_crc16 (void);
wdenka0ff7f22003-10-09 13:16:55 +0000129int do_power_switch (void);
130int do_gain (char **);
131int do_eeprom (char **);
wdenkf5300ab2003-09-12 15:35:15 +0000132
133/* helper functions */
134static void adc_init (void);
135static int adc_read (unsigned int channel);
136static void print_identifier (void);
wdenka0ff7f22003-10-09 13:16:55 +0000137
138#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenkf5300ab2003-09-12 15:35:15 +0000139static void touch_wait_pressed (void);
wdenka0ff7f22003-10-09 13:16:55 +0000140#else
141static int touch_check_pressed (void);
142#endif /* CONFIG_TOUCH_WAIT_PRESSED */
143
wdenkf5300ab2003-09-12 15:35:15 +0000144static void touch_read_x_y (int *x, int *y);
145static int touch_write_clibration_values (int calib_point, int x, int y);
146static int rs485_send_line (const char *data);
147static int rs485_receive_chars (char *data, int timeout);
148static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
wdenka0ff7f22003-10-09 13:16:55 +0000149 unsigned int icnt);
wdenkf5300ab2003-09-12 15:35:15 +0000150
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500151#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +0000152static int trab_eeprom_read (char **argv);
153static int trab_eeprom_write (char **argv);
154int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
155 int len);
156int i2c_read_multiple ( uchar chip, uint addr, int alen, uchar *buffer,
157 int len);
158#endif /* CFG_CMD_I2C */
wdenkf5300ab2003-09-12 15:35:15 +0000159
160/*
161 * TRAB board specific commands. Especially commands for burn-in and function
162 * test.
163 */
164
165int trab_fkt (int argc, char *argv[])
166{
wdenka0ff7f22003-10-09 13:16:55 +0000167 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000168
wdenka0ff7f22003-10-09 13:16:55 +0000169 app_startup(argv);
170 if (get_version () != XF_VERSION) {
171 printf ("Wrong XF_VERSION. Please re-compile with actual "
172 "u-boot sources\n");
173 printf ("Example expects ABI version %d\n", XF_VERSION);
174 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
175 return 1;
176 }
wdenkf5300ab2003-09-12 15:35:15 +0000177
wdenka0ff7f22003-10-09 13:16:55 +0000178 debug ("argc = %d\n", argc);
wdenkf5300ab2003-09-12 15:35:15 +0000179
180 for (i=0; i<=argc; ++i) {
181 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
wdenka0ff7f22003-10-09 13:16:55 +0000182 }
wdenkf5300ab2003-09-12 15:35:15 +0000183
wdenka0ff7f22003-10-09 13:16:55 +0000184 adc_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000185
186 switch (argc) {
187
188 case 0:
189 case 1:
190 break;
191
192 case 2:
193 if (strcmp (argv[1], "info") == 0) {
wdenka0ff7f22003-10-09 13:16:55 +0000194 return (do_info ());
wdenkf5300ab2003-09-12 15:35:15 +0000195 }
wdenka0ff7f22003-10-09 13:16:55 +0000196 if (strcmp (argv[1], "dip") == 0) {
197 return (do_dip ());
198 }
199 if (strcmp (argv[1], "vcc5v") == 0) {
200 return (do_vcc5v ());
201 }
202 if (strcmp (argv[1], "vcc12v") == 0) {
203 return (do_vcc12v ());
204 }
205 if (strcmp (argv[1], "buttons") == 0) {
206 return (do_buttons ());
207 }
208 if (strcmp (argv[1], "fill_level") == 0) {
209 return (do_fill_level ());
210 }
211 if (strcmp (argv[1], "rotary_switch") == 0) {
212 return (do_rotary_switch ());
213 }
214 if (strcmp (argv[1], "pressure") == 0) {
215 return (do_pressure ());
216 }
217 if (strcmp (argv[1], "v_bat") == 0) {
218 return (do_v_bat ());
219 }
220 if (strcmp (argv[1], "vfd_id") == 0) {
221 return (do_vfd_id ());
222 }
223 if (strcmp (argv[1], "motor_contact") == 0) {
224 return (do_motor_contact ());
225 }
226 if (strcmp (argv[1], "crc16") == 0) {
227 return (do_crc16 ());
228 }
229 if (strcmp (argv[1], "power_switch") == 0) {
230 return (do_power_switch ());
231 }
232 break;
wdenkf5300ab2003-09-12 15:35:15 +0000233
234 case 3:
wdenka0ff7f22003-10-09 13:16:55 +0000235 if (strcmp (argv[1], "full_bridge") == 0) {
236 return (do_full_bridge (argv));
237 }
238 if (strcmp (argv[1], "dac") == 0) {
239 return (do_dac (argv));
240 }
241 if (strcmp (argv[1], "motor") == 0) {
242 return (do_motor (argv));
243 }
244 if (strcmp (argv[1], "pwm") == 0) {
245 return (do_pwm (argv));
246 }
247 if (strcmp (argv[1], "thermo") == 0) {
248 return (do_thermo (argv));
249 }
250 if (strcmp (argv[1], "touch") == 0) {
251 return (do_touch (argv));
252 }
253 if (strcmp (argv[1], "serial_number") == 0) {
254 return (do_serial_number (argv));
255 }
256 if (strcmp (argv[1], "buzzer") == 0) {
257 return (do_buzzer (argv));
258 }
259 if (strcmp (argv[1], "gain") == 0) {
260 return (do_gain (argv));
261 }
262 break;
wdenkf5300ab2003-09-12 15:35:15 +0000263
wdenka0ff7f22003-10-09 13:16:55 +0000264 case 4:
265 if (strcmp (argv[1], "led") == 0) {
266 return (do_led (argv));
267 }
268 if (strcmp (argv[1], "rs485") == 0) {
269 return (do_rs485 (argv));
270 }
271 if (strcmp (argv[1], "serial_number") == 0) {
272 return (do_serial_number (argv));
273 }
274 break;
275
276 case 5:
277 if (strcmp (argv[1], "eeprom") == 0) {
278 return (do_eeprom (argv));
279 }
280 break;
281
282 case 6:
283 if (strcmp (argv[1], "eeprom") == 0) {
284 return (do_eeprom (argv));
285 }
286 break;
wdenkf5300ab2003-09-12 15:35:15 +0000287
288 default:
289 break;
290 }
291
292 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
wdenka0ff7f22003-10-09 13:16:55 +0000293 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000294}
295
296int do_info (void)
297{
wdenka0ff7f22003-10-09 13:16:55 +0000298 printf ("Stand-alone application for TRAB board function test\n");
299 printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
wdenkf5300ab2003-09-12 15:35:15 +0000300
301 return 0;
302}
303
304int do_dip (void)
305{
wdenka0ff7f22003-10-09 13:16:55 +0000306 unsigned int result = 0;
307 int adc_val;
308 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000309
310 /***********************************************************
311 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
312 SW1 - AIN4
313 SW2 - AIN5
314 SW3 - AIN6
315 SW4 - AIN7
316
317 "On" DIP switch position short-circuits the voltage from
318 the input channel (i.e. '0' conversion result means "on").
319 *************************************************************/
320
321 for (i = 7; i > 3; i--) {
322
wdenka0ff7f22003-10-09 13:16:55 +0000323 if ((adc_val = adc_read (i)) == -1) {
324 printf ("Channel %d could not be read\n", i);
325 return 1;
326 }
wdenkf5300ab2003-09-12 15:35:15 +0000327
328 /*
329 * Input voltage (switch open) is 1.8 V.
330 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
331 * Set trigger at halve that value.
332 */
333 if (adc_val < 368)
wdenka0ff7f22003-10-09 13:16:55 +0000334 result |= (1 << (i-4));
335 }
wdenkf5300ab2003-09-12 15:35:15 +0000336
wdenka0ff7f22003-10-09 13:16:55 +0000337 /* print result to console */
338 print_identifier ();
339 for (i = 0; i < 4; i++) {
340 if ((result & (1 << i)) == 0)
341 printf("0");
342 else
343 printf("1");
344 }
345 printf("\n");
wdenkf5300ab2003-09-12 15:35:15 +0000346
347 return 0;
348}
349
350
351int do_vcc5v (void)
352{
wdenka0ff7f22003-10-09 13:16:55 +0000353 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000354
wdenka0ff7f22003-10-09 13:16:55 +0000355 /* VCC5V is connected to channel 2 */
wdenkf5300ab2003-09-12 15:35:15 +0000356
wdenka0ff7f22003-10-09 13:16:55 +0000357 if ((result = adc_read (VCC5V)) == -1) {
358 printf ("VCC5V could not be read\n");
359 return 1;
360 }
wdenkf5300ab2003-09-12 15:35:15 +0000361
wdenka0ff7f22003-10-09 13:16:55 +0000362 /*
363 * Calculate voltage value. Split in two parts because there is no
364 * floating point support. VCC5V is connected over an resistor divider:
365 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
366 */
367 print_identifier ();
368 printf ("%d", (result & 0x3FF)* 10 / 1023);
369 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
370 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
371 * 10 / 1024);
wdenkf5300ab2003-09-12 15:35:15 +0000372
373 return 0;
374}
375
376
377int do_vcc12v (void)
378{
wdenka0ff7f22003-10-09 13:16:55 +0000379 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000380
wdenka0ff7f22003-10-09 13:16:55 +0000381 if ((result = adc_read (VCC12V)) == -1) {
382 printf ("VCC12V could not be read\n");
383 return 1;
384 }
wdenkf5300ab2003-09-12 15:35:15 +0000385
wdenka0ff7f22003-10-09 13:16:55 +0000386 /*
387 * Calculate voltage value. Split in two parts because there is no
388 * floating point support. VCC5V is connected over an resistor divider:
389 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
390 */
391 print_identifier ();
392 printf ("%d", (result & 0x3FF)* 25 / 1023);
393 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
wdenkf5300ab2003-09-12 15:35:15 +0000394
wdenka0ff7f22003-10-09 13:16:55 +0000395 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000396}
397
398static int adc_read (unsigned int channel)
399{
wdenka0ff7f22003-10-09 13:16:55 +0000400 int j = 1000; /* timeout value for wait loop in us */
401 int result;
402 S3C2400_ADC *padc;
wdenkf5300ab2003-09-12 15:35:15 +0000403
wdenka0ff7f22003-10-09 13:16:55 +0000404 padc = S3C2400_GetBase_ADC();
405 channel &= 0x7;
wdenkf5300ab2003-09-12 15:35:15 +0000406
wdenka0ff7f22003-10-09 13:16:55 +0000407 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
wdenkf5300ab2003-09-12 15:35:15 +0000408 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
wdenka0ff7f22003-10-09 13:16:55 +0000409 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
wdenkf5300ab2003-09-12 15:35:15 +0000410
wdenka0ff7f22003-10-09 13:16:55 +0000411 while (j--) {
412 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
413 break;
414 udelay (1);
415 }
wdenkf5300ab2003-09-12 15:35:15 +0000416
wdenka0ff7f22003-10-09 13:16:55 +0000417 if (j == 0) {
418 printf("%s: ADC timeout\n", __FUNCTION__);
419 padc->ADCCON |= ADC_STDBM; /* select standby mode */
420 return -1;
421 }
wdenkf5300ab2003-09-12 15:35:15 +0000422
wdenka0ff7f22003-10-09 13:16:55 +0000423 result = padc->ADCDAT & 0x3FF;
wdenkf5300ab2003-09-12 15:35:15 +0000424
wdenka0ff7f22003-10-09 13:16:55 +0000425 padc->ADCCON |= ADC_STDBM; /* select standby mode */
wdenkf5300ab2003-09-12 15:35:15 +0000426
wdenka0ff7f22003-10-09 13:16:55 +0000427 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
428 (padc->ADCCON >> 3) & 0x7, result);
wdenkf5300ab2003-09-12 15:35:15 +0000429
wdenka0ff7f22003-10-09 13:16:55 +0000430 /*
431 * Wait for ADC to be ready for next conversion. This delay value was
432 * estimated, because the datasheet does not specify a value.
433 */
434 udelay (1000);
435
436 return (result);
wdenkf5300ab2003-09-12 15:35:15 +0000437}
438
439
440static void adc_init (void)
441{
wdenka0ff7f22003-10-09 13:16:55 +0000442 S3C2400_ADC *padc;
wdenkf5300ab2003-09-12 15:35:15 +0000443
wdenka0ff7f22003-10-09 13:16:55 +0000444 padc = S3C2400_GetBase_ADC();
wdenkf5300ab2003-09-12 15:35:15 +0000445
446 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
447 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
448
wdenka0ff7f22003-10-09 13:16:55 +0000449 /*
450 * Wait some time to avoid problem with very first call of
451 * adc_read(). Without * this delay, sometimes the first read adc
452 * value is 0. Perhaps because the * adjustment of prescaler takes
453 * some clock cycles?
454 */
455 udelay (1000);
456
457 return;
wdenkf5300ab2003-09-12 15:35:15 +0000458}
459
460
461int do_buttons (void)
462{
wdenka0ff7f22003-10-09 13:16:55 +0000463 int result;
464 int i;
wdenkf5300ab2003-09-12 15:35:15 +0000465
wdenka0ff7f22003-10-09 13:16:55 +0000466 result = *CPLD_BUTTONS; /* read CPLD */
467 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000468
wdenka0ff7f22003-10-09 13:16:55 +0000469 /* print result to console */
470 print_identifier ();
471 for (i = 16; i <= 19; i++) {
472 if ((result & (1 << i)) == 0)
473 printf("0");
474 else
475 printf("1");
476 }
477 printf("\n");
478 return 0;
479}
480
481
482int do_power_switch (void)
483{
484 int result;
485
486 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
487
488 /* configure GPE7 as input */
489 gpio->PECON &= ~(0x3 << (2 * 7));
490
491 /* signal GPE7 from power switch is low active: 0=on , 1=off */
492 result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
493
494 print_identifier ();
495 printf("%d\n", result);
wdenkf5300ab2003-09-12 15:35:15 +0000496 return 0;
497}
498
499
500int do_fill_level (void)
501{
wdenka0ff7f22003-10-09 13:16:55 +0000502 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000503
wdenka0ff7f22003-10-09 13:16:55 +0000504 result = *CPLD_FILL_LEVEL; /* read CPLD */
505 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000506
wdenka0ff7f22003-10-09 13:16:55 +0000507 /* print result to console */
508 print_identifier ();
509 if ((result & (1 << 16)) == 0)
510 printf("0\n");
511 else
512 printf("1\n");
wdenkf5300ab2003-09-12 15:35:15 +0000513 return 0;
514}
515
516
517int do_rotary_switch (void)
518{
wdenka0ff7f22003-10-09 13:16:55 +0000519 int result;
520 /*
521 * Please note, that the default values of the direction bits are
522 * undefined after reset. So it is a good idea, to make first a dummy
523 * call to this function, to clear the direction bits and set so to
524 * proper values.
525 */
wdenkf5300ab2003-09-12 15:35:15 +0000526
wdenka0ff7f22003-10-09 13:16:55 +0000527 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
528 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000529
wdenka0ff7f22003-10-09 13:16:55 +0000530 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
wdenkf5300ab2003-09-12 15:35:15 +0000531
wdenka0ff7f22003-10-09 13:16:55 +0000532 /* print result to console */
533 print_identifier ();
534 if ((result & (1 << 16)) == (1 << 16))
535 printf("R");
536 if ((result & (1 << 17)) == (1 << 17))
537 printf("L");
538 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
539 printf("0");
540 if ((result & (1 << 18)) == 0)
541 printf("0\n");
542 else
543 printf("1\n");
wdenkf5300ab2003-09-12 15:35:15 +0000544 return 0;
545}
546
547
548int do_vfd_id (void)
549{
wdenka0ff7f22003-10-09 13:16:55 +0000550 int i;
551 long int pcup_old, pccon_old;
552 int vfd_board_id;
553 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenkf5300ab2003-09-12 15:35:15 +0000554
555 /* try to red vfd board id from the value defined by pull-ups */
556
wdenka0ff7f22003-10-09 13:16:55 +0000557 pcup_old = gpio->PCUP;
558 pccon_old = gpio->PCCON;
wdenkf5300ab2003-09-12 15:35:15 +0000559
560 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
561 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
wdenka0ff7f22003-10-09 13:16:55 +0000562 * inputs */
wdenkf5300ab2003-09-12 15:35:15 +0000563 udelay (10); /* allow signals to settle */
564 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
565
wdenka0ff7f22003-10-09 13:16:55 +0000566 gpio->PCCON = pccon_old;
567 gpio->PCUP = pcup_old;
wdenkf5300ab2003-09-12 15:35:15 +0000568
wdenka0ff7f22003-10-09 13:16:55 +0000569 /* print vfd_board_id to console */
570 print_identifier ();
571 for (i = 0; i < 4; i++) {
572 if ((vfd_board_id & (1 << i)) == 0)
573 printf("0");
574 else
575 printf("1");
576 }
577 printf("\n");
wdenkf5300ab2003-09-12 15:35:15 +0000578 return 0;
579}
580
wdenka0ff7f22003-10-09 13:16:55 +0000581int do_buzzer (char **argv)
wdenkf5300ab2003-09-12 15:35:15 +0000582{
wdenka0ff7f22003-10-09 13:16:55 +0000583 int counter;
wdenkf5300ab2003-09-12 15:35:15 +0000584
585 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
wdenka0ff7f22003-10-09 13:16:55 +0000586 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenkf5300ab2003-09-12 15:35:15 +0000587
wdenka0ff7f22003-10-09 13:16:55 +0000588 /* set prescaler for timer 2, 3 and 4 */
589 timers->TCFG0 &= ~0xFF00;
wdenkf5300ab2003-09-12 15:35:15 +0000590 timers->TCFG0 |= 0x0F00;
591
wdenka0ff7f22003-10-09 13:16:55 +0000592 /* set divider for timer 2 */
wdenkf5300ab2003-09-12 15:35:15 +0000593 timers->TCFG1 &= ~0xF00;
594 timers->TCFG1 |= 0x300;
595
wdenka0ff7f22003-10-09 13:16:55 +0000596 /* set frequency */
597 counter = (PCLK / BUZZER_FREQ) >> 9;
598 timers->ch[2].TCNTB = counter;
wdenkf5300ab2003-09-12 15:35:15 +0000599 timers->ch[2].TCMPB = counter / 2;
600
wdenka0ff7f22003-10-09 13:16:55 +0000601 if (strcmp (argv[2], "on") == 0) {
602 debug ("%s: frequency: %d\n", __FUNCTION__,
603 BUZZER_FREQ);
wdenkf5300ab2003-09-12 15:35:15 +0000604
wdenka0ff7f22003-10-09 13:16:55 +0000605 /* configure pin GPD7 as TOUT2 */
606 gpio->PDCON &= ~0xC000;
607 gpio->PDCON |= 0x8000;
wdenkf5300ab2003-09-12 15:35:15 +0000608
wdenka0ff7f22003-10-09 13:16:55 +0000609 /* start */
610 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
611 ~INVERT2;
612 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
613 return (0);
614 }
615 else if (strcmp (argv[2], "off") == 0) {
616 /* stop */
617 timers->TCON &= ~(START2 | RELOAD2);
wdenkf5300ab2003-09-12 15:35:15 +0000618
wdenka0ff7f22003-10-09 13:16:55 +0000619 /* configure GPD7 as output and set to low */
620 gpio->PDCON &= ~0xC000;
621 gpio->PDCON |= 0x4000;
622 gpio->PDDAT &= ~0x80;
623 return (0);
624 }
wdenkf5300ab2003-09-12 15:35:15 +0000625
wdenka0ff7f22003-10-09 13:16:55 +0000626 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
627 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000628}
629
630
631int do_led (char **argv)
632{
wdenka0ff7f22003-10-09 13:16:55 +0000633 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenkf5300ab2003-09-12 15:35:15 +0000634
wdenka0ff7f22003-10-09 13:16:55 +0000635 /* configure PC14 and PC15 as output */
636 gpio->PCCON &= ~(0xF << 28);
637 gpio->PCCON |= (0x5 << 28);
wdenkf5300ab2003-09-12 15:35:15 +0000638
wdenka0ff7f22003-10-09 13:16:55 +0000639 /* configure PD0 and PD4 as output */
640 gpio->PDCON &= ~((0x3 << 8) | 0x3);
641 gpio->PDCON |= ((0x1 << 8) | 0x1);
wdenkf5300ab2003-09-12 15:35:15 +0000642
wdenka0ff7f22003-10-09 13:16:55 +0000643 switch (simple_strtoul(argv[2], NULL, 10)) {
wdenkf5300ab2003-09-12 15:35:15 +0000644
645 case 0:
646 case 1:
647 break;
648
wdenka0ff7f22003-10-09 13:16:55 +0000649 case 2:
650 if (strcmp (argv[3], "on") == 0)
651 gpio->PCDAT |= (1 << 14);
652 else
653 gpio->PCDAT &= ~(1 << 14);
654 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000655
wdenka0ff7f22003-10-09 13:16:55 +0000656 case 3:
657 if (strcmp (argv[3], "on") == 0)
658 gpio->PCDAT |= (1 << 15);
659 else
660 gpio->PCDAT &= ~(1 << 15);
661 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000662
wdenka0ff7f22003-10-09 13:16:55 +0000663 case 4:
664 if (strcmp (argv[3], "on") == 0)
665 gpio->PDDAT |= (1 << 0);
666 else
667 gpio->PDDAT &= ~(1 << 0);
668 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000669
wdenka0ff7f22003-10-09 13:16:55 +0000670 case 5:
671 if (strcmp (argv[3], "on") == 0)
672 gpio->PDDAT |= (1 << 4);
673 else
674 gpio->PDDAT &= ~(1 << 4);
675 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000676
wdenka0ff7f22003-10-09 13:16:55 +0000677 default:
678 break;
wdenkf5300ab2003-09-12 15:35:15 +0000679
wdenka0ff7f22003-10-09 13:16:55 +0000680 }
681 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
682 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000683}
684
685
686int do_full_bridge (char **argv)
687{
wdenka0ff7f22003-10-09 13:16:55 +0000688 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenkf5300ab2003-09-12 15:35:15 +0000689
wdenka0ff7f22003-10-09 13:16:55 +0000690 /* configure PD5 and PD6 as output */
691 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
692 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
wdenkf5300ab2003-09-12 15:35:15 +0000693
wdenka0ff7f22003-10-09 13:16:55 +0000694 if (strcmp (argv[2], "+") == 0) {
695 gpio->PDDAT |= (1 << 5);
696 gpio->PDDAT |= (1 << 6);
697 return 0;
698 }
699 else if (strcmp (argv[2], "-") == 0) {
700 gpio->PDDAT &= ~(1 << 5);
701 gpio->PDDAT |= (1 << 6);
702 return 0;
703 }
704 else if (strcmp (argv[2], "off") == 0) {
705 gpio->PDDAT &= ~(1 << 5);
706 gpio->PDDAT &= ~(1 << 6);
707 return 0;
708 }
709 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
710 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000711}
712
713/* val must be in [0, 4095] */
714static inline unsigned long tsc2000_to_uv (u16 val)
715{
716 return ((250000 * val) / 4096) * 10;
717}
718
719
720int do_dac (char **argv)
721{
wdenka0ff7f22003-10-09 13:16:55 +0000722 int brightness;
wdenkf5300ab2003-09-12 15:35:15 +0000723
wdenka0ff7f22003-10-09 13:16:55 +0000724 /* initialize SPI */
725 spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000726
wdenka0ff7f22003-10-09 13:16:55 +0000727 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
728 (brightness > 255)) {
729 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
730 return 1;
731 }
732 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
wdenkf5300ab2003-09-12 15:35:15 +0000733 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
734
wdenka0ff7f22003-10-09 13:16:55 +0000735 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000736}
737
738
739int do_v_bat (void)
740{
wdenka0ff7f22003-10-09 13:16:55 +0000741 unsigned long ret, res;
wdenkf5300ab2003-09-12 15:35:15 +0000742
wdenka0ff7f22003-10-09 13:16:55 +0000743 /* initialize SPI */
744 spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000745
746 tsc2000_write(TSC2000_REG_ADC, 0x1836);
747
wdenka0ff7f22003-10-09 13:16:55 +0000748 /* now wait for data available */
749 adc_wait_conversion_done();
wdenkf5300ab2003-09-12 15:35:15 +0000750
751 ret = tsc2000_read(TSC2000_REG_BAT1);
752 res = (tsc2000_to_uv(ret) + 1250) / 2500;
753 res += (ERROR_BATTERY * res) / 1000;
754
wdenka0ff7f22003-10-09 13:16:55 +0000755 print_identifier ();
756 printf ("%ld", (res / 100));
757 printf (".%ld", ((res % 100) / 10));
758 printf ("%ld V\n", (res % 10));
wdenkf5300ab2003-09-12 15:35:15 +0000759 return 0;
760}
761
762
763int do_pressure (void)
764{
wdenka0ff7f22003-10-09 13:16:55 +0000765 /* initialize SPI */
766 spi_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000767
wdenka0ff7f22003-10-09 13:16:55 +0000768 tsc2000_write(TSC2000_REG_ADC, 0x2436);
wdenkf5300ab2003-09-12 15:35:15 +0000769
wdenka0ff7f22003-10-09 13:16:55 +0000770 /* now wait for data available */
771 adc_wait_conversion_done();
wdenkf5300ab2003-09-12 15:35:15 +0000772
wdenka0ff7f22003-10-09 13:16:55 +0000773 print_identifier ();
774 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
wdenkf5300ab2003-09-12 15:35:15 +0000775 return 0;
776}
777
778
779int do_motor_contact (void)
780{
wdenka0ff7f22003-10-09 13:16:55 +0000781 int result;
wdenkf5300ab2003-09-12 15:35:15 +0000782
wdenka0ff7f22003-10-09 13:16:55 +0000783 result = *CPLD_FILL_LEVEL; /* read CPLD */
784 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
wdenkf5300ab2003-09-12 15:35:15 +0000785
wdenka0ff7f22003-10-09 13:16:55 +0000786 /* print result to console */
787 print_identifier ();
788 if ((result & (1 << 17)) == 0)
789 printf("0\n");
790 else
791 printf("1\n");
792 return 0;
wdenkf5300ab2003-09-12 15:35:15 +0000793}
794
795int do_motor (char **argv)
796{
797 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
798
799 /* Configure I/O port */
800 gpio->PGCON &= ~(0x3 << 0);
801 gpio->PGCON |= (0x1 << 0);
802
wdenka0ff7f22003-10-09 13:16:55 +0000803 if (strcmp (argv[2], "on") == 0) {
804 gpio->PGDAT &= ~(1 << 0);
805 return 0;
806 }
807 if (strcmp (argv[2], "off") == 0) {
808 gpio->PGDAT |= (1 << 0);
809 return 0;
810 }
811 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
812 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000813}
814
815static void print_identifier (void)
816{
wdenka0ff7f22003-10-09 13:16:55 +0000817 printf ("## FKT: ");
wdenkf5300ab2003-09-12 15:35:15 +0000818}
819
820int do_pwm (char **argv)
821{
wdenka0ff7f22003-10-09 13:16:55 +0000822 int counter;
823 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
wdenkf5300ab2003-09-12 15:35:15 +0000824 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
825
wdenka0ff7f22003-10-09 13:16:55 +0000826 if (strcmp (argv[2], "on") == 0) {
827 /* configure pin GPD8 as TOUT3 */
828 gpio->PDCON &= ~(0x3 << 8*2);
829 gpio->PDCON |= (0x2 << 8*2);
wdenkf5300ab2003-09-12 15:35:15 +0000830
wdenka0ff7f22003-10-09 13:16:55 +0000831 /* set prescaler for timer 2, 3 and 4 */
832 timers->TCFG0 &= ~0xFF00;
833 timers->TCFG0 |= 0x0F00;
wdenkf5300ab2003-09-12 15:35:15 +0000834
wdenka0ff7f22003-10-09 13:16:55 +0000835 /* set divider for timer 3 */
836 timers->TCFG1 &= ~(0xf << 12);
837 timers->TCFG1 |= (0x3 << 12);
wdenkf5300ab2003-09-12 15:35:15 +0000838
wdenka0ff7f22003-10-09 13:16:55 +0000839 /* set frequency */
840 counter = (PCLK / PWM_FREQ) >> 9;
841 timers->ch[3].TCNTB = counter;
842 timers->ch[3].TCMPB = counter / 2;
wdenkf5300ab2003-09-12 15:35:15 +0000843
wdenka0ff7f22003-10-09 13:16:55 +0000844 /* start timer */
845 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
846 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
847 return 0;
848 }
849 if (strcmp (argv[2], "off") == 0) {
wdenkf5300ab2003-09-12 15:35:15 +0000850
wdenka0ff7f22003-10-09 13:16:55 +0000851 /* stop timer */
852 timers->TCON &= ~(START2 | RELOAD2);
wdenkf5300ab2003-09-12 15:35:15 +0000853
wdenka0ff7f22003-10-09 13:16:55 +0000854 /* configure pin GPD8 as output and set to 0 */
855 gpio->PDCON &= ~(0x3 << 8*2);
856 gpio->PDCON |= (0x1 << 8*2);
857 gpio->PDDAT &= ~(1 << 8);
858 return 0;
859 }
860 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
861 return 1;
wdenkf5300ab2003-09-12 15:35:15 +0000862}
863
864
865int do_thermo (char **argv)
866{
wdenka0ff7f22003-10-09 13:16:55 +0000867 int channel, res;
wdenkf5300ab2003-09-12 15:35:15 +0000868
wdenka0ff7f22003-10-09 13:16:55 +0000869 tsc2000_reg_init ();
wdenkf5300ab2003-09-12 15:35:15 +0000870
wdenka0ff7f22003-10-09 13:16:55 +0000871 if (strcmp (argv[2], "all") == 0) {
872 int i;
873 for (i=0; i <= 15; i++) {
874 res = tsc2000_read_channel(i);
875 print_identifier ();
876 printf ("c%d: %d\n", i, res);
877 }
878 return 0;
879 }
880 channel = simple_strtoul (argv[2], NULL, 10);
881 res = tsc2000_read_channel(channel);
882 print_identifier ();
883 printf ("%d\n", res);
884 return 0; /* return OK */
wdenkf5300ab2003-09-12 15:35:15 +0000885}
886
887
wdenkf5300ab2003-09-12 15:35:15 +0000888int do_touch (char **argv)
889{
wdenka0ff7f22003-10-09 13:16:55 +0000890 int x, y;
wdenkf5300ab2003-09-12 15:35:15 +0000891
wdenka0ff7f22003-10-09 13:16:55 +0000892 if (strcmp (argv[2], "tl") == 0) {
wdenk42dfe7a2004-03-14 22:25:36 +0000893#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +0000894 touch_wait_pressed();
895#else
896 {
897 int i;
898 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
899 if (touch_check_pressed ()) {
900 break;
901 }
902 udelay (1000); /* pause 1 ms */
903 }
904 }
905 if (!touch_check_pressed()) {
906 print_identifier ();
907 printf ("error: touch not pressed\n");
908 return 1;
909 }
910#endif /* CONFIG_TOUCH_WAIT_PRESSED */
911 touch_read_x_y (&x, &y);
wdenkf5300ab2003-09-12 15:35:15 +0000912
wdenka0ff7f22003-10-09 13:16:55 +0000913 print_identifier ();
914 printf ("x=%d y=%d\n", x, y);
915 return touch_write_clibration_values (CALIB_TL, x, y);
916 }
917 else if (strcmp (argv[2], "dr") == 0) {
wdenk42dfe7a2004-03-14 22:25:36 +0000918#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenka0ff7f22003-10-09 13:16:55 +0000919 touch_wait_pressed();
920#else
921 {
922 int i;
923 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
924 if (touch_check_pressed ()) {
925 break;
926 }
927 udelay (1000); /* pause 1 ms */
928 }
929 }
930 if (!touch_check_pressed()) {
931 print_identifier ();
932 printf ("error: touch not pressed\n");
933 return 1;
934 }
935#endif /* CONFIG_TOUCH_WAIT_PRESSED */
936 touch_read_x_y (&x, &y);
wdenkf5300ab2003-09-12 15:35:15 +0000937
wdenka0ff7f22003-10-09 13:16:55 +0000938 print_identifier ();
939 printf ("x=%d y=%d\n", x, y);
wdenkf5300ab2003-09-12 15:35:15 +0000940
wdenka0ff7f22003-10-09 13:16:55 +0000941 return touch_write_clibration_values (CALIB_DR, x, y);
942 }
943 return 1; /* not "tl", nor "dr", so return error */
wdenkf5300ab2003-09-12 15:35:15 +0000944}
945
946
wdenka0ff7f22003-10-09 13:16:55 +0000947#ifdef CONFIG_TOUCH_WAIT_PRESSED
wdenkf5300ab2003-09-12 15:35:15 +0000948static void touch_wait_pressed (void)
949{
wdenka0ff7f22003-10-09 13:16:55 +0000950 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
wdenkf5300ab2003-09-12 15:35:15 +0000951}
952
wdenka0ff7f22003-10-09 13:16:55 +0000953#else
954static int touch_check_pressed (void)
955{
956 return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
957}
958#endif /* CONFIG_TOUCH_WAIT_PRESSED */
wdenkf5300ab2003-09-12 15:35:15 +0000959
960static int touch_write_clibration_values (int calib_point, int x, int y)
961{
Jon Loeligerab3abcb2007-07-09 18:45:16 -0500962#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +0000963 int x_verify = 0;
964 int y_verify = 0;
wdenkf5300ab2003-09-12 15:35:15 +0000965
wdenka0ff7f22003-10-09 13:16:55 +0000966 tsc2000_reg_init ();
967
968 if (calib_point == CALIB_TL) {
969 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200970 (unsigned char *)&x, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000971 return 1;
972 }
973 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200974 (unsigned char *)&y, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000975 return 1;
976 }
977
978 /* verify written values */
979 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200980 (unsigned char *)&x_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000981 return 1;
982 }
983 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200984 (unsigned char *)&y_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000985 return 1;
986 }
987 if ((y != y_verify) || (x != x_verify)) {
988 print_identifier ();
989 printf ("error: verify error\n");
990 return 1;
991 }
992 return 0; /* no error */
993 }
994 else if (calib_point == CALIB_DR) {
995 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +0200996 (unsigned char *)&x, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +0000997 return 1;
998 }
999 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001000 (unsigned char *)&y, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001001 return 1;
1002 }
1003
1004 /* verify written values */
1005 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001006 (unsigned char *)&x_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001007 return 1;
1008 }
1009 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001010 (unsigned char *)&y_verify, 2)) {
wdenka0ff7f22003-10-09 13:16:55 +00001011 return 1;
1012 }
1013 if ((y != y_verify) || (x != x_verify)) {
1014 print_identifier ();
1015 printf ("error: verify error\n");
1016 return 1;
1017 }
1018 return 0;
1019 }
1020 return 1;
wdenkf5300ab2003-09-12 15:35:15 +00001021#else
wdenka0ff7f22003-10-09 13:16:55 +00001022 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1023 "to EEPROM\n");
1024 return (1);
wdenkf5300ab2003-09-12 15:35:15 +00001025#endif /* CFG_CMD_I2C */
1026}
1027
1028
1029static void touch_read_x_y (int *px, int *py)
1030{
wdenka0ff7f22003-10-09 13:16:55 +00001031 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1032 adc_wait_conversion_done();
1033 *px = tsc2000_read(TSC2000_REG_X);
wdenkf5300ab2003-09-12 15:35:15 +00001034
wdenka0ff7f22003-10-09 13:16:55 +00001035 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1036 adc_wait_conversion_done();
1037 *py = tsc2000_read(TSC2000_REG_Y);
wdenkf5300ab2003-09-12 15:35:15 +00001038}
1039
1040
wdenkf5300ab2003-09-12 15:35:15 +00001041int do_rs485 (char **argv)
1042{
wdenka0ff7f22003-10-09 13:16:55 +00001043 int timeout;
1044 char data[RS485_MAX_RECEIVE_BUF_LEN];
wdenkf5300ab2003-09-12 15:35:15 +00001045
wdenka0ff7f22003-10-09 13:16:55 +00001046 if (strcmp (argv[2], "send") == 0) {
1047 return (rs485_send_line (argv[3]));
1048 }
1049 else if (strcmp (argv[2], "receive") == 0) {
1050 timeout = simple_strtoul(argv[3], NULL, 10);
1051 if (rs485_receive_chars (data, timeout) != 0) {
1052 print_identifier ();
1053 printf ("## nothing received\n");
1054 return (1);
1055 }
1056 else {
1057 print_identifier ();
1058 printf ("%s\n", data);
1059 return (0);
1060 }
1061 }
1062 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1063 return (1); /* unknown command, return error */
wdenkf5300ab2003-09-12 15:35:15 +00001064}
1065
1066
1067static int rs485_send_line (const char *data)
1068{
wdenka0ff7f22003-10-09 13:16:55 +00001069 rs485_init ();
1070 trab_rs485_enable_tx ();
1071 rs485_puts (data);
1072 rs485_putc ('\n');
wdenkf5300ab2003-09-12 15:35:15 +00001073
wdenka0ff7f22003-10-09 13:16:55 +00001074 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001075}
1076
1077
1078static int rs485_receive_chars (char *data, int timeout)
1079{
wdenka0ff7f22003-10-09 13:16:55 +00001080 int i;
1081 int receive_count = 0;
wdenkf5300ab2003-09-12 15:35:15 +00001082
wdenka0ff7f22003-10-09 13:16:55 +00001083 rs485_init ();
1084 trab_rs485_enable_rx ();
wdenkf5300ab2003-09-12 15:35:15 +00001085
wdenka0ff7f22003-10-09 13:16:55 +00001086 /* test every 1 ms for received characters to avoid a receive FIFO
1087 * overrun (@ 38.400 Baud) */
1088 for (i = 0; i < (timeout * 1000); i++) {
1089 while (rs485_tstc ()) {
1090 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1091 break;
1092 *data++ = rs485_getc ();
1093 receive_count++;
1094 }
1095 udelay (1000); /* pause 1 ms */
1096 }
1097 *data = '\0'; /* terminate string */
wdenkf5300ab2003-09-12 15:35:15 +00001098
wdenka0ff7f22003-10-09 13:16:55 +00001099 if (receive_count == 0)
1100 return (1);
1101 else
1102 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001103}
1104
1105
1106int do_serial_number (char **argv)
1107{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001108#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001109 unsigned int serial_number;
wdenkf5300ab2003-09-12 15:35:15 +00001110
wdenka0ff7f22003-10-09 13:16:55 +00001111 if (strcmp (argv[2], "read") == 0) {
1112 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001113 (unsigned char *)&serial_number, 4)) {
wdenka0ff7f22003-10-09 13:16:55 +00001114 printf ("could not read from eeprom\n");
1115 return (1);
1116 }
1117 print_identifier ();
1118 printf ("%08d\n", serial_number);
1119 return (0);
1120 }
1121 else if (strcmp (argv[2], "write") == 0) {
1122 serial_number = simple_strtoul(argv[3], NULL, 10);
1123 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001124 (unsigned char *)&serial_number, 4)) {
wdenka0ff7f22003-10-09 13:16:55 +00001125 printf ("could not write to eeprom\n");
1126 return (1);
1127 }
1128 return (0);
1129 }
1130 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1131 return (1); /* unknown command, return error */
wdenkf5300ab2003-09-12 15:35:15 +00001132#else
wdenka0ff7f22003-10-09 13:16:55 +00001133 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1134 "to EEPROM\n");
1135 return (1);
wdenkf5300ab2003-09-12 15:35:15 +00001136#endif /* CFG_CMD_I2C */
1137}
1138
1139
1140int do_crc16 (void)
1141{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001142#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001143 int crc;
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001144 unsigned char buf[EEPROM_MAX_CRC_BUF];
wdenkf5300ab2003-09-12 15:35:15 +00001145
wdenka0ff7f22003-10-09 13:16:55 +00001146 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1147 printf ("could not read from eeprom\n");
1148 return (1);
1149 }
1150 crc = 0; /* start value of crc calculation */
1151 crc = updcrc (crc, buf, 60);
wdenkf5300ab2003-09-12 15:35:15 +00001152
wdenka0ff7f22003-10-09 13:16:55 +00001153 print_identifier ();
1154 printf ("crc16=%#04x\n", crc);
wdenkf5300ab2003-09-12 15:35:15 +00001155
Wolfgang Denka63c31c2006-06-26 10:54:52 +02001156 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
wdenka0ff7f22003-10-09 13:16:55 +00001157 sizeof (crc))) {
1158 printf ("could not read from eeprom\n");
1159 return (1);
1160 }
1161 return (0);
wdenkf5300ab2003-09-12 15:35:15 +00001162#else
wdenka0ff7f22003-10-09 13:16:55 +00001163 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1164 "to EEPROM\n");
1165 return (1);
wdenkf5300ab2003-09-12 15:35:15 +00001166#endif /* CFG_CMD_I2C */
1167}
1168
1169
1170/*
1171 * Calculate, intelligently, the CRC of a dataset incrementally given a
1172 * buffer full at a time.
1173 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1174 *
1175 * Usage:
1176 * newcrc = updcrc( oldcrc, bufadr, buflen )
1177 * unsigned int oldcrc, buflen;
1178 * char *bufadr;
1179 *
1180 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1181 * Compile with -DMAKETAB to print values for crctab to stdout
1182 */
1183
1184 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1185 * If you change P, you must change crctab[]'s initial value to what is
1186 * printed by initcrctab()
1187 */
1188#define P 0x1021
1189
1190 /* number of bits in CRC: don't change it. */
1191#define W 16
1192
1193 /* this the number of bits per char: don't change it. */
1194#define B 8
1195
1196static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1197 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1198 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1199 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1200 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1201 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1202 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1203 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1204 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1205 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1206 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1207 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1208 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1209 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1210 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1211 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1212 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1213 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1214 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1215 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1216 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1217 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1218 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1219 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1220 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1221 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1222 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1223 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1224 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1225 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1226 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1227 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1228 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1229 };
1230
1231static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
wdenka0ff7f22003-10-09 13:16:55 +00001232 unsigned int icnt )
wdenkf5300ab2003-09-12 15:35:15 +00001233{
wdenka0ff7f22003-10-09 13:16:55 +00001234 register unsigned short crc = icrc;
1235 register unsigned char *cp = icp;
1236 register unsigned int cnt = icnt;
wdenkf5300ab2003-09-12 15:35:15 +00001237
wdenka0ff7f22003-10-09 13:16:55 +00001238 while (cnt--)
1239 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
wdenkf5300ab2003-09-12 15:35:15 +00001240
wdenka0ff7f22003-10-09 13:16:55 +00001241 return (crc);
wdenkf5300ab2003-09-12 15:35:15 +00001242}
wdenka0ff7f22003-10-09 13:16:55 +00001243
1244
1245int do_gain (char **argv)
1246{
1247 int range;
1248
1249 range = simple_strtoul (argv[2], NULL, 10);
1250 if ((range < 1) || (range > 3))
1251 {
1252 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1253 return 1;
1254 }
1255
1256 tsc2000_set_range (range);
1257 return (0);
1258}
1259
1260
1261int do_eeprom (char **argv)
1262{
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001263#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001264 if (strcmp (argv[2], "read") == 0) {
1265 return (trab_eeprom_read (argv));
1266 }
1267
1268 else if (strcmp (argv[2], "write") == 0) {
1269 return (trab_eeprom_write (argv));
1270 }
1271
1272 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1273 return (1);
1274#else
1275 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1276 "to EEPROM\n");
1277 return (1);
1278#endif /* CFG_CMD_I2C */
1279}
1280
Jon Loeligerab3abcb2007-07-09 18:45:16 -05001281#if defined(CONFIG_CMD_I2C)
wdenka0ff7f22003-10-09 13:16:55 +00001282static int trab_eeprom_read (char **argv)
1283{
1284 int i;
1285 int len;
1286 unsigned int addr;
1287 long int value = 0;
1288 uchar *buffer;
1289
1290 buffer = (uchar *) &value;
1291 addr = simple_strtoul (argv[3], NULL, 10);
1292 addr &= 0xfff;
1293 len = simple_strtoul (argv[4], NULL, 10);
1294 if ((len < 1) || (len > 4)) {
1295 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1296 argv[4]);
1297 return (1);
1298 }
1299 for (i = 0; i < len; i++) {
1300 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1301 printf ("%s: could not read from i2c device %#x"
1302 ", addr %d\n", __FUNCTION__,
1303 I2C_EEPROM_DEV_ADDR, addr);
1304 return (1);
1305 }
1306 }
1307 print_identifier ();
1308 if (strcmp (argv[5], "-") == 0) {
1309 if (len == 1)
1310 printf ("%d\n", (signed char) value);
1311 else if (len == 2)
1312 printf ("%d\n", (signed short int) value);
1313 else
1314 printf ("%ld\n", value);
1315 }
1316 else {
1317 if (len == 1)
1318 printf ("%d\n", (unsigned char) value);
1319 else if (len == 2)
1320 printf ("%d\n", (unsigned short int) value);
1321 else
1322 printf ("%ld\n", (unsigned long int) value);
1323 }
1324 return (0);
1325}
1326
1327static int trab_eeprom_write (char **argv)
1328{
1329 int i;
1330 int len;
1331 unsigned int addr;
1332 long int value = 0;
1333 uchar *buffer;
1334
1335 buffer = (uchar *) &value;
1336 addr = simple_strtoul (argv[3], NULL, 10);
1337 addr &= 0xfff;
1338 len = simple_strtoul (argv[4], NULL, 10);
1339 if ((len < 1) || (len > 4)) {
1340 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1341 argv[4]);
1342 return (1);
1343 }
1344 value = simple_strtol (argv[5], NULL, 10);
1345 debug ("value=%ld\n", value);
1346 for (i = 0; i < len; i++) {
1347 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1348 printf ("%s: could not write to i2c device %d"
1349 ", addr %d\n", __FUNCTION__,
1350 I2C_EEPROM_DEV_ADDR, addr);
1351 return (1);
1352 }
1353#if 0
1354 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1355 "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1356 i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1357#endif
1358 udelay (30000); /* wait for EEPROM ready */
1359 }
1360 return (0);
1361}
1362
1363int i2c_write_multiple (uchar chip, uint addr, int alen,
1364 uchar *buffer, int len)
1365{
1366 int i;
1367
1368 if (alen != 1) {
1369 printf ("%s: addr len other than 1 not supported\n",
1370 __FUNCTION__);
1371 return (1);
1372 }
1373
1374 for (i = 0; i < len; i++) {
1375 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1376 printf ("%s: could not write to i2c device %d"
1377 ", addr %d\n", __FUNCTION__, chip, addr);
1378 return (1);
1379 }
1380#if 0
1381 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1382 "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1383 alen, buffer, i, buffer+i, buffer+i);
1384#endif
1385
1386 udelay (30000);
1387 }
1388 return (0);
1389}
1390
1391int i2c_read_multiple ( uchar chip, uint addr, int alen,
1392 uchar *buffer, int len)
1393{
1394 int i;
1395
1396 if (alen != 1) {
1397 printf ("%s: addr len other than 1 not supported\n",
1398 __FUNCTION__);
1399 return (1);
1400 }
1401
1402 for (i = 0; i < len; i++) {
1403 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1404 printf ("%s: could not read from i2c device %#x"
1405 ", addr %d\n", __FUNCTION__, chip, addr);
1406 return (1);
1407 }
1408 }
1409 return (0);
1410}
1411#endif /* CFG_CMD_I2C */