uboot/drivers/i2c/mxs_i2c.c
<<
>>
Prefs
   1/*
   2 * Freescale i.MX28 I2C Driver
   3 *
   4 * Copyright (C) 2011 Marek Vasut <marek.vasut@gmail.com>
   5 * on behalf of DENX Software Engineering GmbH
   6 *
   7 * Partly based on Linux kernel i2c-mxs.c driver:
   8 * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
   9 *
  10 * Which was based on a (non-working) driver which was:
  11 * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
  12 *
  13 * This program is free software; you can redistribute it and/or modify
  14 * it under the terms of the GNU General Public License as published by
  15 * the Free Software Foundation; either version 2 of the License, or
  16 * (at your option) any later version.
  17 *
  18 * This program is distributed in the hope that it will be useful,
  19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21 * GNU General Public License for more details.
  22 *
  23 * You should have received a copy of the GNU General Public License
  24 * along with this program; if not, write to the Free Software
  25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  26 *
  27 */
  28
  29#include <common.h>
  30#include <malloc.h>
  31#include <asm/errno.h>
  32#include <asm/io.h>
  33#include <asm/arch/clock.h>
  34#include <asm/arch/imx-regs.h>
  35#include <asm/arch/sys_proto.h>
  36
  37#define MXS_I2C_MAX_TIMEOUT     1000000
  38
  39void mxs_i2c_reset(void)
  40{
  41        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
  42        int ret;
  43
  44        ret = mx28_reset_block(&i2c_regs->hw_i2c_ctrl0_reg);
  45        if (ret) {
  46                debug("MXS I2C: Block reset timeout\n");
  47                return;
  48        }
  49
  50        writel(I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | I2C_CTRL1_NO_SLAVE_ACK_IRQ |
  51                I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
  52                I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ,
  53                &i2c_regs->hw_i2c_ctrl1_clr);
  54
  55        writel(I2C_QUEUECTRL_PIO_QUEUE_MODE, &i2c_regs->hw_i2c_queuectrl_set);
  56}
  57
  58void mxs_i2c_setup_read(uint8_t chip, int len)
  59{
  60        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
  61
  62        writel(I2C_QUEUECMD_RETAIN_CLOCK | I2C_QUEUECMD_PRE_SEND_START |
  63                I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
  64                (1 << I2C_QUEUECMD_XFER_COUNT_OFFSET),
  65                &i2c_regs->hw_i2c_queuecmd);
  66
  67        writel((chip << 1) | 1, &i2c_regs->hw_i2c_data);
  68
  69        writel(I2C_QUEUECMD_SEND_NAK_ON_LAST | I2C_QUEUECMD_MASTER_MODE |
  70                (len << I2C_QUEUECMD_XFER_COUNT_OFFSET) |
  71                I2C_QUEUECMD_POST_SEND_STOP, &i2c_regs->hw_i2c_queuecmd);
  72
  73        writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
  74}
  75
  76void mxs_i2c_write(uchar chip, uint addr, int alen,
  77                        uchar *buf, int blen, int stop)
  78{
  79        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
  80        uint32_t data;
  81        int i, remain, off;
  82
  83        if ((alen > 4) || (alen == 0)) {
  84                debug("MXS I2C: Invalid address length\n");
  85                return;
  86        }
  87
  88        if (stop)
  89                stop = I2C_QUEUECMD_POST_SEND_STOP;
  90
  91        writel(I2C_QUEUECMD_PRE_SEND_START |
  92                I2C_QUEUECMD_MASTER_MODE | I2C_QUEUECMD_DIRECTION |
  93                ((blen + alen + 1) << I2C_QUEUECMD_XFER_COUNT_OFFSET) | stop,
  94                &i2c_regs->hw_i2c_queuecmd);
  95
  96        data = (chip << 1) << 24;
  97
  98        for (i = 0; i < alen; i++) {
  99                data >>= 8;
 100                data |= ((char *)&addr)[alen - i - 1] << 24;
 101                if ((i & 3) == 2)
 102                        writel(data, &i2c_regs->hw_i2c_data);
 103        }
 104
 105        off = i;
 106        for (; i < off + blen; i++) {
 107                data >>= 8;
 108                data |= buf[i - off] << 24;
 109                if ((i & 3) == 2)
 110                        writel(data, &i2c_regs->hw_i2c_data);
 111        }
 112
 113        remain = 24 - ((i & 3) * 8);
 114        if (remain)
 115                writel(data >> remain, &i2c_regs->hw_i2c_data);
 116
 117        writel(I2C_QUEUECTRL_QUEUE_RUN, &i2c_regs->hw_i2c_queuectrl_set);
 118}
 119
 120int mxs_i2c_wait_for_ack(void)
 121{
 122        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
 123        uint32_t tmp;
 124        int timeout = MXS_I2C_MAX_TIMEOUT;
 125
 126        for (;;) {
 127                tmp = readl(&i2c_regs->hw_i2c_ctrl1);
 128                if (tmp & I2C_CTRL1_NO_SLAVE_ACK_IRQ) {
 129                        debug("MXS I2C: No slave ACK\n");
 130                        goto err;
 131                }
 132
 133                if (tmp & (
 134                        I2C_CTRL1_EARLY_TERM_IRQ | I2C_CTRL1_MASTER_LOSS_IRQ |
 135                        I2C_CTRL1_SLAVE_STOP_IRQ | I2C_CTRL1_SLAVE_IRQ)) {
 136                        debug("MXS I2C: Error (CTRL1 = %08x)\n", tmp);
 137                        goto err;
 138                }
 139
 140                if (tmp & I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ)
 141                        break;
 142
 143                if (!timeout--) {
 144                        debug("MXS I2C: Operation timed out\n");
 145                        goto err;
 146                }
 147
 148                udelay(1);
 149        }
 150
 151        return 0;
 152
 153err:
 154        mxs_i2c_reset();
 155        return 1;
 156}
 157
 158int i2c_read(uchar chip, uint addr, int alen, uchar *buffer, int len)
 159{
 160        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
 161        uint32_t tmp = 0;
 162        int ret;
 163        int i;
 164
 165        mxs_i2c_write(chip, addr, alen, NULL, 0, 0);
 166        ret = mxs_i2c_wait_for_ack();
 167        if (ret) {
 168                debug("MXS I2C: Failed writing address\n");
 169                return ret;
 170        }
 171
 172        mxs_i2c_setup_read(chip, len);
 173        ret = mxs_i2c_wait_for_ack();
 174        if (ret) {
 175                debug("MXS I2C: Failed reading address\n");
 176                return ret;
 177        }
 178
 179        for (i = 0; i < len; i++) {
 180                if (!(i & 3)) {
 181                        while (readl(&i2c_regs->hw_i2c_queuestat) &
 182                                I2C_QUEUESTAT_RD_QUEUE_EMPTY)
 183                                ;
 184                        tmp = readl(&i2c_regs->hw_i2c_queuedata);
 185                }
 186                buffer[i] = tmp & 0xff;
 187                tmp >>= 8;
 188        }
 189
 190        return 0;
 191}
 192
 193int i2c_write(uchar chip, uint addr, int alen, uchar *buffer, int len)
 194{
 195        int ret;
 196        mxs_i2c_write(chip, addr, alen, buffer, len, 1);
 197        ret = mxs_i2c_wait_for_ack();
 198        if (ret)
 199                debug("MXS I2C: Failed writing address\n");
 200
 201        return ret;
 202}
 203
 204int i2c_probe(uchar chip)
 205{
 206        int ret;
 207        mxs_i2c_write(chip, 0, 1, NULL, 0, 1);
 208        ret = mxs_i2c_wait_for_ack();
 209        mxs_i2c_reset();
 210        return ret;
 211}
 212
 213void i2c_init(int speed, int slaveadd)
 214{
 215        struct mx28_i2c_regs *i2c_regs = (struct mx28_i2c_regs *)MXS_I2C0_BASE;
 216
 217        mxs_i2c_reset();
 218
 219        switch (speed) {
 220        case 100000:
 221                writel((0x0078 << I2C_TIMING0_HIGH_COUNT_OFFSET) |
 222                        (0x0030 << I2C_TIMING0_RCV_COUNT_OFFSET),
 223                        &i2c_regs->hw_i2c_timing0);
 224                writel((0x0080 << I2C_TIMING1_LOW_COUNT_OFFSET) |
 225                        (0x0030 << I2C_TIMING1_XMIT_COUNT_OFFSET),
 226                        &i2c_regs->hw_i2c_timing1);
 227                break;
 228        case 400000:
 229                writel((0x000f << I2C_TIMING0_HIGH_COUNT_OFFSET) |
 230                        (0x0007 << I2C_TIMING0_RCV_COUNT_OFFSET),
 231                        &i2c_regs->hw_i2c_timing0);
 232                writel((0x001f << I2C_TIMING1_LOW_COUNT_OFFSET) |
 233                        (0x000f << I2C_TIMING1_XMIT_COUNT_OFFSET),
 234                        &i2c_regs->hw_i2c_timing1);
 235                break;
 236        default:
 237                printf("MXS I2C: Invalid speed selected (%d Hz)\n", speed);
 238                return;
 239        }
 240
 241        writel((0x0015 << I2C_TIMING2_BUS_FREE_OFFSET) |
 242                (0x000d << I2C_TIMING2_LEADIN_COUNT_OFFSET),
 243                &i2c_regs->hw_i2c_timing2);
 244
 245        return;
 246}
 247