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