]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/trab/trab_fkt.c
* Patches by Xianghua Xiao, 15 Oct 2003:
[karo-tx-uboot.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 /*
33  * define, to wait for the touch to be pressed, before reading coordinates in
34  * command do_touch. If not defined, an error message is printed, when the
35  * command do_touch is invoked and the touch is not pressed within an specific
36  * interval.
37  */
38 #undef  CONFIG_TOUCH_WAIT_PRESSED 1
39
40 /* max time to wait for touch is pressed */
41 #ifndef CONFIG_TOUCH_WAIT_PRESSED
42 #define TOUCH_TIMEOUT   5
43 #endif /* !CONFIG_TOUCH_WAIT_PRESSED */
44
45 /* assignment of CPU internal ADC channels with TRAB hardware */
46 #define VCC5V   2
47 #define VCC12V  3
48
49 /* CPLD-Register for controlling TRAB hardware functions */
50 #define CPLD_BUTTONS            ((volatile unsigned long *)0x04020000)
51 #define CPLD_FILL_LEVEL         ((volatile unsigned long *)0x04008000)
52 #define CPLD_ROTARY_SWITCH      ((volatile unsigned long *)0x04018000)
53 #define CPLD_RS485_RE           ((volatile unsigned long *)0x04028000)
54
55 /* timer configuration bits for buzzer and PWM */
56 #define START2          (1 << 12)
57 #define UPDATE2         (1 << 13)
58 #define INVERT2         (1 << 14)
59 #define RELOAD2         (1 << 15)
60 #define START3          (1 << 16)
61 #define UPDATE3         (1 << 17)
62 #define INVERT3         (1 << 18)
63 #define RELOAD3         (1 << 19)
64
65 #define PCLK            66000000
66 #define BUZZER_FREQ     1000    /* frequency in Hz */
67 #define PWM_FREQ        500
68
69
70 /* definitions of I2C EEPROM device address */
71 #define I2C_EEPROM_DEV_ADDR     0x54
72
73 /* definition for touch panel calibration points */
74 #define CALIB_TL 0              /* calibration point in (T)op (L)eft corner */
75 #define CALIB_DR 1              /* calibration point in (D)own (R)ight corner */
76
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
84
85 /* EEPROM stuff */
86 #define EEPROM_MAX_CRC_BUF      64
87
88 /* RS485 stuff */
89 #define RS485_MAX_RECEIVE_BUF_LEN  100
90
91 /* Bit definitions for ADCCON */
92 #define ADC_ENABLE_START     0x1
93 #define ADC_READ_START       0x2
94 #define ADC_STDBM            0x4
95 #define ADC_INP_AIN0         (0x0 << 3)
96 #define ADC_INP_AIN1         (0x1 << 3)
97 #define ADC_INP_AIN2         (0x2 << 3)
98 #define ADC_INP_AIN3         (0x3 << 3)
99 #define ADC_INP_AIN4         (0x4 << 3)
100 #define ADC_INP_AIN5         (0x5 << 3)
101 #define ADC_INP_AIN6         (0x6 << 3)
102 #define ADC_INP_AIN7         (0x7 << 3)
103 #define ADC_PRSCEN           0x4000
104 #define ADC_ECFLG            0x8000
105
106 /* function test functions */
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 **);
132
133 /* helper functions */
134 static void adc_init (void);
135 static int adc_read (unsigned int channel);
136 static void print_identifier (void);
137
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 */
143
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);
150
151 #if (CONFIG_COMMANDS & CFG_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 /* CFG_CMD_I2C */
159
160 /*
161  * TRAB board specific commands. Especially commands for burn-in and function
162  * test.
163  */
164
165 int trab_fkt (int argc, char *argv[])
166 {
167         int i;
168
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;
176         }
177
178         debug ("argc = %d\n", argc);
179
180         for (i=0; i<=argc; ++i) {
181                 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
182         }
183
184         adc_init ();
185
186         switch (argc) {
187
188         case 0:
189         case 1:
190                 break;
191
192         case 2:
193                 if (strcmp (argv[1], "info") == 0) {
194                         return (do_info ());
195                 }
196                 if (strcmp (argv[1], "dip") == 0) {
197                         return (do_dip ());
198                 }
199                 if (strcmp (argv[1], "vcc5v") == 0) {
200                         return (do_vcc5v ());
201                 }
202                 if (strcmp (argv[1], "vcc12v") == 0) {
203                         return (do_vcc12v ());
204                 }
205                 if (strcmp (argv[1], "buttons") == 0) {
206                         return (do_buttons ());
207                 }
208                 if (strcmp (argv[1], "fill_level") == 0) {
209                         return (do_fill_level ());
210                 }
211                 if (strcmp (argv[1], "rotary_switch") == 0) {
212                         return (do_rotary_switch ());
213                 }
214                 if (strcmp (argv[1], "pressure") == 0) {
215                         return (do_pressure ());
216                 }
217                 if (strcmp (argv[1], "v_bat") == 0) {
218                         return (do_v_bat ());
219                 }
220                 if (strcmp (argv[1], "vfd_id") == 0) {
221                         return (do_vfd_id ());
222                 }
223                 if (strcmp (argv[1], "motor_contact") == 0) {
224                         return (do_motor_contact ());
225                 }
226                 if (strcmp (argv[1], "crc16") == 0) {
227                         return (do_crc16 ());
228                 }
229                 if (strcmp (argv[1], "power_switch") == 0) {
230                         return (do_power_switch ());
231                 }
232                 break;
233
234         case 3:
235                 if (strcmp (argv[1], "full_bridge") == 0) {
236                         return (do_full_bridge (argv));
237                 }
238                 if (strcmp (argv[1], "dac") == 0) {
239                         return (do_dac (argv));
240                 }
241                 if (strcmp (argv[1], "motor") == 0) {
242                         return (do_motor (argv));
243                 }
244                 if (strcmp (argv[1], "pwm") == 0) {
245                         return (do_pwm (argv));
246                 }
247                 if (strcmp (argv[1], "thermo") == 0) {
248                         return (do_thermo (argv));
249                 }
250                 if (strcmp (argv[1], "touch") == 0) {
251                         return (do_touch (argv));
252                 }
253                 if (strcmp (argv[1], "serial_number") == 0) {
254                         return (do_serial_number (argv));
255                 }
256                 if (strcmp (argv[1], "buzzer") == 0) {
257                         return (do_buzzer (argv));
258                 }
259                 if (strcmp (argv[1], "gain") == 0) {
260                         return (do_gain (argv));
261                 }
262                 break;
263
264         case 4:
265                 if (strcmp (argv[1], "led") == 0) {
266                         return (do_led (argv));
267                 }
268                 if (strcmp (argv[1], "rs485") == 0) {
269                         return (do_rs485 (argv));
270                 }
271                 if (strcmp (argv[1], "serial_number") == 0) {
272                         return (do_serial_number (argv));
273                 }
274                 break;
275
276         case 5:
277                 if (strcmp (argv[1], "eeprom") == 0) {
278                         return (do_eeprom (argv));
279                 }
280                 break;
281
282         case 6:
283                 if (strcmp (argv[1], "eeprom") == 0) {
284                         return (do_eeprom (argv));
285                 }
286                 break;
287
288         default:
289                 break;
290         }
291
292         printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
293         return 1;
294 }
295
296 int do_info (void)
297 {
298         printf ("Stand-alone application for TRAB board function test\n");
299         printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
300
301         return 0;
302 }
303
304 int do_dip (void)
305 {
306         unsigned int result = 0;
307         int adc_val;
308         int i;
309
310         /***********************************************************
311          DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
312            SW1 - AIN4
313            SW2 - AIN5
314            SW3 - AIN6
315            SW4 - AIN7
316
317            "On" DIP switch position short-circuits the voltage from
318            the input channel (i.e. '0' conversion result means "on").
319         *************************************************************/
320
321         for (i = 7; i > 3; i--) {
322
323                 if ((adc_val = adc_read (i)) == -1) {
324                         printf ("Channel %d could not be read\n", i);
325                         return 1;
326                 }
327
328                 /*
329                  * Input voltage (switch open) is 1.8 V.
330                  * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
331                  * Set trigger at halve that value.
332                  */
333                 if (adc_val < 368)
334                         result |= (1 << (i-4));
335         }
336
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");
344         }
345         printf("\n");
346
347         return 0;
348 }
349
350
351 int do_vcc5v (void)
352 {
353         int result;
354
355         /* VCC5V is connected to channel 2 */
356
357         if ((result = adc_read (VCC5V)) == -1) {
358                 printf ("VCC5V could not be read\n");
359                 return 1;
360         }
361
362         /*
363          * Calculate voltage value. Split in two parts because there is no
364          * floating point support.  VCC5V is connected over an resistor divider:
365          * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
366          */
367         print_identifier ();
368         printf ("%d", (result & 0x3FF)* 10 / 1023);
369         printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
370         printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
371                 * 10 / 1024);
372
373         return 0;
374 }
375
376
377 int do_vcc12v (void)
378 {
379         int result;
380
381         if ((result = adc_read (VCC12V)) == -1) {
382                 printf ("VCC12V could not be read\n");
383                 return 1;
384         }
385
386         /*
387          * Calculate voltage value. Split in two parts because there is no
388          * floating point support.  VCC5V is connected over an resistor divider:
389          * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
390          */
391         print_identifier ();
392         printf ("%d", (result & 0x3FF)* 25 / 1023);
393         printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
394
395         return 0;
396 }
397
398 static int adc_read (unsigned int channel)
399 {
400         int j = 1000; /* timeout value for wait loop in us */
401         int result;
402         S3C2400_ADC *padc;
403
404         padc = S3C2400_GetBase_ADC();
405         channel &= 0x7;
406
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);
410
411         while (j--) {
412                 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
413                         break;
414                 udelay (1);
415         }
416
417         if (j == 0) {
418                 printf("%s: ADC timeout\n", __FUNCTION__);
419                 padc->ADCCON |= ADC_STDBM; /* select standby mode */
420                 return -1;
421         }
422
423         result = padc->ADCDAT & 0x3FF;
424
425         padc->ADCCON |= ADC_STDBM; /* select standby mode */
426
427         debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
428                (padc->ADCCON >> 3) & 0x7, result);
429
430         /*
431          * Wait for ADC to be ready for next conversion. This delay value was
432          * estimated, because the datasheet does not specify a value.
433          */
434         udelay (1000);
435
436         return (result);
437 }
438
439
440 static void adc_init (void)
441 {
442         S3C2400_ADC *padc;
443
444         padc = S3C2400_GetBase_ADC();
445
446         padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
447         padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
448
449         /*
450          * Wait some time to avoid problem with very first call of
451          * adc_read(). Without * this delay, sometimes the first read adc
452          * value is 0. Perhaps because the * adjustment of prescaler takes
453          * some clock cycles?
454          */
455         udelay (1000);
456
457         return;
458 }
459
460
461 int do_buttons (void)
462 {
463         int result;
464         int i;
465
466         result = *CPLD_BUTTONS; /* read CPLD */
467         debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
468
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");
476         }
477         printf("\n");
478         return 0;
479 }
480
481
482 int do_power_switch (void)
483 {
484         int result;
485
486         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
487
488         /* configure GPE7 as input */
489         gpio->PECON &= ~(0x3 << (2 * 7));
490
491         /* signal GPE7 from power switch is low active: 0=on , 1=off */
492         result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
493
494         print_identifier ();
495         printf("%d\n", result);
496         return 0;
497 }
498
499
500 int do_fill_level (void)
501 {
502         int result;
503
504         result = *CPLD_FILL_LEVEL; /* read CPLD */
505         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
506
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;
514 }
515
516
517 int do_rotary_switch (void)
518 {
519         int result;
520         /*
521          * Please note, that the default values of the direction bits are
522          * undefined after reset. So it is a good idea, to make first a dummy
523          * call to this function, to clear the direction bits and set so to
524          * proper values.
525          */
526
527         result = *CPLD_ROTARY_SWITCH; /* read CPLD */
528         debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
529
530         *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
531
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;
545 }
546
547
548 int do_vfd_id (void)
549 {
550         int i;
551         long int pcup_old, pccon_old;
552         int vfd_board_id;
553         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
554
555         /* try to red vfd board id from the value defined by pull-ups */
556
557         pcup_old = gpio->PCUP;
558         pccon_old = gpio->PCCON;
559
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 */
565
566         gpio->PCCON = pccon_old;
567         gpio->PCUP = pcup_old;
568
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");
576         }
577         printf("\n");
578         return 0;
579 }
580
581 int do_buzzer (char **argv)
582 {
583         int counter;
584
585         S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
586         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
587
588         /* set prescaler for timer 2, 3 and 4 */
589         timers->TCFG0 &= ~0xFF00;
590         timers->TCFG0 |=  0x0F00;
591
592         /* set divider for timer 2 */
593         timers->TCFG1 &= ~0xF00;
594         timers->TCFG1 |=  0x300;
595
596         /* set frequency */
597         counter = (PCLK / BUZZER_FREQ) >> 9;
598         timers->ch[2].TCNTB = counter;
599         timers->ch[2].TCMPB = counter / 2;
600
601         if (strcmp (argv[2], "on") == 0) {
602                 debug ("%s: frequency: %d\n", __FUNCTION__,
603                        BUZZER_FREQ);
604
605                 /* configure pin GPD7 as TOUT2 */
606                 gpio->PDCON &= ~0xC000;
607                 gpio->PDCON |= 0x8000;
608
609                 /* start */
610                 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
611                                 ~INVERT2;
612                 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
613                 return (0);
614         }
615         else if (strcmp (argv[2], "off") == 0) {
616                 /* stop */
617                 timers->TCON &= ~(START2 | RELOAD2);
618
619                 /* configure GPD7 as output and set to low */
620                 gpio->PDCON &= ~0xC000;
621                 gpio->PDCON |= 0x4000;
622                 gpio->PDDAT &= ~0x80;
623                 return (0);
624         }
625
626         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
627         return 1;
628 }
629
630
631 int do_led (char **argv)
632 {
633         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
634
635         /* configure PC14 and PC15 as output */
636         gpio->PCCON &= ~(0xF << 28);
637         gpio->PCCON |= (0x5 << 28);
638
639         /* configure PD0 and PD4 as output */
640         gpio->PDCON &= ~((0x3 << 8) | 0x3);
641         gpio->PDCON |= ((0x1 << 8) | 0x1);
642
643         switch (simple_strtoul(argv[2], NULL, 10)) {
644
645         case 0:
646         case 1:
647                 break;
648
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;
655
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;
662
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;
669
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;
676
677         default:
678                 break;
679
680         }
681         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
682         return 1;
683 }
684
685
686 int do_full_bridge (char **argv)
687 {
688         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
689
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));
693
694         if (strcmp (argv[2], "+") == 0) {
695               gpio->PDDAT |= (1 << 5);
696               gpio->PDDAT |= (1 << 6);
697               return 0;
698         }
699         else if (strcmp (argv[2], "-") == 0) {
700                 gpio->PDDAT &= ~(1 << 5);
701                 gpio->PDDAT |= (1 << 6);
702                 return 0;
703         }
704         else if (strcmp (argv[2], "off") == 0) {
705                 gpio->PDDAT &= ~(1 << 5);
706                 gpio->PDDAT &= ~(1 << 6);
707                 return 0;
708         }
709         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
710         return 1;
711 }
712
713 /* val must be in [0, 4095] */
714 static inline unsigned long tsc2000_to_uv (u16 val)
715 {
716         return ((250000 * val) / 4096) * 10;
717 }
718
719
720 int do_dac (char **argv)
721 {
722         int brightness;
723
724         /* initialize SPI */
725         spi_init ();
726
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;
731         }
732         tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
733         tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
734
735         return 0;
736 }
737
738
739 int do_v_bat (void)
740 {
741         unsigned long ret, res;
742
743         /* initialize SPI */
744         spi_init ();
745
746         tsc2000_write(TSC2000_REG_ADC, 0x1836);
747
748         /* now wait for data available */
749         adc_wait_conversion_done();
750
751         ret = tsc2000_read(TSC2000_REG_BAT1);
752         res = (tsc2000_to_uv(ret) + 1250) / 2500;
753         res += (ERROR_BATTERY * res) / 1000;
754
755         print_identifier ();
756         printf ("%ld", (res / 100));
757         printf (".%ld", ((res % 100) / 10));
758         printf ("%ld V\n", (res % 10));
759         return 0;
760 }
761
762
763 int do_pressure (void)
764 {
765         /* initialize SPI */
766         spi_init ();
767
768         tsc2000_write(TSC2000_REG_ADC, 0x2436);
769
770         /* now wait for data available */
771         adc_wait_conversion_done();
772
773         print_identifier ();
774         printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
775         return 0;
776 }
777
778
779 int do_motor_contact (void)
780 {
781         int result;
782
783         result = *CPLD_FILL_LEVEL; /* read CPLD */
784         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
785
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;
793 }
794
795 int do_motor (char **argv)
796 {
797         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
798
799         /* Configure I/O port */
800         gpio->PGCON &= ~(0x3 << 0);
801         gpio->PGCON |= (0x1 << 0);
802
803         if (strcmp (argv[2], "on") == 0) {
804                 gpio->PGDAT &= ~(1 << 0);
805                 return 0;
806         }
807         if (strcmp (argv[2], "off") == 0) {
808                 gpio->PGDAT |= (1 << 0);
809                 return 0;
810         }
811         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
812         return 1;
813 }
814
815 static void print_identifier (void)
816 {
817         printf ("## FKT: ");
818 }
819
820 int do_pwm (char **argv)
821 {
822         int counter;
823         S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
824         S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
825
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);
830
831                 /* set prescaler for timer 2, 3 and 4 */
832                 timers->TCFG0 &= ~0xFF00;
833                 timers->TCFG0 |= 0x0F00;
834
835                 /* set divider for timer 3 */
836                 timers->TCFG1 &= ~(0xf << 12);
837                 timers->TCFG1 |= (0x3 << 12);
838
839                 /* set frequency */
840                 counter = (PCLK / PWM_FREQ) >> 9;
841                 timers->ch[3].TCNTB = counter;
842                 timers->ch[3].TCMPB = counter / 2;
843
844                 /* start timer */
845                 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
846                 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
847                 return 0;
848         }
849         if (strcmp (argv[2], "off") == 0) {
850
851                 /* stop timer */
852                 timers->TCON &= ~(START2 | RELOAD2);
853
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;
859         }
860         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
861         return 1;
862 }
863
864
865 int do_thermo (char **argv)
866 {
867         int     channel, res;
868
869         tsc2000_reg_init ();
870
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);
877                 }
878                 return 0;
879         }
880         channel = simple_strtoul (argv[2], NULL, 10);
881         res = tsc2000_read_channel(channel);
882         print_identifier ();
883         printf ("%d\n", res);
884         return 0;                 /* return OK */
885 }
886
887
888 int do_touch (char **argv)
889 {
890         int     x, y;
891
892         if (strcmp (argv[2], "tl") == 0) {
893 #if CONFIG_TOUCH_WAIT_PRESSED
894                 touch_wait_pressed();
895 #else
896                 {
897                         int i;
898                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
899                                 if (touch_check_pressed ()) {
900                                         break;
901                                 }
902                                 udelay (1000);  /* pause 1 ms */
903                         }
904                 }
905                 if (!touch_check_pressed()) {
906                         print_identifier ();
907                         printf ("error: touch not pressed\n");
908                         return 1;
909                 }
910 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
911                 touch_read_x_y (&x, &y);
912
913                 print_identifier ();
914                 printf ("x=%d y=%d\n", x, y);
915                 return touch_write_clibration_values (CALIB_TL, x, y);
916         }
917         else if (strcmp (argv[2], "dr") == 0) {
918 #if CONFIG_TOUCH_WAIT_PRESSED
919                 touch_wait_pressed();
920 #else
921                 {
922                         int i;
923                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
924                                 if (touch_check_pressed ()) {
925                                         break;
926                                 }
927                                 udelay (1000);  /* pause 1 ms */
928                         }
929                 }
930                 if (!touch_check_pressed()) {
931                         print_identifier ();
932                         printf ("error: touch not pressed\n");
933                         return 1;
934                 }
935 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
936                 touch_read_x_y (&x, &y);
937
938                 print_identifier ();
939                 printf ("x=%d y=%d\n", x, y);
940
941                 return touch_write_clibration_values (CALIB_DR, x, y);
942         }
943         return 1;                 /* not "tl", nor "dr", so return error */
944 }
945
946
947 #ifdef CONFIG_TOUCH_WAIT_PRESSED
948 static void touch_wait_pressed (void)
949 {
950         while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
951 }
952
953 #else
954 static int touch_check_pressed (void)
955 {
956         return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
957 }
958 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
959
960 static int touch_write_clibration_values (int calib_point, int x, int y)
961 {
962 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
963         int x_verify = 0;
964         int y_verify = 0;
965
966         tsc2000_reg_init ();
967
968         if (calib_point == CALIB_TL) {
969                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
970                                (char *)&x, 2)) {
971                         return 1;
972                 }
973                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
974                                (char *)&y, 2)) {
975                         return 1;
976                 }
977
978                 /* verify written values */
979                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
980                               (char *)&x_verify, 2)) {
981                         return 1;
982                 }
983                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
984                                (char *)&y_verify, 2)) {
985                         return 1;
986                 }
987                 if ((y != y_verify) || (x != x_verify)) {
988                         print_identifier ();
989                         printf ("error: verify error\n");
990                         return 1;
991                 }
992                 return 0;       /* no error */
993         }
994         else if (calib_point == CALIB_DR) {
995                   if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
996                                (char *)&x, 2)) {
997                         return 1;
998                   }
999                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1000                                (char *)&y, 2)) {
1001                         return 1;
1002                 }
1003
1004                 /* verify written values */
1005                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
1006                                        (char *)&x_verify, 2)) {
1007                         return 1;
1008                 }
1009                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1010                                (char *)&y_verify, 2)) {
1011                         return 1;
1012                 }
1013                 if ((y != y_verify) || (x != x_verify)) {
1014                         print_identifier ();
1015                         printf ("error: verify error\n");
1016                         return 1;
1017                 }
1018                 return 0;
1019         }
1020         return 1;
1021 #else
1022         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1023                 "to EEPROM\n");
1024         return (1);
1025 #endif /* CFG_CMD_I2C */
1026 }
1027
1028
1029 static void touch_read_x_y (int *px, int *py)
1030 {
1031         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1032         adc_wait_conversion_done();
1033         *px = tsc2000_read(TSC2000_REG_X);
1034
1035         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1036         adc_wait_conversion_done();
1037         *py = tsc2000_read(TSC2000_REG_Y);
1038 }
1039
1040
1041 int do_rs485 (char **argv)
1042 {
1043         int timeout;
1044         char data[RS485_MAX_RECEIVE_BUF_LEN];
1045
1046         if (strcmp (argv[2], "send") == 0) {
1047                 return (rs485_send_line (argv[3]));
1048         }
1049         else if (strcmp (argv[2], "receive") == 0) {
1050                 timeout = simple_strtoul(argv[3], NULL, 10);
1051                 if (rs485_receive_chars (data, timeout) != 0) {
1052                         print_identifier ();
1053                         printf ("## nothing received\n");
1054                         return (1);
1055                 }
1056                 else {
1057                         print_identifier ();
1058                         printf ("%s\n", data);
1059                         return (0);
1060                 }
1061         }
1062         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1063         return (1);             /* unknown command, return error */
1064 }
1065
1066
1067 static int rs485_send_line (const char *data)
1068 {
1069         rs485_init ();
1070         trab_rs485_enable_tx ();
1071         rs485_puts (data);
1072         rs485_putc ('\n');
1073
1074         return (0);
1075 }
1076
1077
1078 static int rs485_receive_chars (char *data, int timeout)
1079 {
1080         int i;
1081         int receive_count = 0;
1082
1083         rs485_init ();
1084         trab_rs485_enable_rx ();
1085
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++;
1094                 }
1095                 udelay (1000);  /* pause 1 ms */
1096         }
1097         *data = '\0';           /* terminate string */
1098
1099         if (receive_count == 0)
1100                 return (1);
1101         else
1102                 return (0);
1103 }
1104
1105
1106 int do_serial_number (char **argv)
1107 {
1108 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1109         unsigned int serial_number;
1110
1111         if (strcmp (argv[2], "read") == 0) {
1112                 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1113                               (char *)&serial_number, 4)) {
1114                         printf ("could not read from eeprom\n");
1115                         return (1);
1116                 }
1117                 print_identifier ();
1118                 printf ("%08d\n", serial_number);
1119                 return (0);
1120         }
1121         else if (strcmp (argv[2], "write") == 0) {
1122                 serial_number = simple_strtoul(argv[3], NULL, 10);
1123                 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1124                               (char *)&serial_number, 4)) {
1125                         printf ("could not write to eeprom\n");
1126                         return (1);
1127                 }
1128                 return (0);
1129         }
1130         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1131         return (1);             /* unknown command, return error */
1132 #else
1133         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1134                 "to EEPROM\n");
1135         return (1);
1136 #endif /* CFG_CMD_I2C */
1137 }
1138
1139
1140 int do_crc16 (void)
1141 {
1142 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1143         int crc;
1144         char buf[EEPROM_MAX_CRC_BUF];
1145
1146         if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1147                 printf ("could not read from eeprom\n");
1148                 return (1);
1149         }
1150         crc = 0;                /* start value of crc calculation */
1151         crc = updcrc (crc, buf, 60);
1152
1153         print_identifier ();
1154         printf ("crc16=%#04x\n", crc);
1155
1156         if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
1157                        sizeof (crc))) {
1158                 printf ("could not read from eeprom\n");
1159                 return (1);
1160         }
1161         return (0);
1162 #else
1163         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1164                 "to EEPROM\n");
1165         return (1);
1166 #endif /* CFG_CMD_I2C */
1167 }
1168
1169
1170 /*
1171  * Calculate, intelligently, the CRC of a dataset incrementally given a
1172  * buffer full at a time.
1173  * Initialize crc to 0 for XMODEM, -1 for CCITT.
1174  *
1175  * Usage:
1176  *   newcrc = updcrc( oldcrc, bufadr, buflen )
1177  *        unsigned int oldcrc, buflen;
1178  *        char *bufadr;
1179  *
1180  * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1181  * Compile with -DMAKETAB to print values for crctab to stdout
1182  */
1183
1184     /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1185      * If you change P, you must change crctab[]'s initial value to what is
1186      * printed by initcrctab()
1187      */
1188 #define   P    0x1021
1189
1190     /* number of bits in CRC: don't change it. */
1191 #define W 16
1192
1193     /* this the number of bits per char: don't change it. */
1194 #define B 8
1195
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
1229     };
1230
1231 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1232                              unsigned int icnt )
1233 {
1234         register unsigned short crc = icrc;
1235         register unsigned char *cp = icp;
1236         register unsigned int cnt = icnt;
1237
1238         while (cnt--)
1239                 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1240
1241         return (crc);
1242 }
1243
1244
1245 int do_gain (char **argv)
1246 {
1247         int range;
1248
1249         range = simple_strtoul (argv[2], NULL, 10);
1250         if ((range < 1) || (range > 3))
1251         {
1252                 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1253                 return 1;
1254         }
1255
1256         tsc2000_set_range (range);
1257         return (0);
1258 }
1259
1260
1261 int do_eeprom (char **argv)
1262 {
1263 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1264         if (strcmp (argv[2], "read") == 0) {
1265                 return (trab_eeprom_read (argv));
1266         }
1267
1268         else if (strcmp (argv[2], "write") == 0) {
1269                 return (trab_eeprom_write (argv));
1270         }
1271
1272         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1273         return (1);
1274 #else
1275         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1276                 "to EEPROM\n");
1277         return (1);
1278 #endif /* CFG_CMD_I2C */
1279 }
1280
1281 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1282 static int trab_eeprom_read (char **argv)
1283 {
1284         int i;
1285         int len;
1286         unsigned int addr;
1287         long int value = 0;
1288         uchar *buffer;
1289
1290         buffer = (uchar *) &value;
1291         addr = simple_strtoul (argv[3], NULL, 10);
1292         addr &= 0xfff;
1293         len = simple_strtoul (argv[4], NULL, 10);
1294         if ((len < 1) || (len > 4)) {
1295                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1296                         argv[4]);
1297                 return (1);
1298         }
1299         for (i = 0; i < len; i++) {
1300                 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1301                         printf ("%s: could not read from i2c device %#x"
1302                                 ", addr %d\n", __FUNCTION__,
1303                                 I2C_EEPROM_DEV_ADDR, addr);
1304                         return (1);
1305                 }
1306         }
1307         print_identifier ();
1308         if (strcmp (argv[5], "-") == 0) {
1309                 if (len == 1)
1310                         printf ("%d\n", (signed char) value);
1311                 else if (len == 2)
1312                         printf ("%d\n", (signed short int) value);
1313                 else
1314                         printf ("%ld\n", value);
1315         }
1316         else {
1317                 if (len == 1)
1318                         printf ("%d\n", (unsigned char) value);
1319                 else if (len == 2)
1320                         printf ("%d\n", (unsigned short int) value);
1321                 else
1322                         printf ("%ld\n", (unsigned long int) value);
1323         }
1324         return (0);
1325 }
1326
1327 static int trab_eeprom_write (char **argv)
1328 {
1329         int i;
1330         int len;
1331         unsigned int addr;
1332         long int value = 0;
1333         uchar *buffer;
1334
1335         buffer = (uchar *) &value;
1336         addr = simple_strtoul (argv[3], NULL, 10);
1337         addr &= 0xfff;
1338         len = simple_strtoul (argv[4], NULL, 10);
1339         if ((len < 1) || (len > 4)) {
1340                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1341                         argv[4]);
1342                 return (1);
1343         }
1344         value = simple_strtol (argv[5], NULL, 10);
1345         debug ("value=%ld\n", value);
1346         for (i = 0; i < len; i++) {
1347                 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1348                         printf ("%s: could not write to i2c device %d"
1349                                 ", addr %d\n", __FUNCTION__,
1350                                 I2C_EEPROM_DEV_ADDR, addr);
1351                         return (1);
1352                 }
1353 #if 0
1354                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1355                         "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1356                         i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1357 #endif
1358                 udelay (30000); /* wait for EEPROM ready */
1359         }
1360         return (0);
1361 }
1362
1363 int i2c_write_multiple (uchar chip, uint addr, int alen,
1364                         uchar *buffer, int len)
1365 {
1366         int i;
1367
1368         if (alen != 1) {
1369                 printf ("%s: addr len other than 1 not supported\n",
1370                          __FUNCTION__);
1371                 return (1);
1372         }
1373
1374         for (i = 0; i < len; i++) {
1375                 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1376                         printf ("%s: could not write to i2c device %d"
1377                                  ", addr %d\n", __FUNCTION__, chip, addr);
1378                         return (1);
1379                 }
1380 #if 0
1381                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1382                         "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1383                         alen, buffer, i, buffer+i, buffer+i);
1384 #endif
1385
1386                 udelay (30000);
1387         }
1388         return (0);
1389 }
1390
1391 int i2c_read_multiple ( uchar chip, uint addr, int alen,
1392                         uchar *buffer, int len)
1393 {
1394         int i;
1395
1396         if (alen != 1) {
1397                 printf ("%s: addr len other than 1 not supported\n",
1398                          __FUNCTION__);
1399                 return (1);
1400         }
1401
1402         for (i = 0; i < len; i++) {
1403                 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1404                         printf ("%s: could not read from i2c device %#x"
1405                                  ", addr %d\n", __FUNCTION__, chip, addr);
1406                         return (1);
1407                 }
1408         }
1409         return (0);
1410 }
1411 #endif /* CFG_CMD_I2C */