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