3 * Martin Krause, TQ-Systems GmbH, martin.krause@tqs.de
5 * See file CREDITS for list of people who contributed to this
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.
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.
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,
32 /* assignment of CPU internal ADC channels with TRAB hardware */
36 /* CPLD-Register for controlling TRAB hardware functions */
37 #define CPLD_BUTTONS ((volatile unsigned long *)0x04020000)
38 #define CPLD_FILL_LEVEL ((volatile unsigned long *)0x04008000)
39 #define CPLD_ROTARY_SWITCH ((volatile unsigned long *)0x04018000)
40 #define CPLD_RS485_RE ((volatile unsigned long *)0x04028000)
42 /* timer configuration bits for buzzer and PWM */
43 #define START2 (1 << 12)
44 #define UPDATE2 (1 << 13)
45 #define INVERT2 (1 << 14)
46 #define RELOAD2 (1 << 15)
47 #define START3 (1 << 16)
48 #define UPDATE3 (1 << 17)
49 #define INVERT3 (1 << 18)
50 #define RELOAD3 (1 << 19)
53 #define BUZZER_FREQ 1000 /* frequency in Hz */
54 #define BUZZER_TIME 1000000 /* time in us */
58 /* definitions of I2C EEPROM device address */
59 #define I2C_EEPROM_DEV_ADDR 0x54
61 /* definition for touch panel calibration points */
62 #define CALIB_TL 0 /* calibration point in (T)op (L)eft corner */
63 #define CALIB_DR 1 /* calibration point in (D)own (R)ight corner */
65 /* EEPROM addresse map */
66 #define SERIAL_NUMBER 8
74 #define EEPROM_MAX_CRC_BUF 64
77 #define RS485_MAX_RECEIVE_BUF_LEN 100
79 /* Bit definitions for ADCCON */
80 #define ADC_ENABLE_START 0x1
81 #define ADC_READ_START 0x2
83 #define ADC_INP_AIN0 (0x0 << 3)
84 #define ADC_INP_AIN1 (0x1 << 3)
85 #define ADC_INP_AIN2 (0x2 << 3)
86 #define ADC_INP_AIN3 (0x3 << 3)
87 #define ADC_INP_AIN4 (0x4 << 3)
88 #define ADC_INP_AIN5 (0x5 << 3)
89 #define ADC_INP_AIN6 (0x6 << 3)
90 #define ADC_INP_AIN7 (0x7 << 3)
91 #define ADC_PRSCEN 0x4000
92 #define ADC_ECFLG 0x8000
94 /* function test functions */
99 int do_buttons (void);
100 int do_fill_level (void);
101 int do_rotary_switch (void);
102 int do_pressure (void);
104 int do_vfd_id (void);
105 int do_buzzer (void);
106 int do_led (char **);
107 int do_full_bridge (char **);
108 int do_dac (char **);
109 int do_motor_contact (void);
110 int do_motor (char **);
111 int do_pwm (char **);
112 int do_thermo (char **);
113 int do_touch (char **);
114 int do_rs485 (char **);
115 int do_serial_number (char **);
118 /* helper functions */
119 static void adc_init (void);
120 static int adc_read (unsigned int channel);
121 static void print_identifier (void);
122 static void touch_wait_pressed (void);
123 static void touch_read_x_y (int *x, int *y);
124 static int touch_write_clibration_values (int calib_point, int x, int y);
125 static int rs485_send_line (const char *data);
126 static int rs485_receive_chars (char *data, int timeout);
127 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
132 * TRAB board specific commands. Especially commands for burn-in and function
136 int trab_fkt (int argc, char *argv[])
141 if (get_version () != XF_VERSION) {
142 printf ("Wrong XF_VERSION. Please re-compile with actual "
144 printf ("Example expects ABI version %d\n", XF_VERSION);
145 printf ("Actual U-Boot ABI version %d\n", (int)get_version());
149 debug ("argc = %d\n", argc);
151 for (i=0; i<=argc; ++i) {
152 debug ("argv[%d] = \"%s\"\n", i, argv[i] ? argv[i] : "<NULL>");
164 if (strcmp (argv[1], "info") == 0) {
167 if (strcmp (argv[1], "dip") == 0) {
170 if (strcmp (argv[1], "vcc5v") == 0) {
171 return (do_vcc5v ());
173 if (strcmp (argv[1], "vcc12v") == 0) {
174 return (do_vcc12v ());
176 if (strcmp (argv[1], "buttons") == 0) {
177 return (do_buttons ());
179 if (strcmp (argv[1], "fill_level") == 0) {
180 return (do_fill_level ());
182 if (strcmp (argv[1], "rotary_switch") == 0) {
183 return (do_rotary_switch ());
185 if (strcmp (argv[1], "pressure") == 0) {
186 return (do_pressure ());
188 if (strcmp (argv[1], "v_bat") == 0) {
189 return (do_v_bat ());
191 if (strcmp (argv[1], "vfd_id") == 0) {
192 return (do_vfd_id ());
194 if (strcmp (argv[1], "buzzer") == 0) {
195 return (do_buzzer ());
197 if (strcmp (argv[1], "motor_contact") == 0) {
198 return (do_motor_contact ());
200 if (strcmp (argv[1], "crc16") == 0) {
201 return (do_crc16 ());
206 if (strcmp (argv[1], "full_bridge") == 0) {
207 return (do_full_bridge (argv));
209 if (strcmp (argv[1], "dac") == 0) {
210 return (do_dac (argv));
212 if (strcmp (argv[1], "motor") == 0) {
213 return (do_motor (argv));
215 if (strcmp (argv[1], "pwm") == 0) {
216 return (do_pwm (argv));
218 if (strcmp (argv[1], "thermo") == 0) {
219 return (do_thermo (argv));
221 if (strcmp (argv[1], "touch") == 0) {
222 return (do_touch (argv));
224 if (strcmp (argv[1], "serial_number") == 0) {
225 return (do_serial_number (argv));
230 if (strcmp (argv[1], "led") == 0) {
231 return (do_led (argv));
233 if (strcmp (argv[1], "rs485") == 0) {
234 return (do_rs485 (argv));
236 if (strcmp (argv[1], "serial_number") == 0) {
237 return (do_serial_number (argv));
245 printf ("Usage:\n<command> <parameter1> <parameter2> ...\n");
251 printf ("Stand-alone application for TRAB board function test\n");
252 printf ("Built: %s at %s\n", __DATE__ , __TIME__ );
259 unsigned int result = 0;
263 /***********************************************************
264 DIP switch connection (according to wa4-cpu.sp.301.pdf, page 3):
270 "On" DIP switch position short-circuits the voltage from
271 the input channel (i.e. '0' conversion result means "on").
272 *************************************************************/
274 for (i = 7; i > 3; i--) {
276 if ((adc_val = adc_read (i)) == -1) {
277 printf ("Channel %d could not be read\n", i);
282 * Input voltage (switch open) is 1.8 V.
283 * (Vin_High/VRef)*adc_res = (1,8V/2,5V)*1023) = 736
284 * Set trigger at halve that value.
287 result |= (1 << (i-4));
290 /* print result to console */
292 for (i = 0; i < 4; i++) {
293 if ((result & (1 << i)) == 0)
308 /* VCC5V is connected to channel 2 */
310 if ((result = adc_read (VCC5V)) == -1) {
311 printf ("VCC5V could not be read\n");
316 * Calculate voltage value. Split in two parts because there is no
317 * floating point support. VCC5V is connected over an resistor divider:
318 * VCC5V=ADCval*2,5V/1023*(10K+30K)/10K.
321 printf ("%d", (result & 0x3FF)* 10 / 1023);
322 printf (".%d", ((result & 0x3FF)* 10 % 1023)* 10 / 1023);
323 printf ("%d V\n", (((result & 0x3FF) * 10 % 1023 ) * 10 % 1023)
334 if ((result = adc_read (VCC12V)) == -1) {
335 printf ("VCC12V could not be read\n");
340 * Calculate voltage value. Split in two parts because there is no
341 * floating point support. VCC5V is connected over an resistor divider:
342 * VCC12V=ADCval*2,5V/1023*(30K+270K)/30K.
345 printf ("%d", (result & 0x3FF)* 25 / 1023);
346 printf (".%d V\n", ((result & 0x3FF)* 25 % 1023) * 10 / 1023);
351 static int adc_read (unsigned int channel)
353 int j = 1000; /* timeout value for wait loop in us */
356 padc = S3C2400_GetBase_ADC();
359 debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
361 padc->ADCCON &= ~ADC_STDBM; /* select normal mode */
362 padc->ADCCON &= ~(0x7 << 3); /* clear the channel bits */
363 padc->ADCCON |= ((channel << 3) | ADC_ENABLE_START);
365 debug ("%s: reading ch %d, addcon %#x\n", __FUNCTION__,
366 (padc->ADCCON >> 3) & 0x7, padc->ADCCON);
369 if ((padc->ADCCON & ADC_ENABLE_START) == 0)
375 printf("%s: ADC timeout\n", __FUNCTION__);
376 padc->ADCCON |= ADC_STDBM; /* select standby mode */
380 padc->ADCCON |= ADC_STDBM; /* select standby mode */
382 debug ("%s: return %#x, adccon %#x\n", __FUNCTION__, padc->ADCDAT & 0x3FF,
385 return (padc->ADCDAT & 0x3FF);
389 static void adc_init (void)
393 padc = S3C2400_GetBase_ADC();
395 debug ("%s: adccon %#x\n", __FUNCTION__, padc->ADCCON);
397 padc->ADCCON &= ~(0xff << 6); /* clear prescaler bits */
398 padc->ADCCON |= ((65 << 6) | ADC_PRSCEN); /* set prescaler */
400 debug ("%s: init completed: adccon %#x\n", __FUNCTION__, padc->ADCCON);
405 int do_buttons (void)
410 result = *CPLD_BUTTONS; /* read CPLD */
411 debug ("%s: cpld_taster (32 bit) %#x\n", __FUNCTION__, result);
413 /* print result to console */
415 for (i = 16; i <= 19; i++) {
416 if ((result & (1 << i)) == 0)
426 int do_fill_level (void)
430 result = *CPLD_FILL_LEVEL; /* read CPLD */
431 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
433 /* print result to console */
435 if ((result & (1 << 16)) == 0)
443 int do_rotary_switch (void)
447 result = *CPLD_ROTARY_SWITCH; /* read CPLD */
448 debug ("%s: cpld_inc (32 bit) %#x\n", __FUNCTION__, result);
450 *CPLD_ROTARY_SWITCH |= (3 << 16); /* clear direction bits in CPLD */
452 /* print result to console */
454 if ((result & (1 << 16)) == (1 << 16))
456 if ((result & (1 << 17)) == (1 << 17))
458 if (((result & (1 << 16)) == 0) && ((result & (1 << 17)) == 0))
460 if ((result & (1 << 18)) == 0)
471 long int pcup_old, pccon_old;
473 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
475 /* try to red vfd board id from the value defined by pull-ups */
477 pcup_old = gpio->PCUP;
478 pccon_old = gpio->PCCON;
480 gpio->PCUP = (gpio->PCUP & 0xFFF0); /* activate GPC0...GPC3 pull-ups */
481 gpio->PCCON = (gpio->PCCON & 0xFFFFFF00); /* configure GPC0...GPC3 as
483 udelay (10); /* allow signals to settle */
484 vfd_board_id = (~gpio->PCDAT) & 0x000F; /* read GPC0...GPC3 port pins */
486 gpio->PCCON = pccon_old;
487 gpio->PCUP = pcup_old;
489 /* print vfd_board_id to console */
491 for (i = 0; i < 4; i++) {
492 if ((vfd_board_id & (1 << i)) == 0)
505 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
506 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
508 /* configure pin GPD7 as TOUT2 */
509 gpio->PDCON &= ~0xC000;
510 gpio->PDCON |= 0x8000;
512 /* set prescaler for timer 2, 3 and 4 */
513 timers->TCFG0 &= ~0xFF00;
514 timers->TCFG0 |= 0x0F00;
516 /* set divider for timer 2 */
517 timers->TCFG1 &= ~0xF00;
518 timers->TCFG1 |= 0x300;
521 counter = (PCLK / BUZZER_FREQ) >> 9;
522 timers->ch[2].TCNTB = counter;
523 timers->ch[2].TCMPB = counter / 2;
525 debug ("%s: frequency: %d, duration: %d\n", __FUNCTION__, BUZZER_FREQ,
529 timers->TCON = (timers->TCON | UPDATE2 | RELOAD2) & ~INVERT2;
530 timers->TCON = (timers->TCON | START2) & ~UPDATE2;
532 udelay (BUZZER_TIME);
535 timers->TCON &= ~(START2 | RELOAD2);
537 /* port pin configuration */
538 gpio->PDCON &= ~0xC000;
539 gpio->PDCON |= 0x4000;
540 gpio->PDDAT &= ~0x80;
545 int do_led (char **argv)
547 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
549 /* configure PC14 and PC15 as output */
550 gpio->PCCON &= ~(0xF << 28);
551 gpio->PCCON |= (0x5 << 28);
553 /* configure PD0 and PD4 as output */
554 gpio->PDCON &= ~((0x3 << 8) | 0x3);
555 gpio->PDCON |= ((0x1 << 8) | 0x1);
557 switch (simple_strtoul(argv[2], NULL, 10)) {
564 if (strcmp (argv[3], "on") == 0)
565 gpio->PCDAT |= (1 << 14);
567 gpio->PCDAT &= ~(1 << 14);
571 if (strcmp (argv[3], "on") == 0)
572 gpio->PCDAT |= (1 << 15);
574 gpio->PCDAT &= ~(1 << 15);
578 if (strcmp (argv[3], "on") == 0)
579 gpio->PDDAT |= (1 << 0);
581 gpio->PDDAT &= ~(1 << 0);
585 if (strcmp (argv[3], "on") == 0)
586 gpio->PDDAT |= (1 << 4);
588 gpio->PDDAT &= ~(1 << 4);
595 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
600 int do_full_bridge (char **argv)
602 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
604 /* configure PD5 and PD6 as output */
605 gpio->PDCON &= ~((0x3 << 5*2) | (0x3 << 6*2));
606 gpio->PDCON |= ((0x1 << 5*2) | (0x1 << 6*2));
608 if (strcmp (argv[2], "+") == 0) {
609 gpio->PDDAT |= (1 << 5);
610 gpio->PDDAT |= (1 << 6);
613 else if (strcmp (argv[2], "-") == 0) {
614 gpio->PDDAT &= ~(1 << 5);
615 gpio->PDDAT |= (1 << 6);
618 else if (strcmp (argv[2], "off") == 0) {
619 gpio->PDDAT &= ~(1 << 5);
620 gpio->PDDAT &= ~(1 << 6);
623 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
627 /* val must be in [0, 4095] */
628 static inline unsigned long tsc2000_to_uv (u16 val)
630 return ((250000 * val) / 4096) * 10;
634 int do_dac (char **argv)
641 if (((brightness = simple_strtoul (argv[2], NULL, 10)) < 0) ||
642 (brightness > 255)) {
643 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
646 tsc2000_write(TSC2000_REG_DACCTL, 0x0); /* Power up DAC */
647 tsc2000_write(TSC2000_REG_DAC, brightness & 0xff);
655 unsigned long ret, res;
660 tsc2000_write(TSC2000_REG_ADC, 0x1836);
662 /* now wait for data available */
663 adc_wait_conversion_done();
665 ret = tsc2000_read(TSC2000_REG_BAT1);
666 res = (tsc2000_to_uv(ret) + 1250) / 2500;
667 res += (ERROR_BATTERY * res) / 1000;
670 printf ("%ld", (res / 100));
671 printf (".%ld", ((res % 100) / 10));
672 printf ("%ld V\n", (res % 10));
677 int do_pressure (void)
682 tsc2000_write(TSC2000_REG_ADC, 0x2436);
684 /* now wait for data available */
685 adc_wait_conversion_done();
688 printf ("%d\n", tsc2000_read(TSC2000_REG_AUX2));
693 int do_motor_contact (void)
697 result = *CPLD_FILL_LEVEL; /* read CPLD */
698 debug ("%s: cpld_fuellstand (32 bit) %#x\n", __FUNCTION__, result);
700 /* print result to console */
702 if ((result & (1 << 17)) == 0)
709 int do_motor (char **argv)
711 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
713 /* Configure I/O port */
714 gpio->PGCON &= ~(0x3 << 0);
715 gpio->PGCON |= (0x1 << 0);
717 if (strcmp (argv[2], "on") == 0) {
718 gpio->PGDAT &= ~(1 << 0);
721 if (strcmp (argv[2], "off") == 0) {
722 gpio->PGDAT |= (1 << 0);
725 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
729 static void print_identifier (void)
734 int do_pwm (char **argv)
737 S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
738 S3C24X0_TIMERS * const timers = S3C24X0_GetBase_TIMERS();
740 if (strcmp (argv[2], "on") == 0) {
741 /* configure pin GPD8 as TOUT3 */
742 gpio->PDCON &= ~(0x3 << 8*2);
743 gpio->PDCON |= (0x2 << 8*2);
745 /* set prescaler for timer 2, 3 and 4 */
746 timers->TCFG0 &= ~0xFF00;
747 timers->TCFG0 |= 0x0F00;
749 /* set divider for timer 3 */
750 timers->TCFG1 &= ~(0xf << 12);
751 timers->TCFG1 |= (0x3 << 12);
754 counter = (PCLK / PWM_FREQ) >> 9;
755 timers->ch[3].TCNTB = counter;
756 timers->ch[3].TCMPB = counter / 2;
759 timers->TCON = (timers->TCON | UPDATE3 | RELOAD3) & ~INVERT3;
760 timers->TCON = (timers->TCON | START3) & ~UPDATE3;
763 if (strcmp (argv[2], "off") == 0) {
766 timers->TCON &= ~(START2 | RELOAD2);
768 /* configure pin GPD8 as output and set to 0 */
769 gpio->PDCON &= ~(0x3 << 8*2);
770 gpio->PDCON |= (0x1 << 8*2);
771 gpio->PDDAT &= ~(1 << 8);
774 printf ("%s: invalid parameter %s\n", __FUNCTION__, argv[2]);
779 int do_thermo (char **argv)
784 tsc2000_set_range (3);
786 if (strcmp (argv[2], "all") == 0) {
788 for (i=0; i <= 15; i++) {
789 res = tsc2000_read_channel(i);
791 printf ("c%d: %d\n", i, res);
795 channel = simple_strtoul (argv[2], NULL, 10);
796 res = tsc2000_read_channel(channel);
798 printf ("%d\n", res);
799 return 0; /* return OK */
804 int do_touch (char **argv)
808 if (strcmp (argv[2], "tl") == 0) {
809 touch_wait_pressed();
810 touch_read_x_y (&x, &y);
813 printf ("x=%d y=%d\n", x, y);
814 return touch_write_clibration_values (CALIB_TL, x, y);
816 else if (strcmp (argv[2], "dr") == 0) {
817 touch_wait_pressed();
818 touch_read_x_y (&x, &y);
821 printf ("x=%d y=%d\n", x, y);
823 return touch_write_clibration_values (CALIB_DR, x, y);
825 return 1; /* return error */
829 static void touch_wait_pressed (void)
831 while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
835 static int touch_write_clibration_values (int calib_point, int x, int y)
837 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
840 if (calib_point == CALIB_TL) {
841 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X0, 1,
843 printf ("could not write to eeprom\n");
847 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y0, 1,
849 printf ("could not write to eeprom\n");
855 else if (calib_point == CALIB_DR) {
856 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_X1, 1,
858 printf ("could not write to eeprom\n");
862 if (i2c_write (I2C_EEPROM_DEV_ADDR, TOUCH_Y1, 1,
864 printf ("could not write to eeprom\n");
872 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
875 #endif /* CFG_CMD_I2C */
879 static void touch_read_x_y (int *px, int *py)
881 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD0 | TC_AD1);
882 adc_wait_conversion_done();
883 *px = tsc2000_read(TSC2000_REG_X);
885 tsc2000_write(TSC2000_REG_ADC, DEFAULT_ADC | TC_AD2);
886 adc_wait_conversion_done();
887 *py = tsc2000_read(TSC2000_REG_Y);
892 int do_rs485 (char **argv)
895 char data[RS485_MAX_RECEIVE_BUF_LEN];
897 if (strcmp (argv[2], "send") == 0) {
898 return (rs485_send_line (argv[3]));
900 else if (strcmp (argv[2], "receive") == 0) {
901 timeout = simple_strtoul(argv[3], NULL, 10);
902 if (rs485_receive_chars (data, timeout) != 0) {
904 printf ("## nothing received\n");
909 printf ("%s\n", data);
913 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
914 return (1); /* unknown command, return error */
918 static int rs485_send_line (const char *data)
921 trab_rs485_enable_tx ();
929 static int rs485_receive_chars (char *data, int timeout)
932 int receive_count = 0;
935 trab_rs485_enable_rx ();
937 /* test every 1 ms for received characters to avoid a receive FIFO
938 * overrun (@ 38.400 Baud) */
939 for (i = 0; i < (timeout * 1000); i++) {
940 while (rs485_tstc ()) {
941 if (receive_count >= RS485_MAX_RECEIVE_BUF_LEN-1)
943 *data++ = rs485_getc ();
946 udelay (1000); /* pause 1 ms */
948 *data = '\0'; /* terminate string */
950 if (receive_count == 0)
957 int do_serial_number (char **argv)
959 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
960 unsigned int serial_number;
962 if (strcmp (argv[2], "read") == 0) {
963 if (i2c_read (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
964 (char *)&serial_number, 4)) {
965 printf ("could not read from eeprom\n");
969 printf ("%08d\n", serial_number);
972 else if (strcmp (argv[2], "write") == 0) {
973 serial_number = simple_strtoul(argv[3], NULL, 10);
974 if (i2c_write (I2C_EEPROM_DEV_ADDR, SERIAL_NUMBER, 1,
975 (char *)&serial_number, 4)) {
976 printf ("could not write to eeprom\n");
981 printf ("%s: unknown command %s\n", __FUNCTION__, argv[2]);
982 return (1); /* unknown command, return error */
984 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
987 #endif /* CFG_CMD_I2C */
993 #if (CONFIG_COMMANDS & CFG_CMD_I2C)
995 char buf[EEPROM_MAX_CRC_BUF];
997 if (i2c_read (I2C_EEPROM_DEV_ADDR, 0, 1, buf, 60)) {
998 printf ("could not read from eeprom\n");
1001 crc = 0; /* start value of crc calculation */
1002 crc = updcrc (crc, buf, 60);
1004 print_identifier ();
1005 printf ("crc16=%#04x\n", crc);
1007 if (i2c_write (I2C_EEPROM_DEV_ADDR, CRC16, 1, (char *)&crc,
1009 printf ("could not read from eeprom\n");
1014 printf ("No I2C support enabled (CFG_CMD_I2C), could not write "
1017 #endif /* CFG_CMD_I2C */
1022 * Calculate, intelligently, the CRC of a dataset incrementally given a
1023 * buffer full at a time.
1024 * Initialize crc to 0 for XMODEM, -1 for CCITT.
1027 * newcrc = updcrc( oldcrc, bufadr, buflen )
1028 * unsigned int oldcrc, buflen;
1031 * Compile with -DTEST to generate program that prints CRC of stdin to stdout.
1032 * Compile with -DMAKETAB to print values for crctab to stdout
1035 /* the CRC polynomial. This is used by XMODEM (almost CCITT).
1036 * If you change P, you must change crctab[]'s initial value to what is
1037 * printed by initcrctab()
1041 /* number of bits in CRC: don't change it. */
1044 /* this the number of bits per char: don't change it. */
1047 static unsigned short crctab[1<<B] = { /* as calculated by initcrctab() */
1048 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
1049 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
1050 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
1051 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
1052 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
1053 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
1054 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
1055 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
1056 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
1057 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
1058 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
1059 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
1060 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
1061 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
1062 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
1063 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
1064 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
1065 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
1066 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
1067 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
1068 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
1069 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
1070 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
1071 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
1072 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
1073 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
1074 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
1075 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
1076 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
1077 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
1078 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
1079 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
1082 static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
1085 register unsigned short crc = icrc;
1086 register unsigned char *cp = icp;
1087 register unsigned int cnt = icnt;
1090 crc = (crc<<B) ^ crctab[(crc>>(W-B)) ^ *cp++];