]> git.ipfire.org Git - people/ms/u-boot.git/blame - board/trab/trab_fkt.c
Clean-up of s3c24x0 drivers excluding nand driver
[people/ms/u-boot.git] / board / trab / trab_fkt.c
CommitLineData
f5300ab2
WD
1/*
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>
561858ee 28#include <timestamp.h>
f5300ab2
WD
29#include <s3c2400.h>
30#include "tsc2000.h"
31#include "rs485.h"
32
a0ff7f2e
WD
33/*
34 * define, to wait for the touch to be pressed, before reading coordinates in
35 * command do_touch. If not defined, an error message is printed, when the
36 * command do_touch is invoked and the touch is not pressed within an specific
37 * interval.
38 */
e86e5a07 39#undef CONFIG_TOUCH_WAIT_PRESSED
a0ff7f2e
WD
40
41/* max time to wait for touch is pressed */
42#ifndef CONFIG_TOUCH_WAIT_PRESSED
43#define TOUCH_TIMEOUT 5
44#endif /* !CONFIG_TOUCH_WAIT_PRESSED */
45
f5300ab2
WD
46/* assignment of CPU internal ADC channels with TRAB hardware */
47#define VCC5V 2
48#define VCC12V 3
49
50/* CPLD-Register for controlling TRAB hardware functions */
51#define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
52#define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
53#define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
54#define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
55
56/* timer configuration bits for buzzer and PWM */
57#define START2 (1 << 12)
58#define UPDATE2 (1 << 13)
59#define INVERT2 (1 << 14)
60#define RELOAD2 (1 << 15)
61#define START3 (1 << 16)
62#define UPDATE3 (1 << 17)
63#define INVERT3 (1 << 18)
64#define RELOAD3 (1 << 19)
65
66#define PCLK 66000000
67#define BUZZER_FREQ 1000 /* frequency in Hz */
f5300ab2
WD
68#define PWM_FREQ 500
69
70
71/* definitions of I2C EEPROM device address */
72#define I2C_EEPROM_DEV_ADDR 0x54
73
74/* definition for touch panel calibration points */
75#define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
76#define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
77
a0ff7f2e 78/* EEPROM address map */
f5300ab2
WD
79#define SERIAL_NUMBER 8
80#define TOUCH_X0 52
81#define TOUCH_Y0 54
82#define TOUCH_X1 56
83#define TOUCH_Y1 58
84#define CRC16 60
85
86/* EEPROM stuff */
87#define EEPROM_MAX_CRC_BUF 64
88
89/* RS485 stuff */
90#define RS485_MAX_RECEIVE_BUF_LEN 100
91
92/* Bit definitions for ADCCON */
93#define ADC_ENABLE_START 0x1
94#define ADC_READ_START 0x2
95#define ADC_STDBM 0x4
96#define ADC_INP_AIN0 (0x0 << 3)
97#define ADC_INP_AIN1 (0x1 << 3)
98#define ADC_INP_AIN2 (0x2 << 3)
99#define ADC_INP_AIN3 (0x3 << 3)
100#define ADC_INP_AIN4 (0x4 << 3)
101#define ADC_INP_AIN5 (0x5 << 3)
102#define ADC_INP_AIN6 (0x6 << 3)
103#define ADC_INP_AIN7 (0x7 << 3)
104#define ADC_PRSCEN 0x4000
105#define ADC_ECFLG 0x8000
106
107/* function test functions */
108int do_dip (void);
109int do_info (void);
110int do_vcc5v (void);
111int do_vcc12v (void);
112int do_buttons (void);
113int do_fill_level (void);
114int do_rotary_switch (void);
115int do_pressure (void);
116int do_v_bat (void);
117int do_vfd_id (void);
a0ff7f2e 118int do_buzzer (char **);
f5300ab2
WD
119int do_led (char **);
120int do_full_bridge (char **);
121int do_dac (char **);
122int do_motor_contact (void);
123int do_motor (char **);
124int do_pwm (char **);
125int do_thermo (char **);
126int do_touch (char **);
127int do_rs485 (char **);
128int do_serial_number (char **);
129int do_crc16 (void);
a0ff7f2e
WD
130int do_power_switch (void);
131int do_gain (char **);
132int do_eeprom (char **);
f5300ab2
WD
133
134/* helper functions */
135static void adc_init (void);
136static int adc_read (unsigned int channel);
137static void print_identifier (void);
a0ff7f2e
WD
138
139#ifdef CONFIG_TOUCH_WAIT_PRESSED
f5300ab2 140static void touch_wait_pressed (void);
a0ff7f2e
WD
141#else
142static int touch_check_pressed (void);
143#endif /* CONFIG_TOUCH_WAIT_PRESSED */
144
f5300ab2
WD
145static void touch_read_x_y (int *x, int *y);
146static int touch_write_clibration_values (int calib_point, int x, int y);
147static int rs485_send_line (const char *data);
148static int rs485_receive_chars (char *data, int timeout);
149static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
a0ff7f2e 150 unsigned int icnt);
f5300ab2 151
ab3abcba 152#if defined(CONFIG_CMD_I2C)
a0ff7f2e
WD
153static int trab_eeprom_read (char **argv);
154static int trab_eeprom_write (char **argv);
155int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
156 int len);
157int i2c_read_multiple ( uchar chip, uint addr, int alen, uchar *buffer,
158 int len);
d39b5741 159#endif
f5300ab2
WD
160
161/*
162 * TRAB board specific commands. Especially commands for burn-in and function
163 * test.
164 */
165
166int trab_fkt (int argc, char *argv[])
167{
a0ff7f2e
WD
168 int i;
169
170 app_startup(argv);
171 if (get_version () != XF_VERSION) {
172 printf ("Wrong XF_VERSION. Please re-compile with actual "
173 "u-boot sources\n");
174 printf ("Example expects ABI version %d\n", XF_VERSION);
175 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
176 return 1;
177 }
f5300ab2 178
a0ff7f2e 179 debug ("argc = %d\n", argc);
f5300ab2
WD
180
181 for (i=0; i<=argc; ++i) {
182 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
a0ff7f2e 183 }
f5300ab2 184
a0ff7f2e 185 adc_init ();
f5300ab2
WD
186
187 switch (argc) {
188
189 case 0:
190 case 1:
191 break;
192
193 case 2:
194 if (strcmp (argv[1], "info") == 0) {
a0ff7f2e
WD
195 return (do_info ());
196 }
197 if (strcmp (argv[1], "dip") == 0) {
198 return (do_dip ());
199 }
200 if (strcmp (argv[1], "vcc5v") == 0) {
201 return (do_vcc5v ());
f5300ab2 202 }
a0ff7f2e
WD
203 if (strcmp (argv[1], "vcc12v") == 0) {
204 return (do_vcc12v ());
205 }
206 if (strcmp (argv[1], "buttons") == 0) {
207 return (do_buttons ());
208 }
209 if (strcmp (argv[1], "fill_level") == 0) {
210 return (do_fill_level ());
211 }
212 if (strcmp (argv[1], "rotary_switch") == 0) {
213 return (do_rotary_switch ());
214 }
215 if (strcmp (argv[1], "pressure") == 0) {
216 return (do_pressure ());
217 }
218 if (strcmp (argv[1], "v_bat") == 0) {
219 return (do_v_bat ());
220 }
221 if (strcmp (argv[1], "vfd_id") == 0) {
222 return (do_vfd_id ());
223 }
224 if (strcmp (argv[1], "motor_contact") == 0) {
225 return (do_motor_contact ());
226 }
227 if (strcmp (argv[1], "crc16") == 0) {
228 return (do_crc16 ());
229 }
230 if (strcmp (argv[1], "power_switch") == 0) {
231 return (do_power_switch ());
232 }
233 break;
f5300ab2
WD
234
235 case 3:
a0ff7f2e
WD
236 if (strcmp (argv[1], "full_bridge") == 0) {
237 return (do_full_bridge (argv));
238 }
239 if (strcmp (argv[1], "dac") == 0) {
240 return (do_dac (argv));
241 }
242 if (strcmp (argv[1], "motor") == 0) {
243 return (do_motor (argv));
244 }
245 if (strcmp (argv[1], "pwm") == 0) {
246 return (do_pwm (argv));
247 }
248 if (strcmp (argv[1], "thermo") == 0) {
249 return (do_thermo (argv));
250 }
251 if (strcmp (argv[1], "touch") == 0) {
252 return (do_touch (argv));
253 }
254 if (strcmp (argv[1], "serial_number") == 0) {
255 return (do_serial_number (argv));
256 }
257 if (strcmp (argv[1], "buzzer") == 0) {
258 return (do_buzzer (argv));
259 }
260 if (strcmp (argv[1], "gain") == 0) {
261 return (do_gain (argv));
262 }
263 break;
264
265 case 4:
266 if (strcmp (argv[1], "led") == 0) {
267 return (do_led (argv));
268 }
269 if (strcmp (argv[1], "rs485") == 0) {
270 return (do_rs485 (argv));
271 }
272 if (strcmp (argv[1], "serial_number") == 0) {
273 return (do_serial_number (argv));
274 }
275 break;
276
277 case 5:
278 if (strcmp (argv[1], "eeprom") == 0) {
279 return (do_eeprom (argv));
280 }
281 break;
282
283 case 6:
284 if (strcmp (argv[1], "eeprom") == 0) {
285 return (do_eeprom (argv));
286 }
287 break;
f5300ab2
WD
288
289 default:
290 break;
291 }
292
293 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
a0ff7f2e 294 return 1;
f5300ab2
WD
295}
296
6cdadcb3
WD
297void hang (void)
298{
299 puts ("### ERROR ### Please RESET the board ###\n");
300 for (;;);
301}
302
f5300ab2
WD
303int do_info (void)
304{
a0ff7f2e 305 printf ("Stand-alone application for TRAB board function test\n");
561858ee 306 printf ("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
f5300ab2
WD
307
308 return 0;
309}
310
311int do_dip (void)
312{
a0ff7f2e
WD
313 unsigned int result = 0;
314 int adc_val;
315 int i;
f5300ab2
WD
316
317 /***********************************************************
318 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
319 SW1 - AIN4
320 SW2 - AIN5
321 SW3 - AIN6
322 SW4 - AIN7
323
324 "On" DIP switch position short-circuits the voltage from
325 the input channel (i.e. '0' conversion result means "on").
326 *************************************************************/
327
328 for (i = 7; i > 3; i--) {
329
a0ff7f2e
WD
330 if ((adc_val = adc_read (i)) == -1) {
331 printf ("Channel %d could not be read\n", i);
332 return 1;
333 }
f5300ab2
WD
334
335 /*
336 * Input voltage (switch open) is 1.8 V.
337 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
338 * Set trigger at halve that value.
339 */
340 if (adc_val < 368)
a0ff7f2e
WD
341 result |= (1 << (i-4));
342 }
343
344 /* print result to console */
345 print_identifier ();
346 for (i = 0; i < 4; i++) {
347 if ((result & (1 << i)) == 0)
348 printf("0");
349 else
350 printf("1");
351 }
352 printf("\n");
f5300ab2
WD
353
354 return 0;
355}
356
357
358int do_vcc5v (void)
359{
a0ff7f2e
WD
360 int result;
361
362 /* VCC5V is connected to channel 2 */
363
364 if ((result = adc_read (VCC5V)) == -1) {
365 printf ("VCC5V could not be read\n");
366 return 1;
367 }
368
369 /*
370 * Calculate voltage value. Split in two parts because there is no
371 * floating point support. VCC5V is connected over an resistor divider:
372 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
373 */
374 print_identifier ();
375 printf ("%d", (result & 0x3FF)* 10 / 1023);
376 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
377 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
378 * 10 / 1024);
f5300ab2
WD
379
380 return 0;
381}
382
383
384int do_vcc12v (void)
385{
a0ff7f2e
WD
386 int result;
387
388 if ((result = adc_read (VCC12V)) == -1) {
389 printf ("VCC12V could not be read\n");
390 return 1;
391 }
392
393 /*
394 * Calculate voltage value. Split in two parts because there is no
395 * floating point support. VCC5V is connected over an resistor divider:
396 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
397 */
398 print_identifier ();
399 printf ("%d", (result & 0x3FF)* 25 / 1023);
400 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
401
402 return 0;
f5300ab2
WD
403}
404
405static int adc_read (unsigned int channel)
406{
a0ff7f2e
WD
407 int j = 1000; /* timeout value for wait loop in us */
408 int result;
eb0ae7f5 409 struct s3c2400_adc *padc;
f5300ab2 410
eb0ae7f5 411 padc = s3c2400_get_base_adc();
a0ff7f2e 412 channel &= 0x7;
f5300ab2 413
a0ff7f2e 414 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
f5300ab2 415 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
a0ff7f2e
WD
416 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
417
418 while (j--) {
419 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
420 break;
421 udelay (1);
422 }
f5300ab2 423
a0ff7f2e
WD
424 if (j == 0) {
425 printf("%s: ADC timeout\n", __FUNCTION__);
426 padc->ADCCON |= ADC_STDBM; /* select standby mode */
427 return -1;
428 }
f5300ab2 429
a0ff7f2e 430 result = padc->ADCDAT & 0x3FF;
f5300ab2 431
a0ff7f2e 432 padc->ADCCON |= ADC_STDBM; /* select standby mode */
f5300ab2 433
a0ff7f2e
WD
434 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
435 (padc->ADCCON >> 3) & 0x7, result);
f5300ab2 436
a0ff7f2e
WD
437 /*
438 * Wait for ADC to be ready for next conversion. This delay value was
439 * estimated, because the datasheet does not specify a value.
440 */
441 udelay (1000);
f5300ab2 442
a0ff7f2e 443 return (result);
f5300ab2
WD
444}
445
446
447static void adc_init (void)
448{
eb0ae7f5 449 struct s3c2400_adc *padc;
f5300ab2 450
eb0ae7f5 451 padc = s3c2400_get_base_adc();
f5300ab2
WD
452
453 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
454 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
455
a0ff7f2e
WD
456 /*
457 * Wait some time to avoid problem with very first call of
458 * adc_read(). Without * this delay, sometimes the first read adc
459 * value is 0. Perhaps because the * adjustment of prescaler takes
460 * some clock cycles?
461 */
462 udelay (1000);
463
464 return;
f5300ab2
WD
465}
466
467
468int do_buttons (void)
469{
a0ff7f2e
WD
470 int result;
471 int i;
472
473 result = *CPLD_BUTTONS; /* read CPLD */
474 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
475
476 /* print result to console */
477 print_identifier ();
478 for (i = 16; i <= 19; i++) {
479 if ((result & (1 << i)) == 0)
480 printf("0");
481 else
482 printf("1");
483 }
484 printf("\n");
485 return 0;
486}
487
488
489int do_power_switch (void)
490{
491 int result;
492
eb0ae7f5 493 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
a0ff7f2e
WD
494
495 /* configure GPE7 as input */
496 gpio->PECON &= ~(0x3 << (2 * 7));
497
498 /* signal GPE7 from power switch is low active: 0=on , 1=off */
499 result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
500
501 print_identifier ();
502 printf("%d\n", result);
f5300ab2
WD
503 return 0;
504}
505
506
507int do_fill_level (void)
508{
a0ff7f2e 509 int result;
f5300ab2 510
a0ff7f2e
WD
511 result = *CPLD_FILL_LEVEL; /* read CPLD */
512 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
f5300ab2 513
a0ff7f2e
WD
514 /* print result to console */
515 print_identifier ();
516 if ((result & (1 << 16)) == 0)
517 printf("0\n");
518 else
519 printf("1\n");
f5300ab2
WD
520 return 0;
521}
522
523
524int do_rotary_switch (void)
525{
a0ff7f2e
WD
526 int result;
527 /*
528 * Please note, that the default values of the direction bits are
529 * undefined after reset. So it is a good idea, to make first a dummy
530 * call to this function, to clear the direction bits and set so to
531 * proper values.
532 */
533
534 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
535 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
536
537 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
538
539 /* print result to console */
540 print_identifier ();
541 if ((result & (1 << 16)) == (1 << 16))
542 printf("R");
543 if ((result & (1 << 17)) == (1 << 17))
544 printf("L");
545 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
546 printf("0");
547 if ((result & (1 << 18)) == 0)
548 printf("0\n");
549 else
550 printf("1\n");
f5300ab2
WD
551 return 0;
552}
553
554
555int do_vfd_id (void)
556{
a0ff7f2e
WD
557 int i;
558 long int pcup_old, pccon_old;
559 int vfd_board_id;
eb0ae7f5 560 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
f5300ab2
WD
561
562 /* try to red vfd board id from the value defined by pull-ups */
563
a0ff7f2e
WD
564 pcup_old = gpio->PCUP;
565 pccon_old = gpio->PCCON;
f5300ab2
WD
566
567 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
568 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
a0ff7f2e 569 * inputs */
f5300ab2
WD
570 udelay (10); /* allow signals to settle */
571 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
572
a0ff7f2e
WD
573 gpio->PCCON = pccon_old;
574 gpio->PCUP = pcup_old;
575
576 /* print vfd_board_id to console */
577 print_identifier ();
578 for (i = 0; i < 4; i++) {
579 if ((vfd_board_id & (1 << i)) == 0)
580 printf("0");
581 else
582 printf("1");
583 }
584 printf("\n");
f5300ab2
WD
585 return 0;
586}
587
a0ff7f2e 588int do_buzzer (char **argv)
f5300ab2 589{
a0ff7f2e 590 int counter;
f5300ab2 591
eb0ae7f5 592 struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
593 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
f5300ab2 594
a0ff7f2e
WD
595 /* set prescaler for timer 2, 3 and 4 */
596 timers->TCFG0 &= ~0xFF00;
f5300ab2
WD
597 timers->TCFG0 |= 0x0F00;
598
a0ff7f2e 599 /* set divider for timer 2 */
f5300ab2
WD
600 timers->TCFG1 &= ~0xF00;
601 timers->TCFG1 |= 0x300;
602
a0ff7f2e
WD
603 /* set frequency */
604 counter = (PCLK / BUZZER_FREQ) >> 9;
605 timers->ch[2].TCNTB = counter;
f5300ab2
WD
606 timers->ch[2].TCMPB = counter / 2;
607
a0ff7f2e
WD
608 if (strcmp (argv[2], "on") == 0) {
609 debug ("%s: frequency: %d\n", __FUNCTION__,
610 BUZZER_FREQ);
f5300ab2 611
a0ff7f2e
WD
612 /* configure pin GPD7 as TOUT2 */
613 gpio->PDCON &= ~0xC000;
614 gpio->PDCON |= 0x8000;
f5300ab2 615
a0ff7f2e
WD
616 /* start */
617 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
618 ~INVERT2;
619 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
620 return (0);
621 }
622 else if (strcmp (argv[2], "off") == 0) {
623 /* stop */
624 timers->TCON &= ~(START2 | RELOAD2);
625
626 /* configure GPD7 as output and set to low */
627 gpio->PDCON &= ~0xC000;
628 gpio->PDCON |= 0x4000;
629 gpio->PDDAT &= ~0x80;
630 return (0);
631 }
f5300ab2 632
a0ff7f2e
WD
633 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
634 return 1;
f5300ab2
WD
635}
636
637
638int do_led (char **argv)
639{
eb0ae7f5 640 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
f5300ab2 641
a0ff7f2e
WD
642 /* configure PC14 and PC15 as output */
643 gpio->PCCON &= ~(0xF << 28);
644 gpio->PCCON |= (0x5 << 28);
f5300ab2 645
a0ff7f2e
WD
646 /* configure PD0 and PD4 as output */
647 gpio->PDCON &= ~((0x3 << 8) | 0x3);
648 gpio->PDCON |= ((0x1 << 8) | 0x1);
f5300ab2 649
a0ff7f2e 650 switch (simple_strtoul(argv[2], NULL, 10)) {
f5300ab2
WD
651
652 case 0:
653 case 1:
654 break;
655
a0ff7f2e
WD
656 case 2:
657 if (strcmp (argv[3], "on") == 0)
658 gpio->PCDAT |= (1 << 14);
659 else
660 gpio->PCDAT &= ~(1 << 14);
661 return 0;
662
663 case 3:
664 if (strcmp (argv[3], "on") == 0)
665 gpio->PCDAT |= (1 << 15);
666 else
667 gpio->PCDAT &= ~(1 << 15);
668 return 0;
669
670 case 4:
671 if (strcmp (argv[3], "on") == 0)
672 gpio->PDDAT |= (1 << 0);
673 else
674 gpio->PDDAT &= ~(1 << 0);
675 return 0;
676
677 case 5:
678 if (strcmp (argv[3], "on") == 0)
679 gpio->PDDAT |= (1 << 4);
680 else
681 gpio->PDDAT &= ~(1 << 4);
682 return 0;
683
684 default:
685 break;
686
687 }
688 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
689 return 1;
f5300ab2
WD
690}
691
692
693int do_full_bridge (char **argv)
694{
eb0ae7f5 695 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
a0ff7f2e
WD
696
697 /* configure PD5 and PD6 as output */
698 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
699 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
700
701 if (strcmp (argv[2], "+") == 0) {
702 gpio->PDDAT |= (1 << 5);
703 gpio->PDDAT |= (1 << 6);
704 return 0;
705 }
706 else if (strcmp (argv[2], "-") == 0) {
707 gpio->PDDAT &= ~(1 << 5);
708 gpio->PDDAT |= (1 << 6);
709 return 0;
710 }
711 else if (strcmp (argv[2], "off") == 0) {
712 gpio->PDDAT &= ~(1 << 5);
713 gpio->PDDAT &= ~(1 << 6);
714 return 0;
715 }
716 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
717 return 1;
f5300ab2
WD
718}
719
720/* val must be in [0, 4095] */
721static inline unsigned long tsc2000_to_uv (u16 val)
722{
723 return ((250000 * val) / 4096) * 10;
724}
725
726
727int do_dac (char **argv)
728{
a0ff7f2e 729 int brightness;
f5300ab2 730
a0ff7f2e 731 /* initialize SPI */
f6e3a1fa 732 tsc2000_spi_init ();
f5300ab2 733
a0ff7f2e
WD
734 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
735 (brightness > 255)) {
736 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
737 return 1;
738 }
739 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
f5300ab2
WD
740 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
741
a0ff7f2e 742 return 0;
f5300ab2
WD
743}
744
745
746int do_v_bat (void)
747{
a0ff7f2e 748 unsigned long ret, res;
f5300ab2 749
a0ff7f2e
WD
750 /* initialize SPI */
751 spi_init ();
f5300ab2
WD
752
753 tsc2000_write(TSC2000_REG_ADC, 0x1836);
754
a0ff7f2e
WD
755 /* now wait for data available */
756 adc_wait_conversion_done();
f5300ab2
WD
757
758 ret = tsc2000_read(TSC2000_REG_BAT1);
759 res = (tsc2000_to_uv(ret) + 1250) / 2500;
760 res += (ERROR_BATTERY * res) / 1000;
761
a0ff7f2e
WD
762 print_identifier ();
763 printf ("%ld", (res / 100));
764 printf (".%ld", ((res % 100) / 10));
765 printf ("%ld V\n", (res % 10));
f5300ab2
WD
766 return 0;
767}
768
769
770int do_pressure (void)
771{
a0ff7f2e
WD
772 /* initialize SPI */
773 spi_init ();
f5300ab2 774
a0ff7f2e 775 tsc2000_write(TSC2000_REG_ADC, 0x2436);
f5300ab2 776
a0ff7f2e
WD
777 /* now wait for data available */
778 adc_wait_conversion_done();
f5300ab2 779
a0ff7f2e
WD
780 print_identifier ();
781 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
f5300ab2
WD
782 return 0;
783}
784
785
786int do_motor_contact (void)
787{
a0ff7f2e
WD
788 int result;
789
790 result = *CPLD_FILL_LEVEL; /* read CPLD */
791 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
792
793 /* print result to console */
794 print_identifier ();
795 if ((result & (1 << 17)) == 0)
796 printf("0\n");
797 else
798 printf("1\n");
799 return 0;
f5300ab2
WD
800}
801
802int do_motor (char **argv)
803{
eb0ae7f5 804 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
f5300ab2
WD
805
806 /* Configure I/O port */
807 gpio->PGCON &= ~(0x3 << 0);
808 gpio->PGCON |= (0x1 << 0);
809
a0ff7f2e
WD
810 if (strcmp (argv[2], "on") == 0) {
811 gpio->PGDAT &= ~(1 << 0);
812 return 0;
813 }
814 if (strcmp (argv[2], "off") == 0) {
815 gpio->PGDAT |= (1 << 0);
816 return 0;
817 }
818 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
819 return 1;
f5300ab2
WD
820}
821
822static void print_identifier (void)
823{
a0ff7f2e 824 printf ("## FKT: ");
f5300ab2
WD
825}
826
827int do_pwm (char **argv)
828{
a0ff7f2e 829 int counter;
eb0ae7f5 830 struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
831 struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
f5300ab2 832
a0ff7f2e
WD
833 if (strcmp (argv[2], "on") == 0) {
834 /* configure pin GPD8 as TOUT3 */
835 gpio->PDCON &= ~(0x3 << 8*2);
836 gpio->PDCON |= (0x2 << 8*2);
837
838 /* set prescaler for timer 2, 3 and 4 */
839 timers->TCFG0 &= ~0xFF00;
840 timers->TCFG0 |= 0x0F00;
841
842 /* set divider for timer 3 */
843 timers->TCFG1 &= ~(0xf << 12);
844 timers->TCFG1 |= (0x3 << 12);
845
846 /* set frequency */
847 counter = (PCLK / PWM_FREQ) >> 9;
848 timers->ch[3].TCNTB = counter;
849 timers->ch[3].TCMPB = counter / 2;
850
851 /* start timer */
852 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
853 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
854 return 0;
855 }
856 if (strcmp (argv[2], "off") == 0) {
857
858 /* stop timer */
859 timers->TCON &= ~(START2 | RELOAD2);
860
861 /* configure pin GPD8 as output and set to 0 */
862 gpio->PDCON &= ~(0x3 << 8*2);
863 gpio->PDCON |= (0x1 << 8*2);
864 gpio->PDDAT &= ~(1 << 8);
865 return 0;
866 }
867 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
868 return 1;
f5300ab2
WD
869}
870
871
872int do_thermo (char **argv)
873{
a0ff7f2e
WD
874 int channel, res;
875
876 tsc2000_reg_init ();
877
878 if (strcmp (argv[2], "all") == 0) {
879 int i;
880 for (i=0; i <= 15; i++) {
881 res = tsc2000_read_channel(i);
882 print_identifier ();
883 printf ("c%d: %d\n", i, res);
884 }
885 return 0;
886 }
887 channel = simple_strtoul (argv[2], NULL, 10);
888 res = tsc2000_read_channel(channel);
889 print_identifier ();
890 printf ("%d\n", res);
891 return 0; /* return OK */
f5300ab2
WD
892}
893
894
f5300ab2
WD
895int do_touch (char **argv)
896{
a0ff7f2e
WD
897 int x, y;
898
899 if (strcmp (argv[2], "tl") == 0) {
42dfe7a1 900#ifdef CONFIG_TOUCH_WAIT_PRESSED
a0ff7f2e
WD
901 touch_wait_pressed();
902#else
903 {
904 int i;
905 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
906 if (touch_check_pressed ()) {
907 break;
908 }
909 udelay (1000); /* pause 1 ms */
910 }
911 }
912 if (!touch_check_pressed()) {
913 print_identifier ();
914 printf ("error: touch not pressed\n");
915 return 1;
916 }
917#endif /* CONFIG_TOUCH_WAIT_PRESSED */
918 touch_read_x_y (&x, &y);
919
920 print_identifier ();
921 printf ("x=%d y=%d\n", x, y);
922 return touch_write_clibration_values (CALIB_TL, x, y);
923 }
924 else if (strcmp (argv[2], "dr") == 0) {
42dfe7a1 925#ifdef CONFIG_TOUCH_WAIT_PRESSED
a0ff7f2e
WD
926 touch_wait_pressed();
927#else
928 {
929 int i;
930 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
931 if (touch_check_pressed ()) {
932 break;
933 }
934 udelay (1000); /* pause 1 ms */
935 }
936 }
937 if (!touch_check_pressed()) {
938 print_identifier ();
939 printf ("error: touch not pressed\n");
940 return 1;
941 }
942#endif /* CONFIG_TOUCH_WAIT_PRESSED */
943 touch_read_x_y (&x, &y);
944
945 print_identifier ();
946 printf ("x=%d y=%d\n", x, y);
947
948 return touch_write_clibration_values (CALIB_DR, x, y);
949 }
950 return 1; /* not "tl", nor "dr", so return error */
f5300ab2
WD
951}
952
953
a0ff7f2e 954#ifdef CONFIG_TOUCH_WAIT_PRESSED
f5300ab2
WD
955static void touch_wait_pressed (void)
956{
a0ff7f2e 957 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
f5300ab2
WD
958}
959
a0ff7f2e
WD
960#else
961static int touch_check_pressed (void)
962{
963 return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
964}
965#endif /* CONFIG_TOUCH_WAIT_PRESSED */
f5300ab2
WD
966
967static int touch_write_clibration_values (int calib_point, int x, int y)
968{
ab3abcba 969#if defined(CONFIG_CMD_I2C)
a0ff7f2e
WD
970 int x_verify = 0;
971 int y_verify = 0;
972
973 tsc2000_reg_init ();
974
975 if (calib_point == CALIB_TL) {
976 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
a63c31cf 977 (unsigned char *)&x, 2)) {
a0ff7f2e
WD
978 return 1;
979 }
980 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
a63c31cf 981 (unsigned char *)&y, 2)) {
a0ff7f2e
WD
982 return 1;
983 }
984
985 /* verify written values */
986 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
a63c31cf 987 (unsigned char *)&x_verify, 2)) {
a0ff7f2e
WD
988 return 1;
989 }
990 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
a63c31cf 991 (unsigned char *)&y_verify, 2)) {
a0ff7f2e
WD
992 return 1;
993 }
994 if ((y != y_verify) || (x != x_verify)) {
995 print_identifier ();
996 printf ("error: verify error\n");
997 return 1;
998 }
999 return 0; /* no error */
1000 }
1001 else if (calib_point == CALIB_DR) {
1002 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
a63c31cf 1003 (unsigned char *)&x, 2)) {
a0ff7f2e
WD
1004 return 1;
1005 }
1006 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
a63c31cf 1007 (unsigned char *)&y, 2)) {
a0ff7f2e
WD
1008 return 1;
1009 }
1010
1011 /* verify written values */
1012 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
a63c31cf 1013 (unsigned char *)&x_verify, 2)) {
a0ff7f2e
WD
1014 return 1;
1015 }
1016 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
a63c31cf 1017 (unsigned char *)&y_verify, 2)) {
a0ff7f2e
WD
1018 return 1;
1019 }
1020 if ((y != y_verify) || (x != x_verify)) {
1021 print_identifier ();
1022 printf ("error: verify error\n");
1023 return 1;
1024 }
1025 return 0;
1026 }
1027 return 1;
f5300ab2 1028#else
d39b5741 1029 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
a0ff7f2e
WD
1030 "to EEPROM\n");
1031 return (1);
d39b5741 1032#endif
f5300ab2
WD
1033}
1034
1035
1036static void touch_read_x_y (int *px, int *py)
1037{
a0ff7f2e
WD
1038 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1039 adc_wait_conversion_done();
1040 *px = tsc2000_read(TSC2000_REG_X);
f5300ab2 1041
a0ff7f2e
WD
1042 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1043 adc_wait_conversion_done();
1044 *py = tsc2000_read(TSC2000_REG_Y);
f5300ab2
WD
1045}
1046
1047
f5300ab2
WD
1048int do_rs485 (char **argv)
1049{
a0ff7f2e
WD
1050 int timeout;
1051 char data[RS485_MAX_RECEIVE_BUF_LEN];
1052
1053 if (strcmp (argv[2], "send") == 0) {
1054 return (rs485_send_line (argv[3]));
1055 }
1056 else if (strcmp (argv[2], "receive") == 0) {
1057 timeout = simple_strtoul(argv[3], NULL, 10);
1058 if (rs485_receive_chars (data, timeout) != 0) {
1059 print_identifier ();
1060 printf ("## nothing received\n");
1061 return (1);
1062 }
1063 else {
1064 print_identifier ();
1065 printf ("%s\n", data);
1066 return (0);
1067 }
1068 }
1069 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1070 return (1); /* unknown command, return error */
f5300ab2
WD
1071}
1072
1073
1074static int rs485_send_line (const char *data)
1075{
a0ff7f2e
WD
1076 rs485_init ();
1077 trab_rs485_enable_tx ();
1078 rs485_puts (data);
1079 rs485_putc ('\n');
f5300ab2 1080
a0ff7f2e 1081 return (0);
f5300ab2
WD
1082}
1083
1084
1085static int rs485_receive_chars (char *data, int timeout)
1086{
a0ff7f2e
WD
1087 int i;
1088 int receive_count = 0;
1089
1090 rs485_init ();
1091 trab_rs485_enable_rx ();
1092
1093 /* test every 1 ms for received characters to avoid a receive FIFO
1094 * overrun (@ 38.400 Baud) */
1095 for (i = 0; i < (timeout * 1000); i++) {
1096 while (rs485_tstc ()) {
1097 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1098 break;
1099 *data++ = rs485_getc ();
1100 receive_count++;
1101 }
1102 udelay (1000); /* pause 1 ms */
1103 }
1104 *data = '\0'; /* terminate string */
1105
1106 if (receive_count == 0)
1107 return (1);
1108 else
1109 return (0);
f5300ab2
WD
1110}
1111
1112
1113int do_serial_number (char **argv)
1114{
ab3abcba 1115#if defined(CONFIG_CMD_I2C)
a0ff7f2e
WD
1116 unsigned int serial_number;
1117
1118 if (strcmp (argv[2], "read") == 0) {
1119 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
a63c31cf 1120 (unsigned char *)&serial_number, 4)) {
a0ff7f2e
WD
1121 printf ("could not read from eeprom\n");
1122 return (1);
1123 }
1124 print_identifier ();
1125 printf ("%08d\n", serial_number);
1126 return (0);
1127 }
1128 else if (strcmp (argv[2], "write") == 0) {
1129 serial_number = simple_strtoul(argv[3], NULL, 10);
1130 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
a63c31cf 1131 (unsigned char *)&serial_number, 4)) {
a0ff7f2e
WD
1132 printf ("could not write to eeprom\n");
1133 return (1);
1134 }
1135 return (0);
1136 }
1137 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1138 return (1); /* unknown command, return error */
f5300ab2 1139#else
d39b5741 1140 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
a0ff7f2e
WD
1141 "to EEPROM\n");
1142 return (1);
d39b5741 1143#endif
f5300ab2
WD
1144}
1145
1146
1147int do_crc16 (void)
1148{
ab3abcba 1149#if defined(CONFIG_CMD_I2C)
a0ff7f2e 1150 int crc;
a63c31cf 1151 unsigned char buf[EEPROM_MAX_CRC_BUF];
a0ff7f2e
WD
1152
1153 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1154 printf ("could not read from eeprom\n");
1155 return (1);
1156 }
1157 crc = 0; /* start value of crc calculation */
1158 crc = updcrc (crc, buf, 60);
1159
1160 print_identifier ();
1161 printf ("crc16=%#04x\n", crc);
1162
a63c31cf 1163 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
a0ff7f2e
WD
1164 sizeof (crc))) {
1165 printf ("could not read from eeprom\n");
1166 return (1);
1167 }
1168 return (0);
f5300ab2 1169#else
d39b5741 1170 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
a0ff7f2e
WD
1171 "to EEPROM\n");
1172 return (1);
d39b5741 1173#endif
f5300ab2
WD
1174}
1175
1176
1177/*
1178 * Calculate, intelligently, the CRC of a dataset incrementally given a
1179 * buffer full at a time.
1180 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1181 *
1182 * Usage:
1183 * newcrc = updcrc( oldcrc, bufadr, buflen )
1184 * unsigned int oldcrc, buflen;
1185 * char *bufadr;
1186 *
1187 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1188 * Compile with -DMAKETAB to print values for crctab to stdout
1189 */
1190
1191 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1192 * If you change P, you must change crctab[]'s initial value to what is
1193 * printed by initcrctab()
1194 */
1195#define P 0x1021
1196
1197 /* number of bits in CRC: don't change it. */
1198#define W 16
1199
1200 /* this the number of bits per char: don't change it. */
1201#define B 8
1202
1203static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1204 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1205 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1206 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1207 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1208 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1209 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1210 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1211 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1212 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1213 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1214 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1215 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1216 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1217 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1218 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1219 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1220 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1221 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1222 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1223 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1224 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1225 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1226 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1227 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1228 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1229 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1230 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1231 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1232 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1233 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1234 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1235 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1236 };
1237
1238static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
a0ff7f2e
WD
1239 unsigned int icnt )
1240{
1241 register unsigned short crc = icrc;
1242 register unsigned char *cp = icp;
1243 register unsigned int cnt = icnt;
1244
1245 while (cnt--)
1246 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1247
1248 return (crc);
1249}
1250
1251
1252int do_gain (char **argv)
1253{
1254 int range;
1255
1256 range = simple_strtoul (argv[2], NULL, 10);
1257 if ((range < 1) || (range > 3))
1258 {
1259 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1260 return 1;
1261 }
1262
1263 tsc2000_set_range (range);
1264 return (0);
1265}
1266
1267
1268int do_eeprom (char **argv)
1269{
ab3abcba 1270#if defined(CONFIG_CMD_I2C)
a0ff7f2e
WD
1271 if (strcmp (argv[2], "read") == 0) {
1272 return (trab_eeprom_read (argv));
1273 }
1274
1275 else if (strcmp (argv[2], "write") == 0) {
1276 return (trab_eeprom_write (argv));
1277 }
1278
1279 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1280 return (1);
1281#else
d39b5741 1282 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
a0ff7f2e
WD
1283 "to EEPROM\n");
1284 return (1);
d39b5741 1285#endif
a0ff7f2e
WD
1286}
1287
ab3abcba 1288#if defined(CONFIG_CMD_I2C)
a0ff7f2e 1289static int trab_eeprom_read (char **argv)
f5300ab2 1290{
a0ff7f2e
WD
1291 int i;
1292 int len;
1293 unsigned int addr;
1294 long int value = 0;
1295 uchar *buffer;
1296
1297 buffer = (uchar *) &value;
1298 addr = simple_strtoul (argv[3], NULL, 10);
1299 addr &= 0xfff;
1300 len = simple_strtoul (argv[4], NULL, 10);
1301 if ((len < 1) || (len > 4)) {
1302 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1303 argv[4]);
1304 return (1);
1305 }
1306 for (i = 0; i < len; i++) {
1307 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1308 printf ("%s: could not read from i2c device %#x"
1309 ", addr %d\n", __FUNCTION__,
1310 I2C_EEPROM_DEV_ADDR, addr);
1311 return (1);
1312 }
1313 }
1314 print_identifier ();
1315 if (strcmp (argv[5], "-") == 0) {
1316 if (len == 1)
1317 printf ("%d\n", (signed char) value);
1318 else if (len == 2)
1319 printf ("%d\n", (signed short int) value);
1320 else
1321 printf ("%ld\n", value);
1322 }
1323 else {
1324 if (len == 1)
1325 printf ("%d\n", (unsigned char) value);
1326 else if (len == 2)
1327 printf ("%d\n", (unsigned short int) value);
1328 else
1329 printf ("%ld\n", (unsigned long int) value);
1330 }
1331 return (0);
1332}
1333
1334static int trab_eeprom_write (char **argv)
1335{
1336 int i;
1337 int len;
1338 unsigned int addr;
1339 long int value = 0;
1340 uchar *buffer;
1341
1342 buffer = (uchar *) &value;
1343 addr = simple_strtoul (argv[3], NULL, 10);
1344 addr &= 0xfff;
1345 len = simple_strtoul (argv[4], NULL, 10);
1346 if ((len < 1) || (len > 4)) {
1347 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1348 argv[4]);
1349 return (1);
1350 }
1351 value = simple_strtol (argv[5], NULL, 10);
1352 debug ("value=%ld\n", value);
1353 for (i = 0; i < len; i++) {
1354 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1355 printf ("%s: could not write to i2c device %d"
1356 ", addr %d\n", __FUNCTION__,
1357 I2C_EEPROM_DEV_ADDR, addr);
1358 return (1);
1359 }
1360#if 0
1361 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1362 "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1363 i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1364#endif
1365 udelay (30000); /* wait for EEPROM ready */
1366 }
1367 return (0);
1368}
f5300ab2 1369
a0ff7f2e
WD
1370int i2c_write_multiple (uchar chip, uint addr, int alen,
1371 uchar *buffer, int len)
1372{
1373 int i;
f5300ab2 1374
a0ff7f2e
WD
1375 if (alen != 1) {
1376 printf ("%s: addr len other than 1 not supported\n",
1377 __FUNCTION__);
1378 return (1);
1379 }
1380
1381 for (i = 0; i < len; i++) {
1382 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1383 printf ("%s: could not write to i2c device %d"
1384 ", addr %d\n", __FUNCTION__, chip, addr);
1385 return (1);
1386 }
1387#if 0
1388 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1389 "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1390 alen, buffer, i, buffer+i, buffer+i);
1391#endif
1392
1393 udelay (30000);
1394 }
1395 return (0);
f5300ab2 1396}
a0ff7f2e
WD
1397
1398int i2c_read_multiple ( uchar chip, uint addr, int alen,
1399 uchar *buffer, int len)
1400{
1401 int i;
1402
1403 if (alen != 1) {
1404 printf ("%s: addr len other than 1 not supported\n",
1405 __FUNCTION__);
1406 return (1);
1407 }
1408
1409 for (i = 0; i < len; i++) {
1410 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1411 printf ("%s: could not read from i2c device %#x"
1412 ", addr %d\n", __FUNCTION__, chip, addr);
1413 return (1);
1414 }
1415 }
1416 return (0);
1417}
d39b5741 1418#endif