uboot/drivers/i2c/s3c44b0_i2c.c
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2004
   3 * DAVE Srl
   4 * http://www.dave-tech.it
   5 * http://www.wawnet.biz
   6 * mailto:info@wawnet.biz
   7 *
   8 * See file CREDITS for list of people who contributed to this
   9 * project.
  10 *
  11 * This program is free software; you can redistribute it and/or
  12 * modify it under the terms of the GNU General Public License as
  13 * published by the Free Software Foundation; either version 2 of
  14 * the License, or (at your option) any later version.
  15 *
  16 * This program is distributed in the hope that it will be useful,
  17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19 * GNU General Public License for more details.
  20 *
  21 * You should have received a copy of the GNU General Public License
  22 * along with this program; if not, write to the Free Software
  23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  24 * MA 02111-1307 USA
  25 */
  26
  27#include <common.h>
  28#include <command.h>
  29#include <asm/hardware.h>
  30
  31/*
  32 * Initialization, must be called once on start up, may be called
  33 * repeatedly to change the speed and slave addresses.
  34 */
  35void i2c_init(int speed, int slaveaddr)
  36{
  37        /*
  38                setting up I2C support
  39        */
  40        unsigned int save_F,save_PF,rIICCON,rPCONA,rPDATA,rPCONF,rPUPF;
  41
  42        save_F = PCONF;
  43        save_PF = PUPF;
  44
  45        rPCONF = ((save_F & ~(0xF))| 0xa);
  46        rPUPF = (save_PF | 0x3);
  47        PCONF = rPCONF; /*PF0:IICSCL, PF1:IICSDA*/
  48        PUPF = rPUPF; /* Disable pull-up */
  49
  50        /* Configuring pin for WC pin of EEprom */
  51        rPCONA = PCONA;
  52        rPCONA &= ~(1<<9);
  53        PCONA = rPCONA;
  54
  55        rPDATA = PDATA;
  56        rPDATA &= ~(1<<9);
  57        PDATA = rPDATA;
  58
  59        /*
  60                Enable ACK, IICCLK=MCLK/16, enable interrupt
  61                75MHz/16/(12+1) = 390625 Hz
  62        */
  63        rIICCON=(1<<7)|(0<<6)|(1<<5)|(0xC);
  64        IICCON = rIICCON;
  65
  66        IICADD = slaveaddr;
  67}
  68
  69/*
  70 * Probe the given I2C chip address.  Returns 0 if a chip responded,
  71 * not 0 on failure.
  72 */
  73int i2c_probe(uchar chip)
  74{
  75        /*
  76                not implemented
  77        */
  78
  79        printf("i2c_probe chip %d\n", (int) chip);
  80        return -1;
  81}
  82
  83/*
  84 * Read/Write interface:
  85 *   chip:    I2C chip address, range 0..127
  86 *   addr:    Memory (register) address within the chip
  87 *   alen:    Number of bytes to use for addr (typically 1, 2 for larger
  88 *              memories, 0 for register type devices with only one
  89 *              register)
  90 *   buffer:  Where to read/write the data
  91 *   len:     How many bytes to read/write
  92 *
  93 *   Returns: 0 on success, not 0 on failure
  94 */
  95
  96#define S3C44B0X_rIIC_INTPEND               (1<<4)
  97#define S3C44B0X_rIIC_LAST_RECEIV_BIT       (1<<0)
  98#define S3C44B0X_rIIC_INTERRUPT_ENABLE      (1<<5)
  99#define S3C44B0_IIC_TIMEOUT 100
 100
 101int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 102{
 103
 104        int k, j, temp;
 105        u32 rIICSTAT;
 106
 107        /*
 108                send the device offset
 109        */
 110
 111        rIICSTAT = 0xD0;
 112        IICSTAT = rIICSTAT;
 113
 114        IICDS = chip;   /* this is a write operation... */
 115
 116        rIICSTAT |= (1<<5);
 117        IICSTAT = rIICSTAT;
 118
 119        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 120                temp = IICCON;
 121                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 122                break;
 123                udelay(2000);
 124        }
 125        if (k==S3C44B0_IIC_TIMEOUT)
 126                return -1;
 127
 128        /* wait and check ACK */
 129        temp = IICSTAT;
 130        if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
 131                return -1;
 132
 133        IICDS = addr;
 134        IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 135
 136        /* wait and check ACK */
 137        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 138                temp = IICCON;
 139                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 140                break;
 141                udelay(2000);
 142        }
 143        if (k==S3C44B0_IIC_TIMEOUT)
 144                return -1;
 145
 146        temp = IICSTAT;
 147        if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
 148                return -1;
 149
 150        /*
 151                now we can start with the read operation...
 152        */
 153
 154        IICDS = chip | 0x01;    /* this is a read operation... */
 155
 156        rIICSTAT = 0x90; /*master recv*/
 157        rIICSTAT |= (1<<5);
 158        IICSTAT = rIICSTAT;
 159
 160        IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 161
 162        /* wait and check ACK */
 163        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 164                temp = IICCON;
 165                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 166                break;
 167                udelay(2000);
 168        }
 169        if (k==S3C44B0_IIC_TIMEOUT)
 170                return -1;
 171
 172        temp = IICSTAT;
 173        if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
 174                return -1;
 175
 176        for (j=0; j<len-1; j++) {
 177
 178        /*clear pending bit to resume */
 179
 180        temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 181        IICCON = temp;
 182
 183        /* wait and check ACK */
 184        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 185                temp = IICCON;
 186                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 187                break;
 188                udelay(2000);
 189        }
 190        if (k==S3C44B0_IIC_TIMEOUT)
 191                return -1;
 192
 193
 194                buffer[j] = IICDS; /*save readed data*/
 195
 196    } /*end for(j)*/
 197
 198        /*
 199                reading the last data
 200                unset ACK generation
 201        */
 202        temp = IICCON & ~(S3C44B0X_rIIC_INTPEND | (1<<7));
 203        IICCON = temp;
 204
 205        /* wait but NOT check ACK */
 206        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 207                temp = IICCON;
 208                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 209                break;
 210                udelay(2000);
 211        }
 212        if (k==S3C44B0_IIC_TIMEOUT)
 213                return -1;
 214
 215        buffer[j] = IICDS; /*save readed data*/
 216
 217        rIICSTAT = 0x90; /*master recv*/
 218
 219        /* Write operation Terminate sending STOP */
 220        IICSTAT = rIICSTAT;
 221        /*Clear Int Pending Bit to RESUME*/
 222        temp = IICCON;
 223        IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
 224
 225        IICCON = IICCON | (1<<7);       /*restore ACK generation*/
 226
 227        return 0;
 228}
 229
 230int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 231{
 232        int j, k;
 233        u32 rIICSTAT, temp;
 234
 235
 236        /*
 237                send the device offset
 238        */
 239
 240        rIICSTAT = 0xD0;
 241        IICSTAT = rIICSTAT;
 242
 243        IICDS = chip;   /* this is a write operation... */
 244
 245        rIICSTAT |= (1<<5);
 246        IICSTAT = rIICSTAT;
 247
 248        IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 249
 250        /* wait and check ACK */
 251        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 252                temp = IICCON;
 253                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 254                break;
 255                udelay(2000);
 256        }
 257        if (k==S3C44B0_IIC_TIMEOUT)
 258                return -1;
 259
 260        temp = IICSTAT;
 261        if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
 262                return -1;
 263
 264        IICDS = addr;
 265        IICCON = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 266
 267        /* wait and check ACK */
 268        for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 269                temp = IICCON;
 270                if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 271                break;
 272                udelay(2000);
 273        }
 274        if (k==S3C44B0_IIC_TIMEOUT)
 275          return -1;
 276
 277        temp = IICSTAT;
 278        if ((temp & S3C44B0X_rIIC_LAST_RECEIV_BIT) == S3C44B0X_rIIC_LAST_RECEIV_BIT )
 279                return -1;
 280
 281        /*
 282                now we can start with the read write operation
 283        */
 284        for (j=0; j<len; j++) {
 285
 286                IICDS = buffer[j]; /*prerare data to write*/
 287
 288                /*clear pending bit to resume*/
 289
 290                temp = IICCON & ~(S3C44B0X_rIIC_INTPEND);
 291                IICCON = temp;
 292
 293                /* wait but NOT check ACK */
 294                for(k=0; k<S3C44B0_IIC_TIMEOUT; k++) {
 295                        temp = IICCON;
 296                        if( (temp & S3C44B0X_rIIC_INTPEND) == S3C44B0X_rIIC_INTPEND)
 297                        break;
 298
 299                        udelay(2000);
 300                }
 301
 302                if (k==S3C44B0_IIC_TIMEOUT)
 303                        return -1;
 304
 305        } /* end for(j) */
 306
 307        /* sending stop to terminate */
 308        rIICSTAT = 0xD0;  /*master send*/
 309        IICSTAT = rIICSTAT;
 310        /*Clear Int Pending Bit to RESUME*/
 311        temp = IICCON;
 312        IICCON = temp & (~S3C44B0X_rIIC_INTPEND);
 313
 314        return 0;
 315}
 316