uboot/drivers/i2c/s3c24x0_i2c.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
   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/* This code should work for both the S3C2400 and the S3C2410
  25 * as they seem to have the same I2C controller inside.
  26 * The different address mapping is handled by the s3c24xx.h files below.
  27 */
  28
  29#include <common.h>
  30#include <asm/arch/s3c24x0_cpu.h>
  31
  32#include <asm/io.h>
  33#include <i2c.h>
  34
  35#ifdef CONFIG_HARD_I2C
  36
  37#define I2C_WRITE       0
  38#define I2C_READ        1
  39
  40#define I2C_OK          0
  41#define I2C_NOK         1
  42#define I2C_NACK        2
  43#define I2C_NOK_LA      3       /* Lost arbitration */
  44#define I2C_NOK_TOUT    4       /* time out */
  45
  46#define I2CSTAT_BSY     0x20    /* Busy bit */
  47#define I2CSTAT_NACK    0x01    /* Nack bit */
  48#define I2CCON_IRPND    0x10    /* Interrupt pending bit */
  49#define I2C_MODE_MT     0xC0    /* Master Transmit Mode */
  50#define I2C_MODE_MR     0x80    /* Master Receive Mode */
  51#define I2C_START_STOP  0x20    /* START / STOP */
  52#define I2C_TXRX_ENA    0x10    /* I2C Tx/Rx enable */
  53
  54#define I2C_TIMEOUT 1           /* 1 second */
  55
  56static int GetI2CSDA(void)
  57{
  58        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
  59
  60#ifdef CONFIG_S3C2410
  61        return (readl(&gpio->gpedat) & 0x8000) >> 15;
  62#endif
  63#ifdef CONFIG_S3C2400
  64        return (readl(&gpio->pgdat) & 0x0020) >> 5;
  65#endif
  66}
  67
  68#if 0
  69static void SetI2CSDA(int x)
  70{
  71        rGPEDAT = (rGPEDAT & ~0x8000) | (x & 1) << 15;
  72}
  73#endif
  74
  75static void SetI2CSCL(int x)
  76{
  77        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
  78
  79#ifdef CONFIG_S3C2410
  80        writel((readl(&gpio->gpedat) & ~0x4000) | (x & 1) << 14, &gpio->gpedat);
  81#endif
  82#ifdef CONFIG_S3C2400
  83        writel((readl(&gpio->pgdat) & ~0x0040) | (x & 1) << 6, &gpio->pgdat);
  84#endif
  85}
  86
  87static int WaitForXfer(void)
  88{
  89        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
  90        int i;
  91
  92        i = I2C_TIMEOUT * 10000;
  93        while (!(readl(&i2c->iiccon) & I2CCON_IRPND) && (i > 0)) {
  94                udelay(100);
  95                i--;
  96        }
  97
  98        return (readl(&i2c->iiccon) & I2CCON_IRPND) ? I2C_OK : I2C_NOK_TOUT;
  99}
 100
 101static int IsACK(void)
 102{
 103        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 104
 105        return !(readl(&i2c->iicstat) & I2CSTAT_NACK);
 106}
 107
 108static void ReadWriteByte(void)
 109{
 110        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 111
 112        writel(readl(&i2c->iiccon) & ~I2CCON_IRPND, &i2c->iiccon);
 113}
 114
 115void i2c_init(int speed, int slaveadd)
 116{
 117        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 118        struct s3c24x0_gpio *gpio = s3c24x0_get_base_gpio();
 119        ulong freq, pres = 16, div;
 120        int i;
 121
 122        /* wait for some time to give previous transfer a chance to finish */
 123
 124        i = I2C_TIMEOUT * 1000;
 125        while ((readl(&i2c->iicstat) && I2CSTAT_BSY) && (i > 0)) {
 126                udelay(1000);
 127                i--;
 128        }
 129
 130        if ((readl(&i2c->iicstat) & I2CSTAT_BSY) || GetI2CSDA() == 0) {
 131#ifdef CONFIG_S3C2410
 132                ulong old_gpecon = readl(&gpio->gpecon);
 133#endif
 134#ifdef CONFIG_S3C2400
 135                ulong old_gpecon = readl(&gpio->pgcon);
 136#endif
 137                /* bus still busy probably by (most) previously interrupted
 138                   transfer */
 139
 140#ifdef CONFIG_S3C2410
 141                /* set I2CSDA and I2CSCL (GPE15, GPE14) to GPIO */
 142                writel((readl(&gpio->gpecon) & ~0xF0000000) | 0x10000000,
 143                       &gpio->gpecon);
 144#endif
 145#ifdef CONFIG_S3C2400
 146                /* set I2CSDA and I2CSCL (PG5, PG6) to GPIO */
 147                writel((readl(&gpio->pgcon) & ~0x00003c00) | 0x00001000,
 148                       &gpio->pgcon);
 149#endif
 150
 151                /* toggle I2CSCL until bus idle */
 152                SetI2CSCL(0);
 153                udelay(1000);
 154                i = 10;
 155                while ((i > 0) && (GetI2CSDA() != 1)) {
 156                        SetI2CSCL(1);
 157                        udelay(1000);
 158                        SetI2CSCL(0);
 159                        udelay(1000);
 160                        i--;
 161                }
 162                SetI2CSCL(1);
 163                udelay(1000);
 164
 165                /* restore pin functions */
 166#ifdef CONFIG_S3C2410
 167                writel(old_gpecon, &gpio->gpecon);
 168#endif
 169#ifdef CONFIG_S3C2400
 170                writel(old_gpecon, &gpio->pgcon);
 171#endif
 172        }
 173
 174        /* calculate prescaler and divisor values */
 175        freq = get_PCLK();
 176        if ((freq / pres / (16 + 1)) > speed)
 177                /* set prescaler to 512 */
 178                pres = 512;
 179
 180        div = 0;
 181        while ((freq / pres / (div + 1)) > speed)
 182                div++;
 183
 184        /* set prescaler, divisor according to freq, also set
 185         * ACKGEN, IRQ */
 186        writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
 187
 188        /* init to SLAVE REVEIVE and set slaveaddr */
 189        writel(0, &i2c->iicstat);
 190        writel(slaveadd, &i2c->iicadd);
 191        /* program Master Transmit (and implicit STOP) */
 192        writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
 193
 194}
 195
 196/*
 197 * cmd_type is 0 for write, 1 for read.
 198 *
 199 * addr_len can take any value from 0-255, it is only limited
 200 * by the char, we could make it larger if needed. If it is
 201 * 0 we skip the address write cycle.
 202 */
 203static
 204int i2c_transfer(unsigned char cmd_type,
 205                 unsigned char chip,
 206                 unsigned char addr[],
 207                 unsigned char addr_len,
 208                 unsigned char data[], unsigned short data_len)
 209{
 210        struct s3c24x0_i2c *i2c = s3c24x0_get_base_i2c();
 211        int i, result;
 212
 213        if (data == 0 || data_len == 0) {
 214                /*Don't support data transfer of no length or to address 0 */
 215                printf("i2c_transfer: bad call\n");
 216                return I2C_NOK;
 217        }
 218
 219        /* Check I2C bus idle */
 220        i = I2C_TIMEOUT * 1000;
 221        while ((readl(&i2c->iicstat) & I2CSTAT_BSY) && (i > 0)) {
 222                udelay(1000);
 223                i--;
 224        }
 225
 226        if (readl(&i2c->iicstat) & I2CSTAT_BSY)
 227                return I2C_NOK_TOUT;
 228
 229        writel(readl(&i2c->iiccon) | 0x80, &i2c->iiccon);
 230        result = I2C_OK;
 231
 232        switch (cmd_type) {
 233        case I2C_WRITE:
 234                if (addr && addr_len) {
 235                        writel(chip, &i2c->iicds);
 236                        /* send START */
 237                        writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
 238                               &i2c->iicstat);
 239                        i = 0;
 240                        while ((i < addr_len) && (result == I2C_OK)) {
 241                                result = WaitForXfer();
 242                                writel(addr[i], &i2c->iicds);
 243                                ReadWriteByte();
 244                                i++;
 245                        }
 246                        i = 0;
 247                        while ((i < data_len) && (result == I2C_OK)) {
 248                                result = WaitForXfer();
 249                                writel(data[i], &i2c->iicds);
 250                                ReadWriteByte();
 251                                i++;
 252                        }
 253                } else {
 254                        writel(chip, &i2c->iicds);
 255                        /* send START */
 256                        writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
 257                               &i2c->iicstat);
 258                        i = 0;
 259                        while ((i < data_len) && (result = I2C_OK)) {
 260                                result = WaitForXfer();
 261                                writel(data[i], &i2c->iicds);
 262                                ReadWriteByte();
 263                                i++;
 264                        }
 265                }
 266
 267                if (result == I2C_OK)
 268                        result = WaitForXfer();
 269
 270                /* send STOP */
 271                writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
 272                ReadWriteByte();
 273                break;
 274
 275        case I2C_READ:
 276                if (addr && addr_len) {
 277                        writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
 278                        writel(chip, &i2c->iicds);
 279                        /* send START */
 280                        writel(readl(&i2c->iicstat) | I2C_START_STOP,
 281                               &i2c->iicstat);
 282                        result = WaitForXfer();
 283                        if (IsACK()) {
 284                                i = 0;
 285                                while ((i < addr_len) && (result == I2C_OK)) {
 286                                        writel(addr[i], &i2c->iicds);
 287                                        ReadWriteByte();
 288                                        result = WaitForXfer();
 289                                        i++;
 290                                }
 291
 292                                writel(chip, &i2c->iicds);
 293                                /* resend START */
 294                                writel(I2C_MODE_MR | I2C_TXRX_ENA |
 295                                       I2C_START_STOP, &i2c->iicstat);
 296                                ReadWriteByte();
 297                                result = WaitForXfer();
 298                                i = 0;
 299                                while ((i < data_len) && (result == I2C_OK)) {
 300                                        /* disable ACK for final READ */
 301                                        if (i == data_len - 1)
 302                                                writel(readl(&i2c->iiccon)
 303                                                       & ~0x80, &i2c->iiccon);
 304                                        ReadWriteByte();
 305                                        result = WaitForXfer();
 306                                        data[i] = readl(&i2c->iicds);
 307                                        i++;
 308                                }
 309                        } else {
 310                                result = I2C_NACK;
 311                        }
 312
 313                } else {
 314                        writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
 315                        writel(chip, &i2c->iicds);
 316                        /* send START */
 317                        writel(readl(&i2c->iicstat) | I2C_START_STOP,
 318                               &i2c->iicstat);
 319                        result = WaitForXfer();
 320
 321                        if (IsACK()) {
 322                                i = 0;
 323                                while ((i < data_len) && (result == I2C_OK)) {
 324                                        /* disable ACK for final READ */
 325                                        if (i == data_len - 1)
 326                                                writel(readl(&i2c->iiccon) &
 327                                                       ~0x80, &i2c->iiccon);
 328                                        ReadWriteByte();
 329                                        result = WaitForXfer();
 330                                        data[i] = readl(&i2c->iicds);
 331                                        i++;
 332                                }
 333                        } else {
 334                                result = I2C_NACK;
 335                        }
 336                }
 337
 338                /* send STOP */
 339                writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
 340                ReadWriteByte();
 341                break;
 342
 343        default:
 344                printf("i2c_transfer: bad call\n");
 345                result = I2C_NOK;
 346                break;
 347        }
 348
 349        return (result);
 350}
 351
 352int i2c_probe(uchar chip)
 353{
 354        uchar buf[1];
 355
 356        buf[0] = 0;
 357
 358        /*
 359         * What is needed is to send the chip address and verify that the
 360         * address was <ACK>ed (i.e. there was a chip at that address which
 361         * drove the data line low).
 362         */
 363        return i2c_transfer(I2C_READ, chip << 1, 0, 0, buf, 1) != I2C_OK;
 364}
 365
 366int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 367{
 368        uchar xaddr[4];
 369        int ret;
 370
 371        if (alen > 4) {
 372                printf("I2C read: addr len %d not supported\n", alen);
 373                return 1;
 374        }
 375
 376        if (alen > 0) {
 377                xaddr[0] = (addr >> 24) & 0xFF;
 378                xaddr[1] = (addr >> 16) & 0xFF;
 379                xaddr[2] = (addr >> 8) & 0xFF;
 380                xaddr[3] = addr & 0xFF;
 381        }
 382
 383#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
 384        /*
 385         * EEPROM chips that implement "address overflow" are ones
 386         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
 387         * address and the extra bits end up in the "chip address"
 388         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
 389         * four 256 byte chips.
 390         *
 391         * Note that we consider the length of the address field to
 392         * still be one byte because the extra address bits are
 393         * hidden in the chip address.
 394         */
 395        if (alen > 0)
 396                chip |= ((addr >> (alen * 8)) &
 397                         CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 398#endif
 399        if ((ret =
 400             i2c_transfer(I2C_READ, chip << 1, &xaddr[4 - alen], alen,
 401                          buffer, len)) != 0) {
 402                printf("I2c read: failed %d\n", ret);
 403                return 1;
 404        }
 405        return 0;
 406}
 407
 408int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 409{
 410        uchar xaddr[4];
 411
 412        if (alen > 4) {
 413                printf("I2C write: addr len %d not supported\n", alen);
 414                return 1;
 415        }
 416
 417        if (alen > 0) {
 418                xaddr[0] = (addr >> 24) & 0xFF;
 419                xaddr[1] = (addr >> 16) & 0xFF;
 420                xaddr[2] = (addr >> 8) & 0xFF;
 421                xaddr[3] = addr & 0xFF;
 422        }
 423#ifdef CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW
 424        /*
 425         * EEPROM chips that implement "address overflow" are ones
 426         * like Catalyst 24WC04/08/16 which has 9/10/11 bits of
 427         * address and the extra bits end up in the "chip address"
 428         * bit slots. This makes a 24WC08 (1Kbyte) chip look like
 429         * four 256 byte chips.
 430         *
 431         * Note that we consider the length of the address field to
 432         * still be one byte because the extra address bits are
 433         * hidden in the chip address.
 434         */
 435        if (alen > 0)
 436                chip |= ((addr >> (alen * 8)) &
 437                         CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW);
 438#endif
 439        return (i2c_transfer
 440                (I2C_WRITE, chip << 1, &xaddr[4 - alen], alen, buffer,
 441                 len) != 0);
 442}
 443#endif /* CONFIG_HARD_I2C */
 444