MINI2440: Add a command to re-init CFI NOR
[u-boot-openmoko/mini2440.git] / board / trab / trab_fkt.c
blob7273ef97b659a7bf55f20fb74d6f6abd2d0ed754
1 /*
2 * (C) Copyright 2003
3 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
5 * See file CREDITS for list of people who contributed to this
6 * project.
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.
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.
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
24 #define DEBUG
26 #include <common.h>
27 #include <exports.h>
28 #include <s3c2400.h>
29 #include "tsc2000.h"
30 #include "rs485.h"
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.
38 #undef CONFIG_TOUCH_WAIT_PRESSED
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 */
45 /* assignment of CPU internal ADC channels with TRAB hardware */
46 #define VCC5V 2
47 #define VCC12V 3
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)
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)
65 #define PCLK 66000000
66 #define BUZZER_FREQ 1000 /* frequency in Hz */
67 #define PWM_FREQ 500
70 /* definitions of I2C EEPROM device address */
71 #define I2C_EEPROM_DEV_ADDR 0x54
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 */
77 /* EEPROM address map */
78 #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
85 /* EEPROM stuff */
86 #define EEPROM_MAX_CRC_BUF 64
88 /* RS485 stuff */
89 #define RS485_MAX_RECEIVE_BUF_LEN 100
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
106 /* function test functions */
107 int do_dip (void);
108 int do_info (void);
109 int do_vcc5v (void);
110 int do_vcc12v (void);
111 int do_buttons (void);
112 int do_fill_level (void);
113 int do_rotary_switch (void);
114 int do_pressure (void);
115 int do_v_bat (void);
116 int do_vfd_id (void);
117 int do_buzzer (char **);
118 int do_led (char **);
119 int do_full_bridge (char **);
120 int do_dac (char **);
121 int do_motor_contact (void);
122 int do_motor (char **);
123 int do_pwm (char **);
124 int do_thermo (char **);
125 int do_touch (char **);
126 int do_rs485 (char **);
127 int do_serial_number (char **);
128 int do_crc16 (void);
129 int do_power_switch (void);
130 int do_gain (char **);
131 int do_eeprom (char **);
133 /* helper functions */
134 static void adc_init (void);
135 static int adc_read (unsigned int channel);
136 static void print_identifier (void);
138 #ifdef CONFIG_TOUCH_WAIT_PRESSED
139 static void touch_wait_pressed (void);
140 #else
141 static int touch_check_pressed (void);
142 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
144 static void touch_read_x_y (int *x, int *y);
145 static int touch_write_clibration_values (int calib_point, int x, int y);
146 static int rs485_send_line (const char *data);
147 static int rs485_receive_chars (char *data, int timeout);
148 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
149 unsigned int icnt);
151 #if defined(CONFIG_CMD_I2C)
152 static int trab_eeprom_read (char **argv);
153 static int trab_eeprom_write (char **argv);
154 int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
155 int len);
156 int i2c_read_multiple ( uchar chip, uint addr, int alen, uchar *buffer,
157 int len);
158 #endif
161 * TRAB board specific commands. Especially commands for burn-in and function
162 * test.
165 int trab_fkt (int argc, char *argv[])
167 int i;
169 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;
178 debug ("argc = %d\n", argc);
180 for (i=0; i<=argc; ++i) {
181 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
184 adc_init ();
186 switch (argc) {
188 case 0:
189 case 1:
190 break;
192 case 2:
193 if (strcmp (argv[1], "info") == 0) {
194 return (do_info ());
196 if (strcmp (argv[1], "dip") == 0) {
197 return (do_dip ());
199 if (strcmp (argv[1], "vcc5v") == 0) {
200 return (do_vcc5v ());
202 if (strcmp (argv[1], "vcc12v") == 0) {
203 return (do_vcc12v ());
205 if (strcmp (argv[1], "buttons") == 0) {
206 return (do_buttons ());
208 if (strcmp (argv[1], "fill_level") == 0) {
209 return (do_fill_level ());
211 if (strcmp (argv[1], "rotary_switch") == 0) {
212 return (do_rotary_switch ());
214 if (strcmp (argv[1], "pressure") == 0) {
215 return (do_pressure ());
217 if (strcmp (argv[1], "v_bat") == 0) {
218 return (do_v_bat ());
220 if (strcmp (argv[1], "vfd_id") == 0) {
221 return (do_vfd_id ());
223 if (strcmp (argv[1], "motor_contact") == 0) {
224 return (do_motor_contact ());
226 if (strcmp (argv[1], "crc16") == 0) {
227 return (do_crc16 ());
229 if (strcmp (argv[1], "power_switch") == 0) {
230 return (do_power_switch ());
232 break;
234 case 3:
235 if (strcmp (argv[1], "full_bridge") == 0) {
236 return (do_full_bridge (argv));
238 if (strcmp (argv[1], "dac") == 0) {
239 return (do_dac (argv));
241 if (strcmp (argv[1], "motor") == 0) {
242 return (do_motor (argv));
244 if (strcmp (argv[1], "pwm") == 0) {
245 return (do_pwm (argv));
247 if (strcmp (argv[1], "thermo") == 0) {
248 return (do_thermo (argv));
250 if (strcmp (argv[1], "touch") == 0) {
251 return (do_touch (argv));
253 if (strcmp (argv[1], "serial_number") == 0) {
254 return (do_serial_number (argv));
256 if (strcmp (argv[1], "buzzer") == 0) {
257 return (do_buzzer (argv));
259 if (strcmp (argv[1], "gain") == 0) {
260 return (do_gain (argv));
262 break;
264 case 4:
265 if (strcmp (argv[1], "led") == 0) {
266 return (do_led (argv));
268 if (strcmp (argv[1], "rs485") == 0) {
269 return (do_rs485 (argv));
271 if (strcmp (argv[1], "serial_number") == 0) {
272 return (do_serial_number (argv));
274 break;
276 case 5:
277 if (strcmp (argv[1], "eeprom") == 0) {
278 return (do_eeprom (argv));
280 break;
282 case 6:
283 if (strcmp (argv[1], "eeprom") == 0) {
284 return (do_eeprom (argv));
286 break;
288 default:
289 break;
292 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
293 return 1;
296 int do_info (void)
298 printf ("Stand-alone application for TRAB board function test\n");
299 printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
301 return 0;
304 int do_dip (void)
306 unsigned int result = 0;
307 int adc_val;
308 int i;
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
317 "On" DIP switch position short-circuits the voltage from
318 the input channel (i.e. '0' conversion result means "on").
319 *************************************************************/
321 for (i = 7; i > 3; i--) {
323 if ((adc_val = adc_read (i)) == -1) {
324 printf ("Channel %d could not be read\n", i);
325 return 1;
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.
333 if (adc_val < 368)
334 result |= (1 << (i-4));
337 /* 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");
345 printf("\n");
347 return 0;
351 int do_vcc5v (void)
353 int result;
355 /* VCC5V is connected to channel 2 */
357 if ((result = adc_read (VCC5V)) == -1) {
358 printf ("VCC5V could not be read\n");
359 return 1;
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.
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);
373 return 0;
377 int do_vcc12v (void)
379 int result;
381 if ((result = adc_read (VCC12V)) == -1) {
382 printf ("VCC12V could not be read\n");
383 return 1;
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.
391 print_identifier ();
392 printf ("%d", (result & 0x3FF)* 25 / 1023);
393 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
395 return 0;
398 static int adc_read (unsigned int channel)
400 int j = 1000; /* timeout value for wait loop in us */
401 int result;
402 S3C2400_ADC *padc;
404 padc = S3C2400_GetBase_ADC();
405 channel &= 0x7;
407 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
408 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
409 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
411 while (j--) {
412 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
413 break;
414 udelay (1);
417 if (j == 0) {
418 printf("%s: ADC timeout\n", __FUNCTION__);
419 padc->ADCCON |= ADC_STDBM; /* select standby mode */
420 return -1;
423 result = padc->ADCDAT & 0x3FF;
425 padc->ADCCON |= ADC_STDBM; /* select standby mode */
427 debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
428 (padc->ADCCON >> 3) & 0x7, result);
431 * Wait for ADC to be ready for next conversion. This delay value was
432 * estimated, because the datasheet does not specify a value.
434 udelay (1000);
436 return (result);
440 static void adc_init (void)
442 S3C2400_ADC *padc;
444 padc = S3C2400_GetBase_ADC();
446 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
447 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
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?
455 udelay (1000);
457 return;
461 int do_buttons (void)
463 int result;
464 int i;
466 result = *CPLD_BUTTONS; /* read CPLD */
467 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
469 /* 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");
477 printf("\n");
478 return 0;
482 int do_power_switch (void)
484 int result;
486 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
488 /* configure GPE7 as input */
489 gpio->PECON &= ~(0x3 << (2 * 7));
491 /* signal GPE7 from power switch is low active: 0=on , 1=off */
492 result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
494 print_identifier ();
495 printf("%d\n", result);
496 return 0;
500 int do_fill_level (void)
502 int result;
504 result = *CPLD_FILL_LEVEL; /* read CPLD */
505 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
507 /* print result to console */
508 print_identifier ();
509 if ((result & (1 << 16)) == 0)
510 printf("0\n");
511 else
512 printf("1\n");
513 return 0;
517 int do_rotary_switch (void)
519 int result;
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.
527 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
528 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
530 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
532 /* 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");
544 return 0;
548 int do_vfd_id (void)
550 int i;
551 long int pcup_old, pccon_old;
552 int vfd_board_id;
553 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
555 /* try to red vfd board id from the value defined by pull-ups */
557 pcup_old = gpio->PCUP;
558 pccon_old = gpio->PCCON;
560 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
561 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
562 * inputs */
563 udelay (10); /* allow signals to settle */
564 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
566 gpio->PCCON = pccon_old;
567 gpio->PCUP = pcup_old;
569 /* 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");
577 printf("\n");
578 return 0;
581 int do_buzzer (char **argv)
583 int counter;
585 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
586 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
588 /* set prescaler for timer 2, 3 and 4 */
589 timers->TCFG0 &= ~0xFF00;
590 timers->TCFG0 |= 0x0F00;
592 /* set divider for timer 2 */
593 timers->TCFG1 &= ~0xF00;
594 timers->TCFG1 |= 0x300;
596 /* set frequency */
597 counter = (PCLK / BUZZER_FREQ) >> 9;
598 timers->ch[2].TCNTB = counter;
599 timers->ch[2].TCMPB = counter / 2;
601 if (strcmp (argv[2], "on") == 0) {
602 debug ("%s: frequency: %d\n", __FUNCTION__,
603 BUZZER_FREQ);
605 /* configure pin GPD7 as TOUT2 */
606 gpio->PDCON &= ~0xC000;
607 gpio->PDCON |= 0x8000;
609 /* start */
610 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
611 ~INVERT2;
612 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
613 return (0);
615 else if (strcmp (argv[2], "off") == 0) {
616 /* stop */
617 timers->TCON &= ~(START2 | RELOAD2);
619 /* configure GPD7 as output and set to low */
620 gpio->PDCON &= ~0xC000;
621 gpio->PDCON |= 0x4000;
622 gpio->PDDAT &= ~0x80;
623 return (0);
626 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
627 return 1;
631 int do_led (char **argv)
633 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
635 /* configure PC14 and PC15 as output */
636 gpio->PCCON &= ~(0xF << 28);
637 gpio->PCCON |= (0x5 << 28);
639 /* configure PD0 and PD4 as output */
640 gpio->PDCON &= ~((0x3 << 8) | 0x3);
641 gpio->PDCON |= ((0x1 << 8) | 0x1);
643 switch (simple_strtoul(argv[2], NULL, 10)) {
645 case 0:
646 case 1:
647 break;
649 case 2:
650 if (strcmp (argv[3], "on") == 0)
651 gpio->PCDAT |= (1 << 14);
652 else
653 gpio->PCDAT &= ~(1 << 14);
654 return 0;
656 case 3:
657 if (strcmp (argv[3], "on") == 0)
658 gpio->PCDAT |= (1 << 15);
659 else
660 gpio->PCDAT &= ~(1 << 15);
661 return 0;
663 case 4:
664 if (strcmp (argv[3], "on") == 0)
665 gpio->PDDAT |= (1 << 0);
666 else
667 gpio->PDDAT &= ~(1 << 0);
668 return 0;
670 case 5:
671 if (strcmp (argv[3], "on") == 0)
672 gpio->PDDAT |= (1 << 4);
673 else
674 gpio->PDDAT &= ~(1 << 4);
675 return 0;
677 default:
678 break;
681 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
682 return 1;
686 int do_full_bridge (char **argv)
688 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
690 /* configure PD5 and PD6 as output */
691 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
692 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
694 if (strcmp (argv[2], "+") == 0) {
695 gpio->PDDAT |= (1 << 5);
696 gpio->PDDAT |= (1 << 6);
697 return 0;
699 else if (strcmp (argv[2], "-") == 0) {
700 gpio->PDDAT &= ~(1 << 5);
701 gpio->PDDAT |= (1 << 6);
702 return 0;
704 else if (strcmp (argv[2], "off") == 0) {
705 gpio->PDDAT &= ~(1 << 5);
706 gpio->PDDAT &= ~(1 << 6);
707 return 0;
709 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
710 return 1;
713 /* val must be in [0, 4095] */
714 static inline unsigned long tsc2000_to_uv (u16 val)
716 return ((250000 * val) / 4096) * 10;
720 int do_dac (char **argv)
722 int brightness;
724 /* initialize SPI */
725 spi_init ();
727 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;
732 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
733 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
735 return 0;
739 int do_v_bat (void)
741 unsigned long ret, res;
743 /* initialize SPI */
744 spi_init ();
746 tsc2000_write(TSC2000_REG_ADC, 0x1836);
748 /* now wait for data available */
749 adc_wait_conversion_done();
751 ret = tsc2000_read(TSC2000_REG_BAT1);
752 res = (tsc2000_to_uv(ret) + 1250) / 2500;
753 res += (ERROR_BATTERY * res) / 1000;
755 print_identifier ();
756 printf ("%ld", (res / 100));
757 printf (".%ld", ((res % 100) / 10));
758 printf ("%ld V\n", (res % 10));
759 return 0;
763 int do_pressure (void)
765 /* initialize SPI */
766 spi_init ();
768 tsc2000_write(TSC2000_REG_ADC, 0x2436);
770 /* now wait for data available */
771 adc_wait_conversion_done();
773 print_identifier ();
774 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
775 return 0;
779 int do_motor_contact (void)
781 int result;
783 result = *CPLD_FILL_LEVEL; /* read CPLD */
784 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
786 /* 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;
795 int do_motor (char **argv)
797 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
799 /* Configure I/O port */
800 gpio->PGCON &= ~(0x3 << 0);
801 gpio->PGCON |= (0x1 << 0);
803 if (strcmp (argv[2], "on") == 0) {
804 gpio->PGDAT &= ~(1 << 0);
805 return 0;
807 if (strcmp (argv[2], "off") == 0) {
808 gpio->PGDAT |= (1 << 0);
809 return 0;
811 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
812 return 1;
815 static void print_identifier (void)
817 printf ("## FKT: ");
820 int do_pwm (char **argv)
822 int counter;
823 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
824 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
826 if (strcmp (argv[2], "on") == 0) {
827 /* configure pin GPD8 as TOUT3 */
828 gpio->PDCON &= ~(0x3 << 8*2);
829 gpio->PDCON |= (0x2 << 8*2);
831 /* set prescaler for timer 2, 3 and 4 */
832 timers->TCFG0 &= ~0xFF00;
833 timers->TCFG0 |= 0x0F00;
835 /* set divider for timer 3 */
836 timers->TCFG1 &= ~(0xf << 12);
837 timers->TCFG1 |= (0x3 << 12);
839 /* set frequency */
840 counter = (PCLK / PWM_FREQ) >> 9;
841 timers->ch[3].TCNTB = counter;
842 timers->ch[3].TCMPB = counter / 2;
844 /* start timer */
845 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
846 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
847 return 0;
849 if (strcmp (argv[2], "off") == 0) {
851 /* stop timer */
852 timers->TCON &= ~(START2 | RELOAD2);
854 /* 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;
860 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
861 return 1;
865 int do_thermo (char **argv)
867 int channel, res;
869 tsc2000_reg_init ();
871 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);
878 return 0;
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 */
888 int do_touch (char **argv)
890 int x, y;
892 if (strcmp (argv[2], "tl") == 0) {
893 #ifdef CONFIG_TOUCH_WAIT_PRESSED
894 touch_wait_pressed();
895 #else
897 int i;
898 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
899 if (touch_check_pressed ()) {
900 break;
902 udelay (1000); /* pause 1 ms */
905 if (!touch_check_pressed()) {
906 print_identifier ();
907 printf ("error: touch not pressed\n");
908 return 1;
910 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
911 touch_read_x_y (&x, &y);
913 print_identifier ();
914 printf ("x=%d y=%d\n", x, y);
915 return touch_write_clibration_values (CALIB_TL, x, y);
917 else if (strcmp (argv[2], "dr") == 0) {
918 #ifdef CONFIG_TOUCH_WAIT_PRESSED
919 touch_wait_pressed();
920 #else
922 int i;
923 for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
924 if (touch_check_pressed ()) {
925 break;
927 udelay (1000); /* pause 1 ms */
930 if (!touch_check_pressed()) {
931 print_identifier ();
932 printf ("error: touch not pressed\n");
933 return 1;
935 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
936 touch_read_x_y (&x, &y);
938 print_identifier ();
939 printf ("x=%d y=%d\n", x, y);
941 return touch_write_clibration_values (CALIB_DR, x, y);
943 return 1; /* not "tl", nor "dr", so return error */
947 #ifdef CONFIG_TOUCH_WAIT_PRESSED
948 static void touch_wait_pressed (void)
950 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
953 #else
954 static int touch_check_pressed (void)
956 return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
958 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
960 static int touch_write_clibration_values (int calib_point, int x, int y)
962 #if defined(CONFIG_CMD_I2C)
963 int x_verify = 0;
964 int y_verify = 0;
966 tsc2000_reg_init ();
968 if (calib_point == CALIB_TL) {
969 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
970 (unsigned char *)&x, 2)) {
971 return 1;
973 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
974 (unsigned char *)&y, 2)) {
975 return 1;
978 /* verify written values */
979 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
980 (unsigned char *)&x_verify, 2)) {
981 return 1;
983 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
984 (unsigned char *)&y_verify, 2)) {
985 return 1;
987 if ((y != y_verify) || (x != x_verify)) {
988 print_identifier ();
989 printf ("error: verify error\n");
990 return 1;
992 return 0; /* no error */
994 else if (calib_point == CALIB_DR) {
995 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
996 (unsigned char *)&x, 2)) {
997 return 1;
999 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1000 (unsigned char *)&y, 2)) {
1001 return 1;
1004 /* verify written values */
1005 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
1006 (unsigned char *)&x_verify, 2)) {
1007 return 1;
1009 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1010 (unsigned char *)&y_verify, 2)) {
1011 return 1;
1013 if ((y != y_verify) || (x != x_verify)) {
1014 print_identifier ();
1015 printf ("error: verify error\n");
1016 return 1;
1018 return 0;
1020 return 1;
1021 #else
1022 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1023 "to EEPROM\n");
1024 return (1);
1025 #endif
1029 static void touch_read_x_y (int *px, int *py)
1031 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1032 adc_wait_conversion_done();
1033 *px = tsc2000_read(TSC2000_REG_X);
1035 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1036 adc_wait_conversion_done();
1037 *py = tsc2000_read(TSC2000_REG_Y);
1041 int do_rs485 (char **argv)
1043 int timeout;
1044 char data[RS485_MAX_RECEIVE_BUF_LEN];
1046 if (strcmp (argv[2], "send") == 0) {
1047 return (rs485_send_line (argv[3]));
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);
1056 else {
1057 print_identifier ();
1058 printf ("%s\n", data);
1059 return (0);
1062 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1063 return (1); /* unknown command, return error */
1067 static int rs485_send_line (const char *data)
1069 rs485_init ();
1070 trab_rs485_enable_tx ();
1071 rs485_puts (data);
1072 rs485_putc ('\n');
1074 return (0);
1078 static int rs485_receive_chars (char *data, int timeout)
1080 int i;
1081 int receive_count = 0;
1083 rs485_init ();
1084 trab_rs485_enable_rx ();
1086 /* 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++;
1095 udelay (1000); /* pause 1 ms */
1097 *data = '\0'; /* terminate string */
1099 if (receive_count == 0)
1100 return (1);
1101 else
1102 return (0);
1106 int do_serial_number (char **argv)
1108 #if defined(CONFIG_CMD_I2C)
1109 unsigned int serial_number;
1111 if (strcmp (argv[2], "read") == 0) {
1112 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1113 (unsigned char *)&serial_number, 4)) {
1114 printf ("could not read from eeprom\n");
1115 return (1);
1117 print_identifier ();
1118 printf ("%08d\n", serial_number);
1119 return (0);
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,
1124 (unsigned char *)&serial_number, 4)) {
1125 printf ("could not write to eeprom\n");
1126 return (1);
1128 return (0);
1130 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1131 return (1); /* unknown command, return error */
1132 #else
1133 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1134 "to EEPROM\n");
1135 return (1);
1136 #endif
1140 int do_crc16 (void)
1142 #if defined(CONFIG_CMD_I2C)
1143 int crc;
1144 unsigned char buf[EEPROM_MAX_CRC_BUF];
1146 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1147 printf ("could not read from eeprom\n");
1148 return (1);
1150 crc = 0; /* start value of crc calculation */
1151 crc = updcrc (crc, buf, 60);
1153 print_identifier ();
1154 printf ("crc16=%#04x\n", crc);
1156 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
1157 sizeof (crc))) {
1158 printf ("could not read from eeprom\n");
1159 return (1);
1161 return (0);
1162 #else
1163 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1164 "to EEPROM\n");
1165 return (1);
1166 #endif
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.
1175 * Usage:
1176 * newcrc = updcrc( oldcrc, bufadr, buflen )
1177 * unsigned int oldcrc, buflen;
1178 * char *bufadr;
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
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()
1188 #define P 0x1021
1190 /* number of bits in CRC: don't change it. */
1191 #define W 16
1193 /* this the number of bits per char: don't change it. */
1194 #define B 8
1196 static 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
1231 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1232 unsigned int icnt )
1234 register unsigned short crc = icrc;
1235 register unsigned char *cp = icp;
1236 register unsigned int cnt = icnt;
1238 while (cnt--)
1239 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1241 return (crc);
1245 int do_gain (char **argv)
1247 int range;
1249 range = simple_strtoul (argv[2], NULL, 10);
1250 if ((range < 1) || (range > 3))
1252 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1253 return 1;
1256 tsc2000_set_range (range);
1257 return (0);
1261 int do_eeprom (char **argv)
1263 #if defined(CONFIG_CMD_I2C)
1264 if (strcmp (argv[2], "read") == 0) {
1265 return (trab_eeprom_read (argv));
1268 else if (strcmp (argv[2], "write") == 0) {
1269 return (trab_eeprom_write (argv));
1272 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1273 return (1);
1274 #else
1275 printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1276 "to EEPROM\n");
1277 return (1);
1278 #endif
1281 #if defined(CONFIG_CMD_I2C)
1282 static int trab_eeprom_read (char **argv)
1284 int i;
1285 int len;
1286 unsigned int addr;
1287 long int value = 0;
1288 uchar *buffer;
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);
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);
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);
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);
1324 return (0);
1327 static int trab_eeprom_write (char **argv)
1329 int i;
1330 int len;
1331 unsigned int addr;
1332 long int value = 0;
1333 uchar *buffer;
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);
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);
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 */
1360 return (0);
1363 int i2c_write_multiple (uchar chip, uint addr, int alen,
1364 uchar *buffer, int len)
1366 int i;
1368 if (alen != 1) {
1369 printf ("%s: addr len other than 1 not supported\n",
1370 __FUNCTION__);
1371 return (1);
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);
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
1386 udelay (30000);
1388 return (0);
1391 int i2c_read_multiple ( uchar chip, uint addr, int alen,
1392 uchar *buffer, int len)
1394 int i;
1396 if (alen != 1) {
1397 printf ("%s: addr len other than 1 not supported\n",
1398 __FUNCTION__);
1399 return (1);
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);
1409 return (0);
1411 #endif