Move TRAB burn-in tests to TRAB board directory
[platform/kernel/u-boot.git] / board / trab / trab_fkt.c
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>
28 #include <s3c2400.h>
29 #include "tsc2000.h"
30 #include "rs485.h"
31
32 /* assignment of CPU internal ADC channels with TRAB hardware */
33 #define VCC5V   2
34 #define VCC12V  3
35
36 /* CPLD-Register for controlling TRAB hardware functions */
37 #define CPLD_BUTTONS            ((volatile unsigned long *)0x04020000)
38 #define CPLD_FILL_LEVEL         ((volatile unsigned long *)0x04008000)
39 #define CPLD_ROTARY_SWITCH      ((volatile unsigned long *)0x04018000)
40 #define CPLD_RS485_RE           ((volatile unsigned long *)0x04028000)
41
42 /* timer configuration bits for buzzer and PWM */
43 #define START2          (1 << 12)
44 #define UPDATE2         (1 << 13)
45 #define INVERT2         (1 << 14)
46 #define RELOAD2         (1 << 15)
47 #define START3          (1 << 16)
48 #define UPDATE3         (1 << 17)
49 #define INVERT3         (1 << 18)
50 #define RELOAD3         (1 << 19)
51
52 #define PCLK            66000000
53 #define BUZZER_FREQ     1000    /* frequency in Hz */
54 #define BUZZER_TIME     1000000 /* time in us */
55 #define PWM_FREQ        500
56
57
58 /* definitions of I2C EEPROM device address */
59 #define I2C_EEPROM_DEV_ADDR     0x54
60
61 /* definition for touch panel calibration points */
62 #define CALIB_TL 0              /* calibration point in (T)op (L)eft corner */
63 #define CALIB_DR 1              /* calibration point in (D)own (R)ight corner */
64
65 /* EEPROM addresse map */
66 #define SERIAL_NUMBER           8
67 #define TOUCH_X0                52
68 #define TOUCH_Y0                54
69 #define TOUCH_X1                56
70 #define TOUCH_Y1                58
71 #define CRC16                   60
72
73 /* EEPROM stuff */
74 #define EEPROM_MAX_CRC_BUF      64
75
76 /* RS485 stuff */
77 #define RS485_MAX_RECEIVE_BUF_LEN  100
78
79 /* Bit definitions for ADCCON */
80 #define ADC_ENABLE_START     0x1
81 #define ADC_READ_START       0x2
82 #define ADC_STDBM            0x4
83 #define ADC_INP_AIN0         (0x0 << 3)
84 #define ADC_INP_AIN1         (0x1 << 3)
85 #define ADC_INP_AIN2         (0x2 << 3)
86 #define ADC_INP_AIN3         (0x3 << 3)
87 #define ADC_INP_AIN4         (0x4 << 3)
88 #define ADC_INP_AIN5         (0x5 << 3)
89 #define ADC_INP_AIN6         (0x6 << 3)
90 #define ADC_INP_AIN7         (0x7 << 3)
91 #define ADC_PRSCEN           0x4000
92 #define ADC_ECFLG            0x8000
93
94 /* function test functions */
95 int do_dip (void);
96 int do_info (void);
97 int do_vcc5v (void);
98 int do_vcc12v (void);
99 int do_buttons (void);
100 int do_fill_level (void);
101 int do_rotary_switch (void);
102 int do_pressure (void);
103 int do_v_bat (void);
104 int do_vfd_id (void);
105 int do_buzzer (void);
106 int do_led (char **);
107 int do_full_bridge (char **);
108 int do_dac (char **);
109 int do_motor_contact (void);
110 int do_motor (char **);
111 int do_pwm (char **);
112 int do_thermo (char **);
113 int do_touch (char **);
114 int do_rs485 (char **);
115 int do_serial_number (char **);
116 int do_crc16 (void);
117
118 /* helper functions */
119 static void adc_init (void);
120 static int adc_read (unsigned int channel);
121 static void print_identifier (void);
122 static void touch_wait_pressed (void);
123 static void touch_read_x_y (int *x, int *y);
124 static int touch_write_clibration_values (int calib_point, int x, int y);
125 static int rs485_send_line (const char *data);
126 static int rs485_receive_chars (char *data, int timeout);
127 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
128                              unsigned int icnt);
129
130
131 /*
132  * TRAB board specific commands. Especially commands for burn-in and function
133  * test.
134  */
135
136 int trab_fkt (int argc, char *argv[])
137 {
138         int i;
139
140         app_startup(argv);
141         if (get_version () != XF_VERSION) {
142                 printf ("Wrong XF_VERSION. Please re-compile with actual "
143                         "u-boot sources\n");
144                 printf ("Example expects ABI version %d\n", XF_VERSION);
145                 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
146                 return 1;
147         }
148
149         debug ("argc = %d\n", argc);
150
151         for (i=0; i<=argc; ++i) {
152                 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
153         }
154
155         adc_init ();
156
157         switch (argc) {
158
159         case 0:
160         case 1:
161                 break;
162
163         case 2:
164                 if (strcmp (argv[1], "info") == 0) {
165                         return (do_info ());
166                 }
167                 if (strcmp (argv[1], "dip") == 0) {
168                         return (do_dip ());
169                 }
170                 if (strcmp (argv[1], "vcc5v") == 0) {
171                         return (do_vcc5v ());
172                 }
173                 if (strcmp (argv[1], "vcc12v") == 0) {
174                         return (do_vcc12v ());
175                 }
176                 if (strcmp (argv[1], "buttons") == 0) {
177                         return (do_buttons ());
178                 }
179                 if (strcmp (argv[1], "fill_level") == 0) {
180                         return (do_fill_level ());
181                 }
182                 if (strcmp (argv[1], "rotary_switch") == 0) {
183                         return (do_rotary_switch ());
184                 }
185                 if (strcmp (argv[1], "pressure") == 0) {
186                         return (do_pressure ());
187                 }
188                 if (strcmp (argv[1], "v_bat") == 0) {
189                         return (do_v_bat ());
190                 }
191                 if (strcmp (argv[1], "vfd_id") == 0) {
192                         return (do_vfd_id ());
193                 }
194                 if (strcmp (argv[1], "buzzer") == 0) {
195                         return (do_buzzer ());
196                 }
197                 if (strcmp (argv[1], "motor_contact") == 0) {
198                         return (do_motor_contact ());
199                 }
200                 if (strcmp (argv[1], "crc16") == 0) {
201                         return (do_crc16 ());
202                 }
203                 break;
204
205         case 3:
206                 if (strcmp (argv[1], "full_bridge") == 0) {
207                         return (do_full_bridge (argv));
208                 }
209                 if (strcmp (argv[1], "dac") == 0) {
210                         return (do_dac (argv));
211                 }
212                 if (strcmp (argv[1], "motor") == 0) {
213                         return (do_motor (argv));
214                 }
215                 if (strcmp (argv[1], "pwm") == 0) {
216                         return (do_pwm (argv));
217                 }
218                 if (strcmp (argv[1], "thermo") == 0) {
219                         return (do_thermo (argv));
220                 }
221                 if (strcmp (argv[1], "touch") == 0) {
222                         return (do_touch (argv));
223                 }
224                 if (strcmp (argv[1], "serial_number") == 0) {
225                         return (do_serial_number (argv));
226                 }
227                 break;
228
229         case 4:
230                 if (strcmp (argv[1], "led") == 0) {
231                         return (do_led (argv));
232                 }
233                 if (strcmp (argv[1], "rs485") == 0) {
234                         return (do_rs485 (argv));
235                 }
236                 if (strcmp (argv[1], "serial_number") == 0) {
237                         return (do_serial_number (argv));
238                 }
239                 break;
240
241         default:
242                 break;
243         }
244
245         printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
246         return 1;
247 }
248
249 int do_info (void)
250 {
251         printf ("Stand-alone application for TRAB board function test\n");
252         printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
253
254         return 0;
255 }
256
257 int do_dip (void)
258 {
259         unsigned int result = 0;
260         int adc_val;
261         int i;
262
263         /***********************************************************
264          DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
265            SW1 - AIN4
266            SW2 - AIN5
267            SW3 - AIN6
268            SW4 - AIN7
269
270            "On" DIP switch position short-circuits the voltage from
271            the input channel (i.e. '0' conversion result means "on").
272         *************************************************************/
273
274         for (i = 7; i > 3; i--) {
275
276                 if ((adc_val = adc_read (i)) == -1) {
277                         printf ("Channel %d could not be read\n", i);
278                         return 1;
279                 }
280
281                 /*
282                  * Input voltage (switch open) is 1.8 V.
283                  * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
284                  * Set trigger at halve that value.
285                  */
286                 if (adc_val < 368)
287                         result |= (1 << (i-4));
288         }
289
290         /* print result to console */
291         print_identifier ();
292         for (i = 0; i < 4; i++) {
293                 if ((result & (1 << i)) == 0)
294                         printf("0");
295                 else
296                         printf("1");
297         }
298         printf("\n");
299
300         return 0;
301 }
302
303
304 int do_vcc5v (void)
305 {
306         int result;
307
308         /* VCC5V is connected to channel 2 */
309
310         if ((result = adc_read (VCC5V)) == -1) {
311                 printf ("VCC5V could not be read\n");
312                 return 1;
313         }
314
315         /*
316          * Calculate voltage value. Split in two parts because there is no
317          * floating point support.  VCC5V is connected over an resistor divider:
318          * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
319          */
320         print_identifier ();
321         printf ("%d", (result & 0x3FF)* 10 / 1023);
322         printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
323         printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
324                 * 10 / 1024);
325
326         return 0;
327 }
328
329
330 int do_vcc12v (void)
331 {
332         int result;
333
334         if ((result = adc_read (VCC12V)) == -1) {
335                 printf ("VCC12V could not be read\n");
336                 return 1;
337         }
338
339         /*
340          * Calculate voltage value. Split in two parts because there is no
341          * floating point support.  VCC5V is connected over an resistor divider:
342          * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
343          */
344         print_identifier ();
345         printf ("%d", (result & 0x3FF)* 25 / 1023);
346         printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
347
348         return 0;
349 }
350
351 static int adc_read (unsigned int channel)
352 {
353         int j = 1000; /* timeout value for wait loop in us */
354         S3C2400_ADC *padc;
355
356         padc = S3C2400_GetBase_ADC();
357         channel &= 0x7;
358
359         debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
360
361         padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
362         padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
363         padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
364
365         debug ("%s: reading ch %d, addcon %#x\n", __FUNCTION__,
366             (padc->ADCCON >> 3) & 0x7, padc->ADCCON);
367
368         while (j--) {
369                 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
370                         break;
371                 udelay (1);
372         }
373
374         if (j == 0) {
375                 printf("%s: ADC timeout\n", __FUNCTION__);
376                 padc->ADCCON |= ADC_STDBM; /* select standby mode */
377                 return -1;
378         }
379
380         padc->ADCCON |= ADC_STDBM; /* select standby mode */
381
382         debug ("%s: return %#x, adccon %#x\n", __FUNCTION__, padc->ADCDAT & 0x3FF,
383             padc->ADCCON);
384
385         return (padc->ADCDAT & 0x3FF);
386 }
387
388
389 static void adc_init (void)
390 {
391         S3C2400_ADC *padc;
392
393         padc = S3C2400_GetBase_ADC();
394
395         debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
396
397         padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
398         padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
399
400         debug ("%s: init completed: adccon %#x\n", __FUNCTION__, padc->ADCCON);
401         return;
402 }
403
404
405 int do_buttons (void)
406 {
407         int result;
408         int i;
409
410         result = *CPLD_BUTTONS; /* read CPLD */
411         debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
412
413         /* print result to console */
414         print_identifier ();
415         for (i = 16; i <= 19; i++) {
416                 if ((result & (1 << i)) == 0)
417                         printf("0");
418                 else
419                         printf("1");
420         }
421         printf("\n");
422         return 0;
423 }
424
425
426 int do_fill_level (void)
427 {
428         int result;
429
430         result = *CPLD_FILL_LEVEL; /* read CPLD */
431         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
432
433         /* print result to console */
434         print_identifier ();
435         if ((result & (1 << 16)) == 0)
436                 printf("0\n");
437         else
438                 printf("1\n");
439         return 0;
440 }
441
442
443 int do_rotary_switch (void)
444 {
445         int result;
446
447         result = *CPLD_ROTARY_SWITCH; /* read CPLD */
448         debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
449
450         *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
451
452         /* print result to console */
453         print_identifier ();
454         if ((result & (1 << 16)) == (1 << 16))
455                 printf("R");
456         if ((result & (1 << 17)) == (1 << 17))
457                 printf("L");
458         if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
459                 printf("0");
460         if ((result & (1 << 18)) == 0)
461                 printf("0\n");
462         else
463                 printf("1\n");
464         return 0;
465 }
466
467
468 int do_vfd_id (void)
469 {
470         int i;
471         long int pcup_old, pccon_old;
472         int vfd_board_id;
473         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
474
475         /* try to red vfd board id from the value defined by pull-ups */
476
477         pcup_old = gpio->PCUP;
478         pccon_old = gpio->PCCON;
479
480         gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate  GPC0...GPC3 pull-ups */
481         gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
482                                                    * inputs */
483         udelay (10);            /* allow signals to settle */
484         vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
485
486         gpio->PCCON = pccon_old;
487         gpio->PCUP = pcup_old;
488
489         /* print vfd_board_id to console */
490         print_identifier ();
491         for (i = 0; i < 4; i++) {
492                 if ((vfd_board_id & (1 << i)) == 0)
493                         printf("0");
494                 else
495                         printf("1");
496         }
497         printf("\n");
498         return 0;
499 }
500
501 int do_buzzer (void)
502 {
503         int counter;
504
505         S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
506         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
507
508         /* configure pin GPD7 as TOUT2 */
509         gpio->PDCON &= ~0xC000;
510         gpio->PDCON |= 0x8000;
511
512         /* set prescaler for timer 2, 3 and 4 */
513         timers->TCFG0 &= ~0xFF00;
514         timers->TCFG0 |=  0x0F00;
515
516         /* set divider for timer 2 */
517         timers->TCFG1 &= ~0xF00;
518         timers->TCFG1 |=  0x300;
519
520         /* set frequency */
521         counter = (PCLK / BUZZER_FREQ) >> 9;
522         timers->ch[2].TCNTB = counter;
523         timers->ch[2].TCMPB = counter / 2;
524
525         debug ("%s: frequency: %d, duration: %d\n", __FUNCTION__, BUZZER_FREQ,
526             BUZZER_TIME);
527
528         /* start */
529         timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) & ~INVERT2;
530         timers->TCON = (timers->TCON | START2) & ~UPDATE2;
531
532         udelay (BUZZER_TIME);
533
534         /* stop */
535         timers->TCON &= ~(START2 | RELOAD2);
536
537         /* port pin configuration */
538         gpio->PDCON &= ~0xC000;
539         gpio->PDCON |= 0x4000;
540         gpio->PDDAT &= ~0x80;
541         return 0;
542 }
543
544
545 int do_led (char **argv)
546 {
547         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
548
549         /* configure PC14 and PC15 as output */
550         gpio->PCCON &= ~(0xF << 28);
551         gpio->PCCON |= (0x5 << 28);
552
553         /* configure PD0 and PD4 as output */
554         gpio->PDCON &= ~((0x3 << 8) | 0x3);
555         gpio->PDCON |= ((0x1 << 8) | 0x1);
556
557         switch (simple_strtoul(argv[2], NULL, 10)) {
558
559         case 0:
560         case 1:
561                 break;
562
563         case 2:
564                 if (strcmp (argv[3], "on") == 0)
565                         gpio->PCDAT |= (1 << 14);
566                 else
567                         gpio->PCDAT &= ~(1 << 14);
568                 return 0;
569
570         case 3:
571                 if (strcmp (argv[3], "on") == 0)
572                         gpio->PCDAT |= (1 << 15);
573                 else
574                         gpio->PCDAT &= ~(1 << 15);
575                 return 0;
576
577         case 4:
578                 if (strcmp (argv[3], "on") == 0)
579                         gpio->PDDAT |= (1 << 0);
580                 else
581                         gpio->PDDAT &= ~(1 << 0);
582                 return 0;
583
584         case 5:
585                 if (strcmp (argv[3], "on") == 0)
586                         gpio->PDDAT |= (1 << 4);
587                 else
588                         gpio->PDDAT &= ~(1 << 4);
589                 return 0;
590
591         default:
592                 break;
593
594         }
595         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
596         return 1;
597 }
598
599
600 int do_full_bridge (char **argv)
601 {
602         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
603
604         /* configure PD5 and PD6 as output */
605         gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
606         gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
607
608         if (strcmp (argv[2], "+") == 0) {
609               gpio->PDDAT |= (1 << 5);
610               gpio->PDDAT |= (1 << 6);
611               return 0;
612         }
613         else if (strcmp (argv[2], "-") == 0) {
614                 gpio->PDDAT &= ~(1 << 5);
615                 gpio->PDDAT |= (1 << 6);
616                 return 0;
617         }
618         else if (strcmp (argv[2], "off") == 0) {
619                 gpio->PDDAT &= ~(1 << 5);
620                 gpio->PDDAT &= ~(1 << 6);
621                 return 0;
622         }
623         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
624         return 1;
625 }
626
627 /* val must be in [0, 4095] */
628 static inline unsigned long tsc2000_to_uv (u16 val)
629 {
630         return ((250000 * val) / 4096) * 10;
631 }
632
633
634 int do_dac (char **argv)
635 {
636         int brightness;
637
638         /* initialize SPI */
639         spi_init ();
640
641         if  (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
642              (brightness > 255)) {
643                 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
644                 return 1;
645         }
646         tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
647         tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
648
649         return 0;
650 }
651
652
653 int do_v_bat (void)
654 {
655         unsigned long ret, res;
656
657         /* initialize SPI */
658         spi_init ();
659
660         tsc2000_write(TSC2000_REG_ADC, 0x1836);
661
662         /* now wait for data available */
663         adc_wait_conversion_done();
664
665         ret = tsc2000_read(TSC2000_REG_BAT1);
666         res = (tsc2000_to_uv(ret) + 1250) / 2500;
667         res += (ERROR_BATTERY * res) / 1000;
668
669         print_identifier ();
670         printf ("%ld", (res / 100));
671         printf (".%ld", ((res % 100) / 10));
672         printf ("%ld V\n", (res % 10));
673         return 0;
674 }
675
676
677 int do_pressure (void)
678 {
679         /* initialize SPI */
680         spi_init ();
681
682         tsc2000_write(TSC2000_REG_ADC, 0x2436);
683
684         /* now wait for data available */
685         adc_wait_conversion_done();
686
687         print_identifier ();
688         printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
689         return 0;
690 }
691
692
693 int do_motor_contact (void)
694 {
695         int result;
696
697         result = *CPLD_FILL_LEVEL; /* read CPLD */
698         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
699
700         /* print result to console */
701         print_identifier ();
702         if ((result & (1 << 17)) == 0)
703                 printf("0\n");
704         else
705                 printf("1\n");
706         return 0;
707 }
708
709 int do_motor (char **argv)
710 {
711         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
712
713         /* Configure I/O port */
714         gpio->PGCON &= ~(0x3 << 0);
715         gpio->PGCON |= (0x1 << 0);
716
717         if (strcmp (argv[2], "on") == 0) {
718                 gpio->PGDAT &= ~(1 << 0);
719                 return 0;
720         }
721         if (strcmp (argv[2], "off") == 0) {
722                 gpio->PGDAT |= (1 << 0);
723                 return 0;
724         }
725         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
726         return 1;
727 }
728
729 static void print_identifier (void)
730 {
731         printf ("## FKT: ");
732 }
733
734 int do_pwm (char **argv)
735 {
736         int counter;
737         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
738         S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
739
740         if (strcmp (argv[2], "on") == 0) {
741                 /* configure pin GPD8 as TOUT3 */
742                 gpio->PDCON &= ~(0x3 << 8*2);
743                 gpio->PDCON |= (0x2 << 8*2);
744
745                 /* set prescaler for timer 2, 3 and 4 */
746                 timers->TCFG0 &= ~0xFF00;
747                 timers->TCFG0 |= 0x0F00;
748
749                 /* set divider for timer 3 */
750                 timers->TCFG1 &= ~(0xf << 12);
751                 timers->TCFG1 |= (0x3 << 12);
752
753                 /* set frequency */
754                 counter = (PCLK / PWM_FREQ) >> 9;
755                 timers->ch[3].TCNTB = counter;
756                 timers->ch[3].TCMPB = counter / 2;
757
758                 /* start timer */
759                 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
760                 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
761                 return 0;
762         }
763         if (strcmp (argv[2], "off") == 0) {
764
765                 /* stop timer */
766                 timers->TCON &= ~(START2 | RELOAD2);
767
768                 /* configure pin GPD8 as output and set to 0 */
769                 gpio->PDCON &= ~(0x3 << 8*2);
770                 gpio->PDCON |= (0x1 << 8*2);
771                 gpio->PDDAT &= ~(1 << 8);
772                 return 0;
773         }
774         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
775         return 1;
776 }
777
778
779 int do_thermo (char **argv)
780 {
781         int     channel, res;
782
783         tsc2000_reg_init ();
784         tsc2000_set_range (3);
785
786         if (strcmp (argv[2], "all") == 0) {
787                 int i;
788                 for (i=0; i <= 15; i++) {
789                         res = tsc2000_read_channel(i);
790                         print_identifier ();
791                         printf ("c%d: %d\n", i, res);
792                 }
793                 return 0;
794         }
795         channel = simple_strtoul (argv[2], NULL, 10);
796         res = tsc2000_read_channel(channel);
797         print_identifier ();
798         printf ("%d\n", res);
799         return 0;                 /* return OK */
800 }
801
802
803
804 int do_touch (char **argv)
805 {
806         int     x, y;
807
808         if (strcmp (argv[2], "tl") == 0) {
809                 touch_wait_pressed();
810                 touch_read_x_y (&x, &y);
811
812                 print_identifier ();
813                 printf ("x=%d y=%d\n", x, y);
814                 return touch_write_clibration_values (CALIB_TL, x, y);
815         }
816         else if (strcmp (argv[2], "dr") == 0) {
817                 touch_wait_pressed();
818                 touch_read_x_y (&x, &y);
819
820                 print_identifier ();
821                 printf ("x=%d y=%d\n", x, y);
822
823                 return touch_write_clibration_values (CALIB_DR, x, y);
824         }
825         return 1;                 /* return error */
826 }
827
828
829 static void touch_wait_pressed (void)
830 {
831         while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
832 }
833
834
835 static int touch_write_clibration_values (int calib_point, int x, int y)
836 {
837 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
838      tsc2000_reg_init ();
839
840         if (calib_point == CALIB_TL) {
841                 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
842                                (char *)&x, 2)) {
843                         printf ("could not write to eeprom\n");
844                         return 1;
845                 }
846                 udelay(11000);
847                 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
848                                (char *)&y, 2)) {
849                         printf ("could not write to eeprom\n");
850                         return 1;
851                 }
852                 udelay(11000);
853                 return 0;
854         }
855         else if (calib_point == CALIB_DR) {
856                   if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
857                                (char *)&x, 2)) {
858                           printf ("could not write to eeprom\n");
859                         return 1;
860                   }
861                 udelay(11000);
862                 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
863                                (char *)&y, 2)) {
864                         printf ("could not write to eeprom\n");
865                         return 1;
866                 }
867                 udelay(11000);
868                 return 0;
869         }
870         return 1;
871 #else
872         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
873                 "to EEPROM\n");
874         return (1);
875 #endif /* CFG_CMD_I2C */
876 }
877
878
879 static void touch_read_x_y (int *px, int *py)
880 {
881         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
882         adc_wait_conversion_done();
883         *px = tsc2000_read(TSC2000_REG_X);
884
885         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
886         adc_wait_conversion_done();
887         *py = tsc2000_read(TSC2000_REG_Y);
888 }
889
890
891
892 int do_rs485 (char **argv)
893 {
894         int timeout;
895         char data[RS485_MAX_RECEIVE_BUF_LEN];
896
897         if (strcmp (argv[2], "send") == 0) {
898                 return (rs485_send_line (argv[3]));
899         }
900         else if (strcmp (argv[2], "receive") == 0) {
901                 timeout = simple_strtoul(argv[3], NULL, 10);
902                 if (rs485_receive_chars (data, timeout) != 0) {
903                         print_identifier ();
904                         printf ("## nothing received\n");
905                         return (1);
906                 }
907                 else {
908                         print_identifier ();
909                         printf ("%s\n", data);
910                         return (0);
911                 }
912         }
913         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
914         return (1);             /* unknown command, return error */
915 }
916
917
918 static int rs485_send_line (const char *data)
919 {
920         rs485_init ();
921         trab_rs485_enable_tx ();
922         rs485_puts (data);
923         rs485_putc ('\n');
924
925         return (0);
926 }
927
928
929 static int rs485_receive_chars (char *data, int timeout)
930 {
931         int i;
932         int receive_count = 0;
933
934         rs485_init ();
935         trab_rs485_enable_rx ();
936
937         /* test every 1 ms for received characters to avoid a receive FIFO
938          * overrun (@ 38.400 Baud) */
939         for (i = 0; i < (timeout * 1000); i++) {
940                 while (rs485_tstc ()) {
941                         if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
942                                 break;
943                         *data++ = rs485_getc ();
944                         receive_count++;
945                 }
946                 udelay (1000);  /* pause 1 ms */
947         }
948         *data = '\0';           /* terminate string */
949
950         if (receive_count == 0)
951                 return (1);
952         else
953                 return (0);
954 }
955
956
957 int do_serial_number (char **argv)
958 {
959 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
960         unsigned int serial_number;
961
962         if (strcmp (argv[2], "read") == 0) {
963                 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
964                               (char *)&serial_number, 4)) {
965                         printf ("could not read from eeprom\n");
966                         return (1);
967                 }
968                 print_identifier ();
969                 printf ("%08d\n", serial_number);
970                 return (0);
971         }
972         else if (strcmp (argv[2], "write") == 0) {
973                 serial_number = simple_strtoul(argv[3], NULL, 10);
974                 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
975                               (char *)&serial_number, 4)) {
976                         printf ("could not write to eeprom\n");
977                         return (1);
978                 }
979                 return (0);
980         }
981         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
982         return (1);             /* unknown command, return error */
983 #else
984         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
985                 "to EEPROM\n");
986         return (1);
987 #endif /* CFG_CMD_I2C */
988 }
989
990
991 int do_crc16 (void)
992 {
993 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
994         int crc;
995         char buf[EEPROM_MAX_CRC_BUF];
996
997         if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
998                 printf ("could not read from eeprom\n");
999                 return (1);
1000         }
1001         crc = 0;                /* start value of crc calculation */
1002         crc = updcrc (crc, buf, 60);
1003
1004         print_identifier ();
1005         printf ("crc16=%#04x\n", crc);
1006
1007         if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
1008                        sizeof (crc))) {
1009                 printf ("could not read from eeprom\n");
1010                 return (1);
1011         }
1012         return (0);
1013 #else
1014         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1015                 "to EEPROM\n");
1016         return (1);
1017 #endif /* CFG_CMD_I2C */
1018 }
1019
1020
1021 /*
1022  * Calculate, intelligently, the CRC of a dataset incrementally given a
1023  * buffer full at a time.
1024  * Initialize crc to 0 for XMODEM, -1 for CCITT.
1025  *
1026  * Usage:
1027  *   newcrc = updcrc( oldcrc, bufadr, buflen )
1028  *        unsigned int oldcrc, buflen;
1029  *        char *bufadr;
1030  *
1031  * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1032  * Compile with -DMAKETAB to print values for crctab to stdout
1033  */
1034
1035     /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1036      * If you change P, you must change crctab[]'s initial value to what is
1037      * printed by initcrctab()
1038      */
1039 #define   P    0x1021
1040
1041     /* number of bits in CRC: don't change it. */
1042 #define W 16
1043
1044     /* this the number of bits per char: don't change it. */
1045 #define B 8
1046
1047 static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1048     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
1049     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
1050     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
1051     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
1052     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
1053     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
1054     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
1055     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
1056     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
1057     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
1058     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
1059     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
1060     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
1061     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
1062     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
1063     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
1064     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
1065     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
1066     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
1067     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
1068     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
1069     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
1070     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
1071     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
1072     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
1073     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
1074     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
1075     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
1076     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
1077     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
1078     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
1079     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
1080     };
1081
1082 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1083                              unsigned int icnt )
1084 {
1085         register unsigned short crc = icrc;
1086         register unsigned char *cp = icp;
1087         register unsigned int cnt = icnt;
1088
1089         while (cnt--)
1090                 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1091
1092         return (crc);
1093 }