uboot/drivers/i2c/i2c-uniphier.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (C) 2014      Panasonic Corporation
   4 * Copyright (C) 2015-2016 Socionext Inc.
   5 *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
   6 */
   7
   8#include <dm/device_compat.h>
   9#include <linux/delay.h>
  10#include <linux/errno.h>
  11#include <linux/io.h>
  12#include <linux/sizes.h>
  13#include <linux/types.h>
  14#include <dm.h>
  15#include <fdtdec.h>
  16#include <i2c.h>
  17
  18struct uniphier_i2c_regs {
  19        u32 dtrm;                       /* data transmission */
  20#define I2C_DTRM_STA    (1 << 10)
  21#define I2C_DTRM_STO    (1 << 9)
  22#define I2C_DTRM_NACK   (1 << 8)
  23#define I2C_DTRM_RD     (1 << 0)
  24        u32 drec;                       /* data reception */
  25#define I2C_DREC_STS    (1 << 12)
  26#define I2C_DREC_LRB    (1 << 11)
  27#define I2C_DREC_LAB    (1 << 9)
  28        u32 myad;                       /* slave address */
  29        u32 clk;                        /* clock frequency control */
  30        u32 brst;                       /* bus reset */
  31#define I2C_BRST_FOEN   (1 << 1)
  32#define I2C_BRST_BRST   (1 << 0)
  33        u32 hold;                       /* hold time control */
  34        u32 bsts;                       /* bus status monitor */
  35        u32 noise;                      /* noise filter control */
  36        u32 setup;                      /* setup time control */
  37};
  38
  39#define IOBUS_FREQ      100000000
  40
  41struct uniphier_i2c_priv {
  42        struct udevice *dev;
  43        struct uniphier_i2c_regs __iomem *regs; /* register base */
  44        unsigned long input_clk;        /* master clock (Hz) */
  45        unsigned long wait_us;          /* wait for every byte transfer (us) */
  46};
  47
  48static int uniphier_i2c_probe(struct udevice *dev)
  49{
  50        fdt_addr_t addr;
  51        struct uniphier_i2c_priv *priv = dev_get_priv(dev);
  52
  53        addr = dev_read_addr(dev);
  54        if (addr == FDT_ADDR_T_NONE)
  55                return -EINVAL;
  56
  57        priv->regs = devm_ioremap(dev, addr, SZ_64);
  58        if (!priv->regs)
  59                return -ENOMEM;
  60
  61        priv->input_clk = IOBUS_FREQ;
  62
  63        priv->dev = dev;
  64
  65        /* deassert reset */
  66        writel(0x3, &priv->regs->brst);
  67
  68        return 0;
  69}
  70
  71static int send_and_recv_byte(struct uniphier_i2c_priv *priv, u32 dtrm)
  72{
  73        writel(dtrm, &priv->regs->dtrm);
  74
  75        /*
  76         * This controller only provides interruption to inform the completion
  77         * of each byte transfer.  (No status register to poll it.)
  78         * Unfortunately, U-Boot does not have a good support of interrupt.
  79         * Wait for a while.
  80         */
  81        udelay(priv->wait_us);
  82
  83        return readl(&priv->regs->drec);
  84}
  85
  86static int send_byte(struct uniphier_i2c_priv *priv, u32 dtrm, bool *stop)
  87{
  88        int ret = 0;
  89        u32 drec;
  90
  91        drec = send_and_recv_byte(priv, dtrm);
  92
  93        if (drec & I2C_DREC_LAB) {
  94                dev_dbg(priv->dev, "uniphier_i2c: bus arbitration failed\n");
  95                *stop = false;
  96                ret = -EREMOTEIO;
  97        }
  98        if (drec & I2C_DREC_LRB) {
  99                dev_dbg(priv->dev, "uniphier_i2c: slave did not return ACK\n");
 100                ret = -EREMOTEIO;
 101        }
 102        return ret;
 103}
 104
 105static int uniphier_i2c_transmit(struct uniphier_i2c_priv *priv, uint addr,
 106                                 uint len, const u8 *buf, bool *stop)
 107{
 108        int ret;
 109
 110        dev_dbg(priv->dev, "%s: addr = %x, len = %d\n", __func__, addr, len);
 111
 112        ret = send_byte(priv, I2C_DTRM_STA | I2C_DTRM_NACK | addr << 1, stop);
 113        if (ret < 0)
 114                goto fail;
 115
 116        while (len--) {
 117                ret = send_byte(priv, I2C_DTRM_NACK | *buf++, stop);
 118                if (ret < 0)
 119                        goto fail;
 120        }
 121
 122fail:
 123        if (*stop)
 124                writel(I2C_DTRM_STO | I2C_DTRM_NACK, &priv->regs->dtrm);
 125
 126        return ret;
 127}
 128
 129static int uniphier_i2c_receive(struct uniphier_i2c_priv *priv, uint addr,
 130                                uint len, u8 *buf, bool *stop)
 131{
 132        int ret;
 133
 134        dev_dbg(priv->dev, "%s: addr = %x, len = %d\n", __func__, addr, len);
 135
 136        ret = send_byte(priv, I2C_DTRM_STA | I2C_DTRM_NACK |
 137                        I2C_DTRM_RD | addr << 1, stop);
 138        if (ret < 0)
 139                goto fail;
 140
 141        while (len--)
 142                *buf++ = send_and_recv_byte(priv, len ? 0 : I2C_DTRM_NACK);
 143
 144fail:
 145        if (*stop)
 146                writel(I2C_DTRM_STO | I2C_DTRM_NACK, &priv->regs->dtrm);
 147
 148        return ret;
 149}
 150
 151static int uniphier_i2c_xfer(struct udevice *bus, struct i2c_msg *msg,
 152                             int nmsgs)
 153{
 154        int ret = 0;
 155        struct uniphier_i2c_priv *priv = dev_get_priv(bus);
 156        bool stop;
 157
 158        for (; nmsgs > 0; nmsgs--, msg++) {
 159                /* If next message is read, skip the stop condition */
 160                stop = nmsgs > 1 && msg[1].flags & I2C_M_RD ? false : true;
 161
 162                if (msg->flags & I2C_M_RD)
 163                        ret = uniphier_i2c_receive(priv, msg->addr, msg->len,
 164                                                   msg->buf, &stop);
 165                else
 166                        ret = uniphier_i2c_transmit(priv, msg->addr, msg->len,
 167                                                    msg->buf, &stop);
 168
 169                if (ret < 0)
 170                        break;
 171        }
 172
 173        return ret;
 174}
 175
 176static int uniphier_i2c_set_bus_speed(struct udevice *bus, unsigned int speed)
 177{
 178        struct uniphier_i2c_priv *priv = dev_get_priv(bus);
 179
 180        /* max supported frequency is 400 kHz */
 181        if (speed > I2C_SPEED_FAST_RATE)
 182                return -EINVAL;
 183
 184        /* bus reset: make sure the bus is idle when change the frequency */
 185        writel(0x1, &priv->regs->brst);
 186
 187        writel((priv->input_clk / speed / 2 << 16) | (priv->input_clk / speed),
 188               &priv->regs->clk);
 189
 190        writel(0x3, &priv->regs->brst);
 191
 192        /*
 193         * Theoretically, each byte can be transferred in
 194         * 1000000 * 9 / speed usec.  For safety, wait more than double.
 195         */
 196        priv->wait_us = 20000000 / speed;
 197
 198        return 0;
 199}
 200
 201
 202static const struct dm_i2c_ops uniphier_i2c_ops = {
 203        .xfer = uniphier_i2c_xfer,
 204        .set_bus_speed = uniphier_i2c_set_bus_speed,
 205};
 206
 207static const struct udevice_id uniphier_i2c_of_match[] = {
 208        { .compatible = "socionext,uniphier-i2c" },
 209        { /* sentinel */ }
 210};
 211
 212U_BOOT_DRIVER(uniphier_i2c) = {
 213        .name = "uniphier-i2c",
 214        .id = UCLASS_I2C,
 215        .of_match = uniphier_i2c_of_match,
 216        .probe = uniphier_i2c_probe,
 217        .priv_auto      = sizeof(struct uniphier_i2c_priv),
 218        .ops = &uniphier_i2c_ops,
 219};
 220