uboot/drivers/i2c/omap1510_i2c.c
<<
>>
Prefs
   1/*
   2 * Basic I2C functions
   3 *
   4 * Copyright (c) 2003 Texas Instruments
   5 *
   6 * This package is free software;  you can redistribute it and/or
   7 * modify it under the terms of the license found in the file
   8 * named COPYING that should have accompanied this file.
   9 *
  10 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  11 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  12 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  13 *
  14 * Author: Jian Zhang jzhang@ti.com, Texas Instruments
  15 *
  16 * Copyright (c) 2003 Wolfgang Denk, wd@denx.de
  17 * Rewritten to fit into the current U-Boot framework
  18 *
  19 */
  20
  21#include <common.h>
  22
  23static void wait_for_bb (void);
  24static u16 wait_for_pin (void);
  25
  26void i2c_init (int speed, int slaveadd)
  27{
  28        u16 scl;
  29
  30        if (inw (I2C_CON) & I2C_CON_EN) {
  31                outw (0, I2C_CON);
  32                udelay (5000);
  33        }
  34
  35        /* 12MHz I2C module clock */
  36        outw (0, I2C_PSC);
  37        outw (I2C_CON_EN, I2C_CON);
  38        outw (0, I2C_SYSTEST);
  39        /* have to enable intrrupts or OMAP i2c module doesn't work */
  40        outw (I2C_IE_XRDY_IE | I2C_IE_RRDY_IE | I2C_IE_ARDY_IE |
  41              I2C_IE_NACK_IE | I2C_IE_AL_IE, I2C_IE);
  42        scl = (12000000 / 2) / speed - 6;
  43        outw (scl, I2C_SCLL);
  44        outw (scl, I2C_SCLH);
  45        /* own address */
  46        outw (slaveadd, I2C_OA);
  47        outw (0, I2C_CNT);
  48        udelay (1000);
  49}
  50
  51static int i2c_read_byte (u8 devaddr, u8 regoffset, u8 * value)
  52{
  53        int i2c_error = 0;
  54        u16 status;
  55
  56        /* wait until bus not busy */
  57        wait_for_bb ();
  58
  59        /* one byte only */
  60        outw (1, I2C_CNT);
  61        /* set slave address */
  62        outw (devaddr, I2C_SA);
  63        /* no stop bit needed here */
  64        outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX, I2C_CON);
  65
  66        status = wait_for_pin ();
  67
  68        if (status & I2C_STAT_XRDY) {
  69                /* Important: have to use byte access */
  70                *(volatile u8 *) (I2C_DATA) = regoffset;
  71                udelay (20000);
  72                if (inw (I2C_STAT) & I2C_STAT_NACK) {
  73                        i2c_error = 1;
  74                }
  75        } else {
  76                i2c_error = 1;
  77        }
  78
  79        if (!i2c_error) {
  80                /* free bus, otherwise we can't use a combined transction */
  81                outw (0, I2C_CON);
  82                while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
  83                        udelay (10000);
  84                        /* Have to clear pending interrupt to clear I2C_STAT */
  85                        inw (I2C_IV);
  86                }
  87
  88                wait_for_bb ();
  89                /* set slave address */
  90                outw (devaddr, I2C_SA);
  91                /* read one byte from slave */
  92                outw (1, I2C_CNT);
  93                /* need stop bit here */
  94                outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP,
  95                      I2C_CON);
  96
  97                status = wait_for_pin ();
  98                if (status & I2C_STAT_RRDY) {
  99                        *value = inw (I2C_DATA);
 100                        udelay (20000);
 101                } else {
 102                        i2c_error = 1;
 103                }
 104
 105                if (!i2c_error) {
 106                        outw (I2C_CON_EN, I2C_CON);
 107                        while (inw (I2C_STAT)
 108                               || (inw (I2C_CON) & I2C_CON_MST)) {
 109                                udelay (10000);
 110                                inw (I2C_IV);
 111                        }
 112                }
 113        }
 114
 115        return i2c_error;
 116}
 117
 118static int i2c_write_byte (u8 devaddr, u8 regoffset, u8 value)
 119{
 120        int i2c_error = 0;
 121        u16 status;
 122
 123        /* wait until bus not busy */
 124        wait_for_bb ();
 125
 126        /* two bytes */
 127        outw (2, I2C_CNT);
 128        /* set slave address */
 129        outw (devaddr, I2C_SA);
 130        /* stop bit needed here */
 131        outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_TRX |
 132              I2C_CON_STP, I2C_CON);
 133
 134        /* wait until state change */
 135        status = wait_for_pin ();
 136
 137        if (status & I2C_STAT_XRDY) {
 138                /* send out two bytes */
 139                outw ((value << 8) + regoffset, I2C_DATA);
 140                /* must have enough delay to allow BB bit to go low */
 141                udelay (30000);
 142                if (inw (I2C_STAT) & I2C_STAT_NACK) {
 143                        i2c_error = 1;
 144                }
 145        } else {
 146                i2c_error = 1;
 147        }
 148
 149        if (!i2c_error) {
 150                outw (I2C_CON_EN, I2C_CON);
 151                while (inw (I2C_STAT) || (inw (I2C_CON) & I2C_CON_MST)) {
 152                        udelay (1000);
 153                        /* have to read to clear intrrupt */
 154                        inw (I2C_IV);
 155                }
 156        }
 157
 158        return i2c_error;
 159}
 160
 161int i2c_probe (uchar chip)
 162{
 163        int res = 1;
 164
 165        if (chip == inw (I2C_OA)) {
 166                return res;
 167        }
 168
 169        /* wait until bus not busy */
 170        wait_for_bb ();
 171
 172        /* try to read one byte */
 173        outw (1, I2C_CNT);
 174        /* set slave address */
 175        outw (chip, I2C_SA);
 176        /* stop bit needed here */
 177        outw (I2C_CON_EN | I2C_CON_MST | I2C_CON_STT | I2C_CON_STP, I2C_CON);
 178        /* enough delay for the NACK bit set */
 179        udelay (2000);
 180        if (!(inw (I2C_STAT) & I2C_STAT_NACK)) {
 181                res = 0;
 182        } else {
 183                outw (inw (I2C_CON) | I2C_CON_STP, I2C_CON);
 184                udelay (20);
 185                wait_for_bb ();
 186        }
 187
 188        return res;
 189}
 190
 191int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)
 192{
 193        int i;
 194
 195        if (alen > 1) {
 196                printf ("I2C read: addr len %d not supported\n", alen);
 197                return 1;
 198        }
 199
 200        if (addr + len > 256) {
 201                printf ("I2C read: address out of range\n");
 202                return 1;
 203        }
 204
 205        for (i = 0; i < len; i++) {
 206                if (i2c_read_byte (chip, addr + i, &buffer[i])) {
 207                        printf ("I2C read: I/O error\n");
 208                        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 209                        return 1;
 210                }
 211        }
 212
 213        return 0;
 214}
 215
 216int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)
 217{
 218        int i;
 219
 220        if (alen > 1) {
 221                printf ("I2C read: addr len %d not supported\n", alen);
 222                return 1;
 223        }
 224
 225        if (addr + len > 256) {
 226                printf ("I2C read: address out of range\n");
 227                return 1;
 228        }
 229
 230        for (i = 0; i < len; i++) {
 231                if (i2c_write_byte (chip, addr + i, buffer[i])) {
 232                        printf ("I2C read: I/O error\n");
 233                        i2c_init (CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
 234                        return 1;
 235                }
 236        }
 237
 238        return 0;
 239}
 240
 241static void wait_for_bb (void)
 242{
 243        int timeout = 10;
 244
 245        while ((inw (I2C_STAT) & I2C_STAT_BB) && timeout--) {
 246                inw (I2C_IV);
 247                udelay (1000);
 248        }
 249
 250        if (timeout <= 0) {
 251                printf ("timed out in wait_for_bb: I2C_STAT=%x\n",
 252                        inw (I2C_STAT));
 253        }
 254}
 255
 256static u16 wait_for_pin (void)
 257{
 258        u16 status, iv;
 259        int timeout = 10;
 260
 261        do {
 262                udelay (1000);
 263                status = inw (I2C_STAT);
 264                iv = inw (I2C_IV);
 265        } while (!iv &&
 266                 !(status &
 267                   (I2C_STAT_ROVR | I2C_STAT_XUDF | I2C_STAT_XRDY |
 268                    I2C_STAT_RRDY | I2C_STAT_ARDY | I2C_STAT_NACK |
 269                    I2C_STAT_AL)) && timeout--);
 270
 271        if (timeout <= 0) {
 272                printf ("timed out in wait_for_pin: I2C_STAT=%x\n",
 273                        inw (I2C_STAT));
 274        }
 275
 276        return status;
 277}
 278