uboot/board/trab/trab_fkt.c
<<
>>
Prefs
   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 */
 108int do_dip (void);
 109int do_info (void);
 110int do_vcc5v (void);
 111int do_vcc12v (void);
 112int do_buttons (void);
 113int do_fill_level (void);
 114int do_rotary_switch (void);
 115int do_pressure (void);
 116int do_v_bat (void);
 117int do_vfd_id (void);
 118int do_buzzer (char **);
 119int do_led (char **);
 120int do_full_bridge (char **);
 121int do_dac (char **);
 122int do_motor_contact (void);
 123int do_motor (char **);
 124int do_pwm (char **);
 125int do_thermo (char **);
 126int do_touch (char **);
 127int do_rs485 (char **);
 128int do_serial_number (char **);
 129int do_crc16 (void);
 130int do_power_switch (void);
 131int do_gain (char **);
 132int do_eeprom (char **);
 133
 134/* helper functions */
 135static void adc_init (void);
 136static int adc_read (unsigned int channel);
 137static void print_identifier (void);
 138
 139#ifdef CONFIG_TOUCH_WAIT_PRESSED
 140static void touch_wait_pressed (void);
 141#else
 142static int touch_check_pressed (void);
 143#endif /* CONFIG_TOUCH_WAIT_PRESSED */
 144
 145static void touch_read_x_y (int *x, int *y);
 146static int touch_write_clibration_values (int calib_point, int x, int y);
 147static int rs485_send_line (const char *data);
 148static int rs485_receive_chars (char *data, int timeout);
 149static unsigned short updcrc(unsigned short icrc, unsigned char *icp,
 150                             unsigned int icnt);
 151
 152#if defined(CONFIG_CMD_I2C)
 153static int trab_eeprom_read (char **argv);
 154static int trab_eeprom_write (char **argv);
 155int i2c_write_multiple (uchar chip, uint addr, int alen, uchar *buffer,
 156                        int len);
 157int 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
 166int 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
 297void hang (void)
 298{
 299        puts ("### ERROR ### Please RESET the board ###\n");
 300        for (;;);
 301}
 302
 303int 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
 311int 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
 358int 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
 384int 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
 405static 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
 447static 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
 468int 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
 489int 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
 507int 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
 524int 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
 555int 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
 588int do_buzzer (char **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
 638int do_led (char **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
 693int do_full_bridge (char **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] */
 721static inline unsigned long tsc2000_to_uv (u16 val)
 722{
 723        return ((250000 * val) / 4096) * 10;
 724}
 725
 726
 727int do_dac (char **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
 746int 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
 770int 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
 786int 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
 802int do_motor (char **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
 822static void print_identifier (void)
 823{
 824        printf ("## FKT: ");
 825}
 826
 827int do_pwm (char **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
 872int 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
 895int 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
 955static void touch_wait_pressed (void)
 956{
 957        while (!(tsc2000_read(TSC2000_REG_ADC) & TC_PSM));
 958}
 959
 960#else
 961static int touch_check_pressed (void)
 962{
 963        return (tsc2000_read(TSC2000_REG_ADC) & TC_PSM);
 964}
 965#endif /* CONFIG_TOUCH_WAIT_PRESSED */
 966
 967static 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
1036static 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
1048int 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
1074static 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
1085static 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
1113int 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
1147int 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
1203static 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
1238static 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
1252int 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
1268int 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)
1289static 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
1334static 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
1370int 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
1398int 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
1419