uboot/drivers/i2c/s3c24x0_i2c.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2002
   4 * David Mueller, ELSOFT AG, d.mueller@elsoft.ch
   5 */
   6
   7#include <common.h>
   8#include <errno.h>
   9#include <dm.h>
  10#include <fdtdec.h>
  11#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
  12#include <asm/arch/clk.h>
  13#include <asm/arch/cpu.h>
  14#include <asm/arch/pinmux.h>
  15#else
  16#include <asm/arch/s3c24x0_cpu.h>
  17#endif
  18#include <asm/io.h>
  19#include <i2c.h>
  20#include "s3c24x0_i2c.h"
  21
  22#ifndef CONFIG_SYS_I2C_S3C24X0_SLAVE
  23#define SYS_I2C_S3C24X0_SLAVE_ADDR      0
  24#else
  25#define SYS_I2C_S3C24X0_SLAVE_ADDR      CONFIG_SYS_I2C_S3C24X0_SLAVE
  26#endif
  27
  28DECLARE_GLOBAL_DATA_PTR;
  29
  30/*
  31 * Wait til the byte transfer is completed.
  32 *
  33 * @param i2c- pointer to the appropriate i2c register bank.
  34 * @return I2C_OK, if transmission was ACKED
  35 *         I2C_NACK, if transmission was NACKED
  36 *         I2C_NOK_TIMEOUT, if transaction did not complete in I2C_TIMEOUT_MS
  37 */
  38
  39static int WaitForXfer(struct s3c24x0_i2c *i2c)
  40{
  41        ulong start_time = get_timer(0);
  42
  43        do {
  44                if (readl(&i2c->iiccon) & I2CCON_IRPND)
  45                        return (readl(&i2c->iicstat) & I2CSTAT_NACK) ?
  46                                I2C_NACK : I2C_OK;
  47        } while (get_timer(start_time) < I2C_TIMEOUT_MS);
  48
  49        return I2C_NOK_TOUT;
  50}
  51
  52static void read_write_byte(struct s3c24x0_i2c *i2c)
  53{
  54        clrbits_le32(&i2c->iiccon, I2CCON_IRPND);
  55}
  56
  57static void i2c_ch_init(struct s3c24x0_i2c *i2c, int speed, int slaveadd)
  58{
  59        ulong freq, pres = 16, div;
  60#if (defined CONFIG_EXYNOS4 || defined CONFIG_EXYNOS5)
  61        freq = get_i2c_clk();
  62#else
  63        freq = get_PCLK();
  64#endif
  65        /* calculate prescaler and divisor values */
  66        if ((freq / pres / (16 + 1)) > speed)
  67                /* set prescaler to 512 */
  68                pres = 512;
  69
  70        div = 0;
  71        while ((freq / pres / (div + 1)) > speed)
  72                div++;
  73
  74        /* set prescaler, divisor according to freq, also set ACKGEN, IRQ */
  75        writel((div & 0x0F) | 0xA0 | ((pres == 512) ? 0x40 : 0), &i2c->iiccon);
  76
  77        /* init to SLAVE REVEIVE and set slaveaddr */
  78        writel(0, &i2c->iicstat);
  79        writel(slaveadd, &i2c->iicadd);
  80        /* program Master Transmit (and implicit STOP) */
  81        writel(I2C_MODE_MT | I2C_TXRX_ENA, &i2c->iicstat);
  82}
  83
  84static int s3c24x0_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
  85{
  86        struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
  87
  88        i2c_bus->clock_frequency = speed;
  89
  90        i2c_ch_init(i2c_bus->regs, i2c_bus->clock_frequency,
  91                    SYS_I2C_S3C24X0_SLAVE_ADDR);
  92
  93        return 0;
  94}
  95
  96/*
  97 * cmd_type is 0 for write, 1 for read.
  98 *
  99 * addr_len can take any value from 0-255, it is only limited
 100 * by the char, we could make it larger if needed. If it is
 101 * 0 we skip the address write cycle.
 102 */
 103static int i2c_transfer(struct s3c24x0_i2c *i2c,
 104                        unsigned char cmd_type,
 105                        unsigned char chip,
 106                        unsigned char addr[],
 107                        unsigned char addr_len,
 108                        unsigned char data[],
 109                        unsigned short data_len)
 110{
 111        int i = 0, result;
 112        ulong start_time = get_timer(0);
 113
 114        if (data == 0 || data_len == 0) {
 115                /*Don't support data transfer of no length or to address 0 */
 116                debug("i2c_transfer: bad call\n");
 117                return I2C_NOK;
 118        }
 119
 120        while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
 121                if (get_timer(start_time) > I2C_TIMEOUT_MS)
 122                        return I2C_NOK_TOUT;
 123        }
 124
 125        writel(readl(&i2c->iiccon) | I2CCON_ACKGEN, &i2c->iiccon);
 126
 127        /* Get the slave chip address going */
 128        writel(chip, &i2c->iicds);
 129        if ((cmd_type == I2C_WRITE) || (addr && addr_len))
 130                writel(I2C_MODE_MT | I2C_TXRX_ENA | I2C_START_STOP,
 131                       &i2c->iicstat);
 132        else
 133                writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
 134                       &i2c->iicstat);
 135
 136        /* Wait for chip address to transmit. */
 137        result = WaitForXfer(i2c);
 138        if (result != I2C_OK)
 139                goto bailout;
 140
 141        /* If register address needs to be transmitted - do it now. */
 142        if (addr && addr_len) {
 143                while ((i < addr_len) && (result == I2C_OK)) {
 144                        writel(addr[i++], &i2c->iicds);
 145                        read_write_byte(i2c);
 146                        result = WaitForXfer(i2c);
 147                }
 148                i = 0;
 149                if (result != I2C_OK)
 150                        goto bailout;
 151        }
 152
 153        switch (cmd_type) {
 154        case I2C_WRITE:
 155                while ((i < data_len) && (result == I2C_OK)) {
 156                        writel(data[i++], &i2c->iicds);
 157                        read_write_byte(i2c);
 158                        result = WaitForXfer(i2c);
 159                }
 160                break;
 161
 162        case I2C_READ:
 163                if (addr && addr_len) {
 164                        /*
 165                         * Register address has been sent, now send slave chip
 166                         * address again to start the actual read transaction.
 167                         */
 168                        writel(chip, &i2c->iicds);
 169
 170                        /* Generate a re-START. */
 171                        writel(I2C_MODE_MR | I2C_TXRX_ENA | I2C_START_STOP,
 172                                &i2c->iicstat);
 173                        read_write_byte(i2c);
 174                        result = WaitForXfer(i2c);
 175
 176                        if (result != I2C_OK)
 177                                goto bailout;
 178                }
 179
 180                while ((i < data_len) && (result == I2C_OK)) {
 181                        /* disable ACK for final READ */
 182                        if (i == data_len - 1)
 183                                writel(readl(&i2c->iiccon)
 184                                       & ~I2CCON_ACKGEN,
 185                                       &i2c->iiccon);
 186                        read_write_byte(i2c);
 187                        result = WaitForXfer(i2c);
 188                        data[i++] = readl(&i2c->iicds);
 189                }
 190                if (result == I2C_NACK)
 191                        result = I2C_OK; /* Normal terminated read. */
 192                break;
 193
 194        default:
 195                debug("i2c_transfer: bad call\n");
 196                result = I2C_NOK;
 197                break;
 198        }
 199
 200bailout:
 201        /* Send STOP. */
 202        writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
 203        read_write_byte(i2c);
 204
 205        return result;
 206}
 207
 208static int s3c24x0_i2c_probe(struct udevice *dev, uint chip, uint chip_flags)
 209{
 210        struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
 211        uchar buf[1];
 212        int ret;
 213
 214        buf[0] = 0;
 215
 216        /*
 217         * What is needed is to send the chip address and verify that the
 218         * address was <ACK>ed (i.e. there was a chip at that address which
 219         * drove the data line low).
 220         */
 221        ret = i2c_transfer(i2c_bus->regs, I2C_READ, chip << 1, 0, 0, buf, 1);
 222
 223        return ret != I2C_OK;
 224}
 225
 226static int s3c24x0_do_msg(struct s3c24x0_i2c_bus *i2c_bus, struct i2c_msg *msg,
 227                          int seq)
 228{
 229        struct s3c24x0_i2c *i2c = i2c_bus->regs;
 230        bool is_read = msg->flags & I2C_M_RD;
 231        uint status;
 232        uint addr;
 233        int ret, i;
 234
 235        if (!seq)
 236                setbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
 237
 238        /* Get the slave chip address going */
 239        addr = msg->addr << 1;
 240        writel(addr, &i2c->iicds);
 241        status = I2C_TXRX_ENA | I2C_START_STOP;
 242        if (is_read)
 243                status |= I2C_MODE_MR;
 244        else
 245                status |= I2C_MODE_MT;
 246        writel(status, &i2c->iicstat);
 247        if (seq)
 248                read_write_byte(i2c);
 249
 250        /* Wait for chip address to transmit */
 251        ret = WaitForXfer(i2c);
 252        if (ret)
 253                goto err;
 254
 255        if (is_read) {
 256                for (i = 0; !ret && i < msg->len; i++) {
 257                        /* disable ACK for final READ */
 258                        if (i == msg->len - 1)
 259                                clrbits_le32(&i2c->iiccon, I2CCON_ACKGEN);
 260                        read_write_byte(i2c);
 261                        ret = WaitForXfer(i2c);
 262                        msg->buf[i] = readl(&i2c->iicds);
 263                }
 264                if (ret == I2C_NACK)
 265                        ret = I2C_OK; /* Normal terminated read */
 266        } else {
 267                for (i = 0; !ret && i < msg->len; i++) {
 268                        writel(msg->buf[i], &i2c->iicds);
 269                        read_write_byte(i2c);
 270                        ret = WaitForXfer(i2c);
 271                }
 272        }
 273
 274err:
 275        return ret;
 276}
 277
 278static int s3c24x0_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
 279                            int nmsgs)
 280{
 281        struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
 282        struct s3c24x0_i2c *i2c = i2c_bus->regs;
 283        ulong start_time;
 284        int ret, i;
 285
 286        start_time = get_timer(0);
 287        while (readl(&i2c->iicstat) & I2CSTAT_BSY) {
 288                if (get_timer(start_time) > I2C_TIMEOUT_MS) {
 289                        debug("Timeout\n");
 290                        return -ETIMEDOUT;
 291                }
 292        }
 293
 294        for (ret = 0, i = 0; !ret && i < nmsgs; i++)
 295                ret = s3c24x0_do_msg(i2c_bus, &msg[i], i);
 296
 297        /* Send STOP */
 298        writel(I2C_MODE_MR | I2C_TXRX_ENA, &i2c->iicstat);
 299        read_write_byte(i2c);
 300
 301        return ret ? -EREMOTEIO : 0;
 302}
 303
 304static int s3c_i2c_ofdata_to_platdata(struct udevice *dev)
 305{
 306        const void *blob = gd->fdt_blob;
 307        struct s3c24x0_i2c_bus *i2c_bus = dev_get_priv(dev);
 308        int node;
 309
 310        node = dev_of_offset(dev);
 311
 312        i2c_bus->regs = (struct s3c24x0_i2c *)devfdt_get_addr(dev);
 313
 314        i2c_bus->id = pinmux_decode_periph_id(blob, node);
 315
 316        i2c_bus->clock_frequency = fdtdec_get_int(blob, node,
 317                                                  "clock-frequency", 100000);
 318        i2c_bus->node = node;
 319        i2c_bus->bus_num = dev->seq;
 320
 321        exynos_pinmux_config(i2c_bus->id, 0);
 322
 323        i2c_bus->active = true;
 324
 325        return 0;
 326}
 327
 328static const struct dm_i2c_ops s3c_i2c_ops = {
 329        .xfer           = s3c24x0_i2c_xfer,
 330        .probe_chip     = s3c24x0_i2c_probe,
 331        .set_bus_speed  = s3c24x0_i2c_set_bus_speed,
 332};
 333
 334static const struct udevice_id s3c_i2c_ids[] = {
 335        { .compatible = "samsung,s3c2440-i2c" },
 336        { }
 337};
 338
 339U_BOOT_DRIVER(i2c_s3c) = {
 340        .name   = "i2c_s3c",
 341        .id     = UCLASS_I2C,
 342        .of_match = s3c_i2c_ids,
 343        .ofdata_to_platdata = s3c_i2c_ofdata_to_platdata,
 344        .priv_auto_alloc_size = sizeof(struct s3c24x0_i2c_bus),
 345        .ops    = &s3c_i2c_ops,
 346};
 347