]> git.kernelconcepts.de Git - karo-tx-uboot.git/blob - board/trab/trab_fkt.c
Make sure that argv[] argument pointers are not modified.
[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 <timestamp.h>
29 #include <asm/arch/s3c24x0_cpu.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 * const *);
119 int do_led (char * const *);
120 int do_full_bridge (char * const *);
121 int do_dac (char * const *);
122 int do_motor_contact (void);
123 int do_motor (char * const *);
124 int do_pwm (char * const *);
125 int do_thermo (char * const *);
126 int do_touch (char * const *);
127 int do_rs485 (char * const *);
128 int do_serial_number (char * const *);
129 int do_crc16 (void);
130 int do_power_switch (void);
131 int do_gain (char * const *);
132 int do_eeprom (char * const *);
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 * const *argv);
154 static int trab_eeprom_write (char * const *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 * const 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 void hang (void)
298 {
299         puts ("### ERROR ### Please RESET the board ###\n");
300         for (;;);
301 }
302
303 int do_info (void)
304 {
305         printf ("Stand-alone application for TRAB board function test\n");
306         printf ("Built: %s at %s\n", U_BOOT_DATE, U_BOOT_TIME);
307
308         return 0;
309 }
310
311 int do_dip (void)
312 {
313         unsigned int result = 0;
314         int adc_val;
315         int i;
316
317         /***********************************************************
318          DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
319            SW1 - AIN4
320            SW2 - AIN5
321            SW3 - AIN6
322            SW4 - AIN7
323
324            "On" DIP switch position short-circuits the voltage from
325            the input channel (i.e. '0' conversion result means "on").
326         *************************************************************/
327
328         for (i = 7; i > 3; i--) {
329
330                 if ((adc_val = adc_read (i)) == -1) {
331                         printf ("Channel %d could not be read\n", i);
332                         return 1;
333                 }
334
335                 /*
336                  * Input voltage (switch open) is 1.8 V.
337                  * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
338                  * Set trigger at halve that value.
339                  */
340                 if (adc_val < 368)
341                         result |= (1 << (i-4));
342         }
343
344         /* print result to console */
345         print_identifier ();
346         for (i = 0; i < 4; i++) {
347                 if ((result & (1 << i)) == 0)
348                         printf("0");
349                 else
350                         printf("1");
351         }
352         printf("\n");
353
354         return 0;
355 }
356
357
358 int do_vcc5v (void)
359 {
360         int result;
361
362         /* VCC5V is connected to channel 2 */
363
364         if ((result = adc_read (VCC5V)) == -1) {
365                 printf ("VCC5V could not be read\n");
366                 return 1;
367         }
368
369         /*
370          * Calculate voltage value. Split in two parts because there is no
371          * floating point support.  VCC5V is connected over an resistor divider:
372          * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
373          */
374         print_identifier ();
375         printf ("%d", (result & 0x3FF)* 10 / 1023);
376         printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
377         printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
378                 * 10 / 1024);
379
380         return 0;
381 }
382
383
384 int do_vcc12v (void)
385 {
386         int result;
387
388         if ((result = adc_read (VCC12V)) == -1) {
389                 printf ("VCC12V could not be read\n");
390                 return 1;
391         }
392
393         /*
394          * Calculate voltage value. Split in two parts because there is no
395          * floating point support.  VCC5V is connected over an resistor divider:
396          * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
397          */
398         print_identifier ();
399         printf ("%d", (result & 0x3FF)* 25 / 1023);
400         printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
401
402         return 0;
403 }
404
405 static int adc_read (unsigned int channel)
406 {
407         int j = 1000; /* timeout value for wait loop in us */
408         int result;
409         struct s3c2400_adc *padc;
410
411         padc = s3c2400_get_base_adc();
412         channel &= 0x7;
413
414         padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
415         padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
416         padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
417
418         while (j--) {
419                 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
420                         break;
421                 udelay (1);
422         }
423
424         if (j == 0) {
425                 printf("%s: ADC timeout\n", __FUNCTION__);
426                 padc->ADCCON |= ADC_STDBM; /* select standby mode */
427                 return -1;
428         }
429
430         result = padc->ADCDAT & 0x3FF;
431
432         padc->ADCCON |= ADC_STDBM; /* select standby mode */
433
434         debug ("%s: channel %d, result[DIGIT]=%d\n", __FUNCTION__,
435                (padc->ADCCON >> 3) & 0x7, result);
436
437         /*
438          * Wait for ADC to be ready for next conversion. This delay value was
439          * estimated, because the datasheet does not specify a value.
440          */
441         udelay (1000);
442
443         return (result);
444 }
445
446
447 static void adc_init (void)
448 {
449         struct s3c2400_adc *padc;
450
451         padc = s3c2400_get_base_adc();
452
453         padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
454         padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
455
456         /*
457          * Wait some time to avoid problem with very first call of
458          * adc_read(). Without * this delay, sometimes the first read adc
459          * value is 0. Perhaps because the * adjustment of prescaler takes
460          * some clock cycles?
461          */
462         udelay (1000);
463
464         return;
465 }
466
467
468 int do_buttons (void)
469 {
470         int result;
471         int i;
472
473         result = *CPLD_BUTTONS; /* read CPLD */
474         debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
475
476         /* print result to console */
477         print_identifier ();
478         for (i = 16; i <= 19; i++) {
479                 if ((result & (1 << i)) == 0)
480                         printf("0");
481                 else
482                         printf("1");
483         }
484         printf("\n");
485         return 0;
486 }
487
488
489 int do_power_switch (void)
490 {
491         int result;
492
493         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
494
495         /* configure GPE7 as input */
496         gpio->PECON &= ~(0x3 << (2 * 7));
497
498         /* signal GPE7 from power switch is low active: 0=on , 1=off */
499         result = ((gpio->PEDAT & (1 << 7)) == (1 << 7)) ? 0 : 1;
500
501         print_identifier ();
502         printf("%d\n", result);
503         return 0;
504 }
505
506
507 int do_fill_level (void)
508 {
509         int result;
510
511         result = *CPLD_FILL_LEVEL; /* read CPLD */
512         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
513
514         /* print result to console */
515         print_identifier ();
516         if ((result & (1 << 16)) == 0)
517                 printf("0\n");
518         else
519                 printf("1\n");
520         return 0;
521 }
522
523
524 int do_rotary_switch (void)
525 {
526         int result;
527         /*
528          * Please note, that the default values of the direction bits are
529          * undefined after reset. So it is a good idea, to make first a dummy
530          * call to this function, to clear the direction bits and set so to
531          * proper values.
532          */
533
534         result = *CPLD_ROTARY_SWITCH; /* read CPLD */
535         debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
536
537         *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
538
539         /* print result to console */
540         print_identifier ();
541         if ((result & (1 << 16)) == (1 << 16))
542                 printf("R");
543         if ((result & (1 << 17)) == (1 << 17))
544                 printf("L");
545         if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
546                 printf("0");
547         if ((result & (1 << 18)) == 0)
548                 printf("0\n");
549         else
550                 printf("1\n");
551         return 0;
552 }
553
554
555 int do_vfd_id (void)
556 {
557         int i;
558         long int pcup_old, pccon_old;
559         int vfd_board_id;
560         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
561
562         /* try to red vfd board id from the value defined by pull-ups */
563
564         pcup_old = gpio->PCUP;
565         pccon_old = gpio->PCCON;
566
567         gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate  GPC0...GPC3 pull-ups */
568         gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
569                                                    * inputs */
570         udelay (10);            /* allow signals to settle */
571         vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
572
573         gpio->PCCON = pccon_old;
574         gpio->PCUP = pcup_old;
575
576         /* print vfd_board_id to console */
577         print_identifier ();
578         for (i = 0; i < 4; i++) {
579                 if ((vfd_board_id & (1 << i)) == 0)
580                         printf("0");
581                 else
582                         printf("1");
583         }
584         printf("\n");
585         return 0;
586 }
587
588 int do_buzzer (char * const *argv)
589 {
590         int counter;
591
592         struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
593         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
594
595         /* set prescaler for timer 2, 3 and 4 */
596         timers->TCFG0 &= ~0xFF00;
597         timers->TCFG0 |=  0x0F00;
598
599         /* set divider for timer 2 */
600         timers->TCFG1 &= ~0xF00;
601         timers->TCFG1 |=  0x300;
602
603         /* set frequency */
604         counter = (PCLK / BUZZER_FREQ) >> 9;
605         timers->ch[2].TCNTB = counter;
606         timers->ch[2].TCMPB = counter / 2;
607
608         if (strcmp (argv[2], "on") == 0) {
609                 debug ("%s: frequency: %d\n", __FUNCTION__,
610                        BUZZER_FREQ);
611
612                 /* configure pin GPD7 as TOUT2 */
613                 gpio->PDCON &= ~0xC000;
614                 gpio->PDCON |= 0x8000;
615
616                 /* start */
617                 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) &
618                                 ~INVERT2;
619                 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
620                 return (0);
621         }
622         else if (strcmp (argv[2], "off") == 0) {
623                 /* stop */
624                 timers->TCON &= ~(START2 | RELOAD2);
625
626                 /* configure GPD7 as output and set to low */
627                 gpio->PDCON &= ~0xC000;
628                 gpio->PDCON |= 0x4000;
629                 gpio->PDDAT &= ~0x80;
630                 return (0);
631         }
632
633         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
634         return 1;
635 }
636
637
638 int do_led (char * const *argv)
639 {
640         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
641
642         /* configure PC14 and PC15 as output */
643         gpio->PCCON &= ~(0xF << 28);
644         gpio->PCCON |= (0x5 << 28);
645
646         /* configure PD0 and PD4 as output */
647         gpio->PDCON &= ~((0x3 << 8) | 0x3);
648         gpio->PDCON |= ((0x1 << 8) | 0x1);
649
650         switch (simple_strtoul(argv[2], NULL, 10)) {
651
652         case 0:
653         case 1:
654                 break;
655
656         case 2:
657                 if (strcmp (argv[3], "on") == 0)
658                         gpio->PCDAT |= (1 << 14);
659                 else
660                         gpio->PCDAT &= ~(1 << 14);
661                 return 0;
662
663         case 3:
664                 if (strcmp (argv[3], "on") == 0)
665                         gpio->PCDAT |= (1 << 15);
666                 else
667                         gpio->PCDAT &= ~(1 << 15);
668                 return 0;
669
670         case 4:
671                 if (strcmp (argv[3], "on") == 0)
672                         gpio->PDDAT |= (1 << 0);
673                 else
674                         gpio->PDDAT &= ~(1 << 0);
675                 return 0;
676
677         case 5:
678                 if (strcmp (argv[3], "on") == 0)
679                         gpio->PDDAT |= (1 << 4);
680                 else
681                         gpio->PDDAT &= ~(1 << 4);
682                 return 0;
683
684         default:
685                 break;
686
687         }
688         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
689         return 1;
690 }
691
692
693 int do_full_bridge (char * const *argv)
694 {
695         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
696
697         /* configure PD5 and PD6 as output */
698         gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
699         gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
700
701         if (strcmp (argv[2], "+") == 0) {
702               gpio->PDDAT |= (1 << 5);
703               gpio->PDDAT |= (1 << 6);
704               return 0;
705         }
706         else if (strcmp (argv[2], "-") == 0) {
707                 gpio->PDDAT &= ~(1 << 5);
708                 gpio->PDDAT |= (1 << 6);
709                 return 0;
710         }
711         else if (strcmp (argv[2], "off") == 0) {
712                 gpio->PDDAT &= ~(1 << 5);
713                 gpio->PDDAT &= ~(1 << 6);
714                 return 0;
715         }
716         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
717         return 1;
718 }
719
720 /* val must be in [0, 4095] */
721 static inline unsigned long tsc2000_to_uv (u16 val)
722 {
723         return ((250000 * val) / 4096) * 10;
724 }
725
726
727 int do_dac (char * const *argv)
728 {
729         int brightness;
730
731         /* initialize SPI */
732         tsc2000_spi_init ();
733
734         if  (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
735              (brightness > 255)) {
736                 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
737                 return 1;
738         }
739         tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
740         tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
741
742         return 0;
743 }
744
745
746 int do_v_bat (void)
747 {
748         unsigned long ret, res;
749
750         /* initialize SPI */
751         spi_init ();
752
753         tsc2000_write(TSC2000_REG_ADC, 0x1836);
754
755         /* now wait for data available */
756         adc_wait_conversion_done();
757
758         ret = tsc2000_read(TSC2000_REG_BAT1);
759         res = (tsc2000_to_uv(ret) + 1250) / 2500;
760         res += (ERROR_BATTERY * res) / 1000;
761
762         print_identifier ();
763         printf ("%ld", (res / 100));
764         printf (".%ld", ((res % 100) / 10));
765         printf ("%ld V\n", (res % 10));
766         return 0;
767 }
768
769
770 int do_pressure (void)
771 {
772         /* initialize SPI */
773         spi_init ();
774
775         tsc2000_write(TSC2000_REG_ADC, 0x2436);
776
777         /* now wait for data available */
778         adc_wait_conversion_done();
779
780         print_identifier ();
781         printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
782         return 0;
783 }
784
785
786 int do_motor_contact (void)
787 {
788         int result;
789
790         result = *CPLD_FILL_LEVEL; /* read CPLD */
791         debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
792
793         /* print result to console */
794         print_identifier ();
795         if ((result & (1 << 17)) == 0)
796                 printf("0\n");
797         else
798                 printf("1\n");
799         return 0;
800 }
801
802 int do_motor (char * const *argv)
803 {
804         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
805
806         /* Configure I/O port */
807         gpio->PGCON &= ~(0x3 << 0);
808         gpio->PGCON |= (0x1 << 0);
809
810         if (strcmp (argv[2], "on") == 0) {
811                 gpio->PGDAT &= ~(1 << 0);
812                 return 0;
813         }
814         if (strcmp (argv[2], "off") == 0) {
815                 gpio->PGDAT |= (1 << 0);
816                 return 0;
817         }
818         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
819         return 1;
820 }
821
822 static void print_identifier (void)
823 {
824         printf ("## FKT: ");
825 }
826
827 int do_pwm (char * const *argv)
828 {
829         int counter;
830         struct s3c24x0_gpio * const gpio = s3c24x0_get_base_gpio();
831         struct s3c24x0_timers * const timers = s3c24x0_get_base_timers();
832
833         if (strcmp (argv[2], "on") == 0) {
834                 /* configure pin GPD8 as TOUT3 */
835                 gpio->PDCON &= ~(0x3 << 8*2);
836                 gpio->PDCON |= (0x2 << 8*2);
837
838                 /* set prescaler for timer 2, 3 and 4 */
839                 timers->TCFG0 &= ~0xFF00;
840                 timers->TCFG0 |= 0x0F00;
841
842                 /* set divider for timer 3 */
843                 timers->TCFG1 &= ~(0xf << 12);
844                 timers->TCFG1 |= (0x3 << 12);
845
846                 /* set frequency */
847                 counter = (PCLK / PWM_FREQ) >> 9;
848                 timers->ch[3].TCNTB = counter;
849                 timers->ch[3].TCMPB = counter / 2;
850
851                 /* start timer */
852                 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
853                 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
854                 return 0;
855         }
856         if (strcmp (argv[2], "off") == 0) {
857
858                 /* stop timer */
859                 timers->TCON &= ~(START2 | RELOAD2);
860
861                 /* configure pin GPD8 as output and set to 0 */
862                 gpio->PDCON &= ~(0x3 << 8*2);
863                 gpio->PDCON |= (0x1 << 8*2);
864                 gpio->PDDAT &= ~(1 << 8);
865                 return 0;
866         }
867         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
868         return 1;
869 }
870
871
872 int do_thermo (char * const *argv)
873 {
874         int     channel, res;
875
876         tsc2000_reg_init ();
877
878         if (strcmp (argv[2], "all") == 0) {
879                 int i;
880                 for (i=0; i <= 15; i++) {
881                         res = tsc2000_read_channel(i);
882                         print_identifier ();
883                         printf ("c%d: %d\n", i, res);
884                 }
885                 return 0;
886         }
887         channel = simple_strtoul (argv[2], NULL, 10);
888         res = tsc2000_read_channel(channel);
889         print_identifier ();
890         printf ("%d\n", res);
891         return 0;                 /* return OK */
892 }
893
894
895 int do_touch (char * const *argv)
896 {
897         int     x, y;
898
899         if (strcmp (argv[2], "tl") == 0) {
900 #ifdef CONFIG_TOUCH_WAIT_PRESSED
901                 touch_wait_pressed();
902 #else
903                 {
904                         int i;
905                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
906                                 if (touch_check_pressed ()) {
907                                         break;
908                                 }
909                                 udelay (1000);  /* pause 1 ms */
910                         }
911                 }
912                 if (!touch_check_pressed()) {
913                         print_identifier ();
914                         printf ("error: touch not pressed\n");
915                         return 1;
916                 }
917 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
918                 touch_read_x_y (&x, &y);
919
920                 print_identifier ();
921                 printf ("x=%d y=%d\n", x, y);
922                 return touch_write_clibration_values (CALIB_TL, x, y);
923         }
924         else if (strcmp (argv[2], "dr") == 0) {
925 #ifdef CONFIG_TOUCH_WAIT_PRESSED
926                 touch_wait_pressed();
927 #else
928                 {
929                         int i;
930                         for (i = 0; i < (TOUCH_TIMEOUT * 1000); i++) {
931                                 if (touch_check_pressed ()) {
932                                         break;
933                                 }
934                                 udelay (1000);  /* pause 1 ms */
935                         }
936                 }
937                 if (!touch_check_pressed()) {
938                         print_identifier ();
939                         printf ("error: touch not pressed\n");
940                         return 1;
941                 }
942 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
943                 touch_read_x_y (&x, &y);
944
945                 print_identifier ();
946                 printf ("x=%d y=%d\n", x, y);
947
948                 return touch_write_clibration_values (CALIB_DR, x, y);
949         }
950         return 1;                 /* not "tl", nor "dr", so return error */
951 }
952
953
954 #ifdef CONFIG_TOUCH_WAIT_PRESSED
955 static void touch_wait_pressed (void)
956 {
957         while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
958 }
959
960 #else
961 static int touch_check_pressed (void)
962 {
963         return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
964 }
965 #endif /* CONFIG_TOUCH_WAIT_PRESSED */
966
967 static int touch_write_clibration_values (int calib_point, int x, int y)
968 {
969 #if defined(CONFIG_CMD_I2C)
970         int x_verify = 0;
971         int y_verify = 0;
972
973         tsc2000_reg_init ();
974
975         if (calib_point == CALIB_TL) {
976                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
977                                (unsigned char *)&x, 2)) {
978                         return 1;
979                 }
980                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
981                                (unsigned char *)&y, 2)) {
982                         return 1;
983                 }
984
985                 /* verify written values */
986                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
987                               (unsigned char *)&x_verify, 2)) {
988                         return 1;
989                 }
990                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
991                                (unsigned char *)&y_verify, 2)) {
992                         return 1;
993                 }
994                 if ((y != y_verify) || (x != x_verify)) {
995                         print_identifier ();
996                         printf ("error: verify error\n");
997                         return 1;
998                 }
999                 return 0;       /* no error */
1000         }
1001         else if (calib_point == CALIB_DR) {
1002                   if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
1003                                (unsigned char *)&x, 2)) {
1004                         return 1;
1005                   }
1006                 if (i2c_write_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1007                                (unsigned char *)&y, 2)) {
1008                         return 1;
1009                 }
1010
1011                 /* verify written values */
1012                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
1013                                        (unsigned char *)&x_verify, 2)) {
1014                         return 1;
1015                 }
1016                 if (i2c_read_multiple (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
1017                                (unsigned char *)&y_verify, 2)) {
1018                         return 1;
1019                 }
1020                 if ((y != y_verify) || (x != x_verify)) {
1021                         print_identifier ();
1022                         printf ("error: verify error\n");
1023                         return 1;
1024                 }
1025                 return 0;
1026         }
1027         return 1;
1028 #else
1029         printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1030                 "to EEPROM\n");
1031         return (1);
1032 #endif
1033 }
1034
1035
1036 static void touch_read_x_y (int *px, int *py)
1037 {
1038         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
1039         adc_wait_conversion_done();
1040         *px = tsc2000_read(TSC2000_REG_X);
1041
1042         tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
1043         adc_wait_conversion_done();
1044         *py = tsc2000_read(TSC2000_REG_Y);
1045 }
1046
1047
1048 int do_rs485 (char * const *argv)
1049 {
1050         int timeout;
1051         char data[RS485_MAX_RECEIVE_BUF_LEN];
1052
1053         if (strcmp (argv[2], "send") == 0) {
1054                 return (rs485_send_line (argv[3]));
1055         }
1056         else if (strcmp (argv[2], "receive") == 0) {
1057                 timeout = simple_strtoul(argv[3], NULL, 10);
1058                 if (rs485_receive_chars (data, timeout) != 0) {
1059                         print_identifier ();
1060                         printf ("## nothing received\n");
1061                         return (1);
1062                 }
1063                 else {
1064                         print_identifier ();
1065                         printf ("%s\n", data);
1066                         return (0);
1067                 }
1068         }
1069         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1070         return (1);             /* unknown command, return error */
1071 }
1072
1073
1074 static int rs485_send_line (const char *data)
1075 {
1076         rs485_init ();
1077         trab_rs485_enable_tx ();
1078         rs485_puts (data);
1079         rs485_putc ('\n');
1080
1081         return (0);
1082 }
1083
1084
1085 static int rs485_receive_chars (char *data, int timeout)
1086 {
1087         int i;
1088         int receive_count = 0;
1089
1090         rs485_init ();
1091         trab_rs485_enable_rx ();
1092
1093         /* test every 1 ms for received characters to avoid a receive FIFO
1094          * overrun (@ 38.400 Baud) */
1095         for (i = 0; i < (timeout * 1000); i++) {
1096                 while (rs485_tstc ()) {
1097                         if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
1098                                 break;
1099                         *data++ = rs485_getc ();
1100                         receive_count++;
1101                 }
1102                 udelay (1000);  /* pause 1 ms */
1103         }
1104         *data = '\0';           /* terminate string */
1105
1106         if (receive_count == 0)
1107                 return (1);
1108         else
1109                 return (0);
1110 }
1111
1112
1113 int do_serial_number (char * const *argv)
1114 {
1115 #if defined(CONFIG_CMD_I2C)
1116         unsigned int serial_number;
1117
1118         if (strcmp (argv[2], "read") == 0) {
1119                 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1120                               (unsigned char *)&serial_number, 4)) {
1121                         printf ("could not read from eeprom\n");
1122                         return (1);
1123                 }
1124                 print_identifier ();
1125                 printf ("%08d\n", serial_number);
1126                 return (0);
1127         }
1128         else if (strcmp (argv[2], "write") == 0) {
1129                 serial_number = simple_strtoul(argv[3], NULL, 10);
1130                 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
1131                               (unsigned char *)&serial_number, 4)) {
1132                         printf ("could not write to eeprom\n");
1133                         return (1);
1134                 }
1135                 return (0);
1136         }
1137         printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
1138         return (1);             /* unknown command, return error */
1139 #else
1140         printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1141                 "to EEPROM\n");
1142         return (1);
1143 #endif
1144 }
1145
1146
1147 int do_crc16 (void)
1148 {
1149 #if defined(CONFIG_CMD_I2C)
1150         int crc;
1151         unsigned char buf[EEPROM_MAX_CRC_BUF];
1152
1153         if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
1154                 printf ("could not read from eeprom\n");
1155                 return (1);
1156         }
1157         crc = 0;                /* start value of crc calculation */
1158         crc = updcrc (crc, buf, 60);
1159
1160         print_identifier ();
1161         printf ("crc16=%#04x\n", crc);
1162
1163         if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (unsigned char *)&crc,
1164                        sizeof (crc))) {
1165                 printf ("could not read from eeprom\n");
1166                 return (1);
1167         }
1168         return (0);
1169 #else
1170         printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1171                 "to EEPROM\n");
1172         return (1);
1173 #endif
1174 }
1175
1176
1177 /*
1178  * Calculate, intelligently, the CRC of a dataset incrementally given a
1179  * buffer full at a time.
1180  * Initialize crc to 0 for XMODEM, -1 for CCITT.
1181  *
1182  * Usage:
1183  *   newcrc = updcrc( oldcrc, bufadr, buflen )
1184  *        unsigned int oldcrc, buflen;
1185  *        char *bufadr;
1186  *
1187  * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1188  * Compile with -DMAKETAB to print values for crctab to stdout
1189  */
1190
1191     /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1192      * If you change P, you must change crctab[]'s initial value to what is
1193      * printed by initcrctab()
1194      */
1195 #define   P    0x1021
1196
1197     /* number of bits in CRC: don't change it. */
1198 #define W 16
1199
1200     /* this the number of bits per char: don't change it. */
1201 #define B 8
1202
1203 static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1204     0x0000,  0x1021,  0x2042,  0x3063,  0x4084,  0x50a5,  0x60c6,  0x70e7,
1205     0x8108,  0x9129,  0xa14a,  0xb16b,  0xc18c,  0xd1ad,  0xe1ce,  0xf1ef,
1206     0x1231,  0x0210,  0x3273,  0x2252,  0x52b5,  0x4294,  0x72f7,  0x62d6,
1207     0x9339,  0x8318,  0xb37b,  0xa35a,  0xd3bd,  0xc39c,  0xf3ff,  0xe3de,
1208     0x2462,  0x3443,  0x0420,  0x1401,  0x64e6,  0x74c7,  0x44a4,  0x5485,
1209     0xa56a,  0xb54b,  0x8528,  0x9509,  0xe5ee,  0xf5cf,  0xc5ac,  0xd58d,
1210     0x3653,  0x2672,  0x1611,  0x0630,  0x76d7,  0x66f6,  0x5695,  0x46b4,
1211     0xb75b,  0xa77a,  0x9719,  0x8738,  0xf7df,  0xe7fe,  0xd79d,  0xc7bc,
1212     0x48c4,  0x58e5,  0x6886,  0x78a7,  0x0840,  0x1861,  0x2802,  0x3823,
1213     0xc9cc,  0xd9ed,  0xe98e,  0xf9af,  0x8948,  0x9969,  0xa90a,  0xb92b,
1214     0x5af5,  0x4ad4,  0x7ab7,  0x6a96,  0x1a71,  0x0a50,  0x3a33,  0x2a12,
1215     0xdbfd,  0xcbdc,  0xfbbf,  0xeb9e,  0x9b79,  0x8b58,  0xbb3b,  0xab1a,
1216     0x6ca6,  0x7c87,  0x4ce4,  0x5cc5,  0x2c22,  0x3c03,  0x0c60,  0x1c41,
1217     0xedae,  0xfd8f,  0xcdec,  0xddcd,  0xad2a,  0xbd0b,  0x8d68,  0x9d49,
1218     0x7e97,  0x6eb6,  0x5ed5,  0x4ef4,  0x3e13,  0x2e32,  0x1e51,  0x0e70,
1219     0xff9f,  0xefbe,  0xdfdd,  0xcffc,  0xbf1b,  0xaf3a,  0x9f59,  0x8f78,
1220     0x9188,  0x81a9,  0xb1ca,  0xa1eb,  0xd10c,  0xc12d,  0xf14e,  0xe16f,
1221     0x1080,  0x00a1,  0x30c2,  0x20e3,  0x5004,  0x4025,  0x7046,  0x6067,
1222     0x83b9,  0x9398,  0xa3fb,  0xb3da,  0xc33d,  0xd31c,  0xe37f,  0xf35e,
1223     0x02b1,  0x1290,  0x22f3,  0x32d2,  0x4235,  0x5214,  0x6277,  0x7256,
1224     0xb5ea,  0xa5cb,  0x95a8,  0x8589,  0xf56e,  0xe54f,  0xd52c,  0xc50d,
1225     0x34e2,  0x24c3,  0x14a0,  0x0481,  0x7466,  0x6447,  0x5424,  0x4405,
1226     0xa7db,  0xb7fa,  0x8799,  0x97b8,  0xe75f,  0xf77e,  0xc71d,  0xd73c,
1227     0x26d3,  0x36f2,  0x0691,  0x16b0,  0x6657,  0x7676,  0x4615,  0x5634,
1228     0xd94c,  0xc96d,  0xf90e,  0xe92f,  0x99c8,  0x89e9,  0xb98a,  0xa9ab,
1229     0x5844,  0x4865,  0x7806,  0x6827,  0x18c0,  0x08e1,  0x3882,  0x28a3,
1230     0xcb7d,  0xdb5c,  0xeb3f,  0xfb1e,  0x8bf9,  0x9bd8,  0xabbb,  0xbb9a,
1231     0x4a75,  0x5a54,  0x6a37,  0x7a16,  0x0af1,  0x1ad0,  0x2ab3,  0x3a92,
1232     0xfd2e,  0xed0f,  0xdd6c,  0xcd4d,  0xbdaa,  0xad8b,  0x9de8,  0x8dc9,
1233     0x7c26,  0x6c07,  0x5c64,  0x4c45,  0x3ca2,  0x2c83,  0x1ce0,  0x0cc1,
1234     0xef1f,  0xff3e,  0xcf5d,  0xdf7c,  0xaf9b,  0xbfba,  0x8fd9,  0x9ff8,
1235     0x6e17,  0x7e36,  0x4e55,  0x5e74,  0x2e93,  0x3eb2,  0x0ed1,  0x1ef0
1236     };
1237
1238 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1239                              unsigned int icnt )
1240 {
1241         register unsigned short crc = icrc;
1242         register unsigned char *cp = icp;
1243         register unsigned int cnt = icnt;
1244
1245         while (cnt--)
1246                 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];
1247
1248         return (crc);
1249 }
1250
1251
1252 int do_gain (char * const *argv)
1253 {
1254         int range;
1255
1256         range = simple_strtoul (argv[2], NULL, 10);
1257         if ((range < 1) || (range > 3))
1258         {
1259                 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1260                 return 1;
1261         }
1262
1263         tsc2000_set_range (range);
1264         return (0);
1265 }
1266
1267
1268 int do_eeprom (char * const *argv)
1269 {
1270 #if defined(CONFIG_CMD_I2C)
1271         if (strcmp (argv[2], "read") == 0) {
1272                 return (trab_eeprom_read (argv));
1273         }
1274
1275         else if (strcmp (argv[2], "write") == 0) {
1276                 return (trab_eeprom_write (argv));
1277         }
1278
1279         printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
1280         return (1);
1281 #else
1282         printf ("No I2C support enabled (CONFIG_CMD_I2C), could not write "
1283                 "to EEPROM\n");
1284         return (1);
1285 #endif
1286 }
1287
1288 #if defined(CONFIG_CMD_I2C)
1289 static int trab_eeprom_read (char * const *argv)
1290 {
1291         int i;
1292         int len;
1293         unsigned int addr;
1294         long int value = 0;
1295         uchar *buffer;
1296
1297         buffer = (uchar *) &value;
1298         addr = simple_strtoul (argv[3], NULL, 10);
1299         addr &= 0xfff;
1300         len = simple_strtoul (argv[4], NULL, 10);
1301         if ((len < 1) || (len > 4)) {
1302                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1303                         argv[4]);
1304                 return (1);
1305         }
1306         for (i = 0; i < len; i++) {
1307                 if (i2c_read (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1308                         printf ("%s: could not read from i2c device %#x"
1309                                 ", addr %d\n", __FUNCTION__,
1310                                 I2C_EEPROM_DEV_ADDR, addr);
1311                         return (1);
1312                 }
1313         }
1314         print_identifier ();
1315         if (strcmp (argv[5], "-") == 0) {
1316                 if (len == 1)
1317                         printf ("%d\n", (signed char) value);
1318                 else if (len == 2)
1319                         printf ("%d\n", (signed short int) value);
1320                 else
1321                         printf ("%ld\n", value);
1322         }
1323         else {
1324                 if (len == 1)
1325                         printf ("%d\n", (unsigned char) value);
1326                 else if (len == 2)
1327                         printf ("%d\n", (unsigned short int) value);
1328                 else
1329                         printf ("%ld\n", (unsigned long int) value);
1330         }
1331         return (0);
1332 }
1333
1334 static int trab_eeprom_write (char * const *argv)
1335 {
1336         int i;
1337         int len;
1338         unsigned int addr;
1339         long int value = 0;
1340         uchar *buffer;
1341
1342         buffer = (uchar *) &value;
1343         addr = simple_strtoul (argv[3], NULL, 10);
1344         addr &= 0xfff;
1345         len = simple_strtoul (argv[4], NULL, 10);
1346         if ((len < 1) || (len > 4)) {
1347                 printf ("%s: invalid parameter %s\n", __FUNCTION__,
1348                         argv[4]);
1349                 return (1);
1350         }
1351         value = simple_strtol (argv[5], NULL, 10);
1352         debug ("value=%ld\n", value);
1353         for (i = 0; i < len; i++) {
1354                 if (i2c_write (I2C_EEPROM_DEV_ADDR, addr+i, 1, buffer+i, 1)) {
1355                         printf ("%s: could not write to i2c device %d"
1356                                 ", addr %d\n", __FUNCTION__,
1357                                 I2C_EEPROM_DEV_ADDR, addr);
1358                         return (1);
1359                 }
1360 #if 0
1361                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1362                         "%#x+%d=%p=%#x \n",I2C_EEPROM_DEV_ADDR_DEV_ADDR , addr,
1363                         i, addr+i, 1, buffer, i, buffer+i, *(buffer+i));
1364 #endif
1365                 udelay (30000); /* wait for EEPROM ready */
1366         }
1367         return (0);
1368 }
1369
1370 int i2c_write_multiple (uchar chip, uint addr, int alen,
1371                         uchar *buffer, int len)
1372 {
1373         int i;
1374
1375         if (alen != 1) {
1376                 printf ("%s: addr len other than 1 not supported\n",
1377                          __FUNCTION__);
1378                 return (1);
1379         }
1380
1381         for (i = 0; i < len; i++) {
1382                 if (i2c_write (chip, addr+i, alen, buffer+i, 1)) {
1383                         printf ("%s: could not write to i2c device %d"
1384                                  ", addr %d\n", __FUNCTION__, chip, addr);
1385                         return (1);
1386                 }
1387 #if 0
1388                 printf ("chip=%#x, addr+i=%#x+%d=%p, alen=%d, *buffer+i="
1389                         "%#x+%d=%p=\"%.1s\"\n", chip, addr, i, addr+i,
1390                         alen, buffer, i, buffer+i, buffer+i);
1391 #endif
1392
1393                 udelay (30000);
1394         }
1395         return (0);
1396 }
1397
1398 int i2c_read_multiple ( uchar chip, uint addr, int alen,
1399                         uchar *buffer, int len)
1400 {
1401         int i;
1402
1403         if (alen != 1) {
1404                 printf ("%s: addr len other than 1 not supported\n",
1405                          __FUNCTION__);
1406                 return (1);
1407         }
1408
1409         for (i = 0; i < len; i++) {
1410                 if (i2c_read (chip, addr+i, alen, buffer+i, 1)) {
1411                         printf ("%s: could not read from i2c device %#x"
1412                                  ", addr %d\n", __FUNCTION__, chip, addr);
1413                         return (1);
1414                 }
1415         }
1416         return (0);
1417 }
1418 #endif