]> git.karo-electronics.de Git - karo-tx-uboot.git/blob - board/trab/trab_fkt.c
56132818a9b7e3d49b985b8152c11b831be25cb9
[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
889 int do_touch (char **argv)
890 {
891         int     x, y;
892
893         if (strcmp (argv[2], "tl") == 0) {
894 #if CONFIG_TOUCH_WAIT_PRESSED
895                 touch_wait_pressed();
896 #else
897                 {
898                         int i;
899                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
900                                 if (touch_check_pressed ()) {
901                                         break;
902                                 }
903                                 udelay (1000);  /* pause 1 ms */
904                         }
905                 }
906                 if (!touch_check_pressed()) {
907                         print_identifier ();
908                         printf ("error: touch not pressed\n");
909                         return 1;
910                 }
911 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
912                 touch_read_x_y (&x, &y);
913
914                 print_identifier ();
915                 printf ("x=%d y=%d\n", x, y);
916                 return touch_write_clibration_values (CALIB_TL, x, y);
917         }
918         else if (strcmp (argv[2], "dr") == 0) {
919 #if CONFIG_TOUCH_WAIT_PRESSED
920                 touch_wait_pressed();
921 #else
922                 {
923                         int i;
924                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
925                                 if (touch_check_pressed ()) {
926                                         break;
927                                 }
928                                 udelay (1000);  /* pause 1 ms */
929                         }
930                 }
931                 if (!touch_check_pressed()) {
932                         print_identifier ();
933                         printf ("error: touch not pressed\n");
934                         return 1;
935                 }
936 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
937                 touch_read_x_y (&x, &y);
938
939                 print_identifier ();
940                 printf ("x=%d y=%d\n", x, y);
941
942                 return touch_write_clibration_values (CALIB_DR, x, y);
943         }
944         return 1;                 /* not "tl", nor "dr", so return error */
945 }
946
947
948 #ifdef CONFIG_TOUCH_WAIT_PRESSED
949 static void touch_wait_pressed (void)
950 {
951         while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
952 }
953
954 #else
955 static int touch_check_pressed (void)
956 {
957         return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
958 }
959 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
960
961 static int touch_write_clibration_values (int calib_point, int x, int y)
962 {
963 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
964         int x_verify = 0;
965         int y_verify = 0;
966
967         tsc2000_reg_init ();
968
969         if (calib_point == CALIB_TL) {
970                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
971                                (char *)&x, 2)) {
972                         return 1;
973                 }
974                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
975                                (char *)&y, 2)) {
976                         return 1;
977                 }
978
979                 /* verify written values */
980                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
981                               (char *)&x_verify, 2)) {
982                         return 1;
983                 }
984                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
985                                (char *)&y_verify, 2)) {
986                         return 1;
987                 }
988                 if ((y != y_verify) || (x != x_verify)) {
989                         print_identifier ();
990                         printf ("error: verify error\n");
991                         return 1;
992                 }
993                 return 0;       /* no error */
994         }
995         else if (calib_point == CALIB_DR) {
996                   if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
997                                (char *)&x, 2)) {
998                         return 1;
999                   }
1000                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1001                                (char *)&y, 2)) {
1002                         return 1;
1003                 }
1004
1005                 /* verify written values */
1006                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
1007                                        (char *)&x_verify, 2)) {
1008                         return 1;
1009                 }
1010                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1011                                (char *)&y_verify, 2)) {
1012                         return 1;
1013                 }
1014                 if ((y != y_verify) || (x != x_verify)) {
1015                         print_identifier ();
1016                         printf ("error: verify error\n");
1017                         return 1;
1018                 }
1019                 return 0;
1020         }
1021         return 1;
1022 #else
1023         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1024                 "to EEPROM\n");
1025         return (1);
1026 #endif /* CFG_CMD_I2C */
1027 }
1028
1029
1030 static void touch_read_x_y (int *px, int *py)
1031 {
1032         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1033         adc_wait_conversion_done();
1034         *px = tsc2000_read(TSC2000_REG_X);
1035
1036         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1037         adc_wait_conversion_done();
1038         *py = tsc2000_read(TSC2000_REG_Y);
1039 }
1040
1041
1042
1043 int do_rs485 (char **argv)
1044 {
1045         int timeout;
1046         char data[RS485_MAX_RECEIVE_BUF_LEN];
1047
1048         if (strcmp (argv[2], "send") == 0) {
1049                 return (rs485_send_line (argv[3]));
1050         }
1051         else if (strcmp (argv[2], "receive") == 0) {
1052                 timeout = simple_strtoul(argv[3], NULL, 10);
1053                 if (rs485_receive_chars (data, timeout) != 0) {
1054                         print_identifier ();
1055                         printf ("## nothing received\n");
1056                         return (1);
1057                 }
1058                 else {
1059                         print_identifier ();
1060                         printf ("%s\n", data);
1061                         return (0);
1062                 }
1063         }
1064         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1065         return (1);             /* unknown command, return error */
1066 }
1067
1068
1069 static int rs485_send_line (const char *data)
1070 {
1071         rs485_init ();
1072         trab_rs485_enable_tx ();
1073         rs485_puts (data);
1074         rs485_putc ('\n');
1075
1076         return (0);
1077 }
1078
1079
1080 static int rs485_receive_chars (char *data, int timeout)
1081 {
1082         int i;
1083         int receive_count = 0;
1084
1085         rs485_init ();
1086         trab_rs485_enable_rx ();
1087
1088         /* test every 1 ms for received characters to avoid a receive FIFO
1089          * overrun (@ 38.400 Baud) */
1090         for (i = 0; i < (timeout * 1000); i++) {
1091                 while (rs485_tstc ()) {
1092                         if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1093                                 break;
1094                         *data++ = rs485_getc ();
1095                         receive_count++;
1096                 }
1097                 udelay (1000);  /* pause 1 ms */
1098         }
1099         *data = '\0';           /* terminate string */
1100
1101         if (receive_count == 0)
1102                 return (1);
1103         else
1104                 return (0);
1105 }
1106
1107
1108 int do_serial_number (char **argv)
1109 {
1110 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1111         unsigned int serial_number;
1112
1113         if (strcmp (argv[2], "read") == 0) {
1114                 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1115                               (char *)&serial_number, 4)) {
1116                         printf ("could not read from eeprom\n");
1117                         return (1);
1118                 }
1119                 print_identifier ();
1120                 printf ("%08d\n", serial_number);
1121                 return (0);
1122         }
1123         else if (strcmp (argv[2], "write") == 0) {
1124                 serial_number = simple_strtoul(argv[3], NULL, 10);
1125                 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1126                               (char *)&serial_number, 4)) {
1127                         printf ("could not write to eeprom\n");
1128                         return (1);
1129                 }
1130                 return (0);
1131         }
1132         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1133         return (1);             /* unknown command, return error */
1134 #else
1135         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1136                 "to EEPROM\n");
1137         return (1);
1138 #endif /* CFG_CMD_I2C */
1139 }
1140
1141
1142 int do_crc16 (void)
1143 {
1144 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1145         int crc;
1146         char buf[EEPROM_MAX_CRC_BUF];
1147
1148         if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1149                 printf ("could not read from eeprom\n");
1150                 return (1);
1151         }
1152         crc = 0;                /* start value of crc calculation */
1153         crc = updcrc (crc, buf, 60);
1154
1155         print_identifier ();
1156         printf ("crc16=%#04x\n", crc);
1157
1158         if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
1159                        sizeof (crc))) {
1160                 printf ("could not read from eeprom\n");
1161                 return (1);
1162         }
1163         return (0);
1164 #else
1165         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1166                 "to EEPROM\n");
1167         return (1);
1168 #endif /* CFG_CMD_I2C */
1169 }
1170
1171
1172 /*
1173  * Calculate, intelligently, the CRC of a dataset incrementally given a
1174  * buffer full at a time.
1175  * Initialize crc to 0 for XMODEM, -1 for CCITT.
1176  *
1177  * Usage:
1178  *   newcrc = updcrc( oldcrc, bufadr, buflen )
1179  *        unsigned int oldcrc, buflen;
1180  *        char *bufadr;
1181  *
1182  * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1183  * Compile with -DMAKETAB to print values for crctab to stdout
1184  */
1185
1186     /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1187      * If you change P, you must change crctab[]'s initial value to what is
1188      * printed by initcrctab()
1189      */
1190 #define   P    0x1021
1191
1192     /* number of bits in CRC: don't change it. */
1193 #define W 16
1194
1195     /* this the number of bits per char: don't change it. */
1196 #define B 8
1197
1198 static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1199     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
1200     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
1201     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
1202     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
1203     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
1204     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
1205     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
1206     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
1207     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
1208     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
1209     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
1210     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
1211     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
1212     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
1213     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
1214     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
1215     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
1216     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
1217     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
1218     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
1219     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
1220     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
1221     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
1222     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
1223     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
1224     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
1225     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
1226     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
1227     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
1228     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
1229     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
1230     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
1231     };
1232
1233 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1234                              unsigned int icnt )
1235 {
1236         register unsigned short crc = icrc;
1237         register unsigned char *cp = icp;
1238         register unsigned int cnt = icnt;
1239
1240         while (cnt--)
1241                 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1242
1243         return (crc);
1244 }
1245
1246
1247 int do_gain (char **argv)
1248 {
1249         int range;
1250
1251         range = simple_strtoul (argv[2], NULL, 10);
1252         if ((range < 1) || (range > 3))
1253         {
1254                 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1255                 return 1;
1256         }
1257
1258         tsc2000_set_range (range);
1259         return (0);
1260 }
1261
1262
1263 int do_eeprom (char **argv)
1264 {
1265 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1266         if (strcmp (argv[2], "read") == 0) {
1267                 return (trab_eeprom_read (argv));
1268         }
1269
1270         else if (strcmp (argv[2], "write") == 0) {
1271                 return (trab_eeprom_write (argv));
1272         }
1273
1274         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1275         return (1);
1276 #else
1277         printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1278                 "to EEPROM\n");
1279         return (1);
1280 #endif /* CFG_CMD_I2C */
1281 }
1282
1283 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
1284 static int trab_eeprom_read (char **argv)
1285 {
1286         int i;
1287         int len;
1288         unsigned int addr;
1289         long int value = 0;
1290         uchar *buffer;
1291
1292         buffer = (uchar *) &value;
1293         addr = simple_strtoul (argv[3], NULL, 10);
1294         addr &= 0xfff;
1295         len = simple_strtoul (argv[4], NULL, 10);
1296         if ((len < 1) || (len > 4)) {
1297                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1298                         argv[4]);
1299                 return (1);
1300         }
1301         for (i = 0; i < len; i++) {
1302                 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1303                         printf ("%s: could not read from i2c device %#x"
1304                                 ", addr %d\n", __FUNCTION__,
1305                                 I2C_EEPROM_DEV_ADDR, addr);
1306                         return (1);
1307                 }
1308         }
1309         print_identifier ();
1310         if (strcmp (argv[5], "-") == 0) {
1311                 if (len == 1)
1312                         printf ("%d\n", (signed char) value);
1313                 else if (len == 2)
1314                         printf ("%d\n", (signed short int) value);
1315                 else
1316                         printf ("%ld\n", value);
1317         }
1318         else {
1319                 if (len == 1)
1320                         printf ("%d\n", (unsigned char) value);
1321                 else if (len == 2)
1322                         printf ("%d\n", (unsigned short int) value);
1323                 else
1324                         printf ("%ld\n", (unsigned long int) value);
1325         }
1326         return (0);
1327 }
1328
1329 static int trab_eeprom_write (char **argv)
1330 {
1331         int i;
1332         int len;
1333         unsigned int addr;
1334         long int value = 0;
1335         uchar *buffer;
1336
1337         buffer = (uchar *) &value;
1338         addr = simple_strtoul (argv[3], NULL, 10);
1339         addr &= 0xfff;
1340         len = simple_strtoul (argv[4], NULL, 10);
1341         if ((len < 1) || (len > 4)) {
1342                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1343                         argv[4]);
1344                 return (1);
1345         }
1346         value = simple_strtol (argv[5], NULL, 10);
1347         debug ("value=%ld\n", value);
1348         for (i = 0; i < len; i++) {
1349                 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1350                         printf ("%s: could not write to i2c device %d"
1351                                 ", addr %d\n", __FUNCTION__,
1352                                 I2C_EEPROM_DEV_ADDR, addr);
1353                         return (1);
1354                 }
1355 #if 0
1356                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1357                         "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1358                         i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1359 #endif
1360                 udelay (30000); /* wait for EEPROM ready */
1361         }
1362         return (0);
1363 }
1364
1365 int i2c_write_multiple (uchar chip, uint addr, int alen,
1366                         uchar *buffer, int len)
1367 {
1368         int i;
1369
1370         if (alen != 1) {
1371                 printf ("%s: addr len other than 1 not supported\n",
1372                          __FUNCTION__);
1373                 return (1);
1374         }
1375
1376         for (i = 0; i < len; i++) {
1377                 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1378                         printf ("%s: could not write to i2c device %d"
1379                                  ", addr %d\n", __FUNCTION__, chip, addr);
1380                         return (1);
1381                 }
1382 #if 0
1383                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1384                         "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1385                         alen, buffer, i, buffer+i, buffer+i);
1386 #endif
1387
1388                 udelay (30000);
1389         }
1390         return (0);
1391 }
1392
1393 int i2c_read_multiple ( uchar chip, uint addr, int alen,
1394                         uchar *buffer, int len)
1395 {
1396         int i;
1397
1398         if (alen != 1) {
1399                 printf ("%s: addr len other than 1 not supported\n",
1400                          __FUNCTION__);
1401                 return (1);
1402         }
1403
1404         for (i = 0; i < len; i++) {
1405                 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1406                         printf ("%s: could not read from i2c device %#x"
1407                                  ", addr %d\n", __FUNCTION__, chip, addr);
1408                         return (1);
1409                 }
1410         }
1411         return (0);
1412 }
1413 #endif /* CFG_CMD_I2C */