uboot/drivers/i2c/i2c-cortina.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2020
   4 * Arthur Li, Cortina Access, arthur.li@cortina-access.com.
   5 */
   6
   7#include <common.h>
   8#include <i2c.h>
   9#include <log.h>
  10#include <asm/io.h>
  11#include <dm.h>
  12#include <mapmem.h>
  13#include "i2c-cortina.h"
  14
  15static void set_speed(struct i2c_regs *regs, int i2c_spd)
  16{
  17        union ca_biw_cfg i2c_cfg;
  18
  19        i2c_cfg.wrd = readl(&regs->i2c_cfg);
  20        i2c_cfg.bf.core_en = 0;
  21        writel(i2c_cfg.wrd, &regs->i2c_cfg);
  22
  23        switch (i2c_spd) {
  24        case IC_SPEED_MODE_FAST_PLUS:
  25                i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
  26                                  (5 * I2C_SPEED_FAST_PLUS_RATE) - 1;
  27                break;
  28
  29        case IC_SPEED_MODE_STANDARD:
  30                i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
  31                                  (5 * I2C_SPEED_STANDARD_RATE) - 1;
  32                break;
  33
  34        case IC_SPEED_MODE_FAST:
  35        default:
  36                i2c_cfg.bf.prer = CORTINA_PER_IO_FREQ /
  37                                  (5 * I2C_SPEED_FAST_RATE) - 1;
  38                break;
  39        }
  40
  41        i2c_cfg.bf.core_en = 1;
  42        writel(i2c_cfg.wrd, &regs->i2c_cfg);
  43}
  44
  45static int ca_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
  46{
  47        struct ca_i2c *priv = dev_get_priv(bus);
  48        int i2c_spd;
  49
  50        if (speed >= I2C_SPEED_FAST_PLUS_RATE) {
  51                i2c_spd = IC_SPEED_MODE_FAST_PLUS;
  52                priv->speed = I2C_SPEED_FAST_PLUS_RATE;
  53        } else if (speed >= I2C_SPEED_FAST_RATE) {
  54                i2c_spd = IC_SPEED_MODE_FAST;
  55                priv->speed = I2C_SPEED_FAST_RATE;
  56        } else {
  57                i2c_spd = IC_SPEED_MODE_STANDARD;
  58                priv->speed = I2C_SPEED_STANDARD_RATE;
  59        }
  60
  61        set_speed(priv->regs, i2c_spd);
  62
  63        return 0;
  64}
  65
  66static int ca_i2c_get_bus_speed(struct udevice *bus)
  67{
  68        struct ca_i2c *priv = dev_get_priv(bus);
  69
  70        return priv->speed;
  71}
  72
  73static void ca_i2c_init(struct i2c_regs *regs)
  74{
  75        union ca_biw_cfg i2c_cfg;
  76
  77        i2c_cfg.wrd = readl(&regs->i2c_cfg);
  78        i2c_cfg.bf.core_en = 0;
  79        i2c_cfg.bf.biw_soft_reset = 1;
  80        writel(i2c_cfg.wrd, &regs->i2c_cfg);
  81        mdelay(10);
  82        i2c_cfg.bf.biw_soft_reset = 0;
  83        writel(i2c_cfg.wrd, &regs->i2c_cfg);
  84
  85        set_speed(regs, IC_SPEED_MODE_STANDARD);
  86
  87        i2c_cfg.wrd = readl(&regs->i2c_cfg);
  88        i2c_cfg.bf.core_en = 1;
  89        writel(i2c_cfg.wrd, &regs->i2c_cfg);
  90}
  91
  92static int i2c_wait_complete(struct i2c_regs *regs)
  93{
  94        union ca_biw_ctrl i2c_ctrl;
  95        unsigned long start_time_bb = get_timer(0);
  96
  97        i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
  98
  99        while (i2c_ctrl.bf.biwdone == 0) {
 100                i2c_ctrl.wrd = readl(&regs->i2c_ctrl);
 101
 102                if (get_timer(start_time_bb) >
 103                   (unsigned long)(I2C_BYTE_TO_BB)) {
 104                        printf("%s not done!!!\n", __func__);
 105                        return -ETIMEDOUT;
 106                }
 107        }
 108
 109        /* Clear done bit */
 110        writel(i2c_ctrl.wrd, &regs->i2c_ctrl);
 111
 112        return 0;
 113}
 114
 115static void i2c_setaddress(struct i2c_regs *regs, unsigned int i2c_addr,
 116                           int write_read)
 117{
 118        writel(i2c_addr | write_read, &regs->i2c_txr);
 119
 120        writel(BIW_CTRL_START | BIW_CTRL_WRITE,
 121               &regs->i2c_ctrl);
 122
 123        i2c_wait_complete(regs);
 124}
 125
 126static int i2c_wait_for_bus_busy(struct i2c_regs *regs)
 127{
 128        union ca_biw_ack i2c_ack;
 129        unsigned long start_time_bb = get_timer(0);
 130
 131        i2c_ack.wrd = readl(&regs->i2c_ack);
 132
 133        while (i2c_ack.bf.biw_busy) {
 134                i2c_ack.wrd = readl(&regs->i2c_ack);
 135
 136                if (get_timer(start_time_bb) >
 137                   (unsigned long)(I2C_BYTE_TO_BB)) {
 138                        printf("%s: timeout!\n", __func__);
 139                        return -ETIMEDOUT;
 140                }
 141        }
 142
 143        return 0;
 144}
 145
 146static int i2c_xfer_init(struct i2c_regs *regs, uint8_t chip, uint addr,
 147                         int alen, int write_read)
 148{
 149        int addr_len = alen;
 150
 151        if (i2c_wait_for_bus_busy(regs))
 152                return 1;
 153
 154        /* First cycle must write addr + offset */
 155        chip = ((chip & 0x7F) << 1);
 156        if (alen == 0 && write_read == I2C_CMD_RD)
 157                i2c_setaddress(regs, chip, I2C_CMD_RD);
 158        else
 159                i2c_setaddress(regs, chip, I2C_CMD_WT);
 160
 161        while (alen) {
 162                alen--;
 163                writel(addr, &regs->i2c_txr);
 164                if (write_read == I2C_CMD_RD)
 165                        writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
 166                               &regs->i2c_ctrl);
 167                else
 168                        writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
 169                i2c_wait_complete(regs);
 170        }
 171
 172        /* Send address again with Read flag if it's read command */
 173        if (write_read == I2C_CMD_RD && addr_len > 0)
 174                i2c_setaddress(regs, chip, I2C_CMD_RD);
 175
 176        return 0;
 177}
 178
 179static int i2c_xfer_finish(struct i2c_regs *regs)
 180{
 181        /* Dummy read makes bus free */
 182        writel(BIW_CTRL_READ | BIW_CTRL_STOP, &regs->i2c_ctrl);
 183        i2c_wait_complete(regs);
 184
 185        if (i2c_wait_for_bus_busy(regs)) {
 186                printf("Timed out waiting for bus\n");
 187                return -ETIMEDOUT;
 188        }
 189
 190        return 0;
 191}
 192
 193static int ca_i2c_read(struct i2c_regs *regs, uint8_t chip, uint addr,
 194                       int alen, uint8_t *buffer, int len)
 195{
 196        unsigned long start_time_rx;
 197        int rc = 0;
 198
 199        rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_RD);
 200        if (rc)
 201                return rc;
 202
 203        start_time_rx = get_timer(0);
 204        while (len) {
 205                /* ACK_IN is ack value to send during read.
 206                 * ack high only on the very last byte!
 207                 */
 208                if (len == 1)
 209                        writel(BIW_CTRL_READ | BIW_CTRL_ACK_IN | BIW_CTRL_STOP,
 210                               &regs->i2c_ctrl);
 211                else
 212                        writel(BIW_CTRL_READ, &regs->i2c_ctrl);
 213
 214                rc = i2c_wait_complete(regs);
 215                udelay(1);
 216
 217                if (rc == 0) {
 218                        *buffer++ =
 219                                (uchar) readl(&regs->i2c_rxr);
 220                        len--;
 221                        start_time_rx = get_timer(0);
 222
 223                } else if (get_timer(start_time_rx) > I2C_BYTE_TO) {
 224                        return -ETIMEDOUT;
 225                }
 226        }
 227        i2c_xfer_finish(regs);
 228        return rc;
 229}
 230
 231static int ca_i2c_write(struct i2c_regs *regs, uint8_t chip, uint addr,
 232                        int alen, uint8_t *buffer, int len)
 233{
 234        int rc, nb = len;
 235        unsigned long start_time_tx;
 236
 237        rc = i2c_xfer_init(regs, chip, addr, alen, I2C_CMD_WT);
 238        if (rc)
 239                return rc;
 240
 241        start_time_tx = get_timer(0);
 242        while (len) {
 243                writel(*buffer, &regs->i2c_txr);
 244                if (len == 1)
 245                        writel(BIW_CTRL_WRITE | BIW_CTRL_STOP,
 246                               &regs->i2c_ctrl);
 247                else
 248                        writel(BIW_CTRL_WRITE, &regs->i2c_ctrl);
 249
 250                rc = i2c_wait_complete(regs);
 251
 252                if (rc == 0) {
 253                        len--;
 254                        buffer++;
 255                        start_time_tx = get_timer(0);
 256                } else if (get_timer(start_time_tx) > (nb * I2C_BYTE_TO)) {
 257                        return -ETIMEDOUT;
 258                }
 259        }
 260
 261        return 0;
 262}
 263
 264static int ca_i2c_probe_chip(struct udevice *bus, uint chip_addr,
 265                             uint chip_flags)
 266{
 267        struct ca_i2c *priv = dev_get_priv(bus);
 268        int ret;
 269        u32 tmp;
 270
 271        /* Try to read the first location of the chip */
 272        ret = ca_i2c_read(priv->regs, chip_addr, 0, 1, (uchar *)&tmp, 1);
 273        if (ret)
 274                ca_i2c_init(priv->regs);
 275
 276        return ret;
 277}
 278
 279static int ca_i2c_xfer(struct udevice *bus, struct i2c_msg *msg, int nmsgs)
 280{
 281        struct ca_i2c *priv = dev_get_priv(bus);
 282        int ret;
 283
 284        debug("i2c_xfer: %d messages\n", nmsgs);
 285        for (; nmsgs > 0; nmsgs--, msg++) {
 286                debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
 287                if (msg->flags & I2C_M_RD)
 288                        ret = ca_i2c_read(priv->regs, msg->addr, 0, 0,
 289                                          msg->buf, msg->len);
 290                else
 291                        ret = ca_i2c_write(priv->regs, msg->addr, 0, 0,
 292                                           msg->buf, msg->len);
 293
 294                if (ret) {
 295                        printf("i2c_xfer: %s error\n",
 296                               msg->flags & I2C_M_RD ? "read" : "write");
 297                        return ret;
 298                }
 299        }
 300
 301        return 0;
 302}
 303
 304static const struct dm_i2c_ops ca_i2c_ops = {
 305        .xfer           = ca_i2c_xfer,
 306        .probe_chip     = ca_i2c_probe_chip,
 307        .set_bus_speed  = ca_i2c_set_bus_speed,
 308        .get_bus_speed  = ca_i2c_get_bus_speed,
 309};
 310
 311static const struct udevice_id ca_i2c_ids[] = {
 312        { .compatible = "cortina,ca-i2c", },
 313        { }
 314};
 315
 316static int ca_i2c_probe(struct udevice *bus)
 317{
 318        struct ca_i2c *priv = dev_get_priv(bus);
 319
 320        ca_i2c_init(priv->regs);
 321
 322        return 0;
 323}
 324
 325static int ca_i2c_of_to_plat(struct udevice *bus)
 326{
 327        struct ca_i2c *priv = dev_get_priv(bus);
 328
 329        priv->regs = map_sysmem(dev_read_addr(bus), sizeof(struct i2c_regs));
 330        if (!priv->regs) {
 331                printf("I2C: base address is invalid\n");
 332                return -EINVAL;
 333        }
 334
 335        return 0;
 336}
 337
 338U_BOOT_DRIVER(i2c_cortina) = {
 339        .name   = "i2c_cortina",
 340        .id     = UCLASS_I2C,
 341        .of_match = ca_i2c_ids,
 342        .of_to_plat = ca_i2c_of_to_plat,
 343        .probe  = ca_i2c_probe,
 344        .priv_auto      = sizeof(struct ca_i2c),
 345        .ops    = &ca_i2c_ops,
 346        .flags  = DM_FLAG_PRE_RELOC,
 347};
 348