]> git.ipfire.org Git - people/ms/u-boot.git/blob - board/trab/trab_fkt.c
digsy MTC: Add 'mtc' command.
[people/ms/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 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 S3C2400_ADC *padc;
410
411 padc = S3C2400_GetBase_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 S3C2400_ADC *padc;
450
451 padc = S3C2400_GetBase_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 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 **argv)
589 {
590 int counter;
591
592 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
593 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 **argv)
639 {
640 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 **argv)
694 {
695 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 **argv)
728 {
729 int brightness;
730
731 /* initialize SPI */
732 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 **argv)
803 {
804 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_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 **argv)
828 {
829 int counter;
830 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
831 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_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 **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 **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 **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 **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 **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 **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 **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 **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