uboot/board/Marvell/common/i2c.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2000
   3 * Wolfgang Denk, DENX Software Engineering, wd@denx.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 * Hacked for the DB64360 board by Ingo.Assmus@keymile.com
  24 * extra improvments by Brain Waite
  25 */
  26#include <common.h>
  27#include <mpc8xx.h>
  28#include <malloc.h>
  29#include <i2c.h>
  30#include "../include/mv_gen_reg.h"
  31#include "../include/core.h"
  32
  33#define MAX_I2C_RETRYS      10
  34#define I2C_DELAY           1000        /* Should be at least the # of MHz of Tclk */
  35#undef  DEBUG_I2C
  36/*#define DEBUG_I2C*/
  37
  38#ifdef DEBUG_I2C
  39#define DP(x) x
  40#else
  41#define DP(x)
  42#endif
  43
  44/* Assuming that there is only one master on the bus (us) */
  45
  46void i2c_init (int speed, int slaveaddr)
  47{
  48        unsigned int n, m, freq, margin, power;
  49        unsigned int actualN = 0, actualM = 0;
  50        unsigned int control, status;
  51        unsigned int minMargin = 0xffffffff;
  52        unsigned int tclk = CONFIG_SYS_TCLK;
  53        unsigned int i2cFreq = speed;   /* 100000 max. Fast mode not supported */
  54
  55        DP (puts ("i2c_init\n"));
  56/* gtI2cMasterInit */
  57        for (n = 0; n < 8; n++) {
  58                for (m = 0; m < 16; m++) {
  59                        power = 2 << n; /* power = 2^(n+1) */
  60                        freq = tclk / (10 * (m + 1) * power);
  61                        if (i2cFreq > freq)
  62                                margin = i2cFreq - freq;
  63                        else
  64                                margin = freq - i2cFreq;
  65                        if (margin < minMargin) {
  66                                minMargin = margin;
  67                                actualN = n;
  68                                actualM = m;
  69                        }
  70                }
  71        }
  72
  73        DP (puts ("setup i2c bus\n"));
  74
  75        /* Setup bus */
  76/* gtI2cReset */
  77        GT_REG_WRITE (I2C_SOFT_RESET, 0);
  78
  79        DP (puts ("udelay...\n"));
  80
  81        udelay (I2C_DELAY);
  82
  83        DP (puts ("set baudrate\n"));
  84
  85        GT_REG_WRITE (I2C_STATUS_BAUDE_RATE, (actualM << 3) | actualN);
  86        GT_REG_WRITE (I2C_CONTROL, (0x1 << 2) | (0x1 << 6));
  87
  88        udelay (I2C_DELAY * 10);
  89
  90        DP (puts ("read control, baudrate\n"));
  91
  92        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
  93        GT_REG_READ (I2C_CONTROL, &control);
  94}
  95
  96static uchar i2c_start (void)
  97{                               /* DB64360 checked -> ok */
  98        unsigned int control, status;
  99        int count = 0;
 100
 101        DP (puts ("i2c_start\n"));
 102
 103        /* Set the start bit */
 104
 105/* gtI2cGenerateStartBit() */
 106
 107        GT_REG_READ (I2C_CONTROL, &control);
 108        control |= (0x1 << 5);  /* generate the I2C_START_BIT */
 109        GT_REG_WRITE (I2C_CONTROL, control);
 110
 111        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 112
 113        count = 0;
 114        while ((status & 0xff) != 0x08) {
 115                udelay (I2C_DELAY);
 116                if (count > 20) {
 117                        GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 118                        return (status);
 119                }
 120                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 121                count++;
 122        }
 123
 124        return (0);
 125}
 126
 127static uchar i2c_select_device (uchar dev_addr, uchar read, int ten_bit)
 128{
 129        unsigned int status, data, bits = 7;
 130        int count = 0;
 131
 132        DP (puts ("i2c_select_device\n"));
 133
 134        /* Output slave address */
 135
 136        if (ten_bit) {
 137                bits = 10;
 138        }
 139
 140        data = (dev_addr << 1);
 141        /* set the read bit */
 142        data |= read;
 143        GT_REG_WRITE (I2C_DATA, data);
 144        /* assert the address */
 145        RESET_REG_BITS (I2C_CONTROL, BIT3);
 146
 147        udelay (I2C_DELAY);
 148
 149        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 150        count = 0;
 151        while (((status & 0xff) != 0x40) && ((status & 0xff) != 0x18)) {
 152                udelay (I2C_DELAY);
 153                if (count > 20) {
 154                        GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 155                        return (status);
 156                }
 157                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 158                count++;
 159        }
 160
 161        if (bits == 10) {
 162                printf ("10 bit I2C addressing not yet implemented\n");
 163                return (0xff);
 164        }
 165
 166        return (0);
 167}
 168
 169static uchar i2c_get_data (uchar * return_data, int len)
 170{
 171
 172        unsigned int data, status = 0;
 173        int count = 0;
 174
 175        DP (puts ("i2c_get_data\n"));
 176
 177        while (len) {
 178
 179                /* Get and return the data */
 180
 181                RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
 182
 183                udelay (I2C_DELAY * 5);
 184
 185                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 186                count++;
 187                while ((status & 0xff) != 0x50) {
 188                        udelay (I2C_DELAY);
 189                        if (count > 2) {
 190                                GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 191                                return 0;
 192                        }
 193                        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 194                        count++;
 195                }
 196                GT_REG_READ (I2C_DATA, &data);
 197                len--;
 198                *return_data = (uchar) data;
 199                return_data++;
 200        }
 201        RESET_REG_BITS (I2C_CONTROL, BIT2 | BIT3);
 202        while ((status & 0xff) != 0x58) {
 203                udelay (I2C_DELAY);
 204                if (count > 200) {
 205                        GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 206                        return (status);
 207                }
 208                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 209                count++;
 210        }
 211        GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /* stop */
 212
 213        return (0);
 214}
 215
 216static uchar i2c_write_data (unsigned int *data, int len)
 217{
 218        unsigned int status;
 219        int count = 0;
 220        unsigned int temp;
 221        unsigned int *temp_ptr = data;
 222
 223        DP (puts ("i2c_write_data\n"));
 224
 225        while (len) {
 226                temp = (unsigned int) (*temp_ptr);
 227                GT_REG_WRITE (I2C_DATA, temp);
 228                RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
 229
 230                udelay (I2C_DELAY);
 231
 232                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 233                count++;
 234                while ((status & 0xff) != 0x28) {
 235                        udelay (I2C_DELAY);
 236                        if (count > 20) {
 237                                GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 238                                return (status);
 239                        }
 240                        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 241                        count++;
 242                }
 243                len--;
 244                temp_ptr++;
 245        }
 246/* 11-14-2002 Paul Marchese */
 247/* Can't have the write issuing a stop command */
 248/* it's wrong to have a stop bit in read stream or write stream */
 249/* since we don't know if it's really the end of the command */
 250/* or whether we have just send the device address + offset */
 251/* we will push issuing the stop command off to the original */
 252/* calling function */
 253        /* set the interrupt bit in the control register */
 254        GT_REG_WRITE (I2C_CONTROL, (0x1 << 3));
 255        udelay (I2C_DELAY * 10);
 256        return (0);
 257}
 258
 259/* 11-14-2002 Paul Marchese */
 260/* created this function to get the i2c_write() */
 261/* function working properly. */
 262/* function to write bytes out on the i2c bus */
 263/* this is identical to the function i2c_write_data() */
 264/* except that it requires a buffer that is an */
 265/* unsigned character array.  You can't use */
 266/* i2c_write_data() to send an array of unsigned characters */
 267/* since the byte of interest ends up on the wrong end of the bus */
 268/* aah, the joys of big endian versus little endian! */
 269/* */
 270/* returns 0 = success */
 271/*         anything other than zero is failure */
 272static uchar i2c_write_byte (unsigned char *data, int len)
 273{
 274        unsigned int status;
 275        int count = 0;
 276        unsigned int temp;
 277        unsigned char *temp_ptr = data;
 278
 279        DP (puts ("i2c_write_byte\n"));
 280
 281        while (len) {
 282                /* Set and assert the data */
 283                temp = *temp_ptr;
 284                GT_REG_WRITE (I2C_DATA, temp);
 285                RESET_REG_BITS (I2C_CONTROL, (0x1 << 3));
 286
 287                udelay (I2C_DELAY);
 288
 289                GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 290                count++;
 291                while ((status & 0xff) != 0x28) {
 292                        udelay (I2C_DELAY);
 293                        if (count > 20) {
 294                                GT_REG_WRITE (I2C_CONTROL, (0x1 << 4)); /*stop */
 295                                return (status);
 296                        }
 297                        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &status);
 298                        count++;
 299                }
 300                len--;
 301                temp_ptr++;
 302        }
 303/* Can't have the write issuing a stop command */
 304/* it's wrong to have a stop bit in read stream or write stream */
 305/* since we don't know if it's really the end of the command */
 306/* or whether we have just send the device address + offset */
 307/* we will push issuing the stop command off to the original */
 308/* calling function */
 309/*      GT_REG_WRITE(I2C_CONTROL, (0x1 << 3) | (0x1 << 4));
 310        GT_REG_WRITE(I2C_CONTROL, (0x1 << 4)); */
 311        /* set the interrupt bit in the control register */
 312        GT_REG_WRITE (I2C_CONTROL, (0x1 << 3));
 313        udelay (I2C_DELAY * 10);
 314
 315        return (0);
 316}
 317
 318static uchar
 319i2c_set_dev_offset (uchar dev_addr, unsigned int offset, int ten_bit,
 320                    int alen)
 321{
 322        uchar status;
 323        unsigned int table[2];
 324
 325/* initialize the table of address offset bytes */
 326/* utilized for 2 byte address offsets */
 327/* NOTE: the order is high byte first! */
 328        table[1] = offset & 0xff;       /* low byte */
 329        table[0] = offset / 0x100;      /* high byte */
 330
 331        DP (puts ("i2c_set_dev_offset\n"));
 332
 333        status = i2c_select_device (dev_addr, 0, ten_bit);
 334        if (status) {
 335#ifdef DEBUG_I2C
 336                printf ("Failed to select device setting offset: 0x%02x\n",
 337                        status);
 338#endif
 339                return status;
 340        }
 341/* check the address offset length */
 342        if (alen == 0)
 343                /* no address offset */
 344                return (0);
 345        else if (alen == 1) {
 346                /* 1 byte address offset */
 347                status = i2c_write_data (&offset, 1);
 348                if (status) {
 349#ifdef DEBUG_I2C
 350                        printf ("Failed to write data: 0x%02x\n", status);
 351#endif
 352                        return status;
 353                }
 354        } else if (alen == 2) {
 355                /* 2 bytes address offset */
 356                status = i2c_write_data (table, 2);
 357                if (status) {
 358#ifdef DEBUG_I2C
 359                        printf ("Failed to write data: 0x%02x\n", status);
 360#endif
 361                        return status;
 362                }
 363        } else {
 364                /* address offset unknown or not supported */
 365                printf ("Address length offset %d is not supported\n", alen);
 366                return 1;
 367        }
 368        return 0;               /* sucessful completion */
 369}
 370
 371int
 372i2c_read (uchar dev_addr, unsigned int offset, int alen, uchar * data,
 373          int len)
 374{
 375        uchar status = 0;
 376        unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
 377
 378        DP (puts ("i2c_read\n"));
 379
 380        /* set the i2c frequency */
 381        i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
 382
 383        status = i2c_start ();
 384
 385        if (status) {
 386#ifdef DEBUG_I2C
 387                printf ("Transaction start failed: 0x%02x\n", status);
 388#endif
 389                return status;
 390        }
 391
 392        status = i2c_set_dev_offset (dev_addr, offset, 0, alen);        /* send the slave address + offset */
 393        if (status) {
 394#ifdef DEBUG_I2C
 395                printf ("Failed to set slave address & offset: 0x%02x\n",
 396                        status);
 397#endif
 398                return status;
 399        }
 400
 401        /* set the i2c frequency again */
 402        i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
 403
 404        status = i2c_start ();
 405        if (status) {
 406#ifdef DEBUG_I2C
 407                printf ("Transaction restart failed: 0x%02x\n", status);
 408#endif
 409                return status;
 410        }
 411
 412        status = i2c_select_device (dev_addr, 1, 0);    /* send the slave address */
 413        if (status) {
 414#ifdef DEBUG_I2C
 415                printf ("Address not acknowledged: 0x%02x\n", status);
 416#endif
 417                return status;
 418        }
 419
 420        status = i2c_get_data (data, len);
 421        if (status) {
 422#ifdef DEBUG_I2C
 423                printf ("Data not recieved: 0x%02x\n", status);
 424#endif
 425                return status;
 426        }
 427
 428        return 0;
 429}
 430
 431/* 11-14-2002 Paul Marchese */
 432/* Function to set the I2C stop bit */
 433void i2c_stop (void)
 434{
 435        GT_REG_WRITE (I2C_CONTROL, (0x1 << 4));
 436}
 437
 438/* 11-14-2002 Paul Marchese */
 439/* I2C write function */
 440/* dev_addr = device address */
 441/* offset = address offset */
 442/* alen = length in bytes of the address offset */
 443/* data = pointer to buffer to read data into */
 444/* len = # of bytes to read */
 445/* */
 446/* returns 0 = succesful */
 447/*         anything but zero is failure */
 448int
 449i2c_write (uchar dev_addr, unsigned int offset, int alen, uchar * data,
 450           int len)
 451{
 452        uchar status = 0;
 453        unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
 454
 455        DP (puts ("i2c_write\n"));
 456
 457        /* set the i2c frequency */
 458        i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
 459
 460        status = i2c_start ();  /* send a start bit */
 461
 462        if (status) {
 463#ifdef DEBUG_I2C
 464                printf ("Transaction start failed: 0x%02x\n", status);
 465#endif
 466                return status;
 467        }
 468
 469        status = i2c_set_dev_offset (dev_addr, offset, 0, alen);        /* send the slave address + offset */
 470        if (status) {
 471#ifdef DEBUG_I2C
 472                printf ("Failed to set slave address & offset: 0x%02x\n",
 473                        status);
 474#endif
 475                return status;
 476        }
 477
 478
 479        status = i2c_write_byte (data, len);    /* write the data */
 480        if (status) {
 481#ifdef DEBUG_I2C
 482                printf ("Data not written: 0x%02x\n", status);
 483#endif
 484                return status;
 485        }
 486        /* issue a stop bit */
 487        i2c_stop ();
 488        return 0;
 489}
 490
 491/* 11-14-2002 Paul Marchese */
 492/* function to determine if an I2C device is present */
 493/* chip = device address of chip to check for */
 494/* */
 495/* returns 0 = sucessful, the device exists */
 496/*         anything other than zero is failure, no device */
 497int i2c_probe (uchar chip)
 498{
 499
 500        /* We are just looking for an <ACK> back. */
 501        /* To see if the device/chip is there */
 502
 503#ifdef DEBUG_I2C
 504        unsigned int i2c_status;
 505#endif
 506        uchar status = 0;
 507        unsigned int i2cFreq = CONFIG_SYS_I2C_SPEED;
 508
 509        DP (puts ("i2c_probe\n"));
 510
 511        /* set the i2c frequency */
 512        i2c_init (i2cFreq, CONFIG_SYS_I2C_SLAVE);
 513
 514        status = i2c_start ();  /* send a start bit */
 515
 516        if (status) {
 517#ifdef DEBUG_I2C
 518                printf ("Transaction start failed: 0x%02x\n", status);
 519#endif
 520                return (int) status;
 521        }
 522
 523        status = i2c_set_dev_offset (chip, 0, 0, 0);    /* send the slave address + no offset */
 524        if (status) {
 525#ifdef DEBUG_I2C
 526                printf ("Failed to set slave address: 0x%02x\n", status);
 527#endif
 528                return (int) status;
 529        }
 530#ifdef DEBUG_I2C
 531        GT_REG_READ (I2C_STATUS_BAUDE_RATE, &i2c_status);
 532        printf ("address %#x returned %#x\n", chip, i2c_status);
 533#endif
 534        /* issue a stop bit */
 535        i2c_stop ();
 536        return 0;               /* successful completion */
 537}
 538